From bdca36724fe13f60868c0140a18f88d9bba71f40 Mon Sep 17 00:00:00 2001 From: MacroModel Date: Sat, 17 May 2025 02:25:10 +0800 Subject: [PATCH 1/3] FAST_IO_HAS_BUILTIN, fix win9x mutex, fix use sse2 ins in sse --- .../fast_io_core_impl/allocation/c_malloc.h | 44 +- .../allocation/nt_preliminary_definition.h | 2 + include/fast_io_core_impl/codecvt/general.h | 2 +- include/fast_io_core_impl/codecvt/utf.h | 6 +- .../freestanding/algorithm.h | 36 +- .../freestanding/allocator.h | 8 +- .../fast_io_core_impl/freestanding/bytes.h | 44 +- .../fast_io_core_impl/freestanding/cstr_len.h | 12 +- include/fast_io_core_impl/intrinsics.h | 90 +- include/fast_io_core_impl/intrinsics/carry.h | 8 +- include/fast_io_core_impl/intrinsics/umul.h | 8 +- include/fast_io_core_impl/io_lockable.h | 7 + include/fast_io_core_impl/iso/iso8601.h | 44 +- .../fast_io_core_impl/local_new_array_ptr.h | 4 +- .../fast_io_core_impl/operations/lockguard.h | 28 + .../operations/print_freestanding.h | 1466 +++++++++++++++++ .../fast_io_core_impl/secure_clear_guard.h | 12 +- include/fast_io_core_impl/simd/gcc_clang.h | 60 +- include/fast_io_core_impl/simd/generic.h | 12 +- include/fast_io_core_impl/simd/is_all_zeros.h | 2 +- include/fast_io_core_impl/socket/addrscn.h | 18 +- include/fast_io_core_impl/terminate.h | 8 +- include/fast_io_core_impl/timestamp_counter.h | 6 +- include/fast_io_core_impl/utils.h | 8 +- include/fast_io_crypto/hash/crc32.h | 12 +- .../hash/md5_sha_hash_context.h | 18 +- include/fast_io_crypto/hash/sha256.h | 6 +- include/fast_io_crypto/hash/sha512.h | 4 +- include/fast_io_crypto/hash/sha512_simd16.h | 4 +- include/fast_io_crypto/hash/sha512_simd32.h | 2 +- .../hash/sha512_simd32_shuffle.h | 2 +- .../fast_io_crypto/streamcipher/chacha/impl.h | 2 +- include/fast_io_driver/tsc_timer.h | 2 +- include/fast_io_dsal/impl/freestanding.h | 6 +- include/fast_io_dsal/impl/misc/pop_macros.h | 1 + include/fast_io_dsal/impl/misc/push_macros.h | 10 +- .../serializations/lebe.h | 12 +- .../file_loaders/allocation_file_loader.h | 18 +- .../fast_io_hosted/file_loaders/file_size.h | 6 +- include/fast_io_hosted/filesystem/nt.h | 4 +- .../fast_io_hosted/platforms/linux/amd64.h | 1 - include/fast_io_hosted/threads/mutex/impl.h | 4 - .../timeutil/environ_timezone.h | 6 +- include/fast_io_i18n/locale/posix.h | 6 +- include/fast_io_legacy_impl/c/done.h | 55 +- include/fast_io_legacy_impl/c/impl.h | 30 +- include/fast_io_legacy_impl/c/wincrt.h | 10 +- .../filebuf/rtti_hack/impl.h | 6 +- include/fast_io_unit/floating/punning.h | 6 +- 49 files changed, 1691 insertions(+), 477 deletions(-) create mode 100644 include/fast_io_core_impl/operations/print_freestanding.h diff --git a/include/fast_io_core_impl/allocation/c_malloc.h b/include/fast_io_core_impl/allocation/c_malloc.h index a1316de92..c77b868d5 100644 --- a/include/fast_io_core_impl/allocation/c_malloc.h +++ b/include/fast_io_core_impl/allocation/c_malloc.h @@ -39,12 +39,8 @@ class c_malloc_allocator n = 1; } void *p = -#if defined(__has_builtin) -#if __has_builtin(__builtin_malloc) +#if FAST_IO_HAS_BUILTIN(__builtin_malloc) __builtin_malloc(n) -#else - ::std::malloc(n) -#endif #else ::std::malloc(n) #endif @@ -66,12 +62,8 @@ class c_malloc_allocator } ::std::size_t const to_allocate{n}; p = -#if defined(__has_builtin) -#if __has_builtin(__builtin_realloc) +#if FAST_IO_HAS_BUILTIN(__builtin_realloc) __builtin_realloc -#else - ::std::realloc -#endif #else ::std::realloc #endif @@ -93,12 +85,8 @@ class c_malloc_allocator n = 1; } void *p = -#if defined(__has_builtin) -#if __has_builtin(__builtin_calloc) +#if FAST_IO_HAS_BUILTIN(__builtin_calloc) __builtin_calloc -#else - ::std::calloc -#endif #else ::std::calloc #endif @@ -142,12 +130,8 @@ class c_malloc_allocator if (alignment <= __STDCPP_DEFAULT_NEW_ALIGNMENT__) { p = -#if defined(__has_builtin) -#if __has_builtin(__builtin_malloc) +#if FAST_IO_HAS_BUILTIN(__builtin_malloc) __builtin_malloc -#else - ::std::malloc -#endif #else ::std::malloc #endif @@ -175,12 +159,8 @@ class c_malloc_allocator if (alignment <= __STDCPP_DEFAULT_NEW_ALIGNMENT__) { p = -#if defined(__has_builtin) -#if __has_builtin(__builtin_realloc) +#if FAST_IO_HAS_BUILTIN(__builtin_realloc) __builtin_realloc -#else - ::std::realloc -#endif #else ::std::realloc #endif @@ -205,12 +185,8 @@ class c_malloc_allocator } if (alignment <= __STDCPP_DEFAULT_NEW_ALIGNMENT__) { -#if defined(__has_builtin) -#if __has_builtin(__builtin_free) +#if FAST_IO_HAS_BUILTIN(__builtin_free) __builtin_free -#else - ::std::free -#endif #else ::std::free #endif @@ -228,12 +204,8 @@ class c_malloc_allocator { return; } -#if defined(__has_builtin) -#if __has_builtin(__builtin_free) - __builtin_free -#else - ::std::free -#endif +#if FAST_IO_HAS_BUILTIN(__builtin_free) + __builtin_free #else ::std::free #endif diff --git a/include/fast_io_core_impl/allocation/nt_preliminary_definition.h b/include/fast_io_core_impl/allocation/nt_preliminary_definition.h index c2a65cd34..55884e405 100644 --- a/include/fast_io_core_impl/allocation/nt_preliminary_definition.h +++ b/include/fast_io_core_impl/allocation/nt_preliminary_definition.h @@ -96,6 +96,7 @@ struct gdi_teb_batch ::std::uint_least32_t Buffer[310]; }; +// NOLINTBEGIN(*-optin.performance.Padding) struct teb { nt_tib NtTib; @@ -265,6 +266,7 @@ struct teb ::std::uint_least32_t SpinCallCount; ::std::uint_least64_t ExtendedFeatureDisableMask; }; +// NOLINTEND(*-optin.performance.Padding) FAST_IO_DLLIMPORT FAST_IO_GNU_MALLOC void *FAST_IO_WINSTDCALL RtlAllocateHeap(void *, ::std::uint_least32_t, ::std::size_t) noexcept FAST_IO_WINSTDCALL_RENAME(RtlAllocateHeap, 12); FAST_IO_DLLIMPORT char unsigned FAST_IO_WINSTDCALL RtlFreeHeap(void *, ::std::uint_least32_t, void *) noexcept FAST_IO_WINSTDCALL_RENAME(RtlFreeHeap, 12); diff --git a/include/fast_io_core_impl/codecvt/general.h b/include/fast_io_core_impl/codecvt/general.h index 9a4a36519..2dbd4af8f 100644 --- a/include/fast_io_core_impl/codecvt/general.h +++ b/include/fast_io_core_impl/codecvt/general.h @@ -193,7 +193,7 @@ general_code_cvt(src_char_type const *src_first, src_char_type const *src_last, else { #if (defined(_MSC_VER) && defined(_M_AMD64) && !defined(__clang__)) || \ - (defined(__SSE__) && defined(__x86_64__) && __cpp_lib_is_constant_evaluated >= 201811L) + (defined(__SSE__) && defined(__SSE2__) && defined(__x86_64__) && __cpp_lib_is_constant_evaluated >= 201811L) if constexpr (src_encoding != encoding_scheme::utf_ebcdic && encoding != encoding_scheme::utf_ebcdic && 1 == sizeof(src_char_type) && (1 == sizeof(dest_char_type) || encoding_is_utf(encoding))) { diff --git a/include/fast_io_core_impl/codecvt/utf.h b/include/fast_io_core_impl/codecvt/utf.h index f4e9fe83f..9e3e9e080 100644 --- a/include/fast_io_core_impl/codecvt/utf.h +++ b/include/fast_io_core_impl/codecvt/utf.h @@ -498,7 +498,7 @@ inline constexpr char32_t utf16_surrogate_to_utf32(char16_t high, char16_t low) return static_cast((static_cast<::std::uint_least32_t>(high) << 10u) + low - 0x35fdc00u); } -#if (defined(_MSC_VER) && defined(_M_AMD64) && !defined(__clang__)) || (defined(__SSE__) && defined(__x86_64__)) +#if (defined(_MSC_VER) && defined(_M_AMD64) && !defined(__clang__)) || (defined(__SSE__) && defined(__SSE2__) && defined(__x86_64__)) template <::std::integral T, ::std::integral U> requires((sizeof(T) == 1) && (sizeof(U) == 1 || sizeof(U) == 2 || sizeof(U) == 4)) inline code_cvt_result convert_ascii_with_sse(T const *__restrict pSrc, U *__restrict pDst) noexcept @@ -520,7 +520,7 @@ inline code_cvt_result convert_ascii_with_sse(T const *__restrict pSrc, U x86_64_v16qi chunk; __builtin_memcpy(__builtin_addressof(chunk), pSrc, m128i_size); mask = static_cast<::std::uint_least32_t>(__builtin_ia32_pmovmskb128(chunk)); -#if __has_builtin(__builtin_shufflevector) +#if FAST_IO_HAS_BUILTIN(__builtin_shufflevector) x86_64_v16qi half{__builtin_shufflevector(chunk, zero, 0, 16 + 0, 1, 16 + 1, 2, 16 + 2, 3, 16 + 3, 4, 16 + 4, 5, 16 + 5, 6, 16 + 6, 7, 16 + 7)}; __builtin_memcpy(pDst, __builtin_addressof(half), m128i_size); @@ -539,7 +539,7 @@ inline code_cvt_result convert_ascii_with_sse(T const *__restrict pSrc, U x86_64_v16qi chunk; __builtin_memcpy(__builtin_addressof(chunk), pSrc, m128i_size); mask = static_cast<::std::uint_least32_t>(__builtin_ia32_pmovmskb128(chunk)); -#if __has_builtin(__builtin_shufflevector) +#if FAST_IO_HAS_BUILTIN(__builtin_shufflevector) x86_64_v16qi half_result{__builtin_shufflevector(chunk, zero, 0, 16 + 0, 1, 16 + 1, 2, 16 + 2, 3, 16 + 3, 4, 16 + 4, 5, 16 + 5, 6, 16 + 6, 7, 16 + 7)}; x86_64_v8hi half; diff --git a/include/fast_io_core_impl/freestanding/algorithm.h b/include/fast_io_core_impl/freestanding/algorithm.h index a460f26e4..e235170bf 100644 --- a/include/fast_io_core_impl/freestanding/algorithm.h +++ b/include/fast_io_core_impl/freestanding/algorithm.h @@ -243,21 +243,15 @@ namespace fast_io::freestanding { inline -#if defined(__has_builtin) -#if __has_builtin(__builtin_memcpy) +#if FAST_IO_HAS_BUILTIN(__builtin_memcpy) constexpr -#endif #endif void * my_memcpy(void *dest, void const *src, ::std::size_t count) noexcept { return -#if defined(__has_builtin) -#if __has_builtin(__builtin_memcpy) +#if FAST_IO_HAS_BUILTIN(__builtin_memcpy) __builtin_memcpy -#else - ::std::memcpy -#endif #else ::std::memcpy #endif @@ -265,21 +259,15 @@ inline } inline -#if defined(__has_builtin) -#if __has_builtin(__builtin_memmove) +#if FAST_IO_HAS_BUILTIN(__builtin_memmove) constexpr -#endif #endif void * my_memmove(void *dest, void const *src, ::std::size_t count) noexcept { return -#if defined(__has_builtin) -#if __has_builtin(__builtin_memmove) +#if FAST_IO_HAS_BUILTIN(__builtin_memmove) __builtin_memmove -#else - ::std::memmove -#endif #else ::std::memmove #endif @@ -289,12 +277,8 @@ inline inline void *my_memset(void *dest, int ch, ::std::size_t count) noexcept { return -#if defined(__has_builtin) -#if __has_builtin(__builtin_memset) +#if FAST_IO_HAS_BUILTIN(__builtin_memset) __builtin_memset -#else - ::std::memset -#endif #else ::std::memset #endif @@ -302,21 +286,15 @@ inline void *my_memset(void *dest, int ch, ::std::size_t count) noexcept } inline -#if defined(__has_builtin) -#if __has_builtin(__builtin_memcmp) +#if FAST_IO_HAS_BUILTIN(__builtin_memcmp) constexpr -#endif #endif int my_memcmp(void const *dest, void const *src, ::std::size_t count) noexcept { return -#if defined(__has_builtin) -#if __has_builtin(__builtin_memcmp) +#if FAST_IO_HAS_BUILTIN(__builtin_memcmp) __builtin_memcmp -#else - ::std::memcmp -#endif #else ::std::memcmp #endif diff --git a/include/fast_io_core_impl/freestanding/allocator.h b/include/fast_io_core_impl/freestanding/allocator.h index 96145f62a..97210edd4 100644 --- a/include/fast_io_core_impl/freestanding/allocator.h +++ b/include/fast_io_core_impl/freestanding/allocator.h @@ -13,8 +13,8 @@ struct allocator { __builtin_trap(); } -#if __has_builtin(__builtin_operator_new) - return static_cast(__builtin_operator_new(n * sizeof(T))); +#if FAST_IO_HAS_BUILTIN(__builtin_operator_new) + return static_cast(__builtin_operator_new(n * sizeof(T))); #else __builtin_trap(); return nullptr; @@ -22,8 +22,8 @@ struct allocator } inline constexpr void deallocate([[maybe_unused]] T *ptr, [[maybe_unused]] ::std::size_t n) noexcept { -#if __has_builtin(__builtin_operator_delete) - __builtin_operator_delete(ptr, sizeof(T) * n); +#if FAST_IO_HAS_BUILTIN(__builtin_operator_delete) + __builtin_operator_delete(ptr, sizeof(T) * n); #endif } }; diff --git a/include/fast_io_core_impl/freestanding/bytes.h b/include/fast_io_core_impl/freestanding/bytes.h index da215e319..0596e8fac 100644 --- a/include/fast_io_core_impl/freestanding/bytes.h +++ b/include/fast_io_core_impl/freestanding/bytes.h @@ -8,13 +8,13 @@ struct overlapped_copy_buffer_ptr { T *ptr; inline explicit constexpr overlapped_copy_buffer_ptr(::std::size_t n) noexcept - : ptr(new T[n]) + : ptr(::new T[n]) {} inline overlapped_copy_buffer_ptr(overlapped_copy_buffer_ptr const &) = delete; inline overlapped_copy_buffer_ptr &operator=(overlapped_copy_buffer_ptr const &) = delete; inline constexpr ~overlapped_copy_buffer_ptr() { - delete[] ptr; + ::delete[] ptr; } }; @@ -88,10 +88,8 @@ inline constexpr ::std::byte *bytes_copy_n(::std::byte const *first, ::std::size [[likely]] #endif { -#if !defined(__has_builtin) - ::std::memmove(dest, first, n); -#elif __has_builtin(__builtin_memmove) - __builtin_memmove(dest, first, n); +#if FAST_IO_HAS_BUILTIN(__builtin_memmove) + __builtin_memmove(dest, first, n); #else ::std::memmove(dest, first, n); #endif @@ -122,10 +120,8 @@ inline constexpr ::std::byte *nonoverlapped_bytes_copy_n(::std::byte const *firs [[likely]] #endif { -#if !defined(__has_builtin) - ::std::memcpy(dest, first, n); -#elif __has_builtin(__builtin_memcpy) - __builtin_memcpy(dest, first, n); +#if FAST_IO_HAS_BUILTIN(__builtin_memcpy) + __builtin_memcpy(dest, first, n); #else ::std::memcpy(dest, first, n); #endif @@ -157,10 +153,8 @@ inline constexpr ::std::byte const *type_punning_from_bytes(::std::byte const *_ else #endif { -#if !defined(__has_builtin) - ::std::memcpy(__builtin_addressof(t), first, n); -#elif __has_builtin(__builtin_memcpy) - __builtin_memcpy(__builtin_addressof(t), first, n); +#if FAST_IO_HAS_BUILTIN(__builtin_memcpy) + __builtin_memcpy(__builtin_addressof(t), first, n); #else ::std::memcpy(__builtin_addressof(t), first, n); #endif @@ -184,10 +178,8 @@ inline constexpr ::std::byte *type_punning_to_bytes_n(T const &__restrict first, else #endif { -#if !defined(__has_builtin) - ::std::memcpy(dest, __builtin_addressof(first), n); -#elif __has_builtin(__builtin_memcpy) - __builtin_memcpy(dest, __builtin_addressof(first), n); +#if FAST_IO_HAS_BUILTIN(__builtin_memcpy) + __builtin_memcpy(dest, __builtin_addressof(first), n); #else ::std::memcpy(dest, __builtin_addressof(first), n); #endif @@ -214,12 +206,8 @@ inline constexpr ::std::byte *bytes_clear_n(::std::byte *data, ::std::size_t siz } else { -#if defined(__has_builtin) -#if __has_builtin(__builtin_memset) - __builtin_memset(data, 0, size); -#else - ::std::memset(data, 0, size); -#endif +#if FAST_IO_HAS_BUILTIN(__builtin_memset) + __builtin_memset(data, 0, size); #else ::std::memset(data, 0, size); #endif @@ -243,12 +231,8 @@ inline constexpr ::std::byte *bytes_fill_n(::std::byte *data, ::std::size_t size } else { -#if defined(__has_builtin) -#if __has_builtin(__builtin_memset) - __builtin_memset(data, static_cast(val), size); -#else - ::std::memset(data, static_cast(val), size); -#endif +#if FAST_IO_HAS_BUILTIN(__builtin_memset) + __builtin_memset(data, static_cast(val), size); #else ::std::memset(data, static_cast(val), size); #endif diff --git a/include/fast_io_core_impl/freestanding/cstr_len.h b/include/fast_io_core_impl/freestanding/cstr_len.h index a7fda553a..388e5d807 100644 --- a/include/fast_io_core_impl/freestanding/cstr_len.h +++ b/include/fast_io_core_impl/freestanding/cstr_len.h @@ -39,12 +39,8 @@ inline constexpr ::std::size_t cstr_len(char_type const *cstr) noexcept { if constexpr (::std::same_as) { -#if defined(__has_builtin) -#if __has_builtin(__builtin_strlen) +#if FAST_IO_HAS_BUILTIN(__builtin_strlen) return __builtin_strlen(cstr); -#else - return ::std::strlen(cstr); -#endif #else return ::std::strlen(cstr); #endif @@ -67,12 +63,8 @@ inline constexpr ::std::size_t cstr_nlen(char_type const *cstr, ::std::size_t n) { if constexpr (::std::same_as) { -#if defined(__has_builtin) -#if __has_builtin(__builtin_strnlen) +#if FAST_IO_HAS_BUILTIN(__builtin_strnlen) return __builtin_strnlen(cstr, n); -#else - return details::dummy_cstr_nlen(cstr, n); -#endif #else return details::dummy_cstr_nlen(cstr, n); #endif diff --git a/include/fast_io_core_impl/intrinsics.h b/include/fast_io_core_impl/intrinsics.h index e6c327fc7..64dbe733a 100644 --- a/include/fast_io_core_impl/intrinsics.h +++ b/include/fast_io_core_impl/intrinsics.h @@ -24,14 +24,10 @@ inline { if (dest == nullptr || src == nullptr || sizeof(T1) != sizeof(T2) || bytes % sizeof(T1) != 0) { -#if defined(__has_builtin) -#if __has_builtin(__builtin_trap) +#if FAST_IO_HAS_BUILTIN(__builtin_trap) __builtin_trap(); -#elif __has_builtin(__builtin_abort) +#elif FAST_IO_HAS_BUILTIN(__builtin_abort) __builtin_abort(); -#else - ::std::abort(); -#endif #else ::std::abort(); #endif @@ -45,12 +41,8 @@ inline else #endif { -#if defined(__has_builtin) -#if __has_builtin(__builtin_memcpy) +#if FAST_IO_HAS_BUILTIN(__builtin_memcpy) __builtin_memcpy(dest, src, bytes); -#else - memcpy(dest, src, bytes); -#endif #else memcpy(dest, src, bytes); #endif @@ -90,8 +82,7 @@ using ul32x2 = ul_generic_x2<::std::uint_least32_t>; inline constexpr ::std::uint_least32_t umul_least_32(::std::uint_least32_t a, ::std::uint_least32_t b, ::std::uint_least32_t &high) noexcept { -#if defined(__has_builtin) && defined(__GNUC__) && !defined(__clang__) -#if __has_builtin(__builtin_bit_cast) +#if defined(__GNUC__) && !defined(__clang__) && FAST_IO_HAS_BUILTIN(__builtin_bit_cast) if constexpr (::std::endian::native == ::std::endian::little || ::std::endian::native == ::std::endian::big) { auto ret{__builtin_bit_cast(ul32x2, static_cast<::std::uint_least64_t>(a) * b)}; @@ -99,7 +90,6 @@ inline constexpr ::std::uint_least32_t umul_least_32(::std::uint_least32_t a, :: return ret.low; } else -#endif #endif { ::std::uint_least64_t v{static_cast<::std::uint_least64_t>(a) * b}; @@ -110,15 +100,13 @@ inline constexpr ::std::uint_least32_t umul_least_32(::std::uint_least32_t a, :: inline constexpr ::std::uint_least32_t umulh_least_32(::std::uint_least32_t a, ::std::uint_least32_t b) noexcept { -#if defined(__has_builtin) && defined(__GNUC__) && !defined(__clang__) -#if __has_builtin(__builtin_bit_cast) +#if defined(__GNUC__) && !defined(__clang__) && FAST_IO_HAS_BUILTIN(__builtin_bit_cast) if constexpr (::std::endian::native == ::std::endian::little || ::std::endian::native == ::std::endian::big) { auto ret{__builtin_bit_cast(ul32x2, static_cast<::std::uint_least64_t>(a) * b)}; return ret.high; } else -#endif #endif { ::std::uint_least64_t v{static_cast<::std::uint_least64_t>(a) * b}; @@ -128,8 +116,7 @@ inline constexpr ::std::uint_least32_t umulh_least_32(::std::uint_least32_t a, : inline constexpr ::std::uint_least32_t unpack_ul64(::std::uint_least64_t a, ::std::uint_least32_t &high) noexcept { -#if defined(__has_builtin) && defined(__GNUC__) && !defined(__clang__) -#if __has_builtin(__builtin_bit_cast) +#if defined(__GNUC__) && !defined(__clang__) && FAST_IO_HAS_BUILTIN(__builtin_bit_cast) if constexpr (::std::endian::native == ::std::endian::little) { auto [a0, a1] = __builtin_bit_cast(ul32x2_little_endian, a); // get around gcc bug @@ -143,7 +130,6 @@ inline constexpr ::std::uint_least32_t unpack_ul64(::std::uint_least64_t a, ::st return a0; } else -#endif #endif { high = static_cast<::std::uint_least32_t>(a >> ::std::numeric_limits<::std::uint_least32_t>::digits); @@ -155,8 +141,7 @@ template requires(sizeof(T) == sizeof(U) * 2) inline constexpr U unpack_generic(T a, U &high) noexcept { -#if defined(__has_builtin) && defined(__GNUC__) && !defined(__clang__) -#if __has_builtin(__builtin_bit_cast) +#if defined(__GNUC__) && !defined(__clang__) && FAST_IO_HAS_BUILTIN(__builtin_bit_cast) if constexpr (::std::endian::native == ::std::endian::little) { auto [a0, a1] = __builtin_bit_cast(ul_generic_x2_little_endian, a); // get around gcc bug @@ -170,7 +155,6 @@ inline constexpr U unpack_generic(T a, U &high) noexcept return a0; } else -#endif #endif { high = static_cast(a >> ::std::numeric_limits::digits); @@ -239,9 +223,8 @@ inline constexpr bool add_carry(bool carry, T a, T b, T &out) noexcept #else return add_carry_naive(carry, a, b, out); #endif -#elif defined(__has_builtin) && \ - (__has_builtin(__builtin_addcb) && __has_builtin(__builtin_addcs) && __has_builtin(__builtin_addc) && \ - __has_builtin(__builtin_addcl) && __has_builtin(__builtin_addcll)) +#elif (FAST_IO_HAS_BUILTIN(__builtin_addcb) && FAST_IO_HAS_BUILTIN(__builtin_addcs) && FAST_IO_HAS_BUILTIN(__builtin_addc) && \ + FAST_IO_HAS_BUILTIN(__builtin_addcl) && FAST_IO_HAS_BUILTIN(__builtin_addcll)) if constexpr (sizeof(T) == sizeof(long long unsigned)) { long long unsigned carryout; @@ -276,12 +259,11 @@ inline constexpr bool add_carry(bool carry, T a, T b, T &out) noexcept { return add_carry_naive(carry, a, b, out); } -#elif defined(__has_builtin) && \ - (__has_builtin(__builtin_ia32_addcarryx_u32) || __has_builtin(__builtin_ia32_addcarry_u32) || \ - __has_builtin(__builtin_ia32_addcarryx_u64)) +#elif (FAST_IO_HAS_BUILTIN(__builtin_ia32_addcarryx_u32) || FAST_IO_HAS_BUILTIN(__builtin_ia32_addcarry_u32) || \ + FAST_IO_HAS_BUILTIN(__builtin_ia32_addcarryx_u64)) if constexpr (sizeof(T) == 8) { -#if __has_builtin(__builtin_ia32_addcarryx_u64) +#if FAST_IO_HAS_BUILTIN(__builtin_ia32_addcarryx_u64) using may_alias_ptr_type #if __has_cpp_attribute(__gnu__::__may_alias__) [[__gnu__::__may_alias__]] @@ -289,7 +271,7 @@ inline constexpr bool add_carry(bool carry, T a, T b, T &out) noexcept = unsigned long long *; return __builtin_ia32_addcarryx_u64(carry, a, b, reinterpret_cast(__builtin_addressof(out))); -#elif __has_builtin(__builtin_ia32_addcarry_u64) +#elif FAST_IO_HAS_BUILTIN(__builtin_ia32_addcarry_u64) using may_alias_ptr_type #if __has_cpp_attribute(__gnu__::__may_alias__) [[__gnu__::__may_alias__]] @@ -313,12 +295,12 @@ inline constexpr bool add_carry(bool carry, T a, T b, T &out) noexcept [[__gnu__::__may_alias__]] #endif = unsigned *; -#if __has_builtin(__builtin_ia32_addcarryx_u32) +#if FAST_IO_HAS_BUILTIN(__builtin_ia32_addcarryx_u32) return __builtin_ia32_addcarryx_u32( __builtin_ia32_addcarryx_u32(carry, a_low, b_low, reinterpret_cast(__builtin_addressof(out))), a_high, b_high, reinterpret_cast(__builtin_addressof(out)) + 1); -#elif __has_builtin(__builtin_ia32_addcarry_u32) +#elif FAST_IO_HAS_BUILTIN(__builtin_ia32_addcarry_u32) return __builtin_ia32_addcarry_u32( __builtin_ia32_addcarry_u32(carry, a_low, b_low, reinterpret_cast(__builtin_addressof(out))), @@ -335,10 +317,10 @@ inline constexpr bool add_carry(bool carry, T a, T b, T &out) noexcept [[__gnu__::__may_alias__]] #endif = unsigned *; -#if __has_builtin(__builtin_ia32_addcarryx_u32) +#if FAST_IO_HAS_BUILTIN(__builtin_ia32_addcarryx_u32) return __builtin_ia32_addcarryx_u32(carry, a, b, reinterpret_cast(__builtin_addressof(out))); -#elif __has_builtin(__builtin_ia32_addcarry_u32) +#elif FAST_IO_HAS_BUILTIN(__builtin_ia32_addcarry_u32) return __builtin_ia32_addcarry_u32(carry, a, b, reinterpret_cast(__builtin_addressof(out))); #else @@ -427,9 +409,8 @@ inline constexpr bool sub_borrow(bool borrow, T a, T b, T &out) noexcept #else return sub_borrow_naive(borrow, a, b, out); #endif -#elif defined(__has_builtin) && \ - (__has_builtin(__builtin_subcb) && __has_builtin(__builtin_subcs) && __has_builtin(__builtin_subc) && \ - __has_builtin(__builtin_subcl) && __has_builtin(__builtin_subcll)) +#elif (FAST_IO_HAS_BUILTIN(__builtin_subcb) && FAST_IO_HAS_BUILTIN(__builtin_subcs) && FAST_IO_HAS_BUILTIN(__builtin_subc) && \ + FAST_IO_HAS_BUILTIN(__builtin_subcl) && FAST_IO_HAS_BUILTIN(__builtin_subcll)) if constexpr (sizeof(T) == sizeof(long long unsigned)) { long long unsigned borrowout; @@ -464,12 +445,11 @@ inline constexpr bool sub_borrow(bool borrow, T a, T b, T &out) noexcept { return sub_borrow_naive(borrow, a, b, out); } -#elif defined(__has_builtin) && \ - (__has_builtin(__builtin_ia32_sbb_u32) || __has_builtin(__builtin_ia32_sbb_u64) || \ - __has_builtin(__builtin_ia32_subborrow_u64) || __has_builtin(__builtin_ia32_subborrow_u32)) +#elif (FAST_IO_HAS_BUILTIN(__builtin_ia32_sbb_u32) || FAST_IO_HAS_BUILTIN(__builtin_ia32_sbb_u64) || \ + FAST_IO_HAS_BUILTIN(__builtin_ia32_subborrow_u64) || FAST_IO_HAS_BUILTIN(__builtin_ia32_subborrow_u32)) if constexpr (sizeof(T) == 8) { -#if __has_builtin(__builtin_ia32_sbb_u64) +#if FAST_IO_HAS_BUILTIN(__builtin_ia32_sbb_u64) using may_alias_ptr_type #if __has_cpp_attribute(__gnu__::__may_alias__) [[__gnu__::__may_alias__]] @@ -477,7 +457,7 @@ inline constexpr bool sub_borrow(bool borrow, T a, T b, T &out) noexcept = unsigned long long *; return __builtin_ia32_sbb_u64(borrow, a, b, reinterpret_cast(__builtin_addressof(out))); -#elif __has_builtin(__builtin_ia32_subborrow_u64) +#elif FAST_IO_HAS_BUILTIN(__builtin_ia32_subborrow_u64) using may_alias_ptr_type #if __has_cpp_attribute(__gnu__::__may_alias__) [[__gnu__::__may_alias__]] @@ -485,7 +465,7 @@ inline constexpr bool sub_borrow(bool borrow, T a, T b, T &out) noexcept = unsigned long long *; return __builtin_ia32_subborrow_u64(borrow, a, b, reinterpret_cast(__builtin_addressof(out))); -#elif __has_builtin(__builtin_ia32_sbb_u32) || __has_builtin(__builtin_ia32_subborrow_u32) +#elif FAST_IO_HAS_BUILTIN(__builtin_ia32_sbb_u32) || FAST_IO_HAS_BUILTIN(__builtin_ia32_subborrow_u32) ::std::uint_least32_t a_low; ::std::uint_least32_t a_high; __builtin_memcpy(__builtin_addressof(a_low), __builtin_addressof(a), 4); @@ -501,7 +481,7 @@ inline constexpr bool sub_borrow(bool borrow, T a, T b, T &out) noexcept [[__gnu__::__may_alias__]] #endif = unsigned *; -#if __has_builtin(__builtin_ia32_sbb_u32) +#if FAST_IO_HAS_BUILTIN(__builtin_ia32_sbb_u32) return __builtin_ia32_sbb_u32( __builtin_ia32_sbb_u32(borrow, a_low, b_low, reinterpret_cast(__builtin_addressof(out))), @@ -518,7 +498,7 @@ inline constexpr bool sub_borrow(bool borrow, T a, T b, T &out) noexcept } else if constexpr (sizeof(T) == 4) { -#if __has_builtin(__builtin_ia32_sbb_u32) +#if FAST_IO_HAS_BUILTIN(__builtin_ia32_sbb_u32) using may_alias_ptr_type #if __has_cpp_attribute(__gnu__::__may_alias__) [[__gnu__::__may_alias__]] @@ -526,7 +506,7 @@ inline constexpr bool sub_borrow(bool borrow, T a, T b, T &out) noexcept = unsigned *; return __builtin_ia32_sbb_u32(borrow, a, b, reinterpret_cast(__builtin_addressof(out))); -#elif __has_builtin(__builtin_ia32_subborrow_u32) +#elif FAST_IO_HAS_BUILTIN(__builtin_ia32_subborrow_u32) using may_alias_ptr_type #if __has_cpp_attribute(__gnu__::__may_alias__) [[__gnu__::__may_alias__]] @@ -551,8 +531,7 @@ inline constexpr bool sub_borrow(bool borrow, T a, T b, T &out) noexcept inline constexpr ::std::uint_least64_t pack_ul64(::std::uint_least32_t low, ::std::uint_least32_t high) noexcept { -#if defined(__has_builtin) && defined(__GNUC__) && !defined(__clang__) -#if __has_builtin(__builtin_bit_cast) +#if defined(__GNUC__) && !defined(__clang__) && FAST_IO_HAS_BUILTIN(__builtin_bit_cast) if constexpr (::std::endian::native == ::std::endian::little) { return __builtin_bit_cast(::std::uint_least64_t, ul32x2_little_endian{low, high}); // get around gcc bug @@ -562,7 +541,6 @@ inline constexpr ::std::uint_least64_t pack_ul64(::std::uint_least32_t low, ::st return __builtin_bit_cast(::std::uint_least64_t, ul32x2_big_endian{high, low}); // get around gcc bug } else -#endif #endif { return (static_cast<::std::uint_least64_t>(high) << 32u) | low; @@ -625,14 +603,14 @@ inline using u64x2_t = ::std::conditional_t<::std::endian::native == ::std::endian::little, u64x2_little_endian_t, u64x2_big_endian_t>; static_assert(sizeof(__uint128_t) == sizeof(u64x2_t)); -#if __has_builtin(__builtin_bit_cast) +#if FAST_IO_HAS_BUILTIN(__builtin_bit_cast) auto u{__builtin_bit_cast(u64x2_t, static_cast<__uint128_t>(a) * b)}; high = u.high; return u.low; #else __uint128_t res{static_cast<__uint128_t>(a) * b}; u64x2_t u; -#if __has_builtin(__builtin_memcpy) +#if FAST_IO_HAS_BUILTIN(__builtin_memcpy) __builtin_memcpy(__builtin_addressof(u), __builtin_addressof(res), sizeof(u64x2_t)); #else ::std::memcpy(__builtin_addressof(u), __builtin_addressof(res), sizeof(u64x2_t)); @@ -765,7 +743,7 @@ inline constexpr ::std::size_t add_or_overflow_die(::std::size_t a, ::std::size_ } return size; } -#elif __has_builtin(__builtin_add_overflow) && __has_builtin(__builtin_trap) +#elif FAST_IO_HAS_BUILTIN(__builtin_add_overflow) && FAST_IO_HAS_BUILTIN(__builtin_trap) ::std::size_t size; if (__builtin_add_overflow(a, b, __builtin_addressof(size))) [[unlikely]] { @@ -805,7 +783,7 @@ inline constexpr ::std::size_t mul_or_overflow_die(::std::size_t a, ::std::size_ __debugbreak(); } return a * b; -#elif __has_builtin(__builtin_mul_overflow) && __has_builtin(__builtin_trap) +#elif FAST_IO_HAS_BUILTIN(__builtin_mul_overflow) && FAST_IO_HAS_BUILTIN(__builtin_trap) ::std::size_t size; if (__builtin_mul_overflow(a, b, __builtin_addressof(size))) [[unlikely]] { @@ -853,7 +831,7 @@ inline constexpr bool sub_underflow(int_type a, int_type b, int_type &c) noexcep { #if defined(_MSC_VER) && !defined(__clang__) return sub_underflow_naive(a, b, c); -#elif __has_builtin(__builtin_sub_underflow) +#elif FAST_IO_HAS_BUILTIN(__builtin_sub_underflow) return __builtin_sub_underflow(a, b, __builtin_addressof(c)); #else return sub_underflow_naive(a, b, c); @@ -884,7 +862,7 @@ inline constexpr ::std::size_t cal_allocation_size_or_die(::std::size_t size) no __debugbreak(); } return size * sizeof(T); -#elif __has_builtin(__builtin_mul_overflow) && __has_builtin(__builtin_trap) +#elif FAST_IO_HAS_BUILTIN(__builtin_mul_overflow) && FAST_IO_HAS_BUILTIN(__builtin_trap) if (__builtin_mul_overflow(size, sizeof(T), __builtin_addressof(size))) [[unlikely]] { __builtin_trap(); diff --git a/include/fast_io_core_impl/intrinsics/carry.h b/include/fast_io_core_impl/intrinsics/carry.h index 918ea80a0..5a5da23ac 100644 --- a/include/fast_io_core_impl/intrinsics/carry.h +++ b/include/fast_io_core_impl/intrinsics/carry.h @@ -74,14 +74,12 @@ inline constexpr T addc(T a, T b, bool carryin, bool &carryout) noexcept return (static_cast(reshigh) << 32u) | reslow; } } -#elif defined(__has_builtin) -#if __has_builtin(__builtin_add_overflow) +#elif FAST_IO_HAS_BUILTIN(__builtin_add_overflow) T s; auto c1 = __builtin_add_overflow(a, b, __builtin_addressof(s)); auto c2 = __builtin_add_overflow(s, carryin, __builtin_addressof(s)); carryout = c1 | c2; return s; -#endif #endif } a += b; @@ -152,14 +150,12 @@ inline constexpr T subc(T a, T b, bool carryin, bool &carryout) noexcept return (static_cast(reshigh) << 32u) | reslow; } } -#elif defined(__has_builtin) -#if __has_builtin(__builtin_sub_overflow) +#elif FAST_IO_HAS_BUILTIN(__builtin_sub_overflow) T s; auto c1 = __builtin_sub_overflow(a, b, __builtin_addressof(s)); auto c2 = __builtin_sub_overflow(s, carryin, __builtin_addressof(s)); carryout = c1 | c2; return s; -#endif #endif } b = a - b; diff --git a/include/fast_io_core_impl/intrinsics/umul.h b/include/fast_io_core_impl/intrinsics/umul.h index a11b5ced7..29147a75b 100644 --- a/include/fast_io_core_impl/intrinsics/umul.h +++ b/include/fast_io_core_impl/intrinsics/umul.h @@ -100,8 +100,7 @@ template requires(sizeof(U) * 2 <= sizeof(T)) inline constexpr U umul_least_generic(U a, U b, U &high) noexcept { -#if defined(__has_builtin) && defined(__GNUC__) && !defined(__clang__) -#if __has_builtin(__builtin_bit_cast) +#if defined(__GNUC__) && !defined(__clang__) && FAST_IO_HAS_BUILTIN(__builtin_bit_cast) if constexpr (::std::endian::native == ::std::endian::little || ::std::endian::native == ::std::endian::big) { auto ret{__builtin_bit_cast(::fast_io::intrinsics::ul_generic_x2, static_cast(a) * b)}; @@ -109,7 +108,6 @@ inline constexpr U umul_least_generic(U a, U b, U &high) noexcept return ret.low; } else -#endif #endif { T v{static_cast(a) * b}; @@ -174,15 +172,13 @@ template requires(sizeof(U) * 2 <= sizeof(T)) inline constexpr U umulh_least_generic(U a, U b) noexcept { -#if defined(__has_builtin) && defined(__GNUC__) && !defined(__clang__) -#if __has_builtin(__builtin_bit_cast) +#if defined(__GNUC__) && !defined(__clang__) && FAST_IO_HAS_BUILTIN(__builtin_bit_cast) if constexpr (::std::endian::native == ::std::endian::little || ::std::endian::native == ::std::endian::big) { auto ret{__builtin_bit_cast(::fast_io::intrinsics::ul_generic_x2, static_cast(a) * b)}; return ret.high; } else -#endif #endif { T v{static_cast(a) * b}; diff --git a/include/fast_io_core_impl/io_lockable.h b/include/fast_io_core_impl/io_lockable.h index 6f81e8577..63e55c597 100644 --- a/include/fast_io_core_impl/io_lockable.h +++ b/include/fast_io_core_impl/io_lockable.h @@ -52,6 +52,13 @@ struct basic_general_io_lockable_nonmovable this->handle = T(::std::forward(args)...); } } + + inline constexpr auto native_handle() noexcept(noexcept(handle.native_handle())) + requires(requires() { handle.native_handle(); }) + { + return handle.native_handle(); + } + inline constexpr void close() noexcept(noexcept(handle.close())) { ::fast_io::io_lock_guard guard(mutex); diff --git a/include/fast_io_core_impl/iso/iso8601.h b/include/fast_io_core_impl/iso/iso8601.h index 90ec82aaa..fc2a656e4 100644 --- a/include/fast_io_core_impl/iso/iso8601.h +++ b/include/fast_io_core_impl/iso/iso8601.h @@ -443,8 +443,7 @@ inline constexpr ::std::uint_least32_t days_per_4_year{365LL * 4LL + 1LL}; template <::std::signed_integral T> inline constexpr T sub_overflow(T a, T b) noexcept { -#if defined(__has_builtin) -#if __has_builtin(__builtin_sub_overflow) +#if FAST_IO_HAS_BUILTIN(__builtin_sub_overflow) T c; if (__builtin_sub_overflow(a, b, __builtin_addressof(c))) [[unlikely]] { @@ -469,23 +468,6 @@ inline constexpr T sub_overflow(T a, T b) noexcept } return a - b; #endif -#else - if (b <= 0) [[unlikely]] - { - if (a > ::std::numeric_limits::max() + b) [[unlikely]] - { - fast_terminate(); - } - } - else - { - if (a < ::std::numeric_limits::min() + b) [[unlikely]] - { - fast_terminate(); - } - } - return a - b; -#endif } #if __has_cpp_attribute(__gnu__::__pure__) @@ -637,14 +619,10 @@ inline constexpr ::std::uint_least8_t c_weekday_tb[]{0, 3, 2, 5, 0, 3, 5, 1, 4, inline constexpr ::std::uint_least8_t c_weekday_impl(::std::int_least64_t year, ::std::uint_least8_t month_minus1, ::std::uint_least8_t day) noexcept { -#if defined(__has_builtin) -#if __has_builtin(__builtin_unreachable) if (12u <= month_minus1) { - __builtin_unreachable(); + ::fast_io::unreachable(); } -#endif -#endif return static_cast<::std::uint_least8_t>( static_cast<::std::uint_least64_t>( static_cast<::std::uint_least64_t>(year) + static_cast<::std::uint_least64_t>(year / 4) - @@ -656,14 +634,10 @@ inline constexpr ::std::uint_least8_t c_weekday_impl(::std::int_least64_t year, inline constexpr ::std::uint_least8_t weekday_impl(::std::int_least64_t year, ::std::uint_least8_t month_minus1, ::std::uint_least8_t day) noexcept { -#if defined(__has_builtin) -#if __has_builtin(__builtin_unreachable) if (12u <= month_minus1) { - __builtin_unreachable(); + ::fast_io::unreachable(); } -#endif -#endif return static_cast<::std::uint_least8_t>( static_cast<::std::uint_least64_t>( static_cast<::std::uint_least64_t>(year) + static_cast<::std::uint_least64_t>(year / 4) - @@ -1576,11 +1550,7 @@ scan_iso8601_context_2_digits_phase(timestamp_scan_state_t &state, ch break; } default:; -#ifdef __has_builtin -#if __has_builtin(__builtin_unreachable) - __builtin_unreachable(); -#endif -#endif + ::fast_io::unreachable(); } return {begin, parse_code::ok}; } @@ -1842,11 +1812,7 @@ scn_ctx_define_iso8601_impl(timestamp_scan_state_t &state, char_type case scan_timestamp_context_phase::ok: return {begin, parse_code::ok}; } -#ifdef __has_builtin -#if __has_builtin(__builtin_unreachable) - __builtin_unreachable(); -#endif -#endif + ::fast_io::unreachable(); #undef FAST_IO_SCAN_ISO8601_CONTEXT_TOKEN_PHASE } diff --git a/include/fast_io_core_impl/local_new_array_ptr.h b/include/fast_io_core_impl/local_new_array_ptr.h index 94676eaae..8a46a0cf1 100644 --- a/include/fast_io_core_impl/local_new_array_ptr.h +++ b/include/fast_io_core_impl/local_new_array_ptr.h @@ -8,7 +8,7 @@ inline constexpr char_type *allocate_iobuf_space(::std::size_t buffer_size) noex #if __cpp_constexpr >= 201907L && __cpp_constexpr_dynamic_alloc >= 201907L if (__builtin_is_constant_evaluated()) { - return new char_type[buffer_size]; + return ::new char_type[buffer_size]; } else #endif @@ -40,7 +40,7 @@ inline constexpr void deallocate_iobuf_space(char_type *ptr, [[maybe_unused]] :: #if __cpp_constexpr >= 201907L && __cpp_constexpr_dynamic_alloc >= 201907L if (__builtin_is_constant_evaluated()) { - delete[] ptr; + ::delete[] ptr; } else #endif diff --git a/include/fast_io_core_impl/operations/lockguard.h b/include/fast_io_core_impl/operations/lockguard.h index ae4e12850..20b791cb6 100644 --- a/include/fast_io_core_impl/operations/lockguard.h +++ b/include/fast_io_core_impl/operations/lockguard.h @@ -31,4 +31,32 @@ struct stream_ref_decay_lock_guard } }; +template +struct unlock_stream_ref_decay_lock_guard +{ + using mutex_type = mtx_type; + mutex_type device; + #if __has_cpp_attribute(__gnu__::__always_inline__) + [[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) + [[msvc::forceinline]] +#endif + inline explicit constexpr unlock_stream_ref_decay_lock_guard(stream_ref_decay_lock_guard const& lg) + : device(lg.device) + { + device.unlock(); + } + inline unlock_stream_ref_decay_lock_guard(unlock_stream_ref_decay_lock_guard const &) = delete; + inline unlock_stream_ref_decay_lock_guard &operator=(unlock_stream_ref_decay_lock_guard const &) = delete; +#if __has_cpp_attribute(__gnu__::__always_inline__) + [[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) + [[msvc::forceinline]] +#endif + inline constexpr ~unlock_stream_ref_decay_lock_guard() + { + device.lock(); + } +}; + } // namespace fast_io::operations::decay diff --git a/include/fast_io_core_impl/operations/print_freestanding.h b/include/fast_io_core_impl/operations/print_freestanding.h new file mode 100644 index 000000000..20df211ad --- /dev/null +++ b/include/fast_io_core_impl/operations/print_freestanding.h @@ -0,0 +1,1466 @@ +#pragma once + +namespace fast_io +{ + +namespace details::decay +{ + +template <::std::integral char_type, typename T = char_type> +inline constexpr basic_io_scatter_t line_scatter_common{__builtin_addressof(char_literal_v), + ::std::same_as ? sizeof(char_type) : 1}; + +struct contiguous_scatter_result +{ + ::std::size_t position{}; + ::std::size_t neededscatters{}; + ::std::size_t neededspace{}; + ::std::size_t null{}; + bool lastisreserve{}; + bool hasscatters{}; + bool hasreserve{}; + bool hasdynamicreserve{}; +}; + +template <::std::integral char_type, typename Arg, typename... Args> +inline constexpr contiguous_scatter_result find_continuous_scatters_n() +{ + contiguous_scatter_result ret{}; + if constexpr (::fast_io::scatter_printable) + { + if constexpr (sizeof...(Args) != 0) + { + ret = find_continuous_scatters_n(); + } + ++ret.position; + ret.hasscatters = true; + ret.neededscatters = ::fast_io::details::intrinsics::add_or_overflow_die_chain(ret.neededscatters, + static_cast<::std::size_t>(1)); + } + else if constexpr (::fast_io::reserve_printable) + { + if constexpr (sizeof...(Args) != 0) + { + ret = find_continuous_scatters_n(); + } + else + { + ret.lastisreserve = true; + } + constexpr ::std::size_t sz{print_reserve_size(::fast_io::io_reserve_type)}; + static_assert(sz != 0); + ++ret.position; + ret.neededscatters = ::fast_io::details::intrinsics::add_or_overflow_die_chain(ret.neededscatters, + static_cast<::std::size_t>(1)); + ret.neededspace = ::fast_io::details::intrinsics::add_or_overflow_die_chain(ret.neededspace, sz); + ret.hasreserve = true; + } + else if constexpr (::fast_io::dynamic_reserve_printable) + { + if constexpr (sizeof...(Args) != 0) + { + ret = find_continuous_scatters_n(); + } + else + { + ret.lastisreserve = true; + } + ++ret.position; + ret.neededscatters = ::fast_io::details::intrinsics::add_or_overflow_die_chain(ret.neededscatters, + static_cast<::std::size_t>(1)); + ret.hasdynamicreserve = true; + } + else if constexpr (::fast_io::reserve_scatters_printable) + { + if constexpr (sizeof...(Args) != 0) + { + ret = find_continuous_scatters_n(); + } + constexpr auto scatszres{print_reserve_scatters_size(::fast_io::io_reserve_type)}; + static_assert(scatszres.scatters_size != 0); + ret.hasscatters = true; + ret.hasreserve = true; + ++ret.position; + ret.neededspace = + ::fast_io::details::intrinsics::add_or_overflow_die_chain(ret.neededspace, scatszres.reserve_size); + ret.neededscatters = + ::fast_io::details::intrinsics::add_or_overflow_die_chain(ret.neededscatters, scatszres.scatters_size); + } + else if constexpr (::std::same_as<::std::remove_cvref_t, ::fast_io::io_null_t>) + { + if constexpr (sizeof...(Args) != 0) + { + ret = find_continuous_scatters_n(); + } + ++ret.position; + ret.null = ::fast_io::details::intrinsics::add_or_overflow_die_chain(ret.null, + static_cast<::std::size_t>(1)); + } + else if constexpr (::fast_io::printable) + { + } + return ret; +} + +struct scatter_rsv_result +{ + ::std::size_t position{}; + ::std::size_t neededspace{}; + ::std::size_t null{}; +}; + +template +inline constexpr scatter_rsv_result find_continuous_scatters_reserve_n() +{ + if constexpr (::fast_io::reserve_printable && !findscatter) + { + constexpr ::std::size_t sz{print_reserve_size(::fast_io::io_reserve_type)}; + if constexpr (sizeof...(Args) == 0) + { + return {1, sz, 0}; + } + else + { + auto res{find_continuous_scatters_reserve_n()}; + return {res.position + 1, ::fast_io::details::intrinsics::add_or_overflow_die_chain(res.neededspace, sz), res.null}; + } + } + else if constexpr (::fast_io::scatter_printable && findscatter) + { + if constexpr (sizeof...(Args) == 0) + { + return {1, 0, 0}; + } + else + { + auto res{find_continuous_scatters_reserve_n()}; + return {res.position + 1, res.neededspace, res.null}; + } + } + else if constexpr (::std::same_as<::std::remove_cvref_t, ::fast_io::io_null_t>) + { + if constexpr (sizeof...(Args) == 0) + { + return {1, 0, ::fast_io::details::intrinsics::add_or_overflow_die_chain(static_cast<::std::size_t>(0), static_cast<::std::size_t>(1))}; + } + else + { + auto res{find_continuous_scatters_reserve_n()}; + return {res.position + 1, res.neededspace, ::fast_io::details::intrinsics::add_or_overflow_die_chain(res.null, static_cast<::std::size_t>(1))}; + } + } + else + { + return {0, 0, 0}; + } +} + +template +inline constexpr bool minimum_buffer_output_stream_require_size_constant_impl = + (N < obuffer_minimum_size_define(::fast_io::io_reserve_type)); + +template +concept minimum_buffer_output_stream_require_size_impl = + ::fast_io::operations::decay::defines::has_obuffer_minimum_size_operations && + minimum_buffer_output_stream_require_size_constant_impl; + +template <::std::size_t sz> + requires(sz != 0) +inline constexpr void scatter_rsv_update_times(::fast_io::io_scatter_t *first, ::fast_io::io_scatter_t *last) noexcept +{ + if constexpr (sz != 1) + { + for (; first != last; ++first) + { + first->len *= sz; + } + } +} + +template <::std::integral char_type> +struct basic_reserve_scatters_define_byte_result +{ + io_scatter_t *scatters_pos_ptr; + char_type *reserve_pos_ptr; +}; + +template <::std::integral char_type, typename T> +inline ::fast_io::details::decay::basic_reserve_scatters_define_byte_result +prrsvsct_byte_common_rsvsc_impl(io_scatter_t *pscatters, char_type *buffer, T t) +{ + using basicioscattertypealiasptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = basic_io_scatter_t *; + using scatterioscattertypealiasptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = io_scatter_t *; + auto result{print_reserve_scatters_define(::fast_io::io_reserve_type>, + reinterpret_cast(pscatters), buffer, t)}; + scatterioscattertypealiasptr ptr{reinterpret_cast(result.scatters_pos_ptr)}; + if constexpr (sizeof(char_type) != 1) + { + scatter_rsv_update_times(pscatters, ptr); + } + return {ptr, result.reserve_pos_ptr}; +} + +template <::std::integral char_type, typename T> +inline auto prrsvsct_byte_common_impl(io_scatter_t *pscatters, char_type *buffer, T t) +{ + return ::fast_io::details::decay::prrsvsct_byte_common_rsvsc_impl(pscatters, buffer, t).scatters_pos_ptr; +} + +template + requires(::std::is_trivially_copyable_v && ::std::is_trivially_copyable_v) +inline constexpr void print_control_single(output outstm, T t) +{ + using char_type = typename output::output_char_type; + using value_type = ::std::remove_cvref_t; + constexpr bool asan_activated{::fast_io::details::asan_state::current == ::fast_io::details::asan_state::activate}; + constexpr auto lfch{char_literal_v}; + if constexpr (scatter_printable) + { +#if 0 + basic_io_scatter_t scatter; + if constexpr(::std::same_as>) + { + scatter=t; + } + else + { + scatter=print_scatter_define(::fast_io::io_reserve_type,t); + } + if constexpr(line) + { + if constexpr(contiguous_output_stream) + { + auto curr=obuffer_curr(out); + auto end=obuffer_end(out); + ::std::ptrdiff_t sz(end-curr-1); + ::std::size_t const len{scatter.len}; + if(sz(len)) + fast_terminate(); + curr=non_overlapped_copy_n(scatter.base,scatter.len,curr); + *curr=lfch; + ++curr; + obuffer_set_curr(outstm,curr); + } + else if constexpr(::fast_io::operations::decay::defines::has_obuffer_basic_operations) + { + auto curr=obuffer_curr(out); + auto end=obuffer_end(out); + ::std::size_t const len{scatter.len}; + ::std::ptrdiff_t sz(end-curr-1); + if(static_cast<::std::ptrdiff_t>(len) scatter_res{print_scatter_define(::fast_io::io_reserve_type, t)}; + + if constexpr (line) + { + if constexpr (::fast_io::operations::decay::defines::has_any_of_write_or_seek_pwrite_bytes_operations< + output>) + { + ::fast_io::io_scatter_t scatters[2]{ + {scatter_res.base, scatter_res.len * sizeof(char_type)}, + {__builtin_addressof(char_literal_v), sizeof(char_type)}}; + ::fast_io::operations::decay::scatter_write_all_bytes_decay(outstm, scatters, 2); + } + else + { + ::fast_io::basic_io_scatter_t scatters[2]{ + scatter_res, {__builtin_addressof(char_literal_v), 1}}; + ::fast_io::operations::decay::scatter_write_all_decay(outstm, scatters, 2); + } + } + else + { + ::fast_io::operations::decay::write_all_decay(outstm, scatter_res.base, scatter_res.base + scatter_res.len); + } + } + else if constexpr (reserve_printable) + { + constexpr ::std::size_t real_size{print_reserve_size(::fast_io::io_reserve_type)}; + constexpr ::std::size_t size{real_size + static_cast<::std::size_t>(line)}; + static_assert(real_size < PTRDIFF_MAX); +#if 0 + if constexpr(contiguous_output_stream) + { + auto bcurr{obuffer_curr(outstm)}; + auto bend{obuffer_end(outstm)}; + ::std::size_t diff{static_cast<::std::size_t>(bend-bcurr)}; + if(diff,bcurr,t)}; + if constexpr(line) + { + *it=lfch; + ++it; + } + obuffer_set_curr(outstm,it); + } + else +#endif + { + if constexpr (::fast_io::operations::decay::defines::has_obuffer_basic_operations && + !asan_activated) + { + char_type *bcurr{obuffer_curr(outstm)}; + char_type *bend{obuffer_end(outstm)}; + ::std::ptrdiff_t const diff(bend - bcurr); + bool smaller{static_cast<::std::ptrdiff_t>(size) < diff}; + if constexpr (minimum_buffer_output_stream_require_size_impl) + { + if (!smaller) [[unlikely]] + { + obuffer_minimum_size_flush_prepare_define(outstm); + bcurr = obuffer_curr(outstm); + } + bcurr = print_reserve_define(::fast_io::io_reserve_type, bcurr, t); + if constexpr (line) + { + *bcurr = lfch; + ++bcurr; + } + obuffer_set_curr(outstm, bcurr); + } + else + { + char_type buffer[size]; + if (!smaller) [[unlikely]] + { + bcurr = buffer; + } + bcurr = print_reserve_define(::fast_io::io_reserve_type, bcurr, t); + if constexpr (line) + { + *bcurr = lfch; + ++bcurr; + } + if (smaller) [[likely]] + { + obuffer_set_curr(outstm, bcurr); + } + else [[unlikely]] + { + ::fast_io::operations::decay::write_all_decay(outstm, buffer, bcurr); + } + } + } + else + { + char_type buffer[size]; + char_type *i{print_reserve_define(::fast_io::io_reserve_type, buffer, t)}; + if constexpr (line) + { + *i = lfch; + ++i; + } + ::fast_io::operations::decay::write_all_decay(outstm, buffer, i); + } + } + } + else if constexpr (dynamic_reserve_printable) + { + ::std::size_t size{print_reserve_size(::fast_io::io_reserve_type, t)}; + if constexpr (line) + { + constexpr ::std::size_t mx{::std::numeric_limits<::std::ptrdiff_t>::max() - 1}; + if (size >= mx) + { + fast_terminate(); + } + ++size; + } + else + { + constexpr ::std::size_t mx{::std::numeric_limits<::std::ptrdiff_t>::max()}; + if (mx < size) + { + fast_terminate(); + } + } +#if 0 + if constexpr(contiguous_output_stream) + { + auto bcurr{obuffer_curr(outstm)}; + auto bend{obuffer_end(outstm)}; + auto it{print_reserve_define(::fast_io::io_reserve_type,bcurr,t,size)}; + ::std::size_t diff{static_cast<::std::size_t>(bend-bcurr)}; + if(diff && + !asan_activated) + { + auto curr{obuffer_curr(outstm)}; + auto ed{obuffer_end(outstm)}; + ::std::ptrdiff_t diff(ed - curr); + auto toptr{curr}; + bool smaller{static_cast<::std::ptrdiff_t>(size) < diff}; + ::fast_io::details::local_operator_new_array_ptr newptr; + if (!smaller) +#if __has_cpp_attribute(unlikely) + [[unlikely]] +#endif + { + newptr.ptr = toptr = ::fast_io::details::allocate_iobuf_space< + char_type, + typename ::fast_io::details::local_operator_new_array_ptr::allocator_type>(size); + newptr.size = size; + } + + auto it{print_reserve_define(::fast_io::io_reserve_type, toptr, t)}; + if constexpr (line) + { + *it = lfch; + ++it; + } + if (smaller) + { + obuffer_set_curr(outstm, it); + } + else +#if __has_cpp_attribute(unlikely) + [[unlikely]] +#endif + { + ::fast_io::operations::decay::write_all_decay(outstm, toptr, it); + } + } + else + { + ::fast_io::details::local_operator_new_array_ptr newptr(size); + auto it{print_reserve_define(::fast_io::io_reserve_type, newptr.ptr, t)}; + if constexpr (line) + { + *it = lfch; + ++it; + } + ::fast_io::operations::decay::write_all_decay(outstm, newptr.ptr, it); + } + } + } + else if constexpr (reserve_scatters_printable) + { + constexpr auto sz{print_reserve_scatters_size(::fast_io::io_reserve_type)}; + static_assert(!line || sz.scatters_size != SIZE_MAX); + constexpr ::std::size_t scattersnum{sz.scatters_size + static_cast<::std::size_t>(line)}; +#if __cpp_if_consteval >= 202106L + if !consteval +#else + if (!__builtin_is_constant_evaluated()) +#endif + { + if constexpr (::fast_io::operations::decay::defines::has_any_of_write_or_seek_pwrite_bytes_operations< + output>) + { + ::fast_io::io_scatter_t scattersbuffer[scattersnum]; + char_type buffer[sz.reserve_size]; + ::fast_io::io_scatter_t *ptr{ + ::fast_io::details::decay::prrsvsct_byte_common_impl(scattersbuffer, buffer, t)}; + if constexpr (line) + { + *ptr = ::fast_io::details::decay::line_scatter_common; + ++ptr; + } + ::fast_io::operations::decay::scatter_write_all_bytes_decay(outstm, scattersbuffer, static_cast<::std::size_t>(ptr - scattersbuffer)); + return; + } + } + ::fast_io::basic_io_scatter_t scattersbuffer[scattersnum]; + char_type buffer[sz.reserve_size]; + auto ptr{print_reserve_scatters_define(::fast_io::io_reserve_type>, + scattersbuffer, buffer, t) + .scatters_pos_ptr}; + if constexpr (line) + { + *ptr = ::fast_io::details::decay::line_scatter_common; + ++ptr; + } + ::fast_io::operations::decay::scatter_write_all_decay(outstm, scattersbuffer, static_cast<::std::size_t>(ptr - scattersbuffer)); + } + else if constexpr (::fast_io::transcode_imaginary_printable) + { + // todo? + } + else if constexpr (context_printable) + { + typename ::std::remove_cvref_t))>::type st; + constexpr ::std::size_t reserved_size{32u}; + constexpr ::std::ptrdiff_t reserved_size_no_line{ + static_cast<::std::ptrdiff_t>(reserved_size - static_cast<::std::size_t>(line))}; + if constexpr (::fast_io::operations::decay::defines::has_obuffer_basic_operations) + { + for (;;) + { + auto bcurr{obuffer_curr(outstm)}; + auto bed{obuffer_end(outstm)}; + if (bed <= bcurr) +#if __has_cpp_attribute(unlikely) + [[unlikely]] +#endif + { + if constexpr (minimum_buffer_output_stream_require_size_impl) + { + obuffer_minimum_size_flush_prepare_define(outstm); + bcurr = obuffer_curr(outstm); + bed = obuffer_end(outstm); + } + else + { + ::fast_io::operations::decay::output_stream_buffer_flush_decay(outstm); + bcurr = obuffer_curr(outstm); + bed = obuffer_end(outstm); + if (bed - bcurr < reserved_size_no_line) +#if __has_cpp_attribute(unlikely) + [[unlikely]] +#endif + { + char_type buffer[reserved_size]; + char_type *buffered{buffer + reserved_size_no_line}; + for (;;) + { + auto [resit, done] = st.print_context_define(t, buffer, buffered); + if constexpr (line) + { + if (done) + { + *resit = lfch; + ++resit; + } + ::fast_io::operations::decay::write_all_decay(outstm, buffer, resit); + if (done) + { + return; + } + } + else + { + ::fast_io::operations::decay::write_all_decay(outstm, buffer, resit); + if (done) + { + return; + } + } + } + return; + } + } + } + else + { + auto [resit, done] = st.print_context_define(t, bcurr, bed); + obuffer_set_curr(outstm, resit); + if (done) +#if __has_cpp_attribute(likely) + [[likely]] +#endif + { + if constexpr (line) + { + ::fast_io::operations::decay::char_put_decay(outstm, lfch); + } + return; + } + } + } + } + else + { + char_type buffer[reserved_size]; + char_type *buffered{buffer + reserved_size_no_line}; + for (;;) + { + auto [resit, done] = st.print_context_define(t, buffer, buffered); + if constexpr (line) + { + if (done) + { + *resit = lfch; + ++resit; + } + ::fast_io::operations::decay::write_all_decay(outstm, buffer, resit); + if (done) + { + return; + } + } + else + { + ::fast_io::operations::decay::write_all_decay(outstm, buffer, resit); + if (done) + { + return; + } + } + } + return; + } + } + else if constexpr (printable) + { + print_define(::fast_io::io_reserve_type, outstm, t); + if constexpr (line) + { + ::fast_io::operations::decay::char_put_decay(outstm, lfch); + } + } + else if constexpr (::std::same_as<::std::remove_cvref_t, ::fast_io::io_null_t>) + { + } + else + { + constexpr bool no{printable}; + static_assert(no, "type not printable"); + } +} + +#if 0 +template +inline constexpr char_type* printrsvcontiguousimpl(char_type* iter,Arg arg,Args... args) +{ + if constexpr(sizeof...(Args)!=0) + { + ret = find_continuous_scatters_n(); + } + if constexpr(::fast_io::scatter_printable) + { + return {ret.position+1,ret.neededspace,ret.hasdynamicreserve}; + } + else if constexpr(::fast_io::reserve_printable) + { + constexpr + ::std::size_t sz{print_reserve_size(::fast_io::io_reserve_type)}; + return {ret.position+1, + ::fast_io::details::add_overflow(ret.neededspace,sz), + ret.hasdynamicreserve}; + } + else if constexpr(::fast_io::dynamic_reserve_printable) + { + return {ret.position+1,ret.neededspace,true}; + } +} +#endif + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr void print_controls_line(output outstm, T t, Args... args) +{ + if constexpr (sizeof...(Args) == 0) + { + print_control_single(outstm, t); + } + else + { +#if (defined(__OPTIMIZE__) || defined(__OPTIMIZE_SIZE__)) && 0 + print_controls_line_multi_impl(outstm, t, args...); +#else + if constexpr (ln) + { + print_control_single(outstm, t); + print_controls_line(outstm, args...); + } + else + { + print_control_single(outstm, t); + (print_control(outstm, args), ...); + } +#endif + } +} + +template <::std::size_t n, ::std::integral char_type, typename T, typename... Args> +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr char_type *print_n_reserve(char_type *ptr, T t, Args... args) +{ + if constexpr (n == 0) + { + return ptr; + } + else + { + if constexpr (::std::same_as<::std::remove_cvref_t, ::fast_io::io_null_t>) + { + if constexpr (sizeof...(Args) == 0 || n < 2) + { + return ptr; + } + else + { + return print_n_reserve(ptr, args...); + } + } + else + { + ptr = print_reserve_define(::fast_io::io_reserve_type>, ptr, t); + if constexpr (sizeof...(Args) == 0 || n < 2) + { + return ptr; + } + else + { + return print_n_reserve(ptr, args...); + } + } + } +} + +template <::std::size_t n, ::std::integral char_type, typename scattertype, typename T, typename... Args> +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr void print_n_scatters(basic_io_scatter_t *pscatters, +#if __has_cpp_attribute(maybe_unused) + [[maybe_unused]] +#endif + T t, +#if __has_cpp_attribute(maybe_unused) + [[maybe_unused]] +#endif + Args... args) +{ + if constexpr (n != 0) + { + if constexpr (::std::same_as<::std::remove_cvref_t, ::fast_io::io_null_t>) + { + if constexpr (1 < n) + { + return print_n_scatters(pscatters, args...); + } + } + else if constexpr (::std::same_as<::std::remove_cvref_t, basic_io_scatter_t>) + { + if constexpr (::std::same_as) + { + *pscatters = io_scatter_t{t.base, t.len * sizeof(char_type)}; + } + else + { + *pscatters = t; + } + } + else + { + basic_io_scatter_t sct{print_scatter_define(::fast_io::io_reserve_type, t)}; + if constexpr (::std::same_as) + { + *pscatters = io_scatter_t{sct.base, sct.len * sizeof(char_type)}; + } + else + { + *pscatters = sct; + } + } + if constexpr (1 < n) + { + ++pscatters; + return print_n_scatters(pscatters, args...); + } + } +} + +template <::std::size_t n, ::std::integral char_type, typename T, typename... Args> +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr ::std::size_t ndynamic_print_reserve_size(T t, Args... args) +{ + using nocvreft = ::std::remove_cvref_t; + if constexpr (n == 0) + { + return 0; + } + else if constexpr (n == 1) + { + if constexpr (::fast_io::dynamic_reserve_printable) + { + return print_reserve_size(::fast_io::io_reserve_type, t); + } + else + { + return 0; + } + } + else + { + if constexpr (::fast_io::dynamic_reserve_printable) + { + return ::fast_io::details::intrinsics::add_or_overflow_die( + print_reserve_size(::fast_io::io_reserve_type, t), + ::fast_io::details::decay::ndynamic_print_reserve_size(args...)); + } + else + { + return ::fast_io::details::decay::ndynamic_print_reserve_size(args...); + } + } +} + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr auto print_n_scatters_reserve(basic_io_scatter_t *pscatters, char_type *ptr, T t, + Args... args); + +template <::std::integral char_type, typename T, typename... Args> +inline constexpr bool print_next_is_reserve() noexcept +{ + using nocvreft = ::std::remove_cvref_t; + if constexpr (::fast_io::reserve_printable || + ::fast_io::dynamic_reserve_printable) + { + return true; + } + else + { + return false; + } +} + +template <::std::integral char_type> +inline constexpr bool print_next_is_reserve() noexcept +{ + return false; +} + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr auto print_n_scatters_reserve_cont(basic_io_scatter_t *pscatters, char_type *base, + char_type *ptr, T t, Args... args) +{ + if constexpr (n != 0) + { + using nocvreft = ::std::remove_cvref_t; + if constexpr (reserve_printable || dynamic_reserve_printable) + { + ptr = print_reserve_define(::fast_io::io_reserve_type, ptr, t); + if constexpr (::fast_io::details::decay::print_next_is_reserve()) + { + return ::fast_io::details::decay::print_n_scatters_reserve_cont( + pscatters, base, ptr, args...); + } + else + { + if constexpr (n == 1 && needprintlf) + { + *ptr = char_literal_v; + ++ptr; + } + ::std::size_t const sz{static_cast<::std::size_t>(ptr - base)}; + if constexpr (::std::same_as) + { + *pscatters = io_scatter_t{base, sz * sizeof(char_type)}; + } + else + { + *pscatters = basic_io_scatter_t{base, sz}; + } + ++pscatters; + if constexpr (1 < n) + { + return ::fast_io::details::decay::print_n_scatters_reserve( + pscatters, ptr, args...); + } + } + } + else + { + ::std::size_t const sz{static_cast<::std::size_t>(ptr - base)}; + if constexpr (::std::same_as) + { + *pscatters = io_scatter_t{base, sz * sizeof(char_type)}; + } + else + { + *pscatters = basic_io_scatter_t{base, sz}; + } + ++pscatters; + if constexpr (1 < n) + { + return ::fast_io::details::decay::print_n_scatters_reserve( + pscatters, ptr, t, args...); + } + } + } + return pscatters; +} + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr auto print_n_scatters_reserve(basic_io_scatter_t *pscatters, char_type *ptr, T t, + Args... args) +{ + if constexpr (n != 0) + { + using nocvreft = ::std::remove_cvref_t; + if constexpr (::fast_io::reserve_printable || + ::fast_io::dynamic_reserve_printable) + { + auto ptred{print_reserve_define(::fast_io::io_reserve_type, ptr, t)}; + if constexpr (sizeof...(Args) != 0 && + ::fast_io::details::decay::print_next_is_reserve()) + { + return ::fast_io::details::decay::print_n_scatters_reserve_cont( + pscatters, ptr, ptred, args...); + } + else + { + if constexpr (n == 1 && needprintlf) + { + *ptred = char_literal_v; + ++ptred; + } + ::std::size_t const sz{static_cast<::std::size_t>(ptred - ptr)}; + if constexpr (::std::same_as) + { + *pscatters = io_scatter_t{ptr, sz * sizeof(char_type)}; + } + else + { + *pscatters = basic_io_scatter_t{ptr, sz}; + } + ++pscatters; + if constexpr (1 < n) + { + return ::fast_io::details::decay::print_n_scatters_reserve( + pscatters, ptred, args...); + } + } + } + else if constexpr (::fast_io::scatter_printable) + { + if constexpr (::std::same_as>) + { + if constexpr (::std::same_as) + { + *pscatters = io_scatter_t{t.base, t.len * sizeof(char_type)}; + } + else + { + *pscatters = t; + } + } + else + { + basic_io_scatter_t sct{print_scatter_define(::fast_io::io_reserve_type, t)}; + if constexpr (::std::same_as) + { + *pscatters = io_scatter_t{sct.base, sct.len * sizeof(char_type)}; + } + else + { + *pscatters = sct; + } + } + ++pscatters; + if constexpr (n == 1 && needprintlf) + { + *pscatters = ::fast_io::details::decay::line_scatter_common; + ++pscatters; + } + if constexpr (1 < n) + { + return ::fast_io::details::decay::print_n_scatters_reserve(pscatters, + ptr, args...); + } + } + else if constexpr (::fast_io::reserve_scatters_printable) + { + if constexpr (::std::same_as) + { + auto pit{::fast_io::details::decay::prrsvsct_byte_common_rsvsc_impl(pscatters, ptr, t)}; + if constexpr (1 < n) + { + return ::fast_io::details::decay::print_n_scatters_reserve( + pit.scatters_pos_ptr, pit.reserve_pos_ptr, args...); + } + else if constexpr (n == 1 && needprintlf) + { + *pit.scatters_pos_ptr = ::fast_io::details::decay::line_scatter_common; + ++pit.scatters_pos_ptr; + } + return pit.scatters_pos_ptr; + } + else + { + auto pit{ + print_reserve_scatters_define(::fast_io::io_reserve_type, pscatters, ptr, t)}; + if constexpr (1 < n) + { + return ::fast_io::details::decay::print_n_scatters_reserve( + pit.scatters_pos_ptr, pit.reserve_pos_ptr, args...); + } + else if constexpr (n == 1 && needprintlf) + { + *pit = ::fast_io::details::decay::line_scatter_common; + ++pit; + } + return pit; + } + } + else if constexpr (::std::same_as) + { + if constexpr (n == 1 && needprintlf) + { + *pscatters = ::fast_io::details::decay::line_scatter_common; + ++pscatters; + } + if constexpr (1 < n) + { + return ::fast_io::details::decay::print_n_scatters_reserve(pscatters, + ptr, args...); + } + } + } + return pscatters; +} + +template +inline constexpr void print_controls_impl(outputstmtype optstm, T t, Args... args) +{ + using char_type = typename outputstmtype::output_char_type; + using scatter_type = ::std::conditional_t< + ::fast_io::operations::decay::defines::has_any_of_write_or_seek_pwrite_bytes_operations, + io_scatter_t, basic_io_scatter_t>; + constexpr contiguous_scatter_result res{ + ::fast_io::details::decay::find_continuous_scatters_n()}; + if constexpr (skippings != 0) + { + print_controls_impl(optstm, args...); + } + else if constexpr (sizeof...(Args) == 0) + { + print_control_single(optstm, t); + } + else if constexpr (res.position == 0) + { + print_control_single(optstm, t); + print_controls_impl(optstm, args...); + } + else + { + if constexpr (line) + { + static_assert(res.neededscatters != SIZE_MAX); + } + static_assert(SIZE_MAX != sizeof...(Args)); + constexpr ::std::size_t n{sizeof...(Args) + static_cast<::std::size_t>(1)}; + constexpr bool needprintlf{n == res.position && line}; + if constexpr (res.hasscatters && !res.hasreserve && !res.hasdynamicreserve) + { + constexpr ::std::size_t scatterscount{res.neededscatters + static_cast<::std::size_t>(needprintlf)}; + { + scatter_type scatters[scatterscount]; + ::fast_io::details::decay::print_n_scatters(scatters, t, args...); + if constexpr (needprintlf) + { + scatters[scatterscount - 1] = ::fast_io::details::decay::line_scatter_common< + char_type, ::std::conditional_t<::std::same_as, void, char_type>>; + } + if constexpr (::fast_io::operations::decay::defines::has_any_of_write_or_seek_pwrite_bytes_operations< + outputstmtype>) + { + ::fast_io::operations::decay::scatter_write_all_bytes_decay(optstm, scatters, scatterscount); + } + else + { + ::fast_io::operations::decay::scatter_write_all_decay(optstm, scatters, scatterscount); + } + } + if constexpr (res.position != n) + { + print_controls_impl(optstm, args...); + } + } + else + { + constexpr ::std::size_t mxsize{ + static_cast<::std::size_t>(res.neededspace + static_cast<::std::size_t>(needprintlf))}; + if constexpr (!res.hasscatters) + { + static_assert(!needprintlf || res.neededspace != SIZE_MAX); + if constexpr (res.hasdynamicreserve) + { + ::std::size_t dynsz{ + ::fast_io::details::decay::ndynamic_print_reserve_size(t, args...)}; + ::std::size_t totalsz{::fast_io::details::intrinsics::add_or_overflow_die(mxsize, dynsz)}; + ::fast_io::details::local_operator_new_array_ptr newptr(totalsz); + char_type *buffer{newptr.ptr}; + char_type *ptred{ + ::fast_io::details::decay::print_n_reserve(buffer, t, args...)}; + if constexpr (needprintlf) + { + *ptred = ::fast_io::char_literal_v; + ++ptred; + } + ::fast_io::operations::decay::write_all_decay(optstm, buffer, ptred); + } + else if constexpr (res.hasreserve) + { + if constexpr (res.neededspace == 0) + { + if constexpr (needprintlf) + { + ::fast_io::operations::decay::char_put_decay(optstm, + ::fast_io::char_literal_v); + } + } + else + { + char_type buffer[mxsize]; + char_type *ptred{ + ::fast_io::details::decay::print_n_reserve(buffer, t, args...)}; + if constexpr (needprintlf) + { + *ptred = ::fast_io::char_literal_v; + ++ptred; + } + ::fast_io::operations::decay::write_all_decay(optstm, buffer, ptred); + } + } + } + else if constexpr (res.hasreserve && !res.hasdynamicreserve) + { + constexpr ::std::size_t scatterscount{res.neededscatters + + static_cast<::std::size_t>(line && res.position == n)}; + scatter_type scatters[scatterscount]; + char_type buffer[mxsize]; + + auto ptr{::fast_io::details::decay::print_n_scatters_reserve( + scatters, buffer, t, args...)}; + ::std::size_t diff{static_cast<::std::size_t>(ptr - scatters)}; + + if constexpr (::fast_io::operations::decay::defines::has_any_of_write_or_seek_pwrite_bytes_operations< + outputstmtype>) + { + ::fast_io::operations::decay::scatter_write_all_bytes_decay(optstm, scatters, diff); + } + else + { + ::fast_io::operations::decay::scatter_write_all_decay(optstm, scatters, diff); + } + } + else if constexpr (res.hasdynamicreserve) + { + constexpr ::std::size_t scatterscount{res.neededscatters + + static_cast<::std::size_t>(line && res.position == n)}; + ::std::size_t dynsz{ + ::fast_io::details::decay::ndynamic_print_reserve_size(t, args...)}; + ::std::size_t totalsz{::fast_io::details::intrinsics::add_or_overflow_die(mxsize, dynsz)}; + ::fast_io::details::local_operator_new_array_ptr newptr(totalsz); + scatter_type scatters[scatterscount]; + char_type *buffer{newptr.ptr}; + auto ptr{::fast_io::details::decay::print_n_scatters_reserve( + scatters, buffer, t, args...)}; + ::std::size_t diff{static_cast<::std::size_t>(ptr - scatters)}; + if constexpr (::fast_io::operations::decay::defines::has_any_of_write_or_seek_pwrite_bytes_operations< + outputstmtype>) + { + ::fast_io::operations::decay::scatter_write_all_bytes_decay(optstm, scatters, diff); + } + else + { + ::fast_io::operations::decay::scatter_write_all_decay(optstm, scatters, diff); + } + } + if constexpr (res.position != n) + { + print_controls_impl(optstm, args...); + } + } + } +} + +template +inline constexpr void print_controls_buffer_impl(outputstmtype optstm, T t, Args... args) +{ + if constexpr (skippings != 0) + { + ::fast_io::details::decay::print_controls_buffer_impl(optstm, args...); + } + else if constexpr (sizeof...(Args) == 0) + { + print_control_single(optstm, t); + } + else + { + using char_type = typename outputstmtype::output_char_type; + static_assert(SIZE_MAX != sizeof...(Args)); + constexpr ::std::size_t n{sizeof...(Args) + static_cast<::std::size_t>(1)}; + constexpr auto scatters_result{ + ::fast_io::details::decay::find_continuous_scatters_reserve_n()}; + using scatter_type = ::std::conditional_t< + ::fast_io::operations::decay::defines::has_any_of_write_or_seek_pwrite_bytes_operations, + io_scatter_t, basic_io_scatter_t>; + if constexpr (scatters_result.position != 0) + { + if constexpr (line) + { + static_assert(scatters_result.position != SIZE_MAX); + } + constexpr bool needprintlf{n == scatters_result.position && line}; + constexpr ::std::size_t scatterscount{scatters_result.position - scatters_result.null + static_cast<::std::size_t>(needprintlf)}; + scatter_type scatters[scatterscount]; + ::fast_io::details::decay::print_n_scatters(scatters, t, args...); + if constexpr (::fast_io::operations::decay::defines::has_any_of_write_or_seek_pwrite_bytes_operations< + outputstmtype>) + { + if constexpr (needprintlf) + { + scatters[scatterscount - 1] = ::fast_io::details::decay::line_scatter_common; + } + ::fast_io::operations::decay::scatter_write_all_bytes_decay(optstm, scatters, scatterscount); + } + else + { + if constexpr (needprintlf) + { + scatters[scatterscount - 1] = ::fast_io::details::decay::line_scatter_common; + } + ::fast_io::operations::decay::scatter_write_all_decay(optstm, scatters, scatterscount); + } + if constexpr (scatters_result.position != n) + { + ::fast_io::details::decay::print_controls_buffer_impl(optstm, args...); + } + } + else + { + constexpr auto rsvresult{ + ::fast_io::details::decay::find_continuous_scatters_reserve_n()}; + if constexpr (1 < rsvresult.position) + { + constexpr bool needprintlf{n == rsvresult.position && line}; + constexpr ::std::size_t buffersize{rsvresult.neededspace + static_cast<::std::size_t>(needprintlf)}; + char_type *bcurr{obuffer_curr(optstm)}; + char_type *bend{obuffer_end(optstm)}; + ::std::ptrdiff_t const diff(bend - bcurr); + bool smaller{static_cast<::std::ptrdiff_t>(buffersize) < diff}; + if constexpr (minimum_buffer_output_stream_require_size_impl) + { + if (!smaller) [[unlikely]] + { + obuffer_minimum_size_flush_prepare_define(optstm); + bcurr = obuffer_curr(optstm); + } + bcurr = + ::fast_io::details::decay::print_n_reserve(bcurr, t, args...); + if constexpr (needprintlf) + { + *bcurr = ::fast_io::char_literal_v; + ++bcurr; + } + obuffer_set_curr(optstm, bcurr); + } + else + { + char_type buffer[buffersize]; + if (!smaller) [[unlikely]] + { + bcurr = buffer; + } + bcurr = + ::fast_io::details::decay::print_n_reserve(bcurr, t, args...); + if constexpr (needprintlf) + { + *bcurr = ::fast_io::char_literal_v; + ++bcurr; + } + if (smaller) [[likely]] + { + obuffer_set_curr(optstm, bcurr); + } + else [[unlikely]] + { + ::fast_io::operations::decay::write_all_decay(optstm, buffer, bcurr); + } + } + if constexpr (rsvresult.position != n) + { + ::fast_io::details::decay::print_controls_buffer_impl( + optstm, args...); + } + } + else + { + ::fast_io::details::decay::print_control_single(optstm, t); + if constexpr (sizeof...(args) != 0) + { + ::fast_io::details::decay::print_controls_buffer_impl(optstm, args...); + } + } + } + } +} + +} // namespace details::decay + +namespace operations +{ + +namespace decay +{ + +template +inline constexpr decltype(auto) print_freestanding_decay(outputstmtype optstm, Args... args) +{ + if constexpr (::fast_io::operations::decay::defines::has_status_print_define) + { + return status_print_define(optstm, args...); + } + else if constexpr (sizeof...(Args) == 0) + { + if constexpr (line) + { + using char_type = typename outputstmtype::output_char_type; + return ::fast_io::operations::decay::char_put_decay(optstm, char_literal_v); + } + else + { + return; + } + } + else if constexpr (::fast_io::operations::decay::defines::has_output_or_io_stream_mutex_ref_define) + { + ::fast_io::operations::decay::stream_ref_decay_lock_guard lg{ + ::fast_io::operations::decay::output_stream_mutex_ref_decay(optstm)}; + return ::fast_io::operations::decay::print_freestanding_decay( + ::fast_io::operations::decay::output_stream_unlocked_ref_decay(optstm), args...); + } + else if constexpr (::fast_io::operations::decay::defines::has_obuffer_basic_operations) + { + return ::fast_io::details::decay::print_controls_buffer_impl(optstm, args...); + } + else + { + return ::fast_io::details::decay::print_controls_impl(optstm, args...); + } +} + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline constexpr decltype(auto) print_freestanding_decay_cold(outputstmtype optstm, Args... args) +{ +#if !__has_cpp_attribute(__gnu__::__cold__) && __has_cpp_attribute(unlikely) + if (true) [[unlikely]] +#endif + return ::fast_io::operations::decay::print_freestanding_decay(optstm, args...); +} + +} // namespace decay + +namespace decay::defines +{ + +template +concept print_freestanding_params_okay = + ::std::integral && + ((::fast_io::printable || ::fast_io::reserve_printable || + ::fast_io::dynamic_reserve_printable || ::fast_io::scatter_printable || + ::fast_io::reserve_scatters_printable || ::fast_io::context_printable || + ::fast_io::transcode_imaginary_printable || ::std::same_as<::std::remove_cvref_t, ::fast_io::io_null_t>) && + ...); + +template +concept print_freestanding_okay = + ::fast_io::operations::decay::defines::print_freestanding_params_okay; + +} // namespace decay::defines + +namespace defines +{ + +template +concept print_freestanding_params_okay = ::fast_io::operations::decay::defines::print_freestanding_params_okay(::fast_io::io_print_alias(::std::declval())))...>; + +template +concept print_freestanding_okay = ::fast_io::operations::decay::defines::print_freestanding_okay< + decltype(::fast_io::operations::output_stream_ref(::std::declval())), + decltype(::fast_io::io_print_forward()))::output_char_type>(::fast_io::io_print_alias(::std::declval())))...>; + +} // namespace defines + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr void print_freestanding(output &&outstm, Args &&...args) +{ + ::fast_io::operations::decay::print_freestanding_decay( + ::fast_io::operations::output_stream_ref(outstm), + io_print_forward( + io_print_alias(args))...); +} + +} // namespace operations + +} // namespace fast_io diff --git a/include/fast_io_core_impl/secure_clear_guard.h b/include/fast_io_core_impl/secure_clear_guard.h index 0fcbfbc51..b4618df95 100644 --- a/include/fast_io_core_impl/secure_clear_guard.h +++ b/include/fast_io_core_impl/secure_clear_guard.h @@ -52,12 +52,8 @@ inline } else { -#if defined(__has_builtin) -#if __has_builtin(__builtin_memset) +#if FAST_IO_HAS_BUILTIN(__builtin_memset) __builtin_memset(data, 0, size); -#else - ::std::memset(data, 0, size); -#endif #else ::std::memset(data, 0, size); #endif @@ -138,12 +134,8 @@ inline constexpr ::std::byte *bytes_secure_clear_n(::std::byte *data, ::std::siz https://github.com/bminor/glibc/blob/master/string/explicit_bzero.c Referenced from glibc */ -#if defined(__has_builtin) -#if __has_builtin(__builtin_memset) +#if FAST_IO_HAS_BUILTIN(__builtin_memset) __builtin_memset(data, 0, size); -#else - ::std::memset(data, 0, size); -#endif #else ::std::memset(data, 0, size); #endif diff --git a/include/fast_io_core_impl/simd/gcc_clang.h b/include/fast_io_core_impl/simd/gcc_clang.h index b988164b8..934e49de8 100644 --- a/include/fast_io_core_impl/simd/gcc_clang.h +++ b/include/fast_io_core_impl/simd/gcc_clang.h @@ -14,7 +14,7 @@ inline constexpr bool simd_shuffle_size_is_supported(::std::size_t n) noexcept { if (n == 16) { -#if __has_builtin(__builtin_ia32_pshufb128) +#if FAST_IO_HAS_BUILTIN(__builtin_ia32_pshufb128) return true; #else return false; @@ -22,7 +22,7 @@ inline constexpr bool simd_shuffle_size_is_supported(::std::size_t n) noexcept } else if (n == 32) { -#if __has_builtin(__builtin_ia32_pshufb256) +#if FAST_IO_HAS_BUILTIN(__builtin_ia32_pshufb256) return true; #else return false; @@ -115,7 +115,7 @@ struct simd_vector template requires((sizeof(T2) == sizeof(T) * N) && ::std::is_trivially_copyable_v) inline -#if __has_builtin(__builtin_bit_cast) +#if FAST_IO_HAS_BUILTIN(__builtin_bit_cast) constexpr #endif void @@ -130,7 +130,7 @@ struct simd_vector { using unsigned_type = ::std::make_unsigned_t; using unsigned_vec_type = typename simd_vector::vec_type; -#if __has_builtin(__builtin_bit_cast) +#if FAST_IO_HAS_BUILTIN(__builtin_bit_cast) this->value = __builtin_bit_cast(vec_type, __builtin_bit_cast(unsigned_vec_type, this->value) + __builtin_bit_cast(unsigned_vec_type, b)); #else @@ -147,7 +147,7 @@ struct simd_vector template requires((sizeof(T2) == sizeof(T) * N) && ::std::is_trivially_copyable_v) inline -#if __has_builtin(__builtin_bit_cast) +#if FAST_IO_HAS_BUILTIN(__builtin_bit_cast) constexpr #endif void @@ -162,7 +162,7 @@ struct simd_vector { using unsigned_type = ::std::make_unsigned_t; using unsigned_vec_type = typename simd_vector::vec_type; -#if __has_builtin(__builtin_bit_cast) +#if FAST_IO_HAS_BUILTIN(__builtin_bit_cast) this->value = __builtin_bit_cast(vec_type, __builtin_bit_cast(unsigned_vec_type, this->value) - __builtin_bit_cast(unsigned_vec_type, b)); #else @@ -220,12 +220,12 @@ struct simd_vector template requires(sizeof(T1) * N1 == sizeof(T) * N && !::std::same_as) inline explicit -#if __has_builtin(__builtin_bit_cast) +#if FAST_IO_HAS_BUILTIN(__builtin_bit_cast) constexpr #endif operator simd_vector() const noexcept { -#if __has_builtin(__builtin_bit_cast) +#if FAST_IO_HAS_BUILTIN(__builtin_bit_cast) return __builtin_bit_cast(simd_vector, *this); #else simd_vector v; @@ -244,7 +244,7 @@ struct simd_vector return *this; } inline -#if __has_builtin(__builtin_bit_cast) +#if FAST_IO_HAS_BUILTIN(__builtin_bit_cast) constexpr #endif void @@ -259,14 +259,14 @@ struct simd_vector else if constexpr (N * sizeof(T) == 64) { using temp_vec_type [[__gnu__::__vector_size__(64)]] = char; -#if __has_builtin(__builtin_bit_cast) +#if FAST_IO_HAS_BUILTIN(__builtin_bit_cast) auto temp_vec{__builtin_bit_cast(temp_vec_type, this->value)}; #else temp_vec_type temp_vec; __builtin_memcpy(__builtin_addressof(temp_vec), __builtin_addressof(this->value), sizeof(vec_type)); #endif -#if __has_builtin(__builtin_shufflevector) +#if FAST_IO_HAS_BUILTIN(__builtin_shufflevector) if constexpr (sizeof(T) == 8) { // clang-format off @@ -294,7 +294,7 @@ struct simd_vector 48, 51, 50, 53, 52, 55, 54, 57, 56, 59, 58, 61, 60, 63, 62); // clang-format on } -#elif __has_builtin(__builtin_ia32_pshufb512) +#elif FAST_IO_HAS_BUILTIN(__builtin_ia32_pshufb512) if constexpr (sizeof(T) == 8) { // clang-format off @@ -326,7 +326,7 @@ struct simd_vector // clang-format on } #endif -#if __has_builtin(__builtin_bit_cast) +#if FAST_IO_HAS_BUILTIN(__builtin_bit_cast) this->value = __builtin_bit_cast(vec_type, temp_vec); #else __builtin_memcpy(__builtin_addressof(this->value), __builtin_addressof(temp_vec), sizeof(vec_type)); @@ -335,13 +335,13 @@ struct simd_vector else if constexpr (N * sizeof(T) == 32) { using temp_vec_type [[__gnu__::__vector_size__(32)]] = char; -#if __has_builtin(__builtin_bit_cast) +#if FAST_IO_HAS_BUILTIN(__builtin_bit_cast) auto temp_vec{__builtin_bit_cast(temp_vec_type, this->value)}; #else temp_vec_type temp_vec; __builtin_memcpy(__builtin_addressof(temp_vec), __builtin_addressof(this->value), sizeof(vec_type)); #endif -#if __has_builtin(__builtin_shufflevector) +#if FAST_IO_HAS_BUILTIN(__builtin_shufflevector) if constexpr (sizeof(T) == 8) { // clang-format off @@ -364,7 +364,7 @@ struct simd_vector 14, 17, 16, 19, 18, 21, 20, 23, 22, 25, 24, 27, 26, 29, 28, 31, 30); // clang-format on } -#elif __has_builtin(__builtin_ia32_pshufb256) +#elif FAST_IO_HAS_BUILTIN(__builtin_ia32_pshufb256) if constexpr (sizeof(T) == 8) { // clang-format off @@ -390,7 +390,7 @@ struct simd_vector // clang-format on } #endif -#if __has_builtin(__builtin_bit_cast) +#if FAST_IO_HAS_BUILTIN(__builtin_bit_cast) this->value = __builtin_bit_cast(vec_type, temp_vec); #else __builtin_memcpy(__builtin_addressof(this->value), __builtin_addressof(temp_vec), sizeof(vec_type)); @@ -399,13 +399,13 @@ struct simd_vector else { using temp_vec_type [[__gnu__::__vector_size__(16)]] = char; -#if __has_builtin(__builtin_bit_cast) +#if FAST_IO_HAS_BUILTIN(__builtin_bit_cast) auto temp_vec{__builtin_bit_cast(temp_vec_type, this->value)}; #else temp_vec_type temp_vec; __builtin_memcpy(__builtin_addressof(temp_vec), __builtin_addressof(this->value), sizeof(vec_type)); #endif -#if __has_builtin(__builtin_shufflevector) && ((!defined(__x86_64__) && !defined(__i386__)) || \ +#if FAST_IO_HAS_BUILTIN(__builtin_shufflevector) && ((!defined(__x86_64__) && !defined(__i386__)) || \ (!defined(__GNUC__) || defined(__clang__)) || defined(__SSE4_2__)) if constexpr (sizeof(T) == 8) { @@ -428,7 +428,7 @@ struct simd_vector __builtin_shufflevector(temp_vec, temp_vec, 1, 0, 3, 2, 5, 4, 7, 6, 9, 8, 11, 10, 13, 12, 15, 14); // clang-format on } -#elif __has_builtin(__builtin_ia32_pshufb128) && defined(__SSE3__) +#elif FAST_IO_HAS_BUILTIN(__builtin_ia32_pshufb128) && defined(__SSE3__) if constexpr (sizeof(T) == 8) { // clang-format off @@ -450,7 +450,7 @@ struct simd_vector temp_vec = __builtin_ia32_pshufb128(temp_vec, mask); // clang-format on } -#elif defined(__SSE2__) && __has_builtin(__builtin_ia32_punpcklbw128) && __has_builtin(__builtin_ia32_punpckhbw128) +#elif defined(__SSE2__) && FAST_IO_HAS_BUILTIN(__builtin_ia32_punpcklbw128) && FAST_IO_HAS_BUILTIN(__builtin_ia32_punpckhbw128) using x86_64_v4si [[__gnu__::__vector_size__(16)]] = int; using x86_64_v16qi [[__gnu__::__vector_size__(16)]] = char; using x86_64_v8hi [[__gnu__::__vector_size__(16)]] = short; @@ -484,7 +484,7 @@ struct simd_vector temp_vec = (x86_64_v16qi)((res0 >> 8) | (res0 << 8)); } #endif -#if __has_builtin(__builtin_bit_cast) +#if FAST_IO_HAS_BUILTIN(__builtin_bit_cast) this->value = __builtin_bit_cast(vec_type, temp_vec); #else __builtin_memcpy(__builtin_addressof(this->value), __builtin_addressof(temp_vec), sizeof(vec_type)); @@ -498,9 +498,9 @@ struct simd_vector { if constexpr (sizeof(mask) == 16) { -#if __has_builtin(__builtin_ia32_pshufb128) +#if FAST_IO_HAS_BUILTIN(__builtin_ia32_pshufb128) using value_type2 [[__gnu__::__vector_size__(16)]] = char; -#if __has_builtin(__builtin_bit_cast) +#if FAST_IO_HAS_BUILTIN(__builtin_bit_cast) value = __builtin_bit_cast(vec_type, __builtin_ia32_pshufb128(__builtin_bit_cast(value_type2, value), mask.value)); #else @@ -513,9 +513,9 @@ struct simd_vector } else if constexpr (sizeof(mask) == 32) { -#if __has_builtin(__builtin_ia32_pshufb256) +#if FAST_IO_HAS_BUILTIN(__builtin_ia32_pshufb256) using value_type2 [[__gnu__::__vector_size__(32)]] = char; -#if __has_builtin(__builtin_bit_cast) +#if FAST_IO_HAS_BUILTIN(__builtin_bit_cast) value = __builtin_bit_cast(vec_type, __builtin_ia32_pshufb256(__builtin_bit_cast(value_type2, value), mask.value)); #else @@ -633,7 +633,7 @@ inline constexpr simd_vector operator!=(simd_vector const &a, simd_v template <::std::integral T, ::std::size_t N> inline -#if __has_builtin(__builtin_bit_cast) +#if FAST_IO_HAS_BUILTIN(__builtin_bit_cast) constexpr #endif simd_vector @@ -643,7 +643,7 @@ inline { using unsigned_type = ::std::make_unsigned_t; using vec_type = typename simd_vector::vec_type; -#if __has_builtin(__builtin_bit_cast) +#if FAST_IO_HAS_BUILTIN(__builtin_bit_cast) return __builtin_bit_cast(simd_vector, __builtin_bit_cast(vec_type, a) + __builtin_bit_cast(vec_type, b)); #else vec_type asv; @@ -664,7 +664,7 @@ inline template <::std::integral T, ::std::size_t N> inline -#if __has_builtin(__builtin_bit_cast) +#if FAST_IO_HAS_BUILTIN(__builtin_bit_cast) constexpr #endif simd_vector @@ -674,7 +674,7 @@ inline { using unsigned_type = ::std::make_unsigned_t; using vec_type = typename simd_vector::vec_type; -#if __has_builtin(__builtin_bit_cast) +#if FAST_IO_HAS_BUILTIN(__builtin_bit_cast) return __builtin_bit_cast(simd_vector, __builtin_bit_cast(vec_type, a) - __builtin_bit_cast(vec_type, b)); #else vec_type asv; diff --git a/include/fast_io_core_impl/simd/generic.h b/include/fast_io_core_impl/simd/generic.h index c656413e0..c2931e025 100644 --- a/include/fast_io_core_impl/simd/generic.h +++ b/include/fast_io_core_impl/simd/generic.h @@ -36,12 +36,8 @@ struct #endif inline void load(void const *address) noexcept { -#if defined(__has_builtin) -#if __has_builtin(__builtin_memcpy) +#if FAST_IO_HAS_BUILTIN(__builtin_memcpy) __builtin_memcpy(__builtin_addressof(value), address, sizeof(value)); -#else - ::std::memcpy(__builtin_addressof(value), address, sizeof(value)); -#endif #else ::std::memcpy(__builtin_addressof(value), address, sizeof(value)); #endif @@ -55,12 +51,8 @@ struct #endif inline void store(void *address) noexcept { -#if defined(__has_builtin) -#if __has_builtin(__builtin_memcpy) +#if FAST_IO_HAS_BUILTIN(__builtin_memcpy) __builtin_memcpy(address, __builtin_addressof(value), sizeof(value)); -#else - ::std::memcpy(address, __builtin_addressof(value), sizeof(value)); -#endif #else ::std::memcpy(address, __builtin_addressof(value), sizeof(value)); #endif diff --git a/include/fast_io_core_impl/simd/is_all_zeros.h b/include/fast_io_core_impl/simd/is_all_zeros.h index 93a4955e6..35ebcaab6 100644 --- a/include/fast_io_core_impl/simd/is_all_zeros.h +++ b/include/fast_io_core_impl/simd/is_all_zeros.h @@ -87,7 +87,7 @@ inline if constexpr (sizeof(::fast_io::intrinsics::simd_vector) == 16) { #if defined(__has_builtin) && __has_cpp_attribute(__gnu__::__vector_size__) -#if defined(__x86_64__) && defined(__SSE4_1__) && __has_builtin(__builtin_ia32_pmovmskb128) +#if defined(__x86_64__) && defined(__SSE4_1__) && __has_builtin(__builtin_ia32_ptestz128) using x86_64_v2di [[__gnu__::__vector_size__(16)]] = long long; #if __has_builtin(__builtin_bit_cast) return __builtin_ia32_ptestz128(__builtin_bit_cast(x86_64_v2di, vec), __builtin_bit_cast(x86_64_v2di, vec)); diff --git a/include/fast_io_core_impl/socket/addrscn.h b/include/fast_io_core_impl/socket/addrscn.h index e1126c909..9858cc996 100644 --- a/include/fast_io_core_impl/socket/addrscn.h +++ b/include/fast_io_core_impl/socket/addrscn.h @@ -268,11 +268,7 @@ scn_ctx_define_inaddr_impl(ipv4_scan_state_t &state, char_type const return {begin, parse_code::ok}; } } -#ifdef __has_builtin -#if __has_builtin(__builtin_unreachable) - __builtin_unreachable(); -#endif -#endif + ::fast_io::unreachable(); } template <::std::integral char_type> @@ -317,11 +313,7 @@ inline constexpr parse_result scn_ctx_define_port_impl(ip_por } return scan_context_define_parse_impl<10, true, false, false>(state, begin, end, t); default:; -#ifdef __has_builtin -#if __has_builtin(__builtin_unreachable) - __builtin_unreachable(); -#endif -#endif + ::fast_io::unreachable(); } } @@ -844,11 +836,7 @@ scan_context_define(::fast_io::io_reserve_type_tport)}; } #endif -#ifdef __has_builtin -#if __has_builtin(__builtin_unreachable) - __builtin_unreachable(); -#endif -#endif + ::fast_io::unreachable(); } } diff --git a/include/fast_io_core_impl/terminate.h b/include/fast_io_core_impl/terminate.h index c0c87839f..6df2e6855 100644 --- a/include/fast_io_core_impl/terminate.h +++ b/include/fast_io_core_impl/terminate.h @@ -15,17 +15,13 @@ namespace fast_io fast_terminate() noexcept { // https://llvm.org/doxygen/Compiler_8h_source.html -#if defined(__has_builtin) -#if __has_builtin(__builtin_trap) +#if FAST_IO_HAS_BUILTIN(__builtin_trap) __builtin_trap(); -#elif __has_builtin(__builtin_abort) +#elif FAST_IO_HAS_BUILTIN(__builtin_abort) __builtin_abort(); #else ::std::abort(); #endif -#else - ::std::abort(); -#endif } #if __has_cpp_attribute(__gnu__::__always_inline__) diff --git a/include/fast_io_core_impl/timestamp_counter.h b/include/fast_io_core_impl/timestamp_counter.h index bd96b63ee..eb0e15ae7 100644 --- a/include/fast_io_core_impl/timestamp_counter.h +++ b/include/fast_io_core_impl/timestamp_counter.h @@ -5,12 +5,8 @@ namespace fast_io inline auto current_processor_timestamp_counter() noexcept { -#if defined(__has_builtin) -#if __has_builtin(__builtin_ia32_rdtsc) +#if FAST_IO_HAS_BUILTIN(__builtin_ia32_rdtsc) return __builtin_ia32_rdtsc(); -#else - return static_cast<::std::uint_least64_t>(0); -#endif #elif defined(_MSC_VER) && defined(_M_IX86) return __rdtsc(); #else diff --git a/include/fast_io_core_impl/utils.h b/include/fast_io_core_impl/utils.h index c26461af5..49db8400c 100644 --- a/include/fast_io_core_impl/utils.h +++ b/include/fast_io_core_impl/utils.h @@ -21,12 +21,8 @@ inline return ::std::bit_cast(src); #else To dst; -#if defined(__has_builtin) -#if __has_builtin(__builtin_memcpy) +#if FAST_IO_HAS_BUILTIN(__builtin_memcpy) __builtin_memcpy -#else - ::std::memcpy -#endif #else ::std::memcpy #endif @@ -247,7 +243,7 @@ inline constexpr U byte_swap(U a) noexcept #if (defined(__GNUC__) || defined(__clang__)) #ifdef __SIZEOF_INT128__ if constexpr (sizeof(U) == 16) -#if __has_builtin(__builtin_bswap128) +#if FAST_IO_HAS_BUILTIN(__builtin_bswap128) return __builtin_bswap128(a); #else { diff --git a/include/fast_io_crypto/hash/crc32.h b/include/fast_io_crypto/hash/crc32.h index 3cf22fc3e..656805074 100644 --- a/include/fast_io_crypto/hash/crc32.h +++ b/include/fast_io_crypto/hash/crc32.h @@ -109,7 +109,7 @@ inline constexpr ::std::uint_least32_t crc32c_tb[256]{ // clang-format on inline constexpr bool support_hardware_crc32{ -#if defined(__ARM_FEATURE_CRC32) && __has_builtin(__builtin_arm_crc32b) +#if defined(__ARM_FEATURE_CRC32) && FAST_IO_HAS_BUILTIN(__builtin_arm_crc32b) true #endif }; @@ -119,7 +119,7 @@ inline constexpr ::std::uint_least32_t calculate_crc32_hardware(::std::uint_leas { for (; i != ed; ++i) { -#if defined(__ARM_FEATURE_CRC32) && __has_builtin(__builtin_arm_crc32b) +#if defined(__ARM_FEATURE_CRC32) && FAST_IO_HAS_BUILTIN(__builtin_arm_crc32b) crc = __builtin_arm_crc32b(crc, static_cast<::std::uint_least8_t>(*i)); #else crc = crc32_tb[(static_cast<::std::uint_least32_t>(*i) ^ crc) & 0xff] ^ (crc >> 8); @@ -129,8 +129,8 @@ inline constexpr ::std::uint_least32_t calculate_crc32_hardware(::std::uint_leas } inline constexpr bool support_hardware_crc32c{ -#if defined(__CRC32__) && __has_builtin(__builtin_ia32_crc32qi) || \ - defined(__ARM_FEATURE_CRC32) && __has_builtin(__builtin_arm_crc32cb) || \ +#if defined(__CRC32__) && FAST_IO_HAS_BUILTIN(__builtin_ia32_crc32qi) || \ + defined(__ARM_FEATURE_CRC32) && FAST_IO_HAS_BUILTIN(__builtin_arm_crc32cb) || \ ((defined(_MSC_VER) && !defined(__clang__)) && !(!defined(_M_IX86) && !defined(_M_X64) && !(defined(_M_ARM64) && defined(USE_SOFT_INTRINSICS)))) true #endif @@ -141,9 +141,9 @@ inline constexpr ::std::uint_least32_t calculate_crc32c_hardware(::std::uint_lea { for (; i != ed; ++i) { -#if defined(__CRC32__) && __has_builtin(__builtin_ia32_crc32qi) +#if defined(__CRC32__) && FAST_IO_HAS_BUILTIN(__builtin_ia32_crc32qi) crc = __builtin_ia32_crc32qi(crc, static_cast<::std::uint_least8_t>(*i)); -#elif defined(__ARM_FEATURE_CRC32) && __has_builtin(__builtin_arm_crc32cb) +#elif defined(__ARM_FEATURE_CRC32) && FAST_IO_HAS_BUILTIN(__builtin_arm_crc32cb) crc = __builtin_arm_crc32cb(crc, static_cast<::std::uint_least8_t>(*i)); #elif (defined(_MSC_VER) && !defined(__clang__)) && !(!defined(_M_IX86) && !defined(_M_X64) && !(defined(_M_ARM64) && defined(USE_SOFT_INTRINSICS))) crc = ::_mm_crc32_u8(crc, static_cast<::std::uint_least8_t>(*i)); diff --git a/include/fast_io_crypto/hash/md5_sha_hash_context.h b/include/fast_io_crypto/hash/md5_sha_hash_context.h index a08f4d86a..7c6ebe0ad 100644 --- a/include/fast_io_crypto/hash/md5_sha_hash_context.h +++ b/include/fast_io_crypto/hash/md5_sha_hash_context.h @@ -114,14 +114,10 @@ struct md5_sha_common_impl ::std::size_t const buffer_remain_space{static_cast<::std::size_t>(block_size - buffer_offset)}; if (diff < buffer_remain_space) [[likely]] { -#if defined(__has_builtin) -#if __has_builtin(__builtin_unreachable) if (diff >= block_size) { - __builtin_unreachable(); + ::fast_io::unreachable(); } -#endif -#endif ::fast_io::details::non_overlapped_copy_n(block_first, diff, buffer + buffer_offset); buffer_offset += diff; } @@ -147,27 +143,19 @@ struct md5_sha_common_impl if (buffer_off <= sz) { ::std::size_t const to_fill{static_cast<::std::size_t>(sz - buffer_off)}; -#if defined(__has_builtin) -#if __has_builtin(__builtin_unreachable) if (to_fill > sz) { - __builtin_unreachable(); + ::fast_io::unreachable(); } -#endif -#endif ::fast_io::none_secure_clear(this->buffer + buffer_off, to_fill); this->append_sentinal(buffer_offs); return; } ::std::size_t const to_fill{static_cast<::std::size_t>(block_size - buffer_off)}; -#if defined(__has_builtin) -#if __has_builtin(__builtin_unreachable) if (to_fill > counter_type_size) { - __builtin_unreachable(); + ::fast_io::unreachable(); } -#endif -#endif ::fast_io::none_secure_clear(this->buffer + buffer_off, to_fill); this->hasher.update_blocks(this->buffer, this->buffer + block_size); ::fast_io::none_secure_clear(this->buffer, sz); diff --git a/include/fast_io_crypto/hash/sha256.h b/include/fast_io_crypto/hash/sha256.h index 118017223..7acb4569e 100644 --- a/include/fast_io_crypto/hash/sha256.h +++ b/include/fast_io_crypto/hash/sha256.h @@ -152,9 +152,9 @@ inline !defined(__clang__) && defined(__ELF__) && defined(FAST_IO_RUNTIME_DISPATCH) #include "sha256_x86_sha_extensions.h" #include "sha256_simd16.h" -#elif __has_builtin(__builtin_ia32_sha256rnds2) && __has_builtin(__builtin_ia32_pshufd) && \ - __has_builtin(__builtin_ia32_palignr128) && __has_builtin(__builtin_ia32_sha256msg1) && \ - __has_builtin(__builtin_ia32_sha256msg2) && __has_builtin(__builtin_ia32_pshufb128) && \ +#elif FAST_IO_HAS_BUILTIN(__builtin_ia32_sha256rnds2) && FAST_IO_HAS_BUILTIN(__builtin_ia32_pshufd) && \ + FAST_IO_HAS_BUILTIN(__builtin_ia32_palignr128) && FAST_IO_HAS_BUILTIN(__builtin_ia32_sha256msg1) && \ + FAST_IO_HAS_BUILTIN(__builtin_ia32_sha256msg2) && FAST_IO_HAS_BUILTIN(__builtin_ia32_pshufb128) && \ (!defined(__clang__) || (defined(__SSE4_2__) && defined(__SHA__))) #include "sha256_x86_sha_extensions.h" #elif defined(__SSE2__) || defined(__wasm_simd128__) diff --git a/include/fast_io_crypto/hash/sha512.h b/include/fast_io_crypto/hash/sha512.h index 21209a49b..041d38af1 100644 --- a/include/fast_io_crypto/hash/sha512.h +++ b/include/fast_io_crypto/hash/sha512.h @@ -168,11 +168,11 @@ inline constexpr void sha512_do_constexpr_function(::std::uint_least64_t *__rest #include "sha512_scalar.h" #else #if !(defined(_MSC_VER) && !defined(__clang__)) -#if defined(__SSE2__) && !defined(__AVX2__) && __has_builtin(__builtin_shufflevector) && \ +#if defined(__SSE2__) && !defined(__AVX2__) && FAST_IO_HAS_BUILTIN(__builtin_shufflevector) && \ __has_cpp_attribute(__gnu__::__target__) && defined(__ELF__) && defined(FAST_IO_RUNTIME_DISPATCH) #include "sha512_simd32_shuffle.h" #include "sha512_simd16.h" -#elif defined(__AVX2__) && __has_builtin(__builtin_shufflevector) +#elif defined(__AVX2__) && FAST_IO_HAS_BUILTIN(__builtin_shufflevector) #include "sha512_simd32_shuffle.h" #elif defined(__SSE2__) #include "sha512_simd16.h" diff --git a/include/fast_io_crypto/hash/sha512_simd16.h b/include/fast_io_crypto/hash/sha512_simd16.h index e05f2aeaa..446bf75c8 100644 --- a/include/fast_io_crypto/hash/sha512_simd16.h +++ b/include/fast_io_crypto/hash/sha512_simd16.h @@ -62,13 +62,11 @@ sha512_simd16_compute_message_2rounds(::fast_io::intrinsics::simd_vector<::std:: s0.store(wt); } -#if defined(__has_builtin) -#if __has_cpp_attribute(__gnu__::__target__) && __has_builtin(__builtin_shufflevector) && defined(__SSE2__) && \ +#if __has_cpp_attribute(__gnu__::__target__) && FAST_IO_HAS_BUILTIN(__builtin_shufflevector) && defined(__SSE2__) && \ !defined(__AVX2__) && defined(__ELF__) && defined(FAST_IO_RUNTIME_DISPATCH) [[__gnu__::__target__("default")]] #elif __has_cpp_attribute(__gnu__::__flatten__) [[__gnu__::__flatten__]] -#endif #elif __has_cpp_attribute(msvc::flatten) [[msvc::flatten]] #endif diff --git a/include/fast_io_crypto/hash/sha512_simd32.h b/include/fast_io_crypto/hash/sha512_simd32.h index d7af3e708..546fb9f27 100644 --- a/include/fast_io_crypto/hash/sha512_simd32.h +++ b/include/fast_io_crypto/hash/sha512_simd32.h @@ -73,7 +73,7 @@ sha512_simd32_compute_message_4rounds(::fast_io::intrinsics::simd_vector<::std:: s0.store(wt); } -#if __has_cpp_attribute(__gnu__::__target__) && __has_builtin(__builtin_shufflevector) && defined(__SSE2__) && \ +#if __has_cpp_attribute(__gnu__::__target__) && FAST_IO_HAS_BUILTIN(__builtin_shufflevector) && defined(__SSE2__) && \ !defined(__AVX2__) && defined(__ELF__) [[__gnu__::__target__("avx2")]] #elif __has_cpp_attribute(__gnu__::__flatten__) diff --git a/include/fast_io_crypto/hash/sha512_simd32_shuffle.h b/include/fast_io_crypto/hash/sha512_simd32_shuffle.h index 691d6fe67..b2f7c3152 100644 --- a/include/fast_io_crypto/hash/sha512_simd32_shuffle.h +++ b/include/fast_io_crypto/hash/sha512_simd32_shuffle.h @@ -337,7 +337,7 @@ inline void sha512_simd32_compute_message_4rounds( } } -#if __has_cpp_attribute(__gnu__::__target__) && __has_builtin(__builtin_shufflevector) && defined(__SSE2__) && \ +#if __has_cpp_attribute(__gnu__::__target__) && FAST_IO_HAS_BUILTIN(__builtin_shufflevector) && defined(__SSE2__) && \ !defined(__AVX2__) && defined(__ELF__) && defined(FAST_IO_RUNTIME_DISPATCH) [[__gnu__::__target__("avx2")]] #elif __has_cpp_attribute(__gnu__::__flatten__) diff --git a/include/fast_io_crypto/streamcipher/chacha/impl.h b/include/fast_io_crypto/streamcipher/chacha/impl.h index 9bdd75f63..7bccaec90 100644 --- a/include/fast_io_crypto/streamcipher/chacha/impl.h +++ b/include/fast_io_crypto/streamcipher/chacha/impl.h @@ -2,7 +2,7 @@ #include "scalar.h" #if (defined(__GNUC__) || defined(__clang__)) && (defined(__SSE__) || defined(__wasm_simd128__)) -#if __has_builtin(__builtin_shufflevector) +#if FAST_IO_HAS_BUILTIN(__builtin_shufflevector) #include "simd16.h" #else #include "runtime.h" diff --git a/include/fast_io_driver/tsc_timer.h b/include/fast_io_driver/tsc_timer.h index cad2da265..233adbb08 100644 --- a/include/fast_io_driver/tsc_timer.h +++ b/include/fast_io_driver/tsc_timer.h @@ -7,7 +7,7 @@ inline ::std::uint_least64_t current_tsc() noexcept { #if defined(_MSC_VER) && !defined(__clang__) return __rdtsc(); -#elif __has_builtin(__builtin_ia32_rdtsc) +#elif FAST_IO_HAS_BUILTIN(__builtin_ia32_rdtsc) return __builtin_ia32_rdtsc(); #else return 0; diff --git a/include/fast_io_dsal/impl/freestanding.h b/include/fast_io_dsal/impl/freestanding.h index 88982ef12..68c7dbedb 100644 --- a/include/fast_io_dsal/impl/freestanding.h +++ b/include/fast_io_dsal/impl/freestanding.h @@ -287,12 +287,8 @@ inline constexpr Iter uninitialized_fill(Iter first, Iter last, T const &ele) if (!__builtin_is_constant_evaluated()) #endif { -#ifdef __has_builtin -#if __has_builtin(__builtin_memset) +#if FAST_IO_HAS_BUILTIN(__builtin_memset) __builtin_memset -#else - ::std::memset -#endif #else ::std::memset #endif diff --git a/include/fast_io_dsal/impl/misc/pop_macros.h b/include/fast_io_dsal/impl/misc/pop_macros.h index d44ba4729..6f8008b82 100644 --- a/include/fast_io_dsal/impl/misc/pop_macros.h +++ b/include/fast_io_dsal/impl/misc/pop_macros.h @@ -1,5 +1,6 @@ // Please keep it in reverse order with the macros in push_macros.h +#pragma pop_macro("FAST_IO_HAS_BUILTIN") #pragma pop_macro("FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE") #pragma pop_macro("FAST_IO_ASSERT") #pragma pop_macro("FAST_IO_GNU_RETURNS_NONNULL") diff --git a/include/fast_io_dsal/impl/misc/push_macros.h b/include/fast_io_dsal/impl/misc/push_macros.h index f9a229f50..b555a5792 100644 --- a/include/fast_io_dsal/impl/misc/push_macros.h +++ b/include/fast_io_dsal/impl/misc/push_macros.h @@ -215,4 +215,12 @@ Internal assert macros for fuzzing fast_io. #define FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE trivially_relocatable_if_eligible #else #define FAST_IO_TRIVIALLY_RELOCATABLE_IF_ELIGIBLE -#endif \ No newline at end of file +#endif + +#pragma push_macro("FAST_IO_HAS_BUILTIN") +#undef FAST_IO_HAS_BUILTIN +#ifdef __has_builtin +# define FAST_IO_HAS_BUILTIN(...) __has_builtin(__VA_ARGS__) +#else +# define FAST_IO_HAS_BUILTIN(...) 0 +#endif diff --git a/include/fast_io_freestanding_impl/serializations/lebe.h b/include/fast_io_freestanding_impl/serializations/lebe.h index 521e22d51..8c0e0a3f6 100644 --- a/include/fast_io_freestanding_impl/serializations/lebe.h +++ b/include/fast_io_freestanding_impl/serializations/lebe.h @@ -328,9 +328,7 @@ inline } #if __cpp_lib_bit_cast >= 201806L t = ::std::bit_cast(buffer); -#elif !defined(__has_builtin) - ::std::memcpy(__builtin_addressof(t), buffer, n); -#elif __has_builtin(__builtin_memcpy) +#elif FAST_IO_HAS_BUILTIN(__builtin_memcpy) __builtin_memcpy(__builtin_addressof(t), buffer, n); #else ::std::memcpy(__builtin_addressof(t), buffer, n); @@ -375,9 +373,7 @@ inline else #endif { -#if !defined(__has_builtin) - ::std::memcpy(__builtin_addressof(t), iter, sizeof(int_type)); -#elif __has_builtin(__builtin_memcpy) +#if FAST_IO_HAS_BUILTIN(__builtin_memcpy) __builtin_memcpy(__builtin_addressof(t), iter, sizeof(int_type)); #else ::std::memcpy(__builtin_addressof(t), iter, sizeof(int_type)); @@ -566,9 +562,7 @@ inline } else { -#if !defined(__has_builtin) - ::std::memcpy(iter, __builtin_addressof(u), n); -#elif __has_builtin(__builtin_memcpy) +#if FAST_IO_HAS_BUILTIN(__builtin_memcpy) __builtin_memcpy(iter, __builtin_addressof(u), n); #else ::std::memcpy(iter, __builtin_addressof(u), n); diff --git a/include/fast_io_hosted/file_loaders/allocation_file_loader.h b/include/fast_io_hosted/file_loaders/allocation_file_loader.h index b96a94772..253224245 100644 --- a/include/fast_io_hosted/file_loaders/allocation_file_loader.h +++ b/include/fast_io_hosted/file_loaders/allocation_file_loader.h @@ -26,12 +26,8 @@ struct allocation_file_loader_closer_impl ::fast_io::noexcept_call(::close, fd); #endif } -#if defined(__has_builtin) -#if __has_builtin(__builtin_free) +#if FAST_IO_HAS_BUILTIN(__builtin_free) __builtin_free(address_begin); -#else - ::std::free(address_begin); -#endif #else ::std::free(address_begin); #endif @@ -105,12 +101,8 @@ struct load_file_allocation_guard inline explicit constexpr load_file_allocation_guard() noexcept = default; inline explicit load_file_allocation_guard(::std::size_t file_size) : address( -#if defined(__has_builtin) -#if __has_builtin(__builtin_malloc) +#if FAST_IO_HAS_BUILTIN(__builtin_malloc) __builtin_malloc -#else - ::std::malloc -#endif #else ::std::malloc #endif @@ -125,12 +117,8 @@ struct load_file_allocation_guard inline load_file_allocation_guard &operator=(load_file_allocation_guard const &) = delete; inline ~load_file_allocation_guard() { -#if defined(__has_builtin) -#if __has_builtin(__builtin_free) +#if FAST_IO_HAS_BUILTIN(__builtin_free) __builtin_free(address); -#else - ::std::free(address); -#endif #else ::std::free(address); #endif diff --git a/include/fast_io_hosted/file_loaders/file_size.h b/include/fast_io_hosted/file_loaders/file_size.h index 080c3ec62..f997264db 100644 --- a/include/fast_io_hosted/file_loaders/file_size.h +++ b/include/fast_io_hosted/file_loaders/file_size.h @@ -1,10 +1,6 @@ #pragma once -#if defined(__has_builtin) -#if !__has_builtin(__builtin_malloc) || !__has_builtin(__builtin_free) -#include -#endif -#elif !defined(_MSC_VER) +#if !FAST_IO_HAS_BUILTIN(__builtin_malloc) || !FAST_IO_HAS_BUILTIN(__builtin_free) || !defined(_MSC_VER) #include #endif namespace fast_io diff --git a/include/fast_io_hosted/filesystem/nt.h b/include/fast_io_hosted/filesystem/nt.h index 7792d573d..8654c7a06 100644 --- a/include/fast_io_hosted/filesystem/nt.h +++ b/include/fast_io_hosted/filesystem/nt.h @@ -64,7 +64,7 @@ inline { if (__builtin_is_constant_evaluated()) { - return new nt_dirent; + return ::new nt_dirent; } else { @@ -85,7 +85,7 @@ inline { if (__builtin_is_constant_evaluated()) { - delete ptr; + ::delete ptr; } else { diff --git a/include/fast_io_hosted/platforms/linux/amd64.h b/include/fast_io_hosted/platforms/linux/amd64.h index 469d04c06..c20773390 100644 --- a/include/fast_io_hosted/platforms/linux/amd64.h +++ b/include/fast_io_hosted/platforms/linux/amd64.h @@ -117,6 +117,5 @@ template <::std::integral I> inline void fast_exit(I ret) noexcept { system_call_no_return<__NR_exit>(ret); - __builtin_unreachable(); } } // namespace fast_io diff --git a/include/fast_io_hosted/threads/mutex/impl.h b/include/fast_io_hosted/threads/mutex/impl.h index baf559074..ea9f87b17 100644 --- a/include/fast_io_hosted/threads/mutex/impl.h +++ b/include/fast_io_hosted/threads/mutex/impl.h @@ -24,11 +24,7 @@ using native_mutex = mcf_gthread_mutex #elif (defined(_WIN32) && !defined(__WINE__)) || defined(__CYGWIN__) #if !defined(__CYGWIN__) && !defined(__BIONIC__) && defined(_WIN32_WINDOWS) -#if (!defined(_WIN32_WINNT) || _WIN32_WINNT >= 0x0600) - win32_srwlock -#else win32_critical_section -#endif #else #if (!defined(_WIN32_WINNT) || _WIN32_WINNT >= 0x0600) rtl_srwlock diff --git a/include/fast_io_hosted/timeutil/environ_timezone.h b/include/fast_io_hosted/timeutil/environ_timezone.h index e7a600667..f848d82f4 100644 --- a/include/fast_io_hosted/timeutil/environ_timezone.h +++ b/include/fast_io_hosted/timeutil/environ_timezone.h @@ -20,12 +20,8 @@ namespace details inline environ_timezone_name environ_localtimezone_impl() noexcept { auto ptr{reinterpret_cast<::fast_io::environ_timezone_name::char8_const_may_alias_ptr>( -#if !defined(__has_builtin) -#if __has_builtin(__builtin_getenv) +#if FAST_IO_HAS_BUILTIN(__builtin_getenv) __builtin_getenv -#else - ::std::getenv -#endif #else ::std::getenv #endif diff --git a/include/fast_io_i18n/locale/posix.h b/include/fast_io_i18n/locale/posix.h index 79ebcc5a0..1ad364c64 100644 --- a/include/fast_io_i18n/locale/posix.h +++ b/include/fast_io_i18n/locale/posix.h @@ -52,12 +52,8 @@ inline void *posix_load_l10n_common_impl(char8_t const *cstr, ::std::size_t n, l } cstr = reinterpret_cast(lc_all_env); n = -#if defined(__has_builtin) -#if __has_builtin(__builtin_strlen) +#if FAST_IO_HAS_BUILTIN(__builtin_strlen) __builtin_strlen(lc_all_env); -#else - ::std::strlen(lc_all_env); -#endif #else ::std::strlen(lc_all_env); #endif diff --git a/include/fast_io_legacy_impl/c/done.h b/include/fast_io_legacy_impl/c/done.h index f4b823995..3e01c9fc9 100644 --- a/include/fast_io_legacy_impl/c/done.h +++ b/include/fast_io_legacy_impl/c/done.h @@ -59,21 +59,13 @@ inline ::std::size_t c_fwrite_unlocked_impl(void const *__restrict begin, ::std: #if defined(__CYGWIN__) my_cygwin_fwrite_unlocked(begin, type_size, count, fp) #elif (defined(__USE_MISC) || defined(__BSD_VISIBLE)) && (!defined(__BIONIC__) || (defined(__USE_BSD))) -#if !defined(fwrite_unlocked) && defined(__has_builtin) -#if __has_builtin(__builtin_fwrite_unlocked) +#if !defined(fwrite_unlocked) && FAST_IO_HAS_BUILTIN(__builtin_fwrite_unlocked) __builtin_fwrite_unlocked(begin, type_size, count, fp) #else fwrite_unlocked(begin, type_size, count, fp) #endif -#else - fwrite_unlocked(begin, type_size, count, fp) -#endif -#elif !defined(fwrite) && defined(__has_builtin) -#if __has_builtin(__builtin_fwrite) +#elif !defined(fwrite) && FAST_IO_HAS_BUILTIN(__builtin_fwrite) __builtin_fwrite(begin, type_size, count, fp) -#else - fwrite(begin, type_size, count, fp) -#endif #else fwrite(begin, type_size, count, fp) #endif @@ -114,21 +106,14 @@ inline ::std::size_t c_fread_unlocked_impl(void *__restrict begin, ::std::size_t #if defined(__CYGWIN__) my_cygwin_fread_unlocked(begin, type_size, count, fp) #elif (defined(__USE_MISC) || defined(__BSD_VISIBLE)) && (!defined(__BIONIC__) || (defined(__USE_BSD))) -#if !defined(fread_unlocked) && defined(__has_builtin) -#if __has_builtin(__builtin_fread_unlocked) +#if !defined(fread_unlocked) && FAST_IO_HAS_BUILTIN(__builtin_fread_unlocked) __builtin_fread_unlocked(begin, type_size, count, fp) #else fread_unlocked(begin, type_size, count, fp) #endif -#else - fread_unlocked(begin, type_size, count, fp) -#endif -#elif !defined(fread) && defined(__has_builtin) -#if __has_builtin(__builtin_fread) + +#elif !defined(fread) && FAST_IO_HAS_BUILTIN(__builtin_fread) __builtin_fread(begin, type_size, count, fp) -#else - fread(begin, type_size, count, fp) -#endif #else fread(begin, type_size, count, fp) #endif @@ -139,21 +124,13 @@ inline ::std::size_t c_fread_unlocked_impl(void *__restrict begin, ::std::size_t #if defined(__CYGWIN__) __sferror(fp) #elif defined(__USE_MISC) || defined(__BSD_VISIBLE) || defined(__DARWIN_C_LEVEL) -#if defined(__has_builtin) -#if __has_builtin(__builtin_ferror_unlocked) +#if FAST_IO_HAS_BUILTIN(__builtin_ferror_unlocked) __builtin_ferror_unlocked(fp) #else ferror_unlocked(fp) #endif -#else - ferror_unlocked(fp) -#endif -#elif !defined(ferror) && defined(__has_builtin) -#if __has_builtin(__builtin_ferror) +#elif !defined(ferror) && FAST_IO_HAS_BUILTIN(__builtin_ferror) __builtin_ferror(fp) -#else - ferror(fp) -#endif #else ferror(fp) #endif @@ -181,12 +158,8 @@ inline ::std::size_t c_fwrite_impl(void const *__restrict begin, ::std::size_t t #else ::std::size_t written_count{ -#if !defined(fwrite) && defined(__has_builtin) -#if __has_builtin(__builtin_fwrite) +#if !defined(fwrite) && FAST_IO_HAS_BUILTIN(__builtin_fwrite) __builtin_fwrite(begin, type_size, count, fp) -#else - fwrite(begin, type_size, count, fp) -#endif #else fwrite(begin, type_size, count, fp) #endif @@ -218,12 +191,8 @@ inline ::std::size_t c_fread_impl(void *__restrict begin, ::std::size_t type_siz } #else ::std::size_t read_count{ -#if !defined(fread) && defined(__has_builtin) -#if __has_builtin(__builtin_fread) +#if !defined(fread) && FAST_IO_HAS_BUILTIN(__builtin_fread) __builtin_fread(begin, type_size, count, fp) -#else - fread(begin, type_size, count, fp) -#endif #else fread(begin, type_size, count, fp) #endif @@ -231,12 +200,8 @@ inline ::std::size_t c_fread_impl(void *__restrict begin, ::std::size_t type_siz if (read_count == 0) [[unlikely]] { if ( -#if !defined(ferror) && defined(__has_builtin) -#if __has_builtin(__builtin_ferror) +#if !defined(ferror) && FAST_IO_HAS_BUILTIN(__builtin_ferror) __builtin_ferror(fp) -#else - ferror(fp) -#endif #else ferror(fp) #endif diff --git a/include/fast_io_legacy_impl/c/impl.h b/include/fast_io_legacy_impl/c/impl.h index 346688d67..0c6a1f63b 100644 --- a/include/fast_io_legacy_impl/c/impl.h +++ b/include/fast_io_legacy_impl/c/impl.h @@ -324,12 +324,8 @@ inline int my_fclose_impl(FILE *fp) noexcept { if constexpr (family == c_family::standard || family == c_family::emulated) { -#ifdef __has_builtin -#if __has_builtin(__builtin_fclose) +#if FAST_IO_HAS_BUILTIN(__builtin_fclose) return __builtin_fclose(fp); -#else - return fclose(fp); -#endif #else return fclose(fp); #endif @@ -339,15 +335,11 @@ inline int my_fclose_impl(FILE *fp) noexcept #if defined(_MSC_VER) || defined(_UCRT) return noexcept_call(_fclose_nolock, fp); #else -#ifdef __has_builtin -#if __has_builtin(__builtin_fclose) +#if FAST_IO_HAS_BUILTIN(__builtin_fclose) return __builtin_fclose(fp); #else return fclose(fp); #endif -#else - return fclose(fp); -#endif #endif } } @@ -439,12 +431,8 @@ inline void my_c_io_flush_impl(FILE *fp) #else if constexpr (family == c_family::standard) { -#if defined(__has_builtin) -#if __has_builtin(__builtin_fflush) +#if FAST_IO_HAS_BUILTIN(__builtin_fflush) if (__builtin_fflush(fp)) -#else - if (fflush(fp)) -#endif #else if (fflush(fp)) #endif @@ -574,12 +562,8 @@ inline ::fast_io::intfpos_t my_c_io_seek_impl(FILE *fp, ::fast_io::intfpos_t off _fseeki64(fp, offset, static_cast(s)) #elif defined(__USE_LARGEFILE64) noexcept_call(fseeko64, fp, offset, static_cast(s)) -#elif defined(__has_builtin) -#if __has_builtin(__builtin_fseeko) +#elif FAST_IO_HAS_BUILTIN(__builtin_fseeko) __builtin_fseeko(fp, offset, static_cast(s)) -#else - fseeko(fp, offset, static_cast(s)) -#endif #else fseeko(fp, offset, static_cast(s)) #endif @@ -590,12 +574,8 @@ inline ::fast_io::intfpos_t my_c_io_seek_impl(FILE *fp, ::fast_io::intfpos_t off noexcept_call(_ftelli64, fp) #elif defined(__USE_LARGEFILE64) noexcept_call(ftello64, fp) -#elif defined(__has_builtin) -#if __has_builtin(__builtin_ftello) +#elif FAST_IO_HAS_BUILTIN(__builtin_ftello) __builtin_ftello(fp) -#else - ftello(fp) -#endif #else ftello(fp) #endif diff --git a/include/fast_io_legacy_impl/c/wincrt.h b/include/fast_io_legacy_impl/c/wincrt.h index 066e64740..0cd88d702 100644 --- a/include/fast_io_legacy_impl/c/wincrt.h +++ b/include/fast_io_legacy_impl/c/wincrt.h @@ -103,15 +103,11 @@ inline void *my_malloc_crt(::std::size_t buffer_size) noexcept https://github.com/mirror/mingw-w64/blob/master/mingw-w64-headers/crt/crtdbg.h CRT heap debugging does not exist on mingw-w64 */ -#if defined(__has_builtin) -#if __has_builtin(__builtin_malloc) +#if FAST_IO_HAS_BUILTIN(__builtin_malloc) __builtin_malloc(buffer_size) #else malloc(buffer_size) #endif -#else - malloc(buffer_size) -#endif #endif }; // handling allocation failure is a historical mistake and it never happens on windows. Just let it crash. @@ -217,8 +213,8 @@ inline void wincrt_fp_write_cold_impl(FILE *__restrict fp, char const *first, ch crt_iobuf *fpp{reinterpret_cast(fp)}; if (fpp->_base == nullptr) { - wincrt_fp_write_cold_malloc_case_impl(fp, first, diff); - } + wincrt_fp_write_cold_malloc_case_impl(fp, first, diff); + } else { wincrt_fp_write_cold_normal_case_impl(fp, first, diff); diff --git a/include/fast_io_legacy_impl/filebuf/rtti_hack/impl.h b/include/fast_io_legacy_impl/filebuf/rtti_hack/impl.h index 2fd9ac227..87af3c259 100644 --- a/include/fast_io_legacy_impl/filebuf/rtti_hack/impl.h +++ b/include/fast_io_legacy_impl/filebuf/rtti_hack/impl.h @@ -86,12 +86,8 @@ inline constexpr bool symbol_cmp_equal_commom(char8_t const *sym, char const *st } else { -#ifdef __has_builtin -#if __has_builtin(__builtin_memcmp) +#if FAST_IO_HAS_BUILTIN(__builtin_memcmp) return __builtin_memcmp(sym, strp, N) == 0; -#else - return ::std::memcmp(sym, strp, N) == 0; -#endif #else return ::std::memcmp(sym, strp, N) == 0; #endif diff --git a/include/fast_io_unit/floating/punning.h b/include/fast_io_unit/floating/punning.h index 929faadfc..a25d54e57 100644 --- a/include/fast_io_unit/floating/punning.h +++ b/include/fast_io_unit/floating/punning.h @@ -589,12 +589,8 @@ inline constexpr punning_result get_punned_result(flt f) noexcept constexpr mantissa_type exponent_mask{(static_cast(1) << ebits) - 1}; auto unwrap = -#if defined(__has_builtin) -#if __has_builtin(__builtin_bit_cast) +#if FAST_IO_HAS_BUILTIN(__builtin_bit_cast) __builtin_bit_cast(mantissa_type, f) -#else - bit_cast(f) -#endif #elif defined(_MSC_VER) && __cpp_lib_bit_cast >= 201806L __builtin_bit_cast(mantissa_type, f) #else From 32ab3035ed15f384d33af663d490ca588f681081 Mon Sep 17 00:00:00 2001 From: MacroModel Date: Sat, 17 May 2025 02:29:18 +0800 Subject: [PATCH 2/3] rm --- .../operations/print_freestanding.h | 1466 ----------------- 1 file changed, 1466 deletions(-) delete mode 100644 include/fast_io_core_impl/operations/print_freestanding.h diff --git a/include/fast_io_core_impl/operations/print_freestanding.h b/include/fast_io_core_impl/operations/print_freestanding.h deleted file mode 100644 index 20df211ad..000000000 --- a/include/fast_io_core_impl/operations/print_freestanding.h +++ /dev/null @@ -1,1466 +0,0 @@ -#pragma once - -namespace fast_io -{ - -namespace details::decay -{ - -template <::std::integral char_type, typename T = char_type> -inline constexpr basic_io_scatter_t line_scatter_common{__builtin_addressof(char_literal_v), - ::std::same_as ? sizeof(char_type) : 1}; - -struct contiguous_scatter_result -{ - ::std::size_t position{}; - ::std::size_t neededscatters{}; - ::std::size_t neededspace{}; - ::std::size_t null{}; - bool lastisreserve{}; - bool hasscatters{}; - bool hasreserve{}; - bool hasdynamicreserve{}; -}; - -template <::std::integral char_type, typename Arg, typename... Args> -inline constexpr contiguous_scatter_result find_continuous_scatters_n() -{ - contiguous_scatter_result ret{}; - if constexpr (::fast_io::scatter_printable) - { - if constexpr (sizeof...(Args) != 0) - { - ret = find_continuous_scatters_n(); - } - ++ret.position; - ret.hasscatters = true; - ret.neededscatters = ::fast_io::details::intrinsics::add_or_overflow_die_chain(ret.neededscatters, - static_cast<::std::size_t>(1)); - } - else if constexpr (::fast_io::reserve_printable) - { - if constexpr (sizeof...(Args) != 0) - { - ret = find_continuous_scatters_n(); - } - else - { - ret.lastisreserve = true; - } - constexpr ::std::size_t sz{print_reserve_size(::fast_io::io_reserve_type)}; - static_assert(sz != 0); - ++ret.position; - ret.neededscatters = ::fast_io::details::intrinsics::add_or_overflow_die_chain(ret.neededscatters, - static_cast<::std::size_t>(1)); - ret.neededspace = ::fast_io::details::intrinsics::add_or_overflow_die_chain(ret.neededspace, sz); - ret.hasreserve = true; - } - else if constexpr (::fast_io::dynamic_reserve_printable) - { - if constexpr (sizeof...(Args) != 0) - { - ret = find_continuous_scatters_n(); - } - else - { - ret.lastisreserve = true; - } - ++ret.position; - ret.neededscatters = ::fast_io::details::intrinsics::add_or_overflow_die_chain(ret.neededscatters, - static_cast<::std::size_t>(1)); - ret.hasdynamicreserve = true; - } - else if constexpr (::fast_io::reserve_scatters_printable) - { - if constexpr (sizeof...(Args) != 0) - { - ret = find_continuous_scatters_n(); - } - constexpr auto scatszres{print_reserve_scatters_size(::fast_io::io_reserve_type)}; - static_assert(scatszres.scatters_size != 0); - ret.hasscatters = true; - ret.hasreserve = true; - ++ret.position; - ret.neededspace = - ::fast_io::details::intrinsics::add_or_overflow_die_chain(ret.neededspace, scatszres.reserve_size); - ret.neededscatters = - ::fast_io::details::intrinsics::add_or_overflow_die_chain(ret.neededscatters, scatszres.scatters_size); - } - else if constexpr (::std::same_as<::std::remove_cvref_t, ::fast_io::io_null_t>) - { - if constexpr (sizeof...(Args) != 0) - { - ret = find_continuous_scatters_n(); - } - ++ret.position; - ret.null = ::fast_io::details::intrinsics::add_or_overflow_die_chain(ret.null, - static_cast<::std::size_t>(1)); - } - else if constexpr (::fast_io::printable) - { - } - return ret; -} - -struct scatter_rsv_result -{ - ::std::size_t position{}; - ::std::size_t neededspace{}; - ::std::size_t null{}; -}; - -template -inline constexpr scatter_rsv_result find_continuous_scatters_reserve_n() -{ - if constexpr (::fast_io::reserve_printable && !findscatter) - { - constexpr ::std::size_t sz{print_reserve_size(::fast_io::io_reserve_type)}; - if constexpr (sizeof...(Args) == 0) - { - return {1, sz, 0}; - } - else - { - auto res{find_continuous_scatters_reserve_n()}; - return {res.position + 1, ::fast_io::details::intrinsics::add_or_overflow_die_chain(res.neededspace, sz), res.null}; - } - } - else if constexpr (::fast_io::scatter_printable && findscatter) - { - if constexpr (sizeof...(Args) == 0) - { - return {1, 0, 0}; - } - else - { - auto res{find_continuous_scatters_reserve_n()}; - return {res.position + 1, res.neededspace, res.null}; - } - } - else if constexpr (::std::same_as<::std::remove_cvref_t, ::fast_io::io_null_t>) - { - if constexpr (sizeof...(Args) == 0) - { - return {1, 0, ::fast_io::details::intrinsics::add_or_overflow_die_chain(static_cast<::std::size_t>(0), static_cast<::std::size_t>(1))}; - } - else - { - auto res{find_continuous_scatters_reserve_n()}; - return {res.position + 1, res.neededspace, ::fast_io::details::intrinsics::add_or_overflow_die_chain(res.null, static_cast<::std::size_t>(1))}; - } - } - else - { - return {0, 0, 0}; - } -} - -template -inline constexpr bool minimum_buffer_output_stream_require_size_constant_impl = - (N < obuffer_minimum_size_define(::fast_io::io_reserve_type)); - -template -concept minimum_buffer_output_stream_require_size_impl = - ::fast_io::operations::decay::defines::has_obuffer_minimum_size_operations && - minimum_buffer_output_stream_require_size_constant_impl; - -template <::std::size_t sz> - requires(sz != 0) -inline constexpr void scatter_rsv_update_times(::fast_io::io_scatter_t *first, ::fast_io::io_scatter_t *last) noexcept -{ - if constexpr (sz != 1) - { - for (; first != last; ++first) - { - first->len *= sz; - } - } -} - -template <::std::integral char_type> -struct basic_reserve_scatters_define_byte_result -{ - io_scatter_t *scatters_pos_ptr; - char_type *reserve_pos_ptr; -}; - -template <::std::integral char_type, typename T> -inline ::fast_io::details::decay::basic_reserve_scatters_define_byte_result -prrsvsct_byte_common_rsvsc_impl(io_scatter_t *pscatters, char_type *buffer, T t) -{ - using basicioscattertypealiasptr -#if __has_cpp_attribute(__gnu__::__may_alias__) - [[__gnu__::__may_alias__]] -#endif - = basic_io_scatter_t *; - using scatterioscattertypealiasptr -#if __has_cpp_attribute(__gnu__::__may_alias__) - [[__gnu__::__may_alias__]] -#endif - = io_scatter_t *; - auto result{print_reserve_scatters_define(::fast_io::io_reserve_type>, - reinterpret_cast(pscatters), buffer, t)}; - scatterioscattertypealiasptr ptr{reinterpret_cast(result.scatters_pos_ptr)}; - if constexpr (sizeof(char_type) != 1) - { - scatter_rsv_update_times(pscatters, ptr); - } - return {ptr, result.reserve_pos_ptr}; -} - -template <::std::integral char_type, typename T> -inline auto prrsvsct_byte_common_impl(io_scatter_t *pscatters, char_type *buffer, T t) -{ - return ::fast_io::details::decay::prrsvsct_byte_common_rsvsc_impl(pscatters, buffer, t).scatters_pos_ptr; -} - -template - requires(::std::is_trivially_copyable_v && ::std::is_trivially_copyable_v) -inline constexpr void print_control_single(output outstm, T t) -{ - using char_type = typename output::output_char_type; - using value_type = ::std::remove_cvref_t; - constexpr bool asan_activated{::fast_io::details::asan_state::current == ::fast_io::details::asan_state::activate}; - constexpr auto lfch{char_literal_v}; - if constexpr (scatter_printable) - { -#if 0 - basic_io_scatter_t scatter; - if constexpr(::std::same_as>) - { - scatter=t; - } - else - { - scatter=print_scatter_define(::fast_io::io_reserve_type,t); - } - if constexpr(line) - { - if constexpr(contiguous_output_stream) - { - auto curr=obuffer_curr(out); - auto end=obuffer_end(out); - ::std::ptrdiff_t sz(end-curr-1); - ::std::size_t const len{scatter.len}; - if(sz(len)) - fast_terminate(); - curr=non_overlapped_copy_n(scatter.base,scatter.len,curr); - *curr=lfch; - ++curr; - obuffer_set_curr(outstm,curr); - } - else if constexpr(::fast_io::operations::decay::defines::has_obuffer_basic_operations) - { - auto curr=obuffer_curr(out); - auto end=obuffer_end(out); - ::std::size_t const len{scatter.len}; - ::std::ptrdiff_t sz(end-curr-1); - if(static_cast<::std::ptrdiff_t>(len) scatter_res{print_scatter_define(::fast_io::io_reserve_type, t)}; - - if constexpr (line) - { - if constexpr (::fast_io::operations::decay::defines::has_any_of_write_or_seek_pwrite_bytes_operations< - output>) - { - ::fast_io::io_scatter_t scatters[2]{ - {scatter_res.base, scatter_res.len * sizeof(char_type)}, - {__builtin_addressof(char_literal_v), sizeof(char_type)}}; - ::fast_io::operations::decay::scatter_write_all_bytes_decay(outstm, scatters, 2); - } - else - { - ::fast_io::basic_io_scatter_t scatters[2]{ - scatter_res, {__builtin_addressof(char_literal_v), 1}}; - ::fast_io::operations::decay::scatter_write_all_decay(outstm, scatters, 2); - } - } - else - { - ::fast_io::operations::decay::write_all_decay(outstm, scatter_res.base, scatter_res.base + scatter_res.len); - } - } - else if constexpr (reserve_printable) - { - constexpr ::std::size_t real_size{print_reserve_size(::fast_io::io_reserve_type)}; - constexpr ::std::size_t size{real_size + static_cast<::std::size_t>(line)}; - static_assert(real_size < PTRDIFF_MAX); -#if 0 - if constexpr(contiguous_output_stream) - { - auto bcurr{obuffer_curr(outstm)}; - auto bend{obuffer_end(outstm)}; - ::std::size_t diff{static_cast<::std::size_t>(bend-bcurr)}; - if(diff,bcurr,t)}; - if constexpr(line) - { - *it=lfch; - ++it; - } - obuffer_set_curr(outstm,it); - } - else -#endif - { - if constexpr (::fast_io::operations::decay::defines::has_obuffer_basic_operations && - !asan_activated) - { - char_type *bcurr{obuffer_curr(outstm)}; - char_type *bend{obuffer_end(outstm)}; - ::std::ptrdiff_t const diff(bend - bcurr); - bool smaller{static_cast<::std::ptrdiff_t>(size) < diff}; - if constexpr (minimum_buffer_output_stream_require_size_impl) - { - if (!smaller) [[unlikely]] - { - obuffer_minimum_size_flush_prepare_define(outstm); - bcurr = obuffer_curr(outstm); - } - bcurr = print_reserve_define(::fast_io::io_reserve_type, bcurr, t); - if constexpr (line) - { - *bcurr = lfch; - ++bcurr; - } - obuffer_set_curr(outstm, bcurr); - } - else - { - char_type buffer[size]; - if (!smaller) [[unlikely]] - { - bcurr = buffer; - } - bcurr = print_reserve_define(::fast_io::io_reserve_type, bcurr, t); - if constexpr (line) - { - *bcurr = lfch; - ++bcurr; - } - if (smaller) [[likely]] - { - obuffer_set_curr(outstm, bcurr); - } - else [[unlikely]] - { - ::fast_io::operations::decay::write_all_decay(outstm, buffer, bcurr); - } - } - } - else - { - char_type buffer[size]; - char_type *i{print_reserve_define(::fast_io::io_reserve_type, buffer, t)}; - if constexpr (line) - { - *i = lfch; - ++i; - } - ::fast_io::operations::decay::write_all_decay(outstm, buffer, i); - } - } - } - else if constexpr (dynamic_reserve_printable) - { - ::std::size_t size{print_reserve_size(::fast_io::io_reserve_type, t)}; - if constexpr (line) - { - constexpr ::std::size_t mx{::std::numeric_limits<::std::ptrdiff_t>::max() - 1}; - if (size >= mx) - { - fast_terminate(); - } - ++size; - } - else - { - constexpr ::std::size_t mx{::std::numeric_limits<::std::ptrdiff_t>::max()}; - if (mx < size) - { - fast_terminate(); - } - } -#if 0 - if constexpr(contiguous_output_stream) - { - auto bcurr{obuffer_curr(outstm)}; - auto bend{obuffer_end(outstm)}; - auto it{print_reserve_define(::fast_io::io_reserve_type,bcurr,t,size)}; - ::std::size_t diff{static_cast<::std::size_t>(bend-bcurr)}; - if(diff && - !asan_activated) - { - auto curr{obuffer_curr(outstm)}; - auto ed{obuffer_end(outstm)}; - ::std::ptrdiff_t diff(ed - curr); - auto toptr{curr}; - bool smaller{static_cast<::std::ptrdiff_t>(size) < diff}; - ::fast_io::details::local_operator_new_array_ptr newptr; - if (!smaller) -#if __has_cpp_attribute(unlikely) - [[unlikely]] -#endif - { - newptr.ptr = toptr = ::fast_io::details::allocate_iobuf_space< - char_type, - typename ::fast_io::details::local_operator_new_array_ptr::allocator_type>(size); - newptr.size = size; - } - - auto it{print_reserve_define(::fast_io::io_reserve_type, toptr, t)}; - if constexpr (line) - { - *it = lfch; - ++it; - } - if (smaller) - { - obuffer_set_curr(outstm, it); - } - else -#if __has_cpp_attribute(unlikely) - [[unlikely]] -#endif - { - ::fast_io::operations::decay::write_all_decay(outstm, toptr, it); - } - } - else - { - ::fast_io::details::local_operator_new_array_ptr newptr(size); - auto it{print_reserve_define(::fast_io::io_reserve_type, newptr.ptr, t)}; - if constexpr (line) - { - *it = lfch; - ++it; - } - ::fast_io::operations::decay::write_all_decay(outstm, newptr.ptr, it); - } - } - } - else if constexpr (reserve_scatters_printable) - { - constexpr auto sz{print_reserve_scatters_size(::fast_io::io_reserve_type)}; - static_assert(!line || sz.scatters_size != SIZE_MAX); - constexpr ::std::size_t scattersnum{sz.scatters_size + static_cast<::std::size_t>(line)}; -#if __cpp_if_consteval >= 202106L - if !consteval -#else - if (!__builtin_is_constant_evaluated()) -#endif - { - if constexpr (::fast_io::operations::decay::defines::has_any_of_write_or_seek_pwrite_bytes_operations< - output>) - { - ::fast_io::io_scatter_t scattersbuffer[scattersnum]; - char_type buffer[sz.reserve_size]; - ::fast_io::io_scatter_t *ptr{ - ::fast_io::details::decay::prrsvsct_byte_common_impl(scattersbuffer, buffer, t)}; - if constexpr (line) - { - *ptr = ::fast_io::details::decay::line_scatter_common; - ++ptr; - } - ::fast_io::operations::decay::scatter_write_all_bytes_decay(outstm, scattersbuffer, static_cast<::std::size_t>(ptr - scattersbuffer)); - return; - } - } - ::fast_io::basic_io_scatter_t scattersbuffer[scattersnum]; - char_type buffer[sz.reserve_size]; - auto ptr{print_reserve_scatters_define(::fast_io::io_reserve_type>, - scattersbuffer, buffer, t) - .scatters_pos_ptr}; - if constexpr (line) - { - *ptr = ::fast_io::details::decay::line_scatter_common; - ++ptr; - } - ::fast_io::operations::decay::scatter_write_all_decay(outstm, scattersbuffer, static_cast<::std::size_t>(ptr - scattersbuffer)); - } - else if constexpr (::fast_io::transcode_imaginary_printable) - { - // todo? - } - else if constexpr (context_printable) - { - typename ::std::remove_cvref_t))>::type st; - constexpr ::std::size_t reserved_size{32u}; - constexpr ::std::ptrdiff_t reserved_size_no_line{ - static_cast<::std::ptrdiff_t>(reserved_size - static_cast<::std::size_t>(line))}; - if constexpr (::fast_io::operations::decay::defines::has_obuffer_basic_operations) - { - for (;;) - { - auto bcurr{obuffer_curr(outstm)}; - auto bed{obuffer_end(outstm)}; - if (bed <= bcurr) -#if __has_cpp_attribute(unlikely) - [[unlikely]] -#endif - { - if constexpr (minimum_buffer_output_stream_require_size_impl) - { - obuffer_minimum_size_flush_prepare_define(outstm); - bcurr = obuffer_curr(outstm); - bed = obuffer_end(outstm); - } - else - { - ::fast_io::operations::decay::output_stream_buffer_flush_decay(outstm); - bcurr = obuffer_curr(outstm); - bed = obuffer_end(outstm); - if (bed - bcurr < reserved_size_no_line) -#if __has_cpp_attribute(unlikely) - [[unlikely]] -#endif - { - char_type buffer[reserved_size]; - char_type *buffered{buffer + reserved_size_no_line}; - for (;;) - { - auto [resit, done] = st.print_context_define(t, buffer, buffered); - if constexpr (line) - { - if (done) - { - *resit = lfch; - ++resit; - } - ::fast_io::operations::decay::write_all_decay(outstm, buffer, resit); - if (done) - { - return; - } - } - else - { - ::fast_io::operations::decay::write_all_decay(outstm, buffer, resit); - if (done) - { - return; - } - } - } - return; - } - } - } - else - { - auto [resit, done] = st.print_context_define(t, bcurr, bed); - obuffer_set_curr(outstm, resit); - if (done) -#if __has_cpp_attribute(likely) - [[likely]] -#endif - { - if constexpr (line) - { - ::fast_io::operations::decay::char_put_decay(outstm, lfch); - } - return; - } - } - } - } - else - { - char_type buffer[reserved_size]; - char_type *buffered{buffer + reserved_size_no_line}; - for (;;) - { - auto [resit, done] = st.print_context_define(t, buffer, buffered); - if constexpr (line) - { - if (done) - { - *resit = lfch; - ++resit; - } - ::fast_io::operations::decay::write_all_decay(outstm, buffer, resit); - if (done) - { - return; - } - } - else - { - ::fast_io::operations::decay::write_all_decay(outstm, buffer, resit); - if (done) - { - return; - } - } - } - return; - } - } - else if constexpr (printable) - { - print_define(::fast_io::io_reserve_type, outstm, t); - if constexpr (line) - { - ::fast_io::operations::decay::char_put_decay(outstm, lfch); - } - } - else if constexpr (::std::same_as<::std::remove_cvref_t, ::fast_io::io_null_t>) - { - } - else - { - constexpr bool no{printable}; - static_assert(no, "type not printable"); - } -} - -#if 0 -template -inline constexpr char_type* printrsvcontiguousimpl(char_type* iter,Arg arg,Args... args) -{ - if constexpr(sizeof...(Args)!=0) - { - ret = find_continuous_scatters_n(); - } - if constexpr(::fast_io::scatter_printable) - { - return {ret.position+1,ret.neededspace,ret.hasdynamicreserve}; - } - else if constexpr(::fast_io::reserve_printable) - { - constexpr - ::std::size_t sz{print_reserve_size(::fast_io::io_reserve_type)}; - return {ret.position+1, - ::fast_io::details::add_overflow(ret.neededspace,sz), - ret.hasdynamicreserve}; - } - else if constexpr(::fast_io::dynamic_reserve_printable) - { - return {ret.position+1,ret.neededspace,true}; - } -} -#endif - -template -#if __has_cpp_attribute(__gnu__::__always_inline__) -[[__gnu__::__always_inline__]] -#elif __has_cpp_attribute(msvc::forceinline) -[[msvc::forceinline]] -#endif -inline constexpr void print_controls_line(output outstm, T t, Args... args) -{ - if constexpr (sizeof...(Args) == 0) - { - print_control_single(outstm, t); - } - else - { -#if (defined(__OPTIMIZE__) || defined(__OPTIMIZE_SIZE__)) && 0 - print_controls_line_multi_impl(outstm, t, args...); -#else - if constexpr (ln) - { - print_control_single(outstm, t); - print_controls_line(outstm, args...); - } - else - { - print_control_single(outstm, t); - (print_control(outstm, args), ...); - } -#endif - } -} - -template <::std::size_t n, ::std::integral char_type, typename T, typename... Args> -#if __has_cpp_attribute(__gnu__::__always_inline__) -[[__gnu__::__always_inline__]] -#elif __has_cpp_attribute(msvc::forceinline) -[[msvc::forceinline]] -#endif -inline constexpr char_type *print_n_reserve(char_type *ptr, T t, Args... args) -{ - if constexpr (n == 0) - { - return ptr; - } - else - { - if constexpr (::std::same_as<::std::remove_cvref_t, ::fast_io::io_null_t>) - { - if constexpr (sizeof...(Args) == 0 || n < 2) - { - return ptr; - } - else - { - return print_n_reserve(ptr, args...); - } - } - else - { - ptr = print_reserve_define(::fast_io::io_reserve_type>, ptr, t); - if constexpr (sizeof...(Args) == 0 || n < 2) - { - return ptr; - } - else - { - return print_n_reserve(ptr, args...); - } - } - } -} - -template <::std::size_t n, ::std::integral char_type, typename scattertype, typename T, typename... Args> -#if __has_cpp_attribute(__gnu__::__always_inline__) -[[__gnu__::__always_inline__]] -#elif __has_cpp_attribute(msvc::forceinline) -[[msvc::forceinline]] -#endif -inline constexpr void print_n_scatters(basic_io_scatter_t *pscatters, -#if __has_cpp_attribute(maybe_unused) - [[maybe_unused]] -#endif - T t, -#if __has_cpp_attribute(maybe_unused) - [[maybe_unused]] -#endif - Args... args) -{ - if constexpr (n != 0) - { - if constexpr (::std::same_as<::std::remove_cvref_t, ::fast_io::io_null_t>) - { - if constexpr (1 < n) - { - return print_n_scatters(pscatters, args...); - } - } - else if constexpr (::std::same_as<::std::remove_cvref_t, basic_io_scatter_t>) - { - if constexpr (::std::same_as) - { - *pscatters = io_scatter_t{t.base, t.len * sizeof(char_type)}; - } - else - { - *pscatters = t; - } - } - else - { - basic_io_scatter_t sct{print_scatter_define(::fast_io::io_reserve_type, t)}; - if constexpr (::std::same_as) - { - *pscatters = io_scatter_t{sct.base, sct.len * sizeof(char_type)}; - } - else - { - *pscatters = sct; - } - } - if constexpr (1 < n) - { - ++pscatters; - return print_n_scatters(pscatters, args...); - } - } -} - -template <::std::size_t n, ::std::integral char_type, typename T, typename... Args> -#if __has_cpp_attribute(__gnu__::__always_inline__) -[[__gnu__::__always_inline__]] -#elif __has_cpp_attribute(msvc::forceinline) -[[msvc::forceinline]] -#endif -inline constexpr ::std::size_t ndynamic_print_reserve_size(T t, Args... args) -{ - using nocvreft = ::std::remove_cvref_t; - if constexpr (n == 0) - { - return 0; - } - else if constexpr (n == 1) - { - if constexpr (::fast_io::dynamic_reserve_printable) - { - return print_reserve_size(::fast_io::io_reserve_type, t); - } - else - { - return 0; - } - } - else - { - if constexpr (::fast_io::dynamic_reserve_printable) - { - return ::fast_io::details::intrinsics::add_or_overflow_die( - print_reserve_size(::fast_io::io_reserve_type, t), - ::fast_io::details::decay::ndynamic_print_reserve_size(args...)); - } - else - { - return ::fast_io::details::decay::ndynamic_print_reserve_size(args...); - } - } -} - -template -#if __has_cpp_attribute(__gnu__::__always_inline__) -[[__gnu__::__always_inline__]] -#elif __has_cpp_attribute(msvc::forceinline) -[[msvc::forceinline]] -#endif -inline constexpr auto print_n_scatters_reserve(basic_io_scatter_t *pscatters, char_type *ptr, T t, - Args... args); - -template <::std::integral char_type, typename T, typename... Args> -inline constexpr bool print_next_is_reserve() noexcept -{ - using nocvreft = ::std::remove_cvref_t; - if constexpr (::fast_io::reserve_printable || - ::fast_io::dynamic_reserve_printable) - { - return true; - } - else - { - return false; - } -} - -template <::std::integral char_type> -inline constexpr bool print_next_is_reserve() noexcept -{ - return false; -} - -template -#if __has_cpp_attribute(__gnu__::__always_inline__) -[[__gnu__::__always_inline__]] -#elif __has_cpp_attribute(msvc::forceinline) -[[msvc::forceinline]] -#endif -inline constexpr auto print_n_scatters_reserve_cont(basic_io_scatter_t *pscatters, char_type *base, - char_type *ptr, T t, Args... args) -{ - if constexpr (n != 0) - { - using nocvreft = ::std::remove_cvref_t; - if constexpr (reserve_printable || dynamic_reserve_printable) - { - ptr = print_reserve_define(::fast_io::io_reserve_type, ptr, t); - if constexpr (::fast_io::details::decay::print_next_is_reserve()) - { - return ::fast_io::details::decay::print_n_scatters_reserve_cont( - pscatters, base, ptr, args...); - } - else - { - if constexpr (n == 1 && needprintlf) - { - *ptr = char_literal_v; - ++ptr; - } - ::std::size_t const sz{static_cast<::std::size_t>(ptr - base)}; - if constexpr (::std::same_as) - { - *pscatters = io_scatter_t{base, sz * sizeof(char_type)}; - } - else - { - *pscatters = basic_io_scatter_t{base, sz}; - } - ++pscatters; - if constexpr (1 < n) - { - return ::fast_io::details::decay::print_n_scatters_reserve( - pscatters, ptr, args...); - } - } - } - else - { - ::std::size_t const sz{static_cast<::std::size_t>(ptr - base)}; - if constexpr (::std::same_as) - { - *pscatters = io_scatter_t{base, sz * sizeof(char_type)}; - } - else - { - *pscatters = basic_io_scatter_t{base, sz}; - } - ++pscatters; - if constexpr (1 < n) - { - return ::fast_io::details::decay::print_n_scatters_reserve( - pscatters, ptr, t, args...); - } - } - } - return pscatters; -} - -template -#if __has_cpp_attribute(__gnu__::__always_inline__) -[[__gnu__::__always_inline__]] -#elif __has_cpp_attribute(msvc::forceinline) -[[msvc::forceinline]] -#endif -inline constexpr auto print_n_scatters_reserve(basic_io_scatter_t *pscatters, char_type *ptr, T t, - Args... args) -{ - if constexpr (n != 0) - { - using nocvreft = ::std::remove_cvref_t; - if constexpr (::fast_io::reserve_printable || - ::fast_io::dynamic_reserve_printable) - { - auto ptred{print_reserve_define(::fast_io::io_reserve_type, ptr, t)}; - if constexpr (sizeof...(Args) != 0 && - ::fast_io::details::decay::print_next_is_reserve()) - { - return ::fast_io::details::decay::print_n_scatters_reserve_cont( - pscatters, ptr, ptred, args...); - } - else - { - if constexpr (n == 1 && needprintlf) - { - *ptred = char_literal_v; - ++ptred; - } - ::std::size_t const sz{static_cast<::std::size_t>(ptred - ptr)}; - if constexpr (::std::same_as) - { - *pscatters = io_scatter_t{ptr, sz * sizeof(char_type)}; - } - else - { - *pscatters = basic_io_scatter_t{ptr, sz}; - } - ++pscatters; - if constexpr (1 < n) - { - return ::fast_io::details::decay::print_n_scatters_reserve( - pscatters, ptred, args...); - } - } - } - else if constexpr (::fast_io::scatter_printable) - { - if constexpr (::std::same_as>) - { - if constexpr (::std::same_as) - { - *pscatters = io_scatter_t{t.base, t.len * sizeof(char_type)}; - } - else - { - *pscatters = t; - } - } - else - { - basic_io_scatter_t sct{print_scatter_define(::fast_io::io_reserve_type, t)}; - if constexpr (::std::same_as) - { - *pscatters = io_scatter_t{sct.base, sct.len * sizeof(char_type)}; - } - else - { - *pscatters = sct; - } - } - ++pscatters; - if constexpr (n == 1 && needprintlf) - { - *pscatters = ::fast_io::details::decay::line_scatter_common; - ++pscatters; - } - if constexpr (1 < n) - { - return ::fast_io::details::decay::print_n_scatters_reserve(pscatters, - ptr, args...); - } - } - else if constexpr (::fast_io::reserve_scatters_printable) - { - if constexpr (::std::same_as) - { - auto pit{::fast_io::details::decay::prrsvsct_byte_common_rsvsc_impl(pscatters, ptr, t)}; - if constexpr (1 < n) - { - return ::fast_io::details::decay::print_n_scatters_reserve( - pit.scatters_pos_ptr, pit.reserve_pos_ptr, args...); - } - else if constexpr (n == 1 && needprintlf) - { - *pit.scatters_pos_ptr = ::fast_io::details::decay::line_scatter_common; - ++pit.scatters_pos_ptr; - } - return pit.scatters_pos_ptr; - } - else - { - auto pit{ - print_reserve_scatters_define(::fast_io::io_reserve_type, pscatters, ptr, t)}; - if constexpr (1 < n) - { - return ::fast_io::details::decay::print_n_scatters_reserve( - pit.scatters_pos_ptr, pit.reserve_pos_ptr, args...); - } - else if constexpr (n == 1 && needprintlf) - { - *pit = ::fast_io::details::decay::line_scatter_common; - ++pit; - } - return pit; - } - } - else if constexpr (::std::same_as) - { - if constexpr (n == 1 && needprintlf) - { - *pscatters = ::fast_io::details::decay::line_scatter_common; - ++pscatters; - } - if constexpr (1 < n) - { - return ::fast_io::details::decay::print_n_scatters_reserve(pscatters, - ptr, args...); - } - } - } - return pscatters; -} - -template -inline constexpr void print_controls_impl(outputstmtype optstm, T t, Args... args) -{ - using char_type = typename outputstmtype::output_char_type; - using scatter_type = ::std::conditional_t< - ::fast_io::operations::decay::defines::has_any_of_write_or_seek_pwrite_bytes_operations, - io_scatter_t, basic_io_scatter_t>; - constexpr contiguous_scatter_result res{ - ::fast_io::details::decay::find_continuous_scatters_n()}; - if constexpr (skippings != 0) - { - print_controls_impl(optstm, args...); - } - else if constexpr (sizeof...(Args) == 0) - { - print_control_single(optstm, t); - } - else if constexpr (res.position == 0) - { - print_control_single(optstm, t); - print_controls_impl(optstm, args...); - } - else - { - if constexpr (line) - { - static_assert(res.neededscatters != SIZE_MAX); - } - static_assert(SIZE_MAX != sizeof...(Args)); - constexpr ::std::size_t n{sizeof...(Args) + static_cast<::std::size_t>(1)}; - constexpr bool needprintlf{n == res.position && line}; - if constexpr (res.hasscatters && !res.hasreserve && !res.hasdynamicreserve) - { - constexpr ::std::size_t scatterscount{res.neededscatters + static_cast<::std::size_t>(needprintlf)}; - { - scatter_type scatters[scatterscount]; - ::fast_io::details::decay::print_n_scatters(scatters, t, args...); - if constexpr (needprintlf) - { - scatters[scatterscount - 1] = ::fast_io::details::decay::line_scatter_common< - char_type, ::std::conditional_t<::std::same_as, void, char_type>>; - } - if constexpr (::fast_io::operations::decay::defines::has_any_of_write_or_seek_pwrite_bytes_operations< - outputstmtype>) - { - ::fast_io::operations::decay::scatter_write_all_bytes_decay(optstm, scatters, scatterscount); - } - else - { - ::fast_io::operations::decay::scatter_write_all_decay(optstm, scatters, scatterscount); - } - } - if constexpr (res.position != n) - { - print_controls_impl(optstm, args...); - } - } - else - { - constexpr ::std::size_t mxsize{ - static_cast<::std::size_t>(res.neededspace + static_cast<::std::size_t>(needprintlf))}; - if constexpr (!res.hasscatters) - { - static_assert(!needprintlf || res.neededspace != SIZE_MAX); - if constexpr (res.hasdynamicreserve) - { - ::std::size_t dynsz{ - ::fast_io::details::decay::ndynamic_print_reserve_size(t, args...)}; - ::std::size_t totalsz{::fast_io::details::intrinsics::add_or_overflow_die(mxsize, dynsz)}; - ::fast_io::details::local_operator_new_array_ptr newptr(totalsz); - char_type *buffer{newptr.ptr}; - char_type *ptred{ - ::fast_io::details::decay::print_n_reserve(buffer, t, args...)}; - if constexpr (needprintlf) - { - *ptred = ::fast_io::char_literal_v; - ++ptred; - } - ::fast_io::operations::decay::write_all_decay(optstm, buffer, ptred); - } - else if constexpr (res.hasreserve) - { - if constexpr (res.neededspace == 0) - { - if constexpr (needprintlf) - { - ::fast_io::operations::decay::char_put_decay(optstm, - ::fast_io::char_literal_v); - } - } - else - { - char_type buffer[mxsize]; - char_type *ptred{ - ::fast_io::details::decay::print_n_reserve(buffer, t, args...)}; - if constexpr (needprintlf) - { - *ptred = ::fast_io::char_literal_v; - ++ptred; - } - ::fast_io::operations::decay::write_all_decay(optstm, buffer, ptred); - } - } - } - else if constexpr (res.hasreserve && !res.hasdynamicreserve) - { - constexpr ::std::size_t scatterscount{res.neededscatters + - static_cast<::std::size_t>(line && res.position == n)}; - scatter_type scatters[scatterscount]; - char_type buffer[mxsize]; - - auto ptr{::fast_io::details::decay::print_n_scatters_reserve( - scatters, buffer, t, args...)}; - ::std::size_t diff{static_cast<::std::size_t>(ptr - scatters)}; - - if constexpr (::fast_io::operations::decay::defines::has_any_of_write_or_seek_pwrite_bytes_operations< - outputstmtype>) - { - ::fast_io::operations::decay::scatter_write_all_bytes_decay(optstm, scatters, diff); - } - else - { - ::fast_io::operations::decay::scatter_write_all_decay(optstm, scatters, diff); - } - } - else if constexpr (res.hasdynamicreserve) - { - constexpr ::std::size_t scatterscount{res.neededscatters + - static_cast<::std::size_t>(line && res.position == n)}; - ::std::size_t dynsz{ - ::fast_io::details::decay::ndynamic_print_reserve_size(t, args...)}; - ::std::size_t totalsz{::fast_io::details::intrinsics::add_or_overflow_die(mxsize, dynsz)}; - ::fast_io::details::local_operator_new_array_ptr newptr(totalsz); - scatter_type scatters[scatterscount]; - char_type *buffer{newptr.ptr}; - auto ptr{::fast_io::details::decay::print_n_scatters_reserve( - scatters, buffer, t, args...)}; - ::std::size_t diff{static_cast<::std::size_t>(ptr - scatters)}; - if constexpr (::fast_io::operations::decay::defines::has_any_of_write_or_seek_pwrite_bytes_operations< - outputstmtype>) - { - ::fast_io::operations::decay::scatter_write_all_bytes_decay(optstm, scatters, diff); - } - else - { - ::fast_io::operations::decay::scatter_write_all_decay(optstm, scatters, diff); - } - } - if constexpr (res.position != n) - { - print_controls_impl(optstm, args...); - } - } - } -} - -template -inline constexpr void print_controls_buffer_impl(outputstmtype optstm, T t, Args... args) -{ - if constexpr (skippings != 0) - { - ::fast_io::details::decay::print_controls_buffer_impl(optstm, args...); - } - else if constexpr (sizeof...(Args) == 0) - { - print_control_single(optstm, t); - } - else - { - using char_type = typename outputstmtype::output_char_type; - static_assert(SIZE_MAX != sizeof...(Args)); - constexpr ::std::size_t n{sizeof...(Args) + static_cast<::std::size_t>(1)}; - constexpr auto scatters_result{ - ::fast_io::details::decay::find_continuous_scatters_reserve_n()}; - using scatter_type = ::std::conditional_t< - ::fast_io::operations::decay::defines::has_any_of_write_or_seek_pwrite_bytes_operations, - io_scatter_t, basic_io_scatter_t>; - if constexpr (scatters_result.position != 0) - { - if constexpr (line) - { - static_assert(scatters_result.position != SIZE_MAX); - } - constexpr bool needprintlf{n == scatters_result.position && line}; - constexpr ::std::size_t scatterscount{scatters_result.position - scatters_result.null + static_cast<::std::size_t>(needprintlf)}; - scatter_type scatters[scatterscount]; - ::fast_io::details::decay::print_n_scatters(scatters, t, args...); - if constexpr (::fast_io::operations::decay::defines::has_any_of_write_or_seek_pwrite_bytes_operations< - outputstmtype>) - { - if constexpr (needprintlf) - { - scatters[scatterscount - 1] = ::fast_io::details::decay::line_scatter_common; - } - ::fast_io::operations::decay::scatter_write_all_bytes_decay(optstm, scatters, scatterscount); - } - else - { - if constexpr (needprintlf) - { - scatters[scatterscount - 1] = ::fast_io::details::decay::line_scatter_common; - } - ::fast_io::operations::decay::scatter_write_all_decay(optstm, scatters, scatterscount); - } - if constexpr (scatters_result.position != n) - { - ::fast_io::details::decay::print_controls_buffer_impl(optstm, args...); - } - } - else - { - constexpr auto rsvresult{ - ::fast_io::details::decay::find_continuous_scatters_reserve_n()}; - if constexpr (1 < rsvresult.position) - { - constexpr bool needprintlf{n == rsvresult.position && line}; - constexpr ::std::size_t buffersize{rsvresult.neededspace + static_cast<::std::size_t>(needprintlf)}; - char_type *bcurr{obuffer_curr(optstm)}; - char_type *bend{obuffer_end(optstm)}; - ::std::ptrdiff_t const diff(bend - bcurr); - bool smaller{static_cast<::std::ptrdiff_t>(buffersize) < diff}; - if constexpr (minimum_buffer_output_stream_require_size_impl) - { - if (!smaller) [[unlikely]] - { - obuffer_minimum_size_flush_prepare_define(optstm); - bcurr = obuffer_curr(optstm); - } - bcurr = - ::fast_io::details::decay::print_n_reserve(bcurr, t, args...); - if constexpr (needprintlf) - { - *bcurr = ::fast_io::char_literal_v; - ++bcurr; - } - obuffer_set_curr(optstm, bcurr); - } - else - { - char_type buffer[buffersize]; - if (!smaller) [[unlikely]] - { - bcurr = buffer; - } - bcurr = - ::fast_io::details::decay::print_n_reserve(bcurr, t, args...); - if constexpr (needprintlf) - { - *bcurr = ::fast_io::char_literal_v; - ++bcurr; - } - if (smaller) [[likely]] - { - obuffer_set_curr(optstm, bcurr); - } - else [[unlikely]] - { - ::fast_io::operations::decay::write_all_decay(optstm, buffer, bcurr); - } - } - if constexpr (rsvresult.position != n) - { - ::fast_io::details::decay::print_controls_buffer_impl( - optstm, args...); - } - } - else - { - ::fast_io::details::decay::print_control_single(optstm, t); - if constexpr (sizeof...(args) != 0) - { - ::fast_io::details::decay::print_controls_buffer_impl(optstm, args...); - } - } - } - } -} - -} // namespace details::decay - -namespace operations -{ - -namespace decay -{ - -template -inline constexpr decltype(auto) print_freestanding_decay(outputstmtype optstm, Args... args) -{ - if constexpr (::fast_io::operations::decay::defines::has_status_print_define) - { - return status_print_define(optstm, args...); - } - else if constexpr (sizeof...(Args) == 0) - { - if constexpr (line) - { - using char_type = typename outputstmtype::output_char_type; - return ::fast_io::operations::decay::char_put_decay(optstm, char_literal_v); - } - else - { - return; - } - } - else if constexpr (::fast_io::operations::decay::defines::has_output_or_io_stream_mutex_ref_define) - { - ::fast_io::operations::decay::stream_ref_decay_lock_guard lg{ - ::fast_io::operations::decay::output_stream_mutex_ref_decay(optstm)}; - return ::fast_io::operations::decay::print_freestanding_decay( - ::fast_io::operations::decay::output_stream_unlocked_ref_decay(optstm), args...); - } - else if constexpr (::fast_io::operations::decay::defines::has_obuffer_basic_operations) - { - return ::fast_io::details::decay::print_controls_buffer_impl(optstm, args...); - } - else - { - return ::fast_io::details::decay::print_controls_impl(optstm, args...); - } -} - -template -#if __has_cpp_attribute(__gnu__::__cold__) -[[__gnu__::__cold__]] -#endif -inline constexpr decltype(auto) print_freestanding_decay_cold(outputstmtype optstm, Args... args) -{ -#if !__has_cpp_attribute(__gnu__::__cold__) && __has_cpp_attribute(unlikely) - if (true) [[unlikely]] -#endif - return ::fast_io::operations::decay::print_freestanding_decay(optstm, args...); -} - -} // namespace decay - -namespace decay::defines -{ - -template -concept print_freestanding_params_okay = - ::std::integral && - ((::fast_io::printable || ::fast_io::reserve_printable || - ::fast_io::dynamic_reserve_printable || ::fast_io::scatter_printable || - ::fast_io::reserve_scatters_printable || ::fast_io::context_printable || - ::fast_io::transcode_imaginary_printable || ::std::same_as<::std::remove_cvref_t, ::fast_io::io_null_t>) && - ...); - -template -concept print_freestanding_okay = - ::fast_io::operations::decay::defines::print_freestanding_params_okay; - -} // namespace decay::defines - -namespace defines -{ - -template -concept print_freestanding_params_okay = ::fast_io::operations::decay::defines::print_freestanding_params_okay(::fast_io::io_print_alias(::std::declval())))...>; - -template -concept print_freestanding_okay = ::fast_io::operations::decay::defines::print_freestanding_okay< - decltype(::fast_io::operations::output_stream_ref(::std::declval())), - decltype(::fast_io::io_print_forward()))::output_char_type>(::fast_io::io_print_alias(::std::declval())))...>; - -} // namespace defines - -template -#if __has_cpp_attribute(__gnu__::__always_inline__) -[[__gnu__::__always_inline__]] -#elif __has_cpp_attribute(msvc::forceinline) -[[msvc::forceinline]] -#endif -inline constexpr void print_freestanding(output &&outstm, Args &&...args) -{ - ::fast_io::operations::decay::print_freestanding_decay( - ::fast_io::operations::output_stream_ref(outstm), - io_print_forward( - io_print_alias(args))...); -} - -} // namespace operations - -} // namespace fast_io From 275ef8b361c6a58792581ea3f5bc64f37368a0a3 Mon Sep 17 00:00:00 2001 From: MacroModel Date: Sun, 15 Jun 2025 19:23:34 +0800 Subject: [PATCH 3/3] fix --- include/fast_io_core_impl/codecvt/general.h | 18 +++++++-------- include/fast_io_core_impl/literals/literal.h | 22 ++++++++++++++----- .../operations/printimpl/impl.h | 2 +- include/fast_io_core_impl/simd/gcc_clang.h | 2 +- include/fast_io_core_impl/simd/generic.h | 2 +- include/fast_io_core_impl/simd/is_all_zeros.h | 13 ++++++++--- include/fast_io_driver/tsc_timer.h | 4 +++- include/fast_io_hosted/platforms/nt/nt_path.h | 2 +- 8 files changed, 42 insertions(+), 23 deletions(-) diff --git a/include/fast_io_core_impl/codecvt/general.h b/include/fast_io_core_impl/codecvt/general.h index 2dbd4af8f..f554c77e9 100644 --- a/include/fast_io_core_impl/codecvt/general.h +++ b/include/fast_io_core_impl/codecvt/general.h @@ -184,7 +184,7 @@ general_code_cvt(src_char_type const *src_first, src_char_type const *src_last, } else { - dst += get_utf_code_units(code, dst); + dst += get_utf_code_units(static_cast(code), dst); } } } @@ -221,7 +221,7 @@ general_code_cvt(src_char_type const *src_first, src_char_type const *src_last, } else { - dst += get_utf_code_units(code, dst); + dst += get_utf_code_units(static_cast(code), dst); } } else @@ -235,7 +235,7 @@ general_code_cvt(src_char_type const *src_first, src_char_type const *src_last, } else { - dst += get_utf_code_units(code, dst); + dst += get_utf_code_units(static_cast(code), dst); } } } @@ -265,7 +265,7 @@ general_code_cvt(src_char_type const *src_first, src_char_type const *src_last, } else { - dst += get_utf_code_units(code, dst); + dst += get_utf_code_units(static_cast(code), dst); } } else @@ -278,7 +278,7 @@ general_code_cvt(src_char_type const *src_first, src_char_type const *src_last, } else { - *dst = static_cast(*src_first); + *dst = static_cast(static_cast(*src_first)); } if constexpr (sizeof(dest_char_type) != 1 && encoding_is_utf(encoding) && !is_native_scheme(encoding)) @@ -309,7 +309,7 @@ general_code_cvt(src_char_type const *src_first, src_char_type const *src_last, } else { - dst += get_utf_code_units(code, dst); + dst += get_utf_code_units(static_cast(code), dst); } } else @@ -331,7 +331,7 @@ general_code_cvt(src_char_type const *src_first, src_char_type const *src_last, } else { - dst += get_utf_code_units(code, dst); + dst += get_utf_code_units(static_cast(code), dst); } } } @@ -468,7 +468,7 @@ inline constexpr dest_char_type *general_code_cvt(state_type &__restrict state, } else { - dst += get_utf_code_units(code, dst); + dst += get_utf_code_units(static_cast(code), dst); } src_first += static_cast<::std::size_t>(bytes_src - bytes - state_size); } @@ -492,7 +492,7 @@ inline constexpr dest_char_type *general_code_cvt(state_type &__restrict state, } else { - dst += get_utf_code_units(code, dst); + dst += get_utf_code_units(static_cast(code), dst); } src_first += static_cast<::std::size_t>(static_cast<::std::size_t>(adv) - state_size); } diff --git a/include/fast_io_core_impl/literals/literal.h b/include/fast_io_core_impl/literals/literal.h index 4ac8a837b..7e1c7b8fc 100644 --- a/include/fast_io_core_impl/literals/literal.h +++ b/include/fast_io_core_impl/literals/literal.h @@ -73,6 +73,12 @@ inline constexpr ch_type arithmetic_char_literal(char8_t ch) noexcept } } +template <::std::integral ch_type> +inline constexpr auto integral_lifting(ch_type c) noexcept +{ + return static_cast(c); +} + template inline constexpr ch_type arithmetic_char_literal_v{arithmetic_char_literal(ch)}; @@ -85,22 +91,26 @@ inline constexpr char_type char_literal_add(T offs) noexcept [[assume(0 <= offs && offs < 10)]]; } #endif - using unsigned_char_type = ::std::make_unsigned_t; - using unsigned_result_type = - ::std::make_unsigned_t<::std::remove_cvref_t + offs)>>; - if constexpr (::std::same_as && ::fast_io::details::wide_is_none_utf_endian) + // The future cpp standard prohibits arithmetic between different char_types, but allows the same char_type to be arithmetic, so doing an integral_lifting + // and then calculating gives the same result as direct arithmetic + + using unsigned_char_type = ::std::make_unsigned_t; + using unsigned_result_type = ::std::make_unsigned_t< + ::std::remove_cvref_t) + integral_lifting(offs))>>; + + if constexpr (::std::same_as && ::fast_io::details::wide_is_none_utf_endian) { static_assert(::std::numeric_limits<::std::uint_least8_t>::digits <= ::std::numeric_limits::digits); constexpr unsigned leftshift_offset{static_cast(::std::numeric_limits::digits - ::std::numeric_limits<::std::uint_least8_t>::digits)}; return static_cast(static_cast(static_cast( - arithmetic_char_literal_v + offs)) + integral_lifting(arithmetic_char_literal_v) + integral_lifting(offs))) << leftshift_offset); } else { return static_cast(static_cast( - static_cast(arithmetic_char_literal_v + offs))); + static_cast(integral_lifting(arithmetic_char_literal_v) + integral_lifting(offs)))); } } diff --git a/include/fast_io_core_impl/operations/printimpl/impl.h b/include/fast_io_core_impl/operations/printimpl/impl.h index 89ebababc..997a58a4b 100644 --- a/include/fast_io_core_impl/operations/printimpl/impl.h +++ b/include/fast_io_core_impl/operations/printimpl/impl.h @@ -1,3 +1,3 @@ -#pragma once +#pragma once #include "print_freestanding_cxx20.h" \ No newline at end of file diff --git a/include/fast_io_core_impl/simd/gcc_clang.h b/include/fast_io_core_impl/simd/gcc_clang.h index 934e49de8..b3344c0bc 100644 --- a/include/fast_io_core_impl/simd/gcc_clang.h +++ b/include/fast_io_core_impl/simd/gcc_clang.h @@ -59,7 +59,7 @@ struct simd_vector #if __has_cpp_attribute(__gnu__::__always_inline__) [[__gnu__::__always_inline__]] #endif - inline void store(void *address) noexcept + inline void store(void *address) const noexcept { __builtin_memcpy(address, __builtin_addressof(value), sizeof(value)); } diff --git a/include/fast_io_core_impl/simd/generic.h b/include/fast_io_core_impl/simd/generic.h index c2931e025..96f5e09ee 100644 --- a/include/fast_io_core_impl/simd/generic.h +++ b/include/fast_io_core_impl/simd/generic.h @@ -49,7 +49,7 @@ struct #if __has_cpp_attribute(__gnu__::__always_inline__) [[__gnu__::__always_inline__]] #endif - inline void store(void *address) noexcept + inline void store(void *address) const noexcept { #if FAST_IO_HAS_BUILTIN(__builtin_memcpy) __builtin_memcpy(address, __builtin_addressof(value), sizeof(value)); diff --git a/include/fast_io_core_impl/simd/is_all_zeros.h b/include/fast_io_core_impl/simd/is_all_zeros.h index 35ebcaab6..92a0119a1 100644 --- a/include/fast_io_core_impl/simd/is_all_zeros.h +++ b/include/fast_io_core_impl/simd/is_all_zeros.h @@ -176,17 +176,24 @@ inline #if defined(__AVX512BW__) && defined(__x86_64__) && __has_builtin(__builtin_ia32_ptestmb512) using x86_64_v64qi [[__gnu__::__vector_size__(64)]] = char; #if __has_builtin(__builtin_bit_cast) - return __builtin_ia32_ptestmb512(__builtin_bit_cast(x86_64_v64qi, vec), + return !__builtin_ia32_ptestmb512(__builtin_bit_cast(x86_64_v64qi, vec), __builtin_bit_cast(x86_64_v64qi, vec), UINT_LEAST64_MAX); #else - return __builtin_ia32_ptestmb512((x86_64_v64qi)vec.value, (x86_64_v64qi)vec.value, UINT_LEAST64_MAX); + return !__builtin_ia32_ptestmb512((x86_64_v64qi)vec.value, (x86_64_v64qi)vec.value, UINT_LEAST64_MAX); +#endif +#elif defined(__AVX512BW__) && defined(__x86_64__) && __has_builtin(__builtin_ia32_cmpb512_mask) + using x86_64_v64qi [[__gnu__::__vector_size__(64)]] = char; +#if __has_builtin(__builtin_bit_cast) + return !__builtin_ia32_cmpb512_mask(__builtin_bit_cast(x86_64_v64qi, vec), x86_64_v64qi{}, 0x04, UINT_LEAST64_MAX); +#else + return !__builtin_ia32_cmpb512_mask((x86_64_v64qi)vec.value, x86_64_v64qi{}, 0x04, UINT_LEAST64_MAX); #endif #endif #elif (defined(__x86_64__) || defined(_M_AMD64) || defined(__i386__) || defined(_M_IX86)) if constexpr (::fast_io::details::cpu_flags::avx512bw_supported) { __m512i a = __builtin_bit_cast(__m512i, vec); - return _mm512_test_epi8_mask(a, a); + return !_mm512_test_epi8_mask(a, a); } #endif } diff --git a/include/fast_io_driver/tsc_timer.h b/include/fast_io_driver/tsc_timer.h index 233adbb08..14809911c 100644 --- a/include/fast_io_driver/tsc_timer.h +++ b/include/fast_io_driver/tsc_timer.h @@ -7,8 +7,10 @@ inline ::std::uint_least64_t current_tsc() noexcept { #if defined(_MSC_VER) && !defined(__clang__) return __rdtsc(); -#elif FAST_IO_HAS_BUILTIN(__builtin_ia32_rdtsc) +#elif defined(__has_builtin) +#if __has_builtin(__builtin_ia32_rdtsc) return __builtin_ia32_rdtsc(); +#endif #else return 0; #endif diff --git a/include/fast_io_hosted/platforms/nt/nt_path.h b/include/fast_io_hosted/platforms/nt/nt_path.h index 352c5f9e4..f7da26c71 100644 --- a/include/fast_io_hosted/platforms/nt/nt_path.h +++ b/include/fast_io_hosted/platforms/nt/nt_path.h @@ -37,7 +37,7 @@ inline void nt_file_rtl_path(char16_t const *filename, win32::nt::unicode_string { /* https://github.com/mirror/reactos/blob/master/reactos/dll/ntdll/def/ntdll.spec -ReactOS shows that RtlDosPathNameToNtPathName_U_WithStatus was added since Windows XP SP2. +ReactOS shows that RtlDosPathNameToNtPathName_U_WithStatus was added since Windows XP 64bit. */ #if !defined(_WIN32_WINNT) || _WIN32_WINNT >= 0x0502 auto status{rtl_dos_path_name_to_nt_path_name_u_with_status(