blob: eb1d2216639c67bda8d602e15b79bc882e6761d7 [file]
out2x
8build/make/tools/ide_query/prober_scripts/cpp/general.cc8build/make/tools/ide_query/prober_scripts/cpp/general.cc:Žô
8build/make/tools/ide_query/prober_scripts/cpp/general.cc8build/make/tools/ide_query/prober_scripts/cpp/general.cc"8prebuilts/clang/host/linux-x86/clang-r584948/bin/clang++" -nostdlibinc"-mthumb"-Os"-fomit-frame-pointer"-mllvm"-enable-shrink-wrap=false"-O2"-Wall"-Wextra"-Wpointer-arith"-Wunguarded-availability"-Werror=bool-operation"-Werror=date-time"-Werror=int-conversion"-Werror=multichar"-Werror=pragma-pack"&-Werror=pragma-pack-suspicious-include"-Werror=sizeof-array-div" -Werror=sizeof-pointer-memaccess"-Werror=string-plus-int"'-Werror=unreachable-code-loop-increment""-Wno-error=deprecated-declarations"-Wno-c23-extensions"-Wno-c99-designator"-Wno-gnu-folding-constant""-Wno-inconsistent-missing-override"-Wno-error=reorder-init-list"-Wno-reorder-init-list"-Wno-sign-compare" -Wno-unused" -DANDROID"-DNDEBUG"-UDEBUG"(-D__compiler_offsetof=__builtin_offsetof"*-D__ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__" -faddrsig"-fdebug-default-version=5"-fcolor-diagnostics"-ffp-contract=off"-fno-exceptions"-fno-strict-aliasing"-fmessage-length=0"-gsimple-template-names"-gz=zstd"-no-canonical-prefixes""-fdebug-prefix-map=/proc/self/cwd="-ftrivial-auto-var-init=zero"-g"-ffunction-sections"-fdata-sections"-fno-short-enums"-funwind-tables"-fstack-protector-strong"-Wa,--noexecstack"-D_FORTIFY_SOURCE=3"-Werror=non-virtual-dtor"-Werror=address"-Werror=sequence-point"-Werror=format-security" -msoft-float"-march=armv7-a"-mfloat-abi=softfp"
-mfpu=neon"/-Ibuild/make/tools/ide_query/prober_scripts/cpp"³-Iout/soong/.intermediates/build/make/tools/ide_query/prober_scripts/cpp/ide_query_proberscript_cc/android_arm_armv7-a-neon/gen/proto/build/make/tools/ide_query/prober_scripts/cpp"…-Iout/soong/.intermediates/build/make/tools/ide_query/prober_scripts/cpp/ide_query_proberscript_cc/android_arm_armv7-a-neon/gen/proto"-D__LIBC_API__=10000"-D__LIBM_API__=10000"-D__LIBDL_API__=10000"-Iexternal/protobuf/src"*-Iexternal/protobuf/third_party/utf8_range"k-Iout/soong/.intermediates/external/abseil-cpp/absl_base_config_hdrs/gen/external/abseil-cpp/my_include_dir"W-Iout/soong/.intermediates/external/abseil-cpp/absl_base_config_hdrs/gen/my_include_dir"q-Iout/soong/.intermediates/external/abseil-cpp/absl_base_core_headers_hdrs/gen/external/abseil-cpp/my_include_dir"]-Iout/soong/.intermediates/external/abseil-cpp/absl_base_core_headers_hdrs/gen/my_include_dir"x-Iout/soong/.intermediates/external/abseil-cpp/absl_base_dynamic_annotations_hdrs/gen/external/abseil-cpp/my_include_dir"d-Iout/soong/.intermediates/external/abseil-cpp/absl_base_dynamic_annotations_hdrs/gen/my_include_dir"p-Iout/soong/.intermediates/external/abseil-cpp/absl_meta_type_traits_hdrs/gen/external/abseil-cpp/my_include_dir"\-Iout/soong/.intermediates/external/abseil-cpp/absl_meta_type_traits_hdrs/gen/my_include_dir"g-Iout/soong/.intermediates/external/abseil-cpp/absl_utility_hdrs/gen/external/abseil-cpp/my_include_dir"S-Iout/soong/.intermediates/external/abseil-cpp/absl_utility_hdrs/gen/my_include_dir"n-Iout/soong/.intermediates/external/abseil-cpp/absl_types_optional_hdrs/gen/external/abseil-cpp/my_include_dir"Z-Iout/soong/.intermediates/external/abseil-cpp/absl_types_optional_hdrs/gen/my_include_dir"p-Iout/soong/.intermediates/external/abseil-cpp/absl_container_common_hdrs/gen/external/abseil-cpp/my_include_dir"\-Iout/soong/.intermediates/external/abseil-cpp/absl_container_common_hdrs/gen/my_include_dir"~-Iout/soong/.intermediates/external/abseil-cpp/absl_container_common_policy_traits_hdrs/gen/external/abseil-cpp/my_include_dir"j-Iout/soong/.intermediates/external/abseil-cpp/absl_container_common_policy_traits_hdrs/gen/my_include_dir"z-Iout/soong/.intermediates/external/abseil-cpp/absl_container_compressed_tuple_hdrs/gen/external/abseil-cpp/my_include_dir"f-Iout/soong/.intermediates/external/abseil-cpp/absl_container_compressed_tuple_hdrs/gen/my_include_dir"f-Iout/soong/.intermediates/external/abseil-cpp/absl_memory_hdrs/gen/external/abseil-cpp/my_include_dir"R-Iout/soong/.intermediates/external/abseil-cpp/absl_memory_hdrs/gen/my_include_dir"z-Iout/soong/.intermediates/external/abseil-cpp/absl_container_container_memory_hdrs/gen/external/abseil-cpp/my_include_dir"f-Iout/soong/.intermediates/external/abseil-cpp/absl_container_container_memory_hdrs/gen/my_include_dir"p-Iout/soong/.intermediates/external/abseil-cpp/absl_base_atomic_hook_hdrs/gen/external/abseil-cpp/my_include_dir"\-Iout/soong/.intermediates/external/abseil-cpp/absl_base_atomic_hook_hdrs/gen/my_include_dir"r-Iout/soong/.intermediates/external/abseil-cpp/absl_base_base_internal_hdrs/gen/external/abseil-cpp/my_include_dir"^-Iout/soong/.intermediates/external/abseil-cpp/absl_base_base_internal_hdrs/gen/my_include_dir"x-Iout/soong/.intermediates/external/abseil-cpp/absl_base_cycleclock_internal_hdrs/gen/external/abseil-cpp/my_include_dir"d-Iout/soong/.intermediates/external/abseil-cpp/absl_base_cycleclock_internal_hdrs/gen/my_include_dir"q-Iout/soong/.intermediates/external/abseil-cpp/absl_base_log_severity_hdrs/gen/external/abseil-cpp/my_include_dir"]-Iout/soong/.intermediates/external/abseil-cpp/absl_base_log_severity_hdrs/gen/my_include_dir"p-Iout/soong/.intermediates/external/abseil-cpp/absl_base_nullability_hdrs/gen/external/abseil-cpp/my_include_dir"\-Iout/soong/.intermediates/external/abseil-cpp/absl_base_nullability_hdrs/gen/my_include_dir"p-Iout/soong/.intermediates/external/abseil-cpp/absl_base_errno_saver_hdrs/gen/external/abseil-cpp/my_include_dir"\-Iout/soong/.intermediates/external/abseil-cpp/absl_base_errno_saver_hdrs/gen/my_include_dir"y-Iout/soong/.intermediates/external/abseil-cpp/absl_base_raw_logging_internal_hdrs/gen/external/abseil-cpp/my_include_dir"e-Iout/soong/.intermediates/external/abseil-cpp/absl_base_raw_logging_internal_hdrs/gen/my_include_dir"r-Iout/soong/.intermediates/external/abseil-cpp/absl_base_spinlock_wait_hdrs/gen/external/abseil-cpp/my_include_dir"^-Iout/soong/.intermediates/external/abseil-cpp/absl_base_spinlock_wait_hdrs/gen/my_include_dir"d-Iout/soong/.intermediates/external/abseil-cpp/absl_base_hdrs/gen/external/abseil-cpp/my_include_dir"P-Iout/soong/.intermediates/external/abseil-cpp/absl_base_hdrs/gen/my_include_dir"k-Iout/soong/.intermediates/external/abseil-cpp/absl_base_endian_hdrs/gen/external/abseil-cpp/my_include_dir"W-Iout/soong/.intermediates/external/abseil-cpp/absl_base_endian_hdrs/gen/my_include_dir"l-Iout/soong/.intermediates/external/abseil-cpp/absl_numeric_bits_hdrs/gen/external/abseil-cpp/my_include_dir"X-Iout/soong/.intermediates/external/abseil-cpp/absl_numeric_bits_hdrs/gen/my_include_dir"†-Iout/soong/.intermediates/external/abseil-cpp/absl_debugging_bounded_utf8_length_sequence_hdrs/gen/external/abseil-cpp/my_include_dir"r-Iout/soong/.intermediates/external/abseil-cpp/absl_debugging_bounded_utf8_length_sequence_hdrs/gen/my_include_dir"}-Iout/soong/.intermediates/external/abseil-cpp/absl_debugging_utf8_for_code_point_hdrs/gen/external/abseil-cpp/my_include_dir"i-Iout/soong/.intermediates/external/abseil-cpp/absl_debugging_utf8_for_code_point_hdrs/gen/my_include_dir"~-Iout/soong/.intermediates/external/abseil-cpp/absl_debugging_decode_rust_punycode_hdrs/gen/external/abseil-cpp/my_include_dir"j-Iout/soong/.intermediates/external/abseil-cpp/absl_debugging_decode_rust_punycode_hdrs/gen/my_include_dir"w-Iout/soong/.intermediates/external/abseil-cpp/absl_debugging_demangle_rust_hdrs/gen/external/abseil-cpp/my_include_dir"c-Iout/soong/.intermediates/external/abseil-cpp/absl_debugging_demangle_rust_hdrs/gen/my_include_dir"{-Iout/soong/.intermediates/external/abseil-cpp/absl_debugging_demangle_internal_hdrs/gen/external/abseil-cpp/my_include_dir"g-Iout/soong/.intermediates/external/abseil-cpp/absl_debugging_demangle_internal_hdrs/gen/my_include_dir"s-Iout/soong/.intermediates/external/abseil-cpp/absl_base_throw_delegate_hdrs/gen/external/abseil-cpp/my_include_dir"_-Iout/soong/.intermediates/external/abseil-cpp/absl_base_throw_delegate_hdrs/gen/my_include_dir"s-Iout/soong/.intermediates/external/abseil-cpp/absl_strings_string_view_hdrs/gen/external/abseil-cpp/my_include_dir"_-Iout/soong/.intermediates/external/abseil-cpp/absl_strings_string_view_hdrs/gen/my_include_dir"o-Iout/soong/.intermediates/external/abseil-cpp/absl_strings_charset_hdrs/gen/external/abseil-cpp/my_include_dir"[-Iout/soong/.intermediates/external/abseil-cpp/absl_strings_charset_hdrs/gen/my_include_dir"p-Iout/soong/.intermediates/external/abseil-cpp/absl_strings_internal_hdrs/gen/external/abseil-cpp/my_include_dir"\-Iout/soong/.intermediates/external/abseil-cpp/absl_strings_internal_hdrs/gen/my_include_dir"}-Iout/soong/.intermediates/external/abseil-cpp/absl_base_iterator_traits_internal_hdrs/gen/external/abseil-cpp/my_include_dir"i-Iout/soong/.intermediates/external/abseil-cpp/absl_base_iterator_traits_internal_hdrs/gen/my_include_dir"m-Iout/soong/.intermediates/external/abseil-cpp/absl_types_compare_hdrs/gen/external/abseil-cpp/my_include_dir"Y-Iout/soong/.intermediates/external/abseil-cpp/absl_types_compare_hdrs/gen/my_include_dir"n-Iout/soong/.intermediates/external/abseil-cpp/absl_numeric_int128_hdrs/gen/external/abseil-cpp/my_include_dir"Z-Iout/soong/.intermediates/external/abseil-cpp/absl_numeric_int128_hdrs/gen/my_include_dir"g-Iout/soong/.intermediates/external/abseil-cpp/absl_strings_hdrs/gen/external/abseil-cpp/my_include_dir"S-Iout/soong/.intermediates/external/abseil-cpp/absl_strings_hdrs/gen/my_include_dir"i-Iout/soong/.intermediates/external/abseil-cpp/absl_algorithm_hdrs/gen/external/abseil-cpp/my_include_dir"U-Iout/soong/.intermediates/external/abseil-cpp/absl_algorithm_hdrs/gen/my_include_dir"y-Iout/soong/.intermediates/external/abseil-cpp/absl_hash_weakly_mixed_integer_hdrs/gen/external/abseil-cpp/my_include_dir"e-Iout/soong/.intermediates/external/abseil-cpp/absl_hash_weakly_mixed_integer_hdrs/gen/my_include_dir"j-Iout/soong/.intermediates/external/abseil-cpp/absl_types_span_hdrs/gen/external/abseil-cpp/my_include_dir"V-Iout/soong/.intermediates/external/abseil-cpp/absl_types_span_hdrs/gen/my_include_dir"p-Iout/soong/.intermediates/external/abseil-cpp/absl_container_layout_hdrs/gen/external/abseil-cpp/my_include_dir"\-Iout/soong/.intermediates/external/abseil-cpp/absl_container_layout_hdrs/gen/my_include_dir"-Iout/soong/.intermediates/external/abseil-cpp/absl_container_inlined_vector_internal_hdrs/gen/external/abseil-cpp/my_include_dir"m-Iout/soong/.intermediates/external/abseil-cpp/absl_container_inlined_vector_internal_hdrs/gen/my_include_dir"x-Iout/soong/.intermediates/external/abseil-cpp/absl_container_inlined_vector_hdrs/gen/external/abseil-cpp/my_include_dir"d-Iout/soong/.intermediates/external/abseil-cpp/absl_container_inlined_vector_hdrs/gen/my_include_dir"n-Iout/soong/.intermediates/external/abseil-cpp/absl_crc_cpu_detect_hdrs/gen/external/abseil-cpp/my_include_dir"Z-Iout/soong/.intermediates/external/abseil-cpp/absl_crc_cpu_detect_hdrs/gen/my_include_dir"m-Iout/soong/.intermediates/external/abseil-cpp/absl_base_prefetch_hdrs/gen/external/abseil-cpp/my_include_dir"Y-Iout/soong/.intermediates/external/abseil-cpp/absl_base_prefetch_hdrs/gen/my_include_dir"p-Iout/soong/.intermediates/external/abseil-cpp/absl_crc_crc_internal_hdrs/gen/external/abseil-cpp/my_include_dir"\-Iout/soong/.intermediates/external/abseil-cpp/absl_crc_crc_internal_hdrs/gen/my_include_dir"-Iout/soong/.intermediates/external/abseil-cpp/absl_crc_non_temporal_arm_intrinsics_hdrs/gen/external/abseil-cpp/my_include_dir"k-Iout/soong/.intermediates/external/abseil-cpp/absl_crc_non_temporal_arm_intrinsics_hdrs/gen/my_include_dir"w-Iout/soong/.intermediates/external/abseil-cpp/absl_crc_non_temporal_memcpy_hdrs/gen/external/abseil-cpp/my_include_dir"c-Iout/soong/.intermediates/external/abseil-cpp/absl_crc_non_temporal_memcpy_hdrs/gen/my_include_dir"u-Iout/soong/.intermediates/external/abseil-cpp/absl_container_fixed_array_hdrs/gen/external/abseil-cpp/my_include_dir"a-Iout/soong/.intermediates/external/abseil-cpp/absl_container_fixed_array_hdrs/gen/my_include_dir"x-Iout/soong/.intermediates/external/abseil-cpp/absl_functional_any_invocable_hdrs/gen/external/abseil-cpp/my_include_dir"d-Iout/soong/.intermediates/external/abseil-cpp/absl_functional_any_invocable_hdrs/gen/my_include_dir"w-Iout/soong/.intermediates/external/abseil-cpp/absl_functional_function_ref_hdrs/gen/external/abseil-cpp/my_include_dir"c-Iout/soong/.intermediates/external/abseil-cpp/absl_functional_function_ref_hdrs/gen/my_include_dir"v-Iout/soong/.intermediates/external/abseil-cpp/absl_numeric_representation_hdrs/gen/external/abseil-cpp/my_include_dir"b-Iout/soong/.intermediates/external/abseil-cpp/absl_numeric_representation_hdrs/gen/my_include_dir"{-Iout/soong/.intermediates/external/abseil-cpp/absl_strings_str_format_internal_hdrs/gen/external/abseil-cpp/my_include_dir"g-Iout/soong/.intermediates/external/abseil-cpp/absl_strings_str_format_internal_hdrs/gen/my_include_dir"r-Iout/soong/.intermediates/external/abseil-cpp/absl_strings_str_format_hdrs/gen/external/abseil-cpp/my_include_dir"^-Iout/soong/.intermediates/external/abseil-cpp/absl_strings_str_format_hdrs/gen/my_include_dir"j-Iout/soong/.intermediates/external/abseil-cpp/absl_crc_crc32c_hdrs/gen/external/abseil-cpp/my_include_dir"V-Iout/soong/.intermediates/external/abseil-cpp/absl_crc_crc32c_hdrs/gen/my_include_dir"r-Iout/soong/.intermediates/external/abseil-cpp/absl_base_no_destructor_hdrs/gen/external/abseil-cpp/my_include_dir"^-Iout/soong/.intermediates/external/abseil-cpp/absl_base_no_destructor_hdrs/gen/my_include_dir"r-Iout/soong/.intermediates/external/abseil-cpp/absl_crc_crc_cord_state_hdrs/gen/external/abseil-cpp/my_include_dir"^-Iout/soong/.intermediates/external/abseil-cpp/absl_crc_crc_cord_state_hdrs/gen/my_include_dir"u-Iout/soong/.intermediates/external/abseil-cpp/absl_strings_cord_internal_hdrs/gen/external/abseil-cpp/my_include_dir"a-Iout/soong/.intermediates/external/abseil-cpp/absl_strings_cord_internal_hdrs/gen/my_include_dir"|-Iout/soong/.intermediates/external/abseil-cpp/absl_profiling_exponential_biased_hdrs/gen/external/abseil-cpp/my_include_dir"h-Iout/soong/.intermediates/external/abseil-cpp/absl_profiling_exponential_biased_hdrs/gen/my_include_dir"w-Iout/soong/.intermediates/external/abseil-cpp/absl_strings_cordz_functions_hdrs/gen/external/abseil-cpp/my_include_dir"c-Iout/soong/.intermediates/external/abseil-cpp/absl_strings_cordz_functions_hdrs/gen/my_include_dir"t-Iout/soong/.intermediates/external/abseil-cpp/absl_base_malloc_internal_hdrs/gen/external/abseil-cpp/my_include_dir"`-Iout/soong/.intermediates/external/abseil-cpp/absl_base_malloc_internal_hdrs/gen/my_include_dir"„-Iout/soong/.intermediates/external/abseil-cpp/absl_synchronization_graphcycles_internal_hdrs/gen/external/abseil-cpp/my_include_dir"p-Iout/soong/.intermediates/external/abseil-cpp/absl_synchronization_graphcycles_internal_hdrs/gen/my_include_dir"}-Iout/soong/.intermediates/external/abseil-cpp/absl_time_internal_cctz_civil_time_hdrs/gen/external/abseil-cpp/my_include_dir"i-Iout/soong/.intermediates/external/abseil-cpp/absl_time_internal_cctz_civil_time_hdrs/gen/my_include_dir"|-Iout/soong/.intermediates/external/abseil-cpp/absl_time_internal_cctz_time_zone_hdrs/gen/external/abseil-cpp/my_include_dir"h-Iout/soong/.intermediates/external/abseil-cpp/absl_time_internal_cctz_time_zone_hdrs/gen/my_include_dir"d-Iout/soong/.intermediates/external/abseil-cpp/absl_time_hdrs/gen/external/abseil-cpp/my_include_dir"P-Iout/soong/.intermediates/external/abseil-cpp/absl_time_hdrs/gen/my_include_dir"‡-Iout/soong/.intermediates/external/abseil-cpp/absl_synchronization_kernel_timeout_internal_hdrs/gen/external/abseil-cpp/my_include_dir"s-Iout/soong/.intermediates/external/abseil-cpp/absl_synchronization_kernel_timeout_internal_hdrs/gen/my_include_dir"u-Iout/soong/.intermediates/external/abseil-cpp/absl_base_tracing_internal_hdrs/gen/external/abseil-cpp/my_include_dir"a-Iout/soong/.intermediates/external/abseil-cpp/absl_base_tracing_internal_hdrs/gen/my_include_dir"|-Iout/soong/.intermediates/external/abseil-cpp/absl_debugging_debugging_internal_hdrs/gen/external/abseil-cpp/my_include_dir"h-Iout/soong/.intermediates/external/abseil-cpp/absl_debugging_debugging_internal_hdrs/gen/my_include_dir"t-Iout/soong/.intermediates/external/abseil-cpp/absl_debugging_stacktrace_hdrs/gen/external/abseil-cpp/my_include_dir"`-Iout/soong/.intermediates/external/abseil-cpp/absl_debugging_stacktrace_hdrs/gen/my_include_dir"s-Iout/soong/.intermediates/external/abseil-cpp/absl_debugging_symbolize_hdrs/gen/external/abseil-cpp/my_include_dir"_-Iout/soong/.intermediates/external/abseil-cpp/absl_debugging_symbolize_hdrs/gen/my_include_dir"o-Iout/soong/.intermediates/external/abseil-cpp/absl_synchronization_hdrs/gen/external/abseil-cpp/my_include_dir"[-Iout/soong/.intermediates/external/abseil-cpp/absl_synchronization_hdrs/gen/my_include_dir"t-Iout/soong/.intermediates/external/abseil-cpp/absl_strings_cordz_handle_hdrs/gen/external/abseil-cpp/my_include_dir"`-Iout/soong/.intermediates/external/abseil-cpp/absl_strings_cordz_handle_hdrs/gen/my_include_dir"|-Iout/soong/.intermediates/external/abseil-cpp/absl_strings_cordz_update_tracker_hdrs/gen/external/abseil-cpp/my_include_dir"h-Iout/soong/.intermediates/external/abseil-cpp/absl_strings_cordz_update_tracker_hdrs/gen/my_include_dir"x-Iout/soong/.intermediates/external/abseil-cpp/absl_strings_cordz_statistics_hdrs/gen/external/abseil-cpp/my_include_dir"d-Iout/soong/.intermediates/external/abseil-cpp/absl_strings_cordz_statistics_hdrs/gen/my_include_dir"r-Iout/soong/.intermediates/external/abseil-cpp/absl_strings_cordz_info_hdrs/gen/external/abseil-cpp/my_include_dir"^-Iout/soong/.intermediates/external/abseil-cpp/absl_strings_cordz_info_hdrs/gen/my_include_dir"z-Iout/soong/.intermediates/external/abseil-cpp/absl_strings_cordz_update_scope_hdrs/gen/external/abseil-cpp/my_include_dir"f-Iout/soong/.intermediates/external/abseil-cpp/absl_strings_cordz_update_scope_hdrs/gen/my_include_dir"l-Iout/soong/.intermediates/external/abseil-cpp/absl_strings_cord_hdrs/gen/external/abseil-cpp/my_include_dir"X-Iout/soong/.intermediates/external/abseil-cpp/absl_strings_cord_hdrs/gen/my_include_dir"o-Iout/soong/.intermediates/external/abseil-cpp/absl_container_btree_hdrs/gen/external/abseil-cpp/my_include_dir"[-Iout/soong/.intermediates/external/abseil-cpp/absl_container_btree_hdrs/gen/my_include_dir"i-Iout/soong/.intermediates/external/abseil-cpp/absl_hash_city_hdrs/gen/external/abseil-cpp/my_include_dir"U-Iout/soong/.intermediates/external/abseil-cpp/absl_hash_city_hdrs/gen/my_include_dir"s-Iout/soong/.intermediates/external/abseil-cpp/absl_hash_low_level_hash_hdrs/gen/external/abseil-cpp/my_include_dir"_-Iout/soong/.intermediates/external/abseil-cpp/absl_hash_low_level_hash_hdrs/gen/my_include_dir"m-Iout/soong/.intermediates/external/abseil-cpp/absl_types_variant_hdrs/gen/external/abseil-cpp/my_include_dir"Y-Iout/soong/.intermediates/external/abseil-cpp/absl_types_variant_hdrs/gen/my_include_dir"d-Iout/soong/.intermediates/external/abseil-cpp/absl_hash_hdrs/gen/external/abseil-cpp/my_include_dir"P-Iout/soong/.intermediates/external/abseil-cpp/absl_hash_hdrs/gen/my_include_dir"€-Iout/soong/.intermediates/external/abseil-cpp/absl_container_hash_function_defaults_hdrs/gen/external/abseil-cpp/my_include_dir"l-Iout/soong/.intermediates/external/abseil-cpp/absl_container_hash_function_defaults_hdrs/gen/my_include_dir"-Iout/soong/.intermediates/external/abseil-cpp/absl_container_hash_container_defaults_hdrs/gen/external/abseil-cpp/my_include_dir"m-Iout/soong/.intermediates/external/abseil-cpp/absl_container_hash_container_defaults_hdrs/gen/my_include_dir"|-Iout/soong/.intermediates/external/abseil-cpp/absl_container_hash_policy_traits_hdrs/gen/external/abseil-cpp/my_include_dir"h-Iout/soong/.intermediates/external/abseil-cpp/absl_container_hash_policy_traits_hdrs/gen/my_include_dir"-Iout/soong/.intermediates/external/abseil-cpp/absl_container_hashtable_control_bytes_hdrs/gen/external/abseil-cpp/my_include_dir"m-Iout/soong/.intermediates/external/abseil-cpp/absl_container_hashtable_control_bytes_hdrs/gen/my_include_dir"-Iout/soong/.intermediates/external/abseil-cpp/absl_container_hashtable_debug_hooks_hdrs/gen/external/abseil-cpp/my_include_dir"k-Iout/soong/.intermediates/external/abseil-cpp/absl_container_hashtable_debug_hooks_hdrs/gen/my_include_dir"y-Iout/soong/.intermediates/external/abseil-cpp/absl_profiling_sample_recorder_hdrs/gen/external/abseil-cpp/my_include_dir"e-Iout/soong/.intermediates/external/abseil-cpp/absl_profiling_sample_recorder_hdrs/gen/my_include_dir"|-Iout/soong/.intermediates/external/abseil-cpp/absl_container_hashtablez_sampler_hdrs/gen/external/abseil-cpp/my_include_dir"h-Iout/soong/.intermediates/external/abseil-cpp/absl_container_hashtablez_sampler_hdrs/gen/my_include_dir"‚-Iout/soong/.intermediates/external/abseil-cpp/absl_container_raw_hash_set_resize_impl_hdrs/gen/external/abseil-cpp/my_include_dir"n-Iout/soong/.intermediates/external/abseil-cpp/absl_container_raw_hash_set_resize_impl_hdrs/gen/my_include_dir"v-Iout/soong/.intermediates/external/abseil-cpp/absl_container_raw_hash_set_hdrs/gen/external/abseil-cpp/my_include_dir"b-Iout/soong/.intermediates/external/abseil-cpp/absl_container_raw_hash_set_hdrs/gen/my_include_dir"v-Iout/soong/.intermediates/external/abseil-cpp/absl_container_raw_hash_map_hdrs/gen/external/abseil-cpp/my_include_dir"b-Iout/soong/.intermediates/external/abseil-cpp/absl_container_raw_hash_map_hdrs/gen/my_include_dir"s-Iout/soong/.intermediates/external/abseil-cpp/absl_algorithm_container_hdrs/gen/external/abseil-cpp/my_include_dir"_-Iout/soong/.intermediates/external/abseil-cpp/absl_algorithm_container_hdrs/gen/my_include_dir"w-Iout/soong/.intermediates/external/abseil-cpp/absl_container_flat_hash_map_hdrs/gen/external/abseil-cpp/my_include_dir"c-Iout/soong/.intermediates/external/abseil-cpp/absl_container_flat_hash_map_hdrs/gen/my_include_dir"w-Iout/soong/.intermediates/external/abseil-cpp/absl_container_flat_hash_set_hdrs/gen/external/abseil-cpp/my_include_dir"c-Iout/soong/.intermediates/external/abseil-cpp/absl_container_flat_hash_set_hdrs/gen/my_include_dir"v-Iout/soong/.intermediates/external/abseil-cpp/absl_log_internal_nullguard_hdrs/gen/external/abseil-cpp/my_include_dir"b-Iout/soong/.intermediates/external/abseil-cpp/absl_log_internal_nullguard_hdrs/gen/my_include_dir"w-Iout/soong/.intermediates/external/abseil-cpp/absl_log_internal_nullstream_hdrs/gen/external/abseil-cpp/my_include_dir"c-Iout/soong/.intermediates/external/abseil-cpp/absl_log_internal_nullstream_hdrs/gen/my_include_dir"}-Iout/soong/.intermediates/external/abseil-cpp/absl_log_internal_append_truncated_hdrs/gen/external/abseil-cpp/my_include_dir"i-Iout/soong/.intermediates/external/abseil-cpp/absl_log_internal_append_truncated_hdrs/gen/my_include_dir"s-Iout/soong/.intermediates/external/abseil-cpp/absl_log_internal_config_hdrs/gen/external/abseil-cpp/my_include_dir"_-Iout/soong/.intermediates/external/abseil-cpp/absl_log_internal_config_hdrs/gen/my_include_dir"t-Iout/soong/.intermediates/external/abseil-cpp/absl_log_internal_globals_hdrs/gen/external/abseil-cpp/my_include_dir"`-Iout/soong/.intermediates/external/abseil-cpp/absl_log_internal_globals_hdrs/gen/my_include_dir"s-Iout/soong/.intermediates/external/abseil-cpp/absl_log_internal_format_hdrs/gen/external/abseil-cpp/my_include_dir"_-Iout/soong/.intermediates/external/abseil-cpp/absl_log_internal_format_hdrs/gen/my_include_dir"x-Iout/soong/.intermediates/external/abseil-cpp/absl_cleanup_cleanup_internal_hdrs/gen/external/abseil-cpp/my_include_dir"d-Iout/soong/.intermediates/external/abseil-cpp/absl_cleanup_cleanup_internal_hdrs/gen/my_include_dir"g-Iout/soong/.intermediates/external/abseil-cpp/absl_cleanup_hdrs/gen/external/abseil-cpp/my_include_dir"S-Iout/soong/.intermediates/external/abseil-cpp/absl_cleanup_hdrs/gen/my_include_dir"t-Iout/soong/.intermediates/external/abseil-cpp/absl_log_internal_fnmatch_hdrs/gen/external/abseil-cpp/my_include_dir"`-Iout/soong/.intermediates/external/abseil-cpp/absl_log_internal_fnmatch_hdrs/gen/my_include_dir"x-Iout/soong/.intermediates/external/abseil-cpp/absl_log_internal_vlog_config_hdrs/gen/external/abseil-cpp/my_include_dir"d-Iout/soong/.intermediates/external/abseil-cpp/absl_log_internal_vlog_config_hdrs/gen/my_include_dir"k-Iout/soong/.intermediates/external/abseil-cpp/absl_log_globals_hdrs/gen/external/abseil-cpp/my_include_dir"W-Iout/soong/.intermediates/external/abseil-cpp/absl_log_globals_hdrs/gen/my_include_dir"m-Iout/soong/.intermediates/external/abseil-cpp/absl_log_log_entry_hdrs/gen/external/abseil-cpp/my_include_dir"Y-Iout/soong/.intermediates/external/abseil-cpp/absl_log_log_entry_hdrs/gen/my_include_dir"l-Iout/soong/.intermediates/external/abseil-cpp/absl_log_log_sink_hdrs/gen/external/abseil-cpp/my_include_dir"X-Iout/soong/.intermediates/external/abseil-cpp/absl_log_log_sink_hdrs/gen/my_include_dir"y-Iout/soong/.intermediates/external/abseil-cpp/absl_log_internal_log_sink_set_hdrs/gen/external/abseil-cpp/my_include_dir"e-Iout/soong/.intermediates/external/abseil-cpp/absl_log_internal_log_sink_set_hdrs/gen/my_include_dir"r-Iout/soong/.intermediates/external/abseil-cpp/absl_log_internal_proto_hdrs/gen/external/abseil-cpp/my_include_dir"^-Iout/soong/.intermediates/external/abseil-cpp/absl_log_internal_proto_hdrs/gen/my_include_dir"}-Iout/soong/.intermediates/external/abseil-cpp/absl_log_internal_structured_proto_hdrs/gen/external/abseil-cpp/my_include_dir"i-Iout/soong/.intermediates/external/abseil-cpp/absl_log_internal_structured_proto_hdrs/gen/my_include_dir"m-Iout/soong/.intermediates/external/abseil-cpp/absl_base_strerror_hdrs/gen/external/abseil-cpp/my_include_dir"Y-Iout/soong/.intermediates/external/abseil-cpp/absl_base_strerror_hdrs/gen/my_include_dir"w-Iout/soong/.intermediates/external/abseil-cpp/absl_debugging_examine_stack_hdrs/gen/external/abseil-cpp/my_include_dir"c-Iout/soong/.intermediates/external/abseil-cpp/absl_debugging_examine_stack_hdrs/gen/my_include_dir"u-Iout/soong/.intermediates/external/abseil-cpp/absl_log_log_sink_registry_hdrs/gen/external/abseil-cpp/my_include_dir"a-Iout/soong/.intermediates/external/abseil-cpp/absl_log_log_sink_registry_hdrs/gen/my_include_dir"x-Iout/soong/.intermediates/external/abseil-cpp/absl_log_internal_log_message_hdrs/gen/external/abseil-cpp/my_include_dir"d-Iout/soong/.intermediates/external/abseil-cpp/absl_log_internal_log_message_hdrs/gen/my_include_dir"r-Iout/soong/.intermediates/external/abseil-cpp/absl_log_internal_strip_hdrs/gen/external/abseil-cpp/my_include_dir"^-Iout/soong/.intermediates/external/abseil-cpp/absl_log_internal_strip_hdrs/gen/my_include_dir"t-Iout/soong/.intermediates/external/abseil-cpp/absl_debugging_leak_check_hdrs/gen/external/abseil-cpp/my_include_dir"`-Iout/soong/.intermediates/external/abseil-cpp/absl_debugging_leak_check_hdrs/gen/my_include_dir"u-Iout/soong/.intermediates/external/abseil-cpp/absl_log_internal_check_op_hdrs/gen/external/abseil-cpp/my_include_dir"a-Iout/soong/.intermediates/external/abseil-cpp/absl_log_internal_check_op_hdrs/gen/my_include_dir"t-Iout/soong/.intermediates/external/abseil-cpp/absl_log_internal_voidify_hdrs/gen/external/abseil-cpp/my_include_dir"`-Iout/soong/.intermediates/external/abseil-cpp/absl_log_internal_voidify_hdrs/gen/my_include_dir"w-Iout/soong/.intermediates/external/abseil-cpp/absl_log_internal_conditions_hdrs/gen/external/abseil-cpp/my_include_dir"c-Iout/soong/.intermediates/external/abseil-cpp/absl_log_internal_conditions_hdrs/gen/my_include_dir"w-Iout/soong/.intermediates/external/abseil-cpp/absl_log_internal_check_impl_hdrs/gen/external/abseil-cpp/my_include_dir"c-Iout/soong/.intermediates/external/abseil-cpp/absl_log_internal_check_impl_hdrs/gen/my_include_dir"n-Iout/soong/.intermediates/external/abseil-cpp/absl_log_absl_check_hdrs/gen/external/abseil-cpp/my_include_dir"Z-Iout/soong/.intermediates/external/abseil-cpp/absl_log_absl_check_hdrs/gen/my_include_dir"s-Iout/soong/.intermediates/external/abseil-cpp/absl_log_absl_vlog_is_on_hdrs/gen/external/abseil-cpp/my_include_dir"_-Iout/soong/.intermediates/external/abseil-cpp/absl_log_absl_vlog_is_on_hdrs/gen/my_include_dir"u-Iout/soong/.intermediates/external/abseil-cpp/absl_log_internal_log_impl_hdrs/gen/external/abseil-cpp/my_include_dir"a-Iout/soong/.intermediates/external/abseil-cpp/absl_log_internal_log_impl_hdrs/gen/my_include_dir"l-Iout/soong/.intermediates/external/abseil-cpp/absl_log_absl_log_hdrs/gen/external/abseil-cpp/my_include_dir"X-Iout/soong/.intermediates/external/abseil-cpp/absl_log_absl_log_hdrs/gen/my_include_dir"f-Iout/soong/.intermediates/external/abseil-cpp/absl_status_hdrs/gen/external/abseil-cpp/my_include_dir"R-Iout/soong/.intermediates/external/abseil-cpp/absl_status_hdrs/gen/my_include_dir"Y-Iprebuilts/clang/host/linux-x86/clang-r584948/android_libc++/platform/arm/include/c++/v1"=-Iprebuilts/clang/host/linux-x86/clang-r584948/include/c++/v1" -Ibionic/libc/async_safe/include"-Isystem/logging/liblog/include"'-Ibionic/libc/system_properties/include"<-Isystem/core/property_service/libpropertyinfoparser/include"-isystem"bionic/libc/include"-isystem"bionic/libc/kernel/uapi/asm-arm"-isystem"bionic/libc/kernel/uapi"-isystem"bionic/libc/kernel/android/scsi"-isystem"bionic/libc/kernel/android/uapi"-target"armv7a-linux-androideabi10000"-DANDROID_STRICT"-fPIE"-Werror"-Wno-unused-parameter"-DGOOGLE_PROTOBUF_NO_RTTI"-Wimplicit-fallthrough"*-D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS"-Wno-gnu-include-next"-fvisibility-inlines-hidden"-mllvm"-enable-shrink-wrap=false" -std=gnu++20" -fno-rtti"-Isystem/core/include"-Isystem/logging/liblog/include"-Isystem/media/audio/include"-Ihardware/libhardware/include"%-Ihardware/libhardware_legacy/include"-Ihardware/ril/include"-Iframeworks/native/include""-Iframeworks/native/opengl/include"-Iframeworks/av/include"-Werror=address-of-temporary"-Werror=dangling" -Werror=format-insufficient-args"-Werror=fortify-source"+-Werror=incompatible-function-pointer-types"-Werror=int-in-bool-context"-Werror=int-to-pointer-cast"-Werror=null-dereference"-Werror=return-type"-Werror=xor-used-as-pow"-Wno-missing-field-initializers"-Wno-packed-non-pod"(-Wno-error=tautological-constant-compare""-Wno-implicit-int-float-conversion"!-Wno-tautological-overlap-compare"-Wno-deprecated-copy""-Wno-zero-as-null-pointer-constant")-Wno-deprecated-anon-enum-enum-conversion"$-Wno-deprecated-enum-enum-conversion"-Wno-error=pessimizing-move"-Wno-non-c-typedef-for-linkage"-Wno-align-mismatch"#-Wno-error=unused-but-set-parameter"-Wno-error=deprecated"-Wno-error=invalid-offsetof"-Wno-nontrivial-memcall"-Wno-invalid-specialization"'-Wno-unterminated-string-initialization"(-Wno-implicit-int-conversion-on-negation"$-Wno-default-const-init-field-unsafe""-Wno-default-const-init-var-unsafe",-Wno-preferred-type-bitfield-enum-conversion"-Wno-implicit-enum-enum-cast"-Wno-vla-cxx-extension" -Wno-cast-function-type-mismatch"-Wno-character-conversion"&-Wno-error=uninitialized-const-pointer"8build/make/tools/ide_query/prober_scripts/cpp/general.cc2Egenfiles_for_build/make/tools/ide_query/prober_scripts/cpp/general.cc:êÉg
Egenfiles_for_build/make/tools/ide_query/prober_scripts/cpp/general.cc*År
dsoong/.intermediates/external/abseil-cpp/absl_strings_hdrs/gen/my_include_dir/absl/strings/numbers.hÜq// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: numbers.h
// -----------------------------------------------------------------------------
//
// This package contains functions for converting strings to numbers. For
// converting numbers to strings, use `StrCat()` or `StrAppend()` in str_cat.h,
// which automatically detect and convert most number values appropriately.
#ifndef ABSL_STRINGS_NUMBERS_H_
#define ABSL_STRINGS_NUMBERS_H_
#ifdef __SSSE3__
#include <tmmintrin.h>
#endif
#ifdef _MSC_VER
#include <intrin.h>
#endif
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <limits>
#include <string>
#include <type_traits>
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/internal/endian.h"
#include "absl/base/macros.h"
#include "absl/base/nullability.h"
#include "absl/base/port.h"
#include "absl/numeric/bits.h"
#include "absl/numeric/int128.h"
#include "absl/strings/string_view.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
// SimpleAtoi()
//
// Converts the given string (optionally followed or preceded by ASCII
// whitespace) into an integer value, returning `true` if successful. The string
// must reflect a base-10 integer whose value falls within the range of the
// integer type (optionally preceded by a `+` or `-`). If any errors are
// encountered, this function returns `false`, leaving `out` in an unspecified
// state.
template <typename int_type>
[[nodiscard]] bool SimpleAtoi(absl::string_view str,
int_type* absl_nonnull out);
// SimpleAtof()
//
// Converts the given string (optionally followed or preceded by ASCII
// whitespace) into a float, which may be rounded on overflow or underflow,
// returning `true` if successful.
// See https://en.cppreference.com/w/c/string/byte/strtof for details about the
// allowed formats for `str`, except SimpleAtof() is locale-independent and will
// always use the "C" locale. If any errors are encountered, this function
// returns `false`, leaving `out` in an unspecified state.
[[nodiscard]] bool SimpleAtof(absl::string_view str, float* absl_nonnull out);
// SimpleAtod()
//
// Converts the given string (optionally followed or preceded by ASCII
// whitespace) into a double, which may be rounded on overflow or underflow,
// returning `true` if successful.
// See https://en.cppreference.com/w/c/string/byte/strtof for details about the
// allowed formats for `str`, except SimpleAtod is locale-independent and will
// always use the "C" locale. If any errors are encountered, this function
// returns `false`, leaving `out` in an unspecified state.
[[nodiscard]] bool SimpleAtod(absl::string_view str, double* absl_nonnull out);
// SimpleAtob()
//
// Converts the given string into a boolean, returning `true` if successful.
// The following case-insensitive strings are interpreted as boolean `true`:
// "true", "t", "yes", "y", "1". The following case-insensitive strings
// are interpreted as boolean `false`: "false", "f", "no", "n", "0". If any
// errors are encountered, this function returns `false`, leaving `out` in an
// unspecified state.
[[nodiscard]] bool SimpleAtob(absl::string_view str, bool* absl_nonnull out);
// SimpleHexAtoi()
//
// Converts a hexadecimal string (optionally followed or preceded by ASCII
// whitespace) to an integer, returning `true` if successful. Only valid base-16
// hexadecimal integers whose value falls within the range of the integer type
// (optionally preceded by a `+` or `-`) can be converted. A valid hexadecimal
// value may include both upper and lowercase character symbols, and may
// optionally include a leading "0x" (or "0X") number prefix, which is ignored
// by this function. If any errors are encountered, this function returns
// `false`, leaving `out` in an unspecified state.
template <typename int_type>
[[nodiscard]] bool SimpleHexAtoi(absl::string_view str,
int_type* absl_nonnull out);
// Overloads of SimpleHexAtoi() for 128 bit integers.
[[nodiscard]] inline bool SimpleHexAtoi(absl::string_view str,
absl::int128* absl_nonnull out);
[[nodiscard]] inline bool SimpleHexAtoi(absl::string_view str,
absl::uint128* absl_nonnull out);
ABSL_NAMESPACE_END
} // namespace absl
// End of public API. Implementation details follow.
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace numbers_internal {
template <typename int_type>
constexpr bool is_signed() {
if constexpr (std::is_arithmetic<int_type>::value) {
// Use std::numeric_limits<T>::is_signed where it's defined to work.
return std::numeric_limits<int_type>::is_signed;
}
// TODO(jorg): This signed-ness check is used because it works correctly
// with enums, and it also serves to check that int_type is not a pointer.
// If one day something like std::is_signed<enum E> works, switch to it.
return static_cast<int_type>(1) - 2 < 0;
}
// Digit conversion.
ABSL_DLL extern const char kHexChar[17]; // 0123456789abcdef
ABSL_DLL extern const char
kHexTable[513]; // 000102030405060708090a0b0c0d0e0f1011...
// Writes a two-character representation of 'i' to 'buf'. 'i' must be in the
// range 0 <= i < 100, and buf must have space for two characters. Example:
// char buf[2];
// PutTwoDigits(42, buf);
// // buf[0] == '4'
// // buf[1] == '2'
void PutTwoDigits(uint32_t i, char* absl_nonnull buf);
// safe_strto?() functions for implementing SimpleAtoi()
bool safe_strto8_base(absl::string_view text, int8_t* absl_nonnull value,
int base);
bool safe_strto16_base(absl::string_view text, int16_t* absl_nonnull value,
int base);
bool safe_strto32_base(absl::string_view text, int32_t* absl_nonnull value,
int base);
bool safe_strto64_base(absl::string_view text, int64_t* absl_nonnull value,
int base);
bool safe_strto128_base(absl::string_view text,
absl::int128* absl_nonnull value, int base);
bool safe_strtou8_base(absl::string_view text, uint8_t* absl_nonnull value,
int base);
bool safe_strtou16_base(absl::string_view text, uint16_t* absl_nonnull value,
int base);
bool safe_strtou32_base(absl::string_view text, uint32_t* absl_nonnull value,
int base);
bool safe_strtou64_base(absl::string_view text, uint64_t* absl_nonnull value,
int base);
bool safe_strtou128_base(absl::string_view text,
absl::uint128* absl_nonnull value, int base);
static const int kFastToBufferSize = 32;
static const int kSixDigitsToBufferSize = 16;
// Helper function for fast formatting of floating-point values.
// The result is the same as printf's "%g", a.k.a. "%.6g"; that is, six
// significant digits are returned, trailing zeros are removed, and numbers
// outside the range 0.0001-999999 are output using scientific notation
// (1.23456e+06). This routine is heavily optimized.
// Required buffer size is `kSixDigitsToBufferSize`.
size_t SixDigitsToBuffer(double d, char* absl_nonnull buffer);
// WARNING: These functions may write more characters than necessary, because
// they are intended for speed. All functions take an output buffer
// as an argument and return a pointer to the last byte they wrote, which is the
// terminating '\0'. At most `kFastToBufferSize` bytes are written.
char* absl_nonnull FastIntToBuffer(int32_t i, char* absl_nonnull buffer)
ABSL_INTERNAL_NEED_MIN_SIZE(buffer, kFastToBufferSize);
char* absl_nonnull FastIntToBuffer(uint32_t n, char* absl_nonnull out_str)
ABSL_INTERNAL_NEED_MIN_SIZE(out_str, kFastToBufferSize);
char* absl_nonnull FastIntToBuffer(int64_t i, char* absl_nonnull buffer)
ABSL_INTERNAL_NEED_MIN_SIZE(buffer, kFastToBufferSize);
char* absl_nonnull FastIntToBuffer(uint64_t i, char* absl_nonnull buffer)
ABSL_INTERNAL_NEED_MIN_SIZE(buffer, kFastToBufferSize);
// For enums and integer types that are not an exact match for the types above,
// use templates to call the appropriate one of the four overloads above.
template <typename int_type>
char* absl_nonnull FastIntToBuffer(int_type i, char* absl_nonnull buffer)
ABSL_INTERNAL_NEED_MIN_SIZE(buffer, kFastToBufferSize) {
static_assert(sizeof(i) <= 64 / 8,
"FastIntToBuffer works only with 64-bit-or-less integers.");
// These conditions are constexpr bools to suppress MSVC warning C4127.
constexpr bool kIsSigned = is_signed<int_type>();
constexpr bool kUse64Bit = sizeof(i) > 32 / 8;
if (kIsSigned) {
if (kUse64Bit) {
return FastIntToBuffer(static_cast<int64_t>(i), buffer);
} else {
return FastIntToBuffer(static_cast<int32_t>(i), buffer);
}
} else {
if (kUse64Bit) {
return FastIntToBuffer(static_cast<uint64_t>(i), buffer);
} else {
return FastIntToBuffer(static_cast<uint32_t>(i), buffer);
}
}
}
// Implementation of SimpleAtoi, generalized to support arbitrary base (used
// with base different from 10 elsewhere in Abseil implementation).
template <typename int_type>
[[nodiscard]] bool safe_strtoi_base(absl::string_view s,
int_type* absl_nonnull out, int base) {
static_assert(sizeof(*out) == 1 || sizeof(*out) == 2 || sizeof(*out) == 4 ||
sizeof(*out) == 8,
"SimpleAtoi works only with 8, 16, 32, or 64-bit integers.");
static_assert(!std::is_floating_point<int_type>::value,
"Use SimpleAtof or SimpleAtod instead.");
bool parsed;
// These conditions are constexpr bools to suppress MSVC warning C4127.
constexpr bool kIsSigned = is_signed<int_type>();
constexpr int kIntTypeSize = sizeof(*out) * 8;
if (kIsSigned) {
if (kIntTypeSize == 64) {
int64_t val;
parsed = numbers_internal::safe_strto64_base(s, &val, base);
*out = static_cast<int_type>(val);
} else if (kIntTypeSize == 32) {
int32_t val;
parsed = numbers_internal::safe_strto32_base(s, &val, base);
*out = static_cast<int_type>(val);
} else if (kIntTypeSize == 16) {
int16_t val;
parsed = numbers_internal::safe_strto16_base(s, &val, base);
*out = static_cast<int_type>(val);
} else if (kIntTypeSize == 8) {
int8_t val;
parsed = numbers_internal::safe_strto8_base(s, &val, base);
*out = static_cast<int_type>(val);
}
} else {
if (kIntTypeSize == 64) {
uint64_t val;
parsed = numbers_internal::safe_strtou64_base(s, &val, base);
*out = static_cast<int_type>(val);
} else if (kIntTypeSize == 32) {
uint32_t val;
parsed = numbers_internal::safe_strtou32_base(s, &val, base);
*out = static_cast<int_type>(val);
} else if (kIntTypeSize == 16) {
uint16_t val;
parsed = numbers_internal::safe_strtou16_base(s, &val, base);
*out = static_cast<int_type>(val);
} else if (kIntTypeSize == 8) {
uint8_t val;
parsed = numbers_internal::safe_strtou8_base(s, &val, base);
*out = static_cast<int_type>(val);
}
}
return parsed;
}
// FastHexToBufferZeroPad16()
//
// Outputs `val` into `out` as if by `snprintf(out, 17, "%016x", val)` but
// without the terminating null character. Thus `out` must be of length >= 16.
// Returns the number of non-pad digits of the output (it can never be zero
// since 0 has one digit).
inline size_t FastHexToBufferZeroPad16(uint64_t val, char* absl_nonnull out) {
#ifdef ABSL_INTERNAL_HAVE_SSSE3
uint64_t be = absl::big_endian::FromHost64(val);
const auto kNibbleMask = _mm_set1_epi8(0xf);
const auto kHexDigits = _mm_setr_epi8('0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f');
auto v = _mm_loadl_epi64(reinterpret_cast<__m128i*>(&be)); // load lo dword
auto v4 = _mm_srli_epi64(v, 4); // shift 4 right
auto il = _mm_unpacklo_epi8(v4, v); // interleave bytes
auto m = _mm_and_si128(il, kNibbleMask); // mask out nibbles
auto hexchars = _mm_shuffle_epi8(kHexDigits, m); // hex chars
_mm_storeu_si128(reinterpret_cast<__m128i*>(out), hexchars);
#else
for (int i = 0; i < 8; ++i) {
auto byte = (val >> (56 - 8 * i)) & 0xFF;
auto* hex = &absl::numbers_internal::kHexTable[byte * 2];
std::memcpy(out + 2 * i, hex, 2);
}
#endif
// | 0x1 so that even 0 has 1 digit.
return 16 - static_cast<size_t>(countl_zero(val | 0x1) / 4);
}
} // namespace numbers_internal
template <typename int_type>
[[nodiscard]] bool SimpleAtoi(absl::string_view str,
int_type* absl_nonnull out) {
return numbers_internal::safe_strtoi_base(str, out, 10);
}
[[nodiscard]] inline bool SimpleAtoi(absl::string_view str,
absl::int128* absl_nonnull out) {
return numbers_internal::safe_strto128_base(str, out, 10);
}
[[nodiscard]] inline bool SimpleAtoi(absl::string_view str,
absl::uint128* absl_nonnull out) {
return numbers_internal::safe_strtou128_base(str, out, 10);
}
template <typename int_type>
[[nodiscard]] bool SimpleHexAtoi(absl::string_view str,
int_type* absl_nonnull out) {
return numbers_internal::safe_strtoi_base(str, out, 16);
}
[[nodiscard]] inline bool SimpleHexAtoi(absl::string_view str,
absl::int128* absl_nonnull out) {
return numbers_internal::safe_strto128_base(str, out, 16);
}
[[nodiscard]] inline bool SimpleHexAtoi(absl::string_view str,
absl::uint128* absl_nonnull out) {
return numbers_internal::safe_strtou128_base(str, out, 16);
}
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_NUMBERS_H_
*§„
psoong/.intermediates/external/abseil-cpp/absl_container_btree_hdrs/gen/my_include_dir/absl/container/btree_map.h±ƒ// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: btree_map.h
// -----------------------------------------------------------------------------
//
// This header file defines B-tree maps: sorted associative containers mapping
// keys to values.
//
// * `absl::btree_map<>`
// * `absl::btree_multimap<>`
//
// These B-tree types are similar to the corresponding types in the STL
// (`std::map` and `std::multimap`) and generally conform to the STL interfaces
// of those types. However, because they are implemented using B-trees, they
// are more efficient in most situations.
//
// Unlike `std::map` and `std::multimap`, which are commonly implemented using
// red-black tree nodes, B-tree maps use more generic B-tree nodes able to hold
// multiple values per node. Holding multiple values per node often makes
// B-tree maps perform better than their `std::map` counterparts, because
// multiple entries can be checked within the same cache hit.
//
// However, these types should not be considered drop-in replacements for
// `std::map` and `std::multimap` as there are some API differences, which are
// noted in this header file. The most consequential differences with respect to
// migrating to b-tree from the STL types are listed in the next paragraph.
// Other API differences are minor.
//
// Importantly, insertions and deletions may invalidate outstanding iterators,
// pointers, and references to elements. Such invalidations are typically only
// an issue if insertion and deletion operations are interleaved with the use of
// more than one iterator, pointer, or reference simultaneously. For this
// reason, `insert()`, `erase()`, and `extract_and_get_next()` return a valid
// iterator at the current position. Another important difference is that
// key-types must be copy-constructible.
//
// There are other API differences: first, btree iterators can be subtracted,
// and this is faster than using `std::distance`. Additionally, btree
// iterators can be advanced via `operator+=` and `operator-=`, which is faster
// than using `std::advance`.
//
// B-tree maps are not exception-safe.
#ifndef ABSL_CONTAINER_BTREE_MAP_H_
#define ABSL_CONTAINER_BTREE_MAP_H_
#include "absl/base/attributes.h"
#include "absl/container/internal/btree.h" // IWYU pragma: export
#include "absl/container/internal/btree_container.h" // IWYU pragma: export
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace container_internal {
template <typename Key, typename Data, typename Compare, typename Alloc,
int TargetNodeSize, bool IsMulti>
struct map_params;
} // namespace container_internal
// absl::btree_map<>
//
// An `absl::btree_map<K, V>` is an ordered associative container of
// unique keys and associated values designed to be a more efficient replacement
// for `std::map` (in most cases).
//
// Keys are sorted using an (optional) comparison function, which defaults to
// `std::less<K>`.
//
// An `absl::btree_map<K, V>` uses a default allocator of
// `std::allocator<std::pair<const K, V>>` to allocate (and deallocate)
// nodes, and construct and destruct values within those nodes. You may
// instead specify a custom allocator `A` (which in turn requires specifying a
// custom comparator `C`) as in `absl::btree_map<K, V, C, A>`.
//
template <typename Key, typename Value, typename Compare = std::less<Key>,
typename Alloc = std::allocator<std::pair<const Key, Value>>>
class ABSL_ATTRIBUTE_OWNER btree_map
: public container_internal::btree_map_container<
container_internal::btree<container_internal::map_params<
Key, Value, Compare, Alloc, /*TargetNodeSize=*/256,
/*IsMulti=*/false>>> {
using Base = typename btree_map::btree_map_container;
public:
// Constructors and Assignment Operators
//
// A `btree_map` supports the same overload set as `std::map`
// for construction and assignment:
//
// * Default constructor
//
// absl::btree_map<int, std::string> map1;
//
// * Initializer List constructor
//
// absl::btree_map<int, std::string> map2 =
// {{1, "huey"}, {2, "dewey"}, {3, "louie"},};
//
// * Copy constructor
//
// absl::btree_map<int, std::string> map3(map2);
//
// * Copy assignment operator
//
// absl::btree_map<int, std::string> map4;
// map4 = map3;
//
// * Move constructor
//
// // Move is guaranteed efficient
// absl::btree_map<int, std::string> map5(std::move(map4));
//
// * Move assignment operator
//
// // May be efficient if allocators are compatible
// absl::btree_map<int, std::string> map6;
// map6 = std::move(map5);
//
// * Range constructor
//
// std::vector<std::pair<int, std::string>> v = {{1, "a"}, {2, "b"}};
// absl::btree_map<int, std::string> map7(v.begin(), v.end());
btree_map() {}
using Base::Base;
// btree_map::begin()
//
// Returns an iterator to the beginning of the `btree_map`.
using Base::begin;
// btree_map::cbegin()
//
// Returns a const iterator to the beginning of the `btree_map`.
using Base::cbegin;
// btree_map::end()
//
// Returns an iterator to the end of the `btree_map`.
using Base::end;
// btree_map::cend()
//
// Returns a const iterator to the end of the `btree_map`.
using Base::cend;
// btree_map::empty()
//
// Returns whether or not the `btree_map` is empty.
using Base::empty;
// btree_map::max_size()
//
// Returns the largest theoretical possible number of elements within a
// `btree_map` under current memory constraints. This value can be thought
// of as the largest value of `std::distance(begin(), end())` for a
// `btree_map<Key, T>`.
using Base::max_size;
// btree_map::size()
//
// Returns the number of elements currently within the `btree_map`.
using Base::size;
// btree_map::clear()
//
// Removes all elements from the `btree_map`. Invalidates any references,
// pointers, or iterators referring to contained elements.
using Base::clear;
// btree_map::erase()
//
// Erases elements within the `btree_map`. If an erase occurs, any references,
// pointers, or iterators are invalidated.
// Overloads are listed below.
//
// iterator erase(iterator position):
// iterator erase(const_iterator position):
//
// Erases the element at `position` of the `btree_map`, returning
// the iterator pointing to the element after the one that was erased
// (or end() if none exists).
//
// iterator erase(const_iterator first, const_iterator last):
//
// Erases the elements in the open interval [`first`, `last`), returning
// the iterator pointing to the element after the interval that was erased
// (or end() if none exists).
//
// template <typename K> size_type erase(const K& key):
//
// Erases the element with the matching key, if it exists, returning the
// number of elements erased (0 or 1).
using Base::erase;
// btree_map::insert()
//
// Inserts an element of the specified value into the `btree_map`,
// returning an iterator pointing to the newly inserted element, provided that
// an element with the given key does not already exist. If an insertion
// occurs, any references, pointers, or iterators are invalidated.
// Overloads are listed below.
//
// std::pair<iterator,bool> insert(const value_type& value):
//
// Inserts a value into the `btree_map`. Returns a pair consisting of an
// iterator to the inserted element (or to the element that prevented the
// insertion) and a bool denoting whether the insertion took place.
//
// std::pair<iterator,bool> insert(value_type&& value):
//
// Inserts a moveable value into the `btree_map`. Returns a pair
// consisting of an iterator to the inserted element (or to the element that
// prevented the insertion) and a bool denoting whether the insertion took
// place.
//
// iterator insert(const_iterator hint, const value_type& value):
// iterator insert(const_iterator hint, value_type&& value):
//
// Inserts a value, using the position of `hint` as a non-binding suggestion
// for where to begin the insertion search. Returns an iterator to the
// inserted element, or to the existing element that prevented the
// insertion.
//
// void insert(InputIterator first, InputIterator last):
//
// Inserts a range of values [`first`, `last`).
//
// void insert(std::initializer_list<init_type> ilist):
//
// Inserts the elements within the initializer list `ilist`.
using Base::insert;
// btree_map::insert_or_assign()
//
// Inserts an element of the specified value into the `btree_map` provided
// that a value with the given key does not already exist, or replaces the
// corresponding mapped type with the forwarded `obj` argument if a key for
// that value already exists, returning an iterator pointing to the newly
// inserted element. Overloads are listed below.
//
// pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj):
// pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj):
//
// Inserts/Assigns (or moves) the element of the specified key into the
// `btree_map`. If the returned bool is true, insertion took place, and if
// it's false, assignment took place.
//
// iterator insert_or_assign(const_iterator hint,
// const key_type& k, M&& obj):
// iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj):
//
// Inserts/Assigns (or moves) the element of the specified key into the
// `btree_map` using the position of `hint` as a non-binding suggestion
// for where to begin the insertion search.
using Base::insert_or_assign;
// btree_map::emplace()
//
// Inserts an element of the specified value by constructing it in-place
// within the `btree_map`, provided that no element with the given key
// already exists.
//
// The element may be constructed even if there already is an element with the
// key in the container, in which case the newly constructed element will be
// destroyed immediately. Prefer `try_emplace()` unless your key is not
// copyable or moveable.
//
// If an insertion occurs, any references, pointers, or iterators are
// invalidated.
using Base::emplace;
// btree_map::emplace_hint()
//
// Inserts an element of the specified value by constructing it in-place
// within the `btree_map`, using the position of `hint` as a non-binding
// suggestion for where to begin the insertion search, and only inserts
// provided that no element with the given key already exists.
//
// The element may be constructed even if there already is an element with the
// key in the container, in which case the newly constructed element will be
// destroyed immediately. Prefer `try_emplace()` unless your key is not
// copyable or moveable.
//
// If an insertion occurs, any references, pointers, or iterators are
// invalidated.
using Base::emplace_hint;
// btree_map::try_emplace()
//
// Inserts an element of the specified value by constructing it in-place
// within the `btree_map`, provided that no element with the given key
// already exists. Unlike `emplace()`, if an element with the given key
// already exists, we guarantee that no element is constructed.
//
// If an insertion occurs, any references, pointers, or iterators are
// invalidated.
//
// Overloads are listed below.
//
// std::pair<iterator, bool> try_emplace(const key_type& k, Args&&... args):
// std::pair<iterator, bool> try_emplace(key_type&& k, Args&&... args):
//
// Inserts (via copy or move) the element of the specified key into the
// `btree_map`.
//
// iterator try_emplace(const_iterator hint,
// const key_type& k, Args&&... args):
// iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args):
//
// Inserts (via copy or move) the element of the specified key into the
// `btree_map` using the position of `hint` as a non-binding suggestion
// for where to begin the insertion search.
using Base::try_emplace;
// btree_map::extract()
//
// Extracts the indicated element, erasing it in the process, and returns it
// as a C++17-compatible node handle. Any references, pointers, or iterators
// are invalidated. Overloads are listed below.
//
// node_type extract(const_iterator position):
//
// Extracts the element at the indicated position and returns a node handle
// owning that extracted data.
//
// template <typename K> node_type extract(const K& k):
//
// Extracts the element with the key matching the passed key value and
// returns a node handle owning that extracted data. If the `btree_map`
// does not contain an element with a matching key, this function returns an
// empty node handle.
//
// NOTE: when compiled in an earlier version of C++ than C++17,
// `node_type::key()` returns a const reference to the key instead of a
// mutable reference. We cannot safely return a mutable reference without
// std::launder (which is not available before C++17).
//
// NOTE: In this context, `node_type` refers to the C++17 concept of a
// move-only type that owns and provides access to the elements in associative
// containers (https://en.cppreference.com/w/cpp/container/node_handle).
// It does NOT refer to the data layout of the underlying btree.
using Base::extract;
// btree_map::extract_and_get_next()
//
// Extracts the indicated element, erasing it in the process, and returns it
// as a C++17-compatible node handle along with an iterator to the next
// element.
//
// extract_and_get_next_return_type extract_and_get_next(
// const_iterator position):
//
// Extracts the element at the indicated position, returns a struct
// containing a member named `node`: a node handle owning that extracted
// data and a member named `next`: an iterator pointing to the next element
// in the btree.
using Base::extract_and_get_next;
// btree_map::merge()
//
// Extracts elements from a given `source` btree_map into this
// `btree_map`. If the destination `btree_map` already contains an
// element with an equivalent key, that element is not extracted.
using Base::merge;
// btree_map::swap(btree_map& other)
//
// Exchanges the contents of this `btree_map` with those of the `other`
// btree_map, avoiding invocation of any move, copy, or swap operations on
// individual elements.
//
// All iterators and references on the `btree_map` remain valid, excepting
// for the past-the-end iterator, which is invalidated.
using Base::swap;
// btree_map::at()
//
// Returns a reference to the mapped value of the element with key equivalent
// to the passed key.
using Base::at;
// btree_map::contains()
//
// template <typename K> bool contains(const K& key) const:
//
// Determines whether an element comparing equal to the given `key` exists
// within the `btree_map`, returning `true` if so or `false` otherwise.
//
// Supports heterogeneous lookup, provided that the map has a compatible
// heterogeneous comparator.
using Base::contains;
// btree_map::count()
//
// template <typename K> size_type count(const K& key) const:
//
// Returns the number of elements comparing equal to the given `key` within
// the `btree_map`. Note that this function will return either `1` or `0`
// since duplicate elements are not allowed within a `btree_map`.
//
// Supports heterogeneous lookup, provided that the map has a compatible
// heterogeneous comparator.
using Base::count;
// btree_map::equal_range()
//
// Returns a half-open range [first, last), defined by a `std::pair` of two
// iterators, containing all elements with the passed key in the `btree_map`.
using Base::equal_range;
// btree_map::find()
//
// template <typename K> iterator find(const K& key):
// template <typename K> const_iterator find(const K& key) const:
//
// Finds an element with the passed `key` within the `btree_map`.
//
// Supports heterogeneous lookup, provided that the map has a compatible
// heterogeneous comparator.
using Base::find;
// btree_map::lower_bound()
//
// template <typename K> iterator lower_bound(const K& key):
// template <typename K> const_iterator lower_bound(const K& key) const:
//
// Finds the first element with a key that is not less than `key` within the
// `btree_map`.
//
// Supports heterogeneous lookup, provided that the map has a compatible
// heterogeneous comparator.
using Base::lower_bound;
// btree_map::upper_bound()
//
// template <typename K> iterator upper_bound(const K& key):
// template <typename K> const_iterator upper_bound(const K& key) const:
//
// Finds the first element with a key that is greater than `key` within the
// `btree_map`.
//
// Supports heterogeneous lookup, provided that the map has a compatible
// heterogeneous comparator.
using Base::upper_bound;
// btree_map::operator[]()
//
// Returns a reference to the value mapped to the passed key within the
// `btree_map`, performing an `insert()` if the key does not already
// exist.
//
// If an insertion occurs, any references, pointers, or iterators are
// invalidated. Otherwise iterators are not affected and references are not
// invalidated. Overloads are listed below.
//
// T& operator[](key_type&& key):
// T& operator[](const key_type& key):
//
// Inserts a value_type object constructed in-place if the element with the
// given key does not exist.
using Base::operator[];
// btree_map::get_allocator()
//
// Returns the allocator function associated with this `btree_map`.
using Base::get_allocator;
// btree_map::key_comp();
//
// Returns the key comparator associated with this `btree_map`.
using Base::key_comp;
// btree_map::value_comp();
//
// Returns the value comparator associated with this `btree_map`.
using Base::value_comp;
};
// absl::swap(absl::btree_map<>, absl::btree_map<>)
//
// Swaps the contents of two `absl::btree_map` containers.
template <typename K, typename V, typename C, typename A>
void swap(btree_map<K, V, C, A> &x, btree_map<K, V, C, A> &y) {
return x.swap(y);
}
// absl::erase_if(absl::btree_map<>, Pred)
//
// Erases all elements that satisfy the predicate pred from the container.
// Returns the number of erased elements.
template <typename K, typename V, typename C, typename A, typename Pred>
typename btree_map<K, V, C, A>::size_type erase_if(
btree_map<K, V, C, A> &map, Pred pred) {
return container_internal::btree_access::erase_if(map, std::move(pred));
}
// absl::btree_multimap
//
// An `absl::btree_multimap<K, V>` is an ordered associative container of
// keys and associated values designed to be a more efficient replacement for
// `std::multimap` (in most cases). Unlike `absl::btree_map`, a B-tree multimap
// allows multiple elements with equivalent keys.
//
// Keys are sorted using an (optional) comparison function, which defaults to
// `std::less<K>`.
//
// An `absl::btree_multimap<K, V>` uses a default allocator of
// `std::allocator<std::pair<const K, V>>` to allocate (and deallocate)
// nodes, and construct and destruct values within those nodes. You may
// instead specify a custom allocator `A` (which in turn requires specifying a
// custom comparator `C`) as in `absl::btree_multimap<K, V, C, A>`.
//
template <typename Key, typename Value, typename Compare = std::less<Key>,
typename Alloc = std::allocator<std::pair<const Key, Value>>>
class ABSL_ATTRIBUTE_OWNER btree_multimap
: public container_internal::btree_multimap_container<
container_internal::btree<container_internal::map_params<
Key, Value, Compare, Alloc, /*TargetNodeSize=*/256,
/*IsMulti=*/true>>> {
using Base = typename btree_multimap::btree_multimap_container;
public:
// Constructors and Assignment Operators
//
// A `btree_multimap` supports the same overload set as `std::multimap`
// for construction and assignment:
//
// * Default constructor
//
// absl::btree_multimap<int, std::string> map1;
//
// * Initializer List constructor
//
// absl::btree_multimap<int, std::string> map2 =
// {{1, "huey"}, {2, "dewey"}, {3, "louie"},};
//
// * Copy constructor
//
// absl::btree_multimap<int, std::string> map3(map2);
//
// * Copy assignment operator
//
// absl::btree_multimap<int, std::string> map4;
// map4 = map3;
//
// * Move constructor
//
// // Move is guaranteed efficient
// absl::btree_multimap<int, std::string> map5(std::move(map4));
//
// * Move assignment operator
//
// // May be efficient if allocators are compatible
// absl::btree_multimap<int, std::string> map6;
// map6 = std::move(map5);
//
// * Range constructor
//
// std::vector<std::pair<int, std::string>> v = {{1, "a"}, {2, "b"}};
// absl::btree_multimap<int, std::string> map7(v.begin(), v.end());
btree_multimap() {}
using Base::Base;
// btree_multimap::begin()
//
// Returns an iterator to the beginning of the `btree_multimap`.
using Base::begin;
// btree_multimap::cbegin()
//
// Returns a const iterator to the beginning of the `btree_multimap`.
using Base::cbegin;
// btree_multimap::end()
//
// Returns an iterator to the end of the `btree_multimap`.
using Base::end;
// btree_multimap::cend()
//
// Returns a const iterator to the end of the `btree_multimap`.
using Base::cend;
// btree_multimap::empty()
//
// Returns whether or not the `btree_multimap` is empty.
using Base::empty;
// btree_multimap::max_size()
//
// Returns the largest theoretical possible number of elements within a
// `btree_multimap` under current memory constraints. This value can be
// thought of as the largest value of `std::distance(begin(), end())` for a
// `btree_multimap<Key, T>`.
using Base::max_size;
// btree_multimap::size()
//
// Returns the number of elements currently within the `btree_multimap`.
using Base::size;
// btree_multimap::clear()
//
// Removes all elements from the `btree_multimap`. Invalidates any references,
// pointers, or iterators referring to contained elements.
using Base::clear;
// btree_multimap::erase()
//
// Erases elements within the `btree_multimap`. If an erase occurs, any
// references, pointers, or iterators are invalidated.
// Overloads are listed below.
//
// iterator erase(iterator position):
// iterator erase(const_iterator position):
//
// Erases the element at `position` of the `btree_multimap`, returning
// the iterator pointing to the element after the one that was erased
// (or end() if none exists).
//
// iterator erase(const_iterator first, const_iterator last):
//
// Erases the elements in the open interval [`first`, `last`), returning
// the iterator pointing to the element after the interval that was erased
// (or end() if none exists).
//
// template <typename K> size_type erase(const K& key):
//
// Erases the elements matching the key, if any exist, returning the
// number of elements erased.
using Base::erase;
// btree_multimap::insert()
//
// Inserts an element of the specified value into the `btree_multimap`,
// returning an iterator pointing to the newly inserted element.
// Any references, pointers, or iterators are invalidated. Overloads are
// listed below.
//
// iterator insert(const value_type& value):
//
// Inserts a value into the `btree_multimap`, returning an iterator to the
// inserted element.
//
// iterator insert(value_type&& value):
//
// Inserts a moveable value into the `btree_multimap`, returning an iterator
// to the inserted element.
//
// iterator insert(const_iterator hint, const value_type& value):
// iterator insert(const_iterator hint, value_type&& value):
//
// Inserts a value, using the position of `hint` as a non-binding suggestion
// for where to begin the insertion search. Returns an iterator to the
// inserted element.
//
// void insert(InputIterator first, InputIterator last):
//
// Inserts a range of values [`first`, `last`).
//
// void insert(std::initializer_list<init_type> ilist):
//
// Inserts the elements within the initializer list `ilist`.
using Base::insert;
// btree_multimap::emplace()
//
// Inserts an element of the specified value by constructing it in-place
// within the `btree_multimap`. Any references, pointers, or iterators are
// invalidated.
using Base::emplace;
// btree_multimap::emplace_hint()
//
// Inserts an element of the specified value by constructing it in-place
// within the `btree_multimap`, using the position of `hint` as a non-binding
// suggestion for where to begin the insertion search.
//
// Any references, pointers, or iterators are invalidated.
using Base::emplace_hint;
// btree_multimap::extract()
//
// Extracts the indicated element, erasing it in the process, and returns it
// as a C++17-compatible node handle. Overloads are listed below.
//
// node_type extract(const_iterator position):
//
// Extracts the element at the indicated position and returns a node handle
// owning that extracted data.
//
// template <typename K> node_type extract(const K& k):
//
// Extracts the element with the key matching the passed key value and
// returns a node handle owning that extracted data. If the `btree_multimap`
// does not contain an element with a matching key, this function returns an
// empty node handle.
//
// NOTE: when compiled in an earlier version of C++ than C++17,
// `node_type::key()` returns a const reference to the key instead of a
// mutable reference. We cannot safely return a mutable reference without
// std::launder (which is not available before C++17).
//
// NOTE: In this context, `node_type` refers to the C++17 concept of a
// move-only type that owns and provides access to the elements in associative
// containers (https://en.cppreference.com/w/cpp/container/node_handle).
// It does NOT refer to the data layout of the underlying btree.
using Base::extract;
// btree_multimap::extract_and_get_next()
//
// Extracts the indicated element, erasing it in the process, and returns it
// as a C++17-compatible node handle along with an iterator to the next
// element.
//
// extract_and_get_next_return_type extract_and_get_next(
// const_iterator position):
//
// Extracts the element at the indicated position, returns a struct
// containing a member named `node`: a node handle owning that extracted
// data and a member named `next`: an iterator pointing to the next element
// in the btree.
using Base::extract_and_get_next;
// btree_multimap::merge()
//
// Extracts all elements from a given `source` btree_multimap into this
// `btree_multimap`.
using Base::merge;
// btree_multimap::swap(btree_multimap& other)
//
// Exchanges the contents of this `btree_multimap` with those of the `other`
// btree_multimap, avoiding invocation of any move, copy, or swap operations
// on individual elements.
//
// All iterators and references on the `btree_multimap` remain valid,
// excepting for the past-the-end iterator, which is invalidated.
using Base::swap;
// btree_multimap::contains()
//
// template <typename K> bool contains(const K& key) const:
//
// Determines whether an element comparing equal to the given `key` exists
// within the `btree_multimap`, returning `true` if so or `false` otherwise.
//
// Supports heterogeneous lookup, provided that the map has a compatible
// heterogeneous comparator.
using Base::contains;
// btree_multimap::count()
//
// template <typename K> size_type count(const K& key) const:
//
// Returns the number of elements comparing equal to the given `key` within
// the `btree_multimap`.
//
// Supports heterogeneous lookup, provided that the map has a compatible
// heterogeneous comparator.
using Base::count;
// btree_multimap::equal_range()
//
// Returns a half-open range [first, last), defined by a `std::pair` of two
// iterators, containing all elements with the passed key in the
// `btree_multimap`.
using Base::equal_range;
// btree_multimap::find()
//
// template <typename K> iterator find(const K& key):
// template <typename K> const_iterator find(const K& key) const:
//
// Finds an element with the passed `key` within the `btree_multimap`.
//
// Supports heterogeneous lookup, provided that the map has a compatible
// heterogeneous comparator.
using Base::find;
// btree_multimap::lower_bound()
//
// template <typename K> iterator lower_bound(const K& key):
// template <typename K> const_iterator lower_bound(const K& key) const:
//
// Finds the first element with a key that is not less than `key` within the
// `btree_multimap`.
//
// Supports heterogeneous lookup, provided that the map has a compatible
// heterogeneous comparator.
using Base::lower_bound;
// btree_multimap::upper_bound()
//
// template <typename K> iterator upper_bound(const K& key):
// template <typename K> const_iterator upper_bound(const K& key) const:
//
// Finds the first element with a key that is greater than `key` within the
// `btree_multimap`.
//
// Supports heterogeneous lookup, provided that the map has a compatible
// heterogeneous comparator.
using Base::upper_bound;
// btree_multimap::get_allocator()
//
// Returns the allocator function associated with this `btree_multimap`.
using Base::get_allocator;
// btree_multimap::key_comp();
//
// Returns the key comparator associated with this `btree_multimap`.
using Base::key_comp;
// btree_multimap::value_comp();
//
// Returns the value comparator associated with this `btree_multimap`.
using Base::value_comp;
};
// absl::swap(absl::btree_multimap<>, absl::btree_multimap<>)
//
// Swaps the contents of two `absl::btree_multimap` containers.
template <typename K, typename V, typename C, typename A>
void swap(btree_multimap<K, V, C, A> &x, btree_multimap<K, V, C, A> &y) {
return x.swap(y);
}
// absl::erase_if(absl::btree_multimap<>, Pred)
//
// Erases all elements that satisfy the predicate pred from the container.
// Returns the number of erased elements.
template <typename K, typename V, typename C, typename A, typename Pred>
typename btree_multimap<K, V, C, A>::size_type erase_if(
btree_multimap<K, V, C, A> &map, Pred pred) {
return container_internal::btree_access::erase_if(map, std::move(pred));
}
namespace container_internal {
// A parameters structure for holding the type parameters for a btree_map.
// Compare and Alloc should be nothrow copy-constructible.
template <typename Key, typename Data, typename Compare, typename Alloc,
int TargetNodeSize, bool IsMulti>
struct map_params : common_params<Key, Compare, Alloc, TargetNodeSize, IsMulti,
/*IsMap=*/true, map_slot_policy<Key, Data>> {
using super_type = typename map_params::common_params;
using mapped_type = Data;
// This type allows us to move keys when it is safe to do so. It is safe
// for maps in which value_type and mutable_value_type are layout compatible.
using slot_policy = typename super_type::slot_policy;
using slot_type = typename super_type::slot_type;
using value_type = typename super_type::value_type;
using init_type = typename super_type::init_type;
template <typename V>
static auto key(const V &value ABSL_ATTRIBUTE_LIFETIME_BOUND)
-> decltype((value.first)) {
return value.first;
}
static const Key &key(const slot_type *s) { return slot_policy::key(s); }
static const Key &key(slot_type *s) { return slot_policy::key(s); }
// For use in node handle.
static auto mutable_key(slot_type *s)
-> decltype(slot_policy::mutable_key(s)) {
return slot_policy::mutable_key(s);
}
static mapped_type &value(value_type *value) { return value->second; }
};
} // namespace container_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_CONTAINER_BTREE_MAP_H_
*™B
`soong/.intermediates/external/abseil-cpp/absl_base_hdrs/gen/my_include_dir/absl/base/call_once.h´A// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: call_once.h
// -----------------------------------------------------------------------------
//
// This header file provides an Abseil version of `std::call_once` for invoking
// a given function at most once, across all threads. This Abseil version is
// faster than the C++11 version and incorporates the C++17 argument-passing
// fix, so that (for example) non-const references may be passed to the invoked
// function.
#ifndef ABSL_BASE_CALL_ONCE_H_
#define ABSL_BASE_CALL_ONCE_H_
#include <algorithm>
#include <atomic>
#include <cstdint>
#include <functional>
#include <type_traits>
#include <utility>
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/internal/low_level_scheduling.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/base/internal/scheduling_mode.h"
#include "absl/base/internal/spinlock_wait.h"
#include "absl/base/macros.h"
#include "absl/base/nullability.h"
#include "absl/base/optimization.h"
#include "absl/base/port.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
class once_flag;
namespace base_internal {
std::atomic<uint32_t>* absl_nonnull ControlWord(
absl::once_flag* absl_nonnull flag);
} // namespace base_internal
// call_once()
//
// For all invocations using a given `once_flag`, invokes a given `fn` exactly
// once across all threads. The first call to `call_once()` with a particular
// `once_flag` argument (that does not throw an exception) will run the
// specified function with the provided `args`; other calls with the same
// `once_flag` argument will not run the function, but will wait
// for the provided function to finish running (if it is still running).
//
// This mechanism provides a safe, simple, and fast mechanism for one-time
// initialization in a multi-threaded process.
//
// Example:
//
// class MyInitClass {
// public:
// ...
// mutable absl::once_flag once_;
//
// MyInitClass* init() const {
// absl::call_once(once_, &MyInitClass::Init, this);
// return ptr_;
// }
//
template <typename Callable, typename... Args>
void call_once(absl::once_flag& flag, Callable&& fn, Args&&... args);
// once_flag
//
// Objects of this type are used to distinguish calls to `call_once()` and
// ensure the provided function is only invoked once across all threads. This
// type is not copyable or movable. However, it has a `constexpr`
// constructor, and is safe to use as a namespace-scoped global variable.
class once_flag {
public:
constexpr once_flag() : control_(0) {}
once_flag(const once_flag&) = delete;
once_flag& operator=(const once_flag&) = delete;
private:
friend std::atomic<uint32_t>* absl_nonnull base_internal::ControlWord(
once_flag* absl_nonnull flag);
std::atomic<uint32_t> control_;
};
//------------------------------------------------------------------------------
// End of public interfaces.
// Implementation details follow.
//------------------------------------------------------------------------------
namespace base_internal {
// Like call_once, but uses KERNEL_ONLY scheduling. Intended to be used to
// initialize entities used by the scheduler implementation.
template <typename Callable, typename... Args>
void LowLevelCallOnce(absl::once_flag* absl_nonnull flag, Callable&& fn,
Args&&... args);
// Disables scheduling while on stack when scheduling mode is non-cooperative.
// No effect for cooperative scheduling modes.
class SchedulingHelper {
public:
explicit SchedulingHelper(base_internal::SchedulingMode mode) : mode_(mode) {
if (mode_ == base_internal::SCHEDULE_KERNEL_ONLY) {
guard_result_ = base_internal::SchedulingGuard::DisableRescheduling();
}
}
~SchedulingHelper() {
if (mode_ == base_internal::SCHEDULE_KERNEL_ONLY) {
base_internal::SchedulingGuard::EnableRescheduling(guard_result_);
}
}
private:
base_internal::SchedulingMode mode_;
bool guard_result_ = false;
};
// Bit patterns for call_once state machine values. Internal implementation
// detail, not for use by clients.
//
// The bit patterns are arbitrarily chosen from unlikely values, to aid in
// debugging. However, kOnceInit must be 0, so that a zero-initialized
// once_flag will be valid for immediate use.
enum {
kOnceInit = 0,
kOnceRunning = 0x65C2937B,
kOnceWaiter = 0x05A308D2,
// A very small constant is chosen for kOnceDone so that it fit in a single
// compare with immediate instruction for most common ISAs. This is verified
// for x86, POWER and ARM.
kOnceDone = 221, // Random Number
};
template <typename Callable, typename... Args>
void
CallOnceImpl(std::atomic<uint32_t>* absl_nonnull control,
base_internal::SchedulingMode scheduling_mode, Callable&& fn,
Args&&... args) {
#ifndef NDEBUG
{
uint32_t old_control = control->load(std::memory_order_relaxed);
if (old_control != kOnceInit &&
old_control != kOnceRunning &&
old_control != kOnceWaiter &&
old_control != kOnceDone) {
ABSL_RAW_LOG(FATAL, "Unexpected value for control word: 0x%lx",
static_cast<unsigned long>(old_control)); // NOLINT
}
}
#endif // NDEBUG
static const base_internal::SpinLockWaitTransition trans[] = {
{kOnceInit, kOnceRunning, true},
{kOnceRunning, kOnceWaiter, false},
{kOnceDone, kOnceDone, true}};
// Must do this before potentially modifying control word's state.
base_internal::SchedulingHelper maybe_disable_scheduling(scheduling_mode);
// Short circuit the simplest case to avoid procedure call overhead.
// The base_internal::SpinLockWait() call returns either kOnceInit or
// kOnceDone. If it returns kOnceDone, it must have loaded the control word
// with std::memory_order_acquire and seen a value of kOnceDone.
uint32_t old_control = kOnceInit;
if (control->compare_exchange_strong(old_control, kOnceRunning,
std::memory_order_relaxed) ||
base_internal::SpinLockWait(control, ABSL_ARRAYSIZE(trans), trans,
scheduling_mode) == kOnceInit) {
std::invoke(std::forward<Callable>(fn), std::forward<Args>(args)...);
old_control =
control->exchange(base_internal::kOnceDone, std::memory_order_release);
if (old_control == base_internal::kOnceWaiter) {
base_internal::SpinLockWake(control, true);
}
} // else *control is already kOnceDone
}
inline std::atomic<uint32_t>* absl_nonnull ControlWord(
once_flag* absl_nonnull flag) {
return &flag->control_;
}
template <typename Callable, typename... Args>
void LowLevelCallOnce(absl::once_flag* absl_nonnull flag, Callable&& fn,
Args&&... args) {
std::atomic<uint32_t>* once = base_internal::ControlWord(flag);
uint32_t s = once->load(std::memory_order_acquire);
if (ABSL_PREDICT_FALSE(s != base_internal::kOnceDone)) {
base_internal::CallOnceImpl(once, base_internal::SCHEDULE_KERNEL_ONLY,
std::forward<Callable>(fn),
std::forward<Args>(args)...);
}
}
} // namespace base_internal
template <typename Callable, typename... Args>
void
call_once(absl::once_flag& flag, Callable&& fn, Args&&... args) {
std::atomic<uint32_t>* once = base_internal::ControlWord(&flag);
uint32_t s = once->load(std::memory_order_acquire);
if (ABSL_PREDICT_FALSE(s != base_internal::kOnceDone)) {
base_internal::CallOnceImpl(
once, base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL,
std::forward<Callable>(fn), std::forward<Args>(args)...);
}
}
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_CALL_ONCE_H_
*Ó#
ƒsoong/.intermediates/external/abseil-cpp/absl_strings_internal_hdrs/gen/my_include_dir/absl/strings/internal/resize_uninitialized.hÊ"//
// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifndef ABSL_STRINGS_INTERNAL_RESIZE_UNINITIALIZED_H_
#define ABSL_STRINGS_INTERNAL_RESIZE_UNINITIALIZED_H_
#include <algorithm>
#include <string>
#include <type_traits>
#include <utility>
#include "absl/base/port.h"
#include "absl/meta/type_traits.h" // for void_t
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace strings_internal {
// In this type trait, we look for a __resize_default_init member function, and
// we use it if available, otherwise, we use resize. We provide HasMember to
// indicate whether __resize_default_init is present.
template <typename string_type, typename = void>
struct ResizeUninitializedTraits {
using HasMember = std::false_type;
static void Resize(string_type* s, size_t new_size) { s->resize(new_size); }
};
// __resize_default_init is provided by libc++ >= 8.0
template <typename string_type>
struct ResizeUninitializedTraits<
string_type, absl::void_t<decltype(std::declval<string_type&>()
.__resize_default_init(237))> > {
using HasMember = std::true_type;
static void Resize(string_type* s, size_t new_size) {
s->__resize_default_init(new_size);
}
};
// Returns true if the std::string implementation supports a resize where
// the new characters added to the std::string are left untouched.
//
// (A better name might be "STLStringSupportsUninitializedResize", alluding to
// the previous function.)
template <typename string_type>
inline constexpr bool STLStringSupportsNontrashingResize(string_type*) {
return ResizeUninitializedTraits<string_type>::HasMember::value;
}
// Like str->resize(new_size), except any new characters added to "*str" as a
// result of resizing may be left uninitialized, rather than being filled with
// '0' bytes. Typically used when code is then going to overwrite the backing
// store of the std::string with known data.
template <typename string_type, typename = void>
inline void STLStringResizeUninitialized(string_type* s, size_t new_size) {
ResizeUninitializedTraits<string_type>::Resize(s, new_size);
}
// Used to ensure exponential growth so that the amortized complexity of
// increasing the string size by a small amount is O(1), in contrast to
// O(str->size()) in the case of precise growth.
template <typename string_type>
void STLStringReserveAmortized(string_type* s, size_t new_size) {
const size_t cap = s->capacity();
if (new_size > cap) {
// Make sure to always grow by at least a factor of 2x.
s->reserve((std::max)(new_size, 2 * cap));
}
}
// In this type trait, we look for an __append_default_init member function, and
// we use it if available, otherwise, we use append.
template <typename string_type, typename = void>
struct AppendUninitializedTraits {
static void Append(string_type* s, size_t n) {
s->append(n, typename string_type::value_type());
}
};
template <typename string_type>
struct AppendUninitializedTraits<
string_type, absl::void_t<decltype(std::declval<string_type&>()
.__append_default_init(237))> > {
static void Append(string_type* s, size_t n) {
s->__append_default_init(n);
}
};
// Like STLStringResizeUninitialized(str, new_size), except guaranteed to use
// exponential growth so that the amortized complexity of increasing the string
// size by a small amount is O(1), in contrast to O(str->size()) in the case of
// precise growth.
template <typename string_type>
void STLStringResizeUninitializedAmortized(string_type* s, size_t new_size) {
const size_t size = s->size();
if (new_size > size) {
AppendUninitializedTraits<string_type>::Append(s, new_size - size);
} else {
s->erase(new_size);
}
}
} // namespace strings_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_RESIZE_UNINITIALIZED_H_
*—9
hsoong/.intermediates/external/abseil-cpp/absl_base_prefetch_hdrs/gen/my_include_dir/absl/base/prefetch.hª8// Copyright 2023 The Abseil Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: prefetch.h
// -----------------------------------------------------------------------------
//
// This header file defines prefetch functions to prefetch memory contents
// into the first level cache (L1) for the current CPU. The prefetch logic
// offered in this header is limited to prefetching first level cachelines
// only, and is aimed at relatively 'simple' prefetching logic.
//
#ifndef ABSL_BASE_PREFETCH_H_
#define ABSL_BASE_PREFETCH_H_
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#if defined(ABSL_INTERNAL_HAVE_SSE)
#include <xmmintrin.h>
#endif
#if defined(_MSC_VER)
#include <intrin.h>
#if defined(ABSL_INTERNAL_HAVE_SSE)
#pragma intrinsic(_mm_prefetch)
#endif
#endif
namespace absl {
ABSL_NAMESPACE_BEGIN
// Moves data into the L1 cache before it is read, or "prefetches" it.
//
// The value of `addr` is the address of the memory to prefetch. If
// the target and compiler support it, data prefetch instructions are
// generated. If the prefetch is done some time before the memory is
// read, it may be in the cache by the time the read occurs.
//
// This method prefetches data with the highest degree of temporal locality;
// data is prefetched where possible into all levels of the cache.
//
// Incorrect or gratuitous use of this function can degrade performance.
// Use this function only when representative benchmarks show an improvement.
//
// Example:
//
// // Computes incremental checksum for `data`.
// int ComputeChecksum(int sum, absl::string_view data);
//
// // Computes cumulative checksum for all values in `data`
// int ComputeChecksum(absl::Span<const std::string> data) {
// int sum = 0;
// auto it = data.begin();
// auto pit = data.begin();
// auto end = data.end();
// for (int dist = 8; dist > 0 && pit != data.end(); --dist, ++pit) {
// absl::PrefetchToLocalCache(pit->data());
// }
// for (; pit != end; ++pit, ++it) {
// sum = ComputeChecksum(sum, *it);
// absl::PrefetchToLocalCache(pit->data());
// }
// for (; it != end; ++it) {
// sum = ComputeChecksum(sum, *it);
// }
// return sum;
// }
//
void PrefetchToLocalCache(const void* addr);
// Moves data into the L1 cache before it is read, or "prefetches" it.
//
// This function is identical to `PrefetchToLocalCache()` except that it has
// non-temporal locality: the fetched data should not be left in any of the
// cache tiers. This is useful for cases where the data is used only once /
// short term, for example, invoking a destructor on an object.
//
// Incorrect or gratuitous use of this function can degrade performance.
// Use this function only when representative benchmarks show an improvement.
//
// Example:
//
// template <typename Iterator>
// void DestroyPointers(Iterator begin, Iterator end) {
// size_t distance = std::min(8U, bars.size());
//
// int dist = 8;
// auto prefetch_it = begin;
// while (prefetch_it != end && --dist;) {
// absl::PrefetchToLocalCacheNta(*prefetch_it++);
// }
// while (prefetch_it != end) {
// delete *begin++;
// absl::PrefetchToLocalCacheNta(*prefetch_it++);
// }
// while (begin != end) {
// delete *begin++;
// }
// }
//
void PrefetchToLocalCacheNta(const void* addr);
// Moves data into the L1 cache with the intent to modify it.
//
// This function is similar to `PrefetchToLocalCache()` except that it
// prefetches cachelines with an 'intent to modify' This typically includes
// invalidating cache entries for this address in all other cache tiers, and an
// exclusive access intent.
//
// Incorrect or gratuitous use of this function can degrade performance. As this
// function can invalidate cached cachelines on other caches and computer cores,
// incorrect usage of this function can have an even greater negative impact
// than incorrect regular prefetches.
// Use this function only when representative benchmarks show an improvement.
//
// Example:
//
// void* Arena::Allocate(size_t size) {
// void* ptr = AllocateBlock(size);
// absl::PrefetchToLocalCacheForWrite(ptr);
// return ptr;
// }
//
void PrefetchToLocalCacheForWrite(const void* addr);
#if ABSL_HAVE_BUILTIN(__builtin_prefetch) || defined(__GNUC__)
#define ABSL_HAVE_PREFETCH 1
// See __builtin_prefetch:
// https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html.
//
ABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCache(
const void* addr) {
__builtin_prefetch(addr, 0, 3);
}
ABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCacheNta(
const void* addr) {
__builtin_prefetch(addr, 0, 0);
}
ABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCacheForWrite(
const void* addr) {
// [x86] gcc/clang don't generate PREFETCHW for __builtin_prefetch(.., 1)
// unless -march=broadwell or newer; this is not generally the default, so we
// manually emit prefetchw. PREFETCHW is recognized as a no-op on older Intel
// processors and has been present on AMD processors since the K6-2.
#if defined(__x86_64__) && !defined(__PRFCHW__)
asm("prefetchw %0" : : "m"(*reinterpret_cast<const char*>(addr)));
#else
__builtin_prefetch(addr, 1, 3);
#endif
}
#elif defined(ABSL_INTERNAL_HAVE_SSE)
#define ABSL_HAVE_PREFETCH 1
ABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCache(
const void* addr) {
_mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_T0);
}
ABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCacheNta(
const void* addr) {
_mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_NTA);
}
ABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCacheForWrite(
const void* addr) {
#if defined(_MM_HINT_ET0)
_mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_ET0);
#elif !defined(_MSC_VER) && defined(__x86_64__)
// _MM_HINT_ET0 is not universally supported. As we commented further
// up, PREFETCHW is recognized as a no-op on older Intel processors
// and has been present on AMD processors since the K6-2. We have this
// disabled for MSVC compilers as this miscompiles on older MSVC compilers.
asm("prefetchw %0" : : "m"(*reinterpret_cast<const char*>(addr)));
#endif
}
#else
ABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCache(
const void* addr) {}
ABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCacheNta(
const void* addr) {}
ABSL_ATTRIBUTE_ALWAYS_INLINE inline void PrefetchToLocalCacheForWrite(
const void* addr) {}
#endif
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_PREFETCH_H_
*
usoong/.intermediates/external/abseil-cpp/absl_strings_hdrs/gen/my_include_dir/absl/strings/internal/string_constant.h‡// Copyright 2020 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_STRINGS_INTERNAL_STRING_CONSTANT_H_
#define ABSL_STRINGS_INTERNAL_STRING_CONSTANT_H_
#include "absl/meta/type_traits.h"
#include "absl/strings/string_view.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace strings_internal {
// StringConstant<T> represents a compile time string constant.
// It can be accessed via its `absl::string_view value` static member.
// It is guaranteed that the `string_view` returned has constant `.data()`,
// constant `.size()` and constant `value[i]` for all `0 <= i < .size()`
//
// The `T` is an opaque type. It is guaranteed that different string constants
// will have different values of `T`. This allows users to associate the string
// constant with other static state at compile time.
//
// Instances should be made using the `MakeStringConstant()` factory function
// below.
template <typename T>
struct StringConstant {
private:
static constexpr bool TryConstexprEval(absl::string_view view) {
return view.empty() || 2 * view[0] != 1;
}
public:
static constexpr absl::string_view value = T{}();
constexpr absl::string_view operator()() const { return value; }
// Check to be sure `view` points to constant data.
// Otherwise, it can't be constant evaluated.
static_assert(TryConstexprEval(value),
"The input string_view must point to constant data.");
};
// Factory function for `StringConstant` instances.
// It supports callables that have a constexpr default constructor and a
// constexpr operator().
// It must return an `absl::string_view` or `const char*` pointing to constant
// data. This is validated at compile time.
template <typename T>
constexpr StringConstant<T> MakeStringConstant(T) {
return {};
}
} // namespace strings_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_STRING_CONSTANT_H_
*«'
„soong/.intermediates/external/abseil-cpp/absl_synchronization_hdrs/gen/my_include_dir/absl/synchronization/internal/per_thread_sem.h¡&// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// PerThreadSem is a low-level synchronization primitive controlling the
// runnability of a single thread, used internally by Mutex and CondVar.
//
// This is NOT a general-purpose synchronization mechanism, and should not be
// used directly by applications. Applications should use Mutex and CondVar.
//
// The semantics of PerThreadSem are the same as that of a counting semaphore.
// Each thread maintains an abstract "count" value associated with its identity.
#ifndef ABSL_SYNCHRONIZATION_INTERNAL_PER_THREAD_SEM_H_
#define ABSL_SYNCHRONIZATION_INTERNAL_PER_THREAD_SEM_H_
#include <atomic>
#include "absl/base/internal/thread_identity.h"
#include "absl/synchronization/internal/create_thread_identity.h"
#include "absl/synchronization/internal/kernel_timeout.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
class Mutex;
namespace synchronization_internal {
class PerThreadSem {
public:
PerThreadSem() = delete;
PerThreadSem(const PerThreadSem&) = delete;
PerThreadSem& operator=(const PerThreadSem&) = delete;
// Routine invoked periodically (once a second) by a background thread.
// Has no effect on user-visible state.
static void Tick(base_internal::ThreadIdentity* identity);
// ---------------------------------------------------------------------------
// Routines used by autosizing threadpools to detect when threads are
// blocked. Each thread has a counter pointer, initially zero. If non-zero,
// the implementation atomically increments the counter when it blocks on a
// semaphore, a decrements it again when it wakes. This allows a threadpool
// to keep track of how many of its threads are blocked.
// SetThreadBlockedCounter() should be used only by threadpool
// implementations. GetThreadBlockedCounter() should be used by modules that
// block threads; if the pointer returned is non-zero, the location should be
// incremented before the thread blocks, and decremented after it wakes.
static void SetThreadBlockedCounter(std::atomic<int> *counter);
static std::atomic<int> *GetThreadBlockedCounter();
private:
// Create the PerThreadSem associated with "identity". Initializes count=0.
// REQUIRES: May only be called by ThreadIdentity.
static inline void Init(base_internal::ThreadIdentity* identity);
// Increments "identity"'s count.
static inline void Post(base_internal::ThreadIdentity* identity);
// Waits until either our count > 0 or t has expired.
// If count > 0, decrements count and returns true. Otherwise returns false.
// !t.has_timeout() => Wait(t) will return true.
static inline bool Wait(KernelTimeout t);
// Permitted callers.
friend class PerThreadSemTest;
friend class absl::Mutex;
friend void OneTimeInitThreadIdentity(absl::base_internal::ThreadIdentity*);
};
} // namespace synchronization_internal
ABSL_NAMESPACE_END
} // namespace absl
// In some build configurations we pass --detect-odr-violations to the
// gold linker. This causes it to flag weak symbol overrides as ODR
// violations. Because ODR only applies to C++ and not C,
// --detect-odr-violations ignores symbols not mangled with C++ names.
// By changing our extension points to be extern "C", we dodge this
// check.
extern "C" {
void ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemInit)(
absl::base_internal::ThreadIdentity* identity);
void ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemPost)(
absl::base_internal::ThreadIdentity* identity);
bool ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemWait)(
absl::synchronization_internal::KernelTimeout t);
void ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemPoke)(
absl::base_internal::ThreadIdentity* identity);
} // extern "C"
void absl::synchronization_internal::PerThreadSem::Init(
absl::base_internal::ThreadIdentity* identity) {
ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemInit)(identity);
}
void absl::synchronization_internal::PerThreadSem::Post(
absl::base_internal::ThreadIdentity* identity) {
ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemPost)(identity);
}
bool absl::synchronization_internal::PerThreadSem::Wait(
absl::synchronization_internal::KernelTimeout t) {
return ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemWait)(t);
}
#endif // ABSL_SYNCHRONIZATION_INTERNAL_PER_THREAD_SEM_H_
*Ñ
nsoong/.intermediates/external/abseil-cpp/absl_base_hdrs/gen/my_include_dir/absl/base/internal/per_thread_tls.hÞ // Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_BASE_INTERNAL_PER_THREAD_TLS_H_
#define ABSL_BASE_INTERNAL_PER_THREAD_TLS_H_
// This header defines two macros:
//
// If the platform supports thread-local storage:
//
// * ABSL_PER_THREAD_TLS_KEYWORD is the C keyword needed to declare a
// thread-local variable
// * ABSL_PER_THREAD_TLS is 1
//
// Otherwise:
//
// * ABSL_PER_THREAD_TLS_KEYWORD is empty
// * ABSL_PER_THREAD_TLS is 0
//
// Microsoft C supports thread-local storage.
// GCC supports it if the appropriate version of glibc is available,
// which the programmer can indicate by defining ABSL_HAVE_TLS
#include "absl/base/port.h" // For ABSL_HAVE_TLS
#if defined(ABSL_PER_THREAD_TLS)
#error ABSL_PER_THREAD_TLS cannot be directly set
#elif defined(ABSL_PER_THREAD_TLS_KEYWORD)
#error ABSL_PER_THREAD_TLS_KEYWORD cannot be directly set
#elif defined(ABSL_HAVE_TLS)
#define ABSL_PER_THREAD_TLS_KEYWORD __thread
#define ABSL_PER_THREAD_TLS 1
#elif defined(_MSC_VER)
#define ABSL_PER_THREAD_TLS_KEYWORD __declspec(thread)
#define ABSL_PER_THREAD_TLS 1
#else
#define ABSL_PER_THREAD_TLS_KEYWORD
#define ABSL_PER_THREAD_TLS 0
#endif
#endif // ABSL_BASE_INTERNAL_PER_THREAD_TLS_H_
*ò%
soong/.intermediates/external/abseil-cpp/absl_base_malloc_internal_hdrs/gen/my_include_dir/absl/base/internal/low_level_alloc.hî$// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifndef ABSL_BASE_INTERNAL_LOW_LEVEL_ALLOC_H_
#define ABSL_BASE_INTERNAL_LOW_LEVEL_ALLOC_H_
// A simple thread-safe memory allocator that does not depend on
// mutexes or thread-specific data. It is intended to be used
// sparingly, and only when malloc() would introduce an unwanted
// dependency, such as inside the heap-checker, or the Mutex
// implementation.
// IWYU pragma: private, include "base/low_level_alloc.h"
#include <sys/types.h>
#include <cstdint>
#include "absl/base/attributes.h"
#include "absl/base/config.h"
// LowLevelAlloc requires that the platform support low-level
// allocation of virtual memory. Platforms lacking this cannot use
// LowLevelAlloc.
#ifdef ABSL_LOW_LEVEL_ALLOC_MISSING
#error ABSL_LOW_LEVEL_ALLOC_MISSING cannot be directly set
#elif !defined(ABSL_HAVE_MMAP) && !defined(_WIN32)
#define ABSL_LOW_LEVEL_ALLOC_MISSING 1
#endif
// Using LowLevelAlloc with kAsyncSignalSafe isn't supported on Windows or
// asm.js / WebAssembly.
// See https://kripken.github.io/emscripten-site/docs/porting/pthreads.html
// for more information.
#ifdef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING
#error ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING cannot be directly set
#elif defined(_WIN32) || defined(__asmjs__) || defined(__wasm__) || \
defined(__hexagon__)
#define ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING 1
#endif
#include <cstddef>
#include "absl/base/port.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace base_internal {
class LowLevelAlloc {
public:
struct Arena; // an arena from which memory may be allocated
// Returns a pointer to a block of at least "request" bytes
// that have been newly allocated from the specific arena.
// for Alloc() call the DefaultArena() is used.
// Returns 0 if passed request==0.
// Does not return 0 under other circumstances; it crashes if memory
// is not available.
static void *Alloc(size_t request) ABSL_ATTRIBUTE_SECTION(malloc_hook);
static void *AllocWithArena(size_t request, Arena *arena)
ABSL_ATTRIBUTE_SECTION(malloc_hook);
// Deallocates a region of memory that was previously allocated with
// Alloc(). Does nothing if passed 0. "s" must be either 0,
// or must have been returned from a call to Alloc() and not yet passed to
// Free() since that call to Alloc(). The space is returned to the arena
// from which it was allocated.
static void Free(void *s) ABSL_ATTRIBUTE_SECTION(malloc_hook);
// ABSL_ATTRIBUTE_SECTION(malloc_hook) for Alloc* and Free
// are to put all callers of MallocHook::Invoke* in this module
// into special section,
// so that MallocHook::GetCallerStackTrace can function accurately.
// Create a new arena.
// The root metadata for the new arena is allocated in the
// meta_data_arena; the DefaultArena() can be passed for meta_data_arena.
// These values may be ored into flags:
enum {
// Report calls to Alloc() and Free() via the MallocHook interface.
// Set in the DefaultArena.
kCallMallocHook = 0x0001,
#ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING
// Make calls to Alloc(), Free() be async-signal-safe. Not set in
// DefaultArena(). Not supported on all platforms.
kAsyncSignalSafe = 0x0002,
#endif
};
// Construct a new arena. The allocation of the underlying metadata honors
// the provided flags. For example, the call NewArena(kAsyncSignalSafe)
// is itself async-signal-safe, as well as generatating an arena that provides
// async-signal-safe Alloc/Free.
static Arena *NewArena(uint32_t flags);
// Destroys an arena allocated by NewArena and returns true,
// provided no allocated blocks remain in the arena.
// If allocated blocks remain in the arena, does nothing and
// returns false.
// It is illegal to attempt to destroy the DefaultArena().
static bool DeleteArena(Arena *arena);
// The default arena that always exists.
static Arena *DefaultArena();
private:
LowLevelAlloc(); // no instances
};
} // namespace base_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_INTERNAL_LOW_LEVEL_ALLOC_H_
*΍
rsoong/.intermediates/external/abseil-cpp/absl_synchronization_hdrs/gen/my_include_dir/absl/synchronization/mutex.h֌// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// mutex.h
// -----------------------------------------------------------------------------
//
// This header file defines a `Mutex` -- a mutually exclusive lock -- and the
// most common type of synchronization primitive for facilitating locks on
// shared resources. A mutex is used to prevent multiple threads from accessing
// and/or writing to a shared resource concurrently.
//
// Unlike a `std::mutex`, the Abseil `Mutex` provides the following additional
// features:
// * Conditional predicates intrinsic to the `Mutex` object
// * Shared/reader locks, in addition to standard exclusive/writer locks
// * Deadlock detection and debug support.
//
// The following helper classes are also defined within this file:
//
// MutexLock - An RAII wrapper to acquire and release a `Mutex` for exclusive/
// write access within the current scope.
//
// ReaderMutexLock
// - An RAII wrapper to acquire and release a `Mutex` for shared/read
// access within the current scope.
//
// WriterMutexLock
// - Effectively an alias for `MutexLock` above, designed for use in
// distinguishing reader and writer locks within code.
//
// In addition to simple mutex locks, this file also defines ways to perform
// locking under certain conditions.
//
// Condition - (Preferred) Used to wait for a particular predicate that
// depends on state protected by the `Mutex` to become true.
// CondVar - A lower-level variant of `Condition` that relies on
// application code to explicitly signal the `CondVar` when
// a condition has been met.
//
// See below for more information on using `Condition` or `CondVar`.
//
// Mutexes and mutex behavior can be quite complicated. The information within
// this header file is limited, as a result. Please consult the Mutex guide for
// more complete information and examples.
#ifndef ABSL_SYNCHRONIZATION_MUTEX_H_
#define ABSL_SYNCHRONIZATION_MUTEX_H_
#include <atomic>
#include <cstdint>
#include <cstring>
#include <iterator>
#include <string>
#include "absl/base/attributes.h"
#include "absl/base/const_init.h"
#include "absl/base/internal/identity.h"
#include "absl/base/internal/low_level_alloc.h"
#include "absl/base/internal/thread_identity.h"
#include "absl/base/internal/tsan_mutex_interface.h"
#include "absl/base/nullability.h"
#include "absl/base/port.h"
#include "absl/base/thread_annotations.h"
#include "absl/synchronization/internal/kernel_timeout.h"
#include "absl/synchronization/internal/per_thread_sem.h"
#include "absl/time/time.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
class Condition;
struct SynchWaitParams;
// -----------------------------------------------------------------------------
// Mutex
// -----------------------------------------------------------------------------
//
// A `Mutex` is a non-reentrant (aka non-recursive) Mutually Exclusive lock
// on some resource, typically a variable or data structure with associated
// invariants. Proper usage of mutexes prevents concurrent access by different
// threads to the same resource.
//
// A `Mutex` has two basic operations: `Mutex::Lock()` and `Mutex::Unlock()`.
// The `Lock()` operation *acquires* a `Mutex` (in a state known as an
// *exclusive* -- or *write* -- lock), and the `Unlock()` operation *releases* a
// Mutex. During the span of time between the Lock() and Unlock() operations,
// a mutex is said to be *held*. By design, all mutexes support exclusive/write
// locks, as this is the most common way to use a mutex.
//
// Mutex operations are only allowed under certain conditions; otherwise an
// operation is "invalid", and disallowed by the API. The conditions concern
// both the current state of the mutex and the identity of the threads that
// are performing the operations.
//
// The `Mutex` state machine for basic lock/unlock operations is quite simple:
//
// | | Lock() | Unlock() |
// |----------------+------------------------+----------|
// | Free | Exclusive | invalid |
// | Exclusive | blocks, then exclusive | Free |
//
// The full conditions are as follows.
//
// * Calls to `Unlock()` require that the mutex be held, and must be made in the
// same thread that performed the corresponding `Lock()` operation which
// acquired the mutex; otherwise the call is invalid.
//
// * The mutex being non-reentrant (or non-recursive) means that a call to
// `Lock()` or `TryLock()` must not be made in a thread that already holds the
// mutex; such a call is invalid.
//
// * In other words, the state of being "held" has both a temporal component
// (from `Lock()` until `Unlock()`) as well as a thread identity component:
// the mutex is held *by a particular thread*.
//
// An "invalid" operation has undefined behavior. The `Mutex` implementation
// is allowed to do anything on an invalid call, including, but not limited to,
// crashing with a useful error message, silently succeeding, or corrupting
// data structures. In debug mode, the implementation may crash with a useful
// error message.
//
// `Mutex` is not guaranteed to be "fair" in prioritizing waiting threads; it
// is, however, approximately fair over long periods, and starvation-free for
// threads at the same priority.
//
// The lock/unlock primitives are now annotated with lock annotations
// defined in (base/thread_annotations.h). When writing multi-threaded code,
// you should use lock annotations whenever possible to document your lock
// synchronization policy. Besides acting as documentation, these annotations
// also help compilers or static analysis tools to identify and warn about
// issues that could potentially result in race conditions and deadlocks.
//
// For more information about the lock annotations, please see
// [Thread Safety
// Analysis](http://clang.llvm.org/docs/ThreadSafetyAnalysis.html) in the Clang
// documentation.
//
// See also `MutexLock`, below, for scoped `Mutex` acquisition.
class ABSL_LOCKABLE ABSL_ATTRIBUTE_WARN_UNUSED Mutex {
public:
// Creates a `Mutex` that is not held by anyone. This constructor is
// typically used for Mutexes allocated on the heap or the stack.
//
// To create `Mutex` instances with static storage duration
// (e.g. a namespace-scoped or global variable), see
// `Mutex::Mutex(absl::kConstInit)` below instead.
Mutex();
// Creates a mutex with static storage duration. A global variable
// constructed this way avoids the lifetime issues that can occur on program
// startup and shutdown. (See absl/base/const_init.h.)
//
// For Mutexes allocated on the heap and stack, instead use the default
// constructor, which can interact more fully with the thread sanitizer.
//
// Example usage:
// namespace foo {
// ABSL_CONST_INIT absl::Mutex mu(absl::kConstInit);
// }
explicit constexpr Mutex(absl::ConstInitType);
~Mutex();
// Mutex::Lock()
//
// Blocks the calling thread, if necessary, until this `Mutex` is free, and
// then acquires it exclusively. (This lock is also known as a "write lock.")
void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION();
// Mutex::Unlock()
//
// Releases this `Mutex` and returns it from the exclusive/write state to the
// free state. Calling thread must hold the `Mutex` exclusively.
void Unlock() ABSL_UNLOCK_FUNCTION();
// Mutex::TryLock()
//
// If the mutex can be acquired without blocking, does so exclusively and
// returns `true`. Otherwise, returns `false`. Returns `true` with high
// probability if the `Mutex` was free.
[[nodiscard]] bool TryLock() ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true);
// Mutex::AssertHeld()
//
// Require that the mutex be held exclusively (write mode) by this thread.
//
// If the mutex is not currently held by this thread, this function may report
// an error (typically by crashing with a diagnostic) or it may do nothing.
// This function is intended only as a tool to assist debugging; it doesn't
// guarantee correctness.
void AssertHeld() const ABSL_ASSERT_EXCLUSIVE_LOCK();
// ---------------------------------------------------------------------------
// Reader-Writer Locking
// ---------------------------------------------------------------------------
// A Mutex can also be used as a starvation-free reader-writer lock.
// Neither read-locks nor write-locks are reentrant/recursive to avoid
// potential client programming errors.
//
// The Mutex API provides `Writer*()` aliases for the existing `Lock()`,
// `Unlock()` and `TryLock()` methods for use within applications mixing
// reader/writer locks. Using `Reader*()` and `Writer*()` operations in this
// manner can make locking behavior clearer when mixing read and write modes.
//
// Introducing reader locks necessarily complicates the `Mutex` state
// machine somewhat. The table below illustrates the allowed state transitions
// of a mutex in such cases. Note that ReaderLock() may block even if the lock
// is held in shared mode; this occurs when another thread is blocked on a
// call to WriterLock().
//
// ---------------------------------------------------------------------------
// Operation: WriterLock() Unlock() ReaderLock() ReaderUnlock()
// ---------------------------------------------------------------------------
// State
// ---------------------------------------------------------------------------
// Free Exclusive invalid Shared(1) invalid
// Shared(1) blocks invalid Shared(2) or blocks Free
// Shared(n) n>1 blocks invalid Shared(n+1) or blocks Shared(n-1)
// Exclusive blocks Free blocks invalid
// ---------------------------------------------------------------------------
//
// In comments below, "shared" refers to a state of Shared(n) for any n > 0.
// Mutex::ReaderLock()
//
// Blocks the calling thread, if necessary, until this `Mutex` is either free,
// or in shared mode, and then acquires a share of it. Note that
// `ReaderLock()` will block if some other thread has an exclusive/writer lock
// on the mutex.
void ReaderLock() ABSL_SHARED_LOCK_FUNCTION();
// Mutex::ReaderUnlock()
//
// Releases a read share of this `Mutex`. `ReaderUnlock` may return a mutex to
// the free state if this thread holds the last reader lock on the mutex. Note
// that you cannot call `ReaderUnlock()` on a mutex held in write mode.
void ReaderUnlock() ABSL_UNLOCK_FUNCTION();
// Mutex::ReaderTryLock()
//
// If the mutex can be acquired without blocking, acquires this mutex for
// shared access and returns `true`. Otherwise, returns `false`. Returns
// `true` with high probability if the `Mutex` was free or shared.
[[nodiscard]] bool ReaderTryLock() ABSL_SHARED_TRYLOCK_FUNCTION(true);
// Mutex::AssertReaderHeld()
//
// Require that the mutex be held at least in shared mode (read mode) by this
// thread.
//
// If the mutex is not currently held by this thread, this function may report
// an error (typically by crashing with a diagnostic) or it may do nothing.
// This function is intended only as a tool to assist debugging; it doesn't
// guarantee correctness.
void AssertReaderHeld() const ABSL_ASSERT_SHARED_LOCK();
// Mutex::WriterLock()
// Mutex::WriterUnlock()
// Mutex::WriterTryLock()
//
// Aliases for `Mutex::Lock()`, `Mutex::Unlock()`, and `Mutex::TryLock()`.
//
// These methods may be used (along with the complementary `Reader*()`
// methods) to distinguish simple exclusive `Mutex` usage (`Lock()`,
// etc.) from reader/writer lock usage.
void WriterLock() ABSL_EXCLUSIVE_LOCK_FUNCTION() { this->Lock(); }
void WriterUnlock() ABSL_UNLOCK_FUNCTION() { this->Unlock(); }
[[nodiscard]] bool WriterTryLock() ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true) {
return this->TryLock();
}
// ---------------------------------------------------------------------------
// Conditional Critical Regions
// ---------------------------------------------------------------------------
// Conditional usage of a `Mutex` can occur using two distinct paradigms:
//
// * Use of `Mutex` member functions with `Condition` objects.
// * Use of the separate `CondVar` abstraction.
//
// In general, prefer use of `Condition` and the `Mutex` member functions
// listed below over `CondVar`. When there are multiple threads waiting on
// distinctly different conditions, however, a battery of `CondVar`s may be
// more efficient. This section discusses use of `Condition` objects.
//
// `Mutex` contains member functions for performing lock operations only under
// certain conditions, of class `Condition`. For correctness, the `Condition`
// must return a boolean that is a pure function, only of state protected by
// the `Mutex`. The condition must be invariant w.r.t. environmental state
// such as thread, cpu id, or time, and must be `noexcept`. The condition will
// always be invoked with the mutex held in at least read mode, so you should
// not block it for long periods or sleep it on a timer.
//
// Since a condition must not depend directly on the current time, use
// `*WithTimeout()` member function variants to make your condition
// effectively true after a given duration, or `*WithDeadline()` variants to
// make your condition effectively true after a given time.
//
// The condition function should have no side-effects aside from debug
// logging; as a special exception, the function may acquire other mutexes
// provided it releases all those that it acquires. (This exception was
// required to allow logging.)
// Mutex::Await()
//
// Unlocks this `Mutex` and blocks until simultaneously both `cond` is `true`
// and this `Mutex` can be reacquired, then reacquires this `Mutex` in the
// same mode in which it was previously held. If the condition is initially
// `true`, `Await()` *may* skip the release/re-acquire step.
//
// `Await()` requires that this thread holds this `Mutex` in some mode.
void Await(const Condition& cond) {
AwaitCommon(cond, synchronization_internal::KernelTimeout::Never());
}
// Mutex::LockWhen()
// Mutex::ReaderLockWhen()
// Mutex::WriterLockWhen()
//
// Blocks until simultaneously both `cond` is `true` and this `Mutex` can
// be acquired, then atomically acquires this `Mutex`. `LockWhen()` is
// logically equivalent to `*Lock(); Await();` though they may have different
// performance characteristics.
void LockWhen(const Condition& cond) ABSL_EXCLUSIVE_LOCK_FUNCTION() {
LockWhenCommon(cond, synchronization_internal::KernelTimeout::Never(),
true);
}
void ReaderLockWhen(const Condition& cond) ABSL_SHARED_LOCK_FUNCTION() {
LockWhenCommon(cond, synchronization_internal::KernelTimeout::Never(),
false);
}
void WriterLockWhen(const Condition& cond) ABSL_EXCLUSIVE_LOCK_FUNCTION() {
this->LockWhen(cond);
}
// ---------------------------------------------------------------------------
// Mutex Variants with Timeouts/Deadlines
// ---------------------------------------------------------------------------
// Mutex::AwaitWithTimeout()
// Mutex::AwaitWithDeadline()
//
// Unlocks this `Mutex` and blocks until simultaneously:
// - either `cond` is true or the {timeout has expired, deadline has passed}
// and
// - this `Mutex` can be reacquired,
// then reacquire this `Mutex` in the same mode in which it was previously
// held, returning `true` iff `cond` is `true` on return.
//
// If the condition is initially `true`, the implementation *may* skip the
// release/re-acquire step and return immediately.
//
// Deadlines in the past are equivalent to an immediate deadline.
// Negative timeouts are equivalent to a zero timeout.
//
// This method requires that this thread holds this `Mutex` in some mode.
bool AwaitWithTimeout(const Condition& cond, absl::Duration timeout) {
return AwaitCommon(cond, synchronization_internal::KernelTimeout{timeout});
}
bool AwaitWithDeadline(const Condition& cond, absl::Time deadline) {
return AwaitCommon(cond, synchronization_internal::KernelTimeout{deadline});
}
// Mutex::LockWhenWithTimeout()
// Mutex::ReaderLockWhenWithTimeout()
// Mutex::WriterLockWhenWithTimeout()
//
// Blocks until simultaneously both:
// - either `cond` is `true` or the timeout has expired, and
// - this `Mutex` can be acquired,
// then atomically acquires this `Mutex`, returning `true` iff `cond` is
// `true` on return.
//
// Negative timeouts are equivalent to a zero timeout.
bool LockWhenWithTimeout(const Condition& cond, absl::Duration timeout)
ABSL_EXCLUSIVE_LOCK_FUNCTION() {
return LockWhenCommon(
cond, synchronization_internal::KernelTimeout{timeout}, true);
}
bool ReaderLockWhenWithTimeout(const Condition& cond, absl::Duration timeout)
ABSL_SHARED_LOCK_FUNCTION() {
return LockWhenCommon(
cond, synchronization_internal::KernelTimeout{timeout}, false);
}
bool WriterLockWhenWithTimeout(const Condition& cond, absl::Duration timeout)
ABSL_EXCLUSIVE_LOCK_FUNCTION() {
return this->LockWhenWithTimeout(cond, timeout);
}
// Mutex::LockWhenWithDeadline()
// Mutex::ReaderLockWhenWithDeadline()
// Mutex::WriterLockWhenWithDeadline()
//
// Blocks until simultaneously both:
// - either `cond` is `true` or the deadline has been passed, and
// - this `Mutex` can be acquired,
// then atomically acquires this Mutex, returning `true` iff `cond` is `true`
// on return.
//
// Deadlines in the past are equivalent to an immediate deadline.
bool LockWhenWithDeadline(const Condition& cond, absl::Time deadline)
ABSL_EXCLUSIVE_LOCK_FUNCTION() {
return LockWhenCommon(
cond, synchronization_internal::KernelTimeout{deadline}, true);
}
bool ReaderLockWhenWithDeadline(const Condition& cond, absl::Time deadline)
ABSL_SHARED_LOCK_FUNCTION() {
return LockWhenCommon(
cond, synchronization_internal::KernelTimeout{deadline}, false);
}
bool WriterLockWhenWithDeadline(const Condition& cond, absl::Time deadline)
ABSL_EXCLUSIVE_LOCK_FUNCTION() {
return this->LockWhenWithDeadline(cond, deadline);
}
// ---------------------------------------------------------------------------
// Debug Support: Invariant Checking, Deadlock Detection, Logging.
// ---------------------------------------------------------------------------
// Mutex::EnableInvariantDebugging()
//
// If `invariant`!=null and if invariant debugging has been enabled globally,
// cause `(*invariant)(arg)` to be called at moments when the invariant for
// this `Mutex` should hold (for example: just after acquire, just before
// release).
//
// The routine `invariant` should have no side-effects since it is not
// guaranteed how many times it will be called; it should check the invariant
// and crash if it does not hold. Enabling global invariant debugging may
// substantially reduce `Mutex` performance; it should be set only for
// non-production runs. Optimization options may also disable invariant
// checks.
void EnableInvariantDebugging(
void (*absl_nullable invariant)(void* absl_nullability_unknown),
void* absl_nullability_unknown arg);
// Mutex::EnableDebugLog()
//
// Cause all subsequent uses of this `Mutex` to be logged via
// `ABSL_RAW_LOG(INFO)`. Log entries are tagged with `name` if no previous
// call to `EnableInvariantDebugging()` or `EnableDebugLog()` has been made.
//
// Note: This method substantially reduces `Mutex` performance.
void EnableDebugLog(const char* absl_nullable name);
// Deadlock detection
// Mutex::ForgetDeadlockInfo()
//
// Forget any deadlock-detection information previously gathered
// about this `Mutex`. Call this method in debug mode when the lock ordering
// of a `Mutex` changes.
void ForgetDeadlockInfo();
// Mutex::AssertNotHeld()
//
// Return immediately if this thread does not hold this `Mutex` in any
// mode; otherwise, may report an error (typically by crashing with a
// diagnostic), or may return immediately.
//
// Currently this check is performed only if all of:
// - in debug mode
// - SetMutexDeadlockDetectionMode() has been set to kReport or kAbort
// - number of locks concurrently held by this thread is not large.
// are true.
void AssertNotHeld() const;
// Special cases.
// A `MuHow` is a constant that indicates how a lock should be acquired.
// Internal implementation detail. Clients should ignore.
typedef const struct MuHowS* MuHow;
// Mutex::InternalAttemptToUseMutexInFatalSignalHandler()
//
// Causes the `Mutex` implementation to prepare itself for re-entry caused by
// future use of `Mutex` within a fatal signal handler. This method is
// intended for use only for last-ditch attempts to log crash information.
// It does not guarantee that attempts to use Mutexes within the handler will
// not deadlock; it merely makes other faults less likely.
//
// WARNING: This routine must be invoked from a signal handler, and the
// signal handler must either loop forever or terminate the process.
// Attempts to return from (or `longjmp` out of) the signal handler once this
// call has been made may cause arbitrary program behaviour including
// crashes and deadlocks.
static void InternalAttemptToUseMutexInFatalSignalHandler();
private:
std::atomic<intptr_t> mu_; // The Mutex state.
// Post()/Wait() versus associated PerThreadSem; in class for required
// friendship with PerThreadSem.
static void IncrementSynchSem(Mutex* absl_nonnull mu,
base_internal::PerThreadSynch* absl_nonnull w);
static bool DecrementSynchSem(Mutex* absl_nonnull mu,
base_internal::PerThreadSynch* absl_nonnull w,
synchronization_internal::KernelTimeout t);
// slow path acquire
void LockSlowLoop(SynchWaitParams* absl_nonnull waitp, int flags);
// wrappers around LockSlowLoop()
bool LockSlowWithDeadline(MuHow absl_nonnull how,
const Condition* absl_nullable cond,
synchronization_internal::KernelTimeout t,
int flags);
void LockSlow(MuHow absl_nonnull how, const Condition* absl_nullable cond,
int flags) ABSL_ATTRIBUTE_COLD;
// slow path release
void UnlockSlow(SynchWaitParams* absl_nullable waitp) ABSL_ATTRIBUTE_COLD;
// TryLock slow path.
bool TryLockSlow();
// ReaderTryLock slow path.
bool ReaderTryLockSlow();
// Common code between Await() and AwaitWithTimeout/Deadline()
bool AwaitCommon(const Condition& cond,
synchronization_internal::KernelTimeout t);
bool LockWhenCommon(const Condition& cond,
synchronization_internal::KernelTimeout t, bool write);
// Attempt to remove thread s from queue.
void TryRemove(base_internal::PerThreadSynch* absl_nonnull s);
// Block a thread on mutex.
void Block(base_internal::PerThreadSynch* absl_nonnull s);
// Wake a thread; return successor.
base_internal::PerThreadSynch* absl_nullable Wakeup(
base_internal::PerThreadSynch* absl_nonnull w);
void Dtor();
friend class CondVar; // for access to Trans()/Fer().
void Trans(MuHow absl_nonnull how); // used for CondVar->Mutex transfer
void Fer(base_internal::PerThreadSynch* absl_nonnull
w); // used for CondVar->Mutex transfer
// Catch the error of writing Mutex when intending MutexLock.
explicit Mutex(const volatile Mutex* absl_nullable /*ignored*/) {}
Mutex(const Mutex&) = delete;
Mutex& operator=(const Mutex&) = delete;
};
// -----------------------------------------------------------------------------
// Mutex RAII Wrappers
// -----------------------------------------------------------------------------
// MutexLock
//
// `MutexLock` is a helper class, which acquires and releases a `Mutex` via
// RAII.
//
// Example:
//
// Class Foo {
// public:
// Foo::Bar* Baz() {
// MutexLock lock(&mu_);
// ...
// return bar;
// }
//
// private:
// Mutex mu_;
// };
class ABSL_SCOPED_LOCKABLE MutexLock {
public:
// Constructors
// Calls `mu->Lock()` and returns when that call returns. That is, `*mu` is
// guaranteed to be locked when this object is constructed. Requires that
// `mu` be dereferenceable.
explicit MutexLock(Mutex* absl_nonnull mu) ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
: mu_(mu) {
this->mu_->Lock();
}
// Like above, but calls `mu->LockWhen(cond)` instead. That is, in addition to
// the above, the condition given by `cond` is also guaranteed to hold when
// this object is constructed.
explicit MutexLock(Mutex* absl_nonnull mu, const Condition& cond)
ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
: mu_(mu) {
this->mu_->LockWhen(cond);
}
MutexLock(const MutexLock&) = delete; // NOLINT(runtime/mutex)
MutexLock(MutexLock&&) = delete; // NOLINT(runtime/mutex)
MutexLock& operator=(const MutexLock&) = delete;
MutexLock& operator=(MutexLock&&) = delete;
~MutexLock() ABSL_UNLOCK_FUNCTION() { this->mu_->Unlock(); }
private:
Mutex* absl_nonnull const mu_;
};
// ReaderMutexLock
//
// The `ReaderMutexLock` is a helper class, like `MutexLock`, which acquires and
// releases a shared lock on a `Mutex` via RAII.
class ABSL_SCOPED_LOCKABLE ReaderMutexLock {
public:
explicit ReaderMutexLock(Mutex* absl_nonnull mu) ABSL_SHARED_LOCK_FUNCTION(mu)
: mu_(mu) {
mu->ReaderLock();
}
explicit ReaderMutexLock(Mutex* absl_nonnull mu, const Condition& cond)
ABSL_SHARED_LOCK_FUNCTION(mu)
: mu_(mu) {
mu->ReaderLockWhen(cond);
}
ReaderMutexLock(const ReaderMutexLock&) = delete;
ReaderMutexLock(ReaderMutexLock&&) = delete;
ReaderMutexLock& operator=(const ReaderMutexLock&) = delete;
ReaderMutexLock& operator=(ReaderMutexLock&&) = delete;
~ReaderMutexLock() ABSL_UNLOCK_FUNCTION() { this->mu_->ReaderUnlock(); }
private:
Mutex* absl_nonnull const mu_;
};
// WriterMutexLock
//
// The `WriterMutexLock` is a helper class, like `MutexLock`, which acquires and
// releases a write (exclusive) lock on a `Mutex` via RAII.
class ABSL_SCOPED_LOCKABLE WriterMutexLock {
public:
explicit WriterMutexLock(Mutex* absl_nonnull mu)
ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
: mu_(mu) {
mu->WriterLock();
}
explicit WriterMutexLock(Mutex* absl_nonnull mu, const Condition& cond)
ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
: mu_(mu) {
mu->WriterLockWhen(cond);
}
WriterMutexLock(const WriterMutexLock&) = delete;
WriterMutexLock(WriterMutexLock&&) = delete;
WriterMutexLock& operator=(const WriterMutexLock&) = delete;
WriterMutexLock& operator=(WriterMutexLock&&) = delete;
~WriterMutexLock() ABSL_UNLOCK_FUNCTION() { this->mu_->WriterUnlock(); }
private:
Mutex* absl_nonnull const mu_;
};
// -----------------------------------------------------------------------------
// Condition
// -----------------------------------------------------------------------------
//
// `Mutex` contains a number of member functions which take a `Condition` as an
// argument; clients can wait for conditions to become `true` before attempting
// to acquire the mutex. These sections are known as "condition critical"
// sections. To use a `Condition`, you simply need to construct it, and use
// within an appropriate `Mutex` member function; everything else in the
// `Condition` class is an implementation detail.
//
// A `Condition` is specified as a function pointer which returns a boolean.
// `Condition` functions should be pure functions -- their results should depend
// only on passed arguments, should not consult any external state (such as
// clocks), and should have no side-effects, aside from debug logging. Any
// objects that the function may access should be limited to those which are
// constant while the mutex is blocked on the condition (e.g. a stack variable),
// or objects of state protected explicitly by the mutex.
//
// No matter which construction is used for `Condition`, the underlying
// function pointer / functor / callable must not throw any
// exceptions. Correctness of `Mutex` / `Condition` is not guaranteed in
// the face of a throwing `Condition`. (When Abseil is allowed to depend
// on C++17, these function pointers will be explicitly marked
// `noexcept`; until then this requirement cannot be enforced in the
// type system.)
//
// Note: to use a `Condition`, you need only construct it and pass it to a
// suitable `Mutex' member function, such as `Mutex::Await()`, or to the
// constructor of one of the scope guard classes.
//
// Example using LockWhen/Unlock:
//
// // assume count_ is not internal reference count
// int count_ ABSL_GUARDED_BY(mu_);
// Condition count_is_zero(+[](int *count) { return *count == 0; }, &count_);
//
// mu_.LockWhen(count_is_zero);
// // ...
// mu_.Unlock();
//
// Example using a scope guard:
//
// {
// MutexLock lock(&mu_, count_is_zero);
// // ...
// }
//
// When multiple threads are waiting on exactly the same condition, make sure
// that they are constructed with the same parameters (same pointer to function
// + arg, or same pointer to object + method), so that the mutex implementation
// can avoid redundantly evaluating the same condition for each thread.
class Condition {
public:
// A Condition that returns the result of "(*func)(arg)"
Condition(bool (*absl_nonnull func)(void* absl_nullability_unknown),
void* absl_nullability_unknown arg);
// Templated version for people who are averse to casts.
//
// To use a lambda, prepend it with unary plus, which converts the lambda
// into a function pointer:
// Condition(+[](T* t) { return ...; }, arg).
//
// Note: lambdas in this case must contain no bound variables.
//
// See class comment for performance advice.
template <typename T>
Condition(bool (*absl_nonnull func)(T* absl_nullability_unknown),
T* absl_nullability_unknown arg);
// Same as above, but allows for cases where `arg` comes from a pointer that
// is convertible to the function parameter type `T*` but not an exact match.
//
// For example, the argument might be `X*` but the function takes `const X*`,
// or the argument might be `Derived*` while the function takes `Base*`, and
// so on for cases where the argument pointer can be implicitly converted.
//
// Implementation notes: This constructor overload is required in addition to
// the one above to allow deduction of `T` from `arg` for cases such as where
// a function template is passed as `func`. Also, the dummy `typename = void`
// template parameter exists just to work around a MSVC mangling bug.
template <typename T, typename = void>
Condition(
bool (*absl_nonnull func)(T* absl_nullability_unknown),
typename absl::internal::type_identity<T>::type* absl_nullability_unknown
arg);
// Templated version for invoking a method that returns a `bool`.
//
// `Condition(object, &Class::Method)` constructs a `Condition` that evaluates
// `object->Method()`.
//
// Implementation Note: `absl::internal::type_identity` is used to allow
// methods to come from base classes. A simpler signature like
// `Condition(T*, bool (T::*)())` does not suffice.
template <typename T>
Condition(
T* absl_nonnull object,
bool (absl::internal::type_identity<T>::type::* absl_nonnull method)());
// Same as above, for const members
template <typename T>
Condition(
const T* absl_nonnull object,
bool (absl::internal::type_identity<T>::type::* absl_nonnull method)()
const);
// A Condition that returns the value of `*cond`
explicit Condition(const bool* absl_nonnull cond);
// Templated version for invoking a functor that returns a `bool`.
// This approach accepts pointers to non-mutable lambdas, `std::function`,
// the result of` std::bind` and user-defined functors that define
// `bool F::operator()() const`.
//
// Example:
//
// auto reached = [this, current]() {
// mu_.AssertReaderHeld(); // For annotalysis.
// return processed_ >= current;
// };
// mu_.Await(Condition(&reached));
//
// NOTE: never use "mu_.AssertHeld()" instead of "mu_.AssertReaderHeld()" in
// the lambda as it may be called when the mutex is being unlocked from a
// scope holding only a reader lock, which will make the assertion not
// fulfilled and crash the binary.
// See class comment for performance advice. In particular, if there
// might be more than one waiter for the same condition, make sure
// that all waiters construct the condition with the same pointers.
// Implementation note: The second template parameter ensures that this
// constructor doesn't participate in overload resolution if T doesn't have
// `bool operator() const`.
template <typename T, typename E = decltype(static_cast<bool (T::*)() const>(
&T::operator()))>
explicit Condition(const T* absl_nonnull obj)
: Condition(obj, static_cast<bool (T::*)() const>(&T::operator())) {}
// A Condition that always returns `true`.
// kTrue is only useful in a narrow set of circumstances, mostly when
// it's passed conditionally. For example:
//
// mu.LockWhen(some_flag ? kTrue : SomeOtherCondition);
//
// Note: {LockWhen,Await}With{Deadline,Timeout} methods with kTrue condition
// don't return immediately when the timeout happens, they still block until
// the Mutex becomes available. The return value of these methods does
// not indicate if the timeout was reached; rather it indicates whether or
// not the condition is true.
ABSL_CONST_INIT static const Condition kTrue;
// Evaluates the condition.
bool Eval() const;
// Returns `true` if the two conditions are guaranteed to return the same
// value if evaluated at the same time, `false` if the evaluation *may* return
// different results.
//
// Two `Condition` values are guaranteed equal if both their `func` and `arg`
// components are the same. A null pointer is equivalent to a `true`
// condition.
static bool GuaranteedEqual(const Condition* absl_nullable a,
const Condition* absl_nullable b);
private:
// Sizing an allocation for a method pointer can be subtle. In the Itanium
// specifications, a method pointer has a predictable, uniform size. On the
// other hand, MSVC ABI, method pointer sizes vary based on the
// inheritance of the class. Specifically, method pointers from classes with
// multiple inheritance are bigger than those of classes with single
// inheritance. Other variations also exist.
#ifndef _MSC_VER
// Allocation for a function pointer or method pointer.
// The {0} initializer ensures that all unused bytes of this buffer are
// always zeroed out. This is necessary, because GuaranteedEqual() compares
// all of the bytes, unaware of which bytes are relevant to a given `eval_`.
using MethodPtr = bool (Condition::*)();
char callback_[sizeof(MethodPtr)] = {0};
#else
// It is well known that the larget MSVC pointer-to-member is 24 bytes. This
// may be the largest known pointer-to-member of any platform. For this
// reason we will allocate 24 bytes for MSVC platform toolchains.
char callback_[24] = {0};
#endif
// Function with which to evaluate callbacks and/or arguments.
bool (*absl_nullable eval_)(const Condition* absl_nonnull) = nullptr;
// Either an argument for a function call or an object for a method call.
void* absl_nullable arg_ = nullptr;
// Various functions eval_ can point to:
static bool CallVoidPtrFunction(const Condition* absl_nonnull c);
template <typename T>
static bool CastAndCallFunction(const Condition* absl_nonnull c);
template <typename T, typename ConditionMethodPtr>
static bool CastAndCallMethod(const Condition* absl_nonnull c);
// Helper methods for storing, validating, and reading callback arguments.
template <typename T>
inline void StoreCallback(T callback) {
static_assert(
sizeof(callback) <= sizeof(callback_),
"An overlarge pointer was passed as a callback to Condition.");
std::memcpy(callback_, &callback, sizeof(callback));
}
template <typename T>
inline void ReadCallback(T* absl_nonnull callback) const {
std::memcpy(callback, callback_, sizeof(*callback));
}
static bool AlwaysTrue(const Condition* absl_nullable) { return true; }
// Used only to create kTrue.
constexpr Condition() : eval_(AlwaysTrue), arg_(nullptr) {}
};
// -----------------------------------------------------------------------------
// CondVar
// -----------------------------------------------------------------------------
//
// A condition variable, reflecting state evaluated separately outside of the
// `Mutex` object, which can be signaled to wake callers.
// This class is not normally needed; use `Mutex` member functions such as
// `Mutex::Await()` and intrinsic `Condition` abstractions. In rare cases
// with many threads and many conditions, `CondVar` may be faster.
//
// The implementation may deliver signals to any condition variable at
// any time, even when no call to `Signal()` or `SignalAll()` is made; as a
// result, upon being awoken, you must check the logical condition you have
// been waiting upon.
//
// Examples:
//
// Usage for a thread waiting for some condition C protected by mutex mu:
// mu.Lock();
// while (!C) { cv->Wait(&mu); } // releases and reacquires mu
// // C holds; process data
// mu.Unlock();
//
// Usage to wake T is:
// mu.Lock();
// // process data, possibly establishing C
// if (C) { cv->Signal(); }
// mu.Unlock();
//
// If C may be useful to more than one waiter, use `SignalAll()` instead of
// `Signal()`.
//
// With this implementation it is efficient to use `Signal()/SignalAll()` inside
// the locked region; this usage can make reasoning about your program easier.
//
class CondVar {
public:
// A `CondVar` allocated on the heap or on the stack can use the this
// constructor.
CondVar();
// CondVar::Wait()
//
// Atomically releases a `Mutex` and blocks on this condition variable.
// Waits until awakened by a call to `Signal()` or `SignalAll()` (or a
// spurious wakeup), then reacquires the `Mutex` and returns.
//
// Requires and ensures that the current thread holds the `Mutex`.
void Wait(Mutex* absl_nonnull mu) {
WaitCommon(mu, synchronization_internal::KernelTimeout::Never());
}
// CondVar::WaitWithTimeout()
//
// Atomically releases a `Mutex` and blocks on this condition variable.
// Waits until awakened by a call to `Signal()` or `SignalAll()` (or a
// spurious wakeup), or until the timeout has expired, then reacquires
// the `Mutex` and returns.
//
// Returns true if the timeout has expired without this `CondVar`
// being signalled in any manner. If both the timeout has expired
// and this `CondVar` has been signalled, the implementation is free
// to return `true` or `false`.
//
// Requires and ensures that the current thread holds the `Mutex`.
bool WaitWithTimeout(Mutex* absl_nonnull mu, absl::Duration timeout) {
return WaitCommon(mu, synchronization_internal::KernelTimeout(timeout));
}
// CondVar::WaitWithDeadline()
//
// Atomically releases a `Mutex` and blocks on this condition variable.
// Waits until awakened by a call to `Signal()` or `SignalAll()` (or a
// spurious wakeup), or until the deadline has passed, then reacquires
// the `Mutex` and returns.
//
// Deadlines in the past are equivalent to an immediate deadline.
//
// Returns true if the deadline has passed without this `CondVar`
// being signalled in any manner. If both the deadline has passed
// and this `CondVar` has been signalled, the implementation is free
// to return `true` or `false`.
//
// Requires and ensures that the current thread holds the `Mutex`.
bool WaitWithDeadline(Mutex* absl_nonnull mu, absl::Time deadline) {
return WaitCommon(mu, synchronization_internal::KernelTimeout(deadline));
}
// CondVar::Signal()
//
// Signal this `CondVar`; wake at least one waiter if one exists.
void Signal();
// CondVar::SignalAll()
//
// Signal this `CondVar`; wake all waiters.
void SignalAll();
// CondVar::EnableDebugLog()
//
// Causes all subsequent uses of this `CondVar` to be logged via
// `ABSL_RAW_LOG(INFO)`. Log entries are tagged with `name` if `name != 0`.
// Note: this method substantially reduces `CondVar` performance.
void EnableDebugLog(const char* absl_nullable name);
private:
bool WaitCommon(Mutex* absl_nonnull mutex,
synchronization_internal::KernelTimeout t);
void Remove(base_internal::PerThreadSynch* absl_nonnull s);
std::atomic<intptr_t> cv_; // Condition variable state.
CondVar(const CondVar&) = delete;
CondVar& operator=(const CondVar&) = delete;
};
// Variants of MutexLock.
//
// If you find yourself using one of these, consider instead using
// Mutex::Unlock() and/or if-statements for clarity.
// MutexLockMaybe
//
// MutexLockMaybe is like MutexLock, but is a no-op when mu is null.
class ABSL_SCOPED_LOCKABLE MutexLockMaybe {
public:
explicit MutexLockMaybe(Mutex* absl_nullable mu)
ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
: mu_(mu) {
if (this->mu_ != nullptr) {
this->mu_->Lock();
}
}
explicit MutexLockMaybe(Mutex* absl_nullable mu, const Condition& cond)
ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
: mu_(mu) {
if (this->mu_ != nullptr) {
this->mu_->LockWhen(cond);
}
}
~MutexLockMaybe() ABSL_UNLOCK_FUNCTION() {
if (this->mu_ != nullptr) {
this->mu_->Unlock();
}
}
private:
Mutex* absl_nullable const mu_;
MutexLockMaybe(const MutexLockMaybe&) = delete;
MutexLockMaybe(MutexLockMaybe&&) = delete;
MutexLockMaybe& operator=(const MutexLockMaybe&) = delete;
MutexLockMaybe& operator=(MutexLockMaybe&&) = delete;
};
// ReleasableMutexLock
//
// ReleasableMutexLock is like MutexLock, but permits `Release()` of its
// mutex before destruction. `Release()` may be called at most once.
class ABSL_SCOPED_LOCKABLE ReleasableMutexLock {
public:
explicit ReleasableMutexLock(Mutex* absl_nonnull mu)
ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
: mu_(mu) {
this->mu_->Lock();
}
explicit ReleasableMutexLock(Mutex* absl_nonnull mu, const Condition& cond)
ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
: mu_(mu) {
this->mu_->LockWhen(cond);
}
~ReleasableMutexLock() ABSL_UNLOCK_FUNCTION() {
if (this->mu_ != nullptr) {
this->mu_->Unlock();
}
}
void Release() ABSL_UNLOCK_FUNCTION();
private:
Mutex* absl_nonnull mu_;
ReleasableMutexLock(const ReleasableMutexLock&) = delete;
ReleasableMutexLock(ReleasableMutexLock&&) = delete;
ReleasableMutexLock& operator=(const ReleasableMutexLock&) = delete;
ReleasableMutexLock& operator=(ReleasableMutexLock&&) = delete;
};
inline Mutex::Mutex() : mu_(0) {
ABSL_TSAN_MUTEX_CREATE(this, __tsan_mutex_not_static);
}
inline constexpr Mutex::Mutex(absl::ConstInitType) : mu_(0) {}
#if !defined(__APPLE__) && !defined(ABSL_BUILD_DLL)
ABSL_ATTRIBUTE_ALWAYS_INLINE
inline Mutex::~Mutex() { Dtor(); }
#endif
#if defined(NDEBUG) && !defined(ABSL_HAVE_THREAD_SANITIZER)
// Use default (empty) destructor in release build for performance reasons.
// We need to mark both Dtor and ~Mutex as always inline for inconsistent
// builds that use both NDEBUG and !NDEBUG with dynamic libraries. In these
// cases we want the empty functions to dissolve entirely rather than being
// exported from dynamic libraries and potentially override the non-empty ones.
ABSL_ATTRIBUTE_ALWAYS_INLINE
inline void Mutex::Dtor() {}
#endif
inline CondVar::CondVar() : cv_(0) {}
// static
template <typename T, typename ConditionMethodPtr>
bool Condition::CastAndCallMethod(const Condition* absl_nonnull c) {
T* object = static_cast<T*>(c->arg_);
ConditionMethodPtr condition_method_pointer;
c->ReadCallback(&condition_method_pointer);
return (object->*condition_method_pointer)();
}
// static
template <typename T>
bool Condition::CastAndCallFunction(const Condition* absl_nonnull c) {
bool (*function)(T*);
c->ReadCallback(&function);
T* argument = static_cast<T*>(c->arg_);
return (*function)(argument);
}
template <typename T>
inline Condition::Condition(
bool (*absl_nonnull func)(T* absl_nullability_unknown),
T* absl_nullability_unknown arg)
: eval_(&CastAndCallFunction<T>),
arg_(const_cast<void*>(static_cast<const void*>(arg))) {
static_assert(sizeof(&func) <= sizeof(callback_),
"An overlarge function pointer was passed to Condition.");
StoreCallback(func);
}
template <typename T, typename>
inline Condition::Condition(
bool (*absl_nonnull func)(T* absl_nullability_unknown),
typename absl::internal::type_identity<T>::type* absl_nullability_unknown
arg)
// Just delegate to the overload above.
: Condition(func, arg) {}
template <typename T>
inline Condition::Condition(
T* absl_nonnull object,
bool (absl::internal::type_identity<T>::type::* absl_nonnull method)())
: eval_(&CastAndCallMethod<T, decltype(method)>), arg_(object) {
static_assert(sizeof(&method) <= sizeof(callback_),
"An overlarge method pointer was passed to Condition.");
StoreCallback(method);
}
template <typename T>
inline Condition::Condition(
const T* absl_nonnull object,
bool (absl::internal::type_identity<T>::type::* absl_nonnull method)()
const)
: eval_(&CastAndCallMethod<const T, decltype(method)>),
arg_(reinterpret_cast<void*>(const_cast<T*>(object))) {
StoreCallback(method);
}
// Register hooks for profiling support.
//
// The function pointer registered here will be called whenever a mutex is
// contended. The callback is given the cycles for which waiting happened (as
// measured by //absl/base/internal/cycleclock.h, and which may not
// be real "cycle" counts.)
//
// There is no ordering guarantee between when the hook is registered and when
// callbacks will begin. Only a single profiler can be installed in a running
// binary; if this function is called a second time with a different function
// pointer, the value is ignored (and will cause an assertion failure in debug
// mode.)
void RegisterMutexProfiler(void (*absl_nonnull fn)(int64_t wait_cycles));
// Register a hook for Mutex tracing.
//
// The function pointer registered here will be called whenever a mutex is
// contended. The callback is given an opaque handle to the contended mutex,
// an event name, and the number of wait cycles (as measured by
// //absl/base/internal/cycleclock.h, and which may not be real
// "cycle" counts.)
//
// The only event name currently sent is "slow release".
//
// This has the same ordering and single-use limitations as
// RegisterMutexProfiler() above.
void RegisterMutexTracer(void (*absl_nonnull fn)(const char* absl_nonnull msg,
const void* absl_nonnull obj,
int64_t wait_cycles));
// Register a hook for CondVar tracing.
//
// The function pointer registered here will be called here on various CondVar
// events. The callback is given an opaque handle to the CondVar object and
// a string identifying the event. This is thread-safe, but only a single
// tracer can be registered.
//
// Events that can be sent are "Wait", "Unwait", "Signal wakeup", and
// "SignalAll wakeup".
//
// This has the same ordering and single-use limitations as
// RegisterMutexProfiler() above.
void RegisterCondVarTracer(void (*absl_nonnull fn)(
const char* absl_nonnull msg, const void* absl_nonnull cv));
// EnableMutexInvariantDebugging()
//
// Enable or disable global support for Mutex invariant debugging. If enabled,
// then invariant predicates can be registered per-Mutex for debug checking.
// See Mutex::EnableInvariantDebugging().
void EnableMutexInvariantDebugging(bool enabled);
// When in debug mode, and when the feature has been enabled globally, the
// implementation will keep track of lock ordering and complain (or optionally
// crash) if a cycle is detected in the acquired-before graph.
// Possible modes of operation for the deadlock detector in debug mode.
enum class OnDeadlockCycle {
kIgnore, // Neither report on nor attempt to track cycles in lock ordering
kReport, // Report lock cycles to stderr when detected
kAbort, // Report lock cycles to stderr when detected, then abort
};
// SetMutexDeadlockDetectionMode()
//
// Enable or disable global support for detection of potential deadlocks
// due to Mutex lock ordering inversions. When set to 'kIgnore', tracking of
// lock ordering is disabled. Otherwise, in debug builds, a lock ordering graph
// will be maintained internally, and detected cycles will be reported in
// the manner chosen here.
void SetMutexDeadlockDetectionMode(OnDeadlockCycle mode);
ABSL_NAMESPACE_END
} // namespace absl
// In some build configurations we pass --detect-odr-violations to the
// gold linker. This causes it to flag weak symbol overrides as ODR
// violations. Because ODR only applies to C++ and not C,
// --detect-odr-violations ignores symbols not mangled with C++ names.
// By changing our extension points to be extern "C", we dodge this
// check.
extern "C" {
void ABSL_INTERNAL_C_SYMBOL(AbslInternalMutexYield)();
} // extern "C"
#endif // ABSL_SYNCHRONIZATION_MUTEX_H_
*¦
soong/.intermediates/external/abseil-cpp/absl_strings_cordz_update_tracker_hdrs/gen/my_include_dir/absl/strings/internal/cordz_update_tracker.h‘// Copyright 2021 The Abseil Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_STRINGS_INTERNAL_CORDZ_UPDATE_TRACKER_H_
#define ABSL_STRINGS_INTERNAL_CORDZ_UPDATE_TRACKER_H_
#include <atomic>
#include <cstdint>
#include "absl/base/config.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace cord_internal {
// CordzUpdateTracker tracks counters for Cord update methods.
//
// The purpose of CordzUpdateTracker is to track the number of calls to methods
// updating Cord data for sampled cords. The class internally uses 'lossy'
// atomic operations: Cord is thread-compatible, so there is no need to
// synchronize updates. However, Cordz collection threads may call 'Value()' at
// any point, so the class needs to provide thread safe access.
//
// This class is thread-safe. But as per above comments, all non-const methods
// should be used single-threaded only: updates are thread-safe but lossy.
class CordzUpdateTracker {
public:
// Tracked update methods.
enum MethodIdentifier {
kUnknown,
kAppendCord,
kAppendCordBuffer,
kAppendExternalMemory,
kAppendString,
kAssignCord,
kAssignString,
kClear,
kConstructorCord,
kConstructorString,
kCordReader,
kFlatten,
kGetAppendBuffer,
kGetAppendRegion,
kMakeCordFromExternal,
kMoveAppendCord,
kMoveAssignCord,
kMovePrependCord,
kPrependCord,
kPrependCordBuffer,
kPrependString,
kRemovePrefix,
kRemoveSuffix,
kSetExpectedChecksum,
kSubCord,
// kNumMethods defines the number of entries: must be the last entry.
kNumMethods,
};
// Constructs a new instance. All counters are zero-initialized.
constexpr CordzUpdateTracker() noexcept : values_{} {}
// Copy constructs a new instance.
CordzUpdateTracker(const CordzUpdateTracker& rhs) noexcept { *this = rhs; }
// Assigns the provided value to this instance.
CordzUpdateTracker& operator=(const CordzUpdateTracker& rhs) noexcept {
for (int i = 0; i < kNumMethods; ++i) {
values_[i].store(rhs.values_[i].load(std::memory_order_relaxed),
std::memory_order_relaxed);
}
return *this;
}
// Returns the value for the specified method.
int64_t Value(MethodIdentifier method) const {
return values_[method].load(std::memory_order_relaxed);
}
// Increases the value for the specified method by `n`
void LossyAdd(MethodIdentifier method, int64_t n = 1) {
auto& value = values_[method];
value.store(value.load(std::memory_order_relaxed) + n,
std::memory_order_relaxed);
}
// Adds all the values from `src` to this instance
void LossyAdd(const CordzUpdateTracker& src) {
for (int i = 0; i < kNumMethods; ++i) {
MethodIdentifier method = static_cast<MethodIdentifier>(i);
if (int64_t value = src.Value(method)) {
LossyAdd(method, value);
}
}
}
private:
// Until C++20 std::atomic is not constexpr default-constructible, so we need
// a wrapper for this class to be constexpr constructible.
class Counter : public std::atomic<int64_t> {
public:
constexpr Counter() noexcept : std::atomic<int64_t>(0) {}
};
Counter values_[kNumMethods];
};
} // namespace cord_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_CORDZ_UPDATE_TRACKER_H_
*Ô&
tsoong/.intermediates/external/abseil-cpp/absl_base_hdrs/gen/my_include_dir/absl/base/internal/low_level_scheduling.hÛ%// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Core interfaces and definitions used by by low-level interfaces such as
// SpinLock.
#ifndef ABSL_BASE_INTERNAL_LOW_LEVEL_SCHEDULING_H_
#define ABSL_BASE_INTERNAL_LOW_LEVEL_SCHEDULING_H_
#include "absl/base/internal/raw_logging.h"
#include "absl/base/internal/scheduling_mode.h"
#include "absl/base/macros.h"
// The following two declarations exist so SchedulingGuard may friend them with
// the appropriate language linkage. These callbacks allow libc internals, such
// as function level statics, to schedule cooperatively when locking.
extern "C" bool __google_disable_rescheduling(void);
extern "C" void __google_enable_rescheduling(bool disable_result);
namespace absl {
ABSL_NAMESPACE_BEGIN
class CondVar;
class Mutex;
namespace synchronization_internal {
int MutexDelay(int32_t c, int mode);
} // namespace synchronization_internal
namespace base_internal {
class SchedulingHelper; // To allow use of SchedulingGuard.
class SpinLock; // To allow use of SchedulingGuard.
// SchedulingGuard
// Provides guard semantics that may be used to disable cooperative rescheduling
// of the calling thread within specific program blocks. This is used to
// protect resources (e.g. low-level SpinLocks or Domain code) that cooperative
// scheduling depends on.
//
// Domain implementations capable of rescheduling in reaction to involuntary
// kernel thread actions (e.g blocking due to a pagefault or syscall) must
// guarantee that an annotated thread is not allowed to (cooperatively)
// reschedule until the annotated region is complete.
//
// It is an error to attempt to use a cooperatively scheduled resource (e.g.
// Mutex) within a rescheduling-disabled region.
//
// All methods are async-signal safe.
class SchedulingGuard {
public:
// Returns true iff the calling thread may be cooperatively rescheduled.
static bool ReschedulingIsAllowed();
SchedulingGuard(const SchedulingGuard&) = delete;
SchedulingGuard& operator=(const SchedulingGuard&) = delete;
private:
// Disable cooperative rescheduling of the calling thread. It may still
// initiate scheduling operations (e.g. wake-ups), however, it may not itself
// reschedule. Nestable. The returned result is opaque, clients should not
// attempt to interpret it.
// REQUIRES: Result must be passed to a pairing EnableScheduling().
static bool DisableRescheduling();
// Marks the end of a rescheduling disabled region, previously started by
// DisableRescheduling().
// REQUIRES: Pairs with innermost call (and result) of DisableRescheduling().
static void EnableRescheduling(bool disable_result);
// A scoped helper for {Disable, Enable}Rescheduling().
// REQUIRES: destructor must run in same thread as constructor.
struct ScopedDisable {
ScopedDisable() { disabled = SchedulingGuard::DisableRescheduling(); }
~ScopedDisable() { SchedulingGuard::EnableRescheduling(disabled); }
bool disabled;
};
// A scoped helper to enable rescheduling temporarily.
// REQUIRES: destructor must run in same thread as constructor.
class ScopedEnable {
public:
ScopedEnable();
~ScopedEnable();
private:
int scheduling_disabled_depth_;
};
// Access to SchedulingGuard is explicitly permitted.
friend class absl::CondVar;
friend class absl::Mutex;
friend class SchedulingHelper;
friend class SpinLock;
friend int absl::synchronization_internal::MutexDelay(int32_t c, int mode);
};
//------------------------------------------------------------------------------
// End of public interfaces.
//------------------------------------------------------------------------------
inline bool SchedulingGuard::ReschedulingIsAllowed() {
return false;
}
inline bool SchedulingGuard::DisableRescheduling() {
return false;
}
inline void SchedulingGuard::EnableRescheduling(bool /* disable_result */) {
return;
}
inline SchedulingGuard::ScopedEnable::ScopedEnable()
: scheduling_disabled_depth_(0) {}
inline SchedulingGuard::ScopedEnable::~ScopedEnable() {
ABSL_RAW_CHECK(scheduling_disabled_depth_ == 0, "disable unused warning");
}
} // namespace base_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_INTERNAL_LOW_LEVEL_SCHEDULING_H_
*ז
~soong/.intermediates/external/abseil-cpp/absl_base_dynamic_annotations_hdrs/gen/my_include_dir/absl/base/dynamic_annotations.hӕ// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This file defines dynamic annotations for use with dynamic analysis tool
// such as valgrind, PIN, etc.
//
// Dynamic annotation is a source code annotation that affects the generated
// code (that is, the annotation is not a comment). Each such annotation is
// attached to a particular instruction and/or to a particular object (address)
// in the program.
//
// The annotations that should be used by users are macros in all upper-case
// (e.g., ABSL_ANNOTATE_THREAD_NAME).
//
// Actual implementation of these macros may differ depending on the dynamic
// analysis tool being used.
//
// This file supports the following configurations:
// - Dynamic Annotations enabled (with static thread-safety warnings disabled).
// In this case, macros expand to functions implemented by Thread Sanitizer,
// when building with TSan. When not provided an external implementation,
// dynamic_annotations.cc provides no-op implementations.
//
// - Static Clang thread-safety warnings enabled.
// When building with a Clang compiler that supports thread-safety warnings,
// a subset of annotations can be statically-checked at compile-time. We
// expand these macros to static-inline functions that can be analyzed for
// thread-safety, but afterwards elided when building the final binary.
//
// - All annotations are disabled.
// If neither Dynamic Annotations nor Clang thread-safety warnings are
// enabled, then all annotation-macros expand to empty.
#ifndef ABSL_BASE_DYNAMIC_ANNOTATIONS_H_
#define ABSL_BASE_DYNAMIC_ANNOTATIONS_H_
#include <stddef.h>
#include <stdint.h>
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#ifdef __cplusplus
#include "absl/base/macros.h"
#endif
#ifdef ABSL_HAVE_HWADDRESS_SANITIZER
#include <sanitizer/hwasan_interface.h>
#endif
// TODO(rogeeff): Remove after the backward compatibility period.
#include "absl/base/internal/dynamic_annotations.h" // IWYU pragma: export
// -------------------------------------------------------------------------
// Decide which features are enabled.
#ifdef ABSL_HAVE_THREAD_SANITIZER
#define ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED 1
#define ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED 1
#define ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED 1
#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED 0
#define ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED 1
#else
#define ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED 0
#define ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED 0
#define ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED 0
// Clang provides limited support for static thread-safety analysis through a
// feature called Annotalysis. We configure macro-definitions according to
// whether Annotalysis support is available. When running in opt-mode, GCC
// will issue a warning, if these attributes are compiled. Only include them
// when compiling using Clang.
#if defined(__clang__)
#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED 1
#if !defined(SWIG)
#define ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED 1
#endif
#else
#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED 0
#endif
// Read/write annotations are enabled in Annotalysis mode; disabled otherwise.
#define ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED \
ABSL_INTERNAL_ANNOTALYSIS_ENABLED
#endif // ABSL_HAVE_THREAD_SANITIZER
#ifdef __cplusplus
#define ABSL_INTERNAL_BEGIN_EXTERN_C extern "C" {
#define ABSL_INTERNAL_END_EXTERN_C } // extern "C"
#define ABSL_INTERNAL_GLOBAL_SCOPED(F) ::F
#define ABSL_INTERNAL_STATIC_INLINE inline
#else
#define ABSL_INTERNAL_BEGIN_EXTERN_C // empty
#define ABSL_INTERNAL_END_EXTERN_C // empty
#define ABSL_INTERNAL_GLOBAL_SCOPED(F) F
#define ABSL_INTERNAL_STATIC_INLINE static inline
#endif
// -------------------------------------------------------------------------
// Define race annotations.
#if ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED == 1
// Some of the symbols used in this section (e.g. AnnotateBenignRaceSized) are
// defined by the compiler-based sanitizer implementation, not by the Abseil
// library. Therefore they do not use ABSL_INTERNAL_C_SYMBOL.
// -------------------------------------------------------------
// Annotations that suppress errors. It is usually better to express the
// program's synchronization using the other annotations, but these can be used
// when all else fails.
// Report that we may have a benign race at `pointer`, with size
// "sizeof(*(pointer))". `pointer` must be a non-void* pointer. Insert at the
// point where `pointer` has been allocated, preferably close to the point
// where the race happens. See also ABSL_ANNOTATE_BENIGN_RACE_STATIC.
#define ABSL_ANNOTATE_BENIGN_RACE(pointer, description) \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateBenignRaceSized) \
(__FILE__, __LINE__, pointer, sizeof(*(pointer)), description)
// Same as ABSL_ANNOTATE_BENIGN_RACE(`address`, `description`), but applies to
// the memory range [`address`, `address`+`size`).
#define ABSL_ANNOTATE_BENIGN_RACE_SIZED(address, size, description) \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateBenignRaceSized) \
(__FILE__, __LINE__, address, size, description)
// Enable (`enable`!=0) or disable (`enable`==0) race detection for all threads.
// This annotation could be useful if you want to skip expensive race analysis
// during some period of program execution, e.g. during initialization.
#define ABSL_ANNOTATE_ENABLE_RACE_DETECTION(enable) \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateEnableRaceDetection) \
(__FILE__, __LINE__, enable)
// -------------------------------------------------------------
// Annotations useful for debugging.
// Report the current thread `name` to a race detector.
#define ABSL_ANNOTATE_THREAD_NAME(name) \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateThreadName)(__FILE__, __LINE__, name)
// -------------------------------------------------------------
// Annotations useful when implementing locks. They are not normally needed by
// modules that merely use locks. The `lock` argument is a pointer to the lock
// object.
// Report that a lock has been created at address `lock`.
#define ABSL_ANNOTATE_RWLOCK_CREATE(lock) \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreate)(__FILE__, __LINE__, lock)
// Report that a linker initialized lock has been created at address `lock`.
#ifdef ABSL_HAVE_THREAD_SANITIZER
#define ABSL_ANNOTATE_RWLOCK_CREATE_STATIC(lock) \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreateStatic) \
(__FILE__, __LINE__, lock)
#else
#define ABSL_ANNOTATE_RWLOCK_CREATE_STATIC(lock) \
ABSL_ANNOTATE_RWLOCK_CREATE(lock)
#endif
// Report that the lock at address `lock` is about to be destroyed.
#define ABSL_ANNOTATE_RWLOCK_DESTROY(lock) \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockDestroy)(__FILE__, __LINE__, lock)
// Report that the lock at address `lock` has been acquired.
// `is_w`=1 for writer lock, `is_w`=0 for reader lock.
#define ABSL_ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockAcquired) \
(__FILE__, __LINE__, lock, is_w)
// Report that the lock at address `lock` is about to be released.
// `is_w`=1 for writer lock, `is_w`=0 for reader lock.
#define ABSL_ANNOTATE_RWLOCK_RELEASED(lock, is_w) \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockReleased) \
(__FILE__, __LINE__, lock, is_w)
// Apply ABSL_ANNOTATE_BENIGN_RACE_SIZED to a static variable `static_var`.
#define ABSL_ANNOTATE_BENIGN_RACE_STATIC(static_var, description) \
namespace { \
class static_var##_annotator { \
public: \
static_var##_annotator() { \
ABSL_ANNOTATE_BENIGN_RACE_SIZED(&static_var, sizeof(static_var), \
#static_var ": " description); \
} \
}; \
static static_var##_annotator the##static_var##_annotator; \
} // namespace
// Function prototypes of annotations provided by the compiler-based sanitizer
// implementation.
ABSL_INTERNAL_BEGIN_EXTERN_C
void AnnotateRWLockCreate(const char* file, int line,
const volatile void* lock);
void AnnotateRWLockCreateStatic(const char* file, int line,
const volatile void* lock);
void AnnotateRWLockDestroy(const char* file, int line,
const volatile void* lock);
void AnnotateRWLockAcquired(const char* file, int line,
const volatile void* lock, long is_w); // NOLINT
void AnnotateRWLockReleased(const char* file, int line,
const volatile void* lock, long is_w); // NOLINT
void AnnotateBenignRace(const char* file, int line,
const volatile void* address, const char* description);
void AnnotateBenignRaceSized(const char* file, int line,
const volatile void* address, size_t size,
const char* description);
void AnnotateThreadName(const char* file, int line, const char* name);
void AnnotateEnableRaceDetection(const char* file, int line, int enable);
ABSL_INTERNAL_END_EXTERN_C
#else // ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED == 0
#define ABSL_ANNOTATE_RWLOCK_CREATE(lock) // empty
#define ABSL_ANNOTATE_RWLOCK_CREATE_STATIC(lock) // empty
#define ABSL_ANNOTATE_RWLOCK_DESTROY(lock) // empty
#define ABSL_ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) // empty
#define ABSL_ANNOTATE_RWLOCK_RELEASED(lock, is_w) // empty
#define ABSL_ANNOTATE_BENIGN_RACE(address, description) // empty
#define ABSL_ANNOTATE_BENIGN_RACE_SIZED(address, size, description) // empty
#define ABSL_ANNOTATE_THREAD_NAME(name) // empty
#define ABSL_ANNOTATE_ENABLE_RACE_DETECTION(enable) // empty
#define ABSL_ANNOTATE_BENIGN_RACE_STATIC(static_var, description) // empty
#endif // ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED
// -------------------------------------------------------------------------
// Define memory annotations.
#ifdef ABSL_HAVE_MEMORY_SANITIZER
#include <sanitizer/msan_interface.h>
#define ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \
__msan_unpoison(address, size)
#define ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) \
__msan_allocated_memory(address, size)
#else // !defined(ABSL_HAVE_MEMORY_SANITIZER)
#define ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(address, size) // empty
#define ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) // empty
#endif // ABSL_HAVE_MEMORY_SANITIZER
// -------------------------------------------------------------------------
// Define IGNORE_READS_BEGIN/_END attributes.
#if defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
#define ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE \
__attribute((exclusive_lock_function("*")))
#define ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE \
__attribute((unlock_function("*")))
#else // !defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
#define ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE // empty
#define ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE // empty
#endif // defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
// -------------------------------------------------------------------------
// Define IGNORE_READS_BEGIN/_END annotations.
#if ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED == 1
// Some of the symbols used in this section (e.g. AnnotateIgnoreReadsBegin) are
// defined by the compiler-based implementation, not by the Abseil
// library. Therefore they do not use ABSL_INTERNAL_C_SYMBOL.
// Request the analysis tool to ignore all reads in the current thread until
// ABSL_ANNOTATE_IGNORE_READS_END is called. Useful to ignore intentional racey
// reads, while still checking other reads and all writes.
// See also ABSL_ANNOTATE_UNPROTECTED_READ.
#define ABSL_ANNOTATE_IGNORE_READS_BEGIN() \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreReadsBegin) \
(__FILE__, __LINE__)
// Stop ignoring reads.
#define ABSL_ANNOTATE_IGNORE_READS_END() \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreReadsEnd) \
(__FILE__, __LINE__)
// Function prototypes of annotations provided by the compiler-based sanitizer
// implementation.
ABSL_INTERNAL_BEGIN_EXTERN_C
void AnnotateIgnoreReadsBegin(const char* file, int line)
ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE;
void AnnotateIgnoreReadsEnd(const char* file,
int line) ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE;
ABSL_INTERNAL_END_EXTERN_C
#elif defined(ABSL_INTERNAL_ANNOTALYSIS_ENABLED)
// When Annotalysis is enabled without Dynamic Annotations, the use of
// static-inline functions allows the annotations to be read at compile-time,
// while still letting the compiler elide the functions from the final build.
//
// TODO(delesley) -- The exclusive lock here ignores writes as well, but
// allows IGNORE_READS_AND_WRITES to work properly.
#define ABSL_ANNOTATE_IGNORE_READS_BEGIN() \
ABSL_INTERNAL_GLOBAL_SCOPED( \
ABSL_INTERNAL_C_SYMBOL(AbslInternalAnnotateIgnoreReadsBegin)) \
()
#define ABSL_ANNOTATE_IGNORE_READS_END() \
ABSL_INTERNAL_GLOBAL_SCOPED( \
ABSL_INTERNAL_C_SYMBOL(AbslInternalAnnotateIgnoreReadsEnd)) \
()
ABSL_INTERNAL_STATIC_INLINE void ABSL_INTERNAL_C_SYMBOL(
AbslInternalAnnotateIgnoreReadsBegin)()
ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE {}
ABSL_INTERNAL_STATIC_INLINE void ABSL_INTERNAL_C_SYMBOL(
AbslInternalAnnotateIgnoreReadsEnd)()
ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE {}
#else
#define ABSL_ANNOTATE_IGNORE_READS_BEGIN() // empty
#define ABSL_ANNOTATE_IGNORE_READS_END() // empty
#endif
// -------------------------------------------------------------------------
// Define IGNORE_WRITES_BEGIN/_END annotations.
#if ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED == 1
// Similar to ABSL_ANNOTATE_IGNORE_READS_BEGIN, but ignore writes instead.
#define ABSL_ANNOTATE_IGNORE_WRITES_BEGIN() \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreWritesBegin)(__FILE__, __LINE__)
// Stop ignoring writes.
#define ABSL_ANNOTATE_IGNORE_WRITES_END() \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreWritesEnd)(__FILE__, __LINE__)
// Function prototypes of annotations provided by the compiler-based sanitizer
// implementation.
ABSL_INTERNAL_BEGIN_EXTERN_C
void AnnotateIgnoreWritesBegin(const char* file, int line);
void AnnotateIgnoreWritesEnd(const char* file, int line);
ABSL_INTERNAL_END_EXTERN_C
#else
#define ABSL_ANNOTATE_IGNORE_WRITES_BEGIN() // empty
#define ABSL_ANNOTATE_IGNORE_WRITES_END() // empty
#endif
// -------------------------------------------------------------------------
// Define the ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_* annotations using the more
// primitive annotations defined above.
//
// Instead of doing
// ABSL_ANNOTATE_IGNORE_READS_BEGIN();
// ... = x;
// ABSL_ANNOTATE_IGNORE_READS_END();
// one can use
// ... = ABSL_ANNOTATE_UNPROTECTED_READ(x);
#if defined(ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED)
// Start ignoring all memory accesses (both reads and writes).
#define ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \
do { \
ABSL_ANNOTATE_IGNORE_READS_BEGIN(); \
ABSL_ANNOTATE_IGNORE_WRITES_BEGIN(); \
} while (0)
// Stop ignoring both reads and writes.
#define ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END() \
do { \
ABSL_ANNOTATE_IGNORE_WRITES_END(); \
ABSL_ANNOTATE_IGNORE_READS_END(); \
} while (0)
#ifdef __cplusplus
// ABSL_ANNOTATE_UNPROTECTED_READ is the preferred way to annotate racey reads.
#define ABSL_ANNOTATE_UNPROTECTED_READ(x) \
absl::base_internal::AnnotateUnprotectedRead(x)
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace base_internal {
template <typename T>
inline T AnnotateUnprotectedRead(const volatile T& x) { // NOLINT
ABSL_ANNOTATE_IGNORE_READS_BEGIN();
T res = x;
ABSL_ANNOTATE_IGNORE_READS_END();
return res;
}
} // namespace base_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif
#else
#define ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() // empty
#define ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END() // empty
#define ABSL_ANNOTATE_UNPROTECTED_READ(x) (x)
#endif
// -------------------------------------------------------------------------
// Address sanitizer annotations
#ifdef ABSL_HAVE_ADDRESS_SANITIZER
// Describe the current state of a contiguous container such as e.g.
// std::vector or std::string. For more details see
// sanitizer/common_interface_defs.h, which is provided by the compiler.
#include <sanitizer/common_interface_defs.h>
#define ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid) \
__sanitizer_annotate_contiguous_container(beg, end, old_mid, new_mid)
#define ABSL_ADDRESS_SANITIZER_REDZONE(name) \
struct { \
alignas(8) char x[8]; \
} name
#else
#define ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid) // empty
#define ABSL_ADDRESS_SANITIZER_REDZONE(name) static_assert(true, "")
#endif // ABSL_HAVE_ADDRESS_SANITIZER
// -------------------------------------------------------------------------
// HWAddress sanitizer annotations
#ifdef __cplusplus
namespace absl {
#ifdef ABSL_HAVE_HWADDRESS_SANITIZER
// Under HWASAN changes the tag of the pointer.
template <typename T>
T* HwasanTagPointer(T* ptr, uintptr_t tag) {
return reinterpret_cast<T*>(__hwasan_tag_pointer(ptr, tag));
}
#else
template <typename T>
T* HwasanTagPointer(T* ptr, uintptr_t) {
return ptr;
}
#endif
} // namespace absl
#endif
// -------------------------------------------------------------------------
// Undefine the macros intended only for this file.
#undef ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED
#undef ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED
#undef ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED
#undef ABSL_INTERNAL_ANNOTALYSIS_ENABLED
#undef ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED
#undef ABSL_INTERNAL_BEGIN_EXTERN_C
#undef ABSL_INTERNAL_END_EXTERN_C
#undef ABSL_INTERNAL_STATIC_INLINE
#endif // ABSL_BASE_DYNAMIC_ANNOTATIONS_H_
*¶P
hsoong/.intermediates/external/abseil-cpp/absl_base_hdrs/gen/my_include_dir/absl/base/internal/spinlock.hÉO//
// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Most users requiring mutual exclusion should use Mutex.
// SpinLock is provided for use in two situations:
// - for use by Abseil internal code that Mutex itself depends on
// - for async signal safety (see below)
// SpinLock with a base_internal::SchedulingMode::SCHEDULE_KERNEL_ONLY is async
// signal safe. If a spinlock is used within a signal handler, all code that
// acquires the lock must ensure that the signal cannot arrive while they are
// holding the lock. Typically, this is done by blocking the signal.
//
// Threads waiting on a SpinLock may be woken in an arbitrary order.
#ifndef ABSL_BASE_INTERNAL_SPINLOCK_H_
#define ABSL_BASE_INTERNAL_SPINLOCK_H_
#include <atomic>
#include <cstdint>
#include "absl/base/attributes.h"
#include "absl/base/const_init.h"
#include "absl/base/dynamic_annotations.h"
#include "absl/base/internal/low_level_scheduling.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/base/internal/scheduling_mode.h"
#include "absl/base/internal/tsan_mutex_interface.h"
#include "absl/base/thread_annotations.h"
namespace tcmalloc {
namespace tcmalloc_internal {
class AllocationGuardSpinLockHolder;
} // namespace tcmalloc_internal
} // namespace tcmalloc
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace base_internal {
class ABSL_LOCKABLE ABSL_ATTRIBUTE_WARN_UNUSED SpinLock {
public:
SpinLock() : lockword_(kSpinLockCooperative) {
ABSL_TSAN_MUTEX_CREATE(this, __tsan_mutex_not_static);
}
// Constructors that allow non-cooperative spinlocks to be created for use
// inside thread schedulers. Normal clients should not use these.
explicit SpinLock(base_internal::SchedulingMode mode);
// Constructor for global SpinLock instances. See absl/base/const_init.h.
constexpr SpinLock(absl::ConstInitType, base_internal::SchedulingMode mode)
: lockword_(IsCooperative(mode) ? kSpinLockCooperative : 0) {}
// For global SpinLock instances prefer trivial destructor when possible.
// Default but non-trivial destructor in some build configurations causes an
// extra static initializer.
#ifdef ABSL_INTERNAL_HAVE_TSAN_INTERFACE
~SpinLock() { ABSL_TSAN_MUTEX_DESTROY(this, __tsan_mutex_not_static); }
#else
~SpinLock() = default;
#endif
// Acquire this SpinLock.
inline void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION() {
ABSL_TSAN_MUTEX_PRE_LOCK(this, 0);
if (!TryLockImpl()) {
SlowLock();
}
ABSL_TSAN_MUTEX_POST_LOCK(this, 0, 0);
}
// Try to acquire this SpinLock without blocking and return true if the
// acquisition was successful. If the lock was not acquired, false is
// returned. If this SpinLock is free at the time of the call, TryLock
// will return true with high probability.
[[nodiscard]] inline bool TryLock() ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true) {
ABSL_TSAN_MUTEX_PRE_LOCK(this, __tsan_mutex_try_lock);
bool res = TryLockImpl();
ABSL_TSAN_MUTEX_POST_LOCK(
this, __tsan_mutex_try_lock | (res ? 0 : __tsan_mutex_try_lock_failed),
0);
return res;
}
// Release this SpinLock, which must be held by the calling thread.
inline void Unlock() ABSL_UNLOCK_FUNCTION() {
ABSL_TSAN_MUTEX_PRE_UNLOCK(this, 0);
uint32_t lock_value = lockword_.load(std::memory_order_relaxed);
lock_value = lockword_.exchange(lock_value & kSpinLockCooperative,
std::memory_order_release);
if ((lock_value & kSpinLockDisabledScheduling) != 0) {
base_internal::SchedulingGuard::EnableRescheduling(true);
}
if ((lock_value & kWaitTimeMask) != 0) {
// Collect contentionz profile info, and speed the wakeup of any waiter.
// The wait_cycles value indicates how long this thread spent waiting
// for the lock.
SlowUnlock(lock_value);
}
ABSL_TSAN_MUTEX_POST_UNLOCK(this, 0);
}
// Determine if the lock is held. When the lock is held by the invoking
// thread, true will always be returned. Intended to be used as
// CHECK(lock.IsHeld()).
[[nodiscard]] inline bool IsHeld() const {
return (lockword_.load(std::memory_order_relaxed) & kSpinLockHeld) != 0;
}
// Return immediately if this thread holds the SpinLock exclusively.
// Otherwise, report an error by crashing with a diagnostic.
inline void AssertHeld() const ABSL_ASSERT_EXCLUSIVE_LOCK() {
if (!IsHeld()) {
ABSL_RAW_LOG(FATAL, "thread should hold the lock on SpinLock");
}
}
protected:
// These should not be exported except for testing.
// Store number of cycles between wait_start_time and wait_end_time in a
// lock value.
static uint32_t EncodeWaitCycles(int64_t wait_start_time,
int64_t wait_end_time);
// Extract number of wait cycles in a lock value.
static int64_t DecodeWaitCycles(uint32_t lock_value);
// Provide access to protected method above. Use for testing only.
friend struct SpinLockTest;
friend class tcmalloc::tcmalloc_internal::AllocationGuardSpinLockHolder;
private:
// lockword_ is used to store the following:
//
// bit[0] encodes whether a lock is being held.
// bit[1] encodes whether a lock uses cooperative scheduling.
// bit[2] encodes whether the current lock holder disabled scheduling when
// acquiring the lock. Only set when kSpinLockHeld is also set.
// bit[3:31] encodes time a lock spent on waiting as a 29-bit unsigned int.
// This is set by the lock holder to indicate how long it waited on
// the lock before eventually acquiring it. The number of cycles is
// encoded as a 29-bit unsigned int, or in the case that the current
// holder did not wait but another waiter is queued, the LSB
// (kSpinLockSleeper) is set. The implementation does not explicitly
// track the number of queued waiters beyond this. It must always be
// assumed that waiters may exist if the current holder was required to
// queue.
//
// Invariant: if the lock is not held, the value is either 0 or
// kSpinLockCooperative.
static constexpr uint32_t kSpinLockHeld = 1;
static constexpr uint32_t kSpinLockCooperative = 2;
static constexpr uint32_t kSpinLockDisabledScheduling = 4;
static constexpr uint32_t kSpinLockSleeper = 8;
// Includes kSpinLockSleeper.
static constexpr uint32_t kWaitTimeMask =
~(kSpinLockHeld | kSpinLockCooperative | kSpinLockDisabledScheduling);
// Returns true if the provided scheduling mode is cooperative.
static constexpr bool IsCooperative(
base_internal::SchedulingMode scheduling_mode) {
return scheduling_mode == base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL;
}
bool IsCooperative() const {
return lockword_.load(std::memory_order_relaxed) & kSpinLockCooperative;
}
uint32_t TryLockInternal(uint32_t lock_value, uint32_t wait_cycles);
void SlowLock() ABSL_ATTRIBUTE_COLD;
void SlowUnlock(uint32_t lock_value) ABSL_ATTRIBUTE_COLD;
uint32_t SpinLoop();
inline bool TryLockImpl() {
uint32_t lock_value = lockword_.load(std::memory_order_relaxed);
return (TryLockInternal(lock_value, 0) & kSpinLockHeld) == 0;
}
std::atomic<uint32_t> lockword_;
SpinLock(const SpinLock&) = delete;
SpinLock& operator=(const SpinLock&) = delete;
};
// Corresponding locker object that arranges to acquire a spinlock for
// the duration of a C++ scope.
class ABSL_SCOPED_LOCKABLE [[nodiscard]] SpinLockHolder {
public:
inline explicit SpinLockHolder(SpinLock* l) ABSL_EXCLUSIVE_LOCK_FUNCTION(l)
: lock_(l) {
l->Lock();
}
inline ~SpinLockHolder() ABSL_UNLOCK_FUNCTION() { lock_->Unlock(); }
SpinLockHolder(const SpinLockHolder&) = delete;
SpinLockHolder& operator=(const SpinLockHolder&) = delete;
private:
SpinLock* lock_;
};
// Register a hook for profiling support.
//
// The function pointer registered here will be called whenever a spinlock is
// contended. The callback is given an opaque handle to the contended spinlock
// and the number of wait cycles. This is thread-safe, but only a single
// profiler can be registered. It is an error to call this function multiple
// times with different arguments.
void RegisterSpinLockProfiler(void (*fn)(const void* lock,
int64_t wait_cycles));
//------------------------------------------------------------------------------
// Public interface ends here.
//------------------------------------------------------------------------------
// If (result & kSpinLockHeld) == 0, then *this was successfully locked.
// Otherwise, returns last observed value for lockword_.
inline uint32_t SpinLock::TryLockInternal(uint32_t lock_value,
uint32_t wait_cycles) {
if ((lock_value & kSpinLockHeld) != 0) {
return lock_value;
}
uint32_t sched_disabled_bit = 0;
if ((lock_value & kSpinLockCooperative) == 0) {
// For non-cooperative locks we must make sure we mark ourselves as
// non-reschedulable before we attempt to CompareAndSwap.
if (base_internal::SchedulingGuard::DisableRescheduling()) {
sched_disabled_bit = kSpinLockDisabledScheduling;
}
}
if (!lockword_.compare_exchange_strong(
lock_value,
kSpinLockHeld | lock_value | wait_cycles | sched_disabled_bit,
std::memory_order_acquire, std::memory_order_relaxed)) {
base_internal::SchedulingGuard::EnableRescheduling(sched_disabled_bit != 0);
}
return lock_value;
}
} // namespace base_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_INTERNAL_SPINLOCK_H_
*»D
‰soong/.intermediates/external/abseil-cpp/absl_strings_cord_internal_hdrs/gen/my_include_dir/absl/strings/internal/cord_rep_btree_reader.h¬C// Copyright 2021 The Abseil Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_STRINGS_INTERNAL_CORD_REP_BTREE_READER_H_
#define ABSL_STRINGS_INTERNAL_CORD_REP_BTREE_READER_H_
#include <cassert>
#include "absl/base/config.h"
#include "absl/strings/internal/cord_data_edge.h"
#include "absl/strings/internal/cord_internal.h"
#include "absl/strings/internal/cord_rep_btree.h"
#include "absl/strings/internal/cord_rep_btree_navigator.h"
#include "absl/strings/internal/cord_rep_flat.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace cord_internal {
// CordRepBtreeReader implements logic to iterate over cord btrees.
// References to the underlying data are returned as absl::string_view values.
// The most typical use case is a forward only iteration over tree data.
// The class also provides `Skip()`, `Seek()` and `Read()` methods similar to
// CordRepBtreeNavigator that allow more advanced navigation.
//
// Example: iterate over all data inside a cord btree:
//
// CordRepBtreeReader reader;
// for (string_view sv = reader.Init(tree); !sv.Empty(); sv = sv.Next()) {
// DoSomethingWithDataIn(sv);
// }
//
// All navigation methods always return the next 'chunk' of data. The class
// assumes that all data is directly 'consumed' by the caller. For example:
// invoking `Skip()` will skip the desired number of bytes, and directly
// read and return the next chunk of data directly after the skipped bytes.
//
// Example: iterate over all data inside a btree skipping the first 100 bytes:
//
// CordRepBtreeReader reader;
// absl::string_view sv = reader.Init(tree);
// if (sv.length() > 100) {
// sv.RemovePrefix(100);
// } else {
// sv = reader.Skip(100 - sv.length());
// }
// while (!sv.empty()) {
// DoSomethingWithDataIn(sv);
// absl::string_view sv = reader.Next();
// }
//
// It is important to notice that `remaining` is based on the end position of
// the last data edge returned to the caller, not the cumulative data returned
// to the caller which can be less in cases of skipping or seeking over data.
//
// For example, consider a cord btree with five data edges: "abc", "def", "ghi",
// "jkl" and "mno":
//
// absl::string_view sv;
// CordRepBtreeReader reader;
//
// sv = reader.Init(tree); // sv = "abc", remaining = 12
// sv = reader.Skip(4); // sv = "hi", remaining = 6
// sv = reader.Skip(2); // sv = "l", remaining = 3
// sv = reader.Next(); // sv = "mno", remaining = 0
// sv = reader.Seek(1); // sv = "bc", remaining = 12
//
class CordRepBtreeReader {
public:
using ReadResult = CordRepBtreeNavigator::ReadResult;
using Position = CordRepBtreeNavigator::Position;
// Returns true if this instance is not empty.
explicit operator bool() const { return navigator_.btree() != nullptr; }
// Returns the tree referenced by this instance or nullptr if empty.
CordRepBtree* btree() const { return navigator_.btree(); }
// Returns the current data edge inside the referenced btree.
// Requires that the current instance is not empty.
CordRep* node() const { return navigator_.Current(); }
// Returns the length of the referenced tree.
// Requires that the current instance is not empty.
size_t length() const;
// Returns the number of remaining bytes available for iteration, which is the
// number of bytes directly following the end of the last chunk returned.
// This value will be zero if we iterated over the last edge in the bound
// tree, in which case any call to Next() or Skip() will return an empty
// string_view reflecting the EOF state.
// Note that a call to `Seek()` resets `remaining` to a value based on the
// end position of the chunk returned by that call.
size_t remaining() const { return remaining_; }
// Resets this instance to an empty value.
void Reset() { navigator_.Reset(); }
// Initializes this instance with `tree`. `tree` must not be null.
// Returns a reference to the first data edge of the provided tree.
absl::string_view Init(CordRepBtree* tree);
// Navigates to and returns the next data edge of the referenced tree.
// Returns an empty string_view if an attempt is made to read beyond the end
// of the tree, i.e.: if `remaining()` is zero indicating an EOF condition.
// Requires that the current instance is not empty.
absl::string_view Next();
// Skips the provided amount of bytes and returns a reference to the data
// directly following the skipped bytes.
absl::string_view Skip(size_t skip);
// Reads `n` bytes into `tree`.
// If `chunk_size` is zero, starts reading at the next data edge. If
// `chunk_size` is non zero, the read starts at the last `chunk_size` bytes of
// the last returned data edge. Effectively, this means that the read starts
// at offset `consumed() - chunk_size`.
// Requires that `chunk_size` is less than or equal to the length of the
// last returned data edge. The purpose of `chunk_size` is to simplify code
// partially consuming a returned chunk and wanting to include the remaining
// bytes in the Read call. For example, the below code will read 1000 bytes of
// data into a cord tree if the first chunk starts with "big:":
//
// CordRepBtreeReader reader;
// absl::string_view sv = reader.Init(tree);
// if (absl::StartsWith(sv, "big:")) {
// CordRepBtree tree;
// sv = reader.Read(1000, sv.size() - 4 /* "big:" */, &tree);
// }
//
// This method will return an empty string view if all remaining data was
// read. If `n` exceeded the amount of remaining data this function will
// return an empty string view and `tree` will be set to nullptr.
// In both cases, `consumed` will be set to `length`.
absl::string_view Read(size_t n, size_t chunk_size, CordRep*& tree);
// Navigates to the chunk at offset `offset`.
// Returns a reference into the navigated to chunk, adjusted for the relative
// position of `offset` into that chunk. For example, calling `Seek(13)` on a
// cord tree containing 2 chunks of 10 and 20 bytes respectively will return
// a string view into the second chunk starting at offset 3 with a size of 17.
// Returns an empty string view if `offset` is equal to or greater than the
// length of the referenced tree.
absl::string_view Seek(size_t offset);
private:
size_t remaining_ = 0;
CordRepBtreeNavigator navigator_;
};
inline size_t CordRepBtreeReader::length() const {
assert(btree() != nullptr);
return btree()->length;
}
inline absl::string_view CordRepBtreeReader::Init(CordRepBtree* tree) {
assert(tree != nullptr);
const CordRep* edge = navigator_.InitFirst(tree);
remaining_ = tree->length - edge->length;
return EdgeData(edge);
}
inline absl::string_view CordRepBtreeReader::Next() {
if (remaining_ == 0) return {};
const CordRep* edge = navigator_.Next();
assert(edge != nullptr);
remaining_ -= edge->length;
return EdgeData(edge);
}
inline absl::string_view CordRepBtreeReader::Skip(size_t skip) {
// As we are always positioned on the last 'consumed' edge, we
// need to skip the current edge as well as `skip`.
const size_t edge_length = navigator_.Current()->length;
CordRepBtreeNavigator::Position pos = navigator_.Skip(skip + edge_length);
if (ABSL_PREDICT_FALSE(pos.edge == nullptr)) {
remaining_ = 0;
return {};
}
// The combined length of all edges skipped before `pos.edge` is `skip -
// pos.offset`, all of which are 'consumed', as well as the current edge.
remaining_ -= skip - pos.offset + pos.edge->length;
return EdgeData(pos.edge).substr(pos.offset);
}
inline absl::string_view CordRepBtreeReader::Seek(size_t offset) {
const CordRepBtreeNavigator::Position pos = navigator_.Seek(offset);
if (ABSL_PREDICT_FALSE(pos.edge == nullptr)) {
remaining_ = 0;
return {};
}
absl::string_view chunk = EdgeData(pos.edge).substr(pos.offset);
remaining_ = length() - offset - chunk.length();
return chunk;
}
} // namespace cord_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_CORD_REP_BTREE_READER_H_
*Ó;
wsoong/.intermediates/external/abseil-cpp/absl_base_atomic_hook_hdrs/gen/my_include_dir/absl/base/internal/atomic_hook.h×:// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_BASE_INTERNAL_ATOMIC_HOOK_H_
#define ABSL_BASE_INTERNAL_ATOMIC_HOOK_H_
#include <atomic>
#include <cassert>
#include <cstdint>
#include <utility>
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#if defined(_MSC_VER) && !defined(__clang__)
#define ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT 0
#else
#define ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT 1
#endif
#if defined(_MSC_VER)
#define ABSL_HAVE_WORKING_ATOMIC_POINTER 0
#else
#define ABSL_HAVE_WORKING_ATOMIC_POINTER 1
#endif
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace base_internal {
template <typename T>
class AtomicHook;
// To workaround AtomicHook not being constant-initializable on some platforms,
// prefer to annotate instances with `ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES`
// instead of `ABSL_CONST_INIT`.
#if ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT
#define ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES ABSL_CONST_INIT
#else
#define ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
#endif
// `AtomicHook` is a helper class, templatized on a raw function pointer type,
// for implementing Abseil customization hooks. It is a callable object that
// dispatches to the registered hook. Objects of type `AtomicHook` must have
// static or thread storage duration.
//
// A default constructed object performs a no-op (and returns a default
// constructed object) if no hook has been registered.
//
// Hooks can be pre-registered via constant initialization, for example:
//
// ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES static AtomicHook<void(*)()>
// my_hook(DefaultAction);
//
// and then changed at runtime via a call to `Store()`.
//
// Reads and writes guarantee memory_order_acquire/memory_order_release
// semantics.
template <typename ReturnType, typename... Args>
class AtomicHook<ReturnType (*)(Args...)> {
public:
using FnPtr = ReturnType (*)(Args...);
// Constructs an object that by default performs a no-op (and
// returns a default constructed object) when no hook as been registered.
constexpr AtomicHook() : AtomicHook(DummyFunction) {}
// Constructs an object that by default dispatches to/returns the
// pre-registered default_fn when no hook has been registered at runtime.
#if ABSL_HAVE_WORKING_ATOMIC_POINTER && ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT
explicit constexpr AtomicHook(FnPtr default_fn)
: hook_(default_fn), default_fn_(default_fn) {}
#elif ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT
explicit constexpr AtomicHook(FnPtr default_fn)
: hook_(kUninitialized), default_fn_(default_fn) {}
#else
// As of January 2020, on all known versions of MSVC this constructor runs in
// the global constructor sequence. If `Store()` is called by a dynamic
// initializer, we want to preserve the value, even if this constructor runs
// after the call to `Store()`. If not, `hook_` will be
// zero-initialized by the linker and we have no need to set it.
// https://developercommunity.visualstudio.com/content/problem/336946/class-with-constexpr-constructor-not-using-static.html
explicit constexpr AtomicHook(FnPtr default_fn)
: /* hook_(deliberately omitted), */ default_fn_(default_fn) {
static_assert(kUninitialized == 0, "here we rely on zero-initialization");
}
#endif
// Stores the provided function pointer as the value for this hook.
//
// This is intended to be called once. Multiple calls are legal only if the
// same function pointer is provided for each call. The store is implemented
// as a memory_order_release operation, and read accesses are implemented as
// memory_order_acquire.
void Store(FnPtr fn) {
bool success = DoStore(fn);
static_cast<void>(success);
assert(success);
}
// Invokes the registered callback. If no callback has yet been registered, a
// default-constructed object of the appropriate type is returned instead.
template <typename... CallArgs>
ReturnType operator()(CallArgs&&... args) const {
return DoLoad()(std::forward<CallArgs>(args)...);
}
// Returns the registered callback, or nullptr if none has been registered.
// Useful if client code needs to conditionalize behavior based on whether a
// callback was registered.
//
// Note that atomic_hook.Load()() and atomic_hook() have different semantics:
// operator()() will perform a no-op if no callback was registered, while
// Load()() will dereference a null function pointer. Prefer operator()() to
// Load()() unless you must conditionalize behavior on whether a hook was
// registered.
FnPtr Load() const {
FnPtr ptr = DoLoad();
return (ptr == DummyFunction) ? nullptr : ptr;
}
private:
static ReturnType DummyFunction(Args...) {
return ReturnType();
}
// Current versions of MSVC (as of September 2017) have a broken
// implementation of std::atomic<T*>: Its constructor attempts to do the
// equivalent of a reinterpret_cast in a constexpr context, which is not
// allowed.
//
// This causes an issue when building with LLVM under Windows. To avoid this,
// we use a less-efficient, intptr_t-based implementation on Windows.
#if ABSL_HAVE_WORKING_ATOMIC_POINTER
// Return the stored value, or DummyFunction if no value has been stored.
FnPtr DoLoad() const { return hook_.load(std::memory_order_acquire); }
// Store the given value. Returns false if a different value was already
// stored to this object.
bool DoStore(FnPtr fn) {
assert(fn);
FnPtr expected = default_fn_;
const bool store_succeeded = hook_.compare_exchange_strong(
expected, fn, std::memory_order_acq_rel, std::memory_order_acquire);
const bool same_value_already_stored = (expected == fn);
return store_succeeded || same_value_already_stored;
}
std::atomic<FnPtr> hook_;
#else // !ABSL_HAVE_WORKING_ATOMIC_POINTER
// Use a sentinel value unlikely to be the address of an actual function.
static constexpr intptr_t kUninitialized = 0;
static_assert(sizeof(intptr_t) >= sizeof(FnPtr),
"intptr_t can't contain a function pointer");
FnPtr DoLoad() const {
const intptr_t value = hook_.load(std::memory_order_acquire);
if (value == kUninitialized) {
return default_fn_;
}
return reinterpret_cast<FnPtr>(value);
}
bool DoStore(FnPtr fn) {
assert(fn);
const auto value = reinterpret_cast<intptr_t>(fn);
intptr_t expected = kUninitialized;
const bool store_succeeded = hook_.compare_exchange_strong(
expected, value, std::memory_order_acq_rel, std::memory_order_acquire);
const bool same_value_already_stored = (expected == value);
return store_succeeded || same_value_already_stored;
}
std::atomic<intptr_t> hook_;
#endif
const FnPtr default_fn_;
};
#undef ABSL_HAVE_WORKING_ATOMIC_POINTER
#undef ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT
} // namespace base_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_INTERNAL_ATOMIC_HOOK_H_
*–Q
€soong/.intermediates/external/abseil-cpp/absl_base_raw_logging_internal_hdrs/gen/my_include_dir/absl/base/internal/raw_logging.hP// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Thread-safe logging routines that do not allocate any memory or
// acquire any locks, and can therefore be used by low-level memory
// allocation, synchronization, and signal-handling code.
#ifndef ABSL_BASE_INTERNAL_RAW_LOGGING_H_
#define ABSL_BASE_INTERNAL_RAW_LOGGING_H_
#include <string>
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/internal/atomic_hook.h"
#include "absl/base/log_severity.h"
#include "absl/base/macros.h"
#include "absl/base/optimization.h"
#include "absl/base/port.h"
// This is similar to LOG(severity) << format..., but
// * it is to be used ONLY by low-level modules that can't use normal LOG()
// * it is designed to be a low-level logger that does not allocate any
// memory and does not need any locks, hence:
// * it logs straight and ONLY to STDERR w/o buffering
// * it uses an explicit printf-format and arguments list
// * it will silently chop off really long message strings
// Usage example:
// ABSL_RAW_LOG(ERROR, "Failed foo with %i: %s", status, error);
// This will print an almost standard log line like this to stderr only:
// E0821 211317 file.cc:123] RAW: Failed foo with 22: bad_file
#define ABSL_RAW_LOG(severity, ...) \
do { \
constexpr const char* absl_raw_log_internal_basename = \
::absl::raw_log_internal::Basename(__FILE__, sizeof(__FILE__) - 1); \
::absl::raw_log_internal::RawLog(ABSL_RAW_LOG_INTERNAL_##severity, \
absl_raw_log_internal_basename, __LINE__, \
__VA_ARGS__); \
ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_##severity; \
} while (0)
// Similar to CHECK(condition) << message, but for low-level modules:
// we use only ABSL_RAW_LOG that does not allocate memory.
// We do not want to provide args list here to encourage this usage:
// if (!cond) ABSL_RAW_LOG(FATAL, "foo ...", hard_to_compute_args);
// so that the args are not computed when not needed.
#define ABSL_RAW_CHECK(condition, message) \
do { \
if (ABSL_PREDICT_FALSE(!(condition))) { \
ABSL_RAW_LOG(FATAL, "Check %s failed: %s", #condition, message); \
} \
} while (0)
// ABSL_INTERNAL_LOG and ABSL_INTERNAL_CHECK work like the RAW variants above,
// except that if the richer log library is linked into the binary, we dispatch
// to that instead. This is potentially useful for internal logging and
// assertions, where we are using RAW_LOG neither for its async-signal-safety
// nor for its non-allocating nature, but rather because raw logging has very
// few other dependencies.
//
// The API is a subset of the above: each macro only takes two arguments. Use
// StrCat if you need to build a richer message.
#define ABSL_INTERNAL_LOG(severity, message) \
do { \
constexpr const char* absl_raw_log_internal_filename = __FILE__; \
::absl::raw_log_internal::internal_log_function( \
ABSL_RAW_LOG_INTERNAL_##severity, absl_raw_log_internal_filename, \
__LINE__, message); \
ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_##severity; \
} while (0)
#define ABSL_INTERNAL_CHECK(condition, message) \
do { \
if (ABSL_PREDICT_FALSE(!(condition))) { \
std::string death_message = "Check " #condition " failed: "; \
death_message += std::string(message); \
ABSL_INTERNAL_LOG(FATAL, death_message); \
} \
} while (0)
#ifndef NDEBUG
#define ABSL_RAW_DLOG(severity, ...) ABSL_RAW_LOG(severity, __VA_ARGS__)
#define ABSL_RAW_DCHECK(condition, message) ABSL_RAW_CHECK(condition, message)
#else // NDEBUG
#define ABSL_RAW_DLOG(severity, ...) \
while (false) ABSL_RAW_LOG(severity, __VA_ARGS__)
#define ABSL_RAW_DCHECK(condition, message) \
while (false) ABSL_RAW_CHECK(condition, message)
#endif // NDEBUG
#define ABSL_RAW_LOG_INTERNAL_INFO ::absl::LogSeverity::kInfo
#define ABSL_RAW_LOG_INTERNAL_WARNING ::absl::LogSeverity::kWarning
#define ABSL_RAW_LOG_INTERNAL_ERROR ::absl::LogSeverity::kError
#define ABSL_RAW_LOG_INTERNAL_FATAL ::absl::LogSeverity::kFatal
#define ABSL_RAW_LOG_INTERNAL_DFATAL ::absl::kLogDebugFatal
#define ABSL_RAW_LOG_INTERNAL_LEVEL(severity) \
::absl::NormalizeLogSeverity(severity)
#define ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_INFO
#define ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_WARNING
#define ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_ERROR
#define ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_FATAL ABSL_UNREACHABLE()
#define ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_DFATAL
#define ABSL_RAW_LOG_INTERNAL_MAYBE_UNREACHABLE_LEVEL(severity)
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace raw_log_internal {
// Helper function to implement ABSL_RAW_LOG
// Logs format... at "severity" level, reporting it
// as called from file:line.
// This does not allocate memory or acquire locks.
void RawLog(absl::LogSeverity severity, const char* file, int line,
const char* format, ...) ABSL_PRINTF_ATTRIBUTE(4, 5);
// Writes the provided buffer directly to stderr, in a signal-safe, low-level
// manner. Preserves errno.
void AsyncSignalSafeWriteError(const char* s, size_t len);
// compile-time function to get the "base" filename, that is, the part of
// a filename after the last "/" or "\" path separator. The search starts at
// the end of the string; the second parameter is the length of the string.
constexpr const char* Basename(const char* fname, int offset) {
return offset == 0 || fname[offset - 1] == '/' || fname[offset - 1] == '\\'
? fname + offset
: Basename(fname, offset - 1);
}
// For testing only.
// Returns true if raw logging is fully supported. When it is not
// fully supported, no messages will be emitted, but a log at FATAL
// severity will cause an abort.
//
// TODO(gfalcon): Come up with a better name for this method.
bool RawLoggingFullySupported();
// Function type for a raw_log customization hook for suppressing messages
// by severity, and for writing custom prefixes on non-suppressed messages.
//
// The installed hook is called for every raw log invocation. The message will
// be logged to stderr only if the hook returns true. FATAL errors will cause
// the process to abort, even if writing to stderr is suppressed. The hook is
// also provided with an output buffer, where it can write a custom log message
// prefix.
//
// The raw_log system does not allocate memory or grab locks. User-provided
// hooks must avoid these operations, and must not throw exceptions.
//
// 'severity' is the severity level of the message being written.
// 'file' and 'line' are the file and line number where the ABSL_RAW_LOG macro
// was located.
// 'buf' and 'buf_size' are pointers to the buffer and buffer size. If the
// hook writes a prefix, it must increment *buf and decrement *buf_size
// accordingly.
using LogFilterAndPrefixHook = bool (*)(absl::LogSeverity severity,
const char* file, int line, char** buf,
int* buf_size);
// Function type for a raw_log customization hook called to abort a process
// when a FATAL message is logged. If the provided AbortHook() returns, the
// logging system will call abort().
//
// 'file' and 'line' are the file and line number where the ABSL_RAW_LOG macro
// was located.
// The NUL-terminated logged message lives in the buffer between 'buf_start'
// and 'buf_end'. 'prefix_end' points to the first non-prefix character of the
// buffer (as written by the LogFilterAndPrefixHook.)
//
// The lifetime of the filename and message buffers will not end while the
// process remains alive.
using AbortHook = void (*)(const char* file, int line, const char* buf_start,
const char* prefix_end, const char* buf_end);
// Internal logging function for ABSL_INTERNAL_LOG to dispatch to.
//
// TODO(gfalcon): When string_view no longer depends on base, change this
// interface to take its message as a string_view instead.
using InternalLogFunction = void (*)(absl::LogSeverity severity,
const char* file, int line,
const std::string& message);
ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES ABSL_DLL extern base_internal::AtomicHook<
InternalLogFunction>
internal_log_function;
// Registers hooks of the above types. Only a single hook of each type may be
// registered. It is an error to call these functions multiple times with
// different input arguments.
//
// These functions are safe to call at any point during initialization; they do
// not block or malloc, and are async-signal safe.
void RegisterLogFilterAndPrefixHook(LogFilterAndPrefixHook func);
void RegisterAbortHook(AbortHook func);
void RegisterInternalLogFunction(InternalLogFunction func);
} // namespace raw_log_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_INTERNAL_RAW_LOGGING_H_
*ê
‚soong/.intermediates/external/abseil-cpp/absl_strings_cord_internal_hdrs/gen/my_include_dir/absl/strings/internal/cord_data_edge.hâ// Copyright 2022 The Abseil Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_STRINGS_INTERNAL_CORD_DATA_EDGE_H_
#define ABSL_STRINGS_INTERNAL_CORD_DATA_EDGE_H_
#include <cassert>
#include <cstddef>
#include "absl/base/config.h"
#include "absl/strings/internal/cord_internal.h"
#include "absl/strings/internal/cord_rep_flat.h"
#include "absl/strings/string_view.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace cord_internal {
// Returns true if the provided rep is a FLAT, EXTERNAL or a SUBSTRING node
// holding a FLAT or EXTERNAL child rep. Requires `rep != nullptr`.
inline bool IsDataEdge(const CordRep* edge) {
assert(edge != nullptr);
// The fast path is that `edge` is an EXTERNAL or FLAT node, making the below
// if a single, well predicted branch. We then repeat the FLAT or EXTERNAL
// check in the slow path of the SUBSTRING check to optimize for the hot path.
if (edge->tag == EXTERNAL || edge->tag >= FLAT) return true;
if (edge->tag == SUBSTRING) edge = edge->substring()->child;
return edge->tag == EXTERNAL || edge->tag >= FLAT;
}
// Returns the `absl::string_view` data reference for the provided data edge.
// Requires 'IsDataEdge(edge) == true`.
inline absl::string_view EdgeData(const CordRep* edge) {
assert(IsDataEdge(edge));
size_t offset = 0;
const size_t length = edge->length;
if (edge->IsSubstring()) {
offset = edge->substring()->start;
edge = edge->substring()->child;
}
return edge->tag >= FLAT
? absl::string_view{edge->flat()->Data() + offset, length}
: absl::string_view{edge->external()->base + offset, length};
}
} // namespace cord_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_CORD_DATA_EDGE_H_
*ž?
soong/.intermediates/external/abseil-cpp/absl_strings_cord_internal_hdrs/gen/my_include_dir/absl/strings/internal/cord_rep_flat.h—>// Copyright 2020 The Abseil Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_STRINGS_INTERNAL_CORD_REP_FLAT_H_
#define ABSL_STRINGS_INTERNAL_CORD_REP_FLAT_H_
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <memory>
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/macros.h"
#include "absl/strings/internal/cord_internal.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace cord_internal {
// Note: all constants below are never ODR used and internal to cord, we define
// these as static constexpr to avoid 'in struct' definition and usage clutter.
// Largest and smallest flat node lengths we are willing to allocate
// Flat allocation size is stored in tag, which currently can encode sizes up
// to 4K, encoded as multiple of either 8 or 32 bytes.
// If we allow for larger sizes, we need to change this to 8/64, 16/128, etc.
// kMinFlatSize is bounded by tag needing to be at least FLAT * 8 bytes, and
// ideally a 'nice' size aligning with allocation and cacheline sizes like 32.
// kMaxFlatSize is bounded by the size resulting in a computed tag no greater
// than MAX_FLAT_TAG. MAX_FLAT_TAG provides for additional 'high' tag values.
static constexpr size_t kFlatOverhead = offsetof(CordRep, storage);
static constexpr size_t kMinFlatSize = 32;
static constexpr size_t kMaxFlatSize = 4096;
static constexpr size_t kMaxFlatLength = kMaxFlatSize - kFlatOverhead;
static constexpr size_t kMinFlatLength = kMinFlatSize - kFlatOverhead;
static constexpr size_t kMaxLargeFlatSize = 256 * 1024;
static constexpr size_t kMaxLargeFlatLength = kMaxLargeFlatSize - kFlatOverhead;
// kTagBase should make the Size <--> Tag computation resilient
// against changes to the value of FLAT when we add a new tag..
static constexpr uint8_t kTagBase = FLAT - 4;
// Converts the provided rounded size to the corresponding tag
constexpr uint8_t AllocatedSizeToTagUnchecked(size_t size) {
return static_cast<uint8_t>(size <= 512 ? kTagBase + size / 8
: size <= 8192
? kTagBase + 512 / 8 + size / 64 - 512 / 64
: kTagBase + 512 / 8 + ((8192 - 512) / 64) +
size / 4096 - 8192 / 4096);
}
// Converts the provided tag to the corresponding allocated size
constexpr size_t TagToAllocatedSize(uint8_t tag) {
return (tag <= kTagBase + 512 / 8) ? tag * 8 - kTagBase * 8
: (tag <= kTagBase + (512 / 8) + ((8192 - 512) / 64))
? 512 + tag * 64 - kTagBase * 64 - 512 / 8 * 64
: 8192 + tag * 4096 - kTagBase * 4096 -
((512 / 8) + ((8192 - 512) / 64)) * 4096;
}
static_assert(AllocatedSizeToTagUnchecked(kMinFlatSize) == FLAT, "");
static_assert(AllocatedSizeToTagUnchecked(kMaxLargeFlatSize) == MAX_FLAT_TAG,
"");
// RoundUp logically performs `((n + m - 1) / m) * m` to round up to the nearest
// multiple of `m`, optimized for the invariant that `m` is a power of 2.
// Android local modification: disable unsigned integer overflow sanitizer here
// to support enabling it in the clients.
ABSL_ATTRIBUTE_NO_SANITIZE_UNSIGNED_OVERFLOW
constexpr size_t RoundUp(size_t n, size_t m) {
return (n + m - 1) & (0 - m);
}
// Returns the size to the nearest equal or larger value that can be
// expressed exactly as a tag value.
inline size_t RoundUpForTag(size_t size) {
return RoundUp(size, (size <= 512) ? 8 : (size <= 8192 ? 64 : 4096));
}
// Converts the allocated size to a tag, rounding down if the size
// does not exactly match a 'tag expressible' size value. The result is
// undefined if the size exceeds the maximum size that can be encoded in
// a tag, i.e., if size is larger than TagToAllocatedSize(<max tag>).
inline uint8_t AllocatedSizeToTag(size_t size) {
const uint8_t tag = AllocatedSizeToTagUnchecked(size);
assert(tag <= MAX_FLAT_TAG);
return tag;
}
// Converts the provided tag to the corresponding available data length
constexpr size_t TagToLength(uint8_t tag) {
return TagToAllocatedSize(tag) - kFlatOverhead;
}
// Enforce that kMaxFlatSize maps to a well-known exact tag value.
static_assert(TagToAllocatedSize(MAX_FLAT_TAG) == kMaxLargeFlatSize,
"Bad tag logic");
struct CordRepFlat : public CordRep {
// Tag for explicit 'large flat' allocation
struct Large {};
// Creates a new flat node.
template <size_t max_flat_size, typename... Args>
static CordRepFlat* NewImpl(size_t len, Args... args ABSL_ATTRIBUTE_UNUSED) {
if (len <= kMinFlatLength) {
len = kMinFlatLength;
} else if (len > max_flat_size - kFlatOverhead) {
len = max_flat_size - kFlatOverhead;
}
// Round size up so it matches a size we can exactly express in a tag.
const size_t size = RoundUpForTag(len + kFlatOverhead);
void* const raw_rep = ::operator new(size);
// GCC 13 has a false-positive -Wstringop-overflow warning here.
#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(13, 0)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstringop-overflow"
#endif
CordRepFlat* rep = new (raw_rep) CordRepFlat();
rep->tag = AllocatedSizeToTag(size);
#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(13, 0)
#pragma GCC diagnostic pop
#endif
return rep;
}
static CordRepFlat* New(size_t len) { return NewImpl<kMaxFlatSize>(len); }
static CordRepFlat* New(Large, size_t len) {
return NewImpl<kMaxLargeFlatSize>(len);
}
// Deletes a CordRepFlat instance created previously through a call to New().
// Flat CordReps are allocated and constructed with raw ::operator new and
// placement new, and must be destructed and deallocated accordingly.
static void Delete(CordRep*rep) {
assert(rep->tag >= FLAT && rep->tag <= MAX_FLAT_TAG);
#if defined(__cpp_sized_deallocation)
size_t size = TagToAllocatedSize(rep->tag);
rep->~CordRep();
::operator delete(rep, size);
#else
rep->~CordRep();
::operator delete(rep);
#endif
}
// Create a CordRepFlat containing `data`, with an optional additional
// extra capacity of up to `extra` bytes. Requires that `data.size()`
// is less than kMaxFlatLength.
static CordRepFlat* Create(absl::string_view data, size_t extra = 0) {
assert(data.size() <= kMaxFlatLength);
CordRepFlat* flat = New(data.size() + (std::min)(extra, kMaxFlatLength));
memcpy(flat->Data(), data.data(), data.size());
flat->length = data.size();
return flat;
}
// Returns a pointer to the data inside this flat rep.
char* Data() { return reinterpret_cast<char*>(storage); }
const char* Data() const { return reinterpret_cast<const char*>(storage); }
// Returns the maximum capacity (payload size) of this instance.
size_t Capacity() const { return TagToLength(tag); }
// Returns the allocated size (payload + overhead) of this instance.
size_t AllocatedSize() const { return TagToAllocatedSize(tag); }
};
// Now that CordRepFlat is defined, we can define CordRep's helper casts:
inline CordRepFlat* CordRep::flat() {
assert(tag >= FLAT && tag <= MAX_FLAT_TAG);
return reinterpret_cast<CordRepFlat*>(this);
}
inline const CordRepFlat* CordRep::flat() const {
assert(tag >= FLAT && tag <= MAX_FLAT_TAG);
return reinterpret_cast<const CordRepFlat*>(this);
}
} // namespace cord_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_CORD_REP_FLAT_H_
*õ²
msoong/.intermediates/external/abseil-cpp/absl_strings_cord_hdrs/gen/my_include_dir/absl/strings/cord_buffer.h‚²// Copyright 2021 The Abseil Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: cord_buffer.h
// -----------------------------------------------------------------------------
//
// This file defines an `absl::CordBuffer` data structure to hold data for
// eventual inclusion within an existing `Cord` data structure. Cord buffers are
// useful for building large Cords that may require custom allocation of its
// associated memory.
//
#ifndef ABSL_STRINGS_CORD_BUFFER_H_
#define ABSL_STRINGS_CORD_BUFFER_H_
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <utility>
#include "absl/base/config.h"
#include "absl/base/macros.h"
#include "absl/numeric/bits.h"
#include "absl/strings/internal/cord_internal.h"
#include "absl/strings/internal/cord_rep_flat.h"
#include "absl/types/span.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
class Cord;
class CordBufferTestPeer;
// CordBuffer
//
// CordBuffer manages memory buffers for purposes such as zero-copy APIs as well
// as applications building cords with large data requiring granular control
// over the allocation and size of cord data. For example, a function creating
// a cord of random data could use a CordBuffer as follows:
//
// absl::Cord CreateRandomCord(size_t length) {
// absl::Cord cord;
// while (length > 0) {
// CordBuffer buffer = CordBuffer::CreateWithDefaultLimit(length);
// absl::Span<char> data = buffer.available_up_to(length);
// FillRandomValues(data.data(), data.size());
// buffer.IncreaseLengthBy(data.size());
// cord.Append(std::move(buffer));
// length -= data.size();
// }
// return cord;
// }
//
// CordBuffer instances are by default limited to a capacity of `kDefaultLimit`
// bytes. `kDefaultLimit` is currently just under 4KiB, but this default may
// change in the future and/or for specific architectures. The default limit is
// aimed to provide a good trade-off between performance and memory overhead.
// Smaller buffers typically incur more compute cost while larger buffers are
// more CPU efficient but create significant memory overhead because of such
// allocations being less granular. Using larger buffers may also increase the
// risk of memory fragmentation.
//
// Applications create a buffer using one of the `CreateWithDefaultLimit()` or
// `CreateWithCustomLimit()` methods. The returned instance will have a non-zero
// capacity and a zero length. Applications use the `data()` method to set the
// contents of the managed memory, and once done filling the buffer, use the
// `IncreaseLengthBy()` or 'SetLength()' method to specify the length of the
// initialized data before adding the buffer to a Cord.
//
// The `CreateWithCustomLimit()` method is intended for applications needing
// larger buffers than the default memory limit, allowing the allocation of up
// to a capacity of `kCustomLimit` bytes minus some minimum internal overhead.
// The usage of `CreateWithCustomLimit()` should be limited to only those use
// cases where the distribution of the input is relatively well known, and/or
// where the trade-off between the efficiency gains outweigh the risk of memory
// fragmentation. See the documentation for `CreateWithCustomLimit()` for more
// information on using larger custom limits.
//
// The capacity of a `CordBuffer` returned by one of the `Create` methods may
// be larger than the requested capacity due to rounding, alignment and
// granularity of the memory allocator. Applications should use the `capacity`
// method to obtain the effective capacity of the returned instance as
// demonstrated in the provided example above.
//
// CordBuffer is a move-only class. All references into the managed memory are
// invalidated when an instance is moved into either another CordBuffer instance
// or a Cord. Writing to a location obtained by a previous call to `data()`
// after an instance was moved will lead to undefined behavior.
//
// A `moved from` CordBuffer instance will have a valid, but empty state.
// CordBuffer is thread compatible.
class CordBuffer {
public:
// kDefaultLimit
//
// Default capacity limits of allocated CordBuffers.
// See the class comments for more information on allocation limits.
static constexpr size_t kDefaultLimit = cord_internal::kMaxFlatLength;
// kCustomLimit
//
// Maximum size for CreateWithCustomLimit() allocated buffers.
// Note that the effective capacity may be slightly less
// because of internal overhead of internal cord buffers.
static constexpr size_t kCustomLimit = 64U << 10;
// Constructors, Destructors and Assignment Operators
// Creates an empty CordBuffer.
CordBuffer() = default;
// Destroys this CordBuffer instance and, if not empty, releases any memory
// managed by this instance, invalidating previously returned references.
~CordBuffer();
// CordBuffer is move-only
CordBuffer(CordBuffer&& rhs) noexcept;
CordBuffer& operator=(CordBuffer&&) noexcept;
CordBuffer(const CordBuffer&) = delete;
CordBuffer& operator=(const CordBuffer&) = delete;
// CordBuffer::MaximumPayload()
//
// Returns the guaranteed maximum payload for a CordBuffer returned by the
// `CreateWithDefaultLimit()` method. While small, each internal buffer inside
// a Cord incurs an overhead to manage the length, type and reference count
// for the buffer managed inside the cord tree. Applications can use this
// method to get approximate number of buffers required for a given byte
// size, etc.
//
// For example:
// const size_t payload = absl::CordBuffer::MaximumPayload();
// const size_t buffer_count = (total_size + payload - 1) / payload;
// buffers.reserve(buffer_count);
static constexpr size_t MaximumPayload();
// Overload to the above `MaximumPayload()` except that it returns the
// maximum payload for a CordBuffer returned by the `CreateWithCustomLimit()`
// method given the provided `block_size`.
static constexpr size_t MaximumPayload(size_t block_size);
// CordBuffer::CreateWithDefaultLimit()
//
// Creates a CordBuffer instance of the desired `capacity`, capped at the
// default limit `kDefaultLimit`. The returned buffer has a guaranteed
// capacity of at least `min(kDefaultLimit, capacity)`. See the class comments
// for more information on buffer capacities and intended usage.
static CordBuffer CreateWithDefaultLimit(size_t capacity);
// CordBuffer::CreateWithCustomLimit()
//
// Creates a CordBuffer instance of the desired `capacity` rounded to an
// appropriate power of 2 size less than, or equal to `block_size`.
// Requires `block_size` to be a power of 2.
//
// If `capacity` is less than or equal to `kDefaultLimit`, then this method
// behaves identical to `CreateWithDefaultLimit`, which means that the caller
// is guaranteed to get a buffer of at least the requested capacity.
//
// If `capacity` is greater than or equal to `block_size`, then this method
// returns a buffer with an `allocated size` of `block_size` bytes. Otherwise,
// this methods returns a buffer with a suitable smaller power of 2 block size
// to satisfy the request. The actual size depends on a number of factors, and
// is typically (but not necessarily) the highest or second highest power of 2
// value less than or equal to `capacity`.
//
// The 'allocated size' includes a small amount of overhead required for
// internal state, which is currently 13 bytes on 64-bit platforms. For
// example: a buffer created with `block_size` and `capacity' set to 8KiB
// will have an allocated size of 8KiB, and an effective internal `capacity`
// of 8KiB - 13 = 8179 bytes.
//
// To demonstrate this in practice, let's assume we want to read data from
// somewhat larger files using approximately 64KiB buffers:
//
// absl::Cord ReadFromFile(int fd, size_t n) {
// absl::Cord cord;
// while (n > 0) {
// CordBuffer buffer = CordBuffer::CreateWithCustomLimit(64 << 10, n);
// absl::Span<char> data = buffer.available_up_to(n);
// ReadFileDataOrDie(fd, data.data(), data.size());
// buffer.IncreaseLengthBy(data.size());
// cord.Append(std::move(buffer));
// n -= data.size();
// }
// return cord;
// }
//
// If we'd use this function to read a file of 659KiB, we may get the
// following pattern of allocated cord buffer sizes:
//
// CreateWithCustomLimit(64KiB, 674816) --> ~64KiB (65523)
// CreateWithCustomLimit(64KiB, 674816) --> ~64KiB (65523)
// ...
// CreateWithCustomLimit(64KiB, 19586) --> ~16KiB (16371)
// CreateWithCustomLimit(64KiB, 3215) --> 3215 (at least 3215)
//
// The reason the method returns a 16K buffer instead of a roughly 19K buffer
// is to reduce memory overhead and fragmentation risks. Using carefully
// chosen power of 2 values reduces the entropy of allocated memory sizes.
//
// Additionally, let's assume we'd use the above function on files that are
// generally smaller than 64K. If we'd use 'precise' sized buffers for such
// files, than we'd get a very wide distribution of allocated memory sizes
// rounded to 4K page sizes, and we'd end up with a lot of unused capacity.
//
// In general, application should only use custom sizes if the data they are
// consuming or storing is expected to be many times the chosen block size,
// and be based on objective data and performance metrics. For example, a
// compress function may work faster and consume less CPU when using larger
// buffers. Such an application should pick a size offering a reasonable
// trade-off between expected data size, compute savings with larger buffers,
// and the cost or fragmentation effect of larger buffers.
// Applications must pick a reasonable spot on that curve, and make sure their
// data meets their expectations in size distributions such as "mostly large".
static CordBuffer CreateWithCustomLimit(size_t block_size, size_t capacity);
// CordBuffer::available()
//
// Returns the span delineating the available capacity in this buffer
// which is defined as `{ data() + length(), capacity() - length() }`.
absl::Span<char> available();
// CordBuffer::available_up_to()
//
// Returns the span delineating the available capacity in this buffer limited
// to `size` bytes. This is equivalent to `available().subspan(0, size)`.
absl::Span<char> available_up_to(size_t size);
// CordBuffer::data()
//
// Returns a non-null reference to the data managed by this instance.
// Applications are allowed to write up to `capacity` bytes of instance data.
// CordBuffer data is uninitialized by default. Reading data from an instance
// that has not yet been initialized will lead to undefined behavior.
char* data();
const char* data() const;
// CordBuffer::length()
//
// Returns the length of this instance. The default length of a CordBuffer is
// 0, indicating an 'empty' CordBuffer. Applications must specify the length
// of the data in a CordBuffer before adding it to a Cord.
size_t length() const;
// CordBuffer::capacity()
//
// Returns the capacity of this instance. All instances have a non-zero
// capacity: default and `moved from` instances have a small internal buffer.
size_t capacity() const;
// CordBuffer::IncreaseLengthBy()
//
// Increases the length of this buffer by the specified 'n' bytes.
// Applications must make sure all data in this buffer up to the new length
// has been initialized before adding a CordBuffer to a Cord: failure to do so
// will lead to undefined behavior. Requires `length() + n <= capacity()`.
// Typically, applications will use 'available_up_to()` to get a span of the
// desired capacity, and use `span.size()` to increase the length as in:
// absl::Span<char> span = buffer.available_up_to(desired);
// buffer.IncreaseLengthBy(span.size());
// memcpy(span.data(), src, span.size());
// etc...
void IncreaseLengthBy(size_t n);
// CordBuffer::SetLength()
//
// Sets the data length of this instance. Applications must make sure all data
// of the specified length has been initialized before adding a CordBuffer to
// a Cord: failure to do so will lead to undefined behavior.
// Setting the length to a small value or zero does not release any memory
// held by this CordBuffer instance. Requires `length <= capacity()`.
// Applications should preferably use the `IncreaseLengthBy()` method above
// in combination with the 'available()` or `available_up_to()` methods.
void SetLength(size_t length);
private:
// Make sure we don't accidentally over promise.
static_assert(kCustomLimit <= cord_internal::kMaxLargeFlatSize, "");
// Assume the cost of an 'uprounded' allocation to CeilPow2(size) versus
// the cost of allocating at least 1 extra flat <= 4KB:
// - Flat overhead = 13 bytes
// - Btree amortized cost / node =~ 13 bytes
// - 64 byte granularity of tcmalloc at 4K =~ 32 byte average
// CPU cost and efficiency requires we should at least 'save' something by
// splitting, as a poor man's measure, we say the slop needs to be
// at least double the cost offset to make it worth splitting: ~128 bytes.
static constexpr size_t kMaxPageSlop = 128;
// Overhead for allocation a flat.
static constexpr size_t kOverhead = cord_internal::kFlatOverhead;
using CordRepFlat = cord_internal::CordRepFlat;
// `Rep` is the internal data representation of a CordBuffer. The internal
// representation has an internal small size optimization similar to
// std::string (SSO).
struct Rep {
// Inline SSO size of a CordBuffer
static constexpr size_t kInlineCapacity = sizeof(intptr_t) * 2 - 1;
// Creates a default instance with kInlineCapacity.
Rep() : short_rep{} {}
// Creates an instance managing an allocated non zero CordRep.
explicit Rep(cord_internal::CordRepFlat* rep) : long_rep{rep} {
assert(rep != nullptr);
}
// Returns true if this instance manages the SSO internal buffer.
bool is_short() const {
constexpr size_t offset = offsetof(Short, raw_size);
return (reinterpret_cast<const char*>(this)[offset] & 1) != 0;
}
// Returns the available area of the internal SSO data
absl::Span<char> short_available() {
const size_t length = short_length();
return absl::Span<char>(short_rep.data + length,
kInlineCapacity - length);
}
// Returns the available area of the internal SSO data
absl::Span<char> long_available() const {
assert(!is_short());
const size_t length = long_rep.rep->length;
return absl::Span<char>(long_rep.rep->Data() + length,
long_rep.rep->Capacity() - length);
}
// Returns the length of the internal SSO data.
size_t short_length() const {
assert(is_short());
return static_cast<size_t>(short_rep.raw_size >> 1);
}
// Sets the length of the internal SSO data.
// Disregards any previously set CordRep instance.
void set_short_length(size_t length) {
short_rep.raw_size = static_cast<char>((length << 1) + 1);
}
// Adds `n` to the current short length.
void add_short_length(size_t n) {
assert(is_short());
short_rep.raw_size += static_cast<char>(n << 1);
}
// Returns reference to the internal SSO data buffer.
char* data() {
assert(is_short());
return short_rep.data;
}
const char* data() const {
assert(is_short());
return short_rep.data;
}
// Returns a pointer the external CordRep managed by this instance.
cord_internal::CordRepFlat* rep() const {
assert(!is_short());
return long_rep.rep;
}
// The internal representation takes advantage of the fact that allocated
// memory is always on an even address, and uses the least significant bit
// of the first or last byte (depending on endianness) as the inline size
// indicator overlapping with the least significant byte of the CordRep*.
#if defined(ABSL_IS_BIG_ENDIAN)
struct Long {
explicit Long(cord_internal::CordRepFlat* rep_arg) : rep(rep_arg) {}
void* padding;
cord_internal::CordRepFlat* rep;
};
struct Short {
char data[sizeof(Long) - 1];
char raw_size = 1;
};
#else
struct Long {
explicit Long(cord_internal::CordRepFlat* rep_arg) : rep(rep_arg) {}
cord_internal::CordRepFlat* rep;
void* padding;
};
struct Short {
char raw_size = 1;
char data[sizeof(Long) - 1];
};
#endif
union {
Long long_rep;
Short short_rep;
};
};
// Power2 functions
static bool IsPow2(size_t size) { return absl::has_single_bit(size); }
static size_t Log2Floor(size_t size) {
return static_cast<size_t>(absl::bit_width(size) - 1);
}
static size_t Log2Ceil(size_t size) {
return static_cast<size_t>(absl::bit_width(size - 1));
}
// Implementation of `CreateWithCustomLimit()`.
// This implementation allows for future memory allocation hints to
// be passed down into the CordRepFlat allocation function.
template <typename... AllocationHints>
static CordBuffer CreateWithCustomLimitImpl(size_t block_size,
size_t capacity,
AllocationHints... hints);
// Consumes the value contained in this instance and resets the instance.
// This method returns a non-null Cordrep* if the current instances manages a
// CordRep*, and resets the instance to an empty SSO instance. If the current
// instance is an SSO instance, then this method returns nullptr and sets
// `short_value` to the inlined data value. In either case, the current
// instance length is reset to zero.
// This method is intended to be used by Cord internal functions only.
cord_internal::CordRep* ConsumeValue(absl::string_view& short_value) {
cord_internal::CordRep* rep = nullptr;
if (rep_.is_short()) {
short_value = absl::string_view(rep_.data(), rep_.short_length());
} else {
rep = rep_.rep();
}
rep_.set_short_length(0);
return rep;
}
// Internal constructor.
explicit CordBuffer(cord_internal::CordRepFlat* rep) : rep_(rep) {
assert(rep != nullptr);
}
Rep rep_;
friend class Cord;
friend class CordBufferTestPeer;
};
inline constexpr size_t CordBuffer::MaximumPayload() {
return cord_internal::kMaxFlatLength;
}
inline constexpr size_t CordBuffer::MaximumPayload(size_t block_size) {
return (std::min)(kCustomLimit, block_size) - cord_internal::kFlatOverhead;
}
inline CordBuffer CordBuffer::CreateWithDefaultLimit(size_t capacity) {
if (capacity > Rep::kInlineCapacity) {
auto* rep = cord_internal::CordRepFlat::New(capacity);
rep->length = 0;
return CordBuffer(rep);
}
return CordBuffer();
}
template <typename... AllocationHints>
inline CordBuffer CordBuffer::CreateWithCustomLimitImpl(
size_t block_size, size_t capacity, AllocationHints... hints) {
assert(IsPow2(block_size));
capacity = (std::min)(capacity, kCustomLimit);
block_size = (std::min)(block_size, kCustomLimit);
if (capacity + kOverhead >= block_size) {
capacity = block_size;
} else if (capacity <= kDefaultLimit) {
capacity = capacity + kOverhead;
} else if (!IsPow2(capacity)) {
// Check if rounded up to next power 2 is a good enough fit
// with limited waste making it an acceptable direct fit.
const size_t rounded_up = size_t{1} << Log2Ceil(capacity);
const size_t slop = rounded_up - capacity;
if (slop >= kOverhead && slop <= kMaxPageSlop + kOverhead) {
capacity = rounded_up;
} else {
// Round down to highest power of 2 <= capacity.
// Consider a more aggressive step down if that may reduce the
// risk of fragmentation where 'people are holding it wrong'.
const size_t rounded_down = size_t{1} << Log2Floor(capacity);
capacity = rounded_down;
}
}
const size_t length = capacity - kOverhead;
auto* rep = CordRepFlat::New(CordRepFlat::Large(), length, hints...);
rep->length = 0;
return CordBuffer(rep);
}
inline CordBuffer CordBuffer::CreateWithCustomLimit(size_t block_size,
size_t capacity) {
return CreateWithCustomLimitImpl(block_size, capacity);
}
inline CordBuffer::~CordBuffer() {
if (!rep_.is_short()) {
cord_internal::CordRepFlat::Delete(rep_.rep());
}
}
inline CordBuffer::CordBuffer(CordBuffer&& rhs) noexcept : rep_(rhs.rep_) {
rhs.rep_.set_short_length(0);
}
inline CordBuffer& CordBuffer::operator=(CordBuffer&& rhs) noexcept {
if (!rep_.is_short()) cord_internal::CordRepFlat::Delete(rep_.rep());
rep_ = rhs.rep_;
rhs.rep_.set_short_length(0);
return *this;
}
inline absl::Span<char> CordBuffer::available() {
return rep_.is_short() ? rep_.short_available() : rep_.long_available();
}
inline absl::Span<char> CordBuffer::available_up_to(size_t size) {
return available().subspan(0, size);
}
inline char* CordBuffer::data() {
return rep_.is_short() ? rep_.data() : rep_.rep()->Data();
}
inline const char* CordBuffer::data() const {
return rep_.is_short() ? rep_.data() : rep_.rep()->Data();
}
inline size_t CordBuffer::capacity() const {
return rep_.is_short() ? Rep::kInlineCapacity : rep_.rep()->Capacity();
}
inline size_t CordBuffer::length() const {
return rep_.is_short() ? rep_.short_length() : rep_.rep()->length;
}
inline void CordBuffer::SetLength(size_t length) {
ABSL_HARDENING_ASSERT(length <= capacity());
if (rep_.is_short()) {
rep_.set_short_length(length);
} else {
rep_.rep()->length = length;
}
}
inline void CordBuffer::IncreaseLengthBy(size_t n) {
ABSL_HARDENING_ASSERT(n <= capacity() && length() + n <= capacity());
if (rep_.is_short()) {
rep_.add_short_length(n);
} else {
rep_.rep()->length += n;
}
}
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_CORD_BUFFER_H_
*š†
soong/.intermediates/external/abseil-cpp/absl_strings_cord_internal_hdrs/gen/my_include_dir/absl/strings/internal/cord_internal.h’…// Copyright 2021 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_STRINGS_INTERNAL_CORD_INTERNAL_H_
#define ABSL_STRINGS_INTERNAL_CORD_INTERNAL_H_
#include <atomic>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <string>
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/internal/endian.h"
#include "absl/base/macros.h"
#include "absl/base/nullability.h"
#include "absl/base/optimization.h"
#include "absl/container/internal/compressed_tuple.h"
#include "absl/container/internal/container_memory.h"
#include "absl/strings/string_view.h"
// We can only add poisoning if we can detect consteval executions.
#if defined(ABSL_HAVE_CONSTANT_EVALUATED) && \
(defined(ABSL_HAVE_ADDRESS_SANITIZER) || \
defined(ABSL_HAVE_MEMORY_SANITIZER))
#define ABSL_INTERNAL_CORD_HAVE_SANITIZER 1
#endif
#define ABSL_CORD_INTERNAL_NO_SANITIZE \
ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace cord_internal {
// The overhead of a vtable is too much for Cord, so we roll our own subclasses
// using only a single byte to differentiate classes from each other - the "tag"
// byte. Define the subclasses first so we can provide downcasting helper
// functions in the base class.
struct CordRep;
struct CordRepConcat;
struct CordRepExternal;
struct CordRepFlat;
struct CordRepSubstring;
struct CordRepCrc;
class CordRepBtree;
class CordzInfo;
// Default feature enable states for cord ring buffers
enum CordFeatureDefaults { kCordShallowSubcordsDefault = false };
extern std::atomic<bool> shallow_subcords_enabled;
inline void enable_shallow_subcords(bool enable) {
shallow_subcords_enabled.store(enable, std::memory_order_relaxed);
}
enum Constants {
// The inlined size to use with absl::InlinedVector.
//
// Note: The InlinedVectors in this file (and in cord.h) do not need to use
// the same value for their inlined size. The fact that they do is historical.
// It may be desirable for each to use a different inlined size optimized for
// that InlinedVector's usage.
//
// TODO(jgm): Benchmark to see if there's a more optimal value than 47 for
// the inlined vector size (47 exists for backward compatibility).
kInlinedVectorSize = 47,
// Prefer copying blocks of at most this size, otherwise reference count.
kMaxBytesToCopy = 511
};
// Emits a fatal error "Unexpected node type: xyz" and aborts the program.
[[noreturn]] void LogFatalNodeType(CordRep* rep);
// Fast implementation of memmove for up to 15 bytes. This implementation is
// safe for overlapping regions. If nullify_tail is true, the destination is
// padded with '\0' up to 15 bytes.
template <bool nullify_tail = false>
inline void SmallMemmove(char* dst, const char* src, size_t n) {
if (n >= 8) {
assert(n <= 15);
uint64_t buf1;
uint64_t buf2;
memcpy(&buf1, src, 8);
memcpy(&buf2, src + n - 8, 8);
if (nullify_tail) {
memset(dst + 7, 0, 8);
}
// GCC 12 has a false-positive -Wstringop-overflow warning here.
#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(12, 0)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstringop-overflow"
#endif
memcpy(dst, &buf1, 8);
memcpy(dst + n - 8, &buf2, 8);
#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(12, 0)
#pragma GCC diagnostic pop
#endif
} else if (n >= 4) {
uint32_t buf1;
uint32_t buf2;
memcpy(&buf1, src, 4);
memcpy(&buf2, src + n - 4, 4);
if (nullify_tail) {
memset(dst + 4, 0, 4);
memset(dst + 7, 0, 8);
}
memcpy(dst, &buf1, 4);
memcpy(dst + n - 4, &buf2, 4);
} else {
if (n != 0) {
dst[0] = src[0];
dst[n / 2] = src[n / 2];
dst[n - 1] = src[n - 1];
}
if (nullify_tail) {
memset(dst + 7, 0, 8);
memset(dst + n, 0, 8);
}
}
}
// Compact class for tracking the reference count and state flags for CordRep
// instances. Data is stored in an atomic int32_t for compactness and speed.
class RefcountAndFlags {
public:
constexpr RefcountAndFlags() : count_{kRefIncrement} {}
struct Immortal {};
explicit constexpr RefcountAndFlags(Immortal) : count_(kImmortalFlag) {}
// Increments the reference count. Imposes no memory ordering.
inline void Increment() {
count_.fetch_add(kRefIncrement, std::memory_order_relaxed);
}
// Asserts that the current refcount is greater than 0. If the refcount is
// greater than 1, decrements the reference count.
//
// Returns false if there are no references outstanding; true otherwise.
// Inserts barriers to ensure that state written before this method returns
// false will be visible to a thread that just observed this method returning
// false. Always returns false when the immortal bit is set.
inline bool Decrement() {
int32_t refcount = count_.load(std::memory_order_acquire);
assert(refcount > 0 || refcount & kImmortalFlag);
return refcount != kRefIncrement &&
count_.fetch_sub(kRefIncrement, std::memory_order_acq_rel) !=
kRefIncrement;
}
// Same as Decrement but expect that refcount is greater than 1.
inline bool DecrementExpectHighRefcount() {
int32_t refcount =
count_.fetch_sub(kRefIncrement, std::memory_order_acq_rel);
assert(refcount > 0 || refcount & kImmortalFlag);
return refcount != kRefIncrement;
}
// Returns the current reference count using acquire semantics.
inline size_t Get() const {
return static_cast<size_t>(count_.load(std::memory_order_acquire) >>
kNumFlags);
}
// Returns whether the atomic integer is 1.
// If the reference count is used in the conventional way, a
// reference count of 1 implies that the current thread owns the
// reference and no other thread shares it.
// This call performs the test for a reference count of one, and
// performs the memory barrier needed for the owning thread
// to act on the object, knowing that it has exclusive access to the
// object. Always returns false when the immortal bit is set.
inline bool IsOne() {
return count_.load(std::memory_order_acquire) == kRefIncrement;
}
bool IsImmortal() const {
return (count_.load(std::memory_order_relaxed) & kImmortalFlag) != 0;
}
private:
// We reserve the bottom bit for flag.
// kImmortalBit indicates that this entity should never be collected; it is
// used for the StringConstant constructor to avoid collecting immutable
// constant cords.
enum Flags {
kNumFlags = 1,
kImmortalFlag = 0x1,
kRefIncrement = (1 << kNumFlags),
};
std::atomic<int32_t> count_;
};
// Various representations that we allow
enum CordRepKind {
UNUSED_0 = 0,
SUBSTRING = 1,
CRC = 2,
BTREE = 3,
UNUSED_4 = 4,
EXTERNAL = 5,
// We have different tags for different sized flat arrays,
// starting with FLAT, and limited to MAX_FLAT_TAG. The below values map to an
// allocated range of 32 bytes to 256 KB. The current granularity is:
// - 8 byte granularity for flat sizes in [32 - 512]
// - 64 byte granularity for flat sizes in (512 - 8KiB]
// - 4KiB byte granularity for flat sizes in (8KiB, 256 KiB]
// If a new tag is needed in the future, then 'FLAT' and 'MAX_FLAT_TAG' should
// be adjusted as well as the Tag <---> Size mapping logic so that FLAT still
// represents the minimum flat allocation size. (32 bytes as of now).
FLAT = 6,
MAX_FLAT_TAG = 248
};
// There are various locations where we want to check if some rep is a 'plain'
// data edge, i.e. an external or flat rep. By having FLAT == EXTERNAL + 1, we
// can perform this check in a single branch as 'tag >= EXTERNAL'
// Note that we can leave this optimization to the compiler. The compiler will
// DTRT when it sees a condition like `tag == EXTERNAL || tag >= FLAT`.
static_assert(FLAT == EXTERNAL + 1, "EXTERNAL and FLAT not consecutive");
struct CordRep {
// Result from an `extract edge` operation. Contains the (possibly changed)
// tree node as well as the extracted edge, or {tree, nullptr} if no edge
// could be extracted.
// On success, the returned `tree` value is null if `extracted` was the only
// data edge inside the tree, a data edge if there were only two data edges in
// the tree, or the (possibly new / smaller) remaining tree with the extracted
// data edge removed.
struct ExtractResult {
CordRep* tree;
CordRep* extracted;
};
CordRep() = default;
constexpr CordRep(RefcountAndFlags::Immortal immortal, size_t l)
: length(l), refcount(immortal), tag(EXTERNAL), storage{} {}
// The following three fields have to be less than 32 bytes since
// that is the smallest supported flat node size. Some code optimizations rely
// on the specific layout of these fields. Notably: the non-trivial field
// `refcount` being preceded by `length`, and being tailed by POD data
// members only.
// LINT.IfChange
size_t length;
RefcountAndFlags refcount;
// If tag < FLAT, it represents CordRepKind and indicates the type of node.
// Otherwise, the node type is CordRepFlat and the tag is the encoded size.
uint8_t tag;
// `storage` provides two main purposes:
// - the starting point for FlatCordRep.Data() [flexible-array-member]
// - 3 bytes of additional storage for use by derived classes.
// The latter is used by CordrepConcat and CordRepBtree. CordRepConcat stores
// a 'depth' value in storage[0], and the (future) CordRepBtree class stores
// `height`, `begin` and `end` in the 3 entries. Otherwise we would need to
// allocate room for these in the derived class, as not all compilers reuse
// padding space from the base class (clang and gcc do, MSVC does not, etc)
uint8_t storage[3];
// LINT.ThenChange(cord_rep_btree.h:copy_raw)
// Returns true if this instance's tag matches the requested type.
constexpr bool IsSubstring() const { return tag == SUBSTRING; }
constexpr bool IsCrc() const { return tag == CRC; }
constexpr bool IsExternal() const { return tag == EXTERNAL; }
constexpr bool IsFlat() const { return tag >= FLAT; }
constexpr bool IsBtree() const { return tag == BTREE; }
inline CordRepSubstring* substring();
inline const CordRepSubstring* substring() const;
inline CordRepCrc* crc();
inline const CordRepCrc* crc() const;
inline CordRepExternal* external();
inline const CordRepExternal* external() const;
inline CordRepFlat* flat();
inline const CordRepFlat* flat() const;
inline CordRepBtree* btree();
inline const CordRepBtree* btree() const;
// --------------------------------------------------------------------
// Memory management
// Destroys the provided `rep`.
static void Destroy(CordRep* rep);
// Increments the reference count of `rep`.
// Requires `rep` to be a non-null pointer value.
static inline CordRep* Ref(CordRep* rep);
// Decrements the reference count of `rep`. Destroys rep if count reaches
// zero. Requires `rep` to be a non-null pointer value.
static inline void Unref(CordRep* rep);
};
struct CordRepSubstring : public CordRep {
size_t start; // Starting offset of substring in child
CordRep* child;
// Creates a substring on `child`, adopting a reference on `child`.
// Requires `child` to be either a flat or external node, and `pos` and `n` to
// form a non-empty partial sub range of `'child`, i.e.:
// `n > 0 && n < length && n + pos <= length`
static inline CordRepSubstring* Create(CordRep* child, size_t pos, size_t n);
// Creates a substring of `rep`. Does not adopt a reference on `rep`.
// Requires `IsDataEdge(rep) && n > 0 && pos + n <= rep->length`.
// If `n == rep->length` then this method returns `CordRep::Ref(rep)`
// If `rep` is a substring of a flat or external node, then this method will
// return a new substring of that flat or external node with `pos` adjusted
// with the original `start` position.
static inline CordRep* Substring(CordRep* rep, size_t pos, size_t n);
};
// Type for function pointer that will invoke the releaser function and also
// delete the `CordRepExternalImpl` corresponding to the passed in
// `CordRepExternal`.
using ExternalReleaserInvoker = void (*)(CordRepExternal*);
// External CordReps are allocated together with a type erased releaser. The
// releaser is stored in the memory directly following the CordRepExternal.
struct CordRepExternal : public CordRep {
CordRepExternal() = default;
explicit constexpr CordRepExternal(absl::string_view str)
: CordRep(RefcountAndFlags::Immortal{}, str.size()),
base(str.data()),
releaser_invoker(nullptr) {}
const char* base;
// Pointer to function that knows how to call and destroy the releaser.
ExternalReleaserInvoker releaser_invoker;
// Deletes (releases) the external rep.
// Requires rep != nullptr and rep->IsExternal()
static void Delete(CordRep* rep);
};
// Use go/ranked-overloads for dispatching.
struct Rank0 {};
struct Rank1 : Rank0 {};
template <typename Releaser,
typename = ::std::invoke_result_t<Releaser, absl::string_view>>
void InvokeReleaser(Rank1, Releaser&& releaser, absl::string_view data) {
::std::invoke(std::forward<Releaser>(releaser), data);
}
template <typename Releaser, typename = ::std::invoke_result_t<Releaser>>
void InvokeReleaser(Rank0, Releaser&& releaser, absl::string_view) {
::std::invoke(std::forward<Releaser>(releaser));
}
// We use CompressedTuple so that we can benefit from EBCO.
template <typename Releaser>
struct CordRepExternalImpl
: public CordRepExternal,
public ::absl::container_internal::CompressedTuple<Releaser> {
// The extra int arg is so that we can avoid interfering with copy/move
// constructors while still benefitting from perfect forwarding.
template <typename T>
CordRepExternalImpl(T&& releaser, int)
: CordRepExternalImpl::CompressedTuple(std::forward<T>(releaser)) {
this->releaser_invoker = &Release;
}
~CordRepExternalImpl() {
InvokeReleaser(Rank1{}, std::move(this->template get<0>()),
absl::string_view(base, length));
}
static void Release(CordRepExternal* rep) {
delete static_cast<CordRepExternalImpl*>(rep);
}
};
inline CordRepSubstring* CordRepSubstring::Create(CordRep* child, size_t pos,
size_t n) {
assert(child != nullptr);
assert(n > 0);
assert(n < child->length);
assert(pos < child->length);
assert(n <= child->length - pos);
// Move to strategical places inside the Cord logic and make this an assert.
if (ABSL_PREDICT_FALSE(!(child->IsExternal() || child->IsFlat()))) {
LogFatalNodeType(child);
}
CordRepSubstring* rep = new CordRepSubstring();
rep->length = n;
rep->tag = SUBSTRING;
rep->start = pos;
rep->child = child;
return rep;
}
inline CordRep* CordRepSubstring::Substring(CordRep* rep, size_t pos,
size_t n) {
assert(rep != nullptr);
assert(n != 0);
assert(pos < rep->length);
assert(n <= rep->length - pos);
if (n == rep->length) return CordRep::Ref(rep);
if (rep->IsSubstring()) {
pos += rep->substring()->start;
rep = rep->substring()->child;
}
CordRepSubstring* substr = new CordRepSubstring();
substr->length = n;
substr->tag = SUBSTRING;
substr->start = pos;
substr->child = CordRep::Ref(rep);
return substr;
}
inline void CordRepExternal::Delete(CordRep* rep) {
assert(rep != nullptr && rep->IsExternal());
auto* rep_external = static_cast<CordRepExternal*>(rep);
assert(rep_external->releaser_invoker != nullptr);
rep_external->releaser_invoker(rep_external);
}
template <typename Str>
struct ConstInitExternalStorage {
ABSL_CONST_INIT static CordRepExternal value;
};
template <typename Str>
ABSL_CONST_INIT CordRepExternal
ConstInitExternalStorage<Str>::value(Str::value);
enum {
kMaxInline = 15,
};
constexpr char GetOrNull(absl::string_view data, size_t pos) {
return pos < data.size() ? data[pos] : '\0';
}
// We store cordz_info as 64 bit pointer value in little endian format. This
// guarantees that the least significant byte of cordz_info matches the first
// byte of the inline data representation in `data`, which holds the inlined
// size or the 'is_tree' bit.
using cordz_info_t = int64_t;
// Assert that the `cordz_info` pointer value perfectly overlaps the last half
// of `data` and can hold a pointer value.
static_assert(sizeof(cordz_info_t) * 2 == kMaxInline + 1, "");
static_assert(sizeof(cordz_info_t) >= sizeof(intptr_t), "");
// LittleEndianByte() creates a little endian representation of 'value', i.e.:
// a little endian value where the first byte in the host's representation
// holds 'value`, with all other bytes being 0.
static constexpr cordz_info_t LittleEndianByte(unsigned char value) {
#if defined(ABSL_IS_BIG_ENDIAN)
return static_cast<cordz_info_t>(value) << ((sizeof(cordz_info_t) - 1) * 8);
#else
return value;
#endif
}
class InlineData {
public:
// DefaultInitType forces the use of the default initialization constructor.
enum DefaultInitType { kDefaultInit };
// kNullCordzInfo holds the little endian representation of intptr_t(1)
// This is the 'null' / initial value of 'cordz_info'. The null value
// is specifically big endian 1 as with 64-bit pointers, the last
// byte of cordz_info overlaps with the last byte holding the tag.
static constexpr cordz_info_t kNullCordzInfo = LittleEndianByte(1);
// kTagOffset contains the offset of the control byte / tag. This constant is
// intended mostly for debugging purposes: do not remove this constant as it
// is actively inspected and used by gdb pretty printing code.
static constexpr size_t kTagOffset = 0;
// Implement `~InlineData()` conditionally: we only need this destructor to
// unpoison poisoned instances under *SAN, and it will only compile correctly
// if the current compiler supports `absl::is_constant_evaluated()`.
#ifdef ABSL_INTERNAL_CORD_HAVE_SANITIZER
~InlineData() noexcept { unpoison(); }
#endif
constexpr InlineData() noexcept { poison_this(); }
explicit InlineData(DefaultInitType) noexcept : rep_(kDefaultInit) {
poison_this();
}
explicit InlineData(CordRep* rep) noexcept : rep_(rep) {
ABSL_ASSERT(rep != nullptr);
}
// Explicit constexpr constructor to create a constexpr InlineData
// value. Creates an inlined SSO value if `rep` is null, otherwise
// creates a tree instance value.
constexpr InlineData(absl::string_view sv, CordRep* rep) noexcept
: rep_(rep ? Rep(rep) : Rep(sv)) {
poison();
}
constexpr InlineData(const InlineData& rhs) noexcept;
InlineData& operator=(const InlineData& rhs) noexcept;
friend void swap(InlineData& lhs, InlineData& rhs) noexcept;
friend bool operator==(const InlineData& lhs, const InlineData& rhs) {
#ifdef ABSL_INTERNAL_CORD_HAVE_SANITIZER
const Rep l = lhs.rep_.SanitizerSafeCopy();
const Rep r = rhs.rep_.SanitizerSafeCopy();
return memcmp(&l, &r, sizeof(l)) == 0;
#else
return memcmp(&lhs, &rhs, sizeof(lhs)) == 0;
#endif
}
friend bool operator!=(const InlineData& lhs, const InlineData& rhs) {
return !operator==(lhs, rhs);
}
// Poisons the unused inlined SSO data if the current instance
// is inlined, else un-poisons the entire instance.
constexpr void poison();
// Un-poisons this instance.
constexpr void unpoison();
// Poisons the current instance. This is used on default initialization.
constexpr void poison_this();
// Returns true if the current instance is empty.
// The 'empty value' is an inlined data value of zero length.
bool is_empty() const { return rep_.tag() == 0; }
// Returns true if the current instance holds a tree value.
bool is_tree() const { return (rep_.tag() & 1) != 0; }
// Returns true if the current instance holds a cordz_info value.
// Requires the current instance to hold a tree value.
bool is_profiled() const {
assert(is_tree());
return rep_.cordz_info() != kNullCordzInfo;
}
// Returns true if either of the provided instances hold a cordz_info value.
// This method is more efficient than the equivalent `data1.is_profiled() ||
// data2.is_profiled()`. Requires both arguments to hold a tree.
static bool is_either_profiled(const InlineData& data1,
const InlineData& data2) {
assert(data1.is_tree() && data2.is_tree());
return (data1.rep_.cordz_info() | data2.rep_.cordz_info()) !=
kNullCordzInfo;
}
// Returns the cordz_info sampling instance for this instance, or nullptr
// if the current instance is not sampled and does not have CordzInfo data.
// Requires the current instance to hold a tree value.
CordzInfo* cordz_info() const {
assert(is_tree());
intptr_t info = static_cast<intptr_t>(absl::little_endian::ToHost64(
static_cast<uint64_t>(rep_.cordz_info())));
assert(info & 1);
return reinterpret_cast<CordzInfo*>(info - 1);
}
// Sets the current cordz_info sampling instance for this instance, or nullptr
// if the current instance is not sampled and does not have CordzInfo data.
// Requires the current instance to hold a tree value.
void set_cordz_info(CordzInfo* cordz_info) {
assert(is_tree());
uintptr_t info = reinterpret_cast<uintptr_t>(cordz_info) | 1;
rep_.set_cordz_info(
static_cast<cordz_info_t>(absl::little_endian::FromHost64(info)));
}
// Resets the current cordz_info to null / empty.
void clear_cordz_info() {
assert(is_tree());
rep_.set_cordz_info(kNullCordzInfo);
}
// Returns a read only pointer to the character data inside this instance.
// Requires the current instance to hold inline data.
const char* as_chars() const {
assert(!is_tree());
return rep_.as_chars();
}
// Returns a mutable pointer to the character data inside this instance.
// Should be used for 'write only' operations setting an inlined value.
// Applications can set the value of inlined data either before or after
// setting the inlined size, i.e., both of the below are valid:
//
// // Set inlined data and inline size
// memcpy(data_.as_chars(), data, size);
// data_.set_inline_size(size);
//
// // Set inlined size and inline data
// data_.set_inline_size(size);
// memcpy(data_.as_chars(), data, size);
//
// It's an error to read from the returned pointer without a preceding write
// if the current instance does not hold inline data, i.e.: is_tree() == true.
char* as_chars() { return rep_.as_chars(); }
// Returns the tree value of this value.
// Requires the current instance to hold a tree value.
CordRep* as_tree() const {
assert(is_tree());
return rep_.tree();
}
void set_inline_data(const char* data, size_t n) {
ABSL_ASSERT(n <= kMaxInline);
unpoison();
rep_.set_tag(static_cast<int8_t>(n << 1));
SmallMemmove<true>(rep_.as_chars(), data, n);
poison();
}
void CopyInlineToString(std::string* dst) const {
assert(!is_tree());
// As Cord can store only 15 bytes it is smaller than std::string's
// small string optimization buffer size. Therefore we will always trigger
// the fast assign short path.
//
// Copying with a size equal to the maximum allows more efficient, wider
// stores to be used and no branching.
dst->assign(rep_.SanitizerSafeCopy().as_chars(), kMaxInline);
// After the copy we then change the size and put in a 0 byte.
dst->erase(inline_size());
}
void copy_max_inline_to(char* dst) const {
assert(!is_tree());
memcpy(dst, rep_.SanitizerSafeCopy().as_chars(), kMaxInline);
}
// Initialize this instance to holding the tree value `rep`,
// initializing the cordz_info to null, i.e.: 'not profiled'.
void make_tree(CordRep* rep) {
unpoison();
rep_.make_tree(rep);
}
// Set the tree value of this instance to 'rep`.
// Requires the current instance to already hold a tree value.
// Does not affect the value of cordz_info.
void set_tree(CordRep* rep) {
assert(is_tree());
rep_.set_tree(rep);
}
// Returns the size of the inlined character data inside this instance.
// Requires the current instance to hold inline data.
size_t inline_size() const { return rep_.inline_size(); }
// Sets the size of the inlined character data inside this instance.
// Requires `size` to be <= kMaxInline.
// See the documentation on 'as_chars()' for more information and examples.
void set_inline_size(size_t size) {
unpoison();
rep_.set_inline_size(size);
poison();
}
// Compares 'this' inlined data with rhs. The comparison is a straightforward
// lexicographic comparison. `Compare()` returns values as follows:
//
// -1 'this' InlineData instance is smaller
// 0 the InlineData instances are equal
// 1 'this' InlineData instance larger
int Compare(const InlineData& rhs) const {
return Compare(rep_.SanitizerSafeCopy(), rhs.rep_.SanitizerSafeCopy());
}
private:
struct Rep {
// See cordz_info_t for forced alignment and size of `cordz_info` details.
struct AsTree {
explicit constexpr AsTree(absl::cord_internal::CordRep* tree)
: rep(tree) {}
cordz_info_t cordz_info = kNullCordzInfo;
absl::cord_internal::CordRep* rep;
};
explicit Rep(DefaultInitType) {}
constexpr Rep() : data{0} {}
constexpr Rep(const Rep&) = default;
constexpr Rep& operator=(const Rep&) = default;
explicit constexpr Rep(CordRep* rep) : as_tree(rep) {}
explicit constexpr Rep(absl::string_view chars)
: data{static_cast<char>((chars.size() << 1)),
GetOrNull(chars, 0),
GetOrNull(chars, 1),
GetOrNull(chars, 2),
GetOrNull(chars, 3),
GetOrNull(chars, 4),
GetOrNull(chars, 5),
GetOrNull(chars, 6),
GetOrNull(chars, 7),
GetOrNull(chars, 8),
GetOrNull(chars, 9),
GetOrNull(chars, 10),
GetOrNull(chars, 11),
GetOrNull(chars, 12),
GetOrNull(chars, 13),
GetOrNull(chars, 14)} {}
#ifdef ABSL_INTERNAL_CORD_HAVE_SANITIZER
// Break compiler optimization for cases when value is allocated on the
// stack. Compiler assumes that the the variable is fully accessible
// regardless of our poisoning.
// Missing report: https://github.com/llvm/llvm-project/issues/100640
const Rep* self() const {
const Rep* volatile ptr = this;
return ptr;
}
Rep* self() {
Rep* volatile ptr = this;
return ptr;
}
#else
constexpr const Rep* self() const { return this; }
constexpr Rep* self() { return this; }
#endif
// Disable sanitizer as we must always be able to read `tag`.
ABSL_CORD_INTERNAL_NO_SANITIZE
int8_t tag() const { return reinterpret_cast<const int8_t*>(this)[0]; }
void set_tag(int8_t rhs) { reinterpret_cast<int8_t*>(self())[0] = rhs; }
char* as_chars() { return self()->data + 1; }
const char* as_chars() const { return self()->data + 1; }
bool is_tree() const { return (self()->tag() & 1) != 0; }
size_t inline_size() const {
ABSL_ASSERT(!self()->is_tree());
return static_cast<size_t>(self()->tag()) >> 1;
}
void set_inline_size(size_t size) {
ABSL_ASSERT(size <= kMaxInline);
self()->set_tag(static_cast<int8_t>(size << 1));
}
CordRep* tree() const { return self()->as_tree.rep; }
void set_tree(CordRep* rhs) { self()->as_tree.rep = rhs; }
cordz_info_t cordz_info() const { return self()->as_tree.cordz_info; }
void set_cordz_info(cordz_info_t rhs) { self()->as_tree.cordz_info = rhs; }
void make_tree(CordRep* tree) {
self()->as_tree.rep = tree;
self()->as_tree.cordz_info = kNullCordzInfo;
}
#ifdef ABSL_INTERNAL_CORD_HAVE_SANITIZER
constexpr Rep SanitizerSafeCopy() const {
if (!absl::is_constant_evaluated()) {
Rep res;
if (is_tree()) {
res = *this;
} else {
res.set_tag(tag());
memcpy(res.as_chars(), as_chars(), inline_size());
}
return res;
} else {
return *this;
}
}
#else
constexpr const Rep& SanitizerSafeCopy() const { return *this; }
#endif
// If the data has length <= kMaxInline, we store it in `data`, and
// store the size in the first char of `data` shifted left + 1.
// Else we store it in a tree and store a pointer to that tree in
// `as_tree.rep` with a tagged pointer to make `tag() & 1` non zero.
union {
char data[kMaxInline + 1];
AsTree as_tree;
};
// TODO(b/145829486): see swap(InlineData, InlineData) for more info.
inline void SwapValue(Rep rhs, Rep& refrhs) {
memcpy(&refrhs, this, sizeof(*this));
memcpy(this, &rhs, sizeof(*this));
}
};
// Private implementation of `Compare()`
static inline int Compare(const Rep& lhs, const Rep& rhs) {
uint64_t x, y;
memcpy(&x, lhs.as_chars(), sizeof(x));
memcpy(&y, rhs.as_chars(), sizeof(y));
if (x == y) {
memcpy(&x, lhs.as_chars() + 7, sizeof(x));
memcpy(&y, rhs.as_chars() + 7, sizeof(y));
if (x == y) {
if (lhs.inline_size() == rhs.inline_size()) return 0;
return lhs.inline_size() < rhs.inline_size() ? -1 : 1;
}
}
x = absl::big_endian::FromHost64(x);
y = absl::big_endian::FromHost64(y);
return x < y ? -1 : 1;
}
Rep rep_;
};
static_assert(sizeof(InlineData) == kMaxInline + 1, "");
#ifdef ABSL_INTERNAL_CORD_HAVE_SANITIZER
constexpr InlineData::InlineData(const InlineData& rhs) noexcept
: rep_(rhs.rep_.SanitizerSafeCopy()) {
poison();
}
inline InlineData& InlineData::operator=(const InlineData& rhs) noexcept {
unpoison();
rep_ = rhs.rep_.SanitizerSafeCopy();
poison();
return *this;
}
constexpr void InlineData::poison_this() {
if (!absl::is_constant_evaluated()) {
container_internal::SanitizerPoisonObject(this);
}
}
constexpr void InlineData::unpoison() {
if (!absl::is_constant_evaluated()) {
container_internal::SanitizerUnpoisonObject(this);
}
}
constexpr void InlineData::poison() {
if (!absl::is_constant_evaluated()) {
if (is_tree()) {
container_internal::SanitizerUnpoisonObject(this);
} else if (const size_t size = inline_size()) {
if (size < kMaxInline) {
const char* end = rep_.as_chars() + size;
container_internal::SanitizerPoisonMemoryRegion(end, kMaxInline - size);
}
} else {
container_internal::SanitizerPoisonObject(this);
}
}
}
#else // ABSL_INTERNAL_CORD_HAVE_SANITIZER
constexpr InlineData::InlineData(const InlineData&) noexcept = default;
inline InlineData& InlineData::operator=(const InlineData&) noexcept = default;
constexpr void InlineData::poison_this() {}
constexpr void InlineData::unpoison() {}
constexpr void InlineData::poison() {}
#endif // ABSL_INTERNAL_CORD_HAVE_SANITIZER
inline CordRepSubstring* CordRep::substring() {
assert(IsSubstring());
return static_cast<CordRepSubstring*>(this);
}
inline const CordRepSubstring* CordRep::substring() const {
assert(IsSubstring());
return static_cast<const CordRepSubstring*>(this);
}
inline CordRepExternal* CordRep::external() {
assert(IsExternal());
return static_cast<CordRepExternal*>(this);
}
inline const CordRepExternal* CordRep::external() const {
assert(IsExternal());
return static_cast<const CordRepExternal*>(this);
}
inline CordRep* CordRep::Ref(CordRep* rep) {
// ABSL_ASSUME is a workaround for
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105585
ABSL_ASSUME(rep != nullptr);
rep->refcount.Increment();
return rep;
}
inline void CordRep::Unref(CordRep* rep) {
assert(rep != nullptr);
// Expect refcount to be 0. Avoiding the cost of an atomic decrement should
// typically outweigh the cost of an extra branch checking for ref == 1.
if (ABSL_PREDICT_FALSE(!rep->refcount.DecrementExpectHighRefcount())) {
Destroy(rep);
}
}
inline void swap(InlineData& lhs, InlineData& rhs) noexcept {
lhs.unpoison();
rhs.unpoison();
// TODO(b/145829486): `std::swap(lhs.rep_, rhs.rep_)` results in bad codegen
// on clang, spilling the temporary swap value on the stack. Since `Rep` is
// trivial, we can make clang DTRT by calling a hand-rolled `SwapValue` where
// we pass `rhs` both by value (register allocated) and by reference. The IR
// then folds and inlines correctly into an optimized swap without spill.
lhs.rep_.SwapValue(rhs.rep_, rhs.rep_);
rhs.poison();
lhs.poison();
}
} // namespace cord_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_CORD_INTERNAL_H_
*¸
osoong/.intermediates/external/abseil-cpp/absl_strings_cord_hdrs/gen/my_include_dir/absl/strings/cord_analysis.hÄ// Copyright 2021 The Abseil Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_STRINGS_CORD_ANALYSIS_H_
#define ABSL_STRINGS_CORD_ANALYSIS_H_
#include <cstddef>
#include <cstdint>
#include "absl/base/config.h"
#include "absl/base/nullability.h"
#include "absl/strings/internal/cord_internal.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace cord_internal {
// Returns the *approximate* number of bytes held in full or in part by this
// Cord (which may not remain the same between invocations). Cords that share
// memory could each be "charged" independently for the same shared memory.
size_t GetEstimatedMemoryUsage(const CordRep* absl_nonnull rep);
// Returns the *approximate* number of bytes held in full or in part by this
// Cord for the distinct memory held by this cord. This is similar to
// `GetEstimatedMemoryUsage()`, except that if the cord has multiple references
// to the same memory, that memory is only counted once.
//
// For example:
// absl::Cord cord;
// cord.append(some_other_cord);
// cord.append(some_other_cord);
// // Calls GetEstimatedMemoryUsage() and counts `other_cord` twice:
// cord.EstimatedMemoryUsage(kTotal);
// // Calls GetMorePreciseMemoryUsage() and counts `other_cord` once:
// cord.EstimatedMemoryUsage(kTotalMorePrecise);
//
// This is more expensive than `GetEstimatedMemoryUsage()` as it requires
// deduplicating all memory references.
size_t GetMorePreciseMemoryUsage(const CordRep* absl_nonnull rep);
// Returns the *approximate* number of bytes held in full or in part by this
// CordRep weighted by the sharing ratio of that data. For example, if some data
// edge is shared by 4 different Cords, then each cord is attribute 1/4th of
// the total memory usage as a 'fair share' of the total memory usage.
size_t GetEstimatedFairShareMemoryUsage(const CordRep* absl_nonnull rep);
} // namespace cord_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_CORD_ANALYSIS_H_
* –
‡soong/.intermediates/external/abseil-cpp/absl_functional_any_invocable_hdrs/gen/my_include_dir/absl/functional/internal/any_invocable.h’•// Copyright 2022 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Implementation details for `absl::AnyInvocable`
#ifndef ABSL_FUNCTIONAL_INTERNAL_ANY_INVOCABLE_H_
#define ABSL_FUNCTIONAL_INTERNAL_ANY_INVOCABLE_H_
////////////////////////////////////////////////////////////////////////////////
// //
// This implementation chooses between local storage and remote storage for //
// the contained target object based on the target object's size, alignment //
// requirements, and whether or not it has a nothrow move constructor. //
// Additional optimizations are performed when the object is a trivially //
// copyable type [basic.types]. //
// //
// There are three datamembers per `AnyInvocable` instance //
// //
// 1) A union containing either //
// - A pointer to the target object referred to via a void*, or //
// - the target object, emplaced into a raw char buffer //
// //
// 2) A function pointer to a "manager" function operation that takes a //
// discriminator and logically branches to either perform a move operation //
// or destroy operation based on that discriminator. //
// //
// 3) A function pointer to an "invoker" function operation that invokes the //
// target object, directly returning the result. //
// //
// When in the logically empty state, the manager function is an empty //
// function and the invoker function is one that would be undefined behavior //
// to call. //
// //
// An additional optimization is performed when converting from one //
// AnyInvocable to another where only the noexcept specification and/or the //
// cv/ref qualifiers of the function type differ. In these cases, the //
// conversion works by "moving the guts", similar to if they were the same //
// exact type, as opposed to having to perform an additional layer of //
// wrapping through remote storage. //
// //
////////////////////////////////////////////////////////////////////////////////
// IWYU pragma: private, include "absl/functional/any_invocable.h"
#include <cassert>
#include <cstddef>
#include <cstring>
#include <exception>
#include <functional>
#include <memory>
#include <new>
#include <type_traits>
#include <utility>
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/macros.h"
#include "absl/base/optimization.h"
#include "absl/meta/type_traits.h"
#include "absl/utility/utility.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
// Defined in functional/any_invocable.h
template <class Sig>
class AnyInvocable;
namespace internal_any_invocable {
// Constants relating to the small-object-storage for AnyInvocable
enum StorageProperty : std::size_t {
kAlignment = alignof(std::max_align_t), // The alignment of the storage
kStorageSize = sizeof(void*) * 2 // The size of the storage
};
////////////////////////////////////////////////////////////////////////////////
//
// A metafunction for checking if a type is an AnyInvocable instantiation.
// This is used during conversion operations.
template <class T>
struct IsAnyInvocable : std::false_type {};
template <class Sig>
struct IsAnyInvocable<AnyInvocable<Sig>> : std::true_type {};
//
////////////////////////////////////////////////////////////////////////////////
// A metafunction that tells us whether or not a target function type should be
// stored locally in the small object optimization storage
template <class T>
constexpr bool IsStoredLocally() {
if constexpr (sizeof(T) <= kStorageSize && alignof(T) <= kAlignment &&
kAlignment % alignof(T) == 0) {
return std::is_nothrow_move_constructible<T>::value;
}
return false;
}
// An implementation of std::remove_cvref_t of C++20.
template <class T>
using RemoveCVRef =
typename std::remove_cv<typename std::remove_reference<T>::type>::type;
// An implementation of std::invoke_r of C++23.
template <class ReturnType, class F, class... P>
ReturnType InvokeR(F&& f, P&&... args) {
if constexpr (std::is_void_v<ReturnType>) {
std::invoke(std::forward<F>(f), std::forward<P>(args)...);
} else {
return std::invoke(std::forward<F>(f), std::forward<P>(args)...);
}
}
//
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
///
// A metafunction that takes a "T" corresponding to a parameter type of the
// user's specified function type, and yields the parameter type to use for the
// type-erased invoker. In order to prevent observable moves, this must be
// either a reference or, if the type is trivial, the original parameter type
// itself. Since the parameter type may be incomplete at the point that this
// metafunction is used, we can only do this optimization for scalar types
// rather than for any trivial type.
template <typename T>
T ForwardImpl(std::true_type);
template <typename T>
T&& ForwardImpl(std::false_type);
// NOTE: We deliberately use an intermediate struct instead of a direct alias,
// as a workaround for b/206991861 on MSVC versions < 1924.
template <class T>
struct ForwardedParameter {
using type = decltype((
ForwardImpl<T>)(std::integral_constant<bool,
std::is_scalar<T>::value>()));
};
template <class T>
using ForwardedParameterType = typename ForwardedParameter<T>::type;
//
////////////////////////////////////////////////////////////////////////////////
// A discriminator when calling the "manager" function that describes operation
// type-erased operation should be invoked.
//
// "relocate_from_to" specifies that the manager should perform a move.
//
// "dispose" specifies that the manager should perform a destroy.
enum class FunctionToCall : bool { relocate_from_to, dispose };
// The portion of `AnyInvocable` state that contains either a pointer to the
// target object or the object itself in local storage
union TypeErasedState {
struct {
// A pointer to the type-erased object when remotely stored
void* target;
// The size of the object for `RemoteManagerTrivial`
std::size_t size;
} remote;
// Local-storage for the type-erased object when small and trivial enough
alignas(kAlignment) unsigned char storage[kStorageSize];
};
// A typed accessor for the object in `TypeErasedState` storage
template <class T>
T& ObjectInLocalStorage(TypeErasedState* const state) {
// We launder here because the storage may be reused with the same type.
return *std::launder(reinterpret_cast<T*>(&state->storage));
}
// The type for functions issuing lifetime-related operations: move and dispose
// A pointer to such a function is contained in each `AnyInvocable` instance.
// NOTE: When specifying `FunctionToCall::`dispose, the same state must be
// passed as both "from" and "to".
using ManagerType = void(FunctionToCall /*operation*/,
TypeErasedState* /*from*/,
TypeErasedState* /*to*/) noexcept(true);
// The type for functions issuing the actual invocation of the object
// A pointer to such a function is contained in each AnyInvocable instance.
template <bool SigIsNoexcept, class ReturnType, class... P>
using InvokerType = ReturnType(
TypeErasedState*, ForwardedParameterType<P>...) noexcept(SigIsNoexcept);
// The manager that is used when AnyInvocable is empty
inline void EmptyManager(FunctionToCall /*operation*/,
TypeErasedState* /*from*/,
TypeErasedState* /*to*/) noexcept {}
// The manager that is used when a target function is in local storage and is
// a trivially copyable type.
inline void LocalManagerTrivial(FunctionToCall /*operation*/,
TypeErasedState* const from,
TypeErasedState* const to) noexcept {
// This single statement without branching handles both possible operations.
//
// For FunctionToCall::dispose, "from" and "to" point to the same state, and
// so this assignment logically would do nothing.
//
// Note: Correctness here relies on http://wg21.link/p0593, which has only
// become standard in C++20, though implementations do not break it in
// practice for earlier versions of C++.
//
// The correct way to do this without that paper is to first placement-new a
// default-constructed T in "to->storage" prior to the memmove, but doing so
// requires a different function to be created for each T that is stored
// locally, which can cause unnecessary bloat and be less cache friendly.
*to = *from;
// Note: Because the type is trivially copyable, the destructor does not need
// to be called ("trivially copyable" requires a trivial destructor).
}
// The manager that is used when a target function is in local storage and is
// not a trivially copyable type.
template <class T>
void LocalManagerNontrivial(FunctionToCall operation,
TypeErasedState* const from,
TypeErasedState* const to) noexcept {
static_assert(IsStoredLocally<T>(),
"Local storage must only be used for supported types.");
static_assert(!std::is_trivially_copyable<T>::value,
"Locally stored types must be trivially copyable.");
T& from_object = (ObjectInLocalStorage<T>)(from);
switch (operation) {
case FunctionToCall::relocate_from_to:
// NOTE: Requires that the left-hand operand is already empty.
::new (static_cast<void*>(&to->storage)) T(std::move(from_object));
ABSL_FALLTHROUGH_INTENDED;
case FunctionToCall::dispose:
from_object.~T(); // Must not throw. // NOLINT
return;
}
ABSL_UNREACHABLE();
}
// The invoker that is used when a target function is in local storage
// Note: QualTRef here is the target function type along with cv and reference
// qualifiers that must be used when calling the function.
template <bool SigIsNoexcept, class ReturnType, class QualTRef, class... P>
ReturnType LocalInvoker(
TypeErasedState* const state,
ForwardedParameterType<P>... args) noexcept(SigIsNoexcept) {
using RawT = RemoveCVRef<QualTRef>;
static_assert(
IsStoredLocally<RawT>(),
"Target object must be in local storage in order to be invoked from it.");
auto& f = (ObjectInLocalStorage<RawT>)(state);
return (InvokeR<ReturnType>)(static_cast<QualTRef>(f),
static_cast<ForwardedParameterType<P>>(args)...);
}
// The manager that is used when a target function is in remote storage and it
// has a trivial destructor
inline void RemoteManagerTrivial(FunctionToCall operation,
TypeErasedState* const from,
TypeErasedState* const to) noexcept {
switch (operation) {
case FunctionToCall::relocate_from_to:
// NOTE: Requires that the left-hand operand is already empty.
to->remote = from->remote;
return;
case FunctionToCall::dispose:
#if defined(__cpp_sized_deallocation)
::operator delete(from->remote.target, from->remote.size);
#else // __cpp_sized_deallocation
::operator delete(from->remote.target);
#endif // __cpp_sized_deallocation
return;
}
ABSL_UNREACHABLE();
}
// The manager that is used when a target function is in remote storage and the
// destructor of the type is not trivial
template <class T>
void RemoteManagerNontrivial(FunctionToCall operation,
TypeErasedState* const from,
TypeErasedState* const to) noexcept {
static_assert(!IsStoredLocally<T>(),
"Remote storage must only be used for types that do not "
"qualify for local storage.");
switch (operation) {
case FunctionToCall::relocate_from_to:
// NOTE: Requires that the left-hand operand is already empty.
to->remote.target = from->remote.target;
return;
case FunctionToCall::dispose:
::delete static_cast<T*>(from->remote.target); // Must not throw.
return;
}
ABSL_UNREACHABLE();
}
// The invoker that is used when a target function is in remote storage
template <bool SigIsNoexcept, class ReturnType, class QualTRef, class... P>
ReturnType RemoteInvoker(
TypeErasedState* const state,
ForwardedParameterType<P>... args) noexcept(SigIsNoexcept) {
using RawT = RemoveCVRef<QualTRef>;
static_assert(!IsStoredLocally<RawT>(),
"Target object must be in remote storage in order to be "
"invoked from it.");
auto& f = *static_cast<RawT*>(state->remote.target);
return (InvokeR<ReturnType>)(static_cast<QualTRef>(f),
static_cast<ForwardedParameterType<P>>(args)...);
}
////////////////////////////////////////////////////////////////////////////////
//
// A metafunction that checks if a type T is an instantiation of
// absl::in_place_type_t (needed for constructor constraints of AnyInvocable).
template <class T>
struct IsInPlaceType : std::false_type {};
template <class T>
struct IsInPlaceType<absl::in_place_type_t<T>> : std::true_type {};
//
////////////////////////////////////////////////////////////////////////////////
// A constructor name-tag used with CoreImpl (below) to request the
// conversion-constructor. QualDecayedTRef is the decayed-type of the object to
// wrap, along with the cv and reference qualifiers that must be applied when
// performing an invocation of the wrapped object.
template <class QualDecayedTRef>
struct TypedConversionConstruct {};
// A helper base class for all core operations of AnyInvocable. Most notably,
// this class creates the function call operator and constraint-checkers so that
// the top-level class does not have to be a series of partial specializations.
//
// Note: This definition exists (as opposed to being a declaration) so that if
// the user of the top-level template accidentally passes a template argument
// that is not a function type, they will get a static_assert in AnyInvocable's
// class body rather than an error stating that Impl is not defined.
template <class Sig>
class Impl {}; // Note: This is partially-specialized later.
// A std::unique_ptr deleter that deletes memory allocated via ::operator new.
#if defined(__cpp_sized_deallocation)
class TrivialDeleter {
public:
explicit TrivialDeleter(std::size_t size) : size_(size) {}
void operator()(void* target) const {
::operator delete(target, size_);
}
private:
std::size_t size_;
};
#else // __cpp_sized_deallocation
class TrivialDeleter {
public:
explicit TrivialDeleter(std::size_t) {}
void operator()(void* target) const { ::operator delete(target); }
};
#endif // __cpp_sized_deallocation
template <bool SigIsNoexcept, class ReturnType, class... P>
class CoreImpl;
constexpr bool IsCompatibleConversion(void*, void*) { return false; }
template <bool NoExceptSrc, bool NoExceptDest, class... T>
constexpr bool IsCompatibleConversion(CoreImpl<NoExceptSrc, T...>*,
CoreImpl<NoExceptDest, T...>*) {
return !NoExceptDest || NoExceptSrc;
}
// A helper base class for all core operations of AnyInvocable that do not
// depend on the cv/ref qualifiers of the function type.
template <bool SigIsNoexcept, class ReturnType, class... P>
class CoreImpl {
public:
using result_type = ReturnType;
CoreImpl() noexcept : manager_(EmptyManager), invoker_(nullptr) {}
// Note: QualDecayedTRef here includes the cv-ref qualifiers associated with
// the invocation of the Invocable. The unqualified type is the target object
// type to be stored.
template <class QualDecayedTRef, class F>
explicit CoreImpl(TypedConversionConstruct<QualDecayedTRef>, F&& f) {
using DecayedT = RemoveCVRef<QualDecayedTRef>;
if constexpr (std::is_pointer<DecayedT>::value ||
std::is_member_pointer<DecayedT>::value) {
// This condition handles types that decay into pointers. This includes
// function references, which cannot be null. GCC warns against comparing
// their decayed form with nullptr (https://godbolt.org/z/9r9TMTcPK).
// We could work around this warning with constexpr programming, using
// std::is_function_v<std::remove_reference_t<F>>, but we choose to ignore
// it instead of writing more code.
#if !defined(__clang__) && defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpragmas"
#pragma GCC diagnostic ignored "-Waddress"
#pragma GCC diagnostic ignored "-Wnonnull-compare"
#endif
if (static_cast<DecayedT>(f) == nullptr) {
#if !defined(__clang__) && defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
manager_ = EmptyManager;
invoker_ = nullptr;
} else {
InitializeStorage<QualDecayedTRef>(std::forward<F>(f));
}
} else if constexpr (IsCompatibleAnyInvocable<DecayedT>::value) {
// In this case we can "steal the guts" of the other AnyInvocable.
f.manager_(FunctionToCall::relocate_from_to, &f.state_, &state_);
manager_ = f.manager_;
invoker_ = f.invoker_;
f.manager_ = EmptyManager;
f.invoker_ = nullptr;
} else if constexpr (IsAnyInvocable<DecayedT>::value) {
if (f.HasValue()) {
InitializeStorage<QualDecayedTRef>(std::forward<F>(f));
} else {
manager_ = EmptyManager;
invoker_ = nullptr;
}
} else {
InitializeStorage<QualDecayedTRef>(std::forward<F>(f));
}
}
// Note: QualTRef here includes the cv-ref qualifiers associated with the
// invocation of the Invocable. The unqualified type is the target object
// type to be stored.
template <class QualTRef, class... Args>
explicit CoreImpl(absl::in_place_type_t<QualTRef>, Args&&... args) {
InitializeStorage<QualTRef>(std::forward<Args>(args)...);
}
CoreImpl(CoreImpl&& other) noexcept {
other.manager_(FunctionToCall::relocate_from_to, &other.state_, &state_);
manager_ = other.manager_;
invoker_ = other.invoker_;
other.manager_ = EmptyManager;
other.invoker_ = nullptr;
}
CoreImpl& operator=(CoreImpl&& other) noexcept {
// Put the left-hand operand in an empty state.
//
// Note: A full reset that leaves us with an object that has its invariants
// intact is necessary in order to handle self-move. This is required by
// types that are used with certain operations of the standard library, such
// as the default definition of std::swap when both operands target the same
// object.
Clear();
// Perform the actual move/destroy operation on the target function.
other.manager_(FunctionToCall::relocate_from_to, &other.state_, &state_);
manager_ = other.manager_;
invoker_ = other.invoker_;
other.manager_ = EmptyManager;
other.invoker_ = nullptr;
return *this;
}
~CoreImpl() { manager_(FunctionToCall::dispose, &state_, &state_); }
// Check whether or not the AnyInvocable is in the empty state.
bool HasValue() const { return invoker_ != nullptr; }
// Effects: Puts the object into its empty state.
void Clear() {
manager_(FunctionToCall::dispose, &state_, &state_);
manager_ = EmptyManager;
invoker_ = nullptr;
}
// Use local (inline) storage for applicable target object types.
template <class QualTRef, class... Args>
void InitializeStorage(Args&&... args) {
using RawT = RemoveCVRef<QualTRef>;
if constexpr (IsStoredLocally<RawT>()) {
::new (static_cast<void*>(&state_.storage))
RawT(std::forward<Args>(args)...);
invoker_ = LocalInvoker<SigIsNoexcept, ReturnType, QualTRef, P...>;
// We can simplify our manager if we know the type is trivially copyable.
if constexpr (std::is_trivially_copyable_v<RawT>) {
manager_ = LocalManagerTrivial;
} else {
manager_ = LocalManagerNontrivial<RawT>;
}
} else {
InitializeRemoteManager<RawT>(std::forward<Args>(args)...);
// This is set after everything else in case an exception is thrown in an
// earlier step of the initialization.
invoker_ = RemoteInvoker<SigIsNoexcept, ReturnType, QualTRef, P...>;
}
}
template <class T, class... Args>
void InitializeRemoteManager(Args&&... args) {
if constexpr (std::is_trivially_destructible_v<T> &&
alignof(T) <= ABSL_INTERNAL_DEFAULT_NEW_ALIGNMENT) {
// unique_ptr is used for exception-safety in case construction throws.
std::unique_ptr<void, TrivialDeleter> uninitialized_target(
::operator new(sizeof(T)), TrivialDeleter(sizeof(T)));
::new (uninitialized_target.get()) T(std::forward<Args>(args)...);
state_.remote.target = uninitialized_target.release();
state_.remote.size = sizeof(T);
manager_ = RemoteManagerTrivial;
} else {
state_.remote.target = ::new T(std::forward<Args>(args)...);
manager_ = RemoteManagerNontrivial<T>;
}
}
//////////////////////////////////////////////////////////////////////////////
//
// Type trait to determine if the template argument is an AnyInvocable whose
// function type is compatible enough with ours such that we can
// "move the guts" out of it when moving, rather than having to place a new
// object into remote storage.
template <typename Other>
struct IsCompatibleAnyInvocable {
static constexpr bool value = false;
};
template <typename Sig>
struct IsCompatibleAnyInvocable<AnyInvocable<Sig>> {
static constexpr bool value =
(IsCompatibleConversion)(static_cast<
typename AnyInvocable<Sig>::CoreImpl*>(
nullptr),
static_cast<CoreImpl*>(nullptr));
};
//
//////////////////////////////////////////////////////////////////////////////
TypeErasedState state_;
ManagerType* manager_;
InvokerType<SigIsNoexcept, ReturnType, P...>* invoker_;
};
// A constructor name-tag used with Impl to request the
// conversion-constructor
struct ConversionConstruct {};
////////////////////////////////////////////////////////////////////////////////
//
// A metafunction that is normally an identity metafunction except that when
// given a std::reference_wrapper<T>, it yields T&. This is necessary because
// currently std::reference_wrapper's operator() is not conditionally noexcept,
// so when checking if such an Invocable is nothrow-invocable, we must pull out
// the underlying type.
template <class T>
struct UnwrapStdReferenceWrapperImpl {
using type = T;
};
template <class T>
struct UnwrapStdReferenceWrapperImpl<std::reference_wrapper<T>> {
using type = T&;
};
template <class T>
using UnwrapStdReferenceWrapper =
typename UnwrapStdReferenceWrapperImpl<T>::type;
//
////////////////////////////////////////////////////////////////////////////////
// An alias that always yields std::true_type (used with constraints) where
// substitution failures happen when forming the template arguments.
template <class... T>
using TrueAlias =
std::integral_constant<bool, sizeof(absl::void_t<T...>*) != 0>;
/*SFINAE constraints for the conversion-constructor.*/
template <class Sig, class F,
class = absl::enable_if_t<
!std::is_same<RemoveCVRef<F>, AnyInvocable<Sig>>::value>>
using CanConvert = TrueAlias<
absl::enable_if_t<!IsInPlaceType<RemoveCVRef<F>>::value>,
absl::enable_if_t<Impl<Sig>::template CallIsValid<F>::value>,
absl::enable_if_t<
Impl<Sig>::template CallIsNoexceptIfSigIsNoexcept<F>::value>,
absl::enable_if_t<std::is_constructible<absl::decay_t<F>, F>::value>>;
/*SFINAE constraints for the std::in_place constructors.*/
template <class Sig, class F, class... Args>
using CanEmplace = TrueAlias<
absl::enable_if_t<Impl<Sig>::template CallIsValid<F>::value>,
absl::enable_if_t<
Impl<Sig>::template CallIsNoexceptIfSigIsNoexcept<F>::value>,
absl::enable_if_t<std::is_constructible<absl::decay_t<F>, Args...>::value>>;
/*SFINAE constraints for the conversion-assign operator.*/
template <class Sig, class F,
class = absl::enable_if_t<
!std::is_same<RemoveCVRef<F>, AnyInvocable<Sig>>::value>>
using CanAssign = TrueAlias<
absl::enable_if_t<Impl<Sig>::template CallIsValid<F>::value>,
absl::enable_if_t<
Impl<Sig>::template CallIsNoexceptIfSigIsNoexcept<F>::value>,
absl::enable_if_t<std::is_constructible<absl::decay_t<F>, F>::value>>;
/*SFINAE constraints for the reference-wrapper conversion-assign operator.*/
template <class Sig, class F>
using CanAssignReferenceWrapper = TrueAlias<
absl::enable_if_t<
Impl<Sig>::template CallIsValid<std::reference_wrapper<F>>::value>,
absl::enable_if_t<Impl<Sig>::template CallIsNoexceptIfSigIsNoexcept<
std::reference_wrapper<F>>::value>>;
// The constraint for checking whether or not a call meets the noexcept
// callability requirements. We use a preprocessor macro because specifying it
// this way as opposed to a disjunction/branch can improve the user-side error
// messages and avoids an instantiation of std::is_nothrow_invocable_r in the
// cases where the user did not specify a noexcept function type.
//
// The disjunction below is because we can't rely on std::is_nothrow_invocable_r
// to give the right result when ReturnType is non-moveable in toolchains that
// don't treat non-moveable result types correctly. For example this was the
// case in libc++ before commit c3a24882 (2022-05).
#define ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT_true(inv_quals) \
absl::enable_if_t<absl::disjunction< \
std::is_nothrow_invocable_r< \
ReturnType, UnwrapStdReferenceWrapper<absl::decay_t<F>> inv_quals, \
P...>, \
std::conjunction< \
std::is_nothrow_invocable< \
UnwrapStdReferenceWrapper<absl::decay_t<F>> inv_quals, P...>, \
std::is_same< \
ReturnType, \
std::invoke_result_t< \
UnwrapStdReferenceWrapper<absl::decay_t<F>> inv_quals, \
P...>>>>::value>
#define ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT_false(inv_quals)
//
////////////////////////////////////////////////////////////////////////////////
// A macro to generate partial specializations of Impl with the different
// combinations of supported cv/reference qualifiers and noexcept specifier.
//
// Here, `cv` are the cv-qualifiers if any, `ref` is the ref-qualifier if any,
// inv_quals is the reference type to be used when invoking the target, and
// noex is "true" if the function type is noexcept, or false if it is not.
//
// The CallIsValid condition is more complicated than simply using
// std::is_invocable_r because we can't rely on it to give the right result
// when ReturnType is non-moveable in toolchains that don't treat non-moveable
// result types correctly. For example this was the case in libc++ before commit
// c3a24882 (2022-05).
#define ABSL_INTERNAL_ANY_INVOCABLE_IMPL_(cv, ref, inv_quals, noex) \
template <class ReturnType, class... P> \
class Impl<ReturnType(P...) cv ref noexcept(noex)> \
: public CoreImpl<noex, ReturnType, P...> { \
public: \
/*The base class, which contains the datamembers and core operations*/ \
using Core = CoreImpl<noex, ReturnType, P...>; \
\
/*SFINAE constraint to check if F is invocable with the proper signature*/ \
template <class F> \
using CallIsValid = TrueAlias<absl::enable_if_t<absl::disjunction< \
std::is_invocable_r<ReturnType, absl::decay_t<F> inv_quals, P...>, \
std::is_same< \
ReturnType, \
std::invoke_result_t<absl::decay_t<F> inv_quals, P...>>>::value>>; \
\
/*SFINAE constraint to check if F is nothrow-invocable when necessary*/ \
template <class F> \
using CallIsNoexceptIfSigIsNoexcept = \
TrueAlias<ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT_##noex( \
inv_quals)>; \
\
/*Put the AnyInvocable into an empty state.*/ \
Impl() = default; \
\
/*The implementation of a conversion-constructor from "f*/ \
/*This forwards to Core, attaching inv_quals so that the base class*/ \
/*knows how to properly type-erase the invocation.*/ \
template <class F> \
explicit Impl(ConversionConstruct, F&& f) \
: Core(TypedConversionConstruct< \
typename std::decay<F>::type inv_quals>(), \
std::forward<F>(f)) {} \
\
/*Forward along the in-place construction parameters.*/ \
template <class T, class... Args> \
explicit Impl(absl::in_place_type_t<T>, Args&&... args) \
: Core(absl::in_place_type<absl::decay_t<T> inv_quals>, \
std::forward<Args>(args)...) {} \
\
/*Raises a fatal error when the AnyInvocable is invoked after a move*/ \
static ReturnType InvokedAfterMove( \
TypeErasedState*, ForwardedParameterType<P>...) noexcept(noex) { \
ABSL_HARDENING_ASSERT(false && "AnyInvocable use-after-move"); \
std::terminate(); \
} \
\
InvokerType<noex, ReturnType, P...>* ExtractInvoker() cv { \
using QualifiedTestType = int cv ref; \
auto* invoker = this->invoker_; \
if (!std::is_const<QualifiedTestType>::value && \
std::is_rvalue_reference<QualifiedTestType>::value) { \
ABSL_ASSERT([this]() { \
/* We checked that this isn't const above, so const_cast is safe */ \
const_cast<Impl*>(this)->invoker_ = InvokedAfterMove; \
return this->HasValue(); \
}()); \
} \
return invoker; \
} \
\
/*The actual invocation operation with the proper signature*/ \
ReturnType operator()(P... args) cv ref noexcept(noex) { \
assert(this->invoker_ != nullptr); \
return this->ExtractInvoker()( \
const_cast<TypeErasedState*>(&this->state_), \
static_cast<ForwardedParameterType<P>>(args)...); \
} \
}
// A convenience macro that defines specializations for the noexcept(true) and
// noexcept(false) forms, given the other properties.
#define ABSL_INTERNAL_ANY_INVOCABLE_IMPL(cv, ref, inv_quals) \
ABSL_INTERNAL_ANY_INVOCABLE_IMPL_(cv, ref, inv_quals, false); \
ABSL_INTERNAL_ANY_INVOCABLE_IMPL_(cv, ref, inv_quals, true)
// Non-ref-qualified partial specializations
ABSL_INTERNAL_ANY_INVOCABLE_IMPL(, , &);
ABSL_INTERNAL_ANY_INVOCABLE_IMPL(const, , const&);
// Lvalue-ref-qualified partial specializations
ABSL_INTERNAL_ANY_INVOCABLE_IMPL(, &, &);
ABSL_INTERNAL_ANY_INVOCABLE_IMPL(const, &, const&);
// Rvalue-ref-qualified partial specializations
ABSL_INTERNAL_ANY_INVOCABLE_IMPL(, &&, &&);
ABSL_INTERNAL_ANY_INVOCABLE_IMPL(const, &&, const&&);
// Undef the detail-only macros.
#undef ABSL_INTERNAL_ANY_INVOCABLE_IMPL
#undef ABSL_INTERNAL_ANY_INVOCABLE_IMPL_
#undef ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT_false
#undef ABSL_INTERNAL_ANY_INVOCABLE_NOEXCEPT_CONSTRAINT_true
} // namespace internal_any_invocable
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_FUNCTIONAL_INTERNAL_ANY_INVOCABLE_H_
*‘f
~soong/.intermediates/external/abseil-cpp/absl_functional_any_invocable_hdrs/gen/my_include_dir/absl/functional/any_invocable.hŽe// Copyright 2022 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: any_invocable.h
// -----------------------------------------------------------------------------
//
// This header file defines an `absl::AnyInvocable` type that assumes ownership
// and wraps an object of an invocable type. (Invocable types adhere to the
// concept specified in https://en.cppreference.com/w/cpp/concepts/invocable.)
//
// In general, prefer `absl::AnyInvocable` when you need a type-erased
// function parameter that needs to take ownership of the type.
//
// NOTE: `absl::AnyInvocable` is similar to the C++23 `std::move_only_function`
// abstraction, but has a slightly different API and is not designed to be a
// drop-in replacement or backfill of that type.
//
// Credits to Matt Calabrese (https://github.com/mattcalabrese) for the original
// implementation.
#ifndef ABSL_FUNCTIONAL_ANY_INVOCABLE_H_
#define ABSL_FUNCTIONAL_ANY_INVOCABLE_H_
#include <cstddef>
#include <functional>
#include <initializer_list>
#include <type_traits>
#include <utility>
#include "absl/base/config.h"
#include "absl/functional/internal/any_invocable.h"
#include "absl/meta/type_traits.h"
#include "absl/utility/utility.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
// absl::AnyInvocable
//
// `absl::AnyInvocable` is a functional wrapper type, like `std::function`, that
// assumes ownership of an invocable object. Unlike `std::function`, an
// `absl::AnyInvocable` is more type-safe and provides the following additional
// benefits:
//
// * Properly adheres to const correctness of the underlying type
// * Is move-only so avoids concurrency problems with copied invocables and
// unnecessary copies in general.
// * Supports reference qualifiers allowing it to perform unique actions (noted
// below).
//
// `absl::AnyInvocable` is a template, and an `absl::AnyInvocable` instantiation
// may wrap any invocable object with a compatible function signature, e.g.
// having arguments and return types convertible to types matching the
// `absl::AnyInvocable` signature, and also matching any stated reference
// qualifiers, as long as that type is moveable. It therefore provides broad
// type erasure for functional objects.
//
// An `absl::AnyInvocable` is typically used as a type-erased function parameter
// for accepting various functional objects:
//
// // Define a function taking an AnyInvocable parameter.
// void my_func(absl::AnyInvocable<int()> f) {
// ...
// };
//
// // That function can accept any invocable type:
//
// // Accept a function reference. We don't need to move a reference.
// int func1() { return 0; };
// my_func(func1);
//
// // Accept a lambda. We use std::move here because otherwise my_func would
// // copy the lambda.
// auto lambda = []() { return 0; };
// my_func(std::move(lambda));
//
// // Accept a function pointer. We don't need to move a function pointer.
// func2 = &func1;
// my_func(func2);
//
// // Accept an std::function by moving it. Note that the lambda is copyable
// // (satisfying std::function requirements) and moveable (satisfying
// // absl::AnyInvocable requirements).
// std::function<int()> func6 = []() { return 0; };
// my_func(std::move(func6));
//
// `AnyInvocable` also properly respects `const` qualifiers, reference
// qualifiers, and the `noexcept` specification as part of the user-specified
// function type (e.g. `AnyInvocable<void() const && noexcept>`). These
// qualifiers will be applied to the `AnyInvocable` object's `operator()`, and
// the underlying invocable must be compatible with those qualifiers.
//
// Comparison of const and non-const function types:
//
// // Store a closure inside of `func` with the function type `int()`.
// // Note that we have made `func` itself `const`.
// const AnyInvocable<int()> func = [](){ return 0; };
//
// func(); // Compile-error: the passed type `int()` isn't `const`.
//
// // Store a closure inside of `const_func` with the function type
// // `int() const`.
// // Note that we have also made `const_func` itself `const`.
// const AnyInvocable<int() const> const_func = [](){ return 0; };
//
// const_func(); // Fine: `int() const` is `const`.
//
// In the above example, the call `func()` would have compiled if
// `std::function` were used even though the types are not const compatible.
// This is a bug, and using `absl::AnyInvocable` properly detects that bug.
//
// In addition to affecting the signature of `operator()`, the `const` and
// reference qualifiers of the function type also appropriately constrain which
// kinds of invocable objects you are allowed to place into the `AnyInvocable`
// instance. If you specify a function type that is const-qualified, then
// anything that you attempt to put into the `AnyInvocable` must be callable on
// a `const` instance of that type.
//
// Constraint example:
//
// // Fine because the lambda is callable when `const`.
// AnyInvocable<int() const> func = [=](){ return 0; };
//
// // This is a compile-error because the lambda isn't callable when `const`.
// AnyInvocable<int() const> error = [=]() mutable { return 0; };
//
// An `&&` qualifier can be used to express that an `absl::AnyInvocable`
// instance should be invoked at most once:
//
// // Invokes `continuation` with the logical result of an operation when
// // that operation completes (common in asynchronous code).
// void CallOnCompletion(AnyInvocable<void(int)&&> continuation) {
// int result_of_foo = foo();
//
// // `std::move` is required because the `operator()` of `continuation` is
// // rvalue-reference qualified.
// std::move(continuation)(result_of_foo);
// }
//
// Attempting to call `absl::AnyInvocable` multiple times in such a case
// results in undefined behavior.
//
// Invoking an empty `absl::AnyInvocable` results in undefined behavior:
//
// // Create an empty instance using the default constructor.
// AnyInvocable<void()> empty;
// empty(); // WARNING: Undefined behavior!
template <class Sig>
class AnyInvocable : private internal_any_invocable::Impl<Sig> {
private:
static_assert(
std::is_function<Sig>::value,
"The template argument of AnyInvocable must be a function type.");
using Impl = internal_any_invocable::Impl<Sig>;
public:
// The return type of Sig
using result_type = typename Impl::result_type;
// Constructors
// Constructs the `AnyInvocable` in an empty state.
// Invoking it results in undefined behavior.
AnyInvocable() noexcept = default;
AnyInvocable(std::nullptr_t) noexcept {} // NOLINT
// Constructs the `AnyInvocable` from an existing `AnyInvocable` by a move.
// Note that `f` is not guaranteed to be empty after move-construction,
// although it may be.
AnyInvocable(AnyInvocable&& /*f*/) noexcept = default;
// Constructs an `AnyInvocable` from an invocable object.
//
// Upon construction, `*this` is only empty if `f` is a function pointer or
// member pointer type and is null, or if `f` is an `AnyInvocable` that is
// empty.
template <class F, typename = absl::enable_if_t<
internal_any_invocable::CanConvert<Sig, F>::value>>
AnyInvocable(F&& f) // NOLINT
: Impl(internal_any_invocable::ConversionConstruct(),
std::forward<F>(f)) {}
// Constructs an `AnyInvocable` that holds an invocable object of type `T`,
// which is constructed in-place from the given arguments.
//
// Example:
//
// AnyInvocable<int(int)> func(
// absl::in_place_type<PossiblyImmovableType>, arg1, arg2);
//
template <class T, class... Args,
typename = absl::enable_if_t<
internal_any_invocable::CanEmplace<Sig, T, Args...>::value>>
explicit AnyInvocable(absl::in_place_type_t<T>, Args&&... args)
: Impl(absl::in_place_type<absl::decay_t<T>>,
std::forward<Args>(args)...) {
static_assert(std::is_same<T, absl::decay_t<T>>::value,
"The explicit template argument of in_place_type is required "
"to be an unqualified object type.");
}
// Overload of the above constructor to support list-initialization.
template <class T, class U, class... Args,
typename = absl::enable_if_t<internal_any_invocable::CanEmplace<
Sig, T, std::initializer_list<U>&, Args...>::value>>
explicit AnyInvocable(absl::in_place_type_t<T>,
std::initializer_list<U> ilist, Args&&... args)
: Impl(absl::in_place_type<absl::decay_t<T>>, ilist,
std::forward<Args>(args)...) {
static_assert(std::is_same<T, absl::decay_t<T>>::value,
"The explicit template argument of in_place_type is required "
"to be an unqualified object type.");
}
// Assignment Operators
// Assigns an `AnyInvocable` through move-assignment.
// Note that `f` is not guaranteed to be empty after move-assignment
// although it may be.
AnyInvocable& operator=(AnyInvocable&& /*f*/) noexcept = default;
// Assigns an `AnyInvocable` from a nullptr, clearing the `AnyInvocable`. If
// not empty, destroys the target, putting `*this` into an empty state.
AnyInvocable& operator=(std::nullptr_t) noexcept {
this->Clear();
return *this;
}
// Assigns an `AnyInvocable` from an existing `AnyInvocable` instance.
//
// Upon assignment, `*this` is only empty if `f` is a function pointer or
// member pointer type and is null, or if `f` is an `AnyInvocable` that is
// empty.
template <class F, typename = absl::enable_if_t<
internal_any_invocable::CanAssign<Sig, F>::value>>
AnyInvocable& operator=(F&& f) {
*this = AnyInvocable(std::forward<F>(f));
return *this;
}
// Assigns an `AnyInvocable` from a reference to an invocable object.
// Upon assignment, stores a reference to the invocable object in the
// `AnyInvocable` instance.
template <
class F,
typename = absl::enable_if_t<
internal_any_invocable::CanAssignReferenceWrapper<Sig, F>::value>>
AnyInvocable& operator=(std::reference_wrapper<F> f) noexcept {
*this = AnyInvocable(f);
return *this;
}
// Destructor
// If not empty, destroys the target.
~AnyInvocable() = default;
// absl::AnyInvocable::swap()
//
// Exchanges the targets of `*this` and `other`.
void swap(AnyInvocable& other) noexcept { std::swap(*this, other); }
// absl::AnyInvocable::operator bool()
//
// Returns `true` if `*this` is not empty.
//
// WARNING: An `AnyInvocable` that wraps an empty `std::function` is not
// itself empty. This behavior is consistent with the standard equivalent
// `std::move_only_function`. In the following example, `a()` will actually
// invoke `f()`, leading to an `std::bad_function_call` exception:
// std::function<void()> f; // empty
// absl::AnyInvocable<void()> a = f; // not empty
//
// Invoking an empty `AnyInvocable` results in undefined behavior.
explicit operator bool() const noexcept { return this->HasValue(); }
// Invokes the target object of `*this`. `*this` must not be empty.
//
// Note: The signature of this function call operator is the same as the
// template parameter `Sig`.
using Impl::operator();
// Equality operators
// Returns `true` if `*this` is empty.
friend bool operator==(const AnyInvocable& f, std::nullptr_t) noexcept {
return !f.HasValue();
}
// Returns `true` if `*this` is empty.
friend bool operator==(std::nullptr_t, const AnyInvocable& f) noexcept {
return !f.HasValue();
}
// Returns `false` if `*this` is empty.
friend bool operator!=(const AnyInvocable& f, std::nullptr_t) noexcept {
return f.HasValue();
}
// Returns `false` if `*this` is empty.
friend bool operator!=(std::nullptr_t, const AnyInvocable& f) noexcept {
return f.HasValue();
}
// swap()
//
// Exchanges the targets of `f1` and `f2`.
friend void swap(AnyInvocable& f1, AnyInvocable& f2) noexcept { f1.swap(f2); }
private:
// Friending other instantiations is necessary for conversions.
template <bool /*SigIsNoexcept*/, class /*ReturnType*/, class... /*P*/>
friend class internal_any_invocable::CoreImpl;
};
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_FUNCTIONAL_ANY_INVOCABLE_H_
…soong/.intermediates/external/abseil-cpp/absl_functional_function_ref_hdrs/gen/my_include_dir/absl/functional/internal/function_ref.h–// Copyright 2019 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_FUNCTIONAL_INTERNAL_FUNCTION_REF_H_
#define ABSL_FUNCTIONAL_INTERNAL_FUNCTION_REF_H_
#include <cassert>
#include <functional>
#include <type_traits>
#include "absl/functional/any_invocable.h"
#include "absl/meta/type_traits.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace functional_internal {
// Like a void* that can handle function pointers as well. The standard does not
// allow function pointers to round-trip through void*, but void(*)() is fine.
//
// Note: It's important that this class remains trivial and is the same size as
// a pointer, since this allows the compiler to perform tail-call optimizations
// when the underlying function is a callable object with a matching signature.
union VoidPtr {
const void* obj;
void (*fun)();
};
// Chooses the best type for passing T as an argument.
// Attempt to be close to SystemV AMD64 ABI. Objects with trivial copy ctor are
// passed by value.
template <typename T,
bool IsLValueReference = std::is_lvalue_reference<T>::value>
struct PassByValue : std::false_type {};
template <typename T>
struct PassByValue<T, /*IsLValueReference=*/false>
: std::integral_constant<bool,
absl::is_trivially_copy_constructible<T>::value &&
absl::is_trivially_copy_assignable<
typename std::remove_cv<T>::type>::value &&
std::is_trivially_destructible<T>::value &&
sizeof(T) <= 2 * sizeof(void*)> {};
template <typename T>
struct ForwardT : std::conditional<PassByValue<T>::value, T, T&&> {};
// An Invoker takes a pointer to the type-erased invokable object, followed by
// the arguments that the invokable object expects.
//
// Note: The order of arguments here is an optimization, since member functions
// have an implicit "this" pointer as their first argument, putting VoidPtr
// first allows the compiler to perform tail-call optimization in many cases.
template <typename R, typename... Args>
using Invoker = R (*)(VoidPtr, typename ForwardT<Args>::type...);
//
// InvokeObject and InvokeFunction provide static "Invoke" functions that can be
// used as Invokers for objects or functions respectively.
//
// static_cast<R> handles the case the return type is void.
template <typename Obj, typename R, typename... Args>
R InvokeObject(VoidPtr ptr, typename ForwardT<Args>::type... args) {
auto o = static_cast<const Obj*>(ptr.obj);
return static_cast<R>(std::invoke(*o, std::forward<Args>(args)...));
}
template <typename Fun, typename R, typename... Args>
R InvokeFunction(VoidPtr ptr, typename ForwardT<Args>::type... args) {
auto f = reinterpret_cast<Fun>(ptr.fun);
return static_cast<R>(std::invoke(f, std::forward<Args>(args)...));
}
template <typename Sig>
void AssertNonNull(const std::function<Sig>& f) {
assert(f != nullptr);
(void)f;
}
template <typename Sig>
void AssertNonNull(const AnyInvocable<Sig>& f) {
assert(f != nullptr);
(void)f;
}
template <typename F>
void AssertNonNull(const F&) {}
template <typename F, typename C>
void AssertNonNull(F C::*f) {
assert(f != nullptr);
(void)f;
}
template <bool C>
using EnableIf = typename ::std::enable_if<C, int>::type;
} // namespace functional_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_FUNCTIONAL_INTERNAL_FUNCTION_REF_H_
*Ù-
|soong/.intermediates/external/abseil-cpp/absl_functional_function_ref_hdrs/gen/my_include_dir/absl/functional/function_ref.hØ,// Copyright 2019 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: function_ref.h
// -----------------------------------------------------------------------------
//
// This header file defines the `absl::FunctionRef` type for holding a
// non-owning reference to an object of any invocable type. This function
// reference is typically most useful as a type-erased argument type for
// accepting function types that neither take ownership nor copy the type; using
// the reference type in this case avoids a copy and an allocation. Best
// practices of other non-owning reference-like objects (such as
// `absl::string_view`) apply here.
//
// An `absl::FunctionRef` is similar in usage to a `std::function` but has the
// following differences:
//
// * It doesn't own the underlying object.
// * It doesn't have a null or empty state.
// * It never performs deep copies or allocations.
// * It's much faster and cheaper to construct.
// * It's trivially copyable and destructable.
//
// Generally, `absl::FunctionRef` should not be used as a return value, data
// member, or to initialize a `std::function`. Such usages will often lead to
// problematic lifetime issues. Once you convert something to an
// `absl::FunctionRef` you cannot make a deep copy later.
//
// This class is suitable for use wherever a "const std::function<>&"
// would be used without making a copy. ForEach functions and other versions of
// the visitor pattern are a good example of when this class should be used.
//
// This class is trivial to copy and should be passed by value.
#ifndef ABSL_FUNCTIONAL_FUNCTION_REF_H_
#define ABSL_FUNCTIONAL_FUNCTION_REF_H_
#include <cassert>
#include <functional>
#include <type_traits>
#include "absl/base/attributes.h"
#include "absl/functional/internal/function_ref.h"
#include "absl/meta/type_traits.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
// FunctionRef
//
// Dummy class declaration to allow the partial specialization based on function
// types below.
template <typename T>
class FunctionRef;
// FunctionRef
//
// An `absl::FunctionRef` is a lightweight wrapper to any invocable object with
// a compatible signature. Generally, an `absl::FunctionRef` should only be used
// as an argument type and should be preferred as an argument over a const
// reference to a `std::function`. `absl::FunctionRef` itself does not allocate,
// although the wrapped invocable may.
//
// Example:
//
// // The following function takes a function callback by const reference
// bool Visitor(const std::function<void(my_proto&,
// absl::string_view)>& callback);
//
// // Assuming that the function is not stored or otherwise copied, it can be
// // replaced by an `absl::FunctionRef`:
// bool Visitor(absl::FunctionRef<void(my_proto&, absl::string_view)>
// callback);
template <typename R, typename... Args>
class FunctionRef<R(Args...)> {
private:
// Used to disable constructors for objects that are not compatible with the
// signature of this FunctionRef.
template <typename F, typename FR = std::invoke_result_t<F, Args&&...>>
using EnableIfCompatible =
typename std::enable_if<std::is_void<R>::value ||
std::is_convertible<FR, R>::value>::type;
public:
// Constructs a FunctionRef from any invocable type.
template <typename F, typename = EnableIfCompatible<const F&>>
// NOLINTNEXTLINE(runtime/explicit)
FunctionRef(const F& f ABSL_ATTRIBUTE_LIFETIME_BOUND)
: invoker_(&absl::functional_internal::InvokeObject<F, R, Args...>) {
absl::functional_internal::AssertNonNull(f);
ptr_.obj = &f;
}
// Overload for function pointers. This eliminates a level of indirection that
// would happen if the above overload was used (it lets us store the pointer
// instead of a pointer to a pointer).
//
// This overload is also used for references to functions, since references to
// functions can decay to function pointers implicitly.
template <
typename F, typename = EnableIfCompatible<F*>,
absl::functional_internal::EnableIf<absl::is_function<F>::value> = 0>
FunctionRef(F* f) // NOLINT(runtime/explicit)
: invoker_(&absl::functional_internal::InvokeFunction<F*, R, Args...>) {
assert(f != nullptr);
ptr_.fun = reinterpret_cast<decltype(ptr_.fun)>(f);
}
FunctionRef& operator=(const FunctionRef& rhs) = default;
FunctionRef(const FunctionRef& rhs) = default;
// Call the underlying object.
R operator()(Args... args) const {
return invoker_(ptr_, std::forward<Args>(args)...);
}
private:
absl::functional_internal::VoidPtr ptr_;
absl::functional_internal::Invoker<R, Args...> invoker_;
};
// Allow const qualified function signatures. Since FunctionRef requires
// constness anyway we can just make this a no-op.
template <typename R, typename... Args>
class FunctionRef<R(Args...) const> : public FunctionRef<R(Args...)> {
public:
using FunctionRef<R(Args...)>::FunctionRef;
};
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_FUNCTIONAL_FUNCTION_REF_H_
*Ú
nsoong/.intermediates/external/abseil-cpp/absl_base_core_headers_hdrs/gen/my_include_dir/absl/base/const_init.hç// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// kConstInit
// -----------------------------------------------------------------------------
//
// A constructor tag used to mark an object as safe for use as a global
// variable, avoiding the usual lifetime issues that can affect globals.
#ifndef ABSL_BASE_CONST_INIT_H_
#define ABSL_BASE_CONST_INIT_H_
#include "absl/base/config.h"
// In general, objects with static storage duration (such as global variables)
// can trigger tricky object lifetime situations. Attempting to access them
// from the constructors or destructors of other global objects can result in
// undefined behavior, unless their constructors and destructors are designed
// with this issue in mind.
//
// The normal way to deal with this issue in C++11 is to use constant
// initialization and trivial destructors.
//
// Constant initialization is guaranteed to occur before any other code
// executes. Constructors that are declared 'constexpr' are eligible for
// constant initialization. You can annotate a variable declaration with the
// ABSL_CONST_INIT macro to express this intent. For compilers that support
// it, this annotation will cause a compilation error for declarations that
// aren't subject to constant initialization (perhaps because a runtime value
// was passed as a constructor argument).
//
// On program shutdown, lifetime issues can be avoided on global objects by
// ensuring that they contain trivial destructors. A class has a trivial
// destructor unless it has a user-defined destructor, a virtual method or base
// class, or a data member or base class with a non-trivial destructor of its
// own. Objects with static storage duration and a trivial destructor are not
// cleaned up on program shutdown, and are thus safe to access from other code
// running during shutdown.
//
// For a few core Abseil classes, we make a best effort to allow for safe global
// instances, even though these classes have non-trivial destructors. These
// objects can be created with the absl::kConstInit tag. For example:
// ABSL_CONST_INIT absl::Mutex global_mutex(absl::kConstInit);
//
// The line above declares a global variable of type absl::Mutex which can be
// accessed at any point during startup or shutdown. global_mutex's destructor
// will still run, but will not invalidate the object. Note that C++ specifies
// that accessing an object after its destructor has run results in undefined
// behavior, but this pattern works on the toolchains we support.
//
// The absl::kConstInit tag should only be used to define objects with static
// or thread_local storage duration.
namespace absl {
ABSL_NAMESPACE_BEGIN
enum ConstInitType {
kConstInit,
};
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_CONST_INIT_H_
*¢Y
asoong/.intermediates/external/abseil-cpp/absl_memory_hdrs/gen/my_include_dir/absl/memory/memory.h¼X// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: memory.h
// -----------------------------------------------------------------------------
//
// This header file contains utility functions for managing the creation and
// conversion of smart pointers. This file is an extension to the C++
// standard <memory> library header file.
#ifndef ABSL_MEMORY_MEMORY_H_
#define ABSL_MEMORY_MEMORY_H_
#include <cstddef>
#include <limits>
#include <memory>
#include <new>
#include <type_traits>
#include <utility>
#include "absl/base/macros.h"
#include "absl/meta/type_traits.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
// -----------------------------------------------------------------------------
// Function Template: WrapUnique()
// -----------------------------------------------------------------------------
//
// Adopts ownership from a raw pointer and transfers it to the returned
// `std::unique_ptr`, whose type is deduced. Because of this deduction, *do not*
// specify the template type `T` when calling `WrapUnique`.
//
// Example:
// X* NewX(int, int);
// auto x = WrapUnique(NewX(1, 2)); // 'x' is std::unique_ptr<X>.
//
// Do not call WrapUnique with an explicit type, as in
// `WrapUnique<X>(NewX(1, 2))`. The purpose of WrapUnique is to automatically
// deduce the pointer type. If you wish to make the type explicit, just use
// `std::unique_ptr` directly.
//
// auto x = std::unique_ptr<X>(NewX(1, 2));
// - or -
// std::unique_ptr<X> x(NewX(1, 2));
//
// While `absl::WrapUnique` is useful for capturing the output of a raw
// pointer factory, prefer 'absl::make_unique<T>(args...)' over
// 'absl::WrapUnique(new T(args...))'.
//
// auto x = WrapUnique(new X(1, 2)); // works, but nonideal.
// auto x = make_unique<X>(1, 2); // safer, standard, avoids raw 'new'.
//
// Note that `absl::WrapUnique(p)` is valid only if `delete p` is a valid
// expression. In particular, `absl::WrapUnique()` cannot wrap pointers to
// arrays, functions or void, and it must not be used to capture pointers
// obtained from array-new expressions (even though that would compile!).
template <typename T>
std::unique_ptr<T> WrapUnique(T* ptr) {
static_assert(!std::is_array<T>::value, "array types are unsupported");
static_assert(std::is_object<T>::value, "non-object types are unsupported");
return std::unique_ptr<T>(ptr);
}
// -----------------------------------------------------------------------------
// Function Template: make_unique<T>()
// -----------------------------------------------------------------------------
//
// Creates a `std::unique_ptr<>`, while avoiding issues creating temporaries
// during the construction process. `absl::make_unique<>` also avoids redundant
// type declarations, by avoiding the need to explicitly use the `new` operator.
//
// https://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique
//
// For more background on why `std::unique_ptr<T>(new T(a,b))` is problematic,
// see Herb Sutter's explanation on
// (Exception-Safe Function Calls)[https://herbsutter.com/gotw/_102/].
// (In general, reviewers should treat `new T(a,b)` with scrutiny.)
//
// Historical note: Abseil once provided a C++11 compatible implementation of
// the C++14's `std::make_unique`. Now that C++11 support has been sunsetted,
// `absl::make_unique` simply uses the STL-provided implementation. New code
// should use `std::make_unique`.
using std::make_unique;
// -----------------------------------------------------------------------------
// Function Template: RawPtr()
// -----------------------------------------------------------------------------
//
// Extracts the raw pointer from a pointer-like value `ptr`. `absl::RawPtr` is
// useful within templates that need to handle a complement of raw pointers,
// `std::nullptr_t`, and smart pointers.
template <typename T>
auto RawPtr(T&& ptr) -> decltype(std::addressof(*ptr)) {
// ptr is a forwarding reference to support Ts with non-const operators.
return (ptr != nullptr) ? std::addressof(*ptr) : nullptr;
}
inline std::nullptr_t RawPtr(std::nullptr_t) { return nullptr; }
// -----------------------------------------------------------------------------
// Function Template: ShareUniquePtr()
// -----------------------------------------------------------------------------
//
// Adopts a `std::unique_ptr` rvalue and returns a `std::shared_ptr` of deduced
// type. Ownership (if any) of the held value is transferred to the returned
// shared pointer.
//
// Example:
//
// auto up = absl::make_unique<int>(10);
// auto sp = absl::ShareUniquePtr(std::move(up)); // shared_ptr<int>
// CHECK_EQ(*sp, 10);
// CHECK(up == nullptr);
//
// Note that this conversion is correct even when T is an array type, and more
// generally it works for *any* deleter of the `unique_ptr` (single-object
// deleter, array deleter, or any custom deleter), since the deleter is adopted
// by the shared pointer as well. The deleter is copied (unless it is a
// reference).
//
// Implements the resolution of [LWG 2415](http://wg21.link/lwg2415), by which a
// null shared pointer does not attempt to call the deleter.
template <typename T, typename D>
std::shared_ptr<T> ShareUniquePtr(std::unique_ptr<T, D>&& ptr) {
return ptr ? std::shared_ptr<T>(std::move(ptr)) : std::shared_ptr<T>();
}
// -----------------------------------------------------------------------------
// Function Template: WeakenPtr()
// -----------------------------------------------------------------------------
//
// Creates a weak pointer associated with a given shared pointer. The returned
// value is a `std::weak_ptr` of deduced type.
//
// Example:
//
// auto sp = std::make_shared<int>(10);
// auto wp = absl::WeakenPtr(sp);
// CHECK_EQ(sp.get(), wp.lock().get());
// sp.reset();
// CHECK(wp.lock() == nullptr);
//
template <typename T>
std::weak_ptr<T> WeakenPtr(const std::shared_ptr<T>& ptr) {
return std::weak_ptr<T>(ptr);
}
// -----------------------------------------------------------------------------
// Class Template: pointer_traits
// -----------------------------------------------------------------------------
//
// Historical note: Abseil once provided an implementation of
// `std::pointer_traits` for platforms that had not yet provided it. Those
// platforms are no longer supported. New code should simply use
// `std::pointer_traits`.
using std::pointer_traits;
// -----------------------------------------------------------------------------
// Class Template: allocator_traits
// -----------------------------------------------------------------------------
//
// Historical note: Abseil once provided an implementation of
// `std::allocator_traits` for platforms that had not yet provided it. Those
// platforms are no longer supported. New code should simply use
// `std::allocator_traits`.
using std::allocator_traits;
namespace memory_internal {
// ExtractOr<E, O, D>::type evaluates to E<O> if possible. Otherwise, D.
template <template <typename> class Extract, typename Obj, typename Default,
typename>
struct ExtractOr {
using type = Default;
};
template <template <typename> class Extract, typename Obj, typename Default>
struct ExtractOr<Extract, Obj, Default, void_t<Extract<Obj>>> {
using type = Extract<Obj>;
};
template <template <typename> class Extract, typename Obj, typename Default>
using ExtractOrT = typename ExtractOr<Extract, Obj, Default, void>::type;
// This template alias transforms Alloc::is_nothrow into a metafunction with
// Alloc as a parameter so it can be used with ExtractOrT<>.
template <typename Alloc>
using GetIsNothrow = typename Alloc::is_nothrow;
} // namespace memory_internal
// ABSL_ALLOCATOR_NOTHROW is a build time configuration macro for user to
// specify whether the default allocation function can throw or never throws.
// If the allocation function never throws, user should define it to a non-zero
// value (e.g. via `-DABSL_ALLOCATOR_NOTHROW`).
// If the allocation function can throw, user should leave it undefined or
// define it to zero.
//
// allocator_is_nothrow<Alloc> is a traits class that derives from
// Alloc::is_nothrow if present, otherwise std::false_type. It's specialized
// for Alloc = std::allocator<T> for any type T according to the state of
// ABSL_ALLOCATOR_NOTHROW.
//
// default_allocator_is_nothrow is a class that derives from std::true_type
// when the default allocator (global operator new) never throws, and
// std::false_type when it can throw. It is a convenience shorthand for writing
// allocator_is_nothrow<std::allocator<T>> (T can be any type).
// NOTE: allocator_is_nothrow<std::allocator<T>> is guaranteed to derive from
// the same type for all T, because users should specialize neither
// allocator_is_nothrow nor std::allocator.
template <typename Alloc>
struct allocator_is_nothrow
: memory_internal::ExtractOrT<memory_internal::GetIsNothrow, Alloc,
std::false_type> {};
#if defined(ABSL_ALLOCATOR_NOTHROW) && ABSL_ALLOCATOR_NOTHROW
template <typename T>
struct allocator_is_nothrow<std::allocator<T>> : std::true_type {};
struct default_allocator_is_nothrow : std::true_type {};
#else
struct default_allocator_is_nothrow : std::false_type {};
#endif
namespace memory_internal {
template <typename Allocator, typename Iterator, typename... Args>
void ConstructRange(Allocator& alloc, Iterator first, Iterator last,
const Args&... args) {
for (Iterator cur = first; cur != last; ++cur) {
ABSL_INTERNAL_TRY {
std::allocator_traits<Allocator>::construct(alloc, std::addressof(*cur),
args...);
}
ABSL_INTERNAL_CATCH_ANY {
while (cur != first) {
--cur;
std::allocator_traits<Allocator>::destroy(alloc, std::addressof(*cur));
}
ABSL_INTERNAL_RETHROW;
}
}
}
template <typename Allocator, typename Iterator, typename InputIterator>
void CopyRange(Allocator& alloc, Iterator destination, InputIterator first,
InputIterator last) {
for (Iterator cur = destination; first != last;
static_cast<void>(++cur), static_cast<void>(++first)) {
ABSL_INTERNAL_TRY {
std::allocator_traits<Allocator>::construct(alloc, std::addressof(*cur),
*first);
}
ABSL_INTERNAL_CATCH_ANY {
while (cur != destination) {
--cur;
std::allocator_traits<Allocator>::destroy(alloc, std::addressof(*cur));
}
ABSL_INTERNAL_RETHROW;
}
}
}
} // namespace memory_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_MEMORY_MEMORY_H_
*¯¶
soong/.intermediates/external/abseil-cpp/absl_container_inlined_vector_internal_hdrs/gen/my_include_dir/absl/container/internal/inlined_vector.h˜µ// Copyright 2019 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_CONTAINER_INTERNAL_INLINED_VECTOR_H_
#define ABSL_CONTAINER_INTERNAL_INLINED_VECTOR_H_
#include <algorithm>
#include <cstddef>
#include <cstring>
#include <iterator>
#include <limits>
#include <memory>
#include <new>
#include <type_traits>
#include <utility>
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/internal/identity.h"
#include "absl/base/macros.h"
#include "absl/container/internal/compressed_tuple.h"
#include "absl/memory/memory.h"
#include "absl/meta/type_traits.h"
#include "absl/types/span.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace inlined_vector_internal {
// GCC does not deal very well with the below code
#if !defined(__clang__) && defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Warray-bounds"
#endif
template <typename A>
using AllocatorTraits = std::allocator_traits<A>;
template <typename A>
using ValueType = typename AllocatorTraits<A>::value_type;
template <typename A>
using SizeType = typename AllocatorTraits<A>::size_type;
template <typename A>
using Pointer = typename AllocatorTraits<A>::pointer;
template <typename A>
using ConstPointer = typename AllocatorTraits<A>::const_pointer;
template <typename A>
using SizeType = typename AllocatorTraits<A>::size_type;
template <typename A>
using DifferenceType = typename AllocatorTraits<A>::difference_type;
template <typename A>
using Reference = ValueType<A>&;
template <typename A>
using ConstReference = const ValueType<A>&;
template <typename A>
using Iterator = Pointer<A>;
template <typename A>
using ConstIterator = ConstPointer<A>;
template <typename A>
using ReverseIterator = typename std::reverse_iterator<Iterator<A>>;
template <typename A>
using ConstReverseIterator = typename std::reverse_iterator<ConstIterator<A>>;
template <typename A>
using MoveIterator = typename std::move_iterator<Iterator<A>>;
template <typename A>
using IsMoveAssignOk = std::is_move_assignable<ValueType<A>>;
template <typename A>
using IsSwapOk = absl::type_traits_internal::IsSwappable<ValueType<A>>;
template <typename A,
bool IsTriviallyDestructible =
absl::is_trivially_destructible<ValueType<A>>::value &&
std::is_same<A, std::allocator<ValueType<A>>>::value>
struct DestroyAdapter;
template <typename A>
struct DestroyAdapter<A, /* IsTriviallyDestructible */ false> {
static void DestroyElements(A& allocator, Pointer<A> destroy_first,
SizeType<A> destroy_size) {
for (SizeType<A> i = destroy_size; i != 0;) {
--i;
AllocatorTraits<A>::destroy(allocator, destroy_first + i);
}
}
};
template <typename A>
struct DestroyAdapter<A, /* IsTriviallyDestructible */ true> {
static void DestroyElements(A& allocator, Pointer<A> destroy_first,
SizeType<A> destroy_size) {
static_cast<void>(allocator);
static_cast<void>(destroy_first);
static_cast<void>(destroy_size);
}
};
template <typename A>
struct Allocation {
Pointer<A> data = nullptr;
SizeType<A> capacity = 0;
};
template <typename A,
bool IsOverAligned =
(alignof(ValueType<A>) > ABSL_INTERNAL_DEFAULT_NEW_ALIGNMENT)>
struct MallocAdapter {
static Allocation<A> Allocate(A& allocator, SizeType<A> requested_capacity) {
return {AllocatorTraits<A>::allocate(allocator, requested_capacity),
requested_capacity};
}
static void Deallocate(A& allocator, Pointer<A> pointer,
SizeType<A> capacity) {
AllocatorTraits<A>::deallocate(allocator, pointer, capacity);
}
};
template <typename A, typename ValueAdapter>
void ConstructElements(absl::internal::type_identity_t<A>& allocator,
Pointer<A> construct_first, ValueAdapter& values,
SizeType<A> construct_size) {
for (SizeType<A> i = 0; i < construct_size; ++i) {
ABSL_INTERNAL_TRY { values.ConstructNext(allocator, construct_first + i); }
ABSL_INTERNAL_CATCH_ANY {
DestroyAdapter<A>::DestroyElements(allocator, construct_first, i);
ABSL_INTERNAL_RETHROW;
}
}
}
template <typename A, typename ValueAdapter>
void AssignElements(Pointer<A> assign_first, ValueAdapter& values,
SizeType<A> assign_size) {
for (SizeType<A> i = 0; i < assign_size; ++i) {
values.AssignNext(assign_first + i);
}
}
template <typename A>
struct StorageView {
Pointer<A> data;
SizeType<A> size;
SizeType<A> capacity;
};
template <typename A, typename Iterator>
class IteratorValueAdapter {
public:
explicit IteratorValueAdapter(const Iterator& it) : it_(it) {}
void ConstructNext(A& allocator, Pointer<A> construct_at) {
AllocatorTraits<A>::construct(allocator, construct_at, *it_);
++it_;
}
void AssignNext(Pointer<A> assign_at) {
*assign_at = *it_;
++it_;
}
private:
Iterator it_;
};
template <typename A>
class CopyValueAdapter {
public:
explicit CopyValueAdapter(ConstPointer<A> p) : ptr_(p) {}
void ConstructNext(A& allocator, Pointer<A> construct_at) {
AllocatorTraits<A>::construct(allocator, construct_at, *ptr_);
}
void AssignNext(Pointer<A> assign_at) { *assign_at = *ptr_; }
private:
ConstPointer<A> ptr_;
};
template <typename A>
class DefaultValueAdapter {
public:
explicit DefaultValueAdapter() {}
void ConstructNext(A& allocator, Pointer<A> construct_at) {
AllocatorTraits<A>::construct(allocator, construct_at);
}
void AssignNext(Pointer<A> assign_at) { *assign_at = ValueType<A>(); }
};
template <typename A>
class AllocationTransaction {
public:
explicit AllocationTransaction(A& allocator)
: allocator_data_(allocator, nullptr), capacity_(0) {}
~AllocationTransaction() {
if (DidAllocate()) {
MallocAdapter<A>::Deallocate(GetAllocator(), GetData(), GetCapacity());
}
}
AllocationTransaction(const AllocationTransaction&) = delete;
void operator=(const AllocationTransaction&) = delete;
A& GetAllocator() { return allocator_data_.template get<0>(); }
Pointer<A>& GetData() { return allocator_data_.template get<1>(); }
SizeType<A>& GetCapacity() { return capacity_; }
bool DidAllocate() { return GetData() != nullptr; }
Pointer<A> Allocate(SizeType<A> requested_capacity) {
Allocation<A> result =
MallocAdapter<A>::Allocate(GetAllocator(), requested_capacity);
GetData() = result.data;
GetCapacity() = result.capacity;
return result.data;
}
[[nodiscard]] Allocation<A> Release() && {
Allocation<A> result = {GetData(), GetCapacity()};
Reset();
return result;
}
private:
void Reset() {
GetData() = nullptr;
GetCapacity() = 0;
}
container_internal::CompressedTuple<A, Pointer<A>> allocator_data_;
SizeType<A> capacity_;
};
template <typename A>
class ConstructionTransaction {
public:
explicit ConstructionTransaction(A& allocator)
: allocator_data_(allocator, nullptr), size_(0) {}
~ConstructionTransaction() {
if (DidConstruct()) {
DestroyAdapter<A>::DestroyElements(GetAllocator(), GetData(), GetSize());
}
}
ConstructionTransaction(const ConstructionTransaction&) = delete;
void operator=(const ConstructionTransaction&) = delete;
A& GetAllocator() { return allocator_data_.template get<0>(); }
Pointer<A>& GetData() { return allocator_data_.template get<1>(); }
SizeType<A>& GetSize() { return size_; }
bool DidConstruct() { return GetData() != nullptr; }
template <typename ValueAdapter>
void Construct(Pointer<A> data, ValueAdapter& values, SizeType<A> size) {
ConstructElements<A>(GetAllocator(), data, values, size);
GetData() = data;
GetSize() = size;
}
void Commit() && {
GetData() = nullptr;
GetSize() = 0;
}
private:
container_internal::CompressedTuple<A, Pointer<A>> allocator_data_;
SizeType<A> size_;
};
template <typename T, size_t N, typename A>
class Storage {
public:
struct MemcpyPolicy {};
struct ElementwiseAssignPolicy {};
struct ElementwiseSwapPolicy {};
struct ElementwiseConstructPolicy {};
using MoveAssignmentPolicy = absl::conditional_t<
// Fast path: if the value type can be trivially move assigned and
// destroyed, and we know the allocator doesn't do anything fancy, then
// it's safe for us to simply adopt the contents of the storage for
// `other` and remove its own reference to them. It's as if we had
// individually move-assigned each value and then destroyed the original.
absl::conjunction<absl::is_trivially_move_assignable<ValueType<A>>,
absl::is_trivially_destructible<ValueType<A>>,
std::is_same<A, std::allocator<ValueType<A>>>>::value,
MemcpyPolicy,
// Otherwise we use move assignment if possible. If not, we simulate
// move assignment using move construction.
//
// Note that this is in contrast to e.g. std::vector and std::optional,
// which are themselves not move-assignable when their contained type is
// not.
absl::conditional_t<IsMoveAssignOk<A>::value, ElementwiseAssignPolicy,
ElementwiseConstructPolicy>>;
// The policy to be used specifically when swapping inlined elements.
using SwapInlinedElementsPolicy = absl::conditional_t<
// Fast path: if the value type can be trivially relocated, and we
// know the allocator doesn't do anything fancy, then it's safe for us
// to simply swap the bytes in the inline storage. It's as if we had
// relocated the first vector's elements into temporary storage,
// relocated the second's elements into the (now-empty) first's,
// and then relocated from temporary storage into the second.
absl::conjunction<absl::is_trivially_relocatable<ValueType<A>>,
std::is_same<A, std::allocator<ValueType<A>>>>::value,
MemcpyPolicy,
absl::conditional_t<IsSwapOk<A>::value, ElementwiseSwapPolicy,
ElementwiseConstructPolicy>>;
static SizeType<A> NextCapacity(SizeType<A> current_capacity) {
return current_capacity * 2;
}
static SizeType<A> ComputeCapacity(SizeType<A> current_capacity,
SizeType<A> requested_capacity) {
return (std::max)(NextCapacity(current_capacity), requested_capacity);
}
// ---------------------------------------------------------------------------
// Storage Constructors and Destructor
// ---------------------------------------------------------------------------
Storage() : metadata_(A(), /* size and is_allocated */ 0u) {}
explicit Storage(const A& allocator)
: metadata_(allocator, /* size and is_allocated */ 0u) {}
~Storage() {
// Fast path: if we are empty and not allocated, there's nothing to do.
if (GetSizeAndIsAllocated() == 0) {
return;
}
// Fast path: if no destructors need to be run and we know the allocator
// doesn't do anything fancy, then all we need to do is deallocate (and
// maybe not even that).
if (absl::is_trivially_destructible<ValueType<A>>::value &&
std::is_same<A, std::allocator<ValueType<A>>>::value) {
DeallocateIfAllocated();
return;
}
DestroyContents();
}
// ---------------------------------------------------------------------------
// Storage Member Accessors
// ---------------------------------------------------------------------------
SizeType<A>& GetSizeAndIsAllocated() { return metadata_.template get<1>(); }
const SizeType<A>& GetSizeAndIsAllocated() const {
return metadata_.template get<1>();
}
SizeType<A> GetSize() const { return GetSizeAndIsAllocated() >> 1; }
bool GetIsAllocated() const { return GetSizeAndIsAllocated() & 1; }
Pointer<A> GetAllocatedData() {
// GCC 12 has a false-positive -Wmaybe-uninitialized warning here.
#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(12, 0)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
return data_.allocated.allocated_data;
#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(12, 0)
#pragma GCC diagnostic pop
#endif
}
ConstPointer<A> GetAllocatedData() const {
return data_.allocated.allocated_data;
}
// ABSL_ATTRIBUTE_NO_SANITIZE_CFI is used because the memory pointed to may be
// uninitialized, a common pattern in allocate()+construct() APIs.
// https://clang.llvm.org/docs/ControlFlowIntegrity.html#bad-cast-checking
// NOTE: When this was written, LLVM documentation did not explicitly
// mention that casting `char*` and using `reinterpret_cast` qualifies
// as a bad cast.
ABSL_ATTRIBUTE_NO_SANITIZE_CFI Pointer<A> GetInlinedData() {
return reinterpret_cast<Pointer<A>>(data_.inlined.inlined_data);
}
ABSL_ATTRIBUTE_NO_SANITIZE_CFI ConstPointer<A> GetInlinedData() const {
return reinterpret_cast<ConstPointer<A>>(data_.inlined.inlined_data);
}
SizeType<A> GetAllocatedCapacity() const {
return data_.allocated.allocated_capacity;
}
SizeType<A> GetInlinedCapacity() const {
return static_cast<SizeType<A>>(kOptimalInlinedSize);
}
StorageView<A> MakeStorageView() {
return GetIsAllocated() ? StorageView<A>{GetAllocatedData(), GetSize(),
GetAllocatedCapacity()}
: StorageView<A>{GetInlinedData(), GetSize(),
GetInlinedCapacity()};
}
A& GetAllocator() { return metadata_.template get<0>(); }
const A& GetAllocator() const { return metadata_.template get<0>(); }
// ---------------------------------------------------------------------------
// Storage Member Mutators
// ---------------------------------------------------------------------------
ABSL_ATTRIBUTE_NOINLINE void InitFrom(const Storage& other);
template <typename ValueAdapter>
void Initialize(ValueAdapter values, SizeType<A> new_size);
template <typename ValueAdapter>
void Assign(ValueAdapter values, SizeType<A> new_size);
template <typename ValueAdapter>
void Resize(ValueAdapter values, SizeType<A> new_size);
template <typename ValueAdapter>
Iterator<A> Insert(ConstIterator<A> pos, ValueAdapter values,
SizeType<A> insert_count);
template <typename... Args>
Reference<A> EmplaceBack(Args&&... args);
Iterator<A> Erase(ConstIterator<A> from, ConstIterator<A> to);
void Reserve(SizeType<A> requested_capacity);
void ShrinkToFit();
void Swap(Storage* other_storage_ptr);
void SetIsAllocated() {
GetSizeAndIsAllocated() |= static_cast<SizeType<A>>(1);
}
void UnsetIsAllocated() {
GetSizeAndIsAllocated() &= ((std::numeric_limits<SizeType<A>>::max)() - 1);
}
void SetSize(SizeType<A> size) {
GetSizeAndIsAllocated() =
(size << 1) | static_cast<SizeType<A>>(GetIsAllocated());
}
void SetAllocatedSize(SizeType<A> size) {
GetSizeAndIsAllocated() = (size << 1) | static_cast<SizeType<A>>(1);
}
void SetInlinedSize(SizeType<A> size) {
GetSizeAndIsAllocated() = size << static_cast<SizeType<A>>(1);
}
void AddSize(SizeType<A> count) {
GetSizeAndIsAllocated() += count << static_cast<SizeType<A>>(1);
}
void SubtractSize(SizeType<A> count) {
ABSL_HARDENING_ASSERT(count <= GetSize());
GetSizeAndIsAllocated() -= count << static_cast<SizeType<A>>(1);
}
void SetAllocation(Allocation<A> allocation) {
data_.allocated.allocated_data = allocation.data;
data_.allocated.allocated_capacity = allocation.capacity;
}
void MemcpyFrom(const Storage& other_storage) {
// Assumption check: it doesn't make sense to memcpy inlined elements unless
// we know the allocator doesn't do anything fancy, and one of the following
// holds:
//
// * The elements are trivially relocatable.
//
// * It's possible to trivially assign the elements and then destroy the
// source.
//
// * It's possible to trivially copy construct/assign the elements.
//
{
using V = ValueType<A>;
ABSL_HARDENING_ASSERT(
other_storage.GetIsAllocated() ||
(std::is_same<A, std::allocator<V>>::value &&
(
// First case above
absl::is_trivially_relocatable<V>::value ||
// Second case above
(absl::is_trivially_move_assignable<V>::value &&
absl::is_trivially_destructible<V>::value) ||
// Third case above
(absl::is_trivially_copy_constructible<V>::value ||
absl::is_trivially_copy_assignable<V>::value))));
}
GetSizeAndIsAllocated() = other_storage.GetSizeAndIsAllocated();
data_ = other_storage.data_;
}
void DeallocateIfAllocated() {
if (GetIsAllocated()) {
MallocAdapter<A>::Deallocate(GetAllocator(), GetAllocatedData(),
GetAllocatedCapacity());
}
}
private:
ABSL_ATTRIBUTE_NOINLINE void DestroyContents();
using Metadata = container_internal::CompressedTuple<A, SizeType<A>>;
struct Allocated {
Pointer<A> allocated_data;
SizeType<A> allocated_capacity;
};
// `kOptimalInlinedSize` is an automatically adjusted inlined capacity of the
// `InlinedVector`. Sometimes, it is possible to increase the capacity (from
// the user requested `N`) without increasing the size of the `InlinedVector`.
static constexpr size_t kOptimalInlinedSize =
(std::max)(N, sizeof(Allocated) / sizeof(ValueType<A>));
struct Inlined {
alignas(ValueType<A>) unsigned char inlined_data[sizeof(
ValueType<A>[kOptimalInlinedSize])];
};
union Data {
Allocated allocated;
Inlined inlined;
};
void SwapN(ElementwiseSwapPolicy, Storage* other, SizeType<A> n);
void SwapN(ElementwiseConstructPolicy, Storage* other, SizeType<A> n);
void SwapInlinedElements(MemcpyPolicy, Storage* other);
template <typename NotMemcpyPolicy>
void SwapInlinedElements(NotMemcpyPolicy, Storage* other);
template <typename... Args>
ABSL_ATTRIBUTE_NOINLINE Reference<A> EmplaceBackSlow(Args&&... args);
Metadata metadata_;
Data data_;
};
template <typename T, size_t N, typename A>
void Storage<T, N, A>::DestroyContents() {
Pointer<A> data = GetIsAllocated() ? GetAllocatedData() : GetInlinedData();
DestroyAdapter<A>::DestroyElements(GetAllocator(), data, GetSize());
DeallocateIfAllocated();
}
template <typename T, size_t N, typename A>
void Storage<T, N, A>::InitFrom(const Storage& other) {
const SizeType<A> n = other.GetSize();
ABSL_HARDENING_ASSERT(n > 0); // Empty sources handled handled in caller.
ConstPointer<A> src;
Pointer<A> dst;
if (!other.GetIsAllocated()) {
dst = GetInlinedData();
src = other.GetInlinedData();
} else {
// Because this is only called from the `InlinedVector` constructors, it's
// safe to take on the allocation with size `0`. If `ConstructElements(...)`
// throws, deallocation will be automatically handled by `~Storage()`.
SizeType<A> requested_capacity = ComputeCapacity(GetInlinedCapacity(), n);
Allocation<A> allocation =
MallocAdapter<A>::Allocate(GetAllocator(), requested_capacity);
SetAllocation(allocation);
dst = allocation.data;
src = other.GetAllocatedData();
}
// Fast path: if the value type is trivially copy constructible and we know
// the allocator doesn't do anything fancy, then we know it is legal for us to
// simply memcpy the other vector's elements.
if (absl::is_trivially_copy_constructible<ValueType<A>>::value &&
std::is_same<A, std::allocator<ValueType<A>>>::value) {
std::memcpy(reinterpret_cast<char*>(dst),
reinterpret_cast<const char*>(src), n * sizeof(ValueType<A>));
} else {
auto values = IteratorValueAdapter<A, ConstPointer<A>>(src);
ConstructElements<A>(GetAllocator(), dst, values, n);
}
GetSizeAndIsAllocated() = other.GetSizeAndIsAllocated();
}
template <typename T, size_t N, typename A>
template <typename ValueAdapter>
auto Storage<T, N, A>::Initialize(ValueAdapter values,
SizeType<A> new_size) -> void {
// Only callable from constructors!
ABSL_HARDENING_ASSERT(!GetIsAllocated());
ABSL_HARDENING_ASSERT(GetSize() == 0);
Pointer<A> construct_data;
if (new_size > GetInlinedCapacity()) {
// Because this is only called from the `InlinedVector` constructors, it's
// safe to take on the allocation with size `0`. If `ConstructElements(...)`
// throws, deallocation will be automatically handled by `~Storage()`.
SizeType<A> requested_capacity =
ComputeCapacity(GetInlinedCapacity(), new_size);
Allocation<A> allocation =
MallocAdapter<A>::Allocate(GetAllocator(), requested_capacity);
construct_data = allocation.data;
SetAllocation(allocation);
SetIsAllocated();
} else {
construct_data = GetInlinedData();
}
ConstructElements<A>(GetAllocator(), construct_data, values, new_size);
// Since the initial size was guaranteed to be `0` and the allocated bit is
// already correct for either case, *adding* `new_size` gives us the correct
// result faster than setting it directly.
AddSize(new_size);
}
template <typename T, size_t N, typename A>
template <typename ValueAdapter>
auto Storage<T, N, A>::Assign(ValueAdapter values,
SizeType<A> new_size) -> void {
StorageView<A> storage_view = MakeStorageView();
AllocationTransaction<A> allocation_tx(GetAllocator());
absl::Span<ValueType<A>> assign_loop;
absl::Span<ValueType<A>> construct_loop;
absl::Span<ValueType<A>> destroy_loop;
if (new_size > storage_view.capacity) {
SizeType<A> requested_capacity =
ComputeCapacity(storage_view.capacity, new_size);
construct_loop = {allocation_tx.Allocate(requested_capacity), new_size};
destroy_loop = {storage_view.data, storage_view.size};
} else if (new_size > storage_view.size) {
assign_loop = {storage_view.data, storage_view.size};
construct_loop = {storage_view.data + storage_view.size,
new_size - storage_view.size};
} else {
assign_loop = {storage_view.data, new_size};
destroy_loop = {storage_view.data + new_size, storage_view.size - new_size};
}
AssignElements<A>(assign_loop.data(), values, assign_loop.size());
ConstructElements<A>(GetAllocator(), construct_loop.data(), values,
construct_loop.size());
DestroyAdapter<A>::DestroyElements(GetAllocator(), destroy_loop.data(),
destroy_loop.size());
if (allocation_tx.DidAllocate()) {
DeallocateIfAllocated();
SetAllocation(std::move(allocation_tx).Release());
SetIsAllocated();
}
SetSize(new_size);
}
template <typename T, size_t N, typename A>
template <typename ValueAdapter>
auto Storage<T, N, A>::Resize(ValueAdapter values,
SizeType<A> new_size) -> void {
StorageView<A> storage_view = MakeStorageView();
Pointer<A> const base = storage_view.data;
const SizeType<A> size = storage_view.size;
A& alloc = GetAllocator();
if (new_size <= size) {
// Destroy extra old elements.
DestroyAdapter<A>::DestroyElements(alloc, base + new_size, size - new_size);
} else if (new_size <= storage_view.capacity) {
// Construct new elements in place.
ConstructElements<A>(alloc, base + size, values, new_size - size);
} else {
// Steps:
// a. Allocate new backing store.
// b. Construct new elements in new backing store.
// c. Move existing elements from old backing store to new backing store.
// d. Destroy all elements in old backing store.
// Use transactional wrappers for the first two steps so we can roll
// back if necessary due to exceptions.
AllocationTransaction<A> allocation_tx(alloc);
SizeType<A> requested_capacity =
ComputeCapacity(storage_view.capacity, new_size);
Pointer<A> new_data = allocation_tx.Allocate(requested_capacity);
ConstructionTransaction<A> construction_tx(alloc);
construction_tx.Construct(new_data + size, values, new_size - size);
IteratorValueAdapter<A, MoveIterator<A>> move_values(
(MoveIterator<A>(base)));
ConstructElements<A>(alloc, new_data, move_values, size);
DestroyAdapter<A>::DestroyElements(alloc, base, size);
std::move(construction_tx).Commit();
DeallocateIfAllocated();
SetAllocation(std::move(allocation_tx).Release());
SetIsAllocated();
}
SetSize(new_size);
}
template <typename T, size_t N, typename A>
template <typename ValueAdapter>
auto Storage<T, N, A>::Insert(ConstIterator<A> pos, ValueAdapter values,
SizeType<A> insert_count) -> Iterator<A> {
StorageView<A> storage_view = MakeStorageView();
auto insert_index = static_cast<SizeType<A>>(
std::distance(ConstIterator<A>(storage_view.data), pos));
SizeType<A> insert_end_index = insert_index + insert_count;
SizeType<A> new_size = storage_view.size + insert_count;
if (new_size > storage_view.capacity) {
AllocationTransaction<A> allocation_tx(GetAllocator());
ConstructionTransaction<A> construction_tx(GetAllocator());
ConstructionTransaction<A> move_construction_tx(GetAllocator());
IteratorValueAdapter<A, MoveIterator<A>> move_values(
MoveIterator<A>(storage_view.data));
SizeType<A> requested_capacity =
ComputeCapacity(storage_view.capacity, new_size);
Pointer<A> new_data = allocation_tx.Allocate(requested_capacity);
construction_tx.Construct(new_data + insert_index, values, insert_count);
move_construction_tx.Construct(new_data, move_values, insert_index);
ConstructElements<A>(GetAllocator(), new_data + insert_end_index,
move_values, storage_view.size - insert_index);
DestroyAdapter<A>::DestroyElements(GetAllocator(), storage_view.data,
storage_view.size);
std::move(construction_tx).Commit();
std::move(move_construction_tx).Commit();
DeallocateIfAllocated();
SetAllocation(std::move(allocation_tx).Release());
SetAllocatedSize(new_size);
return Iterator<A>(new_data + insert_index);
} else {
SizeType<A> move_construction_destination_index =
(std::max)(insert_end_index, storage_view.size);
ConstructionTransaction<A> move_construction_tx(GetAllocator());
IteratorValueAdapter<A, MoveIterator<A>> move_construction_values(
MoveIterator<A>(storage_view.data +
(move_construction_destination_index - insert_count)));
absl::Span<ValueType<A>> move_construction = {
storage_view.data + move_construction_destination_index,
new_size - move_construction_destination_index};
Pointer<A> move_assignment_values = storage_view.data + insert_index;
absl::Span<ValueType<A>> move_assignment = {
storage_view.data + insert_end_index,
move_construction_destination_index - insert_end_index};
absl::Span<ValueType<A>> insert_assignment = {move_assignment_values,
move_construction.size()};
absl::Span<ValueType<A>> insert_construction = {
insert_assignment.data() + insert_assignment.size(),
insert_count - insert_assignment.size()};
move_construction_tx.Construct(move_construction.data(),
move_construction_values,
move_construction.size());
for (Pointer<A>
destination = move_assignment.data() + move_assignment.size(),
last_destination = move_assignment.data(),
source = move_assignment_values + move_assignment.size();
;) {
--destination;
--source;
if (destination < last_destination) break;
*destination = std::move(*source);
}
AssignElements<A>(insert_assignment.data(), values,
insert_assignment.size());
ConstructElements<A>(GetAllocator(), insert_construction.data(), values,
insert_construction.size());
std::move(move_construction_tx).Commit();
AddSize(insert_count);
return Iterator<A>(storage_view.data + insert_index);
}
}
template <typename T, size_t N, typename A>
template <typename... Args>
auto Storage<T, N, A>::EmplaceBack(Args&&... args) -> Reference<A> {
StorageView<A> storage_view = MakeStorageView();
const SizeType<A> n = storage_view.size;
if (ABSL_PREDICT_TRUE(n != storage_view.capacity)) {
// Fast path; new element fits.
Pointer<A> last_ptr = storage_view.data + n;
AllocatorTraits<A>::construct(GetAllocator(), last_ptr,
std::forward<Args>(args)...);
AddSize(1);
return *last_ptr;
}
// TODO(b/173712035): Annotate with musttail attribute to prevent regression.
return EmplaceBackSlow(std::forward<Args>(args)...);
}
template <typename T, size_t N, typename A>
template <typename... Args>
auto Storage<T, N, A>::EmplaceBackSlow(Args&&... args) -> Reference<A> {
StorageView<A> storage_view = MakeStorageView();
AllocationTransaction<A> allocation_tx(GetAllocator());
IteratorValueAdapter<A, MoveIterator<A>> move_values(
MoveIterator<A>(storage_view.data));
SizeType<A> requested_capacity = NextCapacity(storage_view.capacity);
Pointer<A> construct_data = allocation_tx.Allocate(requested_capacity);
Pointer<A> last_ptr = construct_data + storage_view.size;
// Construct new element.
AllocatorTraits<A>::construct(GetAllocator(), last_ptr,
std::forward<Args>(args)...);
// Move elements from old backing store to new backing store.
ABSL_INTERNAL_TRY {
ConstructElements<A>(GetAllocator(), allocation_tx.GetData(), move_values,
storage_view.size);
}
ABSL_INTERNAL_CATCH_ANY {
AllocatorTraits<A>::destroy(GetAllocator(), last_ptr);
ABSL_INTERNAL_RETHROW;
}
// Destroy elements in old backing store.
DestroyAdapter<A>::DestroyElements(GetAllocator(), storage_view.data,
storage_view.size);
DeallocateIfAllocated();
SetAllocation(std::move(allocation_tx).Release());
SetIsAllocated();
AddSize(1);
return *last_ptr;
}
template <typename T, size_t N, typename A>
auto Storage<T, N, A>::Erase(ConstIterator<A> from,
ConstIterator<A> to) -> Iterator<A> {
StorageView<A> storage_view = MakeStorageView();
auto erase_size = static_cast<SizeType<A>>(std::distance(from, to));
auto erase_index = static_cast<SizeType<A>>(
std::distance(ConstIterator<A>(storage_view.data), from));
SizeType<A> erase_end_index = erase_index + erase_size;
// Fast path: if the value type is trivially relocatable and we know
// the allocator doesn't do anything fancy, then we know it is legal for us to
// simply destroy the elements in the "erasure window" (which cannot throw)
// and then memcpy downward to close the window.
if (absl::is_trivially_relocatable<ValueType<A>>::value &&
std::is_nothrow_destructible<ValueType<A>>::value &&
std::is_same<A, std::allocator<ValueType<A>>>::value) {
DestroyAdapter<A>::DestroyElements(
GetAllocator(), storage_view.data + erase_index, erase_size);
std::memmove(
reinterpret_cast<char*>(storage_view.data + erase_index),
reinterpret_cast<const char*>(storage_view.data + erase_end_index),
(storage_view.size - erase_end_index) * sizeof(ValueType<A>));
} else {
IteratorValueAdapter<A, MoveIterator<A>> move_values(
MoveIterator<A>(storage_view.data + erase_end_index));
AssignElements<A>(storage_view.data + erase_index, move_values,
storage_view.size - erase_end_index);
DestroyAdapter<A>::DestroyElements(
GetAllocator(), storage_view.data + (storage_view.size - erase_size),
erase_size);
}
SubtractSize(erase_size);
return Iterator<A>(storage_view.data + erase_index);
}
template <typename T, size_t N, typename A>
auto Storage<T, N, A>::Reserve(SizeType<A> requested_capacity) -> void {
StorageView<A> storage_view = MakeStorageView();
if (ABSL_PREDICT_FALSE(requested_capacity <= storage_view.capacity)) return;
AllocationTransaction<A> allocation_tx(GetAllocator());
IteratorValueAdapter<A, MoveIterator<A>> move_values(
MoveIterator<A>(storage_view.data));
SizeType<A> new_requested_capacity =
ComputeCapacity(storage_view.capacity, requested_capacity);
Pointer<A> new_data = allocation_tx.Allocate(new_requested_capacity);
ConstructElements<A>(GetAllocator(), new_data, move_values,
storage_view.size);
DestroyAdapter<A>::DestroyElements(GetAllocator(), storage_view.data,
storage_view.size);
DeallocateIfAllocated();
SetAllocation(std::move(allocation_tx).Release());
SetIsAllocated();
}
template <typename T, size_t N, typename A>
auto Storage<T, N, A>::ShrinkToFit() -> void {
// May only be called on allocated instances!
ABSL_HARDENING_ASSERT(GetIsAllocated());
StorageView<A> storage_view{GetAllocatedData(), GetSize(),
GetAllocatedCapacity()};
if (ABSL_PREDICT_FALSE(storage_view.size == storage_view.capacity)) return;
AllocationTransaction<A> allocation_tx(GetAllocator());
IteratorValueAdapter<A, MoveIterator<A>> move_values(
MoveIterator<A>(storage_view.data));
Pointer<A> construct_data;
if (storage_view.size > GetInlinedCapacity()) {
SizeType<A> requested_capacity = storage_view.size;
construct_data = allocation_tx.Allocate(requested_capacity);
if (allocation_tx.GetCapacity() >= storage_view.capacity) {
// Already using the smallest available heap allocation.
return;
}
} else {
construct_data = GetInlinedData();
}
ABSL_INTERNAL_TRY {
ConstructElements<A>(GetAllocator(), construct_data, move_values,
storage_view.size);
}
ABSL_INTERNAL_CATCH_ANY {
SetAllocation({storage_view.data, storage_view.capacity});
ABSL_INTERNAL_RETHROW;
}
DestroyAdapter<A>::DestroyElements(GetAllocator(), storage_view.data,
storage_view.size);
MallocAdapter<A>::Deallocate(GetAllocator(), storage_view.data,
storage_view.capacity);
if (allocation_tx.DidAllocate()) {
SetAllocation(std::move(allocation_tx).Release());
} else {
UnsetIsAllocated();
}
}
template <typename T, size_t N, typename A>
auto Storage<T, N, A>::Swap(Storage* other_storage_ptr) -> void {
using std::swap;
ABSL_HARDENING_ASSERT(this != other_storage_ptr);
if (GetIsAllocated() && other_storage_ptr->GetIsAllocated()) {
swap(data_.allocated, other_storage_ptr->data_.allocated);
} else if (!GetIsAllocated() && !other_storage_ptr->GetIsAllocated()) {
SwapInlinedElements(SwapInlinedElementsPolicy{}, other_storage_ptr);
} else {
Storage* allocated_ptr = this;
Storage* inlined_ptr = other_storage_ptr;
if (!allocated_ptr->GetIsAllocated()) swap(allocated_ptr, inlined_ptr);
StorageView<A> allocated_storage_view{
allocated_ptr->GetAllocatedData(), allocated_ptr->GetSize(),
allocated_ptr->GetAllocatedCapacity()};
IteratorValueAdapter<A, MoveIterator<A>> move_values(
MoveIterator<A>(inlined_ptr->GetInlinedData()));
ABSL_INTERNAL_TRY {
ConstructElements<A>(inlined_ptr->GetAllocator(),
allocated_ptr->GetInlinedData(), move_values,
inlined_ptr->GetSize());
}
ABSL_INTERNAL_CATCH_ANY {
allocated_ptr->SetAllocation(Allocation<A>{
allocated_storage_view.data, allocated_storage_view.capacity});
ABSL_INTERNAL_RETHROW;
}
DestroyAdapter<A>::DestroyElements(inlined_ptr->GetAllocator(),
inlined_ptr->GetInlinedData(),
inlined_ptr->GetSize());
inlined_ptr->SetAllocation(Allocation<A>{allocated_storage_view.data,
allocated_storage_view.capacity});
}
swap(GetSizeAndIsAllocated(), other_storage_ptr->GetSizeAndIsAllocated());
swap(GetAllocator(), other_storage_ptr->GetAllocator());
}
template <typename T, size_t N, typename A>
void Storage<T, N, A>::SwapN(ElementwiseSwapPolicy, Storage* other,
SizeType<A> n) {
std::swap_ranges(GetInlinedData(), GetInlinedData() + n,
other->GetInlinedData());
}
template <typename T, size_t N, typename A>
void Storage<T, N, A>::SwapN(ElementwiseConstructPolicy, Storage* other,
SizeType<A> n) {
Pointer<A> a = GetInlinedData();
Pointer<A> b = other->GetInlinedData();
// see note on allocators in `SwapInlinedElements`.
A& allocator_a = GetAllocator();
A& allocator_b = other->GetAllocator();
for (SizeType<A> i = 0; i < n; ++i, ++a, ++b) {
ValueType<A> tmp(std::move(*a));
AllocatorTraits<A>::destroy(allocator_a, a);
AllocatorTraits<A>::construct(allocator_b, a, std::move(*b));
AllocatorTraits<A>::destroy(allocator_b, b);
AllocatorTraits<A>::construct(allocator_a, b, std::move(tmp));
}
}
template <typename T, size_t N, typename A>
void Storage<T, N, A>::SwapInlinedElements(MemcpyPolicy, Storage* other) {
Data tmp = data_;
data_ = other->data_;
other->data_ = tmp;
}
template <typename T, size_t N, typename A>
template <typename NotMemcpyPolicy>
void Storage<T, N, A>::SwapInlinedElements(NotMemcpyPolicy policy,
Storage* other) {
// Note: `destroy` needs to use pre-swap allocator while `construct` -
// post-swap allocator. Allocators will be swapped later on outside of
// `SwapInlinedElements`.
Storage* small_ptr = this;
Storage* large_ptr = other;
if (small_ptr->GetSize() > large_ptr->GetSize()) {
std::swap(small_ptr, large_ptr);
}
auto small_size = small_ptr->GetSize();
auto diff = large_ptr->GetSize() - small_size;
SwapN(policy, other, small_size);
IteratorValueAdapter<A, MoveIterator<A>> move_values(
MoveIterator<A>(large_ptr->GetInlinedData() + small_size));
ConstructElements<A>(large_ptr->GetAllocator(),
small_ptr->GetInlinedData() + small_size, move_values,
diff);
DestroyAdapter<A>::DestroyElements(large_ptr->GetAllocator(),
large_ptr->GetInlinedData() + small_size,
diff);
}
// End ignore "array-bounds"
#if !defined(__clang__) && defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
} // namespace inlined_vector_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_CONTAINER_INTERNAL_INLINED_VECTOR_H_
*ø
ˆsoong/.intermediates/external/abseil-cpp/absl_base_iterator_traits_internal_hdrs/gen/my_include_dir/absl/base/internal/iterator_traits.hê// Copyright 2025 The Abseil Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: internal/iterator_traits.h
// -----------------------------------------------------------------------------
//
// Helpers for querying traits of iterators, for implementing containers, etc.
#ifndef ABSL_BASE_INTERNAL_ITERATOR_TRAITS_H_
#define ABSL_BASE_INTERNAL_ITERATOR_TRAITS_H_
#include <iterator>
#include <type_traits>
#include "absl/base/config.h"
#include "absl/meta/type_traits.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace base_internal {
template <typename Iterator, typename = void>
struct IteratorCategory {};
template <typename Iterator>
struct IteratorCategory<
Iterator,
absl::void_t<typename std::iterator_traits<Iterator>::iterator_category>> {
using type = typename std::iterator_traits<Iterator>::iterator_category;
};
template <typename Iterator, typename = void>
struct IteratorConceptImpl : IteratorCategory<Iterator> {};
template <typename Iterator>
struct IteratorConceptImpl<
Iterator,
absl::void_t<typename std::iterator_traits<Iterator>::iterator_concept>> {
using type = typename std::iterator_traits<Iterator>::iterator_concept;
};
// The newer `std::iterator_traits<Iterator>::iterator_concept` if available,
// else `std::iterator_traits<Iterator>::iterator_category`.
template <typename Iterator>
using IteratorConcept = typename IteratorConceptImpl<Iterator>::type;
template <typename IteratorTag, typename Iterator>
using IsAtLeastIterator =
std::is_convertible<IteratorConcept<Iterator>, IteratorTag>;
template <typename Iterator>
using IsAtLeastForwardIterator =
IsAtLeastIterator<std::forward_iterator_tag, Iterator>;
} // namespace base_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_INTERNAL_ITERATOR_TRAITS_H_
*ĺ
~soong/.intermediates/external/abseil-cpp/absl_container_inlined_vector_hdrs/gen/my_include_dir/absl/container/inlined_vector.hÀ¹// Copyright 2019 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: inlined_vector.h
// -----------------------------------------------------------------------------
//
// This header file contains the declaration and definition of an "inlined
// vector" which behaves in an equivalent fashion to a `std::vector`, except
// that storage for small sequences of the vector are provided inline without
// requiring any heap allocation.
//
// An `absl::InlinedVector<T, N>` specifies the default capacity `N` as one of
// its template parameters. Instances where `size() <= N` hold contained
// elements in inline space. Typically `N` is very small so that sequences that
// are expected to be short do not require allocations.
//
// An `absl::InlinedVector` does not usually require a specific allocator. If
// the inlined vector grows beyond its initial constraints, it will need to
// allocate (as any normal `std::vector` would). This is usually performed with
// the default allocator (defined as `std::allocator<T>`). Optionally, a custom
// allocator type may be specified as `A` in `absl::InlinedVector<T, N, A>`.
#ifndef ABSL_CONTAINER_INLINED_VECTOR_H_
#define ABSL_CONTAINER_INLINED_VECTOR_H_
#include <algorithm>
#include <cstddef>
#include <cstdlib>
#include <cstring>
#include <initializer_list>
#include <iterator>
#include <memory>
#include <type_traits>
#include <utility>
#include "absl/algorithm/algorithm.h"
#include "absl/base/attributes.h"
#include "absl/base/internal/iterator_traits.h"
#include "absl/base/internal/throw_delegate.h"
#include "absl/base/macros.h"
#include "absl/base/optimization.h"
#include "absl/base/port.h"
#include "absl/container/internal/inlined_vector.h"
#include "absl/hash/internal/weakly_mixed_integer.h"
#include "absl/memory/memory.h"
#include "absl/meta/type_traits.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
// -----------------------------------------------------------------------------
// InlinedVector
// -----------------------------------------------------------------------------
//
// An `absl::InlinedVector` is designed to be a drop-in replacement for
// `std::vector` for use cases where the vector's size is sufficiently small
// that it can be inlined. If the inlined vector does grow beyond its estimated
// capacity, it will trigger an initial allocation on the heap, and will behave
// as a `std::vector`. The API of the `absl::InlinedVector` within this file is
// designed to cover the same API footprint as covered by `std::vector`.
template <typename T, size_t N, typename A = std::allocator<T>>
class ABSL_ATTRIBUTE_WARN_UNUSED InlinedVector {
static_assert(N > 0, "`absl::InlinedVector` requires an inlined capacity.");
using Storage = inlined_vector_internal::Storage<T, N, A>;
template <typename TheA>
using AllocatorTraits = inlined_vector_internal::AllocatorTraits<TheA>;
template <typename TheA>
using MoveIterator = inlined_vector_internal::MoveIterator<TheA>;
template <typename TheA>
using IsMoveAssignOk = inlined_vector_internal::IsMoveAssignOk<TheA>;
template <typename TheA, typename Iterator>
using IteratorValueAdapter =
inlined_vector_internal::IteratorValueAdapter<TheA, Iterator>;
template <typename TheA>
using CopyValueAdapter = inlined_vector_internal::CopyValueAdapter<TheA>;
template <typename TheA>
using DefaultValueAdapter =
inlined_vector_internal::DefaultValueAdapter<TheA>;
template <typename Iterator>
using EnableIfAtLeastForwardIterator = std::enable_if_t<
base_internal::IsAtLeastForwardIterator<Iterator>::value, int>;
template <typename Iterator>
using DisableIfAtLeastForwardIterator = std::enable_if_t<
!base_internal::IsAtLeastForwardIterator<Iterator>::value, int>;
using MemcpyPolicy = typename Storage::MemcpyPolicy;
using ElementwiseAssignPolicy = typename Storage::ElementwiseAssignPolicy;
using ElementwiseConstructPolicy =
typename Storage::ElementwiseConstructPolicy;
using MoveAssignmentPolicy = typename Storage::MoveAssignmentPolicy;
public:
using allocator_type = A;
using value_type = inlined_vector_internal::ValueType<A>;
using pointer = inlined_vector_internal::Pointer<A>;
using const_pointer = inlined_vector_internal::ConstPointer<A>;
using size_type = inlined_vector_internal::SizeType<A>;
using difference_type = inlined_vector_internal::DifferenceType<A>;
using reference = inlined_vector_internal::Reference<A>;
using const_reference = inlined_vector_internal::ConstReference<A>;
using iterator = inlined_vector_internal::Iterator<A>;
using const_iterator = inlined_vector_internal::ConstIterator<A>;
using reverse_iterator = inlined_vector_internal::ReverseIterator<A>;
using const_reverse_iterator =
inlined_vector_internal::ConstReverseIterator<A>;
// ---------------------------------------------------------------------------
// InlinedVector Constructors and Destructor
// ---------------------------------------------------------------------------
// Creates an empty inlined vector with a value-initialized allocator.
InlinedVector() noexcept(noexcept(allocator_type())) : storage_() {}
// Creates an empty inlined vector with a copy of `allocator`.
explicit InlinedVector(const allocator_type& allocator) noexcept
: storage_(allocator) {}
// Creates an inlined vector with `n` copies of `value_type()`.
explicit InlinedVector(size_type n,
const allocator_type& allocator = allocator_type())
: storage_(allocator) {
storage_.Initialize(DefaultValueAdapter<A>(), n);
}
// Creates an inlined vector with `n` copies of `v`.
InlinedVector(size_type n, const_reference v,
const allocator_type& allocator = allocator_type())
: storage_(allocator) {
storage_.Initialize(CopyValueAdapter<A>(std::addressof(v)), n);
}
// Creates an inlined vector with copies of the elements of `list`.
InlinedVector(std::initializer_list<value_type> list,
const allocator_type& allocator = allocator_type())
: InlinedVector(list.begin(), list.end(), allocator) {}
// Creates an inlined vector with elements constructed from the provided
// forward iterator range [`first`, `last`).
//
// NOTE: the `enable_if` prevents ambiguous interpretation between a call to
// this constructor with two integral arguments and a call to the above
// `InlinedVector(size_type, const_reference)` constructor.
template <typename ForwardIterator,
EnableIfAtLeastForwardIterator<ForwardIterator> = 0>
InlinedVector(ForwardIterator first, ForwardIterator last,
const allocator_type& allocator = allocator_type())
: storage_(allocator) {
storage_.Initialize(IteratorValueAdapter<A, ForwardIterator>(first),
static_cast<size_t>(std::distance(first, last)));
}
// Creates an inlined vector with elements constructed from the provided input
// iterator range [`first`, `last`).
template <typename InputIterator,
DisableIfAtLeastForwardIterator<InputIterator> = 0>
InlinedVector(InputIterator first, InputIterator last,
const allocator_type& allocator = allocator_type())
: storage_(allocator) {
std::copy(first, last, std::back_inserter(*this));
}
// Creates an inlined vector by copying the contents of `other` using
// `other`'s allocator.
InlinedVector(const InlinedVector& other)
: InlinedVector(other, other.storage_.GetAllocator()) {}
// Creates an inlined vector by copying the contents of `other` using the
// provided `allocator`.
InlinedVector(const InlinedVector& other, const allocator_type& allocator)
: storage_(allocator) {
// Fast path: if the other vector is empty, there's nothing for us to do.
if (other.empty()) {
return;
}
// Fast path: if the value type is trivially copy constructible, we know the
// allocator doesn't do anything fancy, and there is nothing on the heap
// then we know it is legal for us to simply memcpy the other vector's
// inlined bytes to form our copy of its elements.
if (absl::is_trivially_copy_constructible<value_type>::value &&
std::is_same<A, std::allocator<value_type>>::value &&
!other.storage_.GetIsAllocated()) {
storage_.MemcpyFrom(other.storage_);
return;
}
storage_.InitFrom(other.storage_);
}
// Creates an inlined vector by moving in the contents of `other` without
// allocating. If `other` contains allocated memory, the newly-created inlined
// vector will take ownership of that memory. However, if `other` does not
// contain allocated memory, the newly-created inlined vector will perform
// element-wise move construction of the contents of `other`.
//
// NOTE: since no allocation is performed for the inlined vector in either
// case, the `noexcept(...)` specification depends on whether moving the
// underlying objects can throw. It is assumed assumed that...
// a) move constructors should only throw due to allocation failure.
// b) if `value_type`'s move constructor allocates, it uses the same
// allocation function as the inlined vector's allocator.
// Thus, the move constructor is non-throwing if the allocator is non-throwing
// or `value_type`'s move constructor is specified as `noexcept`.
InlinedVector(InlinedVector&& other) noexcept(
absl::allocator_is_nothrow<allocator_type>::value ||
std::is_nothrow_move_constructible<value_type>::value)
: storage_(other.storage_.GetAllocator()) {
// Fast path: if the value type can be trivially relocated (i.e. moved from
// and destroyed), and we know the allocator doesn't do anything fancy, then
// it's safe for us to simply adopt the contents of the storage for `other`
// and remove its own reference to them. It's as if we had individually
// move-constructed each value and then destroyed the original.
if (absl::is_trivially_relocatable<value_type>::value &&
std::is_same<A, std::allocator<value_type>>::value) {
storage_.MemcpyFrom(other.storage_);
other.storage_.SetInlinedSize(0);
return;
}
// Fast path: if the other vector is on the heap, we can simply take over
// its allocation.
if (other.storage_.GetIsAllocated()) {
storage_.SetAllocation({other.storage_.GetAllocatedData(),
other.storage_.GetAllocatedCapacity()});
storage_.SetAllocatedSize(other.storage_.GetSize());
other.storage_.SetInlinedSize(0);
return;
}
// Otherwise we must move each element individually.
IteratorValueAdapter<A, MoveIterator<A>> other_values(
MoveIterator<A>(other.storage_.GetInlinedData()));
inlined_vector_internal::ConstructElements<A>(
storage_.GetAllocator(), storage_.GetInlinedData(), other_values,
other.storage_.GetSize());
storage_.SetInlinedSize(other.storage_.GetSize());
}
// Creates an inlined vector by moving in the contents of `other` with a copy
// of `allocator`.
//
// NOTE: if `other`'s allocator is not equal to `allocator`, even if `other`
// contains allocated memory, this move constructor will still allocate. Since
// allocation is performed, this constructor can only be `noexcept` if the
// specified allocator is also `noexcept`.
InlinedVector(
InlinedVector&& other,
const allocator_type&
allocator) noexcept(absl::allocator_is_nothrow<allocator_type>::value)
: storage_(allocator) {
// Fast path: if the value type can be trivially relocated (i.e. moved from
// and destroyed), and we know the allocator doesn't do anything fancy, then
// it's safe for us to simply adopt the contents of the storage for `other`
// and remove its own reference to them. It's as if we had individually
// move-constructed each value and then destroyed the original.
if (absl::is_trivially_relocatable<value_type>::value &&
std::is_same<A, std::allocator<value_type>>::value) {
storage_.MemcpyFrom(other.storage_);
other.storage_.SetInlinedSize(0);
return;
}
// Fast path: if the other vector is on the heap and shared the same
// allocator, we can simply take over its allocation.
if ((storage_.GetAllocator() == other.storage_.GetAllocator()) &&
other.storage_.GetIsAllocated()) {
storage_.SetAllocation({other.storage_.GetAllocatedData(),
other.storage_.GetAllocatedCapacity()});
storage_.SetAllocatedSize(other.storage_.GetSize());
other.storage_.SetInlinedSize(0);
return;
}
// Otherwise we must move each element individually.
storage_.Initialize(
IteratorValueAdapter<A, MoveIterator<A>>(MoveIterator<A>(other.data())),
other.size());
}
~InlinedVector() {}
// ---------------------------------------------------------------------------
// InlinedVector Member Accessors
// ---------------------------------------------------------------------------
// `InlinedVector::empty()`
//
// Returns whether the inlined vector contains no elements.
bool empty() const noexcept { return !size(); }
// `InlinedVector::size()`
//
// Returns the number of elements in the inlined vector.
size_type size() const noexcept { return storage_.GetSize(); }
// `InlinedVector::max_size()`
//
// Returns the maximum number of elements the inlined vector can hold.
size_type max_size() const noexcept {
// One bit of the size storage is used to indicate whether the inlined
// vector contains allocated memory. As a result, the maximum size that the
// inlined vector can express is the minimum of the limit of how many
// objects we can allocate and std::numeric_limits<size_type>::max() / 2.
return (std::min)(AllocatorTraits<A>::max_size(storage_.GetAllocator()),
(std::numeric_limits<size_type>::max)() / 2);
}
// `InlinedVector::capacity()`
//
// Returns the number of elements that could be stored in the inlined vector
// without requiring a reallocation.
//
// NOTE: for most inlined vectors, `capacity()` should be equal to the
// template parameter `N`. For inlined vectors which exceed this capacity,
// they will no longer be inlined and `capacity()` will equal the capactity of
// the allocated memory.
size_type capacity() const noexcept {
return storage_.GetIsAllocated() ? storage_.GetAllocatedCapacity()
: storage_.GetInlinedCapacity();
}
// `InlinedVector::data()`
//
// Returns a `pointer` to the elements of the inlined vector. This pointer
// can be used to access and modify the contained elements.
//
// NOTE: only elements within [`data()`, `data() + size()`) are valid.
pointer data() noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
return storage_.GetIsAllocated() ? storage_.GetAllocatedData()
: storage_.GetInlinedData();
}
// Overload of `InlinedVector::data()` that returns a `const_pointer` to the
// elements of the inlined vector. This pointer can be used to access but not
// modify the contained elements.
//
// NOTE: only elements within [`data()`, `data() + size()`) are valid.
const_pointer data() const noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
return storage_.GetIsAllocated() ? storage_.GetAllocatedData()
: storage_.GetInlinedData();
}
// `InlinedVector::operator[](...)`
//
// Returns a `reference` to the `i`th element of the inlined vector.
reference operator[](size_type i) ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(i < size());
return data()[i];
}
// Overload of `InlinedVector::operator[](...)` that returns a
// `const_reference` to the `i`th element of the inlined vector.
const_reference operator[](size_type i) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(i < size());
return data()[i];
}
// `InlinedVector::at(...)`
//
// Returns a `reference` to the `i`th element of the inlined vector.
//
// NOTE: if `i` is not within the required range of `InlinedVector::at(...)`,
// in both debug and non-debug builds, `std::out_of_range` will be thrown.
reference at(size_type i) ABSL_ATTRIBUTE_LIFETIME_BOUND {
if (ABSL_PREDICT_FALSE(i >= size())) {
base_internal::ThrowStdOutOfRange(
"`InlinedVector::at(size_type)` failed bounds check");
}
return data()[i];
}
// Overload of `InlinedVector::at(...)` that returns a `const_reference` to
// the `i`th element of the inlined vector.
//
// NOTE: if `i` is not within the required range of `InlinedVector::at(...)`,
// in both debug and non-debug builds, `std::out_of_range` will be thrown.
const_reference at(size_type i) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
if (ABSL_PREDICT_FALSE(i >= size())) {
base_internal::ThrowStdOutOfRange(
"`InlinedVector::at(size_type) const` failed bounds check");
}
return data()[i];
}
// `InlinedVector::front()`
//
// Returns a `reference` to the first element of the inlined vector.
reference front() ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(!empty());
return data()[0];
}
// Overload of `InlinedVector::front()` that returns a `const_reference` to
// the first element of the inlined vector.
const_reference front() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(!empty());
return data()[0];
}
// `InlinedVector::back()`
//
// Returns a `reference` to the last element of the inlined vector.
reference back() ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(!empty());
return data()[size() - 1];
}
// Overload of `InlinedVector::back()` that returns a `const_reference` to the
// last element of the inlined vector.
const_reference back() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(!empty());
return data()[size() - 1];
}
// `InlinedVector::begin()`
//
// Returns an `iterator` to the beginning of the inlined vector.
iterator begin() noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND { return data(); }
// Overload of `InlinedVector::begin()` that returns a `const_iterator` to
// the beginning of the inlined vector.
const_iterator begin() const noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
return data();
}
// `InlinedVector::end()`
//
// Returns an `iterator` to the end of the inlined vector.
iterator end() noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
return data() + size();
}
// Overload of `InlinedVector::end()` that returns a `const_iterator` to the
// end of the inlined vector.
const_iterator end() const noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
return data() + size();
}
// `InlinedVector::cbegin()`
//
// Returns a `const_iterator` to the beginning of the inlined vector.
const_iterator cbegin() const noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
return begin();
}
// `InlinedVector::cend()`
//
// Returns a `const_iterator` to the end of the inlined vector.
const_iterator cend() const noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
return end();
}
// `InlinedVector::rbegin()`
//
// Returns a `reverse_iterator` from the end of the inlined vector.
reverse_iterator rbegin() noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
return reverse_iterator(end());
}
// Overload of `InlinedVector::rbegin()` that returns a
// `const_reverse_iterator` from the end of the inlined vector.
const_reverse_iterator rbegin() const noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
return const_reverse_iterator(end());
}
// `InlinedVector::rend()`
//
// Returns a `reverse_iterator` from the beginning of the inlined vector.
reverse_iterator rend() noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
return reverse_iterator(begin());
}
// Overload of `InlinedVector::rend()` that returns a `const_reverse_iterator`
// from the beginning of the inlined vector.
const_reverse_iterator rend() const noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
return const_reverse_iterator(begin());
}
// `InlinedVector::crbegin()`
//
// Returns a `const_reverse_iterator` from the end of the inlined vector.
const_reverse_iterator crbegin() const noexcept
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return rbegin();
}
// `InlinedVector::crend()`
//
// Returns a `const_reverse_iterator` from the beginning of the inlined
// vector.
const_reverse_iterator crend() const noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND {
return rend();
}
// `InlinedVector::get_allocator()`
//
// Returns a copy of the inlined vector's allocator.
allocator_type get_allocator() const { return storage_.GetAllocator(); }
// ---------------------------------------------------------------------------
// InlinedVector Member Mutators
// ---------------------------------------------------------------------------
// `InlinedVector::operator=(...)`
//
// Replaces the elements of the inlined vector with copies of the elements of
// `list`.
InlinedVector& operator=(std::initializer_list<value_type> list) {
assign(list.begin(), list.end());
return *this;
}
// Overload of `InlinedVector::operator=(...)` that replaces the elements of
// the inlined vector with copies of the elements of `other`.
InlinedVector& operator=(const InlinedVector& other) {
if (ABSL_PREDICT_TRUE(this != std::addressof(other))) {
const_pointer other_data = other.data();
assign(other_data, other_data + other.size());
}
return *this;
}
// Overload of `InlinedVector::operator=(...)` that moves the elements of
// `other` into the inlined vector.
//
// NOTE: as a result of calling this overload, `other` is left in a valid but
// unspecified state.
InlinedVector& operator=(InlinedVector&& other) {
if (ABSL_PREDICT_TRUE(this != std::addressof(other))) {
MoveAssignment(MoveAssignmentPolicy{}, std::move(other));
}
return *this;
}
// `InlinedVector::assign(...)`
//
// Replaces the contents of the inlined vector with `n` copies of `v`.
void assign(size_type n, const_reference v) {
storage_.Assign(CopyValueAdapter<A>(std::addressof(v)), n);
}
// Overload of `InlinedVector::assign(...)` that replaces the contents of the
// inlined vector with copies of the elements of `list`.
void assign(std::initializer_list<value_type> list) {
assign(list.begin(), list.end());
}
// Overload of `InlinedVector::assign(...)` to replace the contents of the
// inlined vector with the range [`first`, `last`).
//
// NOTE: this overload is for iterators that are "forward" category or better.
template <typename ForwardIterator,
EnableIfAtLeastForwardIterator<ForwardIterator> = 0>
void assign(ForwardIterator first, ForwardIterator last) {
storage_.Assign(IteratorValueAdapter<A, ForwardIterator>(first),
static_cast<size_t>(std::distance(first, last)));
}
// Overload of `InlinedVector::assign(...)` to replace the contents of the
// inlined vector with the range [`first`, `last`).
//
// NOTE: this overload is for iterators that are "input" category.
template <typename InputIterator,
DisableIfAtLeastForwardIterator<InputIterator> = 0>
void assign(InputIterator first, InputIterator last) {
size_type i = 0;
for (; i < size() && first != last; ++i, static_cast<void>(++first)) {
data()[i] = *first;
}
erase(data() + i, data() + size());
std::copy(first, last, std::back_inserter(*this));
}
// `InlinedVector::resize(...)`
//
// Resizes the inlined vector to contain `n` elements.
//
// NOTE: If `n` is smaller than `size()`, extra elements are destroyed. If `n`
// is larger than `size()`, new elements are value-initialized.
void resize(size_type n) {
ABSL_HARDENING_ASSERT(n <= max_size());
storage_.Resize(DefaultValueAdapter<A>(), n);
}
// Overload of `InlinedVector::resize(...)` that resizes the inlined vector to
// contain `n` elements.
//
// NOTE: if `n` is smaller than `size()`, extra elements are destroyed. If `n`
// is larger than `size()`, new elements are copied-constructed from `v`.
void resize(size_type n, const_reference v) {
ABSL_HARDENING_ASSERT(n <= max_size());
storage_.Resize(CopyValueAdapter<A>(std::addressof(v)), n);
}
// `InlinedVector::insert(...)`
//
// Inserts a copy of `v` at `pos`, returning an `iterator` to the newly
// inserted element.
iterator insert(const_iterator pos,
const_reference v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return emplace(pos, v);
}
// Overload of `InlinedVector::insert(...)` that inserts `v` at `pos` using
// move semantics, returning an `iterator` to the newly inserted element.
iterator insert(const_iterator pos,
value_type&& v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return emplace(pos, std::move(v));
}
// Overload of `InlinedVector::insert(...)` that inserts `n` contiguous copies
// of `v` starting at `pos`, returning an `iterator` pointing to the first of
// the newly inserted elements.
iterator insert(const_iterator pos, size_type n,
const_reference v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(pos >= begin());
ABSL_HARDENING_ASSERT(pos <= end());
if (ABSL_PREDICT_TRUE(n != 0)) {
value_type dealias = v;
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102329#c2
// It appears that GCC thinks that since `pos` is a const pointer and may
// point to uninitialized memory at this point, a warning should be
// issued. But `pos` is actually only used to compute an array index to
// write to.
#if !defined(__clang__) && defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
return storage_.Insert(pos, CopyValueAdapter<A>(std::addressof(dealias)),
n);
#if !defined(__clang__) && defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
} else {
return const_cast<iterator>(pos);
}
}
// Overload of `InlinedVector::insert(...)` that inserts copies of the
// elements of `list` starting at `pos`, returning an `iterator` pointing to
// the first of the newly inserted elements.
iterator insert(const_iterator pos, std::initializer_list<value_type> list)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return insert(pos, list.begin(), list.end());
}
// Overload of `InlinedVector::insert(...)` that inserts the range [`first`,
// `last`) starting at `pos`, returning an `iterator` pointing to the first
// of the newly inserted elements.
//
// NOTE: this overload is for iterators that are "forward" category or better.
template <typename ForwardIterator,
EnableIfAtLeastForwardIterator<ForwardIterator> = 0>
iterator insert(const_iterator pos, ForwardIterator first,
ForwardIterator last) ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(pos >= begin());
ABSL_HARDENING_ASSERT(pos <= end());
if (ABSL_PREDICT_TRUE(first != last)) {
return storage_.Insert(
pos, IteratorValueAdapter<A, ForwardIterator>(first),
static_cast<size_type>(std::distance(first, last)));
} else {
return const_cast<iterator>(pos);
}
}
// Overload of `InlinedVector::insert(...)` that inserts the range [`first`,
// `last`) starting at `pos`, returning an `iterator` pointing to the first
// of the newly inserted elements.
//
// NOTE: this overload is for iterators that are "input" category.
template <typename InputIterator,
DisableIfAtLeastForwardIterator<InputIterator> = 0>
iterator insert(const_iterator pos, InputIterator first,
InputIterator last) ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(pos >= begin());
ABSL_HARDENING_ASSERT(pos <= end());
size_type index = static_cast<size_type>(std::distance(cbegin(), pos));
for (size_type i = index; first != last; ++i, static_cast<void>(++first)) {
insert(data() + i, *first);
}
return iterator(data() + index);
}
// `InlinedVector::emplace(...)`
//
// Constructs and inserts an element using `args...` in the inlined vector at
// `pos`, returning an `iterator` pointing to the newly emplaced element.
template <typename... Args>
iterator emplace(const_iterator pos,
Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(pos >= begin());
ABSL_HARDENING_ASSERT(pos <= end());
value_type dealias(std::forward<Args>(args)...);
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102329#c2
// It appears that GCC thinks that since `pos` is a const pointer and may
// point to uninitialized memory at this point, a warning should be
// issued. But `pos` is actually only used to compute an array index to
// write to.
#if !defined(__clang__) && defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
return storage_.Insert(pos,
IteratorValueAdapter<A, MoveIterator<A>>(
MoveIterator<A>(std::addressof(dealias))),
1);
#if !defined(__clang__) && defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
}
// `InlinedVector::emplace_back(...)`
//
// Constructs and inserts an element using `args...` in the inlined vector at
// `end()`, returning a `reference` to the newly emplaced element.
template <typename... Args>
reference emplace_back(Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return storage_.EmplaceBack(std::forward<Args>(args)...);
}
// `InlinedVector::push_back(...)`
//
// Inserts a copy of `v` in the inlined vector at `end()`.
void push_back(const_reference v) { static_cast<void>(emplace_back(v)); }
// Overload of `InlinedVector::push_back(...)` for inserting `v` at `end()`
// using move semantics.
void push_back(value_type&& v) {
static_cast<void>(emplace_back(std::move(v)));
}
// `InlinedVector::pop_back()`
//
// Destroys the element at `back()`, reducing the size by `1`.
void pop_back() noexcept {
ABSL_HARDENING_ASSERT(!empty());
AllocatorTraits<A>::destroy(storage_.GetAllocator(), data() + (size() - 1));
storage_.SubtractSize(1);
}
// `InlinedVector::erase(...)`
//
// Erases the element at `pos`, returning an `iterator` pointing to where the
// erased element was located.
//
// NOTE: may return `end()`, which is not dereferenceable.
iterator erase(const_iterator pos) ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(pos >= begin());
ABSL_HARDENING_ASSERT(pos < end());
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102329#c2
// It appears that GCC thinks that since `pos` is a const pointer and may
// point to uninitialized memory at this point, a warning should be
// issued. But `pos` is actually only used to compute an array index to
// write to.
#if !defined(__clang__) && defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#pragma GCC diagnostic ignored "-Wuninitialized"
#endif
return storage_.Erase(pos, pos + 1);
#if !defined(__clang__) && defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
}
// Overload of `InlinedVector::erase(...)` that erases every element in the
// range [`from`, `to`), returning an `iterator` pointing to where the first
// erased element was located.
//
// NOTE: may return `end()`, which is not dereferenceable.
iterator erase(const_iterator from,
const_iterator to) ABSL_ATTRIBUTE_LIFETIME_BOUND {
ABSL_HARDENING_ASSERT(from >= begin());
ABSL_HARDENING_ASSERT(from <= to);
ABSL_HARDENING_ASSERT(to <= end());
if (ABSL_PREDICT_TRUE(from != to)) {
return storage_.Erase(from, to);
} else {
return const_cast<iterator>(from);
}
}
// `InlinedVector::clear()`
//
// Destroys all elements in the inlined vector, setting the size to `0` and
// deallocating any held memory.
void clear() noexcept {
inlined_vector_internal::DestroyAdapter<A>::DestroyElements(
storage_.GetAllocator(), data(), size());
storage_.DeallocateIfAllocated();
storage_.SetInlinedSize(0);
}
// `InlinedVector::reserve(...)`
//
// Ensures that there is enough room for at least `n` elements.
void reserve(size_type n) { storage_.Reserve(n); }
// `InlinedVector::shrink_to_fit()`
//
// Attempts to reduce memory usage by moving elements to (or keeping elements
// in) the smallest available buffer sufficient for containing `size()`
// elements.
//
// If `size()` is sufficiently small, the elements will be moved into (or kept
// in) the inlined space.
void shrink_to_fit() {
if (storage_.GetIsAllocated()) {
storage_.ShrinkToFit();
}
}
// `InlinedVector::swap(...)`
//
// Swaps the contents of the inlined vector with `other`.
void swap(InlinedVector& other) {
if (ABSL_PREDICT_TRUE(this != std::addressof(other))) {
storage_.Swap(std::addressof(other.storage_));
}
}
private:
template <typename H, typename TheT, size_t TheN, typename TheA>
friend H AbslHashValue(H h, const absl::InlinedVector<TheT, TheN, TheA>& a);
void MoveAssignment(MemcpyPolicy, InlinedVector&& other) {
// Assumption check: we shouldn't be told to use memcpy to implement move
// assignment unless we have trivially destructible elements and an
// allocator that does nothing fancy.
static_assert(absl::is_trivially_destructible<value_type>::value, "");
static_assert(std::is_same<A, std::allocator<value_type>>::value, "");
// Throw away our existing heap allocation, if any. There is no need to
// destroy the existing elements one by one because we know they are
// trivially destructible.
storage_.DeallocateIfAllocated();
// Adopt the other vector's inline elements or heap allocation.
storage_.MemcpyFrom(other.storage_);
other.storage_.SetInlinedSize(0);
}
// Destroy our existing elements, if any, and adopt the heap-allocated
// elements of the other vector.
//
// REQUIRES: other.storage_.GetIsAllocated()
void DestroyExistingAndAdopt(InlinedVector&& other) {
ABSL_HARDENING_ASSERT(other.storage_.GetIsAllocated());
inlined_vector_internal::DestroyAdapter<A>::DestroyElements(
storage_.GetAllocator(), data(), size());
storage_.DeallocateIfAllocated();
storage_.MemcpyFrom(other.storage_);
other.storage_.SetInlinedSize(0);
}
void MoveAssignment(ElementwiseAssignPolicy, InlinedVector&& other) {
// Fast path: if the other vector is on the heap then we don't worry about
// actually move-assigning each element. Instead we only throw away our own
// existing elements and adopt the heap allocation of the other vector.
if (other.storage_.GetIsAllocated()) {
DestroyExistingAndAdopt(std::move(other));
return;
}
storage_.Assign(IteratorValueAdapter<A, MoveIterator<A>>(
MoveIterator<A>(other.storage_.GetInlinedData())),
other.size());
}
void MoveAssignment(ElementwiseConstructPolicy, InlinedVector&& other) {
// Fast path: if the other vector is on the heap then we don't worry about
// actually move-assigning each element. Instead we only throw away our own
// existing elements and adopt the heap allocation of the other vector.
if (other.storage_.GetIsAllocated()) {
DestroyExistingAndAdopt(std::move(other));
return;
}
inlined_vector_internal::DestroyAdapter<A>::DestroyElements(
storage_.GetAllocator(), data(), size());
storage_.DeallocateIfAllocated();
IteratorValueAdapter<A, MoveIterator<A>> other_values(
MoveIterator<A>(other.storage_.GetInlinedData()));
inlined_vector_internal::ConstructElements<A>(
storage_.GetAllocator(), storage_.GetInlinedData(), other_values,
other.storage_.GetSize());
storage_.SetInlinedSize(other.storage_.GetSize());
}
Storage storage_;
};
// -----------------------------------------------------------------------------
// InlinedVector Non-Member Functions
// -----------------------------------------------------------------------------
// `swap(...)`
//
// Swaps the contents of two inlined vectors.
template <typename T, size_t N, typename A>
void swap(absl::InlinedVector<T, N, A>& a,
absl::InlinedVector<T, N, A>& b) noexcept(noexcept(a.swap(b))) {
a.swap(b);
}
// `operator==(...)`
//
// Tests for value-equality of two inlined vectors.
template <typename T, size_t N, typename A>
bool operator==(const absl::InlinedVector<T, N, A>& a,
const absl::InlinedVector<T, N, A>& b) {
auto a_data = a.data();
auto b_data = b.data();
return std::equal(a_data, a_data + a.size(), b_data, b_data + b.size());
}
// `operator!=(...)`
//
// Tests for value-inequality of two inlined vectors.
template <typename T, size_t N, typename A>
bool operator!=(const absl::InlinedVector<T, N, A>& a,
const absl::InlinedVector<T, N, A>& b) {
return !(a == b);
}
// `operator<(...)`
//
// Tests whether the value of an inlined vector is less than the value of
// another inlined vector using a lexicographical comparison algorithm.
template <typename T, size_t N, typename A>
bool operator<(const absl::InlinedVector<T, N, A>& a,
const absl::InlinedVector<T, N, A>& b) {
auto a_data = a.data();
auto b_data = b.data();
return std::lexicographical_compare(a_data, a_data + a.size(), b_data,
b_data + b.size());
}
// `operator>(...)`
//
// Tests whether the value of an inlined vector is greater than the value of
// another inlined vector using a lexicographical comparison algorithm.
template <typename T, size_t N, typename A>
bool operator>(const absl::InlinedVector<T, N, A>& a,
const absl::InlinedVector<T, N, A>& b) {
return b < a;
}
// `operator<=(...)`
//
// Tests whether the value of an inlined vector is less than or equal to the
// value of another inlined vector using a lexicographical comparison algorithm.
template <typename T, size_t N, typename A>
bool operator<=(const absl::InlinedVector<T, N, A>& a,
const absl::InlinedVector<T, N, A>& b) {
return !(b < a);
}
// `operator>=(...)`
//
// Tests whether the value of an inlined vector is greater than or equal to the
// value of another inlined vector using a lexicographical comparison algorithm.
template <typename T, size_t N, typename A>
bool operator>=(const absl::InlinedVector<T, N, A>& a,
const absl::InlinedVector<T, N, A>& b) {
return !(a < b);
}
// `AbslHashValue(...)`
//
// Provides `absl::Hash` support for `absl::InlinedVector`. It is uncommon to
// call this directly.
template <typename H, typename T, size_t N, typename A>
H AbslHashValue(H h, const absl::InlinedVector<T, N, A>& a) {
auto size = a.size();
return H::combine(H::combine_contiguous(std::move(h), a.data(), size),
hash_internal::WeaklyMixedInteger{size});
}
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_CONTAINER_INLINED_VECTOR_H_
*™q
Žsoong/.intermediates/external/abseil-cpp/absl_strings_str_format_internal_hdrs/gen/my_include_dir/absl/strings/internal/str_format/extension.h…p//
// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_
#define ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <ostream>
#include <string>
#include "absl/base/config.h"
#include "absl/strings/internal/str_format/output.h"
#include "absl/strings/string_view.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
enum class FormatConversionChar : uint8_t;
enum class FormatConversionCharSet : uint64_t;
enum class LengthMod : std::uint8_t { h, hh, l, ll, L, j, z, t, q, none };
namespace str_format_internal {
class FormatRawSinkImpl {
public:
// Implicitly convert from any type that provides the hook function as
// described above.
template <typename T, decltype(str_format_internal::InvokeFlush(
std::declval<T*>(), string_view()))* = nullptr>
FormatRawSinkImpl(T* raw) // NOLINT
: sink_(raw), write_(&FormatRawSinkImpl::Flush<T>) {}
void Write(string_view s) { write_(sink_, s); }
template <typename T>
static FormatRawSinkImpl Extract(T s) {
return s.sink_;
}
private:
template <typename T>
static void Flush(void* r, string_view s) {
str_format_internal::InvokeFlush(static_cast<T*>(r), s);
}
void* sink_;
void (*write_)(void*, string_view);
};
// An abstraction to which conversions write their string data.
class FormatSinkImpl {
public:
explicit FormatSinkImpl(FormatRawSinkImpl raw) : raw_(raw) {}
~FormatSinkImpl() { Flush(); }
void Flush() {
raw_.Write(string_view(buf_, static_cast<size_t>(pos_ - buf_)));
pos_ = buf_;
}
void Append(size_t n, char c) {
if (n == 0) return;
size_ += n;
auto raw_append = [&](size_t count) {
memset(pos_, c, count);
pos_ += count;
};
while (n > Avail()) {
n -= Avail();
if (Avail() > 0) {
raw_append(Avail());
}
Flush();
}
raw_append(n);
}
void Append(string_view v) {
size_t n = v.size();
if (n == 0) return;
size_ += n;
if (n >= Avail()) {
Flush();
raw_.Write(v);
return;
}
memcpy(pos_, v.data(), n);
pos_ += n;
}
size_t size() const { return size_; }
// Put 'v' to 'sink' with specified width, precision, and left flag.
bool PutPaddedString(string_view v, int width, int precision, bool left);
template <typename T>
T Wrap() {
return T(this);
}
template <typename T>
static FormatSinkImpl* Extract(T* s) {
return s->sink_;
}
private:
size_t Avail() const {
return static_cast<size_t>(buf_ + sizeof(buf_) - pos_);
}
FormatRawSinkImpl raw_;
size_t size_ = 0;
char* pos_ = buf_;
char buf_[1024];
};
enum class Flags : uint8_t {
kBasic = 0,
kLeft = 1 << 0,
kShowPos = 1 << 1,
kSignCol = 1 << 2,
kAlt = 1 << 3,
kZero = 1 << 4,
// This is not a real flag. It just exists to turn off kBasic when no other
// flags are set. This is for when width/precision are specified, or a length
// modifier affects the behavior ("%lc").
kNonBasic = 1 << 5,
};
constexpr Flags operator|(Flags a, Flags b) {
return static_cast<Flags>(static_cast<uint8_t>(a) | static_cast<uint8_t>(b));
}
constexpr bool FlagsContains(Flags haystack, Flags needle) {
return (static_cast<uint8_t>(haystack) & static_cast<uint8_t>(needle)) ==
static_cast<uint8_t>(needle);
}
std::string FlagsToString(Flags v);
inline std::ostream& operator<<(std::ostream& os, Flags v) {
return os << FlagsToString(v);
}
// clang-format off
#define ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(X_VAL, X_SEP) \
/* text */ \
X_VAL(c) X_SEP X_VAL(s) X_SEP \
/* ints */ \
X_VAL(d) X_SEP X_VAL(i) X_SEP X_VAL(o) X_SEP \
X_VAL(u) X_SEP X_VAL(x) X_SEP X_VAL(X) X_SEP \
/* floats */ \
X_VAL(f) X_SEP X_VAL(F) X_SEP X_VAL(e) X_SEP X_VAL(E) X_SEP \
X_VAL(g) X_SEP X_VAL(G) X_SEP X_VAL(a) X_SEP X_VAL(A) X_SEP \
/* misc */ \
X_VAL(n) X_SEP X_VAL(p) X_SEP X_VAL(v)
// clang-format on
// This type should not be referenced, it exists only to provide labels
// internally that match the values declared in FormatConversionChar in
// str_format.h. This is meant to allow internal libraries to use the same
// declared interface type as the public interface
// (absl::StrFormatConversionChar) while keeping the definition in a public
// header.
// Internal libraries should use the form
// `FormatConversionCharInternal::c`, `FormatConversionCharInternal::kNone` for
// comparisons. Use in switch statements is not recommended due to a bug in how
// gcc 4.9 -Wswitch handles declared but undefined enums.
struct FormatConversionCharInternal {
FormatConversionCharInternal() = delete;
private:
// clang-format off
enum class Enum : uint8_t {
c, s, // text
d, i, o, u, x, X, // int
f, F, e, E, g, G, a, A, // float
n, p, v, // misc
kNone
};
// clang-format on
public:
#define ABSL_INTERNAL_X_VAL(id) \
static constexpr FormatConversionChar id = \
static_cast<FormatConversionChar>(Enum::id);
ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL, )
#undef ABSL_INTERNAL_X_VAL
static constexpr FormatConversionChar kNone =
static_cast<FormatConversionChar>(Enum::kNone);
};
// clang-format on
inline FormatConversionChar FormatConversionCharFromChar(char c) {
switch (c) {
#define ABSL_INTERNAL_X_VAL(id) \
case #id[0]: \
return FormatConversionCharInternal::id;
ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL, )
#undef ABSL_INTERNAL_X_VAL
}
return FormatConversionCharInternal::kNone;
}
inline bool FormatConversionCharIsUpper(FormatConversionChar c) {
if (c == FormatConversionCharInternal::X ||
c == FormatConversionCharInternal::F ||
c == FormatConversionCharInternal::E ||
c == FormatConversionCharInternal::G ||
c == FormatConversionCharInternal::A) {
return true;
} else {
return false;
}
}
inline bool FormatConversionCharIsFloat(FormatConversionChar c) {
if (c == FormatConversionCharInternal::a ||
c == FormatConversionCharInternal::e ||
c == FormatConversionCharInternal::f ||
c == FormatConversionCharInternal::g ||
c == FormatConversionCharInternal::A ||
c == FormatConversionCharInternal::E ||
c == FormatConversionCharInternal::F ||
c == FormatConversionCharInternal::G) {
return true;
} else {
return false;
}
}
inline char FormatConversionCharToChar(FormatConversionChar c) {
if (c == FormatConversionCharInternal::kNone) {
return '\0';
#define ABSL_INTERNAL_X_VAL(e) \
} else if (c == FormatConversionCharInternal::e) { \
return #e[0];
#define ABSL_INTERNAL_X_SEP
ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL,
ABSL_INTERNAL_X_SEP)
} else {
return '\0';
}
#undef ABSL_INTERNAL_X_VAL
#undef ABSL_INTERNAL_X_SEP
}
// The associated char.
inline std::ostream& operator<<(std::ostream& os, FormatConversionChar v) {
char c = FormatConversionCharToChar(v);
if (!c) c = '?';
return os << c;
}
struct FormatConversionSpecImplFriend;
class FormatConversionSpecImpl {
public:
// Width and precision are not specified, no flags are set.
bool is_basic() const { return flags_ == Flags::kBasic; }
bool has_left_flag() const { return FlagsContains(flags_, Flags::kLeft); }
bool has_show_pos_flag() const {
return FlagsContains(flags_, Flags::kShowPos);
}
bool has_sign_col_flag() const {
return FlagsContains(flags_, Flags::kSignCol);
}
bool has_alt_flag() const { return FlagsContains(flags_, Flags::kAlt); }
bool has_zero_flag() const { return FlagsContains(flags_, Flags::kZero); }
LengthMod length_mod() const { return length_mod_; }
FormatConversionChar conversion_char() const {
// Keep this field first in the struct . It generates better code when
// accessing it when ConversionSpec is passed by value in registers.
static_assert(offsetof(FormatConversionSpecImpl, conv_) == 0, "");
return conv_;
}
void set_conversion_char(FormatConversionChar c) { conv_ = c; }
// Returns the specified width. If width is unspecfied, it returns a negative
// value.
int width() const { return width_; }
// Returns the specified precision. If precision is unspecfied, it returns a
// negative value.
int precision() const { return precision_; }
template <typename T>
T Wrap() {
return T(*this);
}
private:
friend struct str_format_internal::FormatConversionSpecImplFriend;
FormatConversionChar conv_ = FormatConversionCharInternal::kNone;
Flags flags_;
LengthMod length_mod_ = LengthMod::none;
int width_;
int precision_;
};
struct FormatConversionSpecImplFriend final {
static void SetFlags(Flags f, FormatConversionSpecImpl* conv) {
conv->flags_ = f;
}
static void SetLengthMod(LengthMod l, FormatConversionSpecImpl* conv) {
conv->length_mod_ = l;
}
static void SetConversionChar(FormatConversionChar c,
FormatConversionSpecImpl* conv) {
conv->conv_ = c;
}
static void SetWidth(int w, FormatConversionSpecImpl* conv) {
conv->width_ = w;
}
static void SetPrecision(int p, FormatConversionSpecImpl* conv) {
conv->precision_ = p;
}
static std::string FlagsToString(const FormatConversionSpecImpl& spec) {
return str_format_internal::FlagsToString(spec.flags_);
}
};
// Type safe OR operator.
// We need this for two reasons:
// 1. operator| on enums makes them decay to integers and the result is an
// integer. We need the result to stay as an enum.
// 2. We use "enum class" which would not work even if we accepted the decay.
constexpr FormatConversionCharSet FormatConversionCharSetUnion(
FormatConversionCharSet a) {
return a;
}
template <typename... CharSet>
constexpr FormatConversionCharSet FormatConversionCharSetUnion(
FormatConversionCharSet a, CharSet... rest) {
return static_cast<FormatConversionCharSet>(
static_cast<uint64_t>(a) |
static_cast<uint64_t>(FormatConversionCharSetUnion(rest...)));
}
constexpr uint64_t FormatConversionCharToConvInt(FormatConversionChar c) {
return uint64_t{1} << (1 + static_cast<uint8_t>(c));
}
constexpr uint64_t FormatConversionCharToConvInt(char conv) {
return
#define ABSL_INTERNAL_CHAR_SET_CASE(c) \
conv == #c[0] \
? FormatConversionCharToConvInt(FormatConversionCharInternal::c) \
:
ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_CHAR_SET_CASE, )
#undef ABSL_INTERNAL_CHAR_SET_CASE
conv == '*'
? 1
: 0;
}
constexpr FormatConversionCharSet FormatConversionCharToConvValue(char conv) {
return static_cast<FormatConversionCharSet>(
FormatConversionCharToConvInt(conv));
}
struct FormatConversionCharSetInternal {
#define ABSL_INTERNAL_CHAR_SET_CASE(c) \
static constexpr FormatConversionCharSet c = \
FormatConversionCharToConvValue(#c[0]);
ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_CHAR_SET_CASE, )
#undef ABSL_INTERNAL_CHAR_SET_CASE
// Used for width/precision '*' specification.
static constexpr FormatConversionCharSet kStar =
FormatConversionCharToConvValue('*');
static constexpr FormatConversionCharSet kIntegral =
FormatConversionCharSetUnion(d, i, u, o, x, X);
static constexpr FormatConversionCharSet kFloating =
FormatConversionCharSetUnion(a, e, f, g, A, E, F, G);
static constexpr FormatConversionCharSet kNumeric =
FormatConversionCharSetUnion(kIntegral, kFloating);
static constexpr FormatConversionCharSet kPointer = p;
};
// Type safe OR operator.
// We need this for two reasons:
// 1. operator| on enums makes them decay to integers and the result is an
// integer. We need the result to stay as an enum.
// 2. We use "enum class" which would not work even if we accepted the decay.
constexpr FormatConversionCharSet operator|(FormatConversionCharSet a,
FormatConversionCharSet b) {
return FormatConversionCharSetUnion(a, b);
}
// Overloaded conversion functions to support absl::ParsedFormat.
// Get a conversion with a single character in it.
constexpr FormatConversionCharSet ToFormatConversionCharSet(char c) {
return static_cast<FormatConversionCharSet>(
FormatConversionCharToConvValue(c));
}
// Get a conversion with a single character in it.
constexpr FormatConversionCharSet ToFormatConversionCharSet(
FormatConversionCharSet c) {
return c;
}
template <typename T>
void ToFormatConversionCharSet(T) = delete;
// Checks whether `c` exists in `set`.
constexpr bool Contains(FormatConversionCharSet set, char c) {
return (static_cast<uint64_t>(set) &
static_cast<uint64_t>(FormatConversionCharToConvValue(c))) != 0;
}
// Checks whether all the characters in `c` are contained in `set`
constexpr bool Contains(FormatConversionCharSet set,
FormatConversionCharSet c) {
return (static_cast<uint64_t>(set) & static_cast<uint64_t>(c)) ==
static_cast<uint64_t>(c);
}
// Checks whether all the characters in `c` are contained in `set`
constexpr bool Contains(FormatConversionCharSet set, FormatConversionChar c) {
return (static_cast<uint64_t>(set) & FormatConversionCharToConvInt(c)) != 0;
}
// Return capacity - used, clipped to a minimum of 0.
inline size_t Excess(size_t used, size_t capacity) {
return used < capacity ? capacity - used : 0;
}
} // namespace str_format_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_
*²_
ysoong/.intermediates/external/abseil-cpp/absl_numeric_int128_hdrs/gen/my_include_dir/absl/numeric/int128_no_intrinsic.inc´^//
// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This file contains :int128 implementation details that depend on internal
// representation when ABSL_HAVE_INTRINSIC_INT128 is *not* defined. This file
// is included by int128.h and relies on ABSL_INTERNAL_WCHAR_T being defined.
constexpr uint64_t Int128Low64(int128 v) { return v.lo_; }
constexpr int64_t Int128High64(int128 v) { return v.hi_; }
#if defined(ABSL_IS_LITTLE_ENDIAN)
constexpr int128::int128(int64_t high, uint64_t low) : lo_(low), hi_(high) {}
constexpr int128::int128(int v)
: lo_{static_cast<uint64_t>(v)}, hi_{v < 0 ? ~int64_t{0} : 0} {}
constexpr int128::int128(long v) // NOLINT(runtime/int)
: lo_{static_cast<uint64_t>(v)}, hi_{v < 0 ? ~int64_t{0} : 0} {}
constexpr int128::int128(long long v) // NOLINT(runtime/int)
: lo_{static_cast<uint64_t>(v)}, hi_{v < 0 ? ~int64_t{0} : 0} {}
constexpr int128::int128(unsigned int v) : lo_{v}, hi_{0} {}
// NOLINTNEXTLINE(runtime/int)
constexpr int128::int128(unsigned long v) : lo_{v}, hi_{0} {}
// NOLINTNEXTLINE(runtime/int)
constexpr int128::int128(unsigned long long v) : lo_{v}, hi_{0} {}
constexpr int128::int128(uint128 v)
: lo_{Uint128Low64(v)}, hi_{static_cast<int64_t>(Uint128High64(v))} {}
#elif defined(ABSL_IS_BIG_ENDIAN)
constexpr int128::int128(int64_t high, uint64_t low) : hi_{high}, lo_{low} {}
constexpr int128::int128(int v)
: hi_{v < 0 ? ~int64_t{0} : 0}, lo_{static_cast<uint64_t>(v)} {}
constexpr int128::int128(long v) // NOLINT(runtime/int)
: hi_{v < 0 ? ~int64_t{0} : 0}, lo_{static_cast<uint64_t>(v)} {}
constexpr int128::int128(long long v) // NOLINT(runtime/int)
: hi_{v < 0 ? ~int64_t{0} : 0}, lo_{static_cast<uint64_t>(v)} {}
constexpr int128::int128(unsigned int v) : hi_{0}, lo_{v} {}
// NOLINTNEXTLINE(runtime/int)
constexpr int128::int128(unsigned long v) : hi_{0}, lo_{v} {}
// NOLINTNEXTLINE(runtime/int)
constexpr int128::int128(unsigned long long v) : hi_{0}, lo_{v} {}
constexpr int128::int128(uint128 v)
: hi_{static_cast<int64_t>(Uint128High64(v))}, lo_{Uint128Low64(v)} {}
#else // byte order
#error "Unsupported byte order: must be little-endian or big-endian."
#endif // byte order
constexpr int128::operator bool() const { return lo_ || hi_; }
constexpr int128::operator char() const {
// NOLINTNEXTLINE(runtime/int)
return static_cast<char>(static_cast<long long>(*this));
}
constexpr int128::operator signed char() const {
// NOLINTNEXTLINE(runtime/int)
return static_cast<signed char>(static_cast<long long>(*this));
}
constexpr int128::operator unsigned char() const {
return static_cast<unsigned char>(lo_);
}
constexpr int128::operator char16_t() const {
return static_cast<char16_t>(lo_);
}
constexpr int128::operator char32_t() const {
return static_cast<char32_t>(lo_);
}
constexpr int128::operator ABSL_INTERNAL_WCHAR_T() const {
// NOLINTNEXTLINE(runtime/int)
return static_cast<ABSL_INTERNAL_WCHAR_T>(static_cast<long long>(*this));
}
constexpr int128::operator short() const { // NOLINT(runtime/int)
// NOLINTNEXTLINE(runtime/int)
return static_cast<short>(static_cast<long long>(*this));
}
constexpr int128::operator unsigned short() const { // NOLINT(runtime/int)
return static_cast<unsigned short>(lo_); // NOLINT(runtime/int)
}
constexpr int128::operator int() const {
// NOLINTNEXTLINE(runtime/int)
return static_cast<int>(static_cast<long long>(*this));
}
constexpr int128::operator unsigned int() const {
return static_cast<unsigned int>(lo_);
}
constexpr int128::operator long() const { // NOLINT(runtime/int)
// NOLINTNEXTLINE(runtime/int)
return static_cast<long>(static_cast<long long>(*this));
}
constexpr int128::operator unsigned long() const { // NOLINT(runtime/int)
return static_cast<unsigned long>(lo_); // NOLINT(runtime/int)
}
constexpr int128::operator long long() const { // NOLINT(runtime/int)
// We don't bother checking the value of hi_. If *this < 0, lo_'s high bit
// must be set in order for the value to fit into a long long. Conversely, if
// lo_'s high bit is set, *this must be < 0 for the value to fit.
return int128_internal::BitCastToSigned(lo_);
}
constexpr int128::operator unsigned long long() const { // NOLINT(runtime/int)
return static_cast<unsigned long long>(lo_); // NOLINT(runtime/int)
}
inline int128::operator float() const {
// We must convert the absolute value and then negate as needed, because
// floating point types are typically sign-magnitude. Otherwise, the
// difference between the high and low 64 bits when interpreted as two's
// complement overwhelms the precision of the mantissa.
//
// Also check to make sure we don't negate Int128Min()
constexpr float pow_2_64 = 18446744073709551616.0f;
return hi_ < 0 && *this != Int128Min()
? -static_cast<float>(-*this)
: static_cast<float>(lo_) +
static_cast<float>(hi_) * pow_2_64;
}
inline int128::operator double() const {
// See comment in int128::operator float() above.
constexpr double pow_2_64 = 18446744073709551616.0;
return hi_ < 0 && *this != Int128Min()
? -static_cast<double>(-*this)
: static_cast<double>(lo_) +
static_cast<double>(hi_) * pow_2_64;
}
inline int128::operator long double() const {
// See comment in int128::operator float() above.
constexpr long double pow_2_64 = 18446744073709551616.0L;
return hi_ < 0 && *this != Int128Min()
? -static_cast<long double>(-*this)
: static_cast<long double>(lo_) +
static_cast<long double>(hi_) * pow_2_64;
}
// Comparison operators.
constexpr bool operator==(int128 lhs, int128 rhs) {
return (Int128Low64(lhs) == Int128Low64(rhs) &&
Int128High64(lhs) == Int128High64(rhs));
}
constexpr bool operator!=(int128 lhs, int128 rhs) { return !(lhs == rhs); }
constexpr bool operator<(int128 lhs, int128 rhs) {
return (Int128High64(lhs) == Int128High64(rhs))
? (Int128Low64(lhs) < Int128Low64(rhs))
: (Int128High64(lhs) < Int128High64(rhs));
}
constexpr bool operator>(int128 lhs, int128 rhs) {
return (Int128High64(lhs) == Int128High64(rhs))
? (Int128Low64(lhs) > Int128Low64(rhs))
: (Int128High64(lhs) > Int128High64(rhs));
}
constexpr bool operator<=(int128 lhs, int128 rhs) { return !(lhs > rhs); }
constexpr bool operator>=(int128 lhs, int128 rhs) { return !(lhs < rhs); }
#ifdef __cpp_impl_three_way_comparison
constexpr absl::strong_ordering operator<=>(int128 lhs, int128 rhs) {
if (int64_t lhs_high = Int128High64(lhs), rhs_high = Int128High64(rhs);
lhs_high < rhs_high) {
return absl::strong_ordering::less;
} else if (lhs_high > rhs_high) {
return absl::strong_ordering::greater;
} else if (uint64_t lhs_low = Uint128Low64(lhs), rhs_low = Uint128Low64(rhs);
lhs_low < rhs_low) {
return absl::strong_ordering::less;
} else if (lhs_low > rhs_low) {
return absl::strong_ordering::greater;
} else {
return absl::strong_ordering::equal;
}
}
#endif
// Unary operators.
constexpr int128 operator-(int128 v) {
return MakeInt128(~Int128High64(v) + (Int128Low64(v) == 0),
~Int128Low64(v) + 1);
}
constexpr bool operator!(int128 v) {
return !Int128Low64(v) && !Int128High64(v);
}
constexpr int128 operator~(int128 val) {
return MakeInt128(~Int128High64(val), ~Int128Low64(val));
}
// Arithmetic operators.
namespace int128_internal {
constexpr int128 SignedAddResult(int128 result, int128 lhs) {
// check for carry
return (Int128Low64(result) < Int128Low64(lhs))
? MakeInt128(Int128High64(result) + 1, Int128Low64(result))
: result;
}
} // namespace int128_internal
constexpr int128 operator+(int128 lhs, int128 rhs) {
return int128_internal::SignedAddResult(
MakeInt128(Int128High64(lhs) + Int128High64(rhs),
Int128Low64(lhs) + Int128Low64(rhs)),
lhs);
}
namespace int128_internal {
constexpr int128 SignedSubstructResult(int128 result, int128 lhs, int128 rhs) {
// check for carry
return (Int128Low64(lhs) < Int128Low64(rhs))
? MakeInt128(Int128High64(result) - 1, Int128Low64(result))
: result;
}
} // namespace int128_internal
constexpr int128 operator-(int128 lhs, int128 rhs) {
return int128_internal::SignedSubstructResult(
MakeInt128(Int128High64(lhs) - Int128High64(rhs),
Int128Low64(lhs) - Int128Low64(rhs)),
lhs, rhs);
}
inline int128 operator*(int128 lhs, int128 rhs) {
return MakeInt128(
int128_internal::BitCastToSigned(Uint128High64(uint128(lhs) * rhs)),
Uint128Low64(uint128(lhs) * rhs));
}
inline int128 int128::operator++(int) {
int128 tmp(*this);
*this += 1;
return tmp;
}
inline int128 int128::operator--(int) {
int128 tmp(*this);
*this -= 1;
return tmp;
}
inline int128& int128::operator++() {
*this += 1;
return *this;
}
inline int128& int128::operator--() {
*this -= 1;
return *this;
}
constexpr int128 operator|(int128 lhs, int128 rhs) {
return MakeInt128(Int128High64(lhs) | Int128High64(rhs),
Int128Low64(lhs) | Int128Low64(rhs));
}
constexpr int128 operator&(int128 lhs, int128 rhs) {
return MakeInt128(Int128High64(lhs) & Int128High64(rhs),
Int128Low64(lhs) & Int128Low64(rhs));
}
constexpr int128 operator^(int128 lhs, int128 rhs) {
return MakeInt128(Int128High64(lhs) ^ Int128High64(rhs),
Int128Low64(lhs) ^ Int128Low64(rhs));
}
constexpr int128 operator<<(int128 lhs, int amount) {
// int64_t shifts of >= 63 are undefined, so we need some special-casing.
assert(amount >= 0 && amount < 127);
if (amount <= 0) {
return lhs;
} else if (amount < 63) {
return MakeInt128(
(Int128High64(lhs) << amount) |
static_cast<int64_t>(Int128Low64(lhs) >> (64 - amount)),
Int128Low64(lhs) << amount);
} else if (amount == 63) {
return MakeInt128(((Int128High64(lhs) << 32) << 31) |
static_cast<int64_t>(Int128Low64(lhs) >> 1),
(Int128Low64(lhs) << 32) << 31);
} else if (amount == 127) {
return MakeInt128(static_cast<int64_t>(Int128Low64(lhs) << 63), 0);
} else if (amount > 127) {
return MakeInt128(0, 0);
} else {
// amount >= 64 && amount < 127
return MakeInt128(static_cast<int64_t>(Int128Low64(lhs) << (amount - 64)),
0);
}
}
constexpr int128 operator>>(int128 lhs, int amount) {
// int64_t shifts of >= 63 are undefined, so we need some special-casing.
assert(amount >= 0 && amount < 127);
if (amount <= 0) {
return lhs;
} else if (amount < 63) {
return MakeInt128(
Int128High64(lhs) >> amount,
Int128Low64(lhs) >> amount | static_cast<uint64_t>(Int128High64(lhs))
<< (64 - amount));
} else if (amount == 63) {
return MakeInt128((Int128High64(lhs) >> 32) >> 31,
static_cast<uint64_t>(Int128High64(lhs) << 1) |
(Int128Low64(lhs) >> 32) >> 31);
} else if (amount >= 127) {
return MakeInt128((Int128High64(lhs) >> 32) >> 31,
static_cast<uint64_t>((Int128High64(lhs) >> 32) >> 31));
} else {
// amount >= 64 && amount < 127
return MakeInt128(
(Int128High64(lhs) >> 32) >> 31,
static_cast<uint64_t>(Int128High64(lhs) >> (amount - 64)));
}
}
*õ»
jsoong/.intermediates/external/abseil-cpp/absl_numeric_int128_hdrs/gen/my_include_dir/absl/numeric/int128.h…»//
// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: int128.h
// -----------------------------------------------------------------------------
//
// This header file defines 128-bit integer types, `uint128` and `int128`.
//
// TODO(absl-team): This module is inconsistent as many inline `uint128` methods
// are defined in this file, while many inline `int128` methods are defined in
// the `int128_*_intrinsic.inc` files.
#ifndef ABSL_NUMERIC_INT128_H_
#define ABSL_NUMERIC_INT128_H_
#include <cassert>
#include <cmath>
#include <cstdint>
#include <cstring>
#include <iosfwd>
#include <limits>
#include <string>
#include <utility>
#include "absl/base/config.h"
#include "absl/base/macros.h"
#include "absl/base/port.h"
#include "absl/types/compare.h"
#if defined(_MSC_VER)
// In very old versions of MSVC and when the /Zc:wchar_t flag is off, wchar_t is
// a typedef for unsigned short. Otherwise wchar_t is mapped to the __wchar_t
// builtin type. We need to make sure not to define operator wchar_t()
// alongside operator unsigned short() in these instances.
#define ABSL_INTERNAL_WCHAR_T __wchar_t
#if defined(_M_X64) && !defined(_M_ARM64EC)
#include <intrin.h>
#pragma intrinsic(_umul128)
#endif // defined(_M_X64)
#else // defined(_MSC_VER)
#define ABSL_INTERNAL_WCHAR_T wchar_t
#endif // defined(_MSC_VER)
namespace absl {
ABSL_NAMESPACE_BEGIN
class int128;
// uint128
//
// An unsigned 128-bit integer type. The API is meant to mimic an intrinsic type
// as closely as is practical, including exhibiting undefined behavior in
// analogous cases (e.g. division by zero). This type is intended to be a
// drop-in replacement once C++ supports an intrinsic `uint128_t` type; when
// that occurs, existing well-behaved uses of `uint128` will continue to work
// using that new type.
//
// Note: code written with this type will continue to compile once `uint128_t`
// is introduced, provided the replacement helper functions
// `Uint128(Low|High)64()` and `MakeUint128()` are made.
//
// A `uint128` supports the following:
//
// * Implicit construction from integral types
// * Explicit conversion to integral types
//
// Additionally, if your compiler supports `__int128`, `uint128` is
// interoperable with that type. (Abseil checks for this compatibility through
// the `ABSL_HAVE_INTRINSIC_INT128` macro.)
//
// However, a `uint128` differs from intrinsic integral types in the following
// ways:
//
// * Errors on implicit conversions that do not preserve value (such as
// loss of precision when converting to float values).
// * Requires explicit construction from and conversion to floating point
// types.
// * Conversion to integral types requires an explicit static_cast() to
// mimic use of the `-Wnarrowing` compiler flag.
// * The alignment requirement of `uint128` may differ from that of an
// intrinsic 128-bit integer type depending on platform and build
// configuration.
//
// Example:
//
// float y = absl::Uint128Max(); // Error. uint128 cannot be implicitly
// // converted to float.
//
// absl::uint128 v;
// uint64_t i = v; // Error
// uint64_t i = static_cast<uint64_t>(v); // OK
//
class
#if defined(ABSL_HAVE_INTRINSIC_INT128)
alignas(unsigned __int128)
#endif // ABSL_HAVE_INTRINSIC_INT128
uint128 {
public:
uint128() = default;
// Constructors from arithmetic types
constexpr uint128(int v); // NOLINT(runtime/explicit)
constexpr uint128(unsigned int v); // NOLINT(runtime/explicit)
constexpr uint128(long v); // NOLINT(runtime/int)
constexpr uint128(unsigned long v); // NOLINT(runtime/int)
constexpr uint128(long long v); // NOLINT(runtime/int)
constexpr uint128(unsigned long long v); // NOLINT(runtime/int)
#ifdef ABSL_HAVE_INTRINSIC_INT128
constexpr uint128(__int128 v); // NOLINT(runtime/explicit)
constexpr uint128(unsigned __int128 v); // NOLINT(runtime/explicit)
#endif // ABSL_HAVE_INTRINSIC_INT128
constexpr uint128(int128 v); // NOLINT(runtime/explicit)
explicit uint128(float v);
explicit uint128(double v);
explicit uint128(long double v);
// Assignment operators from arithmetic types
uint128& operator=(int v);
uint128& operator=(unsigned int v);
uint128& operator=(long v); // NOLINT(runtime/int)
uint128& operator=(unsigned long v); // NOLINT(runtime/int)
uint128& operator=(long long v); // NOLINT(runtime/int)
uint128& operator=(unsigned long long v); // NOLINT(runtime/int)
#ifdef ABSL_HAVE_INTRINSIC_INT128
uint128& operator=(__int128 v);
uint128& operator=(unsigned __int128 v);
#endif // ABSL_HAVE_INTRINSIC_INT128
uint128& operator=(int128 v);
// Conversion operators to other arithmetic types
constexpr explicit operator bool() const;
constexpr explicit operator char() const;
constexpr explicit operator signed char() const;
constexpr explicit operator unsigned char() const;
constexpr explicit operator char16_t() const;
constexpr explicit operator char32_t() const;
constexpr explicit operator ABSL_INTERNAL_WCHAR_T() const;
constexpr explicit operator short() const; // NOLINT(runtime/int)
// NOLINTNEXTLINE(runtime/int)
constexpr explicit operator unsigned short() const;
constexpr explicit operator int() const;
constexpr explicit operator unsigned int() const;
constexpr explicit operator long() const; // NOLINT(runtime/int)
// NOLINTNEXTLINE(runtime/int)
constexpr explicit operator unsigned long() const;
// NOLINTNEXTLINE(runtime/int)
constexpr explicit operator long long() const;
// NOLINTNEXTLINE(runtime/int)
constexpr explicit operator unsigned long long() const;
#ifdef ABSL_HAVE_INTRINSIC_INT128
constexpr explicit operator __int128() const;
constexpr explicit operator unsigned __int128() const;
#endif // ABSL_HAVE_INTRINSIC_INT128
explicit operator float() const;
explicit operator double() const;
explicit operator long double() const;
// Trivial copy constructor, assignment operator and destructor.
// Arithmetic operators.
uint128& operator+=(uint128 other);
uint128& operator-=(uint128 other);
uint128& operator*=(uint128 other);
// Long division/modulo for uint128.
uint128& operator/=(uint128 other);
uint128& operator%=(uint128 other);
uint128 operator++(int);
uint128 operator--(int);
uint128& operator<<=(int);
uint128& operator>>=(int);
uint128& operator&=(uint128 other);
uint128& operator|=(uint128 other);
uint128& operator^=(uint128 other);
uint128& operator++();
uint128& operator--();
// Uint128Low64()
//
// Returns the lower 64-bit value of a `uint128` value.
friend constexpr uint64_t Uint128Low64(uint128 v);
// Uint128High64()
//
// Returns the higher 64-bit value of a `uint128` value.
friend constexpr uint64_t Uint128High64(uint128 v);
// MakeUInt128()
//
// Constructs a `uint128` numeric value from two 64-bit unsigned integers.
// Note that this factory function is the only way to construct a `uint128`
// from integer values greater than 2^64.
//
// Example:
//
// absl::uint128 big = absl::MakeUint128(1, 0);
friend constexpr uint128 MakeUint128(uint64_t high, uint64_t low);
// Uint128Max()
//
// Returns the highest value for a 128-bit unsigned integer.
friend constexpr uint128 Uint128Max();
// Support for absl::Hash.
template <typename H>
friend H AbslHashValue(H h, uint128 v) {
#if defined(ABSL_HAVE_INTRINSIC_INT128)
return H::combine(std::move(h), static_cast<unsigned __int128>(v));
#else
return H::combine(std::move(h), Uint128High64(v), Uint128Low64(v));
#endif
}
// Support for absl::StrCat() etc.
template <typename Sink>
friend void AbslStringify(Sink& sink, uint128 v) {
sink.Append(v.ToString());
}
private:
constexpr uint128(uint64_t high, uint64_t low);
std::string ToString() const;
// TODO(strel) Update implementation to use __int128 once all users of
// uint128 are fixed to not depend on alignof(uint128) == 8. Also add
// alignas(16) to class definition to keep alignment consistent across
// platforms.
#if defined(ABSL_IS_LITTLE_ENDIAN)
uint64_t lo_;
uint64_t hi_;
#elif defined(ABSL_IS_BIG_ENDIAN)
uint64_t hi_;
uint64_t lo_;
#else // byte order
#error "Unsupported byte order: must be little-endian or big-endian."
#endif // byte order
};
// allow uint128 to be logged
std::ostream& operator<<(std::ostream& os, uint128 v);
// TODO(strel) add operator>>(std::istream&, uint128)
constexpr uint128 Uint128Max() {
return uint128((std::numeric_limits<uint64_t>::max)(),
(std::numeric_limits<uint64_t>::max)());
}
ABSL_NAMESPACE_END
} // namespace absl
// Specialized numeric_limits for uint128.
namespace std {
template <>
class numeric_limits<absl::uint128> {
public:
static constexpr bool is_specialized = true;
static constexpr bool is_signed = false;
static constexpr bool is_integer = true;
static constexpr bool is_exact = true;
static constexpr bool has_infinity = false;
static constexpr bool has_quiet_NaN = false;
static constexpr bool has_signaling_NaN = false;
ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING
static constexpr float_denorm_style has_denorm = denorm_absent;
ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING
static constexpr bool has_denorm_loss = false;
static constexpr float_round_style round_style = round_toward_zero;
static constexpr bool is_iec559 = false;
static constexpr bool is_bounded = true;
static constexpr bool is_modulo = true;
static constexpr int digits = 128;
static constexpr int digits10 = 38;
static constexpr int max_digits10 = 0;
static constexpr int radix = 2;
static constexpr int min_exponent = 0;
static constexpr int min_exponent10 = 0;
static constexpr int max_exponent = 0;
static constexpr int max_exponent10 = 0;
#ifdef ABSL_HAVE_INTRINSIC_INT128
static constexpr bool traps = numeric_limits<unsigned __int128>::traps;
#else // ABSL_HAVE_INTRINSIC_INT128
static constexpr bool traps = numeric_limits<uint64_t>::traps;
#endif // ABSL_HAVE_INTRINSIC_INT128
static constexpr bool tinyness_before = false;
static constexpr absl::uint128(min)() { return 0; }
static constexpr absl::uint128 lowest() { return 0; }
static constexpr absl::uint128(max)() { return absl::Uint128Max(); }
static constexpr absl::uint128 epsilon() { return 0; }
static constexpr absl::uint128 round_error() { return 0; }
static constexpr absl::uint128 infinity() { return 0; }
static constexpr absl::uint128 quiet_NaN() { return 0; }
static constexpr absl::uint128 signaling_NaN() { return 0; }
static constexpr absl::uint128 denorm_min() { return 0; }
};
} // namespace std
namespace absl {
ABSL_NAMESPACE_BEGIN
// int128
//
// A signed 128-bit integer type. The API is meant to mimic an intrinsic
// integral type as closely as is practical, including exhibiting undefined
// behavior in analogous cases (e.g. division by zero).
//
// An `int128` supports the following:
//
// * Implicit construction from integral types
// * Explicit conversion to integral types
//
// However, an `int128` differs from intrinsic integral types in the following
// ways:
//
// * It is not implicitly convertible to other integral types.
// * Requires explicit construction from and conversion to floating point
// types.
// Additionally, if your compiler supports `__int128`, `int128` is
// interoperable with that type. (Abseil checks for this compatibility through
// the `ABSL_HAVE_INTRINSIC_INT128` macro.)
//
// The design goal for `int128` is that it will be compatible with a future
// `int128_t`, if that type becomes a part of the standard.
//
// Example:
//
// float y = absl::int128(17); // Error. int128 cannot be implicitly
// // converted to float.
//
// absl::int128 v;
// int64_t i = v; // Error
// int64_t i = static_cast<int64_t>(v); // OK
//
class int128 {
public:
int128() = default;
// Constructors from arithmetic types
constexpr int128(int v); // NOLINT(runtime/explicit)
constexpr int128(unsigned int v); // NOLINT(runtime/explicit)
constexpr int128(long v); // NOLINT(runtime/int)
constexpr int128(unsigned long v); // NOLINT(runtime/int)
constexpr int128(long long v); // NOLINT(runtime/int)
constexpr int128(unsigned long long v); // NOLINT(runtime/int)
#ifdef ABSL_HAVE_INTRINSIC_INT128
constexpr int128(__int128 v); // NOLINT(runtime/explicit)
constexpr explicit int128(unsigned __int128 v);
#endif // ABSL_HAVE_INTRINSIC_INT128
constexpr explicit int128(uint128 v);
explicit int128(float v);
explicit int128(double v);
explicit int128(long double v);
// Assignment operators from arithmetic types
int128& operator=(int v);
int128& operator=(unsigned int v);
int128& operator=(long v); // NOLINT(runtime/int)
int128& operator=(unsigned long v); // NOLINT(runtime/int)
int128& operator=(long long v); // NOLINT(runtime/int)
int128& operator=(unsigned long long v); // NOLINT(runtime/int)
#ifdef ABSL_HAVE_INTRINSIC_INT128
int128& operator=(__int128 v);
#endif // ABSL_HAVE_INTRINSIC_INT128
// Conversion operators to other arithmetic types
constexpr explicit operator bool() const;
constexpr explicit operator char() const;
constexpr explicit operator signed char() const;
constexpr explicit operator unsigned char() const;
constexpr explicit operator char16_t() const;
constexpr explicit operator char32_t() const;
constexpr explicit operator ABSL_INTERNAL_WCHAR_T() const;
constexpr explicit operator short() const; // NOLINT(runtime/int)
// NOLINTNEXTLINE(runtime/int)
constexpr explicit operator unsigned short() const;
constexpr explicit operator int() const;
constexpr explicit operator unsigned int() const;
constexpr explicit operator long() const; // NOLINT(runtime/int)
// NOLINTNEXTLINE(runtime/int)
constexpr explicit operator unsigned long() const;
// NOLINTNEXTLINE(runtime/int)
constexpr explicit operator long long() const;
// NOLINTNEXTLINE(runtime/int)
constexpr explicit operator unsigned long long() const;
#ifdef ABSL_HAVE_INTRINSIC_INT128
constexpr explicit operator __int128() const;
constexpr explicit operator unsigned __int128() const;
#endif // ABSL_HAVE_INTRINSIC_INT128
explicit operator float() const;
explicit operator double() const;
explicit operator long double() const;
// Trivial copy constructor, assignment operator and destructor.
// Arithmetic operators
int128& operator+=(int128 other);
int128& operator-=(int128 other);
int128& operator*=(int128 other);
int128& operator/=(int128 other);
int128& operator%=(int128 other);
int128 operator++(int); // postfix increment: i++
int128 operator--(int); // postfix decrement: i--
int128& operator++(); // prefix increment: ++i
int128& operator--(); // prefix decrement: --i
int128& operator&=(int128 other);
int128& operator|=(int128 other);
int128& operator^=(int128 other);
int128& operator<<=(int amount);
int128& operator>>=(int amount);
// Int128Low64()
//
// Returns the lower 64-bit value of a `int128` value.
friend constexpr uint64_t Int128Low64(int128 v);
// Int128High64()
//
// Returns the higher 64-bit value of a `int128` value.
friend constexpr int64_t Int128High64(int128 v);
// MakeInt128()
//
// Constructs a `int128` numeric value from two 64-bit integers. Note that
// signedness is conveyed in the upper `high` value.
//
// (absl::int128(1) << 64) * high + low
//
// Note that this factory function is the only way to construct a `int128`
// from integer values greater than 2^64 or less than -2^64.
//
// Example:
//
// absl::int128 big = absl::MakeInt128(1, 0);
// absl::int128 big_n = absl::MakeInt128(-1, 0);
friend constexpr int128 MakeInt128(int64_t high, uint64_t low);
// Int128Max()
//
// Returns the maximum value for a 128-bit signed integer.
friend constexpr int128 Int128Max();
// Int128Min()
//
// Returns the minimum value for a 128-bit signed integer.
friend constexpr int128 Int128Min();
// Support for absl::Hash.
template <typename H>
friend H AbslHashValue(H h, int128 v) {
#if defined(ABSL_HAVE_INTRINSIC_INT128)
return H::combine(std::move(h), v.v_);
#else
return H::combine(std::move(h), Int128High64(v), Int128Low64(v));
#endif
}
// Support for absl::StrCat() etc.
template <typename Sink>
friend void AbslStringify(Sink& sink, int128 v) {
sink.Append(v.ToString());
}
private:
constexpr int128(int64_t high, uint64_t low);
std::string ToString() const;
#if defined(ABSL_HAVE_INTRINSIC_INT128)
__int128 v_;
#else // ABSL_HAVE_INTRINSIC_INT128
#if defined(ABSL_IS_LITTLE_ENDIAN)
uint64_t lo_;
int64_t hi_;
#elif defined(ABSL_IS_BIG_ENDIAN)
int64_t hi_;
uint64_t lo_;
#else // byte order
#error "Unsupported byte order: must be little-endian or big-endian."
#endif // byte order
#endif // ABSL_HAVE_INTRINSIC_INT128
};
std::ostream& operator<<(std::ostream& os, int128 v);
// TODO(absl-team) add operator>>(std::istream&, int128)
constexpr int128 Int128Max() {
return int128((std::numeric_limits<int64_t>::max)(),
(std::numeric_limits<uint64_t>::max)());
}
constexpr int128 Int128Min() {
return int128((std::numeric_limits<int64_t>::min)(), 0);
}
ABSL_NAMESPACE_END
} // namespace absl
// Specialized numeric_limits for int128.
namespace std {
template <>
class numeric_limits<absl::int128> {
public:
static constexpr bool is_specialized = true;
static constexpr bool is_signed = true;
static constexpr bool is_integer = true;
static constexpr bool is_exact = true;
static constexpr bool has_infinity = false;
static constexpr bool has_quiet_NaN = false;
static constexpr bool has_signaling_NaN = false;
ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING
static constexpr float_denorm_style has_denorm = denorm_absent;
ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING
static constexpr bool has_denorm_loss = false;
static constexpr float_round_style round_style = round_toward_zero;
static constexpr bool is_iec559 = false;
static constexpr bool is_bounded = true;
static constexpr bool is_modulo = false;
static constexpr int digits = 127;
static constexpr int digits10 = 38;
static constexpr int max_digits10 = 0;
static constexpr int radix = 2;
static constexpr int min_exponent = 0;
static constexpr int min_exponent10 = 0;
static constexpr int max_exponent = 0;
static constexpr int max_exponent10 = 0;
#ifdef ABSL_HAVE_INTRINSIC_INT128
static constexpr bool traps = numeric_limits<__int128>::traps;
#else // ABSL_HAVE_INTRINSIC_INT128
static constexpr bool traps = numeric_limits<uint64_t>::traps;
#endif // ABSL_HAVE_INTRINSIC_INT128
static constexpr bool tinyness_before = false;
static constexpr absl::int128(min)() { return absl::Int128Min(); }
static constexpr absl::int128 lowest() { return absl::Int128Min(); }
static constexpr absl::int128(max)() { return absl::Int128Max(); }
static constexpr absl::int128 epsilon() { return 0; }
static constexpr absl::int128 round_error() { return 0; }
static constexpr absl::int128 infinity() { return 0; }
static constexpr absl::int128 quiet_NaN() { return 0; }
static constexpr absl::int128 signaling_NaN() { return 0; }
static constexpr absl::int128 denorm_min() { return 0; }
};
} // namespace std
// --------------------------------------------------------------------------
// Implementation details follow
// --------------------------------------------------------------------------
namespace absl {
ABSL_NAMESPACE_BEGIN
constexpr uint128 MakeUint128(uint64_t high, uint64_t low) {
return uint128(high, low);
}
// Assignment from integer types.
inline uint128& uint128::operator=(int v) { return *this = uint128(v); }
inline uint128& uint128::operator=(unsigned int v) {
return *this = uint128(v);
}
inline uint128& uint128::operator=(long v) { // NOLINT(runtime/int)
return *this = uint128(v);
}
// NOLINTNEXTLINE(runtime/int)
inline uint128& uint128::operator=(unsigned long v) {
return *this = uint128(v);
}
// NOLINTNEXTLINE(runtime/int)
inline uint128& uint128::operator=(long long v) { return *this = uint128(v); }
// NOLINTNEXTLINE(runtime/int)
inline uint128& uint128::operator=(unsigned long long v) {
return *this = uint128(v);
}
#ifdef ABSL_HAVE_INTRINSIC_INT128
inline uint128& uint128::operator=(__int128 v) { return *this = uint128(v); }
inline uint128& uint128::operator=(unsigned __int128 v) {
return *this = uint128(v);
}
#endif // ABSL_HAVE_INTRINSIC_INT128
inline uint128& uint128::operator=(int128 v) { return *this = uint128(v); }
// Arithmetic operators.
constexpr uint128 operator<<(uint128 lhs, int amount);
constexpr uint128 operator>>(uint128 lhs, int amount);
constexpr uint128 operator+(uint128 lhs, uint128 rhs);
constexpr uint128 operator-(uint128 lhs, uint128 rhs);
uint128 operator*(uint128 lhs, uint128 rhs);
uint128 operator/(uint128 lhs, uint128 rhs);
uint128 operator%(uint128 lhs, uint128 rhs);
inline uint128& uint128::operator<<=(int amount) {
*this = *this << amount;
return *this;
}
inline uint128& uint128::operator>>=(int amount) {
*this = *this >> amount;
return *this;
}
inline uint128& uint128::operator+=(uint128 other) {
*this = *this + other;
return *this;
}
inline uint128& uint128::operator-=(uint128 other) {
*this = *this - other;
return *this;
}
inline uint128& uint128::operator*=(uint128 other) {
*this = *this * other;
return *this;
}
inline uint128& uint128::operator/=(uint128 other) {
*this = *this / other;
return *this;
}
inline uint128& uint128::operator%=(uint128 other) {
*this = *this % other;
return *this;
}
constexpr uint64_t Uint128Low64(uint128 v) { return v.lo_; }
constexpr uint64_t Uint128High64(uint128 v) { return v.hi_; }
// Constructors from integer types.
#if defined(ABSL_IS_LITTLE_ENDIAN)
constexpr uint128::uint128(uint64_t high, uint64_t low) : lo_{low}, hi_{high} {}
constexpr uint128::uint128(int v)
: lo_{static_cast<uint64_t>(v)},
hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0} {}
constexpr uint128::uint128(long v) // NOLINT(runtime/int)
: lo_{static_cast<uint64_t>(v)},
hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0} {}
constexpr uint128::uint128(long long v) // NOLINT(runtime/int)
: lo_{static_cast<uint64_t>(v)},
hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0} {}
constexpr uint128::uint128(unsigned int v) : lo_{v}, hi_{0} {}
// NOLINTNEXTLINE(runtime/int)
constexpr uint128::uint128(unsigned long v) : lo_{v}, hi_{0} {}
// NOLINTNEXTLINE(runtime/int)
constexpr uint128::uint128(unsigned long long v) : lo_{v}, hi_{0} {}
#ifdef ABSL_HAVE_INTRINSIC_INT128
constexpr uint128::uint128(__int128 v)
: lo_{static_cast<uint64_t>(v & ~uint64_t{0})},
hi_{static_cast<uint64_t>(static_cast<unsigned __int128>(v) >> 64)} {}
constexpr uint128::uint128(unsigned __int128 v)
: lo_{static_cast<uint64_t>(v & ~uint64_t{0})},
hi_{static_cast<uint64_t>(v >> 64)} {}
#endif // ABSL_HAVE_INTRINSIC_INT128
constexpr uint128::uint128(int128 v)
: lo_{Int128Low64(v)}, hi_{static_cast<uint64_t>(Int128High64(v))} {}
#elif defined(ABSL_IS_BIG_ENDIAN)
constexpr uint128::uint128(uint64_t high, uint64_t low) : hi_{high}, lo_{low} {}
constexpr uint128::uint128(int v)
: hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0},
lo_{static_cast<uint64_t>(v)} {}
constexpr uint128::uint128(long v) // NOLINT(runtime/int)
: hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0},
lo_{static_cast<uint64_t>(v)} {}
constexpr uint128::uint128(long long v) // NOLINT(runtime/int)
: hi_{v < 0 ? (std::numeric_limits<uint64_t>::max)() : 0},
lo_{static_cast<uint64_t>(v)} {}
constexpr uint128::uint128(unsigned int v) : hi_{0}, lo_{v} {}
// NOLINTNEXTLINE(runtime/int)
constexpr uint128::uint128(unsigned long v) : hi_{0}, lo_{v} {}
// NOLINTNEXTLINE(runtime/int)
constexpr uint128::uint128(unsigned long long v) : hi_{0}, lo_{v} {}
#ifdef ABSL_HAVE_INTRINSIC_INT128
constexpr uint128::uint128(__int128 v)
: hi_{static_cast<uint64_t>(static_cast<unsigned __int128>(v) >> 64)},
lo_{static_cast<uint64_t>(v & ~uint64_t{0})} {}
constexpr uint128::uint128(unsigned __int128 v)
: hi_{static_cast<uint64_t>(v >> 64)},
lo_{static_cast<uint64_t>(v & ~uint64_t{0})} {}
#endif // ABSL_HAVE_INTRINSIC_INT128
constexpr uint128::uint128(int128 v)
: hi_{static_cast<uint64_t>(Int128High64(v))}, lo_{Int128Low64(v)} {}
#else // byte order
#error "Unsupported byte order: must be little-endian or big-endian."
#endif // byte order
// Conversion operators to integer types.
constexpr uint128::operator bool() const { return lo_ || hi_; }
constexpr uint128::operator char() const { return static_cast<char>(lo_); }
constexpr uint128::operator signed char() const {
return static_cast<signed char>(lo_);
}
constexpr uint128::operator unsigned char() const {
return static_cast<unsigned char>(lo_);
}
constexpr uint128::operator char16_t() const {
return static_cast<char16_t>(lo_);
}
constexpr uint128::operator char32_t() const {
return static_cast<char32_t>(lo_);
}
constexpr uint128::operator ABSL_INTERNAL_WCHAR_T() const {
return static_cast<ABSL_INTERNAL_WCHAR_T>(lo_);
}
// NOLINTNEXTLINE(runtime/int)
constexpr uint128::operator short() const { return static_cast<short>(lo_); }
constexpr uint128::operator unsigned short() const { // NOLINT(runtime/int)
return static_cast<unsigned short>(lo_); // NOLINT(runtime/int)
}
constexpr uint128::operator int() const { return static_cast<int>(lo_); }
constexpr uint128::operator unsigned int() const {
return static_cast<unsigned int>(lo_);
}
// NOLINTNEXTLINE(runtime/int)
constexpr uint128::operator long() const { return static_cast<long>(lo_); }
constexpr uint128::operator unsigned long() const { // NOLINT(runtime/int)
return static_cast<unsigned long>(lo_); // NOLINT(runtime/int)
}
constexpr uint128::operator long long() const { // NOLINT(runtime/int)
return static_cast<long long>(lo_); // NOLINT(runtime/int)
}
constexpr uint128::operator unsigned long long() const { // NOLINT(runtime/int)
return static_cast<unsigned long long>(lo_); // NOLINT(runtime/int)
}
#ifdef ABSL_HAVE_INTRINSIC_INT128
constexpr uint128::operator __int128() const {
return (static_cast<__int128>(hi_) << 64) + lo_;
}
constexpr uint128::operator unsigned __int128() const {
return (static_cast<unsigned __int128>(hi_) << 64) + lo_;
}
#endif // ABSL_HAVE_INTRINSIC_INT128
// Conversion operators to floating point types.
inline uint128::operator float() const {
// Note: This method might return Inf.
constexpr float pow_2_64 = 18446744073709551616.0f;
return static_cast<float>(lo_) + static_cast<float>(hi_) * pow_2_64;
}
inline uint128::operator double() const {
constexpr double pow_2_64 = 18446744073709551616.0;
return static_cast<double>(lo_) + static_cast<double>(hi_) * pow_2_64;
}
inline uint128::operator long double() const {
constexpr long double pow_2_64 = 18446744073709551616.0L;
return static_cast<long double>(lo_) +
static_cast<long double>(hi_) * pow_2_64;
}
// Comparison operators.
constexpr bool operator==(uint128 lhs, uint128 rhs) {
#if defined(ABSL_HAVE_INTRINSIC_INT128)
return static_cast<unsigned __int128>(lhs) ==
static_cast<unsigned __int128>(rhs);
#else
return (Uint128Low64(lhs) == Uint128Low64(rhs) &&
Uint128High64(lhs) == Uint128High64(rhs));
#endif
}
constexpr bool operator!=(uint128 lhs, uint128 rhs) { return !(lhs == rhs); }
constexpr bool operator<(uint128 lhs, uint128 rhs) {
#ifdef ABSL_HAVE_INTRINSIC_INT128
return static_cast<unsigned __int128>(lhs) <
static_cast<unsigned __int128>(rhs);
#else
return (Uint128High64(lhs) == Uint128High64(rhs))
? (Uint128Low64(lhs) < Uint128Low64(rhs))
: (Uint128High64(lhs) < Uint128High64(rhs));
#endif
}
constexpr bool operator>(uint128 lhs, uint128 rhs) { return rhs < lhs; }
constexpr bool operator<=(uint128 lhs, uint128 rhs) { return !(rhs < lhs); }
constexpr bool operator>=(uint128 lhs, uint128 rhs) { return !(lhs < rhs); }
#ifdef __cpp_impl_three_way_comparison
constexpr absl::strong_ordering operator<=>(uint128 lhs, uint128 rhs) {
#if defined(ABSL_HAVE_INTRINSIC_INT128)
if (auto lhs_128 = static_cast<unsigned __int128>(lhs),
rhs_128 = static_cast<unsigned __int128>(rhs);
lhs_128 < rhs_128) {
return absl::strong_ordering::less;
} else if (lhs_128 > rhs_128) {
return absl::strong_ordering::greater;
} else {
return absl::strong_ordering::equal;
}
#else
if (uint64_t lhs_high = Uint128High64(lhs), rhs_high = Uint128High64(rhs);
lhs_high < rhs_high) {
return absl::strong_ordering::less;
} else if (lhs_high > rhs_high) {
return absl::strong_ordering::greater;
} else if (uint64_t lhs_low = Uint128Low64(lhs), rhs_low = Uint128Low64(rhs);
lhs_low < rhs_low) {
return absl::strong_ordering::less;
} else if (lhs_low > rhs_low) {
return absl::strong_ordering::greater;
} else {
return absl::strong_ordering::equal;
}
#endif
}
#endif
// Unary operators.
constexpr inline uint128 operator+(uint128 val) { return val; }
constexpr inline int128 operator+(int128 val) { return val; }
constexpr uint128 operator-(uint128 val) {
#if defined(ABSL_HAVE_INTRINSIC_INT128)
return -static_cast<unsigned __int128>(val);
#else
return MakeUint128(
~Uint128High64(val) + static_cast<unsigned long>(Uint128Low64(val) == 0),
~Uint128Low64(val) + 1);
#endif
}
constexpr inline bool operator!(uint128 val) {
#if defined(ABSL_HAVE_INTRINSIC_INT128)
return !static_cast<unsigned __int128>(val);
#else
return !Uint128High64(val) && !Uint128Low64(val);
#endif
}
// Logical operators.
constexpr inline uint128 operator~(uint128 val) {
#if defined(ABSL_HAVE_INTRINSIC_INT128)
return ~static_cast<unsigned __int128>(val);
#else
return MakeUint128(~Uint128High64(val), ~Uint128Low64(val));
#endif
}
constexpr inline uint128 operator|(uint128 lhs, uint128 rhs) {
#if defined(ABSL_HAVE_INTRINSIC_INT128)
return static_cast<unsigned __int128>(lhs) |
static_cast<unsigned __int128>(rhs);
#else
return MakeUint128(Uint128High64(lhs) | Uint128High64(rhs),
Uint128Low64(lhs) | Uint128Low64(rhs));
#endif
}
constexpr inline uint128 operator&(uint128 lhs, uint128 rhs) {
#if defined(ABSL_HAVE_INTRINSIC_INT128)
return static_cast<unsigned __int128>(lhs) &
static_cast<unsigned __int128>(rhs);
#else
return MakeUint128(Uint128High64(lhs) & Uint128High64(rhs),
Uint128Low64(lhs) & Uint128Low64(rhs));
#endif
}
constexpr inline uint128 operator^(uint128 lhs, uint128 rhs) {
#if defined(ABSL_HAVE_INTRINSIC_INT128)
return static_cast<unsigned __int128>(lhs) ^
static_cast<unsigned __int128>(rhs);
#else
return MakeUint128(Uint128High64(lhs) ^ Uint128High64(rhs),
Uint128Low64(lhs) ^ Uint128Low64(rhs));
#endif
}
inline uint128& uint128::operator|=(uint128 other) {
*this = *this | other;
return *this;
}
inline uint128& uint128::operator&=(uint128 other) {
*this = *this & other;
return *this;
}
inline uint128& uint128::operator^=(uint128 other) {
*this = *this ^ other;
return *this;
}
// Arithmetic operators.
constexpr uint128 operator<<(uint128 lhs, int amount) {
#ifdef ABSL_HAVE_INTRINSIC_INT128
return static_cast<unsigned __int128>(lhs) << amount;
#else
// uint64_t shifts of >= 64 are undefined, so we will need some
// special-casing.
return amount >= 64 ? MakeUint128(Uint128Low64(lhs) << (amount - 64), 0)
: amount == 0 ? lhs
: MakeUint128((Uint128High64(lhs) << amount) |
(Uint128Low64(lhs) >> (64 - amount)),
Uint128Low64(lhs) << amount);
#endif
}
constexpr uint128 operator>>(uint128 lhs, int amount) {
#ifdef ABSL_HAVE_INTRINSIC_INT128
return static_cast<unsigned __int128>(lhs) >> amount;
#else
// uint64_t shifts of >= 64 are undefined, so we will need some
// special-casing.
return amount >= 64 ? MakeUint128(0, Uint128High64(lhs) >> (amount - 64))
: amount == 0 ? lhs
: MakeUint128(Uint128High64(lhs) >> amount,
(Uint128Low64(lhs) >> amount) |
(Uint128High64(lhs) << (64 - amount)));
#endif
}
#if !defined(ABSL_HAVE_INTRINSIC_INT128)
namespace int128_internal {
constexpr uint128 AddResult(uint128 result, uint128 lhs) {
// check for carry
return (Uint128Low64(result) < Uint128Low64(lhs))
? MakeUint128(Uint128High64(result) + 1, Uint128Low64(result))
: result;
}
} // namespace int128_internal
#endif
constexpr uint128 operator+(uint128 lhs, uint128 rhs) {
#if defined(ABSL_HAVE_INTRINSIC_INT128)
return static_cast<unsigned __int128>(lhs) +
static_cast<unsigned __int128>(rhs);
#else
return int128_internal::AddResult(
MakeUint128(Uint128High64(lhs) + Uint128High64(rhs),
Uint128Low64(lhs) + Uint128Low64(rhs)),
lhs);
#endif
}
#if !defined(ABSL_HAVE_INTRINSIC_INT128)
namespace int128_internal {
constexpr uint128 SubstructResult(uint128 result, uint128 lhs, uint128 rhs) {
// check for carry
return (Uint128Low64(lhs) < Uint128Low64(rhs))
? MakeUint128(Uint128High64(result) - 1, Uint128Low64(result))
: result;
}
} // namespace int128_internal
#endif
constexpr uint128 operator-(uint128 lhs, uint128 rhs) {
#if defined(ABSL_HAVE_INTRINSIC_INT128)
return static_cast<unsigned __int128>(lhs) -
static_cast<unsigned __int128>(rhs);
#else
return int128_internal::SubstructResult(
MakeUint128(Uint128High64(lhs) - Uint128High64(rhs),
Uint128Low64(lhs) - Uint128Low64(rhs)),
lhs, rhs);
#endif
}
inline uint128 operator*(uint128 lhs, uint128 rhs) {
#if defined(ABSL_HAVE_INTRINSIC_INT128)
// TODO(strel) Remove once alignment issues are resolved and unsigned __int128
// can be used for uint128 storage.
return static_cast<unsigned __int128>(lhs) *
static_cast<unsigned __int128>(rhs);
#elif defined(_MSC_VER) && defined(_M_X64) && !defined(_M_ARM64EC)
uint64_t carry;
uint64_t low = _umul128(Uint128Low64(lhs), Uint128Low64(rhs), &carry);
return MakeUint128(Uint128Low64(lhs) * Uint128High64(rhs) +
Uint128High64(lhs) * Uint128Low64(rhs) + carry,
low);
#else // ABSL_HAVE_INTRINSIC128
uint64_t a32 = Uint128Low64(lhs) >> 32;
uint64_t a00 = Uint128Low64(lhs) & 0xffffffff;
uint64_t b32 = Uint128Low64(rhs) >> 32;
uint64_t b00 = Uint128Low64(rhs) & 0xffffffff;
uint128 result =
MakeUint128(Uint128High64(lhs) * Uint128Low64(rhs) +
Uint128Low64(lhs) * Uint128High64(rhs) + a32 * b32,
a00 * b00);
result += uint128(a32 * b00) << 32;
result += uint128(a00 * b32) << 32;
return result;
#endif // ABSL_HAVE_INTRINSIC128
}
#if defined(ABSL_HAVE_INTRINSIC_INT128)
inline uint128 operator/(uint128 lhs, uint128 rhs) {
return static_cast<unsigned __int128>(lhs) /
static_cast<unsigned __int128>(rhs);
}
inline uint128 operator%(uint128 lhs, uint128 rhs) {
return static_cast<unsigned __int128>(lhs) %
static_cast<unsigned __int128>(rhs);
}
#endif
// Increment/decrement operators.
inline uint128 uint128::operator++(int) {
uint128 tmp(*this);
*this += 1;
return tmp;
}
inline uint128 uint128::operator--(int) {
uint128 tmp(*this);
*this -= 1;
return tmp;
}
inline uint128& uint128::operator++() {
*this += 1;
return *this;
}
inline uint128& uint128::operator--() {
*this -= 1;
return *this;
}
constexpr int128 MakeInt128(int64_t high, uint64_t low) {
return int128(high, low);
}
// Assignment from integer types.
inline int128& int128::operator=(int v) { return *this = int128(v); }
inline int128& int128::operator=(unsigned int v) { return *this = int128(v); }
inline int128& int128::operator=(long v) { // NOLINT(runtime/int)
return *this = int128(v);
}
// NOLINTNEXTLINE(runtime/int)
inline int128& int128::operator=(unsigned long v) { return *this = int128(v); }
// NOLINTNEXTLINE(runtime/int)
inline int128& int128::operator=(long long v) { return *this = int128(v); }
// NOLINTNEXTLINE(runtime/int)
inline int128& int128::operator=(unsigned long long v) {
return *this = int128(v);
}
// Arithmetic operators.
constexpr int128 operator-(int128 v);
constexpr int128 operator+(int128 lhs, int128 rhs);
constexpr int128 operator-(int128 lhs, int128 rhs);
int128 operator*(int128 lhs, int128 rhs);
int128 operator/(int128 lhs, int128 rhs);
int128 operator%(int128 lhs, int128 rhs);
constexpr int128 operator|(int128 lhs, int128 rhs);
constexpr int128 operator&(int128 lhs, int128 rhs);
constexpr int128 operator^(int128 lhs, int128 rhs);
constexpr int128 operator<<(int128 lhs, int amount);
constexpr int128 operator>>(int128 lhs, int amount);
inline int128& int128::operator+=(int128 other) {
*this = *this + other;
return *this;
}
inline int128& int128::operator-=(int128 other) {
*this = *this - other;
return *this;
}
inline int128& int128::operator*=(int128 other) {
*this = *this * other;
return *this;
}
inline int128& int128::operator/=(int128 other) {
*this = *this / other;
return *this;
}
inline int128& int128::operator%=(int128 other) {
*this = *this % other;
return *this;
}
inline int128& int128::operator|=(int128 other) {
*this = *this | other;
return *this;
}
inline int128& int128::operator&=(int128 other) {
*this = *this & other;
return *this;
}
inline int128& int128::operator^=(int128 other) {
*this = *this ^ other;
return *this;
}
inline int128& int128::operator<<=(int amount) {
*this = *this << amount;
return *this;
}
inline int128& int128::operator>>=(int amount) {
*this = *this >> amount;
return *this;
}
// Forward declaration for comparison operators.
constexpr bool operator!=(int128 lhs, int128 rhs);
namespace int128_internal {
// Casts from unsigned to signed while preserving the underlying binary
// representation.
constexpr int64_t BitCastToSigned(uint64_t v) {
// Casting an unsigned integer to a signed integer of the same
// width is implementation defined behavior if the source value would not fit
// in the destination type. We step around it with a roundtrip bitwise not
// operation to make sure this function remains constexpr. Clang, GCC, and
// MSVC optimize this to a no-op on x86-64.
return v & (uint64_t{1} << 63) ? ~static_cast<int64_t>(~v)
: static_cast<int64_t>(v);
}
} // namespace int128_internal
#if defined(ABSL_HAVE_INTRINSIC_INT128)
#include "absl/numeric/int128_have_intrinsic.inc" // IWYU pragma: export
#else // ABSL_HAVE_INTRINSIC_INT128
#include "absl/numeric/int128_no_intrinsic.inc" // IWYU pragma: export
#endif // ABSL_HAVE_INTRINSIC_INT128
ABSL_NAMESPACE_END
} // namespace absl
#undef ABSL_INTERNAL_WCHAR_T
#endif // ABSL_NUMERIC_INT128_H_
*í—
hsoong/.intermediates/external/abseil-cpp/absl_types_compare_hdrs/gen/my_include_dir/absl/types/compare.hÿ–// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// compare.h
// -----------------------------------------------------------------------------
//
// This header file defines the `absl::partial_ordering`, `absl::weak_ordering`,
// and `absl::strong_ordering` types for storing the results of three way
// comparisons.
//
// Example:
// absl::weak_ordering compare(const std::string& a, const std::string& b);
//
// These are C++11 compatible versions of the C++20 corresponding types
// (`std::partial_ordering`, etc.) and are designed to be drop-in replacements
// for code compliant with C++20.
#ifndef ABSL_TYPES_COMPARE_H_
#define ABSL_TYPES_COMPARE_H_
#include "absl/base/config.h"
#ifdef ABSL_USES_STD_ORDERING
#include <compare> // IWYU pragma: export
#include <type_traits>
#include "absl/meta/type_traits.h"
#else
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <type_traits>
#include "absl/base/attributes.h"
#include "absl/base/macros.h"
#include "absl/meta/type_traits.h"
#endif
namespace absl {
ABSL_NAMESPACE_BEGIN
#ifdef ABSL_USES_STD_ORDERING
using std::partial_ordering;
using std::strong_ordering;
using std::weak_ordering;
#else
namespace compare_internal {
using value_type = int8_t;
class OnlyLiteralZero {
public:
#if ABSL_HAVE_ATTRIBUTE(enable_if)
// On clang, we can avoid triggering modernize-use-nullptr by only enabling
// this overload when the value is a compile time integer constant equal to 0.
//
// In c++20, this could be a static_assert in a consteval function.
constexpr OnlyLiteralZero(int n) // NOLINT
__attribute__((enable_if(n == 0, "Only literal `0` is allowed."))) {}
#else // ABSL_HAVE_ATTRIBUTE(enable_if)
// Accept only literal zero since it can be implicitly converted to a pointer
// to member type. nullptr constants will be caught by the other constructor
// which accepts a nullptr_t.
//
// This constructor is not used for clang since it triggers
// modernize-use-nullptr.
constexpr OnlyLiteralZero(int OnlyLiteralZero::*) noexcept {} // NOLINT
#endif
// Fails compilation when `nullptr` or integral type arguments other than
// `int` are passed. This constructor doesn't accept `int` because literal `0`
// has type `int`. Literal `0` arguments will be implicitly converted to
// `std::nullptr_t` and accepted by the above constructor, while other `int`
// arguments will fail to be converted and cause compilation failure.
template <typename T, typename = typename std::enable_if<
std::is_same<T, std::nullptr_t>::value ||
(std::is_integral<T>::value &&
!std::is_same<T, int>::value)>::type>
OnlyLiteralZero(T) { // NOLINT
static_assert(sizeof(T) < 0, "Only literal `0` is allowed.");
}
};
enum class eq : value_type {
equal = 0,
equivalent = equal,
nonequal = 1,
nonequivalent = nonequal,
};
enum class ord : value_type { less = -1, greater = 1 };
enum class ncmp : value_type { unordered = -127 };
// Define macros to allow for creation or emulation of C++17 inline variables
// based on whether the feature is supported. Note: we can't use
// ABSL_INTERNAL_INLINE_CONSTEXPR here because the variables here are of
// incomplete types so they need to be defined after the types are complete.
#ifdef __cpp_inline_variables
// A no-op expansion that can be followed by a semicolon at class level.
#define ABSL_COMPARE_INLINE_BASECLASS_DECL(name) static_assert(true, "")
#define ABSL_COMPARE_INLINE_SUBCLASS_DECL(type, name) \
static const type name
#define ABSL_COMPARE_INLINE_INIT(type, name, init) \
inline constexpr type type::name(init)
#else // __cpp_inline_variables
#define ABSL_COMPARE_INLINE_BASECLASS_DECL(name) \
ABSL_CONST_INIT static const T name
// A no-op expansion that can be followed by a semicolon at class level.
#define ABSL_COMPARE_INLINE_SUBCLASS_DECL(type, name) static_assert(true, "")
#define ABSL_COMPARE_INLINE_INIT(type, name, init) \
template <typename T> \
const T compare_internal::type##_base<T>::name(init)
#endif // __cpp_inline_variables
// These template base classes allow for defining the values of the constants
// in the header file (for performance) without using inline variables (which
// aren't available in C++11).
template <typename T>
struct partial_ordering_base {
ABSL_COMPARE_INLINE_BASECLASS_DECL(less);
ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent);
ABSL_COMPARE_INLINE_BASECLASS_DECL(greater);
ABSL_COMPARE_INLINE_BASECLASS_DECL(unordered);
};
template <typename T>
struct weak_ordering_base {
ABSL_COMPARE_INLINE_BASECLASS_DECL(less);
ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent);
ABSL_COMPARE_INLINE_BASECLASS_DECL(greater);
};
template <typename T>
struct strong_ordering_base {
ABSL_COMPARE_INLINE_BASECLASS_DECL(less);
ABSL_COMPARE_INLINE_BASECLASS_DECL(equal);
ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent);
ABSL_COMPARE_INLINE_BASECLASS_DECL(greater);
};
} // namespace compare_internal
class partial_ordering
: public compare_internal::partial_ordering_base<partial_ordering> {
explicit constexpr partial_ordering(compare_internal::eq v) noexcept
: value_(static_cast<compare_internal::value_type>(v)) {}
explicit constexpr partial_ordering(compare_internal::ord v) noexcept
: value_(static_cast<compare_internal::value_type>(v)) {}
explicit constexpr partial_ordering(compare_internal::ncmp v) noexcept
: value_(static_cast<compare_internal::value_type>(v)) {}
friend struct compare_internal::partial_ordering_base<partial_ordering>;
constexpr bool is_ordered() const noexcept {
return value_ !=
compare_internal::value_type(compare_internal::ncmp::unordered);
}
public:
ABSL_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, less);
ABSL_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, equivalent);
ABSL_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, greater);
ABSL_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, unordered);
// Comparisons
friend constexpr bool operator==(
partial_ordering v, compare_internal::OnlyLiteralZero) noexcept {
return v.is_ordered() && v.value_ == 0;
}
friend constexpr bool operator!=(
partial_ordering v, compare_internal::OnlyLiteralZero) noexcept {
return !v.is_ordered() || v.value_ != 0;
}
friend constexpr bool operator<(
partial_ordering v, compare_internal::OnlyLiteralZero) noexcept {
return v.is_ordered() && v.value_ < 0;
}
friend constexpr bool operator<=(
partial_ordering v, compare_internal::OnlyLiteralZero) noexcept {
return v.is_ordered() && v.value_ <= 0;
}
friend constexpr bool operator>(
partial_ordering v, compare_internal::OnlyLiteralZero) noexcept {
return v.is_ordered() && v.value_ > 0;
}
friend constexpr bool operator>=(
partial_ordering v, compare_internal::OnlyLiteralZero) noexcept {
return v.is_ordered() && v.value_ >= 0;
}
friend constexpr bool operator==(compare_internal::OnlyLiteralZero,
partial_ordering v) noexcept {
return v.is_ordered() && 0 == v.value_;
}
friend constexpr bool operator!=(compare_internal::OnlyLiteralZero,
partial_ordering v) noexcept {
return !v.is_ordered() || 0 != v.value_;
}
friend constexpr bool operator<(compare_internal::OnlyLiteralZero,
partial_ordering v) noexcept {
return v.is_ordered() && 0 < v.value_;
}
friend constexpr bool operator<=(compare_internal::OnlyLiteralZero,
partial_ordering v) noexcept {
return v.is_ordered() && 0 <= v.value_;
}
friend constexpr bool operator>(compare_internal::OnlyLiteralZero,
partial_ordering v) noexcept {
return v.is_ordered() && 0 > v.value_;
}
friend constexpr bool operator>=(compare_internal::OnlyLiteralZero,
partial_ordering v) noexcept {
return v.is_ordered() && 0 >= v.value_;
}
friend constexpr bool operator==(partial_ordering v1,
partial_ordering v2) noexcept {
return v1.value_ == v2.value_;
}
friend constexpr bool operator!=(partial_ordering v1,
partial_ordering v2) noexcept {
return v1.value_ != v2.value_;
}
private:
compare_internal::value_type value_;
};
ABSL_COMPARE_INLINE_INIT(partial_ordering, less, compare_internal::ord::less);
ABSL_COMPARE_INLINE_INIT(partial_ordering, equivalent,
compare_internal::eq::equivalent);
ABSL_COMPARE_INLINE_INIT(partial_ordering, greater,
compare_internal::ord::greater);
ABSL_COMPARE_INLINE_INIT(partial_ordering, unordered,
compare_internal::ncmp::unordered);
class weak_ordering
: public compare_internal::weak_ordering_base<weak_ordering> {
explicit constexpr weak_ordering(compare_internal::eq v) noexcept
: value_(static_cast<compare_internal::value_type>(v)) {}
explicit constexpr weak_ordering(compare_internal::ord v) noexcept
: value_(static_cast<compare_internal::value_type>(v)) {}
friend struct compare_internal::weak_ordering_base<weak_ordering>;
public:
ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_ordering, less);
ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_ordering, equivalent);
ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_ordering, greater);
// Conversions
constexpr operator partial_ordering() const noexcept { // NOLINT
return value_ == 0 ? partial_ordering::equivalent
: (value_ < 0 ? partial_ordering::less
: partial_ordering::greater);
}
// Comparisons
friend constexpr bool operator==(
weak_ordering v, compare_internal::OnlyLiteralZero) noexcept {
return v.value_ == 0;
}
friend constexpr bool operator!=(
weak_ordering v, compare_internal::OnlyLiteralZero) noexcept {
return v.value_ != 0;
}
friend constexpr bool operator<(
weak_ordering v, compare_internal::OnlyLiteralZero) noexcept {
return v.value_ < 0;
}
friend constexpr bool operator<=(
weak_ordering v, compare_internal::OnlyLiteralZero) noexcept {
return v.value_ <= 0;
}
friend constexpr bool operator>(
weak_ordering v, compare_internal::OnlyLiteralZero) noexcept {
return v.value_ > 0;
}
friend constexpr bool operator>=(
weak_ordering v, compare_internal::OnlyLiteralZero) noexcept {
return v.value_ >= 0;
}
friend constexpr bool operator==(compare_internal::OnlyLiteralZero,
weak_ordering v) noexcept {
return 0 == v.value_;
}
friend constexpr bool operator!=(compare_internal::OnlyLiteralZero,
weak_ordering v) noexcept {
return 0 != v.value_;
}
friend constexpr bool operator<(compare_internal::OnlyLiteralZero,
weak_ordering v) noexcept {
return 0 < v.value_;
}
friend constexpr bool operator<=(compare_internal::OnlyLiteralZero,
weak_ordering v) noexcept {
return 0 <= v.value_;
}
friend constexpr bool operator>(compare_internal::OnlyLiteralZero,
weak_ordering v) noexcept {
return 0 > v.value_;
}
friend constexpr bool operator>=(compare_internal::OnlyLiteralZero,
weak_ordering v) noexcept {
return 0 >= v.value_;
}
friend constexpr bool operator==(weak_ordering v1,
weak_ordering v2) noexcept {
return v1.value_ == v2.value_;
}
friend constexpr bool operator!=(weak_ordering v1,
weak_ordering v2) noexcept {
return v1.value_ != v2.value_;
}
private:
compare_internal::value_type value_;
};
ABSL_COMPARE_INLINE_INIT(weak_ordering, less, compare_internal::ord::less);
ABSL_COMPARE_INLINE_INIT(weak_ordering, equivalent,
compare_internal::eq::equivalent);
ABSL_COMPARE_INLINE_INIT(weak_ordering, greater,
compare_internal::ord::greater);
class strong_ordering
: public compare_internal::strong_ordering_base<strong_ordering> {
explicit constexpr strong_ordering(compare_internal::eq v) noexcept
: value_(static_cast<compare_internal::value_type>(v)) {}
explicit constexpr strong_ordering(compare_internal::ord v) noexcept
: value_(static_cast<compare_internal::value_type>(v)) {}
friend struct compare_internal::strong_ordering_base<strong_ordering>;
public:
ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, less);
ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, equal);
ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, equivalent);
ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, greater);
// Conversions
constexpr operator partial_ordering() const noexcept { // NOLINT
return value_ == 0 ? partial_ordering::equivalent
: (value_ < 0 ? partial_ordering::less
: partial_ordering::greater);
}
constexpr operator weak_ordering() const noexcept { // NOLINT
return value_ == 0
? weak_ordering::equivalent
: (value_ < 0 ? weak_ordering::less : weak_ordering::greater);
}
// Comparisons
friend constexpr bool operator==(
strong_ordering v, compare_internal::OnlyLiteralZero) noexcept {
return v.value_ == 0;
}
friend constexpr bool operator!=(
strong_ordering v, compare_internal::OnlyLiteralZero) noexcept {
return v.value_ != 0;
}
friend constexpr bool operator<(
strong_ordering v, compare_internal::OnlyLiteralZero) noexcept {
return v.value_ < 0;
}
friend constexpr bool operator<=(
strong_ordering v, compare_internal::OnlyLiteralZero) noexcept {
return v.value_ <= 0;
}
friend constexpr bool operator>(
strong_ordering v, compare_internal::OnlyLiteralZero) noexcept {
return v.value_ > 0;
}
friend constexpr bool operator>=(
strong_ordering v, compare_internal::OnlyLiteralZero) noexcept {
return v.value_ >= 0;
}
friend constexpr bool operator==(compare_internal::OnlyLiteralZero,
strong_ordering v) noexcept {
return 0 == v.value_;
}
friend constexpr bool operator!=(compare_internal::OnlyLiteralZero,
strong_ordering v) noexcept {
return 0 != v.value_;
}
friend constexpr bool operator<(compare_internal::OnlyLiteralZero,
strong_ordering v) noexcept {
return 0 < v.value_;
}
friend constexpr bool operator<=(compare_internal::OnlyLiteralZero,
strong_ordering v) noexcept {
return 0 <= v.value_;
}
friend constexpr bool operator>(compare_internal::OnlyLiteralZero,
strong_ordering v) noexcept {
return 0 > v.value_;
}
friend constexpr bool operator>=(compare_internal::OnlyLiteralZero,
strong_ordering v) noexcept {
return 0 >= v.value_;
}
friend constexpr bool operator==(strong_ordering v1,
strong_ordering v2) noexcept {
return v1.value_ == v2.value_;
}
friend constexpr bool operator!=(strong_ordering v1,
strong_ordering v2) noexcept {
return v1.value_ != v2.value_;
}
private:
compare_internal::value_type value_;
};
ABSL_COMPARE_INLINE_INIT(strong_ordering, less, compare_internal::ord::less);
ABSL_COMPARE_INLINE_INIT(strong_ordering, equal, compare_internal::eq::equal);
ABSL_COMPARE_INLINE_INIT(strong_ordering, equivalent,
compare_internal::eq::equivalent);
ABSL_COMPARE_INLINE_INIT(strong_ordering, greater,
compare_internal::ord::greater);
#undef ABSL_COMPARE_INLINE_BASECLASS_DECL
#undef ABSL_COMPARE_INLINE_SUBCLASS_DECL
#undef ABSL_COMPARE_INLINE_INIT
#endif // ABSL_USES_STD_ORDERING
namespace compare_internal {
// We also provide these comparator adapter functions for internal absl use.
// Helper functions to do a boolean comparison of two keys given a boolean
// or three-way comparator.
// SFINAE prevents implicit conversions to bool (such as from int).
template <typename BoolT,
absl::enable_if_t<std::is_same<bool, BoolT>::value, int> = 0>
constexpr bool compare_result_as_less_than(const BoolT r) { return r; }
constexpr bool compare_result_as_less_than(const absl::weak_ordering r) {
return r < 0;
}
template <typename Compare, typename K, typename LK>
constexpr bool do_less_than_comparison(const Compare &compare, const K &x,
const LK &y) {
return compare_result_as_less_than(compare(x, y));
}
// Helper functions to do a three-way comparison of two keys given a boolean or
// three-way comparator.
// SFINAE prevents implicit conversions to int (such as from bool).
template <typename Int,
absl::enable_if_t<std::is_same<int, Int>::value, int> = 0>
constexpr absl::weak_ordering compare_result_as_ordering(const Int c) {
return c < 0 ? absl::weak_ordering::less
: c == 0 ? absl::weak_ordering::equivalent
: absl::weak_ordering::greater;
}
constexpr absl::weak_ordering compare_result_as_ordering(
const absl::weak_ordering c) {
return c;
}
template <
typename Compare, typename K, typename LK,
absl::enable_if_t<!std::is_same<bool, absl::result_of_t<Compare(
const K &, const LK &)>>::value,
int> = 0>
constexpr absl::weak_ordering do_three_way_comparison(const Compare &compare,
const K &x, const LK &y) {
return compare_result_as_ordering(compare(x, y));
}
template <
typename Compare, typename K, typename LK,
absl::enable_if_t<std::is_same<bool, absl::result_of_t<Compare(
const K &, const LK &)>>::value,
int> = 0>
constexpr absl::weak_ordering do_three_way_comparison(const Compare &compare,
const K &x, const LK &y) {
return compare(x, y) ? absl::weak_ordering::less
: compare(y, x) ? absl::weak_ordering::greater
: absl::weak_ordering::equivalent;
}
} // namespace compare_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_TYPES_COMPARE_H_
*”C
†soong/.intermediates/external/abseil-cpp/absl_crc_crc_internal_hdrs/gen/my_include_dir/absl/crc/internal/crc32_x86_arm_combined_simd.hˆB// Copyright 2022 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_CRC_INTERNAL_CRC32_X86_ARM_COMBINED_SIMD_H_
#define ABSL_CRC_INTERNAL_CRC32_X86_ARM_COMBINED_SIMD_H_
#include <cstdint>
#include "absl/base/config.h"
// -------------------------------------------------------------------------
// Many x86 and ARM machines have CRC acceleration hardware.
// We can do a faster version of Extend() on such machines.
// We define a translation layer for both x86 and ARM for the ease of use and
// most performance gains.
// This implementation requires 64-bit CRC instructions (part of SSE 4.2) and
// PCLMULQDQ instructions. 32-bit builds with SSE 4.2 do exist, so the
// __x86_64__ condition is necessary.
#if defined(__x86_64__) && defined(__SSE4_2__) && defined(__PCLMUL__)
#include <x86intrin.h>
#define ABSL_CRC_INTERNAL_HAVE_X86_SIMD
#elif defined(_MSC_VER) && !defined(__clang__) && defined(__AVX__) && \
defined(_M_AMD64)
// MSVC AVX (/arch:AVX) implies SSE 4.2 and PCLMULQDQ.
#include <intrin.h>
#define ABSL_CRC_INTERNAL_HAVE_X86_SIMD
#elif defined(__aarch64__) && defined(__LITTLE_ENDIAN__) && \
defined(__ARM_FEATURE_CRC32) && defined(ABSL_INTERNAL_HAVE_ARM_NEON) && \
defined(__ARM_FEATURE_CRYPTO)
#include <arm_acle.h>
#include <arm_neon.h>
#define ABSL_CRC_INTERNAL_HAVE_ARM_SIMD
#endif
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace crc_internal {
#if defined(ABSL_CRC_INTERNAL_HAVE_ARM_SIMD) || \
defined(ABSL_CRC_INTERNAL_HAVE_X86_SIMD)
#if defined(ABSL_CRC_INTERNAL_HAVE_ARM_SIMD)
using V128 = uint64x2_t;
#else
// Note: Do not use __m128i_u, it is not portable.
// Use V128_LoadU() perform an unaligned load from __m128i*.
using V128 = __m128i;
#endif
// Starting with the initial value in |crc|, accumulates a CRC32 value for
// unsigned integers of different sizes.
uint32_t CRC32_u8(uint32_t crc, uint8_t v);
uint32_t CRC32_u16(uint32_t crc, uint16_t v);
uint32_t CRC32_u32(uint32_t crc, uint32_t v);
uint32_t CRC32_u64(uint32_t crc, uint64_t v);
// Loads 128 bits of integer data. |src| must be 16-byte aligned.
V128 V128_Load(const V128* src);
// Load 128 bits of integer data. |src| does not need to be aligned.
V128 V128_LoadU(const V128* src);
// Store 128 bits of integer data. |src| must be 16-byte aligned.
void V128_Store(V128* dst, V128 data);
// Polynomially multiplies the high 64 bits of |l| and |r|.
V128 V128_PMulHi(const V128 l, const V128 r);
// Polynomially multiplies the low 64 bits of |l| and |r|.
V128 V128_PMulLow(const V128 l, const V128 r);
// Polynomially multiplies the low 64 bits of |r| and high 64 bits of |l|.
V128 V128_PMul01(const V128 l, const V128 r);
// Polynomially multiplies the low 64 bits of |l| and high 64 bits of |r|.
V128 V128_PMul10(const V128 l, const V128 r);
// Produces a XOR operation of |l| and |r|.
V128 V128_Xor(const V128 l, const V128 r);
// Sets the lower half of a 128 bit register to the given 64-bit value and
// zeroes the upper half.
// dst[63:0] := |r|
// dst[127:64] := |0|
V128 V128_From64WithZeroFill(const uint64_t r);
// Extracts a 32-bit integer from |l|, selected with |imm|.
template <int imm>
int V128_Extract32(const V128 l);
// Extracts a 64-bit integer from |l|, selected with |imm|.
template <int imm>
uint64_t V128_Extract64(const V128 l);
// Extracts the low 64 bits from V128.
int64_t V128_Low64(const V128 l);
// Add packed 64-bit integers in |l| and |r|.
V128 V128_Add64(const V128 l, const V128 r);
#endif
#if defined(ABSL_CRC_INTERNAL_HAVE_X86_SIMD)
inline uint32_t CRC32_u8(uint32_t crc, uint8_t v) {
return _mm_crc32_u8(crc, v);
}
inline uint32_t CRC32_u16(uint32_t crc, uint16_t v) {
return _mm_crc32_u16(crc, v);
}
inline uint32_t CRC32_u32(uint32_t crc, uint32_t v) {
return _mm_crc32_u32(crc, v);
}
inline uint32_t CRC32_u64(uint32_t crc, uint64_t v) {
return static_cast<uint32_t>(_mm_crc32_u64(crc, v));
}
inline V128 V128_Load(const V128* src) { return _mm_load_si128(src); }
inline V128 V128_LoadU(const V128* src) { return _mm_loadu_si128(src); }
inline void V128_Store(V128* dst, V128 data) { _mm_store_si128(dst, data); }
inline V128 V128_PMulHi(const V128 l, const V128 r) {
return _mm_clmulepi64_si128(l, r, 0x11);
}
inline V128 V128_PMulLow(const V128 l, const V128 r) {
return _mm_clmulepi64_si128(l, r, 0x00);
}
inline V128 V128_PMul01(const V128 l, const V128 r) {
return _mm_clmulepi64_si128(l, r, 0x01);
}
inline V128 V128_PMul10(const V128 l, const V128 r) {
return _mm_clmulepi64_si128(l, r, 0x10);
}
inline V128 V128_Xor(const V128 l, const V128 r) { return _mm_xor_si128(l, r); }
inline V128 V128_From64WithZeroFill(const uint64_t r) {
return _mm_set_epi64x(static_cast<int64_t>(0), static_cast<int64_t>(r));
}
template <int imm>
inline int V128_Extract32(const V128 l) {
return _mm_extract_epi32(l, imm);
}
template <int imm>
inline uint64_t V128_Extract64(const V128 l) {
return static_cast<uint64_t>(_mm_extract_epi64(l, imm));
}
inline int64_t V128_Low64(const V128 l) { return _mm_cvtsi128_si64(l); }
inline V128 V128_Add64(const V128 l, const V128 r) {
return _mm_add_epi64(l, r);
}
#elif defined(ABSL_CRC_INTERNAL_HAVE_ARM_SIMD)
inline uint32_t CRC32_u8(uint32_t crc, uint8_t v) { return __crc32cb(crc, v); }
inline uint32_t CRC32_u16(uint32_t crc, uint16_t v) {
return __crc32ch(crc, v);
}
inline uint32_t CRC32_u32(uint32_t crc, uint32_t v) {
return __crc32cw(crc, v);
}
inline uint32_t CRC32_u64(uint32_t crc, uint64_t v) {
return __crc32cd(crc, v);
}
inline V128 V128_Load(const V128* src) {
return vld1q_u64(reinterpret_cast<const uint64_t*>(src));
}
inline V128 V128_LoadU(const V128* src) {
return vld1q_u64(reinterpret_cast<const uint64_t*>(src));
}
inline void V128_Store(V128* dst, V128 data) {
vst1q_u64(reinterpret_cast<uint64_t*>(dst), data);
}
// Using inline assembly as clang does not generate the pmull2 instruction and
// performance drops by 15-20%.
// TODO(b/193678732): Investigate why there is a slight performance hit when
// using intrinsics instead of inline assembly.
inline V128 V128_PMulHi(const V128 l, const V128 r) {
uint64x2_t res;
__asm__ __volatile__("pmull2 %0.1q, %1.2d, %2.2d \n\t"
: "=w"(res)
: "w"(l), "w"(r));
return res;
}
// TODO(b/193678732): Investigate why the compiler decides to move the constant
// loop multiplicands from GPR to Neon registers every loop iteration.
inline V128 V128_PMulLow(const V128 l, const V128 r) {
uint64x2_t res;
__asm__ __volatile__("pmull %0.1q, %1.1d, %2.1d \n\t"
: "=w"(res)
: "w"(l), "w"(r));
return res;
}
inline V128 V128_PMul01(const V128 l, const V128 r) {
return reinterpret_cast<V128>(vmull_p64(
reinterpret_cast<poly64_t>(vget_high_p64(vreinterpretq_p64_u64(l))),
reinterpret_cast<poly64_t>(vget_low_p64(vreinterpretq_p64_u64(r)))));
}
inline V128 V128_PMul10(const V128 l, const V128 r) {
return reinterpret_cast<V128>(vmull_p64(
reinterpret_cast<poly64_t>(vget_low_p64(vreinterpretq_p64_u64(l))),
reinterpret_cast<poly64_t>(vget_high_p64(vreinterpretq_p64_u64(r)))));
}
inline V128 V128_Xor(const V128 l, const V128 r) { return veorq_u64(l, r); }
inline V128 V128_From64WithZeroFill(const uint64_t r){
constexpr uint64x2_t kZero = {0, 0};
return vsetq_lane_u64(r, kZero, 0);
}
template <int imm>
inline int V128_Extract32(const V128 l) {
return vgetq_lane_s32(vreinterpretq_s32_u64(l), imm);
}
template <int imm>
inline uint64_t V128_Extract64(const V128 l) {
return vgetq_lane_u64(l, imm);
}
inline int64_t V128_Low64(const V128 l) {
return vgetq_lane_s64(vreinterpretq_s64_u64(l), 0);
}
inline V128 V128_Add64(const V128 l, const V128 r) { return vaddq_u64(l, r); }
#endif
} // namespace crc_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_CRC_INTERNAL_CRC32_X86_ARM_COMBINED_SIMD_H_
*³
rsoong/.intermediates/external/abseil-cpp/absl_crc_crc32c_hdrs/gen/my_include_dir/absl/crc/internal/crc32c_inline.h¼// Copyright 2022 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_CRC_INTERNAL_CRC32C_INLINE_H_
#define ABSL_CRC_INTERNAL_CRC32C_INLINE_H_
#include <cstdint>
#include "absl/base/config.h"
#include "absl/base/internal/endian.h"
#include "absl/crc/internal/crc32_x86_arm_combined_simd.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace crc_internal {
// CRC32C implementation optimized for small inputs.
// Either computes crc and return true, or if there is
// no hardware support does nothing and returns false.
inline bool ExtendCrc32cInline(uint32_t* crc, const char* p, size_t n) {
#if defined(ABSL_CRC_INTERNAL_HAVE_ARM_SIMD) || \
defined(ABSL_CRC_INTERNAL_HAVE_X86_SIMD)
constexpr uint32_t kCrc32Xor = 0xffffffffU;
*crc ^= kCrc32Xor;
if (n & 1) {
*crc = CRC32_u8(*crc, static_cast<uint8_t>(*p));
n--;
p++;
}
if (n & 2) {
*crc = CRC32_u16(*crc, absl::little_endian::Load16(p));
n -= 2;
p += 2;
}
if (n & 4) {
*crc = CRC32_u32(*crc, absl::little_endian::Load32(p));
n -= 4;
p += 4;
}
while (n) {
*crc = CRC32_u64(*crc, absl::little_endian::Load64(p));
n -= 8;
p += 8;
}
*crc ^= kCrc32Xor;
return true;
#else
// No hardware support, signal the need to fallback.
static_cast<void>(crc);
static_cast<void>(p);
static_cast<void>(n);
return false;
#endif // defined(ABSL_CRC_INTERNAL_HAVE_ARM_SIMD) ||
// defined(ABSL_CRC_INTERNAL_HAVE_X86_SIMD)
}
} // namespace crc_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_CRC_INTERNAL_CRC32C_INLINE_H_
*ô9
bsoong/.intermediates/external/abseil-cpp/absl_crc_crc32c_hdrs/gen/my_include_dir/absl/crc/crc32c.h9// Copyright 2022 The Abseil Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: crc32c.h
// -----------------------------------------------------------------------------
//
// This header file defines the API for computing CRC32C values as checksums
// for arbitrary sequences of bytes provided as a string buffer.
//
// The API includes the basic functions for computing such CRC32C values and
// some utility functions for performing more efficient mathematical
// computations using an existing checksum.
#ifndef ABSL_CRC_CRC32C_H_
#define ABSL_CRC_CRC32C_H_
#include <cstdint>
#include <ostream>
#include "absl/crc/internal/crc32c_inline.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
//-----------------------------------------------------------------------------
// crc32c_t
//-----------------------------------------------------------------------------
// `crc32c_t` defines a strongly-typed integer for holding a CRC32C value.
//
// Some operators are intentionally omitted. Only equality operators are defined
// so that `crc32c_t` can be directly compared. Methods for putting `crc32c_t`
// directly into a set are omitted because this is bug-prone due to checksum
// collisions. Use an explicit conversion to the `uint32_t` space for operations
// that treat `crc32c_t` as an integer.
class crc32c_t final {
public:
crc32c_t() = default;
constexpr explicit crc32c_t(uint32_t crc) : crc_(crc) {}
crc32c_t(const crc32c_t&) = default;
crc32c_t& operator=(const crc32c_t&) = default;
explicit operator uint32_t() const { return crc_; }
friend bool operator==(crc32c_t lhs, crc32c_t rhs) {
return static_cast<uint32_t>(lhs) == static_cast<uint32_t>(rhs);
}
friend bool operator!=(crc32c_t lhs, crc32c_t rhs) { return !(lhs == rhs); }
template <typename Sink>
friend void AbslStringify(Sink& sink, crc32c_t crc) {
absl::Format(&sink, "%08x", static_cast<uint32_t>(crc));
}
private:
uint32_t crc_;
};
namespace crc_internal {
// Non-inline code path for `absl::ExtendCrc32c()`. Do not call directly.
// Call `absl::ExtendCrc32c()` (defined below) instead.
crc32c_t ExtendCrc32cInternal(crc32c_t initial_crc,
absl::string_view buf_to_add);
} // namespace crc_internal
// -----------------------------------------------------------------------------
// CRC32C Computation Functions
// -----------------------------------------------------------------------------
// ExtendCrc32c()
//
// Computes a CRC32C value from an `initial_crc` CRC32C value including the
// `buf_to_add` bytes of an additional buffer. Using this function is more
// efficient than computing a CRC32C value for the combined buffer from
// scratch.
//
// Note: `ExtendCrc32c` with an initial_crc of 0 is equivalent to
// `ComputeCrc32c`.
//
// This operation has a runtime cost of O(`buf_to_add.size()`)
inline crc32c_t ExtendCrc32c(crc32c_t initial_crc,
absl::string_view buf_to_add) {
// Approximately 75% of calls have size <= 64.
if (buf_to_add.size() <= 64) {
uint32_t crc = static_cast<uint32_t>(initial_crc);
if (crc_internal::ExtendCrc32cInline(&crc, buf_to_add.data(),
buf_to_add.size())) {
return crc32c_t{crc};
}
}
return crc_internal::ExtendCrc32cInternal(initial_crc, buf_to_add);
}
// ComputeCrc32c()
//
// Returns the CRC32C value of the provided string.
inline crc32c_t ComputeCrc32c(absl::string_view buf) {
return ExtendCrc32c(crc32c_t{0}, buf);
}
// ExtendCrc32cByZeroes()
//
// Computes a CRC32C value for a buffer with an `initial_crc` CRC32C value,
// where `length` bytes with a value of 0 are appended to the buffer. Using this
// function is more efficient than computing a CRC32C value for the combined
// buffer from scratch.
//
// This operation has a runtime cost of O(log(`length`))
crc32c_t ExtendCrc32cByZeroes(crc32c_t initial_crc, size_t length);
// MemcpyCrc32c()
//
// Copies `src` to `dest` using `memcpy()` semantics, returning the CRC32C
// value of the copied buffer.
//
// Using `MemcpyCrc32c()` is potentially faster than performing the `memcpy()`
// and `ComputeCrc32c()` operations separately.
crc32c_t MemcpyCrc32c(void* dest, const void* src, size_t count,
crc32c_t initial_crc = crc32c_t{0});
// -----------------------------------------------------------------------------
// CRC32C Arithmetic Functions
// -----------------------------------------------------------------------------
// The following functions perform arithmetic on CRC32C values, which are
// generally more efficient than recalculating any given result's CRC32C value.
// ConcatCrc32c()
//
// Calculates the CRC32C value of two buffers with known CRC32C values
// concatenated together.
//
// Given a buffer with CRC32C value `crc1` and a buffer with
// CRC32C value `crc2` and length, `crc2_length`, returns the CRC32C value of
// the concatenation of these two buffers.
//
// This operation has a runtime cost of O(log(`crc2_length`)).
crc32c_t ConcatCrc32c(crc32c_t crc1, crc32c_t crc2, size_t crc2_length);
// RemoveCrc32cPrefix()
//
// Calculates the CRC32C value of an existing buffer with a series of bytes
// (the prefix) removed from the beginning of that buffer.
//
// Given the CRC32C value of an existing buffer, `full_string_crc`; The CRC32C
// value of a prefix of that buffer, `prefix_crc`; and the length of the buffer
// with the prefix removed, `remaining_string_length` , return the CRC32C
// value of the buffer with the prefix removed.
//
// This operation has a runtime cost of O(log(`remaining_string_length`)).
crc32c_t RemoveCrc32cPrefix(crc32c_t prefix_crc, crc32c_t full_string_crc,
size_t remaining_string_length);
// RemoveCrc32cSuffix()
//
// Calculates the CRC32C value of an existing buffer with a series of bytes
// (the suffix) removed from the end of that buffer.
//
// Given a CRC32C value of an existing buffer `full_string_crc`, the CRC32C
// value of the suffix to remove `suffix_crc`, and the length of that suffix
// `suffix_len`, returns the CRC32C value of the buffer with suffix removed.
//
// This operation has a runtime cost of O(log(`suffix_len`))
crc32c_t RemoveCrc32cSuffix(crc32c_t full_string_crc, crc32c_t suffix_crc,
size_t suffix_length);
// operator<<
//
// Streams the CRC32C value `crc` to the stream `os`.
inline std::ostream& operator<<(std::ostream& os, crc32c_t crc) {
return os << absl::StreamFormat("%08x", static_cast<uint32_t>(crc));
}
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_CRC_CRC32C_H_
*ñ.
{soong/.intermediates/external/abseil-cpp/absl_crc_crc_cord_state_hdrs/gen/my_include_dir/absl/crc/internal/crc_cord_state.hñ-// Copyright 2022 The Abseil Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_CRC_INTERNAL_CRC_CORD_STATE_H_
#define ABSL_CRC_INTERNAL_CRC_CORD_STATE_H_
#include <atomic>
#include <cstddef>
#include <deque>
#include "absl/base/config.h"
#include "absl/crc/crc32c.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace crc_internal {
// CrcCordState is a copy-on-write class that holds the chunked CRC32C data
// that allows CrcCord to perform efficient substring operations. CrcCordState
// is used as a member variable in CrcCord. When a CrcCord is converted to a
// Cord, the CrcCordState is shallow-copied into the root node of the Cord. If
// the converted Cord is modified outside of CrcCord, the CrcCordState is
// discarded from the Cord. If the Cord is converted back to a CrcCord, and the
// Cord is still carrying the CrcCordState in its root node, the CrcCord can
// re-use the CrcCordState, making the construction of the CrcCord cheap.
//
// CrcCordState does not try to encapsulate the CRC32C state (CrcCord requires
// knowledge of how CrcCordState represents the CRC32C state). It does
// encapsulate the copy-on-write nature of the state.
class CrcCordState {
public:
// Constructors.
CrcCordState();
CrcCordState(const CrcCordState&);
CrcCordState(CrcCordState&&);
// Destructor. Atomically unreferences the data.
~CrcCordState();
// Copy and move operators.
CrcCordState& operator=(const CrcCordState&);
CrcCordState& operator=(CrcCordState&&);
// A (length, crc) pair.
struct PrefixCrc {
PrefixCrc() = default;
PrefixCrc(size_t length_arg, absl::crc32c_t crc_arg)
: length(length_arg), crc(crc_arg) {}
size_t length = 0;
// TODO(absl-team): Memory stomping often zeros out memory. If this struct
// gets overwritten, we could end up with {0, 0}, which is the correct CRC
// for a string of length 0. Consider storing a scrambled value and
// unscrambling it before verifying it.
absl::crc32c_t crc = absl::crc32c_t{0};
};
// The representation of the chunked CRC32C data.
struct Rep {
// `removed_prefix` is the crc and length of any prefix that has been
// removed from the Cord (for example, by calling
// `CrcCord::RemovePrefix()`). To get the checksum of any prefix of the
// cord, this value must be subtracted from `prefix_crc`. See `Checksum()`
// for an example.
//
// CrcCordState is said to be "normalized" if removed_prefix.length == 0.
PrefixCrc removed_prefix;
// A deque of (length, crc) pairs, representing length and crc of a prefix
// of the Cord, before removed_prefix has been subtracted. The lengths of
// the prefixes are stored in increasing order. If the Cord is not empty,
// the last value in deque is the contains the CRC32C of the entire Cord
// when removed_prefix is subtracted from it.
std::deque<PrefixCrc> prefix_crc;
};
// Returns a reference to the representation of the chunked CRC32C data.
const Rep& rep() const { return refcounted_rep_->rep; }
// Returns a mutable reference to the representation of the chunked CRC32C
// data. Calling this function will copy the data if another instance also
// holds a reference to the data, so it is important to call rep() instead if
// the data may not be mutated.
Rep* mutable_rep() {
if (refcounted_rep_->count.load(std::memory_order_acquire) != 1) {
RefcountedRep* copy = new RefcountedRep;
copy->rep = refcounted_rep_->rep;
Unref(refcounted_rep_);
refcounted_rep_ = copy;
}
return &refcounted_rep_->rep;
}
// Returns the CRC32C of the entire Cord.
absl::crc32c_t Checksum() const;
// Returns true if the chunked CRC32C cached is normalized.
bool IsNormalized() const { return rep().removed_prefix.length == 0; }
// Normalizes the chunked CRC32C checksum cache by subtracting any removed
// prefix from the chunks.
void Normalize();
// Returns the number of cached chunks.
size_t NumChunks() const { return rep().prefix_crc.size(); }
// Helper that returns the (length, crc) of the `n`-th cached chunked.
PrefixCrc NormalizedPrefixCrcAtNthChunk(size_t n) const;
// Poisons all chunks to so that Checksum() will likely be incorrect with high
// probability.
void Poison();
private:
struct RefcountedRep {
std::atomic<int32_t> count{1};
Rep rep;
};
// Adds a reference to the shared global empty `RefcountedRep`, and returns a
// pointer to the `RefcountedRep`. This is an optimization to avoid unneeded
// allocations when the allocation is unlikely to ever be used. The returned
// pointer can be `Unref()`ed when it is no longer needed. Since the returned
// instance will always have a reference counter greater than 1, attempts to
// modify it (by calling `mutable_rep()`) will create a new unshared copy.
static RefcountedRep* RefSharedEmptyRep();
static void Ref(RefcountedRep* r) {
assert(r != nullptr);
r->count.fetch_add(1, std::memory_order_relaxed);
}
static void Unref(RefcountedRep* r) {
assert(r != nullptr);
if (r->count.fetch_sub(1, std::memory_order_acq_rel) == 1) {
delete r;
}
}
RefcountedRep* refcounted_rep_;
};
} // namespace crc_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_CRC_INTERNAL_CRC_CORD_STATE_H_
*̂
fsoong/.intermediates/external/abseil-cpp/absl_strings_cord_hdrs/gen/my_include_dir/absl/strings/cord.hà// Copyright 2020 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: cord.h
// -----------------------------------------------------------------------------
//
// This file defines the `absl::Cord` data structure and operations on that data
// structure. A Cord is a string-like sequence of characters optimized for
// specific use cases. Unlike a `std::string`, which stores an array of
// contiguous characters, Cord data is stored in a structure consisting of
// separate, reference-counted "chunks."
//
// Because a Cord consists of these chunks, data can be added to or removed from
// a Cord during its lifetime. Chunks may also be shared between Cords. Unlike a
// `std::string`, a Cord can therefore accommodate data that changes over its
// lifetime, though it's not quite "mutable"; it can change only in the
// attachment, detachment, or rearrangement of chunks of its constituent data.
//
// A Cord provides some benefit over `std::string` under the following (albeit
// narrow) circumstances:
//
// * Cord data is designed to grow and shrink over a Cord's lifetime. Cord
// provides efficient insertions and deletions at the start and end of the
// character sequences, avoiding copies in those cases. Static data should
// generally be stored as strings.
// * External memory consisting of string-like data can be directly added to
// a Cord without requiring copies or allocations.
// * Cord data may be shared and copied cheaply. Cord provides a copy-on-write
// implementation and cheap sub-Cord operations. Copying a Cord is an O(1)
// operation.
//
// As a consequence to the above, Cord data is generally large. Small data
// should generally use strings, as construction of a Cord requires some
// overhead. Small Cords (<= 15 bytes) are represented inline, but most small
// Cords are expected to grow over their lifetimes.
//
// Note that because a Cord is made up of separate chunked data, random access
// to character data within a Cord is slower than within a `std::string`.
//
// Thread Safety
//
// Cord has the same thread-safety properties as many other types like
// std::string, std::vector<>, int, etc -- it is thread-compatible. In
// particular, if threads do not call non-const methods, then it is safe to call
// const methods without synchronization. Copying a Cord produces a new instance
// that can be used concurrently with the original in arbitrary ways.
#ifndef ABSL_STRINGS_CORD_H_
#define ABSL_STRINGS_CORD_H_
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <iosfwd>
#include <iterator>
#include <string>
#include <type_traits>
#include <utility>
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/internal/endian.h"
#include "absl/base/macros.h"
#include "absl/base/nullability.h"
#include "absl/base/optimization.h"
#include "absl/crc/internal/crc_cord_state.h"
#include "absl/functional/function_ref.h"
#include "absl/hash/internal/weakly_mixed_integer.h"
#include "absl/meta/type_traits.h"
#include "absl/strings/cord_analysis.h"
#include "absl/strings/cord_buffer.h"
#include "absl/strings/internal/cord_data_edge.h"
#include "absl/strings/internal/cord_internal.h"
#include "absl/strings/internal/cord_rep_btree.h"
#include "absl/strings/internal/cord_rep_btree_reader.h"
#include "absl/strings/internal/cord_rep_crc.h"
#include "absl/strings/internal/cord_rep_flat.h"
#include "absl/strings/internal/cordz_info.h"
#include "absl/strings/internal/cordz_update_scope.h"
#include "absl/strings/internal/cordz_update_tracker.h"
#include "absl/strings/internal/string_constant.h"
#include "absl/strings/string_view.h"
#include "absl/types/compare.h"
#include "absl/types/optional.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
class Cord;
class CordTestPeer;
template <typename Releaser>
Cord MakeCordFromExternal(absl::string_view, Releaser&&);
void CopyCordToString(const Cord& src, std::string* absl_nonnull dst);
void AppendCordToString(const Cord& src, std::string* absl_nonnull dst);
// Cord memory accounting modes
enum class CordMemoryAccounting {
// Counts the *approximate* number of bytes held in full or in part by this
// Cord (which may not remain the same between invocations). Cords that share
// memory could each be "charged" independently for the same shared memory.
// See also comment on `kTotalMorePrecise` on internally shared memory.
kTotal,
// Counts the *approximate* number of bytes held in full or in part by this
// Cord for the distinct memory held by this cord. This option is similar
// to `kTotal`, except that if the cord has multiple references to the same
// memory, that memory is only counted once.
//
// For example:
// absl::Cord cord;
// cord.Append(some_other_cord);
// cord.Append(some_other_cord);
// // Counts `some_other_cord` twice:
// cord.EstimatedMemoryUsage(kTotal);
// // Counts `some_other_cord` once:
// cord.EstimatedMemoryUsage(kTotalMorePrecise);
//
// The `kTotalMorePrecise` number is more expensive to compute as it requires
// deduplicating all memory references. Applications should prefer to use
// `kFairShare` or `kTotal` unless they really need a more precise estimate
// on "how much memory is potentially held / kept alive by this cord?"
kTotalMorePrecise,
// Counts the *approximate* number of bytes held in full or in part by this
// Cord weighted by the sharing ratio of that data. For example, if some data
// edge is shared by 4 different Cords, then each cord is attributed 1/4th of
// the total memory usage as a 'fair share' of the total memory usage.
kFairShare,
};
// Cord
//
// A Cord is a sequence of characters, designed to be more efficient than a
// `std::string` in certain circumstances: namely, large string data that needs
// to change over its lifetime or shared, especially when such data is shared
// across API boundaries.
//
// A Cord stores its character data in a structure that allows efficient prepend
// and append operations. This makes a Cord useful for large string data sent
// over in a wire format that may need to be prepended or appended at some point
// during the data exchange (e.g. HTTP, protocol buffers). For example, a
// Cord is useful for storing an HTTP request, and prepending an HTTP header to
// such a request.
//
// Cords should not be used for storing general string data, however. They
// require overhead to construct and are slower than strings for random access.
//
// The Cord API provides the following common API operations:
//
// * Create or assign Cords out of existing string data, memory, or other Cords
// * Append and prepend data to an existing Cord
// * Create new Sub-Cords from existing Cord data
// * Swap Cord data and compare Cord equality
// * Write out Cord data by constructing a `std::string`
//
// Additionally, the API provides iterator utilities to iterate through Cord
// data via chunks or character bytes.
//
class Cord {
private:
template <typename T>
using EnableIfString =
absl::enable_if_t<std::is_same<T, std::string>::value, int>;
public:
// Cord::Cord() Constructors.
// Creates an empty Cord.
constexpr Cord() noexcept;
// Creates a Cord from an existing Cord. Cord is copyable and efficiently
// movable. The moved-from state is valid but unspecified.
Cord(const Cord& src);
Cord(Cord&& src) noexcept;
Cord& operator=(const Cord& x);
Cord& operator=(Cord&& x) noexcept;
// Creates a Cord from a `src` string. This constructor is marked explicit to
// prevent implicit Cord constructions from arguments convertible to an
// `absl::string_view`.
explicit Cord(absl::string_view src);
Cord& operator=(absl::string_view src);
// Creates a Cord from a `std::string&&` rvalue. These constructors are
// templated to avoid ambiguities for types that are convertible to both
// `absl::string_view` and `std::string`, such as `const char*`.
template <typename T, EnableIfString<T> = 0>
explicit Cord(T&& src);
template <typename T, EnableIfString<T> = 0>
Cord& operator=(T&& src);
// Cord::~Cord()
//
// Destructs the Cord.
~Cord() {
if (contents_.is_tree()) DestroyCordSlow();
}
// MakeCordFromExternal()
//
// Creates a Cord that takes ownership of external string memory. The
// contents of `data` are not copied to the Cord; instead, the external
// memory is added to the Cord and reference-counted. This data may not be
// changed for the life of the Cord, though it may be prepended or appended
// to.
//
// `MakeCordFromExternal()` takes a callable "releaser" that is invoked when
// the reference count for `data` reaches zero. As noted above, this data must
// remain live until the releaser is invoked. The callable releaser also must:
//
// * be move constructible
// * support `void operator()(absl::string_view) const` or `void operator()`
//
// Example:
//
// Cord MakeCord(BlockPool* pool) {
// Block* block = pool->NewBlock();
// FillBlock(block);
// return absl::MakeCordFromExternal(
// block->ToStringView(),
// [pool, block](absl::string_view v) {
// pool->FreeBlock(block, v);
// });
// }
//
// WARNING: Because a Cord can be reference-counted, it's likely a bug if your
// releaser doesn't do anything. For example, consider the following:
//
// void Foo(const char* buffer, int len) {
// auto c = absl::MakeCordFromExternal(absl::string_view(buffer, len),
// [](absl::string_view) {});
//
// // BUG: If Bar() copies its cord for any reason, including keeping a
// // substring of it, the lifetime of buffer might be extended beyond
// // when Foo() returns.
// Bar(c);
// }
template <typename Releaser>
friend Cord MakeCordFromExternal(absl::string_view data, Releaser&& releaser);
// Cord::Clear()
//
// Releases the Cord data. Any nodes that share data with other Cords, if
// applicable, will have their reference counts reduced by 1.
ABSL_ATTRIBUTE_REINITIALIZES void Clear();
// Cord::Append()
//
// Appends data to the Cord, which may come from another Cord or other string
// data.
void Append(const Cord& src);
void Append(Cord&& src);
void Append(absl::string_view src);
template <typename T, EnableIfString<T> = 0>
void Append(T&& src);
// Appends `buffer` to this cord, unless `buffer` has a zero length in which
// case this method has no effect on this cord instance.
// This method is guaranteed to consume `buffer`.
void Append(CordBuffer buffer);
// Returns a CordBuffer, re-using potential existing capacity in this cord.
//
// Cord instances may have additional unused capacity in the last (or first)
// nodes of the underlying tree to facilitate amortized growth. This method
// allows applications to explicitly use this spare capacity if available,
// or create a new CordBuffer instance otherwise.
// If this cord has a final non-shared node with at least `min_capacity`
// available, then this method will return that buffer including its data
// contents. I.e.; the returned buffer will have a non-zero length, and
// a capacity of at least `buffer.length + min_capacity`. Otherwise, this
// method will return `CordBuffer::CreateWithDefaultLimit(capacity)`.
//
// Below an example of using GetAppendBuffer. Notice that in this example we
// use `GetAppendBuffer()` only on the first iteration. As we know nothing
// about any initial extra capacity in `cord`, we may be able to use the extra
// capacity. But as we add new buffers with fully utilized contents after that
// we avoid calling `GetAppendBuffer()` on subsequent iterations: while this
// works fine, it results in an unnecessary inspection of cord contents:
//
// void AppendRandomDataToCord(absl::Cord &cord, size_t n) {
// bool first = true;
// while (n > 0) {
// CordBuffer buffer = first ? cord.GetAppendBuffer(n)
// : CordBuffer::CreateWithDefaultLimit(n);
// absl::Span<char> data = buffer.available_up_to(n);
// FillRandomValues(data.data(), data.size());
// buffer.IncreaseLengthBy(data.size());
// cord.Append(std::move(buffer));
// n -= data.size();
// first = false;
// }
// }
CordBuffer GetAppendBuffer(size_t capacity, size_t min_capacity = 16);
// Returns a CordBuffer, re-using potential existing capacity in this cord.
//
// This function is identical to `GetAppendBuffer`, except that in the case
// where a new `CordBuffer` is allocated, it is allocated using the provided
// custom limit instead of the default limit. `GetAppendBuffer` will default
// to `CordBuffer::CreateWithDefaultLimit(capacity)` whereas this method
// will default to `CordBuffer::CreateWithCustomLimit(block_size, capacity)`.
// This method is equivalent to `GetAppendBuffer` if `block_size` is zero.
// See the documentation for `CreateWithCustomLimit` for more details on the
// restrictions and legal values for `block_size`.
CordBuffer GetCustomAppendBuffer(size_t block_size, size_t capacity,
size_t min_capacity = 16);
// Cord::Prepend()
//
// Prepends data to the Cord, which may come from another Cord or other string
// data.
void Prepend(const Cord& src);
void Prepend(absl::string_view src);
template <typename T, EnableIfString<T> = 0>
void Prepend(T&& src);
// Prepends `buffer` to this cord, unless `buffer` has a zero length in which
// case this method has no effect on this cord instance.
// This method is guaranteed to consume `buffer`.
void Prepend(CordBuffer buffer);
// Cord::RemovePrefix()
//
// Removes the first `n` bytes of a Cord.
void RemovePrefix(size_t n);
void RemoveSuffix(size_t n);
// Cord::Subcord()
//
// Returns a new Cord representing the subrange [pos, pos + new_size) of
// *this. If pos >= size(), the result is empty(). If
// (pos + new_size) >= size(), the result is the subrange [pos, size()).
Cord Subcord(size_t pos, size_t new_size) const;
// Cord::swap()
//
// Swaps the contents of the Cord with `other`.
void swap(Cord& other) noexcept;
// swap()
//
// Swaps the contents of two Cords.
friend void swap(Cord& x, Cord& y) noexcept { x.swap(y); }
// Cord::size()
//
// Returns the size of the Cord.
size_t size() const;
// Cord::empty()
//
// Determines whether the given Cord is empty, returning `true` if so.
bool empty() const;
// Cord::EstimatedMemoryUsage()
//
// Returns the *approximate* number of bytes held by this cord.
// See CordMemoryAccounting for more information on the accounting method.
size_t EstimatedMemoryUsage(CordMemoryAccounting accounting_method =
CordMemoryAccounting::kTotal) const;
// Cord::Compare()
//
// Compares 'this' Cord with rhs. This function and its relatives treat Cords
// as sequences of unsigned bytes. The comparison is a straightforward
// lexicographic comparison. `Cord::Compare()` returns values as follows:
//
// -1 'this' Cord is smaller
// 0 two Cords are equal
// 1 'this' Cord is larger
int Compare(absl::string_view rhs) const;
int Compare(const Cord& rhs) const;
// Cord::StartsWith()
//
// Determines whether the Cord starts with the passed string data `rhs`.
bool StartsWith(const Cord& rhs) const;
bool StartsWith(absl::string_view rhs) const;
// Cord::EndsWith()
//
// Determines whether the Cord ends with the passed string data `rhs`.
bool EndsWith(absl::string_view rhs) const;
bool EndsWith(const Cord& rhs) const;
// Cord::Contains()
//
// Determines whether the Cord contains the passed string data `rhs`.
bool Contains(absl::string_view rhs) const;
bool Contains(const Cord& rhs) const;
// Cord::operator std::string()
//
// Converts a Cord into a `std::string()`. This operator is marked explicit to
// prevent unintended Cord usage in functions that take a string.
explicit operator std::string() const;
// CopyCordToString()
//
// Copies the contents of a `src` Cord into a `*dst` string.
//
// This function optimizes the case of reusing the destination string since it
// can reuse previously allocated capacity. However, this function does not
// guarantee that pointers previously returned by `dst->data()` remain valid
// even if `*dst` had enough capacity to hold `src`. If `*dst` is a new
// object, prefer to simply use the conversion operator to `std::string`.
friend void CopyCordToString(const Cord& src, std::string* absl_nonnull dst);
// AppendCordToString()
//
// Appends the contents of a `src` Cord to a `*dst` string.
//
// This function optimizes the case of appending to a non-empty destination
// string. If `*dst` already has capacity to store the contents of the cord,
// this function does not invalidate pointers previously returned by
// `dst->data()`. If `*dst` is a new object, prefer to simply use the
// conversion operator to `std::string`.
friend void AppendCordToString(const Cord& src,
std::string* absl_nonnull dst);
class CharIterator;
//----------------------------------------------------------------------------
// Cord::ChunkIterator
//----------------------------------------------------------------------------
//
// A `Cord::ChunkIterator` allows iteration over the constituent chunks of its
// Cord. Such iteration allows you to perform non-const operations on the data
// of a Cord without modifying it.
//
// Generally, you do not instantiate a `Cord::ChunkIterator` directly;
// instead, you create one implicitly through use of the `Cord::Chunks()`
// member function.
//
// The `Cord::ChunkIterator` has the following properties:
//
// * The iterator is invalidated after any non-const operation on the
// Cord object over which it iterates.
// * The `string_view` returned by dereferencing a valid, non-`end()`
// iterator is guaranteed to be non-empty.
// * Two `ChunkIterator` objects can be compared equal if and only if they
// remain valid and iterate over the same Cord.
// * The iterator in this case is a proxy iterator; the `string_view`
// returned by the iterator does not live inside the Cord, and its
// lifetime is limited to the lifetime of the iterator itself. To help
// prevent lifetime issues, `ChunkIterator::reference` is not a true
// reference type and is equivalent to `value_type`.
// * The iterator keeps state that can grow for Cords that contain many
// nodes and are imbalanced due to sharing. Prefer to pass this type by
// const reference instead of by value.
class ChunkIterator {
public:
using iterator_category = std::input_iterator_tag;
using value_type = absl::string_view;
using difference_type = ptrdiff_t;
using pointer = const value_type* absl_nonnull;
using reference = value_type;
ChunkIterator() = default;
ChunkIterator& operator++();
ChunkIterator operator++(int);
bool operator==(const ChunkIterator& other) const;
bool operator!=(const ChunkIterator& other) const;
reference operator*() const;
pointer operator->() const;
friend class Cord;
friend class CharIterator;
private:
using CordRep = absl::cord_internal::CordRep;
using CordRepBtree = absl::cord_internal::CordRepBtree;
using CordRepBtreeReader = absl::cord_internal::CordRepBtreeReader;
// Constructs a `begin()` iterator from `tree`.
explicit ChunkIterator(cord_internal::CordRep* absl_nonnull tree);
// Constructs a `begin()` iterator from `cord`.
explicit ChunkIterator(const Cord* absl_nonnull cord);
// Initializes this instance from a tree. Invoked by constructors.
void InitTree(cord_internal::CordRep* absl_nonnull tree);
// Removes `n` bytes from `current_chunk_`. Expects `n` to be smaller than
// `current_chunk_.size()`.
void RemoveChunkPrefix(size_t n);
Cord AdvanceAndReadBytes(size_t n);
void AdvanceBytes(size_t n);
// Btree specific operator++
ChunkIterator& AdvanceBtree();
void AdvanceBytesBtree(size_t n);
// A view into bytes of the current `CordRep`. It may only be a view to a
// suffix of bytes if this is being used by `CharIterator`.
absl::string_view current_chunk_;
// The current leaf, or `nullptr` if the iterator points to short data.
// If the current chunk is a substring node, current_leaf_ points to the
// underlying flat or external node.
absl::cord_internal::CordRep* absl_nullable current_leaf_ = nullptr;
// The number of bytes left in the `Cord` over which we are iterating.
size_t bytes_remaining_ = 0;
// Cord reader for cord btrees. Empty if not traversing a btree.
CordRepBtreeReader btree_reader_;
};
// Cord::chunk_begin()
//
// Returns an iterator to the first chunk of the `Cord`.
//
// Generally, prefer using `Cord::Chunks()` within a range-based for loop for
// iterating over the chunks of a Cord. This method may be useful for getting
// a `ChunkIterator` where range-based for-loops are not useful.
//
// Example:
//
// absl::Cord::ChunkIterator FindAsChunk(const absl::Cord& c,
// absl::string_view s) {
// return std::find(c.chunk_begin(), c.chunk_end(), s);
// }
ChunkIterator chunk_begin() const ABSL_ATTRIBUTE_LIFETIME_BOUND;
// Cord::chunk_end()
//
// Returns an iterator one increment past the last chunk of the `Cord`.
//
// Generally, prefer using `Cord::Chunks()` within a range-based for loop for
// iterating over the chunks of a Cord. This method may be useful for getting
// a `ChunkIterator` where range-based for-loops may not be available.
ChunkIterator chunk_end() const ABSL_ATTRIBUTE_LIFETIME_BOUND;
//----------------------------------------------------------------------------
// Cord::ChunkRange
//----------------------------------------------------------------------------
//
// `ChunkRange` is a helper class for iterating over the chunks of the `Cord`,
// producing an iterator which can be used within a range-based for loop.
// Construction of a `ChunkRange` will return an iterator pointing to the
// first chunk of the Cord. Generally, do not construct a `ChunkRange`
// directly; instead, prefer to use the `Cord::Chunks()` method.
//
// Implementation note: `ChunkRange` is simply a convenience wrapper over
// `Cord::chunk_begin()` and `Cord::chunk_end()`.
class ChunkRange {
public:
// Fulfill minimum c++ container requirements [container.requirements]
// These (partial) container type definitions allow ChunkRange to be used
// in various utilities expecting a subset of [container.requirements].
// For example, the below enables using `::testing::ElementsAre(...)`
using value_type = absl::string_view;
using reference = value_type&;
using const_reference = const value_type&;
using iterator = ChunkIterator;
using const_iterator = ChunkIterator;
explicit ChunkRange(const Cord* absl_nonnull cord) : cord_(cord) {}
ChunkIterator begin() const;
ChunkIterator end() const;
private:
const Cord* absl_nonnull cord_;
};
// Cord::Chunks()
//
// Returns a `Cord::ChunkRange` for iterating over the chunks of a `Cord` with
// a range-based for-loop. For most iteration tasks on a Cord, use
// `Cord::Chunks()` to retrieve this iterator.
//
// Example:
//
// void ProcessChunks(const Cord& cord) {
// for (absl::string_view chunk : cord.Chunks()) { ... }
// }
//
// Note that the ordinary caveats of temporary lifetime extension apply:
//
// void Process() {
// for (absl::string_view chunk : CordFactory().Chunks()) {
// // The temporary Cord returned by CordFactory has been destroyed!
// }
// }
ChunkRange Chunks() const ABSL_ATTRIBUTE_LIFETIME_BOUND;
//----------------------------------------------------------------------------
// Cord::CharIterator
//----------------------------------------------------------------------------
//
// A `Cord::CharIterator` allows iteration over the constituent characters of
// a `Cord`.
//
// Generally, you do not instantiate a `Cord::CharIterator` directly; instead,
// you create one implicitly through use of the `Cord::Chars()` member
// function.
//
// A `Cord::CharIterator` has the following properties:
//
// * The iterator is invalidated after any non-const operation on the
// Cord object over which it iterates.
// * Two `CharIterator` objects can be compared equal if and only if they
// remain valid and iterate over the same Cord.
// * The iterator keeps state that can grow for Cords that contain many
// nodes and are imbalanced due to sharing. Prefer to pass this type by
// const reference instead of by value.
// * This type cannot act as a forward iterator because a `Cord` can reuse
// sections of memory. This fact violates the requirement for forward
// iterators to compare equal if dereferencing them returns the same
// object.
class CharIterator {
public:
using iterator_category = std::input_iterator_tag;
using value_type = char;
using difference_type = ptrdiff_t;
using pointer = const char* absl_nonnull;
using reference = const char&;
CharIterator() = default;
CharIterator& operator++();
CharIterator operator++(int);
bool operator==(const CharIterator& other) const;
bool operator!=(const CharIterator& other) const;
reference operator*() const;
friend Cord;
private:
explicit CharIterator(const Cord* absl_nonnull cord)
: chunk_iterator_(cord) {}
ChunkIterator chunk_iterator_;
};
// Cord::AdvanceAndRead()
//
// Advances the `Cord::CharIterator` by `n_bytes` and returns the bytes
// advanced as a separate `Cord`. `n_bytes` must be less than or equal to the
// number of bytes within the Cord; otherwise, behavior is undefined. It is
// valid to pass `char_end()` and `0`.
static Cord AdvanceAndRead(CharIterator* absl_nonnull it, size_t n_bytes);
// Cord::Advance()
//
// Advances the `Cord::CharIterator` by `n_bytes`. `n_bytes` must be less than
// or equal to the number of bytes remaining within the Cord; otherwise,
// behavior is undefined. It is valid to pass `char_end()` and `0`.
static void Advance(CharIterator* absl_nonnull it, size_t n_bytes);
// Cord::ChunkRemaining()
//
// Returns the longest contiguous view starting at the iterator's position.
//
// `it` must be dereferenceable.
static absl::string_view ChunkRemaining(const CharIterator& it);
// Cord::Distance()
//
// Returns the distance between `first` and `last`, as if
// `std::distance(first, last)` was called.
static ptrdiff_t Distance(const CharIterator& first,
const CharIterator& last);
// Cord::char_begin()
//
// Returns an iterator to the first character of the `Cord`.
//
// Generally, prefer using `Cord::Chars()` within a range-based for loop for
// iterating over the chunks of a Cord. This method may be useful for getting
// a `CharIterator` where range-based for-loops may not be available.
CharIterator char_begin() const ABSL_ATTRIBUTE_LIFETIME_BOUND;
// Cord::char_end()
//
// Returns an iterator to one past the last character of the `Cord`.
//
// Generally, prefer using `Cord::Chars()` within a range-based for loop for
// iterating over the chunks of a Cord. This method may be useful for getting
// a `CharIterator` where range-based for-loops are not useful.
CharIterator char_end() const ABSL_ATTRIBUTE_LIFETIME_BOUND;
// Cord::CharRange
//
// `CharRange` is a helper class for iterating over the characters of a
// producing an iterator which can be used within a range-based for loop.
// Construction of a `CharRange` will return an iterator pointing to the first
// character of the Cord. Generally, do not construct a `CharRange` directly;
// instead, prefer to use the `Cord::Chars()` method shown below.
//
// Implementation note: `CharRange` is simply a convenience wrapper over
// `Cord::char_begin()` and `Cord::char_end()`.
class CharRange {
public:
// Fulfill minimum c++ container requirements [container.requirements]
// These (partial) container type definitions allow CharRange to be used
// in various utilities expecting a subset of [container.requirements].
// For example, the below enables using `::testing::ElementsAre(...)`
using value_type = char;
using reference = value_type&;
using const_reference = const value_type&;
using iterator = CharIterator;
using const_iterator = CharIterator;
explicit CharRange(const Cord* absl_nonnull cord) : cord_(cord) {}
CharIterator begin() const;
CharIterator end() const;
private:
const Cord* absl_nonnull cord_;
};
// Cord::Chars()
//
// Returns a `Cord::CharRange` for iterating over the characters of a `Cord`
// with a range-based for-loop. For most character-based iteration tasks on a
// Cord, use `Cord::Chars()` to retrieve this iterator.
//
// Example:
//
// void ProcessCord(const Cord& cord) {
// for (char c : cord.Chars()) { ... }
// }
//
// Note that the ordinary caveats of temporary lifetime extension apply:
//
// void Process() {
// for (char c : CordFactory().Chars()) {
// // The temporary Cord returned by CordFactory has been destroyed!
// }
// }
CharRange Chars() const ABSL_ATTRIBUTE_LIFETIME_BOUND;
// Cord::operator[]
//
// Gets the "i"th character of the Cord and returns it, provided that
// 0 <= i < Cord.size().
//
// NOTE: This routine is reasonably efficient. It is roughly
// logarithmic based on the number of chunks that make up the cord. Still,
// if you need to iterate over the contents of a cord, you should
// use a CharIterator/ChunkIterator rather than call operator[] or Get()
// repeatedly in a loop.
char operator[](size_t i) const;
// Cord::TryFlat()
//
// If this cord's representation is a single flat array, returns a
// string_view referencing that array. Otherwise returns nullopt.
absl::optional<absl::string_view> TryFlat() const
ABSL_ATTRIBUTE_LIFETIME_BOUND;
// Cord::Flatten()
//
// Flattens the cord into a single array and returns a view of the data.
//
// If the cord was already flat, the contents are not modified.
absl::string_view Flatten() ABSL_ATTRIBUTE_LIFETIME_BOUND;
// Cord::Find()
//
// Returns an iterator to the first occurrence of the substring `needle`.
//
// If the substring `needle` does not occur, `Cord::char_end()` is returned.
CharIterator Find(absl::string_view needle) const;
CharIterator Find(const absl::Cord& needle) const;
// Supports absl::Cord as a sink object for absl::Format().
friend void AbslFormatFlush(absl::Cord* absl_nonnull cord,
absl::string_view part) {
cord->Append(part);
}
// Support automatic stringification with absl::StrCat and absl::StrFormat.
template <typename Sink>
friend void AbslStringify(Sink& sink, const absl::Cord& cord) {
for (absl::string_view chunk : cord.Chunks()) {
sink.Append(chunk);
}
}
// Cord::SetExpectedChecksum()
//
// Stores a checksum value with this non-empty cord instance, for later
// retrieval.
//
// The expected checksum is a number stored out-of-band, alongside the data.
// It is preserved across copies and assignments, but any mutations to a cord
// will cause it to lose its expected checksum.
//
// The expected checksum is not part of a Cord's value, and does not affect
// operations such as equality or hashing.
//
// This field is intended to store a CRC32C checksum for later validation, to
// help support end-to-end checksum workflows. However, the Cord API itself
// does no CRC validation, and assigns no meaning to this number.
//
// This call has no effect if this cord is empty.
void SetExpectedChecksum(uint32_t crc);
// Returns this cord's expected checksum, if it has one. Otherwise, returns
// nullopt.
absl::optional<uint32_t> ExpectedChecksum() const;
template <typename H>
friend H AbslHashValue(H hash_state, const absl::Cord& c) {
absl::optional<absl::string_view> maybe_flat = c.TryFlat();
if (maybe_flat.has_value()) {
return H::combine(std::move(hash_state), *maybe_flat);
}
return c.HashFragmented(std::move(hash_state));
}
// Create a Cord with the contents of StringConstant<T>::value.
// No allocations will be done and no data will be copied.
// This is an INTERNAL API and subject to change or removal. This API can only
// be used by spelling absl::strings_internal::MakeStringConstant, which is
// also an internal API.
template <typename T>
// NOLINTNEXTLINE(google-explicit-constructor)
constexpr Cord(strings_internal::StringConstant<T>);
private:
using CordRep = absl::cord_internal::CordRep;
using CordRepFlat = absl::cord_internal::CordRepFlat;
using CordzInfo = cord_internal::CordzInfo;
using CordzUpdateScope = cord_internal::CordzUpdateScope;
using CordzUpdateTracker = cord_internal::CordzUpdateTracker;
using InlineData = cord_internal::InlineData;
using MethodIdentifier = CordzUpdateTracker::MethodIdentifier;
// Creates a cord instance with `method` representing the originating
// public API call causing the cord to be created.
explicit Cord(absl::string_view src, MethodIdentifier method);
friend class CordTestPeer;
friend bool operator==(const Cord& lhs, const Cord& rhs);
friend bool operator==(const Cord& lhs, absl::string_view rhs);
#ifdef __cpp_impl_three_way_comparison
// Cords support comparison with other Cords and string_views via operator<
// and others; here we provide a wrapper for the C++20 three-way comparison
// <=> operator.
static inline std::strong_ordering ConvertCompareResultToStrongOrdering(
int c) {
if (c == 0) {
return std::strong_ordering::equal;
} else if (c < 0) {
return std::strong_ordering::less;
} else {
return std::strong_ordering::greater;
}
}
friend inline std::strong_ordering operator<=>(const Cord& x, const Cord& y) {
return ConvertCompareResultToStrongOrdering(x.Compare(y));
}
friend inline std::strong_ordering operator<=>(const Cord& lhs,
absl::string_view rhs) {
return ConvertCompareResultToStrongOrdering(lhs.Compare(rhs));
}
friend inline std::strong_ordering operator<=>(absl::string_view lhs,
const Cord& rhs) {
return ConvertCompareResultToStrongOrdering(-rhs.Compare(lhs));
}
#endif
friend const CordzInfo* absl_nullable GetCordzInfoForTesting(
const Cord& cord);
// Calls the provided function once for each cord chunk, in order. Unlike
// Chunks(), this API will not allocate memory.
void ForEachChunk(absl::FunctionRef<void(absl::string_view)>) const;
// Allocates new contiguous storage for the contents of the cord. This is
// called by Flatten() when the cord was not already flat.
absl::string_view FlattenSlowPath();
// Actual cord contents are hidden inside the following simple
// class so that we can isolate the bulk of cord.cc from changes
// to the representation.
//
// InlineRep holds either a tree pointer, or an array of kMaxInline bytes.
class InlineRep {
public:
static constexpr unsigned char kMaxInline = cord_internal::kMaxInline;
static_assert(kMaxInline >= sizeof(absl::cord_internal::CordRep*), "");
constexpr InlineRep() : data_() {}
explicit InlineRep(InlineData::DefaultInitType init) : data_(init) {}
InlineRep(const InlineRep& src);
InlineRep(InlineRep&& src);
InlineRep& operator=(const InlineRep& src);
InlineRep& operator=(InlineRep&& src) noexcept;
explicit constexpr InlineRep(absl::string_view sv,
CordRep* absl_nullable rep);
void Swap(InlineRep* absl_nonnull rhs);
size_t size() const;
// Returns nullptr if holding pointer
const char* absl_nullable data() const;
// Discards pointer, if any
void set_data(const char* absl_nonnull data, size_t n);
char* absl_nonnull set_data(size_t n); // Write data to the result
// Returns nullptr if holding bytes
absl::cord_internal::CordRep* absl_nullable tree() const;
absl::cord_internal::CordRep* absl_nonnull as_tree() const;
const char* absl_nonnull as_chars() const;
// Returns non-null iff was holding a pointer
absl::cord_internal::CordRep* absl_nullable clear();
// Converts to pointer if necessary.
void reduce_size(size_t n); // REQUIRES: holding data
void remove_prefix(size_t n); // REQUIRES: holding data
void AppendArray(absl::string_view src, MethodIdentifier method);
absl::string_view FindFlatStartPiece() const;
// Creates a CordRepFlat instance from the current inlined data with `extra'
// bytes of desired additional capacity.
CordRepFlat* absl_nonnull MakeFlatWithExtraCapacity(size_t extra);
// Sets the tree value for this instance. `rep` must not be null.
// Requires the current instance to hold a tree, and a lock to be held on
// any CordzInfo referenced by this instance. The latter is enforced through
// the CordzUpdateScope argument. If the current instance is sampled, then
// the CordzInfo instance is updated to reference the new `rep` value.
void SetTree(CordRep* absl_nonnull rep, const CordzUpdateScope& scope);
// Identical to SetTree(), except that `rep` is allowed to be null, in
// which case the current instance is reset to an empty value.
void SetTreeOrEmpty(CordRep* absl_nullable rep,
const CordzUpdateScope& scope);
// Sets the tree value for this instance, and randomly samples this cord.
// This function disregards existing contents in `data_`, and should be
// called when a Cord is 'promoted' from an 'uninitialized' or 'inlined'
// value to a non-inlined (tree / ring) value.
void EmplaceTree(CordRep* absl_nonnull rep, MethodIdentifier method);
// Identical to EmplaceTree, except that it copies the parent stack from
// the provided `parent` data if the parent is sampled.
void EmplaceTree(CordRep* absl_nonnull rep, const InlineData& parent,
MethodIdentifier method);
// Commits the change of a newly created, or updated `rep` root value into
// this cord. `old_rep` indicates the old (inlined or tree) value of the
// cord, and determines if the commit invokes SetTree() or EmplaceTree().
void CommitTree(const CordRep* absl_nullable old_rep,
CordRep* absl_nonnull rep, const CordzUpdateScope& scope,
MethodIdentifier method);
void AppendTreeToInlined(CordRep* absl_nonnull tree,
MethodIdentifier method);
void AppendTreeToTree(CordRep* absl_nonnull tree, MethodIdentifier method);
void AppendTree(CordRep* absl_nonnull tree, MethodIdentifier method);
void PrependTreeToInlined(CordRep* absl_nonnull tree,
MethodIdentifier method);
void PrependTreeToTree(CordRep* absl_nonnull tree, MethodIdentifier method);
void PrependTree(CordRep* absl_nonnull tree, MethodIdentifier method);
bool IsSame(const InlineRep& other) const { return data_ == other.data_; }
// Copies the inline contents into `dst`. Assumes the cord is not empty.
void CopyTo(std::string* absl_nonnull dst) const {
data_.CopyInlineToString(dst);
}
// Copies the inline contents into `dst`. Assumes the cord is not empty.
void CopyToArray(char* absl_nonnull dst) const;
bool is_tree() const { return data_.is_tree(); }
// Returns true if the Cord is being profiled by cordz.
bool is_profiled() const { return data_.is_tree() && data_.is_profiled(); }
// Returns the available inlined capacity, or 0 if is_tree() == true.
size_t remaining_inline_capacity() const {
return data_.is_tree() ? 0 : kMaxInline - data_.inline_size();
}
// Returns the profiled CordzInfo, or nullptr if not sampled.
absl::cord_internal::CordzInfo* absl_nullable cordz_info() const {
return data_.cordz_info();
}
// Sets the profiled CordzInfo.
void set_cordz_info(cord_internal::CordzInfo* absl_nonnull cordz_info) {
assert(cordz_info != nullptr);
data_.set_cordz_info(cordz_info);
}
// Resets the current cordz_info to null / empty.
void clear_cordz_info() { data_.clear_cordz_info(); }
private:
friend class Cord;
void AssignSlow(const InlineRep& src);
// Unrefs the tree and stops profiling.
void UnrefTree();
void ResetToEmpty() { data_ = {}; }
void set_inline_size(size_t size) { data_.set_inline_size(size); }
size_t inline_size() const { return data_.inline_size(); }
// Empty cords that carry a checksum have a CordRepCrc node with a null
// child node. The code can avoid lots of special cases where it would
// otherwise transition from tree to inline storage if we just remove the
// CordRepCrc node before mutations. Must never be called inside a
// CordzUpdateScope since it untracks the cordz info.
void MaybeRemoveEmptyCrcNode();
cord_internal::InlineData data_;
};
InlineRep contents_;
// Helper for GetFlat() and TryFlat().
static bool GetFlatAux(absl::cord_internal::CordRep* absl_nonnull rep,
absl::string_view* absl_nonnull fragment);
// Helper for ForEachChunk().
static void ForEachChunkAux(
absl::cord_internal::CordRep* absl_nonnull rep,
absl::FunctionRef<void(absl::string_view)> callback);
// The destructor for non-empty Cords.
void DestroyCordSlow();
// Out-of-line implementation of slower parts of logic.
void CopyToArraySlowPath(char* absl_nonnull dst) const;
int CompareSlowPath(absl::string_view rhs, size_t compared_size,
size_t size_to_compare) const;
int CompareSlowPath(const Cord& rhs, size_t compared_size,
size_t size_to_compare) const;
bool EqualsImpl(absl::string_view rhs, size_t size_to_compare) const;
bool EqualsImpl(const Cord& rhs, size_t size_to_compare) const;
int CompareImpl(const Cord& rhs) const;
template <typename ResultType, typename RHS>
friend ResultType GenericCompare(const Cord& lhs, const RHS& rhs,
size_t size_to_compare);
static absl::string_view GetFirstChunk(const Cord& c);
static absl::string_view GetFirstChunk(absl::string_view sv);
// Returns a new reference to contents_.tree(), or steals an existing
// reference if called on an rvalue.
absl::cord_internal::CordRep* absl_nonnull TakeRep() const&;
absl::cord_internal::CordRep* absl_nonnull TakeRep() &&;
// Helper for Append().
template <typename C>
void AppendImpl(C&& src);
// Appends / Prepends `src` to this instance, using precise sizing.
// This method does explicitly not attempt to use any spare capacity
// in any pending last added private owned flat.
// Requires `src` to be <= kMaxFlatLength.
void AppendPrecise(absl::string_view src, MethodIdentifier method);
void PrependPrecise(absl::string_view src, MethodIdentifier method);
CordBuffer GetAppendBufferSlowPath(size_t block_size, size_t capacity,
size_t min_capacity);
// Prepends the provided data to this instance. `method` contains the public
// API method for this action which is tracked for Cordz sampling purposes.
void PrependArray(absl::string_view src, MethodIdentifier method);
// Assigns the value in 'src' to this instance, 'stealing' its contents.
// Requires src.length() > kMaxBytesToCopy.
Cord& AssignLargeString(std::string&& src);
// Helper for AbslHashValue().
template <typename H>
H HashFragmented(H hash_state) const {
typename H::AbslInternalPiecewiseCombiner combiner;
ForEachChunk([&combiner, &hash_state](absl::string_view chunk) {
hash_state = combiner.add_buffer(std::move(hash_state), chunk.data(),
chunk.size());
});
return H::combine(combiner.finalize(std::move(hash_state)),
hash_internal::WeaklyMixedInteger{size()});
}
friend class CrcCord;
void SetCrcCordState(crc_internal::CrcCordState state);
const crc_internal::CrcCordState* absl_nullable MaybeGetCrcCordState() const;
CharIterator FindImpl(CharIterator it, absl::string_view needle) const;
void CopyToArrayImpl(char* absl_nonnull dst) const;
};
ABSL_NAMESPACE_END
} // namespace absl
namespace absl {
ABSL_NAMESPACE_BEGIN
// allow a Cord to be logged
extern std::ostream& operator<<(std::ostream& out, const Cord& cord);
// ------------------------------------------------------------------
// Internal details follow. Clients should ignore.
namespace cord_internal {
// Does non-template-specific `CordRepExternal` initialization.
// Requires `data` to be non-empty.
void InitializeCordRepExternal(absl::string_view data,
CordRepExternal* absl_nonnull rep);
// Creates a new `CordRep` that owns `data` and `releaser` and returns a pointer
// to it. Requires `data` to be non-empty.
template <typename Releaser>
// NOLINTNEXTLINE - suppress clang-tidy raw pointer return.
CordRep* absl_nonnull NewExternalRep(absl::string_view data,
Releaser&& releaser) {
assert(!data.empty());
using ReleaserType = absl::decay_t<Releaser>;
CordRepExternal* rep = new CordRepExternalImpl<ReleaserType>(
std::forward<Releaser>(releaser), 0);
InitializeCordRepExternal(data, rep);
return rep;
}
// Overload for function reference types that dispatches using a function
// pointer because there are no `alignof()` or `sizeof()` a function reference.
// NOLINTNEXTLINE - suppress clang-tidy raw pointer return.
inline CordRep* absl_nonnull NewExternalRep(
absl::string_view data, void (&releaser)(absl::string_view)) {
return NewExternalRep(data, &releaser);
}
} // namespace cord_internal
template <typename Releaser>
Cord MakeCordFromExternal(absl::string_view data, Releaser&& releaser) {
Cord cord;
if (ABSL_PREDICT_TRUE(!data.empty())) {
cord.contents_.EmplaceTree(::absl::cord_internal::NewExternalRep(
data, std::forward<Releaser>(releaser)),
Cord::MethodIdentifier::kMakeCordFromExternal);
} else {
using ReleaserType = absl::decay_t<Releaser>;
cord_internal::InvokeReleaser(
cord_internal::Rank1{}, ReleaserType(std::forward<Releaser>(releaser)),
data);
}
return cord;
}
constexpr Cord::InlineRep::InlineRep(absl::string_view sv,
CordRep* absl_nullable rep)
: data_(sv, rep) {}
inline Cord::InlineRep::InlineRep(const Cord::InlineRep& src)
: data_(InlineData::kDefaultInit) {
if (CordRep* tree = src.tree()) {
EmplaceTree(CordRep::Ref(tree), src.data_,
CordzUpdateTracker::kConstructorCord);
} else {
data_ = src.data_;
}
}
inline Cord::InlineRep::InlineRep(Cord::InlineRep&& src) : data_(src.data_) {
src.ResetToEmpty();
}
inline Cord::InlineRep& Cord::InlineRep::operator=(const Cord::InlineRep& src) {
if (this == &src) {
return *this;
}
if (!is_tree() && !src.is_tree()) {
data_ = src.data_;
return *this;
}
AssignSlow(src);
return *this;
}
inline Cord::InlineRep& Cord::InlineRep::operator=(
Cord::InlineRep&& src) noexcept {
if (is_tree()) {
UnrefTree();
}
data_ = src.data_;
src.ResetToEmpty();
return *this;
}
inline void Cord::InlineRep::Swap(Cord::InlineRep* absl_nonnull rhs) {
if (rhs == this) {
return;
}
using std::swap;
swap(data_, rhs->data_);
}
inline const char* absl_nullable Cord::InlineRep::data() const {
return is_tree() ? nullptr : data_.as_chars();
}
inline const char* absl_nonnull Cord::InlineRep::as_chars() const {
assert(!data_.is_tree());
return data_.as_chars();
}
inline absl::cord_internal::CordRep* absl_nonnull Cord::InlineRep::as_tree()
const {
assert(data_.is_tree());
return data_.as_tree();
}
inline absl::cord_internal::CordRep* absl_nullable Cord::InlineRep::tree()
const {
if (is_tree()) {
return as_tree();
} else {
return nullptr;
}
}
inline size_t Cord::InlineRep::size() const {
return is_tree() ? as_tree()->length : inline_size();
}
inline cord_internal::CordRepFlat* absl_nonnull
Cord::InlineRep::MakeFlatWithExtraCapacity(size_t extra) {
static_assert(cord_internal::kMinFlatLength >= sizeof(data_), "");
size_t len = data_.inline_size();
auto* result = CordRepFlat::New(len + extra);
result->length = len;
data_.copy_max_inline_to(result->Data());
return result;
}
inline void Cord::InlineRep::EmplaceTree(CordRep* absl_nonnull rep,
MethodIdentifier method) {
assert(rep);
data_.make_tree(rep);
CordzInfo::MaybeTrackCord(data_, method);
}
inline void Cord::InlineRep::EmplaceTree(CordRep* absl_nonnull rep,
const InlineData& parent,
MethodIdentifier method) {
data_.make_tree(rep);
CordzInfo::MaybeTrackCord(data_, parent, method);
}
inline void Cord::InlineRep::SetTree(CordRep* absl_nonnull rep,
const CordzUpdateScope& scope) {
assert(rep);
assert(data_.is_tree());
data_.set_tree(rep);
scope.SetCordRep(rep);
}
inline void Cord::InlineRep::SetTreeOrEmpty(CordRep* absl_nullable rep,
const CordzUpdateScope& scope) {
assert(data_.is_tree());
if (rep) {
data_.set_tree(rep);
} else {
data_ = {};
}
scope.SetCordRep(rep);
}
inline void Cord::InlineRep::CommitTree(const CordRep* absl_nullable old_rep,
CordRep* absl_nonnull rep,
const CordzUpdateScope& scope,
MethodIdentifier method) {
if (old_rep) {
SetTree(rep, scope);
} else {
EmplaceTree(rep, method);
}
}
inline absl::cord_internal::CordRep* absl_nullable Cord::InlineRep::clear() {
if (is_tree()) {
CordzInfo::MaybeUntrackCord(cordz_info());
}
absl::cord_internal::CordRep* result = tree();
ResetToEmpty();
return result;
}
inline void Cord::InlineRep::CopyToArray(char* absl_nonnull dst) const {
assert(!is_tree());
size_t n = inline_size();
assert(n != 0);
cord_internal::SmallMemmove(dst, data_.as_chars(), n);
}
inline void Cord::InlineRep::MaybeRemoveEmptyCrcNode() {
CordRep* rep = tree();
if (rep == nullptr || ABSL_PREDICT_TRUE(rep->length > 0)) {
return;
}
assert(rep->IsCrc());
assert(rep->crc()->child == nullptr);
CordzInfo::MaybeUntrackCord(cordz_info());
CordRep::Unref(rep);
ResetToEmpty();
}
constexpr inline Cord::Cord() noexcept {}
inline Cord::Cord(absl::string_view src)
: Cord(src, CordzUpdateTracker::kConstructorString) {}
template <typename T>
constexpr Cord::Cord(strings_internal::StringConstant<T>)
: contents_(strings_internal::StringConstant<T>::value,
strings_internal::StringConstant<T>::value.size() <=
cord_internal::kMaxInline
? nullptr
: &cord_internal::ConstInitExternalStorage<
strings_internal::StringConstant<T>>::value) {}
inline Cord& Cord::operator=(const Cord& x) {
contents_ = x.contents_;
return *this;
}
template <typename T, Cord::EnableIfString<T>>
Cord& Cord::operator=(T&& src) {
if (src.size() <= cord_internal::kMaxBytesToCopy) {
return operator=(absl::string_view(src));
} else {
return AssignLargeString(std::forward<T>(src));
}
}
inline Cord::Cord(const Cord& src) : contents_(src.contents_) {}
inline Cord::Cord(Cord&& src) noexcept : contents_(std::move(src.contents_)) {}
inline void Cord::swap(Cord& other) noexcept {
contents_.Swap(&other.contents_);
}
inline Cord& Cord::operator=(Cord&& x) noexcept {
contents_ = std::move(x.contents_);
return *this;
}
extern template Cord::Cord(std::string&& src);
inline size_t Cord::size() const {
// Length is 1st field in str.rep_
return contents_.size();
}
inline bool Cord::empty() const { return size() == 0; }
inline size_t Cord::EstimatedMemoryUsage(
CordMemoryAccounting accounting_method) const {
size_t result = sizeof(Cord);
if (const absl::cord_internal::CordRep* rep = contents_.tree()) {
switch (accounting_method) {
case CordMemoryAccounting::kFairShare:
result += cord_internal::GetEstimatedFairShareMemoryUsage(rep);
break;
case CordMemoryAccounting::kTotalMorePrecise:
result += cord_internal::GetMorePreciseMemoryUsage(rep);
break;
case CordMemoryAccounting::kTotal:
result += cord_internal::GetEstimatedMemoryUsage(rep);
break;
}
}
return result;
}
inline absl::optional<absl::string_view> Cord::TryFlat() const
ABSL_ATTRIBUTE_LIFETIME_BOUND {
absl::cord_internal::CordRep* rep = contents_.tree();
if (rep == nullptr) {
return absl::string_view(contents_.data(), contents_.size());
}
absl::string_view fragment;
if (GetFlatAux(rep, &fragment)) {
return fragment;
}
return absl::nullopt;
}
inline absl::string_view Cord::Flatten() ABSL_ATTRIBUTE_LIFETIME_BOUND {
absl::cord_internal::CordRep* rep = contents_.tree();
if (rep == nullptr) {
return absl::string_view(contents_.data(), contents_.size());
} else {
absl::string_view already_flat_contents;
if (GetFlatAux(rep, &already_flat_contents)) {
return already_flat_contents;
}
}
return FlattenSlowPath();
}
inline void Cord::Append(absl::string_view src) {
contents_.AppendArray(src, CordzUpdateTracker::kAppendString);
}
inline void Cord::Prepend(absl::string_view src) {
PrependArray(src, CordzUpdateTracker::kPrependString);
}
inline void Cord::Append(CordBuffer buffer) {
if (ABSL_PREDICT_FALSE(buffer.length() == 0)) return;
contents_.MaybeRemoveEmptyCrcNode();
absl::string_view short_value;
if (CordRep* rep = buffer.ConsumeValue(short_value)) {
contents_.AppendTree(rep, CordzUpdateTracker::kAppendCordBuffer);
} else {
AppendPrecise(short_value, CordzUpdateTracker::kAppendCordBuffer);
}
}
inline void Cord::Prepend(CordBuffer buffer) {
if (ABSL_PREDICT_FALSE(buffer.length() == 0)) return;
contents_.MaybeRemoveEmptyCrcNode();
absl::string_view short_value;
if (CordRep* rep = buffer.ConsumeValue(short_value)) {
contents_.PrependTree(rep, CordzUpdateTracker::kPrependCordBuffer);
} else {
PrependPrecise(short_value, CordzUpdateTracker::kPrependCordBuffer);
}
}
inline CordBuffer Cord::GetAppendBuffer(size_t capacity, size_t min_capacity) {
if (empty()) return CordBuffer::CreateWithDefaultLimit(capacity);
return GetAppendBufferSlowPath(0, capacity, min_capacity);
}
inline CordBuffer Cord::GetCustomAppendBuffer(size_t block_size,
size_t capacity,
size_t min_capacity) {
if (empty()) {
return block_size ? CordBuffer::CreateWithCustomLimit(block_size, capacity)
: CordBuffer::CreateWithDefaultLimit(capacity);
}
return GetAppendBufferSlowPath(block_size, capacity, min_capacity);
}
extern template void Cord::Append(std::string&& src);
extern template void Cord::Prepend(std::string&& src);
inline int Cord::Compare(const Cord& rhs) const {
if (!contents_.is_tree() && !rhs.contents_.is_tree()) {
return contents_.data_.Compare(rhs.contents_.data_);
}
return CompareImpl(rhs);
}
// Does 'this' cord start/end with rhs
inline bool Cord::StartsWith(const Cord& rhs) const {
if (contents_.IsSame(rhs.contents_)) return true;
size_t rhs_size = rhs.size();
if (size() < rhs_size) return false;
return EqualsImpl(rhs, rhs_size);
}
inline bool Cord::StartsWith(absl::string_view rhs) const {
size_t rhs_size = rhs.size();
if (size() < rhs_size) return false;
return EqualsImpl(rhs, rhs_size);
}
inline void Cord::CopyToArrayImpl(char* absl_nonnull dst) const {
if (!contents_.is_tree()) {
if (!empty()) contents_.CopyToArray(dst);
} else {
CopyToArraySlowPath(dst);
}
}
inline void Cord::ChunkIterator::InitTree(
cord_internal::CordRep* absl_nonnull tree) {
tree = cord_internal::SkipCrcNode(tree);
if (tree->tag == cord_internal::BTREE) {
current_chunk_ = btree_reader_.Init(tree->btree());
} else {
current_leaf_ = tree;
current_chunk_ = cord_internal::EdgeData(tree);
}
}
inline Cord::ChunkIterator::ChunkIterator(
cord_internal::CordRep* absl_nonnull tree) {
bytes_remaining_ = tree->length;
InitTree(tree);
}
inline Cord::ChunkIterator::ChunkIterator(const Cord* absl_nonnull cord) {
if (CordRep* tree = cord->contents_.tree()) {
bytes_remaining_ = tree->length;
if (ABSL_PREDICT_TRUE(bytes_remaining_ != 0)) {
InitTree(tree);
} else {
current_chunk_ = {};
}
} else {
bytes_remaining_ = cord->contents_.inline_size();
current_chunk_ = {cord->contents_.data(), bytes_remaining_};
}
}
inline Cord::ChunkIterator& Cord::ChunkIterator::AdvanceBtree() {
current_chunk_ = btree_reader_.Next();
return *this;
}
inline void Cord::ChunkIterator::AdvanceBytesBtree(size_t n) {
assert(n >= current_chunk_.size());
bytes_remaining_ -= n;
if (bytes_remaining_) {
if (n == current_chunk_.size()) {
current_chunk_ = btree_reader_.Next();
} else {
size_t offset = btree_reader_.length() - bytes_remaining_;
current_chunk_ = btree_reader_.Seek(offset);
}
} else {
current_chunk_ = {};
}
}
inline Cord::ChunkIterator& Cord::ChunkIterator::operator++() {
ABSL_HARDENING_ASSERT(bytes_remaining_ > 0 &&
"Attempted to iterate past `end()`");
assert(bytes_remaining_ >= current_chunk_.size());
bytes_remaining_ -= current_chunk_.size();
if (bytes_remaining_ > 0) {
if (btree_reader_) {
return AdvanceBtree();
} else {
assert(!current_chunk_.empty()); // Called on invalid iterator.
}
current_chunk_ = {};
}
return *this;
}
inline Cord::ChunkIterator Cord::ChunkIterator::operator++(int) {
ChunkIterator tmp(*this);
operator++();
return tmp;
}
inline bool Cord::ChunkIterator::operator==(const ChunkIterator& other) const {
return bytes_remaining_ == other.bytes_remaining_;
}
inline bool Cord::ChunkIterator::operator!=(const ChunkIterator& other) const {
return !(*this == other);
}
inline Cord::ChunkIterator::reference Cord::ChunkIterator::operator*() const {
ABSL_HARDENING_ASSERT(bytes_remaining_ != 0);
return current_chunk_;
}
inline Cord::ChunkIterator::pointer Cord::ChunkIterator::operator->() const {
ABSL_HARDENING_ASSERT(bytes_remaining_ != 0);
return &current_chunk_;
}
inline void Cord::ChunkIterator::RemoveChunkPrefix(size_t n) {
assert(n < current_chunk_.size());
current_chunk_.remove_prefix(n);
bytes_remaining_ -= n;
}
inline void Cord::ChunkIterator::AdvanceBytes(size_t n) {
assert(bytes_remaining_ >= n);
if (ABSL_PREDICT_TRUE(n < current_chunk_.size())) {
RemoveChunkPrefix(n);
} else if (n != 0) {
if (btree_reader_) {
AdvanceBytesBtree(n);
} else {
bytes_remaining_ = 0;
}
}
}
inline Cord::ChunkIterator Cord::chunk_begin() const {
return ChunkIterator(this);
}
inline Cord::ChunkIterator Cord::chunk_end() const { return ChunkIterator(); }
inline Cord::ChunkIterator Cord::ChunkRange::begin() const {
return cord_->chunk_begin();
}
inline Cord::ChunkIterator Cord::ChunkRange::end() const {
return cord_->chunk_end();
}
inline Cord::ChunkRange Cord::Chunks() const { return ChunkRange(this); }
inline Cord::CharIterator& Cord::CharIterator::operator++() {
if (ABSL_PREDICT_TRUE(chunk_iterator_->size() > 1)) {
chunk_iterator_.RemoveChunkPrefix(1);
} else {
++chunk_iterator_;
}
return *this;
}
inline Cord::CharIterator Cord::CharIterator::operator++(int) {
CharIterator tmp(*this);
operator++();
return tmp;
}
inline bool Cord::CharIterator::operator==(const CharIterator& other) const {
return chunk_iterator_ == other.chunk_iterator_;
}
inline bool Cord::CharIterator::operator!=(const CharIterator& other) const {
return !(*this == other);
}
inline Cord::CharIterator::reference Cord::CharIterator::operator*() const {
return *chunk_iterator_->data();
}
inline Cord Cord::AdvanceAndRead(CharIterator* absl_nonnull it,
size_t n_bytes) {
assert(it != nullptr);
return it->chunk_iterator_.AdvanceAndReadBytes(n_bytes);
}
inline void Cord::Advance(CharIterator* absl_nonnull it, size_t n_bytes) {
assert(it != nullptr);
it->chunk_iterator_.AdvanceBytes(n_bytes);
}
inline absl::string_view Cord::ChunkRemaining(const CharIterator& it) {
return *it.chunk_iterator_;
}
inline ptrdiff_t Cord::Distance(const CharIterator& first,
const CharIterator& last) {
return static_cast<ptrdiff_t>(first.chunk_iterator_.bytes_remaining_ -
last.chunk_iterator_.bytes_remaining_);
}
inline Cord::CharIterator Cord::char_begin() const {
return CharIterator(this);
}
inline Cord::CharIterator Cord::char_end() const { return CharIterator(); }
inline Cord::CharIterator Cord::CharRange::begin() const {
return cord_->char_begin();
}
inline Cord::CharIterator Cord::CharRange::end() const {
return cord_->char_end();
}
inline Cord::CharRange Cord::Chars() const { return CharRange(this); }
inline void Cord::ForEachChunk(
absl::FunctionRef<void(absl::string_view)> callback) const {
absl::cord_internal::CordRep* rep = contents_.tree();
if (rep == nullptr) {
callback(absl::string_view(contents_.data(), contents_.size()));
} else {
ForEachChunkAux(rep, callback);
}
}
// Nonmember Cord-to-Cord relational operators.
inline bool operator==(const Cord& lhs, const Cord& rhs) {
if (lhs.contents_.IsSame(rhs.contents_)) return true;
size_t rhs_size = rhs.size();
if (lhs.size() != rhs_size) return false;
return lhs.EqualsImpl(rhs, rhs_size);
}
inline bool operator!=(const Cord& x, const Cord& y) { return !(x == y); }
inline bool operator<(const Cord& x, const Cord& y) { return x.Compare(y) < 0; }
inline bool operator>(const Cord& x, const Cord& y) { return x.Compare(y) > 0; }
inline bool operator<=(const Cord& x, const Cord& y) {
return x.Compare(y) <= 0;
}
inline bool operator>=(const Cord& x, const Cord& y) {
return x.Compare(y) >= 0;
}
// Nonmember Cord-to-absl::string_view relational operators.
//
// Due to implicit conversions, these also enable comparisons of Cord with
// std::string and const char*.
inline bool operator==(const Cord& lhs, absl::string_view rhs) {
size_t lhs_size = lhs.size();
size_t rhs_size = rhs.size();
if (lhs_size != rhs_size) return false;
return lhs.EqualsImpl(rhs, rhs_size);
}
inline bool operator==(absl::string_view x, const Cord& y) { return y == x; }
inline bool operator!=(const Cord& x, absl::string_view y) { return !(x == y); }
inline bool operator!=(absl::string_view x, const Cord& y) { return !(x == y); }
inline bool operator<(const Cord& x, absl::string_view y) {
return x.Compare(y) < 0;
}
inline bool operator<(absl::string_view x, const Cord& y) {
return y.Compare(x) > 0;
}
inline bool operator>(const Cord& x, absl::string_view y) { return y < x; }
inline bool operator>(absl::string_view x, const Cord& y) { return y < x; }
inline bool operator<=(const Cord& x, absl::string_view y) { return !(y < x); }
inline bool operator<=(absl::string_view x, const Cord& y) { return !(y < x); }
inline bool operator>=(const Cord& x, absl::string_view y) { return !(x < y); }
inline bool operator>=(absl::string_view x, const Cord& y) { return !(x < y); }
// Some internals exposed to test code.
namespace strings_internal {
class CordTestAccess {
public:
static size_t FlatOverhead();
static size_t MaxFlatLength();
static size_t SizeofCordRepExternal();
static size_t SizeofCordRepSubstring();
static size_t FlatTagToLength(uint8_t tag);
static uint8_t LengthToTag(size_t s);
};
} // namespace strings_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_CORD_H_
*Âd
osoong/.intermediates/external/abseil-cpp/absl_numeric_bits_hdrs/gen/my_include_dir/absl/numeric/internal/bits.hÎc// Copyright 2020 The Abseil Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_NUMERIC_INTERNAL_BITS_H_
#define ABSL_NUMERIC_INTERNAL_BITS_H_
#include <cstdint>
#include <limits>
#include <type_traits>
// Clang on Windows has __builtin_clzll; otherwise we need to use the
// windows intrinsic functions.
#if defined(_MSC_VER) && !defined(__clang__)
#include <intrin.h>
#endif
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#if defined(__GNUC__) && !defined(__clang__)
// GCC
#define ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(x) 1
#else
#define ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(x) ABSL_HAVE_BUILTIN(x)
#endif
#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_popcountl) && \
ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_popcountll)
#define ABSL_INTERNAL_CONSTEXPR_POPCOUNT constexpr
#define ABSL_INTERNAL_HAS_CONSTEXPR_POPCOUNT 1
#else
#define ABSL_INTERNAL_CONSTEXPR_POPCOUNT
#define ABSL_INTERNAL_HAS_CONSTEXPR_POPCOUNT 0
#endif
#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_clz) && \
ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_clzll)
#define ABSL_INTERNAL_CONSTEXPR_CLZ constexpr
#define ABSL_INTERNAL_HAS_CONSTEXPR_CLZ 1
#else
#define ABSL_INTERNAL_CONSTEXPR_CLZ
#define ABSL_INTERNAL_HAS_CONSTEXPR_CLZ 0
#endif
#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_ctz) && \
ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_ctzll)
#define ABSL_INTERNAL_CONSTEXPR_CTZ constexpr
#define ABSL_INTERNAL_HAS_CONSTEXPR_CTZ 1
#else
#define ABSL_INTERNAL_CONSTEXPR_CTZ
#define ABSL_INTERNAL_HAS_CONSTEXPR_CTZ 0
#endif
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace numeric_internal {
constexpr bool IsPowerOf2(unsigned int x) noexcept {
return x != 0 && (x & (x - 1)) == 0;
}
template <class T>
[[nodiscard]] ABSL_ATTRIBUTE_ALWAYS_INLINE constexpr T RotateRight(
T x, int s) noexcept {
static_assert(std::is_unsigned<T>::value, "T must be unsigned");
static_assert(IsPowerOf2(std::numeric_limits<T>::digits),
"T must have a power-of-2 size");
return static_cast<T>(x >> (s & (std::numeric_limits<T>::digits - 1))) |
static_cast<T>(x << ((-s) & (std::numeric_limits<T>::digits - 1)));
}
template <class T>
[[nodiscard]] ABSL_ATTRIBUTE_ALWAYS_INLINE constexpr T RotateLeft(
T x, int s) noexcept {
static_assert(std::is_unsigned<T>::value, "T must be unsigned");
static_assert(IsPowerOf2(std::numeric_limits<T>::digits),
"T must have a power-of-2 size");
return static_cast<T>(x << (s & (std::numeric_limits<T>::digits - 1))) |
static_cast<T>(x >> ((-s) & (std::numeric_limits<T>::digits - 1)));
}
ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_POPCOUNT inline int
Popcount32(uint32_t x) noexcept {
#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_popcount)
static_assert(sizeof(unsigned int) == sizeof(x),
"__builtin_popcount does not take 32-bit arg");
return __builtin_popcount(x);
#else
x -= ((x >> 1) & 0x55555555);
x = ((x >> 2) & 0x33333333) + (x & 0x33333333);
return static_cast<int>((((x + (x >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24);
#endif
}
ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_POPCOUNT inline int
Popcount64(uint64_t x) noexcept {
#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_popcountll)
static_assert(sizeof(unsigned long long) == sizeof(x), // NOLINT(runtime/int)
"__builtin_popcount does not take 64-bit arg");
return __builtin_popcountll(x);
#else
x -= (x >> 1) & 0x5555555555555555ULL;
x = ((x >> 2) & 0x3333333333333333ULL) + (x & 0x3333333333333333ULL);
return static_cast<int>(
(((x + (x >> 4)) & 0xF0F0F0F0F0F0F0FULL) * 0x101010101010101ULL) >> 56);
#endif
}
template <class T>
ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_POPCOUNT inline int
Popcount(T x) noexcept {
static_assert(std::is_unsigned<T>::value, "T must be unsigned");
static_assert(IsPowerOf2(std::numeric_limits<T>::digits),
"T must have a power-of-2 size");
static_assert(sizeof(x) <= sizeof(uint64_t), "T is too large");
if constexpr (sizeof(x) <= sizeof(uint32_t)) {
return Popcount32(x);
} else {
return Popcount64(x);
}
}
ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline int
CountLeadingZeroes32(uint32_t x) {
#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_clz)
// Use __builtin_clz, which uses the following instructions:
// x86: bsr, lzcnt
// ARM64: clz
// PPC: cntlzd
static_assert(sizeof(unsigned int) == sizeof(x),
"__builtin_clz does not take 32-bit arg");
// Handle 0 as a special case because __builtin_clz(0) is undefined.
return x == 0 ? 32 : __builtin_clz(x);
#elif defined(_MSC_VER) && !defined(__clang__)
unsigned long result = 0; // NOLINT(runtime/int)
if (_BitScanReverse(&result, x)) {
return 31 - result;
}
return 32;
#else
int zeroes = 28;
if (x >> 16) {
zeroes -= 16;
x >>= 16;
}
if (x >> 8) {
zeroes -= 8;
x >>= 8;
}
if (x >> 4) {
zeroes -= 4;
x >>= 4;
}
return "\4\3\2\2\1\1\1\1\0\0\0\0\0\0\0"[x] + zeroes;
#endif
}
ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline int
CountLeadingZeroes16(uint16_t x) {
#if ABSL_HAVE_BUILTIN(__builtin_clzg)
return x == 0 ? 16 : __builtin_clzg(x);
#elif ABSL_HAVE_BUILTIN(__builtin_clzs)
static_assert(sizeof(unsigned short) == sizeof(x), // NOLINT(runtime/int)
"__builtin_clzs does not take 16-bit arg");
return x == 0 ? 16 : __builtin_clzs(x);
#else
return CountLeadingZeroes32(x) - 16;
#endif
}
ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline int
CountLeadingZeroes64(uint64_t x) {
#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_clzll)
// Use __builtin_clzll, which uses the following instructions:
// x86: bsr, lzcnt
// ARM64: clz
// PPC: cntlzd
static_assert(sizeof(unsigned long long) == sizeof(x), // NOLINT(runtime/int)
"__builtin_clzll does not take 64-bit arg");
// Handle 0 as a special case because __builtin_clzll(0) is undefined.
return x == 0 ? 64 : __builtin_clzll(x);
#elif defined(_MSC_VER) && !defined(__clang__) && \
(defined(_M_X64) || defined(_M_ARM64))
// MSVC does not have __buitin_clzll. Use _BitScanReverse64.
unsigned long result = 0; // NOLINT(runtime/int)
if (_BitScanReverse64(&result, x)) {
return 63 - result;
}
return 64;
#elif defined(_MSC_VER) && !defined(__clang__)
// MSVC does not have __buitin_clzll. Compose two calls to _BitScanReverse
unsigned long result = 0; // NOLINT(runtime/int)
if ((x >> 32) &&
_BitScanReverse(&result, static_cast<unsigned long>(x >> 32))) {
return 31 - result;
}
if (_BitScanReverse(&result, static_cast<unsigned long>(x))) {
return 63 - result;
}
return 64;
#else
int zeroes = 60;
if (x >> 32) {
zeroes -= 32;
x >>= 32;
}
if (x >> 16) {
zeroes -= 16;
x >>= 16;
}
if (x >> 8) {
zeroes -= 8;
x >>= 8;
}
if (x >> 4) {
zeroes -= 4;
x >>= 4;
}
return "\4\3\2\2\1\1\1\1\0\0\0\0\0\0\0"[x] + zeroes;
#endif
}
template <typename T>
ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline int
CountLeadingZeroes(T x) {
static_assert(std::is_unsigned<T>::value, "T must be unsigned");
static_assert(IsPowerOf2(std::numeric_limits<T>::digits),
"T must have a power-of-2 size");
static_assert(sizeof(T) <= sizeof(uint64_t), "T too large");
return sizeof(T) <= sizeof(uint16_t)
? CountLeadingZeroes16(static_cast<uint16_t>(x)) -
(std::numeric_limits<uint16_t>::digits -
std::numeric_limits<T>::digits)
: (sizeof(T) <= sizeof(uint32_t)
? CountLeadingZeroes32(static_cast<uint32_t>(x)) -
(std::numeric_limits<uint32_t>::digits -
std::numeric_limits<T>::digits)
: CountLeadingZeroes64(x));
}
ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CTZ inline int
CountTrailingZeroesNonzero32(uint32_t x) {
#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_ctz)
static_assert(sizeof(unsigned int) == sizeof(x),
"__builtin_ctz does not take 32-bit arg");
return __builtin_ctz(x);
#elif defined(_MSC_VER) && !defined(__clang__)
unsigned long result = 0; // NOLINT(runtime/int)
_BitScanForward(&result, x);
return result;
#else
int c = 31;
x &= ~x + 1;
if (x & 0x0000FFFF) c -= 16;
if (x & 0x00FF00FF) c -= 8;
if (x & 0x0F0F0F0F) c -= 4;
if (x & 0x33333333) c -= 2;
if (x & 0x55555555) c -= 1;
return c;
#endif
}
ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CTZ inline int
CountTrailingZeroesNonzero64(uint64_t x) {
#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_ctzll)
static_assert(sizeof(unsigned long long) == sizeof(x), // NOLINT(runtime/int)
"__builtin_ctzll does not take 64-bit arg");
return __builtin_ctzll(x);
#elif defined(_MSC_VER) && !defined(__clang__) && \
(defined(_M_X64) || defined(_M_ARM64))
unsigned long result = 0; // NOLINT(runtime/int)
_BitScanForward64(&result, x);
return result;
#elif defined(_MSC_VER) && !defined(__clang__)
unsigned long result = 0; // NOLINT(runtime/int)
if (static_cast<uint32_t>(x) == 0) {
_BitScanForward(&result, static_cast<unsigned long>(x >> 32));
return result + 32;
}
_BitScanForward(&result, static_cast<unsigned long>(x));
return result;
#else
int c = 63;
x &= ~x + 1;
if (x & 0x00000000FFFFFFFF) c -= 32;
if (x & 0x0000FFFF0000FFFF) c -= 16;
if (x & 0x00FF00FF00FF00FF) c -= 8;
if (x & 0x0F0F0F0F0F0F0F0F) c -= 4;
if (x & 0x3333333333333333) c -= 2;
if (x & 0x5555555555555555) c -= 1;
return c;
#endif
}
ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CTZ inline int
CountTrailingZeroesNonzero16(uint16_t x) {
#if ABSL_HAVE_BUILTIN(__builtin_ctzg)
return __builtin_ctzg(x);
#elif ABSL_HAVE_BUILTIN(__builtin_ctzs)
static_assert(sizeof(unsigned short) == sizeof(x), // NOLINT(runtime/int)
"__builtin_ctzs does not take 16-bit arg");
return __builtin_ctzs(x);
#else
return CountTrailingZeroesNonzero32(x);
#endif
}
template <class T>
ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CTZ inline int
CountTrailingZeroes(T x) noexcept {
static_assert(std::is_unsigned<T>::value, "T must be unsigned");
static_assert(IsPowerOf2(std::numeric_limits<T>::digits),
"T must have a power-of-2 size");
static_assert(sizeof(T) <= sizeof(uint64_t), "T too large");
return x == 0 ? std::numeric_limits<T>::digits
: (sizeof(T) <= sizeof(uint16_t)
? CountTrailingZeroesNonzero16(static_cast<uint16_t>(x))
: (sizeof(T) <= sizeof(uint32_t)
? CountTrailingZeroesNonzero32(
static_cast<uint32_t>(x))
: CountTrailingZeroesNonzero64(x)));
}
// If T is narrower than unsigned, T{1} << bit_width will be promoted. We
// want to force it to wraparound so that bit_ceil of an invalid value are not
// core constant expressions.
template <class T>
ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline
typename std::enable_if<std::is_unsigned<T>::value, T>::type
BitCeilPromotionHelper(T x, T promotion) {
return (T{1} << (x + promotion)) >> promotion;
}
template <class T>
ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline
typename std::enable_if<std::is_unsigned<T>::value, T>::type
BitCeilNonPowerOf2(T x) {
// If T is narrower than unsigned, it undergoes promotion to unsigned when we
// shift. We calculate the number of bits added by the wider type.
return BitCeilPromotionHelper(
static_cast<T>(std::numeric_limits<T>::digits - CountLeadingZeroes(x)),
T{sizeof(T) >= sizeof(unsigned) ? 0
: std::numeric_limits<unsigned>::digits -
std::numeric_limits<T>::digits});
}
} // namespace numeric_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_NUMERIC_INTERNAL_BITS_H_
*ë
wsoong/.intermediates/external/abseil-cpp/absl_base_endian_hdrs/gen/my_include_dir/absl/base/internal/unaligned_access.hï//
// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifndef ABSL_BASE_INTERNAL_UNALIGNED_ACCESS_H_
#define ABSL_BASE_INTERNAL_UNALIGNED_ACCESS_H_
#include <string.h>
#include <cstdint>
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/nullability.h"
// unaligned APIs
// Portable handling of unaligned loads, stores, and copies.
// The unaligned API is C++ only. The declarations use C++ features
// (namespaces, inline) which are absent or incompatible in C.
#if defined(__cplusplus)
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace base_internal {
inline uint16_t UnalignedLoad16(const void* absl_nonnull p) {
uint16_t t;
memcpy(&t, p, sizeof t);
return t;
}
inline uint32_t UnalignedLoad32(const void* absl_nonnull p) {
uint32_t t;
memcpy(&t, p, sizeof t);
return t;
}
inline uint64_t UnalignedLoad64(const void* absl_nonnull p) {
uint64_t t;
memcpy(&t, p, sizeof t);
return t;
}
inline void UnalignedStore16(void* absl_nonnull p, uint16_t v) {
memcpy(p, &v, sizeof v);
}
inline void UnalignedStore32(void* absl_nonnull p, uint32_t v) {
memcpy(p, &v, sizeof v);
}
inline void UnalignedStore64(void* absl_nonnull p, uint64_t v) {
memcpy(p, &v, sizeof v);
}
} // namespace base_internal
ABSL_NAMESPACE_END
} // namespace absl
#define ABSL_INTERNAL_UNALIGNED_LOAD16(_p) \
(absl::base_internal::UnalignedLoad16(_p))
#define ABSL_INTERNAL_UNALIGNED_LOAD32(_p) \
(absl::base_internal::UnalignedLoad32(_p))
#define ABSL_INTERNAL_UNALIGNED_LOAD64(_p) \
(absl::base_internal::UnalignedLoad64(_p))
#define ABSL_INTERNAL_UNALIGNED_STORE16(_p, _val) \
(absl::base_internal::UnalignedStore16(_p, _val))
#define ABSL_INTERNAL_UNALIGNED_STORE32(_p, _val) \
(absl::base_internal::UnalignedStore32(_p, _val))
#define ABSL_INTERNAL_UNALIGNED_STORE64(_p, _val) \
(absl::base_internal::UnalignedStore64(_p, _val))
#endif // defined(__cplusplus), end of unaligned API
#endif // ABSL_BASE_INTERNAL_UNALIGNED_ACCESS_H_
* I
msoong/.intermediates/external/abseil-cpp/absl_base_endian_hdrs/gen/my_include_dir/absl/base/internal/endian.h®H// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// This file is for Abseil internal use only.
// See //absl/numeric/bits.h for supported functions related to endian-ness.
#ifndef ABSL_BASE_INTERNAL_ENDIAN_H_
#define ABSL_BASE_INTERNAL_ENDIAN_H_
#include <cstdint>
#include <cstdlib>
#include "absl/base/casts.h"
#include "absl/base/config.h"
#include "absl/base/internal/unaligned_access.h"
#include "absl/base/nullability.h"
#include "absl/base/port.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
constexpr uint64_t gbswap_64(uint64_t x) {
#if ABSL_HAVE_BUILTIN(__builtin_bswap64) || defined(__GNUC__)
return __builtin_bswap64(x);
#else
return (((x & uint64_t{0xFF}) << 56) |
((x & uint64_t{0xFF00}) << 40) |
((x & uint64_t{0xFF0000}) << 24) |
((x & uint64_t{0xFF000000}) << 8) |
((x & uint64_t{0xFF00000000}) >> 8) |
((x & uint64_t{0xFF0000000000}) >> 24) |
((x & uint64_t{0xFF000000000000}) >> 40) |
((x & uint64_t{0xFF00000000000000}) >> 56));
#endif
}
constexpr uint32_t gbswap_32(uint32_t x) {
#if ABSL_HAVE_BUILTIN(__builtin_bswap32) || defined(__GNUC__)
return __builtin_bswap32(x);
#else
return (((x & uint32_t{0xFF}) << 24) |
((x & uint32_t{0xFF00}) << 8) |
((x & uint32_t{0xFF0000}) >> 8) |
((x & uint32_t{0xFF000000}) >> 24));
#endif
}
constexpr uint16_t gbswap_16(uint16_t x) {
#if ABSL_HAVE_BUILTIN(__builtin_bswap16) || defined(__GNUC__)
return __builtin_bswap16(x);
#else
return (((x & uint16_t{0xFF}) << 8) |
((x & uint16_t{0xFF00}) >> 8));
#endif
}
#ifdef ABSL_IS_LITTLE_ENDIAN
// Portable definitions for htonl (host-to-network) and friends on little-endian
// architectures.
inline uint16_t ghtons(uint16_t x) { return gbswap_16(x); }
inline uint32_t ghtonl(uint32_t x) { return gbswap_32(x); }
inline uint64_t ghtonll(uint64_t x) { return gbswap_64(x); }
#elif defined ABSL_IS_BIG_ENDIAN
// Portable definitions for htonl (host-to-network) etc on big-endian
// architectures. These definitions are simpler since the host byte order is the
// same as network byte order.
inline uint16_t ghtons(uint16_t x) { return x; }
inline uint32_t ghtonl(uint32_t x) { return x; }
inline uint64_t ghtonll(uint64_t x) { return x; }
#else
#error \
"Unsupported byte order: Either ABSL_IS_BIG_ENDIAN or " \
"ABSL_IS_LITTLE_ENDIAN must be defined"
#endif // byte order
inline uint16_t gntohs(uint16_t x) { return ghtons(x); }
inline uint32_t gntohl(uint32_t x) { return ghtonl(x); }
inline uint64_t gntohll(uint64_t x) { return ghtonll(x); }
// Utilities to convert numbers between the current hosts's native byte
// order and little-endian byte order
//
// Load/Store methods are alignment safe
namespace little_endian {
// Conversion functions.
#ifdef ABSL_IS_LITTLE_ENDIAN
inline uint16_t FromHost16(uint16_t x) { return x; }
inline uint16_t ToHost16(uint16_t x) { return x; }
inline uint32_t FromHost32(uint32_t x) { return x; }
inline uint32_t ToHost32(uint32_t x) { return x; }
inline uint64_t FromHost64(uint64_t x) { return x; }
inline uint64_t ToHost64(uint64_t x) { return x; }
inline constexpr bool IsLittleEndian() { return true; }
#elif defined ABSL_IS_BIG_ENDIAN
inline uint16_t FromHost16(uint16_t x) { return gbswap_16(x); }
inline uint16_t ToHost16(uint16_t x) { return gbswap_16(x); }
inline uint32_t FromHost32(uint32_t x) { return gbswap_32(x); }
inline uint32_t ToHost32(uint32_t x) { return gbswap_32(x); }
inline uint64_t FromHost64(uint64_t x) { return gbswap_64(x); }
inline uint64_t ToHost64(uint64_t x) { return gbswap_64(x); }
inline constexpr bool IsLittleEndian() { return false; }
#endif /* ENDIAN */
inline uint8_t FromHost(uint8_t x) { return x; }
inline uint16_t FromHost(uint16_t x) { return FromHost16(x); }
inline uint32_t FromHost(uint32_t x) { return FromHost32(x); }
inline uint64_t FromHost(uint64_t x) { return FromHost64(x); }
inline uint8_t ToHost(uint8_t x) { return x; }
inline uint16_t ToHost(uint16_t x) { return ToHost16(x); }
inline uint32_t ToHost(uint32_t x) { return ToHost32(x); }
inline uint64_t ToHost(uint64_t x) { return ToHost64(x); }
inline int8_t FromHost(int8_t x) { return x; }
inline int16_t FromHost(int16_t x) {
return bit_cast<int16_t>(FromHost16(bit_cast<uint16_t>(x)));
}
inline int32_t FromHost(int32_t x) {
return bit_cast<int32_t>(FromHost32(bit_cast<uint32_t>(x)));
}
inline int64_t FromHost(int64_t x) {
return bit_cast<int64_t>(FromHost64(bit_cast<uint64_t>(x)));
}
inline int8_t ToHost(int8_t x) { return x; }
inline int16_t ToHost(int16_t x) {
return bit_cast<int16_t>(ToHost16(bit_cast<uint16_t>(x)));
}
inline int32_t ToHost(int32_t x) {
return bit_cast<int32_t>(ToHost32(bit_cast<uint32_t>(x)));
}
inline int64_t ToHost(int64_t x) {
return bit_cast<int64_t>(ToHost64(bit_cast<uint64_t>(x)));
}
// Functions to do unaligned loads and stores in little-endian order.
inline uint16_t Load16(const void* absl_nonnull p) {
return ToHost16(ABSL_INTERNAL_UNALIGNED_LOAD16(p));
}
inline void Store16(void* absl_nonnull p, uint16_t v) {
ABSL_INTERNAL_UNALIGNED_STORE16(p, FromHost16(v));
}
inline uint32_t Load32(const void* absl_nonnull p) {
return ToHost32(ABSL_INTERNAL_UNALIGNED_LOAD32(p));
}
inline void Store32(void* absl_nonnull p, uint32_t v) {
ABSL_INTERNAL_UNALIGNED_STORE32(p, FromHost32(v));
}
inline uint64_t Load64(const void* absl_nonnull p) {
return ToHost64(ABSL_INTERNAL_UNALIGNED_LOAD64(p));
}
inline void Store64(void* absl_nonnull p, uint64_t v) {
ABSL_INTERNAL_UNALIGNED_STORE64(p, FromHost64(v));
}
} // namespace little_endian
// Utilities to convert numbers between the current hosts's native byte
// order and big-endian byte order (same as network byte order)
//
// Load/Store methods are alignment safe
namespace big_endian {
#ifdef ABSL_IS_LITTLE_ENDIAN
inline uint16_t FromHost16(uint16_t x) { return gbswap_16(x); }
inline uint16_t ToHost16(uint16_t x) { return gbswap_16(x); }
inline uint32_t FromHost32(uint32_t x) { return gbswap_32(x); }
inline uint32_t ToHost32(uint32_t x) { return gbswap_32(x); }
inline uint64_t FromHost64(uint64_t x) { return gbswap_64(x); }
inline uint64_t ToHost64(uint64_t x) { return gbswap_64(x); }
inline constexpr bool IsLittleEndian() { return true; }
#elif defined ABSL_IS_BIG_ENDIAN
inline uint16_t FromHost16(uint16_t x) { return x; }
inline uint16_t ToHost16(uint16_t x) { return x; }
inline uint32_t FromHost32(uint32_t x) { return x; }
inline uint32_t ToHost32(uint32_t x) { return x; }
inline uint64_t FromHost64(uint64_t x) { return x; }
inline uint64_t ToHost64(uint64_t x) { return x; }
inline constexpr bool IsLittleEndian() { return false; }
#endif /* ENDIAN */
inline uint8_t FromHost(uint8_t x) { return x; }
inline uint16_t FromHost(uint16_t x) { return FromHost16(x); }
inline uint32_t FromHost(uint32_t x) { return FromHost32(x); }
inline uint64_t FromHost(uint64_t x) { return FromHost64(x); }
inline uint8_t ToHost(uint8_t x) { return x; }
inline uint16_t ToHost(uint16_t x) { return ToHost16(x); }
inline uint32_t ToHost(uint32_t x) { return ToHost32(x); }
inline uint64_t ToHost(uint64_t x) { return ToHost64(x); }
inline int8_t FromHost(int8_t x) { return x; }
inline int16_t FromHost(int16_t x) {
return bit_cast<int16_t>(FromHost16(bit_cast<uint16_t>(x)));
}
inline int32_t FromHost(int32_t x) {
return bit_cast<int32_t>(FromHost32(bit_cast<uint32_t>(x)));
}
inline int64_t FromHost(int64_t x) {
return bit_cast<int64_t>(FromHost64(bit_cast<uint64_t>(x)));
}
inline int8_t ToHost(int8_t x) { return x; }
inline int16_t ToHost(int16_t x) {
return bit_cast<int16_t>(ToHost16(bit_cast<uint16_t>(x)));
}
inline int32_t ToHost(int32_t x) {
return bit_cast<int32_t>(ToHost32(bit_cast<uint32_t>(x)));
}
inline int64_t ToHost(int64_t x) {
return bit_cast<int64_t>(ToHost64(bit_cast<uint64_t>(x)));
}
// Functions to do unaligned loads and stores in big-endian order.
inline uint16_t Load16(const void* absl_nonnull p) {
return ToHost16(ABSL_INTERNAL_UNALIGNED_LOAD16(p));
}
inline void Store16(void* absl_nonnull p, uint16_t v) {
ABSL_INTERNAL_UNALIGNED_STORE16(p, FromHost16(v));
}
inline uint32_t Load32(const void* absl_nonnull p) {
return ToHost32(ABSL_INTERNAL_UNALIGNED_LOAD32(p));
}
inline void Store32(void* absl_nonnull p, uint32_t v) {
ABSL_INTERNAL_UNALIGNED_STORE32(p, FromHost32(v));
}
inline uint64_t Load64(const void* absl_nonnull p) {
return ToHost64(ABSL_INTERNAL_UNALIGNED_LOAD64(p));
}
inline void Store64(void* absl_nonnull p, uint64_t v) {
ABSL_INTERNAL_UNALIGNED_STORE64(p, FromHost64(v));
}
} // namespace big_endian
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_INTERNAL_ENDIAN_H_
*Á+
jsoong/.intermediates/external/abseil-cpp/absl_log_absl_check_hdrs/gen/my_include_dir/absl/log/absl_check.hÒ*// Copyright 2022 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: log/absl_check.h
// -----------------------------------------------------------------------------
//
// This header declares a family of `ABSL_CHECK` macros as alternative spellings
// for `CHECK` macros in `check.h`.
//
// Except for those whose names begin with `ABSL_DCHECK`, these macros are not
// controlled by `NDEBUG` (cf. `assert`), so the check will be executed
// regardless of compilation mode. `ABSL_CHECK` and friends are thus useful for
// confirming invariants in situations where continuing to run would be worse
// than terminating, e.g., due to risk of data corruption or security
// compromise. It is also more robust and portable to deliberately terminate
// at a particular place with a useful message and backtrace than to assume some
// ultimately unspecified and unreliable crashing behavior (such as a
// "segmentation fault").
//
// For full documentation of each macro, see comments in `check.h`, which has an
// identical set of macros without the ABSL_* prefix.
#ifndef ABSL_LOG_ABSL_CHECK_H_
#define ABSL_LOG_ABSL_CHECK_H_
#include "absl/log/internal/check_impl.h"
#define ABSL_CHECK(condition) \
ABSL_LOG_INTERNAL_CHECK_IMPL((condition), #condition)
#define ABSL_QCHECK(condition) \
ABSL_LOG_INTERNAL_QCHECK_IMPL((condition), #condition)
#define ABSL_PCHECK(condition) \
ABSL_LOG_INTERNAL_PCHECK_IMPL((condition), #condition)
#define ABSL_DCHECK(condition) \
ABSL_LOG_INTERNAL_DCHECK_IMPL((condition), #condition)
#define ABSL_CHECK_EQ(val1, val2) \
ABSL_LOG_INTERNAL_CHECK_EQ_IMPL((val1), #val1, (val2), #val2)
#define ABSL_CHECK_NE(val1, val2) \
ABSL_LOG_INTERNAL_CHECK_NE_IMPL((val1), #val1, (val2), #val2)
#define ABSL_CHECK_LE(val1, val2) \
ABSL_LOG_INTERNAL_CHECK_LE_IMPL((val1), #val1, (val2), #val2)
#define ABSL_CHECK_LT(val1, val2) \
ABSL_LOG_INTERNAL_CHECK_LT_IMPL((val1), #val1, (val2), #val2)
#define ABSL_CHECK_GE(val1, val2) \
ABSL_LOG_INTERNAL_CHECK_GE_IMPL((val1), #val1, (val2), #val2)
#define ABSL_CHECK_GT(val1, val2) \
ABSL_LOG_INTERNAL_CHECK_GT_IMPL((val1), #val1, (val2), #val2)
#define ABSL_QCHECK_EQ(val1, val2) \
ABSL_LOG_INTERNAL_QCHECK_EQ_IMPL((val1), #val1, (val2), #val2)
#define ABSL_QCHECK_NE(val1, val2) \
ABSL_LOG_INTERNAL_QCHECK_NE_IMPL((val1), #val1, (val2), #val2)
#define ABSL_QCHECK_LE(val1, val2) \
ABSL_LOG_INTERNAL_QCHECK_LE_IMPL((val1), #val1, (val2), #val2)
#define ABSL_QCHECK_LT(val1, val2) \
ABSL_LOG_INTERNAL_QCHECK_LT_IMPL((val1), #val1, (val2), #val2)
#define ABSL_QCHECK_GE(val1, val2) \
ABSL_LOG_INTERNAL_QCHECK_GE_IMPL((val1), #val1, (val2), #val2)
#define ABSL_QCHECK_GT(val1, val2) \
ABSL_LOG_INTERNAL_QCHECK_GT_IMPL((val1), #val1, (val2), #val2)
#define ABSL_DCHECK_EQ(val1, val2) \
ABSL_LOG_INTERNAL_DCHECK_EQ_IMPL((val1), #val1, (val2), #val2)
#define ABSL_DCHECK_NE(val1, val2) \
ABSL_LOG_INTERNAL_DCHECK_NE_IMPL((val1), #val1, (val2), #val2)
#define ABSL_DCHECK_LE(val1, val2) \
ABSL_LOG_INTERNAL_DCHECK_LE_IMPL((val1), #val1, (val2), #val2)
#define ABSL_DCHECK_LT(val1, val2) \
ABSL_LOG_INTERNAL_DCHECK_LT_IMPL((val1), #val1, (val2), #val2)
#define ABSL_DCHECK_GE(val1, val2) \
ABSL_LOG_INTERNAL_DCHECK_GE_IMPL((val1), #val1, (val2), #val2)
#define ABSL_DCHECK_GT(val1, val2) \
ABSL_LOG_INTERNAL_DCHECK_GT_IMPL((val1), #val1, (val2), #val2)
#define ABSL_CHECK_OK(status) ABSL_LOG_INTERNAL_CHECK_OK_IMPL((status), #status)
#define ABSL_QCHECK_OK(status) \
ABSL_LOG_INTERNAL_QCHECK_OK_IMPL((status), #status)
#define ABSL_DCHECK_OK(status) \
ABSL_LOG_INTERNAL_DCHECK_OK_IMPL((status), #status)
#define ABSL_CHECK_STREQ(s1, s2) \
ABSL_LOG_INTERNAL_CHECK_STREQ_IMPL((s1), #s1, (s2), #s2)
#define ABSL_CHECK_STRNE(s1, s2) \
ABSL_LOG_INTERNAL_CHECK_STRNE_IMPL((s1), #s1, (s2), #s2)
#define ABSL_CHECK_STRCASEEQ(s1, s2) \
ABSL_LOG_INTERNAL_CHECK_STRCASEEQ_IMPL((s1), #s1, (s2), #s2)
#define ABSL_CHECK_STRCASENE(s1, s2) \
ABSL_LOG_INTERNAL_CHECK_STRCASENE_IMPL((s1), #s1, (s2), #s2)
#define ABSL_QCHECK_STREQ(s1, s2) \
ABSL_LOG_INTERNAL_QCHECK_STREQ_IMPL((s1), #s1, (s2), #s2)
#define ABSL_QCHECK_STRNE(s1, s2) \
ABSL_LOG_INTERNAL_QCHECK_STRNE_IMPL((s1), #s1, (s2), #s2)
#define ABSL_QCHECK_STRCASEEQ(s1, s2) \
ABSL_LOG_INTERNAL_QCHECK_STRCASEEQ_IMPL((s1), #s1, (s2), #s2)
#define ABSL_QCHECK_STRCASENE(s1, s2) \
ABSL_LOG_INTERNAL_QCHECK_STRCASENE_IMPL((s1), #s1, (s2), #s2)
#define ABSL_DCHECK_STREQ(s1, s2) \
ABSL_LOG_INTERNAL_DCHECK_STREQ_IMPL((s1), #s1, (s2), #s2)
#define ABSL_DCHECK_STRNE(s1, s2) \
ABSL_LOG_INTERNAL_DCHECK_STRNE_IMPL((s1), #s1, (s2), #s2)
#define ABSL_DCHECK_STRCASEEQ(s1, s2) \
ABSL_LOG_INTERNAL_DCHECK_STRCASEEQ_IMPL((s1), #s1, (s2), #s2)
#define ABSL_DCHECK_STRCASENE(s1, s2) \
ABSL_LOG_INTERNAL_DCHECK_STRCASENE_IMPL((s1), #s1, (s2), #s2)
#endif // ABSL_LOG_ABSL_CHECK_H_
*¢
…soong/.intermediates/external/abseil-cpp/absl_strings_cordz_functions_hdrs/gen/my_include_dir/absl/strings/internal/cordz_functions.h—// Copyright 2019 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_STRINGS_INTERNAL_CORDZ_FUNCTIONS_H_
#define ABSL_STRINGS_INTERNAL_CORDZ_FUNCTIONS_H_
#include <stdint.h>
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/optimization.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace cord_internal {
// Returns the current sample rate. This represents the average interval
// between samples.
int32_t get_cordz_mean_interval();
// Sets the sample rate with the average interval between samples.
void set_cordz_mean_interval(int32_t mean_interval);
// Cordz is only enabled on Linux with thread_local support.
#if defined(ABSL_INTERNAL_CORDZ_ENABLED)
#error ABSL_INTERNAL_CORDZ_ENABLED cannot be set directly
#elif defined(__linux__) && defined(ABSL_HAVE_THREAD_LOCAL)
#define ABSL_INTERNAL_CORDZ_ENABLED 1
#endif
#ifdef ABSL_INTERNAL_CORDZ_ENABLED
struct SamplingState {
int64_t next_sample;
int64_t sample_stride;
};
// cordz_next_sample is the number of events until the next sample event. If
// the value is 1 or less, the code will check on the next event if cordz is
// enabled, and if so, will sample the Cord. cordz is only enabled when we can
// use thread locals.
ABSL_CONST_INIT extern thread_local SamplingState cordz_next_sample;
// Determines if the next sample should be profiled.
// Returns:
// 0: Do not sample
// >0: Sample with the stride of the last sampling period
int64_t cordz_should_profile_slow(SamplingState& state);
// Determines if the next sample should be profiled.
// Returns:
// 0: Do not sample
// >0: Sample with the stride of the last sampling period
inline int64_t cordz_should_profile() {
if (ABSL_PREDICT_TRUE(cordz_next_sample.next_sample > 1)) {
cordz_next_sample.next_sample--;
return 0;
}
return cordz_should_profile_slow(cordz_next_sample);
}
// Sets the interval until the next sample (for testing only)
void cordz_set_next_sample_for_testing(int64_t next_sample);
#else // ABSL_INTERNAL_CORDZ_ENABLED
inline int64_t cordz_should_profile() { return 0; }
inline void cordz_set_next_sample_for_testing(int64_t) {}
#endif // ABSL_INTERNAL_CORDZ_ENABLED
} // namespace cord_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_CORDZ_FUNCTIONS_H_
|soong/.intermediates/external/abseil-cpp/absl_log_internal_nullstream_hdrs/gen/my_include_dir/absl/log/internal/nullstream.h¶// Copyright 2022 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: log/internal/nullstream.h
// -----------------------------------------------------------------------------
//
// Classes `NullStream`, `NullStreamMaybeFatal ` and `NullStreamFatal`
// implement a subset of the `LogMessage` API and are used instead when logging
// of messages has been disabled.
#ifndef ABSL_LOG_INTERNAL_NULLSTREAM_H_
#define ABSL_LOG_INTERNAL_NULLSTREAM_H_
#ifdef _WIN32
#include <cstdlib>
#else
#include <unistd.h>
#endif
#include <ios>
#include <ostream>
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/log_severity.h"
#include "absl/strings/string_view.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace log_internal {
// A `NullStream` implements the API of `LogMessage` (a few methods and
// `operator<<`) but does nothing. All methods are defined inline so the
// compiler can eliminate the whole instance and discard anything that's
// streamed in.
class NullStream {
public:
NullStream& AtLocation(absl::string_view, int) { return *this; }
template <typename SourceLocationType>
NullStream& AtLocation(SourceLocationType) {
return *this;
}
NullStream& NoPrefix() { return *this; }
NullStream& WithVerbosity(int) { return *this; }
template <typename TimeType>
NullStream& WithTimestamp(TimeType) {
return *this;
}
template <typename Tid>
NullStream& WithThreadID(Tid) {
return *this;
}
template <typename LogEntryType>
NullStream& WithMetadataFrom(const LogEntryType&) {
return *this;
}
NullStream& WithPerror() { return *this; }
template <typename LogSinkType>
NullStream& ToSinkAlso(LogSinkType*) {
return *this;
}
template <typename LogSinkType>
NullStream& ToSinkOnly(LogSinkType*) {
return *this;
}
template <typename LogSinkType>
NullStream& OutputToSink(LogSinkType*, bool) {
return *this;
}
NullStream& InternalStream() { return *this; }
void Flush() {}
};
template <typename T>
inline NullStream& operator<<(NullStream& str, const T&) {
return str;
}
inline NullStream& operator<<(NullStream& str,
std::ostream& (*)(std::ostream& os)) {
return str;
}
inline NullStream& operator<<(NullStream& str,
std::ios_base& (*)(std::ios_base& os)) {
return str;
}
// `NullStreamMaybeFatal` implements the process termination semantics of
// `LogMessage`, which is used for `DFATAL` severity and expression-defined
// severity e.g. `LOG(LEVEL(HowBadIsIt()))`. Like `LogMessage`, it terminates
// the process when destroyed if the passed-in severity equals `FATAL`.
class NullStreamMaybeFatal final : public NullStream {
public:
explicit NullStreamMaybeFatal(absl::LogSeverity severity)
: fatal_(severity == absl::LogSeverity::kFatal) {}
~NullStreamMaybeFatal() {
if (fatal_) {
_exit(1);
}
}
private:
bool fatal_;
};
// `NullStreamFatal` implements the process termination semantics of
// `LogMessageFatal`, which means it always terminates the process. `DFATAL`
// and expression-defined severity use `NullStreamMaybeFatal` above.
class NullStreamFatal final : public NullStream {
public:
NullStreamFatal() = default;
[[noreturn]] ~NullStreamFatal() { _exit(1); }
};
} // namespace log_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_LOG_INTERNAL_GLOBALS_H_
*Ô'
rsoong/.intermediates/external/abseil-cpp/absl_log_internal_strip_hdrs/gen/my_include_dir/absl/log/internal/strip.hÝ&// Copyright 2022 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: log/internal/strip.h
// -----------------------------------------------------------------------------
// SKIP_ABSL_INLINE_NAMESPACE_CHECK
#ifndef ABSL_LOG_INTERNAL_STRIP_H_
#define ABSL_LOG_INTERNAL_STRIP_H_
#include "absl/base/attributes.h" // IWYU pragma: keep
#include "absl/base/log_severity.h"
#include "absl/log/internal/log_message.h"
#include "absl/log/internal/nullstream.h"
// `ABSL_LOGGING_INTERNAL_LOG_*` evaluates to a temporary `LogMessage` object or
// to a related object with a compatible API but different behavior. This set
// of defines comes in three flavors: vanilla, plus two variants that strip some
// logging in subtly different ways for subtly different reasons (see below).
#if defined(STRIP_LOG) && STRIP_LOG
#define ABSL_LOGGING_INTERNAL_LOG_INFO ::absl::log_internal::NullStream()
#define ABSL_LOGGING_INTERNAL_LOG_WARNING ::absl::log_internal::NullStream()
#define ABSL_LOGGING_INTERNAL_LOG_ERROR ::absl::log_internal::NullStream()
#define ABSL_LOGGING_INTERNAL_LOG_FATAL ::absl::log_internal::NullStreamFatal()
#define ABSL_LOGGING_INTERNAL_LOG_QFATAL ::absl::log_internal::NullStreamFatal()
#define ABSL_LOGGING_INTERNAL_LOG_DFATAL \
::absl::log_internal::NullStreamMaybeFatal(::absl::kLogDebugFatal)
#define ABSL_LOGGING_INTERNAL_LOG_LEVEL(severity) \
::absl::log_internal::NullStreamMaybeFatal(absl_log_internal_severity)
// Fatal `DLOG`s expand a little differently to avoid being `[[noreturn]]`.
#define ABSL_LOGGING_INTERNAL_DLOG_FATAL \
::absl::log_internal::NullStreamMaybeFatal(::absl::LogSeverity::kFatal)
#define ABSL_LOGGING_INTERNAL_DLOG_QFATAL \
::absl::log_internal::NullStreamMaybeFatal(::absl::LogSeverity::kFatal)
#define ABSL_LOG_INTERNAL_CHECK(failure_message) ABSL_LOGGING_INTERNAL_LOG_FATAL
#define ABSL_LOG_INTERNAL_QCHECK(failure_message) \
ABSL_LOGGING_INTERNAL_LOG_QFATAL
#else // !defined(STRIP_LOG) || !STRIP_LOG
#define ABSL_LOGGING_INTERNAL_LOG_INFO \
::absl::log_internal::LogMessage( \
__FILE__, __LINE__, ::absl::log_internal::LogMessage::InfoTag{})
#define ABSL_LOGGING_INTERNAL_LOG_WARNING \
::absl::log_internal::LogMessage( \
__FILE__, __LINE__, ::absl::log_internal::LogMessage::WarningTag{})
#define ABSL_LOGGING_INTERNAL_LOG_ERROR \
::absl::log_internal::LogMessage( \
__FILE__, __LINE__, ::absl::log_internal::LogMessage::ErrorTag{})
#define ABSL_LOGGING_INTERNAL_LOG_FATAL \
::absl::log_internal::LogMessageFatal(__FILE__, __LINE__)
#define ABSL_LOGGING_INTERNAL_LOG_QFATAL \
::absl::log_internal::LogMessageQuietlyFatal(__FILE__, __LINE__)
#define ABSL_LOGGING_INTERNAL_LOG_DFATAL \
::absl::log_internal::LogMessage(__FILE__, __LINE__, ::absl::kLogDebugFatal)
#define ABSL_LOGGING_INTERNAL_LOG_LEVEL(severity) \
::absl::log_internal::LogMessage(__FILE__, __LINE__, \
absl_log_internal_severity)
// Fatal `DLOG`s expand a little differently to avoid being `[[noreturn]]`.
#define ABSL_LOGGING_INTERNAL_DLOG_FATAL \
::absl::log_internal::LogMessageDebugFatal(__FILE__, __LINE__)
#define ABSL_LOGGING_INTERNAL_DLOG_QFATAL \
::absl::log_internal::LogMessageQuietlyDebugFatal(__FILE__, __LINE__)
// These special cases dispatch to special-case constructors that allow us to
// avoid an extra function call and shrink non-LTO binaries by a percent or so.
#define ABSL_LOG_INTERNAL_CHECK(failure_message) \
::absl::log_internal::LogMessageFatal(__FILE__, __LINE__, failure_message)
#define ABSL_LOG_INTERNAL_QCHECK(failure_message) \
::absl::log_internal::LogMessageQuietlyFatal(__FILE__, __LINE__, \
failure_message)
#endif // !defined(STRIP_LOG) || !STRIP_LOG
// This part of a non-fatal `DLOG`s expands the same as `LOG`.
#define ABSL_LOGGING_INTERNAL_DLOG_INFO ABSL_LOGGING_INTERNAL_LOG_INFO
#define ABSL_LOGGING_INTERNAL_DLOG_WARNING ABSL_LOGGING_INTERNAL_LOG_WARNING
#define ABSL_LOGGING_INTERNAL_DLOG_ERROR ABSL_LOGGING_INTERNAL_LOG_ERROR
#define ABSL_LOGGING_INTERNAL_DLOG_DFATAL ABSL_LOGGING_INTERNAL_LOG_DFATAL
#define ABSL_LOGGING_INTERNAL_DLOG_LEVEL ABSL_LOGGING_INTERNAL_LOG_LEVEL
#define ABSL_LOGGING_INTERNAL_LOG_DO_NOT_SUBMIT ABSL_LOGGING_INTERNAL_LOG_ERROR
#endif // ABSL_LOG_INTERNAL_STRIP_H_
*ÿ
osoong/.intermediates/external/abseil-cpp/absl_strings_hdrs/gen/my_include_dir/absl/strings/has_absl_stringify.h‹// Copyright 2022 The Abseil Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_STRINGS_HAS_ABSL_STRINGIFY_H_
#define ABSL_STRINGS_HAS_ABSL_STRINGIFY_H_
#include <type_traits>
#include <utility>
#include "absl/base/config.h"
#include "absl/strings/string_view.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace strings_internal {
// This is an empty class not intended to be used. It exists so that
// `HasAbslStringify` can reference a universal class rather than needing to be
// copied for each new sink.
class UnimplementedSink {
public:
void Append(size_t count, char ch);
void Append(string_view v);
// Support `absl::Format(&sink, format, args...)`.
friend void AbslFormatFlush(UnimplementedSink* sink, absl::string_view v);
};
} // namespace strings_internal
// `HasAbslStringify<T>` detects if type `T` supports the `AbslStringify()`
// customization point (see
// https://abseil.io/docs/cpp/guides/format#abslstringify for the
// documentation).
//
// Note that there are types that can be `StrCat`-ed that do not use the
// `AbslStringify` customization point (for example, `int`).
template <typename T, typename = void>
struct HasAbslStringify : std::false_type {};
template <typename T>
struct HasAbslStringify<
T, std::enable_if_t<std::is_void<decltype(AbslStringify(
std::declval<strings_internal::UnimplementedSink&>(),
std::declval<const T&>()))>::value>> : std::true_type {};
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_HAS_ABSL_STRINGIFY_H_
*âª
œsoong/.intermediates/external/abseil-cpp/absl_time_internal_cctz_civil_time_hdrs/gen/my_include_dir/absl/time/internal/cctz/include/cctz/civil_time_detail.h¿©// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_DETAIL_H_
#define ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_DETAIL_H_
#include <cstdint>
#include <limits>
#include <ostream>
#include <type_traits>
#include "absl/base/config.h"
// Disable constexpr support unless we are in C++14 mode.
#if __cpp_constexpr >= 201304 || (defined(_MSC_VER) && _MSC_VER >= 1910)
#define CONSTEXPR_D constexpr // data
#define CONSTEXPR_F constexpr // function
#define CONSTEXPR_M constexpr // member
#else
#define CONSTEXPR_D const
#define CONSTEXPR_F inline
#define CONSTEXPR_M
#endif
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace time_internal {
namespace cctz {
// Support years that at least span the range of 64-bit time_t values.
using year_t = std::int_fast64_t;
// Type alias that indicates an argument is not normalized (e.g., the
// constructor parameters and operands/results of addition/subtraction).
using diff_t = std::int_fast64_t;
namespace detail {
// Type aliases that indicate normalized argument values.
using month_t = std::int_fast8_t; // [1:12]
using day_t = std::int_fast8_t; // [1:31]
using hour_t = std::int_fast8_t; // [0:23]
using minute_t = std::int_fast8_t; // [0:59]
using second_t = std::int_fast8_t; // [0:59]
// Normalized civil-time fields: Y-M-D HH:MM:SS.
struct fields {
CONSTEXPR_M fields(year_t year, month_t month, day_t day, hour_t hour,
minute_t minute, second_t second)
: y(year), m(month), d(day), hh(hour), mm(minute), ss(second) {}
std::int_least64_t y;
std::int_least8_t m;
std::int_least8_t d;
std::int_least8_t hh;
std::int_least8_t mm;
std::int_least8_t ss;
};
struct second_tag {};
struct minute_tag : second_tag {};
struct hour_tag : minute_tag {};
struct day_tag : hour_tag {};
struct month_tag : day_tag {};
struct year_tag : month_tag {};
////////////////////////////////////////////////////////////////////////
// Field normalization (without avoidable overflow).
namespace impl {
CONSTEXPR_F bool is_leap_year(year_t y) noexcept {
return y % 4 == 0 && (y % 100 != 0 || y % 400 == 0);
}
CONSTEXPR_F int year_index(year_t y, month_t m) noexcept {
const int yi = static_cast<int>((y + (m > 2)) % 400);
return yi < 0 ? yi + 400 : yi;
}
CONSTEXPR_F int days_per_century(int yi) noexcept {
return 36524 + (yi == 0 || yi > 300);
}
CONSTEXPR_F int days_per_4years(int yi) noexcept {
return 1460 + (yi == 0 || yi > 300 || (yi - 1) % 100 < 96);
}
CONSTEXPR_F int days_per_year(year_t y, month_t m) noexcept {
return is_leap_year(y + (m > 2)) ? 366 : 365;
}
CONSTEXPR_F int days_per_month(year_t y, month_t m) noexcept {
CONSTEXPR_D int k_days_per_month[1 + 12] = {
-1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 // non leap year
};
return k_days_per_month[m] + (m == 2 && is_leap_year(y));
}
CONSTEXPR_F fields n_day(year_t y, month_t m, diff_t d, diff_t cd, hour_t hh,
minute_t mm, second_t ss) noexcept {
year_t ey = y % 400;
const year_t oey = ey;
ey += (cd / 146097) * 400;
cd %= 146097;
if (cd < 0) {
ey -= 400;
cd += 146097;
}
ey += (d / 146097) * 400;
d = d % 146097 + cd;
if (d > 0) {
if (d > 146097) {
ey += 400;
d -= 146097;
}
} else {
if (d > -365) {
// We often hit the previous year when stepping a civil time backwards,
// so special case it to avoid counting up by 100/4/1-year chunks.
ey -= 1;
d += days_per_year(ey, m);
} else {
ey -= 400;
d += 146097;
}
}
if (d > 365) {
int yi = year_index(ey, m); // Index into Gregorian 400 year cycle.
for (;;) {
int n = days_per_century(yi);
if (d <= n) break;
d -= n;
ey += 100;
yi += 100;
if (yi >= 400) yi -= 400;
}
for (;;) {
int n = days_per_4years(yi);
if (d <= n) break;
d -= n;
ey += 4;
yi += 4;
if (yi >= 400) yi -= 400;
}
for (;;) {
int n = days_per_year(ey, m);
if (d <= n) break;
d -= n;
++ey;
}
}
if (d > 28) {
for (;;) {
int n = days_per_month(ey, m);
if (d <= n) break;
d -= n;
if (++m > 12) {
++ey;
m = 1;
}
}
}
return fields(y + (ey - oey), m, static_cast<day_t>(d), hh, mm, ss);
}
CONSTEXPR_F fields n_mon(year_t y, diff_t m, diff_t d, diff_t cd, hour_t hh,
minute_t mm, second_t ss) noexcept {
if (m != 12) {
y += m / 12;
m %= 12;
if (m <= 0) {
y -= 1;
m += 12;
}
}
return n_day(y, static_cast<month_t>(m), d, cd, hh, mm, ss);
}
CONSTEXPR_F fields n_hour(year_t y, diff_t m, diff_t d, diff_t cd, diff_t hh,
minute_t mm, second_t ss) noexcept {
cd += hh / 24;
hh %= 24;
if (hh < 0) {
cd -= 1;
hh += 24;
}
return n_mon(y, m, d, cd, static_cast<hour_t>(hh), mm, ss);
}
CONSTEXPR_F fields n_min(year_t y, diff_t m, diff_t d, diff_t hh, diff_t ch,
diff_t mm, second_t ss) noexcept {
ch += mm / 60;
mm %= 60;
if (mm < 0) {
ch -= 1;
mm += 60;
}
return n_hour(y, m, d, hh / 24 + ch / 24, hh % 24 + ch % 24,
static_cast<minute_t>(mm), ss);
}
CONSTEXPR_F fields n_sec(year_t y, diff_t m, diff_t d, diff_t hh, diff_t mm,
diff_t ss) noexcept {
// Optimization for when (non-constexpr) fields are already normalized.
if (0 <= ss && ss < 60) {
const second_t nss = static_cast<second_t>(ss);
if (0 <= mm && mm < 60) {
const minute_t nmm = static_cast<minute_t>(mm);
if (0 <= hh && hh < 24) {
const hour_t nhh = static_cast<hour_t>(hh);
if (1 <= d && d <= 28 && 1 <= m && m <= 12) {
const day_t nd = static_cast<day_t>(d);
const month_t nm = static_cast<month_t>(m);
return fields(y, nm, nd, nhh, nmm, nss);
}
return n_mon(y, m, d, 0, nhh, nmm, nss);
}
return n_hour(y, m, d, hh / 24, hh % 24, nmm, nss);
}
return n_min(y, m, d, hh, mm / 60, mm % 60, nss);
}
diff_t cm = ss / 60;
ss %= 60;
if (ss < 0) {
cm -= 1;
ss += 60;
}
return n_min(y, m, d, hh, mm / 60 + cm / 60, mm % 60 + cm % 60,
static_cast<second_t>(ss));
}
} // namespace impl
////////////////////////////////////////////////////////////////////////
// Increments the indicated (normalized) field by "n".
CONSTEXPR_F fields step(second_tag, fields f, diff_t n) noexcept {
return impl::n_sec(f.y, f.m, f.d, f.hh, f.mm + n / 60, f.ss + n % 60);
}
CONSTEXPR_F fields step(minute_tag, fields f, diff_t n) noexcept {
return impl::n_min(f.y, f.m, f.d, f.hh + n / 60, 0, f.mm + n % 60, f.ss);
}
CONSTEXPR_F fields step(hour_tag, fields f, diff_t n) noexcept {
return impl::n_hour(f.y, f.m, f.d + n / 24, 0, f.hh + n % 24, f.mm, f.ss);
}
CONSTEXPR_F fields step(day_tag, fields f, diff_t n) noexcept {
return impl::n_day(f.y, f.m, f.d, n, f.hh, f.mm, f.ss);
}
CONSTEXPR_F fields step(month_tag, fields f, diff_t n) noexcept {
return impl::n_mon(f.y + n / 12, f.m + n % 12, f.d, 0, f.hh, f.mm, f.ss);
}
CONSTEXPR_F fields step(year_tag, fields f, diff_t n) noexcept {
return fields(f.y + n, f.m, f.d, f.hh, f.mm, f.ss);
}
////////////////////////////////////////////////////////////////////////
namespace impl {
// Returns (v * f + a) but avoiding intermediate overflow when possible.
CONSTEXPR_F diff_t scale_add(diff_t v, diff_t f, diff_t a) noexcept {
return (v < 0) ? ((v + 1) * f + a) - f : ((v - 1) * f + a) + f;
}
// Map a (normalized) Y/M/D to the number of days before/after 1970-01-01.
// Probably overflows for years outside [-292277022656:292277026595].
CONSTEXPR_F diff_t ymd_ord(year_t y, month_t m, day_t d) noexcept {
const diff_t eyear = (m <= 2) ? y - 1 : y;
const diff_t era = (eyear >= 0 ? eyear : eyear - 399) / 400;
const diff_t yoe = eyear - era * 400;
const diff_t doy = (153 * (m + (m > 2 ? -3 : 9)) + 2) / 5 + d - 1;
const diff_t doe = yoe * 365 + yoe / 4 - yoe / 100 + doy;
return era * 146097 + doe - 719468;
}
// Returns the difference in days between two normalized Y-M-D tuples.
// ymd_ord() will encounter integer overflow given extreme year values,
// yet the difference between two such extreme values may actually be
// small, so we take a little care to avoid overflow when possible by
// exploiting the 146097-day cycle.
CONSTEXPR_F diff_t day_difference(year_t y1, month_t m1, day_t d1, year_t y2,
month_t m2, day_t d2) noexcept {
const diff_t a_c4_off = y1 % 400;
const diff_t b_c4_off = y2 % 400;
diff_t c4_diff = (y1 - a_c4_off) - (y2 - b_c4_off);
diff_t delta = ymd_ord(a_c4_off, m1, d1) - ymd_ord(b_c4_off, m2, d2);
if (c4_diff > 0 && delta < 0) {
delta += 2 * 146097;
c4_diff -= 2 * 400;
} else if (c4_diff < 0 && delta > 0) {
delta -= 2 * 146097;
c4_diff += 2 * 400;
}
return (c4_diff / 400 * 146097) + delta;
}
} // namespace impl
// Returns the difference between fields structs using the indicated unit.
CONSTEXPR_F diff_t difference(year_tag, fields f1, fields f2) noexcept {
return f1.y - f2.y;
}
CONSTEXPR_F diff_t difference(month_tag, fields f1, fields f2) noexcept {
return impl::scale_add(difference(year_tag{}, f1, f2), 12, (f1.m - f2.m));
}
CONSTEXPR_F diff_t difference(day_tag, fields f1, fields f2) noexcept {
return impl::day_difference(f1.y, f1.m, f1.d, f2.y, f2.m, f2.d);
}
CONSTEXPR_F diff_t difference(hour_tag, fields f1, fields f2) noexcept {
return impl::scale_add(difference(day_tag{}, f1, f2), 24, (f1.hh - f2.hh));
}
CONSTEXPR_F diff_t difference(minute_tag, fields f1, fields f2) noexcept {
return impl::scale_add(difference(hour_tag{}, f1, f2), 60, (f1.mm - f2.mm));
}
CONSTEXPR_F diff_t difference(second_tag, fields f1, fields f2) noexcept {
return impl::scale_add(difference(minute_tag{}, f1, f2), 60, f1.ss - f2.ss);
}
////////////////////////////////////////////////////////////////////////
// Aligns the (normalized) fields struct to the indicated field.
CONSTEXPR_F fields align(second_tag, fields f) noexcept { return f; }
CONSTEXPR_F fields align(minute_tag, fields f) noexcept {
return fields{f.y, f.m, f.d, f.hh, f.mm, 0};
}
CONSTEXPR_F fields align(hour_tag, fields f) noexcept {
return fields{f.y, f.m, f.d, f.hh, 0, 0};
}
CONSTEXPR_F fields align(day_tag, fields f) noexcept {
return fields{f.y, f.m, f.d, 0, 0, 0};
}
CONSTEXPR_F fields align(month_tag, fields f) noexcept {
return fields{f.y, f.m, 1, 0, 0, 0};
}
CONSTEXPR_F fields align(year_tag, fields f) noexcept {
return fields{f.y, 1, 1, 0, 0, 0};
}
////////////////////////////////////////////////////////////////////////
namespace impl {
template <typename H>
H AbslHashValueImpl(second_tag, H h, fields f) {
return H::combine(std::move(h), f.y, f.m, f.d, f.hh, f.mm, f.ss);
}
template <typename H>
H AbslHashValueImpl(minute_tag, H h, fields f) {
return H::combine(std::move(h), f.y, f.m, f.d, f.hh, f.mm);
}
template <typename H>
H AbslHashValueImpl(hour_tag, H h, fields f) {
return H::combine(std::move(h), f.y, f.m, f.d, f.hh);
}
template <typename H>
H AbslHashValueImpl(day_tag, H h, fields f) {
return H::combine(std::move(h), f.y, f.m, f.d);
}
template <typename H>
H AbslHashValueImpl(month_tag, H h, fields f) {
return H::combine(std::move(h), f.y, f.m);
}
template <typename H>
H AbslHashValueImpl(year_tag, H h, fields f) {
return H::combine(std::move(h), f.y);
}
} // namespace impl
////////////////////////////////////////////////////////////////////////
template <typename T>
class civil_time {
public:
explicit CONSTEXPR_M civil_time(year_t y, diff_t m = 1, diff_t d = 1,
diff_t hh = 0, diff_t mm = 0,
diff_t ss = 0) noexcept
: civil_time(impl::n_sec(y, m, d, hh, mm, ss)) {}
CONSTEXPR_M civil_time() noexcept : f_{1970, 1, 1, 0, 0, 0} {}
civil_time(const civil_time&) = default;
civil_time& operator=(const civil_time&) = default;
// Conversion between civil times of different alignment. Conversion to
// a more precise alignment is allowed implicitly (e.g., day -> hour),
// but conversion where information is discarded must be explicit
// (e.g., second -> minute).
template <typename U, typename S>
using preserves_data =
typename std::enable_if<std::is_base_of<U, S>::value>::type;
template <typename U>
CONSTEXPR_M civil_time(const civil_time<U>& ct,
preserves_data<T, U>* = nullptr) noexcept
: civil_time(ct.f_) {}
template <typename U>
explicit CONSTEXPR_M civil_time(const civil_time<U>& ct,
preserves_data<U, T>* = nullptr) noexcept
: civil_time(ct.f_) {}
// Factories for the maximum/minimum representable civil_time.
static CONSTEXPR_F auto(max)() -> civil_time {
const auto max_year = (std::numeric_limits<std::int_least64_t>::max)();
return civil_time(max_year, 12, 31, 23, 59, 59);
}
static CONSTEXPR_F auto(min)() -> civil_time {
const auto min_year = (std::numeric_limits<std::int_least64_t>::min)();
return civil_time(min_year, 1, 1, 0, 0, 0);
}
// Field accessors. Note: All but year() return an int.
CONSTEXPR_M year_t year() const noexcept { return f_.y; }
CONSTEXPR_M int month() const noexcept { return f_.m; }
CONSTEXPR_M int day() const noexcept { return f_.d; }
CONSTEXPR_M int hour() const noexcept { return f_.hh; }
CONSTEXPR_M int minute() const noexcept { return f_.mm; }
CONSTEXPR_M int second() const noexcept { return f_.ss; }
// Assigning arithmetic.
CONSTEXPR_M civil_time& operator+=(diff_t n) noexcept {
return *this = *this + n;
}
CONSTEXPR_M civil_time& operator-=(diff_t n) noexcept {
return *this = *this - n;
}
CONSTEXPR_M civil_time& operator++() noexcept { return *this += 1; }
CONSTEXPR_M civil_time operator++(int) noexcept {
const civil_time a = *this;
++*this;
return a;
}
CONSTEXPR_M civil_time& operator--() noexcept { return *this -= 1; }
CONSTEXPR_M civil_time operator--(int) noexcept {
const civil_time a = *this;
--*this;
return a;
}
// Binary arithmetic operators.
friend CONSTEXPR_F civil_time operator+(civil_time a, diff_t n) noexcept {
return civil_time(step(T{}, a.f_, n));
}
friend CONSTEXPR_F civil_time operator+(diff_t n, civil_time a) noexcept {
return a + n;
}
friend CONSTEXPR_F civil_time operator-(civil_time a, diff_t n) noexcept {
return n != (std::numeric_limits<diff_t>::min)()
? civil_time(step(T{}, a.f_, -n))
: civil_time(step(T{}, step(T{}, a.f_, -(n + 1)), 1));
}
friend CONSTEXPR_F diff_t operator-(civil_time lhs, civil_time rhs) noexcept {
return difference(T{}, lhs.f_, rhs.f_);
}
template <typename H>
friend H AbslHashValue(H h, civil_time a) {
return impl::AbslHashValueImpl(T{}, std::move(h), a.f_);
}
private:
// All instantiations of this template are allowed to call the following
// private constructor and access the private fields member.
template <typename U>
friend class civil_time;
// The designated constructor that all others eventually call.
explicit CONSTEXPR_M civil_time(fields f) noexcept : f_(align(T{}, f)) {}
fields f_;
};
// Disallows difference between differently aligned types.
// auto n = civil_day(...) - civil_hour(...); // would be confusing.
template <typename T, typename U>
CONSTEXPR_F diff_t operator-(civil_time<T>, civil_time<U>) = delete;
using civil_year = civil_time<year_tag>;
using civil_month = civil_time<month_tag>;
using civil_day = civil_time<day_tag>;
using civil_hour = civil_time<hour_tag>;
using civil_minute = civil_time<minute_tag>;
using civil_second = civil_time<second_tag>;
////////////////////////////////////////////////////////////////////////
// Relational operators that work with differently aligned objects.
// Always compares all six fields.
template <typename T1, typename T2>
CONSTEXPR_F bool operator<(const civil_time<T1>& lhs,
const civil_time<T2>& rhs) noexcept {
return (
lhs.year() < rhs.year() ||
(lhs.year() == rhs.year() &&
(lhs.month() < rhs.month() ||
(lhs.month() == rhs.month() &&
(lhs.day() < rhs.day() || (lhs.day() == rhs.day() &&
(lhs.hour() < rhs.hour() ||
(lhs.hour() == rhs.hour() &&
(lhs.minute() < rhs.minute() ||
(lhs.minute() == rhs.minute() &&
(lhs.second() < rhs.second())))))))))));
}
template <typename T1, typename T2>
CONSTEXPR_F bool operator<=(const civil_time<T1>& lhs,
const civil_time<T2>& rhs) noexcept {
return !(rhs < lhs);
}
template <typename T1, typename T2>
CONSTEXPR_F bool operator>=(const civil_time<T1>& lhs,
const civil_time<T2>& rhs) noexcept {
return !(lhs < rhs);
}
template <typename T1, typename T2>
CONSTEXPR_F bool operator>(const civil_time<T1>& lhs,
const civil_time<T2>& rhs) noexcept {
return rhs < lhs;
}
template <typename T1, typename T2>
CONSTEXPR_F bool operator==(const civil_time<T1>& lhs,
const civil_time<T2>& rhs) noexcept {
return lhs.year() == rhs.year() && lhs.month() == rhs.month() &&
lhs.day() == rhs.day() && lhs.hour() == rhs.hour() &&
lhs.minute() == rhs.minute() && lhs.second() == rhs.second();
}
template <typename T1, typename T2>
CONSTEXPR_F bool operator!=(const civil_time<T1>& lhs,
const civil_time<T2>& rhs) noexcept {
return !(lhs == rhs);
}
////////////////////////////////////////////////////////////////////////
enum class weekday {
monday,
tuesday,
wednesday,
thursday,
friday,
saturday,
sunday,
};
CONSTEXPR_F weekday get_weekday(const civil_second& cs) noexcept {
CONSTEXPR_D weekday k_weekday_by_mon_off[13] = {
weekday::monday, weekday::tuesday, weekday::wednesday,
weekday::thursday, weekday::friday, weekday::saturday,
weekday::sunday, weekday::monday, weekday::tuesday,
weekday::wednesday, weekday::thursday, weekday::friday,
weekday::saturday,
};
CONSTEXPR_D int k_weekday_offsets[1 + 12] = {
-1, 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4,
};
year_t wd = 2400 + (cs.year() % 400) - (cs.month() < 3);
wd += wd / 4 - wd / 100 + wd / 400;
wd += k_weekday_offsets[cs.month()] + cs.day();
return k_weekday_by_mon_off[wd % 7 + 6];
}
////////////////////////////////////////////////////////////////////////
CONSTEXPR_F civil_day next_weekday(civil_day cd, weekday wd) noexcept {
CONSTEXPR_D weekday k_weekdays_forw[14] = {
weekday::monday, weekday::tuesday, weekday::wednesday,
weekday::thursday, weekday::friday, weekday::saturday,
weekday::sunday, weekday::monday, weekday::tuesday,
weekday::wednesday, weekday::thursday, weekday::friday,
weekday::saturday, weekday::sunday,
};
weekday base = get_weekday(cd);
for (int i = 0;; ++i) {
if (base == k_weekdays_forw[i]) {
for (int j = i + 1;; ++j) {
if (wd == k_weekdays_forw[j]) {
return cd + (j - i);
}
}
}
}
}
CONSTEXPR_F civil_day prev_weekday(civil_day cd, weekday wd) noexcept {
CONSTEXPR_D weekday k_weekdays_back[14] = {
weekday::sunday, weekday::saturday, weekday::friday,
weekday::thursday, weekday::wednesday, weekday::tuesday,
weekday::monday, weekday::sunday, weekday::saturday,
weekday::friday, weekday::thursday, weekday::wednesday,
weekday::tuesday, weekday::monday,
};
weekday base = get_weekday(cd);
for (int i = 0;; ++i) {
if (base == k_weekdays_back[i]) {
for (int j = i + 1;; ++j) {
if (wd == k_weekdays_back[j]) {
return cd - (j - i);
}
}
}
}
}
CONSTEXPR_F int get_yearday(const civil_second& cs) noexcept {
CONSTEXPR_D int k_month_offsets[1 + 12] = {
-1, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334,
};
const int feb29 = (cs.month() > 2 && impl::is_leap_year(cs.year()));
return k_month_offsets[cs.month()] + feb29 + cs.day();
}
////////////////////////////////////////////////////////////////////////
std::ostream& operator<<(std::ostream& os, const civil_year& y);
std::ostream& operator<<(std::ostream& os, const civil_month& m);
std::ostream& operator<<(std::ostream& os, const civil_day& d);
std::ostream& operator<<(std::ostream& os, const civil_hour& h);
std::ostream& operator<<(std::ostream& os, const civil_minute& m);
std::ostream& operator<<(std::ostream& os, const civil_second& s);
std::ostream& operator<<(std::ostream& os, weekday wd);
} // namespace detail
} // namespace cctz
} // namespace time_internal
ABSL_NAMESPACE_END
} // namespace absl
#undef CONSTEXPR_M
#undef CONSTEXPR_F
#undef CONSTEXPR_D
#endif // ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_DETAIL_H_
*ÎA
œsoong/.intermediates/external/abseil-cpp/absl_synchronization_kernel_timeout_internal_hdrs/gen/my_include_dir/absl/synchronization/internal/kernel_timeout.h¬@// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_SYNCHRONIZATION_INTERNAL_KERNEL_TIMEOUT_H_
#define ABSL_SYNCHRONIZATION_INTERNAL_KERNEL_TIMEOUT_H_
#ifndef _WIN32
#include <sys/types.h>
#endif
#include <algorithm>
#include <chrono> // NOLINT(build/c++11)
#include <cstdint>
#include <ctime>
#include <limits>
#include "absl/base/config.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/time/clock.h"
#include "absl/time/time.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace synchronization_internal {
// An optional timeout, with nanosecond granularity.
//
// This is a private low-level API for use by a handful of low-level
// components. Higher-level components should build APIs based on
// absl::Time and absl::Duration.
class KernelTimeout {
public:
// Construct an absolute timeout that should expire at `t`.
explicit KernelTimeout(absl::Time t);
// Construct a relative timeout that should expire after `d`.
explicit KernelTimeout(absl::Duration d);
// Infinite timeout.
constexpr KernelTimeout() : rep_(kNoTimeout) {}
// A more explicit factory for those who prefer it.
// Equivalent to `KernelTimeout()`.
static constexpr KernelTimeout Never() { return KernelTimeout(); }
// Returns true if there is a timeout that will eventually expire.
// Returns false if the timeout is infinite.
bool has_timeout() const { return rep_ != kNoTimeout; }
// If `has_timeout()` is true, returns true if the timeout was provided as an
// `absl::Time`. The return value is undefined if `has_timeout()` is false
// because all indefinite timeouts are equivalent.
bool is_absolute_timeout() const { return (rep_ & 1) == 0; }
// If `has_timeout()` is true, returns true if the timeout was provided as an
// `absl::Duration`. The return value is undefined if `has_timeout()` is false
// because all indefinite timeouts are equivalent.
bool is_relative_timeout() const { return (rep_ & 1) == 1; }
// Convert to `struct timespec` for interfaces that expect an absolute
// timeout. If !has_timeout() or is_relative_timeout(), attempts to convert to
// a reasonable absolute timeout, but callers should to test has_timeout() and
// is_relative_timeout() and prefer to use a more appropriate interface.
struct timespec MakeAbsTimespec() const;
// Convert to `struct timespec` for interfaces that expect a relative
// timeout. If !has_timeout() or is_absolute_timeout(), attempts to convert to
// a reasonable relative timeout, but callers should to test has_timeout() and
// is_absolute_timeout() and prefer to use a more appropriate interface. Since
// the return value is a relative duration, it should be recomputed by calling
// this method in the case of a spurious wakeup.
struct timespec MakeRelativeTimespec() const;
#ifndef _WIN32
// Convert to `struct timespec` for interfaces that expect an absolute timeout
// on a specific clock `c`. This is similar to `MakeAbsTimespec()`, but
// callers usually want to use this method with `CLOCK_MONOTONIC` when
// relative timeouts are requested, and when the appropriate interface expects
// an absolute timeout relative to a specific clock (for example,
// pthread_cond_clockwait() or sem_clockwait()). If !has_timeout(), attempts
// to convert to a reasonable absolute timeout, but callers should to test
// has_timeout() prefer to use a more appropriate interface.
struct timespec MakeClockAbsoluteTimespec(clockid_t c) const;
#endif
// Convert to unix epoch nanos for interfaces that expect an absolute timeout
// in nanoseconds. If !has_timeout() or is_relative_timeout(), attempts to
// convert to a reasonable absolute timeout, but callers should to test
// has_timeout() and is_relative_timeout() and prefer to use a more
// appropriate interface.
int64_t MakeAbsNanos() const;
// Converts to milliseconds from now, or INFINITE when
// !has_timeout(). For use by SleepConditionVariableSRW on
// Windows. Callers should recognize that the return value is a
// relative duration (it should be recomputed by calling this method
// in the case of a spurious wakeup).
// This header file may be included transitively by public header files,
// so we define our own DWORD and INFINITE instead of getting them from
// <intsafe.h> and <WinBase.h>.
typedef unsigned long DWord; // NOLINT
DWord InMillisecondsFromNow() const;
// Convert to std::chrono::time_point for interfaces that expect an absolute
// timeout, like std::condition_variable::wait_until(). If !has_timeout() or
// is_relative_timeout(), attempts to convert to a reasonable absolute
// timeout, but callers should test has_timeout() and is_relative_timeout()
// and prefer to use a more appropriate interface.
std::chrono::time_point<std::chrono::system_clock> ToChronoTimePoint() const;
// Convert to std::chrono::time_point for interfaces that expect a relative
// timeout, like std::condition_variable::wait_for(). If !has_timeout() or
// is_absolute_timeout(), attempts to convert to a reasonable relative
// timeout, but callers should test has_timeout() and is_absolute_timeout()
// and prefer to use a more appropriate interface. Since the return value is a
// relative duration, it should be recomputed by calling this method in the
// case of a spurious wakeup.
std::chrono::nanoseconds ToChronoDuration() const;
// Returns true if steady (aka monotonic) clocks are supported by the system.
// This method exists because go/btm requires synchronized clocks, and
// thus requires we use the system (aka walltime) clock.
static constexpr bool SupportsSteadyClock() { return true; }
private:
// Returns the current time, expressed as a count of nanoseconds since the
// epoch used by an arbitrary clock. The implementation tries to use a steady
// (monotonic) clock if one is available.
static int64_t SteadyClockNow();
// Internal representation.
// - If the value is kNoTimeout, then the timeout is infinite, and
// has_timeout() will return true.
// - If the low bit is 0, then the high 63 bits is the number of nanoseconds
// after the unix epoch.
// - If the low bit is 1, then the high 63 bits is the number of nanoseconds
// after the epoch used by SteadyClockNow().
//
// In all cases the time is stored as an absolute time, the only difference is
// the clock epoch. The use of absolute times is important since in the case
// of a relative timeout with a spurious wakeup, the program would have to
// restart the wait, and thus needs a way of recomputing the remaining time.
uint64_t rep_;
// Returns the number of nanoseconds stored in the internal representation.
// When combined with the clock epoch indicated by the low bit (which is
// accessed through is_absolute_timeout() and is_relative_timeout()), the
// return value is used to compute when the timeout should occur.
int64_t RawAbsNanos() const { return static_cast<int64_t>(rep_ >> 1); }
// Converts to nanoseconds from now. Since the return value is a relative
// duration, it should be recomputed by calling this method in the case of a
// spurious wakeup.
int64_t InNanosecondsFromNow() const;
// A value that represents no timeout (or an infinite timeout).
static constexpr uint64_t kNoTimeout = (std::numeric_limits<uint64_t>::max)();
// The maximum value that can be stored in the high 63 bits.
static constexpr int64_t kMaxNanos = (std::numeric_limits<int64_t>::max)();
};
} // namespace synchronization_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_SYNCHRONIZATION_INTERNAL_KERNEL_TIMEOUT_H_
*ÑÑ
[soong/.intermediates/external/abseil-cpp/absl_time_hdrs/gen/my_include_dir/absl/time/time.hðÐ// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: time.h
// -----------------------------------------------------------------------------
//
// This header file defines abstractions for computing with absolute points
// in time, durations of time, and formatting and parsing time within a given
// time zone. The following abstractions are defined:
//
// * `absl::Time` defines an absolute, specific instance in time
// * `absl::Duration` defines a signed, fixed-length span of time
// * `absl::TimeZone` defines geopolitical time zone regions (as collected
// within the IANA Time Zone database (https://www.iana.org/time-zones)).
//
// Note: Absolute times are distinct from civil times, which refer to the
// human-scale time commonly represented by `YYYY-MM-DD hh:mm:ss`. The mapping
// between absolute and civil times can be specified by use of time zones
// (`absl::TimeZone` within this API). That is:
//
// Civil Time = F(Absolute Time, Time Zone)
// Absolute Time = G(Civil Time, Time Zone)
//
// See civil_time.h for abstractions related to constructing and manipulating
// civil time.
//
// Example:
//
// absl::TimeZone nyc;
// // LoadTimeZone() may fail so it's always better to check for success.
// if (!absl::LoadTimeZone("America/New_York", &nyc)) {
// // handle error case
// }
//
// // My flight leaves NYC on Jan 2, 2017 at 03:04:05
// absl::CivilSecond cs(2017, 1, 2, 3, 4, 5);
// absl::Time takeoff = absl::FromCivil(cs, nyc);
//
// absl::Duration flight_duration = absl::Hours(21) + absl::Minutes(35);
// absl::Time landing = takeoff + flight_duration;
//
// absl::TimeZone syd;
// if (!absl::LoadTimeZone("Australia/Sydney", &syd)) {
// // handle error case
// }
// std::string s = absl::FormatTime(
// "My flight will land in Sydney on %Y-%m-%d at %H:%M:%S",
// landing, syd);
#ifndef ABSL_TIME_TIME_H_
#define ABSL_TIME_TIME_H_
#if !defined(_MSC_VER)
#include <sys/time.h>
#else
// We don't include `winsock2.h` because it drags in `windows.h` and friends,
// and they define conflicting macros like OPAQUE, ERROR, and more. This has the
// potential to break Abseil users.
//
// Instead we only forward declare `timeval` and require Windows users include
// `winsock2.h` themselves. This is both inconsistent and troublesome, but so is
// including 'windows.h' so we are picking the lesser of two evils here.
struct timeval;
#endif
#include "absl/base/config.h"
// For feature testing and determining which headers can be included.
#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
#include <version>
#endif
#include <chrono> // NOLINT(build/c++11)
#include <cmath>
#ifdef __cpp_lib_three_way_comparison
#include <compare>
#endif // __cpp_lib_three_way_comparison
#include <cstdint>
#include <ctime>
#include <limits>
#include <ostream>
#include <ratio> // NOLINT(build/c++11)
#include <string>
#include <type_traits>
#include <utility>
#include "absl/base/attributes.h"
#include "absl/base/macros.h"
#include "absl/strings/string_view.h"
#include "absl/time/civil_time.h"
#include "absl/time/internal/cctz/include/cctz/time_zone.h"
#if defined(__cpp_impl_three_way_comparison) && \
defined(__cpp_lib_three_way_comparison)
#define ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON 1
#endif
namespace absl {
ABSL_NAMESPACE_BEGIN
class Duration; // Defined below
class Time; // Defined below
class TimeZone; // Defined below
namespace time_internal {
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromUnixDuration(Duration d);
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration ToUnixDuration(Time t);
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t GetRepHi(Duration d);
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr uint32_t GetRepLo(Duration d);
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration MakeDuration(int64_t hi,
uint32_t lo);
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration MakeDuration(int64_t hi,
int64_t lo);
ABSL_ATTRIBUTE_CONST_FUNCTION inline Duration MakePosDoubleDuration(double n);
constexpr int64_t kTicksPerNanosecond = 4;
constexpr int64_t kTicksPerSecond = 1000 * 1000 * 1000 * kTicksPerNanosecond;
template <std::intmax_t N>
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration FromInt64(int64_t v,
std::ratio<1, N>);
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration FromInt64(int64_t v,
std::ratio<60>);
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration FromInt64(int64_t v,
std::ratio<3600>);
template <typename T>
using EnableIfIntegral = typename std::enable_if<
std::is_integral<T>::value || std::is_enum<T>::value, int>::type;
template <typename T>
using EnableIfFloat =
typename std::enable_if<std::is_floating_point<T>::value, int>::type;
} // namespace time_internal
// Duration
//
// The `absl::Duration` class represents a signed, fixed-length amount of time.
// A `Duration` is generated using a unit-specific factory function, or is
// the result of subtracting one `absl::Time` from another. Durations behave
// like unit-safe integers and they support all the natural integer-like
// arithmetic operations. Arithmetic overflows and saturates at +/- infinity.
// `Duration` is trivially destructible and should be passed by value rather
// than const reference.
//
// Factory functions `Nanoseconds()`, `Microseconds()`, `Milliseconds()`,
// `Seconds()`, `Minutes()`, `Hours()` and `InfiniteDuration()` allow for
// creation of constexpr `Duration` values
//
// Examples:
//
// constexpr absl::Duration ten_ns = absl::Nanoseconds(10);
// constexpr absl::Duration min = absl::Minutes(1);
// constexpr absl::Duration hour = absl::Hours(1);
// absl::Duration dur = 60 * min; // dur == hour
// absl::Duration half_sec = absl::Milliseconds(500);
// absl::Duration quarter_sec = 0.25 * absl::Seconds(1);
//
// `Duration` values can be easily converted to an integral number of units
// using the division operator.
//
// Example:
//
// constexpr absl::Duration dur = absl::Milliseconds(1500);
// int64_t ns = dur / absl::Nanoseconds(1); // ns == 1500000000
// int64_t ms = dur / absl::Milliseconds(1); // ms == 1500
// int64_t sec = dur / absl::Seconds(1); // sec == 1 (subseconds truncated)
// int64_t min = dur / absl::Minutes(1); // min == 0
//
// See the `IDivDuration()` and `FDivDuration()` functions below for details on
// how to access the fractional parts of the quotient.
//
// Alternatively, conversions can be performed using helpers such as
// `ToInt64Microseconds()` and `ToDoubleSeconds()`.
class Duration {
public:
// Value semantics.
constexpr Duration() : rep_hi_(0), rep_lo_(0) {} // zero-length duration
// Copyable.
#if !defined(__clang__) && defined(_MSC_VER) && _MSC_VER < 1930
// Explicitly defining the constexpr copy constructor avoids an MSVC bug.
constexpr Duration(const Duration& d)
: rep_hi_(d.rep_hi_), rep_lo_(d.rep_lo_) {}
#else
constexpr Duration(const Duration& d) = default;
#endif
Duration& operator=(const Duration& d) = default;
// Compound assignment operators.
Duration& operator+=(Duration d);
Duration& operator-=(Duration d);
Duration& operator*=(int64_t r);
Duration& operator*=(double r);
Duration& operator/=(int64_t r);
Duration& operator/=(double r);
Duration& operator%=(Duration rhs);
// Overloads that forward to either the int64_t or double overloads above.
// Integer operands must be representable as int64_t. Integer division is
// truncating, so values less than the resolution will be returned as zero.
// Floating-point multiplication and division is rounding (halfway cases
// rounding away from zero), so values less than the resolution may be
// returned as either the resolution or zero. In particular, `d / 2.0`
// can produce `d` when it is the resolution and "even".
template <typename T, time_internal::EnableIfIntegral<T> = 0>
Duration& operator*=(T r) {
int64_t x = r;
return *this *= x;
}
template <typename T, time_internal::EnableIfIntegral<T> = 0>
Duration& operator/=(T r) {
int64_t x = r;
return *this /= x;
}
template <typename T, time_internal::EnableIfFloat<T> = 0>
Duration& operator*=(T r) {
double x = r;
return *this *= x;
}
template <typename T, time_internal::EnableIfFloat<T> = 0>
Duration& operator/=(T r) {
double x = r;
return *this /= x;
}
template <typename H>
friend H AbslHashValue(H h, Duration d) {
return H::combine(std::move(h), d.rep_hi_.Get(), d.rep_lo_);
}
private:
friend constexpr int64_t time_internal::GetRepHi(Duration d);
friend constexpr uint32_t time_internal::GetRepLo(Duration d);
friend constexpr Duration time_internal::MakeDuration(int64_t hi,
uint32_t lo);
constexpr Duration(int64_t hi, uint32_t lo) : rep_hi_(hi), rep_lo_(lo) {}
// We store `rep_hi_` 4-byte rather than 8-byte aligned to avoid 4 bytes of
// tail padding.
class HiRep {
public:
// Default constructor default-initializes `hi_`, which has the same
// semantics as default-initializing an `int64_t` (undetermined value).
HiRep() = default;
HiRep(const HiRep&) = default;
HiRep& operator=(const HiRep&) = default;
explicit constexpr HiRep(const int64_t value)
: // C++17 forbids default-initialization in constexpr contexts. We can
// remove this in C++20.
#if defined(ABSL_IS_BIG_ENDIAN) && ABSL_IS_BIG_ENDIAN
hi_(0),
lo_(0)
#else
lo_(0),
hi_(0)
#endif
{
*this = value;
}
constexpr int64_t Get() const {
const uint64_t unsigned_value =
(static_cast<uint64_t>(hi_) << 32) | static_cast<uint64_t>(lo_);
// `static_cast<int64_t>(unsigned_value)` is implementation-defined
// before c++20. On all supported platforms the behaviour is that mandated
// by c++20, i.e. "If the destination type is signed, [...] the result is
// the unique value of the destination type equal to the source value
// modulo 2^n, where n is the number of bits used to represent the
// destination type."
static_assert(
(static_cast<int64_t>((std::numeric_limits<uint64_t>::max)()) ==
int64_t{-1}) &&
(static_cast<int64_t>(static_cast<uint64_t>(
(std::numeric_limits<int64_t>::max)()) +
1) ==
(std::numeric_limits<int64_t>::min)()),
"static_cast<int64_t>(uint64_t) does not have c++20 semantics");
return static_cast<int64_t>(unsigned_value);
}
constexpr HiRep& operator=(const int64_t value) {
// "If the destination type is unsigned, the resulting value is the
// smallest unsigned value equal to the source value modulo 2^n
// where `n` is the number of bits used to represent the destination
// type".
const auto unsigned_value = static_cast<uint64_t>(value);
hi_ = static_cast<uint32_t>(unsigned_value >> 32);
lo_ = static_cast<uint32_t>(unsigned_value);
return *this;
}
private:
// Notes:
// - Ideally we would use a `char[]` and `std::bitcast`, but the latter
// does not exist (and is not constexpr in `absl`) before c++20.
// - Order is optimized depending on endianness so that the compiler can
// turn `Get()` (resp. `operator=()`) into a single 8-byte load (resp.
// store).
#if defined(ABSL_IS_BIG_ENDIAN) && ABSL_IS_BIG_ENDIAN
uint32_t hi_;
uint32_t lo_;
#else
uint32_t lo_;
uint32_t hi_;
#endif
};
HiRep rep_hi_;
uint32_t rep_lo_;
};
// Relational Operators
#ifdef ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr std::strong_ordering operator<=>(
Duration lhs, Duration rhs);
#endif // ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<(Duration lhs,
Duration rhs);
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator>(Duration lhs,
Duration rhs) {
return rhs < lhs;
}
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator>=(Duration lhs,
Duration rhs) {
return !(lhs < rhs);
}
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<=(Duration lhs,
Duration rhs) {
return !(rhs < lhs);
}
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator==(Duration lhs,
Duration rhs);
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator!=(Duration lhs,
Duration rhs) {
return !(lhs == rhs);
}
// Additive Operators
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration operator-(Duration d);
ABSL_ATTRIBUTE_CONST_FUNCTION inline Duration operator+(Duration lhs,
Duration rhs) {
return lhs += rhs;
}
ABSL_ATTRIBUTE_CONST_FUNCTION inline Duration operator-(Duration lhs,
Duration rhs) {
return lhs -= rhs;
}
// IDivDuration()
//
// Divides a numerator `Duration` by a denominator `Duration`, returning the
// quotient and remainder. The remainder always has the same sign as the
// numerator. The returned quotient and remainder respect the identity:
//
// numerator = denominator * quotient + remainder
//
// Returned quotients are capped to the range of `int64_t`, with the difference
// spilling into the remainder to uphold the above identity. This means that the
// remainder returned could differ from the remainder returned by
// `Duration::operator%` for huge quotients.
//
// See also the notes on `InfiniteDuration()` below regarding the behavior of
// division involving zero and infinite durations.
//
// Example:
//
// constexpr absl::Duration a =
// absl::Seconds(std::numeric_limits<int64_t>::max()); // big
// constexpr absl::Duration b = absl::Nanoseconds(1); // small
//
// absl::Duration rem = a % b;
// // rem == absl::ZeroDuration()
//
// // Here, q would overflow int64_t, so rem accounts for the difference.
// int64_t q = absl::IDivDuration(a, b, &rem);
// // q == std::numeric_limits<int64_t>::max(), rem == a - b * q
int64_t IDivDuration(Duration num, Duration den, Duration* rem);
// FDivDuration()
//
// Divides a `Duration` numerator into a fractional number of units of a
// `Duration` denominator.
//
// See also the notes on `InfiniteDuration()` below regarding the behavior of
// division involving zero and infinite durations.
//
// Example:
//
// double d = absl::FDivDuration(absl::Milliseconds(1500), absl::Seconds(1));
// // d == 1.5
ABSL_ATTRIBUTE_CONST_FUNCTION double FDivDuration(Duration num, Duration den);
// Multiplicative Operators
// Integer operands must be representable as int64_t.
template <typename T>
ABSL_ATTRIBUTE_CONST_FUNCTION Duration operator*(Duration lhs, T rhs) {
return lhs *= rhs;
}
template <typename T>
ABSL_ATTRIBUTE_CONST_FUNCTION Duration operator*(T lhs, Duration rhs) {
return rhs *= lhs;
}
template <typename T>
ABSL_ATTRIBUTE_CONST_FUNCTION Duration operator/(Duration lhs, T rhs) {
return lhs /= rhs;
}
ABSL_ATTRIBUTE_CONST_FUNCTION inline int64_t operator/(Duration lhs,
Duration rhs) {
return IDivDuration(lhs, rhs,
&lhs); // trunc towards zero
}
ABSL_ATTRIBUTE_CONST_FUNCTION inline Duration operator%(Duration lhs,
Duration rhs) {
return lhs %= rhs;
}
// ZeroDuration()
//
// Returns a zero-length duration. This function behaves just like the default
// constructor, but the name helps make the semantics clear at call sites.
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration ZeroDuration() {
return Duration();
}
// AbsDuration()
//
// Returns the absolute value of a duration.
ABSL_ATTRIBUTE_CONST_FUNCTION inline Duration AbsDuration(Duration d) {
return (d < ZeroDuration()) ? -d : d;
}
// Trunc()
//
// Truncates a duration (toward zero) to a multiple of a non-zero unit.
//
// Example:
//
// absl::Duration d = absl::Nanoseconds(123456789);
// absl::Duration a = absl::Trunc(d, absl::Microseconds(1)); // 123456us
ABSL_ATTRIBUTE_CONST_FUNCTION Duration Trunc(Duration d, Duration unit);
// Floor()
//
// Floors a duration using the passed duration unit to its largest value not
// greater than the duration.
//
// Example:
//
// absl::Duration d = absl::Nanoseconds(123456789);
// absl::Duration b = absl::Floor(d, absl::Microseconds(1)); // 123456us
ABSL_ATTRIBUTE_CONST_FUNCTION Duration Floor(Duration d, Duration unit);
// Ceil()
//
// Returns the ceiling of a duration using the passed duration unit to its
// smallest value not less than the duration.
//
// Example:
//
// absl::Duration d = absl::Nanoseconds(123456789);
// absl::Duration c = absl::Ceil(d, absl::Microseconds(1)); // 123457us
ABSL_ATTRIBUTE_CONST_FUNCTION Duration Ceil(Duration d, Duration unit);
// InfiniteDuration()
//
// Returns an infinite `Duration`. To get a `Duration` representing negative
// infinity, use `-InfiniteDuration()`.
//
// Duration arithmetic overflows to +/- infinity and saturates. In general,
// arithmetic with `Duration` infinities is similar to IEEE 754 infinities
// except where IEEE 754 NaN would be involved, in which case +/-
// `InfiniteDuration()` is used in place of a "nan" Duration.
//
// Examples:
//
// constexpr absl::Duration inf = absl::InfiniteDuration();
// const absl::Duration d = ... any finite duration ...
//
// inf == inf + inf
// inf == inf + d
// inf == inf - inf
// -inf == d - inf
//
// inf == d * 1e100
// inf == inf / 2
// 0 == d / inf
// INT64_MAX == inf / d
//
// d < inf
// -inf < d
//
// // Division by zero returns infinity, or INT64_MIN/MAX where appropriate.
// inf == d / 0
// INT64_MAX == d / absl::ZeroDuration()
//
// The examples involving the `/` operator above also apply to `IDivDuration()`
// and `FDivDuration()`.
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration InfiniteDuration();
// Nanoseconds()
// Microseconds()
// Milliseconds()
// Seconds()
// Minutes()
// Hours()
//
// Factory functions for constructing `Duration` values from an integral number
// of the unit indicated by the factory function's name. The number must be
// representable as int64_t.
//
// NOTE: no "Days()" factory function exists because "a day" is ambiguous.
// Civil days are not always 24 hours long, and a 24-hour duration often does
// not correspond with a civil day. If a 24-hour duration is needed, use
// `absl::Hours(24)`. If you actually want a civil day, use absl::CivilDay
// from civil_time.h.
//
// Example:
//
// absl::Duration a = absl::Seconds(60);
// absl::Duration b = absl::Minutes(1); // b == a
template <typename T, time_internal::EnableIfIntegral<T> = 0>
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration Nanoseconds(T n) {
return time_internal::FromInt64(n, std::nano{});
}
template <typename T, time_internal::EnableIfIntegral<T> = 0>
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration Microseconds(T n) {
return time_internal::FromInt64(n, std::micro{});
}
template <typename T, time_internal::EnableIfIntegral<T> = 0>
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration Milliseconds(T n) {
return time_internal::FromInt64(n, std::milli{});
}
template <typename T, time_internal::EnableIfIntegral<T> = 0>
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration Seconds(T n) {
return time_internal::FromInt64(n, std::ratio<1>{});
}
template <typename T, time_internal::EnableIfIntegral<T> = 0>
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration Minutes(T n) {
return time_internal::FromInt64(n, std::ratio<60>{});
}
template <typename T, time_internal::EnableIfIntegral<T> = 0>
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration Hours(T n) {
return time_internal::FromInt64(n, std::ratio<3600>{});
}
// Factory overloads for constructing `Duration` values from a floating-point
// number of the unit indicated by the factory function's name. These functions
// exist for convenience, but they are not as efficient as the integral
// factories, which should be preferred.
//
// Example:
//
// auto a = absl::Seconds(1.5); // OK
// auto b = absl::Milliseconds(1500); // BETTER
template <typename T, time_internal::EnableIfFloat<T> = 0>
ABSL_ATTRIBUTE_CONST_FUNCTION Duration Nanoseconds(T n) {
return n * Nanoseconds(1);
}
template <typename T, time_internal::EnableIfFloat<T> = 0>
ABSL_ATTRIBUTE_CONST_FUNCTION Duration Microseconds(T n) {
return n * Microseconds(1);
}
template <typename T, time_internal::EnableIfFloat<T> = 0>
ABSL_ATTRIBUTE_CONST_FUNCTION Duration Milliseconds(T n) {
return n * Milliseconds(1);
}
template <typename T, time_internal::EnableIfFloat<T> = 0>
ABSL_ATTRIBUTE_CONST_FUNCTION Duration Seconds(T n) {
if (n >= 0) { // Note: `NaN >= 0` is false.
if (n >= static_cast<T>((std::numeric_limits<int64_t>::max)())) {
return InfiniteDuration();
}
return time_internal::MakePosDoubleDuration(n);
} else {
if (std::isnan(n))
return std::signbit(n) ? -InfiniteDuration() : InfiniteDuration();
if (n <= (std::numeric_limits<int64_t>::min)()) return -InfiniteDuration();
return -time_internal::MakePosDoubleDuration(-n);
}
}
template <typename T, time_internal::EnableIfFloat<T> = 0>
ABSL_ATTRIBUTE_CONST_FUNCTION Duration Minutes(T n) {
return n * Minutes(1);
}
template <typename T, time_internal::EnableIfFloat<T> = 0>
ABSL_ATTRIBUTE_CONST_FUNCTION Duration Hours(T n) {
return n * Hours(1);
}
// ToInt64Nanoseconds()
// ToInt64Microseconds()
// ToInt64Milliseconds()
// ToInt64Seconds()
// ToInt64Minutes()
// ToInt64Hours()
//
// Helper functions that convert a Duration to an integral count of the
// indicated unit. These return the same results as the `IDivDuration()`
// function, though they usually do so more efficiently; see the
// documentation of `IDivDuration()` for details about overflow, etc.
//
// Example:
//
// absl::Duration d = absl::Milliseconds(1500);
// int64_t isec = absl::ToInt64Seconds(d); // isec == 1
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t ToInt64Nanoseconds(Duration d);
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t ToInt64Microseconds(Duration d);
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t ToInt64Milliseconds(Duration d);
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t ToInt64Seconds(Duration d);
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t ToInt64Minutes(Duration d);
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t ToInt64Hours(Duration d);
// ToDoubleNanoseconds()
// ToDoubleMicroseconds()
// ToDoubleMilliseconds()
// ToDoubleSeconds()
// ToDoubleMinutes()
// ToDoubleHours()
//
// Helper functions that convert a Duration to a floating point count of the
// indicated unit. These functions are shorthand for the `FDivDuration()`
// function above; see its documentation for details about overflow, etc.
//
// Example:
//
// absl::Duration d = absl::Milliseconds(1500);
// double dsec = absl::ToDoubleSeconds(d); // dsec == 1.5
ABSL_ATTRIBUTE_CONST_FUNCTION double ToDoubleNanoseconds(Duration d);
ABSL_ATTRIBUTE_CONST_FUNCTION double ToDoubleMicroseconds(Duration d);
ABSL_ATTRIBUTE_CONST_FUNCTION double ToDoubleMilliseconds(Duration d);
ABSL_ATTRIBUTE_CONST_FUNCTION double ToDoubleSeconds(Duration d);
ABSL_ATTRIBUTE_CONST_FUNCTION double ToDoubleMinutes(Duration d);
ABSL_ATTRIBUTE_CONST_FUNCTION double ToDoubleHours(Duration d);
// FromChrono()
//
// Converts any of the pre-defined std::chrono durations to an absl::Duration.
//
// Example:
//
// std::chrono::milliseconds ms(123);
// absl::Duration d = absl::FromChrono(ms);
ABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(
const std::chrono::nanoseconds& d);
ABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(
const std::chrono::microseconds& d);
ABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(
const std::chrono::milliseconds& d);
ABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(
const std::chrono::seconds& d);
ABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(
const std::chrono::minutes& d);
ABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(
const std::chrono::hours& d);
// ToChronoNanoseconds()
// ToChronoMicroseconds()
// ToChronoMilliseconds()
// ToChronoSeconds()
// ToChronoMinutes()
// ToChronoHours()
//
// Converts an absl::Duration to any of the pre-defined std::chrono durations.
// If overflow would occur, the returned value will saturate at the min/max
// chrono duration value instead.
//
// Example:
//
// absl::Duration d = absl::Microseconds(123);
// auto x = absl::ToChronoMicroseconds(d);
// auto y = absl::ToChronoNanoseconds(d); // x == y
// auto z = absl::ToChronoSeconds(absl::InfiniteDuration());
// // z == std::chrono::seconds::max()
ABSL_ATTRIBUTE_CONST_FUNCTION std::chrono::nanoseconds ToChronoNanoseconds(
Duration d);
ABSL_ATTRIBUTE_CONST_FUNCTION std::chrono::microseconds ToChronoMicroseconds(
Duration d);
ABSL_ATTRIBUTE_CONST_FUNCTION std::chrono::milliseconds ToChronoMilliseconds(
Duration d);
ABSL_ATTRIBUTE_CONST_FUNCTION std::chrono::seconds ToChronoSeconds(Duration d);
ABSL_ATTRIBUTE_CONST_FUNCTION std::chrono::minutes ToChronoMinutes(Duration d);
ABSL_ATTRIBUTE_CONST_FUNCTION std::chrono::hours ToChronoHours(Duration d);
// FormatDuration()
//
// Returns a string representing the duration in the form "72h3m0.5s".
// Returns "inf" or "-inf" for +/- `InfiniteDuration()`.
ABSL_ATTRIBUTE_CONST_FUNCTION std::string FormatDuration(Duration d);
// Output stream operator.
inline std::ostream& operator<<(std::ostream& os, Duration d) {
return os << FormatDuration(d);
}
// Support for StrFormat(), StrCat() etc.
template <typename Sink>
void AbslStringify(Sink& sink, Duration d) {
sink.Append(FormatDuration(d));
}
// ParseDuration()
//
// Parses a duration string consisting of a possibly signed sequence of
// decimal numbers, each with an optional fractional part and a unit
// suffix. The valid suffixes are "ns", "us" "ms", "s", "m", and "h".
// Simple examples include "300ms", "-1.5h", and "2h45m". Parses "0" as
// `ZeroDuration()`. Parses "inf" and "-inf" as +/- `InfiniteDuration()`.
bool ParseDuration(absl::string_view dur_string, Duration* d);
// AbslParseFlag()
//
// Parses a command-line flag string representation `text` into a Duration
// value. Duration flags must be specified in a format that is valid input for
// `absl::ParseDuration()`.
bool AbslParseFlag(absl::string_view text, Duration* dst, std::string* error);
// AbslUnparseFlag()
//
// Unparses a Duration value into a command-line string representation using
// the format specified by `absl::ParseDuration()`.
std::string AbslUnparseFlag(Duration d);
ABSL_DEPRECATED("Use AbslParseFlag() instead.")
bool ParseFlag(const std::string& text, Duration* dst, std::string* error);
ABSL_DEPRECATED("Use AbslUnparseFlag() instead.")
std::string UnparseFlag(Duration d);
// Time
//
// An `absl::Time` represents a specific instant in time. Arithmetic operators
// are provided for naturally expressing time calculations. Instances are
// created using `absl::Now()` and the `absl::From*()` factory functions that
// accept the gamut of other time representations. Formatting and parsing
// functions are provided for conversion to and from strings. `absl::Time` is
// trivially destructible and should be passed by value rather than const
// reference.
//
// `absl::Time` assumes there are 60 seconds in a minute, which means the
// underlying time scales must be "smeared" to eliminate leap seconds.
// See https://developers.google.com/time/smear.
//
// Even though `absl::Time` supports a wide range of timestamps, exercise
// caution when using values in the distant past. `absl::Time` uses the
// Proleptic Gregorian calendar, which extends the Gregorian calendar backward
// to dates before its introduction in 1582.
// See https://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar
// for more information. Use the ICU calendar classes to convert a date in
// some other calendar (http://userguide.icu-project.org/datetime/calendar).
//
// Similarly, standardized time zones are a reasonably recent innovation, with
// the Greenwich prime meridian being established in 1884. The TZ database
// itself does not profess accurate offsets for timestamps prior to 1970. The
// breakdown of future timestamps is subject to the whim of regional
// governments.
//
// The `absl::Time` class represents an instant in time as a count of clock
// ticks of some granularity (resolution) from some starting point (epoch).
//
// `absl::Time` uses a resolution that is high enough to avoid loss in
// precision, and a range that is wide enough to avoid overflow, when
// converting between tick counts in most Google time scales (i.e., resolution
// of at least one nanosecond, and range +/-100 billion years). Conversions
// between the time scales are performed by truncating (towards negative
// infinity) to the nearest representable point.
//
// Examples:
//
// absl::Time t1 = ...;
// absl::Time t2 = t1 + absl::Minutes(2);
// absl::Duration d = t2 - t1; // == absl::Minutes(2)
//
class Time {
public:
// Value semantics.
// Returns the Unix epoch. However, those reading your code may not know
// or expect the Unix epoch as the default value, so make your code more
// readable by explicitly initializing all instances before use.
//
// Example:
// absl::Time t = absl::UnixEpoch();
// absl::Time t = absl::Now();
// absl::Time t = absl::TimeFromTimeval(tv);
// absl::Time t = absl::InfinitePast();
constexpr Time() = default;
// Copyable.
constexpr Time(const Time& t) = default;
Time& operator=(const Time& t) = default;
// Assignment operators.
Time& operator+=(Duration d) {
rep_ += d;
return *this;
}
Time& operator-=(Duration d) {
rep_ -= d;
return *this;
}
// Time::Breakdown
//
// The calendar and wall-clock (aka "civil time") components of an
// `absl::Time` in a certain `absl::TimeZone`. This struct is not
// intended to represent an instant in time. So, rather than passing
// a `Time::Breakdown` to a function, pass an `absl::Time` and an
// `absl::TimeZone`.
//
// Deprecated. Use `absl::TimeZone::CivilInfo`.
struct ABSL_DEPRECATED("Use `absl::TimeZone::CivilInfo`.") Breakdown {
int64_t year; // year (e.g., 2013)
int month; // month of year [1:12]
int day; // day of month [1:31]
int hour; // hour of day [0:23]
int minute; // minute of hour [0:59]
int second; // second of minute [0:59]
Duration subsecond; // [Seconds(0):Seconds(1)) if finite
int weekday; // 1==Mon, ..., 7=Sun
int yearday; // day of year [1:366]
// Note: The following fields exist for backward compatibility
// with older APIs. Accessing these fields directly is a sign of
// imprudent logic in the calling code. Modern time-related code
// should only access this data indirectly by way of FormatTime().
// These fields are undefined for InfiniteFuture() and InfinitePast().
int offset; // seconds east of UTC
bool is_dst; // is offset non-standard?
const char* zone_abbr; // time-zone abbreviation (e.g., "PST")
};
// Time::In()
//
// Returns the breakdown of this instant in the given TimeZone.
//
// Deprecated. Use `absl::TimeZone::At(Time)`.
ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING
ABSL_DEPRECATED("Use `absl::TimeZone::At(Time)`.")
Breakdown In(TimeZone tz) const;
ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING
template <typename H>
friend H AbslHashValue(H h, Time t) {
return H::combine(std::move(h), t.rep_);
}
private:
friend constexpr Time time_internal::FromUnixDuration(Duration d);
friend constexpr Duration time_internal::ToUnixDuration(Time t);
#ifdef ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON
friend constexpr std::strong_ordering operator<=>(Time lhs, Time rhs);
#endif // ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON
friend constexpr bool operator<(Time lhs, Time rhs);
friend constexpr bool operator==(Time lhs, Time rhs);
friend Duration operator-(Time lhs, Time rhs);
friend constexpr Time UniversalEpoch();
friend constexpr Time InfiniteFuture();
friend constexpr Time InfinitePast();
constexpr explicit Time(Duration rep) : rep_(rep) {}
Duration rep_;
};
// Relational Operators
#ifdef ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr std::strong_ordering operator<=>(
Time lhs, Time rhs) {
return lhs.rep_ <=> rhs.rep_;
}
#endif // ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<(Time lhs, Time rhs) {
return lhs.rep_ < rhs.rep_;
}
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator>(Time lhs, Time rhs) {
return rhs < lhs;
}
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator>=(Time lhs, Time rhs) {
return !(lhs < rhs);
}
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<=(Time lhs, Time rhs) {
return !(rhs < lhs);
}
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator==(Time lhs, Time rhs) {
return lhs.rep_ == rhs.rep_;
}
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator!=(Time lhs, Time rhs) {
return !(lhs == rhs);
}
// Additive Operators
ABSL_ATTRIBUTE_CONST_FUNCTION inline Time operator+(Time lhs, Duration rhs) {
return lhs += rhs;
}
ABSL_ATTRIBUTE_CONST_FUNCTION inline Time operator+(Duration lhs, Time rhs) {
return rhs += lhs;
}
ABSL_ATTRIBUTE_CONST_FUNCTION inline Time operator-(Time lhs, Duration rhs) {
return lhs -= rhs;
}
ABSL_ATTRIBUTE_CONST_FUNCTION inline Duration operator-(Time lhs, Time rhs) {
return lhs.rep_ - rhs.rep_;
}
// UnixEpoch()
//
// Returns the `absl::Time` representing "1970-01-01 00:00:00.0 +0000".
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time UnixEpoch() { return Time(); }
// UniversalEpoch()
//
// Returns the `absl::Time` representing "0001-01-01 00:00:00.0 +0000", the
// epoch of the ICU Universal Time Scale.
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time UniversalEpoch() {
// 719162 is the number of days from 0001-01-01 to 1970-01-01,
// assuming the Gregorian calendar.
return Time(
time_internal::MakeDuration(-24 * 719162 * int64_t{3600}, uint32_t{0}));
}
// InfiniteFuture()
//
// Returns an `absl::Time` that is infinitely far in the future.
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time InfiniteFuture() {
return Time(time_internal::MakeDuration((std::numeric_limits<int64_t>::max)(),
~uint32_t{0}));
}
// InfinitePast()
//
// Returns an `absl::Time` that is infinitely far in the past.
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time InfinitePast() {
return Time(time_internal::MakeDuration((std::numeric_limits<int64_t>::min)(),
~uint32_t{0}));
}
// FromUnixNanos()
// FromUnixMicros()
// FromUnixMillis()
// FromUnixSeconds()
// FromTimeT()
// FromUDate()
// FromUniversal()
//
// Creates an `absl::Time` from a variety of other representations. See
// https://unicode-org.github.io/icu/userguide/datetime/universaltimescale.html
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromUnixNanos(int64_t ns);
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromUnixMicros(int64_t us);
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromUnixMillis(int64_t ms);
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromUnixSeconds(int64_t s);
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromTimeT(time_t t);
ABSL_ATTRIBUTE_CONST_FUNCTION Time FromUDate(double udate);
ABSL_ATTRIBUTE_CONST_FUNCTION Time FromUniversal(int64_t universal);
// ToUnixNanos()
// ToUnixMicros()
// ToUnixMillis()
// ToUnixSeconds()
// ToTimeT()
// ToUDate()
// ToUniversal()
//
// Converts an `absl::Time` to a variety of other representations. See
// https://unicode-org.github.io/icu/userguide/datetime/universaltimescale.html
//
// Note that these operations round down toward negative infinity where
// necessary to adjust to the resolution of the result type. Beware of
// possible time_t over/underflow in ToTime{T,val,spec}() on 32-bit platforms.
ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToUnixNanos(Time t);
ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToUnixMicros(Time t);
ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToUnixMillis(Time t);
ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToUnixSeconds(Time t);
ABSL_ATTRIBUTE_CONST_FUNCTION time_t ToTimeT(Time t);
ABSL_ATTRIBUTE_CONST_FUNCTION double ToUDate(Time t);
ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToUniversal(Time t);
// DurationFromTimespec()
// DurationFromTimeval()
// ToTimespec()
// ToTimeval()
// TimeFromTimespec()
// TimeFromTimeval()
// ToTimespec()
// ToTimeval()
//
// Some APIs use a timespec or a timeval as a Duration (e.g., nanosleep(2)
// and select(2)), while others use them as a Time (e.g. clock_gettime(2)
// and gettimeofday(2)), so conversion functions are provided for both cases.
// The "to timespec/val" direction is easily handled via overloading, but
// for "from timespec/val" the desired type is part of the function name.
ABSL_ATTRIBUTE_CONST_FUNCTION Duration DurationFromTimespec(timespec ts);
ABSL_ATTRIBUTE_CONST_FUNCTION Duration DurationFromTimeval(timeval tv);
ABSL_ATTRIBUTE_CONST_FUNCTION timespec ToTimespec(Duration d);
ABSL_ATTRIBUTE_CONST_FUNCTION timeval ToTimeval(Duration d);
ABSL_ATTRIBUTE_CONST_FUNCTION Time TimeFromTimespec(timespec ts);
ABSL_ATTRIBUTE_CONST_FUNCTION Time TimeFromTimeval(timeval tv);
ABSL_ATTRIBUTE_CONST_FUNCTION timespec ToTimespec(Time t);
ABSL_ATTRIBUTE_CONST_FUNCTION timeval ToTimeval(Time t);
// FromChrono()
//
// Converts a std::chrono::system_clock::time_point to an absl::Time.
//
// Example:
//
// auto tp = std::chrono::system_clock::from_time_t(123);
// absl::Time t = absl::FromChrono(tp);
// // t == absl::FromTimeT(123)
ABSL_ATTRIBUTE_PURE_FUNCTION Time
FromChrono(const std::chrono::system_clock::time_point& tp);
// ToChronoTime()
//
// Converts an absl::Time to a std::chrono::system_clock::time_point. If
// overflow would occur, the returned value will saturate at the min/max time
// point value instead.
//
// Example:
//
// absl::Time t = absl::FromTimeT(123);
// auto tp = absl::ToChronoTime(t);
// // tp == std::chrono::system_clock::from_time_t(123);
ABSL_ATTRIBUTE_CONST_FUNCTION std::chrono::system_clock::time_point
ToChronoTime(Time);
// AbslParseFlag()
//
// Parses the command-line flag string representation `text` into a Time value.
// Time flags must be specified in a format that matches absl::RFC3339_full.
//
// For example:
//
// --start_time=2016-01-02T03:04:05.678+08:00
//
// Note: A UTC offset (or 'Z' indicating a zero-offset from UTC) is required.
//
// Additionally, if you'd like to specify a time as a count of
// seconds/milliseconds/etc from the Unix epoch, use an absl::Duration flag
// and add that duration to absl::UnixEpoch() to get an absl::Time.
bool AbslParseFlag(absl::string_view text, Time* t, std::string* error);
// AbslUnparseFlag()
//
// Unparses a Time value into a command-line string representation using
// the format specified by `absl::ParseTime()`.
std::string AbslUnparseFlag(Time t);
ABSL_DEPRECATED("Use AbslParseFlag() instead.")
bool ParseFlag(const std::string& text, Time* t, std::string* error);
ABSL_DEPRECATED("Use AbslUnparseFlag() instead.")
std::string UnparseFlag(Time t);
// TimeZone
//
// The `absl::TimeZone` is an opaque, small, value-type class representing a
// geo-political region within which particular rules are used for converting
// between absolute and civil times (see https://git.io/v59Ly). `absl::TimeZone`
// values are named using the TZ identifiers from the IANA Time Zone Database,
// such as "America/Los_Angeles" or "Australia/Sydney". `absl::TimeZone` values
// are created from factory functions such as `absl::LoadTimeZone()`. Note:
// strings like "PST" and "EDT" are not valid TZ identifiers. Prefer to pass by
// value rather than const reference.
//
// For more on the fundamental concepts of time zones, absolute times, and civil
// times, see https://github.com/google/cctz#fundamental-concepts
//
// Examples:
//
// absl::TimeZone utc = absl::UTCTimeZone();
// absl::TimeZone pst = absl::FixedTimeZone(-8 * 60 * 60);
// absl::TimeZone loc = absl::LocalTimeZone();
// absl::TimeZone lax;
// if (!absl::LoadTimeZone("America/Los_Angeles", &lax)) {
// // handle error case
// }
//
// See also:
// - https://github.com/google/cctz
// - https://www.iana.org/time-zones
// - https://en.wikipedia.org/wiki/Zoneinfo
class TimeZone {
public:
explicit TimeZone(time_internal::cctz::time_zone tz) : cz_(tz) {}
TimeZone() = default; // UTC, but prefer UTCTimeZone() to be explicit.
// Copyable.
TimeZone(const TimeZone&) = default;
TimeZone& operator=(const TimeZone&) = default;
explicit operator time_internal::cctz::time_zone() const { return cz_; }
std::string name() const { return cz_.name(); }
// TimeZone::CivilInfo
//
// Information about the civil time corresponding to an absolute time.
// This struct is not intended to represent an instant in time. So, rather
// than passing a `TimeZone::CivilInfo` to a function, pass an `absl::Time`
// and an `absl::TimeZone`.
struct CivilInfo {
CivilSecond cs;
Duration subsecond;
// Note: The following fields exist for backward compatibility
// with older APIs. Accessing these fields directly is a sign of
// imprudent logic in the calling code. Modern time-related code
// should only access this data indirectly by way of FormatTime().
// These fields are undefined for InfiniteFuture() and InfinitePast().
int offset; // seconds east of UTC
bool is_dst; // is offset non-standard?
const char* zone_abbr; // time-zone abbreviation (e.g., "PST")
};
// TimeZone::At(Time)
//
// Returns the civil time for this TimeZone at a certain `absl::Time`.
// If the input time is infinite, the output civil second will be set to
// CivilSecond::max() or min(), and the subsecond will be infinite.
//
// Example:
//
// const auto epoch = lax.At(absl::UnixEpoch());
// // epoch.cs == 1969-12-31 16:00:00
// // epoch.subsecond == absl::ZeroDuration()
// // epoch.offset == -28800
// // epoch.is_dst == false
// // epoch.abbr == "PST"
CivilInfo At(Time t) const;
// TimeZone::TimeInfo
//
// Information about the absolute times corresponding to a civil time.
// (Subseconds must be handled separately.)
//
// It is possible for a caller to pass a civil-time value that does
// not represent an actual or unique instant in time (due to a shift
// in UTC offset in the TimeZone, which results in a discontinuity in
// the civil-time components). For example, a daylight-saving-time
// transition skips or repeats civil times---in the United States,
// March 13, 2011 02:15 never occurred, while November 6, 2011 01:15
// occurred twice---so requests for such times are not well-defined.
// To account for these possibilities, `absl::TimeZone::TimeInfo` is
// richer than just a single `absl::Time`.
struct TimeInfo {
enum CivilKind {
UNIQUE, // the civil time was singular (pre == trans == post)
SKIPPED, // the civil time did not exist (pre >= trans > post)
REPEATED, // the civil time was ambiguous (pre < trans <= post)
} kind;
Time pre; // time calculated using the pre-transition offset
Time trans; // when the civil-time discontinuity occurred
Time post; // time calculated using the post-transition offset
};
// TimeZone::At(CivilSecond)
//
// Returns an `absl::TimeInfo` containing the absolute time(s) for this
// TimeZone at an `absl::CivilSecond`. When the civil time is skipped or
// repeated, returns times calculated using the pre-transition and post-
// transition UTC offsets, plus the transition time itself.
//
// Examples:
//
// // A unique civil time
// const auto jan01 = lax.At(absl::CivilSecond(2011, 1, 1, 0, 0, 0));
// // jan01.kind == TimeZone::TimeInfo::UNIQUE
// // jan01.pre is 2011-01-01 00:00:00 -0800
// // jan01.trans is 2011-01-01 00:00:00 -0800
// // jan01.post is 2011-01-01 00:00:00 -0800
//
// // A Spring DST transition, when there is a gap in civil time
// const auto mar13 = lax.At(absl::CivilSecond(2011, 3, 13, 2, 15, 0));
// // mar13.kind == TimeZone::TimeInfo::SKIPPED
// // mar13.pre is 2011-03-13 03:15:00 -0700
// // mar13.trans is 2011-03-13 03:00:00 -0700
// // mar13.post is 2011-03-13 01:15:00 -0800
//
// // A Fall DST transition, when civil times are repeated
// const auto nov06 = lax.At(absl::CivilSecond(2011, 11, 6, 1, 15, 0));
// // nov06.kind == TimeZone::TimeInfo::REPEATED
// // nov06.pre is 2011-11-06 01:15:00 -0700
// // nov06.trans is 2011-11-06 01:00:00 -0800
// // nov06.post is 2011-11-06 01:15:00 -0800
TimeInfo At(CivilSecond ct) const;
// TimeZone::NextTransition()
// TimeZone::PrevTransition()
//
// Finds the time of the next/previous offset change in this time zone.
//
// By definition, `NextTransition(t, &trans)` returns false when `t` is
// `InfiniteFuture()`, and `PrevTransition(t, &trans)` returns false
// when `t` is `InfinitePast()`. If the zone has no transitions, the
// result will also be false no matter what the argument.
//
// Otherwise, when `t` is `InfinitePast()`, `NextTransition(t, &trans)`
// returns true and sets `trans` to the first recorded transition. Chains
// of calls to `NextTransition()/PrevTransition()` will eventually return
// false, but it is unspecified exactly when `NextTransition(t, &trans)`
// jumps to false, or what time is set by `PrevTransition(t, &trans)` for
// a very distant `t`.
//
// Note: Enumeration of time-zone transitions is for informational purposes
// only. Modern time-related code should not care about when offset changes
// occur.
//
// Example:
// absl::TimeZone nyc;
// if (!absl::LoadTimeZone("America/New_York", &nyc)) { ... }
// const auto now = absl::Now();
// auto t = absl::InfinitePast();
// absl::TimeZone::CivilTransition trans;
// while (t <= now && nyc.NextTransition(t, &trans)) {
// // transition: trans.from -> trans.to
// t = nyc.At(trans.to).trans;
// }
struct CivilTransition {
CivilSecond from; // the civil time we jump from
CivilSecond to; // the civil time we jump to
};
bool NextTransition(Time t, CivilTransition* trans) const;
bool PrevTransition(Time t, CivilTransition* trans) const;
template <typename H>
friend H AbslHashValue(H h, TimeZone tz) {
return H::combine(std::move(h), tz.cz_);
}
private:
friend bool operator==(TimeZone a, TimeZone b) { return a.cz_ == b.cz_; }
friend bool operator!=(TimeZone a, TimeZone b) { return a.cz_ != b.cz_; }
friend std::ostream& operator<<(std::ostream& os, TimeZone tz) {
return os << tz.name();
}
time_internal::cctz::time_zone cz_;
};
// LoadTimeZone()
//
// Loads the named zone. May perform I/O on the initial load of the named
// zone. If the name is invalid, or some other kind of error occurs, returns
// `false` and `*tz` is set to the UTC time zone.
inline bool LoadTimeZone(absl::string_view name, TimeZone* tz) {
if (name == "localtime") {
*tz = TimeZone(time_internal::cctz::local_time_zone());
return true;
}
time_internal::cctz::time_zone cz;
const bool b = time_internal::cctz::load_time_zone(std::string(name), &cz);
*tz = TimeZone(cz);
return b;
}
// FixedTimeZone()
//
// Returns a TimeZone that is a fixed offset (seconds east) from UTC.
// Note: If the absolute value of the offset is greater than 24 hours
// you'll get UTC (i.e., no offset) instead.
inline TimeZone FixedTimeZone(int seconds) {
return TimeZone(
time_internal::cctz::fixed_time_zone(std::chrono::seconds(seconds)));
}
// UTCTimeZone()
//
// Convenience method returning the UTC time zone.
inline TimeZone UTCTimeZone() {
return TimeZone(time_internal::cctz::utc_time_zone());
}
// LocalTimeZone()
//
// Convenience method returning the local time zone, or UTC if there is
// no configured local zone. Warning: Be wary of using LocalTimeZone(),
// and particularly so in a server process, as the zone configured for the
// local machine should be irrelevant. Prefer an explicit zone name.
inline TimeZone LocalTimeZone() {
return TimeZone(time_internal::cctz::local_time_zone());
}
// ToCivilSecond()
// ToCivilMinute()
// ToCivilHour()
// ToCivilDay()
// ToCivilMonth()
// ToCivilYear()
//
// Helpers for TimeZone::At(Time) to return particularly aligned civil times.
//
// Example:
//
// absl::Time t = ...;
// absl::TimeZone tz = ...;
// const auto cd = absl::ToCivilDay(t, tz);
ABSL_ATTRIBUTE_PURE_FUNCTION inline CivilSecond ToCivilSecond(Time t,
TimeZone tz) {
return tz.At(t).cs; // already a CivilSecond
}
ABSL_ATTRIBUTE_PURE_FUNCTION inline CivilMinute ToCivilMinute(Time t,
TimeZone tz) {
return CivilMinute(tz.At(t).cs);
}
ABSL_ATTRIBUTE_PURE_FUNCTION inline CivilHour ToCivilHour(Time t, TimeZone tz) {
return CivilHour(tz.At(t).cs);
}
ABSL_ATTRIBUTE_PURE_FUNCTION inline CivilDay ToCivilDay(Time t, TimeZone tz) {
return CivilDay(tz.At(t).cs);
}
ABSL_ATTRIBUTE_PURE_FUNCTION inline CivilMonth ToCivilMonth(Time t,
TimeZone tz) {
return CivilMonth(tz.At(t).cs);
}
ABSL_ATTRIBUTE_PURE_FUNCTION inline CivilYear ToCivilYear(Time t, TimeZone tz) {
return CivilYear(tz.At(t).cs);
}
// FromCivil()
//
// Helper for TimeZone::At(CivilSecond) that provides "order-preserving
// semantics." If the civil time maps to a unique time, that time is
// returned. If the civil time is repeated in the given time zone, the
// time using the pre-transition offset is returned. Otherwise, the
// civil time is skipped in the given time zone, and the transition time
// is returned. This means that for any two civil times, ct1 and ct2,
// (ct1 < ct2) => (FromCivil(ct1) <= FromCivil(ct2)), the equal case
// being when two non-existent civil times map to the same transition time.
//
// Note: Accepts civil times of any alignment.
ABSL_ATTRIBUTE_PURE_FUNCTION inline Time FromCivil(CivilSecond ct,
TimeZone tz) {
const auto ti = tz.At(ct);
if (ti.kind == TimeZone::TimeInfo::SKIPPED) return ti.trans;
return ti.pre;
}
// TimeConversion
//
// An `absl::TimeConversion` represents the conversion of year, month, day,
// hour, minute, and second values (i.e., a civil time), in a particular
// `absl::TimeZone`, to a time instant (an absolute time), as returned by
// `absl::ConvertDateTime()`. Legacy version of `absl::TimeZone::TimeInfo`.
//
// Deprecated. Use `absl::TimeZone::TimeInfo`.
struct ABSL_DEPRECATED("Use `absl::TimeZone::TimeInfo`.") TimeConversion {
Time pre; // time calculated using the pre-transition offset
Time trans; // when the civil-time discontinuity occurred
Time post; // time calculated using the post-transition offset
enum Kind {
UNIQUE, // the civil time was singular (pre == trans == post)
SKIPPED, // the civil time did not exist
REPEATED, // the civil time was ambiguous
};
Kind kind;
bool normalized; // input values were outside their valid ranges
};
// ConvertDateTime()
//
// Legacy version of `absl::TimeZone::At(absl::CivilSecond)` that takes
// the civil time as six, separate values (YMDHMS).
//
// The input month, day, hour, minute, and second values can be outside
// of their valid ranges, in which case they will be "normalized" during
// the conversion.
//
// Example:
//
// // "October 32" normalizes to "November 1".
// absl::TimeConversion tc =
// absl::ConvertDateTime(2013, 10, 32, 8, 30, 0, lax);
// // tc.kind == TimeConversion::UNIQUE && tc.normalized == true
// // absl::ToCivilDay(tc.pre, tz).month() == 11
// // absl::ToCivilDay(tc.pre, tz).day() == 1
//
// Deprecated. Use `absl::TimeZone::At(CivilSecond)`.
ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING
ABSL_DEPRECATED("Use `absl::TimeZone::At(CivilSecond)`.")
TimeConversion ConvertDateTime(int64_t year, int mon, int day, int hour,
int min, int sec, TimeZone tz);
ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING
// FromDateTime()
//
// A convenience wrapper for `absl::ConvertDateTime()` that simply returns
// the "pre" `absl::Time`. That is, the unique result, or the instant that
// is correct using the pre-transition offset (as if the transition never
// happened).
//
// Example:
//
// absl::Time t = absl::FromDateTime(2017, 9, 26, 9, 30, 0, lax);
// // t = 2017-09-26 09:30:00 -0700
//
// Deprecated. Use `absl::FromCivil(CivilSecond, TimeZone)`. Note that the
// behavior of `FromCivil()` differs from `FromDateTime()` for skipped civil
// times. If you care about that see `absl::TimeZone::At(absl::CivilSecond)`.
ABSL_DEPRECATED("Use `absl::FromCivil(CivilSecond, TimeZone)`.")
inline Time FromDateTime(int64_t year, int mon, int day, int hour, int min,
int sec, TimeZone tz) {
ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING
return ConvertDateTime(year, mon, day, hour, min, sec, tz).pre;
ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING
}
// FromTM()
//
// Converts the `tm_year`, `tm_mon`, `tm_mday`, `tm_hour`, `tm_min`, and
// `tm_sec` fields to an `absl::Time` using the given time zone. See ctime(3)
// for a description of the expected values of the tm fields. If the civil time
// is unique (see `absl::TimeZone::At(absl::CivilSecond)` above), the matching
// time instant is returned. Otherwise, the `tm_isdst` field is consulted to
// choose between the possible results. For a repeated civil time, `tm_isdst !=
// 0` returns the matching DST instant, while `tm_isdst == 0` returns the
// matching non-DST instant. For a skipped civil time there is no matching
// instant, so `tm_isdst != 0` returns the DST instant, and `tm_isdst == 0`
// returns the non-DST instant, that would have matched if the transition never
// happened.
ABSL_ATTRIBUTE_PURE_FUNCTION Time FromTM(const struct tm& tm, TimeZone tz);
// ToTM()
//
// Converts the given `absl::Time` to a struct tm using the given time zone.
// See ctime(3) for a description of the values of the tm fields.
ABSL_ATTRIBUTE_PURE_FUNCTION struct tm ToTM(Time t, TimeZone tz);
// RFC3339_full
// RFC3339_sec
//
// FormatTime()/ParseTime() format specifiers for RFC3339 date/time strings,
// with trailing zeros trimmed or with fractional seconds omitted altogether.
//
// Note that RFC3339_sec[] matches an ISO 8601 extended format for date and
// time with UTC offset. Also note the use of "%Y": RFC3339 mandates that
// years have exactly four digits, but we allow them to take their natural
// width.
ABSL_DLL extern const char RFC3339_full[]; // %Y-%m-%d%ET%H:%M:%E*S%Ez
ABSL_DLL extern const char RFC3339_sec[]; // %Y-%m-%d%ET%H:%M:%S%Ez
// RFC1123_full
// RFC1123_no_wday
//
// FormatTime()/ParseTime() format specifiers for RFC1123 date/time strings.
ABSL_DLL extern const char RFC1123_full[]; // %a, %d %b %E4Y %H:%M:%S %z
ABSL_DLL extern const char RFC1123_no_wday[]; // %d %b %E4Y %H:%M:%S %z
// FormatTime()
//
// Formats the given `absl::Time` in the `absl::TimeZone` according to the
// provided format string. Uses strftime()-like formatting options, with
// the following extensions:
//
// - %Ez - RFC3339-compatible numeric UTC offset (+hh:mm or -hh:mm)
// - %E*z - Full-resolution numeric UTC offset (+hh:mm:ss or -hh:mm:ss)
// - %E#S - Seconds with # digits of fractional precision
// - %E*S - Seconds with full fractional precision (a literal '*')
// - %E#f - Fractional seconds with # digits of precision
// - %E*f - Fractional seconds with full precision (a literal '*')
// - %E4Y - Four-character years (-999 ... -001, 0000, 0001 ... 9999)
// - %ET - The RFC3339 "date-time" separator "T"
//
// Note that %E0S behaves like %S, and %E0f produces no characters. In
// contrast %E*f always produces at least one digit, which may be '0'.
//
// Note that %Y produces as many characters as it takes to fully render the
// year. A year outside of [-999:9999] when formatted with %E4Y will produce
// more than four characters, just like %Y.
//
// We recommend that format strings include the UTC offset (%z, %Ez, or %E*z)
// so that the result uniquely identifies a time instant.
//
// Example:
//
// absl::CivilSecond cs(2013, 1, 2, 3, 4, 5);
// absl::Time t = absl::FromCivil(cs, lax);
// std::string f = absl::FormatTime("%H:%M:%S", t, lax); // "03:04:05"
// f = absl::FormatTime("%H:%M:%E3S", t, lax); // "03:04:05.000"
//
// Note: If the given `absl::Time` is `absl::InfiniteFuture()`, the returned
// string will be exactly "infinite-future". If the given `absl::Time` is
// `absl::InfinitePast()`, the returned string will be exactly "infinite-past".
// In both cases the given format string and `absl::TimeZone` are ignored.
//
ABSL_ATTRIBUTE_PURE_FUNCTION std::string FormatTime(absl::string_view format,
Time t, TimeZone tz);
// Convenience functions that format the given time using the RFC3339_full
// format. The first overload uses the provided TimeZone, while the second
// uses LocalTimeZone().
ABSL_ATTRIBUTE_PURE_FUNCTION std::string FormatTime(Time t, TimeZone tz);
ABSL_ATTRIBUTE_PURE_FUNCTION std::string FormatTime(Time t);
// Output stream operator.
inline std::ostream& operator<<(std::ostream& os, Time t) {
return os << FormatTime(t);
}
// Support for StrFormat(), StrCat() etc.
template <typename Sink>
void AbslStringify(Sink& sink, Time t) {
sink.Append(FormatTime(t));
}
// ParseTime()
//
// Parses an input string according to the provided format string and
// returns the corresponding `absl::Time`. Uses strftime()-like formatting
// options, with the same extensions as FormatTime(), but with the
// exceptions that %E#S is interpreted as %E*S, and %E#f as %E*f. %Ez
// and %E*z also accept the same inputs, which (along with %z) includes
// 'z' and 'Z' as synonyms for +00:00. %ET accepts either 'T' or 't'.
//
// %Y consumes as many numeric characters as it can, so the matching data
// should always be terminated with a non-numeric. %E4Y always consumes
// exactly four characters, including any sign.
//
// Unspecified fields are taken from the default date and time of ...
//
// "1970-01-01 00:00:00.0 +0000"
//
// For example, parsing a string of "15:45" (%H:%M) will return an absl::Time
// that represents "1970-01-01 15:45:00.0 +0000".
//
// Note that since ParseTime() returns time instants, it makes the most sense
// to parse fully-specified date/time strings that include a UTC offset (%z,
// %Ez, or %E*z).
//
// Note also that `absl::ParseTime()` only heeds the fields year, month, day,
// hour, minute, (fractional) second, and UTC offset. Other fields, like
// weekday (%a or %A), while parsed for syntactic validity, are ignored
// in the conversion.
//
// Date and time fields that are out-of-range will be treated as errors
// rather than normalizing them like `absl::CivilSecond` does. For example,
// it is an error to parse the date "Oct 32, 2013" because 32 is out of range.
//
// A leap second of ":60" is normalized to ":00" of the following minute
// with fractional seconds discarded. The following table shows how the
// given seconds and subseconds will be parsed:
//
// "59.x" -> 59.x // exact
// "60.x" -> 00.0 // normalized
// "00.x" -> 00.x // exact
//
// Errors are indicated by returning false and assigning an error message
// to the "err" out param if it is non-null.
//
// Note: If the input string is exactly "infinite-future", the returned
// `absl::Time` will be `absl::InfiniteFuture()` and `true` will be returned.
// If the input string is "infinite-past", the returned `absl::Time` will be
// `absl::InfinitePast()` and `true` will be returned.
//
bool ParseTime(absl::string_view format, absl::string_view input, Time* time,
std::string* err);
// Like ParseTime() above, but if the format string does not contain a UTC
// offset specification (%z/%Ez/%E*z) then the input is interpreted in the
// given TimeZone. This means that the input, by itself, does not identify a
// unique instant. Being time-zone dependent, it also admits the possibility
// of ambiguity or non-existence, in which case the "pre" time (as defined
// by TimeZone::TimeInfo) is returned. For these reasons we recommend that
// all date/time strings include a UTC offset so they're context independent.
bool ParseTime(absl::string_view format, absl::string_view input, TimeZone tz,
Time* time, std::string* err);
// ============================================================================
// Implementation Details Follow
// ============================================================================
namespace time_internal {
// Creates a Duration with a given representation.
// REQUIRES: hi,lo is a valid representation of a Duration as specified
// in time/duration.cc.
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration MakeDuration(int64_t hi,
uint32_t lo = 0) {
return Duration(hi, lo);
}
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration MakeDuration(int64_t hi,
int64_t lo) {
return MakeDuration(hi, static_cast<uint32_t>(lo));
}
// Make a Duration value from a floating-point number, as long as that number
// is in the range [ 0 .. numeric_limits<int64_t>::max ), that is, as long as
// it's positive and can be converted to int64_t without risk of UB.
ABSL_ATTRIBUTE_CONST_FUNCTION inline Duration MakePosDoubleDuration(double n) {
const int64_t int_secs = static_cast<int64_t>(n);
const uint32_t ticks = static_cast<uint32_t>(
std::round((n - static_cast<double>(int_secs)) * kTicksPerSecond));
return ticks < kTicksPerSecond
? MakeDuration(int_secs, ticks)
: MakeDuration(int_secs + 1, ticks - kTicksPerSecond);
}
// Creates a normalized Duration from an almost-normalized (sec,ticks)
// pair. sec may be positive or negative. ticks must be in the range
// -kTicksPerSecond < *ticks < kTicksPerSecond. If ticks is negative it
// will be normalized to a positive value in the resulting Duration.
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration MakeNormalizedDuration(
int64_t sec, int64_t ticks) {
return (ticks < 0) ? MakeDuration(sec - 1, ticks + kTicksPerSecond)
: MakeDuration(sec, ticks);
}
// Provide access to the Duration representation.
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t GetRepHi(Duration d) {
return d.rep_hi_.Get();
}
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr uint32_t GetRepLo(Duration d) {
return d.rep_lo_;
}
// Returns true iff d is positive or negative infinity.
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool IsInfiniteDuration(Duration d) {
return GetRepLo(d) == ~uint32_t{0};
}
// Returns an infinite Duration with the opposite sign.
// REQUIRES: IsInfiniteDuration(d)
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration OppositeInfinity(Duration d) {
return GetRepHi(d) < 0
? MakeDuration((std::numeric_limits<int64_t>::max)(), ~uint32_t{0})
: MakeDuration((std::numeric_limits<int64_t>::min)(),
~uint32_t{0});
}
// Returns (-n)-1 (equivalently -(n+1)) without avoidable overflow.
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t NegateAndSubtractOne(
int64_t n) {
// Note: Good compilers will optimize this expression to ~n when using
// a two's-complement representation (which is required for int64_t).
return (n < 0) ? -(n + 1) : (-n) - 1;
}
// Map between a Time and a Duration since the Unix epoch. Note that these
// functions depend on the above mentioned choice of the Unix epoch for the
// Time representation (and both need to be Time friends). Without this
// knowledge, we would need to add-in/subtract-out UnixEpoch() respectively.
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromUnixDuration(Duration d) {
return Time(d);
}
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration ToUnixDuration(Time t) {
return t.rep_;
}
template <std::intmax_t N>
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration FromInt64(int64_t v,
std::ratio<1, N>) {
static_assert(0 < N && N <= 1000 * 1000 * 1000, "Unsupported ratio");
// Subsecond ratios cannot overflow.
return MakeNormalizedDuration(
v / N, v % N * kTicksPerNanosecond * 1000 * 1000 * 1000 / N);
}
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration FromInt64(int64_t v,
std::ratio<60>) {
return (v <= (std::numeric_limits<int64_t>::max)() / 60 &&
v >= (std::numeric_limits<int64_t>::min)() / 60)
? MakeDuration(v * 60)
: v > 0 ? InfiniteDuration() : -InfiniteDuration();
}
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration FromInt64(int64_t v,
std::ratio<3600>) {
return (v <= (std::numeric_limits<int64_t>::max)() / 3600 &&
v >= (std::numeric_limits<int64_t>::min)() / 3600)
? MakeDuration(v * 3600)
: v > 0 ? InfiniteDuration() : -InfiniteDuration();
}
// IsValidRep64<T>(0) is true if the expression `int64_t{std::declval<T>()}` is
// valid. That is, if a T can be assigned to an int64_t without narrowing.
template <typename T>
constexpr auto IsValidRep64(int) -> decltype(int64_t{std::declval<T>()} == 0) {
return true;
}
template <typename T>
constexpr auto IsValidRep64(char) -> bool {
return false;
}
// Converts a std::chrono::duration to an absl::Duration.
template <typename Rep, typename Period>
ABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(
const std::chrono::duration<Rep, Period>& d) {
static_assert(IsValidRep64<Rep>(0), "duration::rep is invalid");
return FromInt64(int64_t{d.count()}, Period{});
}
template <typename Ratio>
ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToInt64(Duration d, Ratio) {
// Note: This may be used on MSVC, which may have a system_clock period of
// std::ratio<1, 10 * 1000 * 1000>
return ToInt64Seconds(d * Ratio::den / Ratio::num);
}
// Fastpath implementations for the 6 common duration units.
ABSL_ATTRIBUTE_CONST_FUNCTION inline int64_t ToInt64(Duration d, std::nano) {
return ToInt64Nanoseconds(d);
}
ABSL_ATTRIBUTE_CONST_FUNCTION inline int64_t ToInt64(Duration d, std::micro) {
return ToInt64Microseconds(d);
}
ABSL_ATTRIBUTE_CONST_FUNCTION inline int64_t ToInt64(Duration d, std::milli) {
return ToInt64Milliseconds(d);
}
ABSL_ATTRIBUTE_CONST_FUNCTION inline int64_t ToInt64(Duration d,
std::ratio<1>) {
return ToInt64Seconds(d);
}
ABSL_ATTRIBUTE_CONST_FUNCTION inline int64_t ToInt64(Duration d,
std::ratio<60>) {
return ToInt64Minutes(d);
}
ABSL_ATTRIBUTE_CONST_FUNCTION inline int64_t ToInt64(Duration d,
std::ratio<3600>) {
return ToInt64Hours(d);
}
// Converts an absl::Duration to a chrono duration of type T.
template <typename T>
ABSL_ATTRIBUTE_CONST_FUNCTION T ToChronoDuration(Duration d) {
using Rep = typename T::rep;
using Period = typename T::period;
static_assert(IsValidRep64<Rep>(0), "duration::rep is invalid");
if (time_internal::IsInfiniteDuration(d))
return d < ZeroDuration() ? (T::min)() : (T::max)();
const auto v = ToInt64(d, Period{});
if (v > (std::numeric_limits<Rep>::max)()) return (T::max)();
if (v < (std::numeric_limits<Rep>::min)()) return (T::min)();
return T{v};
}
} // namespace time_internal
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<(Duration lhs,
Duration rhs) {
return time_internal::GetRepHi(lhs) != time_internal::GetRepHi(rhs)
? time_internal::GetRepHi(lhs) < time_internal::GetRepHi(rhs)
: time_internal::GetRepHi(lhs) == (std::numeric_limits<int64_t>::min)()
? time_internal::GetRepLo(lhs) + 1 <
time_internal::GetRepLo(rhs) + 1
: time_internal::GetRepLo(lhs) < time_internal::GetRepLo(rhs);
}
#ifdef ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr std::strong_ordering operator<=>(
Duration lhs, Duration rhs) {
const int64_t lhs_hi = time_internal::GetRepHi(lhs);
const int64_t rhs_hi = time_internal::GetRepHi(rhs);
if (auto c = lhs_hi <=> rhs_hi; c != std::strong_ordering::equal) {
return c;
}
const uint32_t lhs_lo = time_internal::GetRepLo(lhs);
const uint32_t rhs_lo = time_internal::GetRepLo(rhs);
return (lhs_hi == (std::numeric_limits<int64_t>::min)())
? (lhs_lo + 1) <=> (rhs_lo + 1)
: lhs_lo <=> rhs_lo;
}
#endif // ABSL_INTERNAL_TIME_HAS_THREE_WAY_COMPARISON
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator==(Duration lhs,
Duration rhs) {
return time_internal::GetRepHi(lhs) == time_internal::GetRepHi(rhs) &&
time_internal::GetRepLo(lhs) == time_internal::GetRepLo(rhs);
}
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration operator-(Duration d) {
// This is a little interesting because of the special cases.
//
// If rep_lo_ is zero, we have it easy; it's safe to negate rep_hi_, we're
// dealing with an integral number of seconds, and the only special case is
// the maximum negative finite duration, which can't be negated.
//
// Infinities stay infinite, and just change direction.
//
// Finally we're in the case where rep_lo_ is non-zero, and we can borrow
// a second's worth of ticks and avoid overflow (as negating int64_t-min + 1
// is safe).
return time_internal::GetRepLo(d) == 0
? time_internal::GetRepHi(d) ==
(std::numeric_limits<int64_t>::min)()
? InfiniteDuration()
: time_internal::MakeDuration(-time_internal::GetRepHi(d))
: time_internal::IsInfiniteDuration(d)
? time_internal::OppositeInfinity(d)
: time_internal::MakeDuration(
time_internal::NegateAndSubtractOne(
time_internal::GetRepHi(d)),
time_internal::kTicksPerSecond -
time_internal::GetRepLo(d));
}
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration InfiniteDuration() {
return time_internal::MakeDuration((std::numeric_limits<int64_t>::max)(),
~uint32_t{0});
}
ABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(
const std::chrono::nanoseconds& d) {
return time_internal::FromChrono(d);
}
ABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(
const std::chrono::microseconds& d) {
return time_internal::FromChrono(d);
}
ABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(
const std::chrono::milliseconds& d) {
return time_internal::FromChrono(d);
}
ABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(
const std::chrono::seconds& d) {
return time_internal::FromChrono(d);
}
ABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(
const std::chrono::minutes& d) {
return time_internal::FromChrono(d);
}
ABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(
const std::chrono::hours& d) {
return time_internal::FromChrono(d);
}
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromUnixNanos(int64_t ns) {
return time_internal::FromUnixDuration(Nanoseconds(ns));
}
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromUnixMicros(int64_t us) {
return time_internal::FromUnixDuration(Microseconds(us));
}
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromUnixMillis(int64_t ms) {
return time_internal::FromUnixDuration(Milliseconds(ms));
}
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromUnixSeconds(int64_t s) {
return time_internal::FromUnixDuration(Seconds(s));
}
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromTimeT(time_t t) {
return time_internal::FromUnixDuration(Seconds(t));
}
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t ToInt64Nanoseconds(Duration d) {
if (time_internal::GetRepHi(d) >= 0 &&
time_internal::GetRepHi(d) >> 33 == 0) {
return (time_internal::GetRepHi(d) * 1000 * 1000 * 1000) +
(time_internal::GetRepLo(d) / time_internal::kTicksPerNanosecond);
} else {
return d / Nanoseconds(1);
}
}
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t ToInt64Microseconds(
Duration d) {
if (time_internal::GetRepHi(d) >= 0 &&
time_internal::GetRepHi(d) >> 43 == 0) {
return (time_internal::GetRepHi(d) * 1000 * 1000) +
(time_internal::GetRepLo(d) /
(time_internal::kTicksPerNanosecond * 1000));
} else {
return d / Microseconds(1);
}
}
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t ToInt64Milliseconds(
Duration d) {
if (time_internal::GetRepHi(d) >= 0 &&
time_internal::GetRepHi(d) >> 53 == 0) {
return (time_internal::GetRepHi(d) * 1000) +
(time_internal::GetRepLo(d) /
(time_internal::kTicksPerNanosecond * 1000 * 1000));
} else {
return d / Milliseconds(1);
}
}
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t ToInt64Seconds(Duration d) {
int64_t hi = time_internal::GetRepHi(d);
if (time_internal::IsInfiniteDuration(d)) return hi;
if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi;
return hi;
}
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t ToInt64Minutes(Duration d) {
int64_t hi = time_internal::GetRepHi(d);
if (time_internal::IsInfiniteDuration(d)) return hi;
if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi;
return hi / 60;
}
ABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t ToInt64Hours(Duration d) {
int64_t hi = time_internal::GetRepHi(d);
if (time_internal::IsInfiniteDuration(d)) return hi;
if (hi < 0 && time_internal::GetRepLo(d) != 0) ++hi;
return hi / (60 * 60);
}
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_TIME_TIME_H_
tsoong/.intermediates/external/abseil-cpp/absl_log_internal_config_hdrs/gen/my_include_dir/absl/log/internal/config.h¾ // Copyright 2022 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: log/internal/config.h
// -----------------------------------------------------------------------------
//
#ifndef ABSL_LOG_INTERNAL_CONFIG_H_
#define ABSL_LOG_INTERNAL_CONFIG_H_
#include "absl/base/config.h"
#ifdef _WIN32
#include <cstdint>
#else
#include <sys/types.h>
#endif
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace log_internal {
#ifdef _WIN32
using Tid = uint32_t;
#else
using Tid = pid_t;
#endif
} // namespace log_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_LOG_INTERNAL_CONFIG_H_
*­
hsoong/.intermediates/external/abseil-cpp/absl_types_variant_hdrs/gen/my_include_dir/absl/types/variant.hÀ// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// variant.h
// -----------------------------------------------------------------------------
//
// Historical note: Abseil once provided an implementation of `absl::variant`
// as a polyfill for `std::variant` prior to C++17. Now that C++17 is required,
// `absl::variant` is an alias for `std::variant`.
#ifndef ABSL_TYPES_VARIANT_H_
#define ABSL_TYPES_VARIANT_H_
#include <variant>
#include "absl/base/config.h"
#include "absl/utility/utility.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
using std::bad_variant_access;
using std::get;
using std::get_if;
using std::holds_alternative;
using std::monostate;
using std::variant;
using std::variant_alternative;
using std::variant_alternative_t;
using std::variant_npos;
using std::variant_size;
using std::variant_size_v;
using std::visit;
namespace variant_internal {
// Helper visitor for converting a variant<Ts...>` into another type (mostly
// variant) that can be constructed from any type.
template <typename To>
struct ConversionVisitor {
template <typename T>
To operator()(T&& v) const {
return To(std::forward<T>(v));
}
};
} // namespace variant_internal
// ConvertVariantTo()
//
// Helper functions to convert an `absl::variant` to a variant of another set of
// types, provided that the alternative type of the new variant type can be
// converted from any type in the source variant.
//
// Example:
//
// absl::variant<name1, name2, float> InternalReq(const Req&);
//
// // name1 and name2 are convertible to name
// absl::variant<name, float> ExternalReq(const Req& req) {
// return absl::ConvertVariantTo<absl::variant<name, float>>(
// InternalReq(req));
// }
template <typename To, typename Variant>
To ConvertVariantTo(Variant&& variant) {
return absl::visit(variant_internal::ConversionVisitor<To>{},
std::forward<Variant>(variant));
}
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_TYPES_VARIANT_H_
*×P
‹soong/.intermediates/external/abseil-cpp/absl_container_compressed_tuple_hdrs/gen/my_include_dir/absl/container/internal/compressed_tuple.hÆO// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Helper class to perform the Empty Base Optimization.
// Ts can contain classes and non-classes, empty or not. For the ones that
// are empty classes, we perform the optimization. If all types in Ts are empty
// classes, then CompressedTuple<Ts...> is itself an empty class.
//
// To access the members, use member get<N>() function.
//
// Eg:
// absl::container_internal::CompressedTuple<int, T1, T2, T3> value(7, t1, t2,
// t3);
// assert(value.get<0>() == 7);
// T1& t1 = value.get<1>();
// const T2& t2 = value.get<2>();
// ...
//
// https://en.cppreference.com/w/cpp/language/ebo
#ifndef ABSL_CONTAINER_INTERNAL_COMPRESSED_TUPLE_H_
#define ABSL_CONTAINER_INTERNAL_COMPRESSED_TUPLE_H_
#include <initializer_list>
#include <tuple>
#include <type_traits>
#include <utility>
#include "absl/utility/utility.h"
#if defined(_MSC_VER) && !defined(__NVCC__)
// We need to mark these classes with this declspec to ensure that
// CompressedTuple happens.
#define ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC __declspec(empty_bases)
#else
#define ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC
#endif
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace container_internal {
template <typename... Ts>
class CompressedTuple;
namespace internal_compressed_tuple {
template <typename D, size_t I>
struct Elem;
template <typename... B, size_t I>
struct Elem<CompressedTuple<B...>, I>
: std::tuple_element<I, std::tuple<B...>> {};
template <typename D, size_t I>
using ElemT = typename Elem<D, I>::type;
// We can't use EBCO on other CompressedTuples because that would mean that we
// derive from multiple Storage<> instantiations with the same I parameter,
// and potentially from multiple identical Storage<> instantiations. So anytime
// we use type inheritance rather than encapsulation, we mark
// CompressedTupleImpl, to make this easy to detect.
struct uses_inheritance {};
template <typename T>
constexpr bool ShouldUseBase() {
return std::is_class<T>::value && std::is_empty<T>::value &&
!std::is_final<T>::value &&
!std::is_base_of<uses_inheritance, T>::value;
}
// The storage class provides two specializations:
// - For empty classes, it stores T as a base class.
// - For everything else, it stores T as a member.
template <typename T, size_t I, bool UseBase = ShouldUseBase<T>()>
struct Storage {
T value;
constexpr Storage() = default;
template <typename V>
explicit constexpr Storage(absl::in_place_t, V&& v)
: value(std::forward<V>(v)) {}
constexpr const T& get() const& { return value; }
constexpr T& get() & { return value; }
constexpr const T&& get() const&& { return std::move(*this).value; }
constexpr T&& get() && { return std::move(*this).value; }
};
template <typename T, size_t I>
struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC Storage<T, I, true> : T {
constexpr Storage() = default;
template <typename V>
explicit constexpr Storage(absl::in_place_t, V&& v) : T(std::forward<V>(v)) {}
constexpr const T& get() const& { return *this; }
constexpr T& get() & { return *this; }
constexpr const T&& get() const&& { return std::move(*this); }
constexpr T&& get() && { return std::move(*this); }
};
template <typename D, typename I, bool ShouldAnyUseBase>
struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTupleImpl;
template <typename... Ts, size_t... I, bool ShouldAnyUseBase>
struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTupleImpl<
CompressedTuple<Ts...>, absl::index_sequence<I...>, ShouldAnyUseBase>
// We use the dummy identity function through std::integral_constant to
// convince MSVC of accepting and expanding I in that context. Without it
// you would get:
// error C3548: 'I': parameter pack cannot be used in this context
: uses_inheritance,
Storage<Ts, std::integral_constant<size_t, I>::value>... {
constexpr CompressedTupleImpl() = default;
template <typename... Vs>
explicit constexpr CompressedTupleImpl(absl::in_place_t, Vs&&... args)
: Storage<Ts, I>(absl::in_place, std::forward<Vs>(args))... {}
friend CompressedTuple<Ts...>;
};
template <typename... Ts, size_t... I>
struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTupleImpl<
CompressedTuple<Ts...>, absl::index_sequence<I...>, false>
// We use the dummy identity function as above...
: Storage<Ts, std::integral_constant<size_t, I>::value, false>... {
constexpr CompressedTupleImpl() = default;
template <typename... Vs>
explicit constexpr CompressedTupleImpl(absl::in_place_t, Vs&&... args)
: Storage<Ts, I, false>(absl::in_place, std::forward<Vs>(args))... {}
friend CompressedTuple<Ts...>;
};
std::false_type Or(std::initializer_list<std::false_type>);
std::true_type Or(std::initializer_list<bool>);
// MSVC requires this to be done separately rather than within the declaration
// of CompressedTuple below.
template <typename... Ts>
constexpr bool ShouldAnyUseBase() {
return decltype(
Or({std::integral_constant<bool, ShouldUseBase<Ts>()>()...})){};
}
template <typename T, typename V>
using TupleElementMoveConstructible =
typename std::conditional<std::is_reference<T>::value,
std::is_convertible<V, T>,
std::is_constructible<T, V&&>>::type;
template <bool SizeMatches, class T, class... Vs>
struct TupleMoveConstructible : std::false_type {};
template <class... Ts, class... Vs>
struct TupleMoveConstructible<true, CompressedTuple<Ts...>, Vs...>
: std::integral_constant<
bool, absl::conjunction<
TupleElementMoveConstructible<Ts, Vs&&>...>::value> {};
template <typename T>
struct compressed_tuple_size;
template <typename... Es>
struct compressed_tuple_size<CompressedTuple<Es...>>
: public std::integral_constant<std::size_t, sizeof...(Es)> {};
template <class T, class... Vs>
struct TupleItemsMoveConstructible
: std::integral_constant<
bool, TupleMoveConstructible<compressed_tuple_size<T>::value ==
sizeof...(Vs),
T, Vs...>::value> {};
} // namespace internal_compressed_tuple
// Helper class to perform the Empty Base Class Optimization.
// Ts can contain classes and non-classes, empty or not. For the ones that
// are empty classes, we perform the CompressedTuple. If all types in Ts are
// empty classes, then CompressedTuple<Ts...> is itself an empty class. (This
// does not apply when one or more of those empty classes is itself an empty
// CompressedTuple.)
//
// To access the members, use member .get<N>() function.
//
// Eg:
// absl::container_internal::CompressedTuple<int, T1, T2, T3> value(7, t1, t2,
// t3);
// assert(value.get<0>() == 7);
// T1& t1 = value.get<1>();
// const T2& t2 = value.get<2>();
// ...
//
// https://en.cppreference.com/w/cpp/language/ebo
template <typename... Ts>
class ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple
: private internal_compressed_tuple::CompressedTupleImpl<
CompressedTuple<Ts...>, absl::index_sequence_for<Ts...>,
internal_compressed_tuple::ShouldAnyUseBase<Ts...>()> {
private:
template <int I>
using ElemT = internal_compressed_tuple::ElemT<CompressedTuple, I>;
template <int I>
using StorageT = internal_compressed_tuple::Storage<ElemT<I>, I>;
public:
// There seems to be a bug in MSVC dealing in which using '=default' here will
// cause the compiler to ignore the body of other constructors. The work-
// around is to explicitly implement the default constructor.
#if defined(_MSC_VER)
constexpr CompressedTuple() : CompressedTuple::CompressedTupleImpl() {}
#else
constexpr CompressedTuple() = default;
#endif
explicit constexpr CompressedTuple(const Ts&... base)
: CompressedTuple::CompressedTupleImpl(absl::in_place, base...) {}
template <typename First, typename... Vs,
absl::enable_if_t<
absl::conjunction<
// Ensure we are not hiding default copy/move constructors.
absl::negation<std::is_same<void(CompressedTuple),
void(absl::decay_t<First>)>>,
internal_compressed_tuple::TupleItemsMoveConstructible<
CompressedTuple<Ts...>, First, Vs...>>::value,
bool> = true>
explicit constexpr CompressedTuple(First&& first, Vs&&... base)
: CompressedTuple::CompressedTupleImpl(absl::in_place,
std::forward<First>(first),
std::forward<Vs>(base)...) {}
template <int I>
constexpr ElemT<I>& get() & {
return StorageT<I>::get();
}
template <int I>
constexpr const ElemT<I>& get() const& {
return StorageT<I>::get();
}
template <int I>
constexpr ElemT<I>&& get() && {
return std::move(*this).StorageT<I>::get();
}
template <int I>
constexpr const ElemT<I>&& get() const&& {
return std::move(*this).StorageT<I>::get();
}
};
// Explicit specialization for a zero-element tuple
// (needed to avoid ambiguous overloads for the default constructor).
template <>
class ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple<> {};
} // namespace container_internal
ABSL_NAMESPACE_END
} // namespace absl
#undef ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC
#endif // ABSL_CONTAINER_INTERNAL_COMPRESSED_TUPLE_H_
‰soong/.intermediates/external/abseil-cpp/absl_hash_weakly_mixed_integer_hdrs/gen/my_include_dir/absl/hash/internal/weakly_mixed_integer.h’
// Copyright 2025 The Abseil Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_HASH_INTERNAL_WEAKLY_MIXED_INTEGER_H_
#define ABSL_HASH_INTERNAL_WEAKLY_MIXED_INTEGER_H_
#include <cstddef>
#include "absl/base/config.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace hash_internal {
// Contains an integer that will be mixed into a hash state more weakly than
// regular integers. It is useful for cases in which an integer is a part of a
// larger object and needs to be mixed as a supplement. E.g., absl::string_view
// and absl::Span are mixing their size wrapped with WeaklyMixedInteger.
struct WeaklyMixedInteger {
size_t value;
};
} // namespace hash_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_HASH_INTERNAL_WEAKLY_MIXED_INTEGER_H_
*Êì
bsoong/.intermediates/external/abseil-cpp/absl_types_span_hdrs/gen/my_include_dir/absl/types/span.hâë//
// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// span.h
// -----------------------------------------------------------------------------
//
// This header file defines a `Span<T>` type for holding a reference to existing
// array data. The `Span` object, much like the `absl::string_view` object,
// does not own such data itself, and the data being referenced by the span must
// outlive the span itself. Unlike `view` type references, a span can hold a
// reference to mutable data (and can mutate it for underlying types of
// non-const T.) A span provides a lightweight way to pass a reference to such
// data.
//
// Additionally, this header file defines `MakeSpan()` and `MakeConstSpan()`
// factory functions, for clearly creating spans of type `Span<T>` or read-only
// `Span<const T>` when such types may be difficult to identify due to issues
// with implicit conversion.
//
// The C++20 draft standard includes a `std::span` type. As of June 2020, the
// differences between `absl::Span` and `std::span` are:
// * `absl::Span` has `operator==` (which is likely a design bug,
// per https://abseil.io/blog/20180531-regular-types)
// * `absl::Span` has the factory functions `MakeSpan()` and
// `MakeConstSpan()`
// * bounds-checked access to `absl::Span` is accomplished with `at()`
// * `absl::Span` has compiler-provided move and copy constructors and
// assignment. This is due to them being specified as `constexpr`, but that
// implies const in C++11.
// * A read-only `absl::Span<const T>` can be implicitly constructed from an
// initializer list.
// * `absl::Span` has no `bytes()`, `size_bytes()`, `as_bytes()`, or
// `as_writable_bytes()` methods
// * `absl::Span` has no static extent template parameter, nor constructors
// which exist only because of the static extent parameter.
// * `absl::Span` has an explicit mutable-reference constructor
//
// For more information, see the class comments below.
#ifndef ABSL_TYPES_SPAN_H_
#define ABSL_TYPES_SPAN_H_
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <initializer_list>
#include <iterator>
#include <type_traits>
#include <utility>
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/internal/throw_delegate.h"
#include "absl/base/macros.h"
#include "absl/base/nullability.h"
#include "absl/base/optimization.h"
#include "absl/base/port.h" // TODO(strel): remove this include
#include "absl/hash/internal/weakly_mixed_integer.h"
#include "absl/meta/type_traits.h"
#include "absl/types/internal/span.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
template <typename T>
class Span;
ABSL_NAMESPACE_END
} // namespace absl
// Android local modification: some security tests use "#define private public"
// to access private implementation details. libc++'s <ranges> is currently not
// compatible with that.
#if !defined(private)
// If std::ranges is available, mark Span as satisfying the `view` and
// `borrowed_range` concepts, just like std::span.
#if !defined(__has_include)
#define __has_include(header) 0
#endif
#if __has_include(<version>)
#include <version> // NOLINT(misc-include-cleaner)
#endif
#if defined(__cpp_lib_ranges) && __cpp_lib_ranges >= 201911L
#include <ranges> // NOLINT(build/c++20)
template <typename T>
// NOLINTNEXTLINE(build/c++20)
inline constexpr bool std::ranges::enable_view<absl::Span<T>> = true;
template <typename T>
// NOLINTNEXTLINE(build/c++20)
inline constexpr bool std::ranges::enable_borrowed_range<absl::Span<T>> = true;
#endif
#endif // !defined(private)
namespace absl {
ABSL_NAMESPACE_BEGIN
//------------------------------------------------------------------------------
// Span
//------------------------------------------------------------------------------
//
// A `Span` is an "array reference" type for holding a reference of contiguous
// array data; the `Span` object does not and cannot own such data itself. A
// span provides an easy way to provide overloads for anything operating on
// contiguous sequences without needing to manage pointers and array lengths
// manually.
// A span is conceptually a pointer (ptr) and a length (size) into an already
// existing array of contiguous memory; the array it represents references the
// elements "ptr[0] .. ptr[size-1]". Passing a properly-constructed `Span`
// instead of raw pointers avoids many issues related to index out of bounds
// errors.
//
// Spans may also be constructed from containers holding contiguous sequences.
// Such containers must supply `data()` and `size() const` methods (e.g
// `std::vector<T>`, `absl::InlinedVector<T, N>`). All implicit conversions to
// `absl::Span` from such containers will create spans of type `const T`;
// spans which can mutate their values (of type `T`) must use explicit
// constructors.
//
// A `Span<T>` is somewhat analogous to an `absl::string_view`, but for an array
// of elements of type `T`, and unlike an `absl::string_view`, a span can hold a
// reference to mutable data. A user of `Span` must ensure that the data being
// pointed to outlives the `Span` itself.
//
// You can construct a `Span<T>` in several ways:
//
// * Explicitly from a reference to a container type
// * Explicitly from a pointer and size
// * Implicitly from a container type (but only for spans of type `const T`)
// * Using the `MakeSpan()` or `MakeConstSpan()` factory functions.
//
// Examples:
//
// // Construct a Span explicitly from a container:
// std::vector<int> v = {1, 2, 3, 4, 5};
// auto span = absl::Span<const int>(v);
//
// // Construct a Span explicitly from a C-style array:
// int a[5] = {1, 2, 3, 4, 5};
// auto span = absl::Span<const int>(a);
//
// // Construct a Span implicitly from a container
// void MyRoutine(absl::Span<const int> a) {
// ...
// }
// std::vector v = {1,2,3,4,5};
// MyRoutine(v) // convert to Span<const T>
//
// Note that `Span` objects, in addition to requiring that the memory they
// point to remains alive, must also ensure that such memory does not get
// reallocated. Therefore, to avoid undefined behavior, containers with
// associated spans should not invoke operations that may reallocate memory
// (such as resizing) or invalidate iterators into the container.
//
// One common use for a `Span` is when passing arguments to a routine that can
// accept a variety of array types (e.g. a `std::vector`, `absl::InlinedVector`,
// a C-style array, etc.). Instead of creating overloads for each case, you
// can simply specify a `Span` as the argument to such a routine.
//
// Example:
//
// void MyRoutine(absl::Span<const int> a) {
// ...
// }
//
// std::vector v = {1,2,3,4,5};
// MyRoutine(v);
//
// absl::InlinedVector<int, 4> my_inline_vector;
// MyRoutine(my_inline_vector);
//
// // Explicit constructor from pointer,size
// int* my_array = new int[10];
// MyRoutine(absl::Span<const int>(my_array, 10));
template <typename T>
class ABSL_ATTRIBUTE_VIEW Span {
private:
// Used to determine whether a Span can be constructed from a container of
// type C.
template <typename C>
using EnableIfConvertibleFrom =
typename std::enable_if<span_internal::HasData<T, C>::value &&
span_internal::HasSize<C>::value>::type;
// Used to SFINAE-enable a function when the slice elements are const.
template <typename U>
using EnableIfValueIsConst =
typename std::enable_if<std::is_const<T>::value, U>::type;
// Used to SFINAE-enable a function when the slice elements are mutable.
template <typename U>
using EnableIfValueIsMutable =
typename std::enable_if<!std::is_const<T>::value, U>::type;
public:
using element_type = T;
using value_type = absl::remove_cv_t<T>;
// TODO(b/316099902) - pointer should be absl_nullable, but this makes it hard
// to recognize foreach loops as safe. absl_nullability_unknown is currently
// used to suppress -Wnullability-completeness warnings.
using pointer = T* absl_nullability_unknown;
using const_pointer = const T* absl_nullability_unknown;
using reference = T&;
using const_reference = const T&;
using iterator = pointer;
using const_iterator = const_pointer;
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
using size_type = size_t;
using difference_type = ptrdiff_t;
using absl_internal_is_view = std::true_type;
// NOLINTNEXTLINE
static const size_type npos = ~(size_type(0));
constexpr Span() noexcept : Span(nullptr, 0) {}
constexpr Span(pointer array ABSL_ATTRIBUTE_LIFETIME_BOUND,
size_type length) noexcept
: ptr_(array), len_(length) {}
// Implicit conversion constructors
template <size_t N>
constexpr Span(T( // NOLINT(google-explicit-constructor)
&a ABSL_ATTRIBUTE_LIFETIME_BOUND)[N]) noexcept
: Span(a, N) {}
// Explicit reference constructor for a mutable `Span<T>` type. Can be
// replaced with MakeSpan() to infer the type parameter.
template <typename V, typename = EnableIfConvertibleFrom<V>,
typename = EnableIfValueIsMutable<V>,
typename = span_internal::EnableIfNotIsView<V>>
explicit Span(
V& v
ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept // NOLINT(runtime/references)
: Span(span_internal::GetData(v), v.size()) {}
// Implicit reference constructor for a read-only `Span<const T>` type
template <typename V, typename = EnableIfConvertibleFrom<V>,
typename = EnableIfValueIsConst<V>,
typename = span_internal::EnableIfNotIsView<V>>
// NOLINTNEXTLINE(google-explicit-constructor)
constexpr Span(const V& v ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept
: Span(span_internal::GetData(v), v.size()) {}
// Overloads of the above two functions that are only enabled for view types.
// This is so we can drop the ABSL_ATTRIBUTE_LIFETIME_BOUND annotation. These
// overloads must be made unique by using a different template parameter list
// (hence the = 0 for the IsView enabler).
template <typename V, typename = EnableIfConvertibleFrom<V>,
typename = EnableIfValueIsMutable<V>,
span_internal::EnableIfIsView<V> = 0>
explicit Span(V& v) noexcept // NOLINT(runtime/references)
: Span(span_internal::GetData(v), v.size()) {}
template <typename V, typename = EnableIfConvertibleFrom<V>,
typename = EnableIfValueIsConst<V>,
span_internal::EnableIfIsView<V> = 0>
constexpr Span(const V& v) noexcept // NOLINT(google-explicit-constructor)
: Span(span_internal::GetData(v), v.size()) {}
// Implicit constructor from an initializer list, making it possible to pass a
// brace-enclosed initializer list to a function expecting a `Span`. Such
// spans constructed from an initializer list must be of type `Span<const T>`.
//
// void Process(absl::Span<const int> x);
// Process({1, 2, 3});
//
// Note that as always the array referenced by the span must outlive the span.
// Since an initializer list constructor acts as if it is fed a temporary
// array (cf. C++ standard [dcl.init.list]/5), it's safe to use this
// constructor only when the `std::initializer_list` itself outlives the span.
// In order to meet this requirement it's sufficient to ensure that neither
// the span nor a copy of it is used outside of the expression in which it's
// created:
//
// // Assume that this function uses the array directly, not retaining any
// // copy of the span or pointer to any of its elements.
// void Process(absl::Span<const int> ints);
//
// // Okay: the std::initializer_list<int> will reference a temporary array
// // that isn't destroyed until after the call to Process returns.
// Process({ 17, 19 });
//
// // Not okay: the storage used by the std::initializer_list<int> is not
// // allowed to be referenced after the first line.
// absl::Span<const int> ints = { 17, 19 };
// Process(ints);
//
// // Not okay for the same reason as above: even when the elements of the
// // initializer list expression are not temporaries the underlying array
// // is, so the initializer list must still outlive the span.
// const int foo = 17;
// absl::Span<const int> ints = { foo };
// Process(ints);
//
template <typename LazyT = T,
typename = EnableIfValueIsConst<LazyT>>
Span(std::initializer_list<value_type> v
ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept // NOLINT(runtime/explicit)
: Span(v.begin(), v.size()) {}
// Accessors
// Span::data()
//
// Returns a pointer to the span's underlying array of data (which is held
// outside the span).
constexpr pointer data() const noexcept { return ptr_; }
// Span::size()
//
// Returns the size of this span.
constexpr size_type size() const noexcept { return len_; }
// Span::length()
//
// Returns the length (size) of this span.
constexpr size_type length() const noexcept { return size(); }
// Span::empty()
//
// Returns a boolean indicating whether or not this span is considered empty.
constexpr bool empty() const noexcept { return size() == 0; }
// Span::operator[]
//
// Returns a reference to the i'th element of this span.
constexpr reference operator[](size_type i) const noexcept {
ABSL_HARDENING_ASSERT(i < size());
return ptr_[i];
}
// Span::at()
//
// Returns a reference to the i'th element of this span.
constexpr reference at(size_type i) const {
return ABSL_PREDICT_TRUE(i < size()) //
? *(data() + i)
: (base_internal::ThrowStdOutOfRange(
"Span::at failed bounds check"),
*(data() + i));
}
// Span::front()
//
// Returns a reference to the first element of this span. The span must not
// be empty.
constexpr reference front() const noexcept {
ABSL_HARDENING_ASSERT(size() > 0);
return *data();
}
// Span::back()
//
// Returns a reference to the last element of this span. The span must not
// be empty.
constexpr reference back() const noexcept {
ABSL_HARDENING_ASSERT(size() > 0);
return *(data() + size() - 1);
}
// Span::begin()
//
// Returns an iterator pointing to the first element of this span, or `end()`
// if the span is empty.
constexpr iterator begin() const noexcept { return data(); }
// Span::cbegin()
//
// Returns a const iterator pointing to the first element of this span, or
// `end()` if the span is empty.
constexpr const_iterator cbegin() const noexcept { return begin(); }
// Span::end()
//
// Returns an iterator pointing just beyond the last element at the
// end of this span. This iterator acts as a placeholder; attempting to
// access it results in undefined behavior.
constexpr iterator end() const noexcept { return data() + size(); }
// Span::cend()
//
// Returns a const iterator pointing just beyond the last element at the
// end of this span. This iterator acts as a placeholder; attempting to
// access it results in undefined behavior.
constexpr const_iterator cend() const noexcept { return end(); }
// Span::rbegin()
//
// Returns a reverse iterator pointing to the last element at the end of this
// span, or `rend()` if the span is empty.
constexpr reverse_iterator rbegin() const noexcept {
return reverse_iterator(end());
}
// Span::crbegin()
//
// Returns a const reverse iterator pointing to the last element at the end of
// this span, or `crend()` if the span is empty.
constexpr const_reverse_iterator crbegin() const noexcept { return rbegin(); }
// Span::rend()
//
// Returns a reverse iterator pointing just before the first element
// at the beginning of this span. This pointer acts as a placeholder;
// attempting to access its element results in undefined behavior.
constexpr reverse_iterator rend() const noexcept {
return reverse_iterator(begin());
}
// Span::crend()
//
// Returns a reverse const iterator pointing just before the first element
// at the beginning of this span. This pointer acts as a placeholder;
// attempting to access its element results in undefined behavior.
constexpr const_reverse_iterator crend() const noexcept { return rend(); }
// Span mutations
// Span::remove_prefix()
//
// Removes the first `n` elements from the span.
void remove_prefix(size_type n) noexcept {
ABSL_HARDENING_ASSERT(size() >= n);
ptr_ += n;
len_ -= n;
}
// Span::remove_suffix()
//
// Removes the last `n` elements from the span.
void remove_suffix(size_type n) noexcept {
ABSL_HARDENING_ASSERT(size() >= n);
len_ -= n;
}
// Span::subspan()
//
// Returns a `Span` starting at element `pos` and of length `len`. Both `pos`
// and `len` are of type `size_type` and thus non-negative. Parameter `pos`
// must be <= size(). Any `len` value that points past the end of the span
// will be trimmed to at most size() - `pos`. A default `len` value of `npos`
// ensures the returned subspan continues until the end of the span.
//
// Examples:
//
// std::vector<int> vec = {10, 11, 12, 13};
// absl::MakeSpan(vec).subspan(1, 2); // {11, 12}
// absl::MakeSpan(vec).subspan(2, 8); // {12, 13}
// absl::MakeSpan(vec).subspan(1); // {11, 12, 13}
// absl::MakeSpan(vec).subspan(4); // {}
// absl::MakeSpan(vec).subspan(5); // throws std::out_of_range
constexpr Span subspan(size_type pos = 0, size_type len = npos) const {
return (pos <= size())
? Span(data() + pos, (std::min)(size() - pos, len))
: (base_internal::ThrowStdOutOfRange("pos > size()"), Span());
}
// Span::first()
//
// Returns a `Span` containing first `len` elements. Parameter `len` is of
// type `size_type` and thus non-negative. `len` value must be <= size().
//
// Examples:
//
// std::vector<int> vec = {10, 11, 12, 13};
// absl::MakeSpan(vec).first(1); // {10}
// absl::MakeSpan(vec).first(3); // {10, 11, 12}
// absl::MakeSpan(vec).first(5); // throws std::out_of_range
constexpr Span first(size_type len) const {
return (len <= size())
? Span(data(), len)
: (base_internal::ThrowStdOutOfRange("len > size()"), Span());
}
// Span::last()
//
// Returns a `Span` containing last `len` elements. Parameter `len` is of
// type `size_type` and thus non-negative. `len` value must be <= size().
//
// Examples:
//
// std::vector<int> vec = {10, 11, 12, 13};
// absl::MakeSpan(vec).last(1); // {13}
// absl::MakeSpan(vec).last(3); // {11, 12, 13}
// absl::MakeSpan(vec).last(5); // throws std::out_of_range
constexpr Span last(size_type len) const {
return (len <= size())
? Span(size() - len + data(), len)
: (base_internal::ThrowStdOutOfRange("len > size()"), Span());
}
// Support for absl::Hash.
template <typename H>
friend H AbslHashValue(H h, Span v) {
return H::combine(H::combine_contiguous(std::move(h), v.data(), v.size()),
hash_internal::WeaklyMixedInteger{v.size()});
}
private:
pointer ptr_;
size_type len_;
};
template <typename T>
const typename Span<T>::size_type Span<T>::npos;
// Span relationals
// Equality is compared element-by-element, while ordering is lexicographical.
// We provide three overloads for each operator to cover any combination on the
// left or right hand side of mutable Span<T>, read-only Span<const T>, and
// convertible-to-read-only Span<T>.
// TODO(zhangxy): Due to MSVC overload resolution bug with partial ordering
// template functions, 5 overloads per operator is needed as a workaround. We
// should update them to 3 overloads per operator using non-deduced context like
// string_view, i.e.
// - (Span<T>, Span<T>)
// - (Span<T>, non_deduced<Span<const T>>)
// - (non_deduced<Span<const T>>, Span<T>)
// operator==
template <typename T>
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator==(Span<T> a, Span<T> b) {
return span_internal::EqualImpl<Span, const T>(a, b);
}
template <typename T>
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator==(Span<const T> a,
Span<T> b) {
return span_internal::EqualImpl<Span, const T>(a, b);
}
template <typename T>
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator==(Span<T> a,
Span<const T> b) {
return span_internal::EqualImpl<Span, const T>(a, b);
}
template <
typename T, typename U,
typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator==(const U& a, Span<T> b) {
return span_internal::EqualImpl<Span, const T>(a, b);
}
template <
typename T, typename U,
typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator==(Span<T> a, const U& b) {
return span_internal::EqualImpl<Span, const T>(a, b);
}
// operator!=
template <typename T>
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator!=(Span<T> a, Span<T> b) {
return !(a == b);
}
template <typename T>
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator!=(Span<const T> a,
Span<T> b) {
return !(a == b);
}
template <typename T>
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator!=(Span<T> a,
Span<const T> b) {
return !(a == b);
}
template <
typename T, typename U,
typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator!=(const U& a, Span<T> b) {
return !(a == b);
}
template <
typename T, typename U,
typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator!=(Span<T> a, const U& b) {
return !(a == b);
}
// operator<
template <typename T>
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<(Span<T> a, Span<T> b) {
return span_internal::LessThanImpl<Span, const T>(a, b);
}
template <typename T>
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<(Span<const T> a, Span<T> b) {
return span_internal::LessThanImpl<Span, const T>(a, b);
}
template <typename T>
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<(Span<T> a, Span<const T> b) {
return span_internal::LessThanImpl<Span, const T>(a, b);
}
template <
typename T, typename U,
typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<(const U& a, Span<T> b) {
return span_internal::LessThanImpl<Span, const T>(a, b);
}
template <
typename T, typename U,
typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<(Span<T> a, const U& b) {
return span_internal::LessThanImpl<Span, const T>(a, b);
}
// operator>
template <typename T>
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>(Span<T> a, Span<T> b) {
return b < a;
}
template <typename T>
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>(Span<const T> a, Span<T> b) {
return b < a;
}
template <typename T>
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>(Span<T> a, Span<const T> b) {
return b < a;
}
template <
typename T, typename U,
typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>(const U& a, Span<T> b) {
return b < a;
}
template <
typename T, typename U,
typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>(Span<T> a, const U& b) {
return b < a;
}
// operator<=
template <typename T>
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<=(Span<T> a, Span<T> b) {
return !(b < a);
}
template <typename T>
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<=(Span<const T> a,
Span<T> b) {
return !(b < a);
}
template <typename T>
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<=(Span<T> a,
Span<const T> b) {
return !(b < a);
}
template <
typename T, typename U,
typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<=(const U& a, Span<T> b) {
return !(b < a);
}
template <
typename T, typename U,
typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator<=(Span<T> a, const U& b) {
return !(b < a);
}
// operator>=
template <typename T>
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>=(Span<T> a, Span<T> b) {
return !(a < b);
}
template <typename T>
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>=(Span<const T> a,
Span<T> b) {
return !(a < b);
}
template <typename T>
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>=(Span<T> a,
Span<const T> b) {
return !(a < b);
}
template <
typename T, typename U,
typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>=(const U& a, Span<T> b) {
return !(a < b);
}
template <
typename T, typename U,
typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool operator>=(Span<T> a, const U& b) {
return !(a < b);
}
// MakeSpan()
//
// Constructs a mutable `Span<T>`, deducing `T` automatically from either a
// container or pointer+size.
//
// Because a read-only `Span<const T>` is implicitly constructed from container
// types regardless of whether the container itself is a const container,
// constructing mutable spans of type `Span<T>` from containers requires
// explicit constructors. The container-accepting version of `MakeSpan()`
// deduces the type of `T` by the constness of the pointer received from the
// container's `data()` member. Similarly, the pointer-accepting version returns
// a `Span<const T>` if `T` is `const`, and a `Span<T>` otherwise.
//
// Examples:
//
// void MyRoutine(absl::Span<MyComplicatedType> a) {
// ...
// };
// // my_vector is a container of non-const types
// std::vector<MyComplicatedType> my_vector;
//
// // Constructing a Span implicitly attempts to create a Span of type
// // `Span<const T>`
// MyRoutine(my_vector); // error, type mismatch
//
// // Explicitly constructing the Span is verbose
// MyRoutine(absl::Span<MyComplicatedType>(my_vector));
//
// // Use MakeSpan() to make an absl::Span<T>
// MyRoutine(absl::MakeSpan(my_vector));
//
// // Construct a span from an array ptr+size
// absl::Span<T> my_span() {
// return absl::MakeSpan(&array[0], num_elements_);
// }
//
template <int&... ExplicitArgumentBarrier, typename T>
constexpr Span<T> MakeSpan(T* absl_nullable ptr, size_t size) noexcept {
return Span<T>(ptr, size);
}
template <int&... ExplicitArgumentBarrier, typename T>
Span<T> MakeSpan(T* absl_nullable begin, T* absl_nullable end) noexcept {
ABSL_HARDENING_ASSERT(begin <= end);
return Span<T>(begin, static_cast<size_t>(end - begin));
}
template <int&... ExplicitArgumentBarrier, typename C>
constexpr auto MakeSpan(C& c) noexcept // NOLINT(runtime/references)
-> decltype(absl::MakeSpan(span_internal::GetData(c), c.size())) {
return MakeSpan(span_internal::GetData(c), c.size());
}
template <int&... ExplicitArgumentBarrier, typename T, size_t N>
constexpr Span<T> MakeSpan(T (&array)[N]) noexcept {
return Span<T>(array, N);
}
// MakeConstSpan()
//
// Constructs a `Span<const T>` as with `MakeSpan`, deducing `T` automatically,
// but always returning a `Span<const T>`.
//
// Examples:
//
// void ProcessInts(absl::Span<const int> some_ints);
//
// // Call with a pointer and size.
// int array[3] = { 0, 0, 0 };
// ProcessInts(absl::MakeConstSpan(&array[0], 3));
//
// // Call with a [begin, end) pair.
// ProcessInts(absl::MakeConstSpan(&array[0], &array[3]));
//
// // Call directly with an array.
// ProcessInts(absl::MakeConstSpan(array));
//
// // Call with a contiguous container.
// std::vector<int> some_ints = ...;
// ProcessInts(absl::MakeConstSpan(some_ints));
// ProcessInts(absl::MakeConstSpan(std::vector<int>{ 0, 0, 0 }));
//
template <int&... ExplicitArgumentBarrier, typename T>
constexpr Span<const T> MakeConstSpan(T* absl_nullable ptr,
size_t size) noexcept {
return Span<const T>(ptr, size);
}
template <int&... ExplicitArgumentBarrier, typename T>
Span<const T> MakeConstSpan(T* absl_nullable begin,
T* absl_nullable end) noexcept {
ABSL_HARDENING_ASSERT(begin <= end);
return Span<const T>(begin, end - begin);
}
template <int&... ExplicitArgumentBarrier, typename C>
constexpr auto MakeConstSpan(const C& c) noexcept -> decltype(MakeSpan(c)) {
return MakeSpan(c);
}
template <int&... ExplicitArgumentBarrier, typename T, size_t N>
constexpr Span<const T> MakeConstSpan(const T (&array)[N]) noexcept {
return Span<const T>(array, N);
}
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_TYPES_SPAN_H_
*ìŸ
nsoong/.intermediates/external/abseil-cpp/absl_meta_type_traits_hdrs/gen/my_include_dir/absl/meta/type_traits.høž//
// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// type_traits.h
// -----------------------------------------------------------------------------
//
// This file contains C++11-compatible versions of standard <type_traits> API
// functions for determining the characteristics of types. Such traits can
// support type inference, classification, and transformation, as well as
// make it easier to write templates based on generic type behavior.
//
// See https://en.cppreference.com/w/cpp/header/type_traits
//
// WARNING: use of many of the constructs in this header will count as "complex
// template metaprogramming", so before proceeding, please carefully consider
// https://google.github.io/styleguide/cppguide.html#Template_metaprogramming
//
// WARNING: using template metaprogramming to detect or depend on API
// features is brittle and not guaranteed. Neither the standard library nor
// Abseil provides any guarantee that APIs are stable in the face of template
// metaprogramming. Use with caution.
#ifndef ABSL_META_TYPE_TRAITS_H_
#define ABSL_META_TYPE_TRAITS_H_
#include <cstddef>
#include <functional>
#include <string>
#include <string_view>
#include <type_traits>
#include <vector>
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#ifdef __cpp_lib_span
#include <span> // NOLINT(build/c++20)
#endif
// Defines the default alignment. `__STDCPP_DEFAULT_NEW_ALIGNMENT__` is a C++17
// feature.
#if defined(__STDCPP_DEFAULT_NEW_ALIGNMENT__)
#define ABSL_INTERNAL_DEFAULT_NEW_ALIGNMENT __STDCPP_DEFAULT_NEW_ALIGNMENT__
#else // defined(__STDCPP_DEFAULT_NEW_ALIGNMENT__)
#define ABSL_INTERNAL_DEFAULT_NEW_ALIGNMENT alignof(std::max_align_t)
#endif // defined(__STDCPP_DEFAULT_NEW_ALIGNMENT__)
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace type_traits_internal {
template <typename... Ts>
struct VoidTImpl {
using type = void;
};
////////////////////////////////
// Library Fundamentals V2 TS //
////////////////////////////////
// NOTE: The `is_detected` family of templates here differ from the library
// fundamentals specification in that for library fundamentals, `Op<Args...>` is
// evaluated as soon as the type `is_detected<Op, Args...>` undergoes
// substitution, regardless of whether or not the `::value` is accessed. That
// is inconsistent with all other standard traits and prevents lazy evaluation
// in larger contexts (such as if the `is_detected` check is a trailing argument
// of a `conjunction`. This implementation opts to instead be lazy in the same
// way that the standard traits are (this "defect" of the detection idiom
// specifications has been reported).
template <class Enabler, template <class...> class Op, class... Args>
struct is_detected_impl {
using type = std::false_type;
};
template <template <class...> class Op, class... Args>
struct is_detected_impl<typename VoidTImpl<Op<Args...>>::type, Op, Args...> {
using type = std::true_type;
};
template <template <class...> class Op, class... Args>
struct is_detected : is_detected_impl<void, Op, Args...>::type {};
} // namespace type_traits_internal
// void_t()
//
// Ignores the type of any its arguments and returns `void`. In general, this
// metafunction allows you to create a general case that maps to `void` while
// allowing specializations that map to specific types.
//
// This metafunction is not 100% compatible with the C++17 `std::void_t`
// metafunction. It has slightly different behavior, such as when ordering
// partial specializations. It is recommended to use `std::void_t` instead.
template <typename... Ts>
using void_t = typename type_traits_internal::VoidTImpl<Ts...>::type;
// Historical note: Abseil once provided implementations of these type traits
// for platforms that lacked full support. New code should prefer to use the
// std variants.
//
// See the documentation for the STL <type_traits> header for more information:
// https://en.cppreference.com/w/cpp/header/type_traits
using std::add_const_t;
using std::add_cv_t;
using std::add_lvalue_reference_t;
using std::add_pointer_t;
using std::add_rvalue_reference_t;
using std::add_volatile_t;
using std::common_type_t;
using std::conditional_t;
using std::conjunction;
using std::decay_t;
using std::enable_if_t;
using std::disjunction;
using std::is_copy_assignable;
using std::is_function;
using std::is_move_assignable;
using std::is_trivially_copy_assignable;
using std::is_trivially_copy_constructible;
using std::is_trivially_default_constructible;
using std::is_trivially_destructible;
using std::is_trivially_move_assignable;
using std::is_trivially_move_constructible;
using std::make_signed_t;
using std::make_unsigned_t;
using std::negation;
using std::remove_all_extents_t;
using std::remove_const_t;
using std::remove_cv_t;
using std::remove_extent_t;
using std::remove_pointer_t;
using std::remove_reference_t;
using std::remove_volatile_t;
using std::underlying_type_t;
#if defined(__cpp_lib_remove_cvref) && __cpp_lib_remove_cvref >= 201711L
template <typename T>
using remove_cvref = std::remove_cvref<T>;
template <typename T>
using remove_cvref_t = typename std::remove_cvref<T>::type;
#else
// remove_cvref()
//
// C++11 compatible implementation of std::remove_cvref which was added in
// C++20.
template <typename T>
struct remove_cvref {
using type =
typename std::remove_cv<typename std::remove_reference<T>::type>::type;
};
template <typename T>
using remove_cvref_t = typename remove_cvref<T>::type;
#endif
namespace type_traits_internal {
#if (defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703L) || \
(defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
// std::result_of is deprecated (C++17) or removed (C++20)
template <typename>
struct result_of;
template <typename F, typename... Args>
struct result_of<F(Args...)> : std::invoke_result<F, Args...> {};
#else
template <typename F>
using result_of = std::result_of<F>;
#endif
} // namespace type_traits_internal
template <typename F>
using result_of_t = typename type_traits_internal::result_of<F>::type;
namespace type_traits_internal {
// In MSVC we can't probe std::hash or stdext::hash because it triggers a
// static_assert instead of failing substitution. Libc++ prior to 4.0
// also used a static_assert.
//
#if defined(_MSC_VER) || (defined(_LIBCPP_VERSION) && \
_LIBCPP_VERSION < 4000 && _LIBCPP_STD_VER > 11)
#define ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ 0
#else
#define ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ 1
#endif
#if !ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
template <typename Key, typename = size_t>
struct IsHashable : std::true_type {};
#else // ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
template <typename Key, typename = void>
struct IsHashable : std::false_type {};
template <typename Key>
struct IsHashable<
Key,
absl::enable_if_t<std::is_convertible<
decltype(std::declval<std::hash<Key>&>()(std::declval<Key const&>())),
std::size_t>::value>> : std::true_type {};
#endif // !ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
struct AssertHashEnabledHelper {
private:
static void Sink(...) {}
struct NAT {};
template <class Key>
static auto GetReturnType(int)
-> decltype(std::declval<std::hash<Key>>()(std::declval<Key const&>()));
template <class Key>
static NAT GetReturnType(...);
template <class Key>
static std::nullptr_t DoIt() {
static_assert(IsHashable<Key>::value,
"std::hash<Key> does not provide a call operator");
static_assert(
std::is_default_constructible<std::hash<Key>>::value,
"std::hash<Key> must be default constructible when it is enabled");
static_assert(
std::is_copy_constructible<std::hash<Key>>::value,
"std::hash<Key> must be copy constructible when it is enabled");
static_assert(absl::is_copy_assignable<std::hash<Key>>::value,
"std::hash<Key> must be copy assignable when it is enabled");
// is_destructible is unchecked as it's implied by each of the
// is_constructible checks.
using ReturnType = decltype(GetReturnType<Key>(0));
static_assert(std::is_same<ReturnType, NAT>::value ||
std::is_same<ReturnType, size_t>::value,
"std::hash<Key> must return size_t");
return nullptr;
}
template <class... Ts>
friend void AssertHashEnabled();
};
template <class... Ts>
inline void AssertHashEnabled() {
using Helper = AssertHashEnabledHelper;
Helper::Sink(Helper::DoIt<Ts>()...);
}
} // namespace type_traits_internal
// An internal namespace that is required to implement the C++17 swap traits.
// It is not further nested in type_traits_internal to avoid long symbol names.
namespace swap_internal {
// Necessary for the traits.
using std::swap;
// This declaration prevents global `swap` and `absl::swap` overloads from being
// considered unless ADL picks them up.
void swap();
template <class T>
using IsSwappableImpl = decltype(swap(std::declval<T&>(), std::declval<T&>()));
// NOTE: This dance with the default template parameter is for MSVC.
template <class T,
class IsNoexcept = std::integral_constant<
bool, noexcept(swap(std::declval<T&>(), std::declval<T&>()))>>
using IsNothrowSwappableImpl = typename std::enable_if<IsNoexcept::value>::type;
// IsSwappable
//
// Determines whether the standard swap idiom is a valid expression for
// arguments of type `T`.
template <class T>
struct IsSwappable
: absl::type_traits_internal::is_detected<IsSwappableImpl, T> {};
// IsNothrowSwappable
//
// Determines whether the standard swap idiom is a valid expression for
// arguments of type `T` and is noexcept.
template <class T>
struct IsNothrowSwappable
: absl::type_traits_internal::is_detected<IsNothrowSwappableImpl, T> {};
// Swap()
//
// Performs the swap idiom from a namespace where valid candidates may only be
// found in `std` or via ADL.
template <class T, absl::enable_if_t<IsSwappable<T>::value, int> = 0>
void Swap(T& lhs, T& rhs) noexcept(IsNothrowSwappable<T>::value) {
swap(lhs, rhs);
}
// StdSwapIsUnconstrained
//
// Some standard library implementations are broken in that they do not
// constrain `std::swap`. This will effectively tell us if we are dealing with
// one of those implementations.
using StdSwapIsUnconstrained = IsSwappable<void()>;
} // namespace swap_internal
namespace type_traits_internal {
// Make the swap-related traits/function accessible from this namespace.
using swap_internal::IsNothrowSwappable;
using swap_internal::IsSwappable;
using swap_internal::StdSwapIsUnconstrained;
using swap_internal::Swap;
} // namespace type_traits_internal
// absl::is_trivially_relocatable<T>
//
// https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2786r11.html
//
// Detects whether a type is known to be "trivially relocatable" -- meaning it
// can be relocated from one place to another as if by memcpy/memmove.
// This implies that its object representation doesn't depend on its address,
// and also none of its special member functions do anything strange.
//
// Note that when relocating the caller code should ensure that if the object is
// polymorphic, the dynamic type is of the most derived type. Padding bytes
// should not be copied.
//
// This trait is conservative. If it's true then the type is definitely
// trivially relocatable, but if it's false then the type may or may not be. For
// example, std::vector<int> is trivially relocatable on every known STL
// implementation, but absl::is_trivially_relocatable<std::vector<int>> remains
// false.
//
// Example:
//
// if constexpr (absl::is_trivially_relocatable<T>::value) {
// memcpy(new_location, old_location, sizeof(T));
// } else {
// new(new_location) T(std::move(*old_location));
// old_location->~T();
// }
//
// Upstream documentation:
//
// https://clang.llvm.org/docs/LanguageExtensions.html#:~:text=__builtin_is_cpp_trivially_relocatable
//
// Clang on Windows has the builtin, but it falsely claims types with a
// user-provided destructor are trivial (http://b/275003464). So we opt out
// there.
//
// TODO(b/275003464): remove the opt-out once the bug is fixed.
//
// Starting with Xcode 15, the Apple compiler will falsely say a type
// with a user-provided move constructor is trivially relocatable
// (b/324278148). We will opt out without a version check, due to
// the fluidity of Apple versions.
//
// TODO(b/324278148): If all versions we use have the bug fixed, then
// remove the condition.
//
// Clang on all platforms fails to detect that a type with a user-provided
// move-assignment operator is not trivially relocatable so we also check for
// is_trivially_move_assignable for Clang.
//
// TODO(b/325479096): Remove the Clang is_trivially_move_assignable version once
// Clang's behavior is fixed.
//
// According to https://github.com/abseil/abseil-cpp/issues/1479, this does not
// work with NVCC either.
#if ABSL_HAVE_BUILTIN(__builtin_is_cpp_trivially_relocatable)
// https://github.com/llvm/llvm-project/pull/127636#pullrequestreview-2637005293
// In the current implementation, __builtin_is_cpp_trivially_relocatable will
// only return true for types that are trivially relocatable according to the
// standard. Notably, this means that marking a type [[clang::trivial_abi]] aka
// ABSL_HAVE_ATTRIBUTE_TRIVIAL_ABI will have no effect on this trait.
template <class T>
struct is_trivially_relocatable
: std::integral_constant<bool, __builtin_is_cpp_trivially_relocatable(T)> {
};
#elif ABSL_HAVE_BUILTIN(__is_trivially_relocatable) && defined(__clang__) && \
!(defined(_WIN32) || defined(_WIN64)) && !defined(__APPLE__) && \
!defined(__NVCC__)
// https://github.com/llvm/llvm-project/pull/139061
// __is_trivially_relocatable is deprecated.
// TODO(b/325479096): Remove this case.
template <class T>
struct is_trivially_relocatable
: std::integral_constant<
bool, std::is_trivially_copyable<T>::value ||
(__is_trivially_relocatable(T) &&
std::is_trivially_move_assignable<T>::value)> {};
#else
// Otherwise we use a fallback that detects only those types we can feasibly
// detect. Any type that is trivially copyable is by definition trivially
// relocatable.
template <class T>
struct is_trivially_relocatable : std::is_trivially_copyable<T> {};
#endif
// absl::is_constant_evaluated()
//
// Detects whether the function call occurs within a constant-evaluated context.
// Returns true if the evaluation of the call occurs within the evaluation of an
// expression or conversion that is manifestly constant-evaluated; otherwise
// returns false.
//
// This function is implemented in terms of `std::is_constant_evaluated` for
// c++20 and up. For older c++ versions, the function is implemented in terms
// of `__builtin_is_constant_evaluated` if available, otherwise the function
// will fail to compile.
//
// Applications can inspect `ABSL_HAVE_CONSTANT_EVALUATED` at compile time
// to check if this function is supported.
//
// Example:
//
// constexpr MyClass::MyClass(int param) {
// #ifdef ABSL_HAVE_CONSTANT_EVALUATED
// if (!absl::is_constant_evaluated()) {
// ABSL_LOG(INFO) << "MyClass(" << param << ")";
// }
// #endif // ABSL_HAVE_CONSTANT_EVALUATED
// }
//
// Upstream documentation:
//
// http://en.cppreference.com/w/cpp/types/is_constant_evaluated
// http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html#:~:text=__builtin_is_constant_evaluated
//
#if defined(ABSL_HAVE_CONSTANT_EVALUATED)
constexpr bool is_constant_evaluated() noexcept {
#ifdef __cpp_lib_is_constant_evaluated
return std::is_constant_evaluated();
#elif ABSL_HAVE_BUILTIN(__builtin_is_constant_evaluated)
return __builtin_is_constant_evaluated();
#endif
}
#endif // ABSL_HAVE_CONSTANT_EVALUATED
namespace type_traits_internal {
// Detects if a class's definition has declared itself to be an owner by
// declaring
// using absl_internal_is_view = std::true_type;
// as a member.
// Types that don't want either must either omit this declaration entirely, or
// (if e.g. inheriting from a base class) define the member to something that
// isn't a Boolean trait class, such as `void`.
// Do not specialize or use this directly. It's an implementation detail.
template <typename T, typename = void>
struct IsOwnerImpl : std::false_type {
static_assert(std::is_same<T, absl::remove_cvref_t<T>>::value,
"type must lack qualifiers");
};
template <typename T>
struct IsOwnerImpl<
T,
std::enable_if_t<std::is_class<typename T::absl_internal_is_view>::value>>
: absl::negation<typename T::absl_internal_is_view> {};
// A trait to determine whether a type is an owner.
// Do *not* depend on the correctness of this trait for correct code behavior.
// It is only a safety feature and its value may change in the future.
// Do not specialize this; instead, define the member trait inside your type so
// that it can be auto-detected, and to prevent ODR violations.
// If it ever becomes possible to detect [[gsl::Owner]], we should leverage it:
// https://wg21.link/p1179
template <typename T>
struct IsOwner : IsOwnerImpl<T> {};
template <typename T, typename Traits, typename Alloc>
struct IsOwner<std::basic_string<T, Traits, Alloc>> : std::true_type {};
template <typename T, typename Alloc>
struct IsOwner<std::vector<T, Alloc>> : std::true_type {};
// Detects if a class's definition has declared itself to be a view by declaring
// using absl_internal_is_view = std::true_type;
// as a member.
// Do not specialize or use this directly.
template <typename T, typename = void>
struct IsViewImpl : std::false_type {
static_assert(std::is_same<T, absl::remove_cvref_t<T>>::value,
"type must lack qualifiers");
};
template <typename T>
struct IsViewImpl<
T,
std::enable_if_t<std::is_class<typename T::absl_internal_is_view>::value>>
: T::absl_internal_is_view {};
// A trait to determine whether a type is a view.
// Do *not* depend on the correctness of this trait for correct code behavior.
// It is only a safety feature, and its value may change in the future.
// Do not specialize this trait. Instead, define the member
// using absl_internal_is_view = std::true_type;
// in your class to allow its detection while preventing ODR violations.
// If it ever becomes possible to detect [[gsl::Pointer]], we should leverage
// it: https://wg21.link/p1179
template <typename T>
struct IsView : std::integral_constant<bool, std::is_pointer<T>::value ||
IsViewImpl<T>::value> {};
template <typename Char, typename Traits>
struct IsView<std::basic_string_view<Char, Traits>> : std::true_type {};
#ifdef __cpp_lib_span
template <typename T>
struct IsView<std::span<T>> : std::true_type {};
#endif
// Determines whether the assignment of the given types is lifetime-bound.
// Do *not* depend on the correctness of this trait for correct code behavior.
// It is only a safety feature and its value may change in the future.
// If it ever becomes possible to detect [[clang::lifetimebound]] directly,
// we should change the implementation to leverage that.
// Until then, we consider an assignment from an "owner" (such as std::string)
// to a "view" (such as std::string_view) to be a lifetime-bound assignment.
template <typename T, typename U>
using IsLifetimeBoundAssignment = absl::conjunction<
std::integral_constant<bool, !std::is_lvalue_reference<U>::value>,
IsOwner<absl::remove_cvref_t<U>>, IsView<absl::remove_cvref_t<T>>>;
} // namespace type_traits_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_META_TYPE_TRAITS_H_
vsoong/.intermediates/external/abseil-cpp/absl_base_base_internal_hdrs/gen/my_include_dir/absl/base/internal/identity.hõ// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifndef ABSL_BASE_INTERNAL_IDENTITY_H_
#define ABSL_BASE_INTERNAL_IDENTITY_H_
#include "absl/base/config.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace internal {
// This is a back-fill of C++20's `std::type_identity`.
template <typename T>
struct type_identity {
typedef T type;
};
// This is a back-fill of C++20's `std::type_identity_t`.
template <typename T>
using type_identity_t = typename type_identity<T>::type;
} // namespace internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_INTERNAL_IDENTITY_H_
*’8
\soong/.intermediates/external/abseil-cpp/absl_base_hdrs/gen/my_include_dir/absl/base/casts.h±7//
// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: casts.h
// -----------------------------------------------------------------------------
//
// This header file defines casting templates to fit use cases not covered by
// the standard casts provided in the C++ standard. As with all cast operations,
// use these with caution and only if alternatives do not exist.
#ifndef ABSL_BASE_CASTS_H_
#define ABSL_BASE_CASTS_H_
#include <cstring>
#include <memory>
#include <type_traits>
#include <utility>
#if defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L
#include <bit> // For std::bit_cast.
#endif // defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L
#include "absl/base/internal/identity.h"
#include "absl/base/macros.h"
#include "absl/meta/type_traits.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
// implicit_cast()
//
// Performs an implicit conversion between types following the language
// rules for implicit conversion; if an implicit conversion is otherwise
// allowed by the language in the given context, this function performs such an
// implicit conversion.
//
// Example:
//
// // If the context allows implicit conversion:
// From from;
// To to = from;
//
// // Such code can be replaced by:
// implicit_cast<To>(from);
//
// An `implicit_cast()` may also be used to annotate numeric type conversions
// that, although safe, may produce compiler warnings (such as `long` to `int`).
// Additionally, an `implicit_cast()` is also useful within return statements to
// indicate a specific implicit conversion is being undertaken.
//
// Example:
//
// return implicit_cast<double>(size_in_bytes) / capacity_;
//
// Annotating code with `implicit_cast()` allows you to explicitly select
// particular overloads and template instantiations, while providing a safer
// cast than `reinterpret_cast()` or `static_cast()`.
//
// Additionally, an `implicit_cast()` can be used to allow upcasting within a
// type hierarchy where incorrect use of `static_cast()` could accidentally
// allow downcasting.
//
// Finally, an `implicit_cast()` can be used to perform implicit conversions
// from unrelated types that otherwise couldn't be implicitly cast directly;
// C++ will normally only implicitly cast "one step" in such conversions.
//
// That is, if C is a type which can be implicitly converted to B, with B being
// a type that can be implicitly converted to A, an `implicit_cast()` can be
// used to convert C to B (which the compiler can then implicitly convert to A
// using language rules).
//
// Example:
//
// // Assume an object C is convertible to B, which is implicitly convertible
// // to A
// A a = implicit_cast<B>(C);
//
// Such implicit cast chaining may be useful within template logic.
template <typename To>
constexpr To implicit_cast(typename absl::internal::type_identity_t<To> to) {
return to;
}
// bit_cast()
//
// Creates a value of the new type `Dest` whose representation is the same as
// that of the argument, which is of (deduced) type `Source` (a "bitwise cast";
// every bit in the value representation of the result is equal to the
// corresponding bit in the object representation of the source). Source and
// destination types must be of the same size, and both types must be trivially
// copyable.
//
// As with most casts, use with caution. A `bit_cast()` might be needed when you
// need to treat a value as the value of some other type, for example, to access
// the individual bits of an object which are not normally accessible through
// the object's type, such as for working with the binary representation of a
// floating point value:
//
// float f = 3.14159265358979;
// int i = bit_cast<int>(f);
// // i = 0x40490fdb
//
// Reinterpreting and accessing a value directly as a different type (as shown
// below) usually results in undefined behavior.
//
// Example:
//
// // WRONG
// float f = 3.14159265358979;
// int i = reinterpret_cast<int&>(f); // Wrong
// int j = *reinterpret_cast<int*>(&f); // Equally wrong
// int k = *bit_cast<int*>(&f); // Equally wrong
//
// Reinterpret-casting results in undefined behavior according to the ISO C++
// specification, section [basic.lval]. Roughly, this section says: if an object
// in memory has one type, and a program accesses it with a different type, the
// result is undefined behavior for most "different type".
//
// Using bit_cast on a pointer and then dereferencing it is no better than using
// reinterpret_cast. You should only use bit_cast on the value itself.
//
// Such casting results in type punning: holding an object in memory of one type
// and reading its bits back using a different type. A `bit_cast()` avoids this
// issue by copying the object representation to a new value, which avoids
// introducing this undefined behavior (since the original value is never
// accessed in the wrong way).
//
// The requirements of `absl::bit_cast` are more strict than that of
// `std::bit_cast` unless compiler support is available. Specifically, without
// compiler support, this implementation also requires `Dest` to be
// default-constructible. In C++20, `absl::bit_cast` is replaced by
// `std::bit_cast`.
#if defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L
using std::bit_cast;
#else // defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L
template <
typename Dest, typename Source,
typename std::enable_if<sizeof(Dest) == sizeof(Source) &&
std::is_trivially_copyable<Source>::value &&
std::is_trivially_copyable<Dest>::value
#if !ABSL_HAVE_BUILTIN(__builtin_bit_cast)
&& std::is_default_constructible<Dest>::value
#endif // !ABSL_HAVE_BUILTIN(__builtin_bit_cast)
,
int>::type = 0>
#if ABSL_HAVE_BUILTIN(__builtin_bit_cast)
inline constexpr Dest bit_cast(const Source& source) {
return __builtin_bit_cast(Dest, source);
}
#else // ABSL_HAVE_BUILTIN(__builtin_bit_cast)
inline Dest bit_cast(const Source& source) {
Dest dest;
memcpy(static_cast<void*>(std::addressof(dest)),
static_cast<const void*>(std::addressof(source)), sizeof(dest));
return dest;
}
#endif // ABSL_HAVE_BUILTIN(__builtin_bit_cast)
#endif // defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_CASTS_H_
*Ÿ
ˆsoong/.intermediates/external/abseil-cpp/absl_log_internal_structured_proto_hdrs/gen/my_include_dir/absl/log/internal/structured_proto.h‘// Copyright 2024 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: log/internal/structured_proto.h
// -----------------------------------------------------------------------------
#ifndef ABSL_LOG_INTERNAL_STRUCTURED_PROTO_H_
#define ABSL_LOG_INTERNAL_STRUCTURED_PROTO_H_
#include <cstddef>
#include <cstdint>
#include "absl/base/config.h"
#include "absl/log/internal/proto.h"
#include "absl/types/span.h"
#include "absl/types/variant.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace log_internal {
// Sum type holding a single valid protobuf field suitable for encoding.
struct StructuredProtoField final {
// Numeric type encoded with varint encoding:
// https://protobuf.dev/programming-guides/encoding/#varints
using Varint = absl::variant<uint64_t, int64_t, uint32_t, int32_t, bool>;
// Fixed-length 64-bit integer encoding:
// https://protobuf.dev/programming-guides/encoding/#non-varints
using I64 = absl::variant<uint64_t, int64_t, double>;
// Length-delimited record type (string, sub-message):
// https://protobuf.dev/programming-guides/encoding/#length-types
using LengthDelimited = absl::Span<const char>;
// Fixed-length 32-bit integer encoding:
// https://protobuf.dev/programming-guides/encoding/#non-varints
using I32 = absl::variant<uint32_t, int32_t, float>;
// Valid record type:
// https://protobuf.dev/programming-guides/encoding/#structure
using Value = absl::variant<Varint, I64, LengthDelimited, I32>;
// Field number for the protobuf value.
uint64_t field_number;
// Value to encode.
Value value;
};
// Estimates the number of bytes needed to encode `field` using
// protobuf encoding.
//
// The returned value might be larger than the actual number of bytes needed.
inline size_t BufferSizeForStructuredProtoField(StructuredProtoField field) {
// Visitor to estimate the number of bytes of one of the types contained
// inside `StructuredProtoField`.
struct BufferSizeVisitor final {
size_t operator()(StructuredProtoField::Varint /*unused*/) {
return BufferSizeFor(field_number, WireType::kVarint);
}
size_t operator()(StructuredProtoField::I64 /*unused*/) {
return BufferSizeFor(field_number, WireType::k64Bit);
}
size_t operator()(StructuredProtoField::LengthDelimited length_delimited) {
return BufferSizeFor(field_number, WireType::kLengthDelimited) +
length_delimited.size();
}
size_t operator()(StructuredProtoField::I32 /*unused*/) {
return BufferSizeFor(field_number, WireType::k32Bit);
}
uint64_t field_number;
};
return absl::visit(BufferSizeVisitor{field.field_number}, field.value);
}
// Encodes `field` into `buf` using protobuf encoding.
//
// On success, returns `true` and advances `buf` to the end of
// the bytes consumed.
//
// On failure (if `buf` was too small), returns `false`.
bool EncodeStructuredProtoField(StructuredProtoField field,
absl::Span<char>& buf);
} // namespace log_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_LOG_INTERNAL_STRUCTURED_PROTO_H_
*
zsoong/.intermediates/external/abseil-cpp/absl_log_internal_nullguard_hdrs/gen/my_include_dir/absl/log/internal/nullguard.hž// Copyright 2022 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: log/internal/nullguard.h
// -----------------------------------------------------------------------------
//
// NullGuard exists such that NullGuard<T>::Guard(v) returns v, unless passed a
// nullptr_t, or a null char* or const char*, in which case it returns "(null)".
// This allows streaming NullGuard<T>::Guard(v) to an output stream without
// hitting undefined behavior for null values.
#ifndef ABSL_LOG_INTERNAL_NULLGUARD_H_
#define ABSL_LOG_INTERNAL_NULLGUARD_H_
#include <array>
#include <cstddef>
#include "absl/base/attributes.h"
#include "absl/base/config.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace log_internal {
ABSL_CONST_INIT ABSL_DLL extern const std::array<char, 7> kCharNull;
ABSL_CONST_INIT ABSL_DLL extern const std::array<signed char, 7>
kSignedCharNull;
ABSL_CONST_INIT ABSL_DLL extern const std::array<unsigned char, 7>
kUnsignedCharNull;
template <typename T>
struct NullGuard final {
static const T& Guard(const T& v) { return v; }
};
template <>
struct NullGuard<char*> final {
static const char* Guard(const char* v) { return v ? v : kCharNull.data(); }
};
template <>
struct NullGuard<const char*> final {
static const char* Guard(const char* v) { return v ? v : kCharNull.data(); }
};
template <>
struct NullGuard<signed char*> final {
static const signed char* Guard(const signed char* v) {
return v ? v : kSignedCharNull.data();
}
};
template <>
struct NullGuard<const signed char*> final {
static const signed char* Guard(const signed char* v) {
return v ? v : kSignedCharNull.data();
}
};
template <>
struct NullGuard<unsigned char*> final {
static const unsigned char* Guard(const unsigned char* v) {
return v ? v : kUnsignedCharNull.data();
}
};
template <>
struct NullGuard<const unsigned char*> final {
static const unsigned char* Guard(const unsigned char* v) {
return v ? v : kUnsignedCharNull.data();
}
};
template <>
struct NullGuard<std::nullptr_t> final {
static const char* Guard(const std::nullptr_t&) { return kCharNull.data(); }
};
} // namespace log_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_LOG_INTERNAL_NULLGUARD_H_
*‚
Œsoong/.intermediates/external/abseil-cpp/absl_synchronization_hdrs/gen/my_include_dir/absl/synchronization/internal/create_thread_identity.hð/*
* Copyright 2017 The Abseil Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Interface for getting the current ThreadIdentity, creating one if necessary.
// See thread_identity.h.
//
// This file is separate from thread_identity.h because creating a new
// ThreadIdentity requires slightly higher level libraries (per_thread_sem
// and low_level_alloc) than accessing an existing one. This separation allows
// us to have a smaller //absl/base:base.
#ifndef ABSL_SYNCHRONIZATION_INTERNAL_CREATE_THREAD_IDENTITY_H_
#define ABSL_SYNCHRONIZATION_INTERNAL_CREATE_THREAD_IDENTITY_H_
#include "absl/base/internal/thread_identity.h"
#include "absl/base/port.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace synchronization_internal {
// Allocates and attaches a ThreadIdentity object for the calling thread.
// For private use only.
base_internal::ThreadIdentity* CreateThreadIdentity();
// Returns the ThreadIdentity object representing the calling thread; guaranteed
// to be unique for its lifetime. The returned object will remain valid for the
// program's lifetime; although it may be re-assigned to a subsequent thread.
// If one does not exist for the calling thread, allocate it now.
inline base_internal::ThreadIdentity* GetOrCreateCurrentThreadIdentity() {
base_internal::ThreadIdentity* identity =
base_internal::CurrentThreadIdentityIfPresent();
if (ABSL_PREDICT_FALSE(identity == nullptr)) {
return CreateThreadIdentity();
}
return identity;
}
} // namespace synchronization_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_SYNCHRONIZATION_INTERNAL_CREATE_THREAD_IDENTITY_H_
*©‘
~soong/.intermediates/external/abseil-cpp/absl_log_internal_log_message_hdrs/gen/my_include_dir/absl/log/internal/log_message.h¥// Copyright 2022 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: log/internal/log_message.h
// -----------------------------------------------------------------------------
//
// This file declares `class absl::log_internal::LogMessage`. This class more or
// less represents a particular log message. LOG/CHECK macros create a temporary
// instance of `LogMessage` and then stream values to it. At the end of the
// LOG/CHECK statement, the LogMessage is voidified by operator&&, and `Flush()`
// directs the message to the registered log sinks. Heap-allocation of
// `LogMessage` is unsupported. Construction outside of a `LOG` macro is
// unsupported.
#ifndef ABSL_LOG_INTERNAL_LOG_MESSAGE_H_
#define ABSL_LOG_INTERNAL_LOG_MESSAGE_H_
#include <wchar.h>
#include <cstddef>
#include <ios>
#include <memory>
#include <ostream>
#include <streambuf>
#include <string>
#include <string_view>
#include <type_traits>
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/internal/errno_saver.h"
#include "absl/base/log_severity.h"
#include "absl/base/nullability.h"
#include "absl/log/internal/nullguard.h"
#include "absl/log/internal/structured_proto.h"
#include "absl/log/log_entry.h"
#include "absl/log/log_sink.h"
#include "absl/strings/has_absl_stringify.h"
#include "absl/strings/string_view.h"
#include "absl/time/time.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace log_internal {
constexpr int kLogMessageBufferSize = 15000;
enum class StructuredStringType;
class LogMessage {
public:
struct InfoTag {};
struct WarningTag {};
struct ErrorTag {};
// Used for `LOG`.
LogMessage(const char* absl_nonnull file, int line,
absl::LogSeverity severity) ABSL_ATTRIBUTE_COLD;
// These constructors are slightly smaller/faster to call; the severity is
// curried into the function pointer.
LogMessage(const char* absl_nonnull file, int line,
InfoTag) ABSL_ATTRIBUTE_COLD ABSL_ATTRIBUTE_NOINLINE;
LogMessage(const char* absl_nonnull file, int line,
WarningTag) ABSL_ATTRIBUTE_COLD ABSL_ATTRIBUTE_NOINLINE;
LogMessage(const char* absl_nonnull file, int line,
ErrorTag) ABSL_ATTRIBUTE_COLD ABSL_ATTRIBUTE_NOINLINE;
LogMessage(const LogMessage&) = delete;
LogMessage& operator=(const LogMessage&) = delete;
~LogMessage() ABSL_ATTRIBUTE_COLD;
// Overrides the location inferred from the callsite. The string pointed to
// by `file` must be valid until the end of the statement.
LogMessage& AtLocation(absl::string_view file, int line);
// Omits the prefix from this line. The prefix includes metadata about the
// logged data such as source code location and timestamp.
LogMessage& NoPrefix();
// Sets the verbosity field of the logged message as if it was logged by
// `VLOG(verbose_level)`. Unlike `VLOG`, this method does not affect
// evaluation of the statement when the specified `verbose_level` has been
// disabled. The only effect is on `absl::LogSink` implementations which
// make use of the `absl::LogSink::verbosity()` value. The value
// `absl::LogEntry::kNoVerbosityLevel` can be specified to mark the message
// not verbose.
LogMessage& WithVerbosity(int verbose_level);
// Uses the specified timestamp instead of one collected in the constructor.
LogMessage& WithTimestamp(absl::Time timestamp);
// Uses the specified thread ID instead of one collected in the constructor.
LogMessage& WithThreadID(absl::LogEntry::tid_t tid);
// Copies all metadata (but no data) from the specified `absl::LogEntry`.
LogMessage& WithMetadataFrom(const absl::LogEntry& entry);
// Appends to the logged message a colon, a space, a textual description of
// the current value of `errno` (as by strerror(3)), and the numerical value
// of `errno`.
LogMessage& WithPerror();
// Sends this message to `*sink` in addition to whatever other sinks it would
// otherwise have been sent to.
LogMessage& ToSinkAlso(absl::LogSink* absl_nonnull sink);
// Sends this message to `*sink` and no others.
LogMessage& ToSinkOnly(absl::LogSink* absl_nonnull sink);
// Don't call this method from outside this library.
LogMessage& InternalStream() { return *this; }
// By-value overloads for small, common types let us overlook common failures
// to define globals and static data members (i.e. in a .cc file).
// NOLINTBEGIN(runtime/int)
// NOLINTBEGIN(google-runtime-int)
// clang-format off: The CUDA toolchain cannot handle these <<<'s
LogMessage& operator<<(char v) { return operator<< <char>(v); }
LogMessage& operator<<(signed char v) { return operator<< <signed char>(v); }
LogMessage& operator<<(unsigned char v) {
return operator<< <unsigned char>(v);
}
LogMessage& operator<<(signed short v) {
return operator<< <signed short>(v);
}
LogMessage& operator<<(signed int v) { return operator<< <signed int>(v); }
LogMessage& operator<<(signed long v) {
return operator<< <signed long>(v);
}
LogMessage& operator<<(signed long long v) {
return operator<< <signed long long>(v);
}
LogMessage& operator<<(unsigned short v) {
return operator<< <unsigned short>(v);
}
LogMessage& operator<<(unsigned int v) {
return operator<< <unsigned int>(v);
}
LogMessage& operator<<(unsigned long v) {
return operator<< <unsigned long>(v);
}
LogMessage& operator<<(unsigned long long v) {
return operator<< <unsigned long long>(v);
}
LogMessage& operator<<(void* absl_nullable v) {
return operator<< <void*>(v);
}
LogMessage& operator<<(const void* absl_nullable v) {
return operator<< <const void*>(v);
}
LogMessage& operator<<(float v) { return operator<< <float>(v); }
LogMessage& operator<<(double v) { return operator<< <double>(v); }
LogMessage& operator<<(bool v) { return operator<< <bool>(v); }
// clang-format on
// NOLINTEND(google-runtime-int)
// NOLINTEND(runtime/int)
// These overloads are more efficient since no `ostream` is involved.
LogMessage& operator<<(const std::string& v);
LogMessage& operator<<(absl::string_view v);
// Wide string overloads (since std::ostream does not provide them).
LogMessage& operator<<(const std::wstring& v);
LogMessage& operator<<(std::wstring_view v);
// `const wchar_t*` is handled by `operator<< <const wchar_t*>`.
LogMessage& operator<<(wchar_t* absl_nullable v);
LogMessage& operator<<(wchar_t v);
// Handle stream manipulators e.g. std::endl.
LogMessage& operator<<(std::ostream& (*absl_nonnull m)(std::ostream& os));
LogMessage& operator<<(std::ios_base& (*absl_nonnull m)(std::ios_base& os));
// Literal strings. This allows us to record C string literals as literals in
// the logging.proto.Value.
//
// Allow this overload to be inlined to prevent generating instantiations of
// this template for every value of `SIZE` encountered in each source code
// file. That significantly increases linker input sizes. Inlining is cheap
// because the argument to this overload is almost always a string literal so
// the call to `strlen` can be replaced at compile time. The overloads for
// `char[]`/`wchar_t[]` below should not be inlined. The compiler typically
// does not have the string at compile time and cannot replace the call to
// `strlen` so inlining it increases the binary size. See the discussion on
// cl/107527369.
template <int SIZE>
LogMessage& operator<<(const char (&buf)[SIZE]);
template <int SIZE>
LogMessage& operator<<(const wchar_t (&buf)[SIZE]);
// This prevents non-const `char[]` arrays from looking like literals.
template <int SIZE>
LogMessage& operator<<(char (&buf)[SIZE]) ABSL_ATTRIBUTE_NOINLINE;
// `wchar_t[SIZE]` is handled by `operator<< <const wchar_t*>`.
// Types that support `AbslStringify()` are serialized that way.
// Types that don't support `AbslStringify()` but do support streaming into a
// `std::ostream&` are serialized that way.
template <typename T>
LogMessage& operator<<(const T& v) ABSL_ATTRIBUTE_NOINLINE;
// Dispatches the completed `absl::LogEntry` to applicable `absl::LogSink`s.
void Flush();
// Note: We explicitly do not support `operator<<` for non-const references
// because it breaks logging of non-integer bitfield types (i.e., enums).
protected:
// Call `abort()` or similar to perform `LOG(FATAL)` crash. It is assumed
// that the caller has already generated and written the trace as appropriate.
[[noreturn]] static void FailWithoutStackTrace();
// Similar to `FailWithoutStackTrace()`, but without `abort()`. Terminates
// the process with an error exit code.
[[noreturn]] static void FailQuietly();
// After this is called, failures are done as quiet as possible for this log
// message.
void SetFailQuietly();
private:
struct LogMessageData; // Opaque type containing message state
friend class AsLiteralImpl;
friend class StringifySink;
template <StructuredStringType str_type>
friend class AsStructuredStringTypeImpl;
template <typename T>
friend class AsStructuredValueImpl;
// This streambuf writes directly into the structured logging buffer so that
// arbitrary types can be encoded as string data (using
// `operator<<(std::ostream &, ...)` without any extra allocation or copying.
// Space is reserved before the data to store the length field, which is
// filled in by `~OstreamView`.
class OstreamView final : public std::streambuf {
public:
explicit OstreamView(LogMessageData& message_data);
~OstreamView() override;
OstreamView(const OstreamView&) = delete;
OstreamView& operator=(const OstreamView&) = delete;
std::ostream& stream();
private:
LogMessageData& data_;
absl::Span<char> encoded_remaining_copy_;
absl::Span<char> message_start_;
absl::Span<char> string_start_;
};
enum class StringType {
kLiteral,
kNotLiteral,
};
template <StringType str_type>
void CopyToEncodedBuffer(absl::string_view str) ABSL_ATTRIBUTE_NOINLINE;
template <StringType str_type>
void CopyToEncodedBuffer(char ch, size_t num) ABSL_ATTRIBUTE_NOINLINE;
template <StringType str_type>
void CopyToEncodedBuffer(std::wstring_view str) ABSL_ATTRIBUTE_NOINLINE;
// Copies `field` to the encoded buffer, then appends `str` after it
// (truncating `str` if necessary to fit).
template <StringType str_type>
void CopyToEncodedBufferWithStructuredProtoField(StructuredProtoField field,
absl::string_view str)
ABSL_ATTRIBUTE_NOINLINE;
// Returns `true` if the message is fatal or enabled debug-fatal.
bool IsFatal() const;
// Records some tombstone-type data in anticipation of `Die`.
void PrepareToDie();
void Die();
void SendToLog();
// Checks `FLAGS_log_backtrace_at` and appends a backtrace if appropriate.
void LogBacktraceIfNeeded();
// This should be the first data member so that its initializer captures errno
// before any other initializers alter it (e.g. with calls to new) and so that
// no other destructors run afterward an alter it (e.g. with calls to delete).
absl::base_internal::ErrnoSaver errno_saver_;
// We keep the data in a separate struct so that each instance of `LogMessage`
// uses less stack space.
absl_nonnull std::unique_ptr<LogMessageData> data_;
};
// Explicitly specializes the generic operator<< for `const wchar_t*`
// arguments.
//
// This method is used instead of a non-template `const wchar_t*` overload,
// as the latter was found to take precedence over the array template
// (`operator<<(const wchar_t(&)[SIZE])`) when handling string literals.
// This specialization ensures the array template now correctly processes
// literals.
template <>
LogMessage& LogMessage::operator<< <const wchar_t*>(
const wchar_t* absl_nullable const& v);
inline LogMessage& LogMessage::operator<<(wchar_t* absl_nullable v) {
return operator<<(const_cast<const wchar_t*>(v));
}
// Helper class so that `AbslStringify()` can modify the LogMessage.
class StringifySink final {
public:
explicit StringifySink(LogMessage& message) : message_(message) {}
void Append(size_t count, char ch) {
message_.CopyToEncodedBuffer<LogMessage::StringType::kNotLiteral>(ch,
count);
}
void Append(absl::string_view v) {
message_.CopyToEncodedBuffer<LogMessage::StringType::kNotLiteral>(v);
}
// For types that implement `AbslStringify` using `absl::Format()`.
friend void AbslFormatFlush(StringifySink* absl_nonnull sink,
absl::string_view v) {
sink->Append(v);
}
private:
LogMessage& message_;
};
// Note: the following is declared `ABSL_ATTRIBUTE_NOINLINE`
template <typename T>
LogMessage& LogMessage::operator<<(const T& v) {
if constexpr (absl::HasAbslStringify<T>::value) {
StringifySink sink(*this);
// Replace with public API.
AbslStringify(sink, v);
} else {
OstreamView view(*data_);
view.stream() << log_internal::NullGuard<T>().Guard(v);
}
return *this;
}
template <int SIZE>
LogMessage& LogMessage::operator<<(const char (&buf)[SIZE]) {
CopyToEncodedBuffer<StringType::kLiteral>(buf);
return *this;
}
template <int SIZE>
LogMessage& LogMessage::operator<<(const wchar_t (&buf)[SIZE]) {
CopyToEncodedBuffer<StringType::kLiteral>(buf);
return *this;
}
// Note: the following is declared `ABSL_ATTRIBUTE_NOINLINE`
template <int SIZE>
LogMessage& LogMessage::operator<<(char (&buf)[SIZE]) {
CopyToEncodedBuffer<StringType::kNotLiteral>(buf);
return *this;
}
// We instantiate these specializations in the library's TU to save space in
// other TUs. Since the template is marked `ABSL_ATTRIBUTE_NOINLINE` we will be
// emitting a function call either way.
// NOLINTBEGIN(runtime/int)
// NOLINTBEGIN(google-runtime-int)
extern template LogMessage& LogMessage::operator<<(const char& v);
extern template LogMessage& LogMessage::operator<<(const signed char& v);
extern template LogMessage& LogMessage::operator<<(const unsigned char& v);
extern template LogMessage& LogMessage::operator<<(const short& v);
extern template LogMessage& LogMessage::operator<<(const unsigned short& v);
extern template LogMessage& LogMessage::operator<<(const int& v);
extern template LogMessage& LogMessage::operator<<(const unsigned int& v);
extern template LogMessage& LogMessage::operator<<(const long& v);
extern template LogMessage& LogMessage::operator<<(const unsigned long& v);
extern template LogMessage& LogMessage::operator<<(const long long& v);
extern template LogMessage& LogMessage::operator<<(const unsigned long long& v);
extern template LogMessage& LogMessage::operator<<(
void* absl_nullable const& v);
extern template LogMessage& LogMessage::operator<<(
const void* absl_nullable const& v);
extern template LogMessage& LogMessage::operator<<(const float& v);
extern template LogMessage& LogMessage::operator<<(const double& v);
extern template LogMessage& LogMessage::operator<<(const bool& v);
// NOLINTEND(google-runtime-int)
// NOLINTEND(runtime/int)
extern template void LogMessage::CopyToEncodedBuffer<
LogMessage::StringType::kLiteral>(absl::string_view str);
extern template void LogMessage::CopyToEncodedBuffer<
LogMessage::StringType::kNotLiteral>(absl::string_view str);
extern template void
LogMessage::CopyToEncodedBuffer<LogMessage::StringType::kLiteral>(char ch,
size_t num);
extern template void LogMessage::CopyToEncodedBuffer<
LogMessage::StringType::kNotLiteral>(char ch, size_t num);
extern template void LogMessage::CopyToEncodedBuffer<
LogMessage::StringType::kLiteral>(std::wstring_view str);
extern template void LogMessage::CopyToEncodedBuffer<
LogMessage::StringType::kNotLiteral>(std::wstring_view str);
// `LogMessageFatal` ensures the process will exit in failure after logging this
// message.
class LogMessageFatal final : public LogMessage {
public:
LogMessageFatal(const char* absl_nonnull file, int line) ABSL_ATTRIBUTE_COLD;
LogMessageFatal(const char* absl_nonnull file, int line,
const char* absl_nonnull failure_msg) ABSL_ATTRIBUTE_COLD;
[[noreturn]] ~LogMessageFatal();
};
// `LogMessageDebugFatal` ensures the process will exit in failure after logging
// this message. It matches LogMessageFatal but is not [[noreturn]] as it's used
// for DLOG(FATAL) variants.
class LogMessageDebugFatal final : public LogMessage {
public:
LogMessageDebugFatal(const char* absl_nonnull file,
int line) ABSL_ATTRIBUTE_COLD;
~LogMessageDebugFatal();
};
class LogMessageQuietlyDebugFatal final : public LogMessage {
public:
// DLOG(QFATAL) calls this instead of LogMessageQuietlyFatal to make sure the
// destructor is not [[noreturn]] even if this is always FATAL as this is only
// invoked when DLOG() is enabled.
LogMessageQuietlyDebugFatal(const char* absl_nonnull file,
int line) ABSL_ATTRIBUTE_COLD;
~LogMessageQuietlyDebugFatal();
};
// Used for LOG(QFATAL) to make sure it's properly understood as [[noreturn]].
class LogMessageQuietlyFatal final : public LogMessage {
public:
LogMessageQuietlyFatal(const char* absl_nonnull file,
int line) ABSL_ATTRIBUTE_COLD;
LogMessageQuietlyFatal(const char* absl_nonnull file, int line,
const char* absl_nonnull failure_msg)
ABSL_ATTRIBUTE_COLD;
[[noreturn]] ~LogMessageQuietlyFatal();
};
} // namespace log_internal
ABSL_NAMESPACE_END
} // namespace absl
extern "C" ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(
AbslInternalOnFatalLogMessage)(const absl::LogEntry&);
#endif // ABSL_LOG_INTERNAL_LOG_MESSAGE_H_
*ì
}soong/.intermediates/external/abseil-cpp/absl_base_base_internal_hdrs/gen/my_include_dir/absl/base/internal/scheduling_mode.hê// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Core interfaces and definitions used by by low-level interfaces such as
// SpinLock.
#ifndef ABSL_BASE_INTERNAL_SCHEDULING_MODE_H_
#define ABSL_BASE_INTERNAL_SCHEDULING_MODE_H_
#include "absl/base/config.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace base_internal {
// Used to describe how a thread may be scheduled. Typically associated with
// the declaration of a resource supporting synchronized access.
//
// SCHEDULE_COOPERATIVE_AND_KERNEL:
// Specifies that when waiting, a cooperative thread (e.g. a Fiber) may
// reschedule (using base::scheduling semantics); allowing other cooperative
// threads to proceed.
//
// SCHEDULE_KERNEL_ONLY: (Also described as "non-cooperative")
// Specifies that no cooperative scheduling semantics may be used, even if the
// current thread is itself cooperatively scheduled. This means that
// cooperative threads will NOT allow other cooperative threads to execute in
// their place while waiting for a resource of this type. Host operating system
// semantics (e.g. a futex) may still be used.
//
// When optional, clients should strongly prefer SCHEDULE_COOPERATIVE_AND_KERNEL
// by default. SCHEDULE_KERNEL_ONLY should only be used for resources on which
// base::scheduling (e.g. the implementation of a Scheduler) may depend.
//
// NOTE: Cooperative resources may not be nested below non-cooperative ones.
// This means that it is invalid to to acquire a SCHEDULE_COOPERATIVE_AND_KERNEL
// resource if a SCHEDULE_KERNEL_ONLY resource is already held.
enum SchedulingMode {
SCHEDULE_KERNEL_ONLY = 0, // Allow scheduling only the host OS.
SCHEDULE_COOPERATIVE_AND_KERNEL, // Also allow cooperative scheduling.
};
} // namespace base_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_INTERNAL_SCHEDULING_MODE_H_
*]
|soong/.intermediates/external/abseil-cpp/absl_log_internal_conditions_hdrs/gen/my_include_dir/absl/log/internal/conditions.h\// Copyright 2022 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: log/internal/conditions.h
// -----------------------------------------------------------------------------
//
// This file contains implementation of conditional log statements, like LOG_IF
// including all the ABSL_LOG_INTERNAL_..._CONDITION_... macros and
// various condition classes like LogEveryNState.
#ifndef ABSL_LOG_INTERNAL_CONDITIONS_H_
#define ABSL_LOG_INTERNAL_CONDITIONS_H_
#if defined(_WIN32) || defined(__hexagon__)
#include <cstdlib>
#else
#include <unistd.h>
#endif
#include <stdlib.h>
#include <atomic>
#include <cstdint>
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/log/internal/voidify.h"
// `ABSL_LOG_INTERNAL_CONDITION` prefixes another macro that expands to a
// temporary `LogMessage` instantiation followed by zero or more streamed
// expressions. This definition is tricky to read correctly. It evaluates to
// either
//
// (void)0;
//
// or
//
// ::absl::log_internal::Voidify() &&
// ::absl::log_internal::LogMessage(...) << "the user's message";
//
// If the condition is evaluable at compile time, as is often the case, it
// compiles away to just one side or the other.
//
// Although this is not used anywhere a statement (e.g. `if`) could not go,
// the ternary expression does a better job avoiding spurious diagnostics
// (dangling else, missing switch case) and preserving noreturn semantics (e.g.
// on `LOG(FATAL)`) without requiring braces.
//
// The `switch` ensures that this expansion is the beginning of a statement (as
// opposed to an expression) and prevents shenanigans like
// `AFunction(LOG(INFO))` and `decltype(LOG(INFO))`. The apparently-redundant
// `default` case makes the condition more amenable to Clang dataflow analysis.
#define ABSL_LOG_INTERNAL_STATELESS_CONDITION(condition) \
switch (0) \
case 0: \
default: \
!(condition) ? (void)0 : ::absl::log_internal::Voidify() &&
// `ABSL_LOG_INTERNAL_STATEFUL_CONDITION` applies a condition like
// `ABSL_LOG_INTERNAL_STATELESS_CONDITION` but adds to that a series of variable
// declarations, including a local static object which stores the state needed
// to implement the stateful macros like `LOG_EVERY_N`.
//
// `for`-loops are used to declare scoped variables without braces (to permit
// streaming into the macro's expansion) and without the dangling-`else`
// problems/diagnostics that come with `if`.
//
// Two more variables are declared in separate `for`-loops:
//
// * `COUNTER` implements a streamable token whose value when streamed is the
// number of times execution has passed through the macro.
// * A boolean flag is used to prevent any of the `for`-loops from ever actually
// looping.
#define ABSL_LOG_INTERNAL_STATEFUL_CONDITION(condition) \
for (bool absl_log_internal_stateful_condition_do_log(condition); \
absl_log_internal_stateful_condition_do_log; \
absl_log_internal_stateful_condition_do_log = false) \
ABSL_LOG_INTERNAL_STATEFUL_CONDITION_IMPL
#define ABSL_LOG_INTERNAL_STATEFUL_CONDITION_IMPL(kind, ...) \
for (static ::absl::log_internal::Log##kind##State \
absl_log_internal_stateful_condition_state; \
absl_log_internal_stateful_condition_do_log && \
absl_log_internal_stateful_condition_state.ShouldLog(__VA_ARGS__); \
absl_log_internal_stateful_condition_do_log = false) \
for (const uint32_t COUNTER ABSL_ATTRIBUTE_UNUSED = \
absl_log_internal_stateful_condition_state.counter(); \
absl_log_internal_stateful_condition_do_log; \
absl_log_internal_stateful_condition_do_log = false) \
::absl::log_internal::Voidify() &&
// `ABSL_LOG_INTERNAL_CONDITION_*` serve to combine any conditions from the
// macro (e.g. `LOG_IF` or `VLOG`) with inherent conditions (e.g.
// `ABSL_MIN_LOG_LEVEL`) into a single boolean expression. We could chain
// ternary operators instead, however some versions of Clang sometimes issue
// spurious diagnostics after such expressions due to a control flow analysis
// bug.
#ifdef ABSL_MIN_LOG_LEVEL
#define ABSL_LOG_INTERNAL_CONDITION_INFO(type, condition) \
ABSL_LOG_INTERNAL_##type##_CONDITION( \
(condition) && ::absl::LogSeverity::kInfo >= \
static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL))
#define ABSL_LOG_INTERNAL_CONDITION_WARNING(type, condition) \
ABSL_LOG_INTERNAL_##type##_CONDITION( \
(condition) && ::absl::LogSeverity::kWarning >= \
static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL))
#define ABSL_LOG_INTERNAL_CONDITION_ERROR(type, condition) \
ABSL_LOG_INTERNAL_##type##_CONDITION( \
(condition) && ::absl::LogSeverity::kError >= \
static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL))
#define ABSL_LOG_INTERNAL_CONDITION_DO_NOT_SUBMIT(type, condition) \
ABSL_LOG_INTERNAL_CONDITION_ERROR(type, condition)
// NOTE: Use ternary operators instead of short-circuiting to mitigate
// https://bugs.llvm.org/show_bug.cgi?id=51928.
#define ABSL_LOG_INTERNAL_CONDITION_FATAL(type, condition) \
ABSL_LOG_INTERNAL_##type##_CONDITION( \
((condition) \
? (::absl::LogSeverity::kFatal >= \
static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) \
? true \
: (::absl::log_internal::AbortQuietly(), false)) \
: false))
// NOTE: Use ternary operators instead of short-circuiting to mitigate
// https://bugs.llvm.org/show_bug.cgi?id=51928.
#define ABSL_LOG_INTERNAL_CONDITION_QFATAL(type, condition) \
ABSL_LOG_INTERNAL_##type##_CONDITION( \
((condition) \
? (::absl::LogSeverity::kFatal >= \
static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) \
? true \
: (::absl::log_internal::ExitQuietly(), false)) \
: false))
#define ABSL_LOG_INTERNAL_CONDITION_DFATAL(type, condition) \
ABSL_LOG_INTERNAL_##type##_CONDITION( \
(ABSL_ASSUME(absl::kLogDebugFatal == absl::LogSeverity::kError || \
absl::kLogDebugFatal == absl::LogSeverity::kFatal), \
(condition) && \
(::absl::kLogDebugFatal >= \
static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) || \
(::absl::kLogDebugFatal == ::absl::LogSeverity::kFatal && \
(::absl::log_internal::AbortQuietly(), false)))))
#define ABSL_LOG_INTERNAL_CONDITION_LEVEL(severity) \
for (int absl_log_internal_severity_loop = 1; \
absl_log_internal_severity_loop; absl_log_internal_severity_loop = 0) \
for (const absl::LogSeverity absl_log_internal_severity = \
::absl::NormalizeLogSeverity(severity); \
absl_log_internal_severity_loop; absl_log_internal_severity_loop = 0) \
ABSL_LOG_INTERNAL_CONDITION_LEVEL_IMPL
#define ABSL_LOG_INTERNAL_CONDITION_LEVEL_IMPL(type, condition) \
ABSL_LOG_INTERNAL_##type##_CONDITION(( \
(condition) && \
(absl_log_internal_severity >= \
static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) || \
(absl_log_internal_severity == ::absl::LogSeverity::kFatal && \
(::absl::log_internal::AbortQuietly(), false)))))
#else // ndef ABSL_MIN_LOG_LEVEL
#define ABSL_LOG_INTERNAL_CONDITION_INFO(type, condition) \
ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
#define ABSL_LOG_INTERNAL_CONDITION_WARNING(type, condition) \
ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
#define ABSL_LOG_INTERNAL_CONDITION_ERROR(type, condition) \
ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
#define ABSL_LOG_INTERNAL_CONDITION_DO_NOT_SUBMIT(type, condition) \
ABSL_LOG_INTERNAL_CONDITION_ERROR(type, condition)
#define ABSL_LOG_INTERNAL_CONDITION_FATAL(type, condition) \
ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
#define ABSL_LOG_INTERNAL_CONDITION_QFATAL(type, condition) \
ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
#define ABSL_LOG_INTERNAL_CONDITION_DFATAL(type, condition) \
ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
#define ABSL_LOG_INTERNAL_CONDITION_LEVEL(severity) \
for (int absl_log_internal_severity_loop = 1; \
absl_log_internal_severity_loop; absl_log_internal_severity_loop = 0) \
for (const absl::LogSeverity absl_log_internal_severity = \
::absl::NormalizeLogSeverity(severity); \
absl_log_internal_severity_loop; absl_log_internal_severity_loop = 0) \
ABSL_LOG_INTERNAL_CONDITION_LEVEL_IMPL
#define ABSL_LOG_INTERNAL_CONDITION_LEVEL_IMPL(type, condition) \
ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
#endif // ndef ABSL_MIN_LOG_LEVEL
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace log_internal {
// Stateful condition class name should be "Log" + name + "State".
class LogEveryNState final {
public:
bool ShouldLog(int n);
uint32_t counter() { return counter_.load(std::memory_order_relaxed); }
private:
std::atomic<uint32_t> counter_{0};
};
class LogFirstNState final {
public:
bool ShouldLog(int n);
uint32_t counter() { return counter_.load(std::memory_order_relaxed); }
private:
std::atomic<uint32_t> counter_{0};
};
class LogEveryPow2State final {
public:
bool ShouldLog();
uint32_t counter() { return counter_.load(std::memory_order_relaxed); }
private:
std::atomic<uint32_t> counter_{0};
};
class LogEveryNSecState final {
public:
bool ShouldLog(double seconds);
uint32_t counter() { return counter_.load(std::memory_order_relaxed); }
private:
std::atomic<uint32_t> counter_{0};
// Cycle count according to CycleClock that we should next log at.
std::atomic<int64_t> next_log_time_cycles_{0};
};
// Helper routines to abort the application quietly
[[noreturn]] inline void AbortQuietly() { abort(); }
[[noreturn]] inline void ExitQuietly() { _exit(1); }
} // namespace log_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_LOG_INTERNAL_CONDITIONS_H_
*í
hsoong/.intermediates/external/abseil-cpp/absl_base_core_headers_hdrs/gen/my_include_dir/absl/base/port.h€// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// This files is a forwarding header for other headers containing various
// portability macros and functions.
#ifndef ABSL_BASE_PORT_H_
#define ABSL_BASE_PORT_H_
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/optimization.h"
#endif // ABSL_BASE_PORT_H_
*úC
jsoong/.intermediates/external/abseil-cpp/absl_base_core_headers_hdrs/gen/my_include_dir/absl/base/macros.h‹C//
// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: macros.h
// -----------------------------------------------------------------------------
//
// This header file defines the set of language macros used within Abseil code.
// For the set of macros used to determine supported compilers and platforms,
// see absl/base/config.h instead.
//
// This code is compiled directly on many platforms, including client
// platforms like Windows, Mac, and embedded systems. Before making
// any changes here, make sure that you're not breaking any platforms.
#ifndef ABSL_BASE_MACROS_H_
#define ABSL_BASE_MACROS_H_
#include <cassert>
#include <cstddef>
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/optimization.h"
#include "absl/base/options.h"
#include "absl/base/port.h"
// ABSL_ARRAYSIZE()
//
// Returns the number of elements in an array as a compile-time constant, which
// can be used in defining new arrays. If you use this macro on a pointer by
// mistake, you will get a compile-time error.
#define ABSL_ARRAYSIZE(array) \
(sizeof(::absl::macros_internal::ArraySizeHelper(array)))
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace macros_internal {
// Note: this internal template function declaration is used by ABSL_ARRAYSIZE.
// The function doesn't need a definition, as we only use its type.
template <typename T, size_t N>
auto ArraySizeHelper(const T (&array)[N]) -> char (&)[N];
} // namespace macros_internal
ABSL_NAMESPACE_END
} // namespace absl
// ABSL_BAD_CALL_IF()
//
// Used on a function overload to trap bad calls: any call that matches the
// overload will cause a compile-time error. This macro uses a clang-specific
// "enable_if" attribute, as described at
// https://clang.llvm.org/docs/AttributeReference.html#enable-if
//
// Overloads which use this macro should be bracketed by
// `#ifdef ABSL_BAD_CALL_IF`.
//
// Example:
//
// int isdigit(int c);
// #ifdef ABSL_BAD_CALL_IF
// int isdigit(int c)
// ABSL_BAD_CALL_IF(c <= -1 || c > 255,
// "'c' must have the value of an unsigned char or EOF");
// #endif // ABSL_BAD_CALL_IF
#if ABSL_HAVE_ATTRIBUTE(enable_if)
#define ABSL_BAD_CALL_IF(expr, msg) \
__attribute__((enable_if(expr, "Bad call trap"), unavailable(msg)))
#endif
// ABSL_ASSERT()
//
// In C++11, `assert` can't be used portably within constexpr functions.
// `assert` also generates spurious unused-symbol warnings.
// ABSL_ASSERT functions as a runtime assert but works in C++11 constexpr
// functions, and maintains references to symbols. Example:
//
// constexpr double Divide(double a, double b) {
// return ABSL_ASSERT(b != 0), a / b;
// }
//
// This macro is inspired by
// https://akrzemi1.wordpress.com/2017/05/18/asserts-in-constexpr-functions/
#if defined(NDEBUG)
#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
// We use `decltype` here to avoid generating unnecessary code that the
// optimizer then has to optimize away.
// This not only improves compilation performance by reducing codegen bloat
// and optimization work, but also guarantees fast run-time performance without
// having to rely on the optimizer.
#define ABSL_ASSERT(expr) (decltype((expr) ? void() : void())())
#else
// Pre-C++20, lambdas can't be inside unevaluated operands, so we're forced to
// rely on the optimizer.
#define ABSL_ASSERT(expr) (false ? ((expr) ? void() : void()) : void())
#endif
#else
#define ABSL_ASSERT(expr) \
(ABSL_PREDICT_TRUE((expr)) ? static_cast<void>(0) \
: [] { assert(false && #expr); }()) // NOLINT
#endif
// `ABSL_INTERNAL_HARDENING_ABORT()` controls how `ABSL_HARDENING_ASSERT()`
// aborts the program in release mode (when NDEBUG is defined). The
// implementation should abort the program as quickly as possible and ideally it
// should not be possible to ignore the abort request.
#define ABSL_INTERNAL_HARDENING_ABORT() \
do { \
ABSL_INTERNAL_IMMEDIATE_ABORT_IMPL(); \
ABSL_INTERNAL_UNREACHABLE_IMPL(); \
} while (false)
// ABSL_HARDENING_ASSERT()
//
// `ABSL_HARDENING_ASSERT()` is like `ABSL_ASSERT()`, but used to implement
// runtime assertions that should be enabled in hardened builds even when
// `NDEBUG` is defined.
//
// When `NDEBUG` is not defined, `ABSL_HARDENING_ASSERT()` is identical to
// `ABSL_ASSERT()`.
//
// See `ABSL_OPTION_HARDENED` in `absl/base/options.h` for more information on
// hardened mode.
#if (ABSL_OPTION_HARDENED == 1 || ABSL_OPTION_HARDENED == 2) && defined(NDEBUG)
#define ABSL_HARDENING_ASSERT(expr) \
(ABSL_PREDICT_TRUE((expr)) ? static_cast<void>(0) \
: [] { ABSL_INTERNAL_HARDENING_ABORT(); }())
#else
#define ABSL_HARDENING_ASSERT(expr) ABSL_ASSERT(expr)
#endif
// ABSL_HARDENING_ASSERT_SLOW()
//
// `ABSL_HARDENING_ASSERT()` is like `ABSL_HARDENING_ASSERT()`,
// but specifically for assertions whose predicates are too slow
// to be enabled in many applications.
//
// When `NDEBUG` is not defined, `ABSL_HARDENING_ASSERT_SLOW()` is identical to
// `ABSL_ASSERT()`.
//
// See `ABSL_OPTION_HARDENED` in `absl/base/options.h` for more information on
// hardened mode.
#if ABSL_OPTION_HARDENED == 1 && defined(NDEBUG)
#define ABSL_HARDENING_ASSERT_SLOW(expr) \
(ABSL_PREDICT_TRUE((expr)) ? static_cast<void>(0) \
: [] { ABSL_INTERNAL_HARDENING_ABORT(); }())
#else
#define ABSL_HARDENING_ASSERT_SLOW(expr) ABSL_ASSERT(expr)
#endif
#ifdef ABSL_HAVE_EXCEPTIONS
#define ABSL_INTERNAL_TRY try
#define ABSL_INTERNAL_CATCH_ANY catch (...)
#define ABSL_INTERNAL_RETHROW do { throw; } while (false)
#else // ABSL_HAVE_EXCEPTIONS
#define ABSL_INTERNAL_TRY if (true)
#define ABSL_INTERNAL_CATCH_ANY else if (false)
#define ABSL_INTERNAL_RETHROW do {} while (false)
#endif // ABSL_HAVE_EXCEPTIONS
// ABSL_DEPRECATE_AND_INLINE()
//
// Marks a function or type alias as deprecated and tags it to be picked up for
// automated refactoring by go/cpp-inliner. It can added to inline function
// definitions or type aliases. It should only be used within a header file. It
// differs from `ABSL_DEPRECATED` in the following ways:
//
// 1. New uses of the function or type will be discouraged via Tricorder
// warnings.
// 2. If enabled via `METADATA`, automated changes will be sent out inlining the
// functions's body or replacing the type where it is used.
//
// For example:
//
// ABSL_DEPRECATE_AND_INLINE() inline int OldFunc(int x) {
// return NewFunc(x, 0);
// }
//
// will mark `OldFunc` as deprecated, and the go/cpp-inliner service will
// replace calls to `OldFunc(x)` with calls to `NewFunc(x, 0)`. Once all calls
// to `OldFunc` have been replaced, `OldFunc` can be deleted.
//
// See go/cpp-inliner for more information.
//
// Note: go/cpp-inliner is Google-internal service for automated refactoring.
// While open-source users do not have access to this service, the macro is
// provided for compatibility, and so that users receive deprecation warnings.
#if ABSL_HAVE_CPP_ATTRIBUTE(deprecated) && \
ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate)
#define ABSL_DEPRECATE_AND_INLINE() [[deprecated, clang::annotate("inline-me")]]
#elif ABSL_HAVE_CPP_ATTRIBUTE(deprecated)
#define ABSL_DEPRECATE_AND_INLINE() [[deprecated]]
#else
#define ABSL_DEPRECATE_AND_INLINE()
#endif
// Requires the compiler to prove that the size of the given object is at least
// the expected amount.
#if ABSL_HAVE_ATTRIBUTE(diagnose_if) && ABSL_HAVE_BUILTIN(__builtin_object_size)
#define ABSL_INTERNAL_NEED_MIN_SIZE(Obj, N) \
__attribute__((diagnose_if(__builtin_object_size(Obj, 0) < N, \
"object size provably too small " \
"(this would corrupt memory)", \
"error")))
#else
#define ABSL_INTERNAL_NEED_MIN_SIZE(Obj, N)
#endif
#endif // ABSL_BASE_MACROS_H_
*…
}soong/.intermediates/external/abseil-cpp/absl_base_throw_delegate_hdrs/gen/my_include_dir/absl/base/internal/throw_delegate.hƒ//
// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifndef ABSL_BASE_INTERNAL_THROW_DELEGATE_H_
#define ABSL_BASE_INTERNAL_THROW_DELEGATE_H_
#include <string>
#include "absl/base/config.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace base_internal {
// Helper functions that allow throwing exceptions consistently from anywhere.
// The main use case is for header-based libraries (eg templates), as they will
// be built by many different targets with their own compiler options.
// In particular, this will allow a safe way to throw exceptions even if the
// caller is compiled with -fno-exceptions. This is intended for implementing
// things like map<>::at(), which the standard documents as throwing an
// exception on error.
//
// Using other techniques like #if tricks could lead to ODR violations.
//
// You shouldn't use it unless you're writing code that you know will be built
// both with and without exceptions and you need to conform to an interface
// that uses exceptions.
[[noreturn]] void ThrowStdLogicError(const std::string& what_arg);
[[noreturn]] void ThrowStdLogicError(const char* what_arg);
[[noreturn]] void ThrowStdInvalidArgument(const std::string& what_arg);
[[noreturn]] void ThrowStdInvalidArgument(const char* what_arg);
[[noreturn]] void ThrowStdDomainError(const std::string& what_arg);
[[noreturn]] void ThrowStdDomainError(const char* what_arg);
[[noreturn]] void ThrowStdLengthError(const std::string& what_arg);
[[noreturn]] void ThrowStdLengthError(const char* what_arg);
[[noreturn]] void ThrowStdOutOfRange(const std::string& what_arg);
[[noreturn]] void ThrowStdOutOfRange(const char* what_arg);
[[noreturn]] void ThrowStdRuntimeError(const std::string& what_arg);
[[noreturn]] void ThrowStdRuntimeError(const char* what_arg);
[[noreturn]] void ThrowStdRangeError(const std::string& what_arg);
[[noreturn]] void ThrowStdRangeError(const char* what_arg);
[[noreturn]] void ThrowStdOverflowError(const std::string& what_arg);
[[noreturn]] void ThrowStdOverflowError(const char* what_arg);
[[noreturn]] void ThrowStdUnderflowError(const std::string& what_arg);
[[noreturn]] void ThrowStdUnderflowError(const char* what_arg);
[[noreturn]] void ThrowStdBadFunctionCall();
[[noreturn]] void ThrowStdBadAlloc();
// ThrowStdBadArrayNewLength() cannot be consistently supported because
// std::bad_array_new_length is missing in libstdc++ until 4.9.0.
// https://gcc.gnu.org/onlinedocs/gcc-4.8.3/libstdc++/api/a01379_source.html
// https://gcc.gnu.org/onlinedocs/gcc-4.9.0/libstdc++/api/a01327_source.html
// libcxx (as of 3.2) and msvc (as of 2015) both have it.
// [[noreturn]] void ThrowStdBadArrayNewLength();
} // namespace base_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_INTERNAL_THROW_DELEGATE_H_
*‰^
vsoong/.intermediates/external/abseil-cpp/absl_base_core_headers_hdrs/gen/my_include_dir/absl/base/thread_annotations.hŽ]// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: thread_annotations.h
// -----------------------------------------------------------------------------
//
// This header file contains macro definitions for thread safety annotations
// that allow developers to document the locking policies of multi-threaded
// code. The annotations can also help program analysis tools to identify
// potential thread safety issues.
//
// These annotations are implemented using compiler attributes. Using the macros
// defined here instead of raw attributes allow for portability and future
// compatibility.
//
// When referring to mutexes in the arguments of the attributes, you should
// use variable names or more complex expressions (e.g. my_object->mutex_)
// that evaluate to a concrete mutex object whenever possible. If the mutex
// you want to refer to is not in scope, you may use a member pointer
// (e.g. &MyClass::mutex_) to refer to a mutex in some (unknown) object.
#ifndef ABSL_BASE_THREAD_ANNOTATIONS_H_
#define ABSL_BASE_THREAD_ANNOTATIONS_H_
#include "absl/base/attributes.h"
#include "absl/base/config.h"
// ABSL_GUARDED_BY()
//
// Documents if a shared field or global variable needs to be protected by a
// mutex. ABSL_GUARDED_BY() allows the user to specify a particular mutex that
// should be held when accessing the annotated variable.
//
// Although this annotation (and ABSL_PT_GUARDED_BY, below) cannot be applied to
// local variables, a local variable and its associated mutex can often be
// combined into a small class or struct, thereby allowing the annotation.
//
// Example:
//
// class Foo {
// Mutex mu_;
// int p1_ ABSL_GUARDED_BY(mu_);
// ...
// };
#if ABSL_HAVE_ATTRIBUTE(guarded_by)
#define ABSL_GUARDED_BY(x) __attribute__((guarded_by(x)))
#else
#define ABSL_GUARDED_BY(x)
#endif
// ABSL_PT_GUARDED_BY()
//
// Documents if the memory location pointed to by a pointer should be guarded
// by a mutex when dereferencing the pointer.
//
// Example:
// class Foo {
// Mutex mu_;
// int *p1_ ABSL_PT_GUARDED_BY(mu_);
// ...
// };
//
// Note that a pointer variable to a shared memory location could itself be a
// shared variable.
//
// Example:
//
// // `q_`, guarded by `mu1_`, points to a shared memory location that is
// // guarded by `mu2_`:
// int *q_ ABSL_GUARDED_BY(mu1_) ABSL_PT_GUARDED_BY(mu2_);
#if ABSL_HAVE_ATTRIBUTE(pt_guarded_by)
#define ABSL_PT_GUARDED_BY(x) __attribute__((pt_guarded_by(x)))
#else
#define ABSL_PT_GUARDED_BY(x)
#endif
// ABSL_ACQUIRED_AFTER() / ABSL_ACQUIRED_BEFORE()
//
// Documents the acquisition order between locks that can be held
// simultaneously by a thread. For any two locks that need to be annotated
// to establish an acquisition order, only one of them needs the annotation.
// (i.e. You don't have to annotate both locks with both ABSL_ACQUIRED_AFTER
// and ABSL_ACQUIRED_BEFORE.)
//
// As with ABSL_GUARDED_BY, this is only applicable to mutexes that are shared
// fields or global variables.
//
// Example:
//
// Mutex m1_;
// Mutex m2_ ABSL_ACQUIRED_AFTER(m1_);
#if ABSL_HAVE_ATTRIBUTE(acquired_after)
#define ABSL_ACQUIRED_AFTER(...) __attribute__((acquired_after(__VA_ARGS__)))
#else
#define ABSL_ACQUIRED_AFTER(...)
#endif
#if ABSL_HAVE_ATTRIBUTE(acquired_before)
#define ABSL_ACQUIRED_BEFORE(...) __attribute__((acquired_before(__VA_ARGS__)))
#else
#define ABSL_ACQUIRED_BEFORE(...)
#endif
// ABSL_EXCLUSIVE_LOCKS_REQUIRED() / ABSL_SHARED_LOCKS_REQUIRED()
//
// Documents a function that expects a mutex to be held prior to entry.
// The mutex is expected to be held both on entry to, and exit from, the
// function.
//
// An exclusive lock allows read-write access to the guarded data member(s), and
// only one thread can acquire a lock exclusively at any one time. A shared lock
// allows read-only access, and any number of threads can acquire a shared lock
// concurrently.
//
// Generally, non-const methods should be annotated with
// ABSL_EXCLUSIVE_LOCKS_REQUIRED, while const methods should be annotated with
// ABSL_SHARED_LOCKS_REQUIRED.
//
// Example:
//
// Mutex mu1, mu2;
// int a ABSL_GUARDED_BY(mu1);
// int b ABSL_GUARDED_BY(mu2);
//
// void foo() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu1, mu2) { ... }
// void bar() const ABSL_SHARED_LOCKS_REQUIRED(mu1, mu2) { ... }
#if ABSL_HAVE_ATTRIBUTE(exclusive_locks_required)
#define ABSL_EXCLUSIVE_LOCKS_REQUIRED(...) \
__attribute__((exclusive_locks_required(__VA_ARGS__)))
#else
#define ABSL_EXCLUSIVE_LOCKS_REQUIRED(...)
#endif
#if ABSL_HAVE_ATTRIBUTE(shared_locks_required)
#define ABSL_SHARED_LOCKS_REQUIRED(...) \
__attribute__((shared_locks_required(__VA_ARGS__)))
#else
#define ABSL_SHARED_LOCKS_REQUIRED(...)
#endif
// ABSL_LOCKS_EXCLUDED()
//
// Documents the locks that cannot be held by callers of this function, as they
// might be acquired by this function (Abseil's `Mutex` locks are
// non-reentrant).
#if ABSL_HAVE_ATTRIBUTE(locks_excluded)
#define ABSL_LOCKS_EXCLUDED(...) __attribute__((locks_excluded(__VA_ARGS__)))
#else
#define ABSL_LOCKS_EXCLUDED(...)
#endif
// ABSL_LOCK_RETURNED()
//
// Documents a function that returns a mutex without acquiring it. For example,
// a public getter method that returns a pointer to a private mutex should
// be annotated with ABSL_LOCK_RETURNED.
#if ABSL_HAVE_ATTRIBUTE(lock_returned)
#define ABSL_LOCK_RETURNED(x) __attribute__((lock_returned(x)))
#else
#define ABSL_LOCK_RETURNED(x)
#endif
// ABSL_LOCKABLE
//
// Documents if a class/type is a lockable type (such as the `Mutex` class).
#if ABSL_HAVE_ATTRIBUTE(lockable)
#define ABSL_LOCKABLE __attribute__((lockable))
#else
#define ABSL_LOCKABLE
#endif
// ABSL_SCOPED_LOCKABLE
//
// Documents if a class does RAII locking (such as the `MutexLock` class).
// The constructor should use `LOCK_FUNCTION()` to specify the mutex that is
// acquired, and the destructor should use `UNLOCK_FUNCTION()` with no
// arguments; the analysis will assume that the destructor unlocks whatever the
// constructor locked.
#if ABSL_HAVE_ATTRIBUTE(scoped_lockable)
#define ABSL_SCOPED_LOCKABLE __attribute__((scoped_lockable))
#else
#define ABSL_SCOPED_LOCKABLE
#endif
// ABSL_EXCLUSIVE_LOCK_FUNCTION()
//
// Documents functions that acquire a lock in the body of a function, and do
// not release it.
#if ABSL_HAVE_ATTRIBUTE(exclusive_lock_function)
#define ABSL_EXCLUSIVE_LOCK_FUNCTION(...) \
__attribute__((exclusive_lock_function(__VA_ARGS__)))
#else
#define ABSL_EXCLUSIVE_LOCK_FUNCTION(...)
#endif
// ABSL_SHARED_LOCK_FUNCTION()
//
// Documents functions that acquire a shared (reader) lock in the body of a
// function, and do not release it.
#if ABSL_HAVE_ATTRIBUTE(shared_lock_function)
#define ABSL_SHARED_LOCK_FUNCTION(...) \
__attribute__((shared_lock_function(__VA_ARGS__)))
#else
#define ABSL_SHARED_LOCK_FUNCTION(...)
#endif
// ABSL_UNLOCK_FUNCTION()
//
// Documents functions that expect a lock to be held on entry to the function,
// and release it in the body of the function.
#if ABSL_HAVE_ATTRIBUTE(unlock_function)
#define ABSL_UNLOCK_FUNCTION(...) __attribute__((unlock_function(__VA_ARGS__)))
#else
#define ABSL_UNLOCK_FUNCTION(...)
#endif
// ABSL_EXCLUSIVE_TRYLOCK_FUNCTION() / ABSL_SHARED_TRYLOCK_FUNCTION()
//
// Documents functions that try to acquire a lock, and return success or failure
// (or a non-boolean value that can be interpreted as a boolean).
// The first argument should be `true` for functions that return `true` on
// success, or `false` for functions that return `false` on success. The second
// argument specifies the mutex that is locked on success. If unspecified, this
// mutex is assumed to be `this`.
#if ABSL_HAVE_ATTRIBUTE(exclusive_trylock_function)
#define ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(...) \
__attribute__((exclusive_trylock_function(__VA_ARGS__)))
#else
#define ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(...)
#endif
#if ABSL_HAVE_ATTRIBUTE(shared_trylock_function)
#define ABSL_SHARED_TRYLOCK_FUNCTION(...) \
__attribute__((shared_trylock_function(__VA_ARGS__)))
#else
#define ABSL_SHARED_TRYLOCK_FUNCTION(...)
#endif
// ABSL_ASSERT_EXCLUSIVE_LOCK() / ABSL_ASSERT_SHARED_LOCK()
//
// Documents functions that dynamically check to see if a lock is held, and fail
// if it is not held.
#if ABSL_HAVE_ATTRIBUTE(assert_exclusive_lock)
#define ABSL_ASSERT_EXCLUSIVE_LOCK(...) \
__attribute__((assert_exclusive_lock(__VA_ARGS__)))
#else
#define ABSL_ASSERT_EXCLUSIVE_LOCK(...)
#endif
#if ABSL_HAVE_ATTRIBUTE(assert_shared_lock)
#define ABSL_ASSERT_SHARED_LOCK(...) \
__attribute__((assert_shared_lock(__VA_ARGS__)))
#else
#define ABSL_ASSERT_SHARED_LOCK(...)
#endif
// ABSL_NO_THREAD_SAFETY_ANALYSIS
//
// Turns off thread safety checking within the body of a particular function.
// This annotation is used to mark functions that are known to be correct, but
// the locking behavior is more complicated than the analyzer can handle.
#if ABSL_HAVE_ATTRIBUTE(no_thread_safety_analysis)
#define ABSL_NO_THREAD_SAFETY_ANALYSIS \
__attribute__((no_thread_safety_analysis))
#else
#define ABSL_NO_THREAD_SAFETY_ANALYSIS
#endif
//------------------------------------------------------------------------------
// Tool-Supplied Annotations
//------------------------------------------------------------------------------
// ABSL_TS_UNCHECKED should be placed around lock expressions that are not valid
// C++ syntax, but which are present for documentation purposes. These
// annotations will be ignored by the analysis.
#define ABSL_TS_UNCHECKED(x) ""
// ABSL_TS_FIXME is used to mark lock expressions that are not valid C++ syntax.
// It is used by automated tools to mark and disable invalid expressions.
// The annotation should either be fixed, or changed to ABSL_TS_UNCHECKED.
#define ABSL_TS_FIXME(x) ""
// Like ABSL_NO_THREAD_SAFETY_ANALYSIS, this turns off checking within the body
// of a particular function. However, this attribute is used to mark functions
// that are incorrect and need to be fixed. It is used by automated tools to
// avoid breaking the build when the analysis is updated.
// Code owners are expected to eventually fix the routine.
#define ABSL_NO_THREAD_SAFETY_ANALYSIS_FIXME ABSL_NO_THREAD_SAFETY_ANALYSIS
// Similar to ABSL_NO_THREAD_SAFETY_ANALYSIS_FIXME, this macro marks a
// ABSL_GUARDED_BY annotation that needs to be fixed, because it is producing
// thread safety warning. It disables the ABSL_GUARDED_BY.
#define ABSL_GUARDED_BY_FIXME(x)
// Disables warnings for a single read operation. This can be used to avoid
// warnings when it is known that the read is not actually involved in a race,
// but the compiler cannot confirm that.
#define ABSL_TS_UNCHECKED_READ(x) absl::base_internal::ts_unchecked_read(x)
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace base_internal {
// Takes a reference to a guarded data member, and returns an unguarded
// reference.
// Do not use this function directly, use ABSL_TS_UNCHECKED_READ instead.
template <typename T>
inline const T& ts_unchecked_read(const T& v) ABSL_NO_THREAD_SAFETY_ANALYSIS {
return v;
}
template <typename T>
inline T& ts_unchecked_read(T& v) ABSL_NO_THREAD_SAFETY_ANALYSIS {
return v;
}
} // namespace base_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_THREAD_ANNOTATIONS_H_
*þÔ
nsoong/.intermediates/external/abseil-cpp/absl_base_core_headers_hdrs/gen/my_include_dir/absl/base/attributes.hŠÔ// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// This header file defines macros for declaring attributes for functions,
// types, and variables.
//
// These macros are used within Abseil and allow the compiler to optimize, where
// applicable, certain function calls.
//
// Most macros here are exposing GCC or Clang features, and are stubbed out for
// other compilers.
//
// GCC attributes documentation:
// https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html
// https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Variable-Attributes.html
// https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Type-Attributes.html
//
// Most attributes in this file are already supported by GCC 4.7. However, some
// of them are not supported in older version of Clang. Thus, we check
// `__has_attribute()` first. If the check fails, we check if we are on GCC and
// assume the attribute exists on GCC (which is verified on GCC 4.7).
// SKIP_ABSL_INLINE_NAMESPACE_CHECK
#ifndef ABSL_BASE_ATTRIBUTES_H_
#define ABSL_BASE_ATTRIBUTES_H_
#include "absl/base/config.h"
// ABSL_HAVE_ATTRIBUTE
//
// A function-like feature checking macro that is a wrapper around
// `__has_attribute`, which is defined by GCC 5+ and Clang and evaluates to a
// nonzero constant integer if the attribute is supported or 0 if not.
//
// It evaluates to zero if `__has_attribute` is not defined by the compiler.
//
// GCC: https://gcc.gnu.org/gcc-5/changes.html
// Clang: https://clang.llvm.org/docs/LanguageExtensions.html
#ifdef __has_attribute
#define ABSL_HAVE_ATTRIBUTE(x) __has_attribute(x)
#else
#define ABSL_HAVE_ATTRIBUTE(x) 0
#endif
// ABSL_HAVE_CPP_ATTRIBUTE
//
// A function-like feature checking macro that accepts C++11 style attributes.
// It's a wrapper around `__has_cpp_attribute`, defined by ISO C++ SD-6
// (https://en.cppreference.com/w/cpp/experimental/feature_test). If we don't
// find `__has_cpp_attribute`, will evaluate to 0.
#if defined(__cplusplus) && defined(__has_cpp_attribute)
// NOTE: requiring __cplusplus above should not be necessary, but
// works around https://bugs.llvm.org/show_bug.cgi?id=23435.
#define ABSL_HAVE_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
#else
#define ABSL_HAVE_CPP_ATTRIBUTE(x) 0
#endif
// -----------------------------------------------------------------------------
// Function Attributes
// -----------------------------------------------------------------------------
//
// GCC: https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
// Clang: https://clang.llvm.org/docs/AttributeReference.html
// ABSL_PRINTF_ATTRIBUTE
// ABSL_SCANF_ATTRIBUTE
//
// Tells the compiler to perform `printf` format string checking if the
// compiler supports it; see the 'format' attribute in
// <https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html>.
//
// Note: As the GCC manual states, "[s]ince non-static C++ methods
// have an implicit 'this' argument, the arguments of such methods
// should be counted from two, not one."
#if ABSL_HAVE_ATTRIBUTE(format) || (defined(__GNUC__) && !defined(__clang__))
#define ABSL_PRINTF_ATTRIBUTE(string_index, first_to_check) \
__attribute__((__format__(__printf__, string_index, first_to_check)))
#define ABSL_SCANF_ATTRIBUTE(string_index, first_to_check) \
__attribute__((__format__(__scanf__, string_index, first_to_check)))
#else
#define ABSL_PRINTF_ATTRIBUTE(string_index, first_to_check)
#define ABSL_SCANF_ATTRIBUTE(string_index, first_to_check)
#endif
// ABSL_ATTRIBUTE_ALWAYS_INLINE
// ABSL_ATTRIBUTE_NOINLINE
//
// Forces functions to either inline or not inline. Introduced in gcc 3.1.
#if ABSL_HAVE_ATTRIBUTE(always_inline) || \
(defined(__GNUC__) && !defined(__clang__))
#define ABSL_ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline))
#define ABSL_HAVE_ATTRIBUTE_ALWAYS_INLINE 1
#else
#define ABSL_ATTRIBUTE_ALWAYS_INLINE
#endif
#if ABSL_HAVE_ATTRIBUTE(noinline) || (defined(__GNUC__) && !defined(__clang__))
#define ABSL_ATTRIBUTE_NOINLINE __attribute__((noinline))
#define ABSL_HAVE_ATTRIBUTE_NOINLINE 1
#else
#define ABSL_ATTRIBUTE_NOINLINE
#endif
// ABSL_ATTRIBUTE_NO_TAIL_CALL
//
// Prevents the compiler from optimizing away stack frames for functions which
// end in a call to another function.
#if ABSL_HAVE_ATTRIBUTE(disable_tail_calls)
#define ABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 1
#define ABSL_ATTRIBUTE_NO_TAIL_CALL __attribute__((disable_tail_calls))
#elif defined(__GNUC__) && !defined(__clang__) && !defined(__e2k__)
#define ABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 1
#define ABSL_ATTRIBUTE_NO_TAIL_CALL \
__attribute__((optimize("no-optimize-sibling-calls")))
#else
#define ABSL_ATTRIBUTE_NO_TAIL_CALL
#define ABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 0
#endif
// ABSL_ATTRIBUTE_WEAK
//
// Tags a function as weak for the purposes of compilation and linking.
// Weak attributes did not work properly in LLVM's Windows backend before
// 9.0.0, so disable them there. See https://bugs.llvm.org/show_bug.cgi?id=37598
// for further information. Weak attributes do not work across DLL boundary.
// The MinGW compiler doesn't complain about the weak attribute until the link
// step, presumably because Windows doesn't use ELF binaries.
#if (ABSL_HAVE_ATTRIBUTE(weak) || \
(defined(__GNUC__) && !defined(__clang__))) && \
(!defined(_WIN32) || \
(defined(__clang__) && __clang_major__ >= 9 && \
!defined(ABSL_BUILD_DLL) && !defined(ABSL_CONSUME_DLL))) && \
!defined(__MINGW32__)
#undef ABSL_ATTRIBUTE_WEAK
#define ABSL_ATTRIBUTE_WEAK __attribute__((weak))
#define ABSL_HAVE_ATTRIBUTE_WEAK 1
#else
#define ABSL_ATTRIBUTE_WEAK
#define ABSL_HAVE_ATTRIBUTE_WEAK 0
#endif
// ABSL_ATTRIBUTE_NONNULL
//
// Tells the compiler either (a) that a particular function parameter
// should be a non-null pointer, or (b) that all pointer arguments should
// be non-null.
//
// Note: As the GCC manual states, "[s]ince non-static C++ methods
// have an implicit 'this' argument, the arguments of such methods
// should be counted from two, not one."
//
// Args are indexed starting at 1.
//
// For non-static class member functions, the implicit `this` argument
// is arg 1, and the first explicit argument is arg 2. For static class member
// functions, there is no implicit `this`, and the first explicit argument is
// arg 1.
//
// Example:
//
// /* arg_a cannot be null, but arg_b can */
// void Function(void* arg_a, void* arg_b) ABSL_ATTRIBUTE_NONNULL(1);
//
// class C {
// /* arg_a cannot be null, but arg_b can */
// void Method(void* arg_a, void* arg_b) ABSL_ATTRIBUTE_NONNULL(2);
//
// /* arg_a cannot be null, but arg_b can */
// static void StaticMethod(void* arg_a, void* arg_b)
// ABSL_ATTRIBUTE_NONNULL(1);
// };
//
// If no arguments are provided, then all pointer arguments should be non-null.
//
// /* No pointer arguments may be null. */
// void Function(void* arg_a, void* arg_b, int arg_c) ABSL_ATTRIBUTE_NONNULL();
//
// NOTE: The GCC nonnull attribute actually accepts a list of arguments, but
// ABSL_ATTRIBUTE_NONNULL does not.
#if ABSL_HAVE_ATTRIBUTE(nonnull) || (defined(__GNUC__) && !defined(__clang__))
#define ABSL_ATTRIBUTE_NONNULL(arg_index) __attribute__((nonnull(arg_index)))
#else
#define ABSL_ATTRIBUTE_NONNULL(...)
#endif
// ABSL_ATTRIBUTE_NORETURN
//
// Tells the compiler that a given function never returns.
//
// Deprecated: Prefer the `[[noreturn]]` attribute standardized by C++11 over
// this macro.
#if ABSL_HAVE_ATTRIBUTE(noreturn) || (defined(__GNUC__) && !defined(__clang__))
#define ABSL_ATTRIBUTE_NORETURN __attribute__((noreturn))
#elif defined(_MSC_VER)
#define ABSL_ATTRIBUTE_NORETURN __declspec(noreturn)
#else
#define ABSL_ATTRIBUTE_NORETURN
#endif
// ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS
//
// Tells the AddressSanitizer (or other memory testing tools) to ignore a given
// function. Useful for cases when a function reads random locations on stack,
// calls _exit from a cloned subprocess, deliberately accesses buffer
// out of bounds or does other scary things with memory.
// NOTE: GCC supports AddressSanitizer(asan) since 4.8.
// https://gcc.gnu.org/gcc-4.8/changes.html
#if defined(ABSL_HAVE_ADDRESS_SANITIZER) && \
ABSL_HAVE_ATTRIBUTE(no_sanitize_address)
#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address))
#elif defined(ABSL_HAVE_ADDRESS_SANITIZER) && defined(_MSC_VER) && \
_MSC_VER >= 1928
// https://docs.microsoft.com/en-us/cpp/cpp/no-sanitize-address
#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS __declspec(no_sanitize_address)
#elif defined(ABSL_HAVE_HWADDRESS_SANITIZER) && ABSL_HAVE_ATTRIBUTE(no_sanitize)
// HWAddressSanitizer is a sanitizer similar to AddressSanitizer, which uses CPU
// features to detect similar bugs with less CPU and memory overhead.
// NOTE: GCC supports HWAddressSanitizer(hwasan) since 11.
// https://gcc.gnu.org/gcc-11/changes.html
#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS \
__attribute__((no_sanitize("hwaddress")))
#else
#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS
#endif
// ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY
//
// Tells the MemorySanitizer to relax the handling of a given function. All "Use
// of uninitialized value" warnings from such functions will be suppressed, and
// all values loaded from memory will be considered fully initialized. This
// attribute is similar to the ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS attribute
// above, but deals with initialized-ness rather than addressability issues.
// NOTE: MemorySanitizer(msan) is supported by Clang but not GCC.
#if ABSL_HAVE_ATTRIBUTE(no_sanitize_memory)
#define ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory))
#else
#define ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY
#endif
// ABSL_ATTRIBUTE_NO_SANITIZE_THREAD
//
// Tells the ThreadSanitizer to not instrument a given function.
// NOTE: GCC supports ThreadSanitizer(tsan) since 4.8.
// https://gcc.gnu.org/gcc-4.8/changes.html
#if ABSL_HAVE_ATTRIBUTE(no_sanitize_thread)
#define ABSL_ATTRIBUTE_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread))
#else
#define ABSL_ATTRIBUTE_NO_SANITIZE_THREAD
#endif
// ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED
//
// Tells the UndefinedSanitizer to ignore a given function. Useful for cases
// where certain behavior (eg. division by zero) is being used intentionally.
// NOTE: GCC supports UndefinedBehaviorSanitizer(ubsan) since 4.9.
// https://gcc.gnu.org/gcc-4.9/changes.html
#if ABSL_HAVE_ATTRIBUTE(no_sanitize_undefined)
#define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED \
__attribute__((no_sanitize_undefined))
#elif ABSL_HAVE_ATTRIBUTE(no_sanitize)
#define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED \
__attribute__((no_sanitize("undefined")))
#else
#define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED
#endif
// Android local modification: add attribute for disabling unsigned overflow
// sanitization for code where it's intentional, to support vendor code that
// enables it.
#if ABSL_HAVE_ATTRIBUTE(no_sanitize)
#define ABSL_ATTRIBUTE_NO_SANITIZE_UNSIGNED_OVERFLOW \
__attribute__((no_sanitize("unsigned-integer-overflow")))
#else
#define ABSL_ATTRIBUTE_NO_SANITIZE_UNSIGNED_OVERFLOW
#endif
// ABSL_ATTRIBUTE_NO_SANITIZE_CFI
//
// Tells the ControlFlowIntegrity sanitizer to not instrument a given function.
// See https://clang.llvm.org/docs/ControlFlowIntegrity.html for details.
#if ABSL_HAVE_ATTRIBUTE(no_sanitize) && defined(__llvm__)
#define ABSL_ATTRIBUTE_NO_SANITIZE_CFI __attribute__((no_sanitize("cfi")))
#else
#define ABSL_ATTRIBUTE_NO_SANITIZE_CFI
#endif
// ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK
//
// Tells the SafeStack to not instrument a given function.
// See https://clang.llvm.org/docs/SafeStack.html for details.
#if ABSL_HAVE_ATTRIBUTE(no_sanitize)
#define ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK \
__attribute__((no_sanitize("safe-stack")))
#else
#define ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK
#endif
// ABSL_ATTRIBUTE_RETURNS_NONNULL
//
// Tells the compiler that a particular function never returns a null pointer.
#if ABSL_HAVE_ATTRIBUTE(returns_nonnull)
#define ABSL_ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull))
#else
#define ABSL_ATTRIBUTE_RETURNS_NONNULL
#endif
// ABSL_HAVE_ATTRIBUTE_SECTION
//
// Indicates whether labeled sections are supported. Weak symbol support is
// a prerequisite. Labeled sections are not supported on Darwin/iOS.
#ifdef ABSL_HAVE_ATTRIBUTE_SECTION
#error ABSL_HAVE_ATTRIBUTE_SECTION cannot be directly set
#elif (ABSL_HAVE_ATTRIBUTE(section) || \
(defined(__GNUC__) && !defined(__clang__))) && \
!defined(__APPLE__) && ABSL_HAVE_ATTRIBUTE_WEAK
#define ABSL_HAVE_ATTRIBUTE_SECTION 1
// ABSL_ATTRIBUTE_SECTION
//
// Tells the compiler/linker to put a given function into a section and define
// `__start_ ## name` and `__stop_ ## name` symbols to bracket the section.
// This functionality is supported by GNU linker. Any function annotated with
// `ABSL_ATTRIBUTE_SECTION` must not be inlined, or it will be placed into
// whatever section its caller is placed into.
//
#ifndef ABSL_ATTRIBUTE_SECTION
#define ABSL_ATTRIBUTE_SECTION(name) \
__attribute__((section(#name))) __attribute__((noinline))
#endif
// ABSL_ATTRIBUTE_SECTION_VARIABLE
//
// Tells the compiler/linker to put a given variable into a section and define
// `__start_ ## name` and `__stop_ ## name` symbols to bracket the section.
// This functionality is supported by GNU linker.
#ifndef ABSL_ATTRIBUTE_SECTION_VARIABLE
#ifdef _AIX
// __attribute__((section(#name))) on AIX is achieved by using the `.csect`
// pseudo op which includes an additional integer as part of its syntax
// indicating alignment. If data fall under different alignments then you might
// get a compilation error indicating a `Section type conflict`.
#define ABSL_ATTRIBUTE_SECTION_VARIABLE(name)
#else
#define ABSL_ATTRIBUTE_SECTION_VARIABLE(name) __attribute__((section(#name)))
#endif
#endif
// ABSL_DECLARE_ATTRIBUTE_SECTION_VARS
//
// A weak section declaration to be used as a global declaration
// for ABSL_ATTRIBUTE_SECTION_START|STOP(name) to compile and link
// even without functions with ABSL_ATTRIBUTE_SECTION(name).
// ABSL_DEFINE_ATTRIBUTE_SECTION should be in the exactly one file; it's
// a no-op on ELF but not on Mach-O.
//
#ifndef ABSL_DECLARE_ATTRIBUTE_SECTION_VARS
#define ABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name) \
extern char __start_##name[] ABSL_ATTRIBUTE_WEAK; \
extern char __stop_##name[] ABSL_ATTRIBUTE_WEAK
#endif
#ifndef ABSL_DEFINE_ATTRIBUTE_SECTION_VARS
#define ABSL_INIT_ATTRIBUTE_SECTION_VARS(name)
#define ABSL_DEFINE_ATTRIBUTE_SECTION_VARS(name)
#endif
// ABSL_ATTRIBUTE_SECTION_START
//
// Returns `void*` pointers to start/end of a section of code with
// functions having ABSL_ATTRIBUTE_SECTION(name).
// Returns 0 if no such functions exist.
// One must ABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name) for this to compile and
// link.
//
#define ABSL_ATTRIBUTE_SECTION_START(name) \
(reinterpret_cast<void *>(__start_##name))
#define ABSL_ATTRIBUTE_SECTION_STOP(name) \
(reinterpret_cast<void *>(__stop_##name))
#else // !ABSL_HAVE_ATTRIBUTE_SECTION
#define ABSL_HAVE_ATTRIBUTE_SECTION 0
// provide dummy definitions
#define ABSL_ATTRIBUTE_SECTION(name)
#define ABSL_ATTRIBUTE_SECTION_VARIABLE(name)
#define ABSL_INIT_ATTRIBUTE_SECTION_VARS(name)
#define ABSL_DEFINE_ATTRIBUTE_SECTION_VARS(name)
#define ABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name)
#define ABSL_ATTRIBUTE_SECTION_START(name) (reinterpret_cast<void *>(0))
#define ABSL_ATTRIBUTE_SECTION_STOP(name) (reinterpret_cast<void *>(0))
#endif // ABSL_ATTRIBUTE_SECTION
// ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC
//
// Support for aligning the stack on 32-bit x86.
#if ABSL_HAVE_ATTRIBUTE(force_align_arg_pointer) || \
(defined(__GNUC__) && !defined(__clang__))
#if defined(__i386__)
#define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC \
__attribute__((force_align_arg_pointer))
#define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0)
#elif defined(__x86_64__)
#define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (1)
#define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC
#else // !__i386__ && !__x86_64
#define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0)
#define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC
#endif // __i386__
#else
#define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC
#define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0)
#endif
// ABSL_MUST_USE_RESULT
//
// Tells the compiler to warn about unused results.
//
// For code or headers that are assured to only build with C++17 and up, prefer
// just using the standard `[[nodiscard]]` directly over this macro.
//
// When annotating a function, it must appear as the first part of the
// declaration or definition. The compiler will warn if the return value from
// such a function is unused:
//
// ABSL_MUST_USE_RESULT Sprocket* AllocateSprocket();
// AllocateSprocket(); // Triggers a warning.
//
// When annotating a class, it is equivalent to annotating every function which
// returns an instance.
//
// class ABSL_MUST_USE_RESULT Sprocket {};
// Sprocket(); // Triggers a warning.
//
// Sprocket MakeSprocket();
// MakeSprocket(); // Triggers a warning.
//
// Note that references and pointers are not instances:
//
// Sprocket* SprocketPointer();
// SprocketPointer(); // Does *not* trigger a warning.
//
// ABSL_MUST_USE_RESULT allows using cast-to-void to suppress the unused result
// warning. For that, warn_unused_result is used only for clang but not for gcc.
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425
//
// Note: past advice was to place the macro after the argument list.
//
// TODO(b/176172494): Use ABSL_HAVE_CPP_ATTRIBUTE(nodiscard) when all code is
// compliant with the stricter [[nodiscard]].
#if defined(__clang__) && ABSL_HAVE_ATTRIBUTE(warn_unused_result)
#define ABSL_MUST_USE_RESULT __attribute__((warn_unused_result))
#else
#define ABSL_MUST_USE_RESULT
#endif
// ABSL_ATTRIBUTE_HOT, ABSL_ATTRIBUTE_COLD
//
// Tells GCC that a function is hot or cold. GCC can use this information to
// improve static analysis, i.e. a conditional branch to a cold function
// is likely to be not-taken.
// This annotation is used for function declarations.
//
// Example:
//
// int foo() ABSL_ATTRIBUTE_HOT;
#if ABSL_HAVE_ATTRIBUTE(hot) || (defined(__GNUC__) && !defined(__clang__))
#define ABSL_ATTRIBUTE_HOT __attribute__((hot))
#else
#define ABSL_ATTRIBUTE_HOT
#endif
#if ABSL_HAVE_ATTRIBUTE(cold) || (defined(__GNUC__) && !defined(__clang__))
#define ABSL_ATTRIBUTE_COLD __attribute__((cold))
#else
#define ABSL_ATTRIBUTE_COLD
#endif
// ABSL_XRAY_ALWAYS_INSTRUMENT, ABSL_XRAY_NEVER_INSTRUMENT, ABSL_XRAY_LOG_ARGS
//
// We define the ABSL_XRAY_ALWAYS_INSTRUMENT and ABSL_XRAY_NEVER_INSTRUMENT
// macro used as an attribute to mark functions that must always or never be
// instrumented by XRay. Currently, this is only supported in Clang/LLVM.
//
// For reference on the LLVM XRay instrumentation, see
// http://llvm.org/docs/XRay.html.
//
// A function with the XRAY_ALWAYS_INSTRUMENT macro attribute in its declaration
// will always get the XRay instrumentation sleds. These sleds may introduce
// some binary size and runtime overhead and must be used sparingly.
//
// These attributes only take effect when the following conditions are met:
//
// * The file/target is built in at least C++11 mode, with a Clang compiler
// that supports XRay attributes.
// * The file/target is built with the -fxray-instrument flag set for the
// Clang/LLVM compiler.
// * The function is defined in the translation unit (the compiler honors the
// attribute in either the definition or the declaration, and must match).
//
// There are cases when, even when building with XRay instrumentation, users
// might want to control specifically which functions are instrumented for a
// particular build using special-case lists provided to the compiler. These
// special case lists are provided to Clang via the
// -fxray-always-instrument=... and -fxray-never-instrument=... flags. The
// attributes in source take precedence over these special-case lists.
//
// To disable the XRay attributes at build-time, users may define
// ABSL_NO_XRAY_ATTRIBUTES. Do NOT define ABSL_NO_XRAY_ATTRIBUTES on specific
// packages/targets, as this may lead to conflicting definitions of functions at
// link-time.
//
// XRay isn't currently supported on Android:
// https://github.com/android/ndk/issues/368
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::xray_always_instrument) && \
!defined(ABSL_NO_XRAY_ATTRIBUTES) && !defined(__ANDROID__)
#define ABSL_XRAY_ALWAYS_INSTRUMENT [[clang::xray_always_instrument]]
#define ABSL_XRAY_NEVER_INSTRUMENT [[clang::xray_never_instrument]]
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::xray_log_args)
#define ABSL_XRAY_LOG_ARGS(N) \
[[clang::xray_always_instrument, clang::xray_log_args(N)]]
#else
#define ABSL_XRAY_LOG_ARGS(N) [[clang::xray_always_instrument]]
#endif
#else
#define ABSL_XRAY_ALWAYS_INSTRUMENT
#define ABSL_XRAY_NEVER_INSTRUMENT
#define ABSL_XRAY_LOG_ARGS(N)
#endif
// ABSL_ATTRIBUTE_REINITIALIZES
//
// Indicates that a member function reinitializes the entire object to a known
// state, independent of the previous state of the object.
//
// The clang-tidy check bugprone-use-after-move allows member functions marked
// with this attribute to be called on objects that have been moved from;
// without the attribute, this would result in a use-after-move warning.
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::reinitializes)
#define ABSL_ATTRIBUTE_REINITIALIZES [[clang::reinitializes]]
#else
#define ABSL_ATTRIBUTE_REINITIALIZES
#endif
// -----------------------------------------------------------------------------
// Variable Attributes
// -----------------------------------------------------------------------------
// ABSL_ATTRIBUTE_UNUSED
//
// Prevents the compiler from complaining about variables that appear unused.
//
// Deprecated: Use the standard C++17 `[[maybe_unused]` instead.
//
// Due to differences in positioning requirements between the old, compiler
// specific __attribute__ syntax and the now standard `[[maybe_unused]]`, this
// macro does not attempt to take advantage of `[[maybe_unused]]`.
#if ABSL_HAVE_ATTRIBUTE(unused) || (defined(__GNUC__) && !defined(__clang__))
#undef ABSL_ATTRIBUTE_UNUSED
#define ABSL_ATTRIBUTE_UNUSED __attribute__((__unused__))
#else
#define ABSL_ATTRIBUTE_UNUSED
#endif
// ABSL_ATTRIBUTE_INITIAL_EXEC
//
// Tells the compiler to use "initial-exec" mode for a thread-local variable.
// See http://people.redhat.com/drepper/tls.pdf for the gory details.
#if ABSL_HAVE_ATTRIBUTE(tls_model) || (defined(__GNUC__) && !defined(__clang__))
#define ABSL_ATTRIBUTE_INITIAL_EXEC __attribute__((tls_model("initial-exec")))
#else
#define ABSL_ATTRIBUTE_INITIAL_EXEC
#endif
// ABSL_ATTRIBUTE_PACKED
//
// Instructs the compiler not to use natural alignment for a tagged data
// structure, but instead to reduce its alignment to 1.
//
// Therefore, DO NOT APPLY THIS ATTRIBUTE TO STRUCTS CONTAINING ATOMICS. Doing
// so can cause atomic variables to be mis-aligned and silently violate
// atomicity on x86.
//
// This attribute can either be applied to members of a structure or to a
// structure in its entirety. Applying this attribute (judiciously) to a
// structure in its entirety to optimize the memory footprint of very
// commonly-used structs is fine. Do not apply this attribute to a structure in
// its entirety if the purpose is to control the offsets of the members in the
// structure. Instead, apply this attribute only to structure members that need
// it.
//
// When applying ABSL_ATTRIBUTE_PACKED only to specific structure members the
// natural alignment of structure members not annotated is preserved. Aligned
// member accesses are faster than non-aligned member accesses even if the
// targeted microprocessor supports non-aligned accesses.
#if ABSL_HAVE_ATTRIBUTE(packed) || (defined(__GNUC__) && !defined(__clang__))
#define ABSL_ATTRIBUTE_PACKED __attribute__((__packed__))
#else
#define ABSL_ATTRIBUTE_PACKED
#endif
// ABSL_ATTRIBUTE_FUNC_ALIGN
//
// Tells the compiler to align the function start at least to certain
// alignment boundary
#if ABSL_HAVE_ATTRIBUTE(aligned) || (defined(__GNUC__) && !defined(__clang__))
#define ABSL_ATTRIBUTE_FUNC_ALIGN(bytes) __attribute__((aligned(bytes)))
#else
#define ABSL_ATTRIBUTE_FUNC_ALIGN(bytes)
#endif
// ABSL_FALLTHROUGH_INTENDED
//
// Annotates implicit fall-through between switch labels, allowing a case to
// indicate intentional fallthrough and turn off warnings about any lack of a
// `break` statement. The ABSL_FALLTHROUGH_INTENDED macro should be followed by
// a semicolon and can be used in most places where `break` can, provided that
// no statements exist between it and the next switch label.
//
// Example:
//
// switch (x) {
// case 40:
// case 41:
// if (truth_is_out_there) {
// ++x;
// ABSL_FALLTHROUGH_INTENDED; // Use instead of/along with annotations
// // in comments
// } else {
// return x;
// }
// case 42:
// ...
//
// Notes: When supported, GCC and Clang can issue a warning on switch labels
// with unannotated fallthrough using the warning `-Wimplicit-fallthrough`. See
// clang documentation on language extensions for details:
// https://clang.llvm.org/docs/AttributeReference.html#fallthrough-clang-fallthrough
//
// When used with unsupported compilers, the ABSL_FALLTHROUGH_INTENDED macro has
// no effect on diagnostics. In any case this macro has no effect on runtime
// behavior and performance of code.
#ifdef ABSL_FALLTHROUGH_INTENDED
#error "ABSL_FALLTHROUGH_INTENDED should not be defined."
#elif ABSL_HAVE_CPP_ATTRIBUTE(fallthrough)
#define ABSL_FALLTHROUGH_INTENDED [[fallthrough]]
#elif ABSL_HAVE_CPP_ATTRIBUTE(clang::fallthrough)
#define ABSL_FALLTHROUGH_INTENDED [[clang::fallthrough]]
#elif ABSL_HAVE_CPP_ATTRIBUTE(gnu::fallthrough)
#define ABSL_FALLTHROUGH_INTENDED [[gnu::fallthrough]]
#else
#define ABSL_FALLTHROUGH_INTENDED \
do { \
} while (0)
#endif
// ABSL_DEPRECATED()
//
// Marks a deprecated class, struct, enum, function, method and variable
// declarations. The macro argument is used as a custom diagnostic message (e.g.
// suggestion of a better alternative).
//
// For code or headers that are assured to only build with C++14 and up, prefer
// just using the standard `[[deprecated("message")]]` directly over this macro.
//
// Examples:
//
// class ABSL_DEPRECATED("Use Bar instead") Foo {...};
//
// ABSL_DEPRECATED("Use Baz() instead") void Bar() {...}
//
// template <typename T>
// ABSL_DEPRECATED("Use DoThat() instead")
// void DoThis();
//
// enum FooEnum {
// kBar ABSL_DEPRECATED("Use kBaz instead"),
// };
//
// Every usage of a deprecated entity will trigger a warning when compiled with
// GCC/Clang's `-Wdeprecated-declarations` option. Google's production toolchain
// turns this warning off by default, instead relying on clang-tidy to report
// new uses of deprecated code.
#if ABSL_HAVE_ATTRIBUTE(deprecated)
#define ABSL_DEPRECATED(message) __attribute__((deprecated(message)))
#else
#define ABSL_DEPRECATED(message)
#endif
// When deprecating Abseil code, it is sometimes necessary to turn off the
// warning within Abseil, until the deprecated code is actually removed. The
// deprecated code can be surrounded with these directives to achieve that
// result.
//
// class ABSL_DEPRECATED("Use Bar instead") Foo;
//
// ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING
// Baz ComputeBazFromFoo(Foo f);
// ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING
#if defined(__GNUC__) || defined(__clang__)
// Clang also supports these GCC pragmas.
#define ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING \
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
#define ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING \
_Pragma("GCC diagnostic pop")
#elif defined(_MSC_VER)
#define ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING \
_Pragma("warning(push)") _Pragma("warning(disable: 4996)")
#define ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING \
_Pragma("warning(pop)")
#else
#define ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING
#define ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING
#endif // defined(__GNUC__) || defined(__clang__)
// ABSL_CONST_INIT
//
// A variable declaration annotated with the `ABSL_CONST_INIT` attribute will
// not compile (on supported platforms) unless the variable has a constant
// initializer. This is useful for variables with static and thread storage
// duration, because it guarantees that they will not suffer from the so-called
// "static init order fiasco".
//
// This attribute must be placed on the initializing declaration of the
// variable. Some compilers will give a -Wmissing-constinit warning when this
// attribute is placed on some other declaration but missing from the
// initializing declaration.
//
// In some cases (notably with thread_local variables), `ABSL_CONST_INIT` can
// also be used in a non-initializing declaration to tell the compiler that a
// variable is already initialized, reducing overhead that would otherwise be
// incurred by a hidden guard variable. Thus annotating all declarations with
// this attribute is recommended to potentially enhance optimization.
//
// Example:
//
// class MyClass {
// public:
// ABSL_CONST_INIT static MyType my_var;
// };
//
// ABSL_CONST_INIT MyType MyClass::my_var = MakeMyType(...);
//
// For code or headers that are assured to only build with C++20 and up, prefer
// just using the standard `constinit` keyword directly over this macro.
//
// Note that this attribute is redundant if the variable is declared constexpr.
#if defined(__cpp_constinit) && __cpp_constinit >= 201907L
#define ABSL_CONST_INIT constinit
#elif ABSL_HAVE_CPP_ATTRIBUTE(clang::require_constant_initialization)
#define ABSL_CONST_INIT [[clang::require_constant_initialization]]
#else
#define ABSL_CONST_INIT
#endif
// ABSL_REQUIRE_EXPLICIT_INIT
//
// ABSL_REQUIRE_EXPLICIT_INIT is placed *after* the data members of an aggregate
// type to indicate that the annotated member must be explicitly initialized by
// the user whenever the aggregate is constructed. For example:
//
// struct Coord {
// int x ABSL_REQUIRE_EXPLICIT_INIT;
// int y ABSL_REQUIRE_EXPLICIT_INIT;
// };
// Coord coord = {1}; // warning: field 'y' is not explicitly initialized
//
// Note that usage on C arrays is not supported in C++.
// Use a struct (such as std::array) to wrap the array member instead.
//
// Avoid applying this attribute to the members of non-aggregate types.
// The behavior within non-aggregates is unspecified and subject to change.
//
// Do NOT attempt to suppress or demote the error generated by this attribute.
// Just like with a missing function argument, it is a hard error by design.
//
// See the upstream documentation for more details:
// https://clang.llvm.org/docs/AttributeReference.html#require-explicit-initialization
#ifdef __cplusplus
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::require_explicit_initialization)
// clang-format off
#define ABSL_REQUIRE_EXPLICIT_INIT \
[[clang::require_explicit_initialization]] = \
AbslInternal_YouForgotToExplicitlyInitializeAField::v
#else
#define ABSL_REQUIRE_EXPLICIT_INIT \
= AbslInternal_YouForgotToExplicitlyInitializeAField::v
#endif
// clang-format on
#else
// clang-format off
#if ABSL_HAVE_ATTRIBUTE(require_explicit_initialization)
#define ABSL_REQUIRE_EXPLICIT_INIT \
__attribute__((require_explicit_initialization))
#else
#define ABSL_REQUIRE_EXPLICIT_INIT \
/* No portable fallback for C is available */
#endif
// clang-format on
#endif
#ifdef __cplusplus
struct AbslInternal_YouForgotToExplicitlyInitializeAField {
// A portable version of [[clang::require_explicit_initialization]] that
// never builds, as a last resort for all toolchains.
// The error messages are poor, so we don't rely on this unless we have to.
template <class T>
#if !defined(SWIG)
constexpr
#endif
operator T() const /* NOLINT */ {
const void *volatile deliberately_volatile_ptr = nullptr;
// Infinite loop to prevent constexpr compilation
for (;;) {
// This assignment ensures the 'this' pointer is not optimized away, so
// that linking always fails.
deliberately_volatile_ptr = this; // Deliberately not constexpr
(void)deliberately_volatile_ptr;
}
}
// This is deliberately left undefined to prevent linking
static AbslInternal_YouForgotToExplicitlyInitializeAField v;
};
#endif
// ABSL_ATTRIBUTE_PURE_FUNCTION
//
// ABSL_ATTRIBUTE_PURE_FUNCTION is used to annotate declarations of "pure"
// functions. A function is pure if its return value is only a function of its
// arguments. The pure attribute prohibits a function from modifying the state
// of the program that is observable by means other than inspecting the
// function's return value. Declaring such functions with the pure attribute
// allows the compiler to avoid emitting some calls in repeated invocations of
// the function with the same argument values.
//
// Example:
//
// ABSL_ATTRIBUTE_PURE_FUNCTION std::string FormatTime(Time t);
#if ABSL_HAVE_CPP_ATTRIBUTE(gnu::pure)
#define ABSL_ATTRIBUTE_PURE_FUNCTION [[gnu::pure]]
#elif ABSL_HAVE_ATTRIBUTE(pure)
#define ABSL_ATTRIBUTE_PURE_FUNCTION __attribute__((pure))
#else
// If the attribute isn't defined, we'll fallback to ABSL_MUST_USE_RESULT since
// pure functions are useless if its return is ignored.
#define ABSL_ATTRIBUTE_PURE_FUNCTION ABSL_MUST_USE_RESULT
#endif
// ABSL_ATTRIBUTE_CONST_FUNCTION
//
// ABSL_ATTRIBUTE_CONST_FUNCTION is used to annotate declarations of "const"
// functions. A const function is similar to a pure function, with one
// exception: Pure functions may return value that depend on a non-volatile
// object that isn't provided as a function argument, while the const function
// is guaranteed to return the same result given the same arguments.
//
// Example:
//
// ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToInt64Milliseconds(Duration d);
#if defined(_MSC_VER) && !defined(__clang__)
// Put the MSVC case first since MSVC seems to parse const as a C++ keyword.
#define ABSL_ATTRIBUTE_CONST_FUNCTION ABSL_ATTRIBUTE_PURE_FUNCTION
#elif ABSL_HAVE_CPP_ATTRIBUTE(gnu::const)
#define ABSL_ATTRIBUTE_CONST_FUNCTION [[gnu::const]]
#elif ABSL_HAVE_ATTRIBUTE(const)
#define ABSL_ATTRIBUTE_CONST_FUNCTION __attribute__((const))
#else
// Since const functions are more restrictive pure function, we'll fallback to a
// pure function if the const attribute is not handled.
#define ABSL_ATTRIBUTE_CONST_FUNCTION ABSL_ATTRIBUTE_PURE_FUNCTION
#endif
// ABSL_ATTRIBUTE_LIFETIME_BOUND indicates that a resource owned by a function
// parameter or implicit object parameter is retained by the return value of the
// annotated function (or, for a parameter of a constructor, in the value of the
// constructed object). This attribute causes warnings to be produced if a
// temporary object does not live long enough.
//
// When applied to a reference parameter, the referenced object is assumed to be
// retained by the return value of the function. When applied to a non-reference
// parameter (for example, a pointer or a class type), all temporaries
// referenced by the parameter are assumed to be retained by the return value of
// the function.
//
// See also the upstream documentation:
// https://clang.llvm.org/docs/AttributeReference.html#lifetimebound
// https://learn.microsoft.com/en-us/cpp/code-quality/c26816?view=msvc-170
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::lifetimebound)
#define ABSL_ATTRIBUTE_LIFETIME_BOUND [[clang::lifetimebound]]
#elif ABSL_HAVE_CPP_ATTRIBUTE(msvc::lifetimebound)
#define ABSL_ATTRIBUTE_LIFETIME_BOUND [[msvc::lifetimebound]]
#elif ABSL_HAVE_ATTRIBUTE(lifetimebound)
#define ABSL_ATTRIBUTE_LIFETIME_BOUND __attribute__((lifetimebound))
#else
#define ABSL_ATTRIBUTE_LIFETIME_BOUND
#endif
// Internal attribute; name and documentation TBD.
//
// See the upstream documentation:
// https://clang.llvm.org/docs/AttributeReference.html#lifetime_capture_by
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::lifetime_capture_by)
#define ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(Owner) \
[[clang::lifetime_capture_by(Owner)]]
#else
#define ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(Owner)
#endif
// ABSL_ATTRIBUTE_VIEW indicates that a type is solely a "view" of data that it
// points to, similarly to a span, string_view, or other non-owning reference
// type.
// This enables diagnosing certain lifetime issues similar to those enabled by
// ABSL_ATTRIBUTE_LIFETIME_BOUND, such as:
//
// struct ABSL_ATTRIBUTE_VIEW StringView {
// template<class R>
// StringView(const R&);
// };
//
// StringView f(std::string s) {
// return s; // warning: address of stack memory returned
// }
//
// We disable this on Clang versions < 13 because of the following
// false-positive:
//
// absl::string_view f(absl::optional<absl::string_view> sv) { return *sv; }
//
// See the following links for details:
// https://reviews.llvm.org/D64448
// https://lists.llvm.org/pipermail/cfe-dev/2018-November/060355.html
#if ABSL_HAVE_CPP_ATTRIBUTE(gsl::Pointer) && \
(!defined(__clang_major__) || __clang_major__ >= 13)
#define ABSL_ATTRIBUTE_VIEW [[gsl::Pointer]]
#else
#define ABSL_ATTRIBUTE_VIEW
#endif
// ABSL_ATTRIBUTE_OWNER indicates that a type is a container, smart pointer, or
// similar class that owns all the data that it points to.
// This enables diagnosing certain lifetime issues similar to those enabled by
// ABSL_ATTRIBUTE_LIFETIME_BOUND, such as:
//
// struct ABSL_ATTRIBUTE_VIEW StringView {
// template<class R>
// StringView(const R&);
// };
//
// struct ABSL_ATTRIBUTE_OWNER String {};
//
// StringView f(String s) {
// return s; // warning: address of stack memory returned
// }
//
// We disable this on Clang versions < 13 because of the following
// false-positive:
//
// absl::string_view f(absl::optional<absl::string_view> sv) { return *sv; }
//
// See the following links for details:
// https://reviews.llvm.org/D64448
// https://lists.llvm.org/pipermail/cfe-dev/2018-November/060355.html
#if ABSL_HAVE_CPP_ATTRIBUTE(gsl::Owner) && \
(!defined(__clang_major__) || __clang_major__ >= 13)
#define ABSL_ATTRIBUTE_OWNER [[gsl::Owner]]
#else
#define ABSL_ATTRIBUTE_OWNER
#endif
// ABSL_ATTRIBUTE_TRIVIAL_ABI
// Indicates that a type is "trivially relocatable" -- meaning it can be
// relocated without invoking the constructor/destructor, using a form of move
// elision.
//
// From a memory safety point of view, putting aside destructor ordering, it's
// safe to apply ABSL_ATTRIBUTE_TRIVIAL_ABI if an object's location
// can change over the course of its lifetime: if a constructor can be run one
// place, and then the object magically teleports to another place where some
// methods are run, and then the object teleports to yet another place where it
// is destroyed. This is notably not true for self-referential types, where the
// move-constructor must keep the self-reference up to date. If the type changed
// location without invoking the move constructor, it would have a dangling
// self-reference.
//
// The use of this teleporting machinery means that the number of paired
// move/destroy operations can change, and so it is a bad idea to apply this to
// a type meant to count the number of moves.
//
// Warning: applying this can, rarely, break callers. Objects passed by value
// will be destroyed at the end of the call, instead of the end of the
// full-expression containing the call. In addition, it changes the ABI
// of functions accepting this type by value (e.g. to pass in registers).
//
// See also the upstream documentation:
// https://clang.llvm.org/docs/AttributeReference.html#trivial-abi
//
// b/321691395 - This is currently disabled in open-source builds since
// compiler support differs. If system libraries compiled with GCC are mixed
// with libraries compiled with Clang, types will have different ideas about
// their ABI, leading to hard to debug crashes.
#define ABSL_ATTRIBUTE_TRIVIAL_ABI
// ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS
//
// Indicates a data member can be optimized to occupy no space (if it is empty)
// and/or its tail padding can be used for other members.
//
// For code that is assured to only build with C++20 or later, prefer using
// the standard attribute `[[no_unique_address]]` directly instead of this
// macro.
//
// https://devblogs.microsoft.com/cppblog/msvc-cpp20-and-the-std-cpp20-switch/#c20-no_unique_address
// Current versions of MSVC have disabled `[[no_unique_address]]` since it
// breaks ABI compatibility, but offers `[[msvc::no_unique_address]]` for
// situations when it can be assured that it is desired. Since Abseil does not
// claim ABI compatibility in mixed builds, we can offer it unconditionally.
#if defined(_MSC_VER) && _MSC_VER >= 1929
#define ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]]
#elif ABSL_HAVE_CPP_ATTRIBUTE(no_unique_address)
#define ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS [[no_unique_address]]
#else
#define ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS
#endif
// ABSL_ATTRIBUTE_UNINITIALIZED
//
// GCC and Clang support a flag `-ftrivial-auto-var-init=<option>` (<option>
// can be "zero" or "pattern") that can be used to initialize automatic stack
// variables. Variables with this attribute will be left uninitialized,
// overriding the compiler flag.
//
// See https://clang.llvm.org/docs/AttributeReference.html#uninitialized
// and https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-uninitialized-variable-attribute
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::uninitialized)
#define ABSL_ATTRIBUTE_UNINITIALIZED [[clang::uninitialized]]
#elif ABSL_HAVE_CPP_ATTRIBUTE(gnu::uninitialized)
#define ABSL_ATTRIBUTE_UNINITIALIZED [[gnu::uninitialized]]
#elif ABSL_HAVE_ATTRIBUTE(uninitialized)
#define ABSL_ATTRIBUTE_UNINITIALIZED __attribute__((uninitialized))
#else
#define ABSL_ATTRIBUTE_UNINITIALIZED
#endif
// ABSL_ATTRIBUTE_WARN_UNUSED
//
// Compilers routinely warn about trivial variables that are unused. For
// non-trivial types, this warning is suppressed since the
// constructor/destructor may be intentional and load-bearing, for example, with
// a RAII scoped lock.
//
// For example:
//
// class ABSL_ATTRIBUTE_WARN_UNUSED MyType {
// public:
// MyType();
// ~MyType();
// };
//
// void foo() {
// // Warns with ABSL_ATTRIBUTE_WARN_UNUSED attribute present.
// MyType unused;
// }
//
// See https://clang.llvm.org/docs/AttributeReference.html#warn-unused and
// https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html#index-warn_005funused-type-attribute
#if ABSL_HAVE_CPP_ATTRIBUTE(gnu::warn_unused)
#define ABSL_ATTRIBUTE_WARN_UNUSED [[gnu::warn_unused]]
#else
#define ABSL_ATTRIBUTE_WARN_UNUSED
#endif
#endif // ABSL_BASE_ATTRIBUTES_H_
*µq
xsoong/.intermediates/external/abseil-cpp/absl_log_internal_log_impl_hdrs/gen/my_include_dir/absl/log/internal/log_impl.h¸p// Copyright 2022 The Abseil Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_LOG_INTERNAL_LOG_IMPL_H_
#define ABSL_LOG_INTERNAL_LOG_IMPL_H_
#include "absl/log/absl_vlog_is_on.h"
#include "absl/log/internal/conditions.h"
#include "absl/log/internal/log_message.h"
#include "absl/log/internal/strip.h"
// ABSL_LOG()
#define ABSL_LOG_INTERNAL_LOG_IMPL(severity) \
ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, true) \
ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
// ABSL_PLOG()
#define ABSL_LOG_INTERNAL_PLOG_IMPL(severity) \
ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, true) \
ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() \
.WithPerror()
// ABSL_DLOG()
#ifndef NDEBUG
#define ABSL_LOG_INTERNAL_DLOG_IMPL(severity) \
ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, true) \
ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
#else
#define ABSL_LOG_INTERNAL_DLOG_IMPL(severity) \
ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, false) \
ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
#endif
// The `switch` ensures that this expansion is the beginning of a statement (as
// opposed to an expression). The use of both `case 0` and `default` is to
// suppress a compiler warning.
#define ABSL_LOG_INTERNAL_VLOG_IMPL(verbose_level) \
switch (const int absl_logging_internal_verbose_level = (verbose_level)) \
case 0: \
default: \
ABSL_LOG_INTERNAL_LOG_IF_IMPL( \
_INFO, ABSL_VLOG_IS_ON(absl_logging_internal_verbose_level)) \
.WithVerbosity(absl_logging_internal_verbose_level)
#ifndef NDEBUG
#define ABSL_LOG_INTERNAL_DVLOG_IMPL(verbose_level) \
switch (const int absl_logging_internal_verbose_level = (verbose_level)) \
case 0: \
default: \
ABSL_LOG_INTERNAL_DLOG_IF_IMPL( \
_INFO, ABSL_VLOG_IS_ON(absl_logging_internal_verbose_level)) \
.WithVerbosity(absl_logging_internal_verbose_level)
#else
#define ABSL_LOG_INTERNAL_DVLOG_IMPL(verbose_level) \
switch (const int absl_logging_internal_verbose_level = (verbose_level)) \
case 0: \
default: \
ABSL_LOG_INTERNAL_DLOG_IF_IMPL( \
_INFO, false && ABSL_VLOG_IS_ON(absl_logging_internal_verbose_level)) \
.WithVerbosity(absl_logging_internal_verbose_level)
#endif
#define ABSL_LOG_INTERNAL_LOG_IF_IMPL(severity, condition) \
ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, condition) \
ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
#define ABSL_LOG_INTERNAL_PLOG_IF_IMPL(severity, condition) \
ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, condition) \
ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() \
.WithPerror()
#ifndef NDEBUG
#define ABSL_LOG_INTERNAL_DLOG_IF_IMPL(severity, condition) \
ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, condition) \
ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
#else
#define ABSL_LOG_INTERNAL_DLOG_IF_IMPL(severity, condition) \
ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, false && (condition)) \
ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
#endif
// ABSL_LOG_EVERY_N
#define ABSL_LOG_INTERNAL_LOG_EVERY_N_IMPL(severity, n) \
ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, true)(EveryN, n) \
ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
// ABSL_LOG_FIRST_N
#define ABSL_LOG_INTERNAL_LOG_FIRST_N_IMPL(severity, n) \
ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, true)(FirstN, n) \
ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
// ABSL_LOG_EVERY_POW_2
#define ABSL_LOG_INTERNAL_LOG_EVERY_POW_2_IMPL(severity) \
ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, true)(EveryPow2) \
ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
// ABSL_LOG_EVERY_N_SEC
#define ABSL_LOG_INTERNAL_LOG_EVERY_N_SEC_IMPL(severity, n_seconds) \
ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, true)(EveryNSec, n_seconds) \
ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
#define ABSL_LOG_INTERNAL_PLOG_EVERY_N_IMPL(severity, n) \
ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, true)(EveryN, n) \
ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() \
.WithPerror()
#define ABSL_LOG_INTERNAL_PLOG_FIRST_N_IMPL(severity, n) \
ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, true)(FirstN, n) \
ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() \
.WithPerror()
#define ABSL_LOG_INTERNAL_PLOG_EVERY_POW_2_IMPL(severity) \
ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, true)(EveryPow2) \
ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() \
.WithPerror()
#define ABSL_LOG_INTERNAL_PLOG_EVERY_N_SEC_IMPL(severity, n_seconds) \
ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, true)(EveryNSec, n_seconds) \
ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() \
.WithPerror()
#ifndef NDEBUG
#define ABSL_LOG_INTERNAL_DLOG_EVERY_N_IMPL(severity, n) \
ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, true) \
(EveryN, n) ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
#define ABSL_LOG_INTERNAL_DLOG_FIRST_N_IMPL(severity, n) \
ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, true) \
(FirstN, n) ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
#define ABSL_LOG_INTERNAL_DLOG_EVERY_POW_2_IMPL(severity) \
ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, true) \
(EveryPow2) ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
#define ABSL_LOG_INTERNAL_DLOG_EVERY_N_SEC_IMPL(severity, n_seconds) \
ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, true) \
(EveryNSec, n_seconds) ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
#else // def NDEBUG
#define ABSL_LOG_INTERNAL_DLOG_EVERY_N_IMPL(severity, n) \
ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, false) \
(EveryN, n) ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
#define ABSL_LOG_INTERNAL_DLOG_FIRST_N_IMPL(severity, n) \
ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, false) \
(FirstN, n) ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
#define ABSL_LOG_INTERNAL_DLOG_EVERY_POW_2_IMPL(severity) \
ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, false) \
(EveryPow2) ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
#define ABSL_LOG_INTERNAL_DLOG_EVERY_N_SEC_IMPL(severity, n_seconds) \
ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, false) \
(EveryNSec, n_seconds) ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
#endif // def NDEBUG
#define ABSL_LOG_INTERNAL_VLOG_EVERY_N_IMPL(verbose_level, n) \
switch (const int absl_logging_internal_verbose_level = (verbose_level)) \
case 0: \
default: \
ABSL_LOG_INTERNAL_CONDITION_INFO( \
STATEFUL, ABSL_VLOG_IS_ON(absl_logging_internal_verbose_level)) \
(EveryN, n) ABSL_LOGGING_INTERNAL_LOG_INFO.InternalStream().WithVerbosity( \
absl_logging_internal_verbose_level)
#define ABSL_LOG_INTERNAL_VLOG_FIRST_N_IMPL(verbose_level, n) \
switch (const int absl_logging_internal_verbose_level = (verbose_level)) \
case 0: \
default: \
ABSL_LOG_INTERNAL_CONDITION_INFO( \
STATEFUL, ABSL_VLOG_IS_ON(absl_logging_internal_verbose_level)) \
(FirstN, n) ABSL_LOGGING_INTERNAL_LOG_INFO.InternalStream().WithVerbosity( \
absl_logging_internal_verbose_level)
#define ABSL_LOG_INTERNAL_VLOG_EVERY_POW_2_IMPL(verbose_level) \
switch (const int absl_logging_internal_verbose_level = (verbose_level)) \
case 0: \
default: \
ABSL_LOG_INTERNAL_CONDITION_INFO( \
STATEFUL, ABSL_VLOG_IS_ON(absl_logging_internal_verbose_level)) \
(EveryPow2) ABSL_LOGGING_INTERNAL_LOG_INFO.InternalStream().WithVerbosity( \
absl_logging_internal_verbose_level)
#define ABSL_LOG_INTERNAL_VLOG_EVERY_N_SEC_IMPL(verbose_level, n_seconds) \
switch (const int absl_logging_internal_verbose_level = (verbose_level)) \
case 0: \
default: \
ABSL_LOG_INTERNAL_CONDITION_INFO( \
STATEFUL, ABSL_VLOG_IS_ON(absl_logging_internal_verbose_level)) \
(EveryNSec, n_seconds) ABSL_LOGGING_INTERNAL_LOG_INFO.InternalStream() \
.WithVerbosity(absl_logging_internal_verbose_level)
#define ABSL_LOG_INTERNAL_LOG_IF_EVERY_N_IMPL(severity, condition, n) \
ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryN, n) \
ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
#define ABSL_LOG_INTERNAL_LOG_IF_FIRST_N_IMPL(severity, condition, n) \
ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(FirstN, n) \
ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
#define ABSL_LOG_INTERNAL_LOG_IF_EVERY_POW_2_IMPL(severity, condition) \
ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryPow2) \
ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
#define ABSL_LOG_INTERNAL_LOG_IF_EVERY_N_SEC_IMPL(severity, condition, \
n_seconds) \
ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryNSec, \
n_seconds) \
ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
#define ABSL_LOG_INTERNAL_PLOG_IF_EVERY_N_IMPL(severity, condition, n) \
ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryN, n) \
ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() \
.WithPerror()
#define ABSL_LOG_INTERNAL_PLOG_IF_FIRST_N_IMPL(severity, condition, n) \
ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(FirstN, n) \
ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() \
.WithPerror()
#define ABSL_LOG_INTERNAL_PLOG_IF_EVERY_POW_2_IMPL(severity, condition) \
ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryPow2) \
ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() \
.WithPerror()
#define ABSL_LOG_INTERNAL_PLOG_IF_EVERY_N_SEC_IMPL(severity, condition, \
n_seconds) \
ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryNSec, \
n_seconds) \
ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() \
.WithPerror()
#ifndef NDEBUG
#define ABSL_LOG_INTERNAL_DLOG_IF_EVERY_N_IMPL(severity, condition, n) \
ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryN, n) \
ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
#define ABSL_LOG_INTERNAL_DLOG_IF_FIRST_N_IMPL(severity, condition, n) \
ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(FirstN, n) \
ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
#define ABSL_LOG_INTERNAL_DLOG_IF_EVERY_POW_2_IMPL(severity, condition) \
ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryPow2) \
ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
#define ABSL_LOG_INTERNAL_DLOG_IF_EVERY_N_SEC_IMPL(severity, condition, \
n_seconds) \
ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryNSec, \
n_seconds) \
ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
#else // def NDEBUG
#define ABSL_LOG_INTERNAL_DLOG_IF_EVERY_N_IMPL(severity, condition, n) \
ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, false && (condition))( \
EveryN, n) ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
#define ABSL_LOG_INTERNAL_DLOG_IF_FIRST_N_IMPL(severity, condition, n) \
ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, false && (condition))( \
FirstN, n) ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
#define ABSL_LOG_INTERNAL_DLOG_IF_EVERY_POW_2_IMPL(severity, condition) \
ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, false && (condition))( \
EveryPow2) ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
#define ABSL_LOG_INTERNAL_DLOG_IF_EVERY_N_SEC_IMPL(severity, condition, \
n_seconds) \
ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, false && (condition))( \
EveryNSec, n_seconds) \
ABSL_LOGGING_INTERNAL_DLOG##severity.InternalStream()
#endif // def NDEBUG
#endif // ABSL_LOG_INTERNAL_LOG_IMPL_H_
*Ñ"
ksoong/.intermediates/external/abseil-cpp/absl_base_config_hdrs/gen/my_include_dir/absl/base/policy_checks.há!// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: policy_checks.h
// -----------------------------------------------------------------------------
//
// This header enforces a minimum set of policies at build time, such as the
// supported compiler and library versions. Unsupported configurations are
// reported with `#error`. This enforcement is best effort, so successfully
// compiling this header does not guarantee a supported configuration.
// SKIP_ABSL_INLINE_NAMESPACE_CHECK
#ifndef ABSL_BASE_POLICY_CHECKS_H_
#define ABSL_BASE_POLICY_CHECKS_H_
// Included for the __GLIBC_PREREQ macro used below.
#include <limits.h>
// Included for the _STLPORT_VERSION macro used below.
#if defined(__cplusplus)
#include <cstddef>
#endif
// -----------------------------------------------------------------------------
// Operating System Check
// -----------------------------------------------------------------------------
#if defined(__CYGWIN__)
#error "Cygwin is not supported."
#endif
// -----------------------------------------------------------------------------
// Toolchain Check
// -----------------------------------------------------------------------------
// We support Visual Studio 2019 (MSVC++ 16.0) and later.
// This minimum will go up.
#if defined(_MSC_VER) && _MSC_VER < 1920 && !defined(__clang__)
#error "This package requires Visual Studio 2019 (MSVC++ 16.0) or higher."
#endif
// We support GCC 7 and later.
// This minimum will go up.
#if defined(__GNUC__) && !defined(__clang__)
#if __GNUC__ < 7
#error "This package requires GCC 7 or higher."
#endif
#endif
// We support Apple Xcode clang 4.2.1 (version 421.11.65) and later.
// This corresponds to Apple Xcode version 4.5.
// This minimum will go up.
#if defined(__apple_build_version__) && __apple_build_version__ < 4211165
#error "This package requires __apple_build_version__ of 4211165 or higher."
#endif
// -----------------------------------------------------------------------------
// C++ Version Check
// -----------------------------------------------------------------------------
// Enforce C++17 as the minimum.
#if defined(_MSVC_LANG)
#if _MSVC_LANG < 201703L
#error "C++ versions less than C++17 are not supported."
#endif // _MSVC_LANG < 201703L
#elif defined(__cplusplus)
#if __cplusplus < 201703L
#error "C++ versions less than C++17 are not supported."
#endif // __cplusplus < 201703L
#endif
// -----------------------------------------------------------------------------
// Standard Library Check
// -----------------------------------------------------------------------------
#if defined(_STLPORT_VERSION)
#error "STLPort is not supported."
#endif
// -----------------------------------------------------------------------------
// `char` Size Check
// -----------------------------------------------------------------------------
// Abseil currently assumes CHAR_BIT == 8. If you would like to use Abseil on a
// platform where this is not the case, please provide us with the details about
// your platform so we can consider relaxing this requirement.
#if CHAR_BIT != 8
#error "Abseil assumes CHAR_BIT == 8."
#endif
// -----------------------------------------------------------------------------
// `int` Size Check
// -----------------------------------------------------------------------------
// Abseil currently assumes that an int is 4 bytes. If you would like to use
// Abseil on a platform where this is not the case, please provide us with the
// details about your platform so we can consider relaxing this requirement.
#if INT_MAX < 2147483647
#error "Abseil assumes that int is at least 4 bytes. "
#endif
#endif // ABSL_BASE_POLICY_CHECKS_H_
*I
esoong/.intermediates/external/abseil-cpp/absl_base_config_hdrs/gen/my_include_dir/absl/base/options.h¥H// Copyright 2019 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: options.h
// -----------------------------------------------------------------------------
//
// This file contains Abseil configuration options for setting specific
// implementations instead of letting Abseil determine which implementation to
// use at compile-time. Setting these options may be useful for package or build
// managers who wish to guarantee ABI stability within binary builds (which are
// otherwise difficult to enforce).
//
// *** IMPORTANT NOTICE FOR PACKAGE MANAGERS: It is important that
// maintainers of package managers who wish to package Abseil read and
// understand this file! ***
//
// Abseil contains a number of possible configuration endpoints, based on
// parameters such as the detected platform, language version, or command-line
// flags used to invoke the underlying binary. As is the case with all
// libraries, binaries which contain Abseil code must ensure that separate
// packages use the same compiled copy of Abseil to avoid a diamond dependency
// problem, which can occur if two packages built with different Abseil
// configuration settings are linked together. Diamond dependency problems in
// C++ may manifest as violations to the One Definition Rule (ODR) (resulting in
// linker errors), or undefined behavior (resulting in crashes).
//
// Diamond dependency problems can be avoided if all packages utilize the same
// exact version of Abseil. Building from source code with the same compilation
// parameters is the easiest way to avoid such dependency problems. However, for
// package managers who cannot control such compilation parameters, we are
// providing the file to allow you to inject ABI (Application Binary Interface)
// stability across builds. Settings options in this file will neither change
// API nor ABI, providing a stable copy of Abseil between packages.
//
// Care must be taken to keep options within these configurations isolated
// from any other dynamic settings, such as command-line flags which could alter
// these options. This file is provided specifically to help build and package
// managers provide a stable copy of Abseil within their libraries and binaries;
// other developers should not have need to alter the contents of this file.
//
// -----------------------------------------------------------------------------
// Usage
// -----------------------------------------------------------------------------
//
// For any particular package release, set the appropriate definitions within
// this file to whatever value makes the most sense for your package(s). Note
// that, by default, most of these options, at the moment, affect the
// implementation of types; future options may affect other implementation
// details.
//
// NOTE: the defaults within this file all assume that Abseil can select the
// proper Abseil implementation at compile-time, which will not be sufficient
// to guarantee ABI stability to package managers.
// SKIP_ABSL_INLINE_NAMESPACE_CHECK
#ifndef ABSL_BASE_OPTIONS_H_
#define ABSL_BASE_OPTIONS_H_
// -----------------------------------------------------------------------------
// Type Compatibility Options
// -----------------------------------------------------------------------------
// ABSL_OPTION_USE_STD_STRING_VIEW
//
// This option controls whether absl::string_view is implemented as an alias to
// std::string_view, or as an independent implementation.
//
// A value of 0 means to use Abseil's implementation. This requires only C++11
// support, and is expected to work on every toolchain we support.
//
// A value of 1 means to use an alias to std::string_view. This requires that
// all code using Abseil is built in C++17 mode or later.
//
// A value of 2 means to detect the C++ version being used to compile Abseil,
// and use an alias only if a working std::string_view is available. This
// option is useful when you are building your program from source. It should
// not be used otherwise -- for example, if you are distributing Abseil in a
// binary package manager -- since in mode 2, absl::string_view will name a
// different type, with a different mangled name and binary layout, depending on
// the compiler flags passed by the end user. For more info, see
// https://abseil.io/about/design/dropin-types.
//
// User code should not inspect this macro. To check in the preprocessor if
// absl::string_view is a typedef of std::string_view, use the feature macro
// ABSL_USES_STD_STRING_VIEW.
#define ABSL_OPTION_USE_STD_STRING_VIEW 1
// ABSL_OPTION_USE_STD_ORDERING
//
// This option controls whether absl::{partial,weak,strong}_ordering are
// implemented as aliases to the std:: ordering types, or as an independent
// implementation.
//
// A value of 0 means to use Abseil's implementation. This requires only C++11
// support, and is expected to work on every toolchain we support.
//
// A value of 1 means to use aliases. This requires that all code using Abseil
// is built in C++20 mode or later.
//
// A value of 2 means to detect the C++ version being used to compile Abseil,
// and use an alias only if working std:: ordering types are available. This
// option is useful when you are building your program from source. It should
// not be used otherwise -- for example, if you are distributing Abseil in a
// binary package manager -- since in mode 2, they will name different types,
// with different mangled names and binary layout, depending on the compiler
// flags passed by the end user. For more info, see
// https://abseil.io/about/design/dropin-types.
//
// User code should not inspect this macro. To check in the preprocessor if
// the ordering types are aliases of std:: ordering types, use the feature macro
// ABSL_USES_STD_ORDERING.
#define ABSL_OPTION_USE_STD_ORDERING 2
// ABSL_OPTION_USE_INLINE_NAMESPACE
// ABSL_OPTION_INLINE_NAMESPACE_NAME
//
// These options controls whether all entities in the absl namespace are
// contained within an inner inline namespace. This does not affect the
// user-visible API of Abseil, but it changes the mangled names of all symbols.
//
// This can be useful as a version tag if you are distributing Abseil in
// precompiled form. This will prevent a binary library build of Abseil with
// one inline namespace being used with headers configured with a different
// inline namespace name. Binary packagers are reminded that Abseil does not
// guarantee any ABI stability in Abseil, so any update of Abseil or
// configuration change in such a binary package should be combined with a
// new, unique value for the inline namespace name.
//
// A value of 0 means not to use inline namespaces.
//
// A value of 1 means to use an inline namespace with the given name inside
// namespace absl. If this is set, ABSL_OPTION_INLINE_NAMESPACE_NAME must also
// be changed to a new, unique identifier name. In particular "head" is not
// allowed.
#define ABSL_OPTION_USE_INLINE_NAMESPACE 1
#ifdef ANDROID_DISABLE_TLS_FOR_LINKER
#define ABSL_OPTION_INLINE_NAMESPACE_NAME lts_20250512_notls
#else
#define ABSL_OPTION_INLINE_NAMESPACE_NAME lts_20250512
#endif
// ABSL_OPTION_HARDENED
//
// This option enables a "hardened" build in release mode (in this context,
// release mode is defined as a build where the `NDEBUG` macro is defined).
//
// A value of 0 means that "hardened" mode is not enabled.
//
// A value of 1 means that "hardened" mode is enabled with all checks.
//
// A value of 2 means that "hardened" mode is partially enabled, with
// only a subset of checks chosen to minimize performance impact.
//
// Hardened builds have additional security checks enabled when `NDEBUG` is
// defined. Defining `NDEBUG` is normally used to turn `assert()` macro into a
// no-op, as well as disabling other bespoke program consistency checks. By
// defining ABSL_OPTION_HARDENED to 1, a select set of checks remain enabled in
// release mode. These checks guard against programming errors that may lead to
// security vulnerabilities. In release mode, when one of these programming
// errors is encountered, the program will immediately abort, possibly without
// any attempt at logging.
//
// The checks enabled by this option are not free; they do incur runtime cost.
//
// The checks enabled by this option are always active when `NDEBUG` is not
// defined, even in the case when ABSL_OPTION_HARDENED is defined to 0. The
// checks enabled by this option may abort the program in a different way and
// log additional information when `NDEBUG` is not defined.
#define ABSL_OPTION_HARDENED 0
#endif // ABSL_BASE_OPTIONS_H_
*׆
dsoong/.intermediates/external/abseil-cpp/absl_base_config_hdrs/gen/my_include_dir/absl/base/config.hí…//
// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: config.h
// -----------------------------------------------------------------------------
//
// This header file defines a set of macros for checking the presence of
// important compiler and platform features. Such macros can be used to
// produce portable code by parameterizing compilation based on the presence or
// lack of a given feature.
//
// We define a "feature" as some interface we wish to program to: for example,
// a library function or system call. A value of `1` indicates support for
// that feature; any other value indicates the feature support is undefined.
//
// Example:
//
// Suppose a programmer wants to write a program that uses the 'mmap()' system
// call. The Abseil macro for that feature (`ABSL_HAVE_MMAP`) allows you to
// selectively include the `mmap.h` header and bracket code using that feature
// in the macro:
//
// #include "absl/base/config.h"
//
// #ifdef ABSL_HAVE_MMAP
// #include "sys/mman.h"
// #endif //ABSL_HAVE_MMAP
//
// ...
// #ifdef ABSL_HAVE_MMAP
// void *ptr = mmap(...);
// ...
// #endif // ABSL_HAVE_MMAP
#ifndef ABSL_BASE_CONFIG_H_
#define ABSL_BASE_CONFIG_H_
// Included for the __GLIBC__ macro (or similar macros on other systems).
#include <limits.h>
#ifdef __cplusplus
// Included for __GLIBCXX__, _LIBCPP_VERSION
#include <cstddef>
#endif // __cplusplus
// ABSL_INTERNAL_CPLUSPLUS_LANG
//
// MSVC does not set the value of __cplusplus correctly, but instead uses
// _MSVC_LANG as a stand-in.
// https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros
//
// However, there are reports that MSVC even sets _MSVC_LANG incorrectly at
// times, for example:
// https://github.com/microsoft/vscode-cpptools/issues/1770
// https://reviews.llvm.org/D70996
//
// For this reason, this symbol is considered INTERNAL and code outside of
// Abseil must not use it.
#if defined(_MSVC_LANG)
#define ABSL_INTERNAL_CPLUSPLUS_LANG _MSVC_LANG
#elif defined(__cplusplus)
#define ABSL_INTERNAL_CPLUSPLUS_LANG __cplusplus
#endif
#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
// Include library feature test macros.
#include <version>
#endif
#if defined(__APPLE__)
// Included for TARGET_OS_IPHONE, __IPHONE_OS_VERSION_MIN_REQUIRED,
// __IPHONE_8_0.
#include <Availability.h>
#include <TargetConditionals.h>
#endif
#include "absl/base/options.h"
#include "absl/base/policy_checks.h"
// Abseil long-term support (LTS) releases will define
// `ABSL_LTS_RELEASE_VERSION` to the integer representing the date string of the
// LTS release version, and will define `ABSL_LTS_RELEASE_PATCH_LEVEL` to the
// integer representing the patch-level for that release.
//
// For example, for LTS release version "20300401.2", this would give us
// ABSL_LTS_RELEASE_VERSION == 20300401 && ABSL_LTS_RELEASE_PATCH_LEVEL == 2
//
// These symbols will not be defined in non-LTS code.
//
// Abseil recommends that clients live-at-head. Therefore, if you are using
// these symbols to assert a minimum version requirement, we recommend you do it
// as
//
// #if defined(ABSL_LTS_RELEASE_VERSION) && ABSL_LTS_RELEASE_VERSION < 20300401
// #error Project foo requires Abseil LTS version >= 20300401
// #endif
//
// The `defined(ABSL_LTS_RELEASE_VERSION)` part of the check excludes
// live-at-head clients from the minimum version assertion.
//
// See https://abseil.io/about/releases for more information on Abseil release
// management.
//
// LTS releases can be obtained from
// https://github.com/abseil/abseil-cpp/releases.
#define ABSL_LTS_RELEASE_VERSION 20250512
#define ABSL_LTS_RELEASE_PATCH_LEVEL 1
// Helper macro to convert a CPP variable to a string literal.
#define ABSL_INTERNAL_DO_TOKEN_STR(x) #x
#define ABSL_INTERNAL_TOKEN_STR(x) ABSL_INTERNAL_DO_TOKEN_STR(x)
// -----------------------------------------------------------------------------
// Abseil namespace annotations
// -----------------------------------------------------------------------------
// ABSL_NAMESPACE_BEGIN/ABSL_NAMESPACE_END
//
// An annotation placed at the beginning/end of each `namespace absl` scope.
// This is used to inject an inline namespace.
//
// The proper way to write Abseil code in the `absl` namespace is:
//
// namespace absl {
// ABSL_NAMESPACE_BEGIN
//
// void Foo(); // absl::Foo().
//
// ABSL_NAMESPACE_END
// } // namespace absl
//
// Users of Abseil should not use these macros, because users of Abseil should
// not write `namespace absl {` in their own code for any reason. (Abseil does
// not support forward declarations of its own types, nor does it support
// user-provided specialization of Abseil templates. Code that violates these
// rules may be broken without warning.)
#if !defined(ABSL_OPTION_USE_INLINE_NAMESPACE) || \
!defined(ABSL_OPTION_INLINE_NAMESPACE_NAME)
#error options.h is misconfigured.
#endif
// Check that ABSL_OPTION_INLINE_NAMESPACE_NAME is neither "head" nor ""
#if defined(__cplusplus) && ABSL_OPTION_USE_INLINE_NAMESPACE == 1
#define ABSL_INTERNAL_INLINE_NAMESPACE_STR \
ABSL_INTERNAL_TOKEN_STR(ABSL_OPTION_INLINE_NAMESPACE_NAME)
static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != '\0',
"options.h misconfigured: ABSL_OPTION_INLINE_NAMESPACE_NAME must "
"not be empty.");
static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
ABSL_INTERNAL_INLINE_NAMESPACE_STR[1] != 'e' ||
ABSL_INTERNAL_INLINE_NAMESPACE_STR[2] != 'a' ||
ABSL_INTERNAL_INLINE_NAMESPACE_STR[3] != 'd' ||
ABSL_INTERNAL_INLINE_NAMESPACE_STR[4] != '\0',
"options.h misconfigured: ABSL_OPTION_INLINE_NAMESPACE_NAME must "
"be changed to a new, unique identifier name.");
#endif
#if ABSL_OPTION_USE_INLINE_NAMESPACE == 0
#define ABSL_NAMESPACE_BEGIN
#define ABSL_NAMESPACE_END
#define ABSL_INTERNAL_C_SYMBOL(x) x
#elif ABSL_OPTION_USE_INLINE_NAMESPACE == 1
#define ABSL_NAMESPACE_BEGIN \
inline namespace ABSL_OPTION_INLINE_NAMESPACE_NAME {
#define ABSL_NAMESPACE_END }
#define ABSL_INTERNAL_C_SYMBOL_HELPER_2(x, v) x##_##v
#define ABSL_INTERNAL_C_SYMBOL_HELPER_1(x, v) \
ABSL_INTERNAL_C_SYMBOL_HELPER_2(x, v)
#define ABSL_INTERNAL_C_SYMBOL(x) \
ABSL_INTERNAL_C_SYMBOL_HELPER_1(x, ABSL_OPTION_INLINE_NAMESPACE_NAME)
#else
#error options.h is misconfigured.
#endif
// -----------------------------------------------------------------------------
// Compiler Feature Checks
// -----------------------------------------------------------------------------
// ABSL_HAVE_BUILTIN()
//
// Checks whether the compiler supports a Clang Feature Checking Macro, and if
// so, checks whether it supports the provided builtin function "x" where x
// is one of the functions noted in
// https://clang.llvm.org/docs/LanguageExtensions.html
//
// Note: Use this macro to avoid an extra level of #ifdef __has_builtin check.
// http://releases.llvm.org/3.3/tools/clang/docs/LanguageExtensions.html
#ifdef __has_builtin
#define ABSL_HAVE_BUILTIN(x) __has_builtin(x)
#else
#define ABSL_HAVE_BUILTIN(x) 0
#endif
#ifdef __has_feature
#define ABSL_HAVE_FEATURE(f) __has_feature(f)
#else
#define ABSL_HAVE_FEATURE(f) 0
#endif
// Portable check for GCC minimum version:
// https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
#if defined(__GNUC__) && defined(__GNUC_MINOR__)
#define ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(x, y) \
(__GNUC__ > (x) || __GNUC__ == (x) && __GNUC_MINOR__ >= (y))
#else
#define ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(x, y) 0
#endif
#if defined(__clang__) && defined(__clang_major__) && defined(__clang_minor__)
#define ABSL_INTERNAL_HAVE_MIN_CLANG_VERSION(x, y) \
(__clang_major__ > (x) || __clang_major__ == (x) && __clang_minor__ >= (y))
#else
#define ABSL_INTERNAL_HAVE_MIN_CLANG_VERSION(x, y) 0
#endif
// ABSL_HAVE_TLS is defined to 1 when __thread should be supported.
// We assume __thread is supported on Linux when compiled with Clang or
// compiled against libstdc++ with _GLIBCXX_HAVE_TLS defined.
#ifdef ABSL_HAVE_TLS
#error ABSL_HAVE_TLS cannot be directly set
#elif (defined(__linux__)) && (defined(__clang__) || defined(_GLIBCXX_HAVE_TLS))
#define ABSL_HAVE_TLS 1
#endif
// ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE
//
// Checks whether `std::is_trivially_destructible<T>` is supported.
#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE
#error ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE cannot be directly set
#define ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE 1
#endif
// ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
//
// Checks whether `std::is_trivially_default_constructible<T>` and
// `std::is_trivially_copy_constructible<T>` are supported.
#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
#error ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE cannot be directly set
#else
#define ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE 1
#endif
// ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
//
// Checks whether `std::is_trivially_copy_assignable<T>` is supported.
#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
#error ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE cannot be directly set
#else
#define ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE 1
#endif
// ABSL_HAVE_STD_IS_TRIVIALLY_COPYABLE
//
// Checks whether `std::is_trivially_copyable<T>` is supported.
#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_COPYABLE
#error ABSL_HAVE_STD_IS_TRIVIALLY_COPYABLE cannot be directly set
#define ABSL_HAVE_STD_IS_TRIVIALLY_COPYABLE 1
#endif
// ABSL_HAVE_THREAD_LOCAL
//
// Checks whether the `thread_local` storage duration specifier is supported.
#ifdef ABSL_HAVE_THREAD_LOCAL
#error ABSL_HAVE_THREAD_LOCAL cannot be directly set
#elif !defined(__XTENSA__) && !defined(ANDROID_DISABLE_TLS_FOR_LINKER)
#define ABSL_HAVE_THREAD_LOCAL 1
#endif
// ABSL_HAVE_INTRINSIC_INT128
//
// Checks whether the __int128 compiler extension for a 128-bit integral type is
// supported.
//
// Note: __SIZEOF_INT128__ is defined by Clang and GCC when __int128 is
// supported, but we avoid using it in certain cases:
// * On Clang:
// * Building using Clang for Windows, where the Clang runtime library has
// 128-bit support only on LP64 architectures, but Windows is LLP64.
// * On Nvidia's nvcc:
// * nvcc also defines __GNUC__ and __SIZEOF_INT128__, but not all versions
// actually support __int128.
#ifdef ABSL_HAVE_INTRINSIC_INT128
#error ABSL_HAVE_INTRINSIC_INT128 cannot be directly set
#elif defined(__SIZEOF_INT128__)
#if (defined(__clang__) && !defined(_WIN32)) || \
(defined(__CUDACC__) && __CUDACC_VER_MAJOR__ >= 9) || \
(defined(__GNUC__) && !defined(__clang__) && !defined(__CUDACC__))
#define ABSL_HAVE_INTRINSIC_INT128 1
#elif defined(__CUDACC__)
// __CUDACC_VER__ is a full version number before CUDA 9, and is defined to a
// string explaining that it has been removed starting with CUDA 9. We use
// nested #ifs because there is no short-circuiting in the preprocessor.
// NOTE: `__CUDACC__` could be undefined while `__CUDACC_VER__` is defined.
#if __CUDACC_VER__ >= 70000
#define ABSL_HAVE_INTRINSIC_INT128 1
#endif // __CUDACC_VER__ >= 70000
#endif // defined(__CUDACC__)
#endif // ABSL_HAVE_INTRINSIC_INT128
// ABSL_HAVE_EXCEPTIONS
//
// Checks whether the compiler both supports and enables exceptions. Many
// compilers support a "no exceptions" mode that disables exceptions.
//
// Generally, when ABSL_HAVE_EXCEPTIONS is not defined:
//
// * Code using `throw` and `try` may not compile.
// * The `noexcept` specifier will still compile and behave as normal.
// * The `noexcept` operator may still return `false`.
//
// For further details, consult the compiler's documentation.
#ifdef ABSL_HAVE_EXCEPTIONS
#error ABSL_HAVE_EXCEPTIONS cannot be directly set.
#elif ABSL_INTERNAL_HAVE_MIN_CLANG_VERSION(3, 6)
// Clang >= 3.6
#if ABSL_HAVE_FEATURE(cxx_exceptions)
#define ABSL_HAVE_EXCEPTIONS 1
#endif // ABSL_HAVE_FEATURE(cxx_exceptions)
#elif defined(__clang__)
// Clang < 3.6
// http://releases.llvm.org/3.6.0/tools/clang/docs/ReleaseNotes.html#the-exceptions-macro
#if defined(__EXCEPTIONS) && ABSL_HAVE_FEATURE(cxx_exceptions)
#define ABSL_HAVE_EXCEPTIONS 1
#endif // defined(__EXCEPTIONS) && ABSL_HAVE_FEATURE(cxx_exceptions)
// Handle remaining special cases and default to exceptions being supported.
#elif !(defined(__GNUC__) && !defined(__cpp_exceptions)) && \
!(defined(_MSC_VER) && !defined(_CPPUNWIND))
#define ABSL_HAVE_EXCEPTIONS 1
#endif
// -----------------------------------------------------------------------------
// Platform Feature Checks
// -----------------------------------------------------------------------------
// Currently supported operating systems and associated preprocessor
// symbols:
//
// Linux and Linux-derived __linux__
// Android __ANDROID__ (implies __linux__)
// Linux (non-Android) __linux__ && !__ANDROID__
// Darwin (macOS and iOS) __APPLE__
// Akaros (http://akaros.org) __ros__
// Windows _WIN32
// NaCL __native_client__
// AsmJS __asmjs__
// WebAssembly (Emscripten) __EMSCRIPTEN__
// Fuchsia __Fuchsia__
//
// Note that since Android defines both __ANDROID__ and __linux__, one
// may probe for either Linux or Android by simply testing for __linux__.
// ABSL_HAVE_MMAP
//
// Checks whether the platform has an mmap(2) implementation as defined in
// POSIX.1-2001.
#ifdef ABSL_HAVE_MMAP
#error ABSL_HAVE_MMAP cannot be directly set
#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
defined(_AIX) || defined(__ros__) || defined(__native_client__) || \
defined(__asmjs__) || defined(__EMSCRIPTEN__) || defined(__Fuchsia__) || \
defined(__sun) || defined(__myriad2__) || defined(__HAIKU__) || \
defined(__OpenBSD__) || defined(__NetBSD__) || defined(__QNX__) || \
defined(__VXWORKS__) || defined(__hexagon__) || defined(__XTENSA__)
#define ABSL_HAVE_MMAP 1
#endif
// ABSL_HAVE_PTHREAD_GETSCHEDPARAM
//
// Checks whether the platform implements the pthread_(get|set)schedparam(3)
// functions as defined in POSIX.1-2001.
#ifdef ABSL_HAVE_PTHREAD_GETSCHEDPARAM
#error ABSL_HAVE_PTHREAD_GETSCHEDPARAM cannot be directly set
#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
defined(_AIX) || defined(__ros__) || defined(__OpenBSD__) || \
defined(__NetBSD__) || defined(__VXWORKS__)
#define ABSL_HAVE_PTHREAD_GETSCHEDPARAM 1
#endif
// ABSL_HAVE_SCHED_GETCPU
//
// Checks whether sched_getcpu is available.
#ifdef ABSL_HAVE_SCHED_GETCPU
#error ABSL_HAVE_SCHED_GETCPU cannot be directly set
#elif defined(__linux__)
#define ABSL_HAVE_SCHED_GETCPU 1
#endif
// ABSL_HAVE_SCHED_YIELD
//
// Checks whether the platform implements sched_yield(2) as defined in
// POSIX.1-2001.
#ifdef ABSL_HAVE_SCHED_YIELD
#error ABSL_HAVE_SCHED_YIELD cannot be directly set
#elif defined(__linux__) || defined(__ros__) || defined(__native_client__) || \
defined(__VXWORKS__)
#define ABSL_HAVE_SCHED_YIELD 1
#endif
// ABSL_HAVE_SEMAPHORE_H
//
// Checks whether the platform supports the <semaphore.h> header and sem_init(3)
// family of functions as standardized in POSIX.1-2001.
//
// Note: While Apple provides <semaphore.h> for both iOS and macOS, it is
// explicitly deprecated and will cause build failures if enabled for those
// platforms. We side-step the issue by not defining it here for Apple
// platforms.
#ifdef ABSL_HAVE_SEMAPHORE_H
#error ABSL_HAVE_SEMAPHORE_H cannot be directly set
#elif defined(__linux__) || defined(__ros__) || defined(__VXWORKS__)
#define ABSL_HAVE_SEMAPHORE_H 1
#endif
// ABSL_HAVE_ALARM
//
// Checks whether the platform supports the <signal.h> header and alarm(2)
// function as standardized in POSIX.1-2001.
#ifdef ABSL_HAVE_ALARM
#error ABSL_HAVE_ALARM cannot be directly set
#elif defined(__GOOGLE_GRTE_VERSION__)
// feature tests for Google's GRTE
#define ABSL_HAVE_ALARM 1
#elif defined(__GLIBC__)
// feature test for glibc
#define ABSL_HAVE_ALARM 1
#elif defined(_MSC_VER)
// feature tests for Microsoft's library
#elif defined(__MINGW32__)
// mingw32 doesn't provide alarm(2):
// https://osdn.net/projects/mingw/scm/git/mingw-org-wsl/blobs/5.2-trunk/mingwrt/include/unistd.h
// mingw-w64 provides a no-op implementation:
// https://sourceforge.net/p/mingw-w64/mingw-w64/ci/master/tree/mingw-w64-crt/misc/alarm.c
#elif defined(__EMSCRIPTEN__)
// emscripten doesn't support signals
#elif defined(__wasi__)
// WASI doesn't support signals
#elif defined(__Fuchsia__)
// Signals don't exist on fuchsia.
#elif defined(__native_client__)
// Signals don't exist on hexagon/QuRT
#elif defined(__hexagon__)
#else
// other standard libraries
#define ABSL_HAVE_ALARM 1
#endif
// ABSL_IS_LITTLE_ENDIAN
// ABSL_IS_BIG_ENDIAN
//
// Checks the endianness of the platform.
//
// Prefer using `std::endian` in C++20, or `absl::endian` from
// absl/numeric/bits.h prior to C++20.
//
// Notes: uses the built in endian macros provided by GCC (since 4.6) and
// Clang (since 3.2); see
// https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html.
// Otherwise, if _WIN32, assume little endian. Otherwise, bail with an error.
#if defined(ABSL_IS_BIG_ENDIAN)
#error "ABSL_IS_BIG_ENDIAN cannot be directly set."
#endif
#if defined(ABSL_IS_LITTLE_ENDIAN)
#error "ABSL_IS_LITTLE_ENDIAN cannot be directly set."
#endif
#if (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && \
__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
#define ABSL_IS_LITTLE_ENDIAN 1
#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \
__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define ABSL_IS_BIG_ENDIAN 1
#elif defined(_WIN32)
#define ABSL_IS_LITTLE_ENDIAN 1
#else
#error "absl endian detection needs to be set up for your compiler"
#endif
// macOS < 10.13 and iOS < 12 don't support <any>, <optional>, or <variant>
// because the libc++ shared library shipped on the system doesn't have the
// requisite exported symbols. See
// https://github.com/abseil/abseil-cpp/issues/207 and
// https://developer.apple.com/documentation/xcode_release_notes/xcode_10_release_notes
//
// libc++ spells out the availability requirements in the file
// llvm-project/libcxx/include/__config via the #define
// _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS. The set of versions has been
// modified a few times, via
// https://github.com/llvm/llvm-project/commit/7fb40e1569dd66292b647f4501b85517e9247953
// and
// https://github.com/llvm/llvm-project/commit/0bc451e7e137c4ccadcd3377250874f641ca514a
// The second has the actually correct versions, thus, is what we copy here.
#if defined(__APPLE__) && \
((defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \
__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101300) || \
(defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && \
__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 120000) || \
(defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && \
__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 50000) || \
(defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && \
__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 120000))
#define ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE 1
#else
#define ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE 0
#endif
// Deprecated macros for polyfill detection.
#define ABSL_HAVE_STD_ANY 1
#define ABSL_USES_STD_ANY 1
#define ABSL_HAVE_STD_OPTIONAL 1
#define ABSL_USES_STD_OPTIONAL 1
#define ABSL_HAVE_STD_VARIANT 1
#define ABSL_USES_STD_VARIANT 1
// ABSL_HAVE_STD_STRING_VIEW
//
// Deprecated: always defined to 1.
// std::string_view was added in C++17, which means all versions of C++
// supported by Abseil have it.
#ifdef ABSL_HAVE_STD_STRING_VIEW
#error "ABSL_HAVE_STD_STRING_VIEW cannot be directly set."
#else
#define ABSL_HAVE_STD_STRING_VIEW 1
#endif
// ABSL_HAVE_STD_ORDERING
//
// Checks whether C++20 std::{partial,weak,strong}_ordering are available.
//
// __cpp_lib_three_way_comparison is missing on libc++
// (https://github.com/llvm/llvm-project/issues/73953) so treat it as defined
// when building in C++20 mode.
#ifdef ABSL_HAVE_STD_ORDERING
#error "ABSL_HAVE_STD_ORDERING cannot be directly set."
#elif (defined(__cpp_lib_three_way_comparison) && \
__cpp_lib_three_way_comparison >= 201907L) || \
(defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L)
#define ABSL_HAVE_STD_ORDERING 1
#endif
// ABSL_USES_STD_STRING_VIEW
//
// Indicates whether absl::string_view is an alias for std::string_view.
#if !defined(ABSL_OPTION_USE_STD_STRING_VIEW)
#error options.h is misconfigured.
#elif ABSL_OPTION_USE_STD_STRING_VIEW == 0
#undef ABSL_USES_STD_STRING_VIEW
#elif ABSL_OPTION_USE_STD_STRING_VIEW == 1 || \
ABSL_OPTION_USE_STD_STRING_VIEW == 2
#define ABSL_USES_STD_STRING_VIEW 1
#else
#error options.h is misconfigured.
#endif
// ABSL_USES_STD_ORDERING
//
// Indicates whether absl::{partial,weak,strong}_ordering are aliases for the
// std:: ordering types.
#if !defined(ABSL_OPTION_USE_STD_ORDERING)
#error options.h is misconfigured.
#elif ABSL_OPTION_USE_STD_ORDERING == 0 || \
(ABSL_OPTION_USE_STD_ORDERING == 2 && !defined(ABSL_HAVE_STD_ORDERING))
#undef ABSL_USES_STD_ORDERING
#elif ABSL_OPTION_USE_STD_ORDERING == 1 || \
(ABSL_OPTION_USE_STD_ORDERING == 2 && defined(ABSL_HAVE_STD_ORDERING))
#define ABSL_USES_STD_ORDERING 1
#else
#error options.h is misconfigured.
#endif
// ABSL_INTERNAL_MANGLED_NS
// ABSL_INTERNAL_MANGLED_BACKREFERENCE
//
// Internal macros for building up mangled names in our internal fork of CCTZ.
// This implementation detail is only needed and provided for the MSVC build.
//
// These macros both expand to string literals. ABSL_INTERNAL_MANGLED_NS is
// the mangled spelling of the `absl` namespace, and
// ABSL_INTERNAL_MANGLED_BACKREFERENCE is a back-reference integer representing
// the proper count to skip past the CCTZ fork namespace names. (This number
// is one larger when there is an inline namespace name to skip.)
#if defined(_MSC_VER)
#if ABSL_OPTION_USE_INLINE_NAMESPACE == 0
#define ABSL_INTERNAL_MANGLED_NS "absl"
#define ABSL_INTERNAL_MANGLED_BACKREFERENCE "5"
#else
#define ABSL_INTERNAL_MANGLED_NS \
ABSL_INTERNAL_TOKEN_STR(ABSL_OPTION_INLINE_NAMESPACE_NAME) "@absl"
#define ABSL_INTERNAL_MANGLED_BACKREFERENCE "6"
#endif
#endif
// ABSL_DLL
//
// When building Abseil as a DLL, this macro expands to `__declspec(dllexport)`
// so we can annotate symbols appropriately as being exported. When used in
// headers consuming a DLL, this macro expands to `__declspec(dllimport)` so
// that consumers know the symbol is defined inside the DLL. In all other cases,
// the macro expands to nothing.
#if defined(_MSC_VER)
#if defined(ABSL_BUILD_DLL)
#define ABSL_DLL __declspec(dllexport)
#elif defined(ABSL_CONSUME_DLL)
#define ABSL_DLL __declspec(dllimport)
#else
#define ABSL_DLL
#endif
#else
#define ABSL_DLL
#endif // defined(_MSC_VER)
#if defined(_MSC_VER)
#if defined(ABSL_BUILD_TEST_DLL)
#define ABSL_TEST_DLL __declspec(dllexport)
#elif defined(ABSL_CONSUME_TEST_DLL)
#define ABSL_TEST_DLL __declspec(dllimport)
#else
#define ABSL_TEST_DLL
#endif
#else
#define ABSL_TEST_DLL
#endif // defined(_MSC_VER)
// ABSL_HAVE_MEMORY_SANITIZER
//
// MemorySanitizer (MSan) is a detector of uninitialized reads. It consists of
// a compiler instrumentation module and a run-time library.
#ifdef ABSL_HAVE_MEMORY_SANITIZER
#error "ABSL_HAVE_MEMORY_SANITIZER cannot be directly set."
#elif !defined(__native_client__) && ABSL_HAVE_FEATURE(memory_sanitizer)
#define ABSL_HAVE_MEMORY_SANITIZER 1
#endif
// ABSL_HAVE_THREAD_SANITIZER
//
// ThreadSanitizer (TSan) is a fast data race detector.
#ifdef ABSL_HAVE_THREAD_SANITIZER
#error "ABSL_HAVE_THREAD_SANITIZER cannot be directly set."
#elif defined(__SANITIZE_THREAD__)
#define ABSL_HAVE_THREAD_SANITIZER 1
#elif ABSL_HAVE_FEATURE(thread_sanitizer)
#define ABSL_HAVE_THREAD_SANITIZER 1
#endif
// ABSL_HAVE_ADDRESS_SANITIZER
//
// AddressSanitizer (ASan) is a fast memory error detector.
#ifdef ABSL_HAVE_ADDRESS_SANITIZER
#error "ABSL_HAVE_ADDRESS_SANITIZER cannot be directly set."
#elif defined(__SANITIZE_ADDRESS__)
#define ABSL_HAVE_ADDRESS_SANITIZER 1
#elif ABSL_HAVE_FEATURE(address_sanitizer)
#define ABSL_HAVE_ADDRESS_SANITIZER 1
#endif
// ABSL_HAVE_HWADDRESS_SANITIZER
//
// Hardware-Assisted AddressSanitizer (or HWASAN) is even faster than asan
// memory error detector which can use CPU features like ARM TBI, Intel LAM or
// AMD UAI.
#ifdef ABSL_HAVE_HWADDRESS_SANITIZER
#error "ABSL_HAVE_HWADDRESS_SANITIZER cannot be directly set."
#elif defined(__SANITIZE_HWADDRESS__)
#define ABSL_HAVE_HWADDRESS_SANITIZER 1
#elif ABSL_HAVE_FEATURE(hwaddress_sanitizer)
#define ABSL_HAVE_HWADDRESS_SANITIZER 1
#endif
// ABSL_HAVE_DATAFLOW_SANITIZER
//
// Dataflow Sanitizer (or DFSAN) is a generalised dynamic data flow analysis.
#ifdef ABSL_HAVE_DATAFLOW_SANITIZER
#error "ABSL_HAVE_DATAFLOW_SANITIZER cannot be directly set."
#elif defined(DATAFLOW_SANITIZER)
// GCC provides no method for detecting the presence of the standalone
// DataFlowSanitizer (-fsanitize=dataflow), so GCC users of -fsanitize=dataflow
// should also use -DDATAFLOW_SANITIZER.
#define ABSL_HAVE_DATAFLOW_SANITIZER 1
#elif ABSL_HAVE_FEATURE(dataflow_sanitizer)
#define ABSL_HAVE_DATAFLOW_SANITIZER 1
#endif
// ABSL_HAVE_LEAK_SANITIZER
//
// LeakSanitizer (or lsan) is a detector of memory leaks.
// https://clang.llvm.org/docs/LeakSanitizer.html
// https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer
//
// The macro ABSL_HAVE_LEAK_SANITIZER can be used to detect at compile-time
// whether the LeakSanitizer is potentially available. However, just because the
// LeakSanitizer is available does not mean it is active. Use the
// always-available run-time interface in //absl/debugging/leak_check.h for
// interacting with LeakSanitizer.
#ifdef ABSL_HAVE_LEAK_SANITIZER
#error "ABSL_HAVE_LEAK_SANITIZER cannot be directly set."
#elif defined(LEAK_SANITIZER)
// GCC provides no method for detecting the presence of the standalone
// LeakSanitizer (-fsanitize=leak), so GCC users of -fsanitize=leak should also
// use -DLEAK_SANITIZER.
#define ABSL_HAVE_LEAK_SANITIZER 1
// Clang standalone LeakSanitizer (-fsanitize=leak)
#elif ABSL_HAVE_FEATURE(leak_sanitizer)
#define ABSL_HAVE_LEAK_SANITIZER 1
#elif defined(ABSL_HAVE_ADDRESS_SANITIZER)
// GCC or Clang using the LeakSanitizer integrated into AddressSanitizer.
#define ABSL_HAVE_LEAK_SANITIZER 1
#endif
// ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION
//
// Deprecated: always defined to 1.
// Class template argument deduction is a language feature added in C++17,
// which means all versions of C++ supported by Abseil have it.
#ifdef ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION
#error "ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION cannot be directly set."
#else
#define ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION 1
#endif
// `ABSL_INTERNAL_HAS_RTTI` determines whether abseil is being compiled with
// RTTI support.
#ifdef ABSL_INTERNAL_HAS_RTTI
#error ABSL_INTERNAL_HAS_RTTI cannot be directly set
#elif ABSL_HAVE_FEATURE(cxx_rtti)
#define ABSL_INTERNAL_HAS_RTTI 1
#elif defined(__GNUC__) && defined(__GXX_RTTI)
#define ABSL_INTERNAL_HAS_RTTI 1
#elif defined(_MSC_VER) && defined(_CPPRTTI)
#define ABSL_INTERNAL_HAS_RTTI 1
#elif !defined(__GNUC__) && !defined(_MSC_VER)
// Unknown compiler, default to RTTI
#define ABSL_INTERNAL_HAS_RTTI 1
#endif
// `ABSL_INTERNAL_HAS_CXA_DEMANGLE` determines whether `abi::__cxa_demangle` is
// available.
#ifdef ABSL_INTERNAL_HAS_CXA_DEMANGLE
#error ABSL_INTERNAL_HAS_CXA_DEMANGLE cannot be directly set
#elif defined(OS_ANDROID) && (defined(__i386__) || defined(__x86_64__))
#define ABSL_INTERNAL_HAS_CXA_DEMANGLE 0
#elif defined(__GNUC__)
#define ABSL_INTERNAL_HAS_CXA_DEMANGLE 1
#elif defined(__clang__) && !defined(_MSC_VER)
#define ABSL_INTERNAL_HAS_CXA_DEMANGLE 1
#endif
// ABSL_INTERNAL_HAVE_SSE is used for compile-time detection of SSE support.
// See https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html for an overview of
// which architectures support the various x86 instruction sets.
#ifdef ABSL_INTERNAL_HAVE_SSE
#error ABSL_INTERNAL_HAVE_SSE cannot be directly set
#elif defined(__SSE__)
#define ABSL_INTERNAL_HAVE_SSE 1
#elif (defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 1)) && \
!defined(_M_ARM64EC)
// MSVC only defines _M_IX86_FP for x86 32-bit code, and _M_IX86_FP >= 1
// indicates that at least SSE was targeted with the /arch:SSE option.
// All x86-64 processors support SSE, so support can be assumed.
// https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros
#define ABSL_INTERNAL_HAVE_SSE 1
#endif
// ABSL_INTERNAL_HAVE_SSE2 is used for compile-time detection of SSE2 support.
// See https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html for an overview of
// which architectures support the various x86 instruction sets.
#ifdef ABSL_INTERNAL_HAVE_SSE2
#error ABSL_INTERNAL_HAVE_SSE2 cannot be directly set
#elif defined(__SSE2__)
#define ABSL_INTERNAL_HAVE_SSE2 1
#elif (defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 2)) && \
!defined(_M_ARM64EC)
// MSVC only defines _M_IX86_FP for x86 32-bit code, and _M_IX86_FP >= 2
// indicates that at least SSE2 was targeted with the /arch:SSE2 option.
// All x86-64 processors support SSE2, so support can be assumed.
// https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros
#define ABSL_INTERNAL_HAVE_SSE2 1
#endif
// ABSL_INTERNAL_HAVE_SSSE3 is used for compile-time detection of SSSE3 support.
// See https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html for an overview of
// which architectures support the various x86 instruction sets.
//
// MSVC does not have a mode that targets SSSE3 at compile-time. To use SSSE3
// with MSVC requires either assuming that the code will only every run on CPUs
// that support SSSE3, otherwise __cpuid() can be used to detect support at
// runtime and fallback to a non-SSSE3 implementation when SSSE3 is unsupported
// by the CPU.
#ifdef ABSL_INTERNAL_HAVE_SSSE3
#error ABSL_INTERNAL_HAVE_SSSE3 cannot be directly set
#elif defined(__SSSE3__)
#define ABSL_INTERNAL_HAVE_SSSE3 1
#endif
// ABSL_INTERNAL_HAVE_ARM_NEON is used for compile-time detection of NEON (ARM
// SIMD).
//
// If __CUDA_ARCH__ is defined, then we are compiling CUDA code in device mode.
// In device mode, NEON intrinsics are not available, regardless of host
// platform.
// https://llvm.org/docs/CompileCudaWithLLVM.html#detecting-clang-vs-nvcc-from-code
#ifdef ABSL_INTERNAL_HAVE_ARM_NEON
#error ABSL_INTERNAL_HAVE_ARM_NEON cannot be directly set
#elif defined(__ARM_NEON) && !(defined(__NVCC__) && defined(__CUDACC__))
#define ABSL_INTERNAL_HAVE_ARM_NEON 1
#endif
// ABSL_HAVE_CONSTANT_EVALUATED is used for compile-time detection of
// constant evaluation support through `absl::is_constant_evaluated`.
#ifdef ABSL_HAVE_CONSTANT_EVALUATED
#error ABSL_HAVE_CONSTANT_EVALUATED cannot be directly set
#endif
#ifdef __cpp_lib_is_constant_evaluated
#define ABSL_HAVE_CONSTANT_EVALUATED 1
#elif ABSL_HAVE_BUILTIN(__builtin_is_constant_evaluated)
#define ABSL_HAVE_CONSTANT_EVALUATED 1
#endif
// ABSL_INTERNAL_CONSTEXPR_SINCE_CXXYY is used to conditionally define constexpr
// for different C++ versions.
//
// These macros are an implementation detail and will be unconditionally removed
// once the minimum supported C++ version catches up to a given version.
//
// For this reason, this symbol is considered INTERNAL and code outside of
// Abseil must not use it.
#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
#define ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 constexpr
#else
#define ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17
#endif
#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
#define ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 constexpr
#else
#define ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20
#endif
// ABSL_INTERNAL_EMSCRIPTEN_VERSION combines Emscripten's three version macros
// into an integer that can be compared against.
#ifdef ABSL_INTERNAL_EMSCRIPTEN_VERSION
#error ABSL_INTERNAL_EMSCRIPTEN_VERSION cannot be directly set
#endif
#ifdef __EMSCRIPTEN__
#include <emscripten/version.h>
#ifdef __EMSCRIPTEN_major__
#if __EMSCRIPTEN_minor__ >= 1000
#error __EMSCRIPTEN_minor__ is too big to fit in ABSL_INTERNAL_EMSCRIPTEN_VERSION
#endif
#if __EMSCRIPTEN_tiny__ >= 1000
#error __EMSCRIPTEN_tiny__ is too big to fit in ABSL_INTERNAL_EMSCRIPTEN_VERSION
#endif
#define ABSL_INTERNAL_EMSCRIPTEN_VERSION \
((__EMSCRIPTEN_major__) * 1000000 + (__EMSCRIPTEN_minor__) * 1000 + \
(__EMSCRIPTEN_tiny__))
#endif
#endif
#endif // ABSL_BASE_CONFIG_H_
*Õ`
psoong/.intermediates/external/abseil-cpp/absl_base_core_headers_hdrs/gen/my_include_dir/absl/base/optimization.hà_//
// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: optimization.h
// -----------------------------------------------------------------------------
//
// This header file defines portable macros for performance optimization.
//
// This header is included in both C++ code and legacy C code and thus must
// remain compatible with both C and C++. C compatibility will be removed if
// the legacy code is removed or converted to C++. Do not include this header in
// new code that requires C compatibility or assume C compatibility will remain
// indefinitely.
// SKIP_ABSL_INLINE_NAMESPACE_CHECK
#ifndef ABSL_BASE_OPTIMIZATION_H_
#define ABSL_BASE_OPTIMIZATION_H_
#include <assert.h>
#ifdef __cplusplus
// Included for std::unreachable()
#include <utility>
#endif // __cplusplus
#include "absl/base/config.h"
#include "absl/base/options.h"
// ABSL_BLOCK_TAIL_CALL_OPTIMIZATION
//
// Instructs the compiler to avoid optimizing tail-call recursion. This macro is
// useful when you wish to preserve the existing function order within a stack
// trace for logging, debugging, or profiling purposes.
//
// Example:
//
// int f() {
// int result = g();
// ABSL_BLOCK_TAIL_CALL_OPTIMIZATION();
// return result;
// }
#if defined(__pnacl__)
#define ABSL_BLOCK_TAIL_CALL_OPTIMIZATION() if (volatile int x = 0) { (void)x; }
#elif defined(__clang__)
// Clang will not tail call given inline volatile assembly.
#define ABSL_BLOCK_TAIL_CALL_OPTIMIZATION() __asm__ __volatile__("")
#elif defined(__GNUC__)
// GCC will not tail call given inline volatile assembly.
#define ABSL_BLOCK_TAIL_CALL_OPTIMIZATION() __asm__ __volatile__("")
#elif defined(_MSC_VER)
#include <intrin.h>
// The __nop() intrinsic blocks the optimisation.
#define ABSL_BLOCK_TAIL_CALL_OPTIMIZATION() __nop()
#else
#define ABSL_BLOCK_TAIL_CALL_OPTIMIZATION() if (volatile int x = 0) { (void)x; }
#endif
// ABSL_CACHELINE_SIZE
//
// Explicitly defines the size of the L1 cache for purposes of alignment.
// Setting the cacheline size allows you to specify that certain objects be
// aligned on a cacheline boundary with `ABSL_CACHELINE_ALIGNED` declarations.
// (See below.)
//
// NOTE: this macro should be replaced with the following C++17 features, when
// those are generally available:
//
// * `std::hardware_constructive_interference_size`
// * `std::hardware_destructive_interference_size`
//
// See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0154r1.html
// for more information.
#if defined(__GNUC__)
// Cache line alignment
#if defined(__i386__) || defined(__x86_64__)
#define ABSL_CACHELINE_SIZE 64
#elif defined(__powerpc64__)
#define ABSL_CACHELINE_SIZE 128
#elif defined(__aarch64__)
// We would need to read special register ctr_el0 to find out L1 dcache size.
// This value is a good estimate based on a real aarch64 machine.
#define ABSL_CACHELINE_SIZE 64
#elif defined(__arm__)
// Cache line sizes for ARM: These values are not strictly correct since
// cache line sizes depend on implementations, not architectures. There
// are even implementations with cache line sizes configurable at boot
// time.
#if defined(__ARM_ARCH_5T__)
#define ABSL_CACHELINE_SIZE 32
#elif defined(__ARM_ARCH_7A__)
#define ABSL_CACHELINE_SIZE 64
#endif
#endif
#endif
#ifndef ABSL_CACHELINE_SIZE
// A reasonable default guess. Note that overestimates tend to waste more
// space, while underestimates tend to waste more time.
#define ABSL_CACHELINE_SIZE 64
#endif
// ABSL_CACHELINE_ALIGNED
//
// Indicates that the declared object be cache aligned using
// `ABSL_CACHELINE_SIZE` (see above). Cacheline aligning objects allows you to
// load a set of related objects in the L1 cache for performance improvements.
// Cacheline aligning objects properly allows constructive memory sharing and
// prevents destructive (or "false") memory sharing.
//
// NOTE: callers should replace uses of this macro with `alignas()` using
// `std::hardware_constructive_interference_size` and/or
// `std::hardware_destructive_interference_size` when C++17 becomes available to
// them.
//
// See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0154r1.html
// for more information.
//
// On some compilers, `ABSL_CACHELINE_ALIGNED` expands to an `__attribute__`
// or `__declspec` attribute. For compilers where this is not known to work,
// the macro expands to nothing.
//
// No further guarantees are made here. The result of applying the macro
// to variables and types is always implementation-defined.
//
// WARNING: It is easy to use this attribute incorrectly, even to the point
// of causing bugs that are difficult to diagnose, crash, etc. It does not
// of itself guarantee that objects are aligned to a cache line.
//
// NOTE: Some compilers are picky about the locations of annotations such as
// this attribute, so prefer to put it at the beginning of your declaration.
// For example,
//
// ABSL_CACHELINE_ALIGNED static Foo* foo = ...
//
// class ABSL_CACHELINE_ALIGNED Bar { ...
//
// Recommendations:
//
// 1) Consult compiler documentation; this comment is not kept in sync as
// toolchains evolve.
// 2) Verify your use has the intended effect. This often requires inspecting
// the generated machine code.
// 3) Prefer applying this attribute to individual variables. Avoid
// applying it to types. This tends to localize the effect.
#if defined(__clang__) || defined(__GNUC__)
#define ABSL_CACHELINE_ALIGNED __attribute__((aligned(ABSL_CACHELINE_SIZE)))
#elif defined(_MSC_VER)
#define ABSL_CACHELINE_ALIGNED __declspec(align(ABSL_CACHELINE_SIZE))
#else
#define ABSL_CACHELINE_ALIGNED
#endif
// ABSL_PREDICT_TRUE, ABSL_PREDICT_FALSE
//
// Enables the compiler to prioritize compilation using static analysis for
// likely paths within a boolean branch.
//
// Example:
//
// if (ABSL_PREDICT_TRUE(expression)) {
// return result; // Faster if more likely
// } else {
// return 0;
// }
//
// Compilers can use the information that a certain branch is not likely to be
// taken (for instance, a CHECK failure) to optimize for the common case in
// the absence of better information (ie. compiling gcc with `-fprofile-arcs`).
//
// Recommendation: Modern CPUs dynamically predict branch execution paths,
// typically with accuracy greater than 97%. As a result, annotating every
// branch in a codebase is likely counterproductive; however, annotating
// specific branches that are both hot and consistently mispredicted is likely
// to yield performance improvements.
#if ABSL_HAVE_BUILTIN(__builtin_expect) || \
(defined(__GNUC__) && !defined(__clang__))
#define ABSL_PREDICT_FALSE(x) (__builtin_expect(false || (x), false))
#define ABSL_PREDICT_TRUE(x) (__builtin_expect(false || (x), true))
#else
#define ABSL_PREDICT_FALSE(x) (x)
#define ABSL_PREDICT_TRUE(x) (x)
#endif
// `ABSL_INTERNAL_IMMEDIATE_ABORT_IMPL()` aborts the program in the fastest
// possible way, with no attempt at logging. One use is to implement hardening
// aborts with ABSL_OPTION_HARDENED. Since this is an internal symbol, it
// should not be used directly outside of Abseil.
#if ABSL_HAVE_BUILTIN(__builtin_trap) || \
(defined(__GNUC__) && !defined(__clang__))
#define ABSL_INTERNAL_IMMEDIATE_ABORT_IMPL() __builtin_trap()
#else
#define ABSL_INTERNAL_IMMEDIATE_ABORT_IMPL() abort()
#endif
// `ABSL_INTERNAL_UNREACHABLE_IMPL()` is the platform specific directive to
// indicate that a statement is unreachable, and to allow the compiler to
// optimize accordingly. Clients should use `ABSL_UNREACHABLE()`, which is
// defined below.
#if defined(__cpp_lib_unreachable) && __cpp_lib_unreachable >= 202202L
#define ABSL_INTERNAL_UNREACHABLE_IMPL() std::unreachable()
#elif defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable)
#define ABSL_INTERNAL_UNREACHABLE_IMPL() __builtin_unreachable()
#elif ABSL_HAVE_BUILTIN(__builtin_assume)
#define ABSL_INTERNAL_UNREACHABLE_IMPL() __builtin_assume(false)
#elif defined(_MSC_VER)
#define ABSL_INTERNAL_UNREACHABLE_IMPL() __assume(false)
#else
#define ABSL_INTERNAL_UNREACHABLE_IMPL()
#endif
// `ABSL_UNREACHABLE()` is an unreachable statement. A program which reaches
// one has undefined behavior, and the compiler may optimize accordingly.
#if ABSL_OPTION_HARDENED == 1 && defined(NDEBUG)
// Abort in hardened mode to avoid dangerous undefined behavior.
#define ABSL_UNREACHABLE() \
do { \
ABSL_INTERNAL_IMMEDIATE_ABORT_IMPL(); \
ABSL_INTERNAL_UNREACHABLE_IMPL(); \
} while (false)
#else
// The assert only fires in debug mode to aid in debugging.
// When NDEBUG is defined, reaching ABSL_UNREACHABLE() is undefined behavior.
#define ABSL_UNREACHABLE() \
do { \
/* NOLINTNEXTLINE: misc-static-assert */ \
assert(false && "ABSL_UNREACHABLE reached"); \
ABSL_INTERNAL_UNREACHABLE_IMPL(); \
} while (false)
#endif
// ABSL_ASSUME(cond)
//
// Informs the compiler that a condition is always true and that it can assume
// it to be true for optimization purposes.
//
// WARNING: If the condition is false, the program can produce undefined and
// potentially dangerous behavior.
//
// In !NDEBUG mode, the condition is checked with an assert().
//
// NOTE: The expression must not have side effects, as it may only be evaluated
// in some compilation modes and not others. Some compilers may issue a warning
// if the compiler cannot prove the expression has no side effects. For example,
// the expression should not use a function call since the compiler cannot prove
// that a function call does not have side effects.
//
// Example:
//
// int x = ...;
// ABSL_ASSUME(x >= 0);
// // The compiler can optimize the division to a simple right shift using the
// // assumption specified above.
// int y = x / 16;
//
#if !defined(NDEBUG)
#define ABSL_ASSUME(cond) assert(cond)
#elif ABSL_HAVE_BUILTIN(__builtin_assume)
#define ABSL_ASSUME(cond) __builtin_assume(cond)
#elif defined(_MSC_VER)
#define ABSL_ASSUME(cond) __assume(cond)
#elif defined(__cpp_lib_unreachable) && __cpp_lib_unreachable >= 202202L
#define ABSL_ASSUME(cond) ((cond) ? void() : std::unreachable())
#elif defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable)
#define ABSL_ASSUME(cond) ((cond) ? void() : __builtin_unreachable())
#elif ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
// Unimplemented. Uses the same definition as ABSL_ASSERT in the NDEBUG case.
#define ABSL_ASSUME(expr) (decltype((expr) ? void() : void())())
#else
#define ABSL_ASSUME(expr) (false ? ((expr) ? void() : void()) : void())
#endif
// ABSL_INTERNAL_UNIQUE_SMALL_NAME(cond)
// This macro forces small unique name on a static file level symbols like
// static local variables or static functions. This is intended to be used in
// macro definitions to optimize the cost of generated code. Do NOT use it on
// symbols exported from translation unit since it may cause a link time
// conflict.
//
// Example:
//
// #define MY_MACRO(txt)
// namespace {
// char VeryVeryLongVarName[] ABSL_INTERNAL_UNIQUE_SMALL_NAME() = txt;
// const char* VeryVeryLongFuncName() ABSL_INTERNAL_UNIQUE_SMALL_NAME();
// const char* VeryVeryLongFuncName() { return txt; }
// }
//
#if defined(__GNUC__)
#define ABSL_INTERNAL_UNIQUE_SMALL_NAME2(x) #x
#define ABSL_INTERNAL_UNIQUE_SMALL_NAME1(x) ABSL_INTERNAL_UNIQUE_SMALL_NAME2(x)
#define ABSL_INTERNAL_UNIQUE_SMALL_NAME() \
asm(ABSL_INTERNAL_UNIQUE_SMALL_NAME1(.absl.__COUNTER__))
#else
#define ABSL_INTERNAL_UNIQUE_SMALL_NAME()
#endif
#endif // ABSL_BASE_OPTIMIZATION_H_
*ù
Œsoong/.intermediates/external/abseil-cpp/absl_strings_str_format_internal_hdrs/gen/my_include_dir/absl/strings/internal/str_format/checker.hç// Copyright 2020 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_
#define ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_
#include <algorithm>
#include "absl/base/attributes.h"
#include "absl/strings/internal/str_format/arg.h"
#include "absl/strings/internal/str_format/constexpr_parser.h"
#include "absl/strings/internal/str_format/extension.h"
// Compile time check support for entry points.
#ifndef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
// We disable format checker under vscode intellisense compilation.
// See https://github.com/microsoft/vscode-cpptools/issues/3683 for
// more details.
#if ABSL_HAVE_ATTRIBUTE(enable_if) && !defined(__native_client__) && \
!defined(__INTELLISENSE__)
#define ABSL_INTERNAL_ENABLE_FORMAT_CHECKER 1
#endif // ABSL_HAVE_ATTRIBUTE(enable_if) && !defined(__native_client__) &&
// !defined(__INTELLISENSE__)
#endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
#ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
template <FormatConversionCharSet... C>
constexpr bool ValidFormatImpl(string_view format) {
int next_arg = 0;
const char* p = format.data();
const char* const end = p + format.size();
constexpr FormatConversionCharSet
kAllowedConvs[(std::max)(sizeof...(C), size_t{1})] = {C...};
bool used[(std::max)(sizeof...(C), size_t{1})]{};
constexpr int kNumArgs = sizeof...(C);
while (p != end) {
while (p != end && *p != '%') ++p;
if (p == end) {
break;
}
if (p + 1 >= end) return false;
if (p[1] == '%') {
// %%
p += 2;
continue;
}
UnboundConversion conv(absl::kConstInit);
p = ConsumeUnboundConversion(p + 1, end, &conv, &next_arg);
if (p == nullptr) return false;
if (conv.arg_position <= 0 || conv.arg_position > kNumArgs) {
return false;
}
if (!Contains(kAllowedConvs[conv.arg_position - 1], conv.conv)) {
return false;
}
used[conv.arg_position - 1] = true;
for (auto extra : {conv.width, conv.precision}) {
if (extra.is_from_arg()) {
int pos = extra.get_from_arg();
if (pos <= 0 || pos > kNumArgs) return false;
used[pos - 1] = true;
if (!Contains(kAllowedConvs[pos - 1], '*')) {
return false;
}
}
}
}
if (sizeof...(C) != 0) {
for (bool b : used) {
if (!b) return false;
}
}
return true;
}
#endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
} // namespace str_format_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_
*Ã
„soong/.intermediates/external/abseil-cpp/absl_debugging_demangle_internal_hdrs/gen/my_include_dir/absl/debugging/internal/demangle.h¹// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_DEBUGGING_INTERNAL_DEMANGLE_H_
#define ABSL_DEBUGGING_INTERNAL_DEMANGLE_H_
#include <string>
#include "absl/base/config.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace debugging_internal {
// Demangle `mangled`. On success, return true and write the
// demangled symbol name to `out`. Otherwise, return false.
// `out` is modified even if demangling is unsuccessful.
//
// This function provides an alternative to libstdc++'s abi::__cxa_demangle,
// which is not async signal safe (it uses malloc internally). It's intended to
// be used in async signal handlers to symbolize stack traces.
//
// Note that this demangler doesn't support full demangling. More
// specifically, it doesn't print types of function parameters and
// types of template arguments. It just skips them. However, it's
// still very useful to extract basic information such as class,
// function, constructor, destructor, and operator names.
//
// See the implementation note in demangle.cc if you are interested.
//
// Example:
//
// | Mangled Name | Demangle | DemangleString
// |---------------|-------------|-----------------------
// | _Z1fv | f() | f()
// | _Z1fi | f() | f(int)
// | _Z3foo3bar | foo() | foo(bar)
// | _Z1fIiEvi | f<>() | void f<int>(int)
// | _ZN1N1fE | N::f | N::f
// | _ZN3Foo3BarEv | Foo::Bar() | Foo::Bar()
// | _Zrm1XS_" | operator%() | operator%(X, X)
// | _ZN3FooC1Ev | Foo::Foo() | Foo::Foo()
// | _Z1fSs | f() | f(std::basic_string<char,
// | | | std::char_traits<char>,
// | | | std::allocator<char> >)
//
// See the unit test for more examples.
//
// Demangle also recognizes Rust mangled names by delegating the parsing of
// anything that starts with _R to DemangleRustSymbolEncoding (demangle_rust.h).
//
// Note: we might want to write demanglers for ABIs other than Itanium
// C++ ABI in the future.
bool Demangle(const char* mangled, char* out, size_t out_size);
// A wrapper around `abi::__cxa_demangle()`. On success, returns the demangled
// name. On failure, returns the input mangled name.
//
// This function is not async-signal-safe.
std::string DemangleString(const char* mangled);
} // namespace debugging_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_DEBUGGING_INTERNAL_DEMANGLE_H_
*ã¢
soong/.intermediates/external/abseil-cpp/absl_container_btree_hdrs/gen/my_include_dir/absl/container/internal/btree_container.hÞ¡// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_CONTAINER_INTERNAL_BTREE_CONTAINER_H_
#define ABSL_CONTAINER_INTERNAL_BTREE_CONTAINER_H_
#include <algorithm>
#include <initializer_list>
#include <iterator>
#include <type_traits>
#include <utility>
#include "absl/base/attributes.h"
#include "absl/base/internal/throw_delegate.h"
#include "absl/container/internal/btree.h" // IWYU pragma: export
#include "absl/container/internal/common.h"
#include "absl/hash/internal/weakly_mixed_integer.h"
#include "absl/memory/memory.h"
#include "absl/meta/type_traits.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace container_internal {
// A common base class for btree_set, btree_map, btree_multiset, and
// btree_multimap.
template <typename Tree>
class btree_container {
using params_type = typename Tree::params_type;
protected:
// Alias used for heterogeneous lookup functions.
// `key_arg<K>` evaluates to `K` when the functors are transparent and to
// `key_type` otherwise. It permits template argument deduction on `K` for the
// transparent case.
template <class K>
using key_arg =
typename KeyArg<params_type::kIsKeyCompareTransparent>::template type<
K, typename Tree::key_type>;
public:
using key_type = typename Tree::key_type;
using value_type = typename Tree::value_type;
using size_type = typename Tree::size_type;
using difference_type = typename Tree::difference_type;
using key_compare = typename Tree::original_key_compare;
using value_compare = typename Tree::value_compare;
using allocator_type = typename Tree::allocator_type;
using reference = typename Tree::reference;
using const_reference = typename Tree::const_reference;
using pointer = typename Tree::pointer;
using const_pointer = typename Tree::const_pointer;
using iterator = typename Tree::iterator;
using const_iterator = typename Tree::const_iterator;
using reverse_iterator = typename Tree::reverse_iterator;
using const_reverse_iterator = typename Tree::const_reverse_iterator;
using node_type = typename Tree::node_handle_type;
struct extract_and_get_next_return_type {
node_type node;
iterator next;
};
// Constructors/assignments.
btree_container() : tree_(key_compare(), allocator_type()) {}
explicit btree_container(const key_compare &comp,
const allocator_type &alloc = allocator_type())
: tree_(comp, alloc) {}
explicit btree_container(const allocator_type &alloc)
: tree_(key_compare(), alloc) {}
btree_container(const btree_container &other)
: btree_container(other, absl::allocator_traits<allocator_type>::
select_on_container_copy_construction(
other.get_allocator())) {}
btree_container(const btree_container &other, const allocator_type &alloc)
: tree_(other.tree_, alloc) {}
btree_container(btree_container &&other) noexcept(
std::is_nothrow_move_constructible<Tree>::value) = default;
btree_container(btree_container &&other, const allocator_type &alloc)
: tree_(std::move(other.tree_), alloc) {}
btree_container &operator=(const btree_container &other) = default;
btree_container &operator=(btree_container &&other) noexcept(
std::is_nothrow_move_assignable<Tree>::value) = default;
// Iterator routines.
iterator begin() ABSL_ATTRIBUTE_LIFETIME_BOUND { return tree_.begin(); }
const_iterator begin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return tree_.begin();
}
const_iterator cbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return tree_.begin();
}
iterator end() ABSL_ATTRIBUTE_LIFETIME_BOUND { return tree_.end(); }
const_iterator end() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return tree_.end();
}
const_iterator cend() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return tree_.end();
}
reverse_iterator rbegin() ABSL_ATTRIBUTE_LIFETIME_BOUND {
return tree_.rbegin();
}
const_reverse_iterator rbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return tree_.rbegin();
}
const_reverse_iterator crbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return tree_.rbegin();
}
reverse_iterator rend() ABSL_ATTRIBUTE_LIFETIME_BOUND { return tree_.rend(); }
const_reverse_iterator rend() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return tree_.rend();
}
const_reverse_iterator crend() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return tree_.rend();
}
// Lookup routines.
template <typename K = key_type>
size_type count(const key_arg<K> &key) const {
auto equal_range = this->equal_range(key);
return equal_range.second - equal_range.first;
}
template <typename K = key_type>
iterator find(const key_arg<K> &key) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return tree_.find(key);
}
template <typename K = key_type>
const_iterator find(const key_arg<K> &key) const
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return tree_.find(key);
}
template <typename K = key_type>
bool contains(const key_arg<K> &key) const {
return find(key) != end();
}
template <typename K = key_type>
iterator lower_bound(const key_arg<K> &key) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return tree_.lower_bound(key);
}
template <typename K = key_type>
const_iterator lower_bound(const key_arg<K> &key) const
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return tree_.lower_bound(key);
}
template <typename K = key_type>
iterator upper_bound(const key_arg<K> &key) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return tree_.upper_bound(key);
}
template <typename K = key_type>
const_iterator upper_bound(const key_arg<K> &key) const
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return tree_.upper_bound(key);
}
template <typename K = key_type>
std::pair<iterator, iterator> equal_range(const key_arg<K> &key)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return tree_.equal_range(key);
}
template <typename K = key_type>
std::pair<const_iterator, const_iterator> equal_range(
const key_arg<K> &key) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return tree_.equal_range(key);
}
// Deletion routines. Note that there is also a deletion routine that is
// specific to btree_set_container/btree_multiset_container.
// Erase the specified iterator from the btree. The iterator must be valid
// (i.e. not equal to end()). Return an iterator pointing to the node after
// the one that was erased (or end() if none exists).
iterator erase(const_iterator iter) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return tree_.erase(iterator(iter));
}
iterator erase(iterator iter) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return tree_.erase(iter);
}
iterator erase(const_iterator first,
const_iterator last) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return tree_.erase_range(iterator(first), iterator(last)).second;
}
template <typename K = key_type>
size_type erase(const key_arg<K> &key) {
auto equal_range = this->equal_range(key);
return tree_.erase_range(equal_range.first, equal_range.second).first;
}
// Extract routines.
extract_and_get_next_return_type extract_and_get_next(const_iterator position)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
// Use Construct instead of Transfer because the rebalancing code will
// destroy the slot later.
// Note: we rely on erase() taking place after Construct().
return {CommonAccess::Construct<node_type>(get_allocator(),
iterator(position).slot()),
erase(position)};
}
node_type extract(iterator position) {
// Use Construct instead of Transfer because the rebalancing code will
// destroy the slot later.
auto node =
CommonAccess::Construct<node_type>(get_allocator(), position.slot());
erase(position);
return node;
}
node_type extract(const_iterator position) {
return extract(iterator(position));
}
// Utility routines.
ABSL_ATTRIBUTE_REINITIALIZES void clear() { tree_.clear(); }
void swap(btree_container &other) { tree_.swap(other.tree_); }
void verify() const { tree_.verify(); }
// Size routines.
size_type size() const { return tree_.size(); }
size_type max_size() const { return tree_.max_size(); }
bool empty() const { return tree_.empty(); }
friend bool operator==(const btree_container &x, const btree_container &y) {
if (x.size() != y.size()) return false;
return std::equal(x.begin(), x.end(), y.begin());
}
friend bool operator!=(const btree_container &x, const btree_container &y) {
return !(x == y);
}
friend bool operator<(const btree_container &x, const btree_container &y) {
return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
}
friend bool operator>(const btree_container &x, const btree_container &y) {
return y < x;
}
friend bool operator<=(const btree_container &x, const btree_container &y) {
return !(y < x);
}
friend bool operator>=(const btree_container &x, const btree_container &y) {
return !(x < y);
}
// The allocator used by the btree.
allocator_type get_allocator() const { return tree_.get_allocator(); }
// The key comparator used by the btree.
key_compare key_comp() const { return key_compare(tree_.key_comp()); }
value_compare value_comp() const { return tree_.value_comp(); }
// Support absl::Hash.
template <typename State>
friend State AbslHashValue(State h, const btree_container &b) {
for (const auto &v : b) {
h = State::combine(std::move(h), v);
}
return State::combine(std::move(h),
hash_internal::WeaklyMixedInteger{b.size()});
}
protected:
friend struct btree_access;
Tree tree_;
};
// A common base class for btree_set and btree_map.
template <typename Tree>
class btree_set_container : public btree_container<Tree> {
using super_type = btree_container<Tree>;
using params_type = typename Tree::params_type;
using init_type = typename params_type::init_type;
using is_key_compare_to = typename params_type::is_key_compare_to;
friend class BtreeNodePeer;
protected:
template <class K>
using key_arg = typename super_type::template key_arg<K>;
public:
using key_type = typename Tree::key_type;
using value_type = typename Tree::value_type;
using size_type = typename Tree::size_type;
using key_compare = typename Tree::original_key_compare;
using allocator_type = typename Tree::allocator_type;
using iterator = typename Tree::iterator;
using const_iterator = typename Tree::const_iterator;
using node_type = typename super_type::node_type;
using insert_return_type = InsertReturnType<iterator, node_type>;
// Inherit constructors.
using super_type::super_type;
btree_set_container() {}
// Range constructors.
template <class InputIterator>
btree_set_container(InputIterator b, InputIterator e,
const key_compare &comp = key_compare(),
const allocator_type &alloc = allocator_type())
: super_type(comp, alloc) {
insert(b, e);
}
template <class InputIterator>
btree_set_container(InputIterator b, InputIterator e,
const allocator_type &alloc)
: btree_set_container(b, e, key_compare(), alloc) {}
// Initializer list constructors.
btree_set_container(std::initializer_list<init_type> init,
const key_compare &comp = key_compare(),
const allocator_type &alloc = allocator_type())
: btree_set_container(init.begin(), init.end(), comp, alloc) {}
btree_set_container(std::initializer_list<init_type> init,
const allocator_type &alloc)
: btree_set_container(init.begin(), init.end(), alloc) {}
// Insertion routines.
std::pair<iterator, bool> insert(const value_type &v)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return this->tree_.insert_unique(params_type::key(v), v);
}
std::pair<iterator, bool> insert(value_type &&v)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return this->tree_.insert_unique(params_type::key(v), std::move(v));
}
template <typename... Args>
std::pair<iterator, bool> emplace(Args &&...args)
ABSL_ATTRIBUTE_LIFETIME_BOUND {
// Use a node handle to manage a temp slot.
auto node = CommonAccess::Construct<node_type>(this->get_allocator(),
std::forward<Args>(args)...);
auto *slot = CommonAccess::GetSlot(node);
return this->tree_.insert_unique(params_type::key(slot), slot);
}
iterator insert(const_iterator hint,
const value_type &v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return this->tree_
.insert_hint_unique(iterator(hint), params_type::key(v), v)
.first;
}
iterator insert(const_iterator hint,
value_type &&v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return this->tree_
.insert_hint_unique(iterator(hint), params_type::key(v), std::move(v))
.first;
}
template <typename... Args>
iterator emplace_hint(const_iterator hint,
Args &&...args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
// Use a node handle to manage a temp slot.
auto node = CommonAccess::Construct<node_type>(this->get_allocator(),
std::forward<Args>(args)...);
auto *slot = CommonAccess::GetSlot(node);
return this->tree_
.insert_hint_unique(iterator(hint), params_type::key(slot), slot)
.first;
}
template <typename InputIterator>
void insert(InputIterator b, InputIterator e) {
this->tree_.insert_iterator_unique(b, e, 0);
}
void insert(std::initializer_list<init_type> init) {
this->tree_.insert_iterator_unique(init.begin(), init.end(), 0);
}
insert_return_type insert(node_type &&node) ABSL_ATTRIBUTE_LIFETIME_BOUND {
if (!node) return {this->end(), false, node_type()};
std::pair<iterator, bool> res =
this->tree_.insert_unique(params_type::key(CommonAccess::GetSlot(node)),
CommonAccess::GetSlot(node));
if (res.second) {
CommonAccess::Destroy(&node);
return {res.first, true, node_type()};
} else {
return {res.first, false, std::move(node)};
}
}
iterator insert(const_iterator hint,
node_type &&node) ABSL_ATTRIBUTE_LIFETIME_BOUND {
if (!node) return this->end();
std::pair<iterator, bool> res = this->tree_.insert_hint_unique(
iterator(hint), params_type::key(CommonAccess::GetSlot(node)),
CommonAccess::GetSlot(node));
if (res.second) CommonAccess::Destroy(&node);
return res.first;
}
// Node extraction routines.
template <typename K = key_type>
node_type extract(const key_arg<K> &key) {
const std::pair<iterator, bool> lower_and_equal =
this->tree_.lower_bound_equal(key);
return lower_and_equal.second ? extract(lower_and_equal.first)
: node_type();
}
using super_type::extract;
// Merge routines.
// Moves elements from `src` into `this`. If the element already exists in
// `this`, it is left unmodified in `src`.
template <
typename T,
typename absl::enable_if_t<
absl::conjunction<
std::is_same<value_type, typename T::value_type>,
std::is_same<allocator_type, typename T::allocator_type>,
std::is_same<typename params_type::is_map_container,
typename T::params_type::is_map_container>>::value,
int> = 0>
void merge(btree_container<T> &src) { // NOLINT
for (auto src_it = src.begin(); src_it != src.end();) {
if (insert(std::move(params_type::element(src_it.slot()))).second) {
src_it = src.erase(src_it);
} else {
++src_it;
}
}
}
template <
typename T,
typename absl::enable_if_t<
absl::conjunction<
std::is_same<value_type, typename T::value_type>,
std::is_same<allocator_type, typename T::allocator_type>,
std::is_same<typename params_type::is_map_container,
typename T::params_type::is_map_container>>::value,
int> = 0>
void merge(btree_container<T> &&src) {
merge(src);
}
};
// Base class for btree_map.
template <typename Tree>
class btree_map_container : public btree_set_container<Tree> {
using super_type = btree_set_container<Tree>;
using params_type = typename Tree::params_type;
friend class BtreeNodePeer;
private:
template <class K>
using key_arg = typename super_type::template key_arg<K>;
// NOTE: The mess here is to shorten the code for the (very repetitive)
// function overloads, and to allow the lifetime-bound overloads to dispatch
// to the non-lifetime-bound overloads, to ensure there is a single source of
// truth for each overload set.
//
// Enabled if an assignment from the given type would require the
// source object to remain alive for the life of the element.
//
// TODO(b/402804213): Remove these traits and simplify the overloads whenever
// we have a better mechanism available to handle lifetime analysis.
template <class K, bool Value, typename = void>
using LifetimeBoundK =
HasValue<Value, type_traits_internal::IsLifetimeBoundAssignment<
typename Tree::key_type, K>>;
template <class M, bool Value, typename = void>
using LifetimeBoundV =
HasValue<Value, type_traits_internal::IsLifetimeBoundAssignment<
typename Tree::params_type::mapped_type, M>>;
template <class K, bool KValue, class M, bool MValue, typename... Dummy>
using LifetimeBoundKV =
absl::conjunction<LifetimeBoundK<K, KValue, absl::void_t<Dummy...>>,
LifetimeBoundV<M, MValue>>;
public:
using key_type = typename Tree::key_type;
using mapped_type = typename params_type::mapped_type;
using value_type = typename Tree::value_type;
using key_compare = typename Tree::original_key_compare;
using allocator_type = typename Tree::allocator_type;
using iterator = typename Tree::iterator;
using const_iterator = typename Tree::const_iterator;
// Inherit constructors.
using super_type::super_type;
btree_map_container() {}
// TODO(b/402804213): Remove these macros whenever we have a better mechanism
// available to handle lifetime analysis.
#define ABSL_INTERNAL_X(Func, Callee, KQual, MQual, KValue, MValue, ...) \
template < \
typename K = key_type, class M, \
ABSL_INTERNAL_IF_##KValue##_NOR_##MValue( \
int = (EnableIf<LifetimeBoundKV<K, KValue, M, MValue, \
IfRRef<int KQual>::AddPtr<K>, \
IfRRef<int MQual>::AddPtr<M>>>()), \
ABSL_INTERNAL_SINGLE_ARG( \
int &..., \
decltype(EnableIf<LifetimeBoundKV<K, KValue, M, MValue>>()) = \
0))> \
decltype(auto) Func( \
__VA_ARGS__ key_arg<K> KQual k ABSL_INTERNAL_IF_##KValue( \
ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this)), \
M MQual obj ABSL_INTERNAL_IF_##MValue( \
ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this))) \
ABSL_ATTRIBUTE_LIFETIME_BOUND { \
return ABSL_INTERNAL_IF_##KValue##_OR_##MValue( \
(this->template Func<K, M, 0>), Callee)( \
__VA_ARGS__ std::forward<decltype(k)>(k), \
std::forward<decltype(obj)>(obj)); \
} \
friend struct std::enable_if<false> /* just to force a semicolon */
// Insertion routines.
// Note: the nullptr template arguments and extra `const M&` overloads allow
// for supporting bitfield arguments.
ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, const &,
false, false);
ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, const &,
false, true);
ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, const &,
true, false);
ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, const &,
true, true);
ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, &&, false,
false);
ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, &&, false,
true);
ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, &&, true,
false);
ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, const &, &&, true,
true);
ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, const &, false,
false);
ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, const &, false,
true);
ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, const &, true,
false);
ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, const &, true,
true);
ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, &&, false,
false);
ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, &&, false, true);
ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, &&, true, false);
ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_impl, &&, &&, true, true);
ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, const &,
const &, false, false,
const_iterator(hint) ABSL_INTERNAL_COMMA);
ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, const &,
const &, false, true,
const_iterator(hint) ABSL_INTERNAL_COMMA);
ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, const &,
const &, true, false,
const_iterator(hint) ABSL_INTERNAL_COMMA);
ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, const &,
const &, true, true,
const_iterator(hint) ABSL_INTERNAL_COMMA);
ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, const &, &&,
false, false, const_iterator(hint) ABSL_INTERNAL_COMMA);
ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, const &, &&,
false, true, const_iterator(hint) ABSL_INTERNAL_COMMA);
ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, const &, &&,
true, false, const_iterator(hint) ABSL_INTERNAL_COMMA);
ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, const &, &&,
true, true, const_iterator(hint) ABSL_INTERNAL_COMMA);
ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, &&, const &,
false, false, const_iterator(hint) ABSL_INTERNAL_COMMA);
ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, &&, const &,
false, true, const_iterator(hint) ABSL_INTERNAL_COMMA);
ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, &&, const &,
true, false, const_iterator(hint) ABSL_INTERNAL_COMMA);
ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, &&, const &,
true, true, const_iterator(hint) ABSL_INTERNAL_COMMA);
ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, &&, &&, false,
false, const_iterator(hint) ABSL_INTERNAL_COMMA);
ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, &&, &&, false,
true, const_iterator(hint) ABSL_INTERNAL_COMMA);
ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, &&, &&, true,
false, const_iterator(hint) ABSL_INTERNAL_COMMA);
ABSL_INTERNAL_X(insert_or_assign, insert_or_assign_hint_impl, &&, &&, true,
true, const_iterator(hint) ABSL_INTERNAL_COMMA);
#undef ABSL_INTERNAL_X
#define ABSL_INTERNAL_X(Func, Callee, KQual, KValue, ...) \
template < \
class K = key_type, \
ABSL_INTERNAL_IF_##KValue( \
class... Args, \
int = (EnableIf< \
LifetimeBoundK<K, KValue, IfRRef<int KQual>::AddPtr<K>>>())), \
ABSL_INTERNAL_IF_##KValue( \
decltype(EnableIf<LifetimeBoundK< \
K, KValue, IfRRef<int KQual>::AddPtr<K>>>()) = 0, \
class... Args), \
std::enable_if_t<!std::is_convertible<K, const_iterator>::value, int> = \
0> \
decltype(auto) Func( \
__VA_ARGS__ key_arg<K> KQual k ABSL_INTERNAL_IF_##KValue( \
ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this)), \
Args &&...args) ABSL_ATTRIBUTE_LIFETIME_BOUND { \
return ABSL_INTERNAL_IF_##KValue((this->template Func<K, 0>), Callee)( \
__VA_ARGS__ std::forward<decltype(k)>(k), \
std::forward<decltype(args)>(args)...); \
} \
friend struct std::enable_if<false> /* just to force a semicolon */
ABSL_INTERNAL_X(try_emplace, try_emplace_impl, const &, false);
ABSL_INTERNAL_X(try_emplace, try_emplace_impl, const &, true);
ABSL_INTERNAL_X(try_emplace, try_emplace_impl, &&, false);
ABSL_INTERNAL_X(try_emplace, try_emplace_impl, &&, true);
ABSL_INTERNAL_X(try_emplace, try_emplace_hint_impl, const &, false,
const_iterator(hint) ABSL_INTERNAL_COMMA);
ABSL_INTERNAL_X(try_emplace, try_emplace_hint_impl, const &, true,
const_iterator(hint) ABSL_INTERNAL_COMMA);
ABSL_INTERNAL_X(try_emplace, try_emplace_hint_impl, &&, false,
const_iterator(hint) ABSL_INTERNAL_COMMA);
ABSL_INTERNAL_X(try_emplace, try_emplace_hint_impl, &&, true,
const_iterator(hint) ABSL_INTERNAL_COMMA);
#undef ABSL_INTERNAL_X
template <class K = key_type, int = EnableIf<LifetimeBoundK<K, false>>()>
mapped_type &operator[](const key_arg<K> &k) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return try_emplace(k).first->second;
}
template <class K = key_type, int &..., EnableIf<LifetimeBoundK<K, true>> = 0>
mapped_type &operator[](
const key_arg<K> &k ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(this))
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return this->template operator[]<K, 0>(k);
}
template <class K = key_type, int = EnableIf<LifetimeBoundK<K, false>>()>
mapped_type &operator[](key_arg<K> &&k) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return try_emplace(std::forward<K>(k)).first->second;
}
template <class K = key_type, int &..., EnableIf<LifetimeBoundK<K, true>> = 0>
mapped_type &operator[](key_arg<K> &&k ABSL_INTERNAL_ATTRIBUTE_CAPTURED_BY(
this)) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return this->template operator[]<K, 0>(std::forward<K>(k));
}
template <typename K = key_type>
mapped_type &at(const key_arg<K> &key) ABSL_ATTRIBUTE_LIFETIME_BOUND {
auto it = this->find(key);
if (it == this->end())
base_internal::ThrowStdOutOfRange("absl::btree_map::at");
return it->second;
}
template <typename K = key_type>
const mapped_type &at(const key_arg<K> &key) const
ABSL_ATTRIBUTE_LIFETIME_BOUND {
auto it = this->find(key);
if (it == this->end())
base_internal::ThrowStdOutOfRange("absl::btree_map::at");
return it->second;
}
private:
// Note: when we call `std::forward<M>(obj)` twice, it's safe because
// insert_unique/insert_hint_unique are guaranteed to not consume `obj` when
// `ret.second` is false.
template <class K, class M>
std::pair<iterator, bool> insert_or_assign_impl(K &&k, M &&obj) {
const std::pair<iterator, bool> ret =
this->tree_.insert_unique(k, std::forward<K>(k), std::forward<M>(obj));
if (!ret.second) ret.first->second = std::forward<M>(obj);
return ret;
}
template <class K, class M>
iterator insert_or_assign_hint_impl(const_iterator hint, K &&k, M &&obj) {
const std::pair<iterator, bool> ret = this->tree_.insert_hint_unique(
iterator(hint), k, std::forward<K>(k), std::forward<M>(obj));
if (!ret.second) ret.first->second = std::forward<M>(obj);
return ret.first;
}
template <class K, class... Args>
std::pair<iterator, bool> try_emplace_impl(K &&k, Args &&... args) {
return this->tree_.insert_unique(
k, std::piecewise_construct, std::forward_as_tuple(std::forward<K>(k)),
std::forward_as_tuple(std::forward<Args>(args)...));
}
template <class K, class... Args>
iterator try_emplace_hint_impl(const_iterator hint, K &&k, Args &&... args) {
return this->tree_
.insert_hint_unique(iterator(hint), k, std::piecewise_construct,
std::forward_as_tuple(std::forward<K>(k)),
std::forward_as_tuple(std::forward<Args>(args)...))
.first;
}
};
// A common base class for btree_multiset and btree_multimap.
template <typename Tree>
class btree_multiset_container : public btree_container<Tree> {
using super_type = btree_container<Tree>;
using params_type = typename Tree::params_type;
using init_type = typename params_type::init_type;
using is_key_compare_to = typename params_type::is_key_compare_to;
friend class BtreeNodePeer;
template <class K>
using key_arg = typename super_type::template key_arg<K>;
public:
using key_type = typename Tree::key_type;
using value_type = typename Tree::value_type;
using size_type = typename Tree::size_type;
using key_compare = typename Tree::original_key_compare;
using allocator_type = typename Tree::allocator_type;
using iterator = typename Tree::iterator;
using const_iterator = typename Tree::const_iterator;
using node_type = typename super_type::node_type;
// Inherit constructors.
using super_type::super_type;
btree_multiset_container() {}
// Range constructors.
template <class InputIterator>
btree_multiset_container(InputIterator b, InputIterator e,
const key_compare &comp = key_compare(),
const allocator_type &alloc = allocator_type())
: super_type(comp, alloc) {
insert(b, e);
}
template <class InputIterator>
btree_multiset_container(InputIterator b, InputIterator e,
const allocator_type &alloc)
: btree_multiset_container(b, e, key_compare(), alloc) {}
// Initializer list constructors.
btree_multiset_container(std::initializer_list<init_type> init,
const key_compare &comp = key_compare(),
const allocator_type &alloc = allocator_type())
: btree_multiset_container(init.begin(), init.end(), comp, alloc) {}
btree_multiset_container(std::initializer_list<init_type> init,
const allocator_type &alloc)
: btree_multiset_container(init.begin(), init.end(), alloc) {}
// Insertion routines.
iterator insert(const value_type &v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return this->tree_.insert_multi(v);
}
iterator insert(value_type &&v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return this->tree_.insert_multi(std::move(v));
}
iterator insert(const_iterator hint,
const value_type &v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return this->tree_.insert_hint_multi(iterator(hint), v);
}
iterator insert(const_iterator hint,
value_type &&v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
return this->tree_.insert_hint_multi(iterator(hint), std::move(v));
}
template <typename InputIterator>
void insert(InputIterator b, InputIterator e) {
this->tree_.insert_iterator_multi(b, e);
}
void insert(std::initializer_list<init_type> init) {
this->tree_.insert_iterator_multi(init.begin(), init.end());
}
template <typename... Args>
iterator emplace(Args &&...args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
// Use a node handle to manage a temp slot.
auto node = CommonAccess::Construct<node_type>(this->get_allocator(),
std::forward<Args>(args)...);
return this->tree_.insert_multi(CommonAccess::GetSlot(node));
}
template <typename... Args>
iterator emplace_hint(const_iterator hint,
Args &&...args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
// Use a node handle to manage a temp slot.
auto node = CommonAccess::Construct<node_type>(this->get_allocator(),
std::forward<Args>(args)...);
return this->tree_.insert_hint_multi(iterator(hint),
CommonAccess::GetSlot(node));
}
iterator insert(node_type &&node) ABSL_ATTRIBUTE_LIFETIME_BOUND {
if (!node) return this->end();
iterator res =
this->tree_.insert_multi(params_type::key(CommonAccess::GetSlot(node)),
CommonAccess::GetSlot(node));
CommonAccess::Destroy(&node);
return res;
}
iterator insert(const_iterator hint,
node_type &&node) ABSL_ATTRIBUTE_LIFETIME_BOUND {
if (!node) return this->end();
iterator res = this->tree_.insert_hint_multi(
iterator(hint),
std::move(params_type::element(CommonAccess::GetSlot(node))));
CommonAccess::Destroy(&node);
return res;
}
// Node extraction routines.
template <typename K = key_type>
node_type extract(const key_arg<K> &key) {
const std::pair<iterator, bool> lower_and_equal =
this->tree_.lower_bound_equal(key);
return lower_and_equal.second ? extract(lower_and_equal.first)
: node_type();
}
using super_type::extract;
// Merge routines.
// Moves all elements from `src` into `this`.
template <
typename T,
typename absl::enable_if_t<
absl::conjunction<
std::is_same<value_type, typename T::value_type>,
std::is_same<allocator_type, typename T::allocator_type>,
std::is_same<typename params_type::is_map_container,
typename T::params_type::is_map_container>>::value,
int> = 0>
void merge(btree_container<T> &src) { // NOLINT
for (auto src_it = src.begin(), end = src.end(); src_it != end; ++src_it) {
insert(std::move(params_type::element(src_it.slot())));
}
src.clear();
}
template <
typename T,
typename absl::enable_if_t<
absl::conjunction<
std::is_same<value_type, typename T::value_type>,
std::is_same<allocator_type, typename T::allocator_type>,
std::is_same<typename params_type::is_map_container,
typename T::params_type::is_map_container>>::value,
int> = 0>
void merge(btree_container<T> &&src) {
merge(src);
}
};
// A base class for btree_multimap.
template <typename Tree>
class btree_multimap_container : public btree_multiset_container<Tree> {
using super_type = btree_multiset_container<Tree>;
using params_type = typename Tree::params_type;
friend class BtreeNodePeer;
public:
using mapped_type = typename params_type::mapped_type;
// Inherit constructors.
using super_type::super_type;
btree_multimap_container() {}
};
} // namespace container_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_CONTAINER_INTERNAL_BTREE_CONTAINER_H_
*›
€soong/.intermediates/external/abseil-cpp/absl_strings_cord_internal_hdrs/gen/my_include_dir/absl/strings/internal/cord_rep_crc.h•// Copyright 2021 The Abseil Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_STRINGS_INTERNAL_CORD_REP_CRC_H_
#define ABSL_STRINGS_INTERNAL_CORD_REP_CRC_H_
#include <cassert>
#include <cstdint>
#include "absl/base/config.h"
#include "absl/base/optimization.h"
#include "absl/crc/internal/crc_cord_state.h"
#include "absl/strings/internal/cord_internal.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace cord_internal {
// CordRepCrc is a CordRep node intended only to appear at the top level of a
// cord tree. It associates an "expected CRC" with the contained data, to allow
// for easy passage of checksum data in Cord data flows.
//
// From Cord's perspective, the crc value has no semantics; any validation of
// the contained checksum is the user's responsibility.
struct CordRepCrc : public CordRep {
CordRep* child;
absl::crc_internal::CrcCordState crc_cord_state;
// Consumes `child` and returns a CordRepCrc prefixed tree containing `child`.
// If the specified `child` is itself a CordRepCrc node, then this method
// either replaces the existing node, or directly updates the crc state in it
// depending on the node being shared or not, i.e.: refcount.IsOne().
// `child` must only be null if the Cord is empty. Never returns null.
static CordRepCrc* New(CordRep* child, crc_internal::CrcCordState state);
// Destroys (deletes) the provided node. `node` must not be null.
static void Destroy(CordRepCrc* node);
};
// Consumes `rep` and returns a CordRep* with any outer CordRepCrc wrapper
// removed. This is usually a no-op (returning `rep`), but this will remove and
// unref an outer CordRepCrc node.
inline CordRep* RemoveCrcNode(CordRep* rep) {
assert(rep != nullptr);
if (ABSL_PREDICT_FALSE(rep->IsCrc())) {
CordRep* child = rep->crc()->child;
if (rep->refcount.IsOne()) {
delete rep->crc();
} else {
CordRep::Ref(child);
CordRep::Unref(rep);
}
return child;
}
return rep;
}
// Returns `rep` if it is not a CordRepCrc node, or its child if it is.
// Does not consume or create a reference on `rep` or the returned value.
inline CordRep* SkipCrcNode(CordRep* rep) {
assert(rep != nullptr);
if (ABSL_PREDICT_FALSE(rep->IsCrc())) {
return rep->crc()->child;
} else {
return rep;
}
}
inline const CordRep* SkipCrcNode(const CordRep* rep) {
assert(rep != nullptr);
if (ABSL_PREDICT_FALSE(rep->IsCrc())) {
return rep->crc()->child;
} else {
return rep;
}
}
inline CordRepCrc* CordRep::crc() {
assert(IsCrc());
return static_cast<CordRepCrc*>(this);
}
inline const CordRepCrc* CordRep::crc() const {
assert(IsCrc());
return static_cast<const CordRepCrc*>(this);
}
} // namespace cord_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_CORD_REP_CRC_H_
*÷‘
‹soong/.intermediates/external/abseil-cpp/absl_container_container_memory_hdrs/gen/my_include_dir/absl/container/internal/container_memory.hå// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_CONTAINER_INTERNAL_CONTAINER_MEMORY_H_
#define ABSL_CONTAINER_INTERNAL_CONTAINER_MEMORY_H_
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <memory>
#include <new>
#include <tuple>
#include <type_traits>
#include <utility>
#include "absl/base/config.h"
#include "absl/memory/memory.h"
#include "absl/meta/type_traits.h"
#include "absl/utility/utility.h"
#ifdef ABSL_HAVE_ADDRESS_SANITIZER
#include <sanitizer/asan_interface.h>
#endif
#ifdef ABSL_HAVE_MEMORY_SANITIZER
#include <sanitizer/msan_interface.h>
#endif
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace container_internal {
template <size_t Alignment>
struct alignas(Alignment) AlignedType {};
// Allocates at least n bytes aligned to the specified alignment.
// Alignment must be a power of 2. It must be positive.
//
// Note that many allocators don't honor alignment requirements above certain
// threshold (usually either alignof(std::max_align_t) or alignof(void*)).
// Allocate() doesn't apply alignment corrections. If the underlying allocator
// returns insufficiently alignment pointer, that's what you are going to get.
template <size_t Alignment, class Alloc>
void* Allocate(Alloc* alloc, size_t n) {
static_assert(Alignment > 0, "");
assert(n && "n must be positive");
using M = AlignedType<Alignment>;
using A = typename absl::allocator_traits<Alloc>::template rebind_alloc<M>;
using AT = typename absl::allocator_traits<Alloc>::template rebind_traits<M>;
// On macOS, "mem_alloc" is a #define with one argument defined in
// rpc/types.h, so we can't name the variable "mem_alloc" and initialize it
// with the "foo(bar)" syntax.
A my_mem_alloc(*alloc);
void* p = AT::allocate(my_mem_alloc, (n + sizeof(M) - 1) / sizeof(M));
assert(reinterpret_cast<uintptr_t>(p) % Alignment == 0 &&
"allocator does not respect alignment");
return p;
}
// Returns true if the destruction of the value with given Allocator will be
// trivial.
template <class Allocator, class ValueType>
constexpr auto IsDestructionTrivial() {
constexpr bool result =
std::is_trivially_destructible<ValueType>::value &&
std::is_same<typename absl::allocator_traits<
Allocator>::template rebind_alloc<char>,
std::allocator<char>>::value;
return std::integral_constant<bool, result>();
}
// The pointer must have been previously obtained by calling
// Allocate<Alignment>(alloc, n).
template <size_t Alignment, class Alloc>
void Deallocate(Alloc* alloc, void* p, size_t n) {
static_assert(Alignment > 0, "");
assert(n && "n must be positive");
using M = AlignedType<Alignment>;
using A = typename absl::allocator_traits<Alloc>::template rebind_alloc<M>;
using AT = typename absl::allocator_traits<Alloc>::template rebind_traits<M>;
// On macOS, "mem_alloc" is a #define with one argument defined in
// rpc/types.h, so we can't name the variable "mem_alloc" and initialize it
// with the "foo(bar)" syntax.
A my_mem_alloc(*alloc);
AT::deallocate(my_mem_alloc, static_cast<M*>(p),
(n + sizeof(M) - 1) / sizeof(M));
}
namespace memory_internal {
// Constructs T into uninitialized storage pointed by `ptr` using the args
// specified in the tuple.
template <class Alloc, class T, class Tuple, size_t... I>
void ConstructFromTupleImpl(Alloc* alloc, T* ptr, Tuple&& t,
absl::index_sequence<I...>) {
absl::allocator_traits<Alloc>::construct(
*alloc, ptr, std::get<I>(std::forward<Tuple>(t))...);
}
template <class T, class F>
struct WithConstructedImplF {
template <class... Args>
decltype(std::declval<F>()(std::declval<T>())) operator()(
Args&&... args) const {
return std::forward<F>(f)(T(std::forward<Args>(args)...));
}
F&& f;
};
template <class T, class Tuple, size_t... Is, class F>
decltype(std::declval<F>()(std::declval<T>())) WithConstructedImpl(
Tuple&& t, absl::index_sequence<Is...>, F&& f) {
return WithConstructedImplF<T, F>{std::forward<F>(f)}(
std::get<Is>(std::forward<Tuple>(t))...);
}
template <class T, size_t... Is>
auto TupleRefImpl(T&& t, absl::index_sequence<Is...>)
-> decltype(std::forward_as_tuple(std::get<Is>(std::forward<T>(t))...)) {
return std::forward_as_tuple(std::get<Is>(std::forward<T>(t))...);
}
// Returns a tuple of references to the elements of the input tuple. T must be a
// tuple.
template <class T>
auto TupleRef(T&& t) -> decltype(TupleRefImpl(
std::forward<T>(t),
absl::make_index_sequence<
std::tuple_size<typename std::decay<T>::type>::value>())) {
return TupleRefImpl(
std::forward<T>(t),
absl::make_index_sequence<
std::tuple_size<typename std::decay<T>::type>::value>());
}
template <class F, class K, class V>
decltype(std::declval<F>()(std::declval<const K&>(), std::piecewise_construct,
std::declval<std::tuple<K>>(), std::declval<V>()))
DecomposePairImpl(F&& f, std::pair<std::tuple<K>, V> p) {
const auto& key = std::get<0>(p.first);
return std::forward<F>(f)(key, std::piecewise_construct, std::move(p.first),
std::move(p.second));
}
} // namespace memory_internal
// Constructs T into uninitialized storage pointed by `ptr` using the args
// specified in the tuple.
template <class Alloc, class T, class Tuple>
void ConstructFromTuple(Alloc* alloc, T* ptr, Tuple&& t) {
memory_internal::ConstructFromTupleImpl(
alloc, ptr, std::forward<Tuple>(t),
absl::make_index_sequence<
std::tuple_size<typename std::decay<Tuple>::type>::value>());
}
// Constructs T using the args specified in the tuple and calls F with the
// constructed value.
template <class T, class Tuple, class F>
decltype(std::declval<F>()(std::declval<T>())) WithConstructed(Tuple&& t,
F&& f) {
return memory_internal::WithConstructedImpl<T>(
std::forward<Tuple>(t),
absl::make_index_sequence<
std::tuple_size<typename std::decay<Tuple>::type>::value>(),
std::forward<F>(f));
}
// Given arguments of an std::pair's constructor, PairArgs() returns a pair of
// tuples with references to the passed arguments. The tuples contain
// constructor arguments for the first and the second elements of the pair.
//
// The following two snippets are equivalent.
//
// 1. std::pair<F, S> p(args...);
//
// 2. auto a = PairArgs(args...);
// std::pair<F, S> p(std::piecewise_construct,
// std::move(a.first), std::move(a.second));
inline std::pair<std::tuple<>, std::tuple<>> PairArgs() { return {}; }
template <class F, class S>
std::pair<std::tuple<F&&>, std::tuple<S&&>> PairArgs(F&& f, S&& s) {
return {std::piecewise_construct, std::forward_as_tuple(std::forward<F>(f)),
std::forward_as_tuple(std::forward<S>(s))};
}
template <class F, class S>
std::pair<std::tuple<const F&>, std::tuple<const S&>> PairArgs(
const std::pair<F, S>& p) {
return PairArgs(p.first, p.second);
}
template <class F, class S>
std::pair<std::tuple<F&&>, std::tuple<S&&>> PairArgs(std::pair<F, S>&& p) {
return PairArgs(std::forward<F>(p.first), std::forward<S>(p.second));
}
template <class F, class S>
auto PairArgs(std::piecewise_construct_t, F&& f, S&& s)
-> decltype(std::make_pair(memory_internal::TupleRef(std::forward<F>(f)),
memory_internal::TupleRef(std::forward<S>(s)))) {
return std::make_pair(memory_internal::TupleRef(std::forward<F>(f)),
memory_internal::TupleRef(std::forward<S>(s)));
}
// A helper function for implementing apply() in map policies.
template <class F, class... Args>
auto DecomposePair(F&& f, Args&&... args)
-> decltype(memory_internal::DecomposePairImpl(
std::forward<F>(f), PairArgs(std::forward<Args>(args)...))) {
return memory_internal::DecomposePairImpl(
std::forward<F>(f), PairArgs(std::forward<Args>(args)...));
}
// A helper function for implementing apply() in set policies.
template <class F, class Arg>
decltype(std::declval<F>()(std::declval<const Arg&>(), std::declval<Arg>()))
DecomposeValue(F&& f, Arg&& arg) {
const auto& key = arg;
return std::forward<F>(f)(key, std::forward<Arg>(arg));
}
// Helper functions for asan and msan.
inline void SanitizerPoisonMemoryRegion(const void* m, size_t s) {
#ifdef ABSL_HAVE_ADDRESS_SANITIZER
ASAN_POISON_MEMORY_REGION(m, s);
#endif
#ifdef ABSL_HAVE_MEMORY_SANITIZER
__msan_poison(m, s);
#endif
(void)m;
(void)s;
}
inline void SanitizerUnpoisonMemoryRegion(const void* m, size_t s) {
#ifdef ABSL_HAVE_ADDRESS_SANITIZER
ASAN_UNPOISON_MEMORY_REGION(m, s);
#endif
#ifdef ABSL_HAVE_MEMORY_SANITIZER
__msan_unpoison(m, s);
#endif
(void)m;
(void)s;
}
template <typename T>
inline void SanitizerPoisonObject(const T* object) {
SanitizerPoisonMemoryRegion(object, sizeof(T));
}
template <typename T>
inline void SanitizerUnpoisonObject(const T* object) {
SanitizerUnpoisonMemoryRegion(object, sizeof(T));
}
namespace memory_internal {
// If Pair is a standard-layout type, OffsetOf<Pair>::kFirst and
// OffsetOf<Pair>::kSecond are equivalent to offsetof(Pair, first) and
// offsetof(Pair, second) respectively. Otherwise they are -1.
//
// The purpose of OffsetOf is to avoid calling offsetof() on non-standard-layout
// type, which is non-portable.
template <class Pair, class = std::true_type>
struct OffsetOf {
static constexpr size_t kFirst = static_cast<size_t>(-1);
static constexpr size_t kSecond = static_cast<size_t>(-1);
};
template <class Pair>
struct OffsetOf<Pair, typename std::is_standard_layout<Pair>::type> {
static constexpr size_t kFirst = offsetof(Pair, first);
static constexpr size_t kSecond = offsetof(Pair, second);
};
template <class K, class V>
struct IsLayoutCompatible {
private:
struct Pair {
K first;
V second;
};
// Is P layout-compatible with Pair?
template <class P>
static constexpr bool LayoutCompatible() {
return std::is_standard_layout<P>() && sizeof(P) == sizeof(Pair) &&
alignof(P) == alignof(Pair) &&
memory_internal::OffsetOf<P>::kFirst ==
memory_internal::OffsetOf<Pair>::kFirst &&
memory_internal::OffsetOf<P>::kSecond ==
memory_internal::OffsetOf<Pair>::kSecond;
}
public:
// Whether pair<const K, V> and pair<K, V> are layout-compatible. If they are,
// then it is safe to store them in a union and read from either.
static constexpr bool value = std::is_standard_layout<K>() &&
std::is_standard_layout<Pair>() &&
memory_internal::OffsetOf<Pair>::kFirst == 0 &&
LayoutCompatible<std::pair<K, V>>() &&
LayoutCompatible<std::pair<const K, V>>();
};
} // namespace memory_internal
// The internal storage type for key-value containers like flat_hash_map.
//
// It is convenient for the value_type of a flat_hash_map<K, V> to be
// pair<const K, V>; the "const K" prevents accidental modification of the key
// when dealing with the reference returned from find() and similar methods.
// However, this creates other problems; we want to be able to emplace(K, V)
// efficiently with move operations, and similarly be able to move a
// pair<K, V> in insert().
//
// The solution is this union, which aliases the const and non-const versions
// of the pair. This also allows flat_hash_map<const K, V> to work, even though
// that has the same efficiency issues with move in emplace() and insert() -
// but people do it anyway.
//
// If kMutableKeys is false, only the value member can be accessed.
//
// If kMutableKeys is true, key can be accessed through all slots while value
// and mutable_value must be accessed only via INITIALIZED slots. Slots are
// created and destroyed via mutable_value so that the key can be moved later.
//
// Accessing one of the union fields while the other is active is safe as
// long as they are layout-compatible, which is guaranteed by the definition of
// kMutableKeys. For C++11, the relevant section of the standard is
// https://timsong-cpp.github.io/cppwp/n3337/class.mem#19 (9.2.19)
template <class K, class V>
union map_slot_type {
map_slot_type() {}
~map_slot_type() = delete;
using value_type = std::pair<const K, V>;
using mutable_value_type =
std::pair<absl::remove_const_t<K>, absl::remove_const_t<V>>;
value_type value;
mutable_value_type mutable_value;
absl::remove_const_t<K> key;
};
template <class K, class V>
struct map_slot_policy {
using slot_type = map_slot_type<K, V>;
using value_type = std::pair<const K, V>;
using mutable_value_type =
std::pair<absl::remove_const_t<K>, absl::remove_const_t<V>>;
private:
static void emplace(slot_type* slot) {
// The construction of union doesn't do anything at runtime but it allows us
// to access its members without violating aliasing rules.
new (slot) slot_type;
}
// If pair<const K, V> and pair<K, V> are layout-compatible, we can accept one
// or the other via slot_type. We are also free to access the key via
// slot_type::key in this case.
using kMutableKeys = memory_internal::IsLayoutCompatible<K, V>;
public:
static value_type& element(slot_type* slot) { return slot->value; }
static const value_type& element(const slot_type* slot) {
return slot->value;
}
static K& mutable_key(slot_type* slot) {
// Still check for kMutableKeys so that we can avoid calling std::launder
// unless necessary because it can interfere with optimizations.
return kMutableKeys::value ? slot->key
: *std::launder(const_cast<K*>(
std::addressof(slot->value.first)));
}
static const K& key(const slot_type* slot) {
return kMutableKeys::value ? slot->key : slot->value.first;
}
template <class Allocator, class... Args>
static void construct(Allocator* alloc, slot_type* slot, Args&&... args) {
emplace(slot);
if (kMutableKeys::value) {
absl::allocator_traits<Allocator>::construct(*alloc, &slot->mutable_value,
std::forward<Args>(args)...);
} else {
absl::allocator_traits<Allocator>::construct(*alloc, &slot->value,
std::forward<Args>(args)...);
}
}
// Construct this slot by moving from another slot.
template <class Allocator>
static void construct(Allocator* alloc, slot_type* slot, slot_type* other) {
emplace(slot);
if (kMutableKeys::value) {
absl::allocator_traits<Allocator>::construct(
*alloc, &slot->mutable_value, std::move(other->mutable_value));
} else {
absl::allocator_traits<Allocator>::construct(*alloc, &slot->value,
std::move(other->value));
}
}
// Construct this slot by copying from another slot.
template <class Allocator>
static void construct(Allocator* alloc, slot_type* slot,
const slot_type* other) {
emplace(slot);
absl::allocator_traits<Allocator>::construct(*alloc, &slot->value,
other->value);
}
template <class Allocator>
static auto destroy(Allocator* alloc, slot_type* slot) {
if (kMutableKeys::value) {
absl::allocator_traits<Allocator>::destroy(*alloc, &slot->mutable_value);
} else {
absl::allocator_traits<Allocator>::destroy(*alloc, &slot->value);
}
return IsDestructionTrivial<Allocator, value_type>();
}
template <class Allocator>
static auto transfer(Allocator* alloc, slot_type* new_slot,
slot_type* old_slot) {
// This should really just be
// typename absl::is_trivially_relocatable<value_type>::type()
// but std::pair is not trivially copyable in C++23 in some standard
// library versions.
// See https://github.com/llvm/llvm-project/pull/95444 for instance.
auto is_relocatable = typename std::conjunction<
absl::is_trivially_relocatable<typename value_type::first_type>,
absl::is_trivially_relocatable<typename value_type::second_type>>::
type();
emplace(new_slot);
if (is_relocatable) {
// TODO(b/247130232,b/251814870): remove casts after fixing warnings.
std::memcpy(static_cast<void*>(std::launder(&new_slot->value)),
static_cast<const void*>(&old_slot->value),
sizeof(value_type));
return is_relocatable;
}
if (kMutableKeys::value) {
absl::allocator_traits<Allocator>::construct(
*alloc, &new_slot->mutable_value, std::move(old_slot->mutable_value));
} else {
absl::allocator_traits<Allocator>::construct(*alloc, &new_slot->value,
std::move(old_slot->value));
}
destroy(alloc, old_slot);
return is_relocatable;
}
};
// Type erased function for computing hash of the slot.
using HashSlotFn = size_t (*)(const void* hash_fn, void* slot);
// Type erased function to apply `Fn` to data inside of the `slot`.
// The data is expected to have type `T`.
template <class Fn, class T>
size_t TypeErasedApplyToSlotFn(const void* fn, void* slot) {
const auto* f = static_cast<const Fn*>(fn);
return (*f)(*static_cast<const T*>(slot));
}
// Type erased function to apply `Fn` to data inside of the `*slot_ptr`.
// The data is expected to have type `T`.
template <class Fn, class T>
size_t TypeErasedDerefAndApplyToSlotFn(const void* fn, void* slot_ptr) {
const auto* f = static_cast<const Fn*>(fn);
const T* slot = *static_cast<const T**>(slot_ptr);
return (*f)(*slot);
}
} // namespace container_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_CONTAINER_INTERNAL_CONTAINER_MEMORY_H_
*ÿ1
~soong/.intermediates/external/abseil-cpp/absl_log_internal_vlog_config_hdrs/gen/my_include_dir/absl/log/internal/vlog_config.hü0// Copyright 2022 The Abseil Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// vlog_config.h
// -----------------------------------------------------------------------------
//
// This header file defines `VLogSite`, a public primitive that represents
// a callsite for the `VLOG` family of macros and related libraries.
// It also declares and defines multiple internal utilities used to implement
// `VLOG`, such as `VLogSiteManager`.
#ifndef ABSL_LOG_INTERNAL_VLOG_CONFIG_H_
#define ABSL_LOG_INTERNAL_VLOG_CONFIG_H_
// IWYU pragma: private, include "absl/log/log.h"
#include <atomic>
#include <cstdint>
#include <functional>
#include <limits>
#include <type_traits>
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/nullability.h"
#include "absl/base/optimization.h"
#include "absl/base/thread_annotations.h"
#include "absl/strings/string_view.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace log_internal {
class SyntheticBinary;
class VLogSite;
int RegisterAndInitialize(VLogSite* absl_nonnull v);
void UpdateVLogSites();
constexpr int kUseFlag = (std::numeric_limits<int16_t>::min)();
// Represents a unique callsite for a `VLOG()` or `VLOG_IS_ON()` call.
//
// Libraries that provide `VLOG`-like functionality should use this to
// efficiently handle --vmodule.
//
// VLogSite objects must not be destroyed until the program exits. Doing so will
// probably yield nasty segfaults in VLogSiteManager::UpdateLogSites(). The
// recommendation is to make all such objects function-local statics.
class VLogSite final {
public:
// `f` must not be destroyed until the program exits.
explicit constexpr VLogSite(const char* absl_nonnull f)
: file_(f), v_(kUninitialized), next_(nullptr) {}
VLogSite(const VLogSite&) = delete;
VLogSite& operator=(const VLogSite&) = delete;
// Inlining the function yields a ~3x performance improvement at the cost of a
// 1.5x code size increase at the call site.
// Takes locks but does not allocate memory.
ABSL_ATTRIBUTE_ALWAYS_INLINE
bool IsEnabled(int level) {
int stale_v = v_.load(std::memory_order_relaxed);
if (ABSL_PREDICT_TRUE(level > stale_v)) {
return false;
}
// We put everything other than the fast path, i.e. vlogging is initialized
// but not on, behind an out-of-line function to reduce code size.
// "level" is almost always a call-site constant, so we can save a bit
// of code space by special-casing for a few common levels.
#if ABSL_HAVE_BUILTIN(__builtin_constant_p) || defined(__GNUC__)
if (__builtin_constant_p(level)) {
if (level == 0) return SlowIsEnabled0(stale_v);
if (level == 1) return SlowIsEnabled1(stale_v);
if (level == 2) return SlowIsEnabled2(stale_v);
if (level == 3) return SlowIsEnabled3(stale_v);
if (level == 4) return SlowIsEnabled4(stale_v);
if (level == 5) return SlowIsEnabled5(stale_v);
}
#endif
return SlowIsEnabled(stale_v, level);
}
private:
friend int log_internal::RegisterAndInitialize(VLogSite* absl_nonnull v);
friend void log_internal::UpdateVLogSites();
friend class log_internal::SyntheticBinary;
static constexpr int kUninitialized = (std::numeric_limits<int>::max)();
// SlowIsEnabled performs slower checks to determine whether a log site is
// enabled. Because it is expected to be called somewhat rarely
// (comparatively), it is not inlined to save on code size.
//
// Prerequisites to calling SlowIsEnabled:
// 1) stale_v is uninitialized OR
// 2) stale_v is initialized and >= level (meaning we must log).
// Takes locks but does not allocate memory.
ABSL_ATTRIBUTE_NOINLINE
bool SlowIsEnabled(int stale_v, int level);
ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled0(int stale_v);
ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled1(int stale_v);
ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled2(int stale_v);
ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled3(int stale_v);
ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled4(int stale_v);
ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled5(int stale_v);
// This object is too size-sensitive to use absl::string_view.
const char* absl_nonnull const file_;
std::atomic<int> v_;
std::atomic<VLogSite*> next_;
};
static_assert(std::is_trivially_destructible<VLogSite>::value,
"VLogSite must be trivially destructible");
// Returns the current verbose log level of `file`.
// Does not allocate memory.
int VLogLevel(absl::string_view file);
// Registers a site `v` to get updated as `vmodule` and `v` change. Also
// initializes the site based on their current values, and returns that result.
// Does not allocate memory.
int RegisterAndInitialize(VLogSite* absl_nonnull v);
// Allocates memory.
void UpdateVLogSites();
// Completely overwrites the saved value of `vmodule`.
// Allocates memory.
void UpdateVModule(absl::string_view vmodule);
// Updates the global verbosity level to `v` and returns the prior value.
// Allocates memory.
int UpdateGlobalVLogLevel(int v);
// Atomically prepends `module_pattern=log_level` to the start of vmodule.
// Returns the prior value for `module_pattern` if there was an exact match and
// `global_v` otherwise.
// Allocates memory.
int PrependVModule(absl::string_view module_pattern, int log_level);
// Registers `on_update` to be called whenever `v` or `vmodule` change.
// Allocates memory.
void OnVLogVerbosityUpdate(std::function<void()> cb);
// Does not allocate memory.
VLogSite* absl_nullable SetVModuleListHeadForTestOnly(
VLogSite* absl_nullable v);
} // namespace log_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_LOG_INTERNAL_VLOG_CONFIG_H_
*¶å
tsoong/.intermediates/external/abseil-cpp/absl_strings_string_view_hdrs/gen/my_include_dir/absl/strings/string_view.h¼ä//
// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: string_view.h
// -----------------------------------------------------------------------------
//
// This file contains the definition of the `absl::string_view` class. A
// `string_view` points to a contiguous span of characters, often part or all of
// another `std::string`, double-quoted string literal, character array, or even
// another `string_view`.
//
// This `absl::string_view` abstraction is designed to be a drop-in
// replacement for the C++17 `std::string_view` abstraction.
#ifndef ABSL_STRINGS_STRING_VIEW_H_
#define ABSL_STRINGS_STRING_VIEW_H_
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstring>
#include <iosfwd>
#include <iterator>
#include <limits>
#include <string>
#include "absl/base/attributes.h"
#include "absl/base/nullability.h"
#include "absl/base/config.h"
#include "absl/base/internal/throw_delegate.h"
#include "absl/base/macros.h"
#include "absl/base/optimization.h"
#include "absl/base/port.h"
#ifdef ABSL_USES_STD_STRING_VIEW
#include <string_view> // IWYU pragma: export
namespace absl {
ABSL_NAMESPACE_BEGIN
using string_view = std::string_view;
ABSL_NAMESPACE_END
} // namespace absl
#else // ABSL_USES_STD_STRING_VIEW
#if ABSL_HAVE_BUILTIN(__builtin_memcmp) || \
(defined(__GNUC__) && !defined(__clang__)) || \
(defined(_MSC_VER) && _MSC_VER >= 1928)
#define ABSL_INTERNAL_STRING_VIEW_MEMCMP __builtin_memcmp
#else // ABSL_HAVE_BUILTIN(__builtin_memcmp)
#define ABSL_INTERNAL_STRING_VIEW_MEMCMP memcmp
#endif // ABSL_HAVE_BUILTIN(__builtin_memcmp)
namespace absl {
ABSL_NAMESPACE_BEGIN
// absl::string_view
//
// A `string_view` provides a lightweight view into the string data provided by
// a `std::string`, double-quoted string literal, character array, or even
// another `string_view`. A `string_view` does *not* own the string to which it
// points, and that data cannot be modified through the view.
//
// You can use `string_view` as a function or method parameter anywhere a
// parameter can receive a double-quoted string literal, `const char*`,
// `std::string`, or another `absl::string_view` argument with no need to copy
// the string data. Systematic use of `string_view` within function arguments
// reduces data copies and `strlen()` calls.
//
// Because of its small size, prefer passing `string_view` by value:
//
// void MyFunction(absl::string_view arg);
//
// If circumstances require, you may also pass one by const reference:
//
// void MyFunction(const absl::string_view& arg); // not preferred
//
// Passing by value generates slightly smaller code for many architectures.
//
// In either case, the source data of the `string_view` must outlive the
// `string_view` itself.
//
// A `string_view` is also suitable for local variables if you know that the
// lifetime of the underlying object is longer than the lifetime of your
// `string_view` variable. However, beware of binding a `string_view` to a
// temporary value:
//
// // BAD use of string_view: lifetime problem
// absl::string_view sv = obj.ReturnAString();
//
// // GOOD use of string_view: str outlives sv
// std::string str = obj.ReturnAString();
// absl::string_view sv = str;
//
// Due to lifetime issues, a `string_view` is sometimes a poor choice for a
// return value and usually a poor choice for a data member. If you do use a
// `string_view` this way, it is your responsibility to ensure that the object
// pointed to by the `string_view` outlives the `string_view`.
//
// A `string_view` may represent a whole string or just part of a string. For
// example, when splitting a string, `std::vector<absl::string_view>` is a
// natural data type for the output.
//
// For another example, a Cord is a non-contiguous, potentially very
// long string-like object. The Cord class has an interface that iteratively
// provides string_view objects that point to the successive pieces of a Cord
// object.
//
// When constructed from a source which is NUL-terminated, the `string_view`
// itself will not include the NUL-terminator unless a specific size (including
// the NUL) is passed to the constructor. As a result, common idioms that work
// on NUL-terminated strings do not work on `string_view` objects. If you write
// code that scans a `string_view`, you must check its length rather than test
// for nul, for example. Note, however, that nuls may still be embedded within
// a `string_view` explicitly.
//
// You may create a null `string_view` in two ways:
//
// absl::string_view sv;
// absl::string_view sv(nullptr, 0);
//
// For the above, `sv.data() == nullptr`, `sv.length() == 0`, and
// `sv.empty() == true`. Also, if you create a `string_view` with a non-null
// pointer then `sv.data() != nullptr`. Thus, you can use `string_view()` to
// signal an undefined value that is different from other `string_view` values
// in a similar fashion to how `const char* p1 = nullptr;` is different from
// `const char* p2 = "";`. However, in practice, it is not recommended to rely
// on this behavior.
//
// Be careful not to confuse a null `string_view` with an empty one. A null
// `string_view` is an empty `string_view`, but some empty `string_view`s are
// not null. Prefer checking for emptiness over checking for null.
//
// There are many ways to create an empty string_view:
//
// const char* nullcp = nullptr;
// // string_view.size() will return 0 in all cases.
// absl::string_view();
// absl::string_view(nullcp, 0);
// absl::string_view("");
// absl::string_view("", 0);
// absl::string_view("abcdef", 0);
// absl::string_view("abcdef" + 6, 0);
//
// All empty `string_view` objects whether null or not, are equal:
//
// absl::string_view() == absl::string_view("", 0)
// absl::string_view(nullptr, 0) == absl::string_view("abcdef"+6, 0)
class ABSL_ATTRIBUTE_VIEW string_view {
public:
using traits_type = std::char_traits<char>;
using value_type = char;
using pointer = char* absl_nullable;
using const_pointer = const char* absl_nullable;
using reference = char&;
using const_reference = const char&;
using const_iterator = const char* absl_nullable;
using iterator = const_iterator;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
using reverse_iterator = const_reverse_iterator;
using size_type = size_t;
using difference_type = std::ptrdiff_t;
using absl_internal_is_view = std::true_type;
static constexpr size_type npos = static_cast<size_type>(-1);
// Null `string_view` constructor
constexpr string_view() noexcept : ptr_(nullptr), length_(0) {}
// Implicit constructors
template <typename Allocator>
string_view( // NOLINT(runtime/explicit)
const std::basic_string<char, std::char_traits<char>, Allocator>& str
ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept
// This is implemented in terms of `string_view(p, n)` so `str.size()`
// doesn't need to be reevaluated after `ptr_` is set.
// The length check is also skipped since it is unnecessary and causes
// code bloat.
: string_view(str.data(), str.size(), SkipCheckLengthTag{}) {}
// Implicit constructor of a `string_view` from NUL-terminated `str`. When
// accepting possibly null strings, use `absl::NullSafeStringView(str)`
// instead (see below).
// The length check is skipped since it is unnecessary and causes code bloat.
constexpr string_view( // NOLINT(runtime/explicit)
const char* absl_nonnull str)
: ptr_(str), length_(str ? StrlenInternal(str) : 0) {}
// Constructor of a `string_view` from a `const char*` and length.
constexpr string_view(const char* absl_nullable data, size_type len)
: ptr_(data), length_(CheckLengthInternal(len)) {}
constexpr string_view(const string_view&) noexcept = default;
string_view& operator=(const string_view&) noexcept = default;
// Iterators
// string_view::begin()
//
// Returns an iterator pointing to the first character at the beginning of the
// `string_view`, or `end()` if the `string_view` is empty.
constexpr const_iterator begin() const noexcept { return ptr_; }
// string_view::end()
//
// Returns an iterator pointing just beyond the last character at the end of
// the `string_view`. This iterator acts as a placeholder; attempting to
// access it results in undefined behavior.
constexpr const_iterator end() const noexcept { return ptr_ + length_; }
// string_view::cbegin()
//
// Returns a const iterator pointing to the first character at the beginning
// of the `string_view`, or `end()` if the `string_view` is empty.
constexpr const_iterator cbegin() const noexcept { return begin(); }
// string_view::cend()
//
// Returns a const iterator pointing just beyond the last character at the end
// of the `string_view`. This pointer acts as a placeholder; attempting to
// access its element results in undefined behavior.
constexpr const_iterator cend() const noexcept { return end(); }
// string_view::rbegin()
//
// Returns a reverse iterator pointing to the last character at the end of the
// `string_view`, or `rend()` if the `string_view` is empty.
const_reverse_iterator rbegin() const noexcept {
return const_reverse_iterator(end());
}
// string_view::rend()
//
// Returns a reverse iterator pointing just before the first character at the
// beginning of the `string_view`. This pointer acts as a placeholder;
// attempting to access its element results in undefined behavior.
const_reverse_iterator rend() const noexcept {
return const_reverse_iterator(begin());
}
// string_view::crbegin()
//
// Returns a const reverse iterator pointing to the last character at the end
// of the `string_view`, or `crend()` if the `string_view` is empty.
const_reverse_iterator crbegin() const noexcept { return rbegin(); }
// string_view::crend()
//
// Returns a const reverse iterator pointing just before the first character
// at the beginning of the `string_view`. This pointer acts as a placeholder;
// attempting to access its element results in undefined behavior.
const_reverse_iterator crend() const noexcept { return rend(); }
// Capacity Utilities
// string_view::size()
//
// Returns the number of characters in the `string_view`.
constexpr size_type size() const noexcept { return length_; }
// string_view::length()
//
// Returns the number of characters in the `string_view`. Alias for `size()`.
constexpr size_type length() const noexcept { return size(); }
// string_view::max_size()
//
// Returns the maximum number of characters the `string_view` can hold.
constexpr size_type max_size() const noexcept { return kMaxSize; }
// string_view::empty()
//
// Checks if the `string_view` is empty (refers to no characters).
constexpr bool empty() const noexcept { return length_ == 0; }
// string_view::operator[]
//
// Returns the ith element of the `string_view` using the array operator.
// Note that this operator does not perform any bounds checking.
constexpr const_reference operator[](size_type i) const {
ABSL_HARDENING_ASSERT(i < size());
return ptr_[i];
}
// string_view::at()
//
// Returns the ith element of the `string_view`. Bounds checking is performed,
// and an exception of type `std::out_of_range` will be thrown on invalid
// access.
constexpr const_reference at(size_type i) const {
if (ABSL_PREDICT_FALSE(i >= size())) {
base_internal::ThrowStdOutOfRange("absl::string_view::at");
}
return ptr_[i];
}
// string_view::front()
//
// Returns the first element of a `string_view`.
constexpr const_reference front() const {
ABSL_HARDENING_ASSERT(!empty());
return ptr_[0];
}
// string_view::back()
//
// Returns the last element of a `string_view`.
constexpr const_reference back() const {
ABSL_HARDENING_ASSERT(!empty());
return ptr_[size() - 1];
}
// string_view::data()
//
// Returns a pointer to the underlying character array (which is of course
// stored elsewhere). Note that `string_view::data()` may contain embedded nul
// characters, but the returned buffer may or may not be NUL-terminated;
// therefore, do not pass `data()` to a routine that expects a NUL-terminated
// string.
constexpr const_pointer data() const noexcept { return ptr_; }
// Modifiers
// string_view::remove_prefix()
//
// Removes the first `n` characters from the `string_view`. Note that the
// underlying string is not changed, only the view.
constexpr void remove_prefix(size_type n) {
ABSL_HARDENING_ASSERT(n <= length_);
ptr_ += n;
length_ -= n;
}
// string_view::remove_suffix()
//
// Removes the last `n` characters from the `string_view`. Note that the
// underlying string is not changed, only the view.
constexpr void remove_suffix(size_type n) {
ABSL_HARDENING_ASSERT(n <= length_);
length_ -= n;
}
// string_view::swap()
//
// Swaps this `string_view` with another `string_view`.
constexpr void swap(string_view& s) noexcept {
auto t = *this;
*this = s;
s = t;
}
// Explicit conversion operators
// Converts to `std::basic_string`.
template <typename A>
explicit operator std::basic_string<char, traits_type, A>() const {
if (!data()) return {};
return std::basic_string<char, traits_type, A>(data(), size());
}
// string_view::copy()
//
// Copies the contents of the `string_view` at offset `pos` and length `n`
// into `buf`.
size_type copy(char* buf, size_type n, size_type pos = 0) const {
if (ABSL_PREDICT_FALSE(pos > length_)) {
base_internal::ThrowStdOutOfRange("absl::string_view::copy");
}
size_type rlen = (std::min)(length_ - pos, n);
if (rlen > 0) {
const char* start = ptr_ + pos;
traits_type::copy(buf, start, rlen);
}
return rlen;
}
// string_view::substr()
//
// Returns a "substring" of the `string_view` (at offset `pos` and length
// `n`) as another string_view. This function throws `std::out_of_bounds` if
// `pos > size`.
// Use absl::ClippedSubstr if you need a truncating substr operation.
constexpr string_view substr(size_type pos = 0, size_type n = npos) const {
if (ABSL_PREDICT_FALSE(pos > length_)) {
base_internal::ThrowStdOutOfRange("absl::string_view::substr");
}
return string_view(ptr_ + pos, (std::min)(n, length_ - pos));
}
// string_view::compare()
//
// Performs a lexicographical comparison between this `string_view` and
// another `string_view` `x`, returning a negative value if `*this` is less
// than `x`, 0 if `*this` is equal to `x`, and a positive value if `*this`
// is greater than `x`.
constexpr int compare(string_view x) const noexcept {
return CompareImpl(length_, x.length_,
(std::min)(length_, x.length_) == 0
? 0
: ABSL_INTERNAL_STRING_VIEW_MEMCMP(
ptr_, x.ptr_, (std::min)(length_, x.length_)));
}
// Overload of `string_view::compare()` for comparing a substring of the
// 'string_view` and another `absl::string_view`.
constexpr int compare(size_type pos1, size_type count1, string_view v) const {
return substr(pos1, count1).compare(v);
}
// Overload of `string_view::compare()` for comparing a substring of the
// `string_view` and a substring of another `absl::string_view`.
constexpr int compare(size_type pos1, size_type count1, string_view v,
size_type pos2, size_type count2) const {
return substr(pos1, count1).compare(v.substr(pos2, count2));
}
// Overload of `string_view::compare()` for comparing a `string_view` and a
// a different C-style string `s`.
constexpr int compare(const char* absl_nonnull s) const {
return compare(string_view(s));
}
// Overload of `string_view::compare()` for comparing a substring of the
// `string_view` and a different string C-style string `s`.
constexpr int compare(size_type pos1, size_type count1,
const char* absl_nonnull s) const {
return substr(pos1, count1).compare(string_view(s));
}
// Overload of `string_view::compare()` for comparing a substring of the
// `string_view` and a substring of a different C-style string `s`.
constexpr int compare(size_type pos1, size_type count1,
const char* absl_nonnull s, size_type count2) const {
return substr(pos1, count1).compare(string_view(s, count2));
}
// Find Utilities
// string_view::find()
//
// Finds the first occurrence of the substring `s` within the `string_view`,
// returning the position of the first character's match, or `npos` if no
// match was found.
size_type find(string_view s, size_type pos = 0) const noexcept;
// Overload of `string_view::find()` for finding the given character `c`
// within the `string_view`.
size_type find(char c, size_type pos = 0) const noexcept;
// Overload of `string_view::find()` for finding a substring of a different
// C-style string `s` within the `string_view`.
size_type find(const char* absl_nonnull s, size_type pos,
size_type count) const {
return find(string_view(s, count), pos);
}
// Overload of `string_view::find()` for finding a different C-style string
// `s` within the `string_view`.
size_type find(const char* absl_nonnull s, size_type pos = 0) const {
return find(string_view(s), pos);
}
// string_view::rfind()
//
// Finds the last occurrence of a substring `s` within the `string_view`,
// returning the position of the first character's match, or `npos` if no
// match was found.
size_type rfind(string_view s, size_type pos = npos) const noexcept;
// Overload of `string_view::rfind()` for finding the last given character `c`
// within the `string_view`.
size_type rfind(char c, size_type pos = npos) const noexcept;
// Overload of `string_view::rfind()` for finding a substring of a different
// C-style string `s` within the `string_view`.
size_type rfind(const char* absl_nonnull s, size_type pos,
size_type count) const {
return rfind(string_view(s, count), pos);
}
// Overload of `string_view::rfind()` for finding a different C-style string
// `s` within the `string_view`.
size_type rfind(const char* absl_nonnull s, size_type pos = npos) const {
return rfind(string_view(s), pos);
}
// string_view::find_first_of()
//
// Finds the first occurrence of any of the characters in `s` within the
// `string_view`, returning the start position of the match, or `npos` if no
// match was found.
size_type find_first_of(string_view s, size_type pos = 0) const noexcept;
// Overload of `string_view::find_first_of()` for finding a character `c`
// within the `string_view`.
size_type find_first_of(char c, size_type pos = 0) const noexcept {
return find(c, pos);
}
// Overload of `string_view::find_first_of()` for finding a substring of a
// different C-style string `s` within the `string_view`.
size_type find_first_of(const char* absl_nonnull s, size_type pos,
size_type count) const {
return find_first_of(string_view(s, count), pos);
}
// Overload of `string_view::find_first_of()` for finding a different C-style
// string `s` within the `string_view`.
size_type find_first_of(const char* absl_nonnull s, size_type pos = 0) const {
return find_first_of(string_view(s), pos);
}
// string_view::find_last_of()
//
// Finds the last occurrence of any of the characters in `s` within the
// `string_view`, returning the start position of the match, or `npos` if no
// match was found.
size_type find_last_of(string_view s, size_type pos = npos) const noexcept;
// Overload of `string_view::find_last_of()` for finding a character `c`
// within the `string_view`.
size_type find_last_of(char c, size_type pos = npos) const noexcept {
return rfind(c, pos);
}
// Overload of `string_view::find_last_of()` for finding a substring of a
// different C-style string `s` within the `string_view`.
size_type find_last_of(const char* absl_nonnull s, size_type pos,
size_type count) const {
return find_last_of(string_view(s, count), pos);
}
// Overload of `string_view::find_last_of()` for finding a different C-style
// string `s` within the `string_view`.
size_type find_last_of(const char* absl_nonnull s,
size_type pos = npos) const {
return find_last_of(string_view(s), pos);
}
// string_view::find_first_not_of()
//
// Finds the first occurrence of any of the characters not in `s` within the
// `string_view`, returning the start position of the first non-match, or
// `npos` if no non-match was found.
size_type find_first_not_of(string_view s, size_type pos = 0) const noexcept;
// Overload of `string_view::find_first_not_of()` for finding a character
// that is not `c` within the `string_view`.
size_type find_first_not_of(char c, size_type pos = 0) const noexcept;
// Overload of `string_view::find_first_not_of()` for finding a substring of a
// different C-style string `s` within the `string_view`.
size_type find_first_not_of(const char* absl_nonnull s, size_type pos,
size_type count) const {
return find_first_not_of(string_view(s, count), pos);
}
// Overload of `string_view::find_first_not_of()` for finding a different
// C-style string `s` within the `string_view`.
size_type find_first_not_of(const char* absl_nonnull s,
size_type pos = 0) const {
return find_first_not_of(string_view(s), pos);
}
// string_view::find_last_not_of()
//
// Finds the last occurrence of any of the characters not in `s` within the
// `string_view`, returning the start position of the last non-match, or
// `npos` if no non-match was found.
size_type find_last_not_of(string_view s,
size_type pos = npos) const noexcept;
// Overload of `string_view::find_last_not_of()` for finding a character
// that is not `c` within the `string_view`.
size_type find_last_not_of(char c, size_type pos = npos) const noexcept;
// Overload of `string_view::find_last_not_of()` for finding a substring of a
// different C-style string `s` within the `string_view`.
size_type find_last_not_of(const char* absl_nonnull s, size_type pos,
size_type count) const {
return find_last_not_of(string_view(s, count), pos);
}
// Overload of `string_view::find_last_not_of()` for finding a different
// C-style string `s` within the `string_view`.
size_type find_last_not_of(const char* absl_nonnull s,
size_type pos = npos) const {
return find_last_not_of(string_view(s), pos);
}
#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
// string_view::starts_with()
//
// Returns true if the `string_view` starts with the prefix `s`.
//
// This method only exists when targeting at least C++20.
// If support for C++ prior to C++20 is required, use `absl::StartsWith()`
// from `//absl/strings/match.h` for compatibility.
constexpr bool starts_with(string_view s) const noexcept {
return s.empty() ||
(size() >= s.size() &&
ABSL_INTERNAL_STRING_VIEW_MEMCMP(data(), s.data(), s.size()) == 0);
}
// Overload of `string_view::starts_with()` that returns true if `c` is the
// first character of the `string_view`.
constexpr bool starts_with(char c) const noexcept {
return !empty() && front() == c;
}
// Overload of `string_view::starts_with()` that returns true if the
// `string_view` starts with the C-style prefix `s`.
constexpr bool starts_with(const char* s) const {
return starts_with(string_view(s));
}
// string_view::ends_with()
//
// Returns true if the `string_view` ends with the suffix `s`.
//
// This method only exists when targeting at least C++20.
// If support for C++ prior to C++20 is required, use `absl::EndsWith()`
// from `//absl/strings/match.h` for compatibility.
constexpr bool ends_with(string_view s) const noexcept {
return s.empty() || (size() >= s.size() && ABSL_INTERNAL_STRING_VIEW_MEMCMP(
data() + (size() - s.size()),
s.data(), s.size()) == 0);
}
// Overload of `string_view::ends_with()` that returns true if `c` is the
// last character of the `string_view`.
constexpr bool ends_with(char c) const noexcept {
return !empty() && back() == c;
}
// Overload of `string_view::ends_with()` that returns true if the
// `string_view` ends with the C-style suffix `s`.
constexpr bool ends_with(const char* s) const {
return ends_with(string_view(s));
}
#endif // ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
private:
// The constructor from std::string delegates to this constructor.
// See the comment on that constructor for the rationale.
struct SkipCheckLengthTag {};
string_view(const char* absl_nullable data, size_type len,
SkipCheckLengthTag) noexcept
: ptr_(data), length_(len) {}
static constexpr size_type kMaxSize =
(std::numeric_limits<difference_type>::max)();
static constexpr size_type CheckLengthInternal(size_type len) {
ABSL_HARDENING_ASSERT(len <= kMaxSize);
return len;
}
static constexpr size_type StrlenInternal(const char* absl_nonnull str) {
#if defined(_MSC_VER) && !defined(__clang__)
// MSVC 2017+ can evaluate this at compile-time.
const char* begin = str;
while (*str != '\0') ++str;
return str - begin;
#elif ABSL_HAVE_BUILTIN(__builtin_strlen) || \
(defined(__GNUC__) && !defined(__clang__))
// GCC has __builtin_strlen according to
// https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Other-Builtins.html, but
// ABSL_HAVE_BUILTIN doesn't detect that, so we use the extra checks above.
// __builtin_strlen is constexpr.
return __builtin_strlen(str);
#else
return str ? strlen(str) : 0;
#endif
}
static constexpr int CompareImpl(size_type length_a, size_type length_b,
int compare_result) {
return compare_result == 0 ? static_cast<int>(length_a > length_b) -
static_cast<int>(length_a < length_b)
: (compare_result < 0 ? -1 : 1);
}
const char* absl_nullable ptr_;
size_type length_;
};
// This large function is defined inline so that in a fairly common case where
// one of the arguments is a literal, the compiler can elide a lot of the
// following comparisons.
constexpr bool operator==(string_view x, string_view y) noexcept {
return x.size() == y.size() &&
(x.empty() ||
ABSL_INTERNAL_STRING_VIEW_MEMCMP(x.data(), y.data(), x.size()) == 0);
}
constexpr bool operator!=(string_view x, string_view y) noexcept {
return !(x == y);
}
constexpr bool operator<(string_view x, string_view y) noexcept {
return x.compare(y) < 0;
}
constexpr bool operator>(string_view x, string_view y) noexcept {
return y < x;
}
constexpr bool operator<=(string_view x, string_view y) noexcept {
return !(y < x);
}
constexpr bool operator>=(string_view x, string_view y) noexcept {
return !(x < y);
}
// IO Insertion Operator
std::ostream& operator<<(std::ostream& o, string_view piece);
ABSL_NAMESPACE_END
} // namespace absl
#undef ABSL_INTERNAL_STRING_VIEW_MEMCMP
#endif // ABSL_USES_STD_STRING_VIEW
namespace absl {
ABSL_NAMESPACE_BEGIN
// ClippedSubstr()
//
// Like `s.substr(pos, n)`, but clips `pos` to an upper bound of `s.size()`.
// Provided because std::string_view::substr throws if `pos > size()`
inline string_view ClippedSubstr(string_view s, size_t pos,
size_t n = string_view::npos) {
pos = (std::min)(pos, static_cast<size_t>(s.size()));
return s.substr(pos, n);
}
// NullSafeStringView()
//
// Creates an `absl::string_view` from a pointer `p` even if it's null-valued.
// This function should be used where an `absl::string_view` can be created from
// a possibly-null pointer.
constexpr string_view NullSafeStringView(const char* absl_nullable p) {
return p ? string_view(p) : string_view();
}
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_STRING_VIEW_H_
tsoong/.intermediates/external/abseil-cpp/absl_strings_hdrs/gen/my_include_dir/absl/strings/internal/stringify_sink.hö // Copyright 2022 The Abseil Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_STRINGS_INTERNAL_STRINGIFY_SINK_H_
#define ABSL_STRINGS_INTERNAL_STRINGIFY_SINK_H_
#include <string>
#include <type_traits>
#include <utility>
#include "absl/strings/string_view.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace strings_internal {
class StringifySink {
public:
void Append(size_t count, char ch);
void Append(string_view v);
// Support `absl::Format(&sink, format, args...)`.
friend void AbslFormatFlush(StringifySink* sink, absl::string_view v) {
sink->Append(v);
}
private:
template <typename T>
friend string_view ExtractStringification(StringifySink& sink, const T& v);
std::string buffer_;
};
template <typename T>
string_view ExtractStringification(StringifySink& sink, const T& v) {
AbslStringify(sink, v);
return sink.buffer_;
}
} // namespace strings_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_STRINGIFY_SINK_H_
*Š
{soong/.intermediates/external/abseil-cpp/absl_base_spinlock_wait_hdrs/gen/my_include_dir/absl/base/internal/spinlock_wait.hŠ// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_BASE_INTERNAL_SPINLOCK_WAIT_H_
#define ABSL_BASE_INTERNAL_SPINLOCK_WAIT_H_
// Operations to make atomic transitions on a word, and to allow
// waiting for those transitions to become possible.
#include <stdint.h>
#include <atomic>
#include "absl/base/internal/scheduling_mode.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace base_internal {
// SpinLockWait() waits until it can perform one of several transitions from
// "from" to "to". It returns when it performs a transition where done==true.
struct SpinLockWaitTransition {
uint32_t from;
uint32_t to;
bool done;
};
// Wait until *w can transition from trans[i].from to trans[i].to for some i
// satisfying 0<=i<n && trans[i].done, atomically make the transition,
// then return the old value of *w. Make any other atomic transitions
// where !trans[i].done, but continue waiting.
//
// Wakeups for threads blocked on SpinLockWait do not respect priorities.
uint32_t SpinLockWait(std::atomic<uint32_t> *w, int n,
const SpinLockWaitTransition trans[],
SchedulingMode scheduling_mode);
// If possible, wake some thread that has called SpinLockDelay(w, ...). If `all`
// is true, wake all such threads. On some systems, this may be a no-op; on
// those systems, threads calling SpinLockDelay() will always wake eventually
// even if SpinLockWake() is never called.
void SpinLockWake(std::atomic<uint32_t> *w, bool all);
// Wait for an appropriate spin delay on iteration "loop" of a
// spin loop on location *w, whose previously observed value was "value".
// SpinLockDelay() may do nothing, may yield the CPU, may sleep a clock tick,
// or may wait for a call to SpinLockWake(w).
void SpinLockDelay(std::atomic<uint32_t> *w, uint32_t value, int loop,
base_internal::SchedulingMode scheduling_mode);
// Helper used by AbslInternalSpinLockDelay.
// Returns a suggested delay in nanoseconds for iteration number "loop".
int SpinLockSuggestedDelayNS(int loop);
} // namespace base_internal
ABSL_NAMESPACE_END
} // namespace absl
// In some build configurations we pass --detect-odr-violations to the
// gold linker. This causes it to flag weak symbol overrides as ODR
// violations. Because ODR only applies to C++ and not C,
// --detect-odr-violations ignores symbols not mangled with C++ names.
// By changing our extension points to be extern "C", we dodge this
// check.
extern "C" {
void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockWake)(std::atomic<uint32_t> *w,
bool all);
void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockDelay)(
std::atomic<uint32_t> *w, uint32_t value, int loop,
absl::base_internal::SchedulingMode scheduling_mode);
}
inline void absl::base_internal::SpinLockWake(std::atomic<uint32_t> *w,
bool all) {
ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockWake)(w, all);
}
inline void absl::base_internal::SpinLockDelay(
std::atomic<uint32_t> *w, uint32_t value, int loop,
absl::base_internal::SchedulingMode scheduling_mode) {
ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockDelay)
(w, value, loop, scheduling_mode);
}
#endif // ABSL_BASE_INTERNAL_SPINLOCK_WAIT_H_
*þ
‚soong/.intermediates/external/abseil-cpp/absl_base_nullability_hdrs/gen/my_include_dir/absl/base/internal/nullability_deprecated.hö// Copyright 2023 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_BASE_INTERNAL_NULLABILITY_DEPRECATED_H_
#define ABSL_BASE_INTERNAL_NULLABILITY_DEPRECATED_H_
#include "absl/base/attributes.h"
#include "absl/base/config.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace nullability_internal {
template <typename T>
using NullableImpl
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate)
[[clang::annotate("Nullable")]]
#endif
// Don't add the _Nullable attribute in Objective-C compiles. Many Objective-C
// projects enable the `-Wnullable-to-nonnull-conversion warning`, which is
// liable to produce false positives.
#if ABSL_HAVE_FEATURE(nullability_on_classes) && !defined(__OBJC__)
= T _Nullable;
#else
= T;
#endif
template <typename T>
using NonnullImpl
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate)
[[clang::annotate("Nonnull")]]
#endif
#if ABSL_HAVE_FEATURE(nullability_on_classes) && !defined(__OBJC__)
= T _Nonnull;
#else
= T;
#endif
template <typename T>
using NullabilityUnknownImpl
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::annotate)
[[clang::annotate("Nullability_Unspecified")]]
#endif
#if ABSL_HAVE_FEATURE(nullability_on_classes) && !defined(__OBJC__)
= T _Null_unspecified;
#else
= T;
#endif
} // namespace nullability_internal
// The following template aliases are deprecated forms of nullability
// annotations. They have some limitations, for example, an incompatibility with
// `auto*` pointers, as `auto` cannot be used in a template argument.
//
// It is important to note that these annotations are not distinct strong
// *types*. They are alias templates defined to be equal to the underlying
// pointer type. A pointer annotated `Nonnull<T*>`, for example, is simply a
// pointer of type `T*`.
//
// Prefer the macro style annotations in `absl/base/nullability.h` instead.
// absl::Nonnull, analogous to absl_nonnull
//
// Example:
// absl::Nonnull<int*> foo;
// Is equivalent to:
// int* absl_nonnull foo;
template <typename T>
using Nonnull [[deprecated("Use `absl_nonnull`.")]] =
nullability_internal::NonnullImpl<T>;
// absl::Nullable, analogous to absl_nullable
//
// Example:
// absl::Nullable<int*> foo;
// Is equivalent to:
// int* absl_nullable foo;
template <typename T>
using Nullable [[deprecated("Use `absl_nullable`.")]] =
nullability_internal::NullableImpl<T>;
// absl::NullabilityUnknown, analogous to absl_nullability_unknown
//
// Example:
// absl::NullabilityUnknown<int*> foo;
// Is equivalent to:
// int* absl_nullability_unknown foo;
template <typename T>
using NullabilityUnknown [[deprecated("Use `absl_nullability_unknown`.")]] =
nullability_internal::NullabilityUnknownImpl<T>;
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_INTERNAL_NULLABILITY_DEPRECATED_H_
*õ
‹soong/.intermediates/external/abseil-cpp/absl_strings_str_format_internal_hdrs/gen/my_include_dir/absl/strings/internal/str_format/output.hä// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Output extension hooks for the Format library.
// `internal::InvokeFlush` calls the appropriate flush function for the
// specified output argument.
// `BufferRawSink` is a simple output sink for a char buffer. Used by SnprintF.
// `FILERawSink` is a std::FILE* based sink. Used by PrintF and FprintF.
#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_OUTPUT_H_
#define ABSL_STRINGS_INTERNAL_STR_FORMAT_OUTPUT_H_
#include <cstdio>
#include <ios>
#include <ostream>
#include <string>
#include "absl/base/port.h"
#include "absl/strings/string_view.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
// RawSink implementation that writes into a char* buffer.
// It will not overflow the buffer, but will keep the total count of chars
// that would have been written.
class BufferRawSink {
public:
BufferRawSink(char* buffer, size_t size) : buffer_(buffer), size_(size) {}
size_t total_written() const { return total_written_; }
void Write(string_view v);
private:
char* buffer_;
size_t size_;
size_t total_written_ = 0;
};
// RawSink implementation that writes into a FILE*.
// It keeps track of the total number of bytes written and any error encountered
// during the writes.
class FILERawSink {
public:
explicit FILERawSink(std::FILE* output) : output_(output) {}
void Write(string_view v);
size_t count() const { return count_; }
int error() const { return error_; }
private:
std::FILE* output_;
int error_ = 0;
size_t count_ = 0;
};
// Provide RawSink integration with common types from the STL.
inline void AbslFormatFlush(std::string* out, string_view s) {
out->append(s.data(), s.size());
}
inline void AbslFormatFlush(std::ostream* out, string_view s) {
out->write(s.data(), static_cast<std::streamsize>(s.size()));
}
inline void AbslFormatFlush(FILERawSink* sink, string_view v) {
sink->Write(v);
}
inline void AbslFormatFlush(BufferRawSink* sink, string_view v) {
sink->Write(v);
}
// This is a SFINAE to get a better compiler error message when the type
// is not supported.
template <typename T>
auto InvokeFlush(T* out, string_view s) -> decltype(AbslFormatFlush(out, s)) {
AbslFormatFlush(out, s);
}
} // namespace str_format_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_OUTPUT_H_
*Ý@
‰soong/.intermediates/external/abseil-cpp/absl_strings_str_format_internal_hdrs/gen/my_include_dir/absl/strings/internal/str_format/bind.hÎ?// Copyright 2020 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_
#define ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_
#include <cassert>
#include <cstdio>
#include <ostream>
#include <string>
#include "absl/base/config.h"
#include "absl/container/inlined_vector.h"
#include "absl/strings/internal/str_format/arg.h"
#include "absl/strings/internal/str_format/checker.h"
#include "absl/strings/internal/str_format/constexpr_parser.h"
#include "absl/strings/internal/str_format/extension.h"
#include "absl/strings/internal/str_format/parser.h"
#include "absl/strings/string_view.h"
#include "absl/types/span.h"
#include "absl/utility/utility.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
class UntypedFormatSpec;
namespace str_format_internal {
class BoundConversion : public FormatConversionSpecImpl {
public:
const FormatArgImpl* arg() const { return arg_; }
void set_arg(const FormatArgImpl* a) { arg_ = a; }
private:
const FormatArgImpl* arg_;
};
// This is the type-erased class that the implementation uses.
class UntypedFormatSpecImpl {
public:
UntypedFormatSpecImpl() = delete;
explicit UntypedFormatSpecImpl(string_view s)
: data_(s.data()), size_(s.size()) {}
explicit UntypedFormatSpecImpl(
const str_format_internal::ParsedFormatBase* pc)
: data_(pc), size_(~size_t{}) {}
bool has_parsed_conversion() const { return size_ == ~size_t{}; }
string_view str() const {
assert(!has_parsed_conversion());
return string_view(static_cast<const char*>(data_), size_);
}
const str_format_internal::ParsedFormatBase* parsed_conversion() const {
assert(has_parsed_conversion());
return static_cast<const str_format_internal::ParsedFormatBase*>(data_);
}
template <typename T>
static const UntypedFormatSpecImpl& Extract(const T& s) {
return s.spec_;
}
private:
const void* data_;
size_t size_;
};
template <typename T, FormatConversionCharSet...>
struct MakeDependent {
using type = T;
};
// Implicitly convertible from `const char*`, `string_view`, and the
// `ExtendedParsedFormat` type. This abstraction allows all format functions to
// operate on any without providing too many overloads.
template <FormatConversionCharSet... Args>
class FormatSpecTemplate
: public MakeDependent<UntypedFormatSpec, Args...>::type {
using Base = typename MakeDependent<UntypedFormatSpec, Args...>::type;
template <bool res>
struct ErrorMaker {
constexpr bool operator()(int) const { return res; }
};
template <int i, int j>
static constexpr bool CheckArity(ErrorMaker<true> SpecifierCount = {},
ErrorMaker<i == j> ParametersPassed = {}) {
static_assert(SpecifierCount(i) == ParametersPassed(j),
"Number of arguments passed must match the number of "
"conversion specifiers.");
return true;
}
template <FormatConversionCharSet specified, FormatConversionCharSet passed,
int arg>
static constexpr bool CheckMatch(
ErrorMaker<Contains(specified, passed)> MismatchedArgumentNumber = {}) {
static_assert(MismatchedArgumentNumber(arg),
"Passed argument must match specified format.");
return true;
}
template <FormatConversionCharSet... C, size_t... I>
static bool CheckMatches(absl::index_sequence<I...>) {
bool res[] = {true, CheckMatch<Args, C, I + 1>()...};
(void)res;
return true;
}
public:
#ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
// Honeypot overload for when the string is not constexpr.
// We use the 'unavailable' attribute to give a better compiler error than
// just 'method is deleted'.
FormatSpecTemplate(...) // NOLINT
__attribute__((unavailable("Format string is not constexpr.")));
// Honeypot overload for when the format is constexpr and invalid.
// We use the 'unavailable' attribute to give a better compiler error than
// just 'method is deleted'.
// To avoid checking the format twice, we just check that the format is
// constexpr. If it is valid, then the overload below will kick in.
// We add the template here to make this overload have lower priority.
template <typename = void>
FormatSpecTemplate(const char* s) // NOLINT
__attribute__((
enable_if(str_format_internal::EnsureConstexpr(s), "constexpr trap"),
unavailable(
"Format specified does not match the arguments passed.")));
template <typename T = void>
FormatSpecTemplate(string_view s) // NOLINT
__attribute__((enable_if(str_format_internal::EnsureConstexpr(s),
"constexpr trap")))
: Base("to avoid noise in the compiler error") {
static_assert(sizeof(T*) == 0,
"Format specified does not match the arguments passed.");
}
// Good format overload.
FormatSpecTemplate(const char* s) // NOLINT
__attribute__((enable_if(ValidFormatImpl<Args...>(s), "bad format trap")))
: Base(s) {}
FormatSpecTemplate(string_view s) // NOLINT
__attribute__((enable_if(ValidFormatImpl<Args...>(s), "bad format trap")))
: Base(s) {}
#else // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
FormatSpecTemplate(const char* s) : Base(s) {} // NOLINT
FormatSpecTemplate(string_view s) : Base(s) {} // NOLINT
#endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
template <FormatConversionCharSet... C>
FormatSpecTemplate(const ExtendedParsedFormat<C...>& pc) // NOLINT
: Base(&pc) {
CheckArity<sizeof...(C), sizeof...(Args)>();
CheckMatches<C...>(absl::make_index_sequence<sizeof...(C)>{});
}
};
class Streamable {
public:
Streamable(const UntypedFormatSpecImpl& format,
absl::Span<const FormatArgImpl> args)
: format_(format), args_(args.begin(), args.end()) {}
std::ostream& Print(std::ostream& os) const;
friend std::ostream& operator<<(std::ostream& os, const Streamable& l) {
return l.Print(os);
}
private:
const UntypedFormatSpecImpl& format_;
absl::InlinedVector<FormatArgImpl, 4> args_;
};
// for testing
std::string Summarize(UntypedFormatSpecImpl format,
absl::Span<const FormatArgImpl> args);
bool BindWithPack(const UnboundConversion* props,
absl::Span<const FormatArgImpl> pack, BoundConversion* bound);
bool FormatUntyped(FormatRawSinkImpl raw_sink, UntypedFormatSpecImpl format,
absl::Span<const FormatArgImpl> args);
std::string& AppendPack(std::string* out, UntypedFormatSpecImpl format,
absl::Span<const FormatArgImpl> args);
std::string FormatPack(UntypedFormatSpecImpl format,
absl::Span<const FormatArgImpl> args);
int FprintF(std::FILE* output, UntypedFormatSpecImpl format,
absl::Span<const FormatArgImpl> args);
int SnprintF(char* output, size_t size, UntypedFormatSpecImpl format,
absl::Span<const FormatArgImpl> args);
// Returned by Streamed(v). Converts via '%s' to the std::string created
// by std::ostream << v.
template <typename T>
class StreamedWrapper {
public:
explicit StreamedWrapper(const T& v) : v_(v) {}
private:
template <typename S>
friend ArgConvertResult<FormatConversionCharSetUnion(
FormatConversionCharSetInternal::s, FormatConversionCharSetInternal::v)>
FormatConvertImpl(const StreamedWrapper<S>& v, FormatConversionSpecImpl conv,
FormatSinkImpl* out);
const T& v_;
};
} // namespace str_format_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_
*±½
xsoong/.intermediates/external/abseil-cpp/absl_log_internal_check_op_hdrs/gen/my_include_dir/absl/log/internal/check_op.h³¼// Copyright 2022 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: log/internal/check_op.h
// -----------------------------------------------------------------------------
//
// This file declares helpers routines and macros used to implement `CHECK`
// macros.
#ifndef ABSL_LOG_INTERNAL_CHECK_OP_H_
#define ABSL_LOG_INTERNAL_CHECK_OP_H_
#include <stdint.h>
#include <cstddef>
#include <ostream>
#include <sstream>
#include <string>
#include <type_traits>
#include <utility>
#include "absl/base/attributes.h"
#include "absl/base/casts.h"
#include "absl/base/config.h"
#include "absl/base/nullability.h"
#include "absl/base/optimization.h"
#include "absl/log/internal/nullguard.h"
#include "absl/log/internal/nullstream.h"
#include "absl/log/internal/strip.h"
#include "absl/strings/has_absl_stringify.h"
#include "absl/strings/string_view.h"
// `ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL` wraps string literals that
// should be stripped when `ABSL_MIN_LOG_LEVEL` exceeds `kFatal`.
#ifdef ABSL_MIN_LOG_LEVEL
#define ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(literal) \
(::absl::LogSeverity::kFatal >= \
static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) \
? (literal) \
: "")
#else
#define ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(literal) (literal)
#endif
#ifdef NDEBUG
// `NDEBUG` is defined, so `DCHECK_EQ(x, y)` and so on do nothing. However, we
// still want the compiler to parse `x` and `y`, because we don't want to lose
// potentially useful errors and warnings.
#define ABSL_LOG_INTERNAL_DCHECK_NOP(x, y) \
while (false && ((void)(x), (void)(y), 0)) \
::absl::log_internal::NullStream().InternalStream()
#endif
#define ABSL_LOG_INTERNAL_CHECK_OP(name, op, val1, val1_text, val2, val2_text) \
while (const char* absl_nullable absl_log_internal_check_op_result \
[[maybe_unused]] = ::absl::log_internal::name##Impl( \
::absl::log_internal::GetReferenceableValue(val1), \
::absl::log_internal::GetReferenceableValue(val2), \
ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(val1_text " " #op \
" " val2_text))) \
ABSL_LOG_INTERNAL_CONDITION_FATAL(STATELESS, true) \
ABSL_LOG_INTERNAL_CHECK(::absl::implicit_cast<const char* absl_nonnull>( \
absl_log_internal_check_op_result)) \
.InternalStream()
#define ABSL_LOG_INTERNAL_QCHECK_OP(name, op, val1, val1_text, val2, \
val2_text) \
while (const char* absl_nullable absl_log_internal_qcheck_op_result = \
::absl::log_internal::name##Impl( \
::absl::log_internal::GetReferenceableValue(val1), \
::absl::log_internal::GetReferenceableValue(val2), \
ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL( \
val1_text " " #op " " val2_text))) \
ABSL_LOG_INTERNAL_CONDITION_QFATAL(STATELESS, true) \
ABSL_LOG_INTERNAL_QCHECK(::absl::implicit_cast<const char* absl_nonnull>( \
absl_log_internal_qcheck_op_result)) \
.InternalStream()
#define ABSL_LOG_INTERNAL_CHECK_STROP(func, op, expected, s1, s1_text, s2, \
s2_text) \
while (const char* absl_nullable absl_log_internal_check_strop_result = \
::absl::log_internal::Check##func##expected##Impl( \
(s1), (s2), \
ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(s1_text " " #op \
" " s2_text))) \
ABSL_LOG_INTERNAL_CONDITION_FATAL(STATELESS, true) \
ABSL_LOG_INTERNAL_CHECK(::absl::implicit_cast<const char* absl_nonnull>( \
absl_log_internal_check_strop_result)) \
.InternalStream()
#define ABSL_LOG_INTERNAL_QCHECK_STROP(func, op, expected, s1, s1_text, s2, \
s2_text) \
while (const char* absl_nullable absl_log_internal_qcheck_strop_result = \
::absl::log_internal::Check##func##expected##Impl( \
(s1), (s2), \
ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(s1_text " " #op \
" " s2_text))) \
ABSL_LOG_INTERNAL_CONDITION_QFATAL(STATELESS, true) \
ABSL_LOG_INTERNAL_QCHECK(::absl::implicit_cast<const char* absl_nonnull>( \
absl_log_internal_qcheck_strop_result)) \
.InternalStream()
// This one is tricky:
// * We must evaluate `val` exactly once, yet we need to do two things with it:
// evaluate `.ok()` and (sometimes) `.ToString()`.
// * `val` might be an `absl::Status` or some `absl::StatusOr<T>`.
// * `val` might be e.g. `ATemporary().GetStatus()`, which may return a
// reference to a member of `ATemporary` that is only valid until the end of
// the full expression.
// * We don't want this file to depend on `absl::Status` `#include`s or linkage,
// nor do we want to move the definition to status and introduce a dependency
// in the other direction. We can be assured that callers must already have a
// `Status` and the necessary `#include`s and linkage.
// * Callsites should be small and fast (at least when `val.ok()`): one branch,
// minimal stack footprint.
// * In particular, the string concat stuff should be out-of-line and emitted
// in only one TU to save linker input size
// * We want the `val.ok()` check inline so static analyzers and optimizers can
// see it.
// * As usual, no braces so we can stream into the expansion with `operator<<`.
// * Also as usual, it must expand to a single (partial) statement with no
// ambiguous-else problems.
// * When stripped by `ABSL_MIN_LOG_LEVEL`, we must discard the `<expr> is OK`
// string literal and abort without doing any streaming. We don't need to
// strip the call to stringify the non-ok `Status` as long as we don't log it;
// dropping the `Status`'s message text is out of scope.
#define ABSL_LOG_INTERNAL_CHECK_OK(val, val_text) \
for (::std::pair<const ::absl::Status* absl_nonnull, \
const char* absl_nullable> \
absl_log_internal_check_ok_goo; \
absl_log_internal_check_ok_goo.first = \
::absl::log_internal::AsStatus(val), \
absl_log_internal_check_ok_goo.second = \
ABSL_PREDICT_TRUE(absl_log_internal_check_ok_goo.first->ok()) \
? nullptr \
: ::absl::status_internal::MakeCheckFailString( \
absl_log_internal_check_ok_goo.first, \
ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(val_text \
" is OK")), \
!ABSL_PREDICT_TRUE(absl_log_internal_check_ok_goo.first->ok());) \
ABSL_LOG_INTERNAL_CONDITION_FATAL(STATELESS, true) \
ABSL_LOG_INTERNAL_CHECK(::absl::implicit_cast<const char* absl_nonnull>( \
absl_log_internal_check_ok_goo.second)) \
.InternalStream()
#define ABSL_LOG_INTERNAL_QCHECK_OK(val, val_text) \
for (::std::pair<const ::absl::Status* absl_nonnull, \
const char* absl_nullable> \
absl_log_internal_qcheck_ok_goo; \
absl_log_internal_qcheck_ok_goo.first = \
::absl::log_internal::AsStatus(val), \
absl_log_internal_qcheck_ok_goo.second = \
ABSL_PREDICT_TRUE(absl_log_internal_qcheck_ok_goo.first->ok()) \
? nullptr \
: ::absl::status_internal::MakeCheckFailString( \
absl_log_internal_qcheck_ok_goo.first, \
ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(val_text \
" is OK")), \
!ABSL_PREDICT_TRUE(absl_log_internal_qcheck_ok_goo.first->ok());) \
ABSL_LOG_INTERNAL_CONDITION_QFATAL(STATELESS, true) \
ABSL_LOG_INTERNAL_QCHECK(::absl::implicit_cast<const char* absl_nonnull>( \
absl_log_internal_qcheck_ok_goo.second)) \
.InternalStream()
namespace absl {
ABSL_NAMESPACE_BEGIN
class Status;
template <typename T>
class StatusOr;
namespace status_internal {
ABSL_ATTRIBUTE_PURE_FUNCTION const char* absl_nonnull MakeCheckFailString(
const absl::Status* absl_nonnull status, const char* absl_nonnull prefix);
} // namespace status_internal
namespace log_internal {
// Convert a Status or a StatusOr to its underlying status value.
//
// (This implementation does not require a dep on absl::Status to work.)
inline const absl::Status* absl_nonnull AsStatus(const absl::Status& s) {
return &s;
}
template <typename T>
const absl::Status* absl_nonnull AsStatus(const absl::StatusOr<T>& s) {
return &s.status();
}
// A helper class for formatting `expr (V1 vs. V2)` in a `CHECK_XX` statement.
// See `MakeCheckOpString` for sample usage.
class CheckOpMessageBuilder final {
public:
// Inserts `exprtext` and ` (` to the stream.
explicit CheckOpMessageBuilder(const char* absl_nonnull exprtext);
~CheckOpMessageBuilder() = default;
// For inserting the first variable.
std::ostream& ForVar1() { return stream_; }
// For inserting the second variable (adds an intermediate ` vs. `).
std::ostream& ForVar2();
// Get the result (inserts the closing `)`).
const char* absl_nonnull NewString();
private:
std::ostringstream stream_;
};
// This formats a value for a failing `CHECK_XX` statement. Ordinarily, it uses
// the definition for `operator<<`, with a few special cases below.
template <typename T>
inline void MakeCheckOpValueString(std::ostream& os, const T& v) {
os << log_internal::NullGuard<T>::Guard(v);
}
// Overloads for char types provide readable values for unprintable characters.
void MakeCheckOpValueString(std::ostream& os, char v);
void MakeCheckOpValueString(std::ostream& os, signed char v);
void MakeCheckOpValueString(std::ostream& os, unsigned char v);
void MakeCheckOpValueString(std::ostream& os, const void* absl_nullable p);
namespace detect_specialization {
// MakeCheckOpString is being specialized for every T and U pair that is being
// passed to the CHECK_op macros. However, there is a lot of redundancy in these
// specializations that creates unnecessary library and binary bloat.
// The number of instantiations tends to be O(n^2) because we have two
// independent inputs. This technique works by reducing `n`.
//
// Most user-defined types being passed to CHECK_op end up being printed as a
// builtin type. For example, enums tend to be implicitly converted to its
// underlying type when calling operator<<, and pointers are printed with the
// `const void*` overload.
// To reduce the number of instantiations we coerce these values before calling
// MakeCheckOpString instead of inside it.
//
// To detect if this coercion is needed, we duplicate all the relevant
// operator<< overloads as specified in the standard, just in a different
// namespace. If the call to `stream << value` becomes ambiguous, it means that
// one of these overloads is the one selected by overload resolution. We then
// do overload resolution again just with our overload set to see which one gets
// selected. That tells us which type to coerce to.
// If the augmented call was not ambiguous, it means that none of these were
// selected and we can't coerce the input.
//
// As a secondary step to reduce code duplication, we promote integral types to
// their 64-bit variant. This does not change the printed value, but reduces the
// number of instantiations even further. Promoting an integer is very cheap at
// the call site.
int64_t operator<<(std::ostream&, short value); // NOLINT
int64_t operator<<(std::ostream&, unsigned short value); // NOLINT
int64_t operator<<(std::ostream&, int value);
int64_t operator<<(std::ostream&, unsigned int value);
int64_t operator<<(std::ostream&, long value); // NOLINT
uint64_t operator<<(std::ostream&, unsigned long value); // NOLINT
int64_t operator<<(std::ostream&, long long value); // NOLINT
uint64_t operator<<(std::ostream&, unsigned long long value); // NOLINT
float operator<<(std::ostream&, float value);
double operator<<(std::ostream&, double value);
long double operator<<(std::ostream&, long double value);
bool operator<<(std::ostream&, bool value);
const void* absl_nullable operator<<(std::ostream&,
const void* absl_nullable value);
const void* absl_nullable operator<<(std::ostream&, std::nullptr_t);
// These `char` overloads are specified like this in the standard, so we have to
// write them exactly the same to ensure the call is ambiguous.
// If we wrote it in a different way (eg taking std::ostream instead of the
// template) then one call might have a higher rank than the other and it would
// not be ambiguous.
template <typename Traits>
char operator<<(std::basic_ostream<char, Traits>&, char);
template <typename Traits>
signed char operator<<(std::basic_ostream<char, Traits>&, signed char);
template <typename Traits>
unsigned char operator<<(std::basic_ostream<char, Traits>&, unsigned char);
template <typename Traits>
const char* absl_nonnull operator<<(std::basic_ostream<char, Traits>&,
const char* absl_nonnull);
template <typename Traits>
const signed char* absl_nonnull operator<<(std::basic_ostream<char, Traits>&,
const signed char* absl_nonnull);
template <typename Traits>
const unsigned char* absl_nonnull operator<<(std::basic_ostream<char, Traits>&,
const unsigned char* absl_nonnull);
// This overload triggers when the call is not ambiguous.
// It means that T is being printed with some overload not on this list.
// We keep the value as `const T&`.
template <typename T, typename = decltype(std::declval<std::ostream&>()
<< std::declval<const T&>())>
const T& Detect(int);
// This overload triggers when the call is ambiguous.
// It means that T is either one from this list or printed as one from this
// list. Eg an enum that decays to `int` for printing.
// We ask the overload set to give us the type we want to convert it to.
template <typename T>
decltype(detect_specialization::operator<<(std::declval<std::ostream&>(),
std::declval<const T&>()))
Detect(char);
// A sink for AbslStringify which redirects everything to a std::ostream.
class StringifySink {
public:
explicit StringifySink(std::ostream& os ABSL_ATTRIBUTE_LIFETIME_BOUND);
void Append(absl::string_view text);
void Append(size_t length, char ch);
friend void AbslFormatFlush(StringifySink* absl_nonnull sink,
absl::string_view text);
private:
std::ostream& os_;
};
// Wraps a type implementing AbslStringify, and implements operator<<.
template <typename T>
class StringifyToStreamWrapper {
public:
explicit StringifyToStreamWrapper(const T& v ABSL_ATTRIBUTE_LIFETIME_BOUND)
: v_(v) {}
friend std::ostream& operator<<(std::ostream& os,
const StringifyToStreamWrapper& wrapper) {
StringifySink sink(os);
AbslStringify(sink, wrapper.v_);
return os;
}
private:
const T& v_;
};
// This overload triggers when T implements AbslStringify.
// StringifyToStreamWrapper is used to allow MakeCheckOpString to use
// operator<<.
template <typename T>
std::enable_if_t<HasAbslStringify<T>::value,
StringifyToStreamWrapper<T>>
Detect(...); // Ellipsis has lowest preference when int passed.
} // namespace detect_specialization
template <typename T>
using CheckOpStreamType = decltype(detect_specialization::Detect<T>(0));
// Build the error message string. Specify no inlining for code size.
template <typename T1, typename T2>
ABSL_ATTRIBUTE_RETURNS_NONNULL const char* absl_nonnull MakeCheckOpString(
T1 v1, T2 v2, const char* absl_nonnull exprtext) ABSL_ATTRIBUTE_NOINLINE;
template <typename T1, typename T2>
const char* absl_nonnull MakeCheckOpString(T1 v1, T2 v2,
const char* absl_nonnull exprtext) {
CheckOpMessageBuilder comb(exprtext);
MakeCheckOpValueString(comb.ForVar1(), v1);
MakeCheckOpValueString(comb.ForVar2(), v2);
return comb.NewString();
}
// Add a few commonly used instantiations as extern to reduce size of objects
// files.
#define ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(x) \
extern template const char* absl_nonnull MakeCheckOpString( \
x, x, const char* absl_nonnull)
ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(bool);
ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(int64_t);
ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(uint64_t);
ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(float);
ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(double);
ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(char);
ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(unsigned char);
ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const std::string&);
ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const absl::string_view&);
ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const char* absl_nonnull);
ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(
const signed char* absl_nonnull);
ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(
const unsigned char* absl_nonnull);
ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const void* absl_nonnull);
#undef ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN
// `ABSL_LOG_INTERNAL_CHECK_OP_IMPL_RESULT` skips formatting the Check_OP result
// string iff `ABSL_MIN_LOG_LEVEL` exceeds `kFatal`, instead returning an empty
// string.
#ifdef ABSL_MIN_LOG_LEVEL
#define ABSL_LOG_INTERNAL_CHECK_OP_IMPL_RESULT(U1, U2, v1, v2, exprtext) \
((::absl::LogSeverity::kFatal >= \
static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL)) \
? MakeCheckOpString<U1, U2>(v1, v2, exprtext) \
: "")
#else
#define ABSL_LOG_INTERNAL_CHECK_OP_IMPL_RESULT(U1, U2, v1, v2, exprtext) \
MakeCheckOpString<U1, U2>(v1, v2, exprtext)
#endif
// Helper functions for `ABSL_LOG_INTERNAL_CHECK_OP` macro family. The
// `(int, int)` override works around the issue that the compiler will not
// instantiate the template version of the function on values of unnamed enum
// type.
#define ABSL_LOG_INTERNAL_CHECK_OP_IMPL(name, op) \
template <typename T1, typename T2> \
inline constexpr const char* absl_nullable name##Impl( \
const T1& v1, const T2& v2, const char* absl_nonnull exprtext) { \
using U1 = CheckOpStreamType<T1>; \
using U2 = CheckOpStreamType<T2>; \
return ABSL_PREDICT_TRUE(v1 op v2) \
? nullptr \
: ABSL_LOG_INTERNAL_CHECK_OP_IMPL_RESULT(U1, U2, U1(v1), \
U2(v2), exprtext); \
} \
inline constexpr const char* absl_nullable name##Impl( \
int v1, int v2, const char* absl_nonnull exprtext) { \
return name##Impl<int, int>(v1, v2, exprtext); \
}
ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_EQ, ==)
ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_NE, !=)
ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_LE, <=)
ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_LT, <)
ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_GE, >=)
ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_GT, >)
#undef ABSL_LOG_INTERNAL_CHECK_OP_IMPL_RESULT
#undef ABSL_LOG_INTERNAL_CHECK_OP_IMPL
const char* absl_nullable CheckstrcmptrueImpl(
const char* absl_nullable s1, const char* absl_nullable s2,
const char* absl_nonnull exprtext);
const char* absl_nullable CheckstrcmpfalseImpl(
const char* absl_nullable s1, const char* absl_nullable s2,
const char* absl_nonnull exprtext);
const char* absl_nullable CheckstrcasecmptrueImpl(
const char* absl_nullable s1, const char* absl_nullable s2,
const char* absl_nonnull exprtext);
const char* absl_nullable CheckstrcasecmpfalseImpl(
const char* absl_nullable s1, const char* absl_nullable s2,
const char* absl_nonnull exprtext);
// `CHECK_EQ` and friends want to pass their arguments by reference, however
// this winds up exposing lots of cases where people have defined and
// initialized static const data members but never declared them (i.e. in a .cc
// file), meaning they are not referenceable. This function avoids that problem
// for integers (the most common cases) by overloading for every primitive
// integer type, even the ones we discourage, and returning them by value.
// NOLINTBEGIN(runtime/int)
// NOLINTBEGIN(google-runtime-int)
template <typename T>
inline constexpr const T& GetReferenceableValue(const T& t) {
return t;
}
inline constexpr char GetReferenceableValue(char t) { return t; }
inline constexpr unsigned char GetReferenceableValue(unsigned char t) {
return t;
}
inline constexpr signed char GetReferenceableValue(signed char t) { return t; }
inline constexpr short GetReferenceableValue(short t) { return t; }
inline constexpr unsigned short GetReferenceableValue(unsigned short t) {
return t;
}
inline constexpr int GetReferenceableValue(int t) { return t; }
inline constexpr unsigned int GetReferenceableValue(unsigned int t) {
return t;
}
inline constexpr long GetReferenceableValue(long t) { return t; }
inline constexpr unsigned long GetReferenceableValue(unsigned long t) {
return t;
}
inline constexpr long long GetReferenceableValue(long long t) { return t; }
inline constexpr unsigned long long GetReferenceableValue(
unsigned long long t) {
return t;
}
// NOLINTEND(google-runtime-int)
// NOLINTEND(runtime/int)
} // namespace log_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_LOG_INTERNAL_CHECK_OP_H_
*}
‡soong/.intermediates/external/abseil-cpp/absl_base_dynamic_annotations_hdrs/gen/my_include_dir/absl/base/internal/dynamic_annotations.h‚|// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This file defines dynamic annotations for use with dynamic analysis tool
// such as valgrind, PIN, etc.
//
// Dynamic annotation is a source code annotation that affects the generated
// code (that is, the annotation is not a comment). Each such annotation is
// attached to a particular instruction and/or to a particular object (address)
// in the program.
//
// The annotations that should be used by users are macros in all upper-case
// (e.g., ANNOTATE_THREAD_NAME).
//
// Actual implementation of these macros may differ depending on the dynamic
// analysis tool being used.
//
// This file supports the following configurations:
// - Dynamic Annotations enabled (with static thread-safety warnings disabled).
// In this case, macros expand to functions implemented by Thread Sanitizer,
// when building with TSan. When not provided an external implementation,
// dynamic_annotations.cc provides no-op implementations.
//
// - Static Clang thread-safety warnings enabled.
// When building with a Clang compiler that supports thread-safety warnings,
// a subset of annotations can be statically-checked at compile-time. We
// expand these macros to static-inline functions that can be analyzed for
// thread-safety, but afterwards elided when building the final binary.
//
// - All annotations are disabled.
// If neither Dynamic Annotations nor Clang thread-safety warnings are
// enabled, then all annotation-macros expand to empty.
#ifndef ABSL_BASE_INTERNAL_DYNAMIC_ANNOTATIONS_H_
#define ABSL_BASE_INTERNAL_DYNAMIC_ANNOTATIONS_H_
#include <stddef.h>
#include "absl/base/config.h"
// -------------------------------------------------------------------------
// Decide which features are enabled
#ifndef DYNAMIC_ANNOTATIONS_ENABLED
#define DYNAMIC_ANNOTATIONS_ENABLED 0
#endif
#if defined(__clang__) && !defined(SWIG)
#define ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED 1
#endif
#if DYNAMIC_ANNOTATIONS_ENABLED != 0
#define ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED 1
#define ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED 1
#define ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED 1
#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED 0
#define ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED 1
#else
#define ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED 0
#define ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED 0
#define ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED 0
// Clang provides limited support for static thread-safety analysis through a
// feature called Annotalysis. We configure macro-definitions according to
// whether Annotalysis support is available. When running in opt-mode, GCC
// will issue a warning, if these attributes are compiled. Only include them
// when compiling using Clang.
// ANNOTALYSIS_ENABLED == 1 when IGNORE_READ_ATTRIBUTE_ENABLED == 1
#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED \
defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
// Read/write annotations are enabled in Annotalysis mode; disabled otherwise.
#define ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED \
ABSL_INTERNAL_ANNOTALYSIS_ENABLED
#endif
// Memory annotations are also made available to LLVM's Memory Sanitizer
#if defined(ABSL_HAVE_MEMORY_SANITIZER) && !defined(__native_client__)
#define ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED 1
#endif
#ifndef ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED
#define ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED 0
#endif
#ifdef __cplusplus
#define ABSL_INTERNAL_BEGIN_EXTERN_C extern "C" {
#define ABSL_INTERNAL_END_EXTERN_C } // extern "C"
#define ABSL_INTERNAL_GLOBAL_SCOPED(F) ::F
#define ABSL_INTERNAL_STATIC_INLINE inline
#else
#define ABSL_INTERNAL_BEGIN_EXTERN_C // empty
#define ABSL_INTERNAL_END_EXTERN_C // empty
#define ABSL_INTERNAL_GLOBAL_SCOPED(F) F
#define ABSL_INTERNAL_STATIC_INLINE static inline
#endif
// -------------------------------------------------------------------------
// Define race annotations.
#if ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED == 1
// -------------------------------------------------------------
// Annotations that suppress errors. It is usually better to express the
// program's synchronization using the other annotations, but these can be used
// when all else fails.
// Report that we may have a benign race at `pointer`, with size
// "sizeof(*(pointer))". `pointer` must be a non-void* pointer. Insert at the
// point where `pointer` has been allocated, preferably close to the point
// where the race happens. See also ANNOTATE_BENIGN_RACE_STATIC.
#define ANNOTATE_BENIGN_RACE(pointer, description) \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateBenignRaceSized) \
(__FILE__, __LINE__, pointer, sizeof(*(pointer)), description)
// Same as ANNOTATE_BENIGN_RACE(`address`, `description`), but applies to
// the memory range [`address`, `address`+`size`).
#define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateBenignRaceSized) \
(__FILE__, __LINE__, address, size, description)
// Enable (`enable`!=0) or disable (`enable`==0) race detection for all threads.
// This annotation could be useful if you want to skip expensive race analysis
// during some period of program execution, e.g. during initialization.
#define ANNOTATE_ENABLE_RACE_DETECTION(enable) \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateEnableRaceDetection) \
(__FILE__, __LINE__, enable)
// -------------------------------------------------------------
// Annotations useful for debugging.
// Report the current thread `name` to a race detector.
#define ANNOTATE_THREAD_NAME(name) \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateThreadName)(__FILE__, __LINE__, name)
// -------------------------------------------------------------
// Annotations useful when implementing locks. They are not normally needed by
// modules that merely use locks. The `lock` argument is a pointer to the lock
// object.
// Report that a lock has been created at address `lock`.
#define ANNOTATE_RWLOCK_CREATE(lock) \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreate)(__FILE__, __LINE__, lock)
// Report that a linker initialized lock has been created at address `lock`.
#ifdef ABSL_HAVE_THREAD_SANITIZER
#define ANNOTATE_RWLOCK_CREATE_STATIC(lock) \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreateStatic) \
(__FILE__, __LINE__, lock)
#else
#define ANNOTATE_RWLOCK_CREATE_STATIC(lock) ANNOTATE_RWLOCK_CREATE(lock)
#endif
// Report that the lock at address `lock` is about to be destroyed.
#define ANNOTATE_RWLOCK_DESTROY(lock) \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockDestroy)(__FILE__, __LINE__, lock)
// Report that the lock at address `lock` has been acquired.
// `is_w`=1 for writer lock, `is_w`=0 for reader lock.
#define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockAcquired) \
(__FILE__, __LINE__, lock, is_w)
// Report that the lock at address `lock` is about to be released.
// `is_w`=1 for writer lock, `is_w`=0 for reader lock.
#define ANNOTATE_RWLOCK_RELEASED(lock, is_w) \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockReleased) \
(__FILE__, __LINE__, lock, is_w)
// Apply ANNOTATE_BENIGN_RACE_SIZED to a static variable `static_var`.
#define ANNOTATE_BENIGN_RACE_STATIC(static_var, description) \
namespace { \
class static_var##_annotator { \
public: \
static_var##_annotator() { \
ANNOTATE_BENIGN_RACE_SIZED(&static_var, sizeof(static_var), \
#static_var ": " description); \
} \
}; \
static static_var##_annotator the##static_var##_annotator; \
} // namespace
#else // ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED == 0
#define ANNOTATE_RWLOCK_CREATE(lock) // empty
#define ANNOTATE_RWLOCK_CREATE_STATIC(lock) // empty
#define ANNOTATE_RWLOCK_DESTROY(lock) // empty
#define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) // empty
#define ANNOTATE_RWLOCK_RELEASED(lock, is_w) // empty
#define ANNOTATE_BENIGN_RACE(address, description) // empty
#define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) // empty
#define ANNOTATE_THREAD_NAME(name) // empty
#define ANNOTATE_ENABLE_RACE_DETECTION(enable) // empty
#define ANNOTATE_BENIGN_RACE_STATIC(static_var, description) // empty
#endif // ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED
// -------------------------------------------------------------------------
// Define memory annotations.
#if ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED == 1
#include <sanitizer/msan_interface.h>
#define ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \
__msan_unpoison(address, size)
#define ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) \
__msan_allocated_memory(address, size)
#else // ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED == 0
#if DYNAMIC_ANNOTATIONS_ENABLED == 1
#define ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \
do { \
(void)(address); \
(void)(size); \
} while (0)
#define ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) \
do { \
(void)(address); \
(void)(size); \
} while (0)
#else
#define ANNOTATE_MEMORY_IS_INITIALIZED(address, size) // empty
#define ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) // empty
#endif
#endif // ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED
// -------------------------------------------------------------------------
// Define IGNORE_READS_BEGIN/_END attributes.
#if defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
#define ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE \
__attribute((exclusive_lock_function("*")))
#define ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE \
__attribute((unlock_function("*")))
#else // !defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
#define ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE // empty
#define ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE // empty
#endif // defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
// -------------------------------------------------------------------------
// Define IGNORE_READS_BEGIN/_END annotations.
#if ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED == 1
// Request the analysis tool to ignore all reads in the current thread until
// ANNOTATE_IGNORE_READS_END is called. Useful to ignore intentional racey
// reads, while still checking other reads and all writes.
// See also ANNOTATE_UNPROTECTED_READ.
#define ANNOTATE_IGNORE_READS_BEGIN() \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreReadsBegin)(__FILE__, __LINE__)
// Stop ignoring reads.
#define ANNOTATE_IGNORE_READS_END() \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreReadsEnd)(__FILE__, __LINE__)
#elif defined(ABSL_INTERNAL_ANNOTALYSIS_ENABLED)
// When Annotalysis is enabled without Dynamic Annotations, the use of
// static-inline functions allows the annotations to be read at compile-time,
// while still letting the compiler elide the functions from the final build.
//
// TODO(delesley) -- The exclusive lock here ignores writes as well, but
// allows IGNORE_READS_AND_WRITES to work properly.
#define ANNOTATE_IGNORE_READS_BEGIN() \
ABSL_INTERNAL_GLOBAL_SCOPED(AbslInternalAnnotateIgnoreReadsBegin)()
#define ANNOTATE_IGNORE_READS_END() \
ABSL_INTERNAL_GLOBAL_SCOPED(AbslInternalAnnotateIgnoreReadsEnd)()
#else
#define ANNOTATE_IGNORE_READS_BEGIN() // empty
#define ANNOTATE_IGNORE_READS_END() // empty
#endif
// -------------------------------------------------------------------------
// Define IGNORE_WRITES_BEGIN/_END annotations.
#if ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED == 1
// Similar to ANNOTATE_IGNORE_READS_BEGIN, but ignore writes instead.
#define ANNOTATE_IGNORE_WRITES_BEGIN() \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreWritesBegin)(__FILE__, __LINE__)
// Stop ignoring writes.
#define ANNOTATE_IGNORE_WRITES_END() \
ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreWritesEnd)(__FILE__, __LINE__)
#else
#define ANNOTATE_IGNORE_WRITES_BEGIN() // empty
#define ANNOTATE_IGNORE_WRITES_END() // empty
#endif
// -------------------------------------------------------------------------
// Define the ANNOTATE_IGNORE_READS_AND_WRITES_* annotations using the more
// primitive annotations defined above.
//
// Instead of doing
// ANNOTATE_IGNORE_READS_BEGIN();
// ... = x;
// ANNOTATE_IGNORE_READS_END();
// one can use
// ... = ANNOTATE_UNPROTECTED_READ(x);
#if defined(ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED)
// Start ignoring all memory accesses (both reads and writes).
#define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \
do { \
ANNOTATE_IGNORE_READS_BEGIN(); \
ANNOTATE_IGNORE_WRITES_BEGIN(); \
} while (0)
// Stop ignoring both reads and writes.
#define ANNOTATE_IGNORE_READS_AND_WRITES_END() \
do { \
ANNOTATE_IGNORE_WRITES_END(); \
ANNOTATE_IGNORE_READS_END(); \
} while (0)
#ifdef __cplusplus
// ANNOTATE_UNPROTECTED_READ is the preferred way to annotate racey reads.
#define ANNOTATE_UNPROTECTED_READ(x) \
absl::base_internal::AnnotateUnprotectedRead(x)
#endif
#else
#define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() // empty
#define ANNOTATE_IGNORE_READS_AND_WRITES_END() // empty
#define ANNOTATE_UNPROTECTED_READ(x) (x)
#endif
// -------------------------------------------------------------------------
// Address sanitizer annotations
#ifdef ABSL_HAVE_ADDRESS_SANITIZER
// Describe the current state of a contiguous container such as e.g.
// std::vector or std::string. For more details see
// sanitizer/common_interface_defs.h, which is provided by the compiler.
#include <sanitizer/common_interface_defs.h>
#define ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid) \
__sanitizer_annotate_contiguous_container(beg, end, old_mid, new_mid)
#define ADDRESS_SANITIZER_REDZONE(name) \
struct { \
char x[8] __attribute__((aligned(8))); \
} name
#else
#define ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid)
#define ADDRESS_SANITIZER_REDZONE(name) static_assert(true, "")
#endif // ABSL_HAVE_ADDRESS_SANITIZER
// -------------------------------------------------------------------------
// Undefine the macros intended only for this file.
#undef ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED
#undef ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED
#undef ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED
#undef ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED
#undef ABSL_INTERNAL_ANNOTALYSIS_ENABLED
#undef ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED
#undef ABSL_INTERNAL_BEGIN_EXTERN_C
#undef ABSL_INTERNAL_END_EXTERN_C
#undef ABSL_INTERNAL_STATIC_INLINE
#endif // ABSL_BASE_INTERNAL_DYNAMIC_ANNOTATIONS_H_
*”
‹soong/.intermediates/external/abseil-cpp/absl_strings_cordz_update_scope_hdrs/gen/my_include_dir/absl/strings/internal/cordz_update_scope.hƒ// Copyright 2021 The Abseil Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_STRINGS_INTERNAL_CORDZ_UPDATE_SCOPE_H_
#define ABSL_STRINGS_INTERNAL_CORDZ_UPDATE_SCOPE_H_
#include "absl/base/config.h"
#include "absl/base/optimization.h"
#include "absl/base/thread_annotations.h"
#include "absl/strings/internal/cord_internal.h"
#include "absl/strings/internal/cordz_info.h"
#include "absl/strings/internal/cordz_update_tracker.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace cord_internal {
// CordzUpdateScope scopes an update to the provided CordzInfo.
// The class invokes `info->Lock(method)` and `info->Unlock()` to guard
// cordrep updates. This class does nothing if `info` is null.
// See also the 'Lock`, `Unlock` and `SetCordRep` methods in `CordzInfo`.
class ABSL_SCOPED_LOCKABLE CordzUpdateScope {
public:
CordzUpdateScope(CordzInfo* info, CordzUpdateTracker::MethodIdentifier method)
ABSL_EXCLUSIVE_LOCK_FUNCTION(info)
: info_(info) {
if (ABSL_PREDICT_FALSE(info_)) {
info->Lock(method);
}
}
// CordzUpdateScope can not be copied or assigned to.
CordzUpdateScope(CordzUpdateScope&& rhs) = delete;
CordzUpdateScope(const CordzUpdateScope&) = delete;
CordzUpdateScope& operator=(CordzUpdateScope&& rhs) = delete;
CordzUpdateScope& operator=(const CordzUpdateScope&) = delete;
~CordzUpdateScope() ABSL_UNLOCK_FUNCTION() {
if (ABSL_PREDICT_FALSE(info_)) {
info_->Unlock();
}
}
void SetCordRep(CordRep* rep) const {
if (ABSL_PREDICT_FALSE(info_)) {
info_->SetCordRep(rep);
}
}
CordzInfo* info() const { return info_; }
private:
CordzInfo* info_;
};
} // namespace cord_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_CORDZ_UPDATE_SCOPE_H_
jsoong/.intermediates/external/abseil-cpp/absl_types_optional_hdrs/gen/my_include_dir/absl/types/optional.há
// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// optional.h
// -----------------------------------------------------------------------------
//
// Historical note: Abseil once provided an implementation of `absl::optional`
// as a polyfill for `std::optional` prior to C++17. Now that C++17 is required,
// `absl::optional` is an alias for `std::optional`.
#ifndef ABSL_TYPES_OPTIONAL_H_
#define ABSL_TYPES_OPTIONAL_H_
#include <optional>
#include "absl/base/config.h"
#include "absl/utility/utility.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
using std::bad_optional_access;
using std::optional;
using std::make_optional;
using std::nullopt_t;
using std::nullopt;
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_TYPES_OPTIONAL_H_
*¸?
fsoong/.intermediates/external/abseil-cpp/absl_numeric_bits_hdrs/gen/my_include_dir/absl/numeric/bits.hÍ>// Copyright 2020 The Abseil Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: bits.h
// -----------------------------------------------------------------------------
//
// This file contains implementations of C++20's bitwise math functions, as
// defined by:
//
// P0553R4:
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0553r4.html
// P0556R3:
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0556r3.html
// P1355R2:
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1355r2.html
// P1956R1:
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1956r1.pdf
// P0463R1
// https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0463r1.html
// P1272R4
// https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1272r4.html
//
// When using a standard library that implements these functions, we use the
// standard library's implementation.
#ifndef ABSL_NUMERIC_BITS_H_
#define ABSL_NUMERIC_BITS_H_
#include <cstdint>
#include <limits>
#include <type_traits>
#include "absl/base/config.h"
#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
#include <bit>
#endif
#include "absl/base/attributes.h"
#include "absl/base/internal/endian.h"
#include "absl/numeric/internal/bits.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
// https://github.com/llvm/llvm-project/issues/64544
// libc++ had the wrong signature for std::rotl and std::rotr
// prior to libc++ 18.0.
//
#if (defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L) && \
(!defined(_LIBCPP_VERSION) || _LIBCPP_VERSION >= 180000)
using std::rotl;
using std::rotr;
#else
// Rotating functions
template <class T>
[[nodiscard]] constexpr
typename std::enable_if<std::is_unsigned<T>::value, T>::type
rotl(T x, int s) noexcept {
return numeric_internal::RotateLeft(x, s);
}
template <class T>
[[nodiscard]] constexpr
typename std::enable_if<std::is_unsigned<T>::value, T>::type
rotr(T x, int s) noexcept {
return numeric_internal::RotateRight(x, s);
}
#endif
// https://github.com/llvm/llvm-project/issues/64544
// libc++ had the wrong signature for std::rotl and std::rotr
// prior to libc++ 18.0.
//
#if (defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L)
using std::countl_one;
using std::countl_zero;
using std::countr_one;
using std::countr_zero;
using std::popcount;
#else
// Counting functions
//
// While these functions are typically constexpr, on some platforms, they may
// not be marked as constexpr due to constraints of the compiler/available
// intrinsics.
template <class T>
ABSL_INTERNAL_CONSTEXPR_CLZ inline
typename std::enable_if<std::is_unsigned<T>::value, int>::type
countl_zero(T x) noexcept {
return numeric_internal::CountLeadingZeroes(x);
}
template <class T>
ABSL_INTERNAL_CONSTEXPR_CLZ inline
typename std::enable_if<std::is_unsigned<T>::value, int>::type
countl_one(T x) noexcept {
// Avoid integer promotion to a wider type
return countl_zero(static_cast<T>(~x));
}
template <class T>
ABSL_INTERNAL_CONSTEXPR_CTZ inline
typename std::enable_if<std::is_unsigned<T>::value, int>::type
countr_zero(T x) noexcept {
return numeric_internal::CountTrailingZeroes(x);
}
template <class T>
ABSL_INTERNAL_CONSTEXPR_CTZ inline
typename std::enable_if<std::is_unsigned<T>::value, int>::type
countr_one(T x) noexcept {
// Avoid integer promotion to a wider type
return countr_zero(static_cast<T>(~x));
}
template <class T>
ABSL_INTERNAL_CONSTEXPR_POPCOUNT inline
typename std::enable_if<std::is_unsigned<T>::value, int>::type
popcount(T x) noexcept {
return numeric_internal::Popcount(x);
}
#endif
#if (defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L)
using std::bit_ceil;
using std::bit_floor;
using std::bit_width;
using std::has_single_bit;
#else
// Returns: true if x is an integral power of two; false otherwise.
template <class T>
constexpr inline typename std::enable_if<std::is_unsigned<T>::value, bool>::type
has_single_bit(T x) noexcept {
return x != 0 && (x & (x - 1)) == 0;
}
// Returns: If x == 0, 0; otherwise one plus the base-2 logarithm of x, with any
// fractional part discarded.
template <class T>
ABSL_INTERNAL_CONSTEXPR_CLZ inline
typename std::enable_if<std::is_unsigned<T>::value, int>::type
bit_width(T x) noexcept {
return std::numeric_limits<T>::digits - countl_zero(x);
}
// Returns: If x == 0, 0; otherwise the maximal value y such that
// has_single_bit(y) is true and y <= x.
template <class T>
ABSL_INTERNAL_CONSTEXPR_CLZ inline
typename std::enable_if<std::is_unsigned<T>::value, T>::type
bit_floor(T x) noexcept {
return x == 0 ? 0 : T{1} << (bit_width(x) - 1);
}
// Returns: N, where N is the smallest power of 2 greater than or equal to x.
//
// Preconditions: N is representable as a value of type T.
template <class T>
ABSL_INTERNAL_CONSTEXPR_CLZ inline
typename std::enable_if<std::is_unsigned<T>::value, T>::type
bit_ceil(T x) {
// If T is narrower than unsigned, T{1} << bit_width will be promoted. We
// want to force it to wraparound so that bit_ceil of an invalid value are not
// core constant expressions.
//
// BitCeilNonPowerOf2 triggers an overflow in constexpr contexts if we would
// undergo promotion to unsigned but not fit the result into T without
// truncation.
return has_single_bit(x) ? T{1} << (bit_width(x) - 1)
: numeric_internal::BitCeilNonPowerOf2(x);
}
#endif
#if defined(__cpp_lib_endian) && __cpp_lib_endian >= 201907L
// https://en.cppreference.com/w/cpp/types/endian
//
// Indicates the endianness of all scalar types:
// * If all scalar types are little-endian, `absl::endian::native` equals
// absl::endian::little.
// * If all scalar types are big-endian, `absl::endian::native` equals
// `absl::endian::big`.
// * Platforms that use anything else are unsupported.
using std::endian;
#else
enum class endian {
little,
big,
#if defined(ABSL_IS_LITTLE_ENDIAN)
native = little
#elif defined(ABSL_IS_BIG_ENDIAN)
native = big
#else
#error "Endian detection needs to be set up for this platform"
#endif
};
#endif // defined(__cpp_lib_endian) && __cpp_lib_endian >= 201907L
#if defined(__cpp_lib_byteswap) && __cpp_lib_byteswap >= 202110L
// https://en.cppreference.com/w/cpp/numeric/byteswap
//
// Reverses the bytes in the given integer value `x`.
//
// `absl::byteswap` participates in overload resolution only if `T` satisfies
// integral, i.e., `T` is an integer type. The program is ill-formed if `T` has
// padding bits.
using std::byteswap;
#else
template <class T>
[[nodiscard]] constexpr T byteswap(T x) noexcept {
static_assert(std::is_integral_v<T>,
"byteswap requires an integral argument");
static_assert(
sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8,
"byteswap works only with 8, 16, 32, or 64-bit integers");
if constexpr (sizeof(T) == 1) {
return x;
} else if constexpr (sizeof(T) == 2) {
return static_cast<T>(gbswap_16(static_cast<uint16_t>(x)));
} else if constexpr (sizeof(T) == 4) {
return static_cast<T>(gbswap_32(static_cast<uint32_t>(x)));
} else if constexpr (sizeof(T) == 8) {
return static_cast<T>(gbswap_64(static_cast<uint64_t>(x)));
}
}
#endif // defined(__cpp_lib_byteswap) && __cpp_lib_byteswap >= 202110L
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_NUMERIC_BITS_H_
*®›
“soong/.intermediates/external/abseil-cpp/absl_time_internal_cctz_time_zone_hdrs/gen/my_include_dir/absl/time/internal/cctz/include/cctz/time_zone.h”š// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// A library for translating between absolute times (represented by
// std::chrono::time_points of the std::chrono::system_clock) and civil
// times (represented by cctz::civil_second) using the rules defined by
// a time zone (cctz::time_zone).
#ifndef ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_H_
#define ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_H_
#include <chrono>
#include <cstdint>
#include <limits>
#include <ratio> // NOLINT: We use std::ratio in this header
#include <string>
#include <utility>
#include "absl/base/config.h"
#include "absl/time/internal/cctz/include/cctz/civil_time.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace time_internal {
namespace cctz {
// Convenience aliases. Not intended as public API points.
template <typename D>
using time_point = std::chrono::time_point<std::chrono::system_clock, D>;
using seconds = std::chrono::duration<std::int_fast64_t>;
using sys_seconds = seconds; // Deprecated. Use cctz::seconds instead.
namespace detail {
template <typename D>
std::pair<time_point<seconds>, D> split_seconds(const time_point<D>& tp);
std::pair<time_point<seconds>, seconds> split_seconds(
const time_point<seconds>& tp);
} // namespace detail
// cctz::time_zone is an opaque, small, value-type class representing a
// geo-political region within which particular rules are used for mapping
// between absolute and civil times. Time zones are named using the TZ
// identifiers from the IANA Time Zone Database, such as "America/Los_Angeles"
// or "Australia/Sydney". Time zones are created from factory functions such
// as load_time_zone(). Note: strings like "PST" and "EDT" are not valid TZ
// identifiers.
//
// Example:
// cctz::time_zone utc = cctz::utc_time_zone();
// cctz::time_zone pst = cctz::fixed_time_zone(std::chrono::hours(-8));
// cctz::time_zone loc = cctz::local_time_zone();
// cctz::time_zone lax;
// if (!cctz::load_time_zone("America/Los_Angeles", &lax)) { ... }
//
// See also:
// - http://www.iana.org/time-zones
// - https://en.wikipedia.org/wiki/Zoneinfo
class time_zone {
public:
time_zone() : time_zone(nullptr) {} // Equivalent to UTC
time_zone(const time_zone&) = default;
time_zone& operator=(const time_zone&) = default;
std::string name() const;
// An absolute_lookup represents the civil time (cctz::civil_second) within
// this time_zone at the given absolute time (time_point). There are
// additionally a few other fields that may be useful when working with
// older APIs, such as std::tm.
//
// Example:
// const cctz::time_zone tz = ...
// const auto tp = std::chrono::system_clock::now();
// const cctz::time_zone::absolute_lookup al = tz.lookup(tp);
struct absolute_lookup {
civil_second cs;
// Note: The following fields exist for backward compatibility with older
// APIs. Accessing these fields directly is a sign of imprudent logic in
// the calling code. Modern time-related code should only access this data
// indirectly by way of cctz::format().
int offset; // civil seconds east of UTC
bool is_dst; // is offset non-standard?
const char* abbr; // time-zone abbreviation (e.g., "PST")
};
absolute_lookup lookup(const time_point<seconds>& tp) const;
template <typename D>
absolute_lookup lookup(const time_point<D>& tp) const {
return lookup(detail::split_seconds(tp).first);
}
// A civil_lookup represents the absolute time(s) (time_point) that
// correspond to the given civil time (cctz::civil_second) within this
// time_zone. Usually the given civil time represents a unique instant
// in time, in which case the conversion is unambiguous. However,
// within this time zone, the given civil time may be skipped (e.g.,
// during a positive UTC offset shift), or repeated (e.g., during a
// negative UTC offset shift). To account for these possibilities,
// civil_lookup is richer than just a single time_point.
//
// In all cases the civil_lookup::kind enum will indicate the nature
// of the given civil-time argument, and the pre, trans, and post
// members will give the absolute time answers using the pre-transition
// offset, the transition point itself, and the post-transition offset,
// respectively (all three times are equal if kind == UNIQUE). If any
// of these three absolute times is outside the representable range of a
// time_point<seconds> the field is set to its maximum/minimum value.
//
// Example:
// cctz::time_zone lax;
// if (!cctz::load_time_zone("America/Los_Angeles", &lax)) { ... }
//
// // A unique civil time.
// auto jan01 = lax.lookup(cctz::civil_second(2011, 1, 1, 0, 0, 0));
// // jan01.kind == cctz::time_zone::civil_lookup::UNIQUE
// // jan01.pre is 2011/01/01 00:00:00 -0800
// // jan01.trans is 2011/01/01 00:00:00 -0800
// // jan01.post is 2011/01/01 00:00:00 -0800
//
// // A Spring DST transition, when there is a gap in civil time.
// auto mar13 = lax.lookup(cctz::civil_second(2011, 3, 13, 2, 15, 0));
// // mar13.kind == cctz::time_zone::civil_lookup::SKIPPED
// // mar13.pre is 2011/03/13 03:15:00 -0700
// // mar13.trans is 2011/03/13 03:00:00 -0700
// // mar13.post is 2011/03/13 01:15:00 -0800
//
// // A Fall DST transition, when civil times are repeated.
// auto nov06 = lax.lookup(cctz::civil_second(2011, 11, 6, 1, 15, 0));
// // nov06.kind == cctz::time_zone::civil_lookup::REPEATED
// // nov06.pre is 2011/11/06 01:15:00 -0700
// // nov06.trans is 2011/11/06 01:00:00 -0800
// // nov06.post is 2011/11/06 01:15:00 -0800
struct civil_lookup {
enum civil_kind {
UNIQUE, // the civil time was singular (pre == trans == post)
SKIPPED, // the civil time did not exist (pre >= trans > post)
REPEATED, // the civil time was ambiguous (pre < trans <= post)
} kind;
time_point<seconds> pre; // uses the pre-transition offset
time_point<seconds> trans; // instant of civil-offset change
time_point<seconds> post; // uses the post-transition offset
};
civil_lookup lookup(const civil_second& cs) const;
// Finds the time of the next/previous offset change in this time zone.
//
// By definition, next_transition(tp, &trans) returns false when tp has
// its maximum value, and prev_transition(tp, &trans) returns false
// when tp has its minimum value. If the zone has no transitions, the
// result will also be false no matter what the argument.
//
// Otherwise, when tp has its minimum value, next_transition(tp, &trans)
// returns true and sets trans to the first recorded transition. Chains
// of calls to next_transition()/prev_transition() will eventually return
// false, but it is unspecified exactly when next_transition(tp, &trans)
// jumps to false, or what time is set by prev_transition(tp, &trans) for
// a very distant tp.
//
// Note: Enumeration of time-zone transitions is for informational purposes
// only. Modern time-related code should not care about when offset changes
// occur.
//
// Example:
// cctz::time_zone nyc;
// if (!cctz::load_time_zone("America/New_York", &nyc)) { ... }
// const auto now = std::chrono::system_clock::now();
// auto tp = cctz::time_point<cctz::seconds>::min();
// cctz::time_zone::civil_transition trans;
// while (tp <= now && nyc.next_transition(tp, &trans)) {
// // transition: trans.from -> trans.to
// tp = nyc.lookup(trans.to).trans;
// }
struct civil_transition {
civil_second from; // the civil time we jump from
civil_second to; // the civil time we jump to
};
bool next_transition(const time_point<seconds>& tp,
civil_transition* trans) const;
template <typename D>
bool next_transition(const time_point<D>& tp, civil_transition* trans) const {
return next_transition(detail::split_seconds(tp).first, trans);
}
bool prev_transition(const time_point<seconds>& tp,
civil_transition* trans) const;
template <typename D>
bool prev_transition(const time_point<D>& tp, civil_transition* trans) const {
return prev_transition(detail::split_seconds(tp).first, trans);
}
// version() and description() provide additional information about the
// time zone. The content of each of the returned strings is unspecified,
// however, when the IANA Time Zone Database is the underlying data source
// the version() string will be in the familiar form (e.g, "2018e") or
// empty when unavailable.
//
// Note: These functions are for informational or testing purposes only.
std::string version() const; // empty when unknown
std::string description() const;
// Relational operators.
friend bool operator==(time_zone lhs, time_zone rhs) {
return &lhs.effective_impl() == &rhs.effective_impl();
}
friend bool operator!=(time_zone lhs, time_zone rhs) { return !(lhs == rhs); }
template <typename H>
friend H AbslHashValue(H h, time_zone tz) {
return H::combine(std::move(h), &tz.effective_impl());
}
class Impl;
private:
explicit time_zone(const Impl* impl) : impl_(impl) {}
const Impl& effective_impl() const; // handles implicit UTC
const Impl* impl_;
};
// Loads the named time zone. May perform I/O on the initial load.
// If the name is invalid, or some other kind of error occurs, returns
// false and "*tz" is set to the UTC time zone.
bool load_time_zone(const std::string& name, time_zone* tz);
// Returns a time_zone representing UTC. Cannot fail.
time_zone utc_time_zone();
// Returns a time zone that is a fixed offset (seconds east) from UTC.
// Note: If the absolute value of the offset is greater than 24 hours
// you'll get UTC (i.e., zero offset) instead.
time_zone fixed_time_zone(const seconds& offset);
// Returns a time zone representing the local time zone. Falls back to UTC.
// Note: local_time_zone.name() may only be something like "localtime".
time_zone local_time_zone();
// Returns the civil time (cctz::civil_second) within the given time zone at
// the given absolute time (time_point). Since the additional fields provided
// by the time_zone::absolute_lookup struct should rarely be needed in modern
// code, this convert() function is simpler and should be preferred.
template <typename D>
inline civil_second convert(const time_point<D>& tp, const time_zone& tz) {
return tz.lookup(tp).cs;
}
// Returns the absolute time (time_point) that corresponds to the given civil
// time within the given time zone. If the civil time is not unique (i.e., if
// it was either repeated or non-existent), then the returned time_point is
// the best estimate that preserves relative order. That is, this function
// guarantees that if cs1 < cs2, then convert(cs1, tz) <= convert(cs2, tz).
inline time_point<seconds> convert(const civil_second& cs,
const time_zone& tz) {
const time_zone::civil_lookup cl = tz.lookup(cs);
if (cl.kind == time_zone::civil_lookup::SKIPPED) return cl.trans;
return cl.pre;
}
namespace detail {
using femtoseconds = std::chrono::duration<std::int_fast64_t, std::femto>;
std::string format(const std::string&, const time_point<seconds>&,
const femtoseconds&, const time_zone&);
bool parse(const std::string&, const std::string&, const time_zone&,
time_point<seconds>*, femtoseconds*, std::string* err = nullptr);
template <typename Rep, std::intmax_t Denom>
bool join_seconds(
const time_point<seconds>& sec, const femtoseconds& fs,
time_point<std::chrono::duration<Rep, std::ratio<1, Denom>>>* tpp);
template <typename Rep, std::intmax_t Num>
bool join_seconds(
const time_point<seconds>& sec, const femtoseconds& fs,
time_point<std::chrono::duration<Rep, std::ratio<Num, 1>>>* tpp);
template <typename Rep>
bool join_seconds(
const time_point<seconds>& sec, const femtoseconds& fs,
time_point<std::chrono::duration<Rep, std::ratio<1, 1>>>* tpp);
bool join_seconds(const time_point<seconds>& sec, const femtoseconds&,
time_point<seconds>* tpp);
} // namespace detail
// Formats the given time_point in the given cctz::time_zone according to
// the provided format string. Uses strftime()-like formatting options,
// with the following extensions:
//
// - %Ez - RFC3339-compatible numeric UTC offset (+hh:mm or -hh:mm)
// - %E*z - Full-resolution numeric UTC offset (+hh:mm:ss or -hh:mm:ss)
// - %E#S - Seconds with # digits of fractional precision
// - %E*S - Seconds with full fractional precision (a literal '*')
// - %E#f - Fractional seconds with # digits of precision
// - %E*f - Fractional seconds with full precision (a literal '*')
// - %E4Y - Four-character years (-999 ... -001, 0000, 0001 ... 9999)
// - %ET - The RFC3339 "date-time" separator "T"
//
// Note that %E0S behaves like %S, and %E0f produces no characters. In
// contrast %E*f always produces at least one digit, which may be '0'.
//
// Note that %Y produces as many characters as it takes to fully render the
// year. A year outside of [-999:9999] when formatted with %E4Y will produce
// more than four characters, just like %Y.
//
// Tip: Format strings should include the UTC offset (e.g., %z, %Ez, or %E*z)
// so that the resulting string uniquely identifies an absolute time.
//
// Example:
// cctz::time_zone lax;
// if (!cctz::load_time_zone("America/Los_Angeles", &lax)) { ... }
// auto tp = cctz::convert(cctz::civil_second(2013, 1, 2, 3, 4, 5), lax);
// std::string f = cctz::format("%H:%M:%S", tp, lax); // "03:04:05"
// f = cctz::format("%H:%M:%E3S", tp, lax); // "03:04:05.000"
template <typename D>
inline std::string format(const std::string& fmt, const time_point<D>& tp,
const time_zone& tz) {
const auto p = detail::split_seconds(tp);
const auto n = std::chrono::duration_cast<detail::femtoseconds>(p.second);
return detail::format(fmt, p.first, n, tz);
}
// Parses an input string according to the provided format string and
// returns the corresponding time_point. Uses strftime()-like formatting
// options, with the same extensions as cctz::format(), but with the
// exceptions that %E#S is interpreted as %E*S, and %E#f as %E*f. %Ez
// and %E*z also accept the same inputs, which (along with %z) includes
// 'z' and 'Z' as synonyms for +00:00. %ET accepts either 'T' or 't'.
//
// %Y consumes as many numeric characters as it can, so the matching data
// should always be terminated with a non-numeric. %E4Y always consumes
// exactly four characters, including any sign.
//
// Unspecified fields are taken from the default date and time of ...
//
// "1970-01-01 00:00:00.0 +0000"
//
// For example, parsing a string of "15:45" (%H:%M) will return a time_point
// that represents "1970-01-01 15:45:00.0 +0000".
//
// Note that parse() returns time instants, so it makes most sense to parse
// fully-specified date/time strings that include a UTC offset (%z, %Ez, or
// %E*z).
//
// Note also that parse() only heeds the fields year, month, day, hour,
// minute, (fractional) second, and UTC offset. Other fields, like weekday (%a
// or %A), while parsed for syntactic validity, are ignored in the conversion.
//
// Date and time fields that are out-of-range will be treated as errors rather
// than normalizing them like cctz::civil_second() would do. For example, it
// is an error to parse the date "Oct 32, 2013" because 32 is out of range.
//
// A second of ":60" is normalized to ":00" of the following minute with
// fractional seconds discarded. The following table shows how the given
// seconds and subseconds will be parsed:
//
// "59.x" -> 59.x // exact
// "60.x" -> 00.0 // normalized
// "00.x" -> 00.x // exact
//
// Errors are indicated by returning false.
//
// Example:
// const cctz::time_zone tz = ...
// std::chrono::system_clock::time_point tp;
// if (cctz::parse("%Y-%m-%d", "2015-10-09", tz, &tp)) {
// ...
// }
template <typename D>
inline bool parse(const std::string& fmt, const std::string& input,
const time_zone& tz, time_point<D>* tpp) {
time_point<seconds> sec;
detail::femtoseconds fs;
return detail::parse(fmt, input, tz, &sec, &fs) &&
detail::join_seconds(sec, fs, tpp);
}
namespace detail {
// Split a time_point<D> into a time_point<seconds> and a D subseconds.
// Undefined behavior if time_point<seconds> is not of sufficient range.
// Note that this means it is UB to call cctz::time_zone::lookup(tp) or
// cctz::format(fmt, tp, tz) with a time_point that is outside the range
// of a 64-bit std::time_t.
template <typename D>
std::pair<time_point<seconds>, D> split_seconds(const time_point<D>& tp) {
auto sec = std::chrono::time_point_cast<seconds>(tp);
auto sub = tp - sec;
if (sub.count() < 0) {
sec -= seconds(1);
sub += seconds(1);
}
return {sec, std::chrono::duration_cast<D>(sub)};
}
inline std::pair<time_point<seconds>, seconds> split_seconds(
const time_point<seconds>& tp) {
return {tp, seconds::zero()};
}
// Join a time_point<seconds> and femto subseconds into a time_point<D>.
// Floors to the resolution of time_point<D>. Returns false if time_point<D>
// is not of sufficient range.
template <typename Rep, std::intmax_t Denom>
bool join_seconds(
const time_point<seconds>& sec, const femtoseconds& fs,
time_point<std::chrono::duration<Rep, std::ratio<1, Denom>>>* tpp) {
using D = std::chrono::duration<Rep, std::ratio<1, Denom>>;
// TODO(#199): Return false if result unrepresentable as a time_point<D>.
*tpp = std::chrono::time_point_cast<D>(sec);
*tpp += std::chrono::duration_cast<D>(fs);
return true;
}
template <typename Rep, std::intmax_t Num>
bool join_seconds(
const time_point<seconds>& sec, const femtoseconds&,
time_point<std::chrono::duration<Rep, std::ratio<Num, 1>>>* tpp) {
using D = std::chrono::duration<Rep, std::ratio<Num, 1>>;
auto count = sec.time_since_epoch().count();
if (count >= 0 || count % Num == 0) {
count /= Num;
} else {
count /= Num;
count -= 1;
}
if (count > (std::numeric_limits<Rep>::max)()) return false;
if (count < (std::numeric_limits<Rep>::min)()) return false;
*tpp = time_point<D>() + D{static_cast<Rep>(count)};
return true;
}
template <typename Rep>
bool join_seconds(
const time_point<seconds>& sec, const femtoseconds&,
time_point<std::chrono::duration<Rep, std::ratio<1, 1>>>* tpp) {
using D = std::chrono::duration<Rep, std::ratio<1, 1>>;
auto count = sec.time_since_epoch().count();
if (count > (std::numeric_limits<Rep>::max)()) return false;
if (count < (std::numeric_limits<Rep>::min)()) return false;
*tpp = time_point<D>() + D{static_cast<Rep>(count)};
return true;
}
inline bool join_seconds(const time_point<seconds>& sec, const femtoseconds&,
time_point<seconds>* tpp) {
*tpp = sec;
return true;
}
} // namespace detail
} // namespace cctz
} // namespace time_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_H_
*´"
tsoong/.intermediates/external/abseil-cpp/absl_log_absl_vlog_is_on_hdrs/gen/my_include_dir/absl/log/absl_vlog_is_on.h»!// Copyright 2022 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: log/absl_vlog_is_on.h
// -----------------------------------------------------------------------------
//
// This header defines the `ABSL_VLOG_IS_ON()` macro that controls the
// variable-verbosity conditional logging.
//
// It's used by `VLOG` in log.h, or it can also be used directly like this:
//
// if (ABSL_VLOG_IS_ON(2)) {
// foo_server.RecomputeStatisticsExpensive();
// LOG(INFO) << foo_server.LastStatisticsAsString();
// }
//
// Each source file has an effective verbosity level that's a non-negative
// integer computed from the `--vmodule` and `--v` flags.
// `ABSL_VLOG_IS_ON(n)` is true, and `VLOG(n)` logs, if that effective verbosity
// level is greater than or equal to `n`.
//
// `--vmodule` takes a comma-delimited list of key=value pairs. Each key is a
// pattern matched against filenames, and the values give the effective severity
// level applied to matching files. '?' and '*' characters in patterns are
// interpreted as single-character and zero-or-more-character wildcards.
// Patterns including a slash character are matched against full pathnames,
// while those without are matched against basenames only. One suffix (i.e. the
// last . and everything after it) is stripped from each filename prior to
// matching, as is the special suffix "-inl".
//
// Example: --vmodule=module_a=1,module_b=2
//
// Files are matched against globs in `--vmodule` in order, and the first match
// determines the verbosity level.
//
// Files which do not match any pattern in `--vmodule` use the value of `--v` as
// their effective verbosity level. The default is 0.
//
// SetVLogLevel helper function is provided to do limited dynamic control over
// V-logging by appending to `--vmodule`. Because these go at the beginning of
// the list, they take priority over any globs previously added.
//
// Resetting --vmodule will override all previous modifications to `--vmodule`,
// including via SetVLogLevel.
#ifndef ABSL_LOG_ABSL_VLOG_IS_ON_H_
#define ABSL_LOG_ABSL_VLOG_IS_ON_H_
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/log/internal/vlog_config.h" // IWYU pragma: export
#include "absl/strings/string_view.h"
// IWYU pragma: private, include "absl/log/log.h"
// This is expanded at the callsite to allow the compiler to optimize
// always-false cases out of the build.
// An ABSL_MAX_VLOG_VERBOSITY of 2 means that VLOG(3) and above should never
// log.
#ifdef ABSL_MAX_VLOG_VERBOSITY
#define ABSL_LOG_INTERNAL_MAX_LOG_VERBOSITY_CHECK(x) \
((x) <= ABSL_MAX_VLOG_VERBOSITY)&&
#else
#define ABSL_LOG_INTERNAL_MAX_LOG_VERBOSITY_CHECK(x)
#endif
// Each ABSL_VLOG_IS_ON call site gets its own VLogSite that registers with the
// global linked list of sites to asynchronously update its verbosity level on
// changes to --v or --vmodule. The verbosity can also be set by manually
// calling SetVLogLevel.
//
// ABSL_VLOG_IS_ON is not async signal safe, but it is guaranteed not to
// allocate new memory.
#define ABSL_VLOG_IS_ON(verbose_level) \
(ABSL_LOG_INTERNAL_MAX_LOG_VERBOSITY_CHECK(verbose_level)[]() \
->::absl::log_internal::VLogSite * \
{ \
ABSL_CONST_INIT static ::absl::log_internal::VLogSite site(__FILE__); \
return &site; \
}() \
->IsEnabled(verbose_level))
#endif // ABSL_LOG_ABSL_VLOG_IS_ON_H_
*·²
asoong/.intermediates/external/abseil-cpp/absl_time_hdrs/gen/my_include_dir/absl/time/civil_time.hб// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: civil_time.h
// -----------------------------------------------------------------------------
//
// This header file defines abstractions for computing with "civil time".
// The term "civil time" refers to the legally recognized human-scale time
// that is represented by the six fields `YYYY-MM-DD hh:mm:ss`. A "date"
// is perhaps the most common example of a civil time (represented here as
// an `absl::CivilDay`).
//
// Modern-day civil time follows the Gregorian Calendar and is a
// time-zone-independent concept: a civil time of "2015-06-01 12:00:00", for
// example, is not tied to a time zone. Put another way, a civil time does not
// map to a unique point in time; a civil time must be mapped to an absolute
// time *through* a time zone.
//
// Because a civil time is what most people think of as "time," it is common to
// map absolute times to civil times to present to users.
//
// Time zones define the relationship between absolute and civil times. Given an
// absolute or civil time and a time zone, you can compute the other time:
//
// Civil Time = F(Absolute Time, Time Zone)
// Absolute Time = G(Civil Time, Time Zone)
//
// The Abseil time library allows you to construct such civil times from
// absolute times; consult time.h for such functionality.
//
// This library provides six classes for constructing civil-time objects, and
// provides several helper functions for rounding, iterating, and performing
// arithmetic on civil-time objects, while avoiding complications like
// daylight-saving time (DST):
//
// * `absl::CivilSecond`
// * `absl::CivilMinute`
// * `absl::CivilHour`
// * `absl::CivilDay`
// * `absl::CivilMonth`
// * `absl::CivilYear`
//
// Example:
//
// // Construct a civil-time object for a specific day
// const absl::CivilDay cd(1969, 7, 20);
//
// // Construct a civil-time object for a specific second
// const absl::CivilSecond cd(2018, 8, 1, 12, 0, 1);
//
// Note: In C++14 and later, this library is usable in a constexpr context.
//
// Example:
//
// // Valid in C++14
// constexpr absl::CivilDay cd(1969, 7, 20);
#ifndef ABSL_TIME_CIVIL_TIME_H_
#define ABSL_TIME_CIVIL_TIME_H_
#include <iosfwd>
#include <string>
#include "absl/base/config.h"
#include "absl/strings/string_view.h"
#include "absl/time/internal/cctz/include/cctz/civil_time.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace time_internal {
struct second_tag : cctz::detail::second_tag {};
struct minute_tag : second_tag, cctz::detail::minute_tag {};
struct hour_tag : minute_tag, cctz::detail::hour_tag {};
struct day_tag : hour_tag, cctz::detail::day_tag {};
struct month_tag : day_tag, cctz::detail::month_tag {};
struct year_tag : month_tag, cctz::detail::year_tag {};
} // namespace time_internal
// -----------------------------------------------------------------------------
// CivilSecond, CivilMinute, CivilHour, CivilDay, CivilMonth, CivilYear
// -----------------------------------------------------------------------------
//
// Each of these civil-time types is a simple value type with the same
// interface for construction and the same six accessors for each of the civil
// time fields (year, month, day, hour, minute, and second, aka YMDHMS). These
// classes differ only in their alignment, which is indicated by the type name
// and specifies the field on which arithmetic operates.
//
// CONSTRUCTION
//
// Each of the civil-time types can be constructed in two ways: by directly
// passing to the constructor up to six integers representing the YMDHMS fields,
// or by copying the YMDHMS fields from a differently aligned civil-time type.
// Omitted fields are assigned their minimum valid value. Hours, minutes, and
// seconds will be set to 0, month and day will be set to 1. Since there is no
// minimum year, the default is 1970.
//
// Examples:
//
// absl::CivilDay default_value; // 1970-01-01 00:00:00
//
// absl::CivilDay a(2015, 2, 3); // 2015-02-03 00:00:00
// absl::CivilDay b(2015, 2, 3, 4, 5, 6); // 2015-02-03 00:00:00
// absl::CivilDay c(2015); // 2015-01-01 00:00:00
//
// absl::CivilSecond ss(2015, 2, 3, 4, 5, 6); // 2015-02-03 04:05:06
// absl::CivilMinute mm(ss); // 2015-02-03 04:05:00
// absl::CivilHour hh(mm); // 2015-02-03 04:00:00
// absl::CivilDay d(hh); // 2015-02-03 00:00:00
// absl::CivilMonth m(d); // 2015-02-01 00:00:00
// absl::CivilYear y(m); // 2015-01-01 00:00:00
//
// m = absl::CivilMonth(y); // 2015-01-01 00:00:00
// d = absl::CivilDay(m); // 2015-01-01 00:00:00
// hh = absl::CivilHour(d); // 2015-01-01 00:00:00
// mm = absl::CivilMinute(hh); // 2015-01-01 00:00:00
// ss = absl::CivilSecond(mm); // 2015-01-01 00:00:00
//
// Each civil-time class is aligned to the civil-time field indicated in the
// class's name after normalization. Alignment is performed by setting all the
// inferior fields to their minimum valid value (as described above). The
// following are examples of how each of the six types would align the fields
// representing November 22, 2015 at 12:34:56 in the afternoon. (Note: the
// string format used here is not important; it's just a shorthand way of
// showing the six YMDHMS fields.)
//
// absl::CivilSecond : 2015-11-22 12:34:56
// absl::CivilMinute : 2015-11-22 12:34:00
// absl::CivilHour : 2015-11-22 12:00:00
// absl::CivilDay : 2015-11-22 00:00:00
// absl::CivilMonth : 2015-11-01 00:00:00
// absl::CivilYear : 2015-01-01 00:00:00
//
// Each civil-time type performs arithmetic on the field to which it is
// aligned. This means that adding 1 to an absl::CivilDay increments the day
// field (normalizing as necessary), and subtracting 7 from an absl::CivilMonth
// operates on the month field (normalizing as necessary). All arithmetic
// produces a valid civil time. Difference requires two similarly aligned
// civil-time objects and returns the scalar answer in units of the objects'
// alignment. For example, the difference between two absl::CivilHour objects
// will give an answer in units of civil hours.
//
// ALIGNMENT CONVERSION
//
// The alignment of a civil-time object cannot change, but the object may be
// used to construct a new object with a different alignment. This is referred
// to as "realigning". When realigning to a type with the same or more
// precision (e.g., absl::CivilDay -> absl::CivilSecond), the conversion may be
// performed implicitly since no information is lost. However, if information
// could be discarded (e.g., CivilSecond -> CivilDay), the conversion must
// be explicit at the call site.
//
// Examples:
//
// void UseDay(absl::CivilDay day);
//
// absl::CivilSecond cs;
// UseDay(cs); // Won't compile because data may be discarded
// UseDay(absl::CivilDay(cs)); // OK: explicit conversion
//
// absl::CivilDay cd;
// UseDay(cd); // OK: no conversion needed
//
// absl::CivilMonth cm;
// UseDay(cm); // OK: implicit conversion to absl::CivilDay
//
// NORMALIZATION
//
// Normalization takes invalid values and adjusts them to produce valid values.
// Within the civil-time library, integer arguments passed to the Civil*
// constructors may be out-of-range, in which case they are normalized by
// carrying overflow into a field of courser granularity to produce valid
// civil-time objects. This normalization enables natural arithmetic on
// constructor arguments without worrying about the field's range.
//
// Examples:
//
// // Out-of-range; normalized to 2016-11-01
// absl::CivilDay d(2016, 10, 32);
// // Out-of-range, negative: normalized to 2016-10-30T23
// absl::CivilHour h1(2016, 10, 31, -1);
// // Normalization is cumulative: normalized to 2016-10-30T23
// absl::CivilHour h2(2016, 10, 32, -25);
//
// Note: If normalization is undesired, you can signal an error by comparing
// the constructor arguments to the normalized values returned by the YMDHMS
// properties.
//
// COMPARISON
//
// Comparison between civil-time objects considers all six YMDHMS fields,
// regardless of the type's alignment. Comparison between differently aligned
// civil-time types is allowed.
//
// Examples:
//
// absl::CivilDay feb_3(2015, 2, 3); // 2015-02-03 00:00:00
// absl::CivilDay mar_4(2015, 3, 4); // 2015-03-04 00:00:00
// // feb_3 < mar_4
// // absl::CivilYear(feb_3) == absl::CivilYear(mar_4)
//
// absl::CivilSecond feb_3_noon(2015, 2, 3, 12, 0, 0); // 2015-02-03 12:00:00
// // feb_3 < feb_3_noon
// // feb_3 == absl::CivilDay(feb_3_noon)
//
// // Iterates all the days of February 2015.
// for (absl::CivilDay d(2015, 2, 1); d < absl::CivilMonth(2015, 3); ++d) {
// // ...
// }
//
// ARITHMETIC
//
// Civil-time types support natural arithmetic operators such as addition,
// subtraction, and difference. Arithmetic operates on the civil-time field
// indicated in the type's name. Difference operators require arguments with
// the same alignment and return the answer in units of the alignment.
//
// Example:
//
// absl::CivilDay a(2015, 2, 3);
// ++a; // 2015-02-04 00:00:00
// --a; // 2015-02-03 00:00:00
// absl::CivilDay b = a + 1; // 2015-02-04 00:00:00
// absl::CivilDay c = 1 + b; // 2015-02-05 00:00:00
// int n = c - a; // n = 2 (civil days)
// int m = c - absl::CivilMonth(c); // Won't compile: different types.
//
// ACCESSORS
//
// Each civil-time type has accessors for all six of the civil-time fields:
// year, month, day, hour, minute, and second.
//
// civil_year_t year()
// int month()
// int day()
// int hour()
// int minute()
// int second()
//
// Recall that fields inferior to the type's alignment will be set to their
// minimum valid value.
//
// Example:
//
// absl::CivilDay d(2015, 6, 28);
// // d.year() == 2015
// // d.month() == 6
// // d.day() == 28
// // d.hour() == 0
// // d.minute() == 0
// // d.second() == 0
//
// CASE STUDY: Adding a month to January 31.
//
// One of the classic questions that arises when considering a civil time
// library (or a date library or a date/time library) is this:
// "What is the result of adding a month to January 31?"
// This is an interesting question because it is unclear what is meant by a
// "month", and several different answers are possible, depending on context:
//
// 1. March 3 (or 2 if a leap year), if "add a month" means to add a month to
// the current month, and adjust the date to overflow the extra days into
// March. In this case the result of "February 31" would be normalized as
// within the civil-time library.
// 2. February 28 (or 29 if a leap year), if "add a month" means to add a
// month, and adjust the date while holding the resulting month constant.
// In this case, the result of "February 31" would be truncated to the last
// day in February.
// 3. An error. The caller may get some error, an exception, an invalid date
// object, or perhaps return `false`. This may make sense because there is
// no single unambiguously correct answer to the question.
//
// Practically speaking, any answer that is not what the programmer intended
// is the wrong answer.
//
// The Abseil time library avoids this problem by making it impossible to
// ask ambiguous questions. All civil-time objects are aligned to a particular
// civil-field boundary (such as aligned to a year, month, day, hour, minute,
// or second), and arithmetic operates on the field to which the object is
// aligned. This means that in order to "add a month" the object must first be
// aligned to a month boundary, which is equivalent to the first day of that
// month.
//
// Of course, there are ways to compute an answer the question at hand using
// this Abseil time library, but they require the programmer to be explicit
// about the answer they expect. To illustrate, let's see how to compute all
// three of the above possible answers to the question of "Jan 31 plus 1
// month":
//
// Example:
//
// const absl::CivilDay d(2015, 1, 31);
//
// // Answer 1:
// // Add 1 to the month field in the constructor, and rely on normalization.
// const auto normalized = absl::CivilDay(d.year(), d.month() + 1, d.day());
// // normalized == 2015-03-03 (aka Feb 31)
//
// // Answer 2:
// // Add 1 to month field, capping to the end of next month.
// const auto next_month = absl::CivilMonth(d) + 1;
// const auto last_day_of_next_month = absl::CivilDay(next_month + 1) - 1;
// const auto capped = std::min(normalized, last_day_of_next_month);
// // capped == 2015-02-28
//
// // Answer 3:
// // Signal an error if the normalized answer is not in next month.
// if (absl::CivilMonth(normalized) != next_month) {
// // error, month overflow
// }
//
using CivilSecond =
time_internal::cctz::detail::civil_time<time_internal::second_tag>;
using CivilMinute =
time_internal::cctz::detail::civil_time<time_internal::minute_tag>;
using CivilHour =
time_internal::cctz::detail::civil_time<time_internal::hour_tag>;
using CivilDay =
time_internal::cctz::detail::civil_time<time_internal::day_tag>;
using CivilMonth =
time_internal::cctz::detail::civil_time<time_internal::month_tag>;
using CivilYear =
time_internal::cctz::detail::civil_time<time_internal::year_tag>;
// civil_year_t
//
// Type alias of a civil-time year value. This type is guaranteed to (at least)
// support any year value supported by `time_t`.
//
// Example:
//
// absl::CivilSecond cs = ...;
// absl::civil_year_t y = cs.year();
// cs = absl::CivilSecond(y, 1, 1, 0, 0, 0); // CivilSecond(CivilYear(cs))
//
using civil_year_t = time_internal::cctz::year_t;
// civil_diff_t
//
// Type alias of the difference between two civil-time values.
// This type is used to indicate arguments that are not
// normalized (such as parameters to the civil-time constructors), the results
// of civil-time subtraction, or the operand to civil-time addition.
//
// Example:
//
// absl::civil_diff_t n_sec = cs1 - cs2; // cs1 == cs2 + n_sec;
//
using civil_diff_t = time_internal::cctz::diff_t;
// Weekday::monday, Weekday::tuesday, Weekday::wednesday, Weekday::thursday,
// Weekday::friday, Weekday::saturday, Weekday::sunday
//
// The Weekday enum class represents the civil-time concept of a "weekday" with
// members for all days of the week.
//
// absl::Weekday wd = absl::Weekday::thursday;
//
using Weekday = time_internal::cctz::weekday;
// GetWeekday()
//
// Returns the absl::Weekday for the given (realigned) civil-time value.
//
// Example:
//
// absl::CivilDay a(2015, 8, 13);
// absl::Weekday wd = absl::GetWeekday(a); // wd == absl::Weekday::thursday
//
inline Weekday GetWeekday(CivilSecond cs) {
return time_internal::cctz::get_weekday(cs);
}
// NextWeekday()
// PrevWeekday()
//
// Returns the absl::CivilDay that strictly follows or precedes a given
// absl::CivilDay, and that falls on the given absl::Weekday.
//
// Example, given the following month:
//
// August 2015
// Su Mo Tu We Th Fr Sa
// 1
// 2 3 4 5 6 7 8
// 9 10 11 12 13 14 15
// 16 17 18 19 20 21 22
// 23 24 25 26 27 28 29
// 30 31
//
// absl::CivilDay a(2015, 8, 13);
// // absl::GetWeekday(a) == absl::Weekday::thursday
// absl::CivilDay b = absl::NextWeekday(a, absl::Weekday::thursday);
// // b = 2015-08-20
// absl::CivilDay c = absl::PrevWeekday(a, absl::Weekday::thursday);
// // c = 2015-08-06
//
// absl::CivilDay d = ...
// // Gets the following Thursday if d is not already Thursday
// absl::CivilDay thurs1 = absl::NextWeekday(d - 1, absl::Weekday::thursday);
// // Gets the previous Thursday if d is not already Thursday
// absl::CivilDay thurs2 = absl::PrevWeekday(d + 1, absl::Weekday::thursday);
//
inline CivilDay NextWeekday(CivilDay cd, Weekday wd) {
return CivilDay(time_internal::cctz::next_weekday(cd, wd));
}
inline CivilDay PrevWeekday(CivilDay cd, Weekday wd) {
return CivilDay(time_internal::cctz::prev_weekday(cd, wd));
}
// GetYearDay()
//
// Returns the day-of-year for the given (realigned) civil-time value.
//
// Example:
//
// absl::CivilDay a(2015, 1, 1);
// int yd_jan_1 = absl::GetYearDay(a); // yd_jan_1 = 1
// absl::CivilDay b(2015, 12, 31);
// int yd_dec_31 = absl::GetYearDay(b); // yd_dec_31 = 365
//
inline int GetYearDay(CivilSecond cs) {
return time_internal::cctz::get_yearday(cs);
}
// FormatCivilTime()
//
// Formats the given civil-time value into a string value of the following
// format:
//
// Type | Format
// ---------------------------------
// CivilSecond | YYYY-MM-DDTHH:MM:SS
// CivilMinute | YYYY-MM-DDTHH:MM
// CivilHour | YYYY-MM-DDTHH
// CivilDay | YYYY-MM-DD
// CivilMonth | YYYY-MM
// CivilYear | YYYY
//
// Example:
//
// absl::CivilDay d = absl::CivilDay(1969, 7, 20);
// std::string day_string = absl::FormatCivilTime(d); // "1969-07-20"
//
std::string FormatCivilTime(CivilSecond c);
std::string FormatCivilTime(CivilMinute c);
std::string FormatCivilTime(CivilHour c);
std::string FormatCivilTime(CivilDay c);
std::string FormatCivilTime(CivilMonth c);
std::string FormatCivilTime(CivilYear c);
// Support for StrFormat(), StrCat(), etc
template <typename Sink>
void AbslStringify(Sink& sink, CivilSecond c) {
sink.Append(FormatCivilTime(c));
}
template <typename Sink>
void AbslStringify(Sink& sink, CivilMinute c) {
sink.Append(FormatCivilTime(c));
}
template <typename Sink>
void AbslStringify(Sink& sink, CivilHour c) {
sink.Append(FormatCivilTime(c));
}
template <typename Sink>
void AbslStringify(Sink& sink, CivilDay c) {
sink.Append(FormatCivilTime(c));
}
template <typename Sink>
void AbslStringify(Sink& sink, CivilMonth c) {
sink.Append(FormatCivilTime(c));
}
template <typename Sink>
void AbslStringify(Sink& sink, CivilYear c) {
sink.Append(FormatCivilTime(c));
}
// absl::ParseCivilTime()
//
// Parses a civil-time value from the specified `absl::string_view` into the
// passed output parameter. Returns `true` upon successful parsing.
//
// The expected form of the input string is as follows:
//
// Type | Format
// ---------------------------------
// CivilSecond | YYYY-MM-DDTHH:MM:SS
// CivilMinute | YYYY-MM-DDTHH:MM
// CivilHour | YYYY-MM-DDTHH
// CivilDay | YYYY-MM-DD
// CivilMonth | YYYY-MM
// CivilYear | YYYY
//
// Example:
//
// absl::CivilDay d;
// bool ok = absl::ParseCivilTime("2018-01-02", &d); // OK
//
// Note that parsing will fail if the string's format does not match the
// expected type exactly. `ParseLenientCivilTime()` below is more lenient.
//
bool ParseCivilTime(absl::string_view s, CivilSecond* c);
bool ParseCivilTime(absl::string_view s, CivilMinute* c);
bool ParseCivilTime(absl::string_view s, CivilHour* c);
bool ParseCivilTime(absl::string_view s, CivilDay* c);
bool ParseCivilTime(absl::string_view s, CivilMonth* c);
bool ParseCivilTime(absl::string_view s, CivilYear* c);
// ParseLenientCivilTime()
//
// Parses any of the formats accepted by `absl::ParseCivilTime()`, but is more
// lenient if the format of the string does not exactly match the associated
// type.
//
// Example:
//
// absl::CivilDay d;
// bool ok = absl::ParseLenientCivilTime("1969-07-20", &d); // OK
// ok = absl::ParseLenientCivilTime("1969-07-20T10", &d); // OK: T10 floored
// ok = absl::ParseLenientCivilTime("1969-07", &d); // OK: day defaults to 1
//
bool ParseLenientCivilTime(absl::string_view s, CivilSecond* c);
bool ParseLenientCivilTime(absl::string_view s, CivilMinute* c);
bool ParseLenientCivilTime(absl::string_view s, CivilHour* c);
bool ParseLenientCivilTime(absl::string_view s, CivilDay* c);
bool ParseLenientCivilTime(absl::string_view s, CivilMonth* c);
bool ParseLenientCivilTime(absl::string_view s, CivilYear* c);
namespace time_internal { // For functions found via ADL on civil-time tags.
// Streaming Operators
//
// Each civil-time type may be sent to an output stream using operator<<().
// The result matches the string produced by `FormatCivilTime()`.
//
// Example:
//
// absl::CivilDay d = absl::CivilDay(1969, 7, 20);
// std::cout << "Date is: " << d << "\n";
//
std::ostream& operator<<(std::ostream& os, CivilYear y);
std::ostream& operator<<(std::ostream& os, CivilMonth m);
std::ostream& operator<<(std::ostream& os, CivilDay d);
std::ostream& operator<<(std::ostream& os, CivilHour h);
std::ostream& operator<<(std::ostream& os, CivilMinute m);
std::ostream& operator<<(std::ostream& os, CivilSecond s);
// AbslParseFlag()
//
// Parses the command-line flag string representation `s` into a civil-time
// value. Flags must be specified in a format that is valid for
// `absl::ParseLenientCivilTime()`.
bool AbslParseFlag(absl::string_view s, CivilSecond* c, std::string* error);
bool AbslParseFlag(absl::string_view s, CivilMinute* c, std::string* error);
bool AbslParseFlag(absl::string_view s, CivilHour* c, std::string* error);
bool AbslParseFlag(absl::string_view s, CivilDay* c, std::string* error);
bool AbslParseFlag(absl::string_view s, CivilMonth* c, std::string* error);
bool AbslParseFlag(absl::string_view s, CivilYear* c, std::string* error);
// AbslUnparseFlag()
//
// Unparses a civil-time value into a command-line string representation using
// the format specified by `absl::ParseCivilTime()`.
std::string AbslUnparseFlag(CivilSecond c);
std::string AbslUnparseFlag(CivilMinute c);
std::string AbslUnparseFlag(CivilHour c);
std::string AbslUnparseFlag(CivilDay c);
std::string AbslUnparseFlag(CivilMonth c);
std::string AbslUnparseFlag(CivilYear c);
} // namespace time_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_TIME_CIVIL_TIME_H_
*¯*
fsoong/.intermediates/external/abseil-cpp/absl_log_absl_log_hdrs/gen/my_include_dir/absl/log/absl_log.hÄ)// Copyright 2022 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: log/absl_log.h
// -----------------------------------------------------------------------------
//
// This header declares a family of `ABSL_LOG` macros as alternative spellings
// for macros in `log.h`.
//
// Basic invocation looks like this:
//
// ABSL_LOG(INFO) << "Found " << num_cookies << " cookies";
//
// Most `ABSL_LOG` macros take a severity level argument. The severity levels
// are `INFO`, `WARNING`, `ERROR`, and `FATAL`.
//
// For full documentation, see comments in `log.h`, which includes full
// reference documentation on use of the equivalent `LOG` macro and has an
// identical set of macros without the ABSL_* prefix.
#ifndef ABSL_LOG_ABSL_LOG_H_
#define ABSL_LOG_ABSL_LOG_H_
#include "absl/log/internal/log_impl.h"
#define ABSL_LOG(severity) ABSL_LOG_INTERNAL_LOG_IMPL(_##severity)
#define ABSL_PLOG(severity) ABSL_LOG_INTERNAL_PLOG_IMPL(_##severity)
#define ABSL_DLOG(severity) ABSL_LOG_INTERNAL_DLOG_IMPL(_##severity)
#define ABSL_VLOG(verbose_level) ABSL_LOG_INTERNAL_VLOG_IMPL(verbose_level)
#define ABSL_DVLOG(verbose_level) ABSL_LOG_INTERNAL_DVLOG_IMPL(verbose_level)
#define ABSL_LOG_IF(severity, condition) \
ABSL_LOG_INTERNAL_LOG_IF_IMPL(_##severity, condition)
#define ABSL_PLOG_IF(severity, condition) \
ABSL_LOG_INTERNAL_PLOG_IF_IMPL(_##severity, condition)
#define ABSL_DLOG_IF(severity, condition) \
ABSL_LOG_INTERNAL_DLOG_IF_IMPL(_##severity, condition)
#define ABSL_LOG_EVERY_N(severity, n) \
ABSL_LOG_INTERNAL_LOG_EVERY_N_IMPL(_##severity, n)
#define ABSL_LOG_FIRST_N(severity, n) \
ABSL_LOG_INTERNAL_LOG_FIRST_N_IMPL(_##severity, n)
#define ABSL_LOG_EVERY_POW_2(severity) \
ABSL_LOG_INTERNAL_LOG_EVERY_POW_2_IMPL(_##severity)
#define ABSL_LOG_EVERY_N_SEC(severity, n_seconds) \
ABSL_LOG_INTERNAL_LOG_EVERY_N_SEC_IMPL(_##severity, n_seconds)
#define ABSL_PLOG_EVERY_N(severity, n) \
ABSL_LOG_INTERNAL_PLOG_EVERY_N_IMPL(_##severity, n)
#define ABSL_PLOG_FIRST_N(severity, n) \
ABSL_LOG_INTERNAL_PLOG_FIRST_N_IMPL(_##severity, n)
#define ABSL_PLOG_EVERY_POW_2(severity) \
ABSL_LOG_INTERNAL_PLOG_EVERY_POW_2_IMPL(_##severity)
#define ABSL_PLOG_EVERY_N_SEC(severity, n_seconds) \
ABSL_LOG_INTERNAL_PLOG_EVERY_N_SEC_IMPL(_##severity, n_seconds)
#define ABSL_DLOG_EVERY_N(severity, n) \
ABSL_LOG_INTERNAL_DLOG_EVERY_N_IMPL(_##severity, n)
#define ABSL_DLOG_FIRST_N(severity, n) \
ABSL_LOG_INTERNAL_DLOG_FIRST_N_IMPL(_##severity, n)
#define ABSL_DLOG_EVERY_POW_2(severity) \
ABSL_LOG_INTERNAL_DLOG_EVERY_POW_2_IMPL(_##severity)
#define ABSL_DLOG_EVERY_N_SEC(severity, n_seconds) \
ABSL_LOG_INTERNAL_DLOG_EVERY_N_SEC_IMPL(_##severity, n_seconds)
#define ABSL_VLOG_EVERY_N(verbose_level, n) \
ABSL_LOG_INTERNAL_VLOG_EVERY_N_IMPL(verbose_level, n)
#define ABSL_VLOG_FIRST_N(verbose_level, n) \
ABSL_LOG_INTERNAL_VLOG_FIRST_N_IMPL(verbose_level, n)
#define ABSL_VLOG_EVERY_POW_2(verbose_level, n) \
ABSL_LOG_INTERNAL_VLOG_EVERY_POW_2_IMPL(verbose_level, n)
#define ABSL_VLOG_EVERY_N_SEC(verbose_level, n) \
ABSL_LOG_INTERNAL_VLOG_EVERY_N_SEC_IMPL(verbose_level, n)
#define ABSL_LOG_IF_EVERY_N(severity, condition, n) \
ABSL_LOG_INTERNAL_LOG_IF_EVERY_N_IMPL(_##severity, condition, n)
#define ABSL_LOG_IF_FIRST_N(severity, condition, n) \
ABSL_LOG_INTERNAL_LOG_IF_FIRST_N_IMPL(_##severity, condition, n)
#define ABSL_LOG_IF_EVERY_POW_2(severity, condition) \
ABSL_LOG_INTERNAL_LOG_IF_EVERY_POW_2_IMPL(_##severity, condition)
#define ABSL_LOG_IF_EVERY_N_SEC(severity, condition, n_seconds) \
ABSL_LOG_INTERNAL_LOG_IF_EVERY_N_SEC_IMPL(_##severity, condition, n_seconds)
#define ABSL_PLOG_IF_EVERY_N(severity, condition, n) \
ABSL_LOG_INTERNAL_PLOG_IF_EVERY_N_IMPL(_##severity, condition, n)
#define ABSL_PLOG_IF_FIRST_N(severity, condition, n) \
ABSL_LOG_INTERNAL_PLOG_IF_FIRST_N_IMPL(_##severity, condition, n)
#define ABSL_PLOG_IF_EVERY_POW_2(severity, condition) \
ABSL_LOG_INTERNAL_PLOG_IF_EVERY_POW_2_IMPL(_##severity, condition)
#define ABSL_PLOG_IF_EVERY_N_SEC(severity, condition, n_seconds) \
ABSL_LOG_INTERNAL_PLOG_IF_EVERY_N_SEC_IMPL(_##severity, condition, n_seconds)
#define ABSL_DLOG_IF_EVERY_N(severity, condition, n) \
ABSL_LOG_INTERNAL_DLOG_IF_EVERY_N_IMPL(_##severity, condition, n)
#define ABSL_DLOG_IF_FIRST_N(severity, condition, n) \
ABSL_LOG_INTERNAL_DLOG_IF_FIRST_N_IMPL(_##severity, condition, n)
#define ABSL_DLOG_IF_EVERY_POW_2(severity, condition) \
ABSL_LOG_INTERNAL_DLOG_IF_EVERY_POW_2_IMPL(_##severity, condition)
#define ABSL_DLOG_IF_EVERY_N_SEC(severity, condition, n_seconds) \
ABSL_LOG_INTERNAL_DLOG_IF_EVERY_N_SEC_IMPL(_##severity, condition, n_seconds)
#endif // ABSL_LOG_ABSL_LOG_H_
*“
jsoong/.intermediates/external/abseil-cpp/absl_algorithm_hdrs/gen/my_include_dir/absl/algorithm/algorithm.h¤// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: algorithm.h
// -----------------------------------------------------------------------------
//
// This header file contains Google extensions to the standard <algorithm> C++
// header.
#ifndef ABSL_ALGORITHM_ALGORITHM_H_
#define ABSL_ALGORITHM_ALGORITHM_H_
#include <algorithm>
#include <iterator>
#include <type_traits>
#include "absl/base/config.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
// equal()
// rotate()
//
// Historical note: Abseil once provided implementations of these algorithms
// prior to their adoption in C++14. New code should prefer to use the std
// variants.
//
// See the documentation for the STL <algorithm> header for more information:
// https://en.cppreference.com/w/cpp/header/algorithm
using std::equal;
using std::rotate;
// linear_search()
//
// Performs a linear search for `value` using the iterator `first` up to
// but not including `last`, returning true if [`first`, `last`) contains an
// element equal to `value`.
//
// A linear search is of O(n) complexity which is guaranteed to make at most
// n = (`last` - `first`) comparisons. A linear search over short containers
// may be faster than a binary search, even when the container is sorted.
template <typename InputIterator, typename EqualityComparable>
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool linear_search(
InputIterator first, InputIterator last, const EqualityComparable& value) {
return std::find(first, last, value) != last;
}
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_ALGORITHM_ALGORITHM_H_
*«,
“soong/.intermediates/external/abseil-cpp/absl_container_common_policy_traits_hdrs/gen/my_include_dir/absl/container/internal/common_policy_traits.h’+// Copyright 2022 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_CONTAINER_INTERNAL_COMMON_POLICY_TRAITS_H_
#define ABSL_CONTAINER_INTERNAL_COMMON_POLICY_TRAITS_H_
#include <cstddef>
#include <cstring>
#include <memory>
#include <new>
#include <type_traits>
#include <utility>
#include "absl/meta/type_traits.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace container_internal {
template <class Policy, class = void>
struct policy_trait_element_is_owner : std::false_type {};
template <class Policy>
struct policy_trait_element_is_owner<
Policy,
std::enable_if_t<!std::is_void<typename Policy::element_is_owner>::value>>
: Policy::element_is_owner {};
// Defines how slots are initialized/destroyed/moved.
template <class Policy, class = void>
struct common_policy_traits {
// The actual object stored in the container.
using slot_type = typename Policy::slot_type;
using reference = decltype(Policy::element(std::declval<slot_type*>()));
using value_type = typename std::remove_reference<reference>::type;
// PRECONDITION: `slot` is UNINITIALIZED
// POSTCONDITION: `slot` is INITIALIZED
template <class Alloc, class... Args>
static void construct(Alloc* alloc, slot_type* slot, Args&&... args) {
Policy::construct(alloc, slot, std::forward<Args>(args)...);
}
// PRECONDITION: `slot` is INITIALIZED
// POSTCONDITION: `slot` is UNINITIALIZED
// Returns std::true_type in case destroy is trivial.
template <class Alloc>
static auto destroy(Alloc* alloc, slot_type* slot) {
return Policy::destroy(alloc, slot);
}
// Transfers the `old_slot` to `new_slot`. Any memory allocated by the
// allocator inside `old_slot` to `new_slot` can be transferred.
//
// OPTIONAL: defaults to:
//
// clone(new_slot, std::move(*old_slot));
// destroy(old_slot);
//
// PRECONDITION: `new_slot` is UNINITIALIZED and `old_slot` is INITIALIZED
// POSTCONDITION: `new_slot` is INITIALIZED and `old_slot` is
// UNINITIALIZED
template <class Alloc>
static void transfer(Alloc* alloc, slot_type* new_slot, slot_type* old_slot) {
transfer_impl(alloc, new_slot, old_slot, Rank2{});
}
// PRECONDITION: `slot` is INITIALIZED
// POSTCONDITION: `slot` is INITIALIZED
// Note: we use remove_const_t so that the two overloads have different args
// in the case of sets with explicitly const value_types.
template <class P = Policy>
static auto element(absl::remove_const_t<slot_type>* slot)
-> decltype(P::element(slot)) {
return P::element(slot);
}
template <class P = Policy>
static auto element(const slot_type* slot) -> decltype(P::element(slot)) {
return P::element(slot);
}
static constexpr bool transfer_uses_memcpy() {
return std::is_same<decltype(transfer_impl<std::allocator<char>>(
nullptr, nullptr, nullptr, Rank2{})),
std::true_type>::value;
}
// Returns true if destroy is trivial and can be omitted.
template <class Alloc>
static constexpr bool destroy_is_trivial() {
return std::is_same<decltype(destroy<Alloc>(nullptr, nullptr)),
std::true_type>::value;
}
private:
// Use go/ranked-overloads for dispatching.
struct Rank0 {};
struct Rank1 : Rank0 {};
struct Rank2 : Rank1 {};
// Use auto -> decltype as an enabler.
// P::transfer returns std::true_type if transfer uses memcpy (e.g. in
// node_slot_policy).
template <class Alloc, class P = Policy>
static auto transfer_impl(Alloc* alloc, slot_type* new_slot,
slot_type* old_slot,
Rank2) -> decltype(P::transfer(alloc, new_slot,
old_slot)) {
return P::transfer(alloc, new_slot, old_slot);
}
// This overload returns true_type for the trait below.
// The conditional_t is to make the enabler type dependent.
template <class Alloc,
typename = std::enable_if_t<absl::is_trivially_relocatable<
std::conditional_t<false, Alloc, value_type>>::value>>
static std::true_type transfer_impl(Alloc*, slot_type* new_slot,
slot_type* old_slot, Rank1) {
// TODO(b/247130232): remove casts after fixing warnings.
// TODO(b/251814870): remove casts after fixing warnings.
std::memcpy(
static_cast<void*>(std::launder(
const_cast<std::remove_const_t<value_type>*>(&element(new_slot)))),
static_cast<const void*>(&element(old_slot)), sizeof(value_type));
return {};
}
template <class Alloc>
static void transfer_impl(Alloc* alloc, slot_type* new_slot,
slot_type* old_slot, Rank0) {
construct(alloc, new_slot, std::move(element(old_slot)));
destroy(alloc, old_slot);
}
};
} // namespace container_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_CONTAINER_INTERNAL_COMMON_POLICY_TRAITS_H_
*»
\soong/.intermediates/external/abseil-cpp/absl_time_hdrs/gen/my_include_dir/absl/time/clock.hÚ// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: clock.h
// -----------------------------------------------------------------------------
//
// This header file contains utility functions for working with the system-wide
// realtime clock. For descriptions of the main time abstractions used within
// this header file, consult the time.h header file.
#ifndef ABSL_TIME_CLOCK_H_
#define ABSL_TIME_CLOCK_H_
#include <cstdint>
#include "absl/base/config.h"
#include "absl/base/macros.h"
#include "absl/time/time.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
// Now()
//
// Returns the current time, expressed as an `absl::Time` absolute time value.
absl::Time Now();
// GetCurrentTimeNanos()
//
// Returns the current time, expressed as a count of nanoseconds since the Unix
// Epoch (https://en.wikipedia.org/wiki/Unix_time). Prefer `absl::Now()` instead
// for all but the most performance-sensitive cases (i.e. when you are calling
// this function hundreds of thousands of times per second).
int64_t GetCurrentTimeNanos();
// SleepFor()
//
// Sleeps for the specified duration, expressed as an `absl::Duration`.
//
// Notes:
// * Signal interruptions will not reduce the sleep duration.
// * Returns immediately when passed a nonpositive duration.
void SleepFor(absl::Duration duration);
ABSL_NAMESPACE_END
} // namespace absl
// -----------------------------------------------------------------------------
// Implementation Details
// -----------------------------------------------------------------------------
// In some build configurations we pass --detect-odr-violations to the
// gold linker. This causes it to flag weak symbol overrides as ODR
// violations. Because ODR only applies to C++ and not C,
// --detect-odr-violations ignores symbols not mangled with C++ names.
// By changing our extension points to be extern "C", we dodge this
// check.
extern "C" {
ABSL_DLL void ABSL_INTERNAL_C_SYMBOL(AbslInternalSleepFor)(
absl::Duration duration);
} // extern "C"
inline void absl::SleepFor(absl::Duration duration) {
ABSL_INTERNAL_C_SYMBOL(AbslInternalSleepFor)(duration);
}
#endif // ABSL_TIME_CLOCK_H_
*Â
vsoong/.intermediates/external/abseil-cpp/absl_log_internal_voidify_hdrs/gen/my_include_dir/absl/log/internal/voidify.hÇ // Copyright 2022 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: log/internal/voidify.h
// -----------------------------------------------------------------------------
//
// This class does the dispatching of the completed `absl::LogEntry` to
// applicable `absl::LogSink`s, and is used to explicitly ignore values in the
// conditional logging macros. This avoids compiler warnings like "value
// computed is not used" and "statement has no effect".
#ifndef ABSL_LOG_INTERNAL_VOIDIFY_H_
#define ABSL_LOG_INTERNAL_VOIDIFY_H_
#include "absl/base/attributes.h"
#include "absl/base/config.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace log_internal {
class Voidify final {
public:
// This has to be an operator with a precedence lower than << but higher than
// ?:
template <typename T>
ABSL_ATTRIBUTE_COLD void operator&&(T&& message) const&& {
// The dispatching of the completed `absl::LogEntry` to applicable
// `absl::LogSink`s happens here.
message.Flush();
}
};
} // namespace log_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_LOG_INTERNAL_VOIDIFY_H_
*Àh
rsoong/.intermediates/external/abseil-cpp/absl_log_internal_proto_hdrs/gen/my_include_dir/absl/log/internal/proto.hÉg// Copyright 2020 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// -----------------------------------------------------------------------------
// File: internal/proto.h
// -----------------------------------------------------------------------------
//
// Declares functions for serializing and deserializing data to and from memory
// buffers in protocol buffer wire format. This library takes no steps to
// ensure that the encoded data matches with any message specification.
#ifndef ABSL_LOG_INTERNAL_PROTO_H_
#define ABSL_LOG_INTERNAL_PROTO_H_
#include <cstddef>
#include <cstdint>
#include <limits>
#include "absl/base/attributes.h"
#include "absl/base/casts.h"
#include "absl/base/config.h"
#include "absl/strings/string_view.h"
#include "absl/types/span.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace log_internal {
// absl::Span<char> represents a view into the available space in a mutable
// buffer during encoding. Encoding functions shrink the span as they go so
// that the same view can be passed to a series of Encode functions. If the
// data do not fit, nothing is encoded, the view is set to size zero (so that
// all subsequent encode calls fail), and false is returned. Otherwise true is
// returned.
// In particular, attempting to encode a series of data into an insufficient
// buffer has consistent and efficient behavior without any caller-side error
// checking. Individual values will be encoded in their entirety or not at all
// (unless one of the `Truncate` functions is used). Once a value is omitted
// because it does not fit, no subsequent values will be encoded to preserve
// ordering; the decoded sequence will be a prefix of the original sequence.
// There are two ways to encode a message-typed field:
//
// * Construct its contents in a separate buffer and use `EncodeBytes` to copy
// it into the primary buffer with type, tag, and length.
// * Use `EncodeMessageStart` to write type and tag fields and reserve space for
// the length field, then encode the contents directly into the buffer, then
// use `EncodeMessageLength` to write the actual length into the reserved
// bytes. This works fine if the actual length takes fewer bytes to encode
// than were reserved, although you don't get your extra bytes back.
// This approach will always produce a valid encoding, but your protocol may
// require that the whole message field by omitted if the buffer is too small
// to contain all desired subfields. In this case, operate on a copy of the
// buffer view and assign back only if everything fit, i.e. if the last
// `Encode` call returned true.
// Encodes the specified integer as a varint field and returns true if it fits.
// Used for int32_t, int64_t, uint32_t, uint64_t, bool, and enum field types.
// Consumes up to kMaxVarintSize * 2 bytes (20).
bool EncodeVarint(uint64_t tag, uint64_t value, absl::Span<char> *buf);
inline bool EncodeVarint(uint64_t tag, int64_t value, absl::Span<char> *buf) {
return EncodeVarint(tag, static_cast<uint64_t>(value), buf);
}
inline bool EncodeVarint(uint64_t tag, uint32_t value, absl::Span<char> *buf) {
return EncodeVarint(tag, static_cast<uint64_t>(value), buf);
}
inline bool EncodeVarint(uint64_t tag, int32_t value, absl::Span<char> *buf) {
return EncodeVarint(tag, static_cast<uint64_t>(value), buf);
}
// Encodes the specified integer as a varint field using ZigZag encoding and
// returns true if it fits.
// Used for sint32 and sint64 field types.
// Consumes up to kMaxVarintSize * 2 bytes (20).
inline bool EncodeVarintZigZag(uint64_t tag, int64_t value,
absl::Span<char> *buf) {
if (value < 0)
return EncodeVarint(tag, 2 * static_cast<uint64_t>(-(value + 1)) + 1, buf);
return EncodeVarint(tag, 2 * static_cast<uint64_t>(value), buf);
}
// Encodes the specified integer as a 64-bit field and returns true if it fits.
// Used for fixed64 and sfixed64 field types.
// Consumes up to kMaxVarintSize + 8 bytes (18).
bool Encode64Bit(uint64_t tag, uint64_t value, absl::Span<char> *buf);
inline bool Encode64Bit(uint64_t tag, int64_t value, absl::Span<char> *buf) {
return Encode64Bit(tag, static_cast<uint64_t>(value), buf);
}
inline bool Encode64Bit(uint64_t tag, uint32_t value, absl::Span<char> *buf) {
return Encode64Bit(tag, static_cast<uint64_t>(value), buf);
}
inline bool Encode64Bit(uint64_t tag, int32_t value, absl::Span<char> *buf) {
return Encode64Bit(tag, static_cast<uint64_t>(value), buf);
}
// Encodes the specified double as a 64-bit field and returns true if it fits.
// Used for double field type.
// Consumes up to kMaxVarintSize + 8 bytes (18).
inline bool EncodeDouble(uint64_t tag, double value, absl::Span<char> *buf) {
return Encode64Bit(tag, absl::bit_cast<uint64_t>(value), buf);
}
// Encodes the specified integer as a 32-bit field and returns true if it fits.
// Used for fixed32 and sfixed32 field types.
// Consumes up to kMaxVarintSize + 4 bytes (14).
bool Encode32Bit(uint64_t tag, uint32_t value, absl::Span<char> *buf);
inline bool Encode32Bit(uint64_t tag, int32_t value, absl::Span<char> *buf) {
return Encode32Bit(tag, static_cast<uint32_t>(value), buf);
}
// Encodes the specified float as a 32-bit field and returns true if it fits.
// Used for float field type.
// Consumes up to kMaxVarintSize + 4 bytes (14).
inline bool EncodeFloat(uint64_t tag, float value, absl::Span<char> *buf) {
return Encode32Bit(tag, absl::bit_cast<uint32_t>(value), buf);
}
// Encodes the specified bytes as a length-delimited field and returns true if
// they fit.
// Used for string, bytes, message, and packed-repeated field type.
// Consumes up to kMaxVarintSize * 2 + value.size() bytes (20 + value.size()).
bool EncodeBytes(uint64_t tag, absl::Span<const char> value,
absl::Span<char> *buf);
// Encodes as many of the specified bytes as will fit as a length-delimited
// field and returns true as long as the field header (`tag_type` and `length`)
// fits.
// Used for string, bytes, message, and packed-repeated field type.
// Consumes up to kMaxVarintSize * 2 + value.size() bytes (20 + value.size()).
bool EncodeBytesTruncate(uint64_t tag, absl::Span<const char> value,
absl::Span<char> *buf);
// Encodes the specified string as a length-delimited field and returns true if
// it fits.
// Used for string, bytes, message, and packed-repeated field type.
// Consumes up to kMaxVarintSize * 2 + value.size() bytes (20 + value.size()).
inline bool EncodeString(uint64_t tag, absl::string_view value,
absl::Span<char> *buf) {
return EncodeBytes(tag, value, buf);
}
// Encodes as much of the specified string as will fit as a length-delimited
// field and returns true as long as the field header (`tag_type` and `length`)
// fits.
// Used for string, bytes, message, and packed-repeated field type.
// Consumes up to kMaxVarintSize * 2 + value.size() bytes (20 + value.size()).
inline bool EncodeStringTruncate(uint64_t tag, absl::string_view value,
absl::Span<char> *buf) {
return EncodeBytesTruncate(tag, value, buf);
}
// Encodes the header for a length-delimited field containing up to `max_size`
// bytes or the number remaining in the buffer, whichever is less. If the
// header fits, a non-nullptr `Span` is returned; this must be passed to
// `EncodeMessageLength` after all contents are encoded to finalize the length
// field. If the header does not fit, a nullptr `Span` is returned which is
// safe to pass to `EncodeMessageLength` but need not be.
// Used for string, bytes, message, and packed-repeated field type.
// Consumes up to kMaxVarintSize * 2 bytes (20).
[[nodiscard]] absl::Span<char> EncodeMessageStart(uint64_t tag,
uint64_t max_size,
absl::Span<char> *buf);
// Finalizes the length field in `msg` so that it encompasses all data encoded
// since the call to `EncodeMessageStart` which returned `msg`. Does nothing if
// `msg` is a `nullptr` `Span`.
void EncodeMessageLength(absl::Span<char> msg, const absl::Span<char> *buf);
enum class WireType : uint64_t {
kVarint = 0,
k64Bit = 1,
kLengthDelimited = 2,
k32Bit = 5,
};
constexpr size_t VarintSize(uint64_t value) {
return value < 128 ? 1 : 1 + VarintSize(value >> 7);
}
constexpr size_t MinVarintSize() {
return VarintSize((std::numeric_limits<uint64_t>::min)());
}
constexpr size_t MaxVarintSize() {
return VarintSize((std::numeric_limits<uint64_t>::max)());
}
constexpr uint64_t MaxVarintForSize(size_t size) {
return size >= 10 ? (std::numeric_limits<uint64_t>::max)()
: (static_cast<uint64_t>(1) << size * 7) - 1;
}
constexpr uint64_t MakeTagType(uint64_t tag, WireType type) {
return tag << 3 | static_cast<uint64_t>(type);
}
// `BufferSizeFor` returns a number of bytes guaranteed to be sufficient to
// store encoded fields as `(tag, WireType)`, regardless of data values. This
// only makes sense for `WireType::kLengthDelimited` if you add in the length of
// the contents yourself, e.g. for string and bytes fields by adding the lengths
// of any encoded strings to the return value or for submessage fields by
// enumerating the fields you may encode into their contents.
constexpr size_t BufferSizeFor(uint64_t tag, WireType type) {
size_t buffer_size = VarintSize(MakeTagType(tag, type));
switch (type) {
case WireType::kVarint:
buffer_size += MaxVarintSize();
break;
case WireType::k64Bit:
buffer_size += size_t{8};
break;
case WireType::kLengthDelimited:
buffer_size += MaxVarintSize();
break;
case WireType::k32Bit:
buffer_size += size_t{4};
break;
}
return buffer_size;
}
// absl::Span<const char> represents a view into the un-processed space in a
// buffer during decoding. Decoding functions shrink the span as they go so
// that the same view can be decoded iteratively until all data are processed.
// In general, if the buffer is exhausted but additional bytes are expected by
// the decoder, it will return values as if the additional bytes were zeros.
// Length-delimited fields are an exception - if the encoded length field
// indicates more data bytes than are available in the buffer, the `bytes_value`
// and `string_value` accessors will return truncated views.
class ProtoField final {
public:
// Consumes bytes from `data` and returns true if there were any bytes to
// decode.
bool DecodeFrom(absl::Span<const char> *data);
uint64_t tag() const { return tag_; }
WireType type() const { return type_; }
// These value accessors will return nonsense if the data were not encoded in
// the corresponding wiretype from the corresponding C++ (or other language)
// type.
double double_value() const { return absl::bit_cast<double>(value_); }
float float_value() const {
return absl::bit_cast<float>(static_cast<uint32_t>(value_));
}
int32_t int32_value() const { return static_cast<int32_t>(value_); }
int64_t int64_value() const { return static_cast<int64_t>(value_); }
int32_t sint32_value() const {
if (value_ % 2) return static_cast<int32_t>(0 - ((value_ - 1) / 2) - 1);
return static_cast<int32_t>(value_ / 2);
}
int64_t sint64_value() const {
if (value_ % 2) return 0 - ((value_ - 1) / 2) - 1;
return value_ / 2;
}
uint32_t uint32_value() const { return static_cast<uint32_t>(value_); }
uint64_t uint64_value() const { return value_; }
bool bool_value() const { return value_ != 0; }
// To decode an enum, call int32_value() and cast to the appropriate type.
// Note that the official C++ proto compiler treats enum fields with values
// that do not correspond to a defined enumerator as unknown fields.
// To decode fields within a submessage field, call
// `DecodeNextField(field.BytesValue())`.
absl::Span<const char> bytes_value() const { return data_; }
absl::string_view string_value() const {
const auto data = bytes_value();
return absl::string_view(data.data(), data.size());
}
// Returns the encoded length of a length-delimited field. This equals
// `bytes_value().size()` except when the latter has been truncated due to
// buffer underrun.
uint64_t encoded_length() const { return value_; }
private:
uint64_t tag_;
WireType type_;
// For `kTypeVarint`, `kType64Bit`, and `kType32Bit`, holds the decoded value.
// For `kTypeLengthDelimited`, holds the decoded length.
uint64_t value_;
absl::Span<const char> data_;
};
} // namespace log_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_LOG_INTERNAL_PROTO_H_
*¤A
hsoong/.intermediates/external/abseil-cpp/absl_log_log_entry_hdrs/gen/my_include_dir/absl/log/log_entry.h·@// Copyright 2022 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: log/log_entry.h
// -----------------------------------------------------------------------------
//
// This header declares `class absl::LogEntry`, which represents a log record as
// passed to `LogSink::Send`. Data returned by pointer or by reference or by
// `absl::string_view` must be copied if they are needed after the lifetime of
// the `absl::LogEntry`.
#ifndef ABSL_LOG_LOG_ENTRY_H_
#define ABSL_LOG_LOG_ENTRY_H_
#include <cstddef>
#include <string>
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/log_severity.h"
#include "absl/log/internal/config.h"
#include "absl/strings/string_view.h"
#include "absl/time/time.h"
#include "absl/types/span.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace log_internal {
// Test only friend.
class LogEntryTestPeer;
class LogMessage;
} // namespace log_internal
// LogEntry
//
// Represents a single entry in a log, i.e., one `LOG` statement or failed
// `CHECK`.
//
// `LogEntry` is thread-compatible.
class LogEntry final {
public:
using tid_t = log_internal::Tid;
// For non-verbose log entries, `verbosity()` returns `kNoVerbosityLevel`.
static constexpr int kNoVerbosityLevel = -1;
static constexpr int kNoVerboseLevel = -1; // TO BE removed
// Pass `LogEntry` by reference, and do not store it as its state does not
// outlive the call to `LogSink::Send()`.
LogEntry(const LogEntry&) = delete;
LogEntry& operator=(const LogEntry&) = delete;
// Source file and line where the log message occurred. Taken from `__FILE__`
// and `__LINE__` unless overridden by `LOG(...).AtLocation(...)`.
//
// Take special care not to use the values returned by `source_filename()` and
// `source_basename()` after the lifetime of the entry. This is always
// incorrect, but it will often work in practice because they usually point
// into a statically allocated character array obtained from `__FILE__`.
// Statements like `LOG(INFO).AtLocation(std::string(...), ...)` will expose
// the bug. If you need the data later, you must copy them.
absl::string_view source_filename() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return full_filename_;
}
absl::string_view source_basename() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return base_filename_;
}
int source_line() const { return line_; }
// LogEntry::prefix()
//
// True unless the metadata prefix was suppressed once by
// `LOG(...).NoPrefix()` or globally by `absl::EnableLogPrefix(false)`.
// Implies `text_message_with_prefix() == text_message()`.
bool prefix() const { return prefix_; }
// LogEntry::log_severity()
//
// Returns this entry's severity. For `LOG`, taken from the first argument;
// for `CHECK`, always `absl::LogSeverity::kFatal`.
absl::LogSeverity log_severity() const { return severity_; }
// LogEntry::verbosity()
//
// Returns this entry's verbosity, or `kNoVerbosityLevel` for a non-verbose
// entry. Taken from the argument to `VLOG` or from
// `LOG(...).WithVerbosity(...)`.
int verbosity() const { return verbose_level_; }
// LogEntry::timestamp()
//
// Returns the time at which this entry was written. Captured during
// evaluation of `LOG`, but can be overridden by
// `LOG(...).WithTimestamp(...)`.
//
// Take care not to rely on timestamps increasing monotonically, or even to
// rely on timestamps having any particular relationship with reality (since
// they can be overridden).
absl::Time timestamp() const { return timestamp_; }
// LogEntry::tid()
//
// Returns the ID of the thread that wrote this entry. Captured during
// evaluation of `LOG`, but can be overridden by `LOG(...).WithThreadID(...)`.
//
// Take care not to *rely* on reported thread IDs as they can be overridden as
// specified above.
tid_t tid() const { return tid_; }
// Text-formatted version of the log message. An underlying buffer holds
// these contiguous data:
//
// * A prefix formed by formatting metadata (timestamp, filename, line number,
// etc.)
// The prefix may be empty - see `LogEntry::prefix()` - and may rarely be
// truncated if the metadata are very long.
// * The streamed data
// The data may be empty if nothing was streamed, or may be truncated to fit
// the buffer.
// * A newline
// * A nul terminator
//
// The newline and nul terminator will be present even if the prefix and/or
// data are truncated.
//
// These methods give access to the most commonly useful substrings of the
// buffer's contents. Other combinations can be obtained with substring
// arithmetic.
//
// The buffer does not outlive the entry; if you need the data later, you must
// copy them.
absl::string_view text_message_with_prefix_and_newline() const
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return absl::string_view(
text_message_with_prefix_and_newline_and_nul_.data(),
text_message_with_prefix_and_newline_and_nul_.size() - 1);
}
absl::string_view text_message_with_prefix() const
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return absl::string_view(
text_message_with_prefix_and_newline_and_nul_.data(),
text_message_with_prefix_and_newline_and_nul_.size() - 2);
}
absl::string_view text_message_with_newline() const
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return absl::string_view(
text_message_with_prefix_and_newline_and_nul_.data() + prefix_len_,
text_message_with_prefix_and_newline_and_nul_.size() - prefix_len_ - 1);
}
absl::string_view text_message() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return absl::string_view(
text_message_with_prefix_and_newline_and_nul_.data() + prefix_len_,
text_message_with_prefix_and_newline_and_nul_.size() - prefix_len_ - 2);
}
const char* text_message_with_prefix_and_newline_c_str() const
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return text_message_with_prefix_and_newline_and_nul_.data();
}
// Returns a serialized protobuf holding the operands streamed into this
// log message. The message definition is not yet published.
//
// The buffer does not outlive the entry; if you need the data later, you must
// copy them.
absl::string_view encoded_message() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return encoding_;
}
// LogEntry::stacktrace()
//
// Optional stacktrace, e.g. for `FATAL` logs and failed `CHECK`s.
//
// Fatal entries are dispatched to each sink twice: first with all data and
// metadata but no stacktrace, and then with the stacktrace. This is done
// because stacktrace collection is sometimes slow and fallible, and it's
// critical to log enough information to diagnose the failure even if the
// stacktrace collection hangs.
//
// The buffer does not outlive the entry; if you need the data later, you must
// copy them.
absl::string_view stacktrace() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
return stacktrace_;
}
private:
LogEntry() = default;
absl::string_view full_filename_;
absl::string_view base_filename_;
int line_;
bool prefix_;
absl::LogSeverity severity_;
int verbose_level_; // >=0 for `VLOG`, etc.; otherwise `kNoVerbosityLevel`.
absl::Time timestamp_;
tid_t tid_;
absl::Span<const char> text_message_with_prefix_and_newline_and_nul_;
size_t prefix_len_;
absl::string_view encoding_;
std::string stacktrace_;
friend class log_internal::LogEntryTestPeer;
friend class log_internal::LogMessage;
};
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_LOG_LOG_ENTRY_H_
*—8
psoong/.intermediates/external/abseil-cpp/absl_base_log_severity_hdrs/gen/my_include_dir/absl/base/log_severity.h¢7// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_BASE_LOG_SEVERITY_H_
#define ABSL_BASE_LOG_SEVERITY_H_
#include <array>
#include <ostream>
#include "absl/base/attributes.h"
#include "absl/base/config.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
// absl::LogSeverity
//
// Four severity levels are defined. Logging APIs should terminate the program
// when a message is logged at severity `kFatal`; the other levels have no
// special semantics.
//
// Values other than the four defined levels (e.g. produced by `static_cast`)
// are valid, but their semantics when passed to a function, macro, or flag
// depend on the function, macro, or flag. The usual behavior is to normalize
// such values to a defined severity level, however in some cases values other
// than the defined levels are useful for comparison.
//
// Example:
//
// // Effectively disables all logging:
// SetMinLogLevel(static_cast<absl::LogSeverity>(100));
//
// Abseil flags may be defined with type `LogSeverity`. Dependency layering
// constraints require that the `AbslParseFlag()` overload be declared and
// defined in the flags library itself rather than here. The `AbslUnparseFlag()`
// overload is defined there as well for consistency.
//
// absl::LogSeverity Flag String Representation
//
// An `absl::LogSeverity` has a string representation used for parsing
// command-line flags based on the enumerator name (e.g. `kFatal`) or
// its unprefixed name (without the `k`) in any case-insensitive form. (E.g.
// "FATAL", "fatal" or "Fatal" are all valid.) Unparsing such flags produces an
// unprefixed string representation in all caps (e.g. "FATAL") or an integer.
//
// Additionally, the parser accepts arbitrary integers (as if the type were
// `int`).
//
// Examples:
//
// --my_log_level=kInfo
// --my_log_level=INFO
// --my_log_level=info
// --my_log_level=0
//
// `DFATAL` and `kLogDebugFatal` are similarly accepted.
//
// Unparsing a flag produces the same result as `absl::LogSeverityName()` for
// the standard levels and a base-ten integer otherwise.
enum class LogSeverity : int {
kInfo = 0,
kWarning = 1,
kError = 2,
kFatal = 3,
};
// LogSeverities()
//
// Returns an iterable of all standard `absl::LogSeverity` values, ordered from
// least to most severe.
constexpr std::array<absl::LogSeverity, 4> LogSeverities() {
return {{absl::LogSeverity::kInfo, absl::LogSeverity::kWarning,
absl::LogSeverity::kError, absl::LogSeverity::kFatal}};
}
// `absl::kLogDebugFatal` equals `absl::LogSeverity::kFatal` in debug builds
// (i.e. when `NDEBUG` is not defined) and `absl::LogSeverity::kError`
// otherwise. Avoid ODR-using this variable as it has internal linkage and thus
// distinct storage in different TUs.
#ifdef NDEBUG
static constexpr absl::LogSeverity kLogDebugFatal = absl::LogSeverity::kError;
#else
static constexpr absl::LogSeverity kLogDebugFatal = absl::LogSeverity::kFatal;
#endif
// LogSeverityName()
//
// Returns the all-caps string representation (e.g. "INFO") of the specified
// severity level if it is one of the standard levels and "UNKNOWN" otherwise.
constexpr const char* LogSeverityName(absl::LogSeverity s) {
switch (s) {
case absl::LogSeverity::kInfo: return "INFO";
case absl::LogSeverity::kWarning: return "WARNING";
case absl::LogSeverity::kError: return "ERROR";
case absl::LogSeverity::kFatal: return "FATAL";
}
return "UNKNOWN";
}
// NormalizeLogSeverity()
//
// Values less than `kInfo` normalize to `kInfo`; values greater than `kFatal`
// normalize to `kError` (**NOT** `kFatal`).
constexpr absl::LogSeverity NormalizeLogSeverity(absl::LogSeverity s) {
absl::LogSeverity n = s;
if (n < absl::LogSeverity::kInfo) n = absl::LogSeverity::kInfo;
if (n > absl::LogSeverity::kFatal) n = absl::LogSeverity::kError;
return n;
}
constexpr absl::LogSeverity NormalizeLogSeverity(int s) {
return absl::NormalizeLogSeverity(static_cast<absl::LogSeverity>(s));
}
// operator<<
//
// The exact representation of a streamed `absl::LogSeverity` is deliberately
// unspecified; do not rely on it.
std::ostream& operator<<(std::ostream& os, absl::LogSeverity s);
// Enums representing a lower bound for LogSeverity. APIs that only operate on
// messages of at least a certain level (for example, `SetMinLogLevel()`) use
// this type to specify that level. absl::LogSeverityAtLeast::kInfinity is
// a level above all threshold levels and therefore no log message will
// ever meet this threshold.
enum class LogSeverityAtLeast : int {
kInfo = static_cast<int>(absl::LogSeverity::kInfo),
kWarning = static_cast<int>(absl::LogSeverity::kWarning),
kError = static_cast<int>(absl::LogSeverity::kError),
kFatal = static_cast<int>(absl::LogSeverity::kFatal),
kInfinity = 1000,
};
std::ostream& operator<<(std::ostream& os, absl::LogSeverityAtLeast s);
// Enums representing an upper bound for LogSeverity. APIs that only operate on
// messages of at most a certain level (for example, buffer all messages at or
// below a certain level) use this type to specify that level.
// absl::LogSeverityAtMost::kNegativeInfinity is a level below all threshold
// levels and therefore will exclude all log messages.
enum class LogSeverityAtMost : int {
kNegativeInfinity = -1000,
kInfo = static_cast<int>(absl::LogSeverity::kInfo),
kWarning = static_cast<int>(absl::LogSeverity::kWarning),
kError = static_cast<int>(absl::LogSeverity::kError),
kFatal = static_cast<int>(absl::LogSeverity::kFatal),
};
std::ostream& operator<<(std::ostream& os, absl::LogSeverityAtMost s);
#define COMPOP(op1, op2, T) \
constexpr bool operator op1(absl::T lhs, absl::LogSeverity rhs) { \
return static_cast<absl::LogSeverity>(lhs) op1 rhs; \
} \
constexpr bool operator op2(absl::LogSeverity lhs, absl::T rhs) { \
return lhs op2 static_cast<absl::LogSeverity>(rhs); \
}
// Comparisons between `LogSeverity` and `LogSeverityAtLeast`/
// `LogSeverityAtMost` are only supported in one direction.
// Valid checks are:
// LogSeverity >= LogSeverityAtLeast
// LogSeverity < LogSeverityAtLeast
// LogSeverity <= LogSeverityAtMost
// LogSeverity > LogSeverityAtMost
COMPOP(>, <, LogSeverityAtLeast)
COMPOP(<=, >=, LogSeverityAtLeast)
COMPOP(<, >, LogSeverityAtMost)
COMPOP(>=, <=, LogSeverityAtMost)
#undef COMPOP
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_LOG_SEVERITY_H_
*øl
nsoong/.intermediates/external/abseil-cpp/absl_base_nullability_hdrs/gen/my_include_dir/absl/base/nullability.h…l// Copyright 2023 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: nullability.h
// -----------------------------------------------------------------------------
//
// This header file defines a set of annotations for designating the expected
// nullability of pointers. These annotations allow you to designate pointers in
// one of three classification states:
//
// * "Non-null" (for pointers annotated `absl_nonnull`), indicating that it is
// invalid for the given pointer to ever be null.
// * "Nullable" (for pointers annotated `absl_nullable`), indicating that it is
// valid for the given pointer to be null.
// * "Unknown" (for pointers annotated `absl_nullability_unknown`), indicating
// that the given pointer has not yet been classified as either nullable or
// non-null. This is the default state of unannotated pointers.
//
// NOTE: Unannotated pointers implicitly bear the annotation
// `absl_nullability_unknown`; you should rarely, if ever, see this annotation
// used in the codebase explicitly.
//
// -----------------------------------------------------------------------------
// Nullability and Contracts
// -----------------------------------------------------------------------------
//
// These nullability annotations allow you to more clearly specify contracts on
// software components by narrowing the *preconditions*, *postconditions*, and
// *invariants* of pointer state(s) in any given interface. It then depends on
// context who is responsible for fulfilling the annotation's requirements.
//
// For example, a function may receive a pointer argument. Designating that
// pointer argument as "non-null" tightens the precondition of the contract of
// that function. It is then the responsibility of anyone calling such a
// function to ensure that the passed pointer is not null.
//
// Similarly, a function may have a pointer as a return value. Designating that
// return value as "non-null" tightens the postcondition of the contract of that
// function. In this case, however, it is the responsibility of the function
// itself to ensure that the returned pointer is not null.
//
// Clearly defining these contracts allows providers (and consumers) of such
// pointers to have more confidence in their null state. If a function declares
// a return value as "non-null", for example, the caller should not need to
// check whether the returned value is `nullptr`; it can simply assume the
// pointer is valid.
//
// Of course most interfaces already have expectations on the nullability state
// of pointers, and these expectations are, in effect, a contract; often,
// however, those contracts are either poorly or partially specified, assumed,
// or misunderstood. These nullability annotations are designed to allow you to
// formalize those contracts within the codebase.
//
// -----------------------------------------------------------------------------
// Annotation Syntax
// -----------------------------------------------------------------------------
//
// The annotations should be positioned as a qualifier for the pointer type. For
// example, the position of `const` when declaring a const pointer (not a
// pointer to a const type) is the position you should also use for these
// annotations.
//
// Example:
//
// // A const non-null pointer to an `Employee`.
// Employee* absl_nonnull const e;
//
// // A non-null pointer to a const `Employee`.
// const Employee* absl_nonnull e;
//
// // A non-null pointer to a const nullable pointer to an `Employee`.
// Employee* absl_nullable const* absl_nonnull e = nullptr;
//
// // A non-null function pointer.
// void (*absl_nonnull func)(int, double);
//
// // A non-null array of `Employee`s as a parameter.
// void func(Employee employees[absl_nonnull]);
//
// // A non-null std::unique_ptr to an `Employee`.
// // As with `const`, it is possible to place the annotation on either side of
// // a named type not ending in `*`, but placing it before the type it
// // describes is preferred, unless inconsistent with surrounding code.
// absl_nonnull std::unique_ptr<Employee> employee;
//
// // Invalid annotation usage – this attempts to declare a pointer to a
// // nullable `Employee`, which is meaningless.
// absl_nullable Employee* e;
//
// -----------------------------------------------------------------------------
// Using Nullability Annotations
// -----------------------------------------------------------------------------
//
// Each annotation acts as a form of documentation about the contract for the
// given pointer. Each annotation requires providers or consumers of these
// pointers across API boundaries to take appropriate steps when setting or
// using these pointers:
//
// * "Non-null" pointers should never be null. It is the responsibility of the
// provider of this pointer to ensure that the pointer may never be set to
// null. Consumers of such pointers can treat such pointers as non-null.
// * "Nullable" pointers may or may not be null. Consumers of such pointers
// should precede any usage of that pointer (e.g. a dereference operation)
// with a a `nullptr` check.
// * "Unknown" pointers may be either "non-null" or "nullable" but have not been
// definitively determined to be in either classification state. Providers of
// such pointers across API boundaries should determine -- over time -- to
// annotate the pointer in either of the above two states. Consumers of such
// pointers across an API boundary should continue to treat such pointers as
// they currently do.
//
// Example:
//
// // PaySalary() requires the passed pointer to an `Employee` to be non-null.
// void PaySalary(Employee* absl_nonnull e) {
// pay(e->salary); // OK to dereference
// }
//
// // CompleteTransaction() guarantees the returned pointer to an `Account` to
// // be non-null.
// Account* absl_nonnull balance CompleteTransaction(double fee) {
// ...
// }
//
// // Note that specifying a nullability annotation does not prevent someone
// // from violating the contract:
//
// Employee* absl_nullable find(Map& employees, std::string_view name);
//
// void g(Map& employees) {
// Employee *e = find(employees, "Pat");
// // `e` can now be null.
// PaySalary(e); // Violates contract, but compiles!
// }
//
// Nullability annotations, in other words, are useful for defining and
// narrowing contracts; *enforcement* of those contracts depends on use and any
// additional (static or dynamic analysis) tooling.
//
// NOTE: The "unknown" annotation state indicates that a pointer's contract has
// not yet been positively identified. The unknown state therefore acts as a
// form of documentation of your technical debt, and a codebase that adopts
// nullability annotations should aspire to annotate every pointer as either
// "non-null" or "nullable".
//
// -----------------------------------------------------------------------------
// Applicability of Nullability Annotations
// -----------------------------------------------------------------------------
//
// By default, nullability annotations are applicable to raw and smart
// pointers. User-defined types can indicate compatibility with nullability
// annotations by adding the ABSL_NULLABILITY_COMPATIBLE attribute.
//
// // Example:
// struct ABSL_NULLABILITY_COMPATIBLE MyPtr {
// ...
// };
//
// Note: Compilers that don't support the `nullability_on_classes` feature will
// allow nullability annotations to be applied to any type, not just ones
// marked with `ABSL_NULLABILITY_COMPATIBLE`.
//
// DISCLAIMER:
// ===========================================================================
// These nullability annotations are primarily a human readable signal about the
// intended contract of the pointer. They are not *types* and do not currently
// provide any correctness guarantees. For example, a pointer annotated as
// `absl_nonnull` is *not guaranteed* to be non-null, and the compiler won't
// alert or prevent assignment of a `T* absl_nullable` to a `T* absl_nonnull`.
// ===========================================================================
#ifndef ABSL_BASE_NULLABILITY_H_
#define ABSL_BASE_NULLABILITY_H_
#include "absl/base/config.h"
#include "absl/base/internal/nullability_deprecated.h"
// ABSL_POINTERS_DEFAULT_NONNULL
//
// This macro specifies that all unannotated pointer types within the given
// file are designated as nonnull (instead of the default "unknown"). This macro
// exists as a standalone statement and applies default nonnull behavior to all
// subsequent pointers; as a result, place this macro as the first non-comment,
// non-`#include` line in a file.
//
// Example:
//
// #include "absl/base/nullability.h"
//
// ABSL_POINTERS_DEFAULT_NONNULL
//
// void FillMessage(Message *m); // implicitly non-null
// T* absl_nullable GetNullablePtr(); // explicitly nullable
// T* absl_nullability_unknown GetUnknownPtr(); // explicitly unknown
//
// The macro can be safely used in header files – it will not affect any files
// that include it.
//
// In files with the macro, plain `T*` syntax means `T* absl_nonnull`, and the
// exceptions (`absl_nullable` and `absl_nullability_unknown`) must be marked
// explicitly. The same holds, correspondingly, for smart pointer types.
//
// For comparison, without the macro, all unannotated pointers would default to
// unknown, and otherwise require explicit annotations to change this behavior:
//
// #include "absl/base/nullability.h"
//
// void FillMessage(Message* absl_nonnull m); // explicitly non-null
// T* absl_nullable GetNullablePtr(); // explicitly nullable
// T* GetUnknownPtr(); // implicitly unknown
//
// No-op except for being a human readable signal.
#define ABSL_POINTERS_DEFAULT_NONNULL
#if defined(__clang__) && !defined(__OBJC__) && \
ABSL_HAVE_FEATURE(nullability_on_classes)
// absl_nonnull (default with `ABSL_POINTERS_DEFAULT_NONNULL`)
//
// The indicated pointer is never null. It is the responsibility of the provider
// of this pointer across an API boundary to ensure that the pointer is never
// set to null. Consumers of this pointer across an API boundary may safely
// dereference the pointer.
//
// Example:
//
// // `employee` is designated as not null.
// void PaySalary(Employee* absl_nonnull employee) {
// pay(*employee); // OK to dereference
// }
#define absl_nonnull _Nonnull
// absl_nullable
//
// The indicated pointer may, by design, be either null or non-null. Consumers
// of this pointer across an API boundary should perform a `nullptr` check
// before performing any operation using the pointer.
//
// Example:
//
// // `employee` may be null.
// void PaySalary(Employee* absl_nullable employee) {
// if (employee != nullptr) {
// Pay(*employee); // OK to dereference
// }
// }
#define absl_nullable _Nullable
// absl_nullability_unknown (default without `ABSL_POINTERS_DEFAULT_NONNULL`)
//
// The indicated pointer has not yet been determined to be definitively
// "non-null" or "nullable." Providers of such pointers across API boundaries
// should, over time, annotate such pointers as either "non-null" or "nullable."
// Consumers of these pointers across an API boundary should treat such pointers
// with the same caution they treat currently unannotated pointers. Most
// existing code will have "unknown" pointers, which should eventually be
// migrated into one of the above two nullability states: `absl_nonnull` or
// `absl_nullable`.
//
// NOTE: For files that do not specify `ABSL_POINTERS_DEFAULT_NONNULL`,
// because this annotation is the global default state, unannotated pointers are
// are assumed to have "unknown" semantics. This assumption is designed to
// minimize churn and reduce clutter within the codebase.
//
// Example:
//
// // `employee`s nullability state is unknown.
// void PaySalary(Employee* absl_nullability_unknown employee) {
// Pay(*employee); // Potentially dangerous. API provider should investigate.
// }
//
// Note that a pointer without an annotation, by default, is assumed to have the
// annotation `NullabilityUnknown`.
//
// // `employee`s nullability state is unknown.
// void PaySalary(Employee* employee) {
// Pay(*employee); // Potentially dangerous. API provider should investigate.
// }
#define absl_nullability_unknown _Null_unspecified
#else
// No-op for non-Clang compilers or Objective-C.
#define absl_nonnull
// No-op for non-Clang compilers or Objective-C.
#define absl_nullable
// No-op for non-Clang compilers or Objective-C.
#define absl_nullability_unknown
#endif
// ABSL_NULLABILITY_COMPATIBLE
//
// Indicates that a class is compatible with nullability annotations.
//
// For example:
//
// struct ABSL_NULLABILITY_COMPATIBLE MyPtr {
// ...
// };
//
// Note: Compilers that don't support the `nullability_on_classes` feature will
// allow nullability annotations to be applied to any type, not just ones marked
// with `ABSL_NULLABILITY_COMPATIBLE`.
#if ABSL_HAVE_FEATURE(nullability_on_classes)
#define ABSL_NULLABILITY_COMPATIBLE _Nullable
#else
#define ABSL_NULLABILITY_COMPATIBLE
#endif
#endif // ABSL_BASE_NULLABILITY_H_
*м
dsoong/.intermediates/external/abseil-cpp/absl_strings_hdrs/gen/my_include_dir/absl/strings/str_cat.hæ»//
// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: str_cat.h
// -----------------------------------------------------------------------------
//
// This package contains functions for efficiently concatenating and appending
// strings: `StrCat()` and `StrAppend()`. Most of the work within these routines
// is actually handled through use of a special AlphaNum type, which was
// designed to be used as a parameter type that efficiently manages conversion
// to strings and avoids copies in the above operations.
//
// Any routine accepting either a string or a number may accept `AlphaNum`.
// The basic idea is that by accepting a `const AlphaNum &` as an argument
// to your function, your callers will automagically convert bools, integers,
// and floating point values to strings for you.
//
// NOTE: Use of `AlphaNum` outside of the //absl/strings package is unsupported
// except for the specific case of function parameters of type `AlphaNum` or
// `const AlphaNum &`. In particular, instantiating `AlphaNum` directly as a
// stack variable is not supported.
//
// Conversion from 8-bit values is not accepted because, if it were, then an
// attempt to pass ':' instead of ":" might result in a 58 ending up in your
// result.
//
// Bools convert to "0" or "1". Pointers to types other than `char *` are not
// valid inputs. No output is generated for null `char *` pointers.
//
// Floating point numbers are formatted with six-digit precision, which is
// the default for "std::cout <<" or printf "%g" (the same as "%.6g").
//
// You can convert to hexadecimal output rather than decimal output using the
// `Hex` type contained here. To do so, pass `Hex(my_int)` as a parameter to
// `StrCat()` or `StrAppend()`. You may specify a minimum hex field width using
// a `PadSpec` enum.
//
// User-defined types can be formatted with the `AbslStringify()` customization
// point. The API relies on detecting an overload in the user-defined type's
// namespace of a free (non-member) `AbslStringify()` function as a definition
// (typically declared as a friend and implemented in-line.
// with the following signature:
//
// class MyClass { ... };
//
// template <typename Sink>
// void AbslStringify(Sink& sink, const MyClass& value);
//
// An `AbslStringify()` overload for a type should only be declared in the same
// file and namespace as said type.
//
// Note that `AbslStringify()` also supports use with `absl::StrFormat()` and
// `absl::Substitute()`.
//
// Example:
//
// struct Point {
// // To add formatting support to `Point`, we simply need to add a free
// // (non-member) function `AbslStringify()`. This method specifies how
// // Point should be printed when absl::StrCat() is called on it. You can add
// // such a free function using a friend declaration within the body of the
// // class. The sink parameter is a templated type to avoid requiring
// // dependencies.
// template <typename Sink> friend void AbslStringify(Sink&
// sink, const Point& p) {
// absl::Format(&sink, "(%v, %v)", p.x, p.y);
// }
//
// int x;
// int y;
// };
// -----------------------------------------------------------------------------
#ifndef ABSL_STRINGS_STR_CAT_H_
#define ABSL_STRINGS_STR_CAT_H_
#include <algorithm>
#include <array>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <initializer_list>
#include <limits>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/nullability.h"
#include "absl/base/port.h"
#include "absl/meta/type_traits.h"
#include "absl/strings/has_absl_stringify.h"
#include "absl/strings/internal/resize_uninitialized.h"
#include "absl/strings/internal/stringify_sink.h"
#include "absl/strings/numbers.h"
#include "absl/strings/string_view.h"
#if !defined(ABSL_USES_STD_STRING_VIEW)
#include <string_view>
#endif
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace strings_internal {
// AlphaNumBuffer allows a way to pass a string to StrCat without having to do
// memory allocation. It is simply a pair of a fixed-size character array, and
// a size. Please don't use outside of absl, yet.
template <size_t max_size>
struct AlphaNumBuffer {
std::array<char, max_size> data;
size_t size;
};
} // namespace strings_internal
// Enum that specifies the number of significant digits to return in a `Hex` or
// `Dec` conversion and fill character to use. A `kZeroPad2` value, for example,
// would produce hexadecimal strings such as "0a","0f" and a 'kSpacePad5' value
// would produce hexadecimal strings such as " a"," f".
enum PadSpec : uint8_t {
kNoPad = 1,
kZeroPad2,
kZeroPad3,
kZeroPad4,
kZeroPad5,
kZeroPad6,
kZeroPad7,
kZeroPad8,
kZeroPad9,
kZeroPad10,
kZeroPad11,
kZeroPad12,
kZeroPad13,
kZeroPad14,
kZeroPad15,
kZeroPad16,
kZeroPad17,
kZeroPad18,
kZeroPad19,
kZeroPad20,
kSpacePad2 = kZeroPad2 + 64,
kSpacePad3,
kSpacePad4,
kSpacePad5,
kSpacePad6,
kSpacePad7,
kSpacePad8,
kSpacePad9,
kSpacePad10,
kSpacePad11,
kSpacePad12,
kSpacePad13,
kSpacePad14,
kSpacePad15,
kSpacePad16,
kSpacePad17,
kSpacePad18,
kSpacePad19,
kSpacePad20,
};
// -----------------------------------------------------------------------------
// Hex
// -----------------------------------------------------------------------------
//
// `Hex` stores a set of hexadecimal string conversion parameters for use
// within `AlphaNum` string conversions.
struct Hex {
uint64_t value;
uint8_t width;
char fill;
template <typename Int>
explicit Hex(
Int v, PadSpec spec = absl::kNoPad,
std::enable_if_t<sizeof(Int) == 1 && !std::is_pointer<Int>::value, bool> =
true)
: Hex(spec, static_cast<uint8_t>(v)) {}
template <typename Int>
explicit Hex(
Int v, PadSpec spec = absl::kNoPad,
std::enable_if_t<sizeof(Int) == 2 && !std::is_pointer<Int>::value, bool> =
true)
: Hex(spec, static_cast<uint16_t>(v)) {}
template <typename Int>
explicit Hex(
Int v, PadSpec spec = absl::kNoPad,
std::enable_if_t<sizeof(Int) == 4 && !std::is_pointer<Int>::value, bool> =
true)
: Hex(spec, static_cast<uint32_t>(v)) {}
template <typename Int>
explicit Hex(
Int v, PadSpec spec = absl::kNoPad,
std::enable_if_t<sizeof(Int) == 8 && !std::is_pointer<Int>::value, bool> =
true)
: Hex(spec, static_cast<uint64_t>(v)) {}
template <typename Pointee>
explicit Hex(Pointee* absl_nullable v, PadSpec spec = absl::kNoPad)
: Hex(spec, reinterpret_cast<uintptr_t>(v)) {}
template <typename S>
friend void AbslStringify(S& sink, Hex hex) {
static_assert(
numbers_internal::kFastToBufferSize >= 32,
"This function only works when output buffer >= 32 bytes long");
char buffer[numbers_internal::kFastToBufferSize];
char* const end = &buffer[numbers_internal::kFastToBufferSize];
auto real_width =
absl::numbers_internal::FastHexToBufferZeroPad16(hex.value, end - 16);
if (real_width >= hex.width) {
sink.Append(absl::string_view(end - real_width, real_width));
} else {
// Pad first 16 chars because FastHexToBufferZeroPad16 pads only to 16 and
// max pad width can be up to 20.
std::memset(end - 32, hex.fill, 16);
// Patch up everything else up to the real_width.
std::memset(end - real_width - 16, hex.fill, 16);
sink.Append(absl::string_view(end - hex.width, hex.width));
}
}
private:
Hex(PadSpec spec, uint64_t v)
: value(v),
width(spec == absl::kNoPad
? 1
: spec >= absl::kSpacePad2 ? spec - absl::kSpacePad2 + 2
: spec - absl::kZeroPad2 + 2),
fill(spec >= absl::kSpacePad2 ? ' ' : '0') {}
};
// -----------------------------------------------------------------------------
// Dec
// -----------------------------------------------------------------------------
//
// `Dec` stores a set of decimal string conversion parameters for use
// within `AlphaNum` string conversions. Dec is slower than the default
// integer conversion, so use it only if you need padding.
struct Dec {
uint64_t value;
uint8_t width;
char fill;
bool neg;
template <typename Int>
explicit Dec(Int v, PadSpec spec = absl::kNoPad,
std::enable_if_t<sizeof(Int) <= 8, bool> = true)
: value(v >= 0 ? static_cast<uint64_t>(v)
: uint64_t{0} - static_cast<uint64_t>(v)),
width(spec == absl::kNoPad ? 1
: spec >= absl::kSpacePad2 ? spec - absl::kSpacePad2 + 2
: spec - absl::kZeroPad2 + 2),
fill(spec >= absl::kSpacePad2 ? ' ' : '0'),
neg(v < 0) {}
template <typename S>
friend void AbslStringify(S& sink, Dec dec) {
assert(dec.width <= numbers_internal::kFastToBufferSize);
char buffer[numbers_internal::kFastToBufferSize];
char* const end = &buffer[numbers_internal::kFastToBufferSize];
char* const minfill = end - dec.width;
char* writer = end;
uint64_t val = dec.value;
while (val > 9) {
*--writer = '0' + (val % 10);
val /= 10;
}
*--writer = '0' + static_cast<char>(val);
if (dec.neg) *--writer = '-';
ptrdiff_t fillers = writer - minfill;
if (fillers > 0) {
// Tricky: if the fill character is ' ', then it's <fill><+/-><digits>
// But...: if the fill character is '0', then it's <+/-><fill><digits>
bool add_sign_again = false;
if (dec.neg && dec.fill == '0') { // If filling with '0',
++writer; // ignore the sign we just added
add_sign_again = true; // and re-add the sign later.
}
writer -= fillers;
std::fill_n(writer, fillers, dec.fill);
if (add_sign_again) *--writer = '-';
}
sink.Append(absl::string_view(writer, static_cast<size_t>(end - writer)));
}
};
// -----------------------------------------------------------------------------
// AlphaNum
// -----------------------------------------------------------------------------
//
// The `AlphaNum` class acts as the main parameter type for `StrCat()` and
// `StrAppend()`, providing efficient conversion of numeric, boolean, decimal,
// and hexadecimal values (through the `Dec` and `Hex` types) into strings.
// `AlphaNum` should only be used as a function parameter. Do not instantiate
// `AlphaNum` directly as a stack variable.
class AlphaNum {
public:
// No bool ctor -- bools convert to an integral type.
// A bool ctor would also convert incoming pointers (bletch).
// Prevent brace initialization
template <typename T>
AlphaNum(std::initializer_list<T>) = delete; // NOLINT(runtime/explicit)
AlphaNum(int x) // NOLINT(runtime/explicit)
: piece_(digits_, static_cast<size_t>(
numbers_internal::FastIntToBuffer(x, digits_) -
&digits_[0])) {}
AlphaNum(unsigned int x) // NOLINT(runtime/explicit)
: piece_(digits_, static_cast<size_t>(
numbers_internal::FastIntToBuffer(x, digits_) -
&digits_[0])) {}
AlphaNum(long x) // NOLINT(*)
: piece_(digits_, static_cast<size_t>(
numbers_internal::FastIntToBuffer(x, digits_) -
&digits_[0])) {}
AlphaNum(unsigned long x) // NOLINT(*)
: piece_(digits_, static_cast<size_t>(
numbers_internal::FastIntToBuffer(x, digits_) -
&digits_[0])) {}
AlphaNum(long long x) // NOLINT(*)
: piece_(digits_, static_cast<size_t>(
numbers_internal::FastIntToBuffer(x, digits_) -
&digits_[0])) {}
AlphaNum(unsigned long long x) // NOLINT(*)
: piece_(digits_, static_cast<size_t>(
numbers_internal::FastIntToBuffer(x, digits_) -
&digits_[0])) {}
AlphaNum(float f) // NOLINT(runtime/explicit)
: piece_(digits_, numbers_internal::SixDigitsToBuffer(f, digits_)) {}
AlphaNum(double f) // NOLINT(runtime/explicit)
: piece_(digits_, numbers_internal::SixDigitsToBuffer(f, digits_)) {}
template <size_t size>
AlphaNum( // NOLINT(runtime/explicit)
const strings_internal::AlphaNumBuffer<size>& buf
ABSL_ATTRIBUTE_LIFETIME_BOUND)
: piece_(&buf.data[0], buf.size) {}
AlphaNum(const char* absl_nullable c_str // NOLINT(runtime/explicit)
ABSL_ATTRIBUTE_LIFETIME_BOUND)
: piece_(NullSafeStringView(c_str)) {}
AlphaNum(absl::string_view pc // NOLINT(runtime/explicit)
ABSL_ATTRIBUTE_LIFETIME_BOUND)
: piece_(pc) {}
#if !defined(ABSL_USES_STD_STRING_VIEW)
AlphaNum(std::string_view pc // NOLINT(runtime/explicit)
ABSL_ATTRIBUTE_LIFETIME_BOUND)
: piece_(pc.data(), pc.size()) {}
#endif // !ABSL_USES_STD_STRING_VIEW
template <typename T, typename = typename std::enable_if<
HasAbslStringify<T>::value>::type>
AlphaNum( // NOLINT(runtime/explicit)
const T& v ABSL_ATTRIBUTE_LIFETIME_BOUND,
strings_internal::StringifySink&& sink ABSL_ATTRIBUTE_LIFETIME_BOUND = {})
: piece_(strings_internal::ExtractStringification(sink, v)) {}
template <typename Allocator>
AlphaNum( // NOLINT(runtime/explicit)
const std::basic_string<char, std::char_traits<char>, Allocator>& str
ABSL_ATTRIBUTE_LIFETIME_BOUND)
: piece_(str) {}
// Use string literals ":" instead of character literals ':'.
AlphaNum(char c) = delete; // NOLINT(runtime/explicit)
AlphaNum(const AlphaNum&) = delete;
AlphaNum& operator=(const AlphaNum&) = delete;
absl::string_view::size_type size() const { return piece_.size(); }
const char* absl_nullable data() const { return piece_.data(); }
absl::string_view Piece() const { return piece_; }
// Match unscoped enums. Use integral promotion so that a `char`-backed
// enum becomes a wider integral type AlphaNum will accept.
template <typename T,
typename = typename std::enable_if<
std::is_enum<T>{} && std::is_convertible<T, int>{} &&
!HasAbslStringify<T>::value>::type>
AlphaNum(T e) // NOLINT(runtime/explicit)
: AlphaNum(+e) {}
// This overload matches scoped enums. We must explicitly cast to the
// underlying type, but use integral promotion for the same reason as above.
template <typename T,
typename std::enable_if<std::is_enum<T>{} &&
!std::is_convertible<T, int>{} &&
!HasAbslStringify<T>::value,
char*>::type = nullptr>
AlphaNum(T e) // NOLINT(runtime/explicit)
: AlphaNum(+static_cast<typename std::underlying_type<T>::type>(e)) {}
// vector<bool>::reference and const_reference require special help to
// convert to `AlphaNum` because it requires two user defined conversions.
template <
typename T,
typename std::enable_if<
std::is_class<T>::value &&
(std::is_same<T, std::vector<bool>::reference>::value ||
std::is_same<T, std::vector<bool>::const_reference>::value)>::type* =
nullptr>
AlphaNum(T e) : AlphaNum(static_cast<bool>(e)) {} // NOLINT(runtime/explicit)
private:
absl::string_view piece_;
char digits_[numbers_internal::kFastToBufferSize];
};
// -----------------------------------------------------------------------------
// StrCat()
// -----------------------------------------------------------------------------
//
// Merges given strings or numbers, using no delimiter(s), returning the merged
// result as a string.
//
// `StrCat()` is designed to be the fastest possible way to construct a string
// out of a mix of raw C strings, string_views, strings, bool values,
// and numeric values.
//
// Don't use `StrCat()` for user-visible strings. The localization process
// works poorly on strings built up out of fragments.
//
// For clarity and performance, don't use `StrCat()` when appending to a
// string. Use `StrAppend()` instead. In particular, avoid using any of these
// (anti-)patterns:
//
// str.append(StrCat(...))
// str += StrCat(...)
// str = StrCat(str, ...)
//
// The last case is the worst, with a potential to change a loop
// from a linear time operation with O(1) dynamic allocations into a
// quadratic time operation with O(n) dynamic allocations.
//
// See `StrAppend()` below for more information.
namespace strings_internal {
// Do not call directly - this is not part of the public API.
std::string CatPieces(std::initializer_list<absl::string_view> pieces);
void AppendPieces(std::string* absl_nonnull dest,
std::initializer_list<absl::string_view> pieces);
template <typename Integer>
std::string IntegerToString(Integer i) {
// Any integer (signed/unsigned) up to 64 bits can be formatted into a buffer
// with 22 bytes (including NULL at the end).
constexpr size_t kMaxDigits10 = 22;
std::string result;
strings_internal::STLStringResizeUninitialized(&result, kMaxDigits10);
char* start = &result[0];
// note: this can be optimized to not write last zero.
char* end = numbers_internal::FastIntToBuffer(i, start);
auto size = static_cast<size_t>(end - start);
assert((size < result.size()) &&
"StrCat(Integer) does not fit into kMaxDigits10");
result.erase(size);
return result;
}
template <typename Float>
std::string FloatToString(Float f) {
std::string result;
strings_internal::STLStringResizeUninitialized(
&result, numbers_internal::kSixDigitsToBufferSize);
char* start = &result[0];
result.erase(numbers_internal::SixDigitsToBuffer(f, start));
return result;
}
// `SingleArgStrCat` overloads take built-in `int`, `long` and `long long` types
// (signed / unsigned) to avoid ambiguity on the call side. If we used int32_t
// and int64_t, then at least one of the three (`int` / `long` / `long long`)
// would have been ambiguous when passed to `SingleArgStrCat`.
inline std::string SingleArgStrCat(int x) { return IntegerToString(x); }
inline std::string SingleArgStrCat(unsigned int x) {
return IntegerToString(x);
}
// NOLINTNEXTLINE
inline std::string SingleArgStrCat(long x) { return IntegerToString(x); }
// NOLINTNEXTLINE
inline std::string SingleArgStrCat(unsigned long x) {
return IntegerToString(x);
}
// NOLINTNEXTLINE
inline std::string SingleArgStrCat(long long x) { return IntegerToString(x); }
// NOLINTNEXTLINE
inline std::string SingleArgStrCat(unsigned long long x) {
return IntegerToString(x);
}
inline std::string SingleArgStrCat(float x) { return FloatToString(x); }
inline std::string SingleArgStrCat(double x) { return FloatToString(x); }
// As of September 2023, the SingleArgStrCat() optimization is only enabled for
// libc++. The reasons for this are:
// 1) The SSO size for libc++ is 23, while libstdc++ and MSSTL have an SSO size
// of 15. Since IntegerToString unconditionally resizes the string to 22 bytes,
// this causes both libstdc++ and MSSTL to allocate.
// 2) strings_internal::STLStringResizeUninitialized() only has an
// implementation that avoids initialization when using libc++. This isn't as
// relevant as (1), and the cost should be benchmarked if (1) ever changes on
// libstc++ or MSSTL.
#ifdef _LIBCPP_VERSION
#define ABSL_INTERNAL_STRCAT_ENABLE_FAST_CASE true
#else
#define ABSL_INTERNAL_STRCAT_ENABLE_FAST_CASE false
#endif
template <typename T, typename = std::enable_if_t<
ABSL_INTERNAL_STRCAT_ENABLE_FAST_CASE &&
std::is_arithmetic<T>{} && !std::is_same<T, char>{}>>
using EnableIfFastCase = T;
#undef ABSL_INTERNAL_STRCAT_ENABLE_FAST_CASE
} // namespace strings_internal
[[nodiscard]] inline std::string StrCat() { return std::string(); }
template <typename T>
[[nodiscard]] inline std::string StrCat(
strings_internal::EnableIfFastCase<T> a) {
return strings_internal::SingleArgStrCat(a);
}
[[nodiscard]] inline std::string StrCat(const AlphaNum& a) {
return std::string(a.data(), a.size());
}
[[nodiscard]] std::string StrCat(const AlphaNum& a, const AlphaNum& b);
[[nodiscard]] std::string StrCat(const AlphaNum& a, const AlphaNum& b,
const AlphaNum& c);
[[nodiscard]] std::string StrCat(const AlphaNum& a, const AlphaNum& b,
const AlphaNum& c, const AlphaNum& d);
// Support 5 or more arguments
template <typename... AV>
[[nodiscard]] inline std::string StrCat(const AlphaNum& a, const AlphaNum& b,
const AlphaNum& c, const AlphaNum& d,
const AlphaNum& e, const AV&... args) {
return strings_internal::CatPieces(
{a.Piece(), b.Piece(), c.Piece(), d.Piece(), e.Piece(),
static_cast<const AlphaNum&>(args).Piece()...});
}
// -----------------------------------------------------------------------------
// StrAppend()
// -----------------------------------------------------------------------------
//
// Appends a string or set of strings to an existing string, in a similar
// fashion to `StrCat()`.
//
// WARNING: `StrAppend(&str, a, b, c, ...)` requires that none of the
// a, b, c, parameters be a reference into str. For speed, `StrAppend()` does
// not try to check each of its input arguments to be sure that they are not
// a subset of the string being appended to. That is, while this will work:
//
// std::string s = "foo";
// s += s;
//
// This output is undefined:
//
// std::string s = "foo";
// StrAppend(&s, s);
//
// This output is undefined as well, since `absl::string_view` does not own its
// data:
//
// std::string s = "foobar";
// absl::string_view p = s;
// StrAppend(&s, p);
inline void StrAppend(std::string* absl_nonnull) {}
void StrAppend(std::string* absl_nonnull dest, const AlphaNum& a);
void StrAppend(std::string* absl_nonnull dest, const AlphaNum& a,
const AlphaNum& b);
void StrAppend(std::string* absl_nonnull dest, const AlphaNum& a,
const AlphaNum& b, const AlphaNum& c);
void StrAppend(std::string* absl_nonnull dest, const AlphaNum& a,
const AlphaNum& b, const AlphaNum& c, const AlphaNum& d);
// Support 5 or more arguments
template <typename... AV>
inline void StrAppend(std::string* absl_nonnull dest, const AlphaNum& a,
const AlphaNum& b, const AlphaNum& c, const AlphaNum& d,
const AlphaNum& e, const AV&... args) {
strings_internal::AppendPieces(
dest, {a.Piece(), b.Piece(), c.Piece(), d.Piece(), e.Piece(),
static_cast<const AlphaNum&>(args).Piece()...});
}
// Helper function for the future StrCat default floating-point format, %.6g
// This is fast.
inline strings_internal::AlphaNumBuffer<
numbers_internal::kSixDigitsToBufferSize>
SixDigits(double d) {
strings_internal::AlphaNumBuffer<numbers_internal::kSixDigitsToBufferSize>
result;
result.size = numbers_internal::SixDigitsToBuffer(d, &result.data[0]);
return result;
}
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_STR_CAT_H_
*Ò
tsoong/.intermediates/external/abseil-cpp/absl_base_hdrs/gen/my_include_dir/absl/base/internal/tsan_mutex_interface.hÙ// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// This file is intended solely for spinlock.h.
// It provides ThreadSanitizer annotations for custom mutexes.
// See <sanitizer/tsan_interface.h> for meaning of these annotations.
#ifndef ABSL_BASE_INTERNAL_TSAN_MUTEX_INTERFACE_H_
#define ABSL_BASE_INTERNAL_TSAN_MUTEX_INTERFACE_H_
#include "absl/base/config.h"
// ABSL_INTERNAL_HAVE_TSAN_INTERFACE
// Macro intended only for internal use.
//
// Checks whether LLVM Thread Sanitizer interfaces are available.
// First made available in LLVM 5.0 (Sep 2017).
#ifdef ABSL_INTERNAL_HAVE_TSAN_INTERFACE
#error "ABSL_INTERNAL_HAVE_TSAN_INTERFACE cannot be directly set."
#endif
#if defined(ABSL_HAVE_THREAD_SANITIZER) && defined(__has_include)
#if __has_include(<sanitizer/tsan_interface.h>)
#define ABSL_INTERNAL_HAVE_TSAN_INTERFACE 1
#endif
#endif
#ifdef ABSL_INTERNAL_HAVE_TSAN_INTERFACE
#include <sanitizer/tsan_interface.h>
#define ABSL_TSAN_MUTEX_CREATE __tsan_mutex_create
#define ABSL_TSAN_MUTEX_DESTROY __tsan_mutex_destroy
#define ABSL_TSAN_MUTEX_PRE_LOCK __tsan_mutex_pre_lock
#define ABSL_TSAN_MUTEX_POST_LOCK __tsan_mutex_post_lock
#define ABSL_TSAN_MUTEX_PRE_UNLOCK __tsan_mutex_pre_unlock
#define ABSL_TSAN_MUTEX_POST_UNLOCK __tsan_mutex_post_unlock
#define ABSL_TSAN_MUTEX_PRE_SIGNAL __tsan_mutex_pre_signal
#define ABSL_TSAN_MUTEX_POST_SIGNAL __tsan_mutex_post_signal
#define ABSL_TSAN_MUTEX_PRE_DIVERT __tsan_mutex_pre_divert
#define ABSL_TSAN_MUTEX_POST_DIVERT __tsan_mutex_post_divert
#else
#define ABSL_TSAN_MUTEX_CREATE(...)
#define ABSL_TSAN_MUTEX_DESTROY(...)
#define ABSL_TSAN_MUTEX_PRE_LOCK(...)
#define ABSL_TSAN_MUTEX_POST_LOCK(...)
#define ABSL_TSAN_MUTEX_PRE_UNLOCK(...)
#define ABSL_TSAN_MUTEX_POST_UNLOCK(...)
#define ABSL_TSAN_MUTEX_PRE_SIGNAL(...)
#define ABSL_TSAN_MUTEX_POST_SIGNAL(...)
#define ABSL_TSAN_MUTEX_PRE_DIVERT(...)
#define ABSL_TSAN_MUTEX_POST_DIVERT(...)
#endif
#endif // ABSL_BASE_INTERNAL_TSAN_MUTEX_INTERFACE_H_
*‡g
{soong/.intermediates/external/abseil-cpp/absl_strings_cordz_info_hdrs/gen/my_include_dir/absl/strings/internal/cordz_info.h‡f// Copyright 2019 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_STRINGS_INTERNAL_CORDZ_INFO_H_
#define ABSL_STRINGS_INTERNAL_CORDZ_INFO_H_
#include <atomic>
#include <cstdint>
#include <functional>
#include "absl/base/config.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/base/internal/spinlock.h"
#include "absl/base/thread_annotations.h"
#include "absl/strings/internal/cord_internal.h"
#include "absl/strings/internal/cordz_functions.h"
#include "absl/strings/internal/cordz_handle.h"
#include "absl/strings/internal/cordz_statistics.h"
#include "absl/strings/internal/cordz_update_tracker.h"
#include "absl/synchronization/mutex.h"
#include "absl/types/span.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace cord_internal {
// CordzInfo tracks a profiled Cord. Each of these objects can be in two places.
// If a Cord is alive, the CordzInfo will be in the global_cordz_infos map, and
// can also be retrieved via the linked list starting with
// global_cordz_infos_head and continued via the cordz_info_next() method. When
// a Cord has reached the end of its lifespan, the CordzInfo object will be
// migrated out of the global_cordz_infos list and the global_cordz_infos_map,
// and will either be deleted or appended to the global_delete_queue. If it is
// placed on the global_delete_queue, the CordzInfo object will be cleaned in
// the destructor of a CordzSampleToken object.
class ABSL_LOCKABLE CordzInfo : public CordzHandle {
public:
using MethodIdentifier = CordzUpdateTracker::MethodIdentifier;
// TrackCord creates a CordzInfo instance which tracks important metrics of
// a sampled cord, and stores the created CordzInfo instance into `cord'. All
// CordzInfo instances are placed in a global list which is used to discover
// and snapshot all actively tracked cords. Callers are responsible for
// calling UntrackCord() before the tracked Cord instance is deleted, or to
// stop tracking the sampled Cord. Callers are also responsible for guarding
// changes to the 'tree' value of a Cord (InlineData.tree) through the Lock()
// and Unlock() calls. Any change resulting in a new tree value for the cord
// requires a call to SetCordRep() before the old tree has been unreffed
// and/or deleted. `method` identifies the Cord public API method initiating
// the cord to be sampled.
// Requires `cord` to hold a tree, and `cord.cordz_info()` to be null.
static void TrackCord(InlineData& cord, MethodIdentifier method,
int64_t sampling_stride);
// Identical to TrackCord(), except that this function fills the
// `parent_stack` and `parent_method` properties of the returned CordzInfo
// instance from the provided `src` instance if `src` is sampled.
// This function should be used for sampling 'copy constructed' and 'copy
// assigned' cords. This function allows 'cord` to be already sampled, in
// which case the CordzInfo will be newly created from `src`.
static void TrackCord(InlineData& cord, const InlineData& src,
MethodIdentifier method);
// Maybe sample the cord identified by 'cord' for method 'method'.
// Uses `cordz_should_profile` to randomly pick cords to be sampled, and if
// so, invokes `TrackCord` to start sampling `cord`.
static void MaybeTrackCord(InlineData& cord, MethodIdentifier method);
// Maybe sample the cord identified by 'cord' for method 'method'.
// `src` identifies a 'parent' cord which is assigned to `cord`, typically the
// input cord for a copy constructor, or an assign method such as `operator=`
// `cord` will be sampled if (and only if) `src` is sampled.
// If `cord` is currently being sampled and `src` is not being sampled, then
// this function will stop sampling the cord and reset the cord's cordz_info.
//
// Previously this function defined that `cord` will be sampled if either
// `src` is sampled, or if `cord` is randomly picked for sampling. However,
// this can cause issues, as there may be paths where some cord is assigned an
// indirect copy of it's own value. As such a 'string of copies' would then
// remain sampled (`src.is_profiled`), then assigning such a cord back to
// 'itself' creates a cycle where the cord will converge to 'always sampled`.
//
// For example:
//
// Cord x;
// for (...) {
// // Copy ctor --> y.is_profiled := x.is_profiled | random(...)
// Cord y = x;
// ...
// // Assign x = y --> x.is_profiled = y.is_profiled | random(...)
// // ==> x.is_profiled |= random(...)
// // ==> x converges to 'always profiled'
// x = y;
// }
static void MaybeTrackCord(InlineData& cord, const InlineData& src,
MethodIdentifier method);
// Stops tracking changes for a sampled cord, and deletes the provided info.
// This function must be called before the sampled cord instance is deleted,
// and before the root cordrep of the sampled cord is unreffed.
// This function may extend the lifetime of the cordrep in cases where the
// CordInfo instance is being held by a concurrent collection thread.
void Untrack();
// Invokes UntrackCord() on `info` if `info` is not null.
static void MaybeUntrackCord(CordzInfo* info);
CordzInfo() = delete;
CordzInfo(const CordzInfo&) = delete;
CordzInfo& operator=(const CordzInfo&) = delete;
// Retrieves the oldest existing CordzInfo.
static CordzInfo* Head(const CordzSnapshot& snapshot)
ABSL_NO_THREAD_SAFETY_ANALYSIS;
// Retrieves the next oldest existing CordzInfo older than 'this' instance.
CordzInfo* Next(const CordzSnapshot& snapshot) const
ABSL_NO_THREAD_SAFETY_ANALYSIS;
// Locks this instance for the update identified by `method`.
// Increases the count for `method` in `update_tracker`.
void Lock(MethodIdentifier method) ABSL_EXCLUSIVE_LOCK_FUNCTION(mutex_);
// Unlocks this instance. If the contained `rep` has been set to null
// indicating the Cord has been cleared or is otherwise no longer sampled,
// then this method will delete this CordzInfo instance.
void Unlock() ABSL_UNLOCK_FUNCTION(mutex_);
// Asserts that this CordzInfo instance is locked.
void AssertHeld() ABSL_ASSERT_EXCLUSIVE_LOCK(mutex_);
// Updates the `rep` property of this instance. This methods is invoked by
// Cord logic each time the root node of a sampled Cord changes, and before
// the old root reference count is deleted. This guarantees that collection
// code can always safely take a reference on the tracked cord.
// Requires a lock to be held through the `Lock()` method.
// TODO(b/117940323): annotate with ABSL_EXCLUSIVE_LOCKS_REQUIRED once all
// Cord code is in a state where this can be proven true by the compiler.
void SetCordRep(CordRep* rep);
// Returns the current `rep` property of this instance with a reference
// added, or null if this instance represents a cord that has since been
// deleted or untracked.
CordRep* RefCordRep() const ABSL_LOCKS_EXCLUDED(mutex_);
// Returns the current value of `rep_` for testing purposes only.
CordRep* GetCordRepForTesting() const ABSL_NO_THREAD_SAFETY_ANALYSIS {
return rep_;
}
// Sets the current value of `rep_` for testing purposes only.
void SetCordRepForTesting(CordRep* rep) ABSL_NO_THREAD_SAFETY_ANALYSIS {
rep_ = rep;
}
// Returns the stack trace for where the cord was first sampled. Cords are
// potentially sampled when they promote from an inlined cord to a tree or
// ring representation, which is not necessarily the location where the cord
// was first created. Some cords are created as inlined cords, and only as
// data is added do they become a non-inlined cord. However, typically the
// location represents reasonably well where the cord is 'created'.
absl::Span<void* const> GetStack() const;
// Returns the stack trace for a sampled cord's 'parent stack trace'. This
// value may be set if the cord is sampled (promoted) after being created
// from, or being assigned the value of an existing (sampled) cord.
absl::Span<void* const> GetParentStack() const;
// Retrieves the CordzStatistics associated with this Cord. The statistics
// are only updated when a Cord goes through a mutation, such as an Append
// or RemovePrefix.
CordzStatistics GetCordzStatistics() const;
int64_t sampling_stride() const { return sampling_stride_; }
private:
using SpinLock = absl::base_internal::SpinLock;
using SpinLockHolder = ::absl::base_internal::SpinLockHolder;
// Global cordz info list. CordzInfo stores a pointer to the global list
// instance to harden against ODR violations.
struct List {
constexpr explicit List(absl::ConstInitType)
: mutex(absl::kConstInit,
absl::base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL) {}
SpinLock mutex;
std::atomic<CordzInfo*> head ABSL_GUARDED_BY(mutex){nullptr};
};
static constexpr size_t kMaxStackDepth = 64;
explicit CordzInfo(CordRep* rep, const CordzInfo* src,
MethodIdentifier method, int64_t weight);
~CordzInfo() override;
// Sets `rep_` without holding a lock.
void UnsafeSetCordRep(CordRep* rep) ABSL_NO_THREAD_SAFETY_ANALYSIS;
void Track();
// Returns the parent method from `src`, which is either `parent_method_` or
// `method_` depending on `parent_method_` being kUnknown.
// Returns kUnknown if `src` is null.
static MethodIdentifier GetParentMethod(const CordzInfo* src);
// Fills the provided stack from `src`, copying either `parent_stack_` or
// `stack_` depending on `parent_stack_` being empty, returning the size of
// the parent stack.
// Returns 0 if `src` is null.
static size_t FillParentStack(const CordzInfo* src, void** stack);
void ODRCheck() const {
#ifndef NDEBUG
ABSL_RAW_CHECK(list_ == &global_list_, "ODR violation in Cord");
#endif
}
// Non-inlined implementation of `MaybeTrackCord`, which is executed if
// either `src` is sampled or `cord` is sampled, and either untracks or
// tracks `cord` as documented per `MaybeTrackCord`.
static void MaybeTrackCordImpl(InlineData& cord, const InlineData& src,
MethodIdentifier method);
ABSL_CONST_INIT static List global_list_;
List* const list_ = &global_list_;
// ci_prev_ and ci_next_ require the global list mutex to be held.
// Unfortunately we can't use thread annotations such that the thread safety
// analysis understands that list_ and global_list_ are one and the same.
std::atomic<CordzInfo*> ci_prev_{nullptr};
std::atomic<CordzInfo*> ci_next_{nullptr};
mutable absl::Mutex mutex_;
CordRep* rep_ ABSL_GUARDED_BY(mutex_);
void* stack_[kMaxStackDepth];
void* parent_stack_[kMaxStackDepth];
const size_t stack_depth_;
const size_t parent_stack_depth_;
const MethodIdentifier method_;
const MethodIdentifier parent_method_;
CordzUpdateTracker update_tracker_;
const absl::Time create_time_;
const int64_t sampling_stride_;
};
inline ABSL_ATTRIBUTE_ALWAYS_INLINE void CordzInfo::MaybeTrackCord(
InlineData& cord, MethodIdentifier method) {
auto stride = cordz_should_profile();
if (ABSL_PREDICT_FALSE(stride > 0)) {
TrackCord(cord, method, stride);
}
}
inline ABSL_ATTRIBUTE_ALWAYS_INLINE void CordzInfo::MaybeTrackCord(
InlineData& cord, const InlineData& src, MethodIdentifier method) {
if (ABSL_PREDICT_FALSE(InlineData::is_either_profiled(cord, src))) {
MaybeTrackCordImpl(cord, src, method);
}
}
inline ABSL_ATTRIBUTE_ALWAYS_INLINE void CordzInfo::MaybeUntrackCord(
CordzInfo* info) {
if (ABSL_PREDICT_FALSE(info)) {
info->Untrack();
}
}
inline void CordzInfo::AssertHeld() ABSL_ASSERT_EXCLUSIVE_LOCK(mutex_) {
#ifndef NDEBUG
mutex_.AssertHeld();
#endif
}
inline void CordzInfo::SetCordRep(CordRep* rep) {
AssertHeld();
rep_ = rep;
}
inline void CordzInfo::UnsafeSetCordRep(CordRep* rep) { rep_ = rep; }
// Android local modification: locally silence an incorrect warning that
// causes build failures in code that uses -Werror.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wthread-safety-negative"
inline CordRep* CordzInfo::RefCordRep() const ABSL_LOCKS_EXCLUDED(mutex_) {
MutexLock lock(&mutex_);
return rep_ ? CordRep::Ref(rep_) : nullptr;
}
#pragma clang diagnostic pop
} // namespace cord_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_CORDZ_INFO_H_
*®k
•soong/.intermediates/external/abseil-cpp/absl_strings_str_format_internal_hdrs/gen/my_include_dir/absl/strings/internal/str_format/constexpr_parser.h“j// Copyright 2022 The Abseil Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_CONSTEXPR_PARSER_H_
#define ABSL_STRINGS_INTERNAL_STR_FORMAT_CONSTEXPR_PARSER_H_
#include <cassert>
#include <cstdint>
#include <cstdio>
#include <limits>
#include "absl/base/config.h"
#include "absl/base/const_init.h"
#include "absl/base/optimization.h"
#include "absl/strings/internal/str_format/extension.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
// The analyzed properties of a single specified conversion.
struct UnboundConversion {
// This is a user defined default constructor on purpose to skip the
// initialization of parts of the object that are not necessary.
UnboundConversion() {} // NOLINT
// This constructor is provided for the static checker. We don't want to do
// the unnecessary initialization in the normal case.
explicit constexpr UnboundConversion(absl::ConstInitType)
: arg_position{}, width{}, precision{} {}
class InputValue {
public:
constexpr void set_value(int value) {
assert(value >= 0);
value_ = value;
}
constexpr int value() const { return value_; }
// Marks the value as "from arg". aka the '*' format.
// Requires `value >= 1`.
// When set, is_from_arg() return true and get_from_arg() returns the
// original value.
// `value()`'s return value is unspecified in this state.
constexpr void set_from_arg(int value) {
assert(value > 0);
value_ = -value - 1;
}
constexpr bool is_from_arg() const { return value_ < -1; }
constexpr int get_from_arg() const {
assert(is_from_arg());
return -value_ - 1;
}
private:
int value_ = -1;
};
// No need to initialize. It will always be set in the parser.
int arg_position;
InputValue width;
InputValue precision;
Flags flags = Flags::kBasic;
LengthMod length_mod = LengthMod::none;
FormatConversionChar conv = FormatConversionCharInternal::kNone;
};
// Helper tag class for the table below.
// It allows fast `char -> ConversionChar/LengthMod/Flags` checking and
// conversions.
class ConvTag {
public:
constexpr ConvTag(FormatConversionChar conversion_char) // NOLINT
: tag_(static_cast<uint8_t>(conversion_char)) {}
constexpr ConvTag(LengthMod length_mod) // NOLINT
: tag_(0x80 | static_cast<uint8_t>(length_mod)) {}
constexpr ConvTag(Flags flags) // NOLINT
: tag_(0xc0 | static_cast<uint8_t>(flags)) {}
constexpr ConvTag() : tag_(0xFF) {}
constexpr bool is_conv() const { return (tag_ & 0x80) == 0; }
constexpr bool is_length() const { return (tag_ & 0xC0) == 0x80; }
constexpr bool is_flags() const { return (tag_ & 0xE0) == 0xC0; }
constexpr FormatConversionChar as_conv() const {
assert(is_conv());
assert(!is_length());
assert(!is_flags());
return static_cast<FormatConversionChar>(tag_);
}
constexpr LengthMod as_length() const {
assert(!is_conv());
assert(is_length());
assert(!is_flags());
return static_cast<LengthMod>(tag_ & 0x3F);
}
constexpr Flags as_flags() const {
assert(!is_conv());
assert(!is_length());
assert(is_flags());
return static_cast<Flags>(tag_ & 0x1F);
}
private:
uint8_t tag_;
};
struct ConvTagHolder {
using CC = FormatConversionCharInternal;
using LM = LengthMod;
// Abbreviations to fit in the table below.
static constexpr auto kFSign = Flags::kSignCol;
static constexpr auto kFAlt = Flags::kAlt;
static constexpr auto kFPos = Flags::kShowPos;
static constexpr auto kFLeft = Flags::kLeft;
static constexpr auto kFZero = Flags::kZero;
static constexpr ConvTag value[256] = {
{}, {}, {}, {}, {}, {}, {}, {}, // 00-07
{}, {}, {}, {}, {}, {}, {}, {}, // 08-0f
{}, {}, {}, {}, {}, {}, {}, {}, // 10-17
{}, {}, {}, {}, {}, {}, {}, {}, // 18-1f
kFSign, {}, {}, kFAlt, {}, {}, {}, {}, // !"#$%&'
{}, {}, {}, kFPos, {}, kFLeft, {}, {}, // ()*+,-./
kFZero, {}, {}, {}, {}, {}, {}, {}, // 01234567
{}, {}, {}, {}, {}, {}, {}, {}, // 89:;<=>?
{}, CC::A, {}, {}, {}, CC::E, CC::F, CC::G, // @ABCDEFG
{}, {}, {}, {}, LM::L, {}, {}, {}, // HIJKLMNO
{}, {}, {}, {}, {}, {}, {}, {}, // PQRSTUVW
CC::X, {}, {}, {}, {}, {}, {}, {}, // XYZ[\]^_
{}, CC::a, {}, CC::c, CC::d, CC::e, CC::f, CC::g, // `abcdefg
LM::h, CC::i, LM::j, {}, LM::l, {}, CC::n, CC::o, // hijklmno
CC::p, LM::q, {}, CC::s, LM::t, CC::u, CC::v, {}, // pqrstuvw
CC::x, {}, LM::z, {}, {}, {}, {}, {}, // xyz{|}!
{}, {}, {}, {}, {}, {}, {}, {}, // 80-87
{}, {}, {}, {}, {}, {}, {}, {}, // 88-8f
{}, {}, {}, {}, {}, {}, {}, {}, // 90-97
{}, {}, {}, {}, {}, {}, {}, {}, // 98-9f
{}, {}, {}, {}, {}, {}, {}, {}, // a0-a7
{}, {}, {}, {}, {}, {}, {}, {}, // a8-af
{}, {}, {}, {}, {}, {}, {}, {}, // b0-b7
{}, {}, {}, {}, {}, {}, {}, {}, // b8-bf
{}, {}, {}, {}, {}, {}, {}, {}, // c0-c7
{}, {}, {}, {}, {}, {}, {}, {}, // c8-cf
{}, {}, {}, {}, {}, {}, {}, {}, // d0-d7
{}, {}, {}, {}, {}, {}, {}, {}, // d8-df
{}, {}, {}, {}, {}, {}, {}, {}, // e0-e7
{}, {}, {}, {}, {}, {}, {}, {}, // e8-ef
{}, {}, {}, {}, {}, {}, {}, {}, // f0-f7
{}, {}, {}, {}, {}, {}, {}, {}, // f8-ff
};
};
// Keep a single table for all the conversion chars and length modifiers.
constexpr ConvTag GetTagForChar(char c) {
return ConvTagHolder::value[static_cast<unsigned char>(c)];
}
constexpr bool CheckFastPathSetting(const UnboundConversion& conv) {
bool width_precision_needed =
conv.width.value() >= 0 || conv.precision.value() >= 0;
if (width_precision_needed && conv.flags == Flags::kBasic) {
#if defined(__clang__)
// Some compilers complain about this in constexpr even when not executed,
// so only enable the error dump in clang.
fprintf(stderr,
"basic=%d left=%d show_pos=%d sign_col=%d alt=%d zero=%d "
"width=%d precision=%d\n",
conv.flags == Flags::kBasic ? 1 : 0,
FlagsContains(conv.flags, Flags::kLeft) ? 1 : 0,
FlagsContains(conv.flags, Flags::kShowPos) ? 1 : 0,
FlagsContains(conv.flags, Flags::kSignCol) ? 1 : 0,
FlagsContains(conv.flags, Flags::kAlt) ? 1 : 0,
FlagsContains(conv.flags, Flags::kZero) ? 1 : 0, conv.width.value(),
conv.precision.value());
#endif // defined(__clang__)
return false;
}
return true;
}
constexpr int ParseDigits(char& c, const char*& pos, const char* const end) {
int digits = c - '0';
// We do not want to overflow `digits` so we consume at most digits10
// digits. If there are more digits the parsing will fail later on when the
// digit doesn't match the expected characters.
int num_digits = std::numeric_limits<int>::digits10;
for (;;) {
if (ABSL_PREDICT_FALSE(pos == end)) break;
c = *pos++;
if ('0' > c || c > '9') break;
--num_digits;
if (ABSL_PREDICT_FALSE(!num_digits)) break;
digits = 10 * digits + c - '0';
}
return digits;
}
template <bool is_positional>
constexpr const char* ConsumeConversion(const char* pos, const char* const end,
UnboundConversion* conv,
int* next_arg) {
const char* const original_pos = pos;
char c = 0;
// Read the next char into `c` and update `pos`. Returns false if there are
// no more chars to read.
#define ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR() \
do { \
if (ABSL_PREDICT_FALSE(pos == end)) return nullptr; \
c = *pos++; \
} while (0)
if (is_positional) {
ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
if (ABSL_PREDICT_FALSE(c < '1' || c > '9')) return nullptr;
conv->arg_position = ParseDigits(c, pos, end);
assert(conv->arg_position > 0);
if (ABSL_PREDICT_FALSE(c != '$')) return nullptr;
}
ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
// We should start with the basic flag on.
assert(conv->flags == Flags::kBasic);
// Any non alpha character makes this conversion not basic.
// This includes flags (-+ #0), width (1-9, *) or precision (.).
// All conversion characters and length modifiers are alpha characters.
if (c < 'A') {
while (c <= '0') {
auto tag = GetTagForChar(c);
if (tag.is_flags()) {
conv->flags = conv->flags | tag.as_flags();
ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
} else {
break;
}
}
if (c <= '9') {
if (c >= '0') {
int maybe_width = ParseDigits(c, pos, end);
if (!is_positional && c == '$') {
if (ABSL_PREDICT_FALSE(*next_arg != 0)) return nullptr;
// Positional conversion.
*next_arg = -1;
return ConsumeConversion<true>(original_pos, end, conv, next_arg);
}
conv->flags = conv->flags | Flags::kNonBasic;
conv->width.set_value(maybe_width);
} else if (c == '*') {
conv->flags = conv->flags | Flags::kNonBasic;
ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
if (is_positional) {
if (ABSL_PREDICT_FALSE(c < '1' || c > '9')) return nullptr;
conv->width.set_from_arg(ParseDigits(c, pos, end));
if (ABSL_PREDICT_FALSE(c != '$')) return nullptr;
ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
} else {
conv->width.set_from_arg(++*next_arg);
}
}
}
if (c == '.') {
conv->flags = conv->flags | Flags::kNonBasic;
ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
if ('0' <= c && c <= '9') {
conv->precision.set_value(ParseDigits(c, pos, end));
} else if (c == '*') {
ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
if (is_positional) {
if (ABSL_PREDICT_FALSE(c < '1' || c > '9')) return nullptr;
conv->precision.set_from_arg(ParseDigits(c, pos, end));
if (c != '$') return nullptr;
ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
} else {
conv->precision.set_from_arg(++*next_arg);
}
} else {
conv->precision.set_value(0);
}
}
}
auto tag = GetTagForChar(c);
if (ABSL_PREDICT_FALSE(c == 'v' && conv->flags != Flags::kBasic)) {
return nullptr;
}
if (ABSL_PREDICT_FALSE(!tag.is_conv())) {
if (ABSL_PREDICT_FALSE(!tag.is_length())) return nullptr;
// It is a length modifier.
LengthMod length_mod = tag.as_length();
ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
if (c == 'h' && length_mod == LengthMod::h) {
conv->length_mod = LengthMod::hh;
ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
} else if (c == 'l' && length_mod == LengthMod::l) {
conv->length_mod = LengthMod::ll;
ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
} else {
conv->length_mod = length_mod;
}
tag = GetTagForChar(c);
if (ABSL_PREDICT_FALSE(c == 'v')) return nullptr;
if (ABSL_PREDICT_FALSE(!tag.is_conv())) return nullptr;
// `wchar_t` args are marked non-basic so `Bind()` will copy the length mod.
if (conv->length_mod == LengthMod::l && c == 'c') {
conv->flags = conv->flags | Flags::kNonBasic;
}
}
#undef ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR
assert(CheckFastPathSetting(*conv));
(void)(&CheckFastPathSetting);
conv->conv = tag.as_conv();
if (!is_positional) conv->arg_position = ++*next_arg;
return pos;
}
// Consume conversion spec prefix (not including '%') of [p, end) if valid.
// Examples of valid specs would be e.g.: "s", "d", "-12.6f".
// If valid, it returns the first character following the conversion spec,
// and the spec part is broken down and returned in 'conv'.
// If invalid, returns nullptr.
constexpr const char* ConsumeUnboundConversion(const char* p, const char* end,
UnboundConversion* conv,
int* next_arg) {
if (*next_arg < 0) return ConsumeConversion<true>(p, end, conv, next_arg);
return ConsumeConversion<false>(p, end, conv, next_arg);
}
} // namespace str_format_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_CONSTEXPR_PARSER_H_
*”
fsoong/.intermediates/external/abseil-cpp/absl_log_log_sink_hdrs/gen/my_include_dir/absl/log/log_sink.h©// Copyright 2022 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: log/log_sink.h
// -----------------------------------------------------------------------------
//
// This header declares the interface class `absl::LogSink`.
#ifndef ABSL_LOG_LOG_SINK_H_
#define ABSL_LOG_LOG_SINK_H_
#include "absl/base/config.h"
#include "absl/log/log_entry.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
// absl::LogSink
//
// `absl::LogSink` is an interface which can be extended to intercept and
// process particular messages (with `LOG.ToSinkOnly()` or
// `LOG.ToSinkAlso()`) or all messages (if registered with
// `absl::AddLogSink`). Implementations must not take any locks that might be
// held by the `LOG` caller.
class LogSink {
public:
virtual ~LogSink() = default;
// LogSink::Send()
//
// `Send` is called synchronously during the log statement. `Send` must be
// thread-safe.
//
// It is safe to use `LOG` within an implementation of `Send`. `ToSinkOnly`
// and `ToSinkAlso` are safe in general but can be used to create an infinite
// loop if you try.
virtual void Send(const absl::LogEntry& entry) = 0;
// LogSink::Flush()
//
// Sinks that buffer messages should override this method to flush the buffer
// and return. `Flush` must be thread-safe.
virtual void Flush() {}
protected:
LogSink() = default;
// Implementations may be copyable and/or movable.
LogSink(const LogSink&) = default;
LogSink& operator=(const LogSink&) = default;
private:
// https://lld.llvm.org/missingkeyfunction.html#missing-key-function
virtual void KeyFunction() const final; // NOLINT(readability/inheritance)
};
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_LOG_LOG_SINK_H_
*ך
rsoong/.intermediates/external/abseil-cpp/absl_strings_str_format_hdrs/gen/my_include_dir/absl/strings/str_format.hߙ//
// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// -----------------------------------------------------------------------------
// File: str_format.h
// -----------------------------------------------------------------------------
//
// The `str_format` library is a typesafe replacement for the family of
// `printf()` string formatting routines within the `<cstdio>` standard library
// header. Like the `printf` family, `str_format` uses a "format string" to
// perform argument substitutions based on types. See the `FormatSpec` section
// below for format string documentation.
//
// Example:
//
// std::string s = absl::StrFormat(
// "%s %s You have $%d!", "Hello", name, dollars);
//
// The library consists of the following basic utilities:
//
// * `absl::StrFormat()`, a type-safe replacement for `std::sprintf()`, to
// write a format string to a `string` value.
// * `absl::StrAppendFormat()` to append a format string to a `string`
// * `absl::StreamFormat()` to more efficiently write a format string to a
// stream, such as`std::cout`.
// * `absl::PrintF()`, `absl::FPrintF()` and `absl::SNPrintF()` as
// drop-in replacements for `std::printf()`, `std::fprintf()` and
// `std::snprintf()`.
//
// Note: An `absl::SPrintF()` drop-in replacement is not supported as it
// is generally unsafe due to buffer overflows. Use `absl::StrFormat` which
// returns the string as output instead of expecting a pre-allocated buffer.
//
// Additionally, you can provide a format string (and its associated arguments)
// using one of the following abstractions:
//
// * A `FormatSpec` class template fully encapsulates a format string and its
// type arguments and is usually provided to `str_format` functions as a
// variadic argument of type `FormatSpec<Arg...>`. The `FormatSpec<Args...>`
// template is evaluated at compile-time, providing type safety.
// * A `ParsedFormat` instance, which encapsulates a specific, pre-compiled
// format string for a specific set of type(s), and which can be passed
// between API boundaries. (The `FormatSpec` type should not be used
// directly except as an argument type for wrapper functions.)
//
// The `str_format` library provides the ability to output its format strings to
// arbitrary sink types:
//
// * A generic `Format()` function to write outputs to arbitrary sink types,
// which must implement a `FormatRawSink` interface.
//
// * A `FormatUntyped()` function that is similar to `Format()` except it is
// loosely typed. `FormatUntyped()` is not a template and does not perform
// any compile-time checking of the format string; instead, it returns a
// boolean from a runtime check.
//
// In addition, the `str_format` library provides extension points for
// augmenting formatting to new types. See "StrFormat Extensions" below.
#ifndef ABSL_STRINGS_STR_FORMAT_H_
#define ABSL_STRINGS_STR_FORMAT_H_
#include <cstdint>
#include <cstdio>
#include <string>
#include <type_traits>
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/nullability.h"
#include "absl/strings/internal/str_format/arg.h" // IWYU pragma: export
#include "absl/strings/internal/str_format/bind.h" // IWYU pragma: export
#include "absl/strings/internal/str_format/checker.h" // IWYU pragma: export
#include "absl/strings/internal/str_format/extension.h" // IWYU pragma: export
#include "absl/strings/internal/str_format/parser.h" // IWYU pragma: export
#include "absl/strings/string_view.h"
#include "absl/types/span.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
// UntypedFormatSpec
//
// A type-erased class that can be used directly within untyped API entry
// points. An `UntypedFormatSpec` is specifically used as an argument to
// `FormatUntyped()`.
//
// Example:
//
// absl::UntypedFormatSpec format("%d");
// std::string out;
// CHECK(absl::FormatUntyped(&out, format, {absl::FormatArg(1)}));
class UntypedFormatSpec {
public:
UntypedFormatSpec() = delete;
UntypedFormatSpec(const UntypedFormatSpec&) = delete;
UntypedFormatSpec& operator=(const UntypedFormatSpec&) = delete;
explicit UntypedFormatSpec(string_view s) : spec_(s) {}
protected:
explicit UntypedFormatSpec(
const str_format_internal::ParsedFormatBase* absl_nonnull pc)
: spec_(pc) {}
private:
friend str_format_internal::UntypedFormatSpecImpl;
str_format_internal::UntypedFormatSpecImpl spec_;
};
// FormatStreamed()
//
// Takes a streamable argument and returns an object that can print it
// with '%s'. Allows printing of types that have an `operator<<` but no
// intrinsic type support within `StrFormat()` itself.
//
// Example:
//
// absl::StrFormat("%s", absl::FormatStreamed(obj));
template <typename T>
str_format_internal::StreamedWrapper<T> FormatStreamed(const T& v) {
return str_format_internal::StreamedWrapper<T>(v);
}
// FormatCountCapture
//
// This class provides a way to safely wrap `StrFormat()` captures of `%n`
// conversions, which denote the number of characters written by a formatting
// operation to this point, into an integer value.
//
// This wrapper is designed to allow safe usage of `%n` within `StrFormat(); in
// the `printf()` family of functions, `%n` is not safe to use, as the `int *`
// buffer can be used to capture arbitrary data.
//
// Example:
//
// int n = 0;
// std::string s = absl::StrFormat("%s%d%n", "hello", 123,
// absl::FormatCountCapture(&n));
// EXPECT_EQ(8, n);
class FormatCountCapture {
public:
explicit FormatCountCapture(int* absl_nonnull p) : p_(p) {}
private:
// FormatCountCaptureHelper is used to define FormatConvertImpl() for this
// class.
friend struct str_format_internal::FormatCountCaptureHelper;
// Unused() is here because of the false positive from -Wunused-private-field
// p_ is used in the templated function of the friend FormatCountCaptureHelper
// class.
int* absl_nonnull Unused() { return p_; }
int* absl_nonnull p_;
};
// FormatSpec
//
// The `FormatSpec` type defines the makeup of a format string within the
// `str_format` library. It is a variadic class template that is evaluated at
// compile-time, according to the format string and arguments that are passed to
// it.
//
// You should not need to manipulate this type directly. You should only name it
// if you are writing wrapper functions which accept format arguments that will
// be provided unmodified to functions in this library. Such a wrapper function
// might be a class method that provides format arguments and/or internally uses
// the result of formatting.
//
// For a `FormatSpec` to be valid at compile-time, it must be provided as
// either:
//
// * A `constexpr` literal or `absl::string_view`, which is how it is most often
// used.
// * A `ParsedFormat` instantiation, which ensures the format string is
// valid before use. (See below.)
//
// Example:
//
// // Provided as a string literal.
// absl::StrFormat("Welcome to %s, Number %d!", "The Village", 6);
//
// // Provided as a constexpr absl::string_view.
// constexpr absl::string_view formatString = "Welcome to %s, Number %d!";
// absl::StrFormat(formatString, "The Village", 6);
//
// // Provided as a pre-compiled ParsedFormat object.
// // Note that this example is useful only for illustration purposes.
// absl::ParsedFormat<'s', 'd'> formatString("Welcome to %s, Number %d!");
// absl::StrFormat(formatString, "TheVillage", 6);
//
// A format string generally follows the POSIX syntax as used within the POSIX
// `printf` specification. (Exceptions are noted below.)
//
// (See http://pubs.opengroup.org/onlinepubs/9699919799/functions/fprintf.html)
//
// In specific, the `FormatSpec` supports the following type specifiers:
// * `c` for characters
// * `s` for strings
// * `d` or `i` for integers
// * `o` for unsigned integer conversions into octal
// * `x` or `X` for unsigned integer conversions into hex
// * `u` for unsigned integers
// * `f` or `F` for floating point values into decimal notation
// * `e` or `E` for floating point values into exponential notation
// * `a` or `A` for floating point values into hex exponential notation
// * `g` or `G` for floating point values into decimal or exponential
// notation based on their precision
// * `p` for pointer address values
// * `n` for the special case of writing out the number of characters
// written to this point. The resulting value must be captured within an
// `absl::FormatCountCapture` type.
// * `v` for values using the default format for a deduced type. These deduced
// types include many of the primitive types denoted here as well as
// user-defined types containing the proper extensions. (See below for more
// information.)
//
// Implementation-defined behavior:
// * A null pointer provided to "%s" or "%p" is output as "(nil)".
// * A non-null pointer provided to "%p" is output in hex as if by %#x or
// %#lx.
//
// NOTE: `o`, `x\X` and `u` will convert signed values to their unsigned
// counterpart before formatting.
//
// Examples:
// "%c", 'a' -> "a"
// "%c", 32 -> " "
// "%s", "C" -> "C"
// "%s", std::string("C++") -> "C++"
// "%d", -10 -> "-10"
// "%o", 10 -> "12"
// "%x", 16 -> "10"
// "%f", 123456789 -> "123456789.000000"
// "%e", .01 -> "1.00000e-2"
// "%a", -3.0 -> "-0x1.8p+1"
// "%g", .01 -> "1e-2"
// "%p", (void*)&value -> "0x7ffdeb6ad2a4"
//
// int n = 0;
// std::string s = absl::StrFormat(
// "%s%d%n", "hello", 123, absl::FormatCountCapture(&n));
// EXPECT_EQ(8, n);
//
// NOTE: the `v` specifier (for "value") is a type specifier not present in the
// POSIX specification. %v will format values according to their deduced type.
// `v` uses `d` for signed integer values, `u` for unsigned integer values, `g`
// for floating point values, and formats boolean values as "true"/"false"
// (instead of 1 or 0 for booleans formatted using d). `const char*` is not
// supported; please use `std::string` and `string_view`. `char` is also not
// supported due to ambiguity of the type. This specifier does not support
// modifiers.
//
// The `FormatSpec` intrinsically supports all of these fundamental C++ types:
//
// * Characters: `char`, `signed char`, `unsigned char`, `wchar_t`
// * Integers: `int`, `short`, `unsigned short`, `unsigned`, `long`,
// `unsigned long`, `long long`, `unsigned long long`
// * Enums: printed as their underlying integral value
// * Floating-point: `float`, `double`, `long double`
//
// However, in the `str_format` library, a format conversion specifies a broader
// C++ conceptual category instead of an exact type. For example, `%s` binds to
// any string-like argument, so `std::string`, `std::wstring`,
// `absl::string_view`, `const char*`, and `const wchar_t*` are all accepted.
// Likewise, `%d` accepts any integer-like argument, etc.
template <typename... Args>
using FormatSpec = str_format_internal::FormatSpecTemplate<
str_format_internal::ArgumentToConv<Args>()...>;
// ParsedFormat
//
// A `ParsedFormat` is a class template representing a preparsed `FormatSpec`,
// with template arguments specifying the conversion characters used within the
// format string. Such characters must be valid format type specifiers, and
// these type specifiers are checked at compile-time.
//
// Instances of `ParsedFormat` can be created, copied, and reused to speed up
// formatting loops. A `ParsedFormat` may either be constructed statically, or
// dynamically through its `New()` factory function, which only constructs a
// runtime object if the format is valid at that time.
//
// Example:
//
// // Verified at compile time.
// absl::ParsedFormat<'s', 'd'> format_string("Welcome to %s, Number %d!");
// absl::StrFormat(format_string, "TheVillage", 6);
//
// // Verified at runtime.
// auto format_runtime = absl::ParsedFormat<'d'>::New(format_string);
// if (format_runtime) {
// value = absl::StrFormat(*format_runtime, i);
// } else {
// ... error case ...
// }
#if defined(__cpp_nontype_template_parameter_auto)
// If C++17 is available, an 'extended' format is also allowed that can specify
// multiple conversion characters per format argument, using a combination of
// `absl::FormatConversionCharSet` enum values (logically a set union)
// via the `|` operator. (Single character-based arguments are still accepted,
// but cannot be combined). Some common conversions also have predefined enum
// values, such as `absl::FormatConversionCharSet::kIntegral`.
//
// Example:
// // Extended format supports multiple conversion characters per argument,
// // specified via a combination of `FormatConversionCharSet` enums.
// using MyFormat = absl::ParsedFormat<absl::FormatConversionCharSet::d |
// absl::FormatConversionCharSet::x>;
// MyFormat GetFormat(bool use_hex) {
// if (use_hex) return MyFormat("foo %x bar");
// return MyFormat("foo %d bar");
// }
// // `format` can be used with any value that supports 'd' and 'x',
// // like `int`.
// auto format = GetFormat(use_hex);
// value = StringF(format, i);
template <auto... Conv>
using ParsedFormat = absl::str_format_internal::ExtendedParsedFormat<
absl::str_format_internal::ToFormatConversionCharSet(Conv)...>;
#else
template <char... Conv>
using ParsedFormat = str_format_internal::ExtendedParsedFormat<
absl::str_format_internal::ToFormatConversionCharSet(Conv)...>;
#endif // defined(__cpp_nontype_template_parameter_auto)
// StrFormat()
//
// Returns a `string` given a `printf()`-style format string and zero or more
// additional arguments. Use it as you would `sprintf()`. `StrFormat()` is the
// primary formatting function within the `str_format` library, and should be
// used in most cases where you need type-safe conversion of types into
// formatted strings.
//
// The format string generally consists of ordinary character data along with
// one or more format conversion specifiers (denoted by the `%` character).
// Ordinary character data is returned unchanged into the result string, while
// each conversion specification performs a type substitution from
// `StrFormat()`'s other arguments. See the comments for `FormatSpec` for full
// information on the makeup of this format string.
//
// Example:
//
// std::string s = absl::StrFormat(
// "Welcome to %s, Number %d!", "The Village", 6);
// EXPECT_EQ("Welcome to The Village, Number 6!", s);
//
// Returns an empty string in case of error.
template <typename... Args>
[[nodiscard]] std::string StrFormat(const FormatSpec<Args...>& format,
const Args&... args) {
return str_format_internal::FormatPack(
str_format_internal::UntypedFormatSpecImpl::Extract(format),
{str_format_internal::FormatArgImpl(args)...});
}
// StrAppendFormat()
//
// Appends to a `dst` string given a format string, and zero or more additional
// arguments, returning `*dst` as a convenience for chaining purposes. Appends
// nothing in case of error (but possibly alters its capacity).
//
// Example:
//
// std::string orig("For example PI is approximately ");
// std::cout << StrAppendFormat(&orig, "%12.6f", 3.14);
template <typename... Args>
std::string& StrAppendFormat(std::string* absl_nonnull dst,
const FormatSpec<Args...>& format,
const Args&... args) {
return str_format_internal::AppendPack(
dst, str_format_internal::UntypedFormatSpecImpl::Extract(format),
{str_format_internal::FormatArgImpl(args)...});
}
// StreamFormat()
//
// Writes to an output stream given a format string and zero or more arguments,
// generally in a manner that is more efficient than streaming the result of
// `absl::StrFormat()`. The returned object must be streamed before the full
// expression ends.
//
// Example:
//
// std::cout << StreamFormat("%12.6f", 3.14);
template <typename... Args>
[[nodiscard]] str_format_internal::Streamable StreamFormat(
const FormatSpec<Args...>& format, const Args&... args) {
return str_format_internal::Streamable(
str_format_internal::UntypedFormatSpecImpl::Extract(format),
{str_format_internal::FormatArgImpl(args)...});
}
// PrintF()
//
// Writes to stdout given a format string and zero or more arguments. This
// function is functionally equivalent to `std::printf()` (and type-safe);
// prefer `absl::PrintF()` over `std::printf()`.
//
// Example:
//
// std::string_view s = "Ulaanbaatar";
// absl::PrintF("The capital of Mongolia is %s", s);
//
// Outputs: "The capital of Mongolia is Ulaanbaatar"
//
template <typename... Args>
int PrintF(const FormatSpec<Args...>& format, const Args&... args) {
return str_format_internal::FprintF(
stdout, str_format_internal::UntypedFormatSpecImpl::Extract(format),
{str_format_internal::FormatArgImpl(args)...});
}
// FPrintF()
//
// Writes to a file given a format string and zero or more arguments. This
// function is functionally equivalent to `std::fprintf()` (and type-safe);
// prefer `absl::FPrintF()` over `std::fprintf()`.
//
// Example:
//
// std::string_view s = "Ulaanbaatar";
// absl::FPrintF(stdout, "The capital of Mongolia is %s", s);
//
// Outputs: "The capital of Mongolia is Ulaanbaatar"
//
template <typename... Args>
int FPrintF(std::FILE* absl_nonnull output, const FormatSpec<Args...>& format,
const Args&... args) {
return str_format_internal::FprintF(
output, str_format_internal::UntypedFormatSpecImpl::Extract(format),
{str_format_internal::FormatArgImpl(args)...});
}
// SNPrintF()
//
// Writes to a sized buffer given a format string and zero or more arguments.
// This function is functionally equivalent to `std::snprintf()` (and
// type-safe); prefer `absl::SNPrintF()` over `std::snprintf()`.
//
// In particular, a successful call to `absl::SNPrintF()` writes at most `size`
// bytes of the formatted output to `output`, including a NUL-terminator, and
// returns the number of bytes that would have been written if truncation did
// not occur. In the event of an error, a negative value is returned and `errno`
// is set.
//
// Example:
//
// std::string_view s = "Ulaanbaatar";
// char output[128];
// absl::SNPrintF(output, sizeof(output),
// "The capital of Mongolia is %s", s);
//
// Post-condition: output == "The capital of Mongolia is Ulaanbaatar"
//
template <typename... Args>
int SNPrintF(char* absl_nonnull output, std::size_t size,
const FormatSpec<Args...>& format, const Args&... args) {
return str_format_internal::SnprintF(
output, size, str_format_internal::UntypedFormatSpecImpl::Extract(format),
{str_format_internal::FormatArgImpl(args)...});
}
// -----------------------------------------------------------------------------
// Custom Output Formatting Functions
// -----------------------------------------------------------------------------
// FormatRawSink
//
// FormatRawSink is a type erased wrapper around arbitrary sink objects
// specifically used as an argument to `Format()`.
//
// All the object has to do define an overload of `AbslFormatFlush()` for the
// sink, usually by adding a ADL-based free function in the same namespace as
// the sink:
//
// void AbslFormatFlush(MySink* dest, absl::string_view part);
//
// where `dest` is the pointer passed to `absl::Format()`. The function should
// append `part` to `dest`.
//
// FormatRawSink does not own the passed sink object. The passed object must
// outlive the FormatRawSink.
class FormatRawSink {
public:
// Implicitly convert from any type that provides the hook function as
// described above.
template <typename T,
typename = typename std::enable_if<std::is_constructible<
str_format_internal::FormatRawSinkImpl, T*>::value>::type>
FormatRawSink(T* absl_nonnull raw) // NOLINT
: sink_(raw) {}
private:
friend str_format_internal::FormatRawSinkImpl;
str_format_internal::FormatRawSinkImpl sink_;
};
// Format()
//
// Writes a formatted string to an arbitrary sink object (implementing the
// `absl::FormatRawSink` interface), using a format string and zero or more
// additional arguments.
//
// By default, `std::string`, `std::ostream`, and `absl::Cord` are supported as
// destination objects. If a `std::string` is used the formatted string is
// appended to it.
//
// `absl::Format()` is a generic version of `absl::StrAppendFormat()`, for
// custom sinks. The format string, like format strings for `StrFormat()`, is
// checked at compile-time.
//
// On failure, this function returns `false` and the state of the sink is
// unspecified.
template <typename... Args>
bool Format(FormatRawSink raw_sink, const FormatSpec<Args...>& format,
const Args&... args) {
return str_format_internal::FormatUntyped(
str_format_internal::FormatRawSinkImpl::Extract(raw_sink),
str_format_internal::UntypedFormatSpecImpl::Extract(format),
{str_format_internal::FormatArgImpl(args)...});
}
// FormatArg
//
// A type-erased handle to a format argument specifically used as an argument to
// `FormatUntyped()`. You may construct `FormatArg` by passing
// reference-to-const of any printable type. `FormatArg` is both copyable and
// assignable. The source data must outlive the `FormatArg` instance. See
// example below.
//
using FormatArg = str_format_internal::FormatArgImpl;
// FormatUntyped()
//
// Writes a formatted string to an arbitrary sink object (implementing the
// `absl::FormatRawSink` interface), using an `UntypedFormatSpec` and zero or
// more additional arguments.
//
// This function acts as the most generic formatting function in the
// `str_format` library. The caller provides a raw sink, an unchecked format
// string, and (usually) a runtime specified list of arguments; no compile-time
// checking of formatting is performed within this function. As a result, a
// caller should check the return value to verify that no error occurred.
// On failure, this function returns `false` and the state of the sink is
// unspecified.
//
// The arguments are provided in an `absl::Span<const absl::FormatArg>`.
// Each `absl::FormatArg` object binds to a single argument and keeps a
// reference to it. The values used to create the `FormatArg` objects must
// outlive this function call.
//
// Example:
//
// std::optional<std::string> FormatDynamic(
// const std::string& in_format,
// const vector<std::string>& in_args) {
// std::string out;
// std::vector<absl::FormatArg> args;
// for (const auto& v : in_args) {
// // It is important that 'v' is a reference to the objects in in_args.
// // The values we pass to FormatArg must outlive the call to
// // FormatUntyped.
// args.emplace_back(v);
// }
// absl::UntypedFormatSpec format(in_format);
// if (!absl::FormatUntyped(&out, format, args)) {
// return std::nullopt;
// }
// return std::move(out);
// }
//
[[nodiscard]] inline bool FormatUntyped(FormatRawSink raw_sink,
const UntypedFormatSpec& format,
absl::Span<const FormatArg> args) {
return str_format_internal::FormatUntyped(
str_format_internal::FormatRawSinkImpl::Extract(raw_sink),
str_format_internal::UntypedFormatSpecImpl::Extract(format), args);
}
//------------------------------------------------------------------------------
// StrFormat Extensions
//------------------------------------------------------------------------------
//
// AbslStringify()
//
// A simpler customization API for formatting user-defined types using
// absl::StrFormat(). The API relies on detecting an overload in the
// user-defined type's namespace of a free (non-member) `AbslStringify()`
// function as a friend definition with the following signature:
//
// template <typename Sink>
// void AbslStringify(Sink& sink, const X& value);
//
// An `AbslStringify()` overload for a type should only be declared in the same
// file and namespace as said type.
//
// Note that unlike with AbslFormatConvert(), AbslStringify() does not allow
// customization of allowed conversion characters. AbslStringify() uses `%v` as
// the underlying conversion specifier. Additionally, AbslStringify() supports
// use with absl::StrCat while AbslFormatConvert() does not.
//
// Example:
//
// struct Point {
// // To add formatting support to `Point`, we simply need to add a free
// // (non-member) function `AbslStringify()`. This method prints in the
// // request format using the underlying `%v` specifier. You can add such a
// // free function using a friend declaration within the body of the class.
// // The sink parameter is a templated type to avoid requiring dependencies.
// template <typename Sink>
// friend void AbslStringify(Sink& sink, const Point& p) {
// absl::Format(&sink, "(%v, %v)", p.x, p.y);
// }
//
// int x;
// int y;
// };
//
// AbslFormatConvert()
//
// The StrFormat library provides a customization API for formatting
// user-defined types using absl::StrFormat(). The API relies on detecting an
// overload in the user-defined type's namespace of a free (non-member)
// `AbslFormatConvert()` function, usually as a friend definition with the
// following signature:
//
// absl::FormatConvertResult<...> AbslFormatConvert(
// const X& value,
// const absl::FormatConversionSpec& spec,
// absl::FormatSink *sink);
//
// An `AbslFormatConvert()` overload for a type should only be declared in the
// same file and namespace as said type.
//
// The abstractions within this definition include:
//
// * An `absl::FormatConversionSpec` to specify the fields to pull from a
// user-defined type's format string
// * An `absl::FormatSink` to hold the converted string data during the
// conversion process.
// * An `absl::FormatConvertResult` to hold the status of the returned
// formatting operation
//
// The return type encodes all the conversion characters that your
// AbslFormatConvert() routine accepts. The return value should be {true}.
// A return value of {false} will result in `StrFormat()` returning
// an empty string. This result will be propagated to the result of
// `FormatUntyped`.
//
// Example:
//
// struct Point {
// // To add formatting support to `Point`, we simply need to add a free
// // (non-member) function `AbslFormatConvert()`. This method interprets
// // `spec` to print in the request format. The allowed conversion characters
// // can be restricted via the type of the result, in this example
// // string and integral formatting are allowed (but not, for instance
// // floating point characters like "%f"). You can add such a free function
// // using a friend declaration within the body of the class:
// friend absl::FormatConvertResult<absl::FormatConversionCharSet::kString |
// absl::FormatConversionCharSet::kIntegral>
// AbslFormatConvert(const Point& p, const absl::FormatConversionSpec& spec,
// absl::FormatSink* s) {
// if (spec.conversion_char() == absl::FormatConversionChar::s) {
// absl::Format(s, "x=%vy=%v", p.x, p.y);
// } else {
// absl::Format(s, "%v,%v", p.x, p.y);
// }
// return {true};
// }
//
// int x;
// int y;
// };
// clang-format off
// FormatConversionChar
//
// Specifies the formatting character provided in the format string
// passed to `StrFormat()`.
enum class FormatConversionChar : uint8_t {
c, s, // text
d, i, o, u, x, X, // int
f, F, e, E, g, G, a, A, // float
n, p, v // misc
};
// clang-format on
// FormatConversionSpec
//
// Specifies modifications to the conversion of the format string, through use
// of one or more format flags in the source format string.
class FormatConversionSpec {
public:
// FormatConversionSpec::is_basic()
//
// Indicates that width and precision are not specified, and no additional
// flags are set for this conversion character in the format string.
bool is_basic() const { return impl_.is_basic(); }
// FormatConversionSpec::has_left_flag()
//
// Indicates whether the result should be left justified for this conversion
// character in the format string. This flag is set through use of a '-'
// character in the format string. E.g. "%-s"
bool has_left_flag() const { return impl_.has_left_flag(); }
// FormatConversionSpec::has_show_pos_flag()
//
// Indicates whether a sign column is prepended to the result for this
// conversion character in the format string, even if the result is positive.
// This flag is set through use of a '+' character in the format string.
// E.g. "%+d"
bool has_show_pos_flag() const { return impl_.has_show_pos_flag(); }
// FormatConversionSpec::has_sign_col_flag()
//
// Indicates whether a mandatory sign column is added to the result for this
// conversion character. This flag is set through use of a space character
// (' ') in the format string. E.g. "% i"
bool has_sign_col_flag() const { return impl_.has_sign_col_flag(); }
// FormatConversionSpec::has_alt_flag()
//
// Indicates whether an "alternate" format is applied to the result for this
// conversion character. Alternative forms depend on the type of conversion
// character, and unallowed alternatives are undefined. This flag is set
// through use of a '#' character in the format string. E.g. "%#h"
bool has_alt_flag() const { return impl_.has_alt_flag(); }
// FormatConversionSpec::has_zero_flag()
//
// Indicates whether zeroes should be prepended to the result for this
// conversion character instead of spaces. This flag is set through use of the
// '0' character in the format string. E.g. "%0f"
bool has_zero_flag() const { return impl_.has_zero_flag(); }
// FormatConversionSpec::conversion_char()
//
// Returns the underlying conversion character.
FormatConversionChar conversion_char() const {
return impl_.conversion_char();
}
// FormatConversionSpec::width()
//
// Returns the specified width (indicated through use of a non-zero integer
// value or '*' character) of the conversion character. If width is
// unspecified, it returns a negative value.
int width() const { return impl_.width(); }
// FormatConversionSpec::precision()
//
// Returns the specified precision (through use of the '.' character followed
// by a non-zero integer value or '*' character) of the conversion character.
// If precision is unspecified, it returns a negative value.
int precision() const { return impl_.precision(); }
private:
explicit FormatConversionSpec(
str_format_internal::FormatConversionSpecImpl impl)
: impl_(impl) {}
friend str_format_internal::FormatConversionSpecImpl;
absl::str_format_internal::FormatConversionSpecImpl impl_;
};
// Type safe OR operator for FormatConversionCharSet to allow accepting multiple
// conversion chars in custom format converters.
constexpr FormatConversionCharSet operator|(FormatConversionCharSet a,
FormatConversionCharSet b) {
return static_cast<FormatConversionCharSet>(static_cast<uint64_t>(a) |
static_cast<uint64_t>(b));
}
// FormatConversionCharSet
//
// Specifies the _accepted_ conversion types as a template parameter to
// FormatConvertResult for custom implementations of `AbslFormatConvert`.
// Note the helper predefined alias definitions (kIntegral, etc.) below.
enum class FormatConversionCharSet : uint64_t {
// text
c = str_format_internal::FormatConversionCharToConvInt('c'),
s = str_format_internal::FormatConversionCharToConvInt('s'),
// integer
d = str_format_internal::FormatConversionCharToConvInt('d'),
i = str_format_internal::FormatConversionCharToConvInt('i'),
o = str_format_internal::FormatConversionCharToConvInt('o'),
u = str_format_internal::FormatConversionCharToConvInt('u'),
x = str_format_internal::FormatConversionCharToConvInt('x'),
X = str_format_internal::FormatConversionCharToConvInt('X'),
// Float
f = str_format_internal::FormatConversionCharToConvInt('f'),
F = str_format_internal::FormatConversionCharToConvInt('F'),
e = str_format_internal::FormatConversionCharToConvInt('e'),
E = str_format_internal::FormatConversionCharToConvInt('E'),
g = str_format_internal::FormatConversionCharToConvInt('g'),
G = str_format_internal::FormatConversionCharToConvInt('G'),
a = str_format_internal::FormatConversionCharToConvInt('a'),
A = str_format_internal::FormatConversionCharToConvInt('A'),
// misc
n = str_format_internal::FormatConversionCharToConvInt('n'),
p = str_format_internal::FormatConversionCharToConvInt('p'),
v = str_format_internal::FormatConversionCharToConvInt('v'),
// Used for width/precision '*' specification.
kStar = static_cast<uint64_t>(
absl::str_format_internal::FormatConversionCharSetInternal::kStar),
// Some predefined values:
kIntegral = d | i | u | o | x | X,
kFloating = a | e | f | g | A | E | F | G,
kNumeric = kIntegral | kFloating,
kString = s,
kPointer = p,
};
// FormatSink
//
// A format sink is a generic abstraction to which conversions may write their
// formatted string data. `absl::FormatConvert()` uses this sink to write its
// formatted string.
//
class FormatSink {
public:
// FormatSink::Append()
//
// Appends `count` copies of `ch` to the format sink.
void Append(size_t count, char ch) { sink_->Append(count, ch); }
// Overload of FormatSink::Append() for appending the characters of a string
// view to a format sink.
void Append(string_view v) { sink_->Append(v); }
// FormatSink::PutPaddedString()
//
// Appends `precision` number of bytes of `v` to the format sink. If this is
// less than `width`, spaces will be appended first (if `left` is false), or
// after (if `left` is true) to ensure the total amount appended is
// at least `width`.
bool PutPaddedString(string_view v, int width, int precision, bool left) {
return sink_->PutPaddedString(v, width, precision, left);
}
// Support `absl::Format(&sink, format, args...)`.
friend void AbslFormatFlush(FormatSink* absl_nonnull sink,
absl::string_view v) {
sink->Append(v);
}
private:
friend str_format_internal::FormatSinkImpl;
explicit FormatSink(str_format_internal::FormatSinkImpl* absl_nonnull s)
: sink_(s) {}
str_format_internal::FormatSinkImpl* absl_nonnull sink_;
};
// FormatConvertResult
//
// Indicates whether a call to AbslFormatConvert() was successful.
// This return type informs the StrFormat extension framework (through
// ADL but using the return type) of what conversion characters are supported.
// It is strongly discouraged to return {false}, as this will result in an
// empty string in StrFormat.
template <FormatConversionCharSet C>
struct FormatConvertResult {
bool value;
};
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_STR_FORMAT_H_
*áZ
osoong/.intermediates/external/abseil-cpp/absl_base_hdrs/gen/my_include_dir/absl/base/internal/thread_identity.híY// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Each active thread has an ThreadIdentity that may represent the thread in
// various level interfaces. ThreadIdentity objects are never deallocated.
// When a thread terminates, its ThreadIdentity object may be reused for a
// thread created later.
#ifndef ABSL_BASE_INTERNAL_THREAD_IDENTITY_H_
#define ABSL_BASE_INTERNAL_THREAD_IDENTITY_H_
#ifndef _WIN32
#include <pthread.h>
// Defines __GOOGLE_GRTE_VERSION__ (via glibc-specific features.h) when
// supported.
#include <unistd.h>
#endif
#include <atomic>
#include <cstdint>
#include "absl/base/config.h"
#include "absl/base/internal/per_thread_tls.h"
#include "absl/base/optimization.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
struct SynchLocksHeld;
struct SynchWaitParams;
namespace base_internal {
class SpinLock;
struct ThreadIdentity;
// Used by the implementation of absl::Mutex and absl::CondVar.
struct PerThreadSynch {
// The internal representation of absl::Mutex and absl::CondVar rely
// on the alignment of PerThreadSynch. Both store the address of the
// PerThreadSynch in the high-order bits of their internal state,
// which means the low kLowZeroBits of the address of PerThreadSynch
// must be zero.
static constexpr int kLowZeroBits = 8;
static constexpr int kAlignment = 1 << kLowZeroBits;
// Returns the associated ThreadIdentity.
// This can be implemented as a cast because we guarantee
// PerThreadSynch is the first element of ThreadIdentity.
ThreadIdentity* thread_identity() {
return reinterpret_cast<ThreadIdentity*>(this);
}
PerThreadSynch* next; // Circular waiter queue; initialized to 0.
PerThreadSynch* skip; // If non-zero, all entries in Mutex queue
// up to and including "skip" have same
// condition as this, and will be woken later
bool may_skip; // if false while on mutex queue, a mutex unlocker
// is using this PerThreadSynch as a terminator. Its
// skip field must not be filled in because the loop
// might then skip over the terminator.
bool wake; // This thread is to be woken from a Mutex.
// If "x" is on a waiter list for a mutex, "x->cond_waiter" is true iff the
// waiter is waiting on the mutex as part of a CV Wait or Mutex Await.
//
// The value of "x->cond_waiter" is meaningless if "x" is not on a
// Mutex waiter list.
bool cond_waiter;
bool maybe_unlocking; // Valid at head of Mutex waiter queue;
// true if UnlockSlow could be searching
// for a waiter to wake. Used for an optimization
// in Enqueue(). true is always a valid value.
// Can be reset to false when the unlocker or any
// writer releases the lock, or a reader fully
// releases the lock. It may not be set to false
// by a reader that decrements the count to
// non-zero. protected by mutex spinlock
bool suppress_fatal_errors; // If true, try to proceed even in the face
// of broken invariants. This is used within
// fatal signal handlers to improve the
// chances of debug logging information being
// output successfully.
int priority; // Priority of thread (updated every so often).
// State values:
// kAvailable: This PerThreadSynch is available.
// kQueued: This PerThreadSynch is unavailable, it's currently queued on a
// Mutex or CondVar waistlist.
//
// Transitions from kQueued to kAvailable require a release
// barrier. This is needed as a waiter may use "state" to
// independently observe that it's no longer queued.
//
// Transitions from kAvailable to kQueued require no barrier, they
// are externally ordered by the Mutex.
enum State { kAvailable, kQueued };
std::atomic<State> state;
// The wait parameters of the current wait. waitp is null if the
// thread is not waiting. Transitions from null to non-null must
// occur before the enqueue commit point (state = kQueued in
// Enqueue() and CondVarEnqueue()). Transitions from non-null to
// null must occur after the wait is finished (state = kAvailable in
// Mutex::Block() and CondVar::WaitCommon()). This field may be
// changed only by the thread that describes this PerThreadSynch. A
// special case is Fer(), which calls Enqueue() on another thread,
// but with an identical SynchWaitParams pointer, thus leaving the
// pointer unchanged.
SynchWaitParams* waitp;
intptr_t readers; // Number of readers in mutex.
// When priority will next be read (cycles).
int64_t next_priority_read_cycles;
// Locks held; used during deadlock detection.
// Allocated in Synch_GetAllLocks() and freed in ReclaimThreadIdentity().
SynchLocksHeld* all_locks;
};
// The instances of this class are allocated in NewThreadIdentity() with an
// alignment of PerThreadSynch::kAlignment and never destroyed. Initialization
// should happen in OneTimeInitThreadIdentity().
//
// Instances may be reused by new threads - fields should be reset in
// ResetThreadIdentityBetweenReuse().
//
// NOTE: The layout of fields in this structure is critical, please do not
// add, remove, or modify the field placements without fully auditing the
// layout.
struct ThreadIdentity {
// Must be the first member. The Mutex implementation requires that
// the PerThreadSynch object associated with each thread is
// PerThreadSynch::kAlignment aligned. We provide this alignment on
// ThreadIdentity itself.
PerThreadSynch per_thread_synch;
// Private: Reserved for absl::synchronization_internal::Waiter.
struct WaiterState {
alignas(void*) char data[256];
} waiter_state;
// Used by PerThreadSem::{Get,Set}ThreadBlockedCounter().
std::atomic<int>* blocked_count_ptr;
// The following variables are mostly read/written just by the
// thread itself. The only exception is that these are read by
// a ticker thread as a hint.
std::atomic<int> ticker; // Tick counter, incremented once per second.
std::atomic<int> wait_start; // Ticker value when thread started waiting.
std::atomic<bool> is_idle; // Has thread become idle yet?
ThreadIdentity* next;
};
// Returns the ThreadIdentity object representing the calling thread; guaranteed
// to be unique for its lifetime. The returned object will remain valid for the
// program's lifetime; although it may be re-assigned to a subsequent thread.
// If one does not exist, return nullptr instead.
//
// Does not malloc(*), and is async-signal safe.
// [*] Technically pthread_setspecific() does malloc on first use; however this
// is handled internally within tcmalloc's initialization already. Note that
// darwin does *not* use tcmalloc, so this can catch you if using MallocHooks
// on Apple platforms. Whatever function is calling your MallocHooks will need
// to watch for recursion on Apple platforms.
//
// New ThreadIdentity objects can be constructed and associated with a thread
// by calling GetOrCreateCurrentThreadIdentity() in per-thread-sem.h.
ThreadIdentity* CurrentThreadIdentityIfPresent();
using ThreadIdentityReclaimerFunction = void (*)(void*);
// Sets the current thread identity to the given value. 'reclaimer' is a
// pointer to the global function for cleaning up instances on thread
// destruction.
void SetCurrentThreadIdentity(ThreadIdentity* identity,
ThreadIdentityReclaimerFunction reclaimer);
// Removes the currently associated ThreadIdentity from the running thread.
// This must be called from inside the ThreadIdentityReclaimerFunction, and only
// from that function.
void ClearCurrentThreadIdentity();
// May be chosen at compile time via: -DABSL_FORCE_THREAD_IDENTITY_MODE=<mode
// index>
#ifdef ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC
#error ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC cannot be directly set
#else
#define ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC 0
#endif
#ifdef ABSL_THREAD_IDENTITY_MODE_USE_TLS
#error ABSL_THREAD_IDENTITY_MODE_USE_TLS cannot be directly set
#else
#define ABSL_THREAD_IDENTITY_MODE_USE_TLS 1
#endif
#ifdef ABSL_THREAD_IDENTITY_MODE_USE_CPP11
#error ABSL_THREAD_IDENTITY_MODE_USE_CPP11 cannot be directly set
#else
#define ABSL_THREAD_IDENTITY_MODE_USE_CPP11 2
#endif
#ifdef ABSL_THREAD_IDENTITY_MODE
#error ABSL_THREAD_IDENTITY_MODE cannot be directly set
#elif defined(ABSL_FORCE_THREAD_IDENTITY_MODE)
#define ABSL_THREAD_IDENTITY_MODE ABSL_FORCE_THREAD_IDENTITY_MODE
#elif defined(_WIN32) && !defined(__MINGW32__)
#define ABSL_THREAD_IDENTITY_MODE ABSL_THREAD_IDENTITY_MODE_USE_CPP11
#elif defined(__APPLE__) && defined(ABSL_HAVE_THREAD_LOCAL)
#define ABSL_THREAD_IDENTITY_MODE ABSL_THREAD_IDENTITY_MODE_USE_CPP11
#elif ABSL_PER_THREAD_TLS && defined(__GOOGLE_GRTE_VERSION__) && \
(__GOOGLE_GRTE_VERSION__ >= 20140228L)
// Support for async-safe TLS was specifically added in GRTEv4. It's not
// present in the upstream eglibc.
// Note: Current default for production systems.
#define ABSL_THREAD_IDENTITY_MODE ABSL_THREAD_IDENTITY_MODE_USE_TLS
#else
#define ABSL_THREAD_IDENTITY_MODE \
ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC
#endif
#if ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_TLS || \
ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_CPP11
#if ABSL_PER_THREAD_TLS
ABSL_CONST_INIT extern ABSL_PER_THREAD_TLS_KEYWORD ThreadIdentity*
thread_identity_ptr;
#elif defined(ABSL_HAVE_THREAD_LOCAL)
ABSL_CONST_INIT extern thread_local ThreadIdentity* thread_identity_ptr;
#else
#error Thread-local storage not detected on this platform
#endif
// thread_local variables cannot be in headers exposed by DLLs or in certain
// build configurations on Apple platforms. However, it is important for
// performance reasons in general that `CurrentThreadIdentityIfPresent` be
// inlined. In the other cases we opt to have the function not be inlined. Note
// that `CurrentThreadIdentityIfPresent` is declared above so we can exclude
// this entire inline definition.
#if !defined(__APPLE__) && !defined(ABSL_BUILD_DLL) && \
!defined(ABSL_CONSUME_DLL)
#define ABSL_INTERNAL_INLINE_CURRENT_THREAD_IDENTITY_IF_PRESENT 1
#endif
#ifdef ABSL_INTERNAL_INLINE_CURRENT_THREAD_IDENTITY_IF_PRESENT
inline ThreadIdentity* CurrentThreadIdentityIfPresent() {
return thread_identity_ptr;
}
#endif
#elif ABSL_THREAD_IDENTITY_MODE != \
ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC
#error Unknown ABSL_THREAD_IDENTITY_MODE
#endif
} // namespace base_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_INTERNAL_THREAD_IDENTITY_H_
soong/.intermediates/external/abseil-cpp/absl_strings_cordz_handle_hdrs/gen/my_include_dir/absl/strings/internal/cordz_handle.hï// Copyright 2019 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_STRINGS_INTERNAL_CORDZ_HANDLE_H_
#define ABSL_STRINGS_INTERNAL_CORDZ_HANDLE_H_
#include <atomic>
#include <vector>
#include "absl/base/config.h"
#include "absl/base/internal/raw_logging.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace cord_internal {
// This base class allows multiple types of object (CordzInfo and
// CordzSampleToken) to exist simultaneously on the delete queue (pointed to by
// global_dq_tail and traversed using dq_prev_ and dq_next_). The
// delete queue guarantees that once a profiler creates a CordzSampleToken and
// has gained visibility into a CordzInfo object, that CordzInfo object will not
// be deleted prematurely. This allows the profiler to inspect all CordzInfo
// objects that are alive without needing to hold a global lock.
class ABSL_DLL CordzHandle {
public:
CordzHandle() : CordzHandle(false) {}
bool is_snapshot() const { return is_snapshot_; }
// Returns true if this instance is safe to be deleted because it is either a
// snapshot, which is always safe to delete, or not included in the global
// delete queue and thus not included in any snapshot.
// Callers are responsible for making sure this instance can not be newly
// discovered by other threads. For example, CordzInfo instances first de-list
// themselves from the global CordzInfo list before determining if they are
// safe to be deleted directly.
// If SafeToDelete returns false, callers MUST use the Delete() method to
// safely queue CordzHandle instances for deletion.
bool SafeToDelete() const;
// Deletes the provided instance, or puts it on the delete queue to be deleted
// once there are no more sample tokens (snapshot) instances potentially
// referencing the instance. `handle` should not be null.
static void Delete(CordzHandle* handle);
// Returns the current entries in the delete queue in LIFO order.
static std::vector<const CordzHandle*> DiagnosticsGetDeleteQueue();
// Returns true if the provided handle is nullptr or guarded by this handle.
// Since the CordzSnapshot token is itself a CordzHandle, this method will
// allow tests to check if that token is keeping an arbitrary CordzHandle
// alive.
bool DiagnosticsHandleIsSafeToInspect(const CordzHandle* handle) const;
// Returns the current entries in the delete queue, in LIFO order, that are
// protected by this. CordzHandle objects are only placed on the delete queue
// after CordzHandle::Delete is called with them as an argument. Only
// CordzHandle objects that are not also CordzSnapshot objects will be
// included in the return vector. For each of the handles in the return
// vector, the earliest that their memory can be freed is when this
// CordzSnapshot object is deleted.
std::vector<const CordzHandle*> DiagnosticsGetSafeToInspectDeletedHandles();
protected:
explicit CordzHandle(bool is_snapshot);
virtual ~CordzHandle();
private:
const bool is_snapshot_;
// dq_prev_ and dq_next_ require the global queue mutex to be held.
// Unfortunately we can't use thread annotations such that the thread safety
// analysis understands that queue_ and global_queue_ are one and the same.
CordzHandle* dq_prev_ = nullptr;
CordzHandle* dq_next_ = nullptr;
};
class CordzSnapshot : public CordzHandle {
public:
CordzSnapshot() : CordzHandle(true) {}
};
} // namespace cord_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_CORDZ_HANDLE_H_
*Ëk
•soong/.intermediates/external/abseil-cpp/absl_time_internal_cctz_civil_time_hdrs/gen/my_include_dir/absl/time/internal/cctz/include/cctz/civil_time.h°j// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_H_
#define ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_H_
#include "absl/base/config.h"
#include "absl/time/internal/cctz/include/cctz/civil_time_detail.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace time_internal {
namespace cctz {
// The term "civil time" refers to the legally recognized human-scale time
// that is represented by the six fields YYYY-MM-DD hh:mm:ss. Modern-day civil
// time follows the Gregorian Calendar and is a time-zone-independent concept.
// A "date" is perhaps the most common example of a civil time (represented in
// this library as cctz::civil_day). This library provides six classes and a
// handful of functions that help with rounding, iterating, and arithmetic on
// civil times while avoiding complications like daylight-saving time (DST).
//
// The following six classes form the core of this civil-time library:
//
// * civil_second
// * civil_minute
// * civil_hour
// * civil_day
// * civil_month
// * civil_year
//
// Each class is a simple value type with the same interface for construction
// and the same six accessors for each of the civil fields (year, month, day,
// hour, minute, and second, aka YMDHMS). These classes differ only in their
// alignment, which is indicated by the type name and specifies the field on
// which arithmetic operates.
//
// Each class can be constructed by passing up to six optional integer
// arguments representing the YMDHMS fields (in that order) to the
// constructor. Omitted fields are assigned their minimum valid value. Hours,
// minutes, and seconds will be set to 0, month and day will be set to 1, and
// since there is no minimum valid year, it will be set to 1970. So, a
// default-constructed civil-time object will have YMDHMS fields representing
// "1970-01-01 00:00:00". Fields that are out-of-range are normalized (e.g.,
// October 32 -> November 1) so that all civil-time objects represent valid
// values.
//
// Each civil-time class is aligned to the civil-time field indicated in the
// class's name after normalization. Alignment is performed by setting all the
// inferior fields to their minimum valid value (as described above). The
// following are examples of how each of the six types would align the fields
// representing November 22, 2015 at 12:34:56 in the afternoon. (Note: the
// string format used here is not important; it's just a shorthand way of
// showing the six YMDHMS fields.)
//
// civil_second 2015-11-22 12:34:56
// civil_minute 2015-11-22 12:34:00
// civil_hour 2015-11-22 12:00:00
// civil_day 2015-11-22 00:00:00
// civil_month 2015-11-01 00:00:00
// civil_year 2015-01-01 00:00:00
//
// Each civil-time type performs arithmetic on the field to which it is
// aligned. This means that adding 1 to a civil_day increments the day field
// (normalizing as necessary), and subtracting 7 from a civil_month operates
// on the month field (normalizing as necessary). All arithmetic produces a
// valid civil time. Difference requires two similarly aligned civil-time
// objects and returns the scalar answer in units of the objects' alignment.
// For example, the difference between two civil_hour objects will give an
// answer in units of civil hours.
//
// In addition to the six civil-time types just described, there are
// a handful of helper functions and algorithms for performing common
// calculations. These are described below.
//
// Note: In C++14 and later, this library is usable in a constexpr context.
//
// CONSTRUCTION:
//
// Each of the civil-time types can be constructed in two ways: by directly
// passing to the constructor up to six (optional) integers representing the
// YMDHMS fields, or by copying the YMDHMS fields from a differently aligned
// civil-time type.
//
// civil_day default_value; // 1970-01-01 00:00:00
//
// civil_day a(2015, 2, 3); // 2015-02-03 00:00:00
// civil_day b(2015, 2, 3, 4, 5, 6); // 2015-02-03 00:00:00
// civil_day c(2015); // 2015-01-01 00:00:00
//
// civil_second ss(2015, 2, 3, 4, 5, 6); // 2015-02-03 04:05:06
// civil_minute mm(ss); // 2015-02-03 04:05:00
// civil_hour hh(mm); // 2015-02-03 04:00:00
// civil_day d(hh); // 2015-02-03 00:00:00
// civil_month m(d); // 2015-02-01 00:00:00
// civil_year y(m); // 2015-01-01 00:00:00
//
// m = civil_month(y); // 2015-01-01 00:00:00
// d = civil_day(m); // 2015-01-01 00:00:00
// hh = civil_hour(d); // 2015-01-01 00:00:00
// mm = civil_minute(hh); // 2015-01-01 00:00:00
// ss = civil_second(mm); // 2015-01-01 00:00:00
//
// ALIGNMENT CONVERSION:
//
// The alignment of a civil-time object cannot change, but the object may be
// used to construct a new object with a different alignment. This is referred
// to as "realigning". When realigning to a type with the same or more
// precision (e.g., civil_day -> civil_second), the conversion may be
// performed implicitly since no information is lost. However, if information
// could be discarded (e.g., civil_second -> civil_day), the conversion must
// be explicit at the call site.
//
// void fun(const civil_day& day);
//
// civil_second cs;
// fun(cs); // Won't compile because data may be discarded
// fun(civil_day(cs)); // OK: explicit conversion
//
// civil_day cd;
// fun(cd); // OK: no conversion needed
//
// civil_month cm;
// fun(cm); // OK: implicit conversion to civil_day
//
// NORMALIZATION:
//
// Integer arguments passed to the constructor may be out-of-range, in which
// case they are normalized to produce a valid civil-time object. This enables
// natural arithmetic on constructor arguments without worrying about the
// field's range. Normalization guarantees that there are no invalid
// civil-time objects.
//
// civil_day d(2016, 10, 32); // Out-of-range day; normalized to 2016-11-01
//
// Note: If normalization is undesired, you can signal an error by comparing
// the constructor arguments to the normalized values returned by the YMDHMS
// properties.
//
// PROPERTIES:
//
// All civil-time types have accessors for all six of the civil-time fields:
// year, month, day, hour, minute, and second. Recall that fields inferior to
// the type's alignment will be set to their minimum valid value.
//
// civil_day d(2015, 6, 28);
// // d.year() == 2015
// // d.month() == 6
// // d.day() == 28
// // d.hour() == 0
// // d.minute() == 0
// // d.second() == 0
//
// COMPARISON:
//
// Comparison always considers all six YMDHMS fields, regardless of the type's
// alignment. Comparison between differently aligned civil-time types is
// allowed.
//
// civil_day feb_3(2015, 2, 3); // 2015-02-03 00:00:00
// civil_day mar_4(2015, 3, 4); // 2015-03-04 00:00:00
// // feb_3 < mar_4
// // civil_year(feb_3) == civil_year(mar_4)
//
// civil_second feb_3_noon(2015, 2, 3, 12, 0, 0); // 2015-02-03 12:00:00
// // feb_3 < feb_3_noon
// // feb_3 == civil_day(feb_3_noon)
//
// // Iterates all the days of February 2015.
// for (civil_day d(2015, 2, 1); d < civil_month(2015, 3); ++d) {
// // ...
// }
//
// STREAMING:
//
// Each civil-time type may be sent to an output stream using operator<<().
// The output format follows the pattern "YYYY-MM-DDThh:mm:ss" where fields
// inferior to the type's alignment are omitted.
//
// civil_second cs(2015, 2, 3, 4, 5, 6);
// std::cout << cs << "\n"; // Outputs: 2015-02-03T04:05:06
//
// civil_day cd(cs);
// std::cout << cd << "\n"; // Outputs: 2015-02-03
//
// civil_year cy(cs);
// std::cout << cy << "\n"; // Outputs: 2015
//
// ARITHMETIC:
//
// Civil-time types support natural arithmetic operators such as addition,
// subtraction, and difference. Arithmetic operates on the civil-time field
// indicated in the type's name. Difference requires arguments with the same
// alignment and returns the answer in units of the alignment.
//
// civil_day a(2015, 2, 3);
// ++a; // 2015-02-04 00:00:00
// --a; // 2015-02-03 00:00:00
// civil_day b = a + 1; // 2015-02-04 00:00:00
// civil_day c = 1 + b; // 2015-02-05 00:00:00
// int n = c - a; // n = 2 (civil days)
// int m = c - civil_month(c); // Won't compile: different types.
//
// EXAMPLE: Adding a month to January 31.
//
// One of the classic questions that arises when considering a civil-time
// library (or a date library or a date/time library) is this: "What happens
// when you add a month to January 31?" This is an interesting question
// because there could be a number of possible answers:
//
// 1. March 3 (or 2 if a leap year). This may make sense if the operation
// wants the equivalent of February 31.
// 2. February 28 (or 29 if a leap year). This may make sense if the operation
// wants the last day of January to go to the last day of February.
// 3. Error. The caller may get some error, an exception, an invalid date
// object, or maybe false is returned. This may make sense because there is
// no single unambiguously correct answer to the question.
//
// Practically speaking, any answer that is not what the programmer intended
// is the wrong answer.
//
// This civil-time library avoids the problem by making it impossible to ask
// ambiguous questions. All civil-time objects are aligned to a particular
// civil-field boundary (such as aligned to a year, month, day, hour, minute,
// or second), and arithmetic operates on the field to which the object is
// aligned. This means that in order to "add a month" the object must first be
// aligned to a month boundary, which is equivalent to the first day of that
// month.
//
// Of course, there are ways to compute an answer the question at hand using
// this civil-time library, but they require the programmer to be explicit
// about the answer they expect. To illustrate, let's see how to compute all
// three of the above possible answers to the question of "Jan 31 plus 1
// month":
//
// const civil_day d(2015, 1, 31);
//
// // Answer 1:
// // Add 1 to the month field in the constructor, and rely on normalization.
// const auto ans_normalized = civil_day(d.year(), d.month() + 1, d.day());
// // ans_normalized == 2015-03-03 (aka Feb 31)
//
// // Answer 2:
// // Add 1 to month field, capping to the end of next month.
// const auto next_month = civil_month(d) + 1;
// const auto last_day_of_next_month = civil_day(next_month + 1) - 1;
// const auto ans_capped = std::min(ans_normalized, last_day_of_next_month);
// // ans_capped == 2015-02-28
//
// // Answer 3:
// // Signal an error if the normalized answer is not in next month.
// if (civil_month(ans_normalized) != next_month) {
// // error, month overflow
// }
//
using civil_year = detail::civil_year;
using civil_month = detail::civil_month;
using civil_day = detail::civil_day;
using civil_hour = detail::civil_hour;
using civil_minute = detail::civil_minute;
using civil_second = detail::civil_second;
// An enum class with members monday, tuesday, wednesday, thursday, friday,
// saturday, and sunday. These enum values may be sent to an output stream
// using operator<<(). The result is the full weekday name in English with a
// leading capital letter.
//
// weekday wd = weekday::thursday;
// std::cout << wd << "\n"; // Outputs: Thursday
//
using detail::weekday;
// Returns the weekday for the given civil-time value.
//
// civil_day a(2015, 8, 13);
// weekday wd = get_weekday(a); // wd == weekday::thursday
//
using detail::get_weekday;
// Returns the civil_day that strictly follows or precedes the given
// civil_day, and that falls on the given weekday.
//
// For example, given:
//
// August 2015
// Su Mo Tu We Th Fr Sa
// 1
// 2 3 4 5 6 7 8
// 9 10 11 12 13 14 15
// 16 17 18 19 20 21 22
// 23 24 25 26 27 28 29
// 30 31
//
// civil_day a(2015, 8, 13); // get_weekday(a) == weekday::thursday
// civil_day b = next_weekday(a, weekday::thursday); // b = 2015-08-20
// civil_day c = prev_weekday(a, weekday::thursday); // c = 2015-08-06
//
// civil_day d = ...
// // Gets the following Thursday if d is not already Thursday
// civil_day thurs1 = next_weekday(d - 1, weekday::thursday);
// // Gets the previous Thursday if d is not already Thursday
// civil_day thurs2 = prev_weekday(d + 1, weekday::thursday);
//
using detail::next_weekday;
using detail::prev_weekday;
// Returns the day-of-year for the given civil-time value.
//
// civil_day a(2015, 1, 1);
// int yd_jan_1 = get_yearday(a); // yd_jan_1 = 1
// civil_day b(2015, 12, 31);
// int yd_dec_31 = get_yearday(b); // yd_dec_31 = 365
//
using detail::get_yearday;
} // namespace cctz
} // namespace time_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_H_
*Þ×
ˆsoong/.intermediates/external/abseil-cpp/absl_strings_str_format_internal_hdrs/gen/my_include_dir/absl/strings/internal/str_format/arg.hÏÖ// Copyright 2020 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_
#define ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_
#include <string.h>
#include <wchar.h>
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <limits>
#include <memory>
#include <sstream>
#include <string>
#include <string_view>
#include <type_traits>
#include <utility>
#include "absl/base/config.h"
#include "absl/base/optimization.h"
#include "absl/meta/type_traits.h"
#include "absl/numeric/int128.h"
#include "absl/strings/has_absl_stringify.h"
#include "absl/strings/internal/str_format/extension.h"
#include "absl/strings/string_view.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
class Cord;
class FormatCountCapture;
class FormatSink;
template <absl::FormatConversionCharSet C>
struct FormatConvertResult;
class FormatConversionSpec;
namespace str_format_internal {
template <FormatConversionCharSet C>
struct ArgConvertResult {
bool value;
};
using IntegralConvertResult = ArgConvertResult<FormatConversionCharSetUnion(
FormatConversionCharSetInternal::c,
FormatConversionCharSetInternal::kNumeric,
FormatConversionCharSetInternal::kStar,
FormatConversionCharSetInternal::v)>;
using FloatingConvertResult = ArgConvertResult<FormatConversionCharSetUnion(
FormatConversionCharSetInternal::kFloating,
FormatConversionCharSetInternal::v)>;
using CharConvertResult = ArgConvertResult<FormatConversionCharSetUnion(
FormatConversionCharSetInternal::c,
FormatConversionCharSetInternal::kNumeric,
FormatConversionCharSetInternal::kStar)>;
template <typename T, typename = void>
struct HasUserDefinedConvert : std::false_type {};
template <typename T>
struct HasUserDefinedConvert<T, void_t<decltype(AbslFormatConvert(
std::declval<const T&>(),
std::declval<const FormatConversionSpec&>(),
std::declval<FormatSink*>()))>>
: std::true_type {};
// These declarations prevent ADL lookup from continuing in absl namespaces,
// we are deliberately using these as ADL hooks and want them to consider
// non-absl namespaces only.
void AbslFormatConvert();
void AbslStringify();
template <typename T>
bool ConvertIntArg(T v, FormatConversionSpecImpl conv, FormatSinkImpl* sink);
// Forward declarations of internal `ConvertIntArg` function template
// instantiations are here to avoid including the template body in the headers
// and instantiating it in large numbers of translation units. Explicit
// instantiations can be found in "absl/strings/internal/str_format/arg.cc"
extern template bool ConvertIntArg<char>(char v, FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
extern template bool ConvertIntArg<signed char>(signed char v,
FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
extern template bool ConvertIntArg<unsigned char>(unsigned char v,
FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
extern template bool ConvertIntArg<wchar_t>(wchar_t v,
FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
extern template bool ConvertIntArg<short>(short v, // NOLINT
FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
extern template bool ConvertIntArg<unsigned short>( // NOLINT
unsigned short v, FormatConversionSpecImpl conv, // NOLINT
FormatSinkImpl* sink);
extern template bool ConvertIntArg<int>(int v, FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
extern template bool ConvertIntArg<unsigned int>(unsigned int v,
FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
extern template bool ConvertIntArg<long>( // NOLINT
long v, FormatConversionSpecImpl conv, FormatSinkImpl* sink); // NOLINT
extern template bool ConvertIntArg<unsigned long>(unsigned long v, // NOLINT
FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
extern template bool ConvertIntArg<long long>(long long v, // NOLINT
FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
extern template bool ConvertIntArg<unsigned long long>( // NOLINT
unsigned long long v, FormatConversionSpecImpl conv, // NOLINT
FormatSinkImpl* sink);
template <typename T>
auto FormatConvertImpl(const T& v, FormatConversionSpecImpl conv,
FormatSinkImpl* sink)
-> decltype(AbslFormatConvert(v,
std::declval<const FormatConversionSpec&>(),
std::declval<FormatSink*>())) {
using FormatConversionSpecT =
absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatConversionSpec>;
using FormatSinkT =
absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatSink>;
auto fcs = conv.Wrap<FormatConversionSpecT>();
auto fs = sink->Wrap<FormatSinkT>();
return AbslFormatConvert(v, fcs, &fs);
}
template <typename T>
auto FormatConvertImpl(const T& v, FormatConversionSpecImpl conv,
FormatSinkImpl* sink)
-> std::enable_if_t<std::is_enum<T>::value &&
std::is_void<decltype(AbslStringify(
std::declval<FormatSink&>(), v))>::value,
IntegralConvertResult> {
if (conv.conversion_char() == FormatConversionCharInternal::v) {
using FormatSinkT =
absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatSink>;
auto fs = sink->Wrap<FormatSinkT>();
AbslStringify(fs, v);
return {true};
} else {
return {ConvertIntArg(
static_cast<typename std::underlying_type<T>::type>(v), conv, sink)};
}
}
template <typename T>
auto FormatConvertImpl(const T& v, FormatConversionSpecImpl,
FormatSinkImpl* sink)
-> std::enable_if_t<!std::is_enum<T>::value &&
!std::is_same<T, absl::Cord>::value &&
std::is_void<decltype(AbslStringify(
std::declval<FormatSink&>(), v))>::value,
ArgConvertResult<FormatConversionCharSetInternal::v>> {
using FormatSinkT =
absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatSink>;
auto fs = sink->Wrap<FormatSinkT>();
AbslStringify(fs, v);
return {true};
}
template <typename T>
class StreamedWrapper;
// If 'v' can be converted (in the printf sense) according to 'conv',
// then convert it, appending to `sink` and return `true`.
// Otherwise fail and return `false`.
// AbslFormatConvert(v, conv, sink) is intended to be found by ADL on 'v'
// as an extension mechanism. These FormatConvertImpl functions are the default
// implementations.
// The ADL search is augmented via the 'Sink*' parameter, which also
// serves as a disambiguator to reject possible unintended 'AbslFormatConvert'
// functions in the namespaces associated with 'v'.
// Raw pointers.
struct VoidPtr {
VoidPtr() = default;
template <typename T,
decltype(reinterpret_cast<uintptr_t>(std::declval<T*>())) = 0>
VoidPtr(T* ptr) // NOLINT
: value(ptr ? reinterpret_cast<uintptr_t>(ptr) : 0) {}
uintptr_t value;
};
template <FormatConversionCharSet C>
constexpr FormatConversionCharSet ExtractCharSet(FormatConvertResult<C>) {
return C;
}
template <FormatConversionCharSet C>
constexpr FormatConversionCharSet ExtractCharSet(ArgConvertResult<C>) {
return C;
}
ArgConvertResult<FormatConversionCharSetInternal::p> FormatConvertImpl(
VoidPtr v, FormatConversionSpecImpl conv, FormatSinkImpl* sink);
// Strings.
using StringConvertResult = ArgConvertResult<FormatConversionCharSetUnion(
FormatConversionCharSetInternal::s,
FormatConversionCharSetInternal::v)>;
StringConvertResult FormatConvertImpl(const std::string& v,
FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
StringConvertResult FormatConvertImpl(const std::wstring& v,
FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
StringConvertResult FormatConvertImpl(string_view v,
FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
StringConvertResult FormatConvertImpl(std::wstring_view v,
FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
#if !defined(ABSL_USES_STD_STRING_VIEW)
inline StringConvertResult FormatConvertImpl(std::string_view v,
FormatConversionSpecImpl conv,
FormatSinkImpl* sink) {
return FormatConvertImpl(absl::string_view(v.data(), v.size()), conv, sink);
}
#endif // !ABSL_USES_STD_STRING_VIEW
using StringPtrConvertResult = ArgConvertResult<FormatConversionCharSetUnion(
FormatConversionCharSetInternal::s,
FormatConversionCharSetInternal::p)>;
StringPtrConvertResult FormatConvertImpl(const char* v,
FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
StringPtrConvertResult FormatConvertImpl(const wchar_t* v,
FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
// This overload is needed to disambiguate, since `nullptr` could match either
// of the other overloads equally well.
StringPtrConvertResult FormatConvertImpl(std::nullptr_t,
FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
template <class AbslCord, typename std::enable_if<std::is_same<
AbslCord, absl::Cord>::value>::type* = nullptr>
StringConvertResult FormatConvertImpl(const AbslCord& value,
FormatConversionSpecImpl conv,
FormatSinkImpl* sink) {
bool is_left = conv.has_left_flag();
size_t space_remaining = 0;
int width = conv.width();
if (width >= 0) space_remaining = static_cast<size_t>(width);
size_t to_write = value.size();
int precision = conv.precision();
if (precision >= 0)
to_write = (std::min)(to_write, static_cast<size_t>(precision));
space_remaining = Excess(to_write, space_remaining);
if (space_remaining > 0 && !is_left) sink->Append(space_remaining, ' ');
for (string_view piece : value.Chunks()) {
if (piece.size() > to_write) {
piece.remove_suffix(piece.size() - to_write);
to_write = 0;
} else {
to_write -= piece.size();
}
sink->Append(piece);
if (to_write == 0) {
break;
}
}
if (space_remaining > 0 && is_left) sink->Append(space_remaining, ' ');
return {true};
}
bool ConvertBoolArg(bool v, FormatSinkImpl* sink);
// Floats.
FloatingConvertResult FormatConvertImpl(float v, FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
FloatingConvertResult FormatConvertImpl(double v, FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
FloatingConvertResult FormatConvertImpl(long double v,
FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
// Chars.
CharConvertResult FormatConvertImpl(char v, FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
CharConvertResult FormatConvertImpl(wchar_t v,
FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
// Ints.
IntegralConvertResult FormatConvertImpl(signed char v,
FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(unsigned char v,
FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(short v, // NOLINT
FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(unsigned short v, // NOLINT
FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(int v, FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(unsigned v,
FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(long v, // NOLINT
FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(unsigned long v, // NOLINT
FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(long long v, // NOLINT
FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(unsigned long long v, // NOLINT
FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(int128 v, FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(uint128 v,
FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
// This function needs to be a template due to ambiguity regarding type
// conversions.
template <typename T, enable_if_t<std::is_same<T, bool>::value, int> = 0>
IntegralConvertResult FormatConvertImpl(T v, FormatConversionSpecImpl conv,
FormatSinkImpl* sink) {
if (conv.conversion_char() == FormatConversionCharInternal::v) {
return {ConvertBoolArg(v, sink)};
}
return FormatConvertImpl(static_cast<int>(v), conv, sink);
}
// We provide this function to help the checker, but it is never defined.
// FormatArgImpl will use the underlying Convert functions instead.
template <typename T>
typename std::enable_if<std::is_enum<T>::value &&
!HasUserDefinedConvert<T>::value &&
!HasAbslStringify<T>::value,
IntegralConvertResult>::type
FormatConvertImpl(T v, FormatConversionSpecImpl conv, FormatSinkImpl* sink);
template <typename T>
StringConvertResult FormatConvertImpl(const StreamedWrapper<T>& v,
FormatConversionSpecImpl conv,
FormatSinkImpl* out) {
std::ostringstream oss;
oss << v.v_;
if (!oss) return {false};
return str_format_internal::FormatConvertImpl(oss.str(), conv, out);
}
// Use templates and dependent types to delay evaluation of the function
// until after FormatCountCapture is fully defined.
struct FormatCountCaptureHelper {
template <class T = int>
static ArgConvertResult<FormatConversionCharSetInternal::n> ConvertHelper(
const FormatCountCapture& v, FormatConversionSpecImpl conv,
FormatSinkImpl* sink) {
const absl::enable_if_t<sizeof(T) != 0, FormatCountCapture>& v2 = v;
if (conv.conversion_char() !=
str_format_internal::FormatConversionCharInternal::n) {
return {false};
}
*v2.p_ = static_cast<int>(sink->size());
return {true};
}
};
template <class T = int>
ArgConvertResult<FormatConversionCharSetInternal::n> FormatConvertImpl(
const FormatCountCapture& v, FormatConversionSpecImpl conv,
FormatSinkImpl* sink) {
return FormatCountCaptureHelper::ConvertHelper(v, conv, sink);
}
// Helper friend struct to hide implementation details from the public API of
// FormatArgImpl.
struct FormatArgImplFriend {
template <typename Arg>
static bool ToInt(Arg arg, int* out) {
// A value initialized FormatConversionSpecImpl has a `none` conv, which
// tells the dispatcher to run the `int` conversion.
return arg.dispatcher_(arg.data_, {}, out);
}
template <typename Arg>
static bool Convert(Arg arg, FormatConversionSpecImpl conv,
FormatSinkImpl* out) {
return arg.dispatcher_(arg.data_, conv, out);
}
template <typename Arg>
static typename Arg::Dispatcher GetVTablePtrForTest(Arg arg) {
return arg.dispatcher_;
}
};
template <typename Arg>
constexpr FormatConversionCharSet ArgumentToConv() {
using ConvResult = decltype(str_format_internal::FormatConvertImpl(
std::declval<const Arg&>(),
std::declval<const FormatConversionSpecImpl&>(),
std::declval<FormatSinkImpl*>()));
return absl::str_format_internal::ExtractCharSet(ConvResult{});
}
// A type-erased handle to a format argument.
class FormatArgImpl {
private:
enum { kInlinedSpace = 8 };
using VoidPtr = str_format_internal::VoidPtr;
union Data {
const void* ptr;
const volatile void* volatile_ptr;
char buf[kInlinedSpace];
};
using Dispatcher = bool (*)(Data, FormatConversionSpecImpl, void* out);
template <typename T>
struct store_by_value
: std::integral_constant<bool, (sizeof(T) <= kInlinedSpace) &&
(std::is_integral<T>::value ||
std::is_floating_point<T>::value ||
std::is_pointer<T>::value ||
std::is_same<VoidPtr, T>::value)> {};
enum StoragePolicy { ByPointer, ByVolatilePointer, ByValue };
template <typename T>
struct storage_policy
: std::integral_constant<StoragePolicy,
(std::is_volatile<T>::value
? ByVolatilePointer
: (store_by_value<T>::value ? ByValue
: ByPointer))> {
};
// To reduce the number of vtables we will decay values before hand.
// Anything with a user-defined Convert will get its own vtable.
// For everything else:
// - Decay char* and char arrays into `const char*`
// - Decay wchar_t* and wchar_t arrays into `const wchar_t*`
// - Decay any other pointer to `const void*`
// - Decay all enums to the integral promotion of their underlying type.
// - Decay function pointers to void*.
template <typename T, typename = void>
struct DecayType {
static constexpr bool kHasUserDefined =
str_format_internal::HasUserDefinedConvert<T>::value ||
HasAbslStringify<T>::value;
using type = typename std::conditional<
!kHasUserDefined && std::is_convertible<T, const char*>::value,
const char*,
typename std::conditional<
!kHasUserDefined && std::is_convertible<T, const wchar_t*>::value,
const wchar_t*,
typename std::conditional<
!kHasUserDefined && std::is_convertible<T, VoidPtr>::value,
VoidPtr,
const T&>::type>::type>::type;
};
template <typename T>
struct DecayType<
T, typename std::enable_if<
!str_format_internal::HasUserDefinedConvert<T>::value &&
!HasAbslStringify<T>::value && std::is_enum<T>::value>::type> {
using type = decltype(+typename std::underlying_type<T>::type());
};
public:
template <typename T>
explicit FormatArgImpl(const T& value) {
using D = typename DecayType<T>::type;
static_assert(
std::is_same<D, const T&>::value || storage_policy<D>::value == ByValue,
"Decayed types must be stored by value");
Init(static_cast<D>(value));
}
private:
friend struct str_format_internal::FormatArgImplFriend;
template <typename T, StoragePolicy = storage_policy<T>::value>
struct Manager;
template <typename T>
struct Manager<T, ByPointer> {
static Data SetValue(const T& value) {
Data data;
data.ptr = std::addressof(value);
return data;
}
static const T& Value(Data arg) { return *static_cast<const T*>(arg.ptr); }
};
template <typename T>
struct Manager<T, ByVolatilePointer> {
static Data SetValue(const T& value) {
Data data;
data.volatile_ptr = &value;
return data;
}
static const T& Value(Data arg) {
return *static_cast<const T*>(arg.volatile_ptr);
}
};
template <typename T>
struct Manager<T, ByValue> {
static Data SetValue(const T& value) {
Data data;
memcpy(data.buf, &value, sizeof(value));
return data;
}
static T Value(Data arg) {
T value;
memcpy(&value, arg.buf, sizeof(T));
return value;
}
};
template <typename T>
void Init(const T& value) {
data_ = Manager<T>::SetValue(value);
dispatcher_ = &Dispatch<T>;
}
template <typename T>
static int ToIntVal(const T& val) {
using CommonType = typename std::conditional<std::is_signed<T>::value,
int64_t, uint64_t>::type;
if (static_cast<CommonType>(val) >
static_cast<CommonType>((std::numeric_limits<int>::max)())) {
return (std::numeric_limits<int>::max)();
} else if (std::is_signed<T>::value &&
static_cast<CommonType>(val) <
static_cast<CommonType>((std::numeric_limits<int>::min)())) {
return (std::numeric_limits<int>::min)();
}
return static_cast<int>(val);
}
template <typename T>
static bool ToInt(Data arg, int* out, std::true_type /* is_integral */,
std::false_type) {
*out = ToIntVal(Manager<T>::Value(arg));
return true;
}
template <typename T>
static bool ToInt(Data arg, int* out, std::false_type,
std::true_type /* is_enum */) {
*out = ToIntVal(static_cast<typename std::underlying_type<T>::type>(
Manager<T>::Value(arg)));
return true;
}
template <typename T>
static bool ToInt(Data, int*, std::false_type, std::false_type) {
return false;
}
template <typename T>
static bool Dispatch(Data arg, FormatConversionSpecImpl spec, void* out) {
// A `none` conv indicates that we want the `int` conversion.
if (ABSL_PREDICT_FALSE(spec.conversion_char() ==
FormatConversionCharInternal::kNone)) {
return ToInt<T>(arg, static_cast<int*>(out), std::is_integral<T>(),
std::is_enum<T>());
}
if (ABSL_PREDICT_FALSE(!Contains(ArgumentToConv<T>(),
spec.conversion_char()))) {
return false;
}
return str_format_internal::FormatConvertImpl(
Manager<T>::Value(arg), spec,
static_cast<FormatSinkImpl*>(out))
.value;
}
Data data_;
Dispatcher dispatcher_;
};
#define ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(T, E) \
E template bool FormatArgImpl::Dispatch<T>(Data, FormatConversionSpecImpl, \
void*)
#define ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_NO_WSTRING_VIEW_(...) \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(str_format_internal::VoidPtr, \
__VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(bool, __VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(char, __VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(signed char, __VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned char, __VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(short, __VA_ARGS__); /* NOLINT */ \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned short, /* NOLINT */ \
__VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(int, __VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned int, __VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long, __VA_ARGS__); /* NOLINT */ \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned long, /* NOLINT */ \
__VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long long, /* NOLINT */ \
__VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned long long, /* NOLINT */ \
__VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(int128, __VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(uint128, __VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(float, __VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(double, __VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long double, __VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(const char*, __VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(std::string, __VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(string_view, __VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(const wchar_t*, __VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(std::wstring, __VA_ARGS__)
#define ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(...) \
ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_NO_WSTRING_VIEW_( \
__VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(std::wstring_view, __VA_ARGS__)
ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(extern);
} // namespace str_format_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_
*ÏP
Œsoong/.intermediates/external/abseil-cpp/absl_strings_cord_internal_hdrs/gen/my_include_dir/absl/strings/internal/cord_rep_btree_navigator.h½O// Copyright 2021 The Abseil Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_STRINGS_INTERNAL_CORD_REP_BTREE_NAVIGATOR_H_
#define ABSL_STRINGS_INTERNAL_CORD_REP_BTREE_NAVIGATOR_H_
#include <cassert>
#include <iostream>
#include "absl/strings/internal/cord_internal.h"
#include "absl/strings/internal/cord_rep_btree.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace cord_internal {
// CordRepBtreeNavigator is a bi-directional navigator allowing callers to
// navigate all the (leaf) data edges in a CordRepBtree instance.
//
// A CordRepBtreeNavigator instance is by default empty. Callers initialize a
// navigator instance by calling one of `InitFirst()`, `InitLast()` or
// `InitOffset()`, which establishes a current position. Callers can then
// navigate using the `Next`, `Previous`, `Skip` and `Seek` methods.
//
// The navigator instance does not take or adopt a reference on the provided
// `tree` on any of the initialization calls. Callers are responsible for
// guaranteeing the lifecycle of the provided tree. A navigator instance can
// be reset to the empty state by calling `Reset`.
//
// A navigator only keeps positional state on the 'current data edge', it does
// explicitly not keep any 'offset' state. The class does accept and return
// offsets in the `Read()`, `Skip()` and 'Seek()` methods as these would
// otherwise put a big burden on callers. Callers are expected to maintain
// (returned) offset info if they require such granular state.
class CordRepBtreeNavigator {
public:
// The logical position as returned by the Seek() and Skip() functions.
// Returns the current leaf edge for the desired seek or skip position and
// the offset of that position inside that edge.
struct Position {
CordRep* edge;
size_t offset;
};
// The read result as returned by the Read() function.
// `tree` contains the resulting tree which is identical to the result
// of calling CordRepBtree::SubTree(...) on the tree being navigated.
// `n` contains the number of bytes used from the last navigated to
// edge of the tree.
struct ReadResult {
CordRep* tree;
size_t n;
};
// Returns true if this instance is not empty.
explicit operator bool() const;
// Returns the tree for this instance or nullptr if empty.
CordRepBtree* btree() const;
// Returns the data edge of the current position.
// Requires this instance to not be empty.
CordRep* Current() const;
// Resets this navigator to `tree`, returning the first data edge in the tree.
CordRep* InitFirst(CordRepBtree* tree);
// Resets this navigator to `tree`, returning the last data edge in the tree.
CordRep* InitLast(CordRepBtree* tree);
// Resets this navigator to `tree` returning the data edge at position
// `offset` and the relative offset of `offset` into that data edge.
// Returns `Position.edge = nullptr` if the provided offset is greater
// than or equal to the length of the tree, in which case the state of
// the navigator instance remains unchanged.
Position InitOffset(CordRepBtree* tree, size_t offset);
// Navigates to the next data edge.
// Returns the next data edge or nullptr if there is no next data edge, in
// which case the current position remains unchanged.
CordRep* Next();
// Navigates to the previous data edge.
// Returns the previous data edge or nullptr if there is no previous data
// edge, in which case the current position remains unchanged.
CordRep* Previous();
// Navigates to the data edge at position `offset`. Returns the navigated to
// data edge in `Position.edge` and the relative offset of `offset` into that
// data edge in `Position.offset`. Returns `Position.edge = nullptr` if the
// provide offset is greater than or equal to the tree's length.
Position Seek(size_t offset);
// Reads `n` bytes of data starting at offset `edge_offset` of the current
// data edge, and returns the result in `ReadResult.tree`. `ReadResult.n`
// contains the 'bytes used` from the last / current data edge in the tree.
// This allows users that mix regular navigation (using string views) and
// 'read into cord' navigation to keep track of the current state, and which
// bytes have been consumed from a navigator.
// This function returns `ReadResult.tree = nullptr` if the requested length
// exceeds the length of the tree starting at the current data edge.
ReadResult Read(size_t edge_offset, size_t n);
// Skips `n` bytes forward from the current data edge, returning the navigated
// to data edge in `Position.edge` and `Position.offset` containing the offset
// inside that data edge. Note that the state of the navigator is left
// unchanged if `n` is smaller than the length of the current data edge.
Position Skip(size_t n);
// Resets this instance to the default / empty state.
void Reset();
private:
// Slow path for Next() if Next() reached the end of a leaf node. Backtracks
// up the stack until it finds a node that has a 'next' position available,
// and then does a 'front dive' towards the next leaf node.
CordRep* NextUp();
// Slow path for Previous() if Previous() reached the beginning of a leaf
// node. Backtracks up the stack until it finds a node that has a 'previous'
// position available, and then does a 'back dive' towards the previous leaf
// node.
CordRep* PreviousUp();
// Generic implementation of InitFirst() and InitLast().
template <CordRepBtree::EdgeType edge_type>
CordRep* Init(CordRepBtree* tree);
// `height_` contains the height of the current tree, or -1 if empty.
int height_ = -1;
// `index_` and `node_` contain the navigation state as the 'path' to the
// current data edge which is at `node_[0]->Edge(index_[0])`. The contents
// of these are undefined until the instance is initialized (`height_ >= 0`).
uint8_t index_[CordRepBtree::kMaxDepth];
CordRepBtree* node_[CordRepBtree::kMaxDepth];
};
// Returns true if this instance is not empty.
inline CordRepBtreeNavigator::operator bool() const { return height_ >= 0; }
inline CordRepBtree* CordRepBtreeNavigator::btree() const {
return height_ >= 0 ? node_[height_] : nullptr;
}
inline CordRep* CordRepBtreeNavigator::Current() const {
assert(height_ >= 0);
return node_[0]->Edge(index_[0]);
}
inline void CordRepBtreeNavigator::Reset() { height_ = -1; }
inline CordRep* CordRepBtreeNavigator::InitFirst(CordRepBtree* tree) {
return Init<CordRepBtree::kFront>(tree);
}
inline CordRep* CordRepBtreeNavigator::InitLast(CordRepBtree* tree) {
return Init<CordRepBtree::kBack>(tree);
}
template <CordRepBtree::EdgeType edge_type>
inline CordRep* CordRepBtreeNavigator::Init(CordRepBtree* tree) {
assert(tree != nullptr);
assert(tree->size() > 0);
assert(tree->height() <= CordRepBtree::kMaxHeight);
int height = height_ = tree->height();
size_t index = tree->index(edge_type);
node_[height] = tree;
index_[height] = static_cast<uint8_t>(index);
while (--height >= 0) {
tree = tree->Edge(index)->btree();
node_[height] = tree;
index = tree->index(edge_type);
index_[height] = static_cast<uint8_t>(index);
}
return node_[0]->Edge(index);
}
inline CordRepBtreeNavigator::Position CordRepBtreeNavigator::Seek(
size_t offset) {
assert(btree() != nullptr);
int height = height_;
CordRepBtree* edge = node_[height];
if (ABSL_PREDICT_FALSE(offset >= edge->length)) return {nullptr, 0};
CordRepBtree::Position index = edge->IndexOf(offset);
index_[height] = static_cast<uint8_t>(index.index);
while (--height >= 0) {
edge = edge->Edge(index.index)->btree();
node_[height] = edge;
index = edge->IndexOf(index.n);
index_[height] = static_cast<uint8_t>(index.index);
}
return {edge->Edge(index.index), index.n};
}
inline CordRepBtreeNavigator::Position CordRepBtreeNavigator::InitOffset(
CordRepBtree* tree, size_t offset) {
assert(tree != nullptr);
assert(tree->height() <= CordRepBtree::kMaxHeight);
if (ABSL_PREDICT_FALSE(offset >= tree->length)) return {nullptr, 0};
height_ = tree->height();
node_[height_] = tree;
return Seek(offset);
}
inline CordRep* CordRepBtreeNavigator::Next() {
CordRepBtree* edge = node_[0];
return index_[0] == edge->back() ? NextUp() : edge->Edge(++index_[0]);
}
inline CordRep* CordRepBtreeNavigator::Previous() {
CordRepBtree* edge = node_[0];
return index_[0] == edge->begin() ? PreviousUp() : edge->Edge(--index_[0]);
}
inline CordRep* CordRepBtreeNavigator::NextUp() {
assert(index_[0] == node_[0]->back());
CordRepBtree* edge;
size_t index;
int height = 0;
do {
if (++height > height_) return nullptr;
edge = node_[height];
index = index_[height] + 1;
} while (index == edge->end());
index_[height] = static_cast<uint8_t>(index);
do {
node_[--height] = edge = edge->Edge(index)->btree();
index_[height] = static_cast<uint8_t>(index = edge->begin());
} while (height > 0);
return edge->Edge(index);
}
inline CordRep* CordRepBtreeNavigator::PreviousUp() {
assert(index_[0] == node_[0]->begin());
CordRepBtree* edge;
size_t index;
int height = 0;
do {
if (++height > height_) return nullptr;
edge = node_[height];
index = index_[height];
} while (index == edge->begin());
index_[height] = static_cast<uint8_t>(--index);
do {
node_[--height] = edge = edge->Edge(index)->btree();
index_[height] = static_cast<uint8_t>(index = edge->back());
} while (height > 0);
return edge->Edge(index);
}
} // namespace cord_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_CORD_REP_BTREE_NAVIGATOR_H_
wsoong/.intermediates/external/abseil-cpp/absl_base_errno_saver_hdrs/gen/my_include_dir/absl/base/internal/errno_saver.h©
// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_BASE_INTERNAL_ERRNO_SAVER_H_
#define ABSL_BASE_INTERNAL_ERRNO_SAVER_H_
#include <cerrno>
#include "absl/base/config.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace base_internal {
// `ErrnoSaver` captures the value of `errno` upon construction and restores it
// upon deletion. It is used in low-level code and must be super fast. Do not
// add instrumentation, even in debug modes.
class ErrnoSaver {
public:
ErrnoSaver() : saved_errno_(errno) {}
~ErrnoSaver() { errno = saved_errno_; }
int operator()() const { return saved_errno_; }
private:
const int saved_errno_;
};
} // namespace base_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_INTERNAL_ERRNO_SAVER_H_
*¸A
|soong/.intermediates/external/abseil-cpp/absl_log_internal_check_impl_hdrs/gen/my_include_dir/absl/log/internal/check_impl.h·@// Copyright 2022 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_LOG_INTERNAL_CHECK_IMPL_H_
#define ABSL_LOG_INTERNAL_CHECK_IMPL_H_
#include "absl/base/optimization.h"
#include "absl/log/internal/check_op.h"
#include "absl/log/internal/conditions.h"
#include "absl/log/internal/log_message.h"
#include "absl/log/internal/strip.h"
// CHECK
#define ABSL_LOG_INTERNAL_CHECK_IMPL(condition, condition_text) \
ABSL_LOG_INTERNAL_CONDITION_FATAL(STATELESS, \
ABSL_PREDICT_FALSE(!(condition))) \
ABSL_LOG_INTERNAL_CHECK(condition_text).InternalStream()
#define ABSL_LOG_INTERNAL_QCHECK_IMPL(condition, condition_text) \
ABSL_LOG_INTERNAL_CONDITION_QFATAL(STATELESS, \
ABSL_PREDICT_FALSE(!(condition))) \
ABSL_LOG_INTERNAL_QCHECK(condition_text).InternalStream()
#define ABSL_LOG_INTERNAL_PCHECK_IMPL(condition, condition_text) \
ABSL_LOG_INTERNAL_CHECK_IMPL(condition, condition_text).WithPerror()
#ifndef NDEBUG
#define ABSL_LOG_INTERNAL_DCHECK_IMPL(condition, condition_text) \
ABSL_LOG_INTERNAL_CHECK_IMPL(condition, condition_text)
#else
#define ABSL_LOG_INTERNAL_DCHECK_IMPL(condition, condition_text) \
ABSL_LOG_INTERNAL_CHECK_IMPL(true || (condition), "true")
#endif
// CHECK_EQ
#define ABSL_LOG_INTERNAL_CHECK_EQ_IMPL(val1, val1_text, val2, val2_text) \
ABSL_LOG_INTERNAL_CHECK_OP(Check_EQ, ==, val1, val1_text, val2, val2_text)
#define ABSL_LOG_INTERNAL_CHECK_NE_IMPL(val1, val1_text, val2, val2_text) \
ABSL_LOG_INTERNAL_CHECK_OP(Check_NE, !=, val1, val1_text, val2, val2_text)
#define ABSL_LOG_INTERNAL_CHECK_LE_IMPL(val1, val1_text, val2, val2_text) \
ABSL_LOG_INTERNAL_CHECK_OP(Check_LE, <=, val1, val1_text, val2, val2_text)
#define ABSL_LOG_INTERNAL_CHECK_LT_IMPL(val1, val1_text, val2, val2_text) \
ABSL_LOG_INTERNAL_CHECK_OP(Check_LT, <, val1, val1_text, val2, val2_text)
#define ABSL_LOG_INTERNAL_CHECK_GE_IMPL(val1, val1_text, val2, val2_text) \
ABSL_LOG_INTERNAL_CHECK_OP(Check_GE, >=, val1, val1_text, val2, val2_text)
#define ABSL_LOG_INTERNAL_CHECK_GT_IMPL(val1, val1_text, val2, val2_text) \
ABSL_LOG_INTERNAL_CHECK_OP(Check_GT, >, val1, val1_text, val2, val2_text)
#define ABSL_LOG_INTERNAL_QCHECK_EQ_IMPL(val1, val1_text, val2, val2_text) \
ABSL_LOG_INTERNAL_QCHECK_OP(Check_EQ, ==, val1, val1_text, val2, val2_text)
#define ABSL_LOG_INTERNAL_QCHECK_NE_IMPL(val1, val1_text, val2, val2_text) \
ABSL_LOG_INTERNAL_QCHECK_OP(Check_NE, !=, val1, val1_text, val2, val2_text)
#define ABSL_LOG_INTERNAL_QCHECK_LE_IMPL(val1, val1_text, val2, val2_text) \
ABSL_LOG_INTERNAL_QCHECK_OP(Check_LE, <=, val1, val1_text, val2, val2_text)
#define ABSL_LOG_INTERNAL_QCHECK_LT_IMPL(val1, val1_text, val2, val2_text) \
ABSL_LOG_INTERNAL_QCHECK_OP(Check_LT, <, val1, val1_text, val2, val2_text)
#define ABSL_LOG_INTERNAL_QCHECK_GE_IMPL(val1, val1_text, val2, val2_text) \
ABSL_LOG_INTERNAL_QCHECK_OP(Check_GE, >=, val1, val1_text, val2, val2_text)
#define ABSL_LOG_INTERNAL_QCHECK_GT_IMPL(val1, val1_text, val2, val2_text) \
ABSL_LOG_INTERNAL_QCHECK_OP(Check_GT, >, val1, val1_text, val2, val2_text)
#ifndef NDEBUG
#define ABSL_LOG_INTERNAL_DCHECK_EQ_IMPL(val1, val1_text, val2, val2_text) \
ABSL_LOG_INTERNAL_CHECK_EQ_IMPL(val1, val1_text, val2, val2_text)
#define ABSL_LOG_INTERNAL_DCHECK_NE_IMPL(val1, val1_text, val2, val2_text) \
ABSL_LOG_INTERNAL_CHECK_NE_IMPL(val1, val1_text, val2, val2_text)
#define ABSL_LOG_INTERNAL_DCHECK_LE_IMPL(val1, val1_text, val2, val2_text) \
ABSL_LOG_INTERNAL_CHECK_LE_IMPL(val1, val1_text, val2, val2_text)
#define ABSL_LOG_INTERNAL_DCHECK_LT_IMPL(val1, val1_text, val2, val2_text) \
ABSL_LOG_INTERNAL_CHECK_LT_IMPL(val1, val1_text, val2, val2_text)
#define ABSL_LOG_INTERNAL_DCHECK_GE_IMPL(val1, val1_text, val2, val2_text) \
ABSL_LOG_INTERNAL_CHECK_GE_IMPL(val1, val1_text, val2, val2_text)
#define ABSL_LOG_INTERNAL_DCHECK_GT_IMPL(val1, val1_text, val2, val2_text) \
ABSL_LOG_INTERNAL_CHECK_GT_IMPL(val1, val1_text, val2, val2_text)
#else // ndef NDEBUG
#define ABSL_LOG_INTERNAL_DCHECK_EQ_IMPL(val1, val1_text, val2, val2_text) \
ABSL_LOG_INTERNAL_DCHECK_NOP(val1, val2)
#define ABSL_LOG_INTERNAL_DCHECK_NE_IMPL(val1, val1_text, val2, val2_text) \
ABSL_LOG_INTERNAL_DCHECK_NOP(val1, val2)
#define ABSL_LOG_INTERNAL_DCHECK_LE_IMPL(val1, val1_text, val2, val2_text) \
ABSL_LOG_INTERNAL_DCHECK_NOP(val1, val2)
#define ABSL_LOG_INTERNAL_DCHECK_LT_IMPL(val1, val1_text, val2, val2_text) \
ABSL_LOG_INTERNAL_DCHECK_NOP(val1, val2)
#define ABSL_LOG_INTERNAL_DCHECK_GE_IMPL(val1, val1_text, val2, val2_text) \
ABSL_LOG_INTERNAL_DCHECK_NOP(val1, val2)
#define ABSL_LOG_INTERNAL_DCHECK_GT_IMPL(val1, val1_text, val2, val2_text) \
ABSL_LOG_INTERNAL_DCHECK_NOP(val1, val2)
#endif // def NDEBUG
// CHECK_OK
#define ABSL_LOG_INTERNAL_CHECK_OK_IMPL(status, status_text) \
ABSL_LOG_INTERNAL_CHECK_OK(status, status_text)
#define ABSL_LOG_INTERNAL_QCHECK_OK_IMPL(status, status_text) \
ABSL_LOG_INTERNAL_QCHECK_OK(status, status_text)
#ifndef NDEBUG
#define ABSL_LOG_INTERNAL_DCHECK_OK_IMPL(status, status_text) \
ABSL_LOG_INTERNAL_CHECK_OK(status, status_text)
#else
#define ABSL_LOG_INTERNAL_DCHECK_OK_IMPL(status, status_text) \
ABSL_LOG_INTERNAL_DCHECK_NOP(status, nullptr)
#endif
// CHECK_STREQ
#define ABSL_LOG_INTERNAL_CHECK_STREQ_IMPL(s1, s1_text, s2, s2_text) \
ABSL_LOG_INTERNAL_CHECK_STROP(strcmp, ==, true, s1, s1_text, s2, s2_text)
#define ABSL_LOG_INTERNAL_CHECK_STRNE_IMPL(s1, s1_text, s2, s2_text) \
ABSL_LOG_INTERNAL_CHECK_STROP(strcmp, !=, false, s1, s1_text, s2, s2_text)
#define ABSL_LOG_INTERNAL_CHECK_STRCASEEQ_IMPL(s1, s1_text, s2, s2_text) \
ABSL_LOG_INTERNAL_CHECK_STROP(strcasecmp, ==, true, s1, s1_text, s2, s2_text)
#define ABSL_LOG_INTERNAL_CHECK_STRCASENE_IMPL(s1, s1_text, s2, s2_text) \
ABSL_LOG_INTERNAL_CHECK_STROP(strcasecmp, !=, false, s1, s1_text, s2, s2_text)
#define ABSL_LOG_INTERNAL_QCHECK_STREQ_IMPL(s1, s1_text, s2, s2_text) \
ABSL_LOG_INTERNAL_QCHECK_STROP(strcmp, ==, true, s1, s1_text, s2, s2_text)
#define ABSL_LOG_INTERNAL_QCHECK_STRNE_IMPL(s1, s1_text, s2, s2_text) \
ABSL_LOG_INTERNAL_QCHECK_STROP(strcmp, !=, false, s1, s1_text, s2, s2_text)
#define ABSL_LOG_INTERNAL_QCHECK_STRCASEEQ_IMPL(s1, s1_text, s2, s2_text) \
ABSL_LOG_INTERNAL_QCHECK_STROP(strcasecmp, ==, true, s1, s1_text, s2, s2_text)
#define ABSL_LOG_INTERNAL_QCHECK_STRCASENE_IMPL(s1, s1_text, s2, s2_text) \
ABSL_LOG_INTERNAL_QCHECK_STROP(strcasecmp, !=, false, s1, s1_text, s2, \
s2_text)
#ifndef NDEBUG
#define ABSL_LOG_INTERNAL_DCHECK_STREQ_IMPL(s1, s1_text, s2, s2_text) \
ABSL_LOG_INTERNAL_CHECK_STREQ_IMPL(s1, s1_text, s2, s2_text)
#define ABSL_LOG_INTERNAL_DCHECK_STRCASEEQ_IMPL(s1, s1_text, s2, s2_text) \
ABSL_LOG_INTERNAL_CHECK_STRCASEEQ_IMPL(s1, s1_text, s2, s2_text)
#define ABSL_LOG_INTERNAL_DCHECK_STRNE_IMPL(s1, s1_text, s2, s2_text) \
ABSL_LOG_INTERNAL_CHECK_STRNE_IMPL(s1, s1_text, s2, s2_text)
#define ABSL_LOG_INTERNAL_DCHECK_STRCASENE_IMPL(s1, s1_text, s2, s2_text) \
ABSL_LOG_INTERNAL_CHECK_STRCASENE_IMPL(s1, s1_text, s2, s2_text)
#else // ndef NDEBUG
#define ABSL_LOG_INTERNAL_DCHECK_STREQ_IMPL(s1, s1_text, s2, s2_text) \
ABSL_LOG_INTERNAL_DCHECK_NOP(s1, s2)
#define ABSL_LOG_INTERNAL_DCHECK_STRCASEEQ_IMPL(s1, s1_text, s2, s2_text) \
ABSL_LOG_INTERNAL_DCHECK_NOP(s1, s2)
#define ABSL_LOG_INTERNAL_DCHECK_STRNE_IMPL(s1, s1_text, s2, s2_text) \
ABSL_LOG_INTERNAL_DCHECK_NOP(s1, s2)
#define ABSL_LOG_INTERNAL_DCHECK_STRCASENE_IMPL(s1, s1_text, s2, s2_text) \
ABSL_LOG_INTERNAL_DCHECK_NOP(s1, s2)
#endif // def NDEBUG
#endif // ABSL_LOG_INTERNAL_CHECK_IMPL_H_
*³9
wsoong/.intermediates/external/abseil-cpp/absl_container_common_hdrs/gen/my_include_dir/absl/container/internal/common.h·8// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_CONTAINER_INTERNAL_COMMON_H_
#define ABSL_CONTAINER_INTERNAL_COMMON_H_
#include <cassert>
#include <type_traits>
#include "absl/meta/type_traits.h"
#include "absl/types/optional.h"
// TODO(b/402804213): Clean up these macros when no longer needed.
#define ABSL_INTERNAL_SINGLE_ARG(...) __VA_ARGS__
#define ABSL_INTERNAL_IF_true(if_satisfied, ...) if_satisfied
#define ABSL_INTERNAL_IF_false(if_satisfied, ...) __VA_ARGS__
#define ABSL_INTERNAL_IF_true_AND_true ABSL_INTERNAL_IF_true
#define ABSL_INTERNAL_IF_false_AND_false ABSL_INTERNAL_IF_false
#define ABSL_INTERNAL_IF_true_AND_false ABSL_INTERNAL_IF_false_AND_false
#define ABSL_INTERNAL_IF_false_AND_true ABSL_INTERNAL_IF_false_AND_false
#define ABSL_INTERNAL_IF_true_OR_true ABSL_INTERNAL_IF_true
#define ABSL_INTERNAL_IF_false_OR_false ABSL_INTERNAL_IF_false
#define ABSL_INTERNAL_IF_true_OR_false ABSL_INTERNAL_IF_true_OR_true
#define ABSL_INTERNAL_IF_false_OR_true ABSL_INTERNAL_IF_true_OR_true
#define ABSL_INTERNAL_IF_true_NOR_true ABSL_INTERNAL_IF_false_AND_false
#define ABSL_INTERNAL_IF_false_NOR_false ABSL_INTERNAL_IF_true_AND_true
#define ABSL_INTERNAL_IF_true_NOR_false ABSL_INTERNAL_IF_false_AND_true
#define ABSL_INTERNAL_IF_false_NOR_true ABSL_INTERNAL_IF_true_AND_false
#define ABSL_INTERNAL_COMMA ,
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace container_internal {
// TODO(b/402804213): Clean up these traits when no longer needed or
// deduplicate them with absl::functional_internal::EnableIf.
template <class Cond>
using EnableIf = std::enable_if_t<Cond::value, int>;
template <bool Value, class T>
using HasValue = std::conditional_t<Value, T, absl::negation<T>>;
template <class T>
struct IfRRef {
template <class Other>
using AddPtr = Other;
};
template <class T>
struct IfRRef<T&&> {
template <class Other>
using AddPtr = Other*;
};
template <class, class = void>
struct IsTransparent : std::false_type {};
template <class T>
struct IsTransparent<T, absl::void_t<typename T::is_transparent>>
: std::true_type {};
template <bool is_transparent>
struct KeyArg {
// Transparent. Forward `K`.
template <typename K, typename key_type>
using type = K;
};
template <>
struct KeyArg<false> {
// Not transparent. Always use `key_type`.
template <typename K, typename key_type>
using type = key_type;
};
// The node_handle concept from C++17.
// We specialize node_handle for sets and maps. node_handle_base holds the
// common API of both.
template <typename PolicyTraits, typename Alloc>
class node_handle_base {
protected:
using slot_type = typename PolicyTraits::slot_type;
public:
using allocator_type = Alloc;
constexpr node_handle_base() = default;
node_handle_base(node_handle_base&& other) noexcept {
*this = std::move(other);
}
~node_handle_base() { destroy(); }
node_handle_base& operator=(node_handle_base&& other) noexcept {
destroy();
if (!other.empty()) {
alloc_ = other.alloc_;
PolicyTraits::transfer(alloc(), slot(), other.slot());
other.reset();
}
return *this;
}
bool empty() const noexcept { return !alloc_; }
explicit operator bool() const noexcept { return !empty(); }
allocator_type get_allocator() const { return *alloc_; }
protected:
friend struct CommonAccess;
struct transfer_tag_t {};
node_handle_base(transfer_tag_t, const allocator_type& a, slot_type* s)
: alloc_(a) {
PolicyTraits::transfer(alloc(), slot(), s);
}
struct construct_tag_t {};
template <typename... Args>
node_handle_base(construct_tag_t, const allocator_type& a, Args&&... args)
: alloc_(a) {
PolicyTraits::construct(alloc(), slot(), std::forward<Args>(args)...);
}
void destroy() {
if (!empty()) {
PolicyTraits::destroy(alloc(), slot());
reset();
}
}
void reset() {
assert(alloc_.has_value());
alloc_ = absl::nullopt;
}
slot_type* slot() const {
assert(!empty());
return reinterpret_cast<slot_type*>(std::addressof(slot_space_));
}
allocator_type* alloc() { return std::addressof(*alloc_); }
private:
absl::optional<allocator_type> alloc_ = {};
alignas(slot_type) mutable unsigned char slot_space_[sizeof(slot_type)] = {};
};
// For sets.
template <typename Policy, typename PolicyTraits, typename Alloc,
typename = void>
class node_handle : public node_handle_base<PolicyTraits, Alloc> {
using Base = node_handle_base<PolicyTraits, Alloc>;
public:
using value_type = typename PolicyTraits::value_type;
constexpr node_handle() {}
value_type& value() const { return PolicyTraits::element(this->slot()); }
private:
friend struct CommonAccess;
using Base::Base;
};
// For maps.
template <typename Policy, typename PolicyTraits, typename Alloc>
class node_handle<Policy, PolicyTraits, Alloc,
absl::void_t<typename Policy::mapped_type>>
: public node_handle_base<PolicyTraits, Alloc> {
using Base = node_handle_base<PolicyTraits, Alloc>;
using slot_type = typename PolicyTraits::slot_type;
public:
using key_type = typename Policy::key_type;
using mapped_type = typename Policy::mapped_type;
constexpr node_handle() {}
// When C++17 is available, we can use std::launder to provide mutable
// access to the key. Otherwise, we provide const access.
auto key() const
-> decltype(PolicyTraits::mutable_key(std::declval<slot_type*>())) {
return PolicyTraits::mutable_key(this->slot());
}
mapped_type& mapped() const {
return PolicyTraits::value(&PolicyTraits::element(this->slot()));
}
private:
friend struct CommonAccess;
using Base::Base;
};
// Provide access to non-public node-handle functions.
struct CommonAccess {
template <typename Node>
static auto GetSlot(const Node& node) -> decltype(node.slot()) {
return node.slot();
}
template <typename Node>
static void Destroy(Node* node) {
node->destroy();
}
template <typename Node>
static void Reset(Node* node) {
node->reset();
}
template <typename T, typename... Args>
static T Transfer(Args&&... args) {
return T(typename T::transfer_tag_t{}, std::forward<Args>(args)...);
}
template <typename T, typename... Args>
static T Construct(Args&&... args) {
return T(typename T::construct_tag_t{}, std::forward<Args>(args)...);
}
};
// Implement the insert_return_type<> concept of C++17.
template <class Iterator, class NodeType>
struct InsertReturnType {
Iterator position;
bool inserted;
NodeType node;
};
} // namespace container_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_CONTAINER_INTERNAL_COMMON_H_
*ˆ
‡soong/.intermediates/external/abseil-cpp/absl_strings_cordz_statistics_hdrs/gen/my_include_dir/absl/strings/internal/cordz_statistics.hû// Copyright 2019 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_STRINGS_INTERNAL_CORDZ_STATISTICS_H_
#define ABSL_STRINGS_INTERNAL_CORDZ_STATISTICS_H_
#include <cstdint>
#include "absl/base/config.h"
#include "absl/strings/internal/cordz_update_tracker.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace cord_internal {
// CordzStatistics captures some meta information about a Cord's shape.
struct CordzStatistics {
using MethodIdentifier = CordzUpdateTracker::MethodIdentifier;
// Node counts information
struct NodeCounts {
size_t flat = 0; // #flats
size_t flat_64 = 0; // #flats up to 64 bytes
size_t flat_128 = 0; // #flats up to 128 bytes
size_t flat_256 = 0; // #flats up to 256 bytes
size_t flat_512 = 0; // #flats up to 512 bytes
size_t flat_1k = 0; // #flats up to 1K bytes
size_t external = 0; // #external reps
size_t substring = 0; // #substring reps
size_t concat = 0; // #concat reps
size_t ring = 0; // #ring buffer reps
size_t btree = 0; // #btree reps
size_t crc = 0; // #crc reps
};
// The size of the cord in bytes. This matches the result of Cord::size().
size_t size = 0;
// The estimated memory used by the sampled cord. This value matches the
// value as reported by Cord::EstimatedMemoryUsage().
// A value of 0 implies the property has not been recorded.
size_t estimated_memory_usage = 0;
// The effective memory used by the sampled cord, inversely weighted by the
// effective indegree of each allocated node. This is a representation of the
// fair share of memory usage that should be attributed to the sampled cord.
// This value is more useful for cases where one or more nodes are referenced
// by multiple Cord instances, and for cases where a Cord includes the same
// node multiple times (either directly or indirectly).
// A value of 0 implies the property has not been recorded.
size_t estimated_fair_share_memory_usage = 0;
// The total number of nodes referenced by this cord.
// For ring buffer Cords, this includes the 'ring buffer' node.
// For btree Cords, this includes all 'CordRepBtree' tree nodes as well as all
// the substring, flat and external nodes referenced by the tree.
// A value of 0 implies the property has not been recorded.
size_t node_count = 0;
// Detailed node counts per type
NodeCounts node_counts;
// The cord method responsible for sampling the cord.
MethodIdentifier method = MethodIdentifier::kUnknown;
// The cord method responsible for sampling the parent cord if applicable.
MethodIdentifier parent_method = MethodIdentifier::kUnknown;
// Update tracker tracking invocation count per cord method.
CordzUpdateTracker update_tracker;
};
} // namespace cord_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_CORDZ_STATISTICS_H_
*õ¦
usoong/.intermediates/external/abseil-cpp/absl_container_btree_hdrs/gen/my_include_dir/absl/container/internal/btree.hú¥// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// A btree implementation of the STL set and map interfaces. A btree is smaller
// and generally also faster than STL set/map (refer to the benchmarks below).
// The red-black tree implementation of STL set/map has an overhead of 3
// pointers (left, right and parent) plus the node color information for each
// stored value. So a set<int32_t> consumes 40 bytes for each value stored in
// 64-bit mode. This btree implementation stores multiple values on fixed
// size nodes (usually 256 bytes) and doesn't store child pointers for leaf
// nodes. The result is that a btree_set<int32_t> may use much less memory per
// stored value. For the random insertion benchmark in btree_bench.cc, a
// btree_set<int32_t> with node-size of 256 uses 5.1 bytes per stored value.
//
// The packing of multiple values on to each node of a btree has another effect
// besides better space utilization: better cache locality due to fewer cache
// lines being accessed. Better cache locality translates into faster
// operations.
//
// CAVEATS
//
// Insertions and deletions on a btree can cause splitting, merging or
// rebalancing of btree nodes. And even without these operations, insertions
// and deletions on a btree will move values around within a node. In both
// cases, the result is that insertions and deletions can invalidate iterators
// pointing to values other than the one being inserted/deleted. Therefore, this
// container does not provide pointer stability. This is notably different from
// STL set/map which takes care to not invalidate iterators on insert/erase
// except, of course, for iterators pointing to the value being erased. A
// partial workaround when erasing is available: erase() returns an iterator
// pointing to the item just after the one that was erased (or end() if none
// exists).
#ifndef ABSL_CONTAINER_INTERNAL_BTREE_H_
#define ABSL_CONTAINER_INTERNAL_BTREE_H_
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <functional>
#include <iterator>
#include <limits>
#include <string>
#include <type_traits>
#include <utility>
#include "absl/base/config.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/base/macros.h"
#include "absl/base/optimization.h"
#include "absl/container/internal/common.h"
#include "absl/container/internal/common_policy_traits.h"
#include "absl/container/internal/compressed_tuple.h"
#include "absl/container/internal/container_memory.h"
#include "absl/container/internal/layout.h"
#include "absl/memory/memory.h"
#include "absl/meta/type_traits.h"
#include "absl/strings/cord.h"
#include "absl/strings/string_view.h"
#include "absl/types/compare.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace container_internal {
#ifdef ABSL_BTREE_ENABLE_GENERATIONS
#error ABSL_BTREE_ENABLE_GENERATIONS cannot be directly set
#elif (defined(ABSL_HAVE_ADDRESS_SANITIZER) || \
defined(ABSL_HAVE_HWADDRESS_SANITIZER) || \
defined(ABSL_HAVE_MEMORY_SANITIZER)) && \
!defined(NDEBUG_SANITIZER) // If defined, performance is important.
// When compiled in sanitizer mode, we add generation integers to the nodes and
// iterators. When iterators are used, we validate that the container has not
// been mutated since the iterator was constructed.
#define ABSL_BTREE_ENABLE_GENERATIONS
#endif
#ifdef ABSL_BTREE_ENABLE_GENERATIONS
constexpr bool BtreeGenerationsEnabled() { return true; }
#else
constexpr bool BtreeGenerationsEnabled() { return false; }
#endif
template <typename Compare, typename T, typename U>
using compare_result_t = absl::result_of_t<const Compare(const T &, const U &)>;
// A helper class that indicates if the Compare parameter is a key-compare-to
// comparator.
template <typename Compare, typename T>
using btree_is_key_compare_to =
std::is_convertible<compare_result_t<Compare, T, T>, absl::weak_ordering>;
struct StringBtreeDefaultLess {
using is_transparent = void;
StringBtreeDefaultLess() = default;
// Compatibility constructor.
StringBtreeDefaultLess(std::less<std::string>) {} // NOLINT
StringBtreeDefaultLess(std::less<absl::string_view>) {} // NOLINT
// Allow converting to std::less for use in key_comp()/value_comp().
explicit operator std::less<std::string>() const { return {}; }
explicit operator std::less<absl::string_view>() const { return {}; }
explicit operator std::less<absl::Cord>() const { return {}; }
absl::weak_ordering operator()(absl::string_view lhs,
absl::string_view rhs) const {
return compare_internal::compare_result_as_ordering(lhs.compare(rhs));
}
StringBtreeDefaultLess(std::less<absl::Cord>) {} // NOLINT
absl::weak_ordering operator()(const absl::Cord &lhs,
const absl::Cord &rhs) const {
return compare_internal::compare_result_as_ordering(lhs.Compare(rhs));
}
absl::weak_ordering operator()(const absl::Cord &lhs,
absl::string_view rhs) const {
return compare_internal::compare_result_as_ordering(lhs.Compare(rhs));
}
absl::weak_ordering operator()(absl::string_view lhs,
const absl::Cord &rhs) const {
return compare_internal::compare_result_as_ordering(-rhs.Compare(lhs));
}
};
struct StringBtreeDefaultGreater {
using is_transparent = void;
StringBtreeDefaultGreater() = default;
StringBtreeDefaultGreater(std::greater<std::string>) {} // NOLINT
StringBtreeDefaultGreater(std::greater<absl::string_view>) {} // NOLINT
// Allow converting to std::greater for use in key_comp()/value_comp().
explicit operator std::greater<std::string>() const { return {}; }
explicit operator std::greater<absl::string_view>() const { return {}; }
explicit operator std::greater<absl::Cord>() const { return {}; }
absl::weak_ordering operator()(absl::string_view lhs,
absl::string_view rhs) const {
return compare_internal::compare_result_as_ordering(rhs.compare(lhs));
}
StringBtreeDefaultGreater(std::greater<absl::Cord>) {} // NOLINT
absl::weak_ordering operator()(const absl::Cord &lhs,
const absl::Cord &rhs) const {
return compare_internal::compare_result_as_ordering(rhs.Compare(lhs));
}
absl::weak_ordering operator()(const absl::Cord &lhs,
absl::string_view rhs) const {
return compare_internal::compare_result_as_ordering(-lhs.Compare(rhs));
}
absl::weak_ordering operator()(absl::string_view lhs,
const absl::Cord &rhs) const {
return compare_internal::compare_result_as_ordering(rhs.Compare(lhs));
}
};
// See below comments for checked_compare.
template <typename Compare, bool is_class = std::is_class<Compare>::value>
struct checked_compare_base : Compare {
using Compare::Compare;
explicit checked_compare_base(Compare c) : Compare(std::move(c)) {}
const Compare &comp() const { return *this; }
};
template <typename Compare>
struct checked_compare_base<Compare, false> {
explicit checked_compare_base(Compare c) : compare(std::move(c)) {}
const Compare &comp() const { return compare; }
Compare compare;
};
// A mechanism for opting out of checked_compare for use only in btree_test.cc.
struct BtreeTestOnlyCheckedCompareOptOutBase {};
// A helper class to adapt the specified comparator for two use cases:
// (1) When using common Abseil string types with common comparison functors,
// convert a boolean comparison into a three-way comparison that returns an
// `absl::weak_ordering`. This helper class is specialized for
// less<std::string>, greater<std::string>, less<string_view>,
// greater<string_view>, less<absl::Cord>, and greater<absl::Cord>.
// (2) Adapt the comparator to diagnose cases of non-strict-weak-ordering (see
// https://en.cppreference.com/w/cpp/named_req/Compare) in debug mode. Whenever
// a comparison is made, we will make assertions to verify that the comparator
// is valid.
template <typename Compare, typename Key>
struct key_compare_adapter {
// Inherit from checked_compare_base to support function pointers and also
// keep empty-base-optimization (EBO) support for classes.
// Note: we can't use CompressedTuple here because that would interfere
// with the EBO for `btree::rightmost_`. `btree::rightmost_` is itself a
// CompressedTuple and nested `CompressedTuple`s don't support EBO.
// TODO(b/214288561): use CompressedTuple instead once it supports EBO for
// nested `CompressedTuple`s.
struct checked_compare : checked_compare_base<Compare> {
private:
using Base = typename checked_compare::checked_compare_base;
using Base::comp;
// If possible, returns whether `t` is equivalent to itself. We can only do
// this for `Key`s because we can't be sure that it's safe to call
// `comp()(k, k)` otherwise. Even if SFINAE allows it, there could be a
// compilation failure inside the implementation of the comparison operator.
bool is_self_equivalent(const Key &k) const {
// Note: this works for both boolean and three-way comparators.
return comp()(k, k) == 0;
}
// If we can't compare `t` with itself, returns true unconditionally.
template <typename T>
bool is_self_equivalent(const T &) const {
return true;
}
public:
using Base::Base;
checked_compare(Compare cmp) : Base(std::move(cmp)) {} // NOLINT
// Allow converting to Compare for use in key_comp()/value_comp().
explicit operator Compare() const { return comp(); }
template <typename T, typename U,
absl::enable_if_t<
std::is_same<bool, compare_result_t<Compare, T, U>>::value,
int> = 0>
bool operator()(const T &lhs, const U &rhs) const {
// NOTE: if any of these assertions fail, then the comparator does not
// establish a strict-weak-ordering (see
// https://en.cppreference.com/w/cpp/named_req/Compare).
assert(is_self_equivalent(lhs));
assert(is_self_equivalent(rhs));
const bool lhs_comp_rhs = comp()(lhs, rhs);
assert(!lhs_comp_rhs || !comp()(rhs, lhs));
return lhs_comp_rhs;
}
template <
typename T, typename U,
absl::enable_if_t<std::is_convertible<compare_result_t<Compare, T, U>,
absl::weak_ordering>::value,
int> = 0>
absl::weak_ordering operator()(const T &lhs, const U &rhs) const {
// NOTE: if any of these assertions fail, then the comparator does not
// establish a strict-weak-ordering (see
// https://en.cppreference.com/w/cpp/named_req/Compare).
assert(is_self_equivalent(lhs));
assert(is_self_equivalent(rhs));
const absl::weak_ordering lhs_comp_rhs = comp()(lhs, rhs);
#ifndef NDEBUG
const absl::weak_ordering rhs_comp_lhs = comp()(rhs, lhs);
if (lhs_comp_rhs > 0) {
assert(rhs_comp_lhs < 0 && "lhs_comp_rhs > 0 -> rhs_comp_lhs < 0");
} else if (lhs_comp_rhs == 0) {
assert(rhs_comp_lhs == 0 && "lhs_comp_rhs == 0 -> rhs_comp_lhs == 0");
} else {
assert(rhs_comp_lhs > 0 && "lhs_comp_rhs < 0 -> rhs_comp_lhs > 0");
}
#endif
return lhs_comp_rhs;
}
};
using type = absl::conditional_t<
std::is_base_of<BtreeTestOnlyCheckedCompareOptOutBase, Compare>::value,
Compare, checked_compare>;
};
template <>
struct key_compare_adapter<std::less<std::string>, std::string> {
using type = StringBtreeDefaultLess;
};
template <>
struct key_compare_adapter<std::greater<std::string>, std::string> {
using type = StringBtreeDefaultGreater;
};
template <>
struct key_compare_adapter<std::less<absl::string_view>, absl::string_view> {
using type = StringBtreeDefaultLess;
};
template <>
struct key_compare_adapter<std::greater<absl::string_view>, absl::string_view> {
using type = StringBtreeDefaultGreater;
};
template <>
struct key_compare_adapter<std::less<absl::Cord>, absl::Cord> {
using type = StringBtreeDefaultLess;
};
template <>
struct key_compare_adapter<std::greater<absl::Cord>, absl::Cord> {
using type = StringBtreeDefaultGreater;
};
// Detects an 'absl_btree_prefer_linear_node_search' member. This is
// a protocol used as an opt-in or opt-out of linear search.
//
// For example, this would be useful for key types that wrap an integer
// and define their own cheap operator<(). For example:
//
// class K {
// public:
// using absl_btree_prefer_linear_node_search = std::true_type;
// ...
// private:
// friend bool operator<(K a, K b) { return a.k_ < b.k_; }
// int k_;
// };
//
// btree_map<K, V> m; // Uses linear search
//
// If T has the preference tag, then it has a preference.
// Btree will use the tag's truth value.
template <typename T, typename = void>
struct has_linear_node_search_preference : std::false_type {};
template <typename T, typename = void>
struct prefers_linear_node_search : std::false_type {};
template <typename T>
struct has_linear_node_search_preference<
T, absl::void_t<typename T::absl_btree_prefer_linear_node_search>>
: std::true_type {};
template <typename T>
struct prefers_linear_node_search<
T, absl::void_t<typename T::absl_btree_prefer_linear_node_search>>
: T::absl_btree_prefer_linear_node_search {};
template <typename Compare, typename Key>
constexpr bool compare_has_valid_result_type() {
using compare_result_type = compare_result_t<Compare, Key, Key>;
return std::is_same<compare_result_type, bool>::value ||
std::is_convertible<compare_result_type, absl::weak_ordering>::value;
}
template <typename original_key_compare, typename value_type>
class map_value_compare {
template <typename Params>
friend class btree;
// Note: this `protected` is part of the API of std::map::value_compare. See
// https://en.cppreference.com/w/cpp/container/map/value_compare.
protected:
explicit map_value_compare(original_key_compare c) : comp(std::move(c)) {}
original_key_compare comp; // NOLINT
public:
auto operator()(const value_type &lhs, const value_type &rhs) const
-> decltype(comp(lhs.first, rhs.first)) {
return comp(lhs.first, rhs.first);
}
};
template <typename Key, typename Compare, typename Alloc, int TargetNodeSize,
bool IsMulti, bool IsMap, typename SlotPolicy>
struct common_params : common_policy_traits<SlotPolicy> {
using original_key_compare = Compare;
// If Compare is a common comparator for a string-like type, then we adapt it
// to use heterogeneous lookup and to be a key-compare-to comparator.
// We also adapt the comparator to diagnose invalid comparators in debug mode.
// We disable this when `Compare` is invalid in a way that will cause
// adaptation to fail (having invalid return type) so that we can give a
// better compilation failure in static_assert_validation. If we don't do
// this, then there will be cascading compilation failures that are confusing
// for users.
using key_compare =
absl::conditional_t<!compare_has_valid_result_type<Compare, Key>(),
Compare,
typename key_compare_adapter<Compare, Key>::type>;
static constexpr bool kIsKeyCompareStringAdapted =
std::is_same<key_compare, StringBtreeDefaultLess>::value ||
std::is_same<key_compare, StringBtreeDefaultGreater>::value;
static constexpr bool kIsKeyCompareTransparent =
IsTransparent<original_key_compare>::value || kIsKeyCompareStringAdapted;
// A type which indicates if we have a key-compare-to functor or a plain old
// key-compare functor.
using is_key_compare_to = btree_is_key_compare_to<key_compare, Key>;
using allocator_type = Alloc;
using key_type = Key;
using size_type = size_t;
using difference_type = ptrdiff_t;
using slot_policy = SlotPolicy;
using slot_type = typename slot_policy::slot_type;
using value_type = typename slot_policy::value_type;
using init_type = typename slot_policy::mutable_value_type;
using pointer = value_type *;
using const_pointer = const value_type *;
using reference = value_type &;
using const_reference = const value_type &;
using value_compare =
absl::conditional_t<IsMap,
map_value_compare<original_key_compare, value_type>,
original_key_compare>;
using is_map_container = std::integral_constant<bool, IsMap>;
// For the given lookup key type, returns whether we can have multiple
// equivalent keys in the btree. If this is a multi-container, then we can.
// Otherwise, we can have multiple equivalent keys only if all of the
// following conditions are met:
// - The comparator is transparent.
// - The lookup key type is not the same as key_type.
// - The comparator is not a StringBtreeDefault{Less,Greater} comparator
// that we know has the same equivalence classes for all lookup types.
template <typename LookupKey>
constexpr static bool can_have_multiple_equivalent_keys() {
return IsMulti || (IsTransparent<key_compare>::value &&
!std::is_same<LookupKey, Key>::value &&
!kIsKeyCompareStringAdapted);
}
enum {
kTargetNodeSize = TargetNodeSize,
// Upper bound for the available space for slots. This is largest for leaf
// nodes, which have overhead of at least a pointer + 4 bytes (for storing
// 3 field_types and an enum).
kNodeSlotSpace = TargetNodeSize - /*minimum overhead=*/(sizeof(void *) + 4),
};
// This is an integral type large enough to hold as many slots as will fit a
// node of TargetNodeSize bytes.
using node_count_type =
absl::conditional_t<(kNodeSlotSpace / sizeof(slot_type) >
(std::numeric_limits<uint8_t>::max)()),
uint16_t, uint8_t>; // NOLINT
};
// An adapter class that converts a lower-bound compare into an upper-bound
// compare. Note: there is no need to make a version of this adapter specialized
// for key-compare-to functors because the upper-bound (the first value greater
// than the input) is never an exact match.
template <typename Compare>
struct upper_bound_adapter {
explicit upper_bound_adapter(const Compare &c) : comp(c) {}
template <typename K1, typename K2>
bool operator()(const K1 &a, const K2 &b) const {
// Returns true when a is not greater than b.
return !compare_internal::compare_result_as_less_than(comp(b, a));
}
private:
Compare comp;
};
enum class MatchKind : uint8_t { kEq, kNe };
template <typename V, bool IsCompareTo>
struct SearchResult {
V value;
MatchKind match;
static constexpr bool HasMatch() { return true; }
bool IsEq() const { return match == MatchKind::kEq; }
};
// When we don't use CompareTo, `match` is not present.
// This ensures that callers can't use it accidentally when it provides no
// useful information.
template <typename V>
struct SearchResult<V, false> {
SearchResult() = default;
explicit SearchResult(V v) : value(v) {}
SearchResult(V v, MatchKind /*match*/) : value(v) {}
V value;
static constexpr bool HasMatch() { return false; }
static constexpr bool IsEq() { return false; }
};
// A node in the btree holding. The same node type is used for both internal
// and leaf nodes in the btree, though the nodes are allocated in such a way
// that the children array is only valid in internal nodes.
template <typename Params>
class btree_node {
using is_key_compare_to = typename Params::is_key_compare_to;
using field_type = typename Params::node_count_type;
using allocator_type = typename Params::allocator_type;
using slot_type = typename Params::slot_type;
using original_key_compare = typename Params::original_key_compare;
public:
using params_type = Params;
using key_type = typename Params::key_type;
using value_type = typename Params::value_type;
using pointer = typename Params::pointer;
using const_pointer = typename Params::const_pointer;
using reference = typename Params::reference;
using const_reference = typename Params::const_reference;
using key_compare = typename Params::key_compare;
using size_type = typename Params::size_type;
using difference_type = typename Params::difference_type;
// Btree decides whether to use linear node search as follows:
// - If the comparator expresses a preference, use that.
// - If the key expresses a preference, use that.
// - If the key is arithmetic and the comparator is std::less or
// std::greater, choose linear.
// - Otherwise, choose binary.
// TODO(ezb): Might make sense to add condition(s) based on node-size.
using use_linear_search = std::integral_constant<
bool, has_linear_node_search_preference<original_key_compare>::value
? prefers_linear_node_search<original_key_compare>::value
: has_linear_node_search_preference<key_type>::value
? prefers_linear_node_search<key_type>::value
: std::is_arithmetic<key_type>::value &&
(std::is_same<std::less<key_type>,
original_key_compare>::value ||
std::is_same<std::greater<key_type>,
original_key_compare>::value)>;
// This class is organized by absl::container_internal::Layout as if it had
// the following structure:
// // A pointer to the node's parent.
// btree_node *parent;
//
// // When ABSL_BTREE_ENABLE_GENERATIONS is defined, we also have a
// // generation integer in order to check that when iterators are
// // used, they haven't been invalidated already. Only the generation on
// // the root is used, but we have one on each node because whether a node
// // is root or not can change.
// uint32_t generation;
//
// // The position of the node in the node's parent.
// field_type position;
// // The index of the first populated value in `values`.
// // TODO(ezb): right now, `start` is always 0. Update insertion/merge
// // logic to allow for floating storage within nodes.
// field_type start;
// // The index after the last populated value in `values`. Currently, this
// // is the same as the count of values.
// field_type finish;
// // The maximum number of values the node can hold. This is an integer in
// // [1, kNodeSlots] for root leaf nodes, kNodeSlots for non-root leaf
// // nodes, and kInternalNodeMaxCount (as a sentinel value) for internal
// // nodes (even though there are still kNodeSlots values in the node).
// // TODO(ezb): make max_count use only 4 bits and record log2(capacity)
// // to free extra bits for is_root, etc.
// field_type max_count;
//
// // The array of values. The capacity is `max_count` for leaf nodes and
// // kNodeSlots for internal nodes. Only the values in
// // [start, finish) have been initialized and are valid.
// slot_type values[max_count];
//
// // The array of child pointers. The keys in children[i] are all less
// // than key(i). The keys in children[i + 1] are all greater than key(i).
// // There are 0 children for leaf nodes and kNodeSlots + 1 children for
// // internal nodes.
// btree_node *children[kNodeSlots + 1];
//
// This class is only constructed by EmptyNodeType. Normally, pointers to the
// layout above are allocated, cast to btree_node*, and de-allocated within
// the btree implementation.
~btree_node() = default;
btree_node(btree_node const &) = delete;
btree_node &operator=(btree_node const &) = delete;
protected:
btree_node() = default;
private:
using layout_type =
absl::container_internal::Layout<btree_node *, uint32_t, field_type,
slot_type, btree_node *>;
using leaf_layout_type = typename layout_type::template WithStaticSizes<
/*parent*/ 1,
/*generation*/ BtreeGenerationsEnabled() ? 1 : 0,
/*position, start, finish, max_count*/ 4>;
constexpr static size_type SizeWithNSlots(size_type n) {
return leaf_layout_type(/*slots*/ n, /*children*/ 0).AllocSize();
}
// A lower bound for the overhead of fields other than slots in a leaf node.
constexpr static size_type MinimumOverhead() {
return SizeWithNSlots(1) - sizeof(slot_type);
}
// Compute how many values we can fit onto a leaf node taking into account
// padding.
constexpr static size_type NodeTargetSlots(const size_type begin,
const size_type end) {
return begin == end ? begin
: SizeWithNSlots((begin + end) / 2 + 1) >
params_type::kTargetNodeSize
? NodeTargetSlots(begin, (begin + end) / 2)
: NodeTargetSlots((begin + end) / 2 + 1, end);
}
constexpr static size_type kTargetNodeSize = params_type::kTargetNodeSize;
constexpr static size_type kNodeTargetSlots =
NodeTargetSlots(0, kTargetNodeSize);
// We need a minimum of 3 slots per internal node in order to perform
// splitting (1 value for the two nodes involved in the split and 1 value
// propagated to the parent as the delimiter for the split). For performance
// reasons, we don't allow 3 slots-per-node due to bad worst case occupancy of
// 1/3 (for a node, not a b-tree).
constexpr static size_type kMinNodeSlots = 4;
constexpr static size_type kNodeSlots =
kNodeTargetSlots >= kMinNodeSlots ? kNodeTargetSlots : kMinNodeSlots;
using internal_layout_type = typename layout_type::template WithStaticSizes<
/*parent*/ 1,
/*generation*/ BtreeGenerationsEnabled() ? 1 : 0,
/*position, start, finish, max_count*/ 4, /*slots*/ kNodeSlots,
/*children*/ kNodeSlots + 1>;
// The node is internal (i.e. is not a leaf node) if and only if `max_count`
// has this value.
constexpr static field_type kInternalNodeMaxCount = 0;
// Leaves can have less than kNodeSlots values.
constexpr static leaf_layout_type LeafLayout(
const size_type slot_count = kNodeSlots) {
return leaf_layout_type(slot_count, 0);
}
constexpr static auto InternalLayout() { return internal_layout_type(); }
constexpr static size_type LeafSize(const size_type slot_count = kNodeSlots) {
return LeafLayout(slot_count).AllocSize();
}
constexpr static size_type InternalSize() {
return InternalLayout().AllocSize();
}
constexpr static size_type Alignment() {
static_assert(LeafLayout(1).Alignment() == InternalLayout().Alignment(),
"Alignment of all nodes must be equal.");
return InternalLayout().Alignment();
}
// N is the index of the type in the Layout definition.
// ElementType<N> is the Nth type in the Layout definition.
template <size_type N>
inline typename layout_type::template ElementType<N> *GetField() {
// We assert that we don't read from values that aren't there.
assert(N < 4 || is_internal());
return InternalLayout().template Pointer<N>(reinterpret_cast<char *>(this));
}
template <size_type N>
inline const typename layout_type::template ElementType<N> *GetField() const {
assert(N < 4 || is_internal());
return InternalLayout().template Pointer<N>(
reinterpret_cast<const char *>(this));
}
void set_parent(btree_node *p) { *GetField<0>() = p; }
field_type &mutable_finish() { return GetField<2>()[2]; }
slot_type *slot(size_type i) { return &GetField<3>()[i]; }
slot_type *start_slot() { return slot(start()); }
slot_type *finish_slot() { return slot(finish()); }
const slot_type *slot(size_type i) const { return &GetField<3>()[i]; }
void set_position(field_type v) { GetField<2>()[0] = v; }
void set_start(field_type v) { GetField<2>()[1] = v; }
void set_finish(field_type v) { GetField<2>()[2] = v; }
// This method is only called by the node init methods.
void set_max_count(field_type v) { GetField<2>()[3] = v; }
public:
// Whether this is a leaf node or not. This value doesn't change after the
// node is created.
bool is_leaf() const { return GetField<2>()[3] != kInternalNodeMaxCount; }
// Whether this is an internal node or not. This value doesn't change after
// the node is created.
bool is_internal() const { return !is_leaf(); }
// Getter for the position of this node in its parent.
field_type position() const { return GetField<2>()[0]; }
// Getter for the offset of the first value in the `values` array.
field_type start() const {
// TODO(ezb): when floating storage is implemented, return GetField<2>()[1];
assert(GetField<2>()[1] == 0);
return 0;
}
// Getter for the offset after the last value in the `values` array.
field_type finish() const { return GetField<2>()[2]; }
// Getters for the number of values stored in this node.
field_type count() const {
assert(finish() >= start());
return finish() - start();
}
field_type max_count() const {
// Internal nodes have max_count==kInternalNodeMaxCount.
// Leaf nodes have max_count in [1, kNodeSlots].
const field_type max_count = GetField<2>()[3];
return max_count == field_type{kInternalNodeMaxCount}
? field_type{kNodeSlots}
: max_count;
}
// Getter for the parent of this node.
// TODO(ezb): assert that the child of the returned node at position
// `node_->position()` maps to the current node.
btree_node *parent() const { return *GetField<0>(); }
// Getter for whether the node is the root of the tree. The parent of the
// root of the tree is the leftmost node in the tree which is guaranteed to
// be a leaf.
bool is_root() const { return parent()->is_leaf(); }
void make_root() {
assert(parent()->is_root());
set_generation(parent()->generation());
set_parent(parent()->parent());
}
// Gets the root node's generation integer, which is the one used by the tree.
uint32_t *get_root_generation() const {
assert(BtreeGenerationsEnabled());
const btree_node *curr = this;
for (; !curr->is_root(); curr = curr->parent()) continue;
return const_cast<uint32_t *>(&curr->GetField<1>()[0]);
}
// Returns the generation for iterator validation.
uint32_t generation() const {
return BtreeGenerationsEnabled() ? *get_root_generation() : 0;
}
// Updates generation. Should only be called on a root node or during node
// initialization.
void set_generation(uint32_t generation) {
if (BtreeGenerationsEnabled()) GetField<1>()[0] = generation;
}
// Updates the generation. We do this whenever the node is mutated.
void next_generation() {
if (BtreeGenerationsEnabled()) ++*get_root_generation();
}
// Getters for the key/value at position i in the node.
const key_type &key(size_type i) const { return params_type::key(slot(i)); }
reference value(size_type i) { return params_type::element(slot(i)); }
const_reference value(size_type i) const {
return params_type::element(slot(i));
}
// Getters/setter for the child at position i in the node.
btree_node *child(field_type i) const { return GetField<4>()[i]; }
btree_node *start_child() const { return child(start()); }
btree_node *&mutable_child(field_type i) { return GetField<4>()[i]; }
void clear_child(field_type i) {
absl::container_internal::SanitizerPoisonObject(&mutable_child(i));
}
void set_child_noupdate_position(field_type i, btree_node *c) {
absl::container_internal::SanitizerUnpoisonObject(&mutable_child(i));
mutable_child(i) = c;
}
void set_child(field_type i, btree_node *c) {
set_child_noupdate_position(i, c);
c->set_position(i);
}
void init_child(field_type i, btree_node *c) {
set_child(i, c);
c->set_parent(this);
}
// Returns the position of the first value whose key is not less than k.
template <typename K>
SearchResult<size_type, is_key_compare_to::value> lower_bound(
const K &k, const key_compare &comp) const {
return use_linear_search::value ? linear_search(k, comp)
: binary_search(k, comp);
}
// Returns the position of the first value whose key is greater than k.
template <typename K>
size_type upper_bound(const K &k, const key_compare &comp) const {
auto upper_compare = upper_bound_adapter<key_compare>(comp);
return use_linear_search::value ? linear_search(k, upper_compare).value
: binary_search(k, upper_compare).value;
}
template <typename K, typename Compare>
SearchResult<size_type, btree_is_key_compare_to<Compare, key_type>::value>
linear_search(const K &k, const Compare &comp) const {
return linear_search_impl(k, start(), finish(), comp,
btree_is_key_compare_to<Compare, key_type>());
}
template <typename K, typename Compare>
SearchResult<size_type, btree_is_key_compare_to<Compare, key_type>::value>
binary_search(const K &k, const Compare &comp) const {
return binary_search_impl(k, start(), finish(), comp,
btree_is_key_compare_to<Compare, key_type>());
}
// Returns the position of the first value whose key is not less than k using
// linear search performed using plain compare.
template <typename K, typename Compare>
SearchResult<size_type, false> linear_search_impl(
const K &k, size_type s, const size_type e, const Compare &comp,
std::false_type /* IsCompareTo */) const {
while (s < e) {
if (!comp(key(s), k)) {
break;
}
++s;
}
return SearchResult<size_type, false>{s};
}
// Returns the position of the first value whose key is not less than k using
// linear search performed using compare-to.
template <typename K, typename Compare>
SearchResult<size_type, true> linear_search_impl(
const K &k, size_type s, const size_type e, const Compare &comp,
std::true_type /* IsCompareTo */) const {
while (s < e) {
const absl::weak_ordering c = comp(key(s), k);
if (c == 0) {
return {s, MatchKind::kEq};
} else if (c > 0) {
break;
}
++s;
}
return {s, MatchKind::kNe};
}
// Returns the position of the first value whose key is not less than k using
// binary search performed using plain compare.
template <typename K, typename Compare>
SearchResult<size_type, false> binary_search_impl(
const K &k, size_type s, size_type e, const Compare &comp,
std::false_type /* IsCompareTo */) const {
while (s != e) {
const size_type mid = (s + e) >> 1;
if (comp(key(mid), k)) {
s = mid + 1;
} else {
e = mid;
}
}
return SearchResult<size_type, false>{s};
}
// Returns the position of the first value whose key is not less than k using
// binary search performed using compare-to.
template <typename K, typename CompareTo>
SearchResult<size_type, true> binary_search_impl(
const K &k, size_type s, size_type e, const CompareTo &comp,
std::true_type /* IsCompareTo */) const {
if (params_type::template can_have_multiple_equivalent_keys<K>()) {
MatchKind exact_match = MatchKind::kNe;
while (s != e) {
const size_type mid = (s + e) >> 1;
const absl::weak_ordering c = comp(key(mid), k);
if (c < 0) {
s = mid + 1;
} else {
e = mid;
if (c == 0) {
// Need to return the first value whose key is not less than k,
// which requires continuing the binary search if there could be
// multiple equivalent keys.
exact_match = MatchKind::kEq;
}
}
}
return {s, exact_match};
} else { // Can't have multiple equivalent keys.
while (s != e) {
const size_type mid = (s + e) >> 1;
const absl::weak_ordering c = comp(key(mid), k);
if (c < 0) {
s = mid + 1;
} else if (c > 0) {
e = mid;
} else {
return {mid, MatchKind::kEq};
}
}
return {s, MatchKind::kNe};
}
}
// Returns whether key i is ordered correctly with respect to the other keys
// in the node. The motivation here is to detect comparators that violate
// transitivity. Note: we only do comparisons of keys on this node rather than
// the whole tree so that this is constant time.
template <typename Compare>
bool is_ordered_correctly(field_type i, const Compare &comp) const {
if (std::is_base_of<BtreeTestOnlyCheckedCompareOptOutBase,
Compare>::value ||
params_type::kIsKeyCompareStringAdapted) {
return true;
}
const auto compare = [&](field_type a, field_type b) {
const absl::weak_ordering cmp =
compare_internal::do_three_way_comparison(comp, key(a), key(b));
return cmp < 0 ? -1 : cmp > 0 ? 1 : 0;
};
int cmp = -1;
constexpr bool kCanHaveEquivKeys =
params_type::template can_have_multiple_equivalent_keys<key_type>();
for (field_type j = start(); j < finish(); ++j) {
if (j == i) {
if (cmp > 0) return false;
continue;
}
int new_cmp = compare(j, i);
if (new_cmp < cmp || (!kCanHaveEquivKeys && new_cmp == 0)) return false;
cmp = new_cmp;
}
return true;
}
// Emplaces a value at position i, shifting all existing values and
// children at positions >= i to the right by 1.
template <typename... Args>
void emplace_value(field_type i, allocator_type *alloc, Args &&...args);
// Removes the values at positions [i, i + to_erase), shifting all existing
// values and children after that range to the left by to_erase. Clears all
// children between [i, i + to_erase).
void remove_values(field_type i, field_type to_erase, allocator_type *alloc);
// Rebalances a node with its right sibling.
void rebalance_right_to_left(field_type to_move, btree_node *right,
allocator_type *alloc);
void rebalance_left_to_right(field_type to_move, btree_node *right,
allocator_type *alloc);
// Splits a node, moving a portion of the node's values to its right sibling.
void split(int insert_position, btree_node *dest, allocator_type *alloc);
// Merges a node with its right sibling, moving all of the values and the
// delimiting key in the parent node onto itself, and deleting the src node.
void merge(btree_node *src, allocator_type *alloc);
// Node allocation/deletion routines.
void init_leaf(field_type position, field_type max_count,
btree_node *parent) {
set_generation(0);
set_parent(parent);
set_position(position);
set_start(0);
set_finish(0);
set_max_count(max_count);
absl::container_internal::SanitizerPoisonMemoryRegion(
start_slot(), max_count * sizeof(slot_type));
}
void init_internal(field_type position, btree_node *parent) {
init_leaf(position, kNodeSlots, parent);
// Set `max_count` to a sentinel value to indicate that this node is
// internal.
set_max_count(kInternalNodeMaxCount);
absl::container_internal::SanitizerPoisonMemoryRegion(
&mutable_child(start()), (kNodeSlots + 1) * sizeof(btree_node *));
}
static void deallocate(const size_type size, btree_node *node,
allocator_type *alloc) {
absl::container_internal::SanitizerUnpoisonMemoryRegion(node, size);
absl::container_internal::Deallocate<Alignment()>(alloc, node, size);
}
// Deletes a node and all of its children.
static void clear_and_delete(btree_node *node, allocator_type *alloc);
private:
template <typename... Args>
void value_init(const field_type i, allocator_type *alloc, Args &&...args) {
next_generation();
absl::container_internal::SanitizerUnpoisonObject(slot(i));
params_type::construct(alloc, slot(i), std::forward<Args>(args)...);
}
void value_destroy(const field_type i, allocator_type *alloc) {
next_generation();
params_type::destroy(alloc, slot(i));
absl::container_internal::SanitizerPoisonObject(slot(i));
}
void value_destroy_n(const field_type i, const field_type n,
allocator_type *alloc) {
next_generation();
for (slot_type *s = slot(i), *end = slot(i + n); s != end; ++s) {
params_type::destroy(alloc, s);
absl::container_internal::SanitizerPoisonObject(s);
}
}
static void transfer(slot_type *dest, slot_type *src, allocator_type *alloc) {
absl::container_internal::SanitizerUnpoisonObject(dest);
params_type::transfer(alloc, dest, src);
absl::container_internal::SanitizerPoisonObject(src);
}
// Transfers value from slot `src_i` in `src_node` to slot `dest_i` in `this`.
void transfer(const size_type dest_i, const size_type src_i,
btree_node *src_node, allocator_type *alloc) {
next_generation();
transfer(slot(dest_i), src_node->slot(src_i), alloc);
}
// Transfers `n` values starting at value `src_i` in `src_node` into the
// values starting at value `dest_i` in `this`.
void transfer_n(const size_type n, const size_type dest_i,
const size_type src_i, btree_node *src_node,
allocator_type *alloc) {
next_generation();
for (slot_type *src = src_node->slot(src_i), *end = src + n,
*dest = slot(dest_i);
src != end; ++src, ++dest) {
transfer(dest, src, alloc);
}
}
// Same as above, except that we start at the end and work our way to the
// beginning.
void transfer_n_backward(const size_type n, const size_type dest_i,
const size_type src_i, btree_node *src_node,
allocator_type *alloc) {
next_generation();
for (slot_type *src = src_node->slot(src_i + n), *end = src - n,
*dest = slot(dest_i + n);
src != end; --src, --dest) {
// If we modified the loop index calculations above to avoid the -1s here,
// it would result in UB in the computation of `end` (and possibly `src`
// as well, if n == 0), since slot() is effectively an array index and it
// is UB to compute the address of any out-of-bounds array element except
// for one-past-the-end.
transfer(dest - 1, src - 1, alloc);
}
}
template <typename P>
friend class btree;
template <typename N, typename R, typename P>
friend class btree_iterator;
friend class BtreeNodePeer;
friend struct btree_access;
};
template <typename Node>
bool AreNodesFromSameContainer(const Node *node_a, const Node *node_b) {
// If either node is null, then give up on checking whether they're from the
// same container. (If exactly one is null, then we'll trigger the
// default-constructed assert in Equals.)
if (node_a == nullptr || node_b == nullptr) return true;
while (!node_a->is_root()) node_a = node_a->parent();
while (!node_b->is_root()) node_b = node_b->parent();
return node_a == node_b;
}
class btree_iterator_generation_info_enabled {
public:
explicit btree_iterator_generation_info_enabled(uint32_t g)
: generation_(g) {}
// Updates the generation. For use internally right before we return an
// iterator to the user.
template <typename Node>
void update_generation(const Node *node) {
if (node != nullptr) generation_ = node->generation();
}
uint32_t generation() const { return generation_; }
template <typename Node>
void assert_valid_generation(const Node *node) const {
if (node != nullptr && node->generation() != generation_) {
ABSL_INTERNAL_LOG(
FATAL,
"Attempting to use an invalidated iterator. The corresponding b-tree "
"container has been mutated since this iterator was constructed.");
}
}
private:
// Used to check that the iterator hasn't been invalidated.
uint32_t generation_;
};
class btree_iterator_generation_info_disabled {
public:
explicit btree_iterator_generation_info_disabled(uint32_t) {}
static void update_generation(const void *) {}
static uint32_t generation() { return 0; }
static void assert_valid_generation(const void *) {}
};
#ifdef ABSL_BTREE_ENABLE_GENERATIONS
using btree_iterator_generation_info = btree_iterator_generation_info_enabled;
#else
using btree_iterator_generation_info = btree_iterator_generation_info_disabled;
#endif
template <typename Node, typename Reference, typename Pointer>
class btree_iterator : private btree_iterator_generation_info {
using field_type = typename Node::field_type;
using key_type = typename Node::key_type;
using size_type = typename Node::size_type;
using params_type = typename Node::params_type;
using is_map_container = typename params_type::is_map_container;
using node_type = Node;
using normal_node = typename std::remove_const<Node>::type;
using const_node = const Node;
using normal_pointer = typename params_type::pointer;
using normal_reference = typename params_type::reference;
using const_pointer = typename params_type::const_pointer;
using const_reference = typename params_type::const_reference;
using slot_type = typename params_type::slot_type;
// In sets, all iterators are const.
using iterator = absl::conditional_t<
is_map_container::value,
btree_iterator<normal_node, normal_reference, normal_pointer>,
btree_iterator<normal_node, const_reference, const_pointer>>;
using const_iterator =
btree_iterator<const_node, const_reference, const_pointer>;
public:
// These aliases are public for std::iterator_traits.
using difference_type = typename Node::difference_type;
using value_type = typename params_type::value_type;
using pointer = Pointer;
using reference = Reference;
using iterator_category = std::bidirectional_iterator_tag;
btree_iterator() : btree_iterator(nullptr, -1) {}
explicit btree_iterator(Node *n) : btree_iterator(n, n->start()) {}
btree_iterator(Node *n, int p)
: btree_iterator_generation_info(n != nullptr ? n->generation()
: ~uint32_t{}),
node_(n),
position_(p) {}
// NOTE: this SFINAE allows for implicit conversions from iterator to
// const_iterator, but it specifically avoids hiding the copy constructor so
// that the trivial one will be used when possible.
template <typename N, typename R, typename P,
absl::enable_if_t<
std::is_same<btree_iterator<N, R, P>, iterator>::value &&
std::is_same<btree_iterator, const_iterator>::value,
int> = 0>
btree_iterator(const btree_iterator<N, R, P> other) // NOLINT
: btree_iterator_generation_info(other),
node_(other.node_),
position_(other.position_) {}
bool operator==(const iterator &other) const {
return Equals(other);
}
bool operator==(const const_iterator &other) const {
return Equals(other);
}
bool operator!=(const iterator &other) const {
return !Equals(other);
}
bool operator!=(const const_iterator &other) const {
return !Equals(other);
}
// Returns n such that n calls to ++other yields *this.
// Precondition: n exists.
difference_type operator-(const_iterator other) const {
if (node_ == other.node_) {
if (node_->is_leaf()) return position_ - other.position_;
if (position_ == other.position_) return 0;
}
return distance_slow(other);
}
// Advances the iterator by `n`. Values of `n` must not result in going past
// the `end` iterator (for a positive `n`) or before the `begin` iterator (for
// a negative `n`).
btree_iterator &operator+=(difference_type n) {
assert_valid_generation(node_);
if (n == 0) return *this;
if (n < 0) return decrement_n_slow(-n);
return increment_n_slow(n);
}
// Moves the iterator by `n` positions backwards. Values of `n` must not
// result in going before the `begin` iterator (for a positive `n`) or past
// the `end` iterator (for a negative `n`).
btree_iterator &operator-=(difference_type n) {
assert_valid_generation(node_);
if (n == 0) return *this;
if (n < 0) return increment_n_slow(-n);
return decrement_n_slow(n);
}
// Accessors for the key/value the iterator is pointing at.
reference operator*() const {
ABSL_HARDENING_ASSERT(node_ != nullptr);
assert_valid_generation(node_);
ABSL_HARDENING_ASSERT(position_ >= node_->start());
if (position_ >= node_->finish()) {
ABSL_HARDENING_ASSERT(!IsEndIterator() && "Dereferencing end() iterator");
ABSL_HARDENING_ASSERT(position_ < node_->finish());
}
return node_->value(static_cast<field_type>(position_));
}
pointer operator->() const { return &operator*(); }
btree_iterator &operator++() {
increment();
return *this;
}
btree_iterator &operator--() {
decrement();
return *this;
}
btree_iterator operator++(int) {
btree_iterator tmp = *this;
++*this;
return tmp;
}
btree_iterator operator--(int) {
btree_iterator tmp = *this;
--*this;
return tmp;
}
private:
friend iterator;
friend const_iterator;
template <typename Params>
friend class btree;
template <typename Tree>
friend class btree_container;
template <typename Tree>
friend class btree_set_container;
template <typename Tree>
friend class btree_map_container;
template <typename Tree>
friend class btree_multiset_container;
template <typename TreeType, typename CheckerType>
friend class base_checker;
friend struct btree_access;
// This SFINAE allows explicit conversions from const_iterator to
// iterator, but also avoids hiding the copy constructor.
// NOTE: the const_cast is safe because this constructor is only called by
// non-const methods and the container owns the nodes.
template <typename N, typename R, typename P,
absl::enable_if_t<
std::is_same<btree_iterator<N, R, P>, const_iterator>::value &&
std::is_same<btree_iterator, iterator>::value,
int> = 0>
explicit btree_iterator(const btree_iterator<N, R, P> other)
: btree_iterator_generation_info(other.generation()),
node_(const_cast<node_type *>(other.node_)),
position_(other.position_) {}
bool Equals(const const_iterator other) const {
ABSL_HARDENING_ASSERT(((node_ == nullptr && other.node_ == nullptr) ||
(node_ != nullptr && other.node_ != nullptr)) &&
"Comparing default-constructed iterator with "
"non-default-constructed iterator.");
// Note: we use assert instead of ABSL_HARDENING_ASSERT here because this
// changes the complexity of Equals from O(1) to O(log(N) + log(M)) where
// N/M are sizes of the containers containing node_/other.node_.
assert(AreNodesFromSameContainer(node_, other.node_) &&
"Comparing iterators from different containers.");
assert_valid_generation(node_);
other.assert_valid_generation(other.node_);
return node_ == other.node_ && position_ == other.position_;
}
bool IsEndIterator() const {
if (position_ != node_->finish()) return false;
node_type *node = node_;
while (!node->is_root()) {
if (node->position() != node->parent()->finish()) return false;
node = node->parent();
}
return true;
}
// Returns n such that n calls to ++other yields *this.
// Precondition: n exists && (this->node_ != other.node_ ||
// !this->node_->is_leaf() || this->position_ != other.position_).
difference_type distance_slow(const_iterator other) const;
// Increment/decrement the iterator.
void increment() {
assert_valid_generation(node_);
if (node_->is_leaf() && ++position_ < node_->finish()) {
return;
}
increment_slow();
}
void increment_slow();
btree_iterator &increment_n_slow(difference_type n);
void decrement() {
assert_valid_generation(node_);
if (node_->is_leaf() && --position_ >= node_->start()) {
return;
}
decrement_slow();
}
void decrement_slow();
btree_iterator &decrement_n_slow(difference_type n);
const key_type &key() const {
return node_->key(static_cast<size_type>(position_));
}
decltype(std::declval<Node *>()->slot(0)) slot() {
return node_->slot(static_cast<size_type>(position_));
}
void update_generation() {
btree_iterator_generation_info::update_generation(node_);
}
// The node in the tree the iterator is pointing at.
Node *node_;
// The position within the node of the tree the iterator is pointing at.
// NOTE: this is an int rather than a field_type because iterators can point
// to invalid positions (such as -1) in certain circumstances.
int position_;
};
template <typename Params>
class btree {
using node_type = btree_node<Params>;
using is_key_compare_to = typename Params::is_key_compare_to;
using field_type = typename node_type::field_type;
// We use a static empty node for the root/leftmost/rightmost of empty btrees
// in order to avoid branching in begin()/end().
struct EmptyNodeType : node_type {
using field_type = typename node_type::field_type;
node_type *parent;
#ifdef ABSL_BTREE_ENABLE_GENERATIONS
uint32_t generation = 0;
#endif
field_type position = 0;
field_type start = 0;
field_type finish = 0;
// max_count must be != kInternalNodeMaxCount (so that this node is regarded
// as a leaf node). max_count() is never called when the tree is empty.
field_type max_count = node_type::kInternalNodeMaxCount + 1;
constexpr EmptyNodeType() : parent(this) {}
};
static node_type *EmptyNode() {
alignas(node_type::Alignment()) static constexpr EmptyNodeType empty_node;
return const_cast<EmptyNodeType *>(&empty_node);
}
enum : uint32_t {
kNodeSlots = node_type::kNodeSlots,
kMinNodeValues = kNodeSlots / 2,
};
struct node_stats {
using size_type = typename Params::size_type;
node_stats(size_type l, size_type i) : leaf_nodes(l), internal_nodes(i) {}
node_stats &operator+=(const node_stats &other) {
leaf_nodes += other.leaf_nodes;
internal_nodes += other.internal_nodes;
return *this;
}
size_type leaf_nodes;
size_type internal_nodes;
};
public:
using key_type = typename Params::key_type;
using value_type = typename Params::value_type;
using size_type = typename Params::size_type;
using difference_type = typename Params::difference_type;
using key_compare = typename Params::key_compare;
using original_key_compare = typename Params::original_key_compare;
using value_compare = typename Params::value_compare;
using allocator_type = typename Params::allocator_type;
using reference = typename Params::reference;
using const_reference = typename Params::const_reference;
using pointer = typename Params::pointer;
using const_pointer = typename Params::const_pointer;
using iterator =
typename btree_iterator<node_type, reference, pointer>::iterator;
using const_iterator = typename iterator::const_iterator;
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
using node_handle_type = node_handle<Params, Params, allocator_type>;
// Internal types made public for use by btree_container types.
using params_type = Params;
using slot_type = typename Params::slot_type;
private:
// Copies or moves (depending on the template parameter) the values in
// other into this btree in their order in other. This btree must be empty
// before this method is called. This method is used in copy construction,
// copy assignment, and move assignment.
template <typename Btree>
void copy_or_move_values_in_order(Btree &other);
// Validates that various assumptions/requirements are true at compile time.
constexpr static bool static_assert_validation();
public:
btree(const key_compare &comp, const allocator_type &alloc)
: root_(EmptyNode()), rightmost_(comp, alloc, EmptyNode()), size_(0) {}
btree(const btree &other) : btree(other, other.allocator()) {}
btree(const btree &other, const allocator_type &alloc)
: btree(other.key_comp(), alloc) {
copy_or_move_values_in_order(other);
}
btree(btree &&other) noexcept
: root_(std::exchange(other.root_, EmptyNode())),
rightmost_(std::move(other.rightmost_)),
size_(std::exchange(other.size_, 0u)) {
other.mutable_rightmost() = EmptyNode();
}
btree(btree &&other, const allocator_type &alloc)
: btree(other.key_comp(), alloc) {
if (alloc == other.allocator()) {
swap(other);
} else {
// Move values from `other` one at a time when allocators are different.
copy_or_move_values_in_order(other);
}
}
~btree() {
// Put static_asserts in destructor to avoid triggering them before the type
// is complete.
static_assert(static_assert_validation(), "This call must be elided.");
clear();
}
// Assign the contents of other to *this.
btree &operator=(const btree &other);
btree &operator=(btree &&other) noexcept;
iterator begin() { return iterator(leftmost()); }
const_iterator begin() const { return const_iterator(leftmost()); }
iterator end() { return iterator(rightmost(), rightmost()->finish()); }
const_iterator end() const {
return const_iterator(rightmost(), rightmost()->finish());
}
reverse_iterator rbegin() { return reverse_iterator(end()); }
const_reverse_iterator rbegin() const {
return const_reverse_iterator(end());
}
reverse_iterator rend() { return reverse_iterator(begin()); }
const_reverse_iterator rend() const {
return const_reverse_iterator(begin());
}
// Finds the first element whose key is not less than `key`.
template <typename K>
iterator lower_bound(const K &key) {
return internal_end(internal_lower_bound(key).value);
}
template <typename K>
const_iterator lower_bound(const K &key) const {
return internal_end(internal_lower_bound(key).value);
}
// Finds the first element whose key is not less than `key` and also returns
// whether that element is equal to `key`.
template <typename K>
std::pair<iterator, bool> lower_bound_equal(const K &key) const;
// Finds the first element whose key is greater than `key`.
template <typename K>
iterator upper_bound(const K &key) {
return internal_end(internal_upper_bound(key));
}
template <typename K>
const_iterator upper_bound(const K &key) const {
return internal_end(internal_upper_bound(key));
}
// Finds the range of values which compare equal to key. The first member of
// the returned pair is equal to lower_bound(key). The second member of the
// pair is equal to upper_bound(key).
template <typename K>
std::pair<iterator, iterator> equal_range(const K &key);
template <typename K>
std::pair<const_iterator, const_iterator> equal_range(const K &key) const {
return const_cast<btree *>(this)->equal_range(key);
}
// Inserts a value into the btree only if it does not already exist. The
// boolean return value indicates whether insertion succeeded or failed.
// Requirement: if `key` already exists in the btree, does not consume `args`.
// Requirement: `key` is never referenced after consuming `args`.
template <typename K, typename... Args>
std::pair<iterator, bool> insert_unique(const K &key, Args &&...args);
// Inserts with hint. Checks to see if the value should be placed immediately
// before `position` in the tree. If so, then the insertion will take
// amortized constant time. If not, the insertion will take amortized
// logarithmic time as if a call to insert_unique() were made.
// Requirement: if `key` already exists in the btree, does not consume `args`.
// Requirement: `key` is never referenced after consuming `args`.
template <typename K, typename... Args>
std::pair<iterator, bool> insert_hint_unique(iterator position, const K &key,
Args &&...args);
// Insert a range of values into the btree.
// Note: the first overload avoids constructing a value_type if the key
// already exists in the btree.
template <typename InputIterator,
typename = decltype(std::declval<const key_compare &>()(
params_type::key(*std::declval<InputIterator>()),
std::declval<const key_type &>()))>
void insert_iterator_unique(InputIterator b, InputIterator e, int);
// We need the second overload for cases in which we need to construct a
// value_type in order to compare it with the keys already in the btree.
template <typename InputIterator>
void insert_iterator_unique(InputIterator b, InputIterator e, char);
// Inserts a value into the btree.
template <typename ValueType>
iterator insert_multi(const key_type &key, ValueType &&v);
// Inserts a value into the btree.
template <typename ValueType>
iterator insert_multi(ValueType &&v) {
return insert_multi(params_type::key(v), std::forward<ValueType>(v));
}
// Insert with hint. Check to see if the value should be placed immediately
// before position in the tree. If it does, then the insertion will take
// amortized constant time. If not, the insertion will take amortized
// logarithmic time as if a call to insert_multi(v) were made.
template <typename ValueType>
iterator insert_hint_multi(iterator position, ValueType &&v);
// Insert a range of values into the btree.
template <typename InputIterator>
void insert_iterator_multi(InputIterator b,
InputIterator e);
// Erase the specified iterator from the btree. The iterator must be valid
// (i.e. not equal to end()). Return an iterator pointing to the node after
// the one that was erased (or end() if none exists).
// Requirement: does not read the value at `*iter`.
iterator erase(iterator iter);
// Erases range. Returns the number of keys erased and an iterator pointing
// to the element after the last erased element.
std::pair<size_type, iterator> erase_range(iterator begin, iterator end);
// Finds an element with key equivalent to `key` or returns `end()` if `key`
// is not present.
template <typename K>
iterator find(const K &key) {
return internal_end(internal_find(key));
}
template <typename K>
const_iterator find(const K &key) const {
return internal_end(internal_find(key));
}
// Clear the btree, deleting all of the values it contains.
void clear();
// Swaps the contents of `this` and `other`.
void swap(btree &other);
const key_compare &key_comp() const noexcept {
return rightmost_.template get<0>();
}
template <typename K1, typename K2>
bool compare_keys(const K1 &a, const K2 &b) const {
return compare_internal::compare_result_as_less_than(key_comp()(a, b));
}
value_compare value_comp() const {
return value_compare(original_key_compare(key_comp()));
}
// Verifies the structure of the btree.
void verify() const;
// Size routines.
size_type size() const { return size_; }
size_type max_size() const { return (std::numeric_limits<size_type>::max)(); }
bool empty() const { return size_ == 0; }
// The height of the btree. An empty tree will have height 0.
size_type height() const {
size_type h = 0;
if (!empty()) {
// Count the length of the chain from the leftmost node up to the
// root. We actually count from the root back around to the level below
// the root, but the calculation is the same because of the circularity
// of that traversal.
const node_type *n = root();
do {
++h;
n = n->parent();
} while (n != root());
}
return h;
}
// The number of internal, leaf and total nodes used by the btree.
size_type leaf_nodes() const { return internal_stats(root()).leaf_nodes; }
size_type internal_nodes() const {
return internal_stats(root()).internal_nodes;
}
size_type nodes() const {
node_stats stats = internal_stats(root());
return stats.leaf_nodes + stats.internal_nodes;
}
// The total number of bytes used by the btree.
// TODO(b/169338300): update to support node_btree_*.
size_type bytes_used() const {
node_stats stats = internal_stats(root());
if (stats.leaf_nodes == 1 && stats.internal_nodes == 0) {
return sizeof(*this) + node_type::LeafSize(root()->max_count());
} else {
return sizeof(*this) + stats.leaf_nodes * node_type::LeafSize() +
stats.internal_nodes * node_type::InternalSize();
}
}
// The average number of bytes used per value stored in the btree assuming
// random insertion order.
static double average_bytes_per_value() {
// The expected number of values per node with random insertion order is the
// average of the maximum and minimum numbers of values per node.
const double expected_values_per_node = (kNodeSlots + kMinNodeValues) / 2.0;
return node_type::LeafSize() / expected_values_per_node;
}
// The fullness of the btree. Computed as the number of elements in the btree
// divided by the maximum number of elements a tree with the current number
// of nodes could hold. A value of 1 indicates perfect space
// utilization. Smaller values indicate space wastage.
// Returns 0 for empty trees.
double fullness() const {
if (empty()) return 0.0;
return static_cast<double>(size()) / (nodes() * kNodeSlots);
}
// The overhead of the btree structure in bytes per node. Computed as the
// total number of bytes used by the btree minus the number of bytes used for
// storing elements divided by the number of elements.
// Returns 0 for empty trees.
double overhead() const {
if (empty()) return 0.0;
return (bytes_used() - size() * sizeof(value_type)) /
static_cast<double>(size());
}
// The allocator used by the btree.
allocator_type get_allocator() const { return allocator(); }
private:
friend struct btree_access;
// Internal accessor routines.
node_type *root() { return root_; }
const node_type *root() const { return root_; }
node_type *&mutable_root() noexcept { return root_; }
node_type *rightmost() { return rightmost_.template get<2>(); }
const node_type *rightmost() const { return rightmost_.template get<2>(); }
node_type *&mutable_rightmost() noexcept {
return rightmost_.template get<2>();
}
key_compare *mutable_key_comp() noexcept {
return &rightmost_.template get<0>();
}
// The leftmost node is stored as the parent of the root node.
node_type *leftmost() { return root()->parent(); }
const node_type *leftmost() const { return root()->parent(); }
// Allocator routines.
allocator_type *mutable_allocator() noexcept {
return &rightmost_.template get<1>();
}
const allocator_type &allocator() const noexcept {
return rightmost_.template get<1>();
}
// Allocates a correctly aligned node of at least size bytes using the
// allocator.
node_type *allocate(size_type size) {
return reinterpret_cast<node_type *>(
absl::container_internal::Allocate<node_type::Alignment()>(
mutable_allocator(), size));
}
// Node creation/deletion routines.
node_type *new_internal_node(field_type position, node_type *parent) {
node_type *n = allocate(node_type::InternalSize());
n->init_internal(position, parent);
return n;
}
node_type *new_leaf_node(field_type position, node_type *parent) {
node_type *n = allocate(node_type::LeafSize());
n->init_leaf(position, kNodeSlots, parent);
return n;
}
node_type *new_leaf_root_node(field_type max_count) {
node_type *n = allocate(node_type::LeafSize(max_count));
n->init_leaf(/*position=*/0, max_count, /*parent=*/n);
return n;
}
// Deletion helper routines.
iterator rebalance_after_delete(iterator iter);
// Rebalances or splits the node iter points to.
void rebalance_or_split(iterator *iter);
// Merges the values of left, right and the delimiting key on their parent
// onto left, removing the delimiting key and deleting right.
void merge_nodes(node_type *left, node_type *right);
// Tries to merge node with its left or right sibling, and failing that,
// rebalance with its left or right sibling. Returns true if a merge
// occurred, at which point it is no longer valid to access node. Returns
// false if no merging took place.
bool try_merge_or_rebalance(iterator *iter);
// Tries to shrink the height of the tree by 1.
void try_shrink();
iterator internal_end(iterator iter) {
return iter.node_ != nullptr ? iter : end();
}
const_iterator internal_end(const_iterator iter) const {
return iter.node_ != nullptr ? iter : end();
}
// Emplaces a value into the btree immediately before iter. Requires that
// key(v) <= iter.key() and (--iter).key() <= key(v).
template <typename... Args>
iterator internal_emplace(iterator iter, Args &&...args);
// Returns an iterator pointing to the first value >= the value "iter" is
// pointing at. Note that "iter" might be pointing to an invalid location such
// as iter.position_ == iter.node_->finish(). This routine simply moves iter
// up in the tree to a valid location. Requires: iter.node_ is non-null.
template <typename IterType>
static IterType internal_last(IterType iter);
// Returns an iterator pointing to the leaf position at which key would
// reside in the tree, unless there is an exact match - in which case, the
// result may not be on a leaf. When there's a three-way comparator, we can
// return whether there was an exact match. This allows the caller to avoid a
// subsequent comparison to determine if an exact match was made, which is
// important for keys with expensive comparison, such as strings.
template <typename K>
SearchResult<iterator, is_key_compare_to::value> internal_locate(
const K &key) const;
// Internal routine which implements lower_bound().
template <typename K>
SearchResult<iterator, is_key_compare_to::value> internal_lower_bound(
const K &key) const;
// Internal routine which implements upper_bound().
template <typename K>
iterator internal_upper_bound(const K &key) const;
// Internal routine which implements find().
template <typename K>
iterator internal_find(const K &key) const;
// Verifies the tree structure of node.
size_type internal_verify(const node_type *node, const key_type *lo,
const key_type *hi) const;
node_stats internal_stats(const node_type *node) const {
// The root can be a static empty node.
if (node == nullptr || (node == root() && empty())) {
return node_stats(0, 0);
}
if (node->is_leaf()) {
return node_stats(1, 0);
}
node_stats res(0, 1);
for (int i = node->start(); i <= node->finish(); ++i) {
res += internal_stats(node->child(i));
}
return res;
}
node_type *root_;
// A pointer to the rightmost node. Note that the leftmost node is stored as
// the root's parent. We use compressed tuple in order to save space because
// key_compare and allocator_type are usually empty.
absl::container_internal::CompressedTuple<key_compare, allocator_type,
node_type *>
rightmost_;
// Number of values.
size_type size_;
};
////
// btree_node methods
template <typename P>
template <typename... Args>
inline void btree_node<P>::emplace_value(const field_type i,
allocator_type *alloc,
Args &&...args) {
assert(i >= start());
assert(i <= finish());
// Shift old values to create space for new value and then construct it in
// place.
if (i < finish()) {
transfer_n_backward(finish() - i, /*dest_i=*/i + 1, /*src_i=*/i, this,
alloc);
}
value_init(static_cast<field_type>(i), alloc, std::forward<Args>(args)...);
set_finish(finish() + 1);
if (is_internal() && finish() > i + 1) {
for (field_type j = finish(); j > i + 1; --j) {
set_child(j, child(j - 1));
}
clear_child(i + 1);
}
}
template <typename P>
inline void btree_node<P>::remove_values(const field_type i,
const field_type to_erase,
allocator_type *alloc) {
// Transfer values after the removed range into their new places.
value_destroy_n(i, to_erase, alloc);
const field_type orig_finish = finish();
const field_type src_i = i + to_erase;
transfer_n(orig_finish - src_i, i, src_i, this, alloc);
if (is_internal()) {
// Delete all children between begin and end.
for (field_type j = 0; j < to_erase; ++j) {
clear_and_delete(child(i + j + 1), alloc);
}
// Rotate children after end into new positions.
for (field_type j = i + to_erase + 1; j <= orig_finish; ++j) {
set_child(j - to_erase, child(j));
clear_child(j);
}
}
set_finish(orig_finish - to_erase);
}
template <typename P>
void btree_node<P>::rebalance_right_to_left(field_type to_move,
btree_node *right,
allocator_type *alloc) {
assert(parent() == right->parent());
assert(position() + 1 == right->position());
assert(right->count() >= count());
assert(to_move >= 1);
assert(to_move <= right->count());
// 1) Move the delimiting value in the parent to the left node.
transfer(finish(), position(), parent(), alloc);
// 2) Move the (to_move - 1) values from the right node to the left node.
transfer_n(to_move - 1, finish() + 1, right->start(), right, alloc);
// 3) Move the new delimiting value to the parent from the right node.
parent()->transfer(position(), right->start() + to_move - 1, right, alloc);
// 4) Shift the values in the right node to their correct positions.
right->transfer_n(right->count() - to_move, right->start(),
right->start() + to_move, right, alloc);
if (is_internal()) {
// Move the child pointers from the right to the left node.
for (field_type i = 0; i < to_move; ++i) {
init_child(finish() + i + 1, right->child(i));
}
for (field_type i = right->start(); i <= right->finish() - to_move; ++i) {
assert(i + to_move <= right->max_count());
right->init_child(i, right->child(i + to_move));
right->clear_child(i + to_move);
}
}
// Fixup `finish` on the left and right nodes.
set_finish(finish() + to_move);
right->set_finish(right->finish() - to_move);
}
template <typename P>
void btree_node<P>::rebalance_left_to_right(field_type to_move,
btree_node *right,
allocator_type *alloc) {
assert(parent() == right->parent());
assert(position() + 1 == right->position());
assert(count() >= right->count());
assert(to_move >= 1);
assert(to_move <= count());
// Values in the right node are shifted to the right to make room for the
// new to_move values. Then, the delimiting value in the parent and the
// other (to_move - 1) values in the left node are moved into the right node.
// Lastly, a new delimiting value is moved from the left node into the
// parent, and the remaining empty left node entries are destroyed.
// 1) Shift existing values in the right node to their correct positions.
right->transfer_n_backward(right->count(), right->start() + to_move,
right->start(), right, alloc);
// 2) Move the delimiting value in the parent to the right node.
right->transfer(right->start() + to_move - 1, position(), parent(), alloc);
// 3) Move the (to_move - 1) values from the left node to the right node.
right->transfer_n(to_move - 1, right->start(), finish() - (to_move - 1), this,
alloc);
// 4) Move the new delimiting value to the parent from the left node.
parent()->transfer(position(), finish() - to_move, this, alloc);
if (is_internal()) {
// Move the child pointers from the left to the right node.
for (field_type i = right->finish() + 1; i > right->start(); --i) {
right->init_child(i - 1 + to_move, right->child(i - 1));
right->clear_child(i - 1);
}
for (field_type i = 1; i <= to_move; ++i) {
right->init_child(i - 1, child(finish() - to_move + i));
clear_child(finish() - to_move + i);
}
}
// Fixup the counts on the left and right nodes.
set_finish(finish() - to_move);
right->set_finish(right->finish() + to_move);
}
template <typename P>
void btree_node<P>::split(const int insert_position, btree_node *dest,
allocator_type *alloc) {
assert(dest->count() == 0);
assert(max_count() == kNodeSlots);
assert(position() + 1 == dest->position());
assert(parent() == dest->parent());
// We bias the split based on the position being inserted. If we're
// inserting at the beginning of the left node then bias the split to put
// more values on the right node. If we're inserting at the end of the
// right node then bias the split to put more values on the left node.
if (insert_position == start()) {
dest->set_finish(dest->start() + finish() - 1);
} else if (insert_position == kNodeSlots) {
dest->set_finish(dest->start());
} else {
dest->set_finish(dest->start() + count() / 2);
}
set_finish(finish() - dest->count());
assert(count() >= 1);
// Move values from the left sibling to the right sibling.
dest->transfer_n(dest->count(), dest->start(), finish(), this, alloc);
// The split key is the largest value in the left sibling.
--mutable_finish();
parent()->emplace_value(position(), alloc, finish_slot());
value_destroy(finish(), alloc);
parent()->set_child_noupdate_position(position() + 1, dest);
if (is_internal()) {
for (field_type i = dest->start(), j = finish() + 1; i <= dest->finish();
++i, ++j) {
assert(child(j) != nullptr);
dest->init_child(i, child(j));
clear_child(j);
}
}
}
template <typename P>
void btree_node<P>::merge(btree_node *src, allocator_type *alloc) {
assert(parent() == src->parent());
assert(position() + 1 == src->position());
// Move the delimiting value to the left node.
value_init(finish(), alloc, parent()->slot(position()));
// Move the values from the right to the left node.
transfer_n(src->count(), finish() + 1, src->start(), src, alloc);
if (is_internal()) {
// Move the child pointers from the right to the left node.
for (field_type i = src->start(), j = finish() + 1; i <= src->finish();
++i, ++j) {
init_child(j, src->child(i));
src->clear_child(i);
}
}
// Fixup `finish` on the src and dest nodes.
set_finish(start() + 1 + count() + src->count());
src->set_finish(src->start());
// Remove the value on the parent node and delete the src node.
parent()->remove_values(position(), /*to_erase=*/1, alloc);
}
template <typename P>
void btree_node<P>::clear_and_delete(btree_node *node, allocator_type *alloc) {
if (node->is_leaf()) {
node->value_destroy_n(node->start(), node->count(), alloc);
deallocate(LeafSize(node->max_count()), node, alloc);
return;
}
if (node->count() == 0) {
deallocate(InternalSize(), node, alloc);
return;
}
// The parent of the root of the subtree we are deleting.
btree_node *delete_root_parent = node->parent();
// Navigate to the leftmost leaf under node, and then delete upwards.
while (node->is_internal()) node = node->start_child();
#ifdef ABSL_BTREE_ENABLE_GENERATIONS
// When generations are enabled, we delete the leftmost leaf last in case it's
// the parent of the root and we need to check whether it's a leaf before we
// can update the root's generation.
// TODO(ezb): if we change btree_node::is_root to check a bool inside the node
// instead of checking whether the parent is a leaf, we can remove this logic.
btree_node *leftmost_leaf = node;
#endif
// Use `size_type` because `pos` needs to be able to hold `kNodeSlots+1`,
// which isn't guaranteed to be a valid `field_type`.
size_type pos = node->position();
btree_node *parent = node->parent();
for (;;) {
// In each iteration of the next loop, we delete one leaf node and go right.
assert(pos <= parent->finish());
do {
node = parent->child(static_cast<field_type>(pos));
if (node->is_internal()) {
// Navigate to the leftmost leaf under node.
while (node->is_internal()) node = node->start_child();
pos = node->position();
parent = node->parent();
}
node->value_destroy_n(node->start(), node->count(), alloc);
#ifdef ABSL_BTREE_ENABLE_GENERATIONS
if (leftmost_leaf != node)
#endif
deallocate(LeafSize(node->max_count()), node, alloc);
++pos;
} while (pos <= parent->finish());
// Once we've deleted all children of parent, delete parent and go up/right.
assert(pos > parent->finish());
do {
node = parent;
pos = node->position();
parent = node->parent();
node->value_destroy_n(node->start(), node->count(), alloc);
deallocate(InternalSize(), node, alloc);
if (parent == delete_root_parent) {
#ifdef ABSL_BTREE_ENABLE_GENERATIONS
deallocate(LeafSize(leftmost_leaf->max_count()), leftmost_leaf, alloc);
#endif
return;
}
++pos;
} while (pos > parent->finish());
}
}
////
// btree_iterator methods
// Note: the implementation here is based on btree_node::clear_and_delete.
template <typename N, typename R, typename P>
auto btree_iterator<N, R, P>::distance_slow(const_iterator other) const
-> difference_type {
const_iterator begin = other;
const_iterator end = *this;
assert(begin.node_ != end.node_ || !begin.node_->is_leaf() ||
begin.position_ != end.position_);
const node_type *node = begin.node_;
// We need to compensate for double counting if begin.node_ is a leaf node.
difference_type count = node->is_leaf() ? -begin.position_ : 0;
// First navigate to the leftmost leaf node past begin.
if (node->is_internal()) {
++count;
node = node->child(begin.position_ + 1);
}
while (node->is_internal()) node = node->start_child();
// Use `size_type` because `pos` needs to be able to hold `kNodeSlots+1`,
// which isn't guaranteed to be a valid `field_type`.
size_type pos = node->position();
const node_type *parent = node->parent();
for (;;) {
// In each iteration of the next loop, we count one leaf node and go right.
assert(pos <= parent->finish());
do {
node = parent->child(static_cast<field_type>(pos));
if (node->is_internal()) {
// Navigate to the leftmost leaf under node.
while (node->is_internal()) node = node->start_child();
pos = node->position();
parent = node->parent();
}
if (node == end.node_) return count + end.position_;
if (parent == end.node_ && pos == static_cast<size_type>(end.position_))
return count + node->count();
// +1 is for the next internal node value.
count += node->count() + 1;
++pos;
} while (pos <= parent->finish());
// Once we've counted all children of parent, go up/right.
assert(pos > parent->finish());
do {
node = parent;
pos = node->position();
parent = node->parent();
// -1 because we counted the value at end and shouldn't.
if (parent == end.node_ && pos == static_cast<size_type>(end.position_))
return count - 1;
++pos;
} while (pos > parent->finish());
}
}
template <typename N, typename R, typename P>
void btree_iterator<N, R, P>::increment_slow() {
N* node = node_;
int position = position_;
if (node->is_leaf()) {
assert(position >= node->finish());
while (position == node->finish() && !node->is_root()) {
assert(node->parent()->child(node->position()) == node);
position = node->position();
node = node->parent();
}
// TODO(ezb): assert we aren't incrementing end() instead of handling.
if (position == node->finish()) {
return;
}
} else {
assert(position < node->finish());
node = node->child(static_cast<field_type>(position + 1));
while (node->is_internal()) {
node = node->start_child();
}
position = node->start();
}
*this = {node, position};
}
template <typename N, typename R, typename P>
void btree_iterator<N, R, P>::decrement_slow() {
N* node = node_;
int position = position_;
if (node->is_leaf()) {
assert(position <= -1);
while (position < node->start() && !node->is_root()) {
assert(node->parent()->child(node->position()) == node);
position = node->position() - 1;
node = node->parent();
}
// TODO(ezb): assert we aren't decrementing begin() instead of handling.
if (position < node->start()) {
return;
}
} else {
assert(position >= node->start());
node = node->child(static_cast<field_type>(position));
while (node->is_internal()) {
node = node->child(node->finish());
}
position = node->finish() - 1;
}
*this = {node, position};
}
template <typename N, typename R, typename P>
btree_iterator<N, R, P> &btree_iterator<N, R, P>::increment_n_slow(
difference_type n) {
N *node = node_;
int position = position_;
ABSL_ASSUME(n > 0);
while (n > 0) {
if (node->is_leaf()) {
if (position + n < node->finish()) {
position += n;
break;
} else {
n -= node->finish() - position;
position = node->finish();
btree_iterator save = {node, position};
while (position == node->finish() && !node->is_root()) {
position = node->position();
node = node->parent();
}
if (position == node->finish()) {
ABSL_HARDENING_ASSERT(n == 0);
return *this = save;
}
}
} else {
--n;
assert(position < node->finish());
node = node->child(static_cast<field_type>(position + 1));
while (node->is_internal()) {
node = node->start_child();
}
position = node->start();
}
}
node_ = node;
position_ = position;
return *this;
}
template <typename N, typename R, typename P>
btree_iterator<N, R, P> &btree_iterator<N, R, P>::decrement_n_slow(
difference_type n) {
N *node = node_;
int position = position_;
ABSL_ASSUME(n > 0);
while (n > 0) {
if (node->is_leaf()) {
if (position - n >= node->start()) {
position -= n;
break;
} else {
n -= 1 + position - node->start();
position = node->start() - 1;
while (position < node->start() && !node->is_root()) {
position = node->position() - 1;
node = node->parent();
}
ABSL_HARDENING_ASSERT(position >= node->start());
}
} else {
--n;
assert(position >= node->start());
node = node->child(static_cast<field_type>(position));
while (node->is_internal()) {
node = node->child(node->finish());
}
position = node->finish() - 1;
}
}
node_ = node;
position_ = position;
return *this;
}
////
// btree methods
template <typename P>
template <typename Btree>
void btree<P>::copy_or_move_values_in_order(Btree &other) {
static_assert(std::is_same<btree, Btree>::value ||
std::is_same<const btree, Btree>::value,
"Btree type must be same or const.");
assert(empty());
// We can avoid key comparisons because we know the order of the
// values is the same order we'll store them in.
auto iter = other.begin();
if (iter == other.end()) return;
insert_multi(iter.slot());
++iter;
for (; iter != other.end(); ++iter) {
// If the btree is not empty, we can just insert the new value at the end
// of the tree.
internal_emplace(end(), iter.slot());
}
}
template <typename P>
constexpr bool btree<P>::static_assert_validation() {
static_assert(std::is_nothrow_copy_constructible<key_compare>::value,
"Key comparison must be nothrow copy constructible");
static_assert(std::is_nothrow_copy_constructible<allocator_type>::value,
"Allocator must be nothrow copy constructible");
static_assert(std::is_trivially_copyable<iterator>::value,
"iterator not trivially copyable.");
// Note: We assert that kTargetValues, which is computed from
// Params::kTargetNodeSize, must fit the node_type::field_type.
static_assert(
kNodeSlots < (1 << (8 * sizeof(typename node_type::field_type))),
"target node size too large");
// Verify that key_compare returns an absl::{weak,strong}_ordering or bool.
static_assert(
compare_has_valid_result_type<key_compare, key_type>(),
"key comparison function must return absl::{weak,strong}_ordering or "
"bool.");
// Test the assumption made in setting kNodeSlotSpace.
static_assert(node_type::MinimumOverhead() >= sizeof(void *) + 4,
"node space assumption incorrect");
return true;
}
template <typename P>
template <typename K>
auto btree<P>::lower_bound_equal(const K &key) const
-> std::pair<iterator, bool> {
const SearchResult<iterator, is_key_compare_to::value> res =
internal_lower_bound(key);
const iterator lower = iterator(internal_end(res.value));
const bool equal = res.HasMatch()
? res.IsEq()
: lower != end() && !compare_keys(key, lower.key());
return {lower, equal};
}
template <typename P>
template <typename K>
auto btree<P>::equal_range(const K &key) -> std::pair<iterator, iterator> {
const std::pair<iterator, bool> lower_and_equal = lower_bound_equal(key);
const iterator lower = lower_and_equal.first;
if (!lower_and_equal.second) {
return {lower, lower};
}
const iterator next = std::next(lower);
if (!params_type::template can_have_multiple_equivalent_keys<K>()) {
// The next iterator after lower must point to a key greater than `key`.
// Note: if this assert fails, then it may indicate that the comparator does
// not meet the equivalence requirements for Compare
// (see https://en.cppreference.com/w/cpp/named_req/Compare).
assert(next == end() || compare_keys(key, next.key()));
return {lower, next};
}
// Try once more to avoid the call to upper_bound() if there's only one
// equivalent key. This should prevent all calls to upper_bound() in cases of
// unique-containers with heterogeneous comparators in which all comparison
// operators have the same equivalence classes.
if (next == end() || compare_keys(key, next.key())) return {lower, next};
// In this case, we need to call upper_bound() to avoid worst case O(N)
// behavior if we were to iterate over equal keys.
return {lower, upper_bound(key)};
}
template <typename P>
template <typename K, typename... Args>
auto btree<P>::insert_unique(const K &key, Args &&...args)
-> std::pair<iterator, bool> {
if (empty()) {
mutable_root() = mutable_rightmost() = new_leaf_root_node(1);
}
SearchResult<iterator, is_key_compare_to::value> res = internal_locate(key);
iterator iter = res.value;
if (res.HasMatch()) {
if (res.IsEq()) {
// The key already exists in the tree, do nothing.
return {iter, false};
}
} else {
iterator last = internal_last(iter);
if (last.node_ && !compare_keys(key, last.key())) {
// The key already exists in the tree, do nothing.
return {last, false};
}
}
return {internal_emplace(iter, std::forward<Args>(args)...), true};
}
template <typename P>
template <typename K, typename... Args>
inline auto btree<P>::insert_hint_unique(iterator position, const K &key,
Args &&...args)
-> std::pair<iterator, bool> {
if (!empty()) {
if (position == end() || compare_keys(key, position.key())) {
if (position == begin() || compare_keys(std::prev(position).key(), key)) {
// prev.key() < key < position.key()
return {internal_emplace(position, std::forward<Args>(args)...), true};
}
} else if (compare_keys(position.key(), key)) {
++position;
if (position == end() || compare_keys(key, position.key())) {
// {original `position`}.key() < key < {current `position`}.key()
return {internal_emplace(position, std::forward<Args>(args)...), true};
}
} else {
// position.key() == key
return {position, false};
}
}
return insert_unique(key, std::forward<Args>(args)...);
}
template <typename P>
template <typename InputIterator, typename>
void btree<P>::insert_iterator_unique(InputIterator b, InputIterator e, int) {
for (; b != e; ++b) {
insert_hint_unique(end(), params_type::key(*b), *b);
}
}
template <typename P>
template <typename InputIterator>
void btree<P>::insert_iterator_unique(InputIterator b, InputIterator e, char) {
for (; b != e; ++b) {
// Use a node handle to manage a temp slot.
auto node_handle =
CommonAccess::Construct<node_handle_type>(get_allocator(), *b);
slot_type *slot = CommonAccess::GetSlot(node_handle);
insert_hint_unique(end(), params_type::key(slot), slot);
}
}
template <typename P>
template <typename ValueType>
auto btree<P>::insert_multi(const key_type &key, ValueType &&v) -> iterator {
if (empty()) {
mutable_root() = mutable_rightmost() = new_leaf_root_node(1);
}
iterator iter = internal_upper_bound(key);
if (iter.node_ == nullptr) {
iter = end();
}
return internal_emplace(iter, std::forward<ValueType>(v));
}
template <typename P>
template <typename ValueType>
auto btree<P>::insert_hint_multi(iterator position, ValueType &&v) -> iterator {
if (!empty()) {
const key_type &key = params_type::key(v);
if (position == end() || !compare_keys(position.key(), key)) {
if (position == begin() ||
!compare_keys(key, std::prev(position).key())) {
// prev.key() <= key <= position.key()
return internal_emplace(position, std::forward<ValueType>(v));
}
} else {
++position;
if (position == end() || !compare_keys(position.key(), key)) {
// {original `position`}.key() < key < {current `position`}.key()
return internal_emplace(position, std::forward<ValueType>(v));
}
}
}
return insert_multi(std::forward<ValueType>(v));
}
template <typename P>
template <typename InputIterator>
void btree<P>::insert_iterator_multi(InputIterator b, InputIterator e) {
for (; b != e; ++b) {
insert_hint_multi(end(), *b);
}
}
template <typename P>
auto btree<P>::operator=(const btree &other) -> btree & {
if (this != &other) {
clear();
*mutable_key_comp() = other.key_comp();
if (absl::allocator_traits<
allocator_type>::propagate_on_container_copy_assignment::value) {
*mutable_allocator() = other.allocator();
}
copy_or_move_values_in_order(other);
}
return *this;
}
template <typename P>
auto btree<P>::operator=(btree &&other) noexcept -> btree & {
if (this != &other) {
clear();
using std::swap;
if (absl::allocator_traits<
allocator_type>::propagate_on_container_move_assignment::value) {
swap(root_, other.root_);
// Note: `rightmost_` also contains the allocator and the key comparator.
swap(rightmost_, other.rightmost_);
swap(size_, other.size_);
} else {
if (allocator() == other.allocator()) {
swap(mutable_root(), other.mutable_root());
swap(*mutable_key_comp(), *other.mutable_key_comp());
swap(mutable_rightmost(), other.mutable_rightmost());
swap(size_, other.size_);
} else {
// We aren't allowed to propagate the allocator and the allocator is
// different so we can't take over its memory. We must move each element
// individually. We need both `other` and `this` to have `other`s key
// comparator while moving the values so we can't swap the key
// comparators.
*mutable_key_comp() = other.key_comp();
copy_or_move_values_in_order(other);
}
}
}
return *this;
}
template <typename P>
auto btree<P>::erase(iterator iter) -> iterator {
iter.node_->value_destroy(static_cast<field_type>(iter.position_),
mutable_allocator());
iter.update_generation();
const bool internal_delete = iter.node_->is_internal();
if (internal_delete) {
// Deletion of a value on an internal node. First, transfer the largest
// value from our left child here, then erase/rebalance from that position.
// We can get to the largest value from our left child by decrementing iter.
iterator internal_iter(iter);
--iter;
assert(iter.node_->is_leaf());
internal_iter.node_->transfer(
static_cast<size_type>(internal_iter.position_),
static_cast<size_type>(iter.position_), iter.node_,
mutable_allocator());
} else {
// Shift values after erased position in leaf. In the internal case, we
// don't need to do this because the leaf position is the end of the node.
const field_type transfer_from =
static_cast<field_type>(iter.position_ + 1);
const field_type num_to_transfer = iter.node_->finish() - transfer_from;
iter.node_->transfer_n(num_to_transfer,
static_cast<size_type>(iter.position_),
transfer_from, iter.node_, mutable_allocator());
}
// Update node finish and container size.
iter.node_->set_finish(iter.node_->finish() - 1);
--size_;
// We want to return the next value after the one we just erased. If we
// erased from an internal node (internal_delete == true), then the next
// value is ++(++iter). If we erased from a leaf node (internal_delete ==
// false) then the next value is ++iter. Note that ++iter may point to an
// internal node and the value in the internal node may move to a leaf node
// (iter.node_) when rebalancing is performed at the leaf level.
iterator res = rebalance_after_delete(iter);
// If we erased from an internal node, advance the iterator.
if (internal_delete) {
++res;
}
return res;
}
template <typename P>
auto btree<P>::rebalance_after_delete(iterator iter) -> iterator {
// Merge/rebalance as we walk back up the tree.
iterator res(iter);
bool first_iteration = true;
for (;;) {
if (iter.node_ == root()) {
try_shrink();
if (empty()) {
return end();
}
break;
}
if (iter.node_->count() >= kMinNodeValues) {
break;
}
bool merged = try_merge_or_rebalance(&iter);
// On the first iteration, we should update `res` with `iter` because `res`
// may have been invalidated.
if (first_iteration) {
res = iter;
first_iteration = false;
}
if (!merged) {
break;
}
iter.position_ = iter.node_->position();
iter.node_ = iter.node_->parent();
}
res.update_generation();
// Adjust our return value. If we're pointing at the end of a node, advance
// the iterator.
if (res.position_ == res.node_->finish()) {
res.position_ = res.node_->finish() - 1;
++res;
}
return res;
}
// Note: we tried implementing this more efficiently by erasing all of the
// elements in [begin, end) at once and then doing rebalancing once at the end
// (rather than interleaving deletion and rebalancing), but that adds a lot of
// complexity, which seems to outweigh the performance win.
template <typename P>
auto btree<P>::erase_range(iterator begin, iterator end)
-> std::pair<size_type, iterator> {
size_type count = static_cast<size_type>(end - begin);
assert(count >= 0);
if (count == 0) {
return {0, begin};
}
if (static_cast<size_type>(count) == size_) {
clear();
return {count, this->end()};
}
if (begin.node_ == end.node_) {
assert(end.position_ > begin.position_);
begin.node_->remove_values(
static_cast<field_type>(begin.position_),
static_cast<field_type>(end.position_ - begin.position_),
mutable_allocator());
size_ -= count;
return {count, rebalance_after_delete(begin)};
}
const size_type target_size = size_ - count;
while (size_ > target_size) {
if (begin.node_->is_leaf()) {
const size_type remaining_to_erase = size_ - target_size;
const size_type remaining_in_node =
static_cast<size_type>(begin.node_->finish() - begin.position_);
const field_type to_erase = static_cast<field_type>(
(std::min)(remaining_to_erase, remaining_in_node));
begin.node_->remove_values(static_cast<field_type>(begin.position_),
to_erase, mutable_allocator());
size_ -= to_erase;
begin = rebalance_after_delete(begin);
} else {
begin = erase(begin);
}
}
begin.update_generation();
return {count, begin};
}
template <typename P>
void btree<P>::clear() {
if (!empty()) {
node_type::clear_and_delete(root(), mutable_allocator());
}
mutable_root() = mutable_rightmost() = EmptyNode();
size_ = 0;
}
template <typename P>
void btree<P>::swap(btree &other) {
using std::swap;
if (absl::allocator_traits<
allocator_type>::propagate_on_container_swap::value) {
// Note: `rightmost_` also contains the allocator and the key comparator.
swap(rightmost_, other.rightmost_);
} else {
// It's undefined behavior if the allocators are unequal here.
assert(allocator() == other.allocator());
swap(mutable_rightmost(), other.mutable_rightmost());
swap(*mutable_key_comp(), *other.mutable_key_comp());
}
swap(mutable_root(), other.mutable_root());
swap(size_, other.size_);
}
template <typename P>
void btree<P>::verify() const {
assert(root() != nullptr);
assert(leftmost() != nullptr);
assert(rightmost() != nullptr);
assert(empty() || size() == internal_verify(root(), nullptr, nullptr));
assert(leftmost() == (++const_iterator(root(), -1)).node_);
assert(rightmost() == (--const_iterator(root(), root()->finish())).node_);
assert(leftmost()->is_leaf());
assert(rightmost()->is_leaf());
}
template <typename P>
void btree<P>::rebalance_or_split(iterator *iter) {
node_type *&node = iter->node_;
int &insert_position = iter->position_;
assert(node->count() == node->max_count());
assert(kNodeSlots == node->max_count());
// First try to make room on the node by rebalancing.
node_type *parent = node->parent();
if (node != root()) {
if (node->position() > parent->start()) {
// Try rebalancing with our left sibling.
node_type *left = parent->child(node->position() - 1);
assert(left->max_count() == kNodeSlots);
if (left->count() < kNodeSlots) {
// We bias rebalancing based on the position being inserted. If we're
// inserting at the end of the right node then we bias rebalancing to
// fill up the left node.
field_type to_move =
(kNodeSlots - left->count()) /
(1 + (static_cast<field_type>(insert_position) < kNodeSlots));
to_move = (std::max)(field_type{1}, to_move);
if (static_cast<field_type>(insert_position) - to_move >=
node->start() ||
left->count() + to_move < kNodeSlots) {
left->rebalance_right_to_left(to_move, node, mutable_allocator());
assert(node->max_count() - node->count() == to_move);
insert_position = static_cast<int>(
static_cast<field_type>(insert_position) - to_move);
if (insert_position < node->start()) {
insert_position = insert_position + left->count() + 1;
node = left;
}
assert(node->count() < node->max_count());
return;
}
}
}
if (node->position() < parent->finish()) {
// Try rebalancing with our right sibling.
node_type *right = parent->child(node->position() + 1);
assert(right->max_count() == kNodeSlots);
if (right->count() < kNodeSlots) {
// We bias rebalancing based on the position being inserted. If we're
// inserting at the beginning of the left node then we bias rebalancing
// to fill up the right node.
field_type to_move = (kNodeSlots - right->count()) /
(1 + (insert_position > node->start()));
to_move = (std::max)(field_type{1}, to_move);
if (static_cast<field_type>(insert_position) <=
node->finish() - to_move ||
right->count() + to_move < kNodeSlots) {
node->rebalance_left_to_right(to_move, right, mutable_allocator());
if (insert_position > node->finish()) {
insert_position = insert_position - node->count() - 1;
node = right;
}
assert(node->count() < node->max_count());
return;
}
}
}
// Rebalancing failed, make sure there is room on the parent node for a new
// value.
assert(parent->max_count() == kNodeSlots);
if (parent->count() == kNodeSlots) {
iterator parent_iter(parent, node->position());
rebalance_or_split(&parent_iter);
parent = node->parent();
}
} else {
// Rebalancing not possible because this is the root node.
// Create a new root node and set the current root node as the child of the
// new root.
parent = new_internal_node(/*position=*/0, parent);
parent->set_generation(root()->generation());
parent->init_child(parent->start(), node);
mutable_root() = parent;
// If the former root was a leaf node, then it's now the rightmost node.
assert(parent->start_child()->is_internal() ||
parent->start_child() == rightmost());
}
// Split the node.
node_type *split_node;
if (node->is_leaf()) {
split_node = new_leaf_node(node->position() + 1, parent);
node->split(insert_position, split_node, mutable_allocator());
if (rightmost() == node) mutable_rightmost() = split_node;
} else {
split_node = new_internal_node(node->position() + 1, parent);
node->split(insert_position, split_node, mutable_allocator());
}
if (insert_position > node->finish()) {
insert_position = insert_position - node->count() - 1;
node = split_node;
}
}
template <typename P>
void btree<P>::merge_nodes(node_type *left, node_type *right) {
left->merge(right, mutable_allocator());
if (rightmost() == right) mutable_rightmost() = left;
}
template <typename P>
bool btree<P>::try_merge_or_rebalance(iterator *iter) {
node_type *parent = iter->node_->parent();
if (iter->node_->position() > parent->start()) {
// Try merging with our left sibling.
node_type *left = parent->child(iter->node_->position() - 1);
assert(left->max_count() == kNodeSlots);
if (1U + left->count() + iter->node_->count() <= kNodeSlots) {
iter->position_ += 1 + left->count();
merge_nodes(left, iter->node_);
iter->node_ = left;
return true;
}
}
if (iter->node_->position() < parent->finish()) {
// Try merging with our right sibling.
node_type *right = parent->child(iter->node_->position() + 1);
assert(right->max_count() == kNodeSlots);
if (1U + iter->node_->count() + right->count() <= kNodeSlots) {
merge_nodes(iter->node_, right);
return true;
}
// Try rebalancing with our right sibling. We don't perform rebalancing if
// we deleted the first element from iter->node_ and the node is not
// empty. This is a small optimization for the common pattern of deleting
// from the front of the tree.
if (right->count() > kMinNodeValues &&
(iter->node_->count() == 0 || iter->position_ > iter->node_->start())) {
field_type to_move = (right->count() - iter->node_->count()) / 2;
to_move =
(std::min)(to_move, static_cast<field_type>(right->count() - 1));
iter->node_->rebalance_right_to_left(to_move, right, mutable_allocator());
return false;
}
}
if (iter->node_->position() > parent->start()) {
// Try rebalancing with our left sibling. We don't perform rebalancing if
// we deleted the last element from iter->node_ and the node is not
// empty. This is a small optimization for the common pattern of deleting
// from the back of the tree.
node_type *left = parent->child(iter->node_->position() - 1);
if (left->count() > kMinNodeValues &&
(iter->node_->count() == 0 ||
iter->position_ < iter->node_->finish())) {
field_type to_move = (left->count() - iter->node_->count()) / 2;
to_move = (std::min)(to_move, static_cast<field_type>(left->count() - 1));
left->rebalance_left_to_right(to_move, iter->node_, mutable_allocator());
iter->position_ += to_move;
return false;
}
}
return false;
}
template <typename P>
void btree<P>::try_shrink() {
node_type *orig_root = root();
if (orig_root->count() > 0) {
return;
}
// Deleted the last item on the root node, shrink the height of the tree.
if (orig_root->is_leaf()) {
assert(size() == 0);
mutable_root() = mutable_rightmost() = EmptyNode();
} else {
node_type *child = orig_root->start_child();
child->make_root();
mutable_root() = child;
}
node_type::clear_and_delete(orig_root, mutable_allocator());
}
template <typename P>
template <typename IterType>
inline IterType btree<P>::internal_last(IterType iter) {
assert(iter.node_ != nullptr);
while (iter.position_ == iter.node_->finish()) {
iter.position_ = iter.node_->position();
iter.node_ = iter.node_->parent();
if (iter.node_->is_leaf()) {
iter.node_ = nullptr;
break;
}
}
iter.update_generation();
return iter;
}
template <typename P>
template <typename... Args>
inline auto btree<P>::internal_emplace(iterator iter, Args &&...args)
-> iterator {
if (iter.node_->is_internal()) {
// We can't insert on an internal node. Instead, we'll insert after the
// previous value which is guaranteed to be on a leaf node.
--iter;
++iter.position_;
}
const field_type max_count = iter.node_->max_count();
allocator_type *alloc = mutable_allocator();
const auto transfer_and_delete = [&](node_type *old_node,
node_type *new_node) {
new_node->transfer_n(old_node->count(), new_node->start(),
old_node->start(), old_node, alloc);
new_node->set_finish(old_node->finish());
old_node->set_finish(old_node->start());
new_node->set_generation(old_node->generation());
node_type::clear_and_delete(old_node, alloc);
};
const auto replace_leaf_root_node = [&](field_type new_node_size) {
assert(iter.node_ == root());
node_type *old_root = iter.node_;
node_type *new_root = iter.node_ = new_leaf_root_node(new_node_size);
transfer_and_delete(old_root, new_root);
mutable_root() = mutable_rightmost() = new_root;
};
bool replaced_node = false;
if (iter.node_->count() == max_count) {
// Make room in the leaf for the new item.
if (max_count < kNodeSlots) {
// Insertion into the root where the root is smaller than the full node
// size. Simply grow the size of the root node.
replace_leaf_root_node(static_cast<field_type>(
(std::min)(static_cast<int>(kNodeSlots), 2 * max_count)));
replaced_node = true;
} else {
rebalance_or_split(&iter);
}
}
(void)replaced_node;
#if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \
defined(ABSL_HAVE_HWADDRESS_SANITIZER)
if (!replaced_node) {
assert(iter.node_->is_leaf());
if (iter.node_->is_root()) {
replace_leaf_root_node(max_count);
} else {
node_type *old_node = iter.node_;
const bool was_rightmost = rightmost() == old_node;
const bool was_leftmost = leftmost() == old_node;
node_type *parent = old_node->parent();
const field_type position = old_node->position();
node_type *new_node = iter.node_ = new_leaf_node(position, parent);
parent->set_child_noupdate_position(position, new_node);
transfer_and_delete(old_node, new_node);
if (was_rightmost) mutable_rightmost() = new_node;
// The leftmost node is stored as the parent of the root node.
if (was_leftmost) root()->set_parent(new_node);
}
}
#endif
iter.node_->emplace_value(static_cast<field_type>(iter.position_), alloc,
std::forward<Args>(args)...);
assert(
iter.node_->is_ordered_correctly(static_cast<field_type>(iter.position_),
original_key_compare(key_comp())) &&
"If this assert fails, then either (1) the comparator may violate "
"transitivity, i.e. comp(a,b) && comp(b,c) -> comp(a,c) (see "
"https://en.cppreference.com/w/cpp/named_req/Compare), or (2) a "
"key may have been mutated after it was inserted into the tree.");
++size_;
iter.update_generation();
return iter;
}
template <typename P>
template <typename K>
inline auto btree<P>::internal_locate(const K &key) const
-> SearchResult<iterator, is_key_compare_to::value> {
iterator iter(const_cast<node_type *>(root()));
for (;;) {
SearchResult<size_type, is_key_compare_to::value> res =
iter.node_->lower_bound(key, key_comp());
iter.position_ = static_cast<int>(res.value);
if (res.IsEq()) {
return {iter, MatchKind::kEq};
}
// Note: in the non-key-compare-to case, we don't need to walk all the way
// down the tree if the keys are equal, but determining equality would
// require doing an extra comparison on each node on the way down, and we
// will need to go all the way to the leaf node in the expected case.
if (iter.node_->is_leaf()) {
break;
}
iter.node_ = iter.node_->child(static_cast<field_type>(iter.position_));
}
// Note: in the non-key-compare-to case, the key may actually be equivalent
// here (and the MatchKind::kNe is ignored).
return {iter, MatchKind::kNe};
}
template <typename P>
template <typename K>
auto btree<P>::internal_lower_bound(const K &key) const
-> SearchResult<iterator, is_key_compare_to::value> {
if (!params_type::template can_have_multiple_equivalent_keys<K>()) {
SearchResult<iterator, is_key_compare_to::value> ret = internal_locate(key);
ret.value = internal_last(ret.value);
return ret;
}
iterator iter(const_cast<node_type *>(root()));
SearchResult<size_type, is_key_compare_to::value> res;
bool seen_eq = false;
for (;;) {
res = iter.node_->lower_bound(key, key_comp());
iter.position_ = static_cast<int>(res.value);
if (iter.node_->is_leaf()) {
break;
}
seen_eq = seen_eq || res.IsEq();
iter.node_ = iter.node_->child(static_cast<field_type>(iter.position_));
}
if (res.IsEq()) return {iter, MatchKind::kEq};
return {internal_last(iter), seen_eq ? MatchKind::kEq : MatchKind::kNe};
}
template <typename P>
template <typename K>
auto btree<P>::internal_upper_bound(const K &key) const -> iterator {
iterator iter(const_cast<node_type *>(root()));
for (;;) {
iter.position_ = static_cast<int>(iter.node_->upper_bound(key, key_comp()));
if (iter.node_->is_leaf()) {
break;
}
iter.node_ = iter.node_->child(static_cast<field_type>(iter.position_));
}
return internal_last(iter);
}
template <typename P>
template <typename K>
auto btree<P>::internal_find(const K &key) const -> iterator {
SearchResult<iterator, is_key_compare_to::value> res = internal_locate(key);
if (res.HasMatch()) {
if (res.IsEq()) {
return res.value;
}
} else {
const iterator iter = internal_last(res.value);
if (iter.node_ != nullptr && !compare_keys(key, iter.key())) {
return iter;
}
}
return {nullptr, 0};
}
template <typename P>
typename btree<P>::size_type btree<P>::internal_verify(
const node_type *node, const key_type *lo, const key_type *hi) const {
assert(node->count() > 0);
assert(node->count() <= node->max_count());
if (lo) {
assert(!compare_keys(node->key(node->start()), *lo));
}
if (hi) {
assert(!compare_keys(*hi, node->key(node->finish() - 1)));
}
for (int i = node->start() + 1; i < node->finish(); ++i) {
assert(!compare_keys(node->key(i), node->key(i - 1)));
}
size_type count = node->count();
if (node->is_internal()) {
for (field_type i = node->start(); i <= node->finish(); ++i) {
assert(node->child(i) != nullptr);
assert(node->child(i)->parent() == node);
assert(node->child(i)->position() == i);
count += internal_verify(node->child(i),
i == node->start() ? lo : &node->key(i - 1),
i == node->finish() ? hi : &node->key(i));
}
}
return count;
}
struct btree_access {
template <typename BtreeContainer, typename Pred>
static auto erase_if(BtreeContainer &container, Pred pred) ->
typename BtreeContainer::size_type {
const auto initial_size = container.size();
auto &tree = container.tree_;
auto *alloc = tree.mutable_allocator();
for (auto it = container.begin(); it != container.end();) {
if (!pred(*it)) {
++it;
continue;
}
auto *node = it.node_;
if (node->is_internal()) {
// Handle internal nodes normally.
it = container.erase(it);
continue;
}
// If this is a leaf node, then we do all the erases from this node
// at once before doing rebalancing.
// The current position to transfer slots to.
int to_pos = it.position_;
node->value_destroy(it.position_, alloc);
while (++it.position_ < node->finish()) {
it.update_generation();
if (pred(*it)) {
node->value_destroy(it.position_, alloc);
} else {
node->transfer(node->slot(to_pos++), node->slot(it.position_), alloc);
}
}
const int num_deleted = node->finish() - to_pos;
tree.size_ -= num_deleted;
node->set_finish(to_pos);
it.position_ = to_pos;
it = tree.rebalance_after_delete(it);
}
return initial_size - container.size();
}
};
#undef ABSL_BTREE_ENABLE_GENERATIONS
} // namespace container_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_CONTAINER_INTERNAL_BTREE_H_
*°%
ksoong/.intermediates/external/abseil-cpp/absl_types_span_hdrs/gen/my_include_dir/absl/types/internal/span.hÀ$//
// Copyright 2019 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifndef ABSL_TYPES_INTERNAL_SPAN_H_
#define ABSL_TYPES_INTERNAL_SPAN_H_
#include <algorithm>
#include <cstddef>
#include <string>
#include <type_traits>
#include "absl/algorithm/algorithm.h"
#include "absl/base/config.h"
#include "absl/base/internal/throw_delegate.h"
#include "absl/meta/type_traits.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
template <typename T>
class Span;
namespace span_internal {
// Wrappers for access to container data pointers.
template <typename C>
constexpr auto GetDataImpl(C& c, char) noexcept // NOLINT(runtime/references)
-> decltype(c.data()) {
return c.data();
}
// Before C++17, std::string::data returns a const char* in all cases.
inline char* GetDataImpl(std::string& s, // NOLINT(runtime/references)
int) noexcept {
return &s[0];
}
template <typename C>
constexpr auto GetData(C& c) noexcept // NOLINT(runtime/references)
-> decltype(GetDataImpl(c, 0)) {
return GetDataImpl(c, 0);
}
// Detection idioms for size() and data().
template <typename C>
using HasSize =
std::is_integral<absl::decay_t<decltype(std::declval<C&>().size())>>;
// We want to enable conversion from vector<T*> to Span<const T* const> but
// disable conversion from vector<Derived> to Span<Base>. Here we use
// the fact that U** is convertible to Q* const* if and only if Q is the same
// type or a more cv-qualified version of U. We also decay the result type of
// data() to avoid problems with classes which have a member function data()
// which returns a reference.
template <typename T, typename C>
using HasData =
std::is_convertible<absl::decay_t<decltype(GetData(std::declval<C&>()))>*,
T* const*>;
// Extracts value type from a Container
template <typename C>
struct ElementType {
using type = typename absl::remove_reference_t<C>::value_type;
};
template <typename T, size_t N>
struct ElementType<T (&)[N]> {
using type = T;
};
template <typename C>
using ElementT = typename ElementType<C>::type;
template <typename T>
using EnableIfMutable =
typename std::enable_if<!std::is_const<T>::value, int>::type;
template <template <typename> class SpanT, typename T>
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool EqualImpl(SpanT<T> a, SpanT<T> b) {
static_assert(std::is_const<T>::value, "");
return std::equal(a.begin(), a.end(), b.begin(), b.end());
}
template <template <typename> class SpanT, typename T>
ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool LessThanImpl(SpanT<T> a, SpanT<T> b) {
// We can't use value_type since that is remove_cv_t<T>, so we go the long way
// around.
static_assert(std::is_const<T>::value, "");
return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());
}
template <typename From, typename To>
using EnableIfConvertibleTo =
typename std::enable_if<std::is_convertible<From, To>::value>::type;
// IsView is true for types where the return type of .data() is the same for
// mutable and const instances. This isn't foolproof, but it's only used to
// enable a compiler warning.
template <typename T, typename = void, typename = void>
struct IsView {
static constexpr bool value = false;
};
template <typename T>
struct IsView<
T, absl::void_t<decltype(span_internal::GetData(std::declval<const T&>()))>,
absl::void_t<decltype(span_internal::GetData(std::declval<T&>()))>> {
private:
using Container = std::remove_const_t<T>;
using ConstData =
decltype(span_internal::GetData(std::declval<const Container&>()));
using MutData = decltype(span_internal::GetData(std::declval<Container&>()));
public:
static constexpr bool value = std::is_same<ConstData, MutData>::value;
};
// These enablers result in 'int' so they can be used as typenames or defaults
// in template parameters lists.
template <typename T>
using EnableIfIsView = std::enable_if_t<IsView<T>::value, int>;
template <typename T>
using EnableIfNotIsView = std::enable_if_t<!IsView<T>::value, int>;
} // namespace span_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_TYPES_INTERNAL_SPAN_H_
dsoong/.intermediates/external/abseil-cpp/absl_utility_hdrs/gen/my_include_dir/absl/utility/utility.hÜ // Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_UTILITY_UTILITY_H_
#define ABSL_UTILITY_UTILITY_H_
#include <cstddef>
#include <cstdlib>
#include <tuple>
#include <utility>
#include "absl/base/config.h"
// TODO(b/290784225): Include what you use cleanup required.
#include "absl/meta/type_traits.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
// Historical note: Abseil once provided implementations of these
// abstractions for platforms that had not yet provided them. Those
// platforms are no longer supported. New code should simply use the
// the ones from std directly.
using std::apply;
using std::exchange;
using std::forward;
using std::in_place;
using std::in_place_index;
using std::in_place_index_t;
using std::in_place_t;
using std::in_place_type;
using std::in_place_type_t;
using std::index_sequence;
using std::index_sequence_for;
using std::integer_sequence;
using std::make_from_tuple;
using std::make_index_sequence;
using std::make_integer_sequence;
using std::move;
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_UTILITY_UTILITY_H_
*ëø
wsoong/.intermediates/external/abseil-cpp/absl_container_layout_hdrs/gen/my_include_dir/absl/container/internal/layout.hî÷// Copyright 2018 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// MOTIVATION AND TUTORIAL
//
// If you want to put in a single heap allocation N doubles followed by M ints,
// it's easy if N and M are known at compile time.
//
// struct S {
// double a[N];
// int b[M];
// };
//
// S* p = new S;
//
// But what if N and M are known only in run time? Class template Layout to the
// rescue! It's a portable generalization of the technique known as struct hack.
//
// // This object will tell us everything we need to know about the memory
// // layout of double[N] followed by int[M]. It's structurally identical to
// // size_t[2] that stores N and M. It's very cheap to create.
// const Layout<double, int> layout(N, M);
//
// // Allocate enough memory for both arrays. `AllocSize()` tells us how much
// // memory is needed. We are free to use any allocation function we want as
// // long as it returns aligned memory.
// std::unique_ptr<unsigned char[]> p(new unsigned char[layout.AllocSize()]);
//
// // Obtain the pointer to the array of doubles.
// // Equivalent to `reinterpret_cast<double*>(p.get())`.
// //
// // We could have written layout.Pointer<0>(p) instead. If all the types are
// // unique you can use either form, but if some types are repeated you must
// // use the index form.
// double* a = layout.Pointer<double>(p.get());
//
// // Obtain the pointer to the array of ints.
// // Equivalent to `reinterpret_cast<int*>(p.get() + N * 8)`.
// int* b = layout.Pointer<int>(p);
//
// If we are unable to specify sizes of all fields, we can pass as many sizes as
// we can to `Partial()`. In return, it'll allow us to access the fields whose
// locations and sizes can be computed from the provided information.
// `Partial()` comes in handy when the array sizes are embedded into the
// allocation.
//
// // size_t[0] containing N, size_t[1] containing M, double[N], int[M].
// using L = Layout<size_t, size_t, double, int>;
//
// unsigned char* Allocate(size_t n, size_t m) {
// const L layout(1, 1, n, m);
// unsigned char* p = new unsigned char[layout.AllocSize()];
// *layout.Pointer<0>(p) = n;
// *layout.Pointer<1>(p) = m;
// return p;
// }
//
// void Use(unsigned char* p) {
// // First, extract N and M.
// // Specify that the first array has only one element. Using `prefix` we
// // can access the first two arrays but not more.
// constexpr auto prefix = L::Partial(1);
// size_t n = *prefix.Pointer<0>(p);
// size_t m = *prefix.Pointer<1>(p);
//
// // Now we can get pointers to the payload.
// const L layout(1, 1, n, m);
// double* a = layout.Pointer<double>(p);
// int* b = layout.Pointer<int>(p);
// }
//
// The layout we used above combines fixed-size with dynamically-sized fields.
// This is quite common. Layout is optimized for this use case and attempts to
// generate optimal code. To help the compiler do that in more cases, you can
// specify the fixed sizes using `WithStaticSizes`. This ensures that all
// computations that can be performed at compile time are indeed performed at
// compile time. Note that sometimes the `template` keyword is needed. E.g.:
//
// using SL = L::template WithStaticSizes<1, 1>;
//
// void Use(unsigned char* p) {
// // First, extract N and M.
// // Using `prefix` we can access the first three arrays but not more.
// //
// // More details: The first element always has offset 0. `SL`
// // has offsets for the second and third array based on sizes of
// // the first and second array, specified via `WithStaticSizes`.
// constexpr auto prefix = SL::Partial();
// size_t n = *prefix.Pointer<0>(p);
// size_t m = *prefix.Pointer<1>(p);
//
// // Now we can get a pointer to the final payload.
// const SL layout(n, m);
// double* a = layout.Pointer<double>(p);
// int* b = layout.Pointer<int>(p);
// }
//
// Efficiency tip: The order of fields matters. In `Layout<T1, ..., TN>` try to
// ensure that `alignof(T1) >= ... >= alignof(TN)`. This way you'll have no
// padding in between arrays.
//
// You can manually override the alignment of an array by wrapping the type in
// `Aligned<T, N>`. `Layout<..., Aligned<T, N>, ...>` has exactly the same API
// and behavior as `Layout<..., T, ...>` except that the first element of the
// array of `T` is aligned to `N` (the rest of the elements follow without
// padding). `N` cannot be less than `alignof(T)`.
//
// `AllocSize()` and `Pointer()` are the most basic methods for dealing with
// memory layouts. Check out the reference or code below to discover more.
//
// EXAMPLE
//
// // Immutable move-only string with sizeof equal to sizeof(void*). The
// // string size and the characters are kept in the same heap allocation.
// class CompactString {
// public:
// CompactString(const char* s = "") {
// const size_t size = strlen(s);
// // size_t[1] followed by char[size + 1].
// const L layout(size + 1);
// p_.reset(new unsigned char[layout.AllocSize()]);
// // If running under ASAN, mark the padding bytes, if any, to catch
// // memory errors.
// layout.PoisonPadding(p_.get());
// // Store the size in the allocation.
// *layout.Pointer<size_t>(p_.get()) = size;
// // Store the characters in the allocation.
// memcpy(layout.Pointer<char>(p_.get()), s, size + 1);
// }
//
// size_t size() const {
// // Equivalent to reinterpret_cast<size_t&>(*p).
// return *L::Partial().Pointer<size_t>(p_.get());
// }
//
// const char* c_str() const {
// // Equivalent to reinterpret_cast<char*>(p.get() + sizeof(size_t)).
// return L::Partial().Pointer<char>(p_.get());
// }
//
// private:
// // Our heap allocation contains a single size_t followed by an array of
// // chars.
// using L = Layout<size_t, char>::WithStaticSizes<1>;
// std::unique_ptr<unsigned char[]> p_;
// };
//
// int main() {
// CompactString s = "hello";
// assert(s.size() == 5);
// assert(strcmp(s.c_str(), "hello") == 0);
// }
//
// DOCUMENTATION
//
// The interface exported by this file consists of:
// - class `Layout<>` and its public members.
// - The public members of classes `internal_layout::LayoutWithStaticSizes<>`
// and `internal_layout::LayoutImpl<>`. Those classes aren't intended to be
// used directly, and their name and template parameter list are internal
// implementation details, but the classes themselves provide most of the
// functionality in this file. See comments on their members for detailed
// documentation.
//
// `Layout<T1,... Tn>::Partial(count1,..., countm)` (where `m` <= `n`) returns a
// `LayoutImpl<>` object. `Layout<T1,..., Tn> layout(count1,..., countn)`
// creates a `Layout` object, which exposes the same functionality by inheriting
// from `LayoutImpl<>`.
#ifndef ABSL_CONTAINER_INTERNAL_LAYOUT_H_
#define ABSL_CONTAINER_INTERNAL_LAYOUT_H_
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <array>
#include <string>
#include <tuple>
#include <type_traits>
#include <typeinfo>
#include <utility>
#include "absl/base/config.h"
#include "absl/debugging/internal/demangle.h"
#include "absl/meta/type_traits.h"
#include "absl/strings/str_cat.h"
#include "absl/types/span.h"
#include "absl/utility/utility.h"
#ifdef ABSL_HAVE_ADDRESS_SANITIZER
#include <sanitizer/asan_interface.h>
#endif
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace container_internal {
// A type wrapper that instructs `Layout` to use the specific alignment for the
// array. `Layout<..., Aligned<T, N>, ...>` has exactly the same API
// and behavior as `Layout<..., T, ...>` except that the first element of the
// array of `T` is aligned to `N` (the rest of the elements follow without
// padding).
//
// Requires: `N >= alignof(T)` and `N` is a power of 2.
template <class T, size_t N>
struct Aligned;
namespace internal_layout {
template <class T>
struct NotAligned {};
template <class T, size_t N>
struct NotAligned<const Aligned<T, N>> {
static_assert(sizeof(T) == 0, "Aligned<T, N> cannot be const-qualified");
};
template <size_t>
using IntToSize = size_t;
template <class T>
struct Type : NotAligned<T> {
using type = T;
};
template <class T, size_t N>
struct Type<Aligned<T, N>> {
using type = T;
};
template <class T>
struct SizeOf : NotAligned<T>, std::integral_constant<size_t, sizeof(T)> {};
template <class T, size_t N>
struct SizeOf<Aligned<T, N>> : std::integral_constant<size_t, sizeof(T)> {};
// Note: workaround for https://gcc.gnu.org/PR88115
template <class T>
struct AlignOf : NotAligned<T> {
static constexpr size_t value = alignof(T);
};
template <class T, size_t N>
struct AlignOf<Aligned<T, N>> {
static_assert(N % alignof(T) == 0,
"Custom alignment can't be lower than the type's alignment");
static constexpr size_t value = N;
};
// Does `Ts...` contain `T`?
template <class T, class... Ts>
using Contains = absl::disjunction<std::is_same<T, Ts>...>;
template <class From, class To>
using CopyConst =
typename std::conditional<std::is_const<From>::value, const To, To>::type;
// Note: We're not qualifying this with absl:: because it doesn't compile under
// MSVC.
template <class T>
using SliceType = Span<T>;
// This namespace contains no types. It prevents functions defined in it from
// being found by ADL.
namespace adl_barrier {
template <class Needle, class... Ts>
constexpr size_t Find(Needle, Needle, Ts...) {
static_assert(!Contains<Needle, Ts...>(), "Duplicate element type");
return 0;
}
template <class Needle, class T, class... Ts>
constexpr size_t Find(Needle, T, Ts...) {
return adl_barrier::Find(Needle(), Ts()...) + 1;
}
constexpr bool IsPow2(size_t n) { return !(n & (n - 1)); }
// Returns `q * m` for the smallest `q` such that `q * m >= n`.
// Requires: `m` is a power of two. It's enforced by IsLegalElementType below.
constexpr size_t Align(size_t n, size_t m) { return (n + m - 1) & ~(m - 1); }
constexpr size_t Min(size_t a, size_t b) { return b < a ? b : a; }
constexpr size_t Max(size_t a) { return a; }
template <class... Ts>
constexpr size_t Max(size_t a, size_t b, Ts... rest) {
return adl_barrier::Max(b < a ? a : b, rest...);
}
template <class T>
std::string TypeName() {
std::string out;
#ifdef ABSL_INTERNAL_HAS_RTTI
absl::StrAppend(&out, "<",
absl::debugging_internal::DemangleString(typeid(T).name()),
">");
#endif
return out;
}
} // namespace adl_barrier
// Can `T` be a template argument of `Layout`?
template <class T>
using IsLegalElementType = std::integral_constant<
bool, !std::is_reference<T>::value && !std::is_volatile<T>::value &&
!std::is_reference<typename Type<T>::type>::value &&
!std::is_volatile<typename Type<T>::type>::value &&
adl_barrier::IsPow2(AlignOf<T>::value)>;
template <class Elements, class StaticSizeSeq, class RuntimeSizeSeq,
class SizeSeq, class OffsetSeq>
class LayoutImpl;
// Public base class of `Layout` and the result type of `Layout::Partial()`.
//
// `Elements...` contains all template arguments of `Layout` that created this
// instance.
//
// `StaticSizeSeq...` is an index_sequence containing the sizes specified at
// compile-time.
//
// `RuntimeSizeSeq...` is `[0, NumRuntimeSizes)`, where `NumRuntimeSizes` is the
// number of arguments passed to `Layout::Partial()` or `Layout::Layout()`.
//
// `SizeSeq...` is `[0, NumSizes)` where `NumSizes` is `NumRuntimeSizes` plus
// the number of sizes in `StaticSizeSeq`.
//
// `OffsetSeq...` is `[0, NumOffsets)` where `NumOffsets` is
// `Min(sizeof...(Elements), NumSizes + 1)` (the number of arrays for which we
// can compute offsets).
template <class... Elements, size_t... StaticSizeSeq, size_t... RuntimeSizeSeq,
size_t... SizeSeq, size_t... OffsetSeq>
class LayoutImpl<
std::tuple<Elements...>, absl::index_sequence<StaticSizeSeq...>,
absl::index_sequence<RuntimeSizeSeq...>, absl::index_sequence<SizeSeq...>,
absl::index_sequence<OffsetSeq...>> {
private:
static_assert(sizeof...(Elements) > 0, "At least one field is required");
static_assert(absl::conjunction<IsLegalElementType<Elements>...>::value,
"Invalid element type (see IsLegalElementType)");
static_assert(sizeof...(StaticSizeSeq) <= sizeof...(Elements),
"Too many static sizes specified");
enum {
NumTypes = sizeof...(Elements),
NumStaticSizes = sizeof...(StaticSizeSeq),
NumRuntimeSizes = sizeof...(RuntimeSizeSeq),
NumSizes = sizeof...(SizeSeq),
NumOffsets = sizeof...(OffsetSeq),
};
// These are guaranteed by `Layout`.
static_assert(NumStaticSizes + NumRuntimeSizes == NumSizes, "Internal error");
static_assert(NumSizes <= NumTypes, "Internal error");
static_assert(NumOffsets == adl_barrier::Min(NumTypes, NumSizes + 1),
"Internal error");
static_assert(NumTypes > 0, "Internal error");
static constexpr std::array<size_t, sizeof...(StaticSizeSeq)> kStaticSizes = {
StaticSizeSeq...};
// Returns the index of `T` in `Elements...`. Results in a compilation error
// if `Elements...` doesn't contain exactly one instance of `T`.
template <class T>
static constexpr size_t ElementIndex() {
static_assert(Contains<Type<T>, Type<typename Type<Elements>::type>...>(),
"Type not found");
return adl_barrier::Find(Type<T>(),
Type<typename Type<Elements>::type>()...);
}
template <size_t N>
using ElementAlignment =
AlignOf<typename std::tuple_element<N, std::tuple<Elements...>>::type>;
public:
// Element types of all arrays packed in a tuple.
using ElementTypes = std::tuple<typename Type<Elements>::type...>;
// Element type of the Nth array.
template <size_t N>
using ElementType = typename std::tuple_element<N, ElementTypes>::type;
constexpr explicit LayoutImpl(IntToSize<RuntimeSizeSeq>... sizes)
: size_{sizes...} {}
// Alignment of the layout, equal to the strictest alignment of all elements.
// All pointers passed to the methods of layout must be aligned to this value.
static constexpr size_t Alignment() {
return adl_barrier::Max(AlignOf<Elements>::value...);
}
// Offset in bytes of the Nth array.
//
// // int[3], 4 bytes of padding, double[4].
// Layout<int, double> x(3, 4);
// assert(x.Offset<0>() == 0); // The ints starts from 0.
// assert(x.Offset<1>() == 16); // The doubles starts from 16.
//
// Requires: `N <= NumSizes && N < sizeof...(Ts)`.
template <size_t N>
constexpr size_t Offset() const {
if constexpr (N == 0) {
return 0;
} else {
static_assert(N < NumOffsets, "Index out of bounds");
return adl_barrier::Align(
Offset<N - 1>() + SizeOf<ElementType<N - 1>>::value * Size<N - 1>(),
ElementAlignment<N>::value);
}
}
// Offset in bytes of the array with the specified element type. There must
// be exactly one such array and its zero-based index must be at most
// `NumSizes`.
//
// // int[3], 4 bytes of padding, double[4].
// Layout<int, double> x(3, 4);
// assert(x.Offset<int>() == 0); // The ints starts from 0.
// assert(x.Offset<double>() == 16); // The doubles starts from 16.
template <class T>
constexpr size_t Offset() const {
return Offset<ElementIndex<T>()>();
}
// Offsets in bytes of all arrays for which the offsets are known.
constexpr std::array<size_t, NumOffsets> Offsets() const {
return {{Offset<OffsetSeq>()...}};
}
// The number of elements in the Nth array (zero-based).
//
// // int[3], 4 bytes of padding, double[4].
// Layout<int, double> x(3, 4);
// assert(x.Size<0>() == 3);
// assert(x.Size<1>() == 4);
//
// Requires: `N < NumSizes`.
template <size_t N>
constexpr size_t Size() const {
if constexpr (N < NumStaticSizes) {
return kStaticSizes[N];
} else {
static_assert(N < NumSizes, "Index out of bounds");
return size_[N - NumStaticSizes];
}
}
// The number of elements in the array with the specified element type.
// There must be exactly one such array and its zero-based index must be
// at most `NumSizes`.
//
// // int[3], 4 bytes of padding, double[4].
// Layout<int, double> x(3, 4);
// assert(x.Size<int>() == 3);
// assert(x.Size<double>() == 4);
template <class T>
constexpr size_t Size() const {
return Size<ElementIndex<T>()>();
}
// The number of elements of all arrays for which they are known.
constexpr std::array<size_t, NumSizes> Sizes() const {
return {{Size<SizeSeq>()...}};
}
// Pointer to the beginning of the Nth array.
//
// `Char` must be `[const] [signed|unsigned] char`.
//
// // int[3], 4 bytes of padding, double[4].
// Layout<int, double> x(3, 4);
// unsigned char* p = new unsigned char[x.AllocSize()];
// int* ints = x.Pointer<0>(p);
// double* doubles = x.Pointer<1>(p);
//
// Requires: `N <= NumSizes && N < sizeof...(Ts)`.
// Requires: `p` is aligned to `Alignment()`.
template <size_t N, class Char>
CopyConst<Char, ElementType<N>>* Pointer(Char* p) const {
using C = typename std::remove_const<Char>::type;
static_assert(
std::is_same<C, char>() || std::is_same<C, unsigned char>() ||
std::is_same<C, signed char>(),
"The argument must be a pointer to [const] [signed|unsigned] char");
constexpr size_t alignment = Alignment();
(void)alignment;
assert(reinterpret_cast<uintptr_t>(p) % alignment == 0);
return reinterpret_cast<CopyConst<Char, ElementType<N>>*>(p + Offset<N>());
}
// Pointer to the beginning of the array with the specified element type.
// There must be exactly one such array and its zero-based index must be at
// most `NumSizes`.
//
// `Char` must be `[const] [signed|unsigned] char`.
//
// // int[3], 4 bytes of padding, double[4].
// Layout<int, double> x(3, 4);
// unsigned char* p = new unsigned char[x.AllocSize()];
// int* ints = x.Pointer<int>(p);
// double* doubles = x.Pointer<double>(p);
//
// Requires: `p` is aligned to `Alignment()`.
template <class T, class Char>
CopyConst<Char, T>* Pointer(Char* p) const {
return Pointer<ElementIndex<T>()>(p);
}
// Pointers to all arrays for which pointers are known.
//
// `Char` must be `[const] [signed|unsigned] char`.
//
// // int[3], 4 bytes of padding, double[4].
// Layout<int, double> x(3, 4);
// unsigned char* p = new unsigned char[x.AllocSize()];
//
// int* ints;
// double* doubles;
// std::tie(ints, doubles) = x.Pointers(p);
//
// Requires: `p` is aligned to `Alignment()`.
template <class Char>
auto Pointers(Char* p) const {
return std::tuple<CopyConst<Char, ElementType<OffsetSeq>>*...>(
Pointer<OffsetSeq>(p)...);
}
// The Nth array.
//
// `Char` must be `[const] [signed|unsigned] char`.
//
// // int[3], 4 bytes of padding, double[4].
// Layout<int, double> x(3, 4);
// unsigned char* p = new unsigned char[x.AllocSize()];
// Span<int> ints = x.Slice<0>(p);
// Span<double> doubles = x.Slice<1>(p);
//
// Requires: `N < NumSizes`.
// Requires: `p` is aligned to `Alignment()`.
template <size_t N, class Char>
SliceType<CopyConst<Char, ElementType<N>>> Slice(Char* p) const {
return SliceType<CopyConst<Char, ElementType<N>>>(Pointer<N>(p), Size<N>());
}
// The array with the specified element type. There must be exactly one
// such array and its zero-based index must be less than `NumSizes`.
//
// `Char` must be `[const] [signed|unsigned] char`.
//
// // int[3], 4 bytes of padding, double[4].
// Layout<int, double> x(3, 4);
// unsigned char* p = new unsigned char[x.AllocSize()];
// Span<int> ints = x.Slice<int>(p);
// Span<double> doubles = x.Slice<double>(p);
//
// Requires: `p` is aligned to `Alignment()`.
template <class T, class Char>
SliceType<CopyConst<Char, T>> Slice(Char* p) const {
return Slice<ElementIndex<T>()>(p);
}
// All arrays with known sizes.
//
// `Char` must be `[const] [signed|unsigned] char`.
//
// // int[3], 4 bytes of padding, double[4].
// Layout<int, double> x(3, 4);
// unsigned char* p = new unsigned char[x.AllocSize()];
//
// Span<int> ints;
// Span<double> doubles;
// std::tie(ints, doubles) = x.Slices(p);
//
// Requires: `p` is aligned to `Alignment()`.
//
// Note: We mark the parameter as maybe_unused because GCC detects it is not
// used when `SizeSeq` is empty [-Werror=unused-but-set-parameter].
template <class Char>
auto Slices([[maybe_unused]] Char* p) const {
return std::tuple<SliceType<CopyConst<Char, ElementType<SizeSeq>>>...>(
Slice<SizeSeq>(p)...);
}
// The size of the allocation that fits all arrays.
//
// // int[3], 4 bytes of padding, double[4].
// Layout<int, double> x(3, 4);
// unsigned char* p = new unsigned char[x.AllocSize()]; // 48 bytes
//
// Requires: `NumSizes == sizeof...(Ts)`.
constexpr size_t AllocSize() const {
static_assert(NumTypes == NumSizes, "You must specify sizes of all fields");
return Offset<NumTypes - 1>() +
SizeOf<ElementType<NumTypes - 1>>::value * Size<NumTypes - 1>();
}
// If built with --config=asan, poisons padding bytes (if any) in the
// allocation. The pointer must point to a memory block at least
// `AllocSize()` bytes in length.
//
// `Char` must be `[const] [signed|unsigned] char`.
//
// Requires: `p` is aligned to `Alignment()`.
template <class Char, size_t N = NumOffsets - 1>
void PoisonPadding(const Char* p) const {
if constexpr (N == 0) {
Pointer<0>(p); // verify the requirements on `Char` and `p`
} else {
static_assert(N < NumOffsets, "Index out of bounds");
(void)p;
#ifdef ABSL_HAVE_ADDRESS_SANITIZER
PoisonPadding<Char, N - 1>(p);
// The `if` is an optimization. It doesn't affect the observable behaviour.
if (ElementAlignment<N - 1>::value % ElementAlignment<N>::value) {
size_t start =
Offset<N - 1>() + SizeOf<ElementType<N - 1>>::value * Size<N - 1>();
ASAN_POISON_MEMORY_REGION(p + start, Offset<N>() - start);
}
#endif
}
}
// Human-readable description of the memory layout. Useful for debugging.
// Slow.
//
// // char[5], 3 bytes of padding, int[3], 4 bytes of padding, followed
// // by an unknown number of doubles.
// auto x = Layout<char, int, double>::Partial(5, 3);
// assert(x.DebugString() ==
// "@0<char>(1)[5]; @8<int>(4)[3]; @24<double>(8)");
//
// Each field is in the following format: @offset<type>(sizeof)[size] (<type>
// may be missing depending on the target platform). For example,
// @8<int>(4)[3] means that at offset 8 we have an array of ints, where each
// int is 4 bytes, and we have 3 of those ints. The size of the last field may
// be missing (as in the example above). Only fields with known offsets are
// described. Type names may differ across platforms: one compiler might
// produce "unsigned*" where another produces "unsigned int *".
std::string DebugString() const {
const auto offsets = Offsets();
const size_t sizes[] = {SizeOf<ElementType<OffsetSeq>>::value...};
const std::string types[] = {
adl_barrier::TypeName<ElementType<OffsetSeq>>()...};
std::string res = absl::StrCat("@0", types[0], "(", sizes[0], ")");
for (size_t i = 0; i != NumOffsets - 1; ++i) {
absl::StrAppend(&res, "[", DebugSize(i), "]; @", offsets[i + 1],
types[i + 1], "(", sizes[i + 1], ")");
}
// NumSizes is a constant that may be zero. Some compilers cannot see that
// inside the if statement "size_[NumSizes - 1]" must be valid.
int last = static_cast<int>(NumSizes) - 1;
if (NumTypes == NumSizes && last >= 0) {
absl::StrAppend(&res, "[", DebugSize(static_cast<size_t>(last)), "]");
}
return res;
}
private:
size_t DebugSize(size_t n) const {
if (n < NumStaticSizes) {
return kStaticSizes[n];
} else {
return size_[n - NumStaticSizes];
}
}
// Arguments of `Layout::Partial()` or `Layout::Layout()`.
size_t size_[NumRuntimeSizes > 0 ? NumRuntimeSizes : 1];
};
template <class StaticSizeSeq, size_t NumRuntimeSizes, class... Ts>
using LayoutType = LayoutImpl<
std::tuple<Ts...>, StaticSizeSeq,
absl::make_index_sequence<NumRuntimeSizes>,
absl::make_index_sequence<NumRuntimeSizes + StaticSizeSeq::size()>,
absl::make_index_sequence<adl_barrier::Min(
sizeof...(Ts), NumRuntimeSizes + StaticSizeSeq::size() + 1)>>;
template <class StaticSizeSeq, class... Ts>
class LayoutWithStaticSizes
: public LayoutType<StaticSizeSeq,
sizeof...(Ts) - adl_barrier::Min(sizeof...(Ts),
StaticSizeSeq::size()),
Ts...> {
private:
using Super =
LayoutType<StaticSizeSeq,
sizeof...(Ts) -
adl_barrier::Min(sizeof...(Ts), StaticSizeSeq::size()),
Ts...>;
public:
// The result type of `Partial()` with `NumSizes` arguments.
template <size_t NumSizes>
using PartialType =
internal_layout::LayoutType<StaticSizeSeq, NumSizes, Ts...>;
// `Layout` knows the element types of the arrays we want to lay out in
// memory but not the number of elements in each array.
// `Partial(size1, ..., sizeN)` allows us to specify the latter. The
// resulting immutable object can be used to obtain pointers to the
// individual arrays.
//
// It's allowed to pass fewer array sizes than the number of arrays. E.g.,
// if all you need is to the offset of the second array, you only need to
// pass one argument -- the number of elements in the first array.
//
// // int[3] followed by 4 bytes of padding and an unknown number of
// // doubles.
// auto x = Layout<int, double>::Partial(3);
// // doubles start at byte 16.
// assert(x.Offset<1>() == 16);
//
// If you know the number of elements in all arrays, you can still call
// `Partial()` but it's more convenient to use the constructor of `Layout`.
//
// Layout<int, double> x(3, 5);
//
// Note: The sizes of the arrays must be specified in number of elements,
// not in bytes.
//
// Requires: `sizeof...(Sizes) + NumStaticSizes <= sizeof...(Ts)`.
// Requires: all arguments are convertible to `size_t`.
template <class... Sizes>
static constexpr PartialType<sizeof...(Sizes)> Partial(Sizes&&... sizes) {
static_assert(sizeof...(Sizes) + StaticSizeSeq::size() <= sizeof...(Ts),
"");
return PartialType<sizeof...(Sizes)>(
static_cast<size_t>(std::forward<Sizes>(sizes))...);
}
// Inherit LayoutType's constructor.
//
// Creates a layout with the sizes of all arrays specified. If you know
// only the sizes of the first N arrays (where N can be zero), you can use
// `Partial()` defined above. The constructor is essentially equivalent to
// calling `Partial()` and passing in all array sizes; the constructor is
// provided as a convenient abbreviation.
//
// Note: The sizes of the arrays must be specified in number of elements,
// not in bytes.
//
// Implementation note: we do this via a `using` declaration instead of
// defining our own explicit constructor because the signature of LayoutType's
// constructor depends on RuntimeSizeSeq, which we don't have access to here.
// If we defined our own constructor here, it would have to use a parameter
// pack and then cast the arguments to size_t when calling the superclass
// constructor, similar to what Partial() does. But that would suffer from the
// same problem that Partial() has, which is that the parameter types are
// inferred from the arguments, which may be signed types, which must then be
// cast to size_t. This can lead to negative values being silently (i.e. with
// no compiler warnings) cast to an unsigned type. Having a constructor with
// size_t parameters helps the compiler generate better warnings about
// potential bad casts, while avoiding false warnings when positive literal
// arguments are used. If an argument is a positive literal integer (e.g.
// `1`), the compiler will understand that it can be safely converted to
// size_t, and hence not generate a warning. But if a negative literal (e.g.
// `-1`) or a variable with signed type is used, then it can generate a
// warning about a potentially unsafe implicit cast. It would be great if we
// could do this for Partial() too, but unfortunately as of C++23 there seems
// to be no way to define a function with a variable number of parameters of a
// certain type, a.k.a. homogeneous function parameter packs. So we're forced
// to choose between explicitly casting the arguments to size_t, which
// suppresses all warnings, even potentially valid ones, or implicitly casting
// them to size_t, which generates bogus warnings whenever literal arguments
// are used, even if they're positive.
using Super::Super;
};
} // namespace internal_layout
// Descriptor of arrays of various types and sizes laid out in memory one after
// another. See the top of the file for documentation.
//
// Check out the public API of internal_layout::LayoutWithStaticSizes and
// internal_layout::LayoutImpl above. Those types are internal to the library
// but their methods are public, and they are inherited by `Layout`.
template <class... Ts>
class Layout : public internal_layout::LayoutWithStaticSizes<
absl::make_index_sequence<0>, Ts...> {
private:
using Super =
internal_layout::LayoutWithStaticSizes<absl::make_index_sequence<0>,
Ts...>;
public:
// If you know the sizes of some or all of the arrays at compile time, you can
// use `WithStaticSizes` or `WithStaticSizeSequence` to create a `Layout` type
// with those sizes baked in. This can help the compiler generate optimal code
// for calculating array offsets and AllocSize().
//
// Like `Partial()`, the N sizes you specify are for the first N arrays, and
// they specify the number of elements in each array, not the number of bytes.
template <class StaticSizeSeq>
using WithStaticSizeSequence =
internal_layout::LayoutWithStaticSizes<StaticSizeSeq, Ts...>;
template <size_t... StaticSizes>
using WithStaticSizes =
WithStaticSizeSequence<std::index_sequence<StaticSizes...>>;
// Inherit LayoutWithStaticSizes's constructor, which requires you to specify
// all the array sizes.
using Super::Super;
};
} // namespace container_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_CONTAINER_INTERNAL_LAYOUT_H_
*ðN
‹soong/.intermediates/external/abseil-cpp/absl_strings_str_format_internal_hdrs/gen/my_include_dir/absl/strings/internal/str_format/parser.hßM// Copyright 2020 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_PARSER_H_
#define ABSL_STRINGS_INTERNAL_STR_FORMAT_PARSER_H_
#include <stddef.h>
#include <stdlib.h>
#include <cassert>
#include <cstring>
#include <initializer_list>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "absl/base/config.h"
#include "absl/base/optimization.h"
#include "absl/strings/internal/str_format/checker.h"
#include "absl/strings/internal/str_format/constexpr_parser.h"
#include "absl/strings/internal/str_format/extension.h"
#include "absl/strings/string_view.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
std::string LengthModToString(LengthMod v);
const char* ConsumeUnboundConversionNoInline(const char* p, const char* end,
UnboundConversion* conv,
int* next_arg);
// Parse the format string provided in 'src' and pass the identified items into
// 'consumer'.
// Text runs will be passed by calling
// Consumer::Append(string_view);
// ConversionItems will be passed by calling
// Consumer::ConvertOne(UnboundConversion, string_view);
// In the case of ConvertOne, the string_view that is passed is the
// portion of the format string corresponding to the conversion, not including
// the leading %. On success, it returns true. On failure, it stops and returns
// false.
template <typename Consumer>
bool ParseFormatString(string_view src, Consumer consumer) {
int next_arg = 0;
const char* p = src.data();
const char* const end = p + src.size();
while (p != end) {
const char* percent =
static_cast<const char*>(memchr(p, '%', static_cast<size_t>(end - p)));
if (!percent) {
// We found the last substring.
return consumer.Append(string_view(p, static_cast<size_t>(end - p)));
}
// We found a percent, so push the text run then process the percent.
if (ABSL_PREDICT_FALSE(!consumer.Append(
string_view(p, static_cast<size_t>(percent - p))))) {
return false;
}
if (ABSL_PREDICT_FALSE(percent + 1 >= end)) return false;
auto tag = GetTagForChar(percent[1]);
if (tag.is_conv()) {
if (ABSL_PREDICT_FALSE(next_arg < 0)) {
// This indicates an error in the format string.
// The only way to get `next_arg < 0` here is to have a positional
// argument first which sets next_arg to -1 and then a non-positional
// argument.
return false;
}
p = percent + 2;
// Keep this case separate from the one below.
// ConvertOne is more efficient when the compiler can see that the `basic`
// flag is set.
UnboundConversion conv;
conv.conv = tag.as_conv();
conv.arg_position = ++next_arg;
if (ABSL_PREDICT_FALSE(
!consumer.ConvertOne(conv, string_view(percent + 1, 1)))) {
return false;
}
} else if (percent[1] != '%') {
UnboundConversion conv;
p = ConsumeUnboundConversionNoInline(percent + 1, end, &conv, &next_arg);
if (ABSL_PREDICT_FALSE(p == nullptr)) return false;
if (ABSL_PREDICT_FALSE(!consumer.ConvertOne(
conv, string_view(percent + 1,
static_cast<size_t>(p - (percent + 1)))))) {
return false;
}
} else {
if (ABSL_PREDICT_FALSE(!consumer.Append("%"))) return false;
p = percent + 2;
continue;
}
}
return true;
}
// Always returns true, or fails to compile in a constexpr context if s does not
// point to a constexpr char array.
constexpr bool EnsureConstexpr(string_view s) {
return s.empty() || s[0] == s[0];
}
class ParsedFormatBase {
public:
explicit ParsedFormatBase(
string_view format, bool allow_ignored,
std::initializer_list<FormatConversionCharSet> convs);
ParsedFormatBase(const ParsedFormatBase& other) { *this = other; }
ParsedFormatBase(ParsedFormatBase&& other) { *this = std::move(other); }
ParsedFormatBase& operator=(const ParsedFormatBase& other) {
if (this == &other) return *this;
has_error_ = other.has_error_;
items_ = other.items_;
size_t text_size = items_.empty() ? 0 : items_.back().text_end;
data_ = std::make_unique<char[]>(text_size);
if (text_size > 0) {
memcpy(data_.get(), other.data_.get(), text_size);
}
return *this;
}
ParsedFormatBase& operator=(ParsedFormatBase&& other) {
if (this == &other) return *this;
has_error_ = other.has_error_;
data_ = std::move(other.data_);
items_ = std::move(other.items_);
// Reset the vector to make sure the invariants hold.
other.items_.clear();
return *this;
}
template <typename Consumer>
bool ProcessFormat(Consumer consumer) const {
const char* const base = data_.get();
string_view text(base, 0);
for (const auto& item : items_) {
const char* const end = text.data() + text.size();
text =
string_view(end, static_cast<size_t>((base + item.text_end) - end));
if (item.is_conversion) {
if (!consumer.ConvertOne(item.conv, text)) return false;
} else {
if (!consumer.Append(text)) return false;
}
}
return !has_error_;
}
bool has_error() const { return has_error_; }
private:
// Returns whether the conversions match and if !allow_ignored it verifies
// that all conversions are used by the format.
bool MatchesConversions(
bool allow_ignored,
std::initializer_list<FormatConversionCharSet> convs) const;
struct ParsedFormatConsumer;
struct ConversionItem {
bool is_conversion;
// Points to the past-the-end location of this element in the data_ array.
size_t text_end;
UnboundConversion conv;
};
bool has_error_;
std::unique_ptr<char[]> data_;
std::vector<ConversionItem> items_;
};
// A value type representing a preparsed format. These can be created, copied
// around, and reused to speed up formatting loops.
// The user must specify through the template arguments the conversion
// characters used in the format. This will be checked at compile time.
//
// This class uses Conv enum values to specify each argument.
// This allows for more flexibility as you can specify multiple possible
// conversion characters for each argument.
// ParsedFormat<char...> is a simplified alias for when the user only
// needs to specify a single conversion character for each argument.
//
// Example:
// // Extended format supports multiple characters per argument:
// using MyFormat = ExtendedParsedFormat<Conv::d | Conv::x>;
// MyFormat GetFormat(bool use_hex) {
// if (use_hex) return MyFormat("foo %x bar");
// return MyFormat("foo %d bar");
// }
// // 'format' can be used with any value that supports 'd' and 'x',
// // like `int`.
// auto format = GetFormat(use_hex);
// value = StringF(format, i);
//
// This class also supports runtime format checking with the ::New() and
// ::NewAllowIgnored() factory functions.
// This is the only API that allows the user to pass a runtime specified format
// string. These factory functions will return NULL if the format does not match
// the conversions requested by the user.
template <FormatConversionCharSet... C>
class ExtendedParsedFormat : public str_format_internal::ParsedFormatBase {
public:
explicit ExtendedParsedFormat(string_view format)
#ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
__attribute__((
enable_if(str_format_internal::EnsureConstexpr(format),
"Format string is not constexpr."),
enable_if(str_format_internal::ValidFormatImpl<C...>(format),
"Format specified does not match the template arguments.")))
#endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
: ExtendedParsedFormat(format, false) {
}
// ExtendedParsedFormat factory function.
// The user still has to specify the conversion characters, but they will not
// be checked at compile time. Instead, it will be checked at runtime.
// This delays the checking to runtime, but allows the user to pass
// dynamically sourced formats.
// It returns NULL if the format does not match the conversion characters.
// The user is responsible for checking the return value before using it.
//
// The 'New' variant will check that all the specified arguments are being
// consumed by the format and return NULL if any argument is being ignored.
// The 'NewAllowIgnored' variant will not verify this and will allow formats
// that ignore arguments.
static std::unique_ptr<ExtendedParsedFormat> New(string_view format) {
return New(format, false);
}
static std::unique_ptr<ExtendedParsedFormat> NewAllowIgnored(
string_view format) {
return New(format, true);
}
private:
static std::unique_ptr<ExtendedParsedFormat> New(string_view format,
bool allow_ignored) {
std::unique_ptr<ExtendedParsedFormat> conv(
new ExtendedParsedFormat(format, allow_ignored));
if (conv->has_error()) return nullptr;
return conv;
}
ExtendedParsedFormat(string_view s, bool allow_ignored)
: ParsedFormatBase(s, allow_ignored, {C...}) {}
};
} // namespace str_format_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_PARSER_H_
*£V
¶soong/.intermediates/build/make/tools/ide_query/prober_scripts/cpp/ide_query_proberscript_cc/android_arm_armv7-a-neon/gen/proto/build/make/tools/ide_query/prober_scripts/cpp/foo.pb.hçT// Generated by the protocol buffer compiler. DO NOT EDIT!
// NO CHECKED-IN PROTOBUF GENCODE
// source: build/make/tools/ide_query/prober_scripts/cpp/foo.proto
// Protobuf C++ Version: 6.33.1
#ifndef build_2fmake_2ftools_2fide_5fquery_2fprober_5fscripts_2fcpp_2ffoo_2eproto_2epb_2eh
#define build_2fmake_2ftools_2fide_5fquery_2fprober_5fscripts_2fcpp_2ffoo_2eproto_2epb_2eh
#include <cstdint>
#include <limits>
#include <string>
#include <type_traits>
#include <utility>
#include "google/protobuf/runtime_version.h"
#if PROTOBUF_VERSION != 6033001
#error "Protobuf C++ gencode is built with an incompatible version of"
#error "Protobuf C++ headers/runtime. See"
#error "https://protobuf.dev/support/cross-version-runtime-guarantee/#cpp"
#endif
#include "google/protobuf/io/coded_stream.h"
#include "google/protobuf/arena.h"
#include "google/protobuf/arenastring.h"
#include "google/protobuf/generated_message_tctable_decl.h"
#include "google/protobuf/generated_message_util.h"
#include "google/protobuf/metadata_lite.h"
#include "google/protobuf/message_lite.h"
#include "google/protobuf/repeated_field.h" // IWYU pragma: export
#include "google/protobuf/extension_set.h" // IWYU pragma: export
// @@protoc_insertion_point(includes)
// Must be included last.
#include "google/protobuf/port_def.inc"
#define PROTOBUF_INTERNAL_EXPORT_build_2fmake_2ftools_2fide_5fquery_2fprober_5fscripts_2fcpp_2ffoo_2eproto
namespace google {
namespace protobuf {
namespace internal {
template <typename T>
::absl::string_view GetAnyMessageName();
} // namespace internal
} // namespace protobuf
} // namespace google
// Internal implementation detail -- do not use these members.
struct TableStruct_build_2fmake_2ftools_2fide_5fquery_2fprober_5fscripts_2fcpp_2ffoo_2eproto {
static const ::uint32_t offsets[];
};
namespace ide_query {
namespace prober_scripts {
class ProtoMsg;
struct ProtoMsgDefaultTypeInternal;
extern ProtoMsgDefaultTypeInternal _ProtoMsg_default_instance_;
extern const ::google::protobuf::internal::ClassDataLite<34> ProtoMsg_class_data_;
} // namespace prober_scripts
} // namespace ide_query
namespace google {
namespace protobuf {
} // namespace protobuf
} // namespace google
namespace ide_query {
namespace prober_scripts {
// ===================================================================
// -------------------------------------------------------------------
class ProtoMsg final : public ::google::protobuf::MessageLite
/* @@protoc_insertion_point(class_definition:ide_query.prober_scripts.ProtoMsg) */ {
public:
inline ProtoMsg() : ProtoMsg(nullptr) {}
~ProtoMsg() PROTOBUF_FINAL;
#if defined(PROTOBUF_CUSTOM_VTABLE)
void operator delete(ProtoMsg* PROTOBUF_NONNULL msg, ::std::destroying_delete_t) {
SharedDtor(*msg);
::google::protobuf::internal::SizedDelete(msg, sizeof(ProtoMsg));
}
#endif
template <typename = void>
explicit PROTOBUF_CONSTEXPR ProtoMsg(::google::protobuf::internal::ConstantInitialized);
inline ProtoMsg(const ProtoMsg& from) : ProtoMsg(nullptr, from) {}
inline ProtoMsg(ProtoMsg&& from) noexcept
: ProtoMsg(nullptr, ::std::move(from)) {}
inline ProtoMsg& operator=(const ProtoMsg& from) {
CopyFrom(from);
return *this;
}
inline ProtoMsg& operator=(ProtoMsg&& from) noexcept {
if (this == &from) return *this;
if (::google::protobuf::internal::CanMoveWithInternalSwap(GetArena(), from.GetArena())) {
InternalSwap(&from);
} else {
CopyFrom(from);
}
return *this;
}
inline const ::std::string& unknown_fields() const
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return _internal_metadata_.unknown_fields<::std::string>(::google::protobuf::internal::GetEmptyString);
}
inline ::std::string* PROTOBUF_NONNULL mutable_unknown_fields()
ABSL_ATTRIBUTE_LIFETIME_BOUND {
return _internal_metadata_.mutable_unknown_fields<::std::string>();
}
static const ProtoMsg& default_instance() {
return *reinterpret_cast<const ProtoMsg*>(
&_ProtoMsg_default_instance_);
}
static constexpr int kIndexInFileMessages = 0;
friend void swap(ProtoMsg& a, ProtoMsg& b) { a.Swap(&b); }
inline void Swap(ProtoMsg* PROTOBUF_NONNULL other) {
if (other == this) return;
if (::google::protobuf::internal::CanUseInternalSwap(GetArena(), other->GetArena())) {
InternalSwap(other);
} else {
::google::protobuf::internal::GenericSwap(this, other);
}
}
void UnsafeArenaSwap(ProtoMsg* PROTOBUF_NONNULL other) {
if (other == this) return;
ABSL_DCHECK(GetArena() == other->GetArena());
InternalSwap(other);
}
// implements Message ----------------------------------------------
ProtoMsg* PROTOBUF_NONNULL New(::google::protobuf::Arena* PROTOBUF_NULLABLE arena = nullptr) const {
return ::google::protobuf::MessageLite::DefaultConstruct<ProtoMsg>(arena);
}
void CopyFrom(const ProtoMsg& from);
void MergeFrom(const ProtoMsg& from) { ProtoMsg::MergeImpl(*this, from); }
private:
static void MergeImpl(::google::protobuf::MessageLite& to_msg,
const ::google::protobuf::MessageLite& from_msg);
public:
bool IsInitialized() const {
return true;
}
ABSL_ATTRIBUTE_REINITIALIZES void Clear() PROTOBUF_FINAL;
#if defined(PROTOBUF_CUSTOM_VTABLE)
private:
static ::size_t ByteSizeLong(const ::google::protobuf::MessageLite& msg);
static ::uint8_t* PROTOBUF_NONNULL _InternalSerialize(
const ::google::protobuf::MessageLite& msg, ::uint8_t* PROTOBUF_NONNULL target,
::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream);
public:
::size_t ByteSizeLong() const { return ByteSizeLong(*this); }
::uint8_t* PROTOBUF_NONNULL _InternalSerialize(
::uint8_t* PROTOBUF_NONNULL target,
::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const {
return _InternalSerialize(*this, target, stream);
}
#else // PROTOBUF_CUSTOM_VTABLE
::size_t ByteSizeLong() const final;
::uint8_t* PROTOBUF_NONNULL _InternalSerialize(
::uint8_t* PROTOBUF_NONNULL target,
::google::protobuf::io::EpsCopyOutputStream* PROTOBUF_NONNULL stream) const final;
#endif // PROTOBUF_CUSTOM_VTABLE
int GetCachedSize() const { return _impl_._cached_size_.Get(); }
private:
void SharedCtor(::google::protobuf::Arena* PROTOBUF_NULLABLE arena);
static void SharedDtor(MessageLite& self);
void InternalSwap(ProtoMsg* PROTOBUF_NONNULL other);
private:
template <typename T>
friend ::absl::string_view(::google::protobuf::internal::GetAnyMessageName)();
static ::absl::string_view FullMessageName() { return "ide_query.prober_scripts.ProtoMsg"; }
explicit ProtoMsg(::google::protobuf::Arena* PROTOBUF_NULLABLE arena);
ProtoMsg(::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const ProtoMsg& from);
ProtoMsg(
::google::protobuf::Arena* PROTOBUF_NULLABLE arena, ProtoMsg&& from) noexcept
: ProtoMsg(arena) {
*this = ::std::move(from);
}
const ::google::protobuf::internal::ClassData* PROTOBUF_NONNULL GetClassData() const PROTOBUF_FINAL;
static void* PROTOBUF_NONNULL PlacementNew_(
const void* PROTOBUF_NONNULL, void* PROTOBUF_NONNULL mem,
::google::protobuf::Arena* PROTOBUF_NULLABLE arena);
static constexpr auto InternalNewImpl_();
public:
static constexpr auto InternalGenerateClassData_();
// nested types ----------------------------------------------------
// accessors -------------------------------------------------------
enum : int {
kSomeFieldFieldNumber = 1,
};
// int64 some_field = 1;
void clear_some_field() ;
::int64_t some_field() const;
void set_some_field(::int64_t value);
private:
::int64_t _internal_some_field() const;
void _internal_set_some_field(::int64_t value);
public:
// @@protoc_insertion_point(class_scope:ide_query.prober_scripts.ProtoMsg)
private:
class _Internal;
friend class ::google::protobuf::internal::TcParser;
static const ::google::protobuf::internal::TcParseTable<0, 1,
0, 0,
2>
_table_;
friend class ::google::protobuf::MessageLite;
friend class ::google::protobuf::Arena;
template <typename T>
friend class ::google::protobuf::Arena::InternalHelper;
using InternalArenaConstructable_ = void;
using DestructorSkippable_ = void;
struct Impl_ {
inline explicit constexpr Impl_(::google::protobuf::internal::ConstantInitialized) noexcept;
inline explicit Impl_(
::google::protobuf::internal::InternalVisibility visibility,
::google::protobuf::Arena* PROTOBUF_NULLABLE arena);
inline explicit Impl_(
::google::protobuf::internal::InternalVisibility visibility,
::google::protobuf::Arena* PROTOBUF_NULLABLE arena, const Impl_& from,
const ProtoMsg& from_msg);
::google::protobuf::internal::HasBits<1> _has_bits_;
::google::protobuf::internal::CachedSize _cached_size_;
::int64_t some_field_;
PROTOBUF_TSAN_DECLARE_MEMBER
};
union { Impl_ _impl_; };
friend struct ::TableStruct_build_2fmake_2ftools_2fide_5fquery_2fprober_5fscripts_2fcpp_2ffoo_2eproto;
};
extern const ::google::protobuf::internal::ClassDataLite<34> ProtoMsg_class_data_;
// ===================================================================
// ===================================================================
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
#endif // __GNUC__
// -------------------------------------------------------------------
// ProtoMsg
// int64 some_field = 1;
inline void ProtoMsg::clear_some_field() {
::google::protobuf::internal::TSanWrite(&_impl_);
_impl_.some_field_ = ::int64_t{0};
ClearHasBit(_impl_._has_bits_[0],
0x00000001U);
}
inline ::int64_t ProtoMsg::some_field() const {
// @@protoc_insertion_point(field_get:ide_query.prober_scripts.ProtoMsg.some_field)
return _internal_some_field();
}
inline void ProtoMsg::set_some_field(::int64_t value) {
_internal_set_some_field(value);
SetHasBit(_impl_._has_bits_[0], 0x00000001U);
// @@protoc_insertion_point(field_set:ide_query.prober_scripts.ProtoMsg.some_field)
}
inline ::int64_t ProtoMsg::_internal_some_field() const {
::google::protobuf::internal::TSanRead(&_impl_);
return _impl_.some_field_;
}
inline void ProtoMsg::_internal_set_some_field(::int64_t value) {
::google::protobuf::internal::TSanWrite(&_impl_);
_impl_.some_field_ = value;
}
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif // __GNUC__
// @@protoc_insertion_point(namespace_scope)
} // namespace prober_scripts
} // namespace ide_query
// @@protoc_insertion_point(global_scope)
#include "google/protobuf/port_undef.inc"
#endif // build_2fmake_2ftools_2fide_5fquery_2fprober_5fscripts_2fcpp_2ffoo_2eproto_2epb_2eh
*¹Ã
‚soong/.intermediates/external/abseil-cpp/absl_strings_cord_internal_hdrs/gen/my_include_dir/absl/strings/internal/cord_rep_btree.h°Â// Copyright 2021 The Abseil Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef ABSL_STRINGS_INTERNAL_CORD_REP_BTREE_H_
#define ABSL_STRINGS_INTERNAL_CORD_REP_BTREE_H_
#include <cassert>
#include <cstdint>
#include <iosfwd>
#include "absl/base/config.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/base/optimization.h"
#include "absl/strings/internal/cord_data_edge.h"
#include "absl/strings/internal/cord_internal.h"
#include "absl/strings/internal/cord_rep_flat.h"
#include "absl/strings/string_view.h"
#include "absl/types/span.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace cord_internal {
// `SetCordBtreeExhaustiveValidation()` can be set to force exhaustive
// validation in debug assertions, and code that calls `IsValid()`
// explicitly. By default, assertions should be relatively cheap and
// AssertValid() can easily lead to O(n^2) complexity as recursive / full tree
// validation is O(n).
void SetCordBtreeExhaustiveValidation(bool do_exaustive_validation);
bool IsCordBtreeExhaustiveValidationEnabled();
class CordRepBtreeNavigator;
// CordRepBtree is as the name implies a btree implementation of a Cordrep tree.
// Data is stored at the leaf level only, non leaf nodes contain down pointers
// only. Allowed types of data edges are FLAT, EXTERNAL and SUBSTRINGs of FLAT
// or EXTERNAL nodes. The implementation allows for data to be added to either
// end of the tree only, it does not provide any 'insert' logic. This has the
// benefit that we can expect good fill ratios: all nodes except the outer
// 'legs' will have 100% fill ratios for trees built using Append/Prepend
// methods. Merged trees will typically have a fill ratio well above 50% as in a
// similar fashion, one side of the merged tree will typically have a 100% fill
// ratio, and the 'open' end will average 50%. All operations are O(log(n)) or
// better, and the tree never needs balancing.
//
// All methods accepting a CordRep* or CordRepBtree* adopt a reference on that
// input unless explicitly stated otherwise. All functions returning a CordRep*
// or CordRepBtree* instance transfer a reference back to the caller.
// Simplified, callers both 'donate' and 'consume' a reference count on each
// call, simplifying the API. An example of building a tree:
//
// CordRepBtree* tree = CordRepBtree::Create(MakeFlat("Hello"));
// tree = CordRepBtree::Append(tree, MakeFlat("world"));
//
// In the above example, all inputs are consumed, making each call affecting
// `tree` reference count neutral. The returned `tree` value can be different
// from the input if the input is shared with other threads, or if the tree
// grows in height, but callers typically never have to concern themselves with
// that and trust that all methods DTRT at all times.
class CordRepBtree : public CordRep {
public:
// EdgeType identifies `front` and `back` enum values.
// Various implementations in CordRepBtree such as `Add` and `Edge` are
// generic and templated on operating on either of the boundary edges.
// For more information on the possible edges contained in a CordRepBtree
// instance see the documentation for `edges_`.
enum class EdgeType { kFront, kBack };
// Convenience constants into `EdgeType`
static constexpr EdgeType kFront = EdgeType::kFront;
static constexpr EdgeType kBack = EdgeType::kBack;
// Maximum number of edges: based on experiments and performance data, we can
// pick suitable values resulting in optimum cacheline aligned values. The
// preferred values are based on 64-bit systems where we aim to align this
// class onto 64 bytes, i.e.: 6 = 64 bytes, 14 = 128 bytes, etc.
// TODO(b/192061034): experiment with alternative sizes.
static constexpr size_t kMaxCapacity = 6;
// Reasonable maximum height of the btree. We can expect a fill ratio of at
// least 50%: trees are always expanded at the front or back. Concatenating
// trees will then typically fold at the top most node, where the lower nodes
// are at least at capacity on one side of joined inputs. At a lower fill
// rate of 4 edges per node, we have capacity for ~16 million leaf nodes.
// We will fail / abort if an application ever exceeds this height, which
// should be extremely rare (near impossible) and be an indication of an
// application error: we do not assume it reasonable for any application to
// operate correctly with such monster trees.
// Another compelling reason for the number `12` is that any contextual stack
// required for navigation or insertion requires 12 words and 12 bytes, which
// fits inside 2 cache lines with some room to spare, and is reasonable as a
// local stack variable compared to Cord's current near 400 bytes stack use.
// The maximum `height` value of a node is then `kMaxDepth - 1` as node height
// values start with a value of 0 for leaf nodes.
static constexpr size_t kMaxDepth = 12;
// See comments on height() for why this is an int and not a size_t.
static constexpr int kMaxHeight = static_cast<int>(kMaxDepth - 1);
// `Action` defines the action for unwinding changes done at the btree's leaf
// level that need to be propagated up to the parent node(s). Each operation
// on a node has an effect / action defined as follows:
// - kSelf
// The operation (add / update, etc) was performed directly on the node as
// the node is private to the current thread (i.e.: not shared directly or
// indirectly through a refcount > 1). Changes can be propagated directly to
// all parent nodes as all parent nodes are also then private to the current
// thread.
// - kCopied
// The operation (add / update, etc) was performed on a copy of the original
// node, as the node is (potentially) directly or indirectly shared with
// other threads. Changes need to be propagated into the parent nodes where
// the old down pointer must be unreffed and replaced with this new copy.
// Such changes to parent nodes may themselves require a copy if the parent
// node is also shared. A kCopied action can propagate all the way to the
// top node where we then must unref the `tree` input provided by the
// caller, and return the new copy.
// - kPopped
// The operation (typically add) could not be satisfied due to insufficient
// capacity in the targeted node, and a new 'leg' was created that needs to
// be added into the parent node. For example, adding a FLAT inside a leaf
// node that is at capacity will create a new leaf node containing that
// FLAT, that needs to be 'popped' up the btree. Such 'pop' actions can
// cascade up the tree if parent nodes are also at capacity. A 'Popped'
// action propagating all the way to the top of the tree will result in
// the tree becoming one level higher than the current tree through a final
// `CordRepBtree::New(tree, popped)` call, resulting in a new top node
// referencing the old tree and the new (fully popped upwards) 'leg'.
enum Action { kSelf, kCopied, kPopped };
// Result of an operation on a node. See the `Action` enum for details.
struct OpResult {
CordRepBtree* tree;
Action action;
};
// Return value of the CopyPrefix and CopySuffix methods which can
// return a node or data edge at any height inside the tree.
// A height of 0 defines the lowest (leaf) node, a height of -1 identifies
// `edge` as being a plain data node: EXTERNAL / FLAT or SUBSTRING thereof.
struct CopyResult {
CordRep* edge;
int height;
};
// Logical position inside a node:
// - index: index of the edge.
// - n: size or offset value depending on context.
struct Position {
size_t index;
size_t n;
};
// Creates a btree from the given input. Adopts a ref of `rep`.
// If the input `rep` is itself a btree, i.e., `IsBtree()`, then this
// function immediately returns `rep->btree()`. If the input is a valid data
// edge (see IsDataEdge()), then a new leaf node is returned containing `rep`
// as the sole data edge. Else, the input is assumed to be a (legacy) concat
// tree, and the input is consumed and transformed into a btree().
static CordRepBtree* Create(CordRep* rep);
// Destroys the provided tree. Should only be called by cord internal API's,
// typically after a ref_count.Decrement() on the last reference count.
static void Destroy(CordRepBtree* tree);
// Destruction
static void Delete(CordRepBtree* tree) { delete tree; }
// Use CordRep::Unref() as we overload for absl::Span<CordRep* const>.
using CordRep::Unref;
// Unrefs all edges in `edges` which are assumed to be 'likely one'.
static void Unref(absl::Span<CordRep* const> edges);
// Appends / Prepends an existing CordRep instance to this tree.
// The below methods accept three types of input:
// 1) `rep` is a data node (See `IsDataNode` for valid data edges).
// `rep` is appended or prepended to this tree 'as is'.
// 2) `rep` is a BTREE.
// `rep` is merged into `tree` respecting the Append/Prepend order.
// 3) `rep` is some other (legacy) type.
// `rep` is converted in place and added to `tree`
// Requires `tree` and `rep` to be not null.
static CordRepBtree* Append(CordRepBtree* tree, CordRep* rep);
static CordRepBtree* Prepend(CordRepBtree* tree, CordRep* rep);
// Append/Prepend the data in `data` to this tree.
// The `extra` parameter defines how much extra capacity should be allocated
// for any additional FLAT being allocated. This is an optimization hint from
// the caller. For example, a caller may need to add 2 string_views of data
// "abc" and "defghi" which are not consecutive. The caller can in this case
// invoke `AddData(tree, "abc", 6)`, and any newly added flat is allocated
// where possible with at least 6 bytes of extra capacity beyond `length`.
// This helps avoiding data getting fragmented over multiple flats.
// There is no limit on the size of `data`. If `data` can not be stored inside
// a single flat, then the function will iteratively add flats until all data
// has been consumed and appended or prepended to the tree.
static CordRepBtree* Append(CordRepBtree* tree, string_view data,
size_t extra = 0);
static CordRepBtree* Prepend(CordRepBtree* tree, string_view data,
size_t extra = 0);
// Returns a new tree, containing `n` bytes of data from this instance
// starting at offset `offset`. Where possible, the returned tree shares
// (re-uses) data edges and nodes with this instance to minimize the
// combined memory footprint of both trees.
// Requires `offset + n <= length`. Returns `nullptr` if `n` is zero.
CordRep* SubTree(size_t offset, size_t n);
// Removes `n` trailing bytes from `tree`, and returns the resulting tree
// or data edge. Returns `tree` if n is zero, and nullptr if n == length.
// This function is logically identical to:
// result = tree->SubTree(0, tree->length - n);
// Unref(tree);
// return result;
// However, the actual implementation will as much as possible perform 'in
// place' modifications on the tree on all nodes and edges that are mutable.
// For example, in a fully privately owned tree with the last edge being a
// flat of length 12, RemoveSuffix(1) will simply set the length of that data
// edge to 11, and reduce the length of all nodes on the edge path by 1.
static CordRep* RemoveSuffix(CordRepBtree* tree, size_t n);
// Returns the character at the given offset.
char GetCharacter(size_t offset) const;
// Returns true if this node holds a single data edge, and if so, sets
// `fragment` to reference the contained data. `fragment` is an optional
// output parameter and allowed to be null.
bool IsFlat(absl::string_view* fragment) const;
// Returns true if the data of `n` bytes starting at offset `offset`
// is contained in a single data edge, and if so, sets fragment to reference
// the contained data. `fragment` is an optional output parameter and allowed
// to be null.
bool IsFlat(size_t offset, size_t n, absl::string_view* fragment) const;
// Returns a span (mutable range of bytes) of up to `size` bytes into the
// last FLAT data edge inside this tree under the following conditions:
// - none of the nodes down into the FLAT node are shared.
// - the last data edge in this tree is a non-shared FLAT.
// - the referenced FLAT has additional capacity available.
// If all these conditions are met, a non-empty span is returned, and the
// length of the flat node and involved tree nodes have been increased by
// `span.length()`. The caller is responsible for immediately assigning values
// to all uninitialized data reference by the returned span.
// Requires `this->refcount.IsOne()`: this function forces the caller to do
// this fast path check on the top level node, as this is the most commonly
// shared node of a cord tree.
Span<char> GetAppendBuffer(size_t size);
// Extracts the right-most data edge from this tree iff:
// - the tree and all internal edges to the right-most node are not shared.
// - the right-most node is a FLAT node and not shared.
// - the right-most node has at least the desired extra capacity.
//
// Returns {tree, nullptr} if any of the above conditions are not met.
// This method effectively removes data from the tree. The intent of this
// method is to allow applications appending small string data to use
// pre-existing capacity, and add the modified rep back to the tree.
//
// Simplified such code would look similar to this:
// void MyTreeBuilder::Append(string_view data) {
// ExtractResult result = CordRepBtree::ExtractAppendBuffer(tree_, 1);
// if (CordRep* rep = result.extracted) {
// size_t available = rep->Capacity() - rep->length;
// size_t n = std::min(data.size(), n);
// memcpy(rep->Data(), data.data(), n);
// rep->length += n;
// data.remove_prefix(n);
// if (!result.tree->IsBtree()) {
// tree_ = CordRepBtree::Create(result.tree);
// }
// tree_ = CordRepBtree::Append(tree_, rep);
// }
// ...
// // Remaining edge in `result.tree`.
// }
static ExtractResult ExtractAppendBuffer(CordRepBtree* tree,
size_t extra_capacity = 1);
// Returns the `height` of the tree. The height of a tree is limited to
// kMaxHeight. `height` is implemented as an `int` as in some places we
// use negative (-1) values for 'data edges'.
int height() const { return static_cast<int>(storage[0]); }
// Properties: begin, back, end, front/back boundary indexes.
size_t begin() const { return static_cast<size_t>(storage[1]); }
size_t back() const { return static_cast<size_t>(storage[2]) - 1; }
size_t end() const { return static_cast<size_t>(storage[2]); }
size_t index(EdgeType edge) const {
return edge == kFront ? begin() : back();
}
// Properties: size and capacity.
// `capacity` contains the current capacity of this instance, where
// `kMaxCapacity` contains the maximum capacity of a btree node.
// For now, `capacity` and `kMaxCapacity` return the same value, but this may
// change in the future if we see benefit in dynamically sizing 'small' nodes
// to 'large' nodes for large data trees.
size_t size() const { return end() - begin(); }
size_t capacity() const { return kMaxCapacity; }
// Edge access
inline CordRep* Edge(size_t index) const;
inline CordRep* Edge(EdgeType edge_type) const;
inline absl::Span<CordRep* const> Edges() const;
inline absl::Span<CordRep* const> Edges(size_t begin, size_t end) const;
// Returns reference to the data edge at `index`.
// Requires this instance to be a leaf node, and `index` to be valid index.
inline absl::string_view Data(size_t index) const;
// Diagnostics: returns true if `tree` is valid and internally consistent.
// If `shallow` is false, then the provided top level node and all child nodes
// below it are recursively checked. If `shallow` is true, only the provided
// node in `tree` and the cumulative length, type and height of the direct
// child nodes of `tree` are checked. The value of `shallow` is ignored if the
// internal `cord_btree_exhaustive_validation` diagnostics variable is true,
// in which case the performed validations works as if `shallow` were false.
// This function is intended for debugging and testing purposes only.
static bool IsValid(const CordRepBtree* tree, bool shallow = false);
// Diagnostics: asserts that the provided tree is valid.
// `AssertValid()` performs a shallow validation by default. `shallow` can be
// set to false in which case an exhaustive validation is performed. This
// function is implemented in terms of calling `IsValid()` and asserting the
// return value to be true. See `IsValid()` for more information.
// This function is intended for debugging and testing purposes only.
static CordRepBtree* AssertValid(CordRepBtree* tree, bool shallow = true);
static const CordRepBtree* AssertValid(const CordRepBtree* tree,
bool shallow = true);
// Diagnostics: dump the contents of this tree to `stream`.
// This function is intended for debugging and testing purposes only.
static void Dump(const CordRep* rep, std::ostream& stream);
static void Dump(const CordRep* rep, absl::string_view label,
std::ostream& stream);
static void Dump(const CordRep* rep, absl::string_view label,
bool include_contents, std::ostream& stream);
// Adds the edge `edge` to this node if possible. `owned` indicates if the
// current node is potentially shared or not with other threads. Returns:
// - {kSelf, <this>}
// The edge was directly added to this node.
// - {kCopied, <node>}
// The edge was added to a copy of this node.
// - {kPopped, New(edge, height())}
// A new leg with the edge was created as this node has no extra capacity.
template <EdgeType edge_type>
inline OpResult AddEdge(bool owned, CordRep* edge, size_t delta);
// Replaces the front or back edge with the provided new edge. Returns:
// - {kSelf, <this>}
// The edge was directly set in this node. The old edge is unreffed.
// - {kCopied, <node>}
// A copy of this node was created with the new edge value.
// In both cases, the function adopts a reference on `edge`.
template <EdgeType edge_type>
OpResult SetEdge(bool owned, CordRep* edge, size_t delta);
// Creates a new empty node at the specified height.
static CordRepBtree* New(int height = 0);
// Creates a new node containing `rep`, with the height being computed
// automatically based on the type of `rep`.
static CordRepBtree* New(CordRep* rep);
// Creates a new node containing both `front` and `back` at height
// `front.height() + 1`. Requires `back.height() == front.height()`.
static CordRepBtree* New(CordRepBtree* front, CordRepBtree* back);
// Creates a fully balanced tree from the provided tree by rebuilding a new
// tree from all data edges in the input. This function is automatically
// invoked internally when the tree exceeds the maximum height.
static CordRepBtree* Rebuild(CordRepBtree* tree);
private:
CordRepBtree() = default;
~CordRepBtree() = default;
// Initializes the main properties `tag`, `begin`, `end`, `height`.
inline void InitInstance(int height, size_t begin = 0, size_t end = 0);
// Direct property access begin / end
void set_begin(size_t begin) { storage[1] = static_cast<uint8_t>(begin); }
void set_end(size_t end) { storage[2] = static_cast<uint8_t>(end); }
// Decreases the value of `begin` by `n`, and returns the new value. Notice
// how this returns the new value unlike atomic::fetch_add which returns the
// old value. This is because this is used to prepend edges at 'begin - 1'.
size_t sub_fetch_begin(size_t n) {
storage[1] -= static_cast<uint8_t>(n);
return storage[1];
}
// Increases the value of `end` by `n`, and returns the previous value. This
// function is typically used to append edges at 'end'.
size_t fetch_add_end(size_t n) {
const uint8_t current = storage[2];
storage[2] = static_cast<uint8_t>(current + n);
return current;
}
// Returns the index of the last edge starting on, or before `offset`, with
// `n` containing the relative offset of `offset` inside that edge.
// Requires `offset` < length.
Position IndexOf(size_t offset) const;
// Returns the index of the last edge starting before `offset`, with `n`
// containing the relative offset of `offset` inside that edge.
// This function is useful to find the edges for some span of bytes ending at
// `offset` (i.e., `n` bytes). For example:
//
// Position pos = IndexBefore(n)
// edges = Edges(begin(), pos.index) // All full edges (may be empty)
// last = Sub(Edge(pos.index), 0, pos.n) // Last partial edge (may be empty)
//
// Requires 0 < `offset` <= length.
Position IndexBefore(size_t offset) const;
// Returns the index of the edge ending at (or on) length `length`, and the
// number of bytes inside that edge up to `length`. For example, if we have a
// Node with 2 edges, one of 10 and one of 20 long, then IndexOfLength(27)
// will return {1, 17}, and IndexOfLength(10) will return {0, 10}.
Position IndexOfLength(size_t n) const;
// Identical to the above function except starting from the position `front`.
// This function is equivalent to `IndexBefore(front.n + offset)`, with
// the difference that this function is optimized to start at `front.index`.
Position IndexBefore(Position front, size_t offset) const;
// Returns the index of the edge directly beyond the edge containing offset
// `offset`, with `n` containing the distance of that edge from `offset`.
// This function is useful for iteratively finding suffix nodes and remaining
// partial bytes in left-most suffix nodes as for example in CopySuffix.
// Requires `offset` < length.
Position IndexBeyond(size_t offset) const;
// Creates a new leaf node containing as much data as possible from `data`.
// The data is added either forwards or reversed depending on `edge_type`.
// Callers must check the length of the returned node to determine if all data
// was copied or not.
// See the `Append/Prepend` function for the meaning and purpose of `extra`.
template <EdgeType edge_type>
static CordRepBtree* NewLeaf(absl::string_view data, size_t extra);
// Creates a raw copy of this Btree node with the specified length, copying
// all properties, but without adding any references to existing edges.
CordRepBtree* CopyRaw(size_t new_length) const;
// Creates a full copy of this Btree node, adding a reference on all edges.
CordRepBtree* Copy() const;
// Creates a partial copy of this Btree node, copying all edges up to `end`,
// adding a reference on each copied edge, and sets the length of the newly
// created copy to `new_length`.
CordRepBtree* CopyBeginTo(size_t end, size_t new_length) const;
// Returns a tree containing the edges [tree->begin(), end) and length
// of `new_length`. This method consumes a reference on the provided
// tree, and logically performs the following operation:
// result = tree->CopyBeginTo(end, new_length);
// CordRep::Unref(tree);
// return result;
static CordRepBtree* ConsumeBeginTo(CordRepBtree* tree, size_t end,
size_t new_length);
// Creates a partial copy of this Btree node, copying all edges starting at
// `begin`, adding a reference on each copied edge, and sets the length of
// the newly created copy to `new_length`.
CordRepBtree* CopyToEndFrom(size_t begin, size_t new_length) const;
// Extracts and returns the front edge from the provided tree.
// This method consumes a reference on the provided tree, and logically
// performs the following operation:
// edge = CordRep::Ref(tree->Edge(kFront));
// CordRep::Unref(tree);
// return edge;
static CordRep* ExtractFront(CordRepBtree* tree);
// Returns a tree containing the result of appending `right` to `left`.
static CordRepBtree* MergeTrees(CordRepBtree* left, CordRepBtree* right);
// Fallback functions for `Create()`, `Append()` and `Prepend()` which
// deal with legacy / non conforming input, i.e.: CONCAT trees.
static CordRepBtree* CreateSlow(CordRep* rep);
static CordRepBtree* AppendSlow(CordRepBtree*, CordRep* rep);
static CordRepBtree* PrependSlow(CordRepBtree*, CordRep* rep);
// Recursively rebuilds `tree` into `stack`. If 'consume` is set to true, the
// function will consume a reference on `tree`. `stack` is a null terminated
// array containing the new tree's state, with the current leaf node at
// stack[0], and parent nodes above that, or null for 'top of tree'.
static void Rebuild(CordRepBtree** stack, CordRepBtree* tree, bool consume);
// Aligns existing edges to start at index 0, to allow for a new edge to be
// added to the back of the current edges.
inline void AlignBegin();
// Aligns existing edges to end at `capacity`, to allow for a new edge to be
// added in front of the current edges.
inline void AlignEnd();
// Adds the provided edge to this node.
// Requires this node to have capacity for the edge. Realigns / moves
// existing edges as needed to prepend or append the new edge.
template <EdgeType edge_type>
inline void Add(CordRep* rep);
// Adds the provided edges to this node.
// Requires this node to have capacity for the edges. Realigns / moves
// existing edges as needed to prepend or append the new edges.
template <EdgeType edge_type>
inline void Add(absl::Span<CordRep* const>);
// Adds data from `data` to this node until either all data has been consumed,
// or there is no more capacity for additional flat nodes inside this node.
// Requires the current node to be a leaf node, data to be non empty, and the
// current node to have capacity for at least one more data edge.
// Returns any remaining data from `data` that was not added, which is
// depending on the edge type (front / back) either the remaining prefix of
// suffix of the input.
// See the `Append/Prepend` function for the meaning and purpose of `extra`.
template <EdgeType edge_type>
absl::string_view AddData(absl::string_view data, size_t extra);
// Replace the front or back edge with the provided value.
// Adopts a reference on `edge` and unrefs the old edge.
template <EdgeType edge_type>
inline void SetEdge(CordRep* edge);
// Returns a partial copy of the current tree containing the first `n` bytes
// of data. `CopyResult` contains both the resulting edge and its height. The
// resulting tree may be less high than the current tree, or even be a single
// matching data edge if `allow_folding` is set to true.
// For example, if `n == 1`, then the result will be the single data edge, and
// height will be set to -1 (one below the owning leaf node). If n == 0, this
// function returns null. Requires `n <= length`
CopyResult CopyPrefix(size_t n, bool allow_folding = true);
// Returns a partial copy of the current tree containing all data starting
// after `offset`. `CopyResult` contains both the resulting edge and its
// height. The resulting tree may be less high than the current tree, or even
// be a single matching data edge. For example, if `n == length - 1`, then the
// result will be a single data edge, and height will be set to -1 (one below
// the owning leaf node).
// Requires `offset < length`
CopyResult CopySuffix(size_t offset);
// Returns a OpResult value of {this, kSelf} or {Copy(), kCopied}
// depending on the value of `owned`.
inline OpResult ToOpResult(bool owned);
// Adds `rep` to the specified tree, returning the modified tree.
template <EdgeType edge_type>
static CordRepBtree* AddCordRep(CordRepBtree* tree, CordRep* rep);
// Adds `data` to the specified tree, returning the modified tree.
// See the `Append/Prepend` function for the meaning and purpose of `extra`.
template <EdgeType edge_type>
static CordRepBtree* AddData(CordRepBtree* tree, absl::string_view data,
size_t extra = 0);
// Merges `src` into `dst` with `src` being added either before (kFront) or
// after (kBack) `dst`. Requires the height of `dst` to be greater than or
// equal to the height of `src`.
template <EdgeType edge_type>
static CordRepBtree* Merge(CordRepBtree* dst, CordRepBtree* src);
// Fallback version of GetAppendBuffer for large trees: GetAppendBuffer()
// implements an inlined version for trees of limited height (3 levels),
// GetAppendBufferSlow implements the logic for large trees.
Span<char> GetAppendBufferSlow(size_t size);
// `edges_` contains all edges starting from this instance.
// These are explicitly `child` edges only, a cord btree (or any cord tree in
// that respect) does not store `parent` pointers anywhere: multiple trees /
// parents can reference the same shared child edge. The type of these edges
// depends on the height of the node. `Leaf nodes` (height == 0) contain `data
// edges` (external or flat nodes, or sub-strings thereof). All other nodes
// (height > 0) contain pointers to BTREE nodes with a height of `height - 1`.
CordRep* edges_[kMaxCapacity];
friend class CordRepBtreeTestPeer;
friend class CordRepBtreeNavigator;
};
inline CordRepBtree* CordRep::btree() {
assert(IsBtree());
return static_cast<CordRepBtree*>(this);
}
inline const CordRepBtree* CordRep::btree() const {
assert(IsBtree());
return static_cast<const CordRepBtree*>(this);
}
inline void CordRepBtree::InitInstance(int height, size_t begin, size_t end) {
tag = BTREE;
storage[0] = static_cast<uint8_t>(height);
storage[1] = static_cast<uint8_t>(begin);
storage[2] = static_cast<uint8_t>(end);
}
inline CordRep* CordRepBtree::Edge(size_t index) const {
assert(index >= begin());
assert(index < end());
return edges_[index];
}
inline CordRep* CordRepBtree::Edge(EdgeType edge_type) const {
return edges_[edge_type == kFront ? begin() : back()];
}
inline absl::Span<CordRep* const> CordRepBtree::Edges() const {
return {edges_ + begin(), size()};
}
inline absl::Span<CordRep* const> CordRepBtree::Edges(size_t begin,
size_t end) const {
assert(begin <= end);
assert(begin >= this->begin());
assert(end <= this->end());
return {edges_ + begin, static_cast<size_t>(end - begin)};
}
inline absl::string_view CordRepBtree::Data(size_t index) const {
assert(height() == 0);
return EdgeData(Edge(index));
}
inline CordRepBtree* CordRepBtree::New(int height) {
CordRepBtree* tree = new CordRepBtree;
tree->length = 0;
tree->InitInstance(height);
return tree;
}
inline CordRepBtree* CordRepBtree::New(CordRep* rep) {
CordRepBtree* tree = new CordRepBtree;
int height = rep->IsBtree() ? rep->btree()->height() + 1 : 0;
tree->length = rep->length;
tree->InitInstance(height, /*begin=*/0, /*end=*/1);
tree->edges_[0] = rep;
return tree;
}
inline CordRepBtree* CordRepBtree::New(CordRepBtree* front,
CordRepBtree* back) {
assert(front->height() == back->height());
CordRepBtree* tree = new CordRepBtree;
tree->length = front->length + back->length;
tree->InitInstance(front->height() + 1, /*begin=*/0, /*end=*/2);
tree->edges_[0] = front;
tree->edges_[1] = back;
return tree;
}
inline void CordRepBtree::Unref(absl::Span<CordRep* const> edges) {
for (CordRep* edge : edges) {
if (ABSL_PREDICT_FALSE(!edge->refcount.Decrement())) {
CordRep::Destroy(edge);
}
}
}
inline CordRepBtree* CordRepBtree::CopyRaw(size_t new_length) const {
CordRepBtree* tree = new CordRepBtree;
// `length` and `refcount` are the first members of `CordRepBtree`.
// We initialize `length` using the given length, have `refcount` be set to
// ref = 1 through its default constructor, and copy all data beyond
// 'refcount' which starts with `tag` using a single memcpy: all contents
// except `refcount` is trivially copyable, and the compiler does not
// efficiently coalesce member-wise copy of these members.
// See https://gcc.godbolt.org/z/qY8zsca6z
// LINT.IfChange(copy_raw)
tree->length = new_length;
uint8_t* dst = &tree->tag;
const uint8_t* src = &tag;
const ptrdiff_t offset = src - reinterpret_cast<const uint8_t*>(this);
memcpy(dst, src, sizeof(CordRepBtree) - static_cast<size_t>(offset));
return tree;
// LINT.ThenChange()
}
inline CordRepBtree* CordRepBtree::Copy() const {
CordRepBtree* tree = CopyRaw(length);
for (CordRep* rep : Edges()) CordRep::Ref(rep);
return tree;
}
inline CordRepBtree* CordRepBtree::CopyToEndFrom(size_t begin,
size_t new_length) const {
assert(begin >= this->begin());
assert(begin <= this->end());
CordRepBtree* tree = CopyRaw(new_length);
tree->set_begin(begin);
for (CordRep* edge : tree->Edges()) CordRep::Ref(edge);
return tree;
}
inline CordRepBtree* CordRepBtree::CopyBeginTo(size_t end,
size_t new_length) const {
assert(end <= capacity());
assert(end >= this->begin());
CordRepBtree* tree = CopyRaw(new_length);
tree->set_end(end);
for (CordRep* edge : tree->Edges()) CordRep::Ref(edge);
return tree;
}
inline void CordRepBtree::AlignBegin() {
// The below code itself does not need to be fast as typically we have
// mono-directional append/prepend calls, and `begin` / `end` are typically
// adjusted no more than once. But we want to avoid potential register clobber
// effects, making the compiler emit register save/store/spills, and minimize
// the size of code.
const size_t delta = begin();
if (ABSL_PREDICT_FALSE(delta != 0)) {
const size_t new_end = end() - delta;
set_begin(0);
set_end(new_end);
// TODO(mvels): we can write this using 2 loads / 2 stores depending on
// total size for the kMaxCapacity = 6 case. I.e., we can branch (switch) on
// size, and then do overlapping load/store of up to 4 pointers (inlined as
// XMM, YMM or ZMM load/store) and up to 2 pointers (XMM / YMM), which is a)
// compact and b) not clobbering any registers.
ABSL_ASSUME(new_end <= kMaxCapacity);
#ifdef __clang__
#pragma unroll 1
#endif
for (size_t i = 0; i < new_end; ++i) {
edges_[i] = edges_[i + delta];
}
}
}
inline void CordRepBtree::AlignEnd() {
// See comments in `AlignBegin` for motivation on the hand-rolled for loops.
const size_t delta = capacity() - end();
if (delta != 0) {
const size_t new_begin = begin() + delta;
const size_t new_end = end() + delta;
set_begin(new_begin);
set_end(new_end);
ABSL_ASSUME(new_end <= kMaxCapacity);
#ifdef __clang__
#pragma unroll 1
#endif
for (size_t i = new_end - 1; i >= new_begin; --i) {
edges_[i] = edges_[i - delta];
}
}
}
template <>
inline void CordRepBtree::Add<CordRepBtree::kBack>(CordRep* rep) {
AlignBegin();
edges_[fetch_add_end(1)] = rep;
}
template <>
inline void CordRepBtree::Add<CordRepBtree::kBack>(
absl::Span<CordRep* const> edges) {
AlignBegin();
size_t new_end = end();
for (CordRep* edge : edges) edges_[new_end++] = edge;
set_end(new_end);
}
template <>
inline void CordRepBtree::Add<CordRepBtree::kFront>(CordRep* rep) {
AlignEnd();
edges_[sub_fetch_begin(1)] = rep;
}
template <>
inline void CordRepBtree::Add<CordRepBtree::kFront>(
absl::Span<CordRep* const> edges) {
AlignEnd();
size_t new_begin = begin() - edges.size();
set_begin(new_begin);
for (CordRep* edge : edges) edges_[new_begin++] = edge;
}
template <CordRepBtree::EdgeType edge_type>
inline void CordRepBtree::SetEdge(CordRep* edge) {
const int idx = edge_type == kFront ? begin() : back();
CordRep::Unref(edges_[idx]);
edges_[idx] = edge;
}
inline CordRepBtree::OpResult CordRepBtree::ToOpResult(bool owned) {
return owned ? OpResult{this, kSelf} : OpResult{Copy(), kCopied};
}
inline CordRepBtree::Position CordRepBtree::IndexOf(size_t offset) const {
assert(offset < length);
size_t index = begin();
while (offset >= edges_[index]->length) offset -= edges_[index++]->length;
return {index, offset};
}
inline CordRepBtree::Position CordRepBtree::IndexBefore(size_t offset) const {
assert(offset > 0);
assert(offset <= length);
size_t index = begin();
while (offset > edges_[index]->length) offset -= edges_[index++]->length;
return {index, offset};
}
inline CordRepBtree::Position CordRepBtree::IndexBefore(Position front,
size_t offset) const {
size_t index = front.index;
offset = offset + front.n;
while (offset > edges_[index]->length) offset -= edges_[index++]->length;
return {index, offset};
}
inline CordRepBtree::Position CordRepBtree::IndexOfLength(size_t n) const {
assert(n <= length);
size_t index = back();
size_t strip = length - n;
while (strip >= edges_[index]->length) strip -= edges_[index--]->length;
return {index, edges_[index]->length - strip};
}
inline CordRepBtree::Position CordRepBtree::IndexBeyond(
const size_t offset) const {
// We need to find the edge which `starting offset` is beyond (>=)`offset`.
// For this we can't use the `offset -= length` logic of IndexOf. Instead, we
// track the offset of the `current edge` in `off`, which we increase as we
// iterate over the edges until we find the matching edge.
size_t off = 0;
size_t index = begin();
while (offset > off) off += edges_[index++]->length;
return {index, off - offset};
}
inline CordRepBtree* CordRepBtree::Create(CordRep* rep) {
if (IsDataEdge(rep)) return New(rep);
return CreateSlow(rep);
}
inline Span<char> CordRepBtree::GetAppendBuffer(size_t size) {
assert(refcount.IsOne());
CordRepBtree* tree = this;
const int height = this->height();
CordRepBtree* n1 = tree;
CordRepBtree* n2 = tree;
CordRepBtree* n3 = tree;
switch (height) {
case 3:
tree = tree->Edge(kBack)->btree();
if (!tree->refcount.IsOne()) return {};
n2 = tree;
ABSL_FALLTHROUGH_INTENDED;
case 2:
tree = tree->Edge(kBack)->btree();
if (!tree->refcount.IsOne()) return {};
n1 = tree;
ABSL_FALLTHROUGH_INTENDED;
case 1:
tree = tree->Edge(kBack)->btree();
if (!tree->refcount.IsOne()) return {};
ABSL_FALLTHROUGH_INTENDED;
case 0:
CordRep* edge = tree->Edge(kBack);
if (!edge->refcount.IsOne()) return {};
if (edge->tag < FLAT) return {};
size_t avail = edge->flat()->Capacity() - edge->length;
if (avail == 0) return {};
size_t delta = (std::min)(size, avail);
Span<char> span = {edge->flat()->Data() + edge->length, delta};
edge->length += delta;
switch (height) {
case 3:
n3->length += delta;
ABSL_FALLTHROUGH_INTENDED;
case 2:
n2->length += delta;
ABSL_FALLTHROUGH_INTENDED;
case 1:
n1->length += delta;
ABSL_FALLTHROUGH_INTENDED;
case 0:
tree->length += delta;
return span;
}
break;
}
return GetAppendBufferSlow(size);
}
extern template CordRepBtree* CordRepBtree::AddCordRep<CordRepBtree::kBack>(
CordRepBtree* tree, CordRep* rep);
extern template CordRepBtree* CordRepBtree::AddCordRep<CordRepBtree::kFront>(
CordRepBtree* tree, CordRep* rep);
inline CordRepBtree* CordRepBtree::Append(CordRepBtree* tree, CordRep* rep) {
if (ABSL_PREDICT_TRUE(IsDataEdge(rep))) {
return CordRepBtree::AddCordRep<kBack>(tree, rep);
}
return AppendSlow(tree, rep);
}
inline CordRepBtree* CordRepBtree::Prepend(CordRepBtree* tree, CordRep* rep) {
if (ABSL_PREDICT_TRUE(IsDataEdge(rep))) {
return CordRepBtree::AddCordRep<kFront>(tree, rep);
}
return PrependSlow(tree, rep);
}
#ifdef NDEBUG
inline CordRepBtree* CordRepBtree::AssertValid(CordRepBtree* tree,
bool /* shallow */) {
return tree;
}
inline const CordRepBtree* CordRepBtree::AssertValid(const CordRepBtree* tree,
bool /* shallow */) {
return tree;
}
#endif
} // namespace cord_internal
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_CORD_REP_BTREE_H_