| 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.hP// Copyright 2017 The Abseil Authors. | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // https://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT 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.he// 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.hB// 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.h9// 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 ¤t_chunk_; | |
| } | |
| inline void Cord::ChunkIterator::RemoveChunkPrefix(size_t n) { | |
| assert(n < current_chunk_.size()); | |
| current_chunk_.remove_prefix(n); | |
| bytes_remaining_ -= n; | |
| } | |
| inline void Cord::ChunkIterator::AdvanceBytes(size_t n) { | |
| 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.hC// | |
| // Copyright 2017 The Abseil Authors. | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // https://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT 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.hf// 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.hj// 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_ |