From 28b74b405680ab0a120afce84623f156d289ad86 Mon Sep 17 00:00:00 2001 From: catalinvasile Date: Wed, 10 Jul 2024 13:31:12 +0200 Subject: [PATCH] Using PathView to pass paths to APIs --- CMakeLists.txt | 2 +- include/fs/AbsPath.h | 12 +- include/fs/AbsPath.inl | 10 +- include/fs/CRCStream.h | 4 +- include/fs/CopyStream.h | 6 +- include/fs/CustomFilesystem.h | 50 +- include/fs/FileMapSink.h | 2 +- include/fs/FileMapSource.h | 4 +- include/fs/FileSink.h | 2 +- include/fs/FileSource.h | 4 +- include/fs/FolderPack.h | 26 +- include/fs/IFilesystem.h | 44 +- include/fs/IPack.h | 20 +- include/fs/IWritablePack.h | 16 +- include/fs/NativeFilesystem.h | 48 +- include/fs/NativeUtils.h | 4 +- include/fs/ReadStream.h | 6 +- include/fs/WritableFolderPack.h | 20 +- include/fs/zip/DeflateFileWriter.h | 4 +- include/fs/zip/StoreFileWriter.h | 4 +- include/fs/zip/ZipPack.h | 26 +- include/fs/zip/ZipUtils.h | 8 +- src/CRCStream.cpp | 4 +- src/CopyStream.cpp | 6 +- src/CustomFilesystem.cpp | 73 +- src/FileMapSink.cpp | 2 +- src/FileMapSource.cpp | 4 +- src/FileSink.cpp | 2 +- src/FileSource.cpp | 8 +- src/FolderPack.cpp | 26 +- src/NativeFilesystem.cpp | 60 +- src/NativeUtils.cpp | 14 +- src/ReadStream.cpp | 6 +- src/WritableFolderPack.cpp | 20 +- src/fast_io/.editorconfig | 4 + src/fast_io/.git-blame-ignore-revs | 7 + src/fast_io/.gitignore | 15 + src/fast_io/include/fast_io.h | 562 +++ src/fast_io/include/fast_io_concept.h | 30 + src/fast_io/include/fast_io_core.h | 124 + src/fast_io/include/fast_io_core_impl/alias.h | 71 + .../fast_io_core_impl/allocation/adapters.h | 1991 ++++++++ .../allocation/allocator_adapter_flags.h | 47 + .../fast_io_core_impl/allocation/c_malloc.h | 253 + .../fast_io_core_impl/allocation/common.h | 17 + .../fast_io_core_impl/allocation/custom.h | 14 + .../allocation/has_methods_detect.h | 289 ++ .../fast_io_core_impl/allocation/impl.h | 76 + .../allocation/linux_kernel.h | 71 + .../allocation/mimalloc_driver.h | 159 + .../fast_io_core_impl/allocation/msvc/impl.h | 9 + .../allocation/msvc/msvc_linker_32.h | 15 + .../allocation/msvc/msvc_linker_32_i686.h | 15 + .../allocation/msvc/msvc_linker_64.h | 15 + .../allocation/nt_rtlheapalloc.h | 354 ++ .../allocation/win32_heapalloc.h | 275 ++ .../allocation/wincrt_malloc_dbg.h | 96 + .../include/fast_io_core_impl/asan_support.h | 28 + .../include/fast_io_core_impl/black_hole.h | 28 + .../include/fast_io_core_impl/buffer_view.h | 195 + .../include/fast_io_core_impl/char_category.h | 500 ++ .../fast_io_core_impl/codecvt/code_cvt.h | 54 + .../fast_io_core_impl/codecvt/gb18030.h | 46 + .../fast_io_core_impl/codecvt/general.h | 569 +++ .../include/fast_io_core_impl/codecvt/impl.h | 27 + .../include/fast_io_core_impl/codecvt/utf.h | 632 +++ .../fast_io_core_impl/codecvt/utf_ebcdic.h | 112 + .../codecvt/utf_util_table.h | 10 + .../include/fast_io_core_impl/compare.h | 51 + .../fast_io_core_impl/concat/concat_buffer.h | 102 + .../fast_io_core_impl/concat/concat_general.h | 312 ++ .../include/fast_io_core_impl/concat/impl.h | 4 + .../concat/strlike_reference_wrapper.h | 189 + .../fast_io_core_impl/concepts/decorator.h | 50 + .../fast_io_core_impl/concepts/details.h | 258 + .../include/fast_io_core_impl/concepts/impl.h | 10 + .../fast_io_core_impl/concepts/operation.h | 195 + .../concepts/operation_details.h | 158 + .../fast_io_core_impl/concepts/parse_code.h | 24 + .../fast_io_core_impl/concepts/stream.h | 172 + .../fast_io_core_impl/concepts/strlike.h | 81 + .../include/fast_io_core_impl/concepts/type.h | 91 + .../include/fast_io_core_impl/dll_mode.h | 62 + src/fast_io/include/fast_io_core_impl/drain.h | 21 + .../fast_io_core_impl/dynamic_io_buffer.h | 166 + .../include/fast_io_core_impl/ebcdic.h | 59 + src/fast_io/include/fast_io_core_impl/empty.h | 6 + .../fast_io_core_impl/enums/access_how.h | 44 + .../include/fast_io_core_impl/enums/flock.h | 62 + .../include/fast_io_core_impl/enums/impl.h | 5 + .../fast_io_core_impl/enums/utime_flags.h | 20 + src/fast_io/include/fast_io_core_impl/error.h | 80 + .../freestanding/addressof.h | 53 + .../freestanding/algorithm.h | 847 ++++ .../freestanding/allocator.h | 31 + .../fast_io_core_impl/freestanding/array.h | 84 + .../fast_io_core_impl/freestanding/bytes.h | 245 + .../fast_io_core_impl/freestanding/cstr_len.h | 101 + .../fast_io_core_impl/freestanding/impl.h | 51 + .../freestanding/noexcept_call.h | 83 + .../fast_io_core_impl/freestanding/ranges.h | 17 + .../freestanding/relocatable.h | 40 + .../freestanding/std_allocator.h | 13 + .../include/fast_io_core_impl/http_header.h | 324 ++ .../include/fast_io_core_impl/igenerator.h | 111 + .../fast_io_core_impl/integers/chrono.h | 193 + .../fast_io_core_impl/integers/crypto_hash.h | 631 +++ .../fast_io_core_impl/integers/digits_table.h | 93 + .../include/fast_io_core_impl/integers/impl.h | 1771 +++++++ .../fast_io_core_impl/integers/integer.h | 9 + .../integers/jeaiii_method.h | 612 +++ .../fast_io_core_impl/integers/match.h | 82 + .../integers/optimize_size/impl.h | 143 + .../fast_io_core_impl/integers/pointer.h | 252 + .../integers/sto/sto_contiguous.h | 1327 ++++++ .../integers/sto/sto_generate_base_tb.h | 170 + .../fast_io_core_impl/integers/uprsv/dec.h | 286 ++ .../fast_io_core_impl/integers/uprsv/hex.h | 142 + .../fast_io_core_impl/integers/uprsv/impl.h | 67 + .../include/fast_io_core_impl/intrinsics.h | 1060 ++++ .../fast_io_core_impl/intrinsics/carry.h | 174 + .../fast_io_core_impl/intrinsics/impl.h | 4 + .../intrinsics/msvc/common.h | 6 + .../fast_io_core_impl/intrinsics/msvc/impl.h | 5 + .../fast_io_core_impl/intrinsics/msvc/x86.h | 25 + .../fast_io_core_impl/intrinsics/udivmod.h | 224 + .../include/fast_io_core_impl/io_deco_ref.h | 100 + .../include/fast_io_core_impl/io_ref.h | 236 + .../include/fast_io_core_impl/iso/iso8601.h | 1530 ++++++ .../include/fast_io_core_impl/iso/isos.h | 55 + .../fast_io_core_impl/literals/literal.h | 71 + .../fast_io_core_impl/literals/none_ascii.h | 19 + .../fast_io_core_impl/local_new_array_ptr.h | 107 + src/fast_io/include/fast_io_core_impl/mode.h | 575 +++ .../include/fast_io_core_impl/overflow.h | 35 + .../include/fast_io_core_impl/parse_code.h | 138 + src/fast_io/include/fast_io_core_impl/perms.h | 123 + .../include/fast_io_core_impl/pr_rsv.h | 182 + .../fast_io_core_impl/print_freestanding.h | 837 ++++ .../random_access_transmit.h | 115 + .../include/fast_io_core_impl/range_view.h | 147 + .../include/fast_io_core_impl/read_all.h | 208 + .../fast_io_core_impl/rwreflect/impl.h | 4 + .../fast_io_core_impl/rwreflect/reflectread.h | 691 +++ .../rwreflect/reflectwrite.h | 713 +++ .../fast_io_core_impl/scan_freestanding.h | 479 ++ .../fast_io_core_impl/secure_clear_guard.h | 196 + src/fast_io/include/fast_io_core_impl/seek.h | 35 + .../fast_io_core_impl/simd/cpu_flags.h | 87 + .../fast_io_core_impl/simd/gcc_clang.h | 648 +++ .../include/fast_io_core_impl/simd/generic.h | 285 ++ .../simd/generic_operations.h | 4245 +++++++++++++++++ .../include/fast_io_core_impl/simd/impl.h | 14 + .../fast_io_core_impl/simd/is_all_zeros.h | 215 + .../fast_io_core_impl/simd/mask_countr.h | 224 + .../include/fast_io_core_impl/simd/prrsv.h | 43 + .../include/fast_io_core_impl/simd/x86_64.h | 35 + .../include/fast_io_core_impl/simd_find.h | 684 +++ .../fast_io_core_impl/socket/addrprt.h | 387 ++ .../fast_io_core_impl/socket/addrscn.h | 668 +++ .../include/fast_io_core_impl/socket/impl.h | 23 + .../include/fast_io_core_impl/socket/ip.h | 48 + .../fast_io_core_impl/socket/posix_sockaddr.h | 68 + .../fast_io_core_impl/socket/sock_family.h | 94 + .../fast_io_core_impl/socket/sock_protocol.h | 66 + .../fast_io_core_impl/socket/sock_type.h | 16 + .../include/fast_io_core_impl/socket_enum.h | 61 + .../fast_io_core_impl/source_location.h | 66 + .../fast_io_core_impl/temporary_buffer.h | 171 + .../include/fast_io_core_impl/terminate.h | 26 + .../fast_io_core_impl/timestamp_counter.h | 23 + src/fast_io/include/fast_io_core_impl/to.h | 540 +++ .../include/fast_io_core_impl/transmit/impl.h | 4 + .../fast_io_core_impl/transmit/scanner.h | 251 + .../fast_io_core_impl/transmit/transmit.h | 296 ++ .../unit_character_input_buffer.h | 73 + src/fast_io/include/fast_io_core_impl/utils.h | 951 ++++ src/fast_io/include/fast_io_crypto.h | 32 + .../include/fast_io_crypto/cipher/aes.h | 130 + .../include/fast_io_crypto/hash/crc32.h | 94 + .../include/fast_io_crypto/hash/impl.h | 7 + src/fast_io/include/fast_io_crypto/hash/md5.h | 409 ++ .../hash/md5_sha_hash_context.h | 313 ++ .../include/fast_io_crypto/hash/sha1.h | 767 +++ .../include/fast_io_crypto/hash/sha256.h | 232 + .../fast_io_crypto/hash/sha256_scalar.h | 99 + .../fast_io_crypto/hash/sha256_simd16.h | 155 + .../hash/sha256_x86_sha_extensions.h | 249 + .../hash/sha256_x86_sha_extensions_msvc.h | 193 + .../include/fast_io_crypto/hash/sha512.h | 289 ++ .../fast_io_crypto/hash/sha512_scalar.h | 99 + .../fast_io_crypto/hash/sha512_simd16.h | 163 + .../fast_io_crypto/hash/sha512_simd32.h | 154 + .../hash/sha512_simd32_shuffle.h | 410 ++ .../include/fast_io_crypto/padding/padding.h | 4 + .../fast_io_crypto/padding/pkcs7_padding.h | 20 + .../fast_io_crypto/padding/zero_padding.h | 17 + .../include/fast_io_crypto/platforms/impl.h | 22 + .../fast_io_crypto/platforms/nt_bcrypt.h | 193 + .../fast_io_crypto/platforms/ossl_evp.h | 122 + .../fast_io_crypto/platforms/win32/apis.h | 189 + .../fast_io_crypto/platforms/win32/impl.h | 6 + .../platforms/win32/msvc_linker.h | 9 + .../platforms/win32/msvc_linker_32.h | 9 + .../platforms/win32/msvc_linker_32_i686.h | 9 + .../platforms/win32/msvc_linker_64.h | 9 + .../fast_io_crypto/streamcipher/chacha/impl.h | 35 + .../streamcipher/chacha/runtime.h | 13 + .../streamcipher/chacha/scalar.h | 110 + .../streamcipher/chacha/simd16.h | 97 + .../include/fast_io_crypto/tls/cipher_suite.h | 166 + .../include/fast_io_crypto/tls/client_hello.h | 20 + src/fast_io/include/fast_io_crypto/tls/tls.h | 7 + .../include/fast_io_crypto/tls/version.h | 22 + src/fast_io/include/fast_io_device.h | 292 ++ .../include/fast_io_driver/asio_driver.h | 20 + .../asio_driver/socket_io_observer.h | 53 + .../include/fast_io_driver/avformat/avio.h | 413 ++ .../include/fast_io_driver/avr/console.h | 84 + .../include/fast_io_driver/boost/graph.h | 19 + .../include/fast_io_driver/boost/uuid.h | 52 + .../include/fast_io_driver/boost_iostreams.h | 88 + .../include/fast_io_driver/bootloader/stvl2.h | 447 ++ .../bootloader/stvl2_struct_iterator.h | 54 + src/fast_io/include/fast_io_driver/capstone.h | 219 + src/fast_io/include/fast_io_driver/cppwinrt.h | 4 + .../fast_io_driver/cppwinrt_impl/hstring.h | 40 + .../fast_io_driver/cppwinrt_impl/impl.h | 4 + .../include/fast_io_driver/cryptopp_driver.h | 41 + .../include/fast_io_driver/fast_io_async.h | 3 + src/fast_io/include/fast_io_driver/kernel.h | 127 + .../fast_io_driver/limine/kernel_console.h | 50 + .../include/fast_io_driver/linux_kernel.h | 4 + .../fast_io_driver/linux_kernel_impl/kpr.h | 337 ++ src/fast_io/include/fast_io_driver/llvm.h | 9 + .../llvm_impl/hack_buffer_ptr.h | 84 + .../llvm_impl/raw_fd_ostream_file.h | 117 + .../llvm_impl/raw_ostream_io_observer.h | 141 + src/fast_io/include/fast_io_driver/mangling.h | 98 + src/fast_io/include/fast_io_driver/mfc.h | 14 + .../fast_io_driver/mfc_impl/atl_cstring.h | 38 + .../fast_io_driver/mfc_impl/atl_file.h | 236 + .../fast_io_driver/mfc_impl/mfc_file.h | 211 + .../include/fast_io_driver/nt_kernel.h | 4 + .../nt_kernel_impl/driver_object.h | 24 + .../include/fast_io_driver/openssl_driver.h | 31 + .../fast_io_driver/openssl_driver/bio.h | 490 ++ .../fast_io_driver/openssl_driver/context.h | 76 + .../fast_io_driver/openssl_driver/crypto.h | 22 + .../fast_io_driver/openssl_driver/error.h | 25 + .../fast_io_driver/openssl_driver/evp.h | 246 + .../fast_io_driver/openssl_driver/hash.h | 168 + .../fast_io_driver/openssl_driver/init.h | 16 + .../fast_io_driver/openssl_driver/observer.h | 36 + .../openssl_driver/ossl_lib_context.h | 37 + .../fast_io_driver/openssl_driver/settings.h | 45 + .../fast_io_driver/openssl_driver/ssl.h | 197 + .../include/fast_io_driver/posix_iconv.h | 41 + .../fast_io_driver/posix_iconv_impl/impl.h | 318 ++ .../include/fast_io_driver/pulseaudio.h | 135 + .../include/fast_io_driver/python/pyobject.h | 224 + src/fast_io/include/fast_io_driver/qt.h | 29 + .../include/fast_io_driver/qt_impl/qdebug.h | 79 + .../include/fast_io_driver/qt_impl/qfile.h | 185 + .../fast_io_driver/qt_impl/qiodevice.h | 157 + .../include/fast_io_driver/qt_impl/qstring.h | 150 + src/fast_io/include/fast_io_driver/refterm.h | 52 + src/fast_io/include/fast_io_driver/stvl2.h | 1521 ++++++ src/fast_io/include/fast_io_driver/timer.h | 25 + .../include/fast_io_driver/tsc_timer.h | 36 + .../include/fast_io_driver/win32_internet.h | 178 + .../include/fast_io_driver/win32_memory.h | 500 ++ .../include/fast_io_driver/zlib_driver.h | 9 + .../fast_io_driver/zlib_driver/gzfile.h | 225 + .../include/fast_io_dsal/impl/common.h | 131 + .../include/fast_io_dsal/impl/freestanding.h | 173 + .../include/fast_io_dsal/impl/vector.h | 1099 +++++ src/fast_io/include/fast_io_dsal/vector.h | 76 + src/fast_io/include/fast_io_freestanding.h | 87 + .../fast_io_freestanding_impl/auto_indent.h | 168 + .../include/fast_io_freestanding_impl/cond.h | 175 + .../fast_io_freestanding_impl/exception.h | 36 + .../fast_io_freestanding_impl/generator.h | 199 + .../io_buffer/general.h | 47 + .../io_buffer/impl.h | 7 + .../io_buffer/input.h | 207 + .../io_buffer/input_deco.h | 129 + .../io_buffer/input_normal.h | 48 + .../io_buffer/main.h | 409 ++ .../io_buffer/mode.h | 109 + .../io_buffer/output.h | 231 + .../io_buffer/output_deco.h | 88 + .../io_buffer/output_normal.h | 124 + .../fast_io_freestanding_impl/scanners/impl.h | 3 + .../scanners/line_scanner.h | 243 + .../serializations/impl.h | 7 + .../serializations/leb128.h | 291 ++ .../serializations/lebe.h | 615 +++ .../serializations/str_get.h | 119 + .../serializations/strlike_get.h | 325 ++ .../serializations/wasm.h | 59 + .../fast_io_freestanding_impl/space_reserve.h | 33 + .../include/fast_io_freestanding_impl/width.h | 547 +++ src/fast_io/include/fast_io_hosted.h | 132 + .../api_encoding_converter/impl.h | 47 + .../api_encoding_converter/nt.h | 71 + .../api_encoding_converter/posix.h | 164 + .../std_filesystem_pseudo.h | 36 + .../api_encoding_converter/win32.h | 135 + .../include/fast_io_hosted/async_coro.h | 182 + .../include/fast_io_hosted/auto_indent.h | 19 + src/fast_io/include/fast_io_hosted/box.h | 89 + .../include/fast_io_hosted/dbg/android.h | 255 + .../include/fast_io_hosted/dbg/common.h | 13 + src/fast_io/include/fast_io_hosted/dbg/err.h | 25 + src/fast_io/include/fast_io_hosted/dbg/impl.h | 11 + .../include/fast_io_hosted/dbg/nt_dbg.h | 184 + src/fast_io/include/fast_io_hosted/dll/dll.h | 9 + .../include/fast_io_hosted/dll/posix.h | 233 + .../include/fast_io_hosted/dll/win32.h | 209 + .../file_loaders/allocation_file_loader.h | 215 + .../fast_io_hosted/file_loaders/impl.h | 22 + .../file_loaders/posix_file_loader.h | 540 +++ .../file_loaders/win32_file_loader.h | 244 + .../include/fast_io_hosted/filesystem/apis.h | 27 + .../fast_io_hosted/filesystem/fsutils.h | 67 + .../fast_io_hosted/filesystem/native.h | 14 + .../include/fast_io_hosted/filesystem/nt.h | 556 +++ .../include/fast_io_hosted/filesystem/nt_at.h | 304 ++ .../include/fast_io_hosted/filesystem/posix.h | 513 ++ .../fast_io_hosted/filesystem/posix_at.h | 740 +++ src/fast_io/include/fast_io_hosted/iomutex.h | 93 + src/fast_io/include/fast_io_hosted/mmap.h | 19 + .../fast_io_hosted/platforms/com_error.h | 41 + .../platforms/errc_default_impl.h | 13 + .../fast_io_hosted/platforms/errc_impl.h | 16 + .../platforms/errno_to_win32_code.h | 131 + .../fast_io_hosted/platforms/linux/aarch64.h | 145 + .../fast_io_hosted/platforms/linux/amd64.h | 143 + .../fast_io_hosted/platforms/linux/generic.h | 29 + .../platforms/linux/loongarch64.h | 150 + .../fast_io_hosted/platforms/linux/riscv64.h | 150 + .../platforms/linux/system_call.h | 61 + .../fast_io_hosted/platforms/linux_zerocopy.h | 134 + .../include/fast_io_hosted/platforms/msdos.h | 60 + .../include/fast_io_hosted/platforms/native.h | 12 + .../fast_io_hosted/platforms/native_base.h | 103 + .../include/fast_io_hosted/platforms/nt.h | 1267 +++++ .../fast_io_hosted/platforms/nt/impl.h | 7 + .../fast_io_hosted/platforms/nt/nt_code.h | 88 + .../platforms/nt/nt_definitions.h | 606 +++ .../fast_io_hosted/platforms/nt/nt_linker.h | 1692 +++++++ .../fast_io_hosted/platforms/nt/nt_path.h | 156 + .../nt/rtl_unicode_string_unique_ptr.h | 32 + .../include/fast_io_hosted/platforms/omap.h | 129 + .../include/fast_io_hosted/platforms/posix.h | 1894 ++++++++ .../fast_io_hosted/platforms/posix_dns.h | 236 + .../platforms/posix_file_lock.h | 150 + .../fast_io_hosted/platforms/posix_mapping.h | 255 + .../fast_io_hosted/platforms/posix_netmode.h | 744 +++ .../fast_io_hosted/platforms/posix_netop.h | 124 + .../platforms/systemcall_details.h | 81 + .../include/fast_io_hosted/platforms/win32.h | 1486 ++++++ .../fast_io_hosted/platforms/win32/apis.h | 2772 +++++++++++ .../fast_io_hosted/platforms/win32/impl.h | 14 + .../platforms/win32/msvc_linker.h | 9 + .../platforms/win32/msvc_linker_32.h | 164 + .../platforms/win32/msvc_linker_32_i686.h | 164 + .../platforms/win32/msvc_linker_64.h | 164 + .../fast_io_hosted/platforms/win32/utils.h | 43 + .../platforms/win32/win32_definitions.h | 326 ++ .../fast_io_hosted/platforms/win32_code.h | 161 + .../platforms/win32_code_to_errno.h | 131 + .../fast_io_hosted/platforms/win32_error.h | 217 + .../platforms/win32_iocp_overlapped.h | 21 + .../fast_io_hosted/platforms/win32_mapping.h | 235 + .../platforms/win32_network/service.h | 28 + .../platforms/win32_network/socket_file.h | 783 +++ .../platforms/win32_network/win32.h | 13 + .../platforms/win32_network/win32_9x_dns.h | 220 + .../platforms/win32_network/win32_dns.h | 272 ++ .../platforms/win32_scheduling.h | 43 + .../platforms/wine/linux_syscall_table/i686.h | 1 + .../platforms/wine/linux_syscall_table/impl.h | 14 + .../wine/linux_syscall_table/x86_64.h | 6 + .../fast_io_hosted/platforms/wine/wine.h | 80 + .../include/fast_io_hosted/posix_error.h | 102 + .../fast_io_hosted/posix_error_scatter/avr.h | 190 + .../posix_error_scatter/generic.h | 1975 ++++++++ .../fast_io_hosted/posix_error_scatter/impl.h | 43 + .../posix_error_scatter/unknown.h | 20 + .../include/fast_io_hosted/posix_status.h | 264 + .../fast_io_hosted/process_revamp/native.h | 12 + .../fast_io_hosted/process_revamp/nt.h | 353 ++ .../fast_io_hosted/process_revamp/posix.h | 450 ++ .../fast_io_hosted/process_revamp/win32.h | 36 + .../threads/mutex/gcc_gthread_mutex.h | 27 + .../fast_io_hosted/threads/mutex/impl.h | 31 + .../threads/mutex/mcf_gthread_mutex.h | 31 + .../threads/mutex/posix_pthread_mutex.h | 36 + .../threads/mutex/rtl_critical_section.h | 34 + .../fast_io_hosted/threads/mutex/single.h | 13 + .../threads/mutex/win32_critical_section.h | 34 + .../timeutil/environ_timezone.h | 54 + .../include/fast_io_hosted/timeutil/impl.h | 16 + .../fast_io_hosted/timeutil/posix_timezone.h | 105 + .../include/fast_io_hosted/timeutil/time.h | 920 ++++ .../timeutil/win32_regtz_to_ianatz.h | 988 ++++ .../fast_io_hosted/timeutil/win32_timezone.h | 187 + .../white_hole/linux_getrandom.h | 51 + .../white_hole/posix_dev_urandom.h | 53 + .../white_hole/rtl_gen_random.h | 79 + .../white_hole/wasi_random_get.h | 84 + .../fast_io_hosted/white_hole/white_hole.h | 126 + .../white_hole/win32_crypt_gen_random.h | 135 + src/fast_io/include/fast_io_hosted/wrapper.h | 37 + src/fast_io/include/fast_io_hosted_crypto.h | 33 + src/fast_io/include/fast_io_i18n.h | 43 + src/fast_io/include/fast_io_i18n/imbuer.h | 43 + src/fast_io/include/fast_io_i18n/iso14651.h | 24 + src/fast_io/include/fast_io_i18n/lc.h | 290 ++ .../fast_io_i18n/lc_numbers/boolalpha.h | 16 + .../include/fast_io_i18n/lc_numbers/chrono.h | 308 ++ .../include/fast_io_i18n/lc_numbers/cond.h | 159 + .../include/fast_io_i18n/lc_numbers/impl.h | 16 + .../fast_io_i18n/lc_numbers/integers.h | 416 ++ .../include/fast_io_i18n/lc_numbers/lc_time.h | 1243 +++++ .../include/fast_io_i18n/lc_numbers/width.h | 125 + src/fast_io/include/fast_io_i18n/lc_print.h | 1000 ++++ .../include/fast_io_i18n/lc_print_status.h | 442 ++ .../include/fast_io_i18n/locale/impl.h | 8 + .../include/fast_io_i18n/locale/posix.h | 225 + .../include/fast_io_i18n/locale/win32.h | 405 ++ .../fast_io_i18n/locale/win32_lcid_table.h | 412 ++ src/fast_io/include/fast_io_i18n/timezone.h | 2 + src/fast_io/include/fast_io_legacy.h | 37 + .../include/fast_io_legacy_impl/c/avrlibc.h | 78 + .../include/fast_io_legacy_impl/c/custom.h | 107 + .../include/fast_io_legacy_impl/c/done.h | 345 ++ .../include/fast_io_legacy_impl/c/general.h | 119 + .../include/fast_io_legacy_impl/c/glibc.h | 274 ++ .../include/fast_io_legacy_impl/c/impl.h | 1110 +++++ .../include/fast_io_legacy_impl/c/llvm.h | 250 + .../fast_io_legacy_impl/c/macros_general.h | 50 + .../include/fast_io_legacy_impl/c/mlibc.h | 204 + .../fast_io_legacy_impl/c/msvcrt_lock.h | 131 + .../include/fast_io_legacy_impl/c/musl.h | 280 ++ .../include/fast_io_legacy_impl/c/serenity.h | 262 + .../include/fast_io_legacy_impl/c/uclibc.h | 226 + .../include/fast_io_legacy_impl/c/unix.h | 332 ++ .../include/fast_io_legacy_impl/c/wincrt.h | 630 +++ .../filebuf/bp_hack/common.h | 49 + .../filebuf/bp_hack/emulated.h | 132 + .../filebuf/bp_hack/impl.h | 13 + .../filebuf/bp_hack/libc++.h | 119 + .../filebuf/bp_hack/libstdc++.h | 131 + .../filebuf/bp_hack/msvc_stl.h | 146 + .../filebuf/filebuf_file.h | 179 + .../filebuf/fp_hack/impl.h | 8 + .../filebuf/fp_hack/libc++.h | 167 + .../filebuf/fp_hack/libc++symbol.h | 214 + .../filebuf/fp_hack/libstdc++.h | 144 + .../filebuf/fp_hack/msvc_stl.h | 84 + .../fast_io_legacy_impl/filebuf/op_out.h | 58 + .../filebuf/streambuf_io_observer.h | 298 ++ src/fast_io/include/fast_io_unit/async.h | 54 + src/fast_io/include/fast_io_unit/bitset.h | 83 + src/fast_io/include/fast_io_unit/chrono.h | 464 ++ src/fast_io/include/fast_io_unit/complex.h | 395 ++ src/fast_io/include/fast_io_unit/filesystem.h | 12 + src/fast_io/include/fast_io_unit/floating.h | 2 + .../include/fast_io_unit/floating/hexfloat.h | 100 + .../include/fast_io_unit/floating/impl.h | 104 + .../fast_io_unit/floating/lc_hexfloat.h | 78 + .../include/fast_io_unit/floating/lc_impl.h | 133 + .../fast_io_unit/floating/lc_roundtrip.h | 392 ++ .../include/fast_io_unit/floating/precision.h | 367 ++ .../include/fast_io_unit/floating/punning.h | 633 +++ .../include/fast_io_unit/floating/roundtrip.h | 1375 ++++++ src/fast_io/include/fast_io_unit/gb18030.h | 266 ++ .../fast_io_unit/gb18030_impl/gb18030_tb.h | 1 + .../gb18030_impl/gb18030_uni2_tb.h | 1 + .../gb18030_impl/gb18030_uni4_tb.h | 1 + src/fast_io/include/fast_io_unit/string.h | 4 + .../include/fast_io_unit/string_impl/concat.h | 196 + .../include/fast_io_unit/string_impl/impl.h | 15 + .../fast_io_unit/string_impl/lc_concat.h | 290 ++ .../include/fast_io_unit/string_impl/libc++.h | 134 + .../fast_io_unit/string_impl/libstdc++.h | 82 + .../fast_io_unit/string_impl/msvc_stl.h | 59 + .../fast_io_unit/string_impl/ostring_ref.h | 140 + .../string_impl/scan_str_ctx_impl.h | 170 + src/fast_io/include/fast_io_unit/timespec.h | 89 + src/fast_io/readme.md | 338 ++ src/fast_io/support.md | 147 + src/zip/DeflateFileWriter.cpp | 12 +- src/zip/StoreFileWriter.cpp | 10 +- src/zip/ZipPack.cpp | 31 +- src/zip/ZipUtils.cpp | 14 +- 499 files changed, 99851 insertions(+), 300 deletions(-) create mode 100644 src/fast_io/.editorconfig create mode 100644 src/fast_io/.git-blame-ignore-revs create mode 100644 src/fast_io/.gitignore create mode 100644 src/fast_io/include/fast_io.h create mode 100644 src/fast_io/include/fast_io_concept.h create mode 100644 src/fast_io/include/fast_io_core.h create mode 100644 src/fast_io/include/fast_io_core_impl/alias.h create mode 100644 src/fast_io/include/fast_io_core_impl/allocation/adapters.h create mode 100644 src/fast_io/include/fast_io_core_impl/allocation/allocator_adapter_flags.h create mode 100644 src/fast_io/include/fast_io_core_impl/allocation/c_malloc.h create mode 100644 src/fast_io/include/fast_io_core_impl/allocation/common.h create mode 100644 src/fast_io/include/fast_io_core_impl/allocation/custom.h create mode 100644 src/fast_io/include/fast_io_core_impl/allocation/has_methods_detect.h create mode 100644 src/fast_io/include/fast_io_core_impl/allocation/impl.h create mode 100644 src/fast_io/include/fast_io_core_impl/allocation/linux_kernel.h create mode 100644 src/fast_io/include/fast_io_core_impl/allocation/mimalloc_driver.h create mode 100644 src/fast_io/include/fast_io_core_impl/allocation/msvc/impl.h create mode 100644 src/fast_io/include/fast_io_core_impl/allocation/msvc/msvc_linker_32.h create mode 100644 src/fast_io/include/fast_io_core_impl/allocation/msvc/msvc_linker_32_i686.h create mode 100644 src/fast_io/include/fast_io_core_impl/allocation/msvc/msvc_linker_64.h create mode 100644 src/fast_io/include/fast_io_core_impl/allocation/nt_rtlheapalloc.h create mode 100644 src/fast_io/include/fast_io_core_impl/allocation/win32_heapalloc.h create mode 100644 src/fast_io/include/fast_io_core_impl/allocation/wincrt_malloc_dbg.h create mode 100644 src/fast_io/include/fast_io_core_impl/asan_support.h create mode 100644 src/fast_io/include/fast_io_core_impl/black_hole.h create mode 100644 src/fast_io/include/fast_io_core_impl/buffer_view.h create mode 100644 src/fast_io/include/fast_io_core_impl/char_category.h create mode 100644 src/fast_io/include/fast_io_core_impl/codecvt/code_cvt.h create mode 100644 src/fast_io/include/fast_io_core_impl/codecvt/gb18030.h create mode 100644 src/fast_io/include/fast_io_core_impl/codecvt/general.h create mode 100644 src/fast_io/include/fast_io_core_impl/codecvt/impl.h create mode 100644 src/fast_io/include/fast_io_core_impl/codecvt/utf.h create mode 100644 src/fast_io/include/fast_io_core_impl/codecvt/utf_ebcdic.h create mode 100644 src/fast_io/include/fast_io_core_impl/codecvt/utf_util_table.h create mode 100644 src/fast_io/include/fast_io_core_impl/compare.h create mode 100644 src/fast_io/include/fast_io_core_impl/concat/concat_buffer.h create mode 100644 src/fast_io/include/fast_io_core_impl/concat/concat_general.h create mode 100644 src/fast_io/include/fast_io_core_impl/concat/impl.h create mode 100644 src/fast_io/include/fast_io_core_impl/concat/strlike_reference_wrapper.h create mode 100644 src/fast_io/include/fast_io_core_impl/concepts/decorator.h create mode 100644 src/fast_io/include/fast_io_core_impl/concepts/details.h create mode 100644 src/fast_io/include/fast_io_core_impl/concepts/impl.h create mode 100644 src/fast_io/include/fast_io_core_impl/concepts/operation.h create mode 100644 src/fast_io/include/fast_io_core_impl/concepts/operation_details.h create mode 100644 src/fast_io/include/fast_io_core_impl/concepts/parse_code.h create mode 100644 src/fast_io/include/fast_io_core_impl/concepts/stream.h create mode 100644 src/fast_io/include/fast_io_core_impl/concepts/strlike.h create mode 100644 src/fast_io/include/fast_io_core_impl/concepts/type.h create mode 100644 src/fast_io/include/fast_io_core_impl/dll_mode.h create mode 100644 src/fast_io/include/fast_io_core_impl/drain.h create mode 100644 src/fast_io/include/fast_io_core_impl/dynamic_io_buffer.h create mode 100644 src/fast_io/include/fast_io_core_impl/ebcdic.h create mode 100644 src/fast_io/include/fast_io_core_impl/empty.h create mode 100644 src/fast_io/include/fast_io_core_impl/enums/access_how.h create mode 100644 src/fast_io/include/fast_io_core_impl/enums/flock.h create mode 100644 src/fast_io/include/fast_io_core_impl/enums/impl.h create mode 100644 src/fast_io/include/fast_io_core_impl/enums/utime_flags.h create mode 100644 src/fast_io/include/fast_io_core_impl/error.h create mode 100644 src/fast_io/include/fast_io_core_impl/freestanding/addressof.h create mode 100644 src/fast_io/include/fast_io_core_impl/freestanding/algorithm.h create mode 100644 src/fast_io/include/fast_io_core_impl/freestanding/allocator.h create mode 100644 src/fast_io/include/fast_io_core_impl/freestanding/array.h create mode 100644 src/fast_io/include/fast_io_core_impl/freestanding/bytes.h create mode 100644 src/fast_io/include/fast_io_core_impl/freestanding/cstr_len.h create mode 100644 src/fast_io/include/fast_io_core_impl/freestanding/impl.h create mode 100644 src/fast_io/include/fast_io_core_impl/freestanding/noexcept_call.h create mode 100644 src/fast_io/include/fast_io_core_impl/freestanding/ranges.h create mode 100644 src/fast_io/include/fast_io_core_impl/freestanding/relocatable.h create mode 100644 src/fast_io/include/fast_io_core_impl/freestanding/std_allocator.h create mode 100644 src/fast_io/include/fast_io_core_impl/http_header.h create mode 100644 src/fast_io/include/fast_io_core_impl/igenerator.h create mode 100644 src/fast_io/include/fast_io_core_impl/integers/chrono.h create mode 100644 src/fast_io/include/fast_io_core_impl/integers/crypto_hash.h create mode 100644 src/fast_io/include/fast_io_core_impl/integers/digits_table.h create mode 100644 src/fast_io/include/fast_io_core_impl/integers/impl.h create mode 100644 src/fast_io/include/fast_io_core_impl/integers/integer.h create mode 100644 src/fast_io/include/fast_io_core_impl/integers/jeaiii_method.h create mode 100644 src/fast_io/include/fast_io_core_impl/integers/match.h create mode 100644 src/fast_io/include/fast_io_core_impl/integers/optimize_size/impl.h create mode 100644 src/fast_io/include/fast_io_core_impl/integers/pointer.h create mode 100644 src/fast_io/include/fast_io_core_impl/integers/sto/sto_contiguous.h create mode 100644 src/fast_io/include/fast_io_core_impl/integers/sto/sto_generate_base_tb.h create mode 100644 src/fast_io/include/fast_io_core_impl/integers/uprsv/dec.h create mode 100644 src/fast_io/include/fast_io_core_impl/integers/uprsv/hex.h create mode 100644 src/fast_io/include/fast_io_core_impl/integers/uprsv/impl.h create mode 100644 src/fast_io/include/fast_io_core_impl/intrinsics.h create mode 100644 src/fast_io/include/fast_io_core_impl/intrinsics/carry.h create mode 100644 src/fast_io/include/fast_io_core_impl/intrinsics/impl.h create mode 100644 src/fast_io/include/fast_io_core_impl/intrinsics/msvc/common.h create mode 100644 src/fast_io/include/fast_io_core_impl/intrinsics/msvc/impl.h create mode 100644 src/fast_io/include/fast_io_core_impl/intrinsics/msvc/x86.h create mode 100644 src/fast_io/include/fast_io_core_impl/intrinsics/udivmod.h create mode 100644 src/fast_io/include/fast_io_core_impl/io_deco_ref.h create mode 100644 src/fast_io/include/fast_io_core_impl/io_ref.h create mode 100644 src/fast_io/include/fast_io_core_impl/iso/iso8601.h create mode 100644 src/fast_io/include/fast_io_core_impl/iso/isos.h create mode 100644 src/fast_io/include/fast_io_core_impl/literals/literal.h create mode 100644 src/fast_io/include/fast_io_core_impl/literals/none_ascii.h create mode 100644 src/fast_io/include/fast_io_core_impl/local_new_array_ptr.h create mode 100644 src/fast_io/include/fast_io_core_impl/mode.h create mode 100644 src/fast_io/include/fast_io_core_impl/overflow.h create mode 100644 src/fast_io/include/fast_io_core_impl/parse_code.h create mode 100644 src/fast_io/include/fast_io_core_impl/perms.h create mode 100644 src/fast_io/include/fast_io_core_impl/pr_rsv.h create mode 100644 src/fast_io/include/fast_io_core_impl/print_freestanding.h create mode 100644 src/fast_io/include/fast_io_core_impl/random_access_transmit.h create mode 100644 src/fast_io/include/fast_io_core_impl/range_view.h create mode 100644 src/fast_io/include/fast_io_core_impl/read_all.h create mode 100644 src/fast_io/include/fast_io_core_impl/rwreflect/impl.h create mode 100644 src/fast_io/include/fast_io_core_impl/rwreflect/reflectread.h create mode 100644 src/fast_io/include/fast_io_core_impl/rwreflect/reflectwrite.h create mode 100644 src/fast_io/include/fast_io_core_impl/scan_freestanding.h create mode 100644 src/fast_io/include/fast_io_core_impl/secure_clear_guard.h create mode 100644 src/fast_io/include/fast_io_core_impl/seek.h create mode 100644 src/fast_io/include/fast_io_core_impl/simd/cpu_flags.h create mode 100644 src/fast_io/include/fast_io_core_impl/simd/gcc_clang.h create mode 100644 src/fast_io/include/fast_io_core_impl/simd/generic.h create mode 100644 src/fast_io/include/fast_io_core_impl/simd/generic_operations.h create mode 100644 src/fast_io/include/fast_io_core_impl/simd/impl.h create mode 100644 src/fast_io/include/fast_io_core_impl/simd/is_all_zeros.h create mode 100644 src/fast_io/include/fast_io_core_impl/simd/mask_countr.h create mode 100644 src/fast_io/include/fast_io_core_impl/simd/prrsv.h create mode 100644 src/fast_io/include/fast_io_core_impl/simd/x86_64.h create mode 100644 src/fast_io/include/fast_io_core_impl/simd_find.h create mode 100644 src/fast_io/include/fast_io_core_impl/socket/addrprt.h create mode 100644 src/fast_io/include/fast_io_core_impl/socket/addrscn.h create mode 100644 src/fast_io/include/fast_io_core_impl/socket/impl.h create mode 100644 src/fast_io/include/fast_io_core_impl/socket/ip.h create mode 100644 src/fast_io/include/fast_io_core_impl/socket/posix_sockaddr.h create mode 100644 src/fast_io/include/fast_io_core_impl/socket/sock_family.h create mode 100644 src/fast_io/include/fast_io_core_impl/socket/sock_protocol.h create mode 100644 src/fast_io/include/fast_io_core_impl/socket/sock_type.h create mode 100644 src/fast_io/include/fast_io_core_impl/socket_enum.h create mode 100644 src/fast_io/include/fast_io_core_impl/source_location.h create mode 100644 src/fast_io/include/fast_io_core_impl/temporary_buffer.h create mode 100644 src/fast_io/include/fast_io_core_impl/terminate.h create mode 100644 src/fast_io/include/fast_io_core_impl/timestamp_counter.h create mode 100644 src/fast_io/include/fast_io_core_impl/to.h create mode 100644 src/fast_io/include/fast_io_core_impl/transmit/impl.h create mode 100644 src/fast_io/include/fast_io_core_impl/transmit/scanner.h create mode 100644 src/fast_io/include/fast_io_core_impl/transmit/transmit.h create mode 100644 src/fast_io/include/fast_io_core_impl/unit_character_input_buffer.h create mode 100644 src/fast_io/include/fast_io_core_impl/utils.h create mode 100644 src/fast_io/include/fast_io_crypto.h create mode 100644 src/fast_io/include/fast_io_crypto/cipher/aes.h create mode 100644 src/fast_io/include/fast_io_crypto/hash/crc32.h create mode 100644 src/fast_io/include/fast_io_crypto/hash/impl.h create mode 100644 src/fast_io/include/fast_io_crypto/hash/md5.h create mode 100644 src/fast_io/include/fast_io_crypto/hash/md5_sha_hash_context.h create mode 100644 src/fast_io/include/fast_io_crypto/hash/sha1.h create mode 100644 src/fast_io/include/fast_io_crypto/hash/sha256.h create mode 100644 src/fast_io/include/fast_io_crypto/hash/sha256_scalar.h create mode 100644 src/fast_io/include/fast_io_crypto/hash/sha256_simd16.h create mode 100644 src/fast_io/include/fast_io_crypto/hash/sha256_x86_sha_extensions.h create mode 100644 src/fast_io/include/fast_io_crypto/hash/sha256_x86_sha_extensions_msvc.h create mode 100644 src/fast_io/include/fast_io_crypto/hash/sha512.h create mode 100644 src/fast_io/include/fast_io_crypto/hash/sha512_scalar.h create mode 100644 src/fast_io/include/fast_io_crypto/hash/sha512_simd16.h create mode 100644 src/fast_io/include/fast_io_crypto/hash/sha512_simd32.h create mode 100644 src/fast_io/include/fast_io_crypto/hash/sha512_simd32_shuffle.h create mode 100644 src/fast_io/include/fast_io_crypto/padding/padding.h create mode 100644 src/fast_io/include/fast_io_crypto/padding/pkcs7_padding.h create mode 100644 src/fast_io/include/fast_io_crypto/padding/zero_padding.h create mode 100644 src/fast_io/include/fast_io_crypto/platforms/impl.h create mode 100644 src/fast_io/include/fast_io_crypto/platforms/nt_bcrypt.h create mode 100644 src/fast_io/include/fast_io_crypto/platforms/ossl_evp.h create mode 100644 src/fast_io/include/fast_io_crypto/platforms/win32/apis.h create mode 100644 src/fast_io/include/fast_io_crypto/platforms/win32/impl.h create mode 100644 src/fast_io/include/fast_io_crypto/platforms/win32/msvc_linker.h create mode 100644 src/fast_io/include/fast_io_crypto/platforms/win32/msvc_linker_32.h create mode 100644 src/fast_io/include/fast_io_crypto/platforms/win32/msvc_linker_32_i686.h create mode 100644 src/fast_io/include/fast_io_crypto/platforms/win32/msvc_linker_64.h create mode 100644 src/fast_io/include/fast_io_crypto/streamcipher/chacha/impl.h create mode 100644 src/fast_io/include/fast_io_crypto/streamcipher/chacha/runtime.h create mode 100644 src/fast_io/include/fast_io_crypto/streamcipher/chacha/scalar.h create mode 100644 src/fast_io/include/fast_io_crypto/streamcipher/chacha/simd16.h create mode 100644 src/fast_io/include/fast_io_crypto/tls/cipher_suite.h create mode 100644 src/fast_io/include/fast_io_crypto/tls/client_hello.h create mode 100644 src/fast_io/include/fast_io_crypto/tls/tls.h create mode 100644 src/fast_io/include/fast_io_crypto/tls/version.h create mode 100644 src/fast_io/include/fast_io_device.h create mode 100644 src/fast_io/include/fast_io_driver/asio_driver.h create mode 100644 src/fast_io/include/fast_io_driver/asio_driver/socket_io_observer.h create mode 100644 src/fast_io/include/fast_io_driver/avformat/avio.h create mode 100644 src/fast_io/include/fast_io_driver/avr/console.h create mode 100644 src/fast_io/include/fast_io_driver/boost/graph.h create mode 100644 src/fast_io/include/fast_io_driver/boost/uuid.h create mode 100644 src/fast_io/include/fast_io_driver/boost_iostreams.h create mode 100644 src/fast_io/include/fast_io_driver/bootloader/stvl2.h create mode 100644 src/fast_io/include/fast_io_driver/bootloader/stvl2_struct_iterator.h create mode 100644 src/fast_io/include/fast_io_driver/capstone.h create mode 100644 src/fast_io/include/fast_io_driver/cppwinrt.h create mode 100644 src/fast_io/include/fast_io_driver/cppwinrt_impl/hstring.h create mode 100644 src/fast_io/include/fast_io_driver/cppwinrt_impl/impl.h create mode 100644 src/fast_io/include/fast_io_driver/cryptopp_driver.h create mode 100644 src/fast_io/include/fast_io_driver/fast_io_async.h create mode 100644 src/fast_io/include/fast_io_driver/kernel.h create mode 100644 src/fast_io/include/fast_io_driver/limine/kernel_console.h create mode 100644 src/fast_io/include/fast_io_driver/linux_kernel.h create mode 100644 src/fast_io/include/fast_io_driver/linux_kernel_impl/kpr.h create mode 100644 src/fast_io/include/fast_io_driver/llvm.h create mode 100644 src/fast_io/include/fast_io_driver/llvm_impl/hack_buffer_ptr.h create mode 100644 src/fast_io/include/fast_io_driver/llvm_impl/raw_fd_ostream_file.h create mode 100644 src/fast_io/include/fast_io_driver/llvm_impl/raw_ostream_io_observer.h create mode 100644 src/fast_io/include/fast_io_driver/mangling.h create mode 100644 src/fast_io/include/fast_io_driver/mfc.h create mode 100644 src/fast_io/include/fast_io_driver/mfc_impl/atl_cstring.h create mode 100644 src/fast_io/include/fast_io_driver/mfc_impl/atl_file.h create mode 100644 src/fast_io/include/fast_io_driver/mfc_impl/mfc_file.h create mode 100644 src/fast_io/include/fast_io_driver/nt_kernel.h create mode 100644 src/fast_io/include/fast_io_driver/nt_kernel_impl/driver_object.h create mode 100644 src/fast_io/include/fast_io_driver/openssl_driver.h create mode 100644 src/fast_io/include/fast_io_driver/openssl_driver/bio.h create mode 100644 src/fast_io/include/fast_io_driver/openssl_driver/context.h create mode 100644 src/fast_io/include/fast_io_driver/openssl_driver/crypto.h create mode 100644 src/fast_io/include/fast_io_driver/openssl_driver/error.h create mode 100644 src/fast_io/include/fast_io_driver/openssl_driver/evp.h create mode 100644 src/fast_io/include/fast_io_driver/openssl_driver/hash.h create mode 100644 src/fast_io/include/fast_io_driver/openssl_driver/init.h create mode 100644 src/fast_io/include/fast_io_driver/openssl_driver/observer.h create mode 100644 src/fast_io/include/fast_io_driver/openssl_driver/ossl_lib_context.h create mode 100644 src/fast_io/include/fast_io_driver/openssl_driver/settings.h create mode 100644 src/fast_io/include/fast_io_driver/openssl_driver/ssl.h create mode 100644 src/fast_io/include/fast_io_driver/posix_iconv.h create mode 100644 src/fast_io/include/fast_io_driver/posix_iconv_impl/impl.h create mode 100644 src/fast_io/include/fast_io_driver/pulseaudio.h create mode 100644 src/fast_io/include/fast_io_driver/python/pyobject.h create mode 100644 src/fast_io/include/fast_io_driver/qt.h create mode 100644 src/fast_io/include/fast_io_driver/qt_impl/qdebug.h create mode 100644 src/fast_io/include/fast_io_driver/qt_impl/qfile.h create mode 100644 src/fast_io/include/fast_io_driver/qt_impl/qiodevice.h create mode 100644 src/fast_io/include/fast_io_driver/qt_impl/qstring.h create mode 100644 src/fast_io/include/fast_io_driver/refterm.h create mode 100644 src/fast_io/include/fast_io_driver/stvl2.h create mode 100644 src/fast_io/include/fast_io_driver/timer.h create mode 100644 src/fast_io/include/fast_io_driver/tsc_timer.h create mode 100644 src/fast_io/include/fast_io_driver/win32_internet.h create mode 100644 src/fast_io/include/fast_io_driver/win32_memory.h create mode 100644 src/fast_io/include/fast_io_driver/zlib_driver.h create mode 100644 src/fast_io/include/fast_io_driver/zlib_driver/gzfile.h create mode 100644 src/fast_io/include/fast_io_dsal/impl/common.h create mode 100644 src/fast_io/include/fast_io_dsal/impl/freestanding.h create mode 100644 src/fast_io/include/fast_io_dsal/impl/vector.h create mode 100644 src/fast_io/include/fast_io_dsal/vector.h create mode 100644 src/fast_io/include/fast_io_freestanding.h create mode 100644 src/fast_io/include/fast_io_freestanding_impl/auto_indent.h create mode 100644 src/fast_io/include/fast_io_freestanding_impl/cond.h create mode 100644 src/fast_io/include/fast_io_freestanding_impl/exception.h create mode 100644 src/fast_io/include/fast_io_freestanding_impl/generator.h create mode 100644 src/fast_io/include/fast_io_freestanding_impl/io_buffer/general.h create mode 100644 src/fast_io/include/fast_io_freestanding_impl/io_buffer/impl.h create mode 100644 src/fast_io/include/fast_io_freestanding_impl/io_buffer/input.h create mode 100644 src/fast_io/include/fast_io_freestanding_impl/io_buffer/input_deco.h create mode 100644 src/fast_io/include/fast_io_freestanding_impl/io_buffer/input_normal.h create mode 100644 src/fast_io/include/fast_io_freestanding_impl/io_buffer/main.h create mode 100644 src/fast_io/include/fast_io_freestanding_impl/io_buffer/mode.h create mode 100644 src/fast_io/include/fast_io_freestanding_impl/io_buffer/output.h create mode 100644 src/fast_io/include/fast_io_freestanding_impl/io_buffer/output_deco.h create mode 100644 src/fast_io/include/fast_io_freestanding_impl/io_buffer/output_normal.h create mode 100644 src/fast_io/include/fast_io_freestanding_impl/scanners/impl.h create mode 100644 src/fast_io/include/fast_io_freestanding_impl/scanners/line_scanner.h create mode 100644 src/fast_io/include/fast_io_freestanding_impl/serializations/impl.h create mode 100644 src/fast_io/include/fast_io_freestanding_impl/serializations/leb128.h create mode 100644 src/fast_io/include/fast_io_freestanding_impl/serializations/lebe.h create mode 100644 src/fast_io/include/fast_io_freestanding_impl/serializations/str_get.h create mode 100644 src/fast_io/include/fast_io_freestanding_impl/serializations/strlike_get.h create mode 100644 src/fast_io/include/fast_io_freestanding_impl/serializations/wasm.h create mode 100644 src/fast_io/include/fast_io_freestanding_impl/space_reserve.h create mode 100644 src/fast_io/include/fast_io_freestanding_impl/width.h create mode 100644 src/fast_io/include/fast_io_hosted.h create mode 100644 src/fast_io/include/fast_io_hosted/api_encoding_converter/impl.h create mode 100644 src/fast_io/include/fast_io_hosted/api_encoding_converter/nt.h create mode 100644 src/fast_io/include/fast_io_hosted/api_encoding_converter/posix.h create mode 100644 src/fast_io/include/fast_io_hosted/api_encoding_converter/std_filesystem_pseudo.h create mode 100644 src/fast_io/include/fast_io_hosted/api_encoding_converter/win32.h create mode 100644 src/fast_io/include/fast_io_hosted/async_coro.h create mode 100644 src/fast_io/include/fast_io_hosted/auto_indent.h create mode 100644 src/fast_io/include/fast_io_hosted/box.h create mode 100644 src/fast_io/include/fast_io_hosted/dbg/android.h create mode 100644 src/fast_io/include/fast_io_hosted/dbg/common.h create mode 100644 src/fast_io/include/fast_io_hosted/dbg/err.h create mode 100644 src/fast_io/include/fast_io_hosted/dbg/impl.h create mode 100644 src/fast_io/include/fast_io_hosted/dbg/nt_dbg.h create mode 100644 src/fast_io/include/fast_io_hosted/dll/dll.h create mode 100644 src/fast_io/include/fast_io_hosted/dll/posix.h create mode 100644 src/fast_io/include/fast_io_hosted/dll/win32.h create mode 100644 src/fast_io/include/fast_io_hosted/file_loaders/allocation_file_loader.h create mode 100644 src/fast_io/include/fast_io_hosted/file_loaders/impl.h create mode 100644 src/fast_io/include/fast_io_hosted/file_loaders/posix_file_loader.h create mode 100644 src/fast_io/include/fast_io_hosted/file_loaders/win32_file_loader.h create mode 100644 src/fast_io/include/fast_io_hosted/filesystem/apis.h create mode 100644 src/fast_io/include/fast_io_hosted/filesystem/fsutils.h create mode 100644 src/fast_io/include/fast_io_hosted/filesystem/native.h create mode 100644 src/fast_io/include/fast_io_hosted/filesystem/nt.h create mode 100644 src/fast_io/include/fast_io_hosted/filesystem/nt_at.h create mode 100644 src/fast_io/include/fast_io_hosted/filesystem/posix.h create mode 100644 src/fast_io/include/fast_io_hosted/filesystem/posix_at.h create mode 100644 src/fast_io/include/fast_io_hosted/iomutex.h create mode 100644 src/fast_io/include/fast_io_hosted/mmap.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/com_error.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/errc_default_impl.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/errc_impl.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/errno_to_win32_code.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/linux/aarch64.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/linux/amd64.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/linux/generic.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/linux/loongarch64.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/linux/riscv64.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/linux/system_call.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/linux_zerocopy.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/msdos.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/native.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/native_base.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/nt.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/nt/impl.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/nt/nt_code.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/nt/nt_definitions.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/nt/nt_linker.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/nt/nt_path.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/nt/rtl_unicode_string_unique_ptr.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/omap.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/posix.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/posix_dns.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/posix_file_lock.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/posix_mapping.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/posix_netmode.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/posix_netop.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/systemcall_details.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/win32.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/win32/apis.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/win32/impl.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/win32/msvc_linker.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/win32/msvc_linker_32.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/win32/msvc_linker_32_i686.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/win32/msvc_linker_64.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/win32/utils.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/win32/win32_definitions.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/win32_code.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/win32_code_to_errno.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/win32_error.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/win32_iocp_overlapped.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/win32_mapping.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/win32_network/service.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/win32_network/socket_file.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/win32_network/win32.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/win32_network/win32_9x_dns.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/win32_network/win32_dns.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/win32_scheduling.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/wine/linux_syscall_table/i686.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/wine/linux_syscall_table/impl.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/wine/linux_syscall_table/x86_64.h create mode 100644 src/fast_io/include/fast_io_hosted/platforms/wine/wine.h create mode 100644 src/fast_io/include/fast_io_hosted/posix_error.h create mode 100644 src/fast_io/include/fast_io_hosted/posix_error_scatter/avr.h create mode 100644 src/fast_io/include/fast_io_hosted/posix_error_scatter/generic.h create mode 100644 src/fast_io/include/fast_io_hosted/posix_error_scatter/impl.h create mode 100644 src/fast_io/include/fast_io_hosted/posix_error_scatter/unknown.h create mode 100644 src/fast_io/include/fast_io_hosted/posix_status.h create mode 100644 src/fast_io/include/fast_io_hosted/process_revamp/native.h create mode 100644 src/fast_io/include/fast_io_hosted/process_revamp/nt.h create mode 100644 src/fast_io/include/fast_io_hosted/process_revamp/posix.h create mode 100644 src/fast_io/include/fast_io_hosted/process_revamp/win32.h create mode 100644 src/fast_io/include/fast_io_hosted/threads/mutex/gcc_gthread_mutex.h create mode 100644 src/fast_io/include/fast_io_hosted/threads/mutex/impl.h create mode 100644 src/fast_io/include/fast_io_hosted/threads/mutex/mcf_gthread_mutex.h create mode 100644 src/fast_io/include/fast_io_hosted/threads/mutex/posix_pthread_mutex.h create mode 100644 src/fast_io/include/fast_io_hosted/threads/mutex/rtl_critical_section.h create mode 100644 src/fast_io/include/fast_io_hosted/threads/mutex/single.h create mode 100644 src/fast_io/include/fast_io_hosted/threads/mutex/win32_critical_section.h create mode 100644 src/fast_io/include/fast_io_hosted/timeutil/environ_timezone.h create mode 100644 src/fast_io/include/fast_io_hosted/timeutil/impl.h create mode 100644 src/fast_io/include/fast_io_hosted/timeutil/posix_timezone.h create mode 100644 src/fast_io/include/fast_io_hosted/timeutil/time.h create mode 100644 src/fast_io/include/fast_io_hosted/timeutil/win32_regtz_to_ianatz.h create mode 100644 src/fast_io/include/fast_io_hosted/timeutil/win32_timezone.h create mode 100644 src/fast_io/include/fast_io_hosted/white_hole/linux_getrandom.h create mode 100644 src/fast_io/include/fast_io_hosted/white_hole/posix_dev_urandom.h create mode 100644 src/fast_io/include/fast_io_hosted/white_hole/rtl_gen_random.h create mode 100644 src/fast_io/include/fast_io_hosted/white_hole/wasi_random_get.h create mode 100644 src/fast_io/include/fast_io_hosted/white_hole/white_hole.h create mode 100644 src/fast_io/include/fast_io_hosted/white_hole/win32_crypt_gen_random.h create mode 100644 src/fast_io/include/fast_io_hosted/wrapper.h create mode 100644 src/fast_io/include/fast_io_hosted_crypto.h create mode 100644 src/fast_io/include/fast_io_i18n.h create mode 100644 src/fast_io/include/fast_io_i18n/imbuer.h create mode 100644 src/fast_io/include/fast_io_i18n/iso14651.h create mode 100644 src/fast_io/include/fast_io_i18n/lc.h create mode 100644 src/fast_io/include/fast_io_i18n/lc_numbers/boolalpha.h create mode 100644 src/fast_io/include/fast_io_i18n/lc_numbers/chrono.h create mode 100644 src/fast_io/include/fast_io_i18n/lc_numbers/cond.h create mode 100644 src/fast_io/include/fast_io_i18n/lc_numbers/impl.h create mode 100644 src/fast_io/include/fast_io_i18n/lc_numbers/integers.h create mode 100644 src/fast_io/include/fast_io_i18n/lc_numbers/lc_time.h create mode 100644 src/fast_io/include/fast_io_i18n/lc_numbers/width.h create mode 100644 src/fast_io/include/fast_io_i18n/lc_print.h create mode 100644 src/fast_io/include/fast_io_i18n/lc_print_status.h create mode 100644 src/fast_io/include/fast_io_i18n/locale/impl.h create mode 100644 src/fast_io/include/fast_io_i18n/locale/posix.h create mode 100644 src/fast_io/include/fast_io_i18n/locale/win32.h create mode 100644 src/fast_io/include/fast_io_i18n/locale/win32_lcid_table.h create mode 100644 src/fast_io/include/fast_io_i18n/timezone.h create mode 100644 src/fast_io/include/fast_io_legacy.h create mode 100644 src/fast_io/include/fast_io_legacy_impl/c/avrlibc.h create mode 100644 src/fast_io/include/fast_io_legacy_impl/c/custom.h create mode 100644 src/fast_io/include/fast_io_legacy_impl/c/done.h create mode 100644 src/fast_io/include/fast_io_legacy_impl/c/general.h create mode 100644 src/fast_io/include/fast_io_legacy_impl/c/glibc.h create mode 100644 src/fast_io/include/fast_io_legacy_impl/c/impl.h create mode 100644 src/fast_io/include/fast_io_legacy_impl/c/llvm.h create mode 100644 src/fast_io/include/fast_io_legacy_impl/c/macros_general.h create mode 100644 src/fast_io/include/fast_io_legacy_impl/c/mlibc.h create mode 100644 src/fast_io/include/fast_io_legacy_impl/c/msvcrt_lock.h create mode 100644 src/fast_io/include/fast_io_legacy_impl/c/musl.h create mode 100644 src/fast_io/include/fast_io_legacy_impl/c/serenity.h create mode 100644 src/fast_io/include/fast_io_legacy_impl/c/uclibc.h create mode 100644 src/fast_io/include/fast_io_legacy_impl/c/unix.h create mode 100644 src/fast_io/include/fast_io_legacy_impl/c/wincrt.h create mode 100644 src/fast_io/include/fast_io_legacy_impl/filebuf/bp_hack/common.h create mode 100644 src/fast_io/include/fast_io_legacy_impl/filebuf/bp_hack/emulated.h create mode 100644 src/fast_io/include/fast_io_legacy_impl/filebuf/bp_hack/impl.h create mode 100644 src/fast_io/include/fast_io_legacy_impl/filebuf/bp_hack/libc++.h create mode 100644 src/fast_io/include/fast_io_legacy_impl/filebuf/bp_hack/libstdc++.h create mode 100644 src/fast_io/include/fast_io_legacy_impl/filebuf/bp_hack/msvc_stl.h create mode 100644 src/fast_io/include/fast_io_legacy_impl/filebuf/filebuf_file.h create mode 100644 src/fast_io/include/fast_io_legacy_impl/filebuf/fp_hack/impl.h create mode 100644 src/fast_io/include/fast_io_legacy_impl/filebuf/fp_hack/libc++.h create mode 100644 src/fast_io/include/fast_io_legacy_impl/filebuf/fp_hack/libc++symbol.h create mode 100644 src/fast_io/include/fast_io_legacy_impl/filebuf/fp_hack/libstdc++.h create mode 100644 src/fast_io/include/fast_io_legacy_impl/filebuf/fp_hack/msvc_stl.h create mode 100644 src/fast_io/include/fast_io_legacy_impl/filebuf/op_out.h create mode 100644 src/fast_io/include/fast_io_legacy_impl/filebuf/streambuf_io_observer.h create mode 100644 src/fast_io/include/fast_io_unit/async.h create mode 100644 src/fast_io/include/fast_io_unit/bitset.h create mode 100644 src/fast_io/include/fast_io_unit/chrono.h create mode 100644 src/fast_io/include/fast_io_unit/complex.h create mode 100644 src/fast_io/include/fast_io_unit/filesystem.h create mode 100644 src/fast_io/include/fast_io_unit/floating.h create mode 100644 src/fast_io/include/fast_io_unit/floating/hexfloat.h create mode 100644 src/fast_io/include/fast_io_unit/floating/impl.h create mode 100644 src/fast_io/include/fast_io_unit/floating/lc_hexfloat.h create mode 100644 src/fast_io/include/fast_io_unit/floating/lc_impl.h create mode 100644 src/fast_io/include/fast_io_unit/floating/lc_roundtrip.h create mode 100644 src/fast_io/include/fast_io_unit/floating/precision.h create mode 100644 src/fast_io/include/fast_io_unit/floating/punning.h create mode 100644 src/fast_io/include/fast_io_unit/floating/roundtrip.h create mode 100644 src/fast_io/include/fast_io_unit/gb18030.h create mode 100644 src/fast_io/include/fast_io_unit/gb18030_impl/gb18030_tb.h create mode 100644 src/fast_io/include/fast_io_unit/gb18030_impl/gb18030_uni2_tb.h create mode 100644 src/fast_io/include/fast_io_unit/gb18030_impl/gb18030_uni4_tb.h create mode 100644 src/fast_io/include/fast_io_unit/string.h create mode 100644 src/fast_io/include/fast_io_unit/string_impl/concat.h create mode 100644 src/fast_io/include/fast_io_unit/string_impl/impl.h create mode 100644 src/fast_io/include/fast_io_unit/string_impl/lc_concat.h create mode 100644 src/fast_io/include/fast_io_unit/string_impl/libc++.h create mode 100644 src/fast_io/include/fast_io_unit/string_impl/libstdc++.h create mode 100644 src/fast_io/include/fast_io_unit/string_impl/msvc_stl.h create mode 100644 src/fast_io/include/fast_io_unit/string_impl/ostring_ref.h create mode 100644 src/fast_io/include/fast_io_unit/string_impl/scan_str_ctx_impl.h create mode 100644 src/fast_io/include/fast_io_unit/timespec.h create mode 100644 src/fast_io/readme.md create mode 100644 src/fast_io/support.md diff --git a/CMakeLists.txt b/CMakeLists.txt index b5c81ba..9c9fdd6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,7 +72,7 @@ target_include_directories(FS PUBLIC "include") target_include_directories(FS PRIVATE "src") target_include_directories(FS PUBLIC "${PROJECT_SOURCE_DIR}/../Logger/include") target_include_directories(FS PUBLIC "${PROJECT_SOURCE_DIR}/../cppcoro/include") -target_include_directories(FS PUBLIC "${PROJECT_SOURCE_DIR}/../fast_io/include") +target_include_directories(FS PRIVATE "src/fast_io/include") target_link_libraries(FS TL) target_link_libraries(FS zlib) diff --git a/include/fs/AbsPath.h b/include/fs/AbsPath.h index a84d6c4..f2e872d 100644 --- a/include/fs/AbsPath.h +++ b/include/fs/AbsPath.h @@ -14,9 +14,9 @@ template struct WindowsSystemCustom : public tl::detail::path_system::base_path_system { template - static T format_absolute(const tl::vector& members); - static void parse_absolute(tl::vector& o_elements, const char* path, size_t size); - static bool validate_abs_path(const tl::vector& members); + static T format_abs(tl::span members); + static void parse_abs(tl::vector& o_elements, const char* path, size_t size); + static bool validate_abs_path(tl::span members); static bool match(const char* path, size_t size); }; TL_DECLARE_STRING_VECTOR(WindowsParseSeparators, "\\", "/"); @@ -35,8 +35,10 @@ TL_DECLARE_STRING_VECTOR(UncParseSeparators, "\\", "/"); TL_DECLARE_STRING_LITERAL(UncFormatSeparator, "\\"); using UncSystem = tl::simple_path_system; -using AbsPath = tl::abs_path >; +using AbsPath = tl::abs_path>; +using AbsPathView = AbsPath::path_view_type; using RelPath = AbsPath::rel_path_type; +using RelPathView = RelPath::path_view_type; } @@ -48,6 +50,6 @@ struct std::formatter constexpr auto parse(format_parse_context& ctx) noexcept { return ctx.begin(); } auto format(const fs::RelPath& p, std::format_context& ctx) const { - return format_to(ctx.out(), "{}", p.get_as()); + return format_to(ctx.out(), "{}", p.str()); } }; diff --git a/include/fs/AbsPath.inl b/include/fs/AbsPath.inl index 62636b1..c6481c2 100644 --- a/include/fs/AbsPath.inl +++ b/include/fs/AbsPath.inl @@ -12,16 +12,16 @@ namespace detail // windows path system template template - T WindowsSystemCustom::format_absolute(const tl::vector& members) + T WindowsSystemCustom::format_abs(tl::span members) { - return tl::simple_path_system::template format_absolute(members); + return tl::simple_path_system::template format_abs(members); } template - void WindowsSystemCustom::parse_absolute(tl::vector& o_elements, const char* path, size_t size) + void WindowsSystemCustom::parse_abs(tl::vector& o_elements, const char* path, size_t size) { // On windows, the drive letter case is undefined. To avoid issues (hashing, etc), we always convert the drive letter to uppercase - tl::simple_path_system::parse_absolute(o_elements, path, size); + tl::simple_path_system::parse_abs(o_elements, path, size); if (!o_elements.empty()) { tl::string& str = o_elements.front(); @@ -42,7 +42,7 @@ namespace detail } template - bool WindowsSystemCustom::validate_abs_path(const tl::vector& members) + bool WindowsSystemCustom::validate_abs_path(tl::span members) { return !members.empty() && match(members[0].c_str(), members[0].size()); } diff --git a/include/fs/CRCStream.h b/include/fs/CRCStream.h index 2e5bd70..9626881 100644 --- a/include/fs/CRCStream.h +++ b/include/fs/CRCStream.h @@ -15,11 +15,11 @@ FS_API uint64_t computeCRC64(uint64_t crc, tl::span data); typedef tl::result CRC32StreamResult; FS_API CRC32StreamResult crc32Stream(IStreamSource& source, uint32_t crc = 0, size_t bufferSize = 0); -FS_API CRC32StreamResult crc32File(const IFilesystem& filesystem, const AbsPath& filePath, uint32_t crc = 0, size_t bufferSize = 0); +FS_API CRC32StreamResult crc32File(const IFilesystem& filesystem, AbsPathView filePath, uint32_t crc = 0, size_t bufferSize = 0); typedef tl::result CRC64StreamResult; FS_API CRC64StreamResult crc64Stream(IStreamSource& source, uint64_t crc = 0, size_t bufferSize = 0); -FS_API CRC64StreamResult crc64File(const IFilesystem& filesystem, const AbsPath& filePath, uint64_t crc = 0, size_t bufferSize = 0); +FS_API CRC64StreamResult crc64File(const IFilesystem& filesystem, AbsPathView filePath, uint64_t crc = 0, size_t bufferSize = 0); ////////////////////////////////////////////////////////////////////////// } diff --git a/include/fs/CopyStream.h b/include/fs/CopyStream.h index cb18618..337e77b 100644 --- a/include/fs/CopyStream.h +++ b/include/fs/CopyStream.h @@ -16,9 +16,9 @@ class IFilesystem; using CopyStreamResult = tl::result; FS_API CopyStreamResult copyStream(IStreamSink& sink, IStreamSource& source, size_t bufferSize = 0); FS_API CopyStreamResult copyStream(IStreamSink& sink, IStreamSource& source, const ProcessDataCallback& dataCallback, size_t bufferSize = 0); -FS_API CopyStreamResult copyFile(IStreamSink& sink, const IFilesystem& filesystem, const AbsPath& filePath, size_t bufferSize = 0); -FS_API CopyStreamResult copyFile(IStreamSink& sink, const IFilesystem& filesystem, const AbsPath& filePath, const ProcessDataCallback& dataCallback, size_t bufferSize = 0); -FS_API CopyStreamResult copyFile(IFilesystem& dstFilesystem, const AbsPath& dstFilePath, const IFilesystem& srcFilesystem, const AbsPath& srcFilePath, size_t bufferSize = 0); +FS_API CopyStreamResult copyFile(IStreamSink& sink, const IFilesystem& filesystem, AbsPathView filePath, size_t bufferSize = 0); +FS_API CopyStreamResult copyFile(IStreamSink& sink, const IFilesystem& filesystem, AbsPathView filePath, const ProcessDataCallback& dataCallback, size_t bufferSize = 0); +FS_API CopyStreamResult copyFile(IFilesystem& dstFilesystem, AbsPathView dstFilePath, const IFilesystem& srcFilesystem, AbsPathView srcFilePath, size_t bufferSize = 0); ////////////////////////////////////////////////////////////////////////// } diff --git a/include/fs/CustomFilesystem.h b/include/fs/CustomFilesystem.h index fb17b1b..758d4eb 100644 --- a/include/fs/CustomFilesystem.h +++ b/include/fs/CustomFilesystem.h @@ -25,8 +25,8 @@ public: TL_DECLARE_INTEGRAL_ID(PackId, uint64_t) - tl::result mountFront(AbsPath mountPoint, tl::unique_ref pack); - tl::result mountBack(AbsPath mountPoint, tl::unique_ref pack); + tl::result mountFront(AbsPathView mountPoint, tl::unique_ref pack); + tl::result mountBack(AbsPathView mountPoint, tl::unique_ref pack); //unmounts all the packs for this point. It basically deletes the mount point cppcoro::generator> unmountAll(); @@ -35,37 +35,37 @@ public: tl::unique_ptr unmount(PackId packId); //Returns the physical location of the virtual pack. - ConvertToNativePathResult convertToNativePath(const AbsPath& path) const override; + ConvertToNativePathResult convertToNativePath(AbsPathView path) const override; - OpenSourceResult openSource(const AbsPath& path, SourceFlags flags = SourceFlags()) const override; - OpenStreamSourceResult openStreamSource(const AbsPath& path, SourceFlags flags = SourceFlags()) const override; - OpenMapSourceResult openMapSource(const AbsPath& path, MapView mapView = MapView(), SourceFlags flags = SourceFlags()) const override; - OpenSinkResult openSink(const AbsPath& path, Mode mode, SinkFlags flags = SinkFlags()) override; - OpenStreamSinkResult openStreamSink(const AbsPath& path, Mode mode, SinkFlags flags = SinkFlags()) override; - OpenMapSinkResult openMapSink(const AbsPath& path, Mode mode, size_t size, SinkFlags flags = SinkFlags()) override; + OpenSourceResult openSource(AbsPathView path, SourceFlags flags = SourceFlags()) const override; + OpenStreamSourceResult openStreamSource(AbsPathView path, SourceFlags flags = SourceFlags()) const override; + OpenMapSourceResult openMapSource(AbsPathView path, MapView mapView = MapView(), SourceFlags flags = SourceFlags()) const override; + OpenSinkResult openSink(AbsPathView path, Mode mode, SinkFlags flags = SinkFlags()) override; + OpenStreamSinkResult openStreamSink(AbsPathView path, Mode mode, SinkFlags flags = SinkFlags()) override; + OpenMapSinkResult openMapSink(AbsPathView path, Mode mode, size_t size, SinkFlags flags = SinkFlags()) override; - IsFileResult isFile(const AbsPath& path) const override; - IsFolderResult isFolder(const AbsPath& path) const override; - ExistsResult exists(const AbsPath& path) const override; + IsFileResult isFile(AbsPathView path) const override; + IsFolderResult isFolder(AbsPathView path) const override; + ExistsResult exists(AbsPathView path) const override; - MakeFolderResult makeFolder(const AbsPath& path) override; + MakeFolderResult makeFolder(AbsPathView path) override; - RenameResult rename(const AbsPath& path, const AbsPath& newPath) override; + RenameResult rename(AbsPathView path, AbsPathView newPath) override; - RemoveResult remove(const AbsPath& path) override; - RemoveRecursivelyResult removeRecursively(const AbsPath& path) override; + RemoveResult remove(AbsPathView path) override; + RemoveRecursivelyResult removeRecursively(AbsPathView path) override; - CopyResult copy(const AbsPath& path, const AbsPath& newPath) override; + CopyResult copy(AbsPathView path, AbsPathView newPath) override; - MakeHardLinkResult makeHardLink(const AbsPath& sourcePath, const AbsPath& linkPath) override; - MakeSoftLinkResult makeSymLink(const AbsPath& sourcePath, const AbsPath& linkPath) override; + MakeHardLinkResult makeHardLink(AbsPathView sourcePath, AbsPathView linkPath) override; + MakeSoftLinkResult makeSymLink(AbsPathView sourcePath, AbsPathView linkPath) override; - SetWriteTimeResult setWriteTime(const AbsPath& path, time_t time) override; + SetWriteTimeResult setWriteTime(AbsPathView path, time_t time) override; - GetStatResult getStat(const AbsPath& path) const override; + GetStatResult getStat(AbsPathView path) const override; - cppcoro::generator enumerate(const AbsPath& path) const override; - cppcoro::generator enumerateRecursively(const AbsPath& path) const override; + cppcoro::generator enumerate(AbsPathView path) const override; + cppcoro::generator enumerateRecursively(AbsPathView path) const override; private: struct PackData @@ -86,14 +86,14 @@ private: }; tl::vector m_packsData; - void convertToPackPath(AbsPath& packPath, const AbsPath& path, const AbsPath& mountPoint) const; + void convertToPackPath(AbsPath& packPath, AbsPathView path, AbsPathView mountPoint) const; enum class MountPolicy { Front, //the pack will be mounted over packs from the same mount point. This pack will take precedence Back //the pack will be at the bottom of existing packs from the same mount point. Its streams will be searched last }; - tl::result mount(AbsPath mountPoint, tl::unique_ref pack, MountPolicy policy); + tl::result mount(AbsPathView mountPoint, tl::unique_ref pack, MountPolicy policy); }; diff --git a/include/fs/FileMapSink.h b/include/fs/FileMapSink.h index e147f87..008478e 100644 --- a/include/fs/FileMapSink.h +++ b/include/fs/FileMapSink.h @@ -16,7 +16,7 @@ class FS_API FileMapSink final : public IMapSink { friend class NativeFilesystem; public: - FileMapSink(const AbsPath& filepath, size_t size, Mode mode = Mode::CreateOrOpenAndClear, Flags flags = Flags()); + FileMapSink(AbsPathView filepath, size_t size, Mode mode = Mode::CreateOrOpenAndClear, Flags flags = Flags()); ~FileMapSink() override; bool isValid() const; diff --git a/include/fs/FileMapSource.h b/include/fs/FileMapSource.h index 4aa6911..8fdc736 100644 --- a/include/fs/FileMapSource.h +++ b/include/fs/FileMapSource.h @@ -15,8 +15,8 @@ class FS_API FileMapSource final : public IMapSource { friend class NativeFilesystem; public: - explicit FileMapSource(const AbsPath& filepath); - FileMapSource(const AbsPath& filepath, uint64_t start, size_t size); + explicit FileMapSource(AbsPathView filepath); + FileMapSource(AbsPathView filepath, uint64_t start, size_t size); ~FileMapSource() override; diff --git a/include/fs/FileSink.h b/include/fs/FileSink.h index a55d2f5..a73e5e0 100644 --- a/include/fs/FileSink.h +++ b/include/fs/FileSink.h @@ -12,7 +12,7 @@ namespace fs class FS_API FileSink final : public ISink { public: - FileSink(const AbsPath& filepath, Mode mode, Flags flags = Flags()) noexcept; + FileSink(AbsPathView filepath, Mode mode, Flags flags = Flags()) noexcept; ~FileSink() noexcept override; FileSink(FileSink&& other) noexcept; diff --git a/include/fs/FileSource.h b/include/fs/FileSource.h index d7182f4..e093e7d 100644 --- a/include/fs/FileSource.h +++ b/include/fs/FileSource.h @@ -10,8 +10,8 @@ namespace fs class FS_API FileSource final : public ISource { public: - explicit FileSource(const AbsPath& i_filepath) noexcept; - FileSource(const AbsPath& i_filepath, Flags i_flags) noexcept; + explicit FileSource(AbsPathView i_filepath) noexcept; + FileSource(AbsPathView i_filepath, Flags i_flags) noexcept; ~FileSource() noexcept override; FileSource(FileSource&& i_other) noexcept; diff --git a/include/fs/FolderPack.h b/include/fs/FolderPack.h index 1236ef1..837858b 100644 --- a/include/fs/FolderPack.h +++ b/include/fs/FolderPack.h @@ -10,28 +10,28 @@ namespace fs class FS_API FolderPack : virtual public IPack { public: - explicit FolderPack(AbsPath location); - FolderPack(tl::lent_ref filesystem, AbsPath location); + explicit FolderPack(AbsPathView location); + FolderPack(tl::lent_ref filesystem, AbsPathView location); ~FolderPack() override = default; - OpenSourceResult openSource(const AbsPath& path, SourceFlags flags = SourceFlags()) const override; - OpenStreamSourceResult openStreamSource(const AbsPath& path, SourceFlags flags = SourceFlags()) const override; - OpenMapSourceResult openMapSource(const AbsPath& path, MapView mapView = MapView(), SourceFlags flags = SourceFlags()) const override; + OpenSourceResult openSource(AbsPathView path, SourceFlags flags = SourceFlags()) const override; + OpenStreamSourceResult openStreamSource(AbsPathView path, SourceFlags flags = SourceFlags()) const override; + OpenMapSourceResult openMapSource(AbsPathView path, MapView mapView = MapView(), SourceFlags flags = SourceFlags()) const override; - IsFileResult isFile(const AbsPath& path) const override; - IsFolderResult isFolder(const AbsPath& path) const override; - ExistsResult exists(const AbsPath& path) const override; + IsFileResult isFile(AbsPathView path) const override; + IsFolderResult isFolder(AbsPathView path) const override; + ExistsResult exists(AbsPathView path) const override; - GetStatResult getStat(const AbsPath& path) const override; + GetStatResult getStat(AbsPathView path) const override; - cppcoro::generator enumerate(const AbsPath& path) const override; - cppcoro::generator enumerateRecursively(const AbsPath& path) const override; + cppcoro::generator enumerate(AbsPathView path) const override; + cppcoro::generator enumerateRecursively(AbsPathView path) const override; - ConvertToNativePathResult convertToNativePath(const AbsPath& path) const override; + ConvertToNativePathResult convertToNativePath(AbsPathView path) const override; protected: - AbsPath convertToUnderlyingPath(const AbsPath& path) const; + AbsPath convertToUnderlyingPath(AbsPathView path) const; tl::lent_ref m_filesystem; AbsPath m_location; }; diff --git a/include/fs/IFilesystem.h b/include/fs/IFilesystem.h index e47b74e..41899f0 100644 --- a/include/fs/IFilesystem.h +++ b/include/fs/IFilesystem.h @@ -44,7 +44,7 @@ using SetWriteTimeResult = tl::result; struct EnumerateEntry { - RelPath path; + RelPathView path; bool isFolder = false; }; @@ -68,9 +68,9 @@ public: //Opens a Read-only Stream //Searches for the stream in the packs from the mountpoint in top to bottom order, and opens if found - virtual OpenSourceResult openSource(const AbsPath& path, SourceFlags flags = SourceFlags()) const = 0; - virtual OpenStreamSourceResult openStreamSource(const AbsPath& path, SourceFlags flags = SourceFlags()) const = 0; - virtual OpenMapSourceResult openMapSource(const AbsPath& path, MapView mapView = MapView(), SourceFlags flags = SourceFlags()) const = 0; + virtual OpenSourceResult openSource(AbsPathView path, SourceFlags flags = SourceFlags()) const = 0; + virtual OpenStreamSourceResult openStreamSource(AbsPathView path, SourceFlags flags = SourceFlags()) const = 0; + virtual OpenMapSourceResult openMapSource(AbsPathView path, MapView mapView = MapView(), SourceFlags flags = SourceFlags()) const = 0; using SinkFlag = ISink::Flag; using SinkFlags = ISink::Flags; @@ -79,46 +79,46 @@ public: //Searches for the stream in the packs from the mountpoint in top to bottom order, and opens if found. //If used with the CREATE flag, it will create the stream if not found. //NOTE: this will fail if the mountpoint has only read-only packs (zip files, etc) - virtual OpenSinkResult openSink(const AbsPath& path, Mode mode, SinkFlags flags = SinkFlags()) = 0; - virtual OpenStreamSinkResult openStreamSink(const AbsPath& path, Mode mode, SinkFlags flags = SinkFlags()) = 0; - virtual OpenMapSinkResult openMapSink(const AbsPath& path, Mode mode, size_t size, SinkFlags flags = SinkFlags()) = 0; + virtual OpenSinkResult openSink(AbsPathView path, Mode mode, SinkFlags flags = SinkFlags()) = 0; + virtual OpenStreamSinkResult openStreamSink(AbsPathView path, Mode mode, SinkFlags flags = SinkFlags()) = 0; + virtual OpenMapSinkResult openMapSink(AbsPathView path, Mode mode, size_t size, SinkFlags flags = SinkFlags()) = 0; ////////////////////////////////////////////////////////////////////////// //Returns the physical location of the virtual pack. - virtual ConvertToNativePathResult convertToNativePath(const AbsPath& path) const = 0; + virtual ConvertToNativePathResult convertToNativePath(AbsPathView path) const = 0; - virtual IsFileResult isFile(const AbsPath& path) const = 0; - virtual IsFolderResult isFolder(const AbsPath& path) const = 0; - virtual ExistsResult exists(const AbsPath& path) const = 0; + virtual IsFileResult isFile(AbsPathView path) const = 0; + virtual IsFolderResult isFolder(AbsPathView path) const = 0; + virtual ExistsResult exists(AbsPathView path) const = 0; - virtual GetStatResult getStat(const AbsPath& path) const = 0; + virtual GetStatResult getStat(AbsPathView path) const = 0; - virtual MakeFolderResult makeFolder(const AbsPath& path) = 0; + virtual MakeFolderResult makeFolder(AbsPathView path) = 0; - virtual RenameResult rename(const AbsPath& path, const AbsPath& newPath) = 0; + virtual RenameResult rename(AbsPathView path, AbsPathView newPath) = 0; //this removes one file or one folder. The folder is removed ONLY if it's empty. If you want to remove a non-empty folder, use RemoveRecursively - virtual RemoveResult remove(const AbsPath& path) = 0; + virtual RemoveResult remove(AbsPathView path) = 0; - virtual CopyResult copy(const AbsPath& path, const AbsPath& newPath) = 0; + virtual CopyResult copy(AbsPathView path, AbsPathView newPath) = 0; // Hard links are essentially a new name for the same file data. // The file becomes reference counted and the data will be deleted when all handles to it are removed from the FS. - virtual MakeHardLinkResult makeHardLink(const AbsPath& sourcePath, const AbsPath& linkPath) = 0; + virtual MakeHardLinkResult makeHardLink(AbsPathView sourcePath, AbsPathView linkPath) = 0; // Soft links are like 'weak' pointers to a file. If the original gets deleted the soft link becomes 'null'. - virtual MakeSoftLinkResult makeSymLink(const AbsPath& sourcePath, const AbsPath& linkPath) = 0; + virtual MakeSoftLinkResult makeSymLink(AbsPathView sourcePath, AbsPathView linkPath) = 0; //Use this function in order to remove the set folder and all of the files and folders contained inside. //This function is not atomic; if the removal of any of the folders or files fails, the process will be stopped //and the function will return false, but any of the previously removed files will be already removed. - virtual RemoveRecursivelyResult removeRecursively(const AbsPath& path) = 0; + virtual RemoveRecursivelyResult removeRecursively(AbsPathView path) = 0; - virtual SetWriteTimeResult setWriteTime(const AbsPath& path, time_t time) = 0; + virtual SetWriteTimeResult setWriteTime(AbsPathView path, time_t time) = 0; - virtual cppcoro::generator enumerate(const AbsPath& path) const = 0; - virtual cppcoro::generator enumerateRecursively(const AbsPath& path) const = 0; + virtual cppcoro::generator enumerate(AbsPathView path) const = 0; + virtual cppcoro::generator enumerateRecursively(AbsPathView path) const = 0; }; diff --git a/include/fs/IPack.h b/include/fs/IPack.h index 6cb6334..28c590e 100644 --- a/include/fs/IPack.h +++ b/include/fs/IPack.h @@ -23,20 +23,20 @@ public: using SourceFlags = IFilesystem::SourceFlags; using MapView = IFilesystem::MapView; - virtual OpenSourceResult openSource(const AbsPath& i_path, SourceFlags i_flags = SourceFlags()) const = 0; - virtual OpenStreamSourceResult openStreamSource(const AbsPath& i_path, SourceFlags i_flags = SourceFlags()) const = 0; - virtual OpenMapSourceResult openMapSource(const AbsPath& i_path, MapView i_mapView = MapView(), SourceFlags i_flags = SourceFlags()) const = 0; + virtual OpenSourceResult openSource(AbsPathView i_path, SourceFlags i_flags = SourceFlags()) const = 0; + virtual OpenStreamSourceResult openStreamSource(AbsPathView i_path, SourceFlags i_flags = SourceFlags()) const = 0; + virtual OpenMapSourceResult openMapSource(AbsPathView i_path, MapView i_mapView = MapView(), SourceFlags i_flags = SourceFlags()) const = 0; - virtual IsFileResult isFile(const AbsPath& i_path) const = 0; - virtual IsFolderResult isFolder(const AbsPath& i_path) const = 0; - virtual ExistsResult exists(const AbsPath& i_path) const = 0; + virtual IsFileResult isFile(AbsPathView i_path) const = 0; + virtual IsFolderResult isFolder(AbsPathView i_path) const = 0; + virtual ExistsResult exists(AbsPathView i_path) const = 0; - virtual GetStatResult getStat(const AbsPath& i_path) const = 0; + virtual GetStatResult getStat(AbsPathView i_path) const = 0; - virtual cppcoro::generator enumerate(const AbsPath& i_path) const = 0; - virtual cppcoro::generator enumerateRecursively(const AbsPath& i_path) const = 0; + virtual cppcoro::generator enumerate(AbsPathView i_path) const = 0; + virtual cppcoro::generator enumerateRecursively(AbsPathView i_path) const = 0; - virtual ConvertToNativePathResult convertToNativePath(const AbsPath& i_path) const = 0; + virtual ConvertToNativePathResult convertToNativePath(AbsPathView i_path) const = 0; protected: IPack() = default; diff --git a/include/fs/IWritablePack.h b/include/fs/IWritablePack.h index d1d6a1f..9634f60 100644 --- a/include/fs/IWritablePack.h +++ b/include/fs/IWritablePack.h @@ -13,17 +13,17 @@ public: using SinkFlag = IFilesystem::SinkFlag; using SinkFlags = IFilesystem::SinkFlags; - virtual OpenSinkResult openSink(const AbsPath& i_path, Mode i_mode, SinkFlags i_flags = SinkFlags()) = 0; - virtual OpenStreamSinkResult openStreamSink(const AbsPath& i_path, Mode i_mode, SinkFlags i_flags = SinkFlags()) = 0; - virtual OpenMapSinkResult openMapSink(const AbsPath& i_path, Mode i_mode, size_t i_size, SinkFlags i_flags = SinkFlags()) = 0; + virtual OpenSinkResult openSink(AbsPathView i_path, Mode i_mode, SinkFlags i_flags = SinkFlags()) = 0; + virtual OpenStreamSinkResult openStreamSink(AbsPathView i_path, Mode i_mode, SinkFlags i_flags = SinkFlags()) = 0; + virtual OpenMapSinkResult openMapSink(AbsPathView i_path, Mode i_mode, size_t i_size, SinkFlags i_flags = SinkFlags()) = 0; - virtual RemoveResult remove(const AbsPath& i_path) = 0; - virtual RenameResult rename(const AbsPath& i_path, const AbsPath& i_newPath) = 0; + virtual RemoveResult remove(AbsPathView i_path) = 0; + virtual RenameResult rename(AbsPathView i_path, AbsPathView i_newPath) = 0; - virtual MakeFolderResult makeFolder(const AbsPath& i_path) = 0; - virtual RemoveRecursivelyResult removeRecursively(const AbsPath& i_path) = 0; + virtual MakeFolderResult makeFolder(AbsPathView i_path) = 0; + virtual RemoveRecursivelyResult removeRecursively(AbsPathView i_path) = 0; - virtual SetWriteTimeResult setWriteTime(const AbsPath& i_path, time_t i_time) = 0; + virtual SetWriteTimeResult setWriteTime(AbsPathView i_path, time_t i_time) = 0; }; } diff --git a/include/fs/NativeFilesystem.h b/include/fs/NativeFilesystem.h index f7ebde9..2495c84 100644 --- a/include/fs/NativeFilesystem.h +++ b/include/fs/NativeFilesystem.h @@ -21,46 +21,46 @@ public: NativeFilesystem() = default; explicit NativeFilesystem(CheckFlags checkFlags); - OpenSourceResult openSource(const AbsPath& path, SourceFlags flags = SourceFlags()) const override; - OpenStreamSourceResult openStreamSource(const AbsPath& path, SourceFlags flags = SourceFlags()) const override; - OpenMapSourceResult openMapSource(const AbsPath& path, MapView mapView = MapView(), SourceFlags flags = SourceFlags()) const override; - OpenSinkResult openSink(const AbsPath& path, Mode mode, SinkFlags flags = SinkFlags()) override; - OpenStreamSinkResult openStreamSink(const AbsPath& path, Mode mode, SinkFlags flags = SinkFlags()) override; - OpenMapSinkResult openMapSink(const AbsPath& path, Mode mode, size_t size, SinkFlags flags = SinkFlags()) override; + OpenSourceResult openSource(AbsPathView path, SourceFlags flags = SourceFlags()) const override; + OpenStreamSourceResult openStreamSource(AbsPathView path, SourceFlags flags = SourceFlags()) const override; + OpenMapSourceResult openMapSource(AbsPathView path, MapView mapView = MapView(), SourceFlags flags = SourceFlags()) const override; + OpenSinkResult openSink(AbsPathView path, Mode mode, SinkFlags flags = SinkFlags()) override; + OpenStreamSinkResult openStreamSink(AbsPathView path, Mode mode, SinkFlags flags = SinkFlags()) override; + OpenMapSinkResult openMapSink(AbsPathView path, Mode mode, size_t size, SinkFlags flags = SinkFlags()) override; - ConvertToNativePathResult convertToNativePath(const AbsPath& path) const override; + ConvertToNativePathResult convertToNativePath(AbsPathView path) const override; - IsFileResult isFile(const AbsPath& path) const override; - IsFolderResult isFolder(const AbsPath& path) const override; - ExistsResult exists(const AbsPath& path) const override; + IsFileResult isFile(AbsPathView path) const override; + IsFolderResult isFolder(AbsPathView path) const override; + ExistsResult exists(AbsPathView path) const override; - MakeFolderResult makeFolder(const AbsPath& path) override; + MakeFolderResult makeFolder(AbsPathView path) override; - RenameResult rename(const AbsPath& path, const AbsPath& newPath) override; + RenameResult rename(AbsPathView path, AbsPathView newPath) override; - RemoveResult remove(const AbsPath& path) override; - RemoveRecursivelyResult removeRecursively(const AbsPath& path) override; + RemoveResult remove(AbsPathView path) override; + RemoveRecursivelyResult removeRecursively(AbsPathView path) override; - CopyResult copy(const AbsPath& path, const AbsPath& newPath) override; + CopyResult copy(AbsPathView path, AbsPathView newPath) override; - MakeHardLinkResult makeHardLink(const AbsPath& sourcePath, const AbsPath& linkPath) override; - MakeSoftLinkResult makeSymLink(const AbsPath& sourcePath, const AbsPath& linkPath) override; + MakeHardLinkResult makeHardLink(AbsPathView sourcePath, AbsPathView linkPath) override; + MakeSoftLinkResult makeSymLink(AbsPathView sourcePath, AbsPathView linkPath) override; - SetWriteTimeResult setWriteTime(const AbsPath& path, time_t time) override; + SetWriteTimeResult setWriteTime(AbsPathView path, time_t time) override; - GetStatResult getStat(const AbsPath& path) const override; + GetStatResult getStat(AbsPathView path) const override; - cppcoro::generator enumerate(const AbsPath& path) const override; - cppcoro::generator enumerateRecursively(const AbsPath& path) const override; + cppcoro::generator enumerate(AbsPathView path) const override; + cppcoro::generator enumerateRecursively(AbsPathView path) const override; AbsPath getCurrentFolder() const; - tl::result setCurrentFolder(const AbsPath& path); + tl::result setCurrentFolder(AbsPathView path); typedef tl::result, Error> EnumerateFilesResult; - EnumerateFilesResult enumerateFiles(const AbsPath& fullPath) const; + EnumerateFilesResult enumerateFiles(AbsPathView fullPath) const; typedef tl::result, Error> EnumerateFoldersResult; - EnumerateFoldersResult enumerateFolders(const AbsPath& fullPath) const; + EnumerateFoldersResult enumerateFolders(AbsPathView fullPath) const; AbsPath makeAbsPath(const tl::string& string) const; diff --git a/include/fs/NativeUtils.h b/include/fs/NativeUtils.h index 78503f9..5b05dbe 100644 --- a/include/fs/NativeUtils.h +++ b/include/fs/NativeUtils.h @@ -8,8 +8,8 @@ namespace fs namespace native_utils { -bool validateCaseSensitiveFilename(const AbsPath& filePath) noexcept; -bool validateCaseSensitiveFolder(const AbsPath& folderPath) noexcept; +bool validateCaseSensitiveFilename(AbsPathView filePath) noexcept; +bool validateCaseSensitiveFolder(AbsPathView folderPath) noexcept; typedef eastl::fixed_string wstring_t; typedef eastl::fixed_string string_t; diff --git a/include/fs/ReadStream.h b/include/fs/ReadStream.h index 4cc7724..85ee083 100644 --- a/include/fs/ReadStream.h +++ b/include/fs/ReadStream.h @@ -13,8 +13,8 @@ FS_API ReadStreamResult readStream(tl::memory_buffer& buffer, IStreamSource& sou FS_API ReadStreamResult readStream(std::string& buffer, IStreamSource& source, size_t bufferSize = 0); FS_API ReadStreamResult readStream(eastl::string& buffer, IStreamSource& source, size_t bufferSize = 0); -FS_API ReadStreamResult readFile(tl::memory_buffer& buffer, IFilesystem& filesystem, const AbsPath& filePath, size_t bufferSize = 0); -FS_API ReadStreamResult readFile(std::string& buffer, IFilesystem& filesystem, const AbsPath& filePath, size_t bufferSize = 0); -FS_API ReadStreamResult readFile(eastl::string& buffer, IFilesystem& filesystem, const AbsPath& filePath, size_t bufferSize = 0); +FS_API ReadStreamResult readFile(tl::memory_buffer& buffer, IFilesystem& filesystem, AbsPathView filePath, size_t bufferSize = 0); +FS_API ReadStreamResult readFile(std::string& buffer, IFilesystem& filesystem, AbsPathView filePath, size_t bufferSize = 0); +FS_API ReadStreamResult readFile(eastl::string& buffer, IFilesystem& filesystem, AbsPathView filePath, size_t bufferSize = 0); } diff --git a/include/fs/WritableFolderPack.h b/include/fs/WritableFolderPack.h index 92aecb3..3355321 100644 --- a/include/fs/WritableFolderPack.h +++ b/include/fs/WritableFolderPack.h @@ -12,21 +12,21 @@ namespace fs class FS_API WritableFolderPack final : virtual public IWritablePack, public FolderPack { public: - explicit WritableFolderPack(AbsPath location); - WritableFolderPack(tl::lent_ref filesystem, AbsPath location); + explicit WritableFolderPack(AbsPathView location); + WritableFolderPack(tl::lent_ref filesystem, AbsPathView location); ~WritableFolderPack() override = default; - OpenSinkResult openSink(const AbsPath& i_path, Mode i_mode, SinkFlags i_flags = SinkFlags()) override; - OpenStreamSinkResult openStreamSink(const AbsPath& i_path, Mode i_mode, SinkFlags i_flags = SinkFlags()) override; - OpenMapSinkResult openMapSink(const AbsPath& i_path, Mode i_mode, size_t i_size, SinkFlags i_flags = SinkFlags()) override; + OpenSinkResult openSink(AbsPathView i_path, Mode i_mode, SinkFlags i_flags = SinkFlags()) override; + OpenStreamSinkResult openStreamSink(AbsPathView i_path, Mode i_mode, SinkFlags i_flags = SinkFlags()) override; + OpenMapSinkResult openMapSink(AbsPathView i_path, Mode i_mode, size_t i_size, SinkFlags i_flags = SinkFlags()) override; - RemoveResult remove(const AbsPath& i_path) override; - RenameResult rename(const AbsPath& i_path, const AbsPath& i_newPath) override; + RemoveResult remove(AbsPathView i_path) override; + RenameResult rename(AbsPathView i_path, AbsPathView i_newPath) override; - MakeFolderResult makeFolder(const AbsPath& i_path) override; - RemoveRecursivelyResult removeRecursively(const AbsPath& i_path) override; + MakeFolderResult makeFolder(AbsPathView i_path) override; + RemoveRecursivelyResult removeRecursively(AbsPathView i_path) override; - SetWriteTimeResult setWriteTime(const AbsPath& i_path, time_t i_time) override; + SetWriteTimeResult setWriteTime(AbsPathView i_path, time_t i_time) override; }; } diff --git a/include/fs/zip/DeflateFileWriter.h b/include/fs/zip/DeflateFileWriter.h index bce5ffd..dbb3059 100644 --- a/include/fs/zip/DeflateFileWriter.h +++ b/include/fs/zip/DeflateFileWriter.h @@ -16,7 +16,7 @@ class FS_API DeflateFileWriter { public: //compression level: 0 to 9 - DeflateFileWriter(AbsPath i_filePath, tl::lent_ref i_filesystem, uint8_t i_compressionLevel); + DeflateFileWriter(AbsPathView filePath, tl::lent_ref filesystem, uint8_t compressionLevel); DeflateFileWriter(const DeflateFileWriter&) = delete; DeflateFileWriter& operator=(const DeflateFileWriter&) = delete; @@ -24,7 +24,7 @@ public: DeflateFileWriter(DeflateFileWriter&&) = default; DeflateFileWriter& operator=(DeflateFileWriter&&) = default; - ZipWriter::DataWriterResult operator()(IStreamSink& i_sink); + ZipWriter::DataWriterResult operator()(IStreamSink& sink); private: AbsPath m_filePath; diff --git a/include/fs/zip/StoreFileWriter.h b/include/fs/zip/StoreFileWriter.h index 17cd15d..c2349e9 100644 --- a/include/fs/zip/StoreFileWriter.h +++ b/include/fs/zip/StoreFileWriter.h @@ -15,7 +15,7 @@ class IFilesystem; class FS_API StoreFileWriter { public: - StoreFileWriter(AbsPath i_filePath, tl::lent_ref i_filesystem); + StoreFileWriter(AbsPathView filePath, tl::lent_ref filesystem); StoreFileWriter(const StoreFileWriter&) = delete; StoreFileWriter& operator=(const StoreFileWriter&) = delete; @@ -23,7 +23,7 @@ public: StoreFileWriter(StoreFileWriter&&) = default; StoreFileWriter& operator=(StoreFileWriter&&) = default; - ZipWriter::DataWriterResult operator()(IStreamSink& i_sink); + ZipWriter::DataWriterResult operator()(IStreamSink& sink); private: AbsPath m_filePath; diff --git a/include/fs/zip/ZipPack.h b/include/fs/zip/ZipPack.h index 1b24d53..6f6574e 100644 --- a/include/fs/zip/ZipPack.h +++ b/include/fs/zip/ZipPack.h @@ -23,24 +23,24 @@ public: typedef tl::result, Error> CreateResult; static CreateResult create(tl::unique_ref zipFileSource); - static CreateResult create(tl::lent_ref filesystem, AbsPath zipFileLocation); + static CreateResult create(tl::lent_ref filesystem, AbsPathView zipFileLocation); virtual void setEncryptionData(const tl::string& key, uint32_t rounds); - OpenSourceResult openSource(const AbsPath& path, SourceFlags flags = SourceFlags()) const override; - OpenStreamSourceResult openStreamSource(const AbsPath& path, SourceFlags flags = SourceFlags()) const override; - OpenMapSourceResult openMapSource(const AbsPath& path, MapView mapView = MapView(), SourceFlags flags = SourceFlags()) const override; + OpenSourceResult openSource(AbsPathView path, SourceFlags flags = SourceFlags()) const override; + OpenStreamSourceResult openStreamSource(AbsPathView path, SourceFlags flags = SourceFlags()) const override; + OpenMapSourceResult openMapSource(AbsPathView path, MapView mapView = MapView(), SourceFlags flags = SourceFlags()) const override; - IsFileResult isFile(const AbsPath& path) const override; - IsFolderResult isFolder(const AbsPath& path) const override; - ExistsResult exists(const AbsPath& path) const override; + IsFileResult isFile(AbsPathView path) const override; + IsFolderResult isFolder(AbsPathView path) const override; + ExistsResult exists(AbsPathView path) const override; - GetStatResult getStat(const AbsPath& path) const override; + GetStatResult getStat(AbsPathView path) const override; - cppcoro::generator enumerate(const AbsPath& path) const override; - cppcoro::generator enumerateRecursively(const AbsPath& path) const override; + cppcoro::generator enumerate(AbsPathView path) const override; + cppcoro::generator enumerateRecursively(AbsPathView path) const override; - tl::result convertToNativePath(const AbsPath& path) const override; + tl::result convertToNativePath(AbsPathView path) const override; protected: struct File; @@ -48,7 +48,7 @@ protected: struct EntryIndex; ZipPack(tl::unique_ref zipFileSource, ZipReader zipReader); - ZipPack(tl::lent_ref filesystem, AbsPath zipFileLocation, ZipReader zipReader); + ZipPack(tl::lent_ref filesystem, AbsPathView zipFileLocation, ZipReader zipReader); OpenMapSourceResult openRawMapSource(const File& file, MapView mapView) const; OpenSourceResult openRawSource(const File& file) const; @@ -57,7 +57,7 @@ protected: OpenMapSourceResult openZipMapSource(const File& file) const; OpenStreamSourceResult openZipStreamSource(const File& file) const; - uint16_t getOrAddFolder(AbsPath folderPath, tl::vector>& io_childrenIndices); + uint16_t getOrAddFolder(AbsPathView folderPath, tl::vector>& io_childrenIndices); void createEntries(ZipReader zipReader); struct File diff --git a/include/fs/zip/ZipUtils.h b/include/fs/zip/ZipUtils.h index eacda52..43a8063 100644 --- a/include/fs/zip/ZipUtils.h +++ b/include/fs/zip/ZipUtils.h @@ -9,11 +9,11 @@ namespace fs class ISink; typedef tl::result UnzipResult; -FS_API UnzipResult unzipSource(IFilesystem& dstFilesystem, const AbsPath& filePath, tl::unique_ref source); -FS_API UnzipResult unzipFile(IFilesystem& dstFilesystem, const AbsPath& filePath, tl::lent_ref filesystem, AbsPath srcFilePath); +FS_API UnzipResult unzipSource(IFilesystem& dstFilesystem, AbsPathView filePath, tl::unique_ref source); +FS_API UnzipResult unzipFile(IFilesystem& dstFilesystem, AbsPathView filePath, tl::lent_ref filesystem, AbsPathView srcFilePath); typedef tl::result ZipResult; -FS_API ZipResult zipToSink(ISink& sink, tl::lent_ref filesystem, const AbsPath& path, uint8_t compressionLevel, size_t fileDataAlignment = 0); -FS_API ZipResult zipToFile(IFilesystem& dstFilesystem, const AbsPath& dstFilePath, tl::lent_ref filesystem, const AbsPath& path, uint8_t compressionLevel, size_t fileDataAlignment = 0); +FS_API ZipResult zipToSink(ISink& sink, tl::lent_ref filesystem, AbsPathView path, uint8_t compressionLevel, size_t fileDataAlignment = 0); +FS_API ZipResult zipToFile(IFilesystem& dstFilesystem, AbsPathView dstFilePath, tl::lent_ref filesystem, AbsPathView path, uint8_t compressionLevel, size_t fileDataAlignment = 0); } diff --git a/src/CRCStream.cpp b/src/CRCStream.cpp index d1f3864..aa8f01f 100644 --- a/src/CRCStream.cpp +++ b/src/CRCStream.cpp @@ -210,7 +210,7 @@ CRC32StreamResult crc32Stream(IStreamSource& source, uint32_t crc, size_t buffer ////////////////////////////////////////////////////////////////////////// -CRC32StreamResult crc32File(const IFilesystem& filesystem, const AbsPath& filePath, uint32_t crc, size_t bufferSize) +CRC32StreamResult crc32File(const IFilesystem& filesystem, AbsPathView filePath, uint32_t crc, size_t bufferSize) { OUTCOME_TRY(const auto source, filesystem.openStreamSource(filePath, IFilesystem::SourceFlags(IFilesystem::SourceFlag::SequentialHint, IFilesystem::SourceFlag::Unbuffered))); return crc32Stream(*source, crc, bufferSize); @@ -245,7 +245,7 @@ CRC64StreamResult crc64Stream(IStreamSource& source, uint64_t crc, size_t buffer ////////////////////////////////////////////////////////////////////////// -CRC64StreamResult crc64File(const IFilesystem& filesystem, const AbsPath& filePath, uint64_t crc, size_t bufferSize) +CRC64StreamResult crc64File(const IFilesystem& filesystem, AbsPathView filePath, uint64_t crc, size_t bufferSize) { OUTCOME_TRY(const auto source, filesystem.openStreamSource(filePath, IFilesystem::SourceFlags(IFilesystem::SourceFlag::SequentialHint, IFilesystem::SourceFlag::Unbuffered))); return crc64Stream(*source, crc, bufferSize); diff --git a/src/CopyStream.cpp b/src/CopyStream.cpp index 060b966..f4951ae 100644 --- a/src/CopyStream.cpp +++ b/src/CopyStream.cpp @@ -60,7 +60,7 @@ CopyStreamResult copyStream(IStreamSink& sink, IStreamSource& source, const Proc ////////////////////////////////////////////////////////////////////////// -CopyStreamResult copyFile(IStreamSink& sink, const IFilesystem& filesystem, const AbsPath& filePath, size_t bufferSize) +CopyStreamResult copyFile(IStreamSink& sink, const IFilesystem& filesystem, AbsPathView filePath, size_t bufferSize) { OUTCOME_TRY(const auto source, filesystem.openStreamSource(filePath, IFilesystem::SourceFlags(IFilesystem::SourceFlag::SequentialHint, IFilesystem::SourceFlag::Unbuffered))); return copyStream(sink, *source, bufferSize); @@ -68,13 +68,13 @@ CopyStreamResult copyFile(IStreamSink& sink, const IFilesystem& filesystem, cons ////////////////////////////////////////////////////////////////////////// -CopyStreamResult copyFile(IStreamSink& sink, const IFilesystem& filesystem, const AbsPath& filePath, const ProcessDataCallback& dataCallback, size_t bufferSize) +CopyStreamResult copyFile(IStreamSink& sink, const IFilesystem& filesystem, AbsPathView filePath, const ProcessDataCallback& dataCallback, size_t bufferSize) { OUTCOME_TRY(const auto source, filesystem.openStreamSource(filePath, IFilesystem::SourceFlags(IFilesystem::SourceFlag::SequentialHint, IFilesystem::SourceFlag::Unbuffered))); return copyStream(sink, *source, dataCallback, bufferSize); } -CopyStreamResult copyFile(IFilesystem& dstFilesystem, const AbsPath& dstFilePath, const IFilesystem& srcFilesystem, const AbsPath& srcFilePath, size_t bufferSize) +CopyStreamResult copyFile(IFilesystem& dstFilesystem, AbsPathView dstFilePath, const IFilesystem& srcFilesystem, AbsPathView srcFilePath, size_t bufferSize) { OUTCOME_TRY(const auto sink, dstFilesystem.openStreamSink(dstFilePath, fs::Mode::CreateOrOpenAndClear)); OUTCOME_TRY(const auto source, srcFilesystem.openStreamSource(srcFilePath, IFilesystem::SourceFlags(IFilesystem::SourceFlag::SequentialHint, IFilesystem::SourceFlag::Unbuffered))); diff --git a/src/CustomFilesystem.cpp b/src/CustomFilesystem.cpp index b738f42..71012eb 100644 --- a/src/CustomFilesystem.cpp +++ b/src/CustomFilesystem.cpp @@ -25,14 +25,14 @@ tl::atomic s_lastId(0); ////////////////////////////////////////////////////////////////////////// -tl::result CustomFilesystem::mountFront(AbsPath mountPoint, tl::unique_ref pack) +tl::result CustomFilesystem::mountFront(AbsPathView mountPoint, tl::unique_ref pack) { return mount(std::move(mountPoint), std::move(pack), MountPolicy::Front); } ////////////////////////////////////////////////////////////////////////// -tl::result CustomFilesystem::mountBack(AbsPath mountPoint, tl::unique_ref pack) +tl::result CustomFilesystem::mountBack(AbsPathView mountPoint, tl::unique_ref pack) { return mount(std::move(mountPoint), std::move(pack), MountPolicy::Back); } @@ -67,7 +67,7 @@ tl::unique_ptr CustomFilesystem::unmount(PackId packId) ////////////////////////////////////////////////////////////////////////// -OpenSourceResult CustomFilesystem::openSource(const AbsPath& path, SourceFlags flags) const +OpenSourceResult CustomFilesystem::openSource(AbsPathView path, SourceFlags flags) const { AbsPath filePackPath; for (const auto& pd : m_packsData) @@ -93,7 +93,7 @@ OpenSourceResult CustomFilesystem::openSource(const AbsPath& path, SourceFlags f ////////////////////////////////////////////////////////////////////////// -OpenStreamSourceResult CustomFilesystem::openStreamSource(const AbsPath& path, SourceFlags flags) const +OpenStreamSourceResult CustomFilesystem::openStreamSource(AbsPathView path, SourceFlags flags) const { AbsPath filePackPath; for (const auto& pd : m_packsData) @@ -119,7 +119,7 @@ OpenStreamSourceResult CustomFilesystem::openStreamSource(const AbsPath& path, S ////////////////////////////////////////////////////////////////////////// -OpenMapSourceResult CustomFilesystem::openMapSource(const AbsPath& path, MapView mapView, SourceFlags flags) const +OpenMapSourceResult CustomFilesystem::openMapSource(AbsPathView path, MapView mapView, SourceFlags flags) const { AbsPath filePackPath; for (const auto& pd : m_packsData) @@ -145,7 +145,7 @@ OpenMapSourceResult CustomFilesystem::openMapSource(const AbsPath& path, MapView ////////////////////////////////////////////////////////////////////////// -OpenMapSinkResult CustomFilesystem::openMapSink(const AbsPath& path, Mode mode, size_t size, SinkFlags flags) +OpenMapSinkResult CustomFilesystem::openMapSink(AbsPathView path, Mode mode, size_t size, SinkFlags flags) { AbsPath filePackPath; for (const auto& pd : m_packsData) @@ -172,7 +172,7 @@ OpenMapSinkResult CustomFilesystem::openMapSink(const AbsPath& path, Mode mode, ////////////////////////////////////////////////////////////////////////// -OpenSinkResult CustomFilesystem::openSink(const AbsPath& path, Mode mode, SinkFlags flags) +OpenSinkResult CustomFilesystem::openSink(AbsPathView path, Mode mode, SinkFlags flags) { AbsPath filePackPath; for (const auto& pd : m_packsData) @@ -197,7 +197,7 @@ OpenSinkResult CustomFilesystem::openSink(const AbsPath& path, Mode mode, SinkFl ////////////////////////////////////////////////////////////////////////// -OpenStreamSinkResult CustomFilesystem::openStreamSink(const AbsPath& path, Mode mode, SinkFlags flags) +OpenStreamSinkResult CustomFilesystem::openStreamSink(AbsPathView path, Mode mode, SinkFlags flags) { AbsPath filePackPath; for (const auto& pd : m_packsData) @@ -222,7 +222,7 @@ OpenStreamSinkResult CustomFilesystem::openStreamSink(const AbsPath& path, Mode ////////////////////////////////////////////////////////////////////////// -ExistsResult CustomFilesystem::exists(const AbsPath& path) const +ExistsResult CustomFilesystem::exists(AbsPathView path) const { AbsPath filePackPath; for (const auto& pd : m_packsData) @@ -252,7 +252,7 @@ ExistsResult CustomFilesystem::exists(const AbsPath& path) const ////////////////////////////////////////////////////////////////////////// -IsFileResult CustomFilesystem::isFile(const AbsPath& path) const +IsFileResult CustomFilesystem::isFile(AbsPathView path) const { AbsPath filePackPath; for (const auto& pd : m_packsData) @@ -277,7 +277,7 @@ IsFileResult CustomFilesystem::isFile(const AbsPath& path) const ////////////////////////////////////////////////////////////////////////// -RenameResult CustomFilesystem::rename(const AbsPath& path, const AbsPath& newPath) +RenameResult CustomFilesystem::rename(AbsPathView path, AbsPathView newPath) { AbsPath fromPackPath; AbsPath toPackPath; @@ -304,7 +304,7 @@ RenameResult CustomFilesystem::rename(const AbsPath& path, const AbsPath& newPat ////////////////////////////////////////////////////////////////////////// -CopyResult CustomFilesystem::copy(const AbsPath& path, const AbsPath& newPath) +CopyResult CustomFilesystem::copy(AbsPathView path, AbsPathView newPath) { OUTCOME_TRY(const auto source, openStreamSource(path, SourceFlags(SourceFlag::SequentialHint, SourceFlag::Uncached))); OUTCOME_TRY(const auto destination, openStreamSink(newPath, Mode::CreateOrOpenAndClear)); @@ -318,7 +318,7 @@ CopyResult CustomFilesystem::copy(const AbsPath& path, const AbsPath& newPath) ////////////////////////////////////////////////////////////////////////// -MakeHardLinkResult CustomFilesystem::makeHardLink(const AbsPath& sourcePath, const AbsPath& linkPath) +MakeHardLinkResult CustomFilesystem::makeHardLink(AbsPathView sourcePath, AbsPathView linkPath) { OUTCOME_TRY(const auto sp, convertToNativePath(sourcePath)); OUTCOME_TRY(const auto lp, convertToNativePath(linkPath)); @@ -327,7 +327,7 @@ MakeHardLinkResult CustomFilesystem::makeHardLink(const AbsPath& sourcePath, con ////////////////////////////////////////////////////////////////////////// -MakeSoftLinkResult CustomFilesystem::makeSymLink(const AbsPath& sourcePath, const AbsPath& linkPath) +MakeSoftLinkResult CustomFilesystem::makeSymLink(AbsPathView sourcePath, AbsPathView linkPath) { OUTCOME_TRY(const auto sp, convertToNativePath(sourcePath)); OUTCOME_TRY(const auto lp, convertToNativePath(linkPath)); @@ -336,7 +336,7 @@ MakeSoftLinkResult CustomFilesystem::makeSymLink(const AbsPath& sourcePath, cons ////////////////////////////////////////////////////////////////////////// -IsFolderResult CustomFilesystem::isFolder(const AbsPath& path) const +IsFolderResult CustomFilesystem::isFolder(AbsPathView path) const { AbsPath folderPackPath; for (const auto& pd : m_packsData) @@ -360,7 +360,7 @@ IsFolderResult CustomFilesystem::isFolder(const AbsPath& path) const ////////////////////////////////////////////////////////////////////////// -MakeFolderResult CustomFilesystem::makeFolder(const AbsPath& path) +MakeFolderResult CustomFilesystem::makeFolder(AbsPathView path) { AbsPath filePackPath; for (const auto& pd : m_packsData) @@ -387,7 +387,7 @@ MakeFolderResult CustomFilesystem::makeFolder(const AbsPath& path) ////////////////////////////////////////////////////////////////////////// -RemoveResult CustomFilesystem::remove(const AbsPath& path) +RemoveResult CustomFilesystem::remove(AbsPathView path) { AbsPath filePackPath; for (const auto& pd : m_packsData) @@ -412,7 +412,7 @@ RemoveResult CustomFilesystem::remove(const AbsPath& path) ////////////////////////////////////////////////////////////////////////// -RemoveRecursivelyResult CustomFilesystem::removeRecursively(const AbsPath& path) +RemoveRecursivelyResult CustomFilesystem::removeRecursively(AbsPathView path) { for (const EnumerateEntry& ee : enumerate(path)) { @@ -432,7 +432,7 @@ RemoveRecursivelyResult CustomFilesystem::removeRecursively(const AbsPath& path) ////////////////////////////////////////////////////////////////////////// -ConvertToNativePathResult CustomFilesystem::convertToNativePath(const AbsPath& path) const +ConvertToNativePathResult CustomFilesystem::convertToNativePath(AbsPathView path) const { AbsPath folderPackPath; for (const auto& pd : m_packsData) @@ -453,7 +453,7 @@ ConvertToNativePathResult CustomFilesystem::convertToNativePath(const AbsPath& p ////////////////////////////////////////////////////////////////////////// -SetWriteTimeResult CustomFilesystem::setWriteTime(const AbsPath& path, time_t time) +SetWriteTimeResult CustomFilesystem::setWriteTime(AbsPathView path, time_t time) { AbsPath filePackPath; for (const auto& pd : m_packsData) @@ -478,7 +478,7 @@ SetWriteTimeResult CustomFilesystem::setWriteTime(const AbsPath& path, time_t ti ////////////////////////////////////////////////////////////////////////// -GetStatResult CustomFilesystem::getStat(const AbsPath& path) const +GetStatResult CustomFilesystem::getStat(AbsPathView path) const { AbsPath folderPackPath; for (const auto& pd : m_packsData) @@ -499,7 +499,7 @@ GetStatResult CustomFilesystem::getStat(const AbsPath& path) const ////////////////////////////////////////////////////////////////////////// -cppcoro::generator CustomFilesystem::enumerate(const AbsPath& path) const +cppcoro::generator CustomFilesystem::enumerate(AbsPathView path) const { AbsPath basePackPath; for (const auto& pd : m_packsData) @@ -521,16 +521,19 @@ cppcoro::generator CustomFilesystem::enumerate(const AbsPath& pa ////////////////////////////////////////////////////////////////////////// -cppcoro::generator CustomFilesystem::enumerateRecursively(const AbsPath& path) const +cppcoro::generator CustomFilesystem::enumerateRecursively(AbsPathView path) const { tl::unordered_set checkedFiles; + const AbsPath rootPath(path); + //Note, the path might not survive after the first co_yield, if it came from a rvalue, in some conditions, so use the rootPath + AbsPath basePackPath; for (const auto& pd : m_packsData) { - if (pd.mountPoint.is_prefix_of(path)) + if (pd.mountPoint.is_prefix_of(rootPath)) { - convertToPackPath(basePackPath, path, pd.mountPoint); + convertToPackPath(basePackPath, rootPath, pd.mountPoint); if (!basePackPath.empty()) { @@ -545,13 +548,17 @@ cppcoro::generator CustomFilesystem::enumerateRecursively(const co_yield std::move(ee); } } - else if (path.is_prefix_of(pd.mountPoint)) + else if (rootPath.is_prefix_of(pd.mountPoint)) { - const RelPath parentPath = path.path_to(pd.mountPoint); + const RelPathView parentPath = rootPath.path_to(pd.mountPoint); + RelPath p = parentPath; for (EnumerateEntry ee : pd.pack->enumerateRecursively(AbsPath(PosixRootTag::value()))) { - ee.path = parentPath + ee.path; + const size_t eePathSize = ee.path.size(); + p += ee.path; + ee.path = p; + p.shrink(eePathSize); if (checkedFiles.insert(ee.path).second) co_yield std::move(ee); } @@ -561,19 +568,19 @@ cppcoro::generator CustomFilesystem::enumerateRecursively(const ////////////////////////////////////////////////////////////////////////// -void CustomFilesystem::convertToPackPath(AbsPath& packPath, const AbsPath& path, const AbsPath& mountPoint) const +void CustomFilesystem::convertToPackPath(AbsPath& packPath, AbsPathView path, AbsPathView mountPoint) const { - RelPath basePath = mountPoint.path_to(path); + RelPathView basePath = mountPoint.prefix_path_to(path); packPath = PosixRootTag::value(); packPath.reserve(basePath.size() + 1); - for (tl::string& element : basePath) - packPath.push_back(std::move(element)); + for (const tl::string& element : basePath) + packPath.push_back(element); } ////////////////////////////////////////////////////////////////////////// -tl::result CustomFilesystem::mount(AbsPath mountPoint, tl::unique_ref pack, MountPolicy policy) +tl::result CustomFilesystem::mount(AbsPathView mountPoint, tl::unique_ref pack, MountPolicy policy) { if (!mountPoint.is_valid()) diff --git a/src/FileMapSink.cpp b/src/FileMapSink.cpp index 1d2ea9f..270bdbb 100644 --- a/src/FileMapSink.cpp +++ b/src/FileMapSink.cpp @@ -14,7 +14,7 @@ struct FileMapSink::Impl mio::ummap_sink sink; }; -FileMapSink::FileMapSink(const AbsPath& filepath, +FileMapSink::FileMapSink(AbsPathView filepath, size_t size, Mode mode /*= Mode::CreateOrOpenAndClear*/, Flags flags /*= Flags()*/) diff --git a/src/FileMapSource.cpp b/src/FileMapSource.cpp index 3dbda01..07125e5 100644 --- a/src/FileMapSource.cpp +++ b/src/FileMapSource.cpp @@ -18,7 +18,7 @@ struct FileMapSource::Impl mio::ummap_source source; }; -FileMapSource::FileMapSource(const AbsPath& filepath) +FileMapSource::FileMapSource(AbsPathView filepath) { std::error_code error; mio::ummap_source mmap; @@ -34,7 +34,7 @@ FileMapSource::FileMapSource(const AbsPath& filepath) ////////////////////////////////////////////////////////////////////////// -FileMapSource::FileMapSource(const AbsPath& filepath, uint64_t start, size_t size) +FileMapSource::FileMapSource(AbsPathView filepath, uint64_t start, size_t size) { std::error_code error; mio::ummap_source mmap; diff --git a/src/FileSink.cpp b/src/FileSink.cpp index 3cdf10b..51afef6 100644 --- a/src/FileSink.cpp +++ b/src/FileSink.cpp @@ -45,7 +45,7 @@ namespace fs { ////////////////////////////////////////////////////////////////////////// -FileSink::FileSink(const AbsPath& filepath, Mode mode, Flags flags) noexcept +FileSink::FileSink(AbsPathView filepath, Mode mode, Flags flags) noexcept { fast_io::open_mode fmode = fast_io::open_mode::out; diff --git a/src/FileSource.cpp b/src/FileSource.cpp index dfe9b6f..f8f44f4 100644 --- a/src/FileSource.cpp +++ b/src/FileSource.cpp @@ -18,9 +18,9 @@ namespace fs namespace native_utils { -extern int validateCaseSensitiveFilename(const AbsPath& filepath, int fd); +extern int validateCaseSensitiveFilename(AbsPathView filepath, int fd); #if defined (TL_PLATFORM_WINDOWS_FAMILY) -extern int validateCaseSensitiveFilename(const AbsPath& filepath, HANDLE handle); +extern int validateCaseSensitiveFilename(AbsPathView filepath, HANDLE handle); #endif } @@ -74,14 +74,14 @@ FileSource& FileSource::operator=(FileSource&& other) noexcept ////////////////////////////////////////////////////////////////////////// -FileSource::FileSource(const AbsPath& filepath) noexcept +FileSource::FileSource(AbsPathView filepath) noexcept : FileSource(filepath, Flags()) { } ////////////////////////////////////////////////////////////////////////// -FileSource::FileSource(const AbsPath& filepath, Flags flags) noexcept +FileSource::FileSource(AbsPathView filepath, Flags flags) noexcept { const tl::string pathStr = filepath.str(); diff --git a/src/FolderPack.cpp b/src/FolderPack.cpp index f15fcc8..da7d3fa 100644 --- a/src/FolderPack.cpp +++ b/src/FolderPack.cpp @@ -9,7 +9,7 @@ namespace fs { ////////////////////////////////////////////////////////////////////////// -FolderPack::FolderPack(AbsPath location) +FolderPack::FolderPack(AbsPathView location) : m_filesystem(tl::lend(native)) , m_location(std::move(location)) { @@ -19,7 +19,7 @@ FolderPack::FolderPack(AbsPath location) ////////////////////////////////////////////////////////////////////////// -FolderPack::FolderPack(tl::lent_ref filesystem, AbsPath location) +FolderPack::FolderPack(tl::lent_ref filesystem, AbsPathView location) : m_filesystem(std::move(filesystem)) , m_location(std::move(location)) { @@ -29,56 +29,56 @@ FolderPack::FolderPack(tl::lent_ref filesystem, AbsPath location) ////////////////////////////////////////////////////////////////////////// -OpenSourceResult FolderPack::openSource(const AbsPath& path, SourceFlags flags) const +OpenSourceResult FolderPack::openSource(AbsPathView path, SourceFlags flags) const { return m_filesystem->openSource(convertToUnderlyingPath(path), flags); } ////////////////////////////////////////////////////////////////////////// -OpenStreamSourceResult FolderPack::openStreamSource(const AbsPath& path, SourceFlags flags) const +OpenStreamSourceResult FolderPack::openStreamSource(AbsPathView path, SourceFlags flags) const { return m_filesystem->openStreamSource(convertToUnderlyingPath(path), flags); } ////////////////////////////////////////////////////////////////////////// -OpenMapSourceResult FolderPack::openMapSource(const AbsPath& path, MapView mapView, SourceFlags flags) const +OpenMapSourceResult FolderPack::openMapSource(AbsPathView path, MapView mapView, SourceFlags flags) const { return m_filesystem->openMapSource(convertToUnderlyingPath(path), mapView, flags); } ////////////////////////////////////////////////////////////////////////// -IsFileResult FolderPack::isFile(const AbsPath& path) const +IsFileResult FolderPack::isFile(AbsPathView path) const { return m_filesystem->isFile(convertToUnderlyingPath(path)); } ////////////////////////////////////////////////////////////////////////// -IsFolderResult FolderPack::isFolder(const AbsPath& path) const +IsFolderResult FolderPack::isFolder(AbsPathView path) const { return m_filesystem->isFolder(convertToUnderlyingPath(path)); } ////////////////////////////////////////////////////////////////////////// -ExistsResult FolderPack::exists(const AbsPath& path) const +ExistsResult FolderPack::exists(AbsPathView path) const { return m_filesystem->exists(convertToUnderlyingPath(path)); } ////////////////////////////////////////////////////////////////////////// -GetStatResult FolderPack::getStat(const AbsPath& path) const +GetStatResult FolderPack::getStat(AbsPathView path) const { return m_filesystem->getStat(convertToUnderlyingPath(path)); } ////////////////////////////////////////////////////////////////////////// -cppcoro::generator FolderPack::enumerate(const AbsPath& path) const +cppcoro::generator FolderPack::enumerate(AbsPathView path) const { const AbsPath localPath = convertToUnderlyingPath(path); for (EnumerateEntry ee : m_filesystem->enumerate(localPath)) @@ -87,7 +87,7 @@ cppcoro::generator FolderPack::enumerate(const AbsPath& path) co ////////////////////////////////////////////////////////////////////////// -cppcoro::generator FolderPack::enumerateRecursively(const AbsPath& path) const +cppcoro::generator FolderPack::enumerateRecursively(AbsPathView path) const { const AbsPath localPath = convertToUnderlyingPath(path); for (EnumerateEntry ee : m_filesystem->enumerateRecursively(localPath)) @@ -96,7 +96,7 @@ cppcoro::generator FolderPack::enumerateRecursively(const AbsPat ////////////////////////////////////////////////////////////////////////// -AbsPath FolderPack::convertToUnderlyingPath(const AbsPath& path) const +AbsPath FolderPack::convertToUnderlyingPath(AbsPathView path) const { AbsPath filePath; filePath.reserve(m_location.size() + path.size()); @@ -109,7 +109,7 @@ AbsPath FolderPack::convertToUnderlyingPath(const AbsPath& path) const ////////////////////////////////////////////////////////////////////////// -ConvertToNativePathResult FolderPack::convertToNativePath(const AbsPath& path) const +ConvertToNativePathResult FolderPack::convertToNativePath(AbsPathView path) const { return m_filesystem->convertToNativePath(convertToUnderlyingPath(path)); } diff --git a/src/NativeFilesystem.cpp b/src/NativeFilesystem.cpp index 773ef35..f8c5753 100644 --- a/src/NativeFilesystem.cpp +++ b/src/NativeFilesystem.cpp @@ -28,7 +28,7 @@ FS_API NativeFilesystem native(NativeFilesystem::CheckFlag::ValidatePathCase); FS_API NativeFilesystem nativeRaw; ////////////////////////////////////////////////////////////////////////// -std::filesystem::path toStdPath(const AbsPath& path) noexcept +std::filesystem::path toStdPath(AbsPathView path) noexcept { const tl::string str = path.str(); return { str.data(), str.data() + str.size() }; @@ -124,7 +124,7 @@ NativeFilesystem::NativeFilesystem(CheckFlags checkFlags) ////////////////////////////////////////////////////////////////////////// -OpenSourceResult NativeFilesystem::openSource(const AbsPath& path, SourceFlags flags) const +OpenSourceResult NativeFilesystem::openSource(AbsPathView path, SourceFlags flags) const { if (!path.is_valid()) return tl::make_error(ErrorCode::BadPath, "Invalid Path"); @@ -158,7 +158,7 @@ OpenSourceResult NativeFilesystem::openSource(const AbsPath& path, SourceFlags f ////////////////////////////////////////////////////////////////////////// -OpenStreamSourceResult NativeFilesystem::openStreamSource(const AbsPath& path, SourceFlags flags) const +OpenStreamSourceResult NativeFilesystem::openStreamSource(AbsPathView path, SourceFlags flags) const { OUTCOME_TRY(auto source, openSource(path, flags)); return source; @@ -166,7 +166,7 @@ OpenStreamSourceResult NativeFilesystem::openStreamSource(const AbsPath& path, S ////////////////////////////////////////////////////////////////////////// -OpenMapSourceResult NativeFilesystem::openMapSource(const AbsPath& path, MapView mapView, SourceFlags flags) const +OpenMapSourceResult NativeFilesystem::openMapSource(AbsPathView path, MapView mapView, SourceFlags flags) const { if (!path.is_valid()) return tl::make_error(ErrorCode::BadPath, "Invalid Path"); @@ -184,7 +184,7 @@ OpenMapSourceResult NativeFilesystem::openMapSource(const AbsPath& path, MapView ////////////////////////////////////////////////////////////////////////// -OpenSinkResult NativeFilesystem::openSink(const AbsPath& path, Mode mode, SinkFlags flags) +OpenSinkResult NativeFilesystem::openSink(AbsPathView path, Mode mode, SinkFlags flags) { if (!path.is_valid()) return tl::make_error(ErrorCode::BadPath, "Invalid Path"); @@ -202,7 +202,7 @@ OpenSinkResult NativeFilesystem::openSink(const AbsPath& path, Mode mode, SinkFl ////////////////////////////////////////////////////////////////////////// -OpenStreamSinkResult NativeFilesystem::openStreamSink(const AbsPath& path, Mode mode, SinkFlags flags) +OpenStreamSinkResult NativeFilesystem::openStreamSink(AbsPathView path, Mode mode, SinkFlags flags) { OUTCOME_TRY(auto source, openSink(path, mode, flags)); return source; @@ -210,7 +210,7 @@ OpenStreamSinkResult NativeFilesystem::openStreamSink(const AbsPath& path, Mode ////////////////////////////////////////////////////////////////////////// -OpenMapSinkResult NativeFilesystem::openMapSink(const AbsPath& path, Mode mode, size_t size, SinkFlags flags) +OpenMapSinkResult NativeFilesystem::openMapSink(AbsPathView path, Mode mode, size_t size, SinkFlags flags) { if (!path.is_valid()) return tl::make_error(ErrorCode::BadPath, "Invalid Path"); @@ -228,14 +228,14 @@ OpenMapSinkResult NativeFilesystem::openMapSink(const AbsPath& path, Mode mode, ////////////////////////////////////////////////////////////////////////// -ConvertToNativePathResult NativeFilesystem::convertToNativePath(const AbsPath& path) const +ConvertToNativePathResult NativeFilesystem::convertToNativePath(AbsPathView path) const { return path; } ////////////////////////////////////////////////////////////////////////// -ExistsResult NativeFilesystem::exists(const AbsPath& path) const +ExistsResult NativeFilesystem::exists(AbsPathView path) const { if (!path.is_valid()) return tl::make_error(ErrorCode::BadPath, "Invalid Path"); @@ -255,7 +255,7 @@ ExistsResult NativeFilesystem::exists(const AbsPath& path) const ////////////////////////////////////////////////////////////////////////// -IsFileResult NativeFilesystem::isFile(const AbsPath& path) const +IsFileResult NativeFilesystem::isFile(AbsPathView path) const { if (!path.is_valid()) return tl::make_error(ErrorCode::BadPath, "Invalid Path"); @@ -277,7 +277,7 @@ IsFileResult NativeFilesystem::isFile(const AbsPath& path) const ////////////////////////////////////////////////////////////////////////// -IsFolderResult NativeFilesystem::isFolder(const AbsPath& path) const +IsFolderResult NativeFilesystem::isFolder(AbsPathView path) const { if (!path.is_valid()) return tl::make_error(ErrorCode::BadPath, "Invalid Path"); @@ -299,7 +299,7 @@ IsFolderResult NativeFilesystem::isFolder(const AbsPath& path) const ////////////////////////////////////////////////////////////////////////// -RenameResult NativeFilesystem::rename(const AbsPath& path, const AbsPath& newPath) +RenameResult NativeFilesystem::rename(AbsPathView path, AbsPathView newPath) { if (!path.is_valid() || !newPath.is_valid()) return tl::make_error(ErrorCode::BadPath, "Invalid Path"); @@ -321,7 +321,7 @@ RenameResult NativeFilesystem::rename(const AbsPath& path, const AbsPath& newPat ////////////////////////////////////////////////////////////////////////// -CopyResult NativeFilesystem::copy(const AbsPath& path, const AbsPath& newPath) +CopyResult NativeFilesystem::copy(AbsPathView path, AbsPathView newPath) { if (!path.is_valid() || !newPath.is_valid()) return tl::make_error(ErrorCode::BadPath, "Invalid Path"); @@ -345,7 +345,7 @@ CopyResult NativeFilesystem::copy(const AbsPath& path, const AbsPath& newPath) ////////////////////////////////////////////////////////////////////////// -MakeHardLinkResult NativeFilesystem::makeHardLink(const AbsPath& sourcePath, const AbsPath& linkPath) +MakeHardLinkResult NativeFilesystem::makeHardLink(AbsPathView sourcePath, AbsPathView linkPath) { if (!sourcePath.is_valid() || !linkPath.is_valid()) return tl::make_error(ErrorCode::BadPath, "Invalid Path"); @@ -368,7 +368,7 @@ MakeHardLinkResult NativeFilesystem::makeHardLink(const AbsPath& sourcePath, con ////////////////////////////////////////////////////////////////////////// -MakeSoftLinkResult NativeFilesystem::makeSymLink(const AbsPath& sourcePath, const AbsPath& linkPath) +MakeSoftLinkResult NativeFilesystem::makeSymLink(AbsPathView sourcePath, AbsPathView linkPath) { if (!sourcePath.is_valid() || !linkPath.is_valid()) return tl::make_error(ErrorCode::BadPath, "Invalid Path"); @@ -397,7 +397,7 @@ MakeSoftLinkResult NativeFilesystem::makeSymLink(const AbsPath& sourcePath, cons ////////////////////////////////////////////////////////////////////////// -MakeFolderResult NativeFilesystem::makeFolder(const AbsPath& path) +MakeFolderResult NativeFilesystem::makeFolder(AbsPathView path) { if (!path.is_valid()) return tl::make_error(ErrorCode::BadPath, "Invalid Path"); @@ -423,7 +423,7 @@ MakeFolderResult NativeFilesystem::makeFolder(const AbsPath& path) ////////////////////////////////////////////////////////////////////////// -RemoveResult NativeFilesystem::remove(const AbsPath& path) +RemoveResult NativeFilesystem::remove(AbsPathView path) { if (!path.is_valid()) return tl::make_error(ErrorCode::BadPath, "Invalid Path"); @@ -445,7 +445,7 @@ RemoveResult NativeFilesystem::remove(const AbsPath& path) ////////////////////////////////////////////////////////////////////////// -RemoveRecursivelyResult NativeFilesystem::removeRecursively(const AbsPath& path) +RemoveRecursivelyResult NativeFilesystem::removeRecursively(AbsPathView path) { if (!path.is_valid()) return tl::make_error(ErrorCode::BadPath, "Invalid Path"); @@ -472,7 +472,7 @@ RemoveRecursivelyResult NativeFilesystem::removeRecursively(const AbsPath& path) ////////////////////////////////////////////////////////////////////////// -SetWriteTimeResult NativeFilesystem::setWriteTime(const AbsPath& path, time_t time) +SetWriteTimeResult NativeFilesystem::setWriteTime(AbsPathView path, time_t time) { if (!path.is_valid()) return tl::make_error(ErrorCode::BadPath, "Invalid Path"); @@ -499,7 +499,7 @@ SetWriteTimeResult NativeFilesystem::setWriteTime(const AbsPath& path, time_t ti ////////////////////////////////////////////////////////////////////////// -GetStatResult NativeFilesystem::getStat(const AbsPath& path) const +GetStatResult NativeFilesystem::getStat(AbsPathView path) const { if (!path.is_valid()) return tl::make_error(ErrorCode::BadPath, "Invalid Path"); @@ -522,7 +522,7 @@ GetStatResult NativeFilesystem::getStat(const AbsPath& path) const ////////////////////////////////////////////////////////////////////////// -cppcoro::generator NativeFilesystem::enumerate(const AbsPath& path) const +cppcoro::generator NativeFilesystem::enumerate(AbsPathView path) const { TL_ASSERT(path.is_valid()); @@ -536,6 +536,8 @@ cppcoro::generator NativeFilesystem::enumerate(const AbsPath& pa co_return; } + //Note, the path might not survive after the first co_yield, if it came from a rvalue, in some conditions, so if you need it below, make a copy in a AbsPath + for (auto const& entry : std::filesystem::directory_iterator{ toStdPath(path) }) { const auto status = entry.status(); @@ -555,7 +557,7 @@ cppcoro::generator NativeFilesystem::enumerate(const AbsPath& pa ////////////////////////////////////////////////////////////////////////// -cppcoro::generator NativeFilesystem::enumerateRecursively(const AbsPath& path) const +cppcoro::generator NativeFilesystem::enumerateRecursively(AbsPathView path) const { TL_ASSERT(path.is_valid()); @@ -569,8 +571,12 @@ cppcoro::generator NativeFilesystem::enumerateRecursively(const co_return; } + const AbsPath rootPath(path); AbsPath eePath; const auto stdRootPath = toStdPath(path); + + //Note, the path might not survive after the first co_yield, if it came from a rvalue, in some conditions, so use the rootPath + for (auto const& entry : std::filesystem::recursive_directory_iterator{ stdRootPath }) { const auto status = entry.status(); @@ -578,12 +584,12 @@ cppcoro::generator NativeFilesystem::enumerateRecursively(const if (type == std::filesystem::file_type::directory) { toFSAbsPath(eePath, entry.path()); - co_yield{ path.path_to(eePath), true }; + co_yield{ rootPath.path_to(eePath), true }; } else if (type == std::filesystem::file_type::regular) { toFSAbsPath(eePath, entry.path()); - co_yield{ path.path_to(eePath), false }; + co_yield{ rootPath.path_to(eePath), false }; } } } @@ -599,7 +605,7 @@ AbsPath NativeFilesystem::getCurrentFolder() const ////////////////////////////////////////////////////////////////////////// -tl::result NativeFilesystem::setCurrentFolder(const AbsPath& path) +tl::result NativeFilesystem::setCurrentFolder(AbsPathView path) { if (!path.is_valid()) return tl::make_error(Error::code_t::BadPath, "Path empty"); @@ -621,7 +627,7 @@ tl::result NativeFilesystem::setCurrentFolder(const AbsPath& path) ////////////////////////////////////////////////////////////////////////// -NativeFilesystem::EnumerateFilesResult NativeFilesystem::enumerateFiles(const AbsPath& fullPath) const +NativeFilesystem::EnumerateFilesResult NativeFilesystem::enumerateFiles(AbsPathView fullPath) const { tl::vector files; for (EnumerateEntry ee: enumerate(fullPath)) @@ -637,7 +643,7 @@ NativeFilesystem::EnumerateFilesResult NativeFilesystem::enumerateFiles(const Ab ////////////////////////////////////////////////////////////////////////// -NativeFilesystem::EnumerateFoldersResult NativeFilesystem::enumerateFolders(const AbsPath& fullPath) const +NativeFilesystem::EnumerateFoldersResult NativeFilesystem::enumerateFolders(AbsPathView fullPath) const { tl::vector folders; for (EnumerateEntry ee : enumerate(fullPath)) diff --git a/src/NativeUtils.cpp b/src/NativeUtils.cpp index e29b5eb..c4925f4 100644 --- a/src/NativeUtils.cpp +++ b/src/NativeUtils.cpp @@ -62,14 +62,14 @@ bool isCapitalizationCorrect(const tl::string& str, HANDLE handle) noexcept ////////////////////////////////////////////////////////////////////////// -bool isCapitalizationCorrect(const AbsPath& path, HANDLE handle) noexcept +bool isCapitalizationCorrect(AbsPathView path, HANDLE handle) noexcept { return isCapitalizationCorrect(path.str(), handle); } ////////////////////////////////////////////////////////////////////////// -static bool isFileCapitalizationCorrect(const AbsPath& filePath) noexcept +static bool isFileCapitalizationCorrect(AbsPathView filePath) noexcept { const tl::string fileStr = filePath.str(); const char* fileName = fileStr.c_str(); @@ -90,7 +90,7 @@ static bool isFileCapitalizationCorrect(const AbsPath& filePath) noexcept ////////////////////////////////////////////////////////////////////////// -static bool isFolderCapitalizationCorrect(const AbsPath& folderPath) noexcept +static bool isFolderCapitalizationCorrect(AbsPathView folderPath) noexcept { const tl::string folderStr = folderPath.str(); const char* folderName = folderStr.c_str(); @@ -116,7 +116,7 @@ static bool isFolderCapitalizationCorrect(const AbsPath& folderPath) noexcept ////////////////////////////////////////////////////////////////////////// -bool validateCaseSensitiveFilename(const AbsPath& filepath) noexcept +bool validateCaseSensitiveFilename(AbsPathView filepath) noexcept { #ifdef TL_PLATFORM_WINDOWS_DESKTOP_APP return isFileCapitalizationCorrect(filepath); @@ -127,7 +127,7 @@ bool validateCaseSensitiveFilename(const AbsPath& filepath) noexcept ////////////////////////////////////////////////////////////////////////// -bool validateCaseSensitiveFilename(const AbsPath& filepath, int fd) noexcept +bool validateCaseSensitiveFilename(AbsPathView filepath, int fd) noexcept { #ifdef TL_PLATFORM_WINDOWS_DESKTOP_APP const HANDLE handle = (HANDLE)_get_osfhandle(fd); @@ -143,7 +143,7 @@ bool validateCaseSensitiveFilename(const AbsPath& filepath, int fd) noexcept ////////////////////////////////////////////////////////////////////////// #ifdef TL_PLATFORM_WINDOWS_FAMILY -bool validateCaseSensitiveFilename(const AbsPath& filepath, HANDLE handle) noexcept +bool validateCaseSensitiveFilename(AbsPathView filepath, HANDLE handle) noexcept { #ifdef TL_PLATFORM_WINDOWS_DESKTOP_APP if (handle == INVALID_HANDLE_VALUE) @@ -157,7 +157,7 @@ bool validateCaseSensitiveFilename(const AbsPath& filepath, HANDLE handle) noexc #endif ////////////////////////////////////////////////////////////////////////// -bool validateCaseSensitiveFolder(const AbsPath& folderPath) noexcept +bool validateCaseSensitiveFolder(AbsPathView folderPath) noexcept { #ifdef TL_PLATFORM_WINDOWS_DESKTOP_APP return isFolderCapitalizationCorrect(folderPath); diff --git a/src/ReadStream.cpp b/src/ReadStream.cpp index 2af7cee..47f6994 100644 --- a/src/ReadStream.cpp +++ b/src/ReadStream.cpp @@ -98,7 +98,7 @@ ReadStreamResult readStream(std::string& buffer, IStreamSource& source, size_t b ////////////////////////////////////////////////////////////////////////// -ReadStreamResult readFile(tl::memory_buffer& buffer, IFilesystem& filesystem, const AbsPath& filePath, size_t bufferSize) +ReadStreamResult readFile(tl::memory_buffer& buffer, IFilesystem& filesystem, AbsPathView filePath, size_t bufferSize) { OUTCOME_TRY(const auto source, filesystem.openStreamSource(filePath, IFilesystem::SourceFlags(IFilesystem::SourceFlag::SequentialHint, IFilesystem::SourceFlag::Unbuffered))); return readStream(buffer, *source, bufferSize); @@ -106,7 +106,7 @@ ReadStreamResult readFile(tl::memory_buffer& buffer, IFilesystem& filesystem, co ////////////////////////////////////////////////////////////////////////// -ReadStreamResult readFile(eastl::string& buffer, IFilesystem& filesystem, const AbsPath& filePath, size_t bufferSize) +ReadStreamResult readFile(eastl::string& buffer, IFilesystem& filesystem, AbsPathView filePath, size_t bufferSize) { OUTCOME_TRY(const auto source, filesystem.openStreamSource(filePath, IFilesystem::SourceFlags(IFilesystem::SourceFlag::SequentialHint, IFilesystem::SourceFlag::Unbuffered))); return readStream(buffer, *source, bufferSize); @@ -114,7 +114,7 @@ ReadStreamResult readFile(eastl::string& buffer, IFilesystem& filesystem, const ////////////////////////////////////////////////////////////////////////// -ReadStreamResult readFile(std::string& buffer, IFilesystem& filesystem, const AbsPath& filePath, size_t bufferSize) +ReadStreamResult readFile(std::string& buffer, IFilesystem& filesystem, AbsPathView filePath, size_t bufferSize) { OUTCOME_TRY(const auto source, filesystem.openStreamSource(filePath, IFilesystem::SourceFlags(IFilesystem::SourceFlag::SequentialHint, IFilesystem::SourceFlag::Unbuffered))); return readStream(buffer, *source, bufferSize); diff --git a/src/WritableFolderPack.cpp b/src/WritableFolderPack.cpp index 15a7a0a..ac7091b 100644 --- a/src/WritableFolderPack.cpp +++ b/src/WritableFolderPack.cpp @@ -7,7 +7,7 @@ namespace fs { ////////////////////////////////////////////////////////////////////////// -WritableFolderPack::WritableFolderPack(AbsPath location) +WritableFolderPack::WritableFolderPack(AbsPathView location) : FolderPack(std::move(location)) { MakeFolderResult result = fs::native.makeFolder(m_location); @@ -17,7 +17,7 @@ WritableFolderPack::WritableFolderPack(AbsPath location) ////////////////////////////////////////////////////////////////////////// -WritableFolderPack::WritableFolderPack(tl::lent_ref filesystem, AbsPath location) +WritableFolderPack::WritableFolderPack(tl::lent_ref filesystem, AbsPathView location) : FolderPack(std::move(filesystem), std::move(location)) { MakeFolderResult result = m_filesystem->makeFolder(m_location); @@ -27,7 +27,7 @@ WritableFolderPack::WritableFolderPack(tl::lent_ref filesystem, Abs ////////////////////////////////////////////////////////////////////////// -OpenSinkResult WritableFolderPack::openSink(const AbsPath& path, Mode mode, SinkFlags flags) +OpenSinkResult WritableFolderPack::openSink(AbsPathView path, Mode mode, SinkFlags flags) { OUTCOME_TRY(const auto npath, convertToNativePath(path)); return m_filesystem->openSink(npath, mode, flags); @@ -35,7 +35,7 @@ OpenSinkResult WritableFolderPack::openSink(const AbsPath& path, Mode mode, Sink ////////////////////////////////////////////////////////////////////////// -OpenStreamSinkResult WritableFolderPack::openStreamSink(const AbsPath& path, Mode mode, SinkFlags flags) +OpenStreamSinkResult WritableFolderPack::openStreamSink(AbsPathView path, Mode mode, SinkFlags flags) { OUTCOME_TRY(const auto npath, convertToNativePath(path)); return m_filesystem->openStreamSink(npath, mode, flags); @@ -43,7 +43,7 @@ OpenStreamSinkResult WritableFolderPack::openStreamSink(const AbsPath& path, Mod ////////////////////////////////////////////////////////////////////////// -OpenMapSinkResult WritableFolderPack::openMapSink(const AbsPath& path, Mode mode, size_t size, SinkFlags flags) +OpenMapSinkResult WritableFolderPack::openMapSink(AbsPathView path, Mode mode, size_t size, SinkFlags flags) { OUTCOME_TRY(const auto npath, convertToNativePath(path)); return m_filesystem->openMapSink(npath, mode, size, flags); @@ -51,7 +51,7 @@ OpenMapSinkResult WritableFolderPack::openMapSink(const AbsPath& path, Mode mode ////////////////////////////////////////////////////////////////////////// -RemoveResult WritableFolderPack::remove(const AbsPath& path) +RemoveResult WritableFolderPack::remove(AbsPathView path) { OUTCOME_TRY(const auto npath, convertToNativePath(path)); return m_filesystem->remove(npath); @@ -59,7 +59,7 @@ RemoveResult WritableFolderPack::remove(const AbsPath& path) ////////////////////////////////////////////////////////////////////////// -RenameResult WritableFolderPack::rename(const AbsPath& path, const AbsPath& newPath) +RenameResult WritableFolderPack::rename(AbsPathView path, AbsPathView newPath) { OUTCOME_TRY(const auto filePath, convertToNativePath(path)); OUTCOME_TRY(const auto newFilePath, convertToNativePath(newPath)); @@ -68,7 +68,7 @@ RenameResult WritableFolderPack::rename(const AbsPath& path, const AbsPath& newP ////////////////////////////////////////////////////////////////////////// -MakeFolderResult WritableFolderPack::makeFolder(const AbsPath& path) +MakeFolderResult WritableFolderPack::makeFolder(AbsPathView path) { OUTCOME_TRY(const auto npath, convertToNativePath(path)); return m_filesystem->makeFolder(npath); @@ -76,7 +76,7 @@ MakeFolderResult WritableFolderPack::makeFolder(const AbsPath& path) ////////////////////////////////////////////////////////////////////////// -RemoveRecursivelyResult WritableFolderPack::removeRecursively(const AbsPath& path) +RemoveRecursivelyResult WritableFolderPack::removeRecursively(AbsPathView path) { OUTCOME_TRY(const auto npath, convertToNativePath(path)); return m_filesystem->removeRecursively(npath); @@ -84,7 +84,7 @@ RemoveRecursivelyResult WritableFolderPack::removeRecursively(const AbsPath& pat ////////////////////////////////////////////////////////////////////////// -SetWriteTimeResult WritableFolderPack::setWriteTime(const AbsPath& path, time_t time) +SetWriteTimeResult WritableFolderPack::setWriteTime(AbsPathView path, time_t time) { OUTCOME_TRY(const auto npath, convertToNativePath(path)); return m_filesystem->setWriteTime(npath, time); diff --git a/src/fast_io/.editorconfig b/src/fast_io/.editorconfig new file mode 100644 index 0000000..5b462cc --- /dev/null +++ b/src/fast_io/.editorconfig @@ -0,0 +1,4 @@ +root = true + +[*] +insert_final_newline = true diff --git a/src/fast_io/.git-blame-ignore-revs b/src/fast_io/.git-blame-ignore-revs new file mode 100644 index 0000000..f5e205a --- /dev/null +++ b/src/fast_io/.git-blame-ignore-revs @@ -0,0 +1,7 @@ +# editorconfig +321f2fa166c804c1ddb0aa5cf9afc8cde7e3be43 +# clang-format +395c9c7f67771c64ae673caa1428f848fd8242e7 +458c2f98c9fee122dd01e04d73b76786b13498d0 +b9db56983496403e8cdd065c6d9e5300eccb05b2 +e3c089ffca7836c3d7d3a022afbbc0f98010a946 \ No newline at end of file diff --git a/src/fast_io/.gitignore b/src/fast_io/.gitignore new file mode 100644 index 0000000..de88e6a --- /dev/null +++ b/src/fast_io/.gitignore @@ -0,0 +1,15 @@ +*.exe +benchmarks/*/*.txt +*/build/* +!.cc +*.app +/include/.vscode +/include/fast_io_network/.vscode/settings.json +.tmp +.vscode +build +.vs/ +.*/* +*.obj +*.html +*.txt diff --git a/src/fast_io/include/fast_io.h b/src/fast_io/include/fast_io.h new file mode 100644 index 0000000..0fe2ffa --- /dev/null +++ b/src/fast_io/include/fast_io.h @@ -0,0 +1,562 @@ +#pragma once +#if !defined(__cplusplus) +#error "You are not using a C++ compiler" +#endif + +#if !defined(__cpp_concepts) +#error "fast_io requires at least C++20 standard compiler." +#else +#include"fast_io_hosted.h" + +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning(push) +#pragma warning( disable : 4514 ) +#endif + +#if ((__STDC_HOSTED__==1 && (!defined(_GLIBCXX_HOSTED) || _GLIBCXX_HOSTED==1) && !defined(_LIBCPP_FREESTANDING)) || defined(FAST_IO_ENABLE_HOSTED_FEATURES)) +#if __has_include() +#include"fast_io_legacy_impl/c/impl.h" +#endif + +namespace fast_io +{ +#if !defined(__AVR__) +inline +#if defined(__WINE__) || !defined(_WIN32) +constexpr +#endif +native_io_observer in() noexcept +{ + return native_stdin(); +} + +inline +#if defined(__WINE__) || !defined(_WIN32) +constexpr +#endif +native_io_observer out() noexcept +{ + return native_stdout(); +} + +inline +#if defined(__WINE__) || !defined(_WIN32) +constexpr +#endif +native_io_observer err() noexcept +{ + return native_stderr(); +} + + +inline +#if defined(__WINE__) || !defined(_WIN32) +constexpr +#endif +decltype(auto) u8in() noexcept +{ + return native_stdin(); +} + +inline +#if defined(__WINE__) || !defined(_WIN32) +constexpr +#endif +decltype(auto) u8out() noexcept +{ + return native_stdout(); +} + +inline +#if defined(__WINE__) || !defined(_WIN32) +constexpr +#endif +decltype(auto) u8err() noexcept +{ + return native_stderr(); +} + + +using in_buf_type = basic_ibuf; +using out_buf_type = basic_obuf; + +using u8in_buf_type = basic_ibuf; +using u8out_buf_type = basic_obuf; + +using in_buf_type_mutex = basic_iomutex; +using out_buf_type_mutex = basic_iomutex; + +using u8in_buf_type_mutex = basic_iomutex; +using u8out_buf_type_mutex = basic_iomutex; + +#if defined(_WIN32) || defined(__CYGWIN__) + +inline constexpr basic_win32_box_t box() noexcept +{ + return basic_win32_box_t{}; +} + +inline constexpr basic_win32_box_t wbox() noexcept +{ + return basic_win32_box_t{}; +} + +inline constexpr basic_win32_box_t u8box() noexcept +{ + return basic_win32_box_t{}; +} + +inline constexpr basic_win32_box_t u16box() noexcept +{ + return basic_win32_box_t{}; +} + +inline constexpr basic_win32_box_t u32box() noexcept +{ + return basic_win32_box_t{}; +} +#else + +inline +#ifndef _WIN32 +constexpr +#endif +decltype(auto) box() noexcept +{ + return native_stdout(); +} + +inline +#ifndef _WIN32 +constexpr +#endif +decltype(auto) wbox() noexcept +{ + return native_stdout(); +} + +inline +#ifndef _WIN32 +constexpr +#endif +decltype(auto) u8box() noexcept +{ + return native_stdout(); +} + +inline +#ifndef _WIN32 +constexpr +#endif +decltype(auto) u16box() noexcept +{ + return native_stdout(); +} + +inline +#ifndef _WIN32 +constexpr +#endif +decltype(auto) u32box() noexcept +{ + return native_stdout(); +} + +#endif +#endif + +namespace details +{ + +template +inline constexpr void print_after_io_print_forward(Args ...args) +{ +#if __has_include() + print_freestanding_decay(c_stdout(),args...); +#else + print_freestanding_decay(out(),args...); +#endif +} + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline constexpr void perr_after_io_print_forward(Args ...args) +{ +#if defined(__AVR__) + print_freestanding_decay(c_stderr(),args...); +#else + print_freestanding_decay(err(),args...); +#endif +} + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline constexpr void debug_print_after_io_print_forward(Args ...args) +{ +#if defined(__AVR__) + print_freestanding_decay(c_stdout(),args...); +#else + print_freestanding_decay(out(),args...); +#endif +} + + +template +inline constexpr std::conditional_t scan_after_io_scan_forward(Args ...args) +{ +#if __has_include() + if constexpr(report) + return scan_freestanding_decay(c_stdin(),args...); + else + { + if(!scan_freestanding_decay(c_stdin(),args...)) + ::fast_io::throw_parse_code(fast_io::parse_code::end_of_file); + } +#else + if constexpr(report) + return scan_freestanding_decay(in(),args...); + else + { + if(!scan_freestanding_decay(in(),args...)) + ::fast_io::throw_parse_code(fast_io::parse_code::end_of_file); + } +#endif +} + + +} + +} +#endif + +namespace fast_io::io +{ + +template +inline constexpr void print(T&& t,Args&& ...args) +{ + constexpr bool device_error{fast_io::output_stream>||fast_io::status_output_stream>}; + if constexpr(device_error) + { + constexpr bool type_error{::fast_io::print_freestanding_okay}; + if constexpr(type_error) + { + ::fast_io::print_freestanding_decay(fast_io::io_ref(t),::fast_io::io_print_forward::char_type>(::fast_io::io_print_alias(args))...); + } + else + { +static_assert(type_error,"some types are not printable for print"); + } + } + else + { +#if ((__STDC_HOSTED__==1 && (!defined(_GLIBCXX_HOSTED) || _GLIBCXX_HOSTED==1) && !defined(_LIBCPP_FREESTANDING)) || defined(FAST_IO_ENABLE_HOSTED_FEATURES)) && __has_include() + constexpr bool type_error{::fast_io::print_freestanding_okay< +#if __has_include() + ::fast_io::c_io_observer +#else + ::fast_io::native_io_observer +#endif + ,T,Args...>}; + if constexpr(type_error) + { + ::fast_io::details::print_after_io_print_forward(::fast_io::io_print_forward(::fast_io::io_print_alias(t)),::fast_io::io_print_forward(::fast_io::io_print_alias(args))...); + } + else + { +static_assert(type_error,"some types are not printable for print on default C's stdout"); + } +#else +static_assert(device_error,"freestanding environment must provide IO device for print"); +#endif + } +} + +template +inline constexpr void println(T&& t,Args&& ...args) +{ + constexpr bool device_error{fast_io::output_stream>||fast_io::status_output_stream>}; + if constexpr(device_error) + { + constexpr bool type_error{::fast_io::print_freestanding_okay}; + if constexpr(type_error) + { + ::fast_io::print_freestanding_decay(fast_io::io_ref(t),fast_io::io_print_forward::char_type>(fast_io::io_print_alias(args))...); + } + else + { +static_assert(type_error,"some types are not printable for println"); + } + } + else + { +#if ((__STDC_HOSTED__==1 && (!defined(_GLIBCXX_HOSTED) || _GLIBCXX_HOSTED==1) && !defined(_LIBCPP_FREESTANDING)) || defined(FAST_IO_ENABLE_HOSTED_FEATURES)) && __has_include() + constexpr bool type_error{::fast_io::print_freestanding_okay< +#if __has_include() + ::fast_io::c_io_observer +#else + ::fast_io::native_io_observer +#endif + ,T,Args...>}; + if constexpr(type_error) + { + ::fast_io::details::print_after_io_print_forward(fast_io::io_print_forward(fast_io::io_print_alias(t)),fast_io::io_print_forward(fast_io::io_print_alias(args))...); + } + else + { +static_assert(type_error,"some types are not printable for println on default C's stdout"); + } +#else +static_assert(device_error,"freestanding environment must provide IO device for println"); +#endif + } +} + +template +inline constexpr void perr(T&& t,Args&&... args) +{ + constexpr bool device_error{fast_io::output_stream>||fast_io::status_output_stream>}; + if constexpr(device_error) + { + constexpr bool type_error{::fast_io::print_freestanding_okay}; + if constexpr(type_error) + { + ::fast_io::print_freestanding_decay_cold(fast_io::io_ref(t),fast_io::io_print_forward::char_type>(fast_io::io_print_alias(args))...); + } + else + { +static_assert(type_error,"some types are not printable for perr"); + } + } + else + { +#if ((__STDC_HOSTED__==1 && (!defined(_GLIBCXX_HOSTED) || _GLIBCXX_HOSTED==1) && !defined(_LIBCPP_FREESTANDING)) || defined(FAST_IO_ENABLE_HOSTED_FEATURES)) + constexpr bool type_error{::fast_io::print_freestanding_okay< +#if defined(__AVR__) + ::fast_io::c_io_observer +#else + ::fast_io::native_io_observer +#endif + ,T,Args...>}; + if constexpr(type_error) + { + ::fast_io::details::perr_after_io_print_forward(fast_io::io_print_forward(fast_io::io_print_alias(t)),fast_io::io_print_forward(fast_io::io_print_alias(args))...); + } + else + { +static_assert(type_error,"some types are not printable for perr on native err"); + } +#else +static_assert(device_error,"freestanding environment must provide IO device"); +#endif + } +} + +template +inline constexpr void perrln(T&& t,Args&&... args) +{ + constexpr bool device_error{fast_io::output_stream>||fast_io::status_output_stream>}; + if constexpr(device_error) + { + constexpr bool type_error{::fast_io::print_freestanding_okay}; + if constexpr(type_error) + { + ::fast_io::print_freestanding_decay_cold(fast_io::io_ref(t),fast_io::io_print_forward::char_type>(fast_io::io_print_alias(args))...); + } + else + { +static_assert(type_error,"some types are not printable for perrln"); + } + } + else + { +#if ((__STDC_HOSTED__==1 && (!defined(_GLIBCXX_HOSTED) || _GLIBCXX_HOSTED==1) && !defined(_LIBCPP_FREESTANDING)) || defined(FAST_IO_ENABLE_HOSTED_FEATURES)) + constexpr bool type_error{::fast_io::print_freestanding_okay< +#if defined(__AVR__) + ::fast_io::c_io_observer +#else + ::fast_io::native_io_observer +#endif + ,T,Args...>}; + if constexpr(type_error) + { + ::fast_io::details::perr_after_io_print_forward(fast_io::io_print_forward(fast_io::io_print_alias(t)),fast_io::io_print_forward(fast_io::io_print_alias(args))...); + } + else + { +static_assert(type_error,"some types are not printable for perrln on native err"); + } +#else +static_assert(device_error,"freestanding environment must provide IO device"); +#endif + } +} + +template +[[noreturn]] inline constexpr void panic(Args&&... args) noexcept +{ + if constexpr(sizeof...(Args)!=0) + { +#ifdef __cpp_exceptions + try + { +#endif + ::fast_io::io::perr(::std::forward(args)...); +#ifdef __cpp_exceptions + } + catch(...){} +#endif + } + ::fast_io::fast_terminate(); +} + +template +requires (sizeof...(Args)!=0) +[[noreturn]] inline constexpr void panicln(Args&&... args) noexcept +{ +#ifdef __cpp_exceptions + try + { +#endif + ::fast_io::io::perrln(::std::forward(args)...); +#ifdef __cpp_exceptions + } + catch(...){} +#endif + ::fast_io::fast_terminate(); +} + +//Allow debug print +#ifndef FAST_IO_DISABLE_DEBUG_PRINT +//With debugging. We output to POSIX fd or Win32 Handle directly instead of C's stdout. +template +inline constexpr void debug_print(T&& t,Args&& ...args) +{ + constexpr bool device_error{fast_io::output_stream>||fast_io::status_output_stream>}; + if constexpr(device_error) + { + constexpr bool type_error{::fast_io::print_freestanding_okay}; + if constexpr(type_error) + { + ::fast_io::print_freestanding_decay(::fast_io::io_ref(t),fast_io::io_print_forward::char_type>(fast_io::io_print_alias(args))...); + } + else + { +static_assert(type_error,"some types are not printable for debug_print"); + } + } + else + { +#if ((__STDC_HOSTED__==1 && (!defined(_GLIBCXX_HOSTED) || _GLIBCXX_HOSTED==1) && !defined(_LIBCPP_FREESTANDING)) || defined(FAST_IO_ENABLE_HOSTED_FEATURES)) + constexpr bool type_error{::fast_io::print_freestanding_okay< +#if defined(__AVR__) + ::fast_io::c_io_observer +#else + ::fast_io::native_io_observer +#endif + ,T,Args...>}; + if constexpr(type_error) + { + fast_io::details::debug_print_after_io_print_forward(fast_io::io_print_forward(fast_io::io_print_alias(t)),fast_io::io_print_forward(fast_io::io_print_alias(args))...); + } + else + { +static_assert(type_error,"some types are not printable for debug_print on native out"); + } +#else +static_assert(device_error,"freestanding environment must provide IO device"); +#endif + } +} + +template +inline constexpr void debug_println(T&& t,Args&& ...args) +{ + constexpr bool device_error{::fast_io::output_stream>||::fast_io::status_output_stream>}; + if constexpr(device_error) + { + constexpr bool type_error{::fast_io::print_freestanding_okay}; + if constexpr(type_error) + { + ::fast_io::print_freestanding_decay(::fast_io::io_ref(t),fast_io::io_print_forward::char_type>(fast_io::io_print_alias(args))...); + } + else + { +static_assert(type_error,"some types are not printable for debug_println"); + } + } + else + { +#if ((__STDC_HOSTED__==1 && (!defined(_GLIBCXX_HOSTED) || _GLIBCXX_HOSTED==1) && !defined(_LIBCPP_FREESTANDING)) || defined(FAST_IO_ENABLE_HOSTED_FEATURES)) + constexpr bool type_error{::fast_io::print_freestanding_okay< +#if defined(__AVR__) + ::fast_io::c_io_observer +#else + ::fast_io::native_io_observer +#endif + ,T,Args...>}; + if constexpr(type_error) + { + fast_io::details::debug_print_after_io_print_forward(fast_io::io_print_forward(fast_io::io_print_alias(t)),fast_io::io_print_forward(fast_io::io_print_alias(args))...); + } + else + { +static_assert(type_error,"some types are not printable for debug_println on native out"); + } +#else +static_assert(device_error,"freestanding environment must provide IO device"); +#endif + } +} + +template +requires (sizeof...(Args)!=0) +inline constexpr void debug_perr(Args&&... args) +{ + ::fast_io::io::perr(::std::forward(args)...); +} + +template +requires (sizeof...(Args)!=0) +inline constexpr void debug_perrln(Args&&... args) +{ + ::fast_io::io::perrln(::std::forward(args)...); +} + +#endif + +template +inline constexpr ::std::conditional_t scan(input&& in,Args&& ...args) +{ + if constexpr(fast_io::input_stream>) + { + if constexpr(report) + return ::fast_io::scan_freestanding_decay(::fast_io::io_ref(in),fast_io::io_scan_forward::char_type>(::fast_io::io_scan_alias(args))...); + else + { + + if(!::fast_io::scan_freestanding_decay(::fast_io::io_ref(in),::fast_io::io_scan_forward::char_type>(::fast_io::io_scan_alias(args))...)) + ::fast_io::throw_parse_code(::fast_io::parse_code::end_of_file); + } + } + else + { +#if ((__STDC_HOSTED__==1 && (!defined(_GLIBCXX_HOSTED) || _GLIBCXX_HOSTED==1) && !defined(_LIBCPP_FREESTANDING)) || defined(FAST_IO_ENABLE_HOSTED_FEATURES)) && __has_include() + return ::fast_io::details::scan_after_io_scan_forward(::fast_io::io_scan_forward(::fast_io::io_scan_alias(in)),::fast_io::io_scan_forward(::fast_io::io_scan_alias(args))...); +#else +static_assert(::fast_io::input_stream>,"freestanding environment must provide IO device"); +#endif + } +} + +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning(pop) +#endif + +#endif + +} diff --git a/src/fast_io/include/fast_io_concept.h b/src/fast_io/include/fast_io_concept.h new file mode 100644 index 0000000..ed27617 --- /dev/null +++ b/src/fast_io/include/fast_io_concept.h @@ -0,0 +1,30 @@ +#pragma once +#undef min +#undef max +//fast_io_concept.h allows you define your device and type without compilation time penalty +#if !defined(__cplusplus) +#error "You must be using a C++ compiler" +#endif +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning(push) +#pragma warning( disable : 4514 ) +#pragma warning( disable : 4623 ) +#pragma warning( disable : 4626 ) +#pragma warning( disable : 4668 ) +#pragma warning( disable : 4820 ) +#pragma warning( disable : 5027 ) +#endif +#if !defined(__cpp_concepts) +#error "fast_io requires at least a C++20 standard compiler." +#else +#include +#include +#include +#include +#include"fast_io_core_impl/freestanding/addressof.h" +#include"fast_io_core_impl/concepts/impl.h" +#endif + +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning (pop) +#endif diff --git a/src/fast_io/include/fast_io_core.h b/src/fast_io/include/fast_io_core.h new file mode 100644 index 0000000..fcb4fc6 --- /dev/null +++ b/src/fast_io/include/fast_io_core.h @@ -0,0 +1,124 @@ +#pragma once +//fast_io_core.h is required to be usable in freestanding environment with EVEN dynamic memory allocation and exceptions are disabled. + +#if !defined(__cplusplus) +#error "You are not using a C++ compiler" +#endif + +#if !defined(__cpp_concepts) +#error "fast_io requires at least C++20 standard compiler." +#else +#include"fast_io_concept.h" +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning(push) +#pragma warning( disable : 4711 ) +#endif +#include //for std::endian, std::rotl and std::bit_cast etc +#include +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning(pop) +#endif + +#include +#if __cpp_lib_three_way_comparison >= 201907L +#include +#endif + +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning(push) +#pragma warning( disable : 4365 ) +#pragma warning( disable : 4514 ) +#pragma warning( disable : 4623 ) +#pragma warning( disable : 4626 ) +#pragma warning( disable : 4668 ) +#pragma warning( disable : 4710 ) +#pragma warning( disable : 4711 ) +#pragma warning( disable : 4820 ) +#pragma warning( disable : 5027 ) +#pragma warning( disable : 5045 ) +#endif + +#include"fast_io_core_impl/empty.h" +#if defined(_MSC_VER) && !defined(__clang__) +#include "fast_io_core_impl/intrinsics/msvc/impl.h" +#endif +#include"fast_io_core_impl/freestanding/impl.h" +#include"fast_io_core_impl/terminate.h" +#include"fast_io_dsal/impl/freestanding.h" +#include"fast_io_core_impl/allocation/impl.h" + +#include"fast_io_core_impl/error.h" +#include"fast_io_core_impl/asan_support.h" +//fast_io core +#include"fast_io_core_impl/utils.h" +#include"fast_io_core_impl/intrinsics.h" +#include"fast_io_core_impl/parse_code.h" + +#include"fast_io_core_impl/ebcdic.h" +#include"fast_io_core_impl/literals/literal.h" +#include"fast_io_core_impl/char_category.h" + + +#include"fast_io_core_impl/overflow.h" + + +#if __cpp_lib_three_way_comparison >= 201907L +#include"fast_io_core_impl/compare.h" +#endif + +#include"fast_io_core_impl/alias.h" +#include"fast_io_core_impl/pr_rsv.h" + +#include"fast_io_core_impl/secure_clear_guard.h" +#include"fast_io_core_impl/local_new_array_ptr.h" +#include"fast_io_core_impl/dynamic_io_buffer.h" +#include"fast_io_core_impl/temporary_buffer.h" +// Although std::ranges is not freestanding, you can use the function by constructing a range_view_t, which relies on iterators not ranges +#include"fast_io_core_impl/range_view.h" +//#include"fast_io_core_impl/manip/impl.h" +#include"fast_io_core_impl/mode.h" +#include"fast_io_core_impl/perms.h" +#include"fast_io_core_impl/seek.h" + +#include"fast_io_core_impl/igenerator.h" +#include"fast_io_core_impl/io_ref.h" +#include"fast_io_core_impl/print_freestanding.h" +#include"fast_io_core_impl/read_all.h" +#include"fast_io_core_impl/scan_freestanding.h" +// This should provide an option macro to disable any generation for table in freestanding environments. +#include"fast_io_core_impl/integers/integer.h" + +#include"fast_io_core_impl/black_hole.h" +#include"fast_io_core_impl/buffer_view.h" +#include"fast_io_core_impl/transmit/impl.h" + +#ifdef __cpp_lib_source_location +#include +#include"fast_io_core_impl/source_location.h" +#endif + +#include"fast_io_core_impl/simd/impl.h" +#include"fast_io_core_impl/simd_find.h" +#include"fast_io_core_impl/integers/sto/sto_contiguous.h" + +#include"fast_io_core_impl/integers/chrono.h" +#include"fast_io_core_impl/iso/isos.h" +#include"fast_io_core_impl/enums/impl.h" + +#ifndef FAST_IO_DISABLE_CODECVT +#include"fast_io_core_impl/codecvt/impl.h" +#endif +#include"fast_io_core_impl/io_deco_ref.h" + +#include"fast_io_core_impl/timestamp_counter.h" +#include"fast_io_core_impl/dll_mode.h" +#include"fast_io_core_impl/socket/impl.h" +#include"fast_io_core_impl/to.h" +#include"fast_io_core_impl/concat/impl.h" +#include"fast_io_core_impl/http_header.h" + +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning(pop) +#endif + +#endif diff --git a/src/fast_io/include/fast_io_core_impl/alias.h b/src/fast_io/include/fast_io_core_impl/alias.h new file mode 100644 index 0000000..699ff3b --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/alias.h @@ -0,0 +1,71 @@ +#pragma once + +namespace fast_io +{ + +namespace details +{ + +struct cannot_output_type +{ +inline explicit constexpr cannot_output_type() noexcept = default; +}; + +} + +template +inline constexpr decltype(auto) io_print_alias(T&& t) noexcept +{ + using no_cvref_t=std::remove_cvref_t; + if constexpr(::std::is_function_v) + { + return ::fast_io::details::cannot_output_type{}; + } + else if constexpr(alias_printable) + return print_alias_define(io_alias,::std::forward(t)); + else + return ::std::forward(t); +} + +template +inline constexpr auto io_print_forward(T&& t) noexcept +{ + using no_cvref_t=std::remove_cvref_t; + if constexpr(::std::is_function_v) + { + return ::fast_io::details::cannot_output_type{}; + } + else if constexpr(status_io_print_forwardable) + return status_io_print_forward(io_alias_type,::std::forward(t)); + else if constexpr(std::is_trivially_copyable_v&&sizeof(no_cvref_t)<=sizeof(std::size_t)*2) + return static_cast(t); + else + return parameter const&>{t}; +} + +template +inline constexpr auto io_scan_forward(T t) noexcept +{ + if constexpr(status_io_scan_forwardable) + return status_io_scan_forward(io_alias_type,t); + else + return t; +} + +template +inline constexpr auto io_scan_alias(T&& t) noexcept +{ + using no_ref_t = std::remove_reference_t; + if constexpr(::std::is_function_v) + { + return ::fast_io::details::cannot_output_type{}; + } + else if constexpr(alias_scannable) + return scan_alias_define(io_alias,::std::forward(t)); + else if constexpr(manipulator) + return t; + else + return parameter{t}; +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/allocation/adapters.h b/src/fast_io/include/fast_io_core_impl/allocation/adapters.h new file mode 100644 index 0000000..3e9e4b7 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/allocation/adapters.h @@ -0,0 +1,1991 @@ +#pragma once + +// To make a constexpr allocator, we need ::std::allocator. Because only new expression and +// ::std::allocator::allocate are allowed in constexpr functions. See https://github.com/microsoft/STL/issues/1532 +// https://github.com/microsoft/STL/issues/4002 gcc and clang provide constexpr new, but still won't compile. +// ::std::allocator is NOT freestanding. + +#pragma push_macro("new") +#undef new + +namespace fast_io +{ + +namespace details +{ + +#include "has_methods_detect.h" + +template +concept has_default_alignment_impl = requires(::std::size_t n) { alloc::default_alignment; }; + +template +inline constexpr ::std::size_t calculate_default_alignment() noexcept +{ + if constexpr (has_default_alignment_impl) + { + return alloc::default_alignment; + } + else + { + return __STDCPP_DEFAULT_NEW_ALIGNMENT__; + } +} + +inline constexpr ::std::size_t allocator_compute_aligned_total_size_impl(::std::size_t alignment, ::std::size_t n) noexcept +{ + constexpr ::std::size_t mxn{::std::numeric_limits<::std::size_t>::max()}, + sizeofptr{sizeof(void *)}, + mxmptr{mxn - sizeofptr}; + if (alignment < sizeofptr) + { + alignment = sizeofptr; + } + if (alignment > mxmptr) + { + ::fast_io::fast_terminate(); + } + ::std::size_t total_extra_space{alignment + sizeofptr}; + ::std::size_t upperlimit{static_cast<::std::size_t>(mxn - total_extra_space)}; + if (n > upperlimit) + { + ::fast_io::fast_terminate(); + } + return n + total_extra_space; +} + +inline void *allocator_adjust_ptr_to_aligned_impl(void *p, ::std::size_t alignment) noexcept +{ + void *aligned_ptr{reinterpret_cast((reinterpret_cast<::std::size_t>(p) + alignment) & (0 - alignment))}; + reinterpret_cast(aligned_ptr)[-1] = p; + return aligned_ptr; +} + +template +inline constexpr void *allocator_pointer_aligned_impl(::std::size_t, ::std::size_t) noexcept; + +template +inline constexpr ::fast_io::allocation_least_result allocator_pointer_aligned_at_least_impl(::std::size_t, ::std::size_t) noexcept; + +template +inline constexpr void *status_allocator_pointer_aligned_impl(typename alloc::handle_type, ::std::size_t, ::std::size_t) noexcept; + +template +inline constexpr ::fast_io::allocation_least_result status_allocator_pointer_aligned_at_least_impl(typename alloc::handle_type, ::std::size_t, ::std::size_t) noexcept; + +} // namespace details + +#if 0 +#include "allocator_adapter_flags.h" +#endif + +template +class generic_allocator_adapter +{ +public: + using allocator_type = alloc; + static inline constexpr bool has_status{::fast_io::details::has_non_empty_handle_type}; + template + struct has + { + using type = allocator_type; // any meaningless type other than void + }; + template + struct has + { + using type = typename T::handle_type; + }; + using handle_type = typename has::type; + static inline constexpr ::std::size_t default_alignment{::fast_io::details::calculate_default_alignment()}; + static inline constexpr bool has_native_allocate{ + !has_status && (::fast_io::details::has_allocate_at_least_impl || + ::fast_io::details::has_allocate_aligned_at_least_impl || + ::fast_io::details::has_allocate_zero_at_least_impl || + ::fast_io::details::has_allocate_aligned_zero_at_least_impl || + ::fast_io::details::has_allocate_impl || + ::fast_io::details::has_allocate_aligned_impl || + ::fast_io::details::has_allocate_zero_impl || + ::fast_io::details::has_allocate_aligned_zero_impl)}; + static inline + + void * + allocate(::std::size_t n) noexcept + requires(!has_status) + { +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if (__builtin_is_constant_evaluated()) +#endif + { + return ::operator new(n); + } + else +#endif + { + if constexpr (::fast_io::details::has_allocate_impl) + { + return allocator_type::allocate(n); + } + else if constexpr (::fast_io::details::has_allocate_aligned_at_least_impl) + { + return allocator_type::allocate_at_least(n).ptr; + } + else if constexpr (::fast_io::details::has_allocate_aligned_impl) + { + return allocator_type::allocate_aligned(default_alignment, n); + } + else if constexpr (::fast_io::details::has_allocate_zero_impl) + { + return allocator_type::allocate_zero(n); + } + else if constexpr (::fast_io::details::has_allocate_aligned_at_least_impl) + { + return allocator_type::allocate_zero_at_least(n).ptr; + } + else if constexpr (::fast_io::details::has_allocate_aligned_zero_impl) + { + return allocator_type::allocate_aligned_zero(default_alignment, n); + } + else + { + fast_io::fast_terminate(); + } + } + } + + static inline void *allocate_zero(::std::size_t n) noexcept + requires(!has_status) + { + if constexpr (::fast_io::details::has_allocate_zero_impl) + { + return allocator_type::allocate_zero(n); + } + else if constexpr (::fast_io::details::has_allocate_zero_at_least_impl) + { + return allocator_type::allocate_zero_at_least(n).ptr; + } + else if constexpr (::fast_io::details::has_allocate_aligned_zero_impl) + { + return allocator_type::allocate_aligned_zero(default_alignment, n); + } + else if constexpr (::fast_io::details::has_allocate_aligned_zero_at_least_impl) + { + return allocator_type::allocate_aligned_zero_at_least(default_alignment, n).ptr; + } + else + { + auto p{generic_allocator_adapter::allocate(n)}; + ::fast_io::freestanding::bytes_clear_n(reinterpret_cast<::std::byte *>(p), n); + return p; + } + } + + static inline constexpr bool has_reallocate = (::fast_io::details::has_reallocate_impl || + ::fast_io::details::has_reallocate_at_least_impl || + ::fast_io::details::has_reallocate_aligned_impl || + ::fast_io::details::has_reallocate_aligned_at_least_impl || + ::fast_io::details::has_reallocate_zero_impl || + ::fast_io::details::has_reallocate_zero_at_least_impl || + ::fast_io::details::has_reallocate_aligned_zero_impl || + ::fast_io::details::has_reallocate_aligned_zero_at_least_impl); + static inline void *reallocate(void *p, ::std::size_t n) noexcept + requires(!has_status && has_reallocate) + { + if constexpr (::fast_io::details::has_reallocate_impl) + { + return allocator_type::reallocate(p, n); + } + else if constexpr (::fast_io::details::has_reallocate_at_least_impl) + { + return allocator_type::reallocate_at_least(p, n).ptr; + } + else if constexpr (::fast_io::details::has_reallocate_aligned_impl) + { + return allocator_type::reallocate_aligned(p, default_alignment, n); + } + else if constexpr (::fast_io::details::has_reallocate_aligned_at_least_impl) + { + return allocator_type::reallocate_aligned_at_least(p, default_alignment, n).ptr; + } + else if constexpr (::fast_io::details::has_reallocate_zero_impl) + { + return allocator_type::reallocate_zero(p, n); + } + else if constexpr (::fast_io::details::has_reallocate_zero_at_least_impl) + { + return allocator_type::reallocate_zero_at_least(p, n).ptr; + } + else if constexpr (::fast_io::details::has_reallocate_aligned_zero_impl) + { + return allocator_type::reallocate_aligned_zero(p, default_alignment, n); + } + else if constexpr (::fast_io::details::has_reallocate_aligned_zero_at_least_impl) + { + return allocator_type::reallocate_aligned_zero_at_least(p, default_alignment, n).ptr; + } + } + static inline constexpr bool has_reallocate_zero = (::fast_io::details::has_reallocate_zero_impl || + ::fast_io::details::has_reallocate_zero_at_least_impl || + ::fast_io::details::has_reallocate_aligned_zero_impl || + ::fast_io::details::has_reallocate_aligned_zero_at_least_impl); + static inline void *reallocate_zero(void *p, ::std::size_t n) noexcept + requires(!has_status && has_reallocate_zero) + { + if constexpr (::fast_io::details::has_reallocate_zero_impl) + { + return allocator_type::reallocate_zero(p, n); + } + else if constexpr (::fast_io::details::has_reallocate_zero_at_least_impl) + { + return allocator_type::reallocate_zero_at_least(p, n).ptr; + } + else if constexpr (::fast_io::details::has_reallocate_aligned_zero_impl) + { + return allocator_type::reallocate_aligned_zero(p, default_alignment, n); + } + else if constexpr (::fast_io::details::has_reallocate_aligned_zero_at_least_impl) + { + return allocator_type::reallocate_aligned_zero_at_least(p, default_alignment, n).ptr; + } + } + static inline void *reallocate_n(void *p, ::std::size_t oldn, ::std::size_t n) noexcept + requires(!has_status) + { + if constexpr (::fast_io::details::has_reallocate_n_impl) + { + return allocator_type::reallocate_n(p, oldn, n); + } + else if constexpr (::fast_io::details::has_reallocate_n_at_least_impl) + { + return allocator_type::reallocate_n_at_least(p, oldn, n).ptr; + } + else if constexpr (::fast_io::details::has_reallocate_aligned_n_impl) + { + return allocator_type::reallocate_aligned_n(p, oldn, default_alignment, n); + } + else if constexpr (::fast_io::details::has_reallocate_aligned_n_at_least_impl) + { + return allocator_type::reallocate_aligned_n_at_least(p, oldn, default_alignment, n).ptr; + } + else if constexpr (::fast_io::details::has_reallocate_zero_n_impl) + { + return allocator_type::reallocate_zero_n(p, oldn, n); + } + else if constexpr (::fast_io::details::has_reallocate_zero_n_at_least_impl) + { + return allocator_type::reallocate_zero_n_at_least(p, oldn, default_alignment, n).ptr; + } + else if constexpr (::fast_io::details::has_reallocate_aligned_zero_n_impl) + { + return allocator_type::reallocate_aligned_zero_n(p, oldn, default_alignment, n); + } + else if constexpr (::fast_io::details::has_reallocate_aligned_zero_n_at_least_impl) + { + return allocator_type::reallocate_aligned_zero_n_at_least(p, oldn, default_alignment, n).ptr; + } + else if constexpr (::fast_io::details::has_reallocate_impl) + { + return allocator_type::reallocate(p, n); + } + else if constexpr (::fast_io::details::has_reallocate_at_least_impl) + { + return allocator_type::reallocate_at_least(p, n).ptr; + } + else if constexpr (::fast_io::details::has_reallocate_aligned_impl) + { + return allocator_type::reallocate_aligned_n(p, default_alignment, n); + } + else if constexpr (::fast_io::details::has_reallocate_aligned_at_least_impl) + { + return allocator_type::reallocate_aligned_n_at_least(p, default_alignment, n).ptr; + } + else if constexpr (::fast_io::details::has_reallocate_zero_impl) + { + return allocator_type::reallocate_zero(p, n); + } + else if constexpr (::fast_io::details::has_reallocate_zero_at_least_impl) + { + return allocator_type::reallocate_zero_at_least(p, n).ptr; + } + else if constexpr (::fast_io::details::has_reallocate_aligned_zero_impl) + { + return allocator_type::reallocate_aligned_zero_n(p, default_alignment, n); + } + else if constexpr (::fast_io::details::has_reallocate_aligned_zero_at_least_impl) + { + return allocator_type::reallocate_aligned_zero_n_at_least(p, default_alignment, n).ptr; + } + else + { + auto newptr{generic_allocator_adapter::allocate(n)}; + if (p != nullptr && n) + { + if (oldn < n) + { + n = oldn; + } + ::fast_io::freestanding::nonoverlapped_bytes_copy_n(reinterpret_cast<::std::byte const *>(p), n, reinterpret_cast<::std::byte *>(newptr)); + generic_allocator_adapter::deallocate_n(p, oldn); + } + return newptr; + } + } + static inline void *reallocate_zero_n(void *p, ::std::size_t oldn, ::std::size_t n) noexcept + requires(!has_status) + { + if constexpr (::fast_io::details::has_reallocate_zero_n_impl) + { + return allocator_type::reallocate_zero_n(p, oldn, n); + } + else if constexpr (::fast_io::details::has_reallocate_zero_n_at_least_impl) + { + return allocator_type::reallocate_zero_n_at_least(p, oldn, n).ptr; + } + else if constexpr (::fast_io::details::has_reallocate_aligned_zero_n_impl) + { + return allocator_type::reallocate_aligned_zero_n(p, oldn, default_alignment, n); + } + else if constexpr (::fast_io::details::has_reallocate_aligned_zero_n_at_least_impl) + { + return allocator_type::reallocate_aligned_zero_n_at_least(p, oldn, default_alignment, n).ptr; + } + else if constexpr (::fast_io::details::has_reallocate_zero_impl) + { + return allocator_type::reallocate_zero(p, n); + } + else if constexpr (::fast_io::details::has_reallocate_zero_at_least_impl) + { + return allocator_type::reallocate_zero_at_least(p, n).ptr; + } + else if constexpr (::fast_io::details::has_reallocate_aligned_zero_impl) + { + return allocator_type::reallocate_aligned_zero(p, default_alignment, n); + } + else if constexpr (::fast_io::details::has_reallocate_aligned_zero_at_least_impl) + { + return allocator_type::reallocate_aligned_zero_at_least(p, default_alignment, n).ptr; + } + else + { + auto newptr{generic_allocator_adapter::reallocate_n(p, oldn, n)}; + if (oldn < n) + { + ::std::size_t const to_zero_bytes{static_cast<::std::size_t>(n - oldn)}; + ::fast_io::freestanding::bytes_clear_n(reinterpret_cast<::std::byte *>(newptr) + oldn, to_zero_bytes); + } + return newptr; + } + } + + static inline constexpr bool has_deallocate = (::fast_io::details::has_deallocate_impl || + ::fast_io::details::has_deallocate_aligned_impl); + static inline void deallocate(void *p) noexcept + requires(!has_status && has_deallocate) + { +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if (__builtin_is_constant_evaluated()) +#endif + { + ::operator delete(p); + } + else +#endif + { + if constexpr (::fast_io::details::has_deallocate_impl) + { + allocator_type::deallocate(p); + } + else if constexpr (::fast_io::details::has_deallocate_aligned_impl) + { + allocator_type::deallocate_aligned(p, default_alignment); + } + } + } + static inline void deallocate_n(void *p, ::std::size_t n) noexcept + requires(!has_status) + { +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if (__builtin_is_constant_evaluated()) +#endif + { + ::operator delete(p); + } + else +#endif + { + if constexpr (::fast_io::details::has_deallocate_n_impl) + { + allocator_type::deallocate_n(p, n); + } + else if constexpr (::fast_io::details::has_deallocate_aligned_n_impl) + { + allocator_type::deallocate_aligned_n(p, default_alignment, n); + } + else if constexpr (::fast_io::details::has_deallocate_impl) + { + allocator_type::deallocate(p); + } + else if constexpr (::fast_io::details::has_deallocate_aligned_impl) + { + allocator_type::deallocate_aligned(p, default_alignment); + } + else + { + fast_io::fast_terminate(); + } + } + } + + static inline + + void * + allocate_aligned(::std::size_t alignment, ::std::size_t n) noexcept + requires(!has_status) + { +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if (__builtin_is_constant_evaluated()) +#endif + { + return ::operator new(n); + } + else +#endif + { + return ::fast_io::details::allocator_pointer_aligned_impl(alignment, n); + } + } + static inline + + void * + allocate_aligned_zero(::std::size_t alignment, ::std::size_t n) noexcept + requires(!has_status) + { +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if (__builtin_is_constant_evaluated()) +#endif + { + return ::operator new(n); // this is problematic. No way to clean it up at compile time. + } + else +#endif + { + return ::fast_io::details::allocator_pointer_aligned_impl(alignment, n); + } + } + static inline constexpr bool has_native_allocate_at_least{ + !has_status && (::fast_io::details::has_allocate_at_least_impl || + ::fast_io::details::has_allocate_aligned_at_least_impl || + ::fast_io::details::has_allocate_zero_at_least_impl || + ::fast_io::details::has_allocate_aligned_zero_at_least_impl)}; + static inline constexpr allocation_least_result + allocate_at_least(::std::size_t n) noexcept + requires(!has_status) + { +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if (__builtin_is_constant_evaluated()) +#endif + { + return {::operator new(n), n}; + } + else +#endif + { + if constexpr (::fast_io::details::has_allocate_at_least_impl) + { + return allocator_type::allocate_at_least(n); + } + else if constexpr (::fast_io::details::has_allocate_aligned_at_least_impl) + { + return allocator_type::allocate_aligned_at_least(n, default_alignment); + } + else if constexpr (::fast_io::details::has_allocate_zero_at_least_impl) + { + return allocator_type::allocate_zero_at_least(n); + } + else if constexpr (::fast_io::details::has_allocate_aligned_zero_at_least_impl) + { + return allocator_type::allocate_aligned_zero_at_least(n, default_alignment); + } + else + { + return {generic_allocator_adapter::allocate(n), n}; + } + } + } + static inline constexpr allocation_least_result + allocate_zero_at_least(::std::size_t n) noexcept + requires(!has_status) + { +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if (__builtin_is_constant_evaluated()) +#endif + { + return {::operator new(n), n}; + } + else +#endif + { + if constexpr (::fast_io::details::has_allocate_zero_at_least_impl) + { + return allocator_type::allocate_zero_at_least(n); + } + else if constexpr (::fast_io::details::has_allocate_aligned_zero_at_least_impl) + { + return allocator_type::allocate_aligned_zero_at_least(n, default_alignment); + } + else if constexpr (::fast_io::details::has_allocate_at_least_impl || + ::fast_io::details::has_allocate_aligned_at_least_impl) + { + auto temp{generic_allocator_adapter::allocate_at_least(n)}; + auto ptr{temp.ptr}; + auto sz{temp.count}; + ::fast_io::freestanding::bytes_clear_n(reinterpret_cast<::std::byte *>(ptr), sz); + return temp; + } + else + { + return {generic_allocator_adapter::allocate_zero(n), n}; + } + } + } + + static inline constexpr allocation_least_result + allocate_aligned_at_least(::std::size_t alignment, ::std::size_t n) noexcept + requires(!has_status) + { +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if (__builtin_is_constant_evaluated()) +#endif + { + return {::operator new(n), n}; + } + else +#endif + { + if constexpr (::fast_io::details::has_allocate_aligned_at_least_impl) + { + return allocator_type::allocate_aligned_at_least(alignment, n); + } + else if constexpr (::fast_io::details::has_allocate_aligned_zero_at_least_impl) + { + return allocator_type::allocate_aligned_zero_at_least(alignment, n); + } + else if constexpr (::fast_io::details::has_allocate_at_least_impl || + ::fast_io::details::has_allocate_zero_at_least_impl) + { + return ::fast_io::details::allocator_pointer_aligned_at_least_impl(alignment, n); + } + else + { + return {generic_allocator_adapter::allocate_aligned(alignment, n), n}; + } + } + } + + static inline constexpr allocation_least_result + allocate_aligned_zero_at_least(::std::size_t alignment, ::std::size_t n) noexcept + requires(!has_status) + { +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if (__builtin_is_constant_evaluated()) +#endif + { + return {::operator new(n), n}; + } + else +#endif + { + if constexpr (::fast_io::details::has_allocate_aligned_zero_at_least_impl) + { + return allocator_type::allocate_aligned_zero_at_least(alignment, n); + } + else if constexpr (::fast_io::details::has_allocate_aligned_at_least_impl) + { + auto temp{allocator_type::allocate_aligned_at_least(alignment, n)}; + ::fast_io::freestanding::bytes_clear_n(reinterpret_cast<::std::byte *>(temp.ptr), temp.count); + return temp; + } + else if constexpr (::fast_io::details::has_allocate_at_least_impl || + ::fast_io::details::has_allocate_zero_at_least_impl) + { + return ::fast_io::details::allocator_pointer_aligned_at_least_impl(alignment, n); + } + else + { + return {generic_allocator_adapter::allocate_aligned(alignment, n), n}; + } + } + } + + static inline constexpr bool has_reallocate_aligned = (::fast_io::details::has_reallocate_aligned_impl || + ::fast_io::details::has_reallocate_aligned_at_least_impl || + ::fast_io::details::has_reallocate_aligned_zero_impl || + ::fast_io::details::has_reallocate_aligned_zero_at_least_impl); + static inline + + void * + reallocate_aligned(void *p, ::std::size_t alignment, ::std::size_t n) noexcept + requires(!has_status && has_reallocate_aligned) + { + if constexpr (::fast_io::details::has_reallocate_aligned_impl) + { + return allocator_type::reallocate_aligned(p, alignment, n); + } + else if constexpr (::fast_io::details::has_reallocate_aligned_at_least_impl) + { + return allocator_type::reallocate_aligned_at_least(p, alignment, n).ptr; + } + else if constexpr (::fast_io::details::has_reallocate_aligned_zero_impl) + { + return allocator_type::reallocate_aligned_zero(p, alignment, n); + } + else if constexpr (::fast_io::details::has_reallocate_aligned_zero_at_least_impl) + { + return allocator_type::reallocate_aligned_zero_at_least(p, alignment, n).ptr; + } + } + static inline constexpr bool has_reallocate_aligned_zero = (::fast_io::details::has_reallocate_aligned_zero_impl || + ::fast_io::details::has_reallocate_aligned_zero_at_least_impl); + static inline + + void * + reallocate_aligned_zero(void *p, ::std::size_t alignment, ::std::size_t n) noexcept + requires(!has_status && has_reallocate_aligned_zero) + { + if constexpr (::fast_io::details::has_reallocate_aligned_zero_impl) + { + return allocator_type::reallocate_aligned_zero(p, alignment, n); + } + else if constexpr (::fast_io::details::has_reallocate_aligned_zero_at_least_impl) + { + return allocator_type::reallocate_aligned_zero(p, alignment, n).ptr; + } + } + static inline + + void * + reallocate_aligned_n(void *p, ::std::size_t oldn, ::std::size_t alignment, ::std::size_t n) noexcept + requires(!has_status) + { + if constexpr (::fast_io::details::has_reallocate_aligned_n_impl) + { + return allocator_type::reallocate_aligned_n(p, oldn, alignment, n); + } + else if constexpr (::fast_io::details::has_reallocate_aligned_n_at_least_impl) + { + return allocator_type::reallocate_aligned_n_at_least(p, oldn, alignment, n).ptr; + } + else if constexpr (::fast_io::details::has_reallocate_aligned_impl) + { + return allocator_type::reallocate_aligned(p, alignment, n); + } + else if constexpr (::fast_io::details::has_reallocate_aligned_at_least_impl) + { + return allocator_type::reallocate_aligned_at_least(p, alignment, n).ptr; + } + else if constexpr (::fast_io::details::has_reallocate_aligned_zero_n_impl) + { + return allocator_type::reallocate_aligned_zero_n(p, oldn, alignment, n); + } + else if constexpr (::fast_io::details::has_reallocate_aligned_zero_n_at_least_impl) + { + return allocator_type::reallocate_aligned_zero_n_at_least(p, oldn, alignment, n).ptr; + } + else if constexpr (::fast_io::details::has_reallocate_aligned_zero_impl) + { + return allocator_type::reallocate_aligned_zero(p, alignment, n); + } + else if constexpr (::fast_io::details::has_reallocate_aligned_zero_n_impl) + { + return allocator_type::reallocate_aligned_zero_n(p, alignment, n).ptr; + } + else + { + if constexpr (::fast_io::details::has_reallocate_n_impl || + ::fast_io::details::has_reallocate_zero_n_impl || + ::fast_io::details::has_reallocate_impl || + ::fast_io::details::has_reallocate_zero_impl) + { + if (alignment <= default_alignment) + { + return generic_allocator_adapter::reallocate_n(p, oldn, n); + } + } + auto newptr{::fast_io::details::allocator_pointer_aligned_impl(alignment, n)}; + if (p != nullptr && n) + { + if (oldn < n) + { + n = oldn; + } + ::fast_io::freestanding::nonoverlapped_bytes_copy_n(reinterpret_cast<::std::byte const *>(p), n, reinterpret_cast<::std::byte *>(newptr)); + generic_allocator_adapter::deallocate_aligned_n(p, alignment, oldn); + } + return newptr; + } + } + static inline + + void * + reallocate_aligned_zero_n(void *p, ::std::size_t oldn, ::std::size_t alignment, ::std::size_t n) noexcept + requires(!has_status) + { + if constexpr (::fast_io::details::has_reallocate_aligned_zero_n_impl) + { + return allocator_type::reallocate_aligned_zero_n(p, oldn, alignment, n); + } + else if constexpr (::fast_io::details::has_reallocate_aligned_zero_n_at_least_impl) + { + return allocator_type::reallocate_aligned_zero_n_at_least(p, oldn, alignment, n).ptr; + } + else + { + auto newptr{generic_allocator_adapter::reallocate_aligned_n(p, oldn, alignment, n)}; + if (oldn < n) + { + ::std::size_t const to_zero_bytes{static_cast<::std::size_t>(n - oldn)}; + ::fast_io::freestanding::bytes_clear_n(reinterpret_cast<::std::byte *>(newptr) + oldn, to_zero_bytes); + } + return newptr; + } + } + + static inline constexpr bool has_native_reallocate_at_least = (has_reallocate && + (::fast_io::details::has_reallocate_aligned_at_least_impl || + ::fast_io::details::has_reallocate_aligned_zero_at_least_impl)); + static inline + + ::fast_io::allocation_least_result + reallocate_at_least(void *p, ::std::size_t n) noexcept + requires(!has_status && has_reallocate) + { + if constexpr (::fast_io::details::has_reallocate_at_least_impl) + { + return allocator_type::reallocate_at_least(p, n); + } + else if constexpr (::fast_io::details::has_reallocate_aligned_at_least_impl) + { + return allocator_type::reallocate_aligned_at_least(p, default_alignment, n); + } + else if constexpr (::fast_io::details::has_reallocate_zero_at_least_impl) + { + return allocator_type::reallocate_zero_at_least(p, n); + } + else if constexpr (::fast_io::details::has_reallocate_aligned_zero_at_least_impl) + { + return allocator_type::reallocate_aligned_zero_at_least(p, default_alignment, n); + } + else if constexpr (::fast_io::details::has_reallocate_impl) + { + return {allocator_type::reallocate(p, n), n}; + } + else if constexpr (::fast_io::details::has_reallocate_aligned_impl) + { + return {allocator_type::reallocate_aligned(p, default_alignment, n), n}; + } + else if constexpr (::fast_io::details::has_reallocate_zero_impl) + { + return {allocator_type::reallocate_zero(p, n), n}; + } + else if constexpr (::fast_io::details::has_reallocate_aligned_zero_impl) + { + return {allocator_type::reallocate_aligned_zero(p, default_alignment, n), n}; + } + } + + static inline constexpr bool has_native_reallocate_zero_at_least = (has_reallocate_zero && + (::fast_io::details::has_reallocate_zero_at_least_impl || + ::fast_io::details::has_reallocate_aligned_zero_at_least_impl)); + static inline + + ::fast_io::allocation_least_result + reallocate_zero_at_least(void *p, ::std::size_t n) noexcept + requires(!has_status && has_reallocate) + { + if constexpr (::fast_io::details::has_reallocate_zero_at_least_impl) + { + return allocator_type::reallocate_zero_at_least(p, n); + } + else if constexpr (::fast_io::details::has_reallocate_aligned_zero_at_least_impl) + { + return allocator_type::reallocate_aligned_zero_at_least(p, default_alignment, n); + } + else if constexpr (::fast_io::details::has_reallocate_zero_impl) + { + return {allocator_type::reallocate_zero(p, n), n}; + } + else if constexpr (::fast_io::details::has_reallocate_aligned_impl) + { + return {allocator_type::reallocate_aligned(p, default_alignment, n), n}; + } + } + + static inline + + ::fast_io::allocation_least_result + reallocate_n_at_least(void *p, ::std::size_t oldn, ::std::size_t n) noexcept + requires(!has_status) + { + if constexpr (::fast_io::details::has_reallocate_n_at_least_impl) + { + return allocator_type::reallocate_n_at_least(p, oldn, n); + } + else if constexpr (::fast_io::details::has_reallocate_aligned_n_at_least_impl) + { + return allocator_type::reallocate_aligned_n_at_least(p, oldn, default_alignment, n); + } + else if constexpr (::fast_io::details::has_reallocate_zero_n_at_least_impl) + { + return allocator_type::reallocate_zero_n_at_least(p, oldn, n); + } + else if constexpr (::fast_io::details::has_reallocate_aligned_zero_n_at_least_impl) + { + return allocator_type::reallocate_aligned_zero_n_at_least(p, oldn, default_alignment, n); + } + else if constexpr (::fast_io::details::has_reallocate_at_least_impl) + { + return allocator_type::reallocate_at_least(p, n); + } + else if constexpr (::fast_io::details::has_reallocate_aligned_at_least_impl) + { + return allocator_type::reallocate_aligned_at_least(p, default_alignment, n); + } + else if constexpr (::fast_io::details::has_reallocate_zero_at_least_impl) + { + return allocator_type::reallocate_zero_at_least(p, n); + } + else if constexpr (::fast_io::details::has_reallocate_aligned_zero_at_least_impl) + { + return allocator_type::reallocate_aligned_zero_at_least(p, default_alignment, n); + } + else if constexpr (::fast_io::details::has_reallocate_n_impl) + { + return {allocator_type::reallocate_n(p, oldn, n), n}; + } + else if constexpr (::fast_io::details::has_reallocate_aligned_n_impl) + { + return {allocator_type::reallocate_aligned_n(p, oldn, default_alignment, n), n}; + } + else if constexpr (::fast_io::details::has_reallocate_zero_n_impl) + { + return {allocator_type::reallocate_zero_n(p, oldn, n), n}; + } + else if constexpr (::fast_io::details::has_reallocate_aligned_zero_n_impl) + { + return {allocator_type::reallocate_aligned_zero_n(p, oldn, default_alignment, n), n}; + } + else if constexpr (::fast_io::details::has_reallocate_impl) + { + return {allocator_type::reallocate(p, n), n}; + } + else if constexpr (::fast_io::details::has_reallocate_aligned_impl) + { + return {allocator_type::reallocate_aligned(p, default_alignment, n), n}; + } + else if constexpr (::fast_io::details::has_reallocate_zero_impl) + { + return {allocator_type::reallocate_zero(p, n), n}; + } + else if constexpr (::fast_io::details::has_reallocate_aligned_zero_impl) + { + return {allocator_type::reallocate_aligned_zero(p, default_alignment, n), n}; + } + else + { + auto newres{generic_allocator_adapter::allocate_at_least(n)}; + auto newptr{newres.ptr}; + if (p != nullptr && n) + { + if (oldn < n) + { + n = oldn; + } + ::fast_io::freestanding::nonoverlapped_bytes_copy_n(reinterpret_cast<::std::byte const *>(p), n, reinterpret_cast<::std::byte *>(newptr)); + generic_allocator_adapter::deallocate_n(p, oldn); + } + return newres; + } + } + + static inline + + ::fast_io::allocation_least_result + reallocate_zero_n_at_least(void *p, ::std::size_t oldn, ::std::size_t n) noexcept + requires(!has_status) + { + if constexpr (::fast_io::details::has_reallocate_zero_n_at_least_impl) + { + return allocator_type::reallocate_zero_n_at_least(p, oldn, n); + } + else if constexpr (::fast_io::details::has_reallocate_aligned_zero_n_at_least_impl) + { + return allocator_type::reallocate_aligned_zero_n_at_least(p, oldn, default_alignment, n); + } + else if constexpr (::fast_io::details::has_reallocate_zero_at_least_impl) + { + return allocator_type::reallocate_zero_at_least(p, n); + } + else if constexpr (::fast_io::details::has_reallocate_aligned_zero_at_least_impl) + { + return allocator_type::reallocate_aligned_zero_at_least(p, default_alignment, n); + } + else + { + auto newres{generic_allocator_adapter::reallocate_n_at_least(p, oldn, n)}; + auto newptr{newres.ptr}; + n = newres.count; + if (oldn < n) + { + ::std::size_t const to_zero_bytes{static_cast<::std::size_t>(n - oldn)}; + ::fast_io::freestanding::bytes_clear_n(reinterpret_cast<::std::byte *>(newptr) + oldn, to_zero_bytes); + } + return newres; + } + } + + static inline constexpr bool has_native_reallocate_aligned_at_least = (has_reallocate_aligned && + (::fast_io::details::has_reallocate_aligned_zero_at_least_impl || + ::fast_io::details::has_reallocate_aligned_at_least_impl)); + + static inline ::fast_io::allocation_least_result + reallocate_aligned_at_least(void *p, ::std::size_t alignment, ::std::size_t n) noexcept + requires(!has_status && has_reallocate_aligned_zero) + { + if constexpr (::fast_io::details::has_reallocate_aligned_at_least_impl) + { + return allocator_type::reallocate_aligned_at_least(p, alignment, n); + } + else if constexpr (::fast_io::details::has_reallocate_aligned_zero_at_least_impl) + { + return allocator_type::reallocate_aligned_zero_at_least(p, alignment, n); + } + else if constexpr (::fast_io::details::has_reallocate_aligned_impl) + { + return {allocator_type::reallocate_aligned(p, alignment, n), n}; + } + else if constexpr (::fast_io::details::has_reallocate_aligned_zero_impl) + { + return {allocator_type::reallocate_aligned_zero(p, alignment, n), n}; + } + } + + static inline constexpr bool has_native_reallocate_aligned_zero_at_least = (has_reallocate_aligned_zero && + ::fast_io::details::has_reallocate_aligned_zero_at_least_impl); + + static inline ::fast_io::allocation_least_result + reallocate_aligned_zero_at_least(void *p, ::std::size_t alignment, ::std::size_t n) noexcept + requires(!has_status && has_reallocate_aligned_zero) + { + if constexpr (::fast_io::details::has_reallocate_aligned_zero_at_least_impl) + { + return allocator_type::reallocate_aligned_zero_at_least(p, alignment, n); + } + else if constexpr (::fast_io::details::has_reallocate_aligned_zero_impl) + { + return {allocator_type::reallocate_aligned_zero(p, alignment, n), n}; + } + } + + static inline constexpr bool has_native_reallocate_aligned_n_at_least = (has_reallocate_aligned && + (::fast_io::details::has_reallocate_aligned_n_at_least_impl || + ::fast_io::details::has_reallocate_aligned_zero_n_at_least_impl)); + static inline ::fast_io::allocation_least_result + reallocate_aligned_n_at_least(void *p, ::std::size_t oldn, ::std::size_t alignment, ::std::size_t n) noexcept + requires(!has_status) + { + if constexpr (::fast_io::details::has_reallocate_aligned_n_at_least_impl) + { + return allocator_type::reallocate_aligned_n_at_least(p, alignment, n); + } + else if constexpr (::fast_io::details::has_reallocate_aligned_at_least_impl) + { + return allocator_type::reallocate_aligned_at_least(p, alignment, n); + } + else if constexpr (::fast_io::details::has_reallocate_aligned_zero_n_at_least_impl) + { + return allocator_type::reallocate_aligned_zero_n_at_least(p, alignment, n); + } + else if constexpr (::fast_io::details::has_reallocate_aligned_zero_at_least_impl) + { + return allocator_type::reallocate_aligned_zero_at_least(p, alignment, n); + } + else if constexpr (::fast_io::details::has_reallocate_aligned_impl) + { + return allocator_type::reallocate_aligned_n(p, alignment, n); + } + else if constexpr (::fast_io::details::has_reallocate_aligned_impl) + { + return allocator_type::reallocate_aligned(p, alignment, n); + } + else if constexpr (::fast_io::details::has_reallocate_aligned_zero_n_impl) + { + return allocator_type::reallocate_aligned_zero_n(p, alignment, n); + } + else if constexpr (::fast_io::details::has_reallocate_aligned_zero_impl) + { + return allocator_type::reallocate_aligned_zero(p, alignment, n); + } + else + { + if constexpr ( + ::fast_io::details::has_reallocate_at_least_impl || + ::fast_io::details::has_reallocate_zero_at_least_impl || + ::fast_io::details::has_reallocate_n_at_least_impl || + ::fast_io::details::has_reallocate_zero_n_at_least_impl) + { + if (alignment <= default_alignment) + { + return generic_allocator_adapter::reallocate_n_at_least(p, oldn, n); + } + } + auto newres{::fast_io::details::allocator_pointer_aligned_at_least_impl(alignment, n)}; + auto newptr{newres.ptr}; + if (p != nullptr && n) + { + if (oldn < n) + { + n = oldn; + } + ::fast_io::freestanding::nonoverlapped_bytes_copy_n(reinterpret_cast<::std::byte const *>(p), n, reinterpret_cast<::std::byte *>(newptr)); + generic_allocator_adapter::deallocate_aligned_n(p, alignment, oldn); + } + return newres; + } + } + + static inline constexpr bool has_native_reallocate_aligned_zero_n_at_least = (has_reallocate_aligned_zero && ::fast_io::details::has_reallocate_aligned_zero_at_least_impl); + + static inline ::fast_io::allocation_least_result reallocate_aligned_zero_n_at_least(void *p, ::std::size_t oldn, ::std::size_t alignment, ::std::size_t n) noexcept + requires(!has_status) + { + if constexpr (::fast_io::details::has_reallocate_aligned_zero_n_at_least_impl) + { + return allocator_type::reallocate_aligned_zero_n_at_least(p, alignment, n); + } + else if constexpr (::fast_io::details::has_reallocate_aligned_zero_n_impl) + { + return {allocator_type::reallocate_aligned_zero_n(p, alignment, n), n}; + } + else + { + auto newres = generic_allocator_adapter::reallocate_aligned_n_at_least(p, oldn, alignment, n); + auto newptr{newres.ptr}; + n = newres.count; + if (oldn < n) + { + ::std::size_t const to_zero_bytes{static_cast<::std::size_t>(n - oldn)}; + ::fast_io::freestanding::bytes_clear_n(reinterpret_cast<::std::byte *>(newptr) + oldn, to_zero_bytes); + } + return newres; + } + } + + static inline constexpr bool has_deallocate_aligned = (::fast_io::details::has_deallocate_aligned_impl || + ::fast_io::details::has_deallocate_impl); + static inline void deallocate_aligned(void *p, ::std::size_t alignment) noexcept + requires(!has_status && has_deallocate_aligned) + { + if constexpr (::fast_io::details::has_deallocate_aligned_impl) + { + allocator_type::deallocate_aligned(p, alignment); + } + else + { + if (p == nullptr) + { + return; + } + if (default_alignment < alignment) + { + p = reinterpret_cast(p)[-1]; + } + allocator_type::deallocate(p); + } + } + static inline void deallocate_aligned_n(void *p, ::std::size_t alignment, ::std::size_t n) noexcept + requires(!has_status) + { + if constexpr (::fast_io::details::has_deallocate_aligned_n_impl) + { + allocator_type::deallocate_aligned_n(p, alignment, n); + } + else if constexpr (::fast_io::details::has_deallocate_aligned_impl) + { + allocator_type::deallocate_aligned(p, alignment); + } + else + { + if (p == nullptr) + { + return; + } + if (default_alignment < alignment) + { + auto start{reinterpret_cast(p)[-1]}; + n += static_cast<::std::size_t>(reinterpret_cast(p) - reinterpret_cast(start)); + p = start; + } + if constexpr (::fast_io::details::has_deallocate_impl) + { + allocator_type::deallocate(p); + } + else + { + allocator_type::deallocate_n(p, n); + } + } + } +}; + +template +class typed_generic_allocator_adapter +{ +public: + using allocator_adaptor = alloc; + static inline constexpr bool has_status{allocator_adaptor::has_status}; + using handle_type = typename allocator_adaptor::handle_type; + static inline +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L + constexpr +#endif + + T * + allocate(::std::size_t n) noexcept + requires(!has_status) + { +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if (__builtin_is_constant_evaluated()) +#endif + { + return ::fast_io::freestanding::allocator{}.allocate(n); + } +#endif + constexpr ::std::size_t mxn{::std::numeric_limits<::std::size_t>::max() / sizeof(T)}; + if (n > mxn) + { + ::fast_io::fast_terminate(); + } + if constexpr (alignof(T) <= alloc::default_alignment) + { + return static_cast(alloc::allocate(n * sizeof(T))); + } + else + { + return static_cast(alloc::allocate_aligned(n * sizeof(T), alignof(T))); + } + } + + static inline +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L + constexpr +#endif + + basic_allocation_least_result + allocate_at_least(::std::size_t n) noexcept + requires(!has_status) + { +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if (__builtin_is_constant_evaluated()) +#endif + { + return {::fast_io::freestanding::allocator{}.allocate(n), n}; + } +#endif + constexpr ::std::size_t mxn{::std::numeric_limits<::std::size_t>::max() / sizeof(T)}; + if (n > mxn) + { + ::fast_io::fast_terminate(); + } + if constexpr (alignof(T) <= alloc::default_alignment) + { + auto newres{alloc::allocate_at_least(n * sizeof(T))}; + return {reinterpret_cast(newres.ptr), newres.count / sizeof(T)}; + } + else + { + auto newres{alloc::allocate_aligned_at_least(n * sizeof(T), alignof(T))}; + return {reinterpret_cast(newres.ptr), newres.count / sizeof(T)}; + } + } + + static inline +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L + constexpr +#endif + + T * + allocate_zero(::std::size_t n) noexcept + requires(!has_status) + { + constexpr ::std::size_t mxn{::std::numeric_limits<::std::size_t>::max() / sizeof(T)}; + if (n > mxn) + { + ::fast_io::fast_terminate(); + } + if constexpr (alignof(T) <= alloc::default_alignment) + { + return static_cast(alloc::allocate_zero(n * sizeof(T))); + } + else + { + return static_cast(alloc::allocate_zero_aligned(n * sizeof(T), alignof(T))); + } + } + + static inline +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L + constexpr +#endif + + basic_allocation_least_result + allocate_zero_at_least(::std::size_t n) noexcept + requires(!has_status) + { +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if (__builtin_is_constant_evaluated()) +#endif + { + return ::fast_io::freestanding::allocator{}.allocate(n); + } +#endif + constexpr ::std::size_t mxn{::std::numeric_limits<::std::size_t>::max() / sizeof(T)}; + if (n > mxn) + { + ::fast_io::fast_terminate(); + } + if constexpr (alignof(T) <= alloc::default_alignment) + { + auto newres{alloc::allocate_zero_at_least(n * sizeof(T))}; + return {reinterpret_cast(newres.ptr), newres.count / sizeof(T)}; + } + else + { + auto newres{alloc::allocate_zero_aligned_at_least(n * sizeof(T), alignof(T))}; + return {reinterpret_cast(newres.ptr), newres.count / sizeof(T)}; + } + } + + static inline constexpr bool has_reallocate = allocator_adaptor::has_reallocate; + + static inline +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L + constexpr +#endif + + T * + reallocate(T *ptr, ::std::size_t n) noexcept + requires(!has_status && has_reallocate) + { + constexpr ::std::size_t mxn{::std::numeric_limits<::std::size_t>::max() / sizeof(T)}; + if (n > mxn) + { + ::fast_io::fast_terminate(); + } + if constexpr (alignof(T) <= alloc::default_alignment) + { + return static_cast(alloc::reallocate(ptr, n * sizeof(T))); + } + else + { + return static_cast(alloc::reallocate_aligned(ptr, n * sizeof(T), alignof(T))); + } + } + + static inline +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L + constexpr +#endif + + basic_allocation_least_result + reallocate_at_least(T *ptr, ::std::size_t n) noexcept + requires(!has_status && has_reallocate) + { + constexpr ::std::size_t mxn{::std::numeric_limits<::std::size_t>::max() / sizeof(T)}; + if (n > mxn) + { + ::fast_io::fast_terminate(); + } + if constexpr (alignof(T) <= alloc::default_alignment) + { + auto newres{alloc::reallocate_zero_at_least(ptr, n * sizeof(T))}; + return {reinterpret_cast(newres.ptr), newres.count / sizeof(T)}; + } + else + { + auto newres{alloc::reallocate_aligned_zero_at_least(ptr, n * sizeof(T), alignof(T))}; + return {reinterpret_cast(newres.ptr), newres.count / sizeof(T)}; + } + } + + static inline constexpr bool has_reallocate_zero = allocator_adaptor::has_reallocate_zero; + static inline +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L + constexpr +#endif + + T * + reallocate_zero(T *ptr, ::std::size_t n) noexcept + requires(!has_status && has_reallocate_zero) + { + constexpr ::std::size_t mxn{::std::numeric_limits<::std::size_t>::max() / sizeof(T)}; + if (n > mxn) + { + ::fast_io::fast_terminate(); + } + if constexpr (alignof(T) <= alloc::default_alignment) + { + return static_cast(alloc::reallocate_zero(ptr, n * sizeof(T))); + } + else + { + return static_cast(alloc::reallocate_aligned_zero(ptr, n * sizeof(T), alignof(T))); + } + } + + static inline +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L + constexpr +#endif + + basic_allocation_least_result + reallocate_zero_at_least(T *ptr, ::std::size_t n) noexcept + requires(!has_status && has_reallocate_zero) + { + constexpr ::std::size_t mxn{::std::numeric_limits<::std::size_t>::max() / sizeof(T)}; + if (n > mxn) + { + ::fast_io::fast_terminate(); + } + if constexpr (alignof(T) <= alloc::default_alignment) + { + auto newres{alloc::reallocate_zero_at_least(ptr, n * sizeof(T))}; + return {reinterpret_cast(newres.ptr), newres.count / sizeof(T)}; + } + else + { + auto newres{alloc::reallocate_aligned_zero_at_least(ptr, alignof(T), n * sizeof(T))}; + return {reinterpret_cast(newres.ptr), newres.count / sizeof(T)}; + } + } + + static inline +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L + constexpr +#endif + + T * + reallocate_n(T *ptr, ::std::size_t oldn, ::std::size_t n) noexcept + requires(!has_status) + { + constexpr ::std::size_t mxn{::std::numeric_limits<::std::size_t>::max() / sizeof(T)}; + if (n > mxn) + { + ::fast_io::fast_terminate(); + } + if constexpr (alignof(T) <= alloc::default_alignment) + { + return static_cast(alloc::reallocate_n(ptr, oldn * sizeof(T), n * sizeof(T))); + } + else + { + return static_cast(alloc::reallocate_aligned_n(ptr, oldn * sizeof(T), alignof(T), n * sizeof(T))); + } + } + + static inline +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L + constexpr +#endif + + basic_allocation_least_result + reallocate_n_at_least(T *ptr, ::std::size_t oldn, ::std::size_t n) noexcept + requires(!has_status) + { + constexpr ::std::size_t mxn{::std::numeric_limits<::std::size_t>::max() / sizeof(T)}; + if (n > mxn) + { + ::fast_io::fast_terminate(); + } + if constexpr (alignof(T) <= alloc::default_alignment) + { + auto newres{alloc::reallocate_n_at_least(ptr, oldn * sizeof(T), n * sizeof(T))}; + return {reinterpret_cast(newres.ptr), newres.count / sizeof(T)}; + } + else + { + auto newres{alloc::reallocate_aligned_n_at_least(ptr, oldn * sizeof(T), alignof(T), n * sizeof(T))}; + return {reinterpret_cast(newres.ptr), newres.count / sizeof(T)}; + } + } + + static inline +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L + constexpr +#endif + + T * + reallocate_zero_n(T *ptr, ::std::size_t oldn, ::std::size_t n) noexcept + requires(!has_status) + { + constexpr ::std::size_t mxn{::std::numeric_limits<::std::size_t>::max() / sizeof(T)}; + if (n > mxn) + { + ::fast_io::fast_terminate(); + } + if constexpr (alignof(T) <= alloc::default_alignment) + { + return static_cast(alloc::reallocate_zero_n(ptr, oldn * sizeof(T), n * sizeof(T))); + } + else + { + return static_cast(alloc::reallocate_aligned_zero_n(ptr, oldn * sizeof(T), alignof(T), n * sizeof(T))); + } + } + + static inline +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L + constexpr +#endif + + basic_allocation_least_result + reallocate_zero_n_at_least(T *ptr, ::std::size_t oldn, ::std::size_t n) noexcept + requires(!has_status) + { + constexpr ::std::size_t mxn{::std::numeric_limits<::std::size_t>::max() / sizeof(T)}; + if (n > mxn) + { + ::fast_io::fast_terminate(); + } + if constexpr (alignof(T) <= alloc::default_alignment) + { + auto newres{alloc::reallocate_zero_n_at_least(ptr, oldn * sizeof(T), n * sizeof(T))}; + return {reinterpret_cast(newres.ptr), newres.count / sizeof(T)}; + } + else + { + auto newres{alloc::reallocate_aligned_zero_n_at_least(ptr, oldn * sizeof(T), alignof(T), n * sizeof(T))}; + return {reinterpret_cast(newres.ptr), newres.count / sizeof(T)}; + } + } + + static inline constexpr bool has_deallocate = allocator_adaptor::has_deallocate; + static inline +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L + constexpr +#endif + void + deallocate(T *ptr) noexcept + requires(!has_status && has_deallocate) + { +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if (__builtin_is_constant_evaluated()) +#endif + { + if (ptr) + { + return ::fast_io::freestanding::allocator{}.deallocate(ptr, 1); + } + else + { + return; + } + } +#endif + if constexpr (alignof(T) <= alloc::default_alignment) + { + return alloc::deallocate(ptr); + } + else + { + return alloc::deallocate_aligned(ptr, alignof(T)); + } + } + static inline +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L + constexpr +#endif + void + deallocate_n(T *ptr, ::std::size_t n) noexcept + requires(!has_status) + { +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if (__builtin_is_constant_evaluated()) +#endif + { + if (ptr) + { + return ::fast_io::freestanding::allocator{}.deallocate(ptr, n); + } + else + { + return; + } + } +#endif + if constexpr (alignof(T) <= alloc::default_alignment) + { + alloc::deallocate_n(ptr, n * sizeof(T)); + } + else + { + alloc::deallocate_aligned_n(ptr, alignof(T), n * sizeof(T)); + } + } +#if 0 + static inline +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L + constexpr +#endif + + + T * + handle_allocate(handle_type handle, ::std::size_t n) noexcept + requires(has_status) + { +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if (__builtin_is_constant_evaluated()) +#endif + { + if (n) + { + return ::fast_io::freestanding::allocator{}.allocate(n); + } + else + { + return nullptr; + } + } +#endif + constexpr ::std::size_t mxn{::std::numeric_limits<::std::size_t>::max() / sizeof(T)}; + if (n > mxn) + { + ::fast_io::fast_terminate(); + } + if constexpr (alignof(T) <= alloc::default_alignment) + { + return static_cast(alloc::handle_allocate(handle, n * sizeof(T))); + } + else + { + return static_cast(alloc::handle_allocate_aligned(handle, n * sizeof(T), alignof(T))); + } + } + static inline +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L + constexpr +#endif + + + T * + handle_allocate_zero(handle_type handle, ::std::size_t n) noexcept + requires(has_status) + { + constexpr ::std::size_t mxn{::std::numeric_limits<::std::size_t>::max() / sizeof(T)}; + if (n > mxn) + { + ::fast_io::fast_terminate(); + } + if constexpr (alignof(T) <= alloc::default_alignment) + { + return static_cast(alloc::handle_allocate_zero(handle, n * sizeof(T))); + } + else + { + return static_cast(alloc::handle_allocate_zero_aligned(handle, n * sizeof(T), alignof(T))); + } + } + + static inline constexpr bool has_handle_reallocate = allocator_adaptor::has_handle_reallocate; + static inline +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L + constexpr +#endif + + + T * + handle_reallocate(handle_type handle, T *ptr, ::std::size_t n) noexcept + requires(has_status && has_handle_reallocate) + { + constexpr ::std::size_t mxn{::std::numeric_limits<::std::size_t>::max() / sizeof(T)}; + if (n > mxn) + { + ::fast_io::fast_terminate(); + } + if constexpr (alignof(T) <= alloc::default_alignment) + { + return static_cast(alloc::handle_reallocate(handle, ptr, n * sizeof(T))); + } + else + { + return static_cast(alloc::handle_reallocate_aligned(handle, ptr, n * sizeof(T), alignof(T))); + } + } + static inline constexpr bool has_handle_reallocate_zero = allocator_adaptor::has_handle_reallocate_zero; + static inline +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L + constexpr +#endif + + + T * + handle_reallocate_zero(handle_type handle, T *ptr, ::std::size_t n) noexcept + requires(has_status && has_handle_reallocate) + { + constexpr ::std::size_t mxn{::std::numeric_limits<::std::size_t>::max() / sizeof(T)}; + if (n > mxn) + { + ::fast_io::fast_terminate(); + } + if constexpr (alignof(T) <= alloc::default_alignment) + { + return static_cast(alloc::handle_reallocate_zero(handle, ptr, n * sizeof(T))); + } + else + { + return static_cast(alloc::handle_reallocate_aligned_zero(handle, ptr, n * sizeof(T), alignof(T))); + } + } + static inline +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L + constexpr +#endif + + + T * + handle_reallocate_n(handle_type handle, T *ptr, ::std::size_t oldn, ::std::size_t n) noexcept + requires(has_status) + { + constexpr ::std::size_t mxn{::std::numeric_limits<::std::size_t>::max() / sizeof(T)}; + if (n > mxn) + { + ::fast_io::fast_terminate(); + } + if constexpr (alignof(T) <= alloc::default_alignment) + { + return static_cast(alloc::handle_reallocate_n(handle, ptr, oldn * sizeof(T), n * sizeof(T))); + } + else + { + return static_cast(alloc::handle_reallocate_aligned_n(handle, ptr, oldn * sizeof(T), alignof(T), n * sizeof(T))); + } + } + static inline +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L + constexpr +#endif + + + T * + handle_reallocate_zero_n(handle_type handle, T *ptr, ::std::size_t oldn, ::std::size_t n) noexcept + requires(has_status) + { + constexpr ::std::size_t mxn{::std::numeric_limits<::std::size_t>::max() / sizeof(T)}; + if (n > mxn) + { + ::fast_io::fast_terminate(); + } + if constexpr (alignof(T) <= alloc::default_alignment) + { + return static_cast(alloc::handle_reallocate_zero_n(handle, ptr, oldn * sizeof(T), n * sizeof(T))); + } + else + { + return static_cast(alloc::handle_reallocate_aligned_zero_n(handle, ptr * sizeof(T), oldn, n * sizeof(T), alignof(T))); + } + } + + static inline constexpr bool has_handle_deallocate = allocator_adaptor::has_handle_deallocate; + static inline +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L + constexpr +#endif + void + handle_deallocate(handle_type handle, T *ptr) noexcept + requires(has_status && has_handle_deallocate) + { +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if (__builtin_is_constant_evaluated()) +#endif + { + if (ptr) + { + return ::fast_io::freestanding::allocator{}.deallocate(ptr, 1); + } + else + { + return; + } + } +#endif + if constexpr (alignof(T) <= alloc::default_alignment) + { + return alloc::handle_deallocate(handle, ptr); + } + else + { + return alloc::handle_deallocate_aligned(handle, ptr, alignof(T)); + } + } + static inline +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L + constexpr +#endif + void + handle_deallocate_n(handle_type handle, T *ptr, ::std::size_t n) noexcept + requires(has_status) + { +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && \ + __cpp_constexpr_dynamic_alloc >= 201907L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if (__builtin_is_constant_evaluated()) +#endif + { + if (ptr) + { + return ::fast_io::freestanding::allocator{}.deallocate(ptr, n); + } + else + { + return; + } + } +#endif + if constexpr (alignof(T) <= alloc::default_alignment) + { + alloc::handle_deallocate_n(handle, ptr, n * sizeof(T)); + } + else + { + alloc::handle_deallocate_aligned_n(handle, ptr, alignof(T), n * sizeof(T)); + } + } +#endif +}; + +namespace details +{ + +template +inline constexpr void *allocator_pointer_aligned_impl(::std::size_t alignment, ::std::size_t n) noexcept +{ + if constexpr (!::fast_io::generic_allocator_adapter::has_native_allocate) + { + ::fast_io::fast_terminate(); + } + else + { + constexpr ::std::size_t defaultalignment{::fast_io::details::calculate_default_alignment()}; + bool const alignedadjustment{defaultalignment < alignment}; + if (alignedadjustment) + { + n = ::fast_io::details::allocator_compute_aligned_total_size_impl(alignment, n); + } + void *p; + if constexpr (zero) + { + p = ::fast_io::generic_allocator_adapter::allocate_zero(n); + } + else + { + p = ::fast_io::generic_allocator_adapter::allocate(n); + } + if (alignedadjustment) + { + p = ::fast_io::details::allocator_adjust_ptr_to_aligned_impl(p, alignment); + } + return p; + } +} + +template +inline constexpr ::fast_io::allocation_least_result allocator_pointer_aligned_at_least_impl(::std::size_t alignment, ::std::size_t n) noexcept +{ + if constexpr (!::fast_io::generic_allocator_adapter::has_native_allocate) + { + ::fast_io::fast_terminate(); + } + else + { + constexpr ::std::size_t defaultalignment{::fast_io::details::calculate_default_alignment()}; + bool const alignedadjustment{defaultalignment < alignment}; + if (alignedadjustment) + { + n = ::fast_io::details::allocator_compute_aligned_total_size_impl(alignment, n); + } + ::fast_io::allocation_least_result res; + if constexpr (zero) + { + res = ::fast_io::generic_allocator_adapter::allocate_zero_at_least(n); + } + else + { + res = ::fast_io::generic_allocator_adapter::allocate_at_least(n); + } + if (alignedadjustment) + { + auto resptr{res.ptr}; + auto aligned_ptr = ::fast_io::details::allocator_adjust_ptr_to_aligned_impl(resptr, alignment); + res = {aligned_ptr, res.count - static_cast<::std::size_t>(reinterpret_cast(aligned_ptr) - reinterpret_cast(resptr))}; + } + return res; + } +} +#if 0 +template +inline constexpr void *status_allocator_pointer_aligned_impl(typename alloc::handle_type handle, ::std::size_t alignment, ::std::size_t n) noexcept +{ + if constexpr (!::fast_io::generic_allocator_adapter::has_native_handle_allocate) + { + ::fast_io::fast_terminate(); + } + else + { + constexpr ::std::size_t defaultalignment{::fast_io::details::calculate_default_alignment()}; + bool const alignedadjustment{defaultalignment < alignment}; + if (alignedadjustment) + { + n = ::fast_io::details::allocator_compute_aligned_total_size_impl(alignment, n); + } + void *p; + if constexpr (zero) + { + p = ::fast_io::generic_allocator_adapter::handle_allocate_zero(handle, n); + } + else + { + p = ::fast_io::generic_allocator_adapter::handle_allocate(handle, n); + } + if (alignedadjustment) + { + p = ::fast_io::details::allocator_adjust_ptr_to_aligned_impl(p,alignment); + } + return p; + } +} + +template +inline constexpr ::fast_io::allocation_least_result status_allocator_pointer_aligned_impl(typename alloc::handle_type handle, ::std::size_t alignment, ::std::size_t n) noexcept +{ + if constexpr (!::fast_io::generic_allocator_adapter::has_native_handle_allocate) + { + ::fast_io::fast_terminate(); + } + else + { + constexpr ::std::size_t defaultalignment{::fast_io::details::calculate_default_alignment()}; + bool const alignedadjustment{defaultalignment < alignment}; + if (alignedadjustment) + { + n = ::fast_io::details::allocator_compute_aligned_total_size_impl(alignment, n); + } + ::fast_io::allocation_least_result res; + if constexpr (zero) + { + res = ::fast_io::generic_allocator_adapter::handle_allocate_zero_at_least(handle, n); + } + else + { + res = ::fast_io::generic_allocator_adapter::handle_allocate_at_least(handle, n); + } + if (alignedadjustment) + { + auto resptr{res.ptr}; + auto aligned_ptr = ::fast_io::details::allocator_adjust_ptr_to_aligned_impl(resptr,alignment); + res = {aligned_ptr,res.count-static_cast<::std::size_t>(reinterpret_cast(aligned_ptr)-reinterpret_cast(resptr))}; + } + return res; + } +} +#endif +} // namespace details + +} // namespace fast_io + +#pragma pop_macro("new") diff --git a/src/fast_io/include/fast_io_core_impl/allocation/allocator_adapter_flags.h b/src/fast_io/include/fast_io_core_impl/allocation/allocator_adapter_flags.h new file mode 100644 index 0000000..4ca7025 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/allocation/allocator_adapter_flags.h @@ -0,0 +1,47 @@ +#pragma once + +enum class allocator_adapter_flags +{ + none = 0, + record_size = 1, + secure_clear = 2 +}; + +constexpr allocator_adapter_flags operator&(allocator_adapter_flags x, allocator_adapter_flags y) noexcept +{ + using utype = typename ::std::underlying_type::type; + return static_cast(static_cast(x) & static_cast(y)); +} + +constexpr allocator_adapter_flags operator|(allocator_adapter_flags x, allocator_adapter_flags y) noexcept +{ + using utype = typename ::std::underlying_type::type; + return static_cast(static_cast(x) | static_cast(y)); +} + +constexpr allocator_adapter_flags operator^(allocator_adapter_flags x, allocator_adapter_flags y) noexcept +{ + using utype = typename ::std::underlying_type::type; + return static_cast(static_cast(x) ^ static_cast(y)); +} + +constexpr allocator_adapter_flags operator~(allocator_adapter_flags x) noexcept +{ + using utype = typename ::std::underlying_type::type; + return static_cast(~static_cast(x)); +} + +inline constexpr allocator_adapter_flags &operator&=(allocator_adapter_flags &x, allocator_adapter_flags y) noexcept +{ + return x = x & y; +} + +inline constexpr allocator_adapter_flags &operator|=(allocator_adapter_flags &x, allocator_adapter_flags y) noexcept +{ + return x = x | y; +} + +inline constexpr allocator_adapter_flags &operator^=(allocator_adapter_flags &x, allocator_adapter_flags y) noexcept +{ + return x = x ^ y; +} diff --git a/src/fast_io/include/fast_io_core_impl/allocation/c_malloc.h b/src/fast_io/include/fast_io_core_impl/allocation/c_malloc.h new file mode 100644 index 0000000..6bde574 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/allocation/c_malloc.h @@ -0,0 +1,253 @@ +#pragma once +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 6308) +#endif + +#if __has_include() +#include +#elif __has_include() +#include +#endif + +namespace fast_io +{ + +namespace details +{ +#if (__has_include() || __has_include()) && !defined(__MSDOS__) && !defined(__LLVM_LIBC__) + +inline ::std::size_t c_malloc_usable_size_impl(void *p) noexcept +{ +#if defined(_WIN32) && !defined(__WINE__) && !defined(__CYGWIN__) + return ::fast_io::noexcept_call(_msize, p); +#else + return ::malloc_usable_size(p); +#endif +} + +#endif + +} // namespace details + +class c_malloc_allocator +{ +public: +#if __has_cpp_attribute(__gnu__::__returns_nonnull__) + [[__gnu__::__returns_nonnull__]] +#endif + static inline void *allocate(::std::size_t n) noexcept + { + if (n == 0) + { + n = 1; + } + void *p = +#if defined(__has_builtin) +#if __has_builtin(__builtin_malloc) + __builtin_malloc(n) +#else + ::std::malloc(n) +#endif +#else + ::std::malloc(n) +#endif + ; + if (p == nullptr) + { + ::fast_io::fast_terminate(); + } + return p; + } +#if __has_cpp_attribute(__gnu__::__returns_nonnull__) + [[__gnu__::__returns_nonnull__]] +#endif + static inline void *reallocate(void *p, ::std::size_t n) noexcept + { + if (n == 0) + { + n = 1; + } + ::std::size_t const to_allocate{n}; + p = +#if defined(__has_builtin) +#if __has_builtin(__builtin_realloc) + __builtin_realloc +#else + ::std::realloc +#endif +#else + ::std::realloc +#endif + + (p, to_allocate); + if (p == nullptr) + { + ::fast_io::fast_terminate(); + } + return p; + } +#if __has_cpp_attribute(__gnu__::__returns_nonnull__) + [[__gnu__::__returns_nonnull__]] +#endif + static inline void *allocate_zero(::std::size_t n) noexcept + { + if (n == 0) + { + n = 1; + } + void *p = +#if defined(__has_builtin) +#if __has_builtin(__builtin_calloc) + __builtin_calloc +#else + ::std::calloc +#endif +#else + ::std::calloc +#endif + + (1, n); + if (p == nullptr) + { + ::fast_io::fast_terminate(); + } + return p; + } +#if (__has_include() || __has_include()) && !defined(__MSDOS__) && !defined(__LLVM_LIBC__) + static inline allocation_least_result allocate_at_least(::std::size_t n) noexcept + { + auto p{::fast_io::c_malloc_allocator::allocate(n)}; + return {p, ::fast_io::details::c_malloc_usable_size_impl(p)}; + } + static inline allocation_least_result allocate_zero_at_least(::std::size_t n) noexcept + { + auto p{::fast_io::c_malloc_allocator::allocate_zero(n)}; + return {p, ::fast_io::details::c_malloc_usable_size_impl(p)}; + } + static inline allocation_least_result reallocate_at_least(void *oldp, ::std::size_t n) noexcept + { + auto p{::fast_io::c_malloc_allocator::reallocate(oldp, n)}; + return {p, ::fast_io::details::c_malloc_usable_size_impl(p)}; + } +#endif + +#if defined(_WIN32) && !defined(__WINE__) && !defined(__CYGWIN__) +#if __has_cpp_attribute(__gnu__::__returns_nonnull__) + [[__gnu__::__returns_nonnull__]] +#endif + static inline void *allocate_aligned(::std::size_t alignment, ::std::size_t n) noexcept + { + if (n == 0) + { + n = 1; + } + void *p; + if (alignment <= __STDCPP_DEFAULT_NEW_ALIGNMENT__) + { + p = +#if defined(__has_builtin) +#if __has_builtin(__builtin_malloc) + __builtin_malloc +#else + ::std::malloc +#endif +#else + ::std::malloc +#endif + (n); + } + else + { + p = ::fast_io::noexcept_call(_aligned_malloc, n, alignment); + } + if (p == nullptr) + { + ::fast_io::fast_terminate(); + } + return p; + } +#if __has_cpp_attribute(__gnu__::__returns_nonnull__) + [[__gnu__::__returns_nonnull__]] +#endif + static inline void *reallocate_aligned(void *p, ::std::size_t alignment, ::std::size_t n) noexcept + { + if (n == 0) + { + n = 1; + } + if (alignment <= __STDCPP_DEFAULT_NEW_ALIGNMENT__) + { + p = +#if defined(__has_builtin) +#if __has_builtin(__builtin_realloc) + __builtin_realloc +#else + ::std::realloc +#endif +#else + ::std::realloc +#endif + + (p, n); + } + else + { + p = ::fast_io::noexcept_call(_aligned_realloc, p, n, alignment); + } + if (p == nullptr) + { + ::fast_io::fast_terminate(); + } + return p; + } + static inline void deallocate_aligned(void *p, ::std::size_t alignment) noexcept + { + if (p == nullptr) + { + return; + } + if (alignment <= __STDCPP_DEFAULT_NEW_ALIGNMENT__) + { +#if defined(__has_builtin) +#if __has_builtin(__builtin_free) + __builtin_free +#else + ::std::free +#endif +#else + ::std::free +#endif + (p); + } + else + { + ::fast_io::noexcept_call(_aligned_free, p); + } + } +#endif + static inline void deallocate(void *p) noexcept + { + if (p == nullptr) + { + return; + } +#if defined(__has_builtin) +#if __has_builtin(__builtin_free) + __builtin_free +#else + ::std::free +#endif +#else + ::std::free +#endif + + (p); + } +}; + +} // namespace fast_io + +#ifdef _MSC_VER +#pragma warning(pop) +#endif diff --git a/src/fast_io/include/fast_io_core_impl/allocation/common.h b/src/fast_io/include/fast_io_core_impl/allocation/common.h new file mode 100644 index 0000000..3dfcc99 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/allocation/common.h @@ -0,0 +1,17 @@ +#pragma once + +namespace fast_io +{ + +template +struct basic_allocation_least_result +{ + using pointer = Pointer; + using size_type = ::std::size_t; + pointer ptr; + size_type count; +}; + +using allocation_least_result = basic_allocation_least_result; + +} // namespace fast_io diff --git a/src/fast_io/include/fast_io_core_impl/allocation/custom.h b/src/fast_io/include/fast_io_core_impl/allocation/custom.h new file mode 100644 index 0000000..128f3cb --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/allocation/custom.h @@ -0,0 +1,14 @@ +#pragma once + +namespace fast_io +{ + +class custom_global_allocator; + +#if defined(FAST_IO_DISABLE_CUSTOM_THREAD_LOCAL_ALLOCATOR) +using custom_thread_local_allocator = custom_global_allocator +#else +class custom_thread_local_allocator; +#endif + +} // namespace fast_io diff --git a/src/fast_io/include/fast_io_core_impl/allocation/has_methods_detect.h b/src/fast_io/include/fast_io_core_impl/allocation/has_methods_detect.h new file mode 100644 index 0000000..9a97cd7 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/allocation/has_methods_detect.h @@ -0,0 +1,289 @@ +#pragma once + +template +concept has_allocate_impl = requires(::std::size_t n) { + { alloc::allocate(n) } -> ::std::same_as; +}; + +template +concept has_allocate_aligned_impl = requires(::std::size_t n) { + { alloc::allocate_aligned(n, n) } -> ::std::same_as; +}; + +template +concept has_allocate_zero_impl = requires(::std::size_t n) { + { alloc::allocate_zero(n) } -> ::std::same_as; +}; + +template +concept has_allocate_aligned_zero_impl = requires(::std::size_t n) { + { alloc::allocate_aligned_zero(n, n) } -> ::std::same_as; +}; + +template +concept has_reallocate_impl = requires(void *p, ::std::size_t n) { + { alloc::reallocate(p, n) } -> ::std::same_as; +}; + +template +concept has_reallocate_aligned_impl = requires(void *p, ::std::size_t n) { + { alloc::reallocate_aligned(p, n, n) } -> ::std::same_as; +}; + +template +concept has_reallocate_zero_impl = requires(void *p, ::std::size_t n) { + { alloc::reallocate_zero(p, n) } -> ::std::same_as; +}; + +template +concept has_reallocate_aligned_zero_impl = requires(void *p, ::std::size_t n) { + { alloc::reallocate_aligned_zero(p, n, n) } -> ::std::same_as; +}; + +template +concept has_reallocate_n_impl = requires(void *p, ::std::size_t n) { + { alloc::reallocate_n(p, n, n) } -> ::std::same_as; +}; + +template +concept has_reallocate_aligned_n_impl = requires(void *p, ::std::size_t n) { + { alloc::reallocate_aligned_n(p, n, n, n) } -> ::std::same_as; +}; + +template +concept has_reallocate_zero_n_impl = requires(void *p, ::std::size_t n) { + { alloc::reallocate_zero_n(p, n, n) } -> ::std::same_as; +}; + +template +concept has_reallocate_aligned_zero_n_impl = requires(void *p, ::std::size_t n) { + { alloc::reallocate_aligned_zero_n(p, n, n, n) } -> ::std::same_as; +}; + +template +concept has_deallocate_impl = requires(void *p) { + { alloc::deallocate(p) } -> ::std::same_as; +}; + +template +concept has_deallocate_aligned_impl = requires(void *p, ::std::size_t n) { + { alloc::deallocate_aligned(p, n) } -> ::std::same_as; +}; + +template +concept has_deallocate_n_impl = requires(void *p, ::std::size_t n) { + { alloc::deallocate_n(p, n) } -> ::std::same_as; +}; + +template +concept has_deallocate_aligned_n_impl = requires(void *p, ::std::size_t n) { + { alloc::deallocate_aligned_n(p, n, n) } -> ::std::same_as; +}; + +template +concept has_allocate_at_least_impl = requires(::std::size_t n) { + { alloc::allocate_at_least(n) } -> ::std::same_as<::fast_io::allocation_least_result>; +}; + +template +concept has_allocate_aligned_at_least_impl = requires(::std::size_t n) { + { alloc::allocate_aligned_at_least(n, n) } -> ::std::same_as<::fast_io::allocation_least_result>; +}; + +template +concept has_allocate_zero_at_least_impl = requires(::std::size_t n) { + { alloc::allocate_zero_at_least(n) } -> ::std::same_as<::fast_io::allocation_least_result>; +}; + +template +concept has_allocate_aligned_zero_at_least_impl = requires(::std::size_t n) { + { alloc::allocate_aligned_zero_at_least(n, n) } -> ::std::same_as<::fast_io::allocation_least_result>; +}; + +template +concept has_reallocate_at_least_impl = requires(void *p, ::std::size_t n) { + { alloc::reallocate_at_least(p, n) } -> ::std::same_as<::fast_io::allocation_least_result>; +}; + +template +concept has_reallocate_aligned_at_least_impl = requires(void *p, ::std::size_t n) { + { alloc::reallocate_aligned_at_least(p, n, n) } -> ::std::same_as<::fast_io::allocation_least_result>; +}; + +template +concept has_reallocate_zero_at_least_impl = requires(void *p, ::std::size_t n) { + { alloc::reallocate_zero_at_least(p, n) } -> ::std::same_as<::fast_io::allocation_least_result>; +}; + +template +concept has_reallocate_aligned_zero_at_least_impl = requires(void *p, ::std::size_t n) { + { alloc::reallocate_aligned_zero_at_least(p, n, n) } -> ::std::same_as<::fast_io::allocation_least_result>; +}; + +template +concept has_reallocate_n_at_least_impl = requires(void *p, ::std::size_t n) { + { alloc::reallocate_n_at_least(p, n, n) } -> ::std::same_as<::fast_io::allocation_least_result>; +}; + +template +concept has_reallocate_aligned_n_at_least_impl = requires(void *p, ::std::size_t n) { + { alloc::reallocate_aligned_n_at_least(p, n, n, n) } -> ::std::same_as<::fast_io::allocation_least_result>; +}; + +template +concept has_reallocate_zero_n_at_least_impl = requires(void *p, ::std::size_t n) { + { alloc::reallocate_zero_n_at_least(p, n, n) } -> ::std::same_as<::fast_io::allocation_least_result>; +}; + +template +concept has_reallocate_aligned_zero_n_at_least_impl = requires(void *p, ::std::size_t n) { + { alloc::reallocate_aligned_zero_n_at_least(p, n, n, n) } -> ::std::same_as<::fast_io::allocation_least_result>; +}; + +template +concept has_non_empty_handle_type = requires { + typename alloc::handle_type; + requires !::std::is_empty_v; +}; + +template +concept has_handle_allocate_impl = requires(typename alloc::handle_type handle, ::std::size_t n) { + { alloc::handle_allocate(handle, n) } -> ::std::same_as; +}; + +template +concept has_handle_allocate_aligned_impl = requires(typename alloc::handle_type handle, ::std::size_t n) { + { alloc::handle_allocate_aligned(handle, n, n) } -> ::std::same_as; +}; + +template +concept has_handle_allocate_zero_impl = requires(typename alloc::handle_type handle, ::std::size_t n) { + { alloc::handle_allocate_zero(handle, n) } -> ::std::same_as; +}; + +template +concept has_handle_allocate_aligned_zero_impl = requires(typename alloc::handle_type handle, ::std::size_t n) { + { alloc::handle_allocate_aligned_zero(handle, n, n) } -> ::std::same_as; +}; + +template +concept has_handle_reallocate_impl = requires(typename alloc::handle_type handle, void *p, ::std::size_t n) { + { alloc::handle_reallocate(handle, p, n) } -> ::std::same_as; +}; + +template +concept has_handle_reallocate_aligned_impl = requires(typename alloc::handle_type handle, void *p, ::std::size_t n) { + { alloc::handle_reallocate_aligned(handle, p, n, n) } -> ::std::same_as; +}; + +template +concept has_handle_reallocate_zero_impl = requires(typename alloc::handle_type handle, void *p, ::std::size_t n) { + { alloc::handle_reallocate_zero(handle, p, n) } -> ::std::same_as; +}; + +template +concept has_handle_reallocate_aligned_zero_impl = requires(typename alloc::handle_type handle, void *p, ::std::size_t n) { + { alloc::handle_reallocate_aligned_zero(handle, p, n, n) } -> ::std::same_as; +}; + +template +concept has_handle_reallocate_n_impl = requires(typename alloc::handle_type handle, void *p, ::std::size_t n) { + { alloc::handle_reallocate_n(handle, p, n, n) } -> ::std::same_as; +}; + +template +concept has_handle_reallocate_aligned_n_impl = requires(typename alloc::handle_type handle, void *p, ::std::size_t n) { + { alloc::handle_reallocate_aligned_n(handle, p, n, n, n) } -> ::std::same_as; +}; + +template +concept has_handle_reallocate_zero_n_impl = requires(typename alloc::handle_type handle, void *p, ::std::size_t n) { + { alloc::handle_reallocate_zero_n(handle, p, n, n) } -> ::std::same_as; +}; + +template +concept has_handle_reallocate_aligned_zero_n_impl = requires(typename alloc::handle_type handle, void *p, ::std::size_t n) { + { alloc::handle_reallocate_aligned_zero_n(handle, p, n, n, n) } -> ::std::same_as; +}; + + +template +concept has_handle_allocate_at_least_impl = requires(typename alloc::handle_type handle, ::std::size_t n) { + { alloc::handle_allocate_at_least(handle, n) } -> ::std::same_as<::fast_io::allocation_least_result>; +}; + +template +concept has_handle_allocate_aligned_at_least_impl = requires(typename alloc::handle_type handle, ::std::size_t n) { + { alloc::handle_allocate_aligned_at_least(handle, n, n) } -> ::std::same_as<::fast_io::allocation_least_result>; +}; + +template +concept has_handle_allocate_zero_at_least_impl = requires(typename alloc::handle_type handle, ::std::size_t n) { + { alloc::handle_allocate_zero_at_least(handle, n) } -> ::std::same_as<::fast_io::allocation_least_result>; +}; + +template +concept has_handle_allocate_aligned_zero_at_least_impl = requires(typename alloc::handle_type handle, ::std::size_t n) { + { alloc::handle_allocate_aligned_zero_at_least(handle, n, n) } -> ::std::same_as<::fast_io::allocation_least_result>; +}; + +template +concept has_handle_reallocate_at_least_impl = requires(typename alloc::handle_type handle, void *p, ::std::size_t n) { + { alloc::handle_reallocate_at_least(handle, p, n) } -> ::std::same_as<::fast_io::allocation_least_result>; +}; + +template +concept has_handle_reallocate_aligned_at_least_impl = requires(typename alloc::handle_type handle, void *p, ::std::size_t n) { + { alloc::handle_reallocate_aligned_at_least(handle, p, n, n) } -> ::std::same_as<::fast_io::allocation_least_result>; +}; + +template +concept has_handle_reallocate_zero_at_least_impl = requires(typename alloc::handle_type handle, void *p, ::std::size_t n) { + { alloc::handle_reallocate_zero_at_least(handle, p, n) } -> ::std::same_as<::fast_io::allocation_least_result>; +}; + +template +concept has_handle_reallocate_aligned_zero_at_least_impl = requires(typename alloc::handle_type handle, void *p, ::std::size_t n) { + { alloc::handle_reallocate_aligned_zero_at_least(handle, p, n, n) } -> ::std::same_as<::fast_io::allocation_least_result>; +}; + +template +concept has_handle_reallocate_n_at_least_impl = requires(typename alloc::handle_type handle, void *p, ::std::size_t n) { + { alloc::handle_reallocate_n_at_least(handle, p, n, n) } -> ::std::same_as<::fast_io::allocation_least_result>; +}; + +template +concept has_handle_reallocate_aligned_n_at_least_impl = requires(typename alloc::handle_type handle, void *p, ::std::size_t n) { + { alloc::handle_reallocate_aligned_n_at_least(handle, p, n, n, n) } -> ::std::same_as<::fast_io::allocation_least_result>; +}; + +template +concept has_handle_reallocate_zero_n_at_least_impl = requires(typename alloc::handle_type handle, void *p, ::std::size_t n) { + { alloc::handle_reallocate_zero_n_at_least(handle, p, n, n) } -> ::std::same_as<::fast_io::allocation_least_result>; +}; + +template +concept has_handle_reallocate_aligned_zero_n_at_least_impl = requires(typename alloc::handle_type handle, void *p, ::std::size_t n) { + { alloc::handle_reallocate_aligned_zero_n_at_least(handle, p, n, n, n) } -> ::std::same_as<::fast_io::allocation_least_result>; +}; + + +template +concept has_handle_deallocate_impl = requires(typename alloc::handle_type handle, void *p) { + { alloc::handle_deallocate(handle, p) } -> ::std::same_as; +}; + +template +concept has_handle_deallocate_aligned_impl = requires(typename alloc::handle_type handle, void *p, ::std::size_t n) { + { alloc::handle_deallocate_aligned(handle, p, n) } -> ::std::same_as; +}; + +template +concept has_handle_deallocate_n_impl = requires(typename alloc::handle_type handle, void *p, ::std::size_t n) { + { alloc::handle_deallocate_n(handle, p, n) } -> ::std::same_as; +}; + +template +concept has_handle_deallocate_aligned_n_impl = requires(typename alloc::handle_type handle, void *p, ::std::size_t n) { + { alloc::handle_deallocate_aligned_n(handle, p, n, n) } -> ::std::same_as; +}; diff --git a/src/fast_io/include/fast_io_core_impl/allocation/impl.h b/src/fast_io/include/fast_io_core_impl/allocation/impl.h new file mode 100644 index 0000000..fd77a45 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/allocation/impl.h @@ -0,0 +1,76 @@ +#pragma once + +#include "common.h" +#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(__WINE__) +#include "win32_heapalloc.h" +#include "nt_rtlheapalloc.h" +#if defined(_MSC_VER) && !defined(__clang__) +#include "msvc/impl.h" +#endif +#endif +#if ((__STDC_HOSTED__ == 1 && (!defined(_GLIBCXX_HOSTED) || _GLIBCXX_HOSTED == 1) && \ + !defined(_LIBCPP_FREESTANDING)) || \ + defined(FAST_IO_ENABLE_HOSTED_FEATURES)) +#include "c_malloc.h" +#if defined(_DEBUG) && defined(_MSC_VER) +#include "wincrt_malloc_dbg.h" +#endif +#endif + +#if (defined(__linux__) && defined(__KERNEL__)) || defined(FAST_IO_USE_LINUX_KERNEL_ALLOCATOR) +#include "linux_kernel.h" +#endif + +#if (defined(FAST_IO_ENABLE_MIMALLOC) || defined(FAST_IO_USE_MIMALLOC)) && (!defined(_MSC_VER) || defined(__clang__)) +#include "mimalloc_driver.h" +#endif + +#include "custom.h" +#include "adapters.h" + +namespace fast_io +{ + +using native_global_allocator = generic_allocator_adapter< +#if defined(FAST_IO_USE_CUSTOM_GLOBAL_ALLOCATOR) + custom_global_allocator +#elif defined(FAST_IO_USE_MIMALLOC) && (!defined(_MSC_VER) || defined(__clang__)) + mimalloc_allocator +#elif (defined(__linux__) && defined(__KERNEL__)) || defined(FAST_IO_USE_LINUX_KERNEL_ALLOCATOR) + linux_kmalloc_allocator +#elif ( \ + (__STDC_HOSTED__ == 1 && (!defined(_GLIBCXX_HOSTED) || _GLIBCXX_HOSTED == 1) && !defined(_LIBCPP_FREESTANDING)) || \ + defined(FAST_IO_ENABLE_HOSTED_FEATURES)) +#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WINE__) && !defined(FAST_IO_USE_C_MALLOC) +#if defined(_DEBUG) && defined(_MSC_VER) + wincrt_malloc_dbg_allocator +#else + win32_heapalloc_allocator +#endif +#else +#if defined(_DEBUG) && defined(_MSC_VER) + wincrt_malloc_dbg_allocator +#else + c_malloc_allocator +#endif +#endif +#else + custom_global_allocator +#endif + >; + +template +using native_typed_global_allocator = typed_generic_allocator_adapter; + +using native_thread_local_allocator = generic_allocator_adapter< +#if defined(FAST_IO_USE_CUSTOM_THREAD_LOCAL_ALLOCATOR) + custom_thread_local_allocator +#else + native_global_allocator +#endif + >; + +template +using native_typed_thread_local_allocator = typed_generic_allocator_adapter; + +} // namespace fast_io diff --git a/src/fast_io/include/fast_io_core_impl/allocation/linux_kernel.h b/src/fast_io/include/fast_io_core_impl/allocation/linux_kernel.h new file mode 100644 index 0000000..21fe77e --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/allocation/linux_kernel.h @@ -0,0 +1,71 @@ +#pragma once + +namespace fast_io +{ + +extern void *linux_kernel_kmalloc(::std::size_t, int unsigned) noexcept __asm__("__kmalloc"); + +extern void *linux_kernel_krealloc(void const *, ::std::size_t, int unsigned) noexcept __asm__("krealloc"); + +extern void linux_kernel_kfree(void const *) noexcept __asm__("kfree"); + +inline constexpr int unsigned linux_kernel_gfp_kernel{0x400u | 0x800u | 0x40u | 0x80u}; + +inline constexpr int unsigned linux_kernel_gfp_kernel_zero{linux_kernel_gfp_kernel | 0x100u}; + +class linux_kmalloc_allocator +{ +public: +#if __has_cpp_attribute(__gnu__::__returns_nonnull__) + [[__gnu__::__returns_nonnull__]] +#endif + static inline void *allocate(::std::size_t n) noexcept + { + if (n == 0) + { + n = 1; + } + void *p = linux_kernel_kmalloc(n, linux_kernel_gfp_kernel); + if (p == nullptr) + { + ::fast_io::fast_terminate(); + } + return p; + } + static inline void *reallocate(void *p, ::std::size_t n) noexcept + { + if (n == 0) + { + n = 1; + } + p = linux_kernel_krealloc(p, n, linux_kernel_gfp_kernel); + if (p == nullptr) + { + ::fast_io::fast_terminate(); + } + return p; + } + static inline void *allocate_zero(::std::size_t n) noexcept + { + if (n == 0) + { + n = 1; + } + void *p = linux_kernel_kmalloc(n, linux_kernel_gfp_kernel_zero); + if (p == nullptr) + { + ::fast_io::fast_terminate(); + } + return p; + } + static inline void deallocate(void *p) noexcept + { + if (p == nullptr) + { + return; + } + linux_kernel_kfree(p); + } +}; + +} // namespace fast_io diff --git a/src/fast_io/include/fast_io_core_impl/allocation/mimalloc_driver.h b/src/fast_io/include/fast_io_core_impl/allocation/mimalloc_driver.h new file mode 100644 index 0000000..391f14b --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/allocation/mimalloc_driver.h @@ -0,0 +1,159 @@ +#pragma once + +namespace fast_io +{ +namespace mimalloc +{ + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__) && !defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if __has_cpp_attribute(__gnu__::__cdecl__) && ((defined(_WIN32) && !defined(__WINE__)) || defined(__CYGWIN__)) +[[__gnu__::__cdecl__]] +#endif +#if __has_cpp_attribute(__gnu__::__malloc__) +[[__gnu__::__malloc__]] +#endif +extern void * +#if !__has_cpp_attribute(__gnu__::__cdecl__) && defined(_MSC_VER) + __cdecl +#endif + mi_malloc(::std::size_t size) noexcept +#if (defined(__clang__) || defined(__GNUC__)) +#if SIZE_MAX <= UINT_LEAST32_MAX && (defined(__x86__) || defined(_M_IX86) || defined(__i386__)) && \ + ((defined(_WIN32) && !defined(__WINE__)) || defined(__CYGWIN__)) +#if !defined(__clang__) + __asm__("mi_malloc") +#else + __asm__("_mi_malloc") +#endif +#else + __asm__("mi_malloc") +#endif +#endif + ; +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__) && !defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if __has_cpp_attribute(__gnu__::__cdecl__) && ((defined(_WIN32) && !defined(__WINE__)) || defined(__CYGWIN__)) +[[__gnu__::__cdecl__]] +#endif +extern void +#if !__has_cpp_attribute(__gnu__::__cdecl__) && defined(_MSC_VER) + __cdecl +#endif + mi_free(void *p) noexcept +#if (defined(__clang__) || defined(__GNUC__)) +#if SIZE_MAX <= UINT_LEAST32_MAX && (defined(__x86__) || defined(_M_IX86) || defined(__i386__)) && \ + ((defined(_WIN32) && !defined(__WINE__)) || defined(__CYGWIN__)) +#if !defined(__clang__) + __asm__("mi_free") +#else + __asm__("_mi_free") +#endif +#else + __asm__("mi_free") +#endif +#endif + ; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__) && !defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if __has_cpp_attribute(__gnu__::__cdecl__) && ((defined(_WIN32) && !defined(__WINE__)) || defined(__CYGWIN__)) +[[__gnu__::__cdecl__]] +#endif +extern void * +#if !__has_cpp_attribute(__gnu__::__cdecl__) && defined(_MSC_VER) + __cdecl +#endif + mi_calloc(::std::size_t count, ::std::size_t size) noexcept +#if (defined(__clang__) || defined(__GNUC__)) +#if SIZE_MAX <= UINT_LEAST32_MAX && (defined(__x86__) || defined(_M_IX86) || defined(__i386__)) && \ + ((defined(_WIN32) && !defined(__WINE__)) || defined(__CYGWIN__)) +#if !defined(__clang__) + __asm__("mi_calloc") +#else + __asm__("_mi_calloc") +#endif +#else + __asm__("mi_calloc") +#endif +#endif + ; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__) && !defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if __has_cpp_attribute(__gnu__::__cdecl__) && ((defined(_WIN32) && !defined(__WINE__)) || defined(__CYGWIN__)) +[[__gnu__::__cdecl__]] +#endif +extern void * +#if !__has_cpp_attribute(__gnu__::__cdecl__) && defined(_MSC_VER) + __cdecl +#endif + mi_realloc(void *p, ::std::size_t newsize) noexcept +#if (defined(__clang__) || defined(__GNUC__)) +#if SIZE_MAX <= UINT_LEAST32_MAX && (defined(__x86__) || defined(_M_IX86) || defined(__i386__)) && \ + ((defined(_WIN32) && !defined(__WINE__)) || defined(__CYGWIN__)) +#if !defined(__clang__) + __asm__("mi_realloc") +#else + __asm__("_mi_realloc") +#endif +#else + __asm__("mi_realloc") +#endif +#endif + ; + +} // namespace mimalloc + +class mimalloc_allocator +{ +public: +#if __has_cpp_attribute(__gnu__::__returns_nonnull__) + [[__gnu__::__returns_nonnull__]] +#endif + static inline void *allocate(::std::size_t n) noexcept + { + void *p = ::fast_io::mimalloc::mi_malloc(n); + if (p == nullptr) + { + ::fast_io::fast_terminate(); + } + return p; + } + static inline void *reallocate(void *p, ::std::size_t n) noexcept + { + p = ::fast_io::mimalloc::mi_realloc(p, n); + if (p == nullptr) + { + ::fast_io::fast_terminate(); + } + return p; + } + static inline void *allocate_zero(::std::size_t n) noexcept + { + void *p = ::fast_io::mimalloc::mi_calloc(1, n); + if (p == nullptr) + { + ::fast_io::fast_terminate(); + } + return p; + } + static inline void deallocate(void *p) noexcept + { + ::fast_io::mimalloc::mi_free(p); + } +}; + +} // namespace fast_io \ No newline at end of file diff --git a/src/fast_io/include/fast_io_core_impl/allocation/msvc/impl.h b/src/fast_io/include/fast_io_core_impl/allocation/msvc/impl.h new file mode 100644 index 0000000..d5dd331 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/allocation/msvc/impl.h @@ -0,0 +1,9 @@ +#pragma once + +#if SIZE_MAX > UINT_LEAST32_MAX +#include "msvc_linker_64.h" +#elif defined(__x86__) || defined(_M_IX86) || defined(__i386__) +#include "msvc_linker_32_i686.h" +#else +#include "msvc_linker_32.h" +#endif diff --git a/src/fast_io/include/fast_io_core_impl/allocation/msvc/msvc_linker_32.h b/src/fast_io/include/fast_io_core_impl/allocation/msvc/msvc_linker_32.h new file mode 100644 index 0000000..65a2ceb --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/allocation/msvc/msvc_linker_32.h @@ -0,0 +1,15 @@ +#pragma once +// clang-format off + +#pragma comment(linker, "/alternatename:__imp_?HeapAlloc@win32@fast_io@@YAPAXPAXII@Z=__imp_HeapAlloc") +#pragma comment(linker, "/alternatename:__imp_?HeapFree@win32@fast_io@@YAHPAXI0@Z=__imp_HeapFree") +#pragma comment(linker, "/alternatename:__imp_?GetProcessHeap@win32@fast_io@@YAPAXXZ=__imp_GetProcessHeap") +#pragma comment(linker, "/alternatename:__imp_?HeapReAlloc@win32@fast_io@@YAPAXPAXI0I@Z=__imp_HeapReAlloc") +#pragma comment(linker, "/alternatename:__imp_?HeapSize@win32@fast_io@@YAIPAXIPBX@Z=__imp_HeapFree") +#pragma comment(linker, "/alternatename:__imp_?RtlAllocateHeap@nt@win32@fast_io@@YAPAXPAXII@Z=__imp_RtlAllocateHeap") +#pragma comment(linker, "/alternatename:__imp_?RtlFreeHeap@nt@win32@fast_io@@YAEPAXI0@Z=__imp_RtlFreeHeap") +#pragma comment(linker, "/alternatename:__imp_?RtlGetCurrentPeb@nt@win32@fast_io@@YAPAUpeb@123@XZ=__imp_RtlGetCurrentPeb") +#pragma comment(linker, "/alternatename:__imp_?RtlReAllocateHeap@nt@win32@fast_io@@YAPAXPAXI0I@Z=__imp_RtlReAllocateHeap") +#pragma comment(linker, "/alternatename:__imp_?RtlSizeHeap@nt@win32@fast_io@@YAIPAXI0@Z=__imp_RtlSizeHeap") + +// clang-format on diff --git a/src/fast_io/include/fast_io_core_impl/allocation/msvc/msvc_linker_32_i686.h b/src/fast_io/include/fast_io_core_impl/allocation/msvc/msvc_linker_32_i686.h new file mode 100644 index 0000000..510be5f --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/allocation/msvc/msvc_linker_32_i686.h @@ -0,0 +1,15 @@ +#pragma once +// clang-format off + +#pragma comment(linker, "/alternatename:__imp_?HeapAlloc@win32@fast_io@@YGPAXPAXII@Z=__imp__HeapAlloc@12") +#pragma comment(linker, "/alternatename:__imp_?HeapFree@win32@fast_io@@YGHPAXI0@Z=__imp__HeapFree@12") +#pragma comment(linker, "/alternatename:__imp_?GetProcessHeap@win32@fast_io@@YGPAXXZ=__imp__GetProcessHeap@0") +#pragma comment(linker, "/alternatename:__imp_?HeapReAlloc@win32@fast_io@@YGPAXPAXI0I@Z=__imp__HeapReAlloc@16") +#pragma comment(linker, "/alternatename:__imp_?HeapSize@win32@fast_io@@YGIPAXIPBX@Z=__imp__HeapSize@12") +#pragma comment(linker, "/alternatename:__imp_?RtlAllocateHeap@nt@win32@fast_io@@YGPAXPAXII@Z=__imp__RtlAllocateHeap@12") +#pragma comment(linker, "/alternatename:__imp_?RtlFreeHeap@nt@win32@fast_io@@YGEPAXI0@Z=__imp__RtlFreeHeap@12") +#pragma comment(linker, "/alternatename:__imp_?RtlGetCurrentPeb@nt@win32@fast_io@@YGPAUpeb@123@XZ=__imp__RtlGetCurrentPeb@0") +#pragma comment(linker, "/alternatename:__imp_?RtlReAllocateHeap@nt@win32@fast_io@@YGPAXPAXI0I@Z=__imp__RtlReAllocateHeap@16") +#pragma comment(linker, "/alternatename:__imp_?RtlSizeHeap@nt@win32@fast_io@@YGIPAXI0@Z=__imp__RtlSizeHeap@12") + +// clang-format on diff --git a/src/fast_io/include/fast_io_core_impl/allocation/msvc/msvc_linker_64.h b/src/fast_io/include/fast_io_core_impl/allocation/msvc/msvc_linker_64.h new file mode 100644 index 0000000..dcedc7d --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/allocation/msvc/msvc_linker_64.h @@ -0,0 +1,15 @@ +#pragma once +// clang-format off + +#pragma comment(linker, "/alternatename:__imp_?HeapAlloc@win32@fast_io@@YAPEAXPEAXI_K@Z=__imp_HeapAlloc") +#pragma comment(linker, "/alternatename:__imp_?HeapFree@win32@fast_io@@YAHPEAXI0@Z=__imp_HeapFree") +#pragma comment(linker, "/alternatename:__imp_?GetProcessHeap@win32@fast_io@@YAPEAXXZ=__imp_GetProcessHeap") +#pragma comment(linker, "/alternatename:__imp_?HeapReAlloc@win32@fast_io@@YAPEAXPEAXI0_K@Z=__imp_HeapReAlloc") +#pragma comment(linker, "/alternatename:__imp_?HeapSize@win32@fast_io@@YA_KPEAXIPEBX@Z=__imp_HeapSize") +#pragma comment(linker, "/alternatename:__imp_?RtlAllocateHeap@nt@win32@fast_io@@YAPEAXPEAXI_K@Z=__imp_RtlAllocateHeap") +#pragma comment(linker, "/alternatename:__imp_?RtlFreeHeap@nt@win32@fast_io@@YAEPEAXI0@Z=__imp_RtlFreeHeap") +#pragma comment(linker, "/alternatename:__imp_?RtlGetCurrentPeb@nt@win32@fast_io@@YAPEAUpeb@123@XZ=__imp_RtlGetCurrentPeb") +#pragma comment(linker, "/alternatename:__imp_?RtlReAllocateHeap@nt@win32@fast_io@@YAPEAXPEAXI0_K@Z=__imp_RtlReAllocateHeap") +#pragma comment(linker, "/alternatename:__imp_?RtlSizeHeap@nt@win32@fast_io@@YA_KPEAXI0@Z=__imp_RtlSizeHeap") + +// clang-format on diff --git a/src/fast_io/include/fast_io_core_impl/allocation/nt_rtlheapalloc.h b/src/fast_io/include/fast_io_core_impl/allocation/nt_rtlheapalloc.h new file mode 100644 index 0000000..ab3990a --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/allocation/nt_rtlheapalloc.h @@ -0,0 +1,354 @@ +#pragma once + +#if defined(_MSC_VER) && !defined(_KERNEL_MODE) && !defined(_WIN32_WINDOWS) +#pragma comment(lib, "ntdll.lib") +#endif + +namespace fast_io +{ + +namespace win32::nt +{ +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__) && !defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__) && !defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern void * +#if (!__has_cpp_attribute(__gnu__::__stdcall__) && !defined(__WINE__)) && defined(_MSC_VER) + __stdcall +#endif + RtlAllocateHeap(void *, ::std::uint_least32_t, ::std::size_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX <= UINT_LEAST32_MAX && (defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) + __asm__("RtlAllocateHeap@12") +#else + __asm__("_RtlAllocateHeap@12") +#endif +#else + __asm__("RtlAllocateHeap") +#endif +#endif + ; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__) && !defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__) && !defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern char unsigned +#if (!__has_cpp_attribute(__gnu__::__stdcall__) && !defined(__WINE__)) && defined(_MSC_VER) + __stdcall +#endif + RtlFreeHeap(void *, ::std::uint_least32_t, void *) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX <= UINT_LEAST32_MAX && (defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) + __asm__("RtlFreeHeap@12") +#else + __asm__("_RtlFreeHeap@12") +#endif +#else + __asm__("RtlFreeHeap") +#endif +#endif + ; + +struct peb_ldr_data; +struct rtl_user_process_parameters; +using pps_post_process_init_routine = void( +#if defined(_MSC_VER) && (!__has_cpp_attribute(__gnu__::__stdcall__) && !defined(__WINE__)) + __stdcall +#elif (__has_cpp_attribute(__gnu__::__stdcall__) && !defined(__WINE__)) + __attribute__((__stdcall__)) +#endif + *)(void) noexcept; + +struct peb +{ + char unsigned InheritedAddressSpace; + char unsigned ReadImageFileExecOptions; + char unsigned BeingDebugged; + char unsigned SpareBool; + void *Mutant; + void *ImageBaseAddress; + peb_ldr_data *Ldr; + rtl_user_process_parameters *ProcessParameters; // PRTL_USER_PROCESS_PARAMETERS + void *SubSystemData; + void *ProcessHeap; + void *FastPebLock; + void *FastPebLockRoutine; + void *FastPebUnlockRoutine; + ::std::uint_least32_t Reserved6; + void *Reserved7; + ::std::uint_least32_t Reserved8; + ::std::uint_least32_t AtlThunkSListPtr32; + void *Reserved9[45]; + char unsigned Reserved10[96]; + pps_post_process_init_routine PostProcessInitRoutine; + char unsigned Reserved11[128]; + void *Reserved12[1]; + ::std::uint_least32_t SessionId; +}; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__) && !defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__) && !defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +#if __has_cpp_attribute(__gnu__::__const__) +[[__gnu__::__const__]] +#endif +extern peb * +#if (!__has_cpp_attribute(__gnu__::__stdcall__) && !defined(__WINE__)) && defined(_MSC_VER) + __stdcall +#endif + RtlGetCurrentPeb() noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX <= UINT_LEAST32_MAX && (defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) + __asm__("RtlGetCurrentPeb@0") +#else + __asm__("_RtlGetCurrentPeb@0") +#endif +#else + __asm__("RtlGetCurrentPeb") +#endif +#endif + ; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__) && !defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__) && !defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern void * +#if (!__has_cpp_attribute(__gnu__::__stdcall__) && !defined(__WINE__)) && defined(_MSC_VER) + __stdcall +#endif + RtlReAllocateHeap(void *, ::std::uint_least32_t, void *, ::std::size_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX <= UINT_LEAST32_MAX && (defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) + __asm__("RtlReAllocateHeap@16") +#else + __asm__("_RtlReAllocateHeap@16") +#endif +#else + __asm__("RtlReAllocateHeap") +#endif +#endif + ; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__) && !defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__) && !defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern ::std::size_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__) && !defined(__WINE__)) && defined(_MSC_VER) + __stdcall +#endif + RtlSizeHeap(void *, ::std::uint_least32_t, void *) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX <= UINT_LEAST32_MAX && (defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) + __asm__("RtlSizeHeap@12") +#else + __asm__("_RtlSizeHeap@12") +#endif +#else + __asm__("RtlSizeHeap") +#endif +#endif + ; + +#if __has_cpp_attribute(__gnu__::__const__) +[[__gnu__::__const__]] +#endif +inline peb *nt_get_current_peb() noexcept +{ +#if (defined(__clang__) || defined(__GNUC__)) && (defined(__i386__) || defined(__x86_64__)) + if constexpr (sizeof(::std::size_t) == sizeof(::std::uint_least64_t)) + { + peb *ppeb; + __asm__("{movq\t%%gs:0x60, %0|mov\t%0, %%gs:[0x60]}" : "=r"(ppeb)); + return ppeb; + } + else if constexpr (sizeof(::std::size_t) == sizeof(::std::uint_least32_t)) + { + peb *ppeb; + __asm__("{movl\t%%fs:0x30, %0|mov\t%0, %%fs:[0x30]}" : "=r"(ppeb)); + return ppeb; + } + else + { + return ::fast_io::win32::nt::RtlGetCurrentPeb(); + } +#elif defined(_MSC_VER) && !defined(__clang__) && (defined(_M_IX86) || defined(_M_AMD64)) +#if defined(_M_AMD64) + return reinterpret_cast(::fast_io::intrinsics::msvc::x86::__readgsqword(0x60)); +#else + return reinterpret_cast(::fast_io::intrinsics::msvc::x86::__readfsdword(0x30)); +#endif +#else + return ::fast_io::win32::nt::RtlGetCurrentPeb(); +#endif +} + +#if __has_cpp_attribute(__gnu__::__const__) +[[__gnu__::__const__]] +#endif +inline void *rtl_get_process_heap() noexcept +{ + return ::fast_io::win32::nt::nt_get_current_peb()->ProcessHeap; +} + +} // namespace win32::nt + +namespace details +{ + +#if __has_cpp_attribute(__gnu__::__returns_nonnull__) +[[__gnu__::__returns_nonnull__]] +#endif +inline void *nt_rtlallocate_heap_handle_common_impl(void *heaphandle, ::std::size_t n, ::std::uint_least32_t flag) noexcept +{ + if (n == 0) + { + n = 1; + } + auto p{::fast_io::win32::nt::RtlAllocateHeap(heaphandle, flag, n)}; + if (p == nullptr) + { + ::fast_io::fast_terminate(); + } + return p; +} + +#if __has_cpp_attribute(__gnu__::__returns_nonnull__) +[[__gnu__::__returns_nonnull__]] +#endif +inline void *nt_rtlreallocate_heap_handle_common_impl(void *heaphandle, void *addr, ::std::size_t n, ::std::uint_least32_t flag) noexcept +{ + if (n == 0) + { + n = 1; + } + if (addr == nullptr) +#if __has_cpp_attribute(unlikely) + [[unlikely]] +#endif + { + return ::fast_io::details::nt_rtlallocate_heap_handle_common_impl(heaphandle, n, flag); + } + auto p{::fast_io::win32::nt::RtlReAllocateHeap(heaphandle, flag, addr, n)}; + if (p == nullptr) + { + ::fast_io::fast_terminate(); + } + return p; +} + +#if __has_cpp_attribute(__gnu__::__returns_nonnull__) +[[__gnu__::__returns_nonnull__]] +#endif +inline void *nt_rtlallocate_heap_common_impl(::std::size_t n, ::std::uint_least32_t flag) noexcept +{ + return ::fast_io::details::nt_rtlallocate_heap_handle_common_impl(::fast_io::win32::nt::rtl_get_process_heap(), n, flag); +} + +#if __has_cpp_attribute(__gnu__::__returns_nonnull__) +[[__gnu__::__returns_nonnull__]] +#endif +inline void *nt_rtlreallocate_heap_common_impl(void *addr, ::std::size_t n, ::std::uint_least32_t flag) noexcept +{ + return ::fast_io::details::nt_rtlreallocate_heap_handle_common_impl(::fast_io::win32::nt::rtl_get_process_heap(), addr, n, flag); +} + +inline ::fast_io::allocation_least_result nt_rtlallocate_heap_least_common_impl(::std::size_t n, ::std::uint_least32_t flag) noexcept +{ + auto processheap{::fast_io::win32::nt::rtl_get_process_heap()}; + auto ptr{::fast_io::details::nt_rtlallocate_heap_handle_common_impl(processheap, n, flag)}; + return {ptr, ::fast_io::win32::nt::RtlSizeHeap(processheap, 0, ptr)}; +} + +inline ::fast_io::allocation_least_result nt_rtlreallocate_heap_least_common_impl(void *addr, ::std::size_t n, ::std::uint_least32_t flag) noexcept +{ + auto processheap{::fast_io::win32::nt::rtl_get_process_heap()}; + auto ptr{::fast_io::details::nt_rtlreallocate_heap_handle_common_impl(processheap, addr, n, flag)}; + return {ptr, ::fast_io::win32::nt::RtlSizeHeap(processheap, 0, ptr)}; +} + +} // namespace details + +class nt_rtlallocateheap_allocator +{ +public: +#if __has_cpp_attribute(__gnu__::__malloc__) + [[__gnu__::__malloc__]] +#endif + static inline void *allocate(::std::size_t n) noexcept + { + return ::fast_io::details::nt_rtlallocate_heap_common_impl(n, 0u); + } +#if __has_cpp_attribute(__gnu__::__malloc__) + [[__gnu__::__malloc__]] +#endif + static inline void *allocate_zero(::std::size_t n) noexcept + { + return ::fast_io::details::nt_rtlallocate_heap_common_impl(n, 0x00000008u); + } + static inline void *reallocate(void *addr, ::std::size_t n) noexcept + { + return ::fast_io::details::nt_rtlreallocate_heap_common_impl(addr, n, 0u); + } + static inline void *reallocate_zero(void *addr, ::std::size_t n) noexcept + { + return ::fast_io::details::nt_rtlreallocate_heap_common_impl(addr, n, 0x00000008u); + } + static inline void deallocate(void *addr) noexcept + { + if (addr == nullptr) + { + return; + } + ::fast_io::win32::nt::RtlFreeHeap(::fast_io::win32::nt::rtl_get_process_heap(), 0u, addr); + } +#if 0 + static inline ::fast_io::allocation_least_result allocate_at_least(::std::size_t n) noexcept + { + return ::fast_io::details::nt_rtlallocate_heap_least_common_impl(n, 0u); + } + static inline ::fast_io::allocation_least_result allocate_zero_at_least(::std::size_t n) noexcept + { + return ::fast_io::details::nt_rtlallocate_heap_least_common_impl(n, 0x00000008u); + } + static inline ::fast_io::allocation_least_result reallocate_at_least(void *addr, ::std::size_t n) noexcept + { + return ::fast_io::details::nt_rtlreallocate_heap_least_common_impl(addr, n, 0u); + } + static inline ::fast_io::allocation_least_result reallocate_zero_at_least(void *addr, ::std::size_t n) noexcept + { + return ::fast_io::details::nt_rtlreallocate_heap_least_common_impl(addr, n, 0x00000008u); + } +#endif +}; + +} // namespace fast_io diff --git a/src/fast_io/include/fast_io_core_impl/allocation/win32_heapalloc.h b/src/fast_io/include/fast_io_core_impl/allocation/win32_heapalloc.h new file mode 100644 index 0000000..5a7409c --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/allocation/win32_heapalloc.h @@ -0,0 +1,275 @@ +#pragma once + +namespace fast_io +{ + +namespace win32 +{ +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__) && !defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__) && !defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +#if __has_cpp_attribute(__gnu__::__malloc__) +[[__gnu__::__malloc__]] +#endif +extern void * +#if (!__has_cpp_attribute(__gnu__::__stdcall__) && !defined(__WINE__)) && defined(_MSC_VER) + __stdcall +#endif + HeapAlloc(void *, ::std::uint_least32_t, ::std::size_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX <= UINT_LEAST32_MAX && (defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) + __asm__("HeapAlloc@12") +#else + __asm__("_HeapAlloc@12") +#endif +#else + __asm__("HeapAlloc") +#endif +#endif + ; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__) && !defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__) && !defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__) && !defined(__WINE__)) && defined(_MSC_VER) + __stdcall +#endif + HeapFree(void *, ::std::uint_least32_t, void *) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX <= UINT_LEAST32_MAX && (defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) + __asm__("HeapFree@12") +#else + __asm__("_HeapFree@12") +#endif +#else + __asm__("HeapFree") +#endif +#endif + ; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__) && !defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__) && !defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +#if __has_cpp_attribute(__gnu__::__const__) +[[__gnu__::__const__]] +#endif +extern void * +#if (!__has_cpp_attribute(__gnu__::__stdcall__) && !defined(__WINE__)) && defined(_MSC_VER) + __stdcall +#endif + GetProcessHeap() noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX <= UINT_LEAST32_MAX && (defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) + __asm__("GetProcessHeap@0") +#else + __asm__("_GetProcessHeap@0") +#endif +#else + __asm__("GetProcessHeap") +#endif +#endif + + ; +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__) && !defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__) && !defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern void * +#if (!__has_cpp_attribute(__gnu__::__stdcall__) && !defined(__WINE__)) && defined(_MSC_VER) + __stdcall +#endif + HeapReAlloc(void *, ::std::uint_least32_t, void *, ::std::size_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX <= UINT_LEAST32_MAX && (defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) + __asm__("HeapReAlloc@16") +#else + __asm__("_HeapReAlloc@16") +#endif +#else + __asm__("HeapReAlloc") +#endif +#endif + ; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__) && !defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__) && !defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern ::std::size_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__) && !defined(__WINE__)) && defined(_MSC_VER) + __stdcall +#endif + HeapSize(void *, ::std::uint_least32_t, void const *) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX <= UINT_LEAST32_MAX && (defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) + __asm__("HeapSize@12") +#else + __asm__("_HeapSize@12") +#endif +#else + __asm__("HeapSize") +#endif +#endif + ; + +} // namespace win32 + +namespace details +{ +#if __has_cpp_attribute(__gnu__::__returns_nonnull__) +[[__gnu__::__returns_nonnull__]] +#endif +inline void *win32_heapalloc_handle_common_impl(void *heaphandle, ::std::size_t n, ::std::uint_least32_t flag) noexcept +{ + if (n == 0) + { + n = 1; + } + auto p{::fast_io::win32::HeapAlloc(heaphandle, flag, n)}; + if (p == nullptr) + { + ::fast_io::fast_terminate(); + } + return p; +} + +#if __has_cpp_attribute(__gnu__::__returns_nonnull__) +[[__gnu__::__returns_nonnull__]] +#endif +inline void *win32_heaprealloc_handle_common_impl(void *heaphandle, void *addr, ::std::size_t n, ::std::uint_least32_t flag) noexcept +{ + if (n == 0) + { + n = 1; + } + if (addr == nullptr) +#if __has_cpp_attribute(unlikely) + [[unlikely]] +#endif + { + return win32_heapalloc_handle_common_impl(heaphandle, n, flag); + } + auto p{::fast_io::win32::HeapReAlloc(heaphandle, flag, addr, n)}; + if (p == nullptr) + { + ::fast_io::fast_terminate(); + } + return p; +} + +#if __has_cpp_attribute(__gnu__::__returns_nonnull__) +[[__gnu__::__returns_nonnull__]] +#endif +inline void *win32_heapalloc_common_impl(::std::size_t n, ::std::uint_least32_t flag) noexcept +{ + return ::fast_io::details::win32_heapalloc_handle_common_impl(::fast_io::win32::GetProcessHeap(), n, flag); +} + +#if __has_cpp_attribute(__gnu__::__returns_nonnull__) +[[__gnu__::__returns_nonnull__]] +#endif +inline void *win32_heaprealloc_common_impl(void *addr, ::std::size_t n, ::std::uint_least32_t flag) noexcept +{ + return ::fast_io::details::win32_heaprealloc_handle_common_impl(::fast_io::win32::GetProcessHeap(), addr, n, flag); +} + +inline ::fast_io::allocation_least_result win32_heapalloc_least_common_impl(::std::size_t n, ::std::uint_least32_t flag) noexcept +{ + auto processheap{::fast_io::win32::GetProcessHeap()}; + auto ptr{::fast_io::details::win32_heapalloc_handle_common_impl(processheap, n, flag)}; + return {ptr, ::fast_io::win32::HeapSize(processheap, 0, ptr)}; +} + +inline ::fast_io::allocation_least_result win32_heaprealloc_least_common_impl(void *addr, ::std::size_t n, ::std::uint_least32_t flag) noexcept +{ + auto processheap{::fast_io::win32::GetProcessHeap()}; + auto ptr{::fast_io::details::win32_heaprealloc_handle_common_impl(processheap, addr, n, flag)}; + return {ptr, ::fast_io::win32::HeapSize(processheap, 0, ptr)}; +} + +} // namespace details + +class win32_heapalloc_allocator +{ +public: +#if __has_cpp_attribute(__gnu__::__malloc__) + [[__gnu__::__malloc__]] +#endif + static inline void *allocate(::std::size_t n) noexcept + { + return ::fast_io::details::win32_heapalloc_common_impl(n, 0u); + } + +#if __has_cpp_attribute(__gnu__::__malloc__) + [[__gnu__::__malloc__]] +#endif + static inline void *allocate_zero(::std::size_t n) noexcept + { + return ::fast_io::details::win32_heapalloc_common_impl(n, 0x00000008u); + } + static inline void *reallocate(void *addr, ::std::size_t n) noexcept + { + return ::fast_io::details::win32_heaprealloc_common_impl(addr, n, 0u); + } + static inline void *reallocate_zero(void *addr, ::std::size_t n) noexcept + { + return ::fast_io::details::win32_heaprealloc_common_impl(addr, n, 0x00000008u); + } + static inline void deallocate(void *addr) noexcept + { + if (addr == nullptr) + { + return; + } + ::fast_io::win32::HeapFree(::fast_io::win32::GetProcessHeap(), 0u, addr); + } +#if 0 + static inline ::fast_io::allocation_least_result allocate_at_least(::std::size_t n) noexcept + { + return ::fast_io::details::win32_heapalloc_least_common_impl(n, 0u); + } + static inline ::fast_io::allocation_least_result allocate_zero_at_least(::std::size_t n) noexcept + { + return ::fast_io::details::win32_heapalloc_least_common_impl(n, 0x00000008u); + } + static inline ::fast_io::allocation_least_result reallocate_at_least(void *addr, ::std::size_t n) noexcept + { + return ::fast_io::details::win32_heaprealloc_least_common_impl(addr, n, 0u); + } + static inline ::fast_io::allocation_least_result reallocate_zero_at_least(void *addr, ::std::size_t n) noexcept + { + return ::fast_io::details::win32_heaprealloc_least_common_impl(addr, n, 0x00000008u); + } +#endif +}; + +} // namespace fast_io diff --git a/src/fast_io/include/fast_io_core_impl/allocation/wincrt_malloc_dbg.h b/src/fast_io/include/fast_io_core_impl/allocation/wincrt_malloc_dbg.h new file mode 100644 index 0000000..90b6931 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/allocation/wincrt_malloc_dbg.h @@ -0,0 +1,96 @@ +#pragma once + +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning(push) +#pragma warning(disable : 6308) +#endif + +#include + +namespace fast_io +{ + +class wincrt_malloc_dbg_allocator +{ +public: +#if __has_cpp_attribute(__gnu__::__returns_nonnull__) + [[__gnu__::__returns_nonnull__]] +#endif + static inline void *allocate(::std::size_t n) noexcept + { + if (n == 0) + { + n = 1; + } + void *p = ::fast_io::noexcept_call(_malloc_dbg, n, 1, __FILE__, __LINE__); + if (p == nullptr) + { + ::fast_io::fast_terminate(); + } + return p; + } +#if __has_cpp_attribute(__gnu__::__returns_nonnull__) + [[__gnu__::__returns_nonnull__]] +#endif + static inline void *reallocate(void *p, ::std::size_t n) noexcept + { + if (n == 0) + { + n = 1; + } + p = ::fast_io::noexcept_call(_realloc_dbg, p, n, 1, __FILE__, __LINE__); + if (p == nullptr) + { + ::fast_io::fast_terminate(); + } + return p; + } +#if __has_cpp_attribute(__gnu__::__returns_nonnull__) + [[__gnu__::__returns_nonnull__]] +#endif + static inline void *allocate_zero(::std::size_t n) noexcept + { + if (n == 0) + { + n = 1; + } + void *p = ::fast_io::noexcept_call(_calloc_dbg, 1, n, 1, __FILE__, __LINE__); + if (p == nullptr) + { + ::fast_io::fast_terminate(); + } + return p; + } + static inline void deallocate(void *p) noexcept + { + if (p == nullptr) + { + return; + } + ::fast_io::noexcept_call(_free_dbg, p, 1); + } + +#if 0 + static inline allocation_least_result allocate_at_least(::std::size_t n) noexcept + { + auto p{::fast_io::wincrt_malloc_dbg_allocator::allocate(n)}; + return {p, ::fast_io::noexcept_call(_msize_dbg, p, 1)}; + } + static inline allocation_least_result allocate_zero_at_least(::std::size_t n) noexcept + { + auto p{::fast_io::wincrt_malloc_dbg_allocator::allocate_zero(n)}; + return {p, ::fast_io::noexcept_call(_msize_dbg, p, 1)}; + } + static inline allocation_least_result reallocate_at_least(void *oldp, ::std::size_t n) noexcept + { + auto p{::fast_io::wincrt_malloc_dbg_allocator::reallocate(oldp, n)}; + return {p, ::fast_io::noexcept_call(_msize_dbg, p, 1)}; + } +#endif +}; + +} // namespace fast_io + +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning(pop) +#endif diff --git a/src/fast_io/include/fast_io_core_impl/asan_support.h b/src/fast_io/include/fast_io_core_impl/asan_support.h new file mode 100644 index 0000000..76c6334 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/asan_support.h @@ -0,0 +1,28 @@ +#pragma once + +namespace fast_io::details +{ + +enum class asan_state +{ +none, +activate, +current= +#if (defined(_GLIBCXX_DEBUG) || defined(_DEBUG) || _ITERATOR_DEBUG_LEVEL>=2 || _LIBCPP_DEBUG >= 2 || defined(FAST_IO_SANITIZE_IO_BUFFER)) +#if defined(__SANITIZE_ADDRESS__) +activate +#elif defined(__has_feature) +#if __has_feature(address_sanitizer) +activate +#else +none +#endif +#else +none +#endif +#else +none +#endif +}; + +} diff --git a/src/fast_io/include/fast_io_core_impl/black_hole.h b/src/fast_io/include/fast_io_core_impl/black_hole.h new file mode 100644 index 0000000..1bb14e1 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/black_hole.h @@ -0,0 +1,28 @@ +#pragma once + +namespace fast_io +{ + +//black_hole is a helper class which helps you remove device requirement for iobuf or iotransform. +//sha256 for example. You do not need a real device. You want to send all your bits to black hole + +template +struct basic_black_hole +{ +public: + using char_type = ch_type; +}; + +template +inline constexpr void write(basic_black_hole,Iter,Iter){} + +template +inline constexpr Iter read(basic_black_hole,Iter b,Iter){return b;} + +template +inline constexpr basic_black_hole io_value_handle(basic_black_hole h) noexcept +{ + return h; +} + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_core_impl/buffer_view.h b/src/fast_io/include/fast_io_core_impl/buffer_view.h new file mode 100644 index 0000000..3950488 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/buffer_view.h @@ -0,0 +1,195 @@ +#pragma once + +namespace fast_io +{ + +template +struct basic_ibuffer_view +{ + using char_type = ch_type; + char_type const *begin_ptr{}; + char_type const *curr_ptr{}; + char_type const *end_ptr{}; + constexpr basic_ibuffer_view() noexcept = default; + template<::std::contiguous_iterator Iter> + requires std::same_as>,char_type> + constexpr basic_ibuffer_view(Iter first,Iter last) noexcept:begin_ptr{::std::to_address(first)},curr_ptr{begin_ptr},end_ptr{curr_ptr+(last-first)}{} + template + requires (std::same_as<::std::ranges::range_value_t,char_type>&&!::std::is_array_v>) + explicit constexpr basic_ibuffer_view(rg& r) noexcept : basic_ibuffer_view(::std::ranges::cbegin(r),::std::ranges::cend(r)){} + constexpr void clear() noexcept + { + curr_ptr=begin_ptr; + } +}; + +template +requires std::same_as<::std::iter_value_t,ch_type> +[[nodiscard]] inline constexpr Iter read(basic_ibuffer_view& view,Iter first,Iter last) noexcept +{ + auto diff{last-first}; + auto view_diff{view.end_ptr-view.curr_ptr}; + if(view_diff(view_diff),first)}; + view.curr_ptr+=diff; + return it; +} + +template +[[nodiscard]] constexpr ch_type const* ibuffer_begin(basic_ibuffer_view& view) noexcept +{ + return view.begin_ptr; +} + +template +[[nodiscard]] constexpr ch_type const* ibuffer_curr(basic_ibuffer_view& view) noexcept +{ + return view.curr_ptr; +} + +template +[[nodiscard]] constexpr ch_type const* ibuffer_end(basic_ibuffer_view& view) noexcept +{ + return view.end_ptr; +} + +template +constexpr void ibuffer_set_curr(basic_ibuffer_view& view,ch_type const* ptr) noexcept +{ + view.curr_ptr=ptr; +} + +template +[[nodiscard]] constexpr bool ibuffer_underflow(basic_ibuffer_view&) noexcept +{ + return false; +} + +template +inline constexpr bool ibuffer_underflow_never(basic_ibuffer_view&) noexcept +{ + return true; +} + +template +struct basic_obuffer_view +{ + using char_type = ch_type; + char_type *begin_ptr{},*curr_ptr{},*end_ptr{}; + constexpr basic_obuffer_view() noexcept = default; + template<::std::contiguous_iterator Iter> + requires std::same_as<::std::iter_value_t,char_type> + constexpr basic_obuffer_view(Iter first,Iter last) noexcept:begin_ptr{::std::to_address(first)}, + curr_ptr{begin_ptr}, + end_ptr{::std::to_address(last)}{} + template + requires (std::same_as<::std::ranges::range_value_t,char_type>&&!::std::is_array_v>) + explicit constexpr basic_obuffer_view(rg& r) noexcept : basic_obuffer_view(::std::ranges::begin(r),::std::ranges::end(r)){} + constexpr void clear() noexcept + { + curr_ptr=begin_ptr; + } + constexpr char_type const* cbegin() const noexcept + { + return begin_ptr; + } + constexpr char_type const* cend() const noexcept + { + return curr_ptr; + } + constexpr char_type const* begin() const noexcept + { + return begin_ptr; + } + constexpr char_type const* end() const noexcept + { + return curr_ptr; + } + constexpr char_type* begin() noexcept + { + return begin_ptr; + } + constexpr char_type* end() noexcept + { + return curr_ptr; + } + + constexpr char_type const* data() const noexcept + { + return begin_ptr; + } + constexpr char_type* data() noexcept + { + return begin_ptr; + } + + constexpr std::size_t size() const noexcept + { + return static_cast(curr_ptr-begin_ptr); + } + + constexpr std::size_t capacity() const noexcept + { + return static_cast(end_ptr-begin_ptr); + } +}; + +template +requires std::same_as<::std::iter_value_t,ch_type> +inline constexpr void write(basic_obuffer_view& view,Iter first,Iter last) noexcept +{ + auto diff{last-first}; + auto view_diff{view.end_ptr-view.curr_ptr}; + if(view_diff(diff),view.curr_ptr); +} + +template +[[nodiscard]] constexpr ch_type* obuffer_begin(basic_obuffer_view& view) noexcept +{ + return view.begin_ptr; +} + +template +[[nodiscard]] constexpr ch_type* obuffer_curr(basic_obuffer_view& view) noexcept +{ + return view.curr_ptr; +} + +template +[[nodiscard]] constexpr ch_type* obuffer_end(basic_obuffer_view& view) noexcept +{ + return view.end_ptr; +} + +template +constexpr void obuffer_set_curr(basic_obuffer_view& view,ch_type* ptr) noexcept +{ + view.curr_ptr=ptr; +} + +template +constexpr void obuffer_overflow(basic_obuffer_view&,ch_type) noexcept +{ + fast_terminate(); +} + +template +inline constexpr bool obuffer_overflow_never(basic_obuffer_view&) noexcept +{ + return true; +} + +using ibuffer_view = basic_ibuffer_view; +using wibuffer_view = basic_ibuffer_view; +using u8ibuffer_view = basic_ibuffer_view; +using u16ibuffer_view = basic_ibuffer_view; +using u32ibuffer_view = basic_ibuffer_view; +using obuffer_view = basic_obuffer_view; +using wobuffer_view = basic_obuffer_view; +using u8obuffer_view = basic_obuffer_view; +using u16obuffer_view = basic_obuffer_view; +using u32obuffer_view = basic_obuffer_view; +} diff --git a/src/fast_io/include/fast_io_core_impl/char_category.h b/src/fast_io/include/fast_io_core_impl/char_category.h new file mode 100644 index 0000000..1a73a4f --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/char_category.h @@ -0,0 +1,500 @@ +#pragma once + +namespace fast_io::char_category +{ + +template +inline constexpr bool is_c_alnum(char_type ch) noexcept +{ + if constexpr(std::same_as) +switch(ch){case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':case 'A':case 'B':case 'C':case 'D':case 'E':case 'F':case 'G':case 'H':case 'I':case 'J':case 'K':case 'L':case 'M':case 'N':case 'O':case 'P':case 'Q':case 'R':case 'S':case 'T':case 'U':case 'V':case 'W':case 'X':case 'Y':case 'Z':case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':case 'g':case 'h':case 'i':case 'j':case 'k':case 'l':case 'm':case 'n':case 'o':case 'p':case 'q':case 'r':case 's':case 't':case 'u':case 'v':case 'w':case 'x':case 'y':case 'z':return true;default:return false;} + else if constexpr(std::same_as) +switch(ch){case L'0':case L'1':case L'2':case L'3':case L'4':case L'5':case L'6':case L'7':case L'8':case L'9':case L'A':case L'B':case L'C':case L'D':case L'E':case L'F':case L'G':case L'H':case L'I':case L'J':case L'K':case L'L':case L'M':case L'N':case L'O':case L'P':case L'Q':case L'R':case L'S':case L'T':case L'U':case L'V':case L'W':case L'X':case L'Y':case L'Z':case L'a':case L'b':case L'c':case L'd':case L'e':case L'f':case L'g':case L'h':case L'i':case L'j':case L'k':case L'l':case L'm':case L'n':case L'o':case L'p':case L'q':case L'r':case L's':case L't':case L'u':case L'v':case L'w':case L'x':case L'y':case L'z':return true;default:return false;} + else +switch(ch){case u8'0':case u8'1':case u8'2':case u8'3':case u8'4':case u8'5':case u8'6':case u8'7':case u8'8':case u8'9':case u8'A':case u8'B':case u8'C':case u8'D':case u8'E':case u8'F':case u8'G':case u8'H':case u8'I':case u8'J':case u8'K':case u8'L':case u8'M':case u8'N':case u8'O':case u8'P':case u8'Q':case u8'R':case u8'S':case u8'T':case u8'U':case u8'V':case u8'W':case u8'X':case u8'Y':case u8'Z':case u8'a':case u8'b':case u8'c':case u8'd':case u8'e':case u8'f':case u8'g':case u8'h':case u8'i':case u8'j':case u8'k':case u8'l':case u8'm':case u8'n':case u8'o':case u8'p':case u8'q':case u8'r':case u8's':case u8't':case u8'u':case u8'v':case u8'w':case u8'x':case u8'y':case u8'z':return true;default:return false;} +} + +template +inline constexpr bool is_c_alpha(char_type ch) noexcept +{ + if constexpr(std::same_as) +switch(ch){case 'A':case 'B':case 'C':case 'D':case 'E':case 'F':case 'G':case 'H':case 'I':case 'J':case 'K':case 'L':case 'M':case 'N':case 'O':case 'P':case 'Q':case 'R':case 'S':case 'T':case 'U':case 'V':case 'W':case 'X':case 'Y':case 'Z':case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':case 'g':case 'h':case 'i':case 'j':case 'k':case 'l':case 'm':case 'n':case 'o':case 'p':case 'q':case 'r':case 's':case 't':case 'u':case 'v':case 'w':case 'x':case 'y':case 'z':return true;default:return false;} + else if constexpr(std::same_as) +switch(ch){case L'A':case L'B':case L'C':case L'D':case L'E':case L'F':case L'G':case L'H':case L'I':case L'J':case L'K':case L'L':case L'M':case L'N':case L'O':case L'P':case L'Q':case L'R':case L'S':case L'T':case L'U':case L'V':case L'W':case L'X':case L'Y':case L'Z':case L'a':case L'b':case L'c':case L'd':case L'e':case L'f':case L'g':case L'h':case L'i':case L'j':case L'k':case L'l':case L'm':case L'n':case L'o':case L'p':case L'q':case L'r':case L's':case L't':case L'u':case L'v':case L'w':case L'x':case L'y':case L'z':return true;default:return false;} + else +switch(ch){case u8'A':case u8'B':case u8'C':case u8'D':case u8'E':case u8'F':case u8'G':case u8'H':case u8'I':case u8'J':case u8'K':case u8'L':case u8'M':case u8'N':case u8'O':case u8'P':case u8'Q':case u8'R':case u8'S':case u8'T':case u8'U':case u8'V':case u8'W':case u8'X':case u8'Y':case u8'Z':case u8'a':case u8'b':case u8'c':case u8'd':case u8'e':case u8'f':case u8'g':case u8'h':case u8'i':case u8'j':case u8'k':case u8'l':case u8'm':case u8'n':case u8'o':case u8'p':case u8'q':case u8'r':case u8's':case u8't':case u8'u':case u8'v':case u8'w':case u8'x':case u8'y':case u8'z':return true;default:return false;} +} + +template +inline constexpr bool is_c_lower(char_type ch) noexcept +{ + if constexpr(std::same_as) +switch(ch){case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':case 'g':case 'h':case 'i':case 'j':case 'k':case 'l':case 'm':case 'n':case 'o':case 'p':case 'q':case 'r':case 's':case 't':case 'u':case 'v':case 'w':case 'x':case 'y':case 'z':return true;default:return false;} + else if constexpr(std::same_as) +switch(ch){case L'a':case L'b':case L'c':case L'd':case L'e':case L'f':case L'g':case L'h':case L'i':case L'j':case L'k':case L'l':case L'm':case L'n':case L'o':case L'p':case L'q':case L'r':case L's':case L't':case L'u':case L'v':case L'w':case L'x':case L'y':case L'z':return true;default:return false;} + else +switch(ch){case u8'a':case u8'b':case u8'c':case u8'd':case u8'e':case u8'f':case u8'g':case u8'h':case u8'i':case u8'j':case u8'k':case u8'l':case u8'm':case u8'n':case u8'o':case u8'p':case u8'q':case u8'r':case u8's':case u8't':case u8'u':case u8'v':case u8'w':case u8'x':case u8'y':case u8'z':return true;default:return false;} +} + +template +inline constexpr bool is_c_upper(char_type ch) noexcept +{ + if constexpr(std::same_as) +switch(ch){case 'A':case 'B':case 'C':case 'D':case 'E':case 'F':case 'G':case 'H':case 'I':case 'J':case 'K':case 'L':case 'M':case 'N':case 'O':case 'P':case 'Q':case 'R':case 'S':case 'T':case 'U':case 'V':case 'W':case 'X':case 'Y':case 'Z':return true;default:return false;} + else if constexpr(std::same_as) +switch(ch){case L'A':case L'B':case L'C':case L'D':case L'E':case L'F':case L'G':case L'H':case L'I':case L'J':case L'K':case L'L':case L'M':case L'N':case L'O':case L'P':case L'Q':case L'R':case L'S':case L'T':case L'U':case L'V':case L'W':case L'X':case L'Y':case L'Z':return true;default:return false;} + else +switch(ch){case u8'A':case u8'B':case u8'C':case u8'D':case u8'E':case u8'F':case u8'G':case u8'H':case u8'I':case u8'J':case u8'K':case u8'L':case u8'M':case u8'N':case u8'O':case u8'P':case u8'Q':case u8'R':case u8'S':case u8'T':case u8'U':case u8'V':case u8'W':case u8'X':case u8'Y':case u8'Z':return true;default:return false;} +} + +template +inline constexpr bool is_c_digit(char_type ch) noexcept +{ + if constexpr(std::same_as) +switch(ch){case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':return true;default:return false;} + else if constexpr(std::same_as) +switch(ch){case L'0':case L'1':case L'2':case L'3':case L'4':case L'5':case L'6':case L'7':case L'8':case L'9':return true;default:return false;} + else +switch(ch){case u8'0':case u8'1':case u8'2':case u8'3':case u8'4':case u8'5':case u8'6':case u8'7':case u8'8':case u8'9':return true;default:return false;} +} + +template +inline constexpr bool is_c_xdigit(char_type ch) noexcept +{ + if constexpr(std::same_as) +switch(ch){case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':case 'A':case 'B':case 'C':case 'D':case 'E':case 'F':return true;default:return false;} + else if constexpr(std::same_as) +switch(ch){case L'0':case L'1':case L'2':case L'3':case L'4':case L'5':case L'6':case L'7':case L'8':case L'9':case L'a':case L'b':case L'c':case L'd':case L'e':case L'f':case L'A':case L'B':case L'C':case L'D':case L'E':case L'F':return true;default:return false;} + else +switch(ch){case u8'0':case u8'1':case u8'2':case u8'3':case u8'4':case u8'5':case u8'6':case u8'7':case u8'8':case u8'9':case u8'a':case u8'b':case u8'c':case u8'd':case u8'e':case u8'f':case u8'A':case u8'B':case u8'C':case u8'D':case u8'E':case u8'F':return true;default:return false;} +} + +template +inline constexpr bool is_c_punct(char_type ch) noexcept +{ + if constexpr(std::same_as) +switch(ch){case '!':case '\"':case '#':case '$':case '%':case '&':case '\'':case '(':case ')':case '*':case '+':case ',':case '-':case '.':case '/':case ':':case ';':case '<':case '=':case '>':case '?':case '@':case '[':case '\\':case ']':case '^':case '_':case '`':case '{':case '|':case '}':case '~':return true;default:return false;} + else if constexpr(std::same_as) +switch(ch){case L'!':case L'\"':case L'#':case L'$':case L'%':case L'&':case L'\'':case L'(':case L')':case L'*':case L'+':case L',':case L'-':case L'.':case L'/':case L':':case L';':case L'<':case L'=':case L'>':case L'?':case L'@':case L'[':case L'\\':case L']':case L'^':case L'_':case L'`':case L'{':case L'|':case L'}':case L'~':return true;default:return false;} + else +switch(ch){case u8'!':case u8'\"':case u8'#':case u8'$':case u8'%':case u8'&':case u8'\'':case u8'(':case u8')':case u8'*':case u8'+':case u8',':case u8'-':case u8'.':case u8'/':case u8':':case u8';':case u8'<':case u8'=':case u8'>':case u8'?':case u8'@':case u8'[':case u8'\\':case u8']':case u8'^':case u8'_':case u8'`':case u8'{':case u8'|':case u8'}':case u8'~':return true;default:return false;} +} + +template +inline constexpr bool is_c_graph(char_type ch) noexcept +{ + if constexpr(std::same_as) +switch(ch){case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':case 'A':case 'B':case 'C':case 'D':case 'E':case 'F':case 'G':case 'H':case 'I':case 'J':case 'K':case 'L':case 'M':case 'N':case 'O':case 'P':case 'Q':case 'R':case 'S':case 'T':case 'U':case 'V':case 'W':case 'X':case 'Y':case 'Z':case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':case 'g':case 'h':case 'i':case 'j':case 'k':case 'l':case 'm':case 'n':case 'o':case 'p':case 'q':case 'r':case 's':case 't':case 'u':case 'v':case 'w':case 'x':case 'y':case 'z':case '!':case '\"':case '#':case '$':case '%':case '&':case '\'':case '(':case ')':case '*':case '+':case ',':case '-':case '.':case '/':case ':':case ';':case '<':case '=':case '>':case '?':case '@':case '[':case '\\':case ']':case '^':case '_':case '`':case '{':case '|':case '}':case '~':return true;default:return false;} + else if constexpr(std::same_as) +switch(ch){case L'0':case L'1':case L'2':case L'3':case L'4':case L'5':case L'6':case L'7':case L'8':case L'9':case L'A':case L'B':case L'C':case L'D':case L'E':case L'F':case L'G':case L'H':case L'I':case L'J':case L'K':case L'L':case L'M':case L'N':case L'O':case L'P':case L'Q':case L'R':case L'S':case L'T':case L'U':case L'V':case L'W':case L'X':case L'Y':case L'Z':case L'a':case L'b':case L'c':case L'd':case L'e':case L'f':case L'g':case L'h':case L'i':case L'j':case L'k':case L'l':case L'm':case L'n':case L'o':case L'p':case L'q':case L'r':case L's':case L't':case L'u':case L'v':case L'w':case L'x':case L'y':case L'z':case L'!':case L'\"':case L'#':case L'$':case L'%':case L'&':case L'\'':case L'(':case L')':case L'*':case L'+':case L',':case L'-':case L'.':case L'/':case L':':case L';':case L'<':case L'=':case L'>':case L'?':case L'@':case L'[':case L'\\':case L']':case L'^':case L'_':case L'`':case L'{':case L'|':case L'}':case L'~':return true;default:return false;} + else +switch(ch){case u8'0':case u8'1':case u8'2':case u8'3':case u8'4':case u8'5':case u8'6':case u8'7':case u8'8':case u8'9':case u8'A':case u8'B':case u8'C':case u8'D':case u8'E':case u8'F':case u8'G':case u8'H':case u8'I':case u8'J':case u8'K':case u8'L':case u8'M':case u8'N':case u8'O':case u8'P':case u8'Q':case u8'R':case u8'S':case u8'T':case u8'U':case u8'V':case u8'W':case u8'X':case u8'Y':case u8'Z':case u8'a':case u8'b':case u8'c':case u8'd':case u8'e':case u8'f':case u8'g':case u8'h':case u8'i':case u8'j':case u8'k':case u8'l':case u8'm':case u8'n':case u8'o':case u8'p':case u8'q':case u8'r':case u8's':case u8't':case u8'u':case u8'v':case u8'w':case u8'x':case u8'y':case u8'z':case u8'!':case u8'\"':case u8'#':case u8'$':case u8'%':case u8'&':case u8'\'':case u8'(':case u8')':case u8'*':case u8'+':case u8',':case u8'-':case u8'.':case u8'/':case u8':':case u8';':case u8'<':case u8'=':case u8'>':case u8'?':case u8'@':case u8'[':case u8'\\':case u8']':case u8'^':case u8'_':case u8'`':case u8'{':case u8'|':case u8'}':case u8'~':return true;default:return false;} +} + +template +inline constexpr bool is_c_print(char_type ch) noexcept +{ + if constexpr(std::same_as) +switch(ch){case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':case 'A':case 'B':case 'C':case 'D':case 'E':case 'F':case 'G':case 'H':case 'I':case 'J':case 'K':case 'L':case 'M':case 'N':case 'O':case 'P':case 'Q':case 'R':case 'S':case 'T':case 'U':case 'V':case 'W':case 'X':case 'Y':case 'Z':case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':case 'g':case 'h':case 'i':case 'j':case 'k':case 'l':case 'm':case 'n':case 'o':case 'p':case 'q':case 'r':case 's':case 't':case 'u':case 'v':case 'w':case 'x':case 'y':case 'z':case '!':case '\"':case '#':case '$':case '%':case '&':case '\'':case '(':case ')':case '*':case '+':case ',':case '-':case '.':case '/':case ':':case ';':case '<':case '=':case '>':case '?':case '@':case '[':case '\\':case ']':case '^':case '_':case '`':case '{':case '|':case '}':case '~':case ' ':return true;default:return false;} + else if constexpr(std::same_as) +switch(ch){case L'0':case L'1':case L'2':case L'3':case L'4':case L'5':case L'6':case L'7':case L'8':case L'9':case L'A':case L'B':case L'C':case L'D':case L'E':case L'F':case L'G':case L'H':case L'I':case L'J':case L'K':case L'L':case L'M':case L'N':case L'O':case L'P':case L'Q':case L'R':case L'S':case L'T':case L'U':case L'V':case L'W':case L'X':case L'Y':case L'Z':case L'a':case L'b':case L'c':case L'd':case L'e':case L'f':case L'g':case L'h':case L'i':case L'j':case L'k':case L'l':case L'm':case L'n':case L'o':case L'p':case L'q':case L'r':case L's':case L't':case L'u':case L'v':case L'w':case L'x':case L'y':case L'z':case L'!':case L'\"':case L'#':case L'$':case L'%':case L'&':case L'\'':case L'(':case L')':case L'*':case L'+':case L',':case L'-':case L'.':case L'/':case L':':case L';':case L'<':case L'=':case L'>':case L'?':case L'@':case L'[':case L'\\':case L']':case L'^':case L'_':case L'`':case L'{':case L'|':case L'}':case L'~':case L' ':return true;default:return false;} + else +switch(ch){case u8'0':case u8'1':case u8'2':case u8'3':case u8'4':case u8'5':case u8'6':case u8'7':case u8'8':case u8'9':case u8'A':case u8'B':case u8'C':case u8'D':case u8'E':case u8'F':case u8'G':case u8'H':case u8'I':case u8'J':case u8'K':case u8'L':case u8'M':case u8'N':case u8'O':case u8'P':case u8'Q':case u8'R':case u8'S':case u8'T':case u8'U':case u8'V':case u8'W':case u8'X':case u8'Y':case u8'Z':case u8'a':case u8'b':case u8'c':case u8'd':case u8'e':case u8'f':case u8'g':case u8'h':case u8'i':case u8'j':case u8'k':case u8'l':case u8'm':case u8'n':case u8'o':case u8'p':case u8'q':case u8'r':case u8's':case u8't':case u8'u':case u8'v':case u8'w':case u8'x':case u8'y':case u8'z':case u8'!':case u8'\"':case u8'#':case u8'$':case u8'%':case u8'&':case u8'\'':case u8'(':case u8')':case u8'*':case u8'+':case u8',':case u8'-':case u8'.':case u8'/':case u8':':case u8';':case u8'<':case u8'=':case u8'>':case u8'?':case u8'@':case u8'[':case u8'\\':case u8']':case u8'^':case u8'_':case u8'`':case u8'{':case u8'|':case u8'}':case u8'~':case u8' ':return true;default:return false;} +} + +namespace details +{ +inline constexpr char32_t to_c_upper_ascii_impl(char32_t ch) noexcept +{ + constexpr char32_t alphanum{static_cast(26u)}; + char32_t res{ch-U'a'}; + if(res(26u)}; + char32_t res{ch-U'A'}; + if(res +inline constexpr char_type to_c_lower(char_type ch) noexcept +{ + using unsigned_char_type = std::make_unsigned_t; + if constexpr(!::fast_io::details::is_ebcdic) + return static_cast(static_cast(details::to_c_lower_ascii_impl(static_cast(ch)))); + else if constexpr(std::same_as) +switch(ch){case 'A':return 'a';case 'B':return 'b';case 'C':return 'c';case 'D':return 'd';case 'E':return 'e';case 'F':return 'f';case 'G':return 'g';case 'H':return 'h';case 'I':return 'i';case 'J':return 'j';case 'K':return 'k';case 'L':return 'l';case 'M':return 'm';case 'N':return 'n';case 'O':return 'o';case 'P':return 'p';case 'Q':return 'q';case 'R':return 'r';case 'S':return 's';case 'T':return 't';case 'U':return 'u';case 'V':return 'v';case 'W':return 'w';case 'X':return 'x';case 'Y':return 'y';case 'Z':return 'z';default:return ch;} + else if constexpr(std::same_as) +switch(ch){case L'A':return L'a';case L'B':return L'b';case L'C':return L'c';case L'D':return L'd';case L'E':return L'e';case L'F':return L'f';case L'G':return L'g';case L'H':return L'h';case L'I':return L'i';case L'J':return L'j';case L'K':return L'k';case L'L':return L'l';case L'M':return L'm';case L'N':return L'n';case L'O':return L'o';case L'P':return L'p';case L'Q':return L'q';case L'R':return L'r';case L'S':return L's';case L'T':return L't';case L'U':return L'u';case L'V':return L'v';case L'W':return L'w';case L'X':return L'x';case L'Y':return L'y';case L'Z':return L'z';default:return ch;} +} + +template +inline constexpr char_type to_c_upper(char_type ch) noexcept +{ + using unsigned_char_type = std::make_unsigned_t; + if constexpr(!::fast_io::details::is_ebcdic) + return static_cast(static_cast(details::to_c_upper_ascii_impl(static_cast(ch)))); + else if constexpr(std::same_as) +switch(ch){case 'a':return 'A';case 'b':return 'B';case 'c':return 'C';case 'd':return 'D';case 'e':return 'E';case 'f':return 'F';case 'g':return 'G';case 'h':return 'H';case 'i':return 'I';case 'j':return 'J';case 'k':return 'K';case 'l':return 'L';case 'm':return 'M';case 'n':return 'N';case 'o':return 'O';case 'p':return 'P';case 'q':return 'Q';case 'r':return 'R';case 's':return 'S';case 't':return 'T';case 'u':return 'U';case 'v':return 'V';case 'w':return 'W';case 'x':return 'X';case 'y':return 'Y';case 'z':return 'Z';default:return ch;} + else if constexpr(std::same_as) +switch(ch){case L'a':return L'A';case L'b':return L'B';case L'c':return L'C';case L'd':return L'D';case L'e':return L'E';case L'f':return L'F';case L'g':return L'G';case L'h':return L'H';case L'i':return L'I';case L'j':return L'J';case L'k':return L'K';case L'l':return L'L';case L'm':return L'M';case L'n':return L'N';case L'o':return L'O';case L'p':return L'P';case L'q':return L'Q';case L'r':return L'R';case L's':return L'S';case L't':return L'T';case L'u':return L'U';case L'v':return L'V';case L'w':return L'W';case L'x':return L'X';case L'y':return L'Y';case L'z':return L'Z';default:return ch;} +} + +/* +All Ascii based charset, only 6 character is supported +space (0x20, ' ') +form feed (0x0c, '\f') +line feed (0x0a, '\n') +carriage return (0x0d, '\r') +horizontal tab (0x09, '\t') +vertical tab (0x0b, '\v') + +Any other exec-charset, besides these 6 characters, they can optionally support others, but too many are not allowed. + +For EBCDIC NL should also get supported. +ASCII: space (0x20, ' '), EBCDIC:64 +ASCII: form feed (0x0c, '\f'), EBCDIC:12 +ASCII: line feed (0x0a, '\n'), EBCDIC:37 +ASCII: carriage return (0x0d, '\r'), EBCDIC:13 +ASCII: horizontal tab (0x09, '\t'), EBCDIC:5 +ASCII: vertical tab (0x0b, '\v'), EBCDIC:11 +EBCDIC specific: NL:21 +*/ + +namespace details +{ +inline constexpr bool is_c_space_wide_impl(wchar_t ch) noexcept +{ + switch(ch) + { + case L'\f':case L'\n':case L'\r': + case L'\t':case L'\v':case L' ':return true; + default: + return false; + }; +} + +template +inline constexpr bool is_c_space_impl(char_type ch) noexcept +{ + if constexpr(use_ebcdic) + { + switch(ch) + { + case 5:case 11:case 12:case 13: + case 21:case 37:case 64:return true; + default: + return false; + }; + } + else + { + if constexpr(std::unsigned_integral>) + { + using unsigned_t = char_type; + return (ch==0x20)|(static_cast(ch-0x9)(0x5)); + } + else + { + using unsigned_t = std::make_unsigned_t; + unsigned_t const e(ch); + return (e==0x20)|(static_cast(e-0x9)(0x5)); + } + } +} + +template +inline constexpr auto is_c_space_tb_impl() noexcept +{ + ::fast_io::freestanding::array tb; + for(std::size_t i{};i!=tb.size();++i) + tb[i]=is_c_space_impl(static_cast(i)); + return tb; +} + +template +requires (sizeof(char_type)==1) +inline constexpr auto is_c_space_tb{is_c_space_tb_impl()}; +} + +template +inline constexpr bool is_c_space(char_type ch) noexcept +{ + constexpr bool optimize_with_spacetb{sizeof(char_type)==1&&std::numeric_limits::digits==8}; + if constexpr(optimize_with_spacetb) + { + if constexpr(::fast_io::details::is_ebcdic) + return details::is_c_space_tb[static_cast>(ch)]; + else + return details::is_c_space_tb[static_cast>(ch)]; + } + else + { + if constexpr(::fast_io::details::is_ebcdic) + return details::is_c_space_impl(ch); + else if constexpr(::std::same_as&&::fast_io::details::wide_is_none_utf_endian) + return details::is_c_space_wide_impl(ch); + else + return details::is_c_space_impl(static_cast(static_cast>(ch))); + } +} + +/* +https://www.gnu.org/software/gcc/gcc-11/changes.html + + +A series of conditional expressions that compare the same variable can be transformed into a switch statement if each of them contains a comparison expression. Example: + int IsHTMLWhitespace(int aChar) { + return aChar == 0x0009 || aChar == 0x000A || + aChar == 0x000C || aChar == 0x000D || + aChar == 0x0020; + } +Let's just add this into this library + +*/ + +namespace details +{ +template +inline constexpr bool is_html_whitespace_ascii_impl(char_type ch) noexcept +{ + switch(ch) + { + case 0x0009:case 0x000A:case 0x000C:case 0x000D:case 0x0020:return true; + default:return false; + } +} + +/* +For EBCDIC NL should also get supported. +ASCII: space (0x20, ' '), EBCDIC:64 +ASCII: form feed (0x0c, '\f'), EBCDIC:12 +ASCII: line feed (0x0a, '\n'), EBCDIC:37 +ASCII: carriage return (0x0d, '\r'), EBCDIC:13 +ASCII: horizontal tab (0x09, '\t'), EBCDIC:5 +EBCDIC specific: NL:21 +*/ +inline constexpr bool is_html_whitespace_ebcdic_impl(char32_t ch) noexcept +{ + switch(ch) + { + case 5:case 12:case 13: + case 21:case 37:case 64:return true; + default: + return false; + }; +} + +inline constexpr bool is_html_whitespace_wide_impl(wchar_t ch) noexcept +{ + switch(ch) + { + case L'\f':case L'\n':case L'\r': + case L'\t':case L' ':return true; + default: + return false; + }; +} + +} + +template +inline constexpr bool is_html_whitespace(char_type ch) noexcept +{ + using unsigned_char_type = std::make_unsigned_t; + if constexpr(::fast_io::details::is_ebcdic) + { + return details::is_html_whitespace_ebcdic_impl(static_cast(ch)); + } + else + { + if constexpr(sizeof(char_type)<=sizeof(char32_t)) + { + return details::is_html_whitespace_ascii_impl(static_cast(static_cast(ch))); + } + else + { + return details::is_html_whitespace_ascii_impl(static_cast(ch)); + } + } +} + +template +inline constexpr bool is_c_halfwidth(char_type ch) noexcept +{ + using unsigned_char_type = std::make_unsigned_t; + if constexpr(sizeof(char_type)&&sizeof(char_type)==sizeof(char32_t)) + { + return is_c_halfwidth(static_cast(ch)); + } + else if constexpr(std::signed_integral) + { + return is_c_halfwidth(static_cast(ch)); + } + else if constexpr(::std::same_as&&::fast_io::details::wide_is_none_utf_endian) + { + constexpr unsigned_char_type halfwidth_exclaimation_mark_val{u8'!'}; + constexpr unsigned_char_type num{94}; + unsigned_char_type cht{ch}; + cht=::fast_io::byte_swap(cht); + return static_cast(cht-halfwidth_exclaimation_mark_val)(ch-halfwidth_exclaimation_mark_val) +inline constexpr bool is_c_fullwidth(char_type ch) noexcept +{ + using unsigned_char_type = std::make_unsigned_t; + if constexpr(sizeof(char_type)&&sizeof(char_type)==sizeof(char32_t)) + { + return is_c_fullwidth(static_cast(ch)); + } + else if constexpr(std::signed_integral) + { + return is_c_fullwidth(static_cast(ch)); + } + else if constexpr(::std::same_as&&::fast_io::details::wide_is_none_utf_endian) + { + constexpr unsigned_char_type halfwidth_exclaimation_mark_val{0xFF01}; + constexpr unsigned_char_type num{94}; + unsigned_char_type cht{ch}; + cht=::fast_io::byte_swap(cht); + return static_cast(cht-halfwidth_exclaimation_mark_val)(ch-fullwidth_exclaimation_mark_val) +inline constexpr char_type to_c_halfwidth(char_type ch) noexcept +{ + using unsigned_char_type = std::make_unsigned_t; + if constexpr(sizeof(char_type)&&sizeof(char_type)==sizeof(char32_t)) + { + return static_cast(to_c_halfwidth(static_cast(ch))); + } + else if constexpr(std::signed_integral) + { + return static_cast(to_c_halfwidth(static_cast(ch))); + } + else if constexpr(::std::same_as&&::fast_io::details::wide_is_none_utf_endian) + { + constexpr unsigned_char_type fullwidth_exclaimation_mark_val{0xFF01}; + constexpr unsigned_char_type num{94}; + constexpr unsigned_char_type halfwidth_exclaimation_mark_val{u8'!'}; + unsigned_char_type cht{ch}; + cht=::fast_io::byte_swap(cht); + unsigned_char_type const umav{static_cast(cht-fullwidth_exclaimation_mark_val)}; + if(umav(umav+halfwidth_exclaimation_mark_val); + } + return cht; + } + else + { + constexpr unsigned_char_type fullwidth_exclaimation_mark_val{0xFF01}; + constexpr unsigned_char_type num{94}; + constexpr unsigned_char_type halfwidth_exclaimation_mark_val{u8'!'}; + unsigned_char_type const umav{static_cast(ch-fullwidth_exclaimation_mark_val)}; + if(umav(umav+halfwidth_exclaimation_mark_val); + } + return ch; + } +} + +} + +namespace fast_io +{ +namespace details +{ +template +inline constexpr char_type const* find_lf_simd_impl(char_type const*,char_type const*) noexcept; + +template +requires (::std::integral<::std::iter_value_t>) +inline constexpr Iter find_space_impl(Iter,Iter); +} + +template<::std::forward_iterator Iter> +requires (::std::integral<::std::iter_value_t>) +inline constexpr Iter find_lf(Iter first, Iter last) +{ + using char_type = ::std::iter_value_t; + if constexpr(::std::contiguous_iterator) + { + return ::fast_io::details::find_lf_simd_impl(::std::to_address(first),::std::to_address(last))-::std::to_address(first)+first; + } + else + { + return ::fast_io::freestanding::find(first,last,::fast_io::char_literal_v); + } +} + +template<::std::forward_iterator Iter> +requires (::std::integral<::std::iter_value_t>) +inline constexpr Iter find_none_c_space(Iter begin,Iter end) +{ + return ::fast_io::details::find_space_impl(begin,end); +} + +template<::std::forward_iterator Iter> +requires (::std::integral<::std::iter_value_t>) +inline constexpr Iter find_c_space(Iter begin,Iter end) +{ + return ::fast_io::details::find_space_impl(begin,end); +} + +template<::std::forward_iterator Iter> +requires (::std::integral<::std::iter_value_t>) +inline constexpr Iter find_none_html_whitespace(Iter begin,Iter end) +{ + return ::fast_io::details::find_space_impl(begin,end); +} + +template<::std::forward_iterator Iter> +requires (::std::integral<::std::iter_value_t>) +inline constexpr Iter find_html_whitespace(Iter begin,Iter end) +{ + return ::fast_io::details::find_space_impl(begin,end); +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/codecvt/code_cvt.h b/src/fast_io/include/fast_io_core_impl/codecvt/code_cvt.h new file mode 100644 index 0000000..07092d6 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/codecvt/code_cvt.h @@ -0,0 +1,54 @@ +#pragma once + +namespace fast_io +{ + +template(), + encoding_scheme dst_scheme=encoding_scheme::execution_charset> +struct basic_code_converter +{ + using char_type=src_char_type; + inline static constexpr auto from_scheme = src_scheme; + inline static constexpr auto to_scheme = dst_scheme; + basic_mb_state state; +}; + +using code_converter=basic_code_converter; +using wcode_converter=basic_code_converter; +using u8code_converter=basic_code_converter; +using u16code_converter=basic_code_converter; +using u32code_converter=basic_code_converter; + +template +inline constexpr std::size_t deco_reserve_size(io_reserve_type_t>, +basic_code_converter&,std::size_t from_size) noexcept +{ + return details::cal_decorated_reserve_size(from_size); +} + +template +inline constexpr to_iter deco_reserve_define(io_reserve_type_t<::std::iter_value_t, +basic_code_converter<::std::iter_value_t,from_scheme,to_scheme>>, +basic_code_converter<::std::iter_value_t,from_scheme,to_scheme>& conv,from_iter src_first,from_iter src_last,to_iter dst) noexcept +{ + if constexpr(std::is_pointer_v&&std::is_pointer_v) + return details::codecvt::general_code_cvt(conv.state,src_first,src_last,dst); + else if constexpr(std::is_pointer_v) + return details::codecvt::general_code_cvt(conv.state, + ::std::to_address(src_first), + ::std::to_address(src_last), + dst); + else + { + return dst+(details::codecvt::general_code_cvt(conv.state, + ::std::to_address(src_first), + ::std::to_address(src_last), + ::std::to_address(dst))-::std::to_address(dst)); + } +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/codecvt/gb18030.h b/src/fast_io/include/fast_io_core_impl/codecvt/gb18030.h new file mode 100644 index 0000000..7494b95 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/codecvt/gb18030.h @@ -0,0 +1,46 @@ +#pragma once + +namespace fast_io +{ + +namespace details::codecvt::gb18030 +{ + +template +requires (sizeof(T)==1) +inline constexpr std::size_t get_gb18030_invalid_code_units(T* p_dst) noexcept; + +template +requires (sizeof(T)==1) +inline constexpr std::size_t lookup_uni_to_gb18030(char32_t cdpt, T* p_dst) noexcept; + +template +requires (sizeof(T)==1) +inline constexpr std::size_t get_gb18030_code_units_unhappy(char32_t u32, T* p_dst) noexcept; + +template +requires (sizeof(T)==1) +inline constexpr std::size_t get_gb18030_code_units(char32_t cdpt, T* p_dst) noexcept; + +template +requires (sizeof(T)==1) +struct gb18030_advance_unchecked_result +{ + char32_t cdpt; + char8_t adv; +}; + +inline constexpr char32_t lookup_gb18030_to_uni4_func(char32_t index) noexcept; + +inline constexpr char32_t utf32cp_by_gb18030_index(char32_t index) noexcept; + +template +requires (sizeof(T)==1) +inline constexpr gb18030_advance_unchecked_result gb18030_advance_unchecked(T const* src) noexcept; + +template +requires (sizeof(T)==1) +inline constexpr gb18030_advance_unchecked_result gb18030_advance(T const* src,std::size_t sz) noexcept; +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/codecvt/general.h b/src/fast_io/include/fast_io_core_impl/codecvt/general.h new file mode 100644 index 0000000..205f8b2 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/codecvt/general.h @@ -0,0 +1,569 @@ +#pragma once + +namespace fast_io +{ + +namespace details::codecvt +{ +template +inline constexpr auto general_advance(T* src_first,std::size_t sz) noexcept +{ + if constexpr(encoding_scheme::utf_ebcdic==encoding) + return utf_ebcdic_advance(src_first,sz); + else + return gb18030::gb18030_advance(src_first,sz); +} + +template +inline constexpr std::size_t get_general_invalid_code_units(T* dst) noexcept +{ + if constexpr(encoding==encoding_scheme::utf_ebcdic) + return get_utf_ebcdic_invalid_code_units(dst); + else if constexpr(encoding==encoding_scheme::gb18030) + return gb18030::get_gb18030_invalid_code_units(dst); + else + { + if constexpr(sizeof(T)>=2) + { + if constexpr(encoding_is_utf(encoding)&&!is_native_scheme(encoding)) + { + constexpr T val{byte_swap(static_cast(0xFFFD))}; + *dst=val; + } + else + *dst=static_cast(0xFFFD); + return 1; + } + else + return get_utf8_invalid_code_units(dst); + } +} + +template +inline constexpr encoding_scheme get_execution_charset_encoding_scheme(encoding_scheme scheme) noexcept +{ + if(scheme!=encoding_scheme::execution_charset) + return scheme; + return execution_charset_encoding_scheme(); +} + +template< +encoding_scheme src_encoding=encoding_scheme::execution_charset, +encoding_scheme encoding=encoding_scheme::execution_charset, +std::integral src_char_type,std::integral dest_char_type> +requires (sizeof(src_char_type)<=4 &&sizeof(dest_char_type)<=4) +inline constexpr code_cvt_result general_code_cvt(src_char_type const* src_first,src_char_type const* src_last,dest_char_type* __restrict dst) noexcept +{ + if constexpr(src_encoding==encoding_scheme::execution_charset) + { + return general_code_cvt(src_encoding), + encoding>(src_first,src_last,dst); + } + else if constexpr(encoding==encoding_scheme::execution_charset) + { + return general_code_cvt(encoding)>(src_first,src_last,dst); + } + else if constexpr(sizeof(src_char_type)==sizeof(dest_char_type)&&src_encoding==encoding) + { + std::size_t diff{static_cast(src_last-src_first)}; + non_overlapped_copy_n(src_first,diff,dst); + return {src_last,dst+diff}; + } + else if constexpr(sizeof(src_char_type)==sizeof(dest_char_type)&& + ((src_encoding==encoding_scheme::utf_le&&encoding==encoding_scheme::utf_be)|| + (src_encoding==encoding_scheme::utf_be&&encoding==encoding_scheme::utf_le))) + { + if constexpr(sizeof(src_char_type)==1) + { + return general_code_cvt(src_first,src_last,dst); + } + else + { + for(;src_first!=src_last;++src_first) + *dst=byte_swap(*src_first); + return {src_first,dst}; + } + } + else if constexpr(sizeof(src_char_type)==4) + { + static_assert(src_encoding==encoding_scheme::utf_be||src_encoding==encoding_scheme::utf_le); + for(;src_first!=src_last;++src_first) + dst+=get_utf_code_units(static_cast(*src_first),dst); + return {src_last,dst}; + } + else if constexpr(sizeof(src_char_type)==2) + { + static_assert(src_encoding==encoding_scheme::utf_be||src_encoding==encoding_scheme::utf_le); +/* +Referenced from +https://stackoverflow.com/questions/23919515/how-to-convert-from-utf-16-to-utf-32-on-linux-with-std-library +*/ + for(;src_first!=src_last;++src_first) + { + char16_t code{static_cast(*src_first)}; + if constexpr(!is_native_scheme(src_encoding)) + code=byte_swap(code); + if(is_utf16_surrogate(code))[[unlikely]] + { + if(is_utf16_high_surrogate(code)) + { + if(src_first+1==src_last) + { + break; + } + char16_t code1{static_cast(*++src_first)}; + if constexpr(!is_native_scheme(src_encoding)) + code1=byte_swap(code1); + if(is_utf16_low_surrogate(code1)) + { + if constexpr(sizeof(dest_char_type)==4) + { + *dst = utf16_surrogate_to_utf32(code,code1); + ++dst; + } + else + dst+=get_utf_code_units(utf16_surrogate_to_utf32(code,code1),dst); + continue; + } + } + if constexpr(sizeof(dest_char_type)==4) + { + if constexpr(is_native_scheme(encoding)) + *dst=static_cast(0xFFFD); + else + *dst=static_cast(0xFDFF0000); + ++dst; + } + else + { + dst+=get_general_invalid_code_units(dst); + } + } + else[[likely]] + { + if constexpr(sizeof(dest_char_type)==4) + { + if constexpr(src_encoding==encoding) + *dst=static_cast(code); + else + *dst=byte_swap(static_cast(code)); + ++dst; + } + else + dst+=get_utf_code_units(code,dst); + } + } + return {src_first,dst}; + } + else + { +#if (defined(_MSC_VER)&&defined(_M_AMD64)&&!defined(__clang__)) || (defined(__SSE__) && 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))) + { + if (!std::is_constant_evaluated()) + { + constexpr std::size_t m128i_size{16}; + while(m128i_size < static_cast(src_last-src_first)) + { + if (static_cast(*src_first) < 0x80) + { + auto [new_src,new_dst]= convert_ascii_with_sse(src_first, dst); + src_first=new_src; + dst=new_dst; + } + else + { + if constexpr(src_encoding==encoding_scheme::gb18030) + { + auto [code,adv] = gb18030::gb18030_advance_unchecked(src_first); + src_first+=adv; + if constexpr(sizeof(dest_char_type)==4) + { + *dst=code; + ++dst; + } + else + dst+=get_utf_code_units(code,dst); + } + else + { + auto [src,code] = advance_with_big_table_unchecked(src_first); + src_first=src; + if constexpr(sizeof(dest_char_type)==4) + { + *dst=code; + ++dst; + } + else + dst+=get_utf_code_units(code,dst); + } + } + } + } + } +#endif + + for(;src_first!=src_last;) + if constexpr(src_encoding==encoding_scheme::utf_ebcdic) + { + auto [code,adv]=general_advance(src_first,src_last-src_first); + if(adv==static_cast(-1)) + break; + src_first+=adv; + if constexpr(sizeof(dest_char_type)==4) + { + *dst=code; + if constexpr(encoding_is_utf(encoding)&&!is_native_scheme(encoding)) + *dst=byte_swap(*dst); + ++dst; + } + else + { + dst+=get_utf_code_units(code,dst); + } + } + else + { + if (static_cast(*src_first) < 0x80) + { + if constexpr(encoding_scheme::utf_ebcdic==encoding) + *dst= static_cast(bm_i8_to_ebcdic[*src_first]); + else + *dst= static_cast(*src_first); + if constexpr(sizeof(dest_char_type)!=1&&encoding_is_utf(encoding)&&!is_native_scheme(encoding)) + *dst=byte_swap(*dst); + ++src_first; + ++dst; + } + else + { + if constexpr(src_encoding!=encoding_scheme::utf) + { + auto [code,adv]=general_advance(src_first,src_last-src_first); + if(adv==static_cast(-1)) + break; + src_first+=adv; + if constexpr(sizeof(dest_char_type)==4) + { + *dst=code; + if constexpr(encoding_is_utf(encoding)&&!is_native_scheme(encoding)) + *dst=byte_swap(*dst); + ++dst; + } + else + { + dst+=get_utf_code_units(code,dst); + } + } + else + { + auto [failed,src,code] = advance_with_big_table(src_first, src_last); + if(failed) + break; + src_first=src; + if constexpr(sizeof(dest_char_type)==4) + { + *dst=code; + if constexpr(encoding_is_utf(encoding)&&!is_native_scheme(encoding)) + *dst=byte_swap(*dst); + ++dst; + } + else + dst+=get_utf_code_units(code,dst); + } + } + } + return {src_first,dst}; + } + +} + +template< +encoding_scheme src_encoding=encoding_scheme::execution_charset, +encoding_scheme encoding=encoding_scheme::execution_charset,typename state_type, +std::integral src_char_type,std::integral dest_char_type> +requires (sizeof(src_char_type)<=4 &&sizeof(dest_char_type)<=4) +inline constexpr dest_char_type* general_code_cvt(state_type& __restrict state,src_char_type const* src_first,src_char_type const* src_last,dest_char_type* __restrict dst) noexcept +{ + if constexpr(src_encoding==encoding_scheme::execution_charset) + { + return general_code_cvt(src_encoding), + encoding>(state,src_first,src_last,dst); + } + else if constexpr(encoding==encoding_scheme::execution_charset) + { + return general_code_cvt(encoding)>(state,src_first,src_last,dst); + } + else if constexpr(sizeof(src_char_type)==4) + { + static_assert(src_encoding==encoding_scheme::utf); + return general_code_cvt(src_first,src_last,dst).dst; + } + else if constexpr(sizeof(src_char_type)==2) + { + static_assert(src_encoding==encoding_scheme::utf); + if(state.state) + { + if(src_first==src_last) + return dst; + char16_t low{state.value}; + if constexpr(!is_native_scheme(src_encoding)) + low=byte_swap(low); + char16_t v{static_cast(*src_first)}; + if constexpr(!is_native_scheme(src_encoding)) + v=byte_swap(v); + if(is_utf16_low_surrogate(v)) + { + if constexpr(sizeof(dest_char_type)==4) + { + *dst = utf16_surrogate_to_utf32(low,v); + if constexpr(!is_native_scheme(encoding)) + *dst = byte_swap(*dst); + ++dst; + } + else + dst+=get_utf_code_units(utf16_surrogate_to_utf32(low,v),dst); + ++src_first; + } + else[[unlikely]] + { + if constexpr(sizeof(dest_char_type)==4) + { + if constexpr(is_native_scheme(encoding)) + *dst=static_cast(0xFFFD); + else + *dst=static_cast(0xFDFF0000); + ++dst; + } + else + dst+=get_general_invalid_code_units(dst); + } + } + auto [new_src,new_dst]=general_code_cvt(src_first,src_last,dst); + if((state.state=(new_src!=src_last))) + state.value=*new_src; + return new_dst; + } + else if constexpr(sizeof(src_char_type)==1) + { + std::size_t const state_size{static_cast(state.size)}; + if(state_size) + { + std::size_t src_diff{static_cast(src_last-src_first)}; + if(src_diff==0) + return dst; + constexpr std::size_t state_bytes{8}; + constexpr std::size_t state_bytesm1{state_bytes-1}; + std::size_t remain_unsolved{state_bytes-state_size}; + char8_t bytes[state_bytes]; + non_overlapped_copy_n(state.bytes,state_bytesm1,bytes); + if(src_diff(total_bytes); + return dst; + } + if constexpr(sizeof(dest_char_type)==4) + { + *dst=code; + if constexpr(!is_native_scheme(encoding)) + *dst=byte_swap(*dst); + ++dst; + } + else + dst+=get_utf_code_units(code,dst); + src_first+=static_cast(bytes_src-bytes-state_size); + } + else + { + auto [code,adv]=general_advance(bytes,total_bytes); + if(adv==static_cast(-1)) + { + non_overlapped_copy_n(bytes,state_bytesm1,state.bytes); + state.size=static_cast(total_bytes); + return dst; + } + if constexpr(sizeof(dest_char_type)==4) + { + *dst=code; + if constexpr(!is_native_scheme(encoding)) + *dst=byte_swap(*dst); + ++dst; + } + else + dst+=get_utf_code_units(code,dst); + src_first+=static_cast(static_cast(adv)-state_size); + } + } + auto [new_src,new_dst]=general_code_cvt(src_first,src_last,dst); + std::size_t diff{static_cast(src_last-new_src)}; + state.size=static_cast(diff); + non_overlapped_copy_n(new_src,diff,state.bytes); + return new_dst; + } + else + return dst; +} + +template< +encoding_scheme src_encoding=encoding_scheme::execution_charset, +encoding_scheme encoding=encoding_scheme::execution_charset, +std::integral src_char_type,std::integral dest_char_type> +requires (sizeof(src_char_type)<=4 &&sizeof(dest_char_type)<=4) +inline constexpr dest_char_type* general_code_cvt_full(src_char_type const* src_first,src_char_type const* src_last,dest_char_type* __restrict dst) noexcept +{ + if constexpr(src_encoding==encoding_scheme::execution_charset) + { + constexpr auto src_scheme = get_execution_charset_encoding_scheme(src_encoding); + constexpr auto dst_scheme = get_execution_charset_encoding_scheme(encoding); + return general_code_cvt_full(src_first,src_last,dst); + } + else + { + auto [src,new_dst]=general_code_cvt(src_first,src_last,dst); + if(src!=src_last) + { + if constexpr(sizeof(dest_char_type)==4) + { + if constexpr(is_native_scheme(encoding)) + *new_dst=static_cast(0xFFFD); + else + *new_dst=static_cast(0xFDFF0000); + ++new_dst; + } + else + new_dst+=get_general_invalid_code_units(dst); + } + return new_dst; + } +} + +template +concept type_has_value_type = requires(T) +{ + typename T::value_type; +}; + +template +inline constexpr bool print_alias_test_codecvt_impl() noexcept +{ + if constexpr(alias_printable) + { + using alias_type = decltype(print_alias_define(io_alias,*static_cast(static_cast(nullptr)))); + if constexpr(type_has_value_type) + { + using value_type = typename alias_type::value_type; + return std::same_as>; + } + else + { + return false; + } + } + else + { + return false; + } +} + +} + +namespace manipulators +{ + +template< +encoding_scheme src_scheme, +encoding_scheme dst_scheme, +std::integral char_type> +struct code_cvt_t +{ + using manip_tag = manip_tag_t; + basic_io_scatter_t reference; +}; + +template< +encoding_scheme src_scheme=encoding_scheme::execution_charset, +encoding_scheme dst_scheme=encoding_scheme::execution_charset, +typename T> +requires (::fast_io::details::codecvt::print_alias_test_codecvt_impl()) +constexpr auto code_cvt(T const& t) noexcept +{ + using value_type = typename decltype(print_alias_define(io_alias,t))::value_type; + return code_cvt_t{print_alias_define(io_alias,t)}; +} + +template< +encoding_scheme src_scheme=encoding_scheme::execution_charset, +encoding_scheme dst_scheme=encoding_scheme::execution_charset, +std::integral char_type> +constexpr auto code_cvt(basic_io_scatter_t t) noexcept +{ + return code_cvt_t{t}; +} + +template< +encoding_scheme src_scheme=encoding_scheme::execution_charset, +encoding_scheme dst_scheme=encoding_scheme::execution_charset, +std::integral char_type,std::size_t N> +constexpr auto code_cvt(small_scatter_t t) noexcept +{ + return code_cvt_t{{t.base,t.len}}; +} + +template< +encoding_scheme src_scheme=encoding_scheme::execution_charset, +encoding_scheme dst_scheme=encoding_scheme::execution_charset, +::std::integral char_type> +constexpr auto code_cvt_os_c_str(char_type const* cstr) noexcept +{ + return ::fast_io::manipulators::code_cvt(::fast_io::manipulators::os_c_str(cstr)); +} + +template< +encoding_scheme src_scheme=encoding_scheme::execution_charset, +encoding_scheme dst_scheme=encoding_scheme::execution_charset, +::std::integral char_type> +constexpr auto code_cvt_os_c_str(char_type const* cstr,::std::size_t n) noexcept +{ + return ::fast_io::manipulators::code_cvt(::fast_io::mnp::os_c_str(cstr,n)); +} + +template< +encoding_scheme src_scheme=encoding_scheme::execution_charset, +encoding_scheme dst_scheme=encoding_scheme::execution_charset, +std::integral src_char_type, +std::integral dst_char_type> +inline constexpr std::size_t print_reserve_size( +io_reserve_type_t>, +code_cvt_t v) noexcept +{ + return details::cal_full_reserve_size(v.reference.len); +} + +template< +encoding_scheme src_scheme=encoding_scheme::execution_charset, +encoding_scheme dst_scheme=encoding_scheme::execution_charset, +std::integral src_char_type, +::std::integral char_type> +inline constexpr char_type* print_reserve_define( +io_reserve_type_t>, +char_type* iter, +code_cvt_t v) noexcept +{ + return details::codecvt::general_code_cvt_full(v.reference.base,v.reference.base+v.reference.len,iter); +} + +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/codecvt/impl.h b/src/fast_io/include/fast_io_core_impl/codecvt/impl.h new file mode 100644 index 0000000..0249c6a --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/codecvt/impl.h @@ -0,0 +1,27 @@ +#pragma once + +#include"gb18030.h" +#include"utf_ebcdic.h" +#include"utf_util_table.h" +#include"utf.h" +#include"general.h" +#include"code_cvt.h" + + +namespace fast_io +{ + +template +inline constexpr auto status_io_print_forward(io_alias_type_t,cross_code_cvt_t const& ccvt) noexcept +{ + if constexpr(std::same_as) + { + return ccvt.scatter; + } + else + { + return ::fast_io::mnp::code_cvt_t{ccvt.scatter}; + } +} + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_core_impl/codecvt/utf.h b/src/fast_io/include/fast_io_core_impl/codecvt/utf.h new file mode 100644 index 0000000..a55d389 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/codecvt/utf.h @@ -0,0 +1,632 @@ +#pragma once + +namespace fast_io +{ + +struct u8utf_mb_state +{ + char8_t bytes[7]; + char8_t size{}; + explicit inline constexpr operator bool() const noexcept + { + return static_cast(size); + } +}; + +struct u16utf_mb_state +{ + char16_t value; + bool state{}; + explicit inline constexpr operator bool() const noexcept + { + return state; + } +}; + +struct u32utf_mb_state +{ + explicit inline constexpr operator bool() const noexcept + { + return false; + } +}; + + +template +requires (sizeof(char_type)<=4) +using basic_utf_mb_state = std::conditional_t>; +using utf_mb_state = basic_utf_mb_state; +using wutf_mb_state = basic_utf_mb_state; + +using gb18030_mb_state = utf_mb_state; +using ebcdic_mb_state = utf_mb_state; + +using execution_charset_mb_state = utf_mb_state; +using wexecution_charset_mb_state = wutf_mb_state; + +enum class encoding_scheme +{ +execution_charset, +utf_le, +utf_be, +gb18030, +utf_ebcdic, +utf=std::endian::big==std::endian::native?utf_be:(std::endian::little==std::endian::native?utf_le:5) +}; +/* +CppCon 2018: Bob Steagall “Fast Conversion From UTF-8 with C++, DFAs, and SSE Intrinsics” + +https://www.youtube.com/watch?v=5FQ87-Ecb-A +https://github.com/BobSteagall/utf_utils/blob/master/src/utf_utils.cpp +*/ + +namespace details +{ + +template +requires ((dest_char_type_size<=4)&&(src_char_type_size<=4)) +inline constexpr std::size_t cal_full_reserve_size(std::size_t internal_size) noexcept +{ + constexpr std::size_t external_max{std::numeric_limits::max()/dest_char_type_size}; + constexpr std::size_t internal_max{std::numeric_limits::max()/src_char_type_size}; + if constexpr(src_char_type_size==4) + { + if constexpr(dest_char_type_size==4) + { + constexpr std::size_t imax{external_max}; + if(internal_size>=imax) + fast_terminate(); + return internal_size; + } + else if constexpr(dest_char_type_size==2) + { + constexpr std::size_t imax{external_max/2}; + if(internal_size>=imax) + fast_terminate(); + return internal_size*2; + } + else + { + constexpr std::size_t imax{external_max/8}; + if(internal_size>=imax) + fast_terminate(); + return internal_size*8; + } + } + else if constexpr(src_char_type_size==2) + { + if constexpr(dest_char_type_size==4) + { + constexpr std::size_t imax{external_max}; + if(internal_size>=imax) + fast_terminate(); + return internal_size; + } + else if constexpr(dest_char_type_size==2) + { + constexpr std::size_t imax{external_max/2}; + if(internal_size>=imax) + fast_terminate(); + return internal_size*2; + } + else + { + constexpr std::size_t imax{external_max/8}; + if(internal_size>=imax) + fast_terminate(); + return internal_size*8; + } + } + else + { + if constexpr(dest_char_type_size==4) + { + constexpr std::size_t imax{external_max}; + if(internal_size>=imax) + fast_terminate(); + return internal_size; + } + else if constexpr(dest_char_type_size==2) + { + constexpr std::size_t imax{internal_max/2}; + if(internal_size>=imax) + fast_terminate(); + return 2*internal_size; + } + else + { + constexpr std::size_t imax{internal_max/8}; + if(internal_size>=imax) + fast_terminate(); + return 8*internal_size; + } + } +} + +template +requires ((dest_char_type_size<=4)&&(src_char_type_size<=4)) +inline constexpr std::size_t cal_decorated_reserve_size(std::size_t internal_size) noexcept +{ + constexpr std::size_t external_max{std::numeric_limits::max()/dest_char_type_size}; + constexpr std::size_t internal_max{std::numeric_limits::max()/src_char_type_size}; + if constexpr(src_char_type_size==4) + { + if constexpr(dest_char_type_size==4) + { + constexpr std::size_t imax{external_max}; + if(internal_size>=imax) + fast_terminate(); + return internal_size; + } + else if constexpr(dest_char_type_size==2) + { + constexpr std::size_t imax{external_max/2}; + if(internal_size>=imax) + fast_terminate(); + return internal_size*2; + } + else + { + constexpr std::size_t imax{external_max/8}; + if(internal_size>=imax) + fast_terminate(); + return internal_size*8; + } + } + else if constexpr(src_char_type_size==2) + { + if constexpr(dest_char_type_size==4) + { + constexpr std::size_t imax{external_max-1}; + if(internal_size>=imax) + fast_terminate(); + return internal_size+1; + } + else if constexpr(dest_char_type_size==2) + { + constexpr std::size_t imax{external_max/2-1}; + if(internal_size>=imax) + fast_terminate(); + return internal_size*2+2; + } + else + { + constexpr std::size_t imax{external_max/8-1}; + if(internal_size>=imax) + fast_terminate(); + return internal_size*8+8; + } + } + else + { + if constexpr(dest_char_type_size==4) + { + constexpr std::size_t imax{external_max-7}; + if(internal_size>=imax) + fast_terminate(); + return internal_size+7; + } + else if constexpr(dest_char_type_size==2) + { + constexpr std::size_t imax{internal_max/2-7}; + if(internal_size>=imax) + fast_terminate(); + return 2*internal_size+14; + } + else + { + constexpr std::size_t imax{internal_max/8-7}; + if(internal_size>=imax) + fast_terminate(); + return 8*internal_size+56; + } + } +} +#if defined(__GNUC_EXECUTION_CHARSET_NAME) || defined(__GNUC_WIDE_EXECUTION_CHARSET_NAME) + +template +inline constexpr bool execution_charset_is(char const (&str)[N1],char8_t const (&encoding)[N2]) noexcept +{ + if constexpr(N1!=N2) + { + return false; + } + else + { + for(std::size_t i{};i!=N1;++i) + { + char8_t ch{::fast_io::char_category::to_c_upper(static_cast(str[i]))}; + char8_t ch1{::fast_io::char_category::to_c_upper(static_cast(encoding[i]))}; + if(ch!=ch1) + { + return false; + } + } + return true; + } +} + +#endif +} + +template +inline constexpr encoding_scheme execution_charset_encoding_scheme() noexcept +{ + using char_type_no_cvref_t = std::remove_cvref_t; + if constexpr(::fast_io::details::is_ebcdic) + return encoding_scheme::utf_ebcdic; + else + { + if constexpr(std::same_as) + { +#if defined(_MSVC_EXECUTION_CHARACTER_SET) + if constexpr(_MSVC_EXECUTION_CHARACTER_SET == 936 || _MSVC_EXECUTION_CHARACTER_SET == 54936) + { + return encoding_scheme::gb18030; + } + else + { + return encoding_scheme::utf; + } +#elif defined(__GNUC_EXECUTION_CHARSET_NAME) + if constexpr(::fast_io::details::execution_charset_is(__GNUC_EXECUTION_CHARSET_NAME,u8"GB18030") + || ::fast_io::details::execution_charset_is(__GNUC_EXECUTION_CHARSET_NAME,u8"GBK")) + { + return encoding_scheme::gb18030; + } + else + { + return encoding_scheme::utf; + } +#else + return encoding_scheme::utf; +#endif + } + else if constexpr(std::same_as) + { +#if defined(__GNUC_WIDE_EXECUTION_CHARSET_NAME) + if constexpr(sizeof(wchar_t)==1&& + (::fast_io::details::execution_charset_is(__GNUC_WIDE_EXECUTION_CHARSET_NAME,u8"GB18030") + || ::fast_io::details::execution_charset_is(__GNUC_WIDE_EXECUTION_CHARSET_NAME,u8"GBK"))) + { + return encoding_scheme::gb18030; + } + else + { + if constexpr(::fast_io::details::wide_is_none_utf_endian) + { + if constexpr(encoding_scheme::utf==encoding_scheme::utf_le) + { + return encoding_scheme::utf_be; + } + else + { + return encoding_scheme::utf_le; + } + } + return encoding_scheme::utf; + } +#else + return encoding_scheme::utf; +#endif + } + else + { + return encoding_scheme::utf; + } + } +} + +template()> +using basic_mb_state=basic_utf_mb_state; + +template +struct code_cvt_result +{ + src_char_type const* src; + dest_char_type* dst; +}; + + +namespace details::codecvt +{ + +inline constexpr bool encoding_is_utf(encoding_scheme scheme) noexcept +{ + return scheme==encoding_scheme::utf||scheme==encoding_scheme::utf_le||scheme==encoding_scheme::utf_be; +} + +inline constexpr bool is_native_scheme(encoding_scheme scheme) noexcept +{ + return scheme==encoding_scheme::utf; +} + +template +requires (sizeof(T)==1) +inline constexpr std::size_t get_utf8_invalid_code_units(T* dst) noexcept +{ + *dst = static_cast(0xEF); + dst[1] = static_cast(0xBF); + dst[2] = static_cast(0xBD); + return 3; +} + +template +requires (sizeof(T)<=4) +inline constexpr std::size_t get_utf_code_units(char32_t cdpt,T* dst) noexcept +{ + if constexpr(scheme==encoding_scheme::utf_ebcdic) + { + return get_utf_ebcdic_code_units(cdpt,dst); + } + else if constexpr(scheme==encoding_scheme::gb18030) + { + return gb18030::get_gb18030_code_units(cdpt,dst); + } + else + { + if constexpr(sizeof(T)==sizeof(char32_t)) + { + if constexpr(is_native_scheme(scheme)) + *dst=static_cast(cdpt); + else + *dst=byte_swap(static_cast(cdpt)); + return 1; + } + else if constexpr(sizeof(T)==sizeof(char16_t)) + { + if (cdpt < 0x10000) + { + if constexpr(is_native_scheme(scheme)) + *dst = static_cast(cdpt); + else + *dst = byte_swap(static_cast(cdpt)); + return 1; + } + else + { + if constexpr(is_native_scheme(scheme)) + { + *dst = static_cast(0xD7C0 + (cdpt >> 10)); + dst[1] = static_cast(0xDC00 + (cdpt & 0x3FF)); + } + else + { + *dst = byte_swap(static_cast(0xD7C0 + (cdpt >> 10))); + dst[1] = byte_swap(static_cast(0xDC00 + (cdpt & 0x3FF))); + } + return 2; + } + } + else + { + if (cdpt <= 0x7F)[[likely]] + { + *dst = static_cast(cdpt); + return 1; + } + else if (cdpt <= 0x7FF) + { + *dst = static_cast(0xC0 | ((cdpt >> 6) & 0x1F)); + dst[1] = static_cast(0x80 | (cdpt & 0x3F)); + return 2; + } + else if (cdpt <= 0xFFFF) + { + *dst = static_cast(0xE0 | ((cdpt >> 12) & 0x0F)); + dst[1] = static_cast(0x80 | ((cdpt >> 6) & 0x3F)); + dst[2] = static_cast(0x80 | (cdpt & 0x3F)); + return 3; + } + else if (cdpt <= 0x10FFFF) + { + *dst = static_cast(0xF0 | ((cdpt >> 18) & 0x07)); + dst[1] = static_cast(0x80 | ((cdpt >> 12) & 0x3F)); + dst[2] = static_cast(0x80 | ((cdpt >> 6) & 0x3F)); + dst[3] = static_cast(0x80 | (cdpt & 0x3F)); + return 4; + } + else [[unlikely]] + return get_utf8_invalid_code_units(dst); + } + } +} +inline constexpr bool is_utf16_surrogate(char16_t uc) noexcept { return (uc - 0xd800u) < 2048u; } +inline constexpr bool is_utf16_high_surrogate(char16_t uc) noexcept { return (uc & 0xfffffc00) == 0xd800; } +inline constexpr bool is_utf16_low_surrogate(char16_t uc) noexcept { return (uc & 0xfffffc00) == 0xdc00; } + +inline constexpr char32_t utf16_surrogate_to_utf32(char16_t high, char16_t low) noexcept +{ + return static_cast((static_cast(high) << 10u) + low - 0x35fdc00u); +} + +#if (defined(_MSC_VER)&&defined(_M_AMD64)&&!defined(__clang__)) || (defined(__SSE__) && defined(__x86_64__)) +template +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 +{ + std::uint_least32_t mask; +#if (defined(__GNUC__) || defined(__clang__)) && !defined(__INTEL_COMPILER) + using namespace fast_io::intrinsics; + constexpr std::size_t m128i_size{16}; + if constexpr(sizeof(U)==1) + { + x86_64_v16qi chunk; + __builtin_memcpy(__builtin_addressof(chunk),pSrc,m128i_size); + mask = static_cast(__builtin_ia32_pmovmskb128(chunk)); + __builtin_memcpy(pDst,__builtin_addressof(chunk),m128i_size); + } + else if constexpr(sizeof(U)==2) + { + x86_64_v16qi const zero{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + x86_64_v16qi chunk; + __builtin_memcpy(__builtin_addressof(chunk),pSrc,m128i_size); + mask = static_cast(__builtin_ia32_pmovmskb128(chunk)); +#if __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); + half = __builtin_shufflevector(chunk, zero, 8, 16+8, 9, 16+9, 10, 16+10, 11, 16+11, 12, 16+12, 13, 16+13, 14, 16+14, 15, 16+15); +#else + x86_64_v16qi half{__builtin_ia32_punpcklbw128(chunk, zero)}; + __builtin_memcpy(pDst,__builtin_addressof(half),m128i_size); + half = __builtin_ia32_punpckhbw128(chunk, zero); +#endif + __builtin_memcpy(pDst+8,__builtin_addressof(half),m128i_size); + } + else if constexpr(sizeof(U)==4) + { + x86_64_v16qi const zero{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + x86_64_v16qi chunk; + __builtin_memcpy(__builtin_addressof(chunk),pSrc,m128i_size); + mask = static_cast(__builtin_ia32_pmovmskb128(chunk)); +#if __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; + __builtin_memcpy(__builtin_addressof(half),__builtin_addressof(half_result),m128i_size); + x86_64_v8hi const zero8{0, 0, 0, 0, 0, 0, 0, 0}; + x86_64_v8hi qrtr{__builtin_shufflevector(half, zero8, 0, 8+0, 1, 8+1, 2, 8+2, 3, 8+3)}; + __builtin_memcpy(pDst,__builtin_addressof(qrtr),m128i_size); + qrtr = __builtin_shufflevector(half, zero8, 4, 8+4, 5, 8+5, 6, 8+6, 7, 8+7); + __builtin_memcpy(pDst+4,__builtin_addressof(qrtr),m128i_size); + half_result = __builtin_shufflevector(chunk, zero, 8, 16+8, 9, 16+9, 10, 16+10, 11, 16+11, 12, 16+12, 13, 16+13, 14, 16+14, 15, 16+15); + __builtin_memcpy(__builtin_addressof(half),__builtin_addressof(half_result),m128i_size); + qrtr=__builtin_shufflevector(half, zero8, 0, 8+0, 1, 8+1, 2, 8+2, 3, 8+3); + __builtin_memcpy(pDst+8,__builtin_addressof(qrtr),m128i_size); + qrtr = __builtin_shufflevector(half, zero8, 4, 8+4, 5, 8+5, 6, 8+6, 7, 8+7); +#else + x86_64_v16qi half_result{__builtin_ia32_punpcklbw128(chunk, zero)}; + x86_64_v8hi half; + __builtin_memcpy(__builtin_addressof(half),__builtin_addressof(half_result),m128i_size); + x86_64_v8hi const zero8{0, 0, 0, 0, 0, 0, 0, 0}; + x86_64_v8hi qrtr{__builtin_ia32_punpcklwd128(half, zero8)}; + __builtin_memcpy(pDst,__builtin_addressof(qrtr),m128i_size); + qrtr = __builtin_ia32_punpckhwd128(half, zero8); + __builtin_memcpy(pDst+4,__builtin_addressof(qrtr),m128i_size); + half_result = __builtin_ia32_punpckhbw128(chunk, zero); + __builtin_memcpy(__builtin_addressof(half),__builtin_addressof(half_result),m128i_size); + qrtr=__builtin_ia32_punpcklwd128(half, zero8); + __builtin_memcpy(pDst+8,__builtin_addressof(qrtr),m128i_size); + qrtr = __builtin_ia32_punpckhwd128(half, zero8); +#endif + __builtin_memcpy(pDst+12,__builtin_addressof(qrtr),m128i_size); + } +#else + using x86_64_m128i = __m128i; + if constexpr(sizeof(U)==1) + { + x86_64_m128i chunk; + chunk = _mm_loadu_si128((x86_64_m128i const*) pSrc); //- Load the register with 8-bit bytes + mask = _mm_movemask_epi8(chunk); //- Determine which octets have high bit set + _mm_storeu_si128((x86_64_m128i*) pDst, chunk); //- Write to memory + } + else if constexpr(sizeof(U)==2) + { + x86_64_m128i chunk, half; + chunk = _mm_loadu_si128((x86_64_m128i const*) pSrc); //- Load the register with 8-bit bytes + mask = _mm_movemask_epi8(chunk); //- Determine which octets have high bit set + + half = _mm_unpacklo_epi8(chunk, _mm_set1_epi8(0)); //- Unpack lower half into 16-bit words + _mm_storeu_si128((x86_64_m128i*) pDst, half); //- Write to memory + + half = _mm_unpackhi_epi8(chunk, _mm_set1_epi8(0)); //- Unpack upper half into 16-bit words + _mm_storeu_si128((x86_64_m128i*) (pDst + 8), half); //- Write to memory + + } + else + { + x86_64_m128i chunk, half, qrtr, zero; + zero = _mm_set1_epi8(0); //- Zero out the interleave register + chunk = _mm_loadu_si128((x86_64_m128i const*) pSrc); //- Load a register with 8-bit bytes + mask = _mm_movemask_epi8(chunk); //- Determine which octets have high bit set + + half = _mm_unpacklo_epi8(chunk, zero); //- Unpack bytes 0-7 into 16-bit words + qrtr = _mm_unpacklo_epi16(half, zero); //- Unpack words 0-3 into 32-bit dwords + _mm_storeu_si128((x86_64_m128i*) pDst, qrtr); //- Write to memory + qrtr = _mm_unpackhi_epi16(half, zero); //- Unpack words 4-7 into 32-bit dwords + _mm_storeu_si128((x86_64_m128i*) (pDst + 4), qrtr); //- Write to memory + + half = _mm_unpackhi_epi8(chunk, zero); //- Unpack bytes 8-15 into 16-bit words + qrtr = _mm_unpacklo_epi16(half, zero); //- Unpack words 8-11 into 32-bit dwords + _mm_storeu_si128((x86_64_m128i*) (pDst + 8), qrtr); //- Write to memory + qrtr = _mm_unpackhi_epi16(half, zero); //- Unpack words 12-15 into 32-bit dwords + _mm_storeu_si128((x86_64_m128i*) (pDst + 12), qrtr); //- Write to memory + } +#endif + auto const incr{std::countr_zero(static_cast(mask))}; + return {pSrc+incr,pDst+incr}; +} + +#endif + +template +struct advance_with_big_table_unchecked_result +{ + T const* src; + char32_t cdpt; +}; + +template +requires (sizeof(T)==1) +inline constexpr advance_with_big_table_unchecked_result advance_with_big_table_unchecked(T const* it) noexcept +{ + char8_t const* info{first_unit_info[static_cast(*it)]}; + char32_t cdpt{static_cast(*info)}; //- From it, get the initial code point value + std::int_least32_t curr{info[1]}; //- From it, get the second state + for(++it;12(*it)}; + ++it; //- Cache the current code unit + cdpt = (cdpt << 6) | (unit & 0x3F); //- Adjust code point with continuation bits + curr = transitions[curr + octet_category[unit]]; + //- Look up the next state + } + if(curr==12)[[unlikely]] + cdpt=0xFFFD; + return {it,cdpt}; +} + +template +struct advance_with_big_table_result +{ + bool failed; + T const* src; + char32_t cdpt; +}; + +template +requires (sizeof(T)==1) +inline constexpr advance_with_big_table_result advance_with_big_table(T const* first, T const* last) noexcept +{ + char8_t const* info{first_unit_info[static_cast(*first)]}; + char32_t cdpt{static_cast(*info)}; //- From it, get the initial code point value + std::int_least32_t curr{info[1]}; //- From it, get the second state + auto it{first}; + for(++it;12(*it)}; + ++it; //- Cache the current code unit + cdpt = (cdpt << 6) | (unit & 0x3F); //- Adjust code point with continuation bits + curr = transitions[curr + octet_category[unit]]; + //- Look up the next state + } + else + return {true,nullptr,0}; + } + if(curr==12)[[unlikely]] + cdpt=0xFFFD; + return {false,it,cdpt}; +} + +} + +template +requires (sizeof(T)<=4) +inline constexpr std::size_t get_utf_code_units(char32_t ch,T* ptr) noexcept +{ + return details::codecvt::get_utf_code_units(ch,ptr); +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/codecvt/utf_ebcdic.h b/src/fast_io/include/fast_io_core_impl/codecvt/utf_ebcdic.h new file mode 100644 index 0000000..85fa090 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/codecvt/utf_ebcdic.h @@ -0,0 +1,112 @@ +#pragma once + +namespace fast_io::details +{ +/* +Referenced from UTF-EBCDIC +Unicode Technical Report #16 +UTF-EBCDIC +EBCDIC-Friendly Unicode (or UCS) Transformation Format +1999-06-24 +https://www.unicode.org/reports/tr16/tr16-5.html +*/ +inline constexpr char8_t bm_i8_to_ebcdic[256]{0x0,0x1,0x2,0x3,0x37,0x2D,0x2E,0x2F,0x16,0x5,0x15,0xB,0xC,0xD,0xE,0xF,0x10,0x11,0x12,0x13,0x3C,0x3D,0x32,0x26,0x18,0x19,0x3F,0x27,0x1C,0x1D,0x1E,0x1F,0x40,0x5A,0x7F,0x7B,0x5B,0x6C,0x50,0x7D,0x4D,0x5D,0x5C,0x4E,0x6B,0x60,0x4B,0x61,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0x7A,0x5E,0x4C,0x7E,0x6E,0x6F,0x7C,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xAD,0xE0,0xBD,0x5F,0x6D,0x79,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xC0,0x4F,0xD0,0xA1,0x7,0x20,0x21,0x22,0x23,0x24,0x25,0x6,0x17,0x28,0x29,0x2A,0x2B,0x2C,0x9,0xA,0x1B,0x30,0x31,0x1A,0x33,0x34,0x35,0x36,0x8,0x38,0x39,0x3A,0x3B,0x4,0x14,0x3E,0xFF,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x80,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,0xA0,0xAA,0xAB,0xAC,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBE,0xBF,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,0xE1,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xFA,0xFB,0xFC,0xFD,0xFE}; +inline constexpr char8_t bm_ebcdic_to_i8[256]{0x0,0x1,0x2,0x3,0x9C,0x9,0x86,0x7F,0x97,0x8D,0x8E,0xB,0xC,0xD,0xE,0xF,0x10,0x11,0x12,0x13,0x9D,0xA,0x8,0x87,0x18,0x19,0x92,0x8F,0x1C,0x1D,0x1E,0x1F,0x80,0x81,0x82,0x83,0x84,0x85,0x17,0x1B,0x88,0x89,0x8A,0x8B,0x8C,0x5,0x6,0x7,0x90,0x91,0x16,0x93,0x94,0x95,0x96,0x4,0x98,0x99,0x9A,0x9B,0x14,0x15,0x9E,0x1A,0x20,0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0x2E,0x3C,0x28,0x2B,0x7C,0x26,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0x21,0x24,0x2A,0x29,0x3B,0x5E,0x2D,0x2F,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0x2C,0x25,0x5F,0x3E,0x3F,0xBC,0xBD,0xBE,0xBF,0xC0,0xC1,0xC2,0xC3,0xC4,0x60,0x3A,0x23,0x40,0x27,0x3D,0x22,0xC5,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,0x70,0x71,0x72,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0x7E,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0xD4,0xD5,0xD6,0x5B,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0x5D,0xE6,0xE7,0x7B,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0x7D,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,0x50,0x51,0x52,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0x5C,0xF4,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0xFB,0xFC,0xFD,0xFE,0xFF,0x9F}; +inline constexpr char8_t utfebcdic_shadow_flags[256]{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,9,9,9,9,9,9,9,9,9,9,1,1,1,1,1,1,9,9,9,9,9,9,9,9,9,1,1,1,1,1,1,1,1,9,9,9,9,9,9,9,9,9,1,1,1,1,1,9,9,9,9,2,2,2,2,2,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,2,2,2,1,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,1,3,3,1,1,1,1,1,1,1,1,1,1,3,3,3,3,3,3,1,1,1,1,1,1,1,1,1,1,3,3,4,4,4,4,1,4,1,1,1,1,1,1,1,1,4,4,4,5,5,5,1,1,1,1,1,1,1,1,1,1,5,6,6,7,7,0}; + +template +requires (sizeof(T)==1) +inline constexpr std::size_t get_utf_ebcdic_invalid_code_units(T* dst) noexcept +{ + *dst=0xDD; + dst[1]=0x73; + dst[2]=0x66; + dst[3]=0x73; + return 4; +} + +template +requires (sizeof(T)==1) +inline constexpr std::size_t get_utf_ebcdic_code_units(char32_t code,T* dst) noexcept +{ + if(code<0xA0) + { + *dst=static_cast(bm_i8_to_ebcdic[code]); + return 1; + } + else if(code<0x400) + { + *dst=static_cast(bm_i8_to_ebcdic[static_cast(0b11000000)|(code>>5)]); + dst[1]=static_cast(bm_i8_to_ebcdic[static_cast(0b10100000)|(code&static_cast(0b11111))]); + return 2; + } + else if(code<0x4000) + { + *dst=static_cast(bm_i8_to_ebcdic[static_cast(0b11100000)|(code>>10)]); + dst[1]=static_cast(bm_i8_to_ebcdic[static_cast(0b10100000)|((code>>5)&static_cast(0b11111))]); + dst[2]=static_cast(bm_i8_to_ebcdic[static_cast(0b10100000)|(code&static_cast(0b11111))]); + return 3; + } + else if(code<0x40000) + { + *dst=static_cast(bm_i8_to_ebcdic[static_cast(0b11110000)|(code>>15)]); + dst[1]=static_cast(bm_i8_to_ebcdic[static_cast(0b10100000)|((code>>10)&static_cast(0b11111))]); + dst[2]=static_cast(bm_i8_to_ebcdic[static_cast(0b10100000)|((code>>5)&static_cast(0b11111))]); + dst[3]=static_cast(bm_i8_to_ebcdic[static_cast(0b10100000)|(code&static_cast(0b11111))]); + return 4; + } + else if(code<0x110000) + { + *dst=static_cast(bm_i8_to_ebcdic[static_cast(0b11111000)|(code>>20)]); + dst[1]=static_cast(bm_i8_to_ebcdic[static_cast(0b10100000)|((code>>15)&static_cast(0b11111))]); + dst[2]=static_cast(bm_i8_to_ebcdic[static_cast(0b10100000)|((code>>10)&static_cast(0b11111))]); + dst[3]=static_cast(bm_i8_to_ebcdic[static_cast(0b10100000)|((code>>5)&static_cast(0b11111))]); + dst[4]=static_cast(bm_i8_to_ebcdic[static_cast(0b10100000)|(code&static_cast(0b11111))]); + return 5; + } + return get_utf_ebcdic_invalid_code_units(dst); +} + +struct from_ebcdic_result +{ + char32_t code; + char8_t len; +}; + +template +requires (sizeof(T)==1) +inline constexpr from_ebcdic_result utf_ebcdic_advance(T* src_first,std::size_t sz) noexcept +{ + char8_t src0(static_cast(*src_first)); + char8_t shadow{utfebcdic_shadow_flags[src0]}; + if(shadow<2) + return {static_cast(bm_ebcdic_to_i8[src0]),1}; + if(shadow==9) + return {0xFFFD,1}; + if(sz(-1)}; + char32_t res{}; + for(char8_t i{1};i!=shadow;++i) + { + char8_t code(bm_ebcdic_to_i8[static_cast(src_first[i])]); + if((code>>5)!=0b101)[[unlikely]] + return {0xFFFD,i}; + res=(res<<5)|(code&0b11111); + } + char8_t src0i18{bm_ebcdic_to_i8[src0]}; + switch(shadow) + { + case 2: + return {((static_cast(src0i18&0b11111))<<5)|res,2}; + case 3: + return {((static_cast(src0i18&0b1111))<<10)|res,3}; + case 4: + return {((static_cast(src0i18&0b111))<<15)|res,4}; + case 5: + return {((static_cast(src0i18&0b1))<<20)|res,5}; + default: + return {0xFFFD,shadow}; + }; +} + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_core_impl/codecvt/utf_util_table.h b/src/fast_io/include/fast_io_core_impl/codecvt/utf_util_table.h new file mode 100644 index 0000000..32a5d28 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/codecvt/utf_util_table.h @@ -0,0 +1,10 @@ +#pragma once + + +namespace fast_io::details::codecvt +{ +inline constexpr char8_t first_unit_info[256][2]{{0,0},{1,0},{2,0},{3,0},{4,0},{5,0},{6,0},{7,0},{8,0},{9,0},{10,0},{11,0},{12,0},{13,0},{14,0},{15,0},{16,0},{17,0},{18,0},{19,0},{20,0},{21,0},{22,0},{23,0},{24,0},{25,0},{26,0},{27,0},{28,0},{29,0},{30,0},{31,0},{32,0},{33,0},{34,0},{35,0},{36,0},{37,0},{38,0},{39,0},{40,0},{41,0},{42,0},{43,0},{44,0},{45,0},{46,0},{47,0},{48,0},{49,0},{50,0},{51,0},{52,0},{53,0},{54,0},{55,0},{56,0},{57,0},{58,0},{59,0},{60,0},{61,0},{62,0},{63,0},{64,0},{65,0},{66,0},{67,0},{68,0},{69,0},{70,0},{71,0},{72,0},{73,0},{74,0},{75,0},{76,0},{77,0},{78,0},{79,0},{80,0},{81,0},{82,0},{83,0},{84,0},{85,0},{86,0},{87,0},{88,0},{89,0},{90,0},{91,0},{92,0},{93,0},{94,0},{95,0},{96,0},{97,0},{98,0},{99,0},{100,0},{101,0},{102,0},{103,0},{104,0},{105,0},{106,0},{107,0},{108,0},{109,0},{110,0},{111,0},{112,0},{113,0},{114,0},{115,0},{116,0},{117,0},{118,0},{119,0},{120,0},{121,0},{122,0},{123,0},{124,0},{125,0},{126,0},{127,0},{0,12},{1,12},{2,12},{3,12},{4,12},{5,12},{6,12},{7,12},{8,12},{9,12},{10,12},{11,12},{12,12},{13,12},{14,12},{15,12},{16,12},{17,12},{18,12},{19,12},{20,12},{21,12},{22,12},{23,12},{24,12},{25,12},{26,12},{27,12},{28,12},{29,12},{30,12},{31,12},{32,12},{33,12},{34,12},{35,12},{36,12},{37,12},{38,12},{39,12},{40,12},{41,12},{42,12},{43,12},{44,12},{45,12},{46,12},{47,12},{48,12},{49,12},{50,12},{51,12},{52,12},{53,12},{54,12},{55,12},{56,12},{57,12},{58,12},{59,12},{60,12},{61,12},{62,12},{63,12},{192,12},{193,12},{2,24},{3,24},{4,24},{5,24},{6,24},{7,24},{8,24},{9,24},{10,24},{11,24},{12,24},{13,24},{14,24},{15,24},{16,24},{17,24},{18,24},{19,24},{20,24},{21,24},{22,24},{23,24},{24,24},{25,24},{26,24},{27,24},{28,24},{29,24},{30,24},{31,24},{0,60},{1,36},{2,36},{3,36},{4,36},{5,36},{6,36},{7,36},{8,36},{9,36},{10,36},{11,36},{12,36},{13,72},{14,36},{15,36},{0,84},{1,48},{2,48},{3,48},{4,96},{245,12},{246,12},{247,12},{248,12},{249,12},{250,12},{251,12},{252,12},{253,12},{254,12},{255,12}}; +inline constexpr char8_t octet_category[256]{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,7,7,7,7,7,7,7,7,7,7,7,7,8,7,7,9,10,10,10,11,0,0,0,0,0,0,0,0,0,0,0}; +inline constexpr char8_t transitions[108]{12,0,12,12,12,24,60,36,72,84,48,96,12,12,12,12,12,12,12,12,12,12,12,12,12,12,0,0,0,12,12,12,12,12,12,12,12,12,24,24,24,12,12,12,12,12,12,12,12,12,36,36,36,12,12,12,12,12,12,12,12,12,12,12,24,12,12,12,12,12,12,12,12,12,24,24,12,12,12,12,12,12,12,12,12,12,12,36,36,12,12,12,12,12,12,12,12,12,36,12,12,12,12,12,12,12,12,12}; + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_core_impl/compare.h b/src/fast_io/include/fast_io_core_impl/compare.h new file mode 100644 index 0000000..849d566 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/compare.h @@ -0,0 +1,51 @@ +#pragma once + +namespace fast_io +{ + +template +requires (std::same_as||std::same_as|| + std::same_as) +inline constexpr std::size_t print_reserve_size(io_reserve_type_t) noexcept +{ + return 1; +} + +template<::std::integral char_type,typename T> +requires (std::same_as||std::same_as|| + std::same_as) +inline constexpr char_type* print_reserve_define(io_reserve_type_t, char_type* iter,T t) noexcept +{ + if(t<0) + { + if constexpr(std::same_as) + *iter='<'; + else if constexpr(std::same_as) + *iter=L'<'; + else + *iter=u8'<'; + } + else if(t==0) + { + if constexpr(std::same_as) + *iter='='; + else if constexpr(std::same_as) + *iter=L'='; + else + *iter=u8'='; + } + else + { + if constexpr(std::same_as) + *iter='>'; + else if constexpr(std::same_as) + *iter=L'>'; + else + *iter=u8'>'; + } + ++iter; + return iter; +} + + +} diff --git a/src/fast_io/include/fast_io_core_impl/concat/concat_buffer.h b/src/fast_io/include/fast_io_core_impl/concat/concat_buffer.h new file mode 100644 index 0000000..b0ef26c --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/concat/concat_buffer.h @@ -0,0 +1,102 @@ +#pragma once + +namespace fast_io::details +{ + +template +struct basic_concat_buffer +{ + using char_type = ch_type; + static inline constexpr std::size_t buffer_size{2048u/sizeof(ch_type)}; + char_type *buffer_begin,*buffer_curr,*buffer_end; + char_type stack_buffer[buffer_size]; + constexpr basic_concat_buffer() noexcept: + buffer_begin{stack_buffer}, + buffer_curr{stack_buffer}, + buffer_end{stack_buffer+buffer_size} + {} + basic_concat_buffer(basic_concat_buffer const&)=delete; + basic_concat_buffer& operator=(basic_concat_buffer const&)=delete; +#if __cpp_constexpr_dynamic_alloc >= 201907L + constexpr +#endif + ~basic_concat_buffer() + { + if(buffer_begin!=stack_buffer)[[unlikely]] + { + deallocate_iobuf_space(buffer_begin,static_cast(buffer_end-buffer_begin)); + } + } +}; + +template +inline constexpr char_type* strlike_begin(::fast_io::io_strlike_type_t>,::fast_io::details::basic_concat_buffer& str) noexcept +{ + return str.buffer_begin; +} + +template +inline constexpr char_type* strlike_curr(::fast_io::io_strlike_type_t>,::fast_io::details::basic_concat_buffer& str) noexcept +{ + return str.buffer_curr; +} + +template +inline constexpr char_type* strlike_end(::fast_io::io_strlike_type_t>,::fast_io::details::basic_concat_buffer& str) noexcept +{ + return str.buffer_end; +} + +template +inline constexpr void strlike_set_curr(::fast_io::io_strlike_type_t>,::fast_io::details::basic_concat_buffer& str,char_type* p) noexcept +{ + str.buffer_curr=p; +} + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline constexpr void basic_concat_buffer_strlike_reserve_cold_impl(::fast_io::details::basic_concat_buffer& str,std::size_t n,std::size_t df) noexcept +{ + auto old_buffer_begin_ptr{str.buffer_begin}; + bool onstack{old_buffer_begin_ptr==str.stack_buffer}; + auto newptr{allocate_iobuf_space(n)}; + std::size_t const elements{static_cast(str.buffer_curr-str.buffer_begin)}; + auto newcurr_ptr{non_overlapped_copy_n(old_buffer_begin_ptr,elements,newptr)}; + str.buffer_curr=newcurr_ptr; + if(!onstack) + { + deallocate_iobuf_space(old_buffer_begin_ptr,df); + } + str.buffer_begin=newptr; + str.buffer_end=newptr+n; +} + +template +inline constexpr void basic_concat_buffer_strlike_reserve_impl(::fast_io::details::basic_concat_buffer& str,std::size_t n) noexcept +{ + std::size_t df{static_cast(str.buffer_end-str.buffer_begin)}; + if(df +inline constexpr void strlike_reserve(::fast_io::io_strlike_type_t>,::fast_io::details::basic_concat_buffer& str,std::size_t n) noexcept +{ + basic_concat_buffer_strlike_reserve_impl(str,n); +} + +template +inline constexpr std::size_t strlike_sso_size(::fast_io::io_strlike_type_t>) noexcept +{ + return ::fast_io::details::basic_concat_buffer::buffer_size; +} + +template +inline constexpr io_strlike_reference_wrapper> io_strlike_ref(io_alias_t,::fast_io::details::basic_concat_buffer& str) noexcept +{ + return {__builtin_addressof(str)}; +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/concat/concat_general.h b/src/fast_io/include/fast_io_core_impl/concat/concat_general.h new file mode 100644 index 0000000..785ffc8 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/concat/concat_general.h @@ -0,0 +1,312 @@ +#pragma once + +namespace fast_io::details::decay +{ + +template +inline constexpr char_type* print_reserve_define_chain_impl(char_type* p,T t,Args ...args) +{ + if constexpr(sizeof...(Args)==0) + { + p=print_reserve_define(io_reserve_type>,p,t); + if constexpr(line) + { + *p=char_literal_v; + ++p; + } + return p; + } + else + return print_reserve_define_chain_impl(print_reserve_define(io_reserve_type>,p,t),args...); +} + +template +inline constexpr std::size_t calculate_scatter_dynamic_reserve_size_with_scatter([[maybe_unused]] T t,Args... args) +{ + if constexpr(dynamic_reserve_printable) + { + std::size_t res{print_reserve_size(io_reserve_type,t)}; + if constexpr(sizeof...(Args)==0) + return res; + else + return ::fast_io::details::intrinsics::add_or_overflow_die(res,calculate_scatter_dynamic_reserve_size_with_scatter(args...)); + } + else if constexpr(scatter_printable) + { + std::size_t res{print_scatter_define(io_reserve_type>,t).len}; + if constexpr(sizeof...(Args)==0) + return res; + else + return ::fast_io::details::intrinsics::add_or_overflow_die(res,calculate_scatter_dynamic_reserve_size_with_scatter(args...)); + } + else + { + if constexpr(sizeof...(Args)==0) + return 0; + else + return calculate_scatter_dynamic_reserve_size_with_scatter(args...); + } +} + +template +inline constexpr char_type* print_reserve_define_chain_scatter_impl(char_type* p,T t,Args ...args) +{ + if constexpr(dynamic_reserve_printable||reserve_printable) + p = print_reserve_define(io_reserve_type>,p,t); + else + { + auto sc{print_scatter_define(io_reserve_type>,t)}; + p = non_overlapped_copy_n(sc.base,sc.len,p); + } + if constexpr(sizeof...(Args)==0) + { + if constexpr(line) + { + *p=char_literal_v; + ++p; + } + return p; + } + else + return print_reserve_define_chain_scatter_impl(p,args...); +} + +template +inline constexpr basic_io_scatter_t print_scatter_define_extract_one(T t) +{ + return print_scatter_define(io_reserve_type>,t); +} + +template +inline constexpr T basic_general_concat_decay_impl_precise(T& str,Arg arg) +{ + std::size_t precise_size{print_reserve_precise_size(io_reserve_type,arg)}; + std::size_t precise_size_with_line{precise_size}; + if constexpr(line) + ++precise_size_with_line; + constexpr std::size_t local_cap{strlike_sso_size(io_strlike_type)}; + if(local_cap,str,local_cap); + auto first{strlike_begin(io_strlike_type,str)}; + print_reserve_precise_define(io_reserve_type,first,precise_size,arg); + auto ptr{first+precise_size}; + if constexpr(line) + { + *ptr=char_literal_v; + ++ptr; + } + strlike_set_curr(io_strlike_type,str,ptr); + return str; +} + +template +inline constexpr T basic_general_concat_decay_impl(Args ...args) +{ + if constexpr(sizeof...(Args)==0) + { + if constexpr(line) + { + return strlike_construct_single_character_define(io_strlike_type,char_literal_v); + } + else + { + return {}; + } + } + else if constexpr(((reserve_printable||scatter_printable||dynamic_reserve_printable)&&...)) + { + constexpr std::size_t sz{calculate_scatter_reserve_size()}; + if constexpr(line) + static_assert(sz!=SIZE_MAX,"overflow\n"); + constexpr std::size_t sz_with_line{sz+static_cast(line)}; + if constexpr((reserve_printable&&...)) + { + if constexpr(sso_buffer_strlike) + { + constexpr std::size_t local_cap{strlike_sso_size(io_reserve_type)}; + constexpr bool not_enough_space{(local_cap&&...))) + { + return basic_general_concat_decay_impl_precise(args...); + } + else + { + T str; + if constexpr(not_enough_space) + strlike_reserve(io_strlike_type,str,sz_with_line); + strlike_set_curr(io_strlike_type,str, + print_reserve_define_chain_impl(strlike_begin(io_strlike_type,str),args...)); + return str; + } + } + else + { + T str; + strlike_reserve(io_strlike_type,str,sz_with_line); + strlike_set_curr(io_strlike_type,str, + print_reserve_define_chain_impl(strlike_begin(io_strlike_type,str),args...)); + return str; + } + } + else + { + if constexpr((!line)&&sizeof...(args)==1&&(scatter_printable&&...)) + { + basic_io_scatter_t scatter{print_scatter_define_extract_one(args...)}; + return strlike_construct_define(io_strlike_type(scatter.base,scatter.base+scatter.len)); + } + else + { + std::size_t total_size{::fast_io::details::intrinsics::add_or_overflow_die(sz_with_line,calculate_scatter_dynamic_reserve_size_with_scatter(args...))}; + T str; + strlike_reserve(io_strlike_type,str,total_size); + strlike_set_curr(io_strlike_type,str, + print_reserve_define_chain_scatter_impl(strlike_begin(io_strlike_type,str),args...)); + return str; + } + } + } + else + { + T str; + auto oref{io_strlike_ref(fast_io::io_alias,str)}; + ::fast_io::print_freestanding_decay_no_status(oref,args...); + return str; + } +} + +template +inline constexpr void basic_general_concat_decay_ref_impl_precise(T& str,Arg arg) +{ + std::size_t precise_size{print_reserve_precise_size(io_reserve_type,arg)}; + std::size_t precise_size_with_line{precise_size}; + if constexpr(line) + ++precise_size_with_line; + constexpr std::size_t local_cap{strlike_sso_size(io_strlike_type)}; + if(local_cap,str,precise_size_with_line); + auto first{strlike_begin(io_strlike_type,str)}; + print_reserve_precise_define(io_reserve_type,first,precise_size,arg); + auto ptr{first+precise_size}; + if constexpr(line) + { + *ptr=char_literal_v; + ++ptr; + } + strlike_set_curr(io_strlike_type,str,ptr); +} + +template +inline constexpr void basic_general_concat_decay_ref_impl(T& str,Args ...args) +{ + if constexpr(((reserve_printable||scatter_printable||dynamic_reserve_printable)&&...)) + { + constexpr std::size_t sz{calculate_scatter_reserve_size()}; + if constexpr(line) + static_assert(sz!=SIZE_MAX,"overflow\n"); + constexpr std::size_t sz_with_line{sz+static_cast(line)}; + if constexpr((reserve_printable&&...)) + { + if constexpr(sso_buffer_strlike) + { + constexpr std::size_t local_cap{strlike_sso_size(io_strlike_type)}; + constexpr bool not_enough_space{(local_cap&&...))) + { + basic_general_concat_decay_ref_impl_precise(str,args...); + } + else + { + if constexpr(not_enough_space) + strlike_reserve(io_strlike_type,str,sz_with_line); + strlike_set_curr(io_strlike_type,str, + print_reserve_define_chain_impl(strlike_begin(io_strlike_type,str),args...)); + } + } + else + { + strlike_reserve(io_strlike_type,str,sz_with_line); + strlike_set_curr(io_strlike_type,str, + print_reserve_define_chain_impl(strlike_begin(io_strlike_type,str),args...)); + } + } + else + { + std::size_t total_size{::fast_io::details::intrinsics::add_or_overflow_die(sz_with_line,calculate_scatter_dynamic_reserve_size_with_scatter(args...))}; + strlike_reserve(io_strlike_type,str,total_size); + strlike_set_curr(io_strlike_type,str, + print_reserve_define_chain_scatter_impl(strlike_begin(io_strlike_type,str),args...)); + } + } + else + { + auto oref{io_strlike_ref(fast_io::io_alias,str)}; + ::fast_io::print_freestanding_decay_no_status(oref,args...); + } +} + +template +inline constexpr T basic_general_concat_phase1_decay_impl(Args ...args) +{ + if constexpr(sizeof...(Args)==0) + { + if constexpr(line) + { + if constexpr(single_character_constructible_strlike) + return strlike_construct_single_character_define(io_strlike_type,char_literal_v); + else + { + return strlike_construct_define(io_strlike_type,__builtin_addressof(char_literal_v),__builtin_addressof(char_literal_v)+1); + } + } + else + { + return {}; + } + } + else + { + if constexpr(buffer_strlike) + { + T str; + basic_general_concat_decay_ref_impl(str,args...); + return str; + } + else if constexpr((!line)&&sizeof...(args)==1&&(scatter_printable&&...)) + { + basic_io_scatter_t scatter{print_scatter_define_extract_one(args...)}; + return strlike_construct_define(io_strlike_type,scatter.base,scatter.base+scatter.len); + } + else if constexpr((reserve_printable&&...)) + { + constexpr std::size_t sz{calculate_scatter_reserve_size()}; + if constexpr(line) + static_assert(sz!=SIZE_MAX,"overflow\n"); + constexpr std::size_t sz_with_line{sz+static_cast(line)}; + ch_type buffer[sz_with_line]; + auto p{print_reserve_define_chain_impl(buffer,args...)}; + return strlike_construct_define(io_strlike_type,buffer,p); + } + else + { + basic_concat_buffer buffer; + basic_general_concat_decay_ref_impl(buffer,args...); + return strlike_construct_define(io_strlike_type,buffer.buffer_begin,buffer.buffer_curr); + } + } +} + +} + +namespace fast_io +{ + +template +requires strlike +inline constexpr T basic_general_concat(Args&& ...args) +{ + return ::fast_io::details::decay::basic_general_concat_phase1_decay_impl( + io_print_forward(io_print_alias(args))...); +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/concat/impl.h b/src/fast_io/include/fast_io_core_impl/concat/impl.h new file mode 100644 index 0000000..2719313 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/concat/impl.h @@ -0,0 +1,4 @@ +#pragma once +#include"strlike_reference_wrapper.h" +#include"concat_buffer.h" +#include"concat_general.h" diff --git a/src/fast_io/include/fast_io_core_impl/concat/strlike_reference_wrapper.h b/src/fast_io/include/fast_io_core_impl/concat/strlike_reference_wrapper.h new file mode 100644 index 0000000..009bf9e --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/concat/strlike_reference_wrapper.h @@ -0,0 +1,189 @@ +#pragma once + +namespace fast_io +{ + +template +struct io_strlike_reference_wrapper +{ + using value_type = T; + using native_handle_type = value_type*; + using char_type = ch_type; + using pointer = char_type*; + using const_pointer = char_type const*; + native_handle_type ptr{}; + inline constexpr native_handle_type release() noexcept + { + auto temp{ptr}; + ptr=nullptr; + return temp; + } + inline constexpr native_handle_type native_handle() const noexcept + { + return ptr; + } +}; + +template +[[nodiscard]] inline constexpr io_strlike_reference_wrapper io_value_handle(io_strlike_reference_wrapper bref) noexcept +{ + return bref; +} + +template +requires buffer_strlike +inline constexpr char_type* obuffer_begin(io_strlike_reference_wrapper bref) noexcept +{ + return strlike_begin(io_strlike_type,*bref.ptr); +} + +template +requires buffer_strlike +inline constexpr char_type* obuffer_curr(io_strlike_reference_wrapper bref) noexcept +{ + return strlike_curr(io_strlike_type,*bref.ptr); +} + +template +requires buffer_strlike +inline constexpr char_type* obuffer_end(io_strlike_reference_wrapper bref) noexcept +{ + return strlike_end(io_strlike_type,*bref.ptr); +} + +template +requires buffer_strlike +inline constexpr void obuffer_set_curr(io_strlike_reference_wrapper bref,char_type* i) noexcept +{ + return strlike_set_curr(io_strlike_type,*bref.ptr,i); +} + +namespace details +{ + +template +inline constexpr std::size_t cal_new_cap_io_strlike(std::size_t cap) noexcept +{ + std::size_t new_cap{}; + if(cap==0) + new_cap=1; + else + { + constexpr std::size_t mx_size{SIZE_MAX/size_char_type}; + constexpr std::size_t mx_div2{static_cast(mx_size/2u)}; + if(mx_size==cap)[[unlikely]] + { + fast_terminate(); + } + else if(cap>=mx_div2) + { + new_cap=mx_size; + } + else + { + new_cap=cap; + new_cap<<=1u; + } + } + return new_cap; +} + +} + +template +requires buffer_strlike +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline constexpr void obuffer_overflow(io_strlike_reference_wrapper bref,ch_type ch) +{ + auto& strref{*bref.ptr}; + if constexpr(auxiliary_strlike) + { + strlike_push_back(io_strlike_type,strref,ch); + } + else + { + auto bptr{strlike_begin(io_strlike_type,strref)}; + auto eptr{strlike_end(io_strlike_type,strref)}; + auto cap{static_cast(eptr-bptr)}; + strlike_reserve(io_strlike_type,strref,::fast_io::details::cal_new_cap_io_strlike(cap)); + auto curr_ptr{strlike_curr(io_strlike_type,strref)}; + *curr_ptr=ch; + ++curr_ptr; + strlike_set_curr(io_strlike_type,strref,curr_ptr); + } +} + +namespace details +{ + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline constexpr void write_strike_like_cold(io_strlike_reference_wrapper bref,ch_type const* first,ch_type const* last) +{ + auto& strref{*bref.ptr}; + auto curr{strlike_curr(io_strlike_type,strref)}; + std::size_t const bufferdiff{static_cast(strlike_end(io_strlike_type,strref)-curr)}; + curr=non_overlapped_copy_n(first,bufferdiff,curr); + first+=bufferdiff; + strlike_set_curr(io_strlike_type,strref,curr); + auto bptr{strlike_begin(io_strlike_type,strref)}; + auto eptr{strlike_end(io_strlike_type,strref)}; + auto cap{static_cast(eptr-bptr)}; + std::size_t new_cap{::fast_io::details::cal_new_cap_io_strlike(cap)}; + std::size_t const size_minimum{::fast_io::details::intrinsics::add_or_overflow_die(static_cast(last-first),cap)}; + if(new_cap,strref,new_cap); + auto curr_ptr{strlike_curr(io_strlike_type,strref)}; + curr_ptr=non_overlapped_copy(first,last,curr_ptr); + strlike_set_curr(io_strlike_type,strref,curr_ptr); +} + +} + +template +requires (std::same_as||std::same_as>) +inline constexpr void write(io_strlike_reference_wrapper bref,Iter first,Iter last) +{ + if constexpr(std::same_as<::std::iter_value_t,ch_type>) + { + if constexpr(std::is_pointer_v) + { + auto& strref{*bref.ptr}; + if constexpr(auxiliary_strlike) + { + strlike_append(io_strlike_type,strref,first,last); + } + else + { + std::size_t const iterdiff{static_cast(last-first)}; + ch_type* curr{strlike_curr(io_strlike_type,strref)}; + std::size_t const bufferdiff{static_cast(strlike_end(io_strlike_type,strref)-curr)}; + if(iterdiff<=bufferdiff)[[likely]] + { + ::fast_io::details::non_overlapped_copy_n(first,iterdiff,curr); + strlike_set_curr(io_strlike_type,strref,curr+iterdiff); + } + else[[unlikely]] + { + ::fast_io::details::write_strike_like_cold(bref,first,last); + } + } + } + else + { + write(bref,::std::to_address(first),::std::to_address(last)); + } + } + else + { + write(bref,reinterpret_cast(::std::to_address(first)), + reinterpret_cast(::std::to_address(last))); + } +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/concepts/decorator.h b/src/fast_io/include/fast_io_core_impl/concepts/decorator.h new file mode 100644 index 0000000..4482463 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/concepts/decorator.h @@ -0,0 +1,50 @@ +#pragma once + +namespace fast_io +{ +#if 0 +template +concept decorator=requires(T t,to_value_type* dest,std::size_t size) +{ + {deco_reserve_size(io_reserve_type,t,size)}->std::same_as; +}; + +template +concept decoratable = decorator&&requires(T t,from_value_type const* ptr,to_value_type* dest) +{ + {deco_reserve_define(io_reserve_type,t,ptr,ptr,dest)}->std::convertible_to; +}; + + +template +concept maybe_noop_decorator=decorator&&requires(T t) +{ + {deco_maybe_noop(io_reserve_type,t)}->std::convertible_to; +}; + +template +concept always_noop_decorator=decorator&&requires() +{ + deco_always_noop(io_reserve_type);//must be consteval +}; + +template +concept reserve_inverse_size_decorator=decorator&&requires(T t,std::size_t size) +{ + {deco_reserve_inverse_size(io_reserve_type,t,size)}->std::same_as; +}; +#endif +template +concept value_based_decorator = requires(T t) +{ + {deco_value_handle(t)}; +}; +#if 0 +template +concept unshift_decorator = decorator&&requires(T t,to_value_type const* from_iter,to_value_type const* to_iter) +{ + {deco_unshift_size(io_reserve_type,t)}; + {deco_unshift_define(io_reserve_type,t,from_iter,to_iter)}; +}; +#endif +} diff --git a/src/fast_io/include/fast_io_core_impl/concepts/details.h b/src/fast_io/include/fast_io_core_impl/concepts/details.h new file mode 100644 index 0000000..08884e7 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/concepts/details.h @@ -0,0 +1,258 @@ +#pragma once + +namespace fast_io::details +{ + +template +concept stream_char_type_requirement = requires() +{ + typename std::remove_cvref_t::char_type; +}; + +template +concept input_stream_impl = +(stream_char_type_requirement|| +(requires() +{ + typename std::remove_cvref_t::input_char_type; +}) +)&&requires(T&& in,typename std::remove_cvref_t::char_type* b) +{ + read(in,b,b); +}; + +template +concept output_stream_impl = (stream_char_type_requirement|| +(requires() +{ + typename std::remove_cvref_t::output_char_type; +}) +)&&requires(T&& out,typename std::remove_cvref_t::char_type const* b) +{ + write(out,b,b); +}; + +template +concept mutex_stream_impl = requires(T&& t) +{ + t.lock(); + t.unlock(); + t.unlocked_handle(); +}; + +template +concept random_access_stream_impl = requires(T&& t) +{ + seek(t,5); +}; + +template +concept buffer_input_stream_impl = requires(T&& in) +{ + ibuffer_begin(in); + ibuffer_set_curr(in,ibuffer_curr(in)); + ibuffer_end(in); + {ibuffer_underflow(in)}->std::convertible_to; +}; + +template +concept contiguous_input_stream_impl = requires(T&& in) +{ + ibuffer_underflow_never(in); +}; + +template +concept contiguous_output_stream_impl = requires(T&& out) +{ + obuffer_overflow_never(out); +}; + +template +concept refill_buffer_input_stream_impl = requires(T&& in) +{ + {irefill(in)}->std::convertible_to; +}; + +template +concept buffer_output_stream_impl = requires(T&& out,typename std::remove_cvref_t::char_type ch) +{ + obuffer_begin(out); + obuffer_end(out); + obuffer_set_curr(out,obuffer_curr(out)); + obuffer_overflow(out,ch); +}; + +template +concept constant_buffer_output_stream_impl = requires(T&& out) +{ + {obuffer_constant_size(io_reserve_type::char_type,std::remove_cvref_t>)}->std::same_as; + obuffer_constant_flush_prepare(out); +}; + +template +concept flush_output_stream_impl = requires(T&& out) +{ + flush(out); +}; + +template +concept fill_nc_output_stream_impl = requires(T&& out,std::size_t n,typename std::remove_cvref_t::char_type ch) +{ + fill_nc_define(out,n,ch); +}; + +template +concept dynamic_output_stream_impl = requires(T&& out,std::size_t size,typename std::remove_cvref_t::char_type* ptr) +{ + oreserve(out,size); + oshrink_to_fit(out); +}; + +template +concept zero_copy_input_stream_impl = requires(T&& in) +{ + zero_copy_in_handle(in); +}; + +template +concept zero_copy_output_stream_impl = requires(T&& out) +{ + zero_copy_out_handle(out); +}; + +template +concept redirect_stream_impl = requires(T&& h) +{ + redirect_handle(h); +}; + +template +concept status_stream_impl = requires(T&& stm) +{ + typename std::remove_cvref_t::status_type; +}; + +template +concept scatter_input_stream_impl = requires(T&& in,io_scatters_t sp) +{ + scatter_read(in,sp); +}; + +template +concept scatter_output_stream_impl = requires(T&& out,io_scatters_t sp) +{ + scatter_write(out,sp); +}; + +template +concept scatter_constant_output_stream_impl = requires(T&& out,io_scatter_t const* sp) +{ + scatter_constant_write<1>(out,sp); +}; + + +template +struct dummy_buffer_output_stream +{ + using char_type = ch_type; +}; + +template +inline constexpr dummy_buffer_output_stream io_value_handle(dummy_buffer_output_stream) noexcept +{ + return {}; +} + +template +inline constexpr char_type* obuffer_begin(dummy_buffer_output_stream) noexcept +{ + return nullptr; +} + +template +inline constexpr char_type* obuffer_curr(dummy_buffer_output_stream) noexcept +{ + return nullptr; +} + +template +inline constexpr char_type* obuffer_end(dummy_buffer_output_stream) noexcept +{ + return nullptr; +} + +template +inline constexpr void obuffer_set_curr(dummy_buffer_output_stream,char_type*) noexcept{} + +template +inline constexpr void obuffer_overflow(dummy_buffer_output_stream,char_type) noexcept{} + +template +inline constexpr void write(dummy_buffer_output_stream,char_type const*,char_type const*) noexcept{} + +template +struct dummy_buffer_input_stream +{ + using char_type = ch_type; +}; + +template +inline constexpr dummy_buffer_input_stream io_value_handle(dummy_buffer_input_stream) noexcept +{ + return {}; +} + +template +inline constexpr char_type* ibuffer_begin(dummy_buffer_input_stream) noexcept +{ + return nullptr; +} + +template +inline constexpr char_type* ibuffer_curr(dummy_buffer_input_stream) noexcept +{ + return nullptr; +} + +template +inline constexpr char_type* ibuffer_end(dummy_buffer_input_stream) noexcept +{ + return nullptr; +} + +template +inline constexpr void ibuffer_set_curr(dummy_buffer_input_stream,char_type*) noexcept{} + +template +inline constexpr bool ibuffer_underflow(dummy_buffer_input_stream) noexcept +{ + return true; +} + +template +inline constexpr char_type* read(dummy_buffer_input_stream,char_type* first,char_type*) noexcept +{ + return first; +} + +#if 0 + +template +concept async_input_stream64_impl = requires(T in,typename T::char_type* first,typename T::char_type* last,std::int_least64_t offset) +{ + async_read_define64(in,first,last,offset,[](typename T::char_type*,::std::errc ec) + { + }); +}; + +template +concept async_input_stream64_impl = requires(T in,typename T::char_type* first,typename T::char_type* last,std::int_least64_t offset) +{ + async_write_define64(in,first,last,offset,[](typename T::char_type*,::std::errc ec) + { + }); +}; + +#endif + +} diff --git a/src/fast_io/include/fast_io_core_impl/concepts/impl.h b/src/fast_io/include/fast_io_core_impl/concepts/impl.h new file mode 100644 index 0000000..30ff153 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/concepts/impl.h @@ -0,0 +1,10 @@ +#pragma once + +#include"type.h" +#include"parse_code.h" +#include"details.h" +#include"stream.h" +#include"operation_details.h" +#include"operation.h" +#include"decorator.h" +#include"strlike.h" diff --git a/src/fast_io/include/fast_io_core_impl/concepts/operation.h b/src/fast_io/include/fast_io_core_impl/concepts/operation.h new file mode 100644 index 0000000..94a682a --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/concepts/operation.h @@ -0,0 +1,195 @@ +#pragma once + +namespace fast_io +{ + +template +concept contiguous_scannable = requires(char_type const* begin, char_type const* end, T t) +{ + {scan_contiguous_define(io_reserve_type,begin,end,t)}->std::same_as>; +}; + +template +concept context_scannable = requires(char_type const* begin, char_type const* end, T t) +{ + requires requires(typename std::remove_cvref_t))>::type st) + { + {scan_context_define(io_reserve_type,st,begin,end,t)}->std::same_as>; + {scan_context_eof_define(io_reserve_type,st,t)}->std::same_as; + }; +}; + +template +concept reserve_printable=std::integral&&requires(T t,char_type* ptr) +{ + {print_reserve_size(io_reserve_type>)}->std::convertible_to; + {print_reserve_define(io_reserve_type>,ptr,t)}->std::convertible_to; +}; + +template +concept dynamic_reserve_printable=std::integral&&requires(T t,char_type* ptr) +{ + {print_reserve_size(io_reserve_type>,t)}->std::convertible_to; + {print_reserve_define(io_reserve_type>,ptr,t)}->std::convertible_to; +}; + +template +concept printable_internal_shift=requires(T t) +{ + {print_define_internal_shift(io_reserve_type>,t)}->std::same_as; +}; + +template +concept precise_reserve_printable=std::integral&&(reserve_printable||dynamic_reserve_printable)&&requires(T t,char_type* ptr,std::size_t n) +{ + {print_reserve_precise_size(io_reserve_type>,t)}->std::convertible_to; + print_reserve_precise_define(io_reserve_type>,ptr,n,t); +}; + +template +concept printable=requires(::fast_io::details::dummy_buffer_output_stream out,T t) +{ + print_define(io_reserve_type>,out,t); +}; + +template +concept scatter_printable=requires(char_type ch,T&& t) +{ + {print_scatter_define(io_reserve_type>,::fast_io::freestanding::forward(t))}->std::same_as>; +}; + +template +concept alias_scannable=requires(T&& t) +{ + scan_alias_define(io_alias,t); +}; + +template +concept alias_printable=requires(T&& t) +{ + print_alias_define(io_alias,::fast_io::freestanding::forward(t)); +}; + +template +concept status_io_scan_forwardable=std::integral&&requires(T t) +{ + status_io_scan_forward(io_alias_type,t); +}; + +template +concept status_io_print_forwardable=std::integral&&requires(T&& t) +{ + status_io_print_forward(io_alias_type,::fast_io::freestanding::forward(t)); +}; + +template +concept io_controllable=requires(io_device device,Args&& ...args) +{ + io_control(device,::fast_io::freestanding::forward(args)...); +}; + +struct manip_tag_t{}; + +template +concept manipulator = requires(T t) +{ + typename T::manip_tag; +}; + +template +struct parameter +{ + using manip_tag = manip_tag_t; + T reference; +}; + +template +requires (printable>&&std::is_trivially_copyable_v) +constexpr void print_define(io_reserve_type_t>,output out, parameter wrapper) +{ + print_define(io_reserve_type>,out,wrapper.reference); +} + +template +requires reserve_printable> +constexpr std::size_t print_reserve_size(io_reserve_type_t>) +{ + return print_reserve_size(io_reserve_type>); +} + +template +requires dynamic_reserve_printable> +constexpr std::size_t print_reserve_size(io_reserve_type_t>,parameter para) +{ + return print_reserve_size(io_reserve_type>,para.reference); +} + +template +requires (reserve_printable>||dynamic_reserve_printable>) +constexpr auto print_reserve_define(io_reserve_type_t>,char_type* begin,parameter para) +{ + return print_reserve_define(io_reserve_type>,begin,para.reference); +} + +template +requires (printable_internal_shift>) +constexpr auto print_define_internal_shift(io_reserve_type_t>,Iter begin,parameter para) +{ + return print_define_internal_shift(io_reserve_type>,begin,para.reference); +} + +template +requires precise_reserve_printable> +constexpr std::size_t print_reserve_precise_size(io_reserve_type_t>,parameter para) +{ + return print_reserve_precise_size(io_reserve_type>,para.reference); +} + +template +requires precise_reserve_printable> +constexpr void print_reserve_precise_define(io_reserve_type_t>,Iter begin,std::size_t n,parameter para) +{ + print_reserve_precise_define(io_reserve_type>,begin,n,para.reference); +} + +template +requires scatter_printable> +constexpr auto print_scatter_define(io_reserve_type_t>,parameter para) +{ + return print_scatter_define(io_reserve_type>,para.reference); +} + + +template +concept iterative_scannable = ::std::integral&&requires(T& t,char_type const* buffer_curr,char_type const* buffer_end) +{ + {scan_iterative_init_define(io_reserve_type>,t)}; + {scan_iterative_next_define(io_reserve_type>,t,buffer_curr,buffer_end)}->std::same_as>; + {scan_iterative_eof_define(io_reserve_type>,t)}->std::same_as; +}; + +template +concept iterative_contiguous_scannable = ::std::integral&&requires(T t,char_type const* buffer_curr,char_type const* buffer_end) +{ + {scan_iterative_contiguous_define(io_reserve_type>,t,buffer_curr,buffer_end)}->std::same_as>; +}; + +template +concept precise_reserve_scannable = ::std::integral&&requires(char_type const* buffer_curr,T t) +{ + {scan_precise_reserve_size(io_reserve_type>)}->::std::same_as<::std::size_t>; + scan_precise_reserve_define(io_reserve_type>,buffer_curr,t); +}; + +template +concept precise_reserve_scannable_no_error = precise_reserve_scannable&&requires(char_type const* buffer_curr,T t) +{ + {scan_precise_reserve_define(io_reserve_type>,buffer_curr,t)}->::std::same_as; +}; + +namespace manipulators +{} + +namespace mnp=manipulators; + +} diff --git a/src/fast_io/include/fast_io_core_impl/concepts/operation_details.h b/src/fast_io/include/fast_io_core_impl/concepts/operation_details.h new file mode 100644 index 0000000..cf85e42 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/concepts/operation_details.h @@ -0,0 +1,158 @@ +#pragma once + +namespace fast_io::details +{ + +template +concept character = std::integral&&(std::same_as||std::same_as||std::same_as|| +std::same_as||std::same_as); + +template +concept c_str_pointer = std::same_as||std::same_as||std::same_as|| + std::same_as||std::same_as; + +} + +namespace fast_io +{ + +template +concept type_has_c_str_method = requires(T&& t) +{ + {t.c_str()}->::fast_io::details::c_str_pointer; +}; + +template +concept constructible_to_os_c_str = type_has_c_str_method||(std::is_array_v>)||requires(T&& t) +{ + {t.length()}; + {t.substr()}; + {t.data()}; +}; + +template +concept constructible_to_os_c_str_or_nullptr = constructible_to_os_c_str||requires(T&& t) +{ + {t.is_nullptr()}->std::same_as; +}; + +namespace manipulators +{ + +template +struct basic_os_c_str +{ + using char_type = ch_type; + char_type const* ptr{}; + inline constexpr char_type const* c_str() const noexcept + { + return ptr; + } +}; + +template<::std::integral char_type> +inline constexpr basic_os_c_str os_c_str(char_type const* cstr) noexcept +{ + return {cstr}; +} + +inline constexpr void os_c_str(decltype(nullptr))=delete; + +template +struct basic_os_c_str_or_nullptr +{ + using char_type = ch_type; + char_type const* ptr{}; + inline constexpr char_type const* c_str() const noexcept + { + return ptr; + } + inline constexpr bool is_nullptr() const noexcept + { + return ptr==nullptr; + } +}; + +template +inline constexpr basic_os_c_str_or_nullptr os_c_str_or_nullptr(char_type const* cstr) noexcept +{ + return {cstr}; +} + +template +struct basic_os_c_str_with_known_size +{ + using char_type = ch_type; + char_type const* ptr{}; + std::size_t n{}; + inline constexpr char_type const* c_str() const noexcept + { + return ptr; + } + inline constexpr std::size_t size() const noexcept + { + return n; + } + inline constexpr char_type const* data() const noexcept + { + return ptr; + } + inline constexpr char_type const* begin() const noexcept + { + return ptr; + } + inline constexpr char_type const* end() const noexcept + { + return ptr+n; + } +}; + +template +inline constexpr basic_os_c_str_with_known_size os_c_str_with_known_size(char_type const* cstr,std::size_t n) noexcept +{ + return {cstr,n}; +} + +inline constexpr void os_c_str_with_known_size(decltype(nullptr),std::size_t)=delete; + +template +struct basic_os_str_known_size_without_null_terminated +{ + using char_type = ch_type; + char_type const* ptr{}; + std::size_t n{}; + inline constexpr std::size_t size() const noexcept + { + return n; + } + inline constexpr char_type const* data() const noexcept + { + return ptr; + } + inline constexpr char_type const* begin() const noexcept + { + return ptr; + } + inline constexpr char_type const* end() const noexcept + { + return ptr+n; + } +}; + +template +inline constexpr basic_os_str_known_size_without_null_terminated os_str_known_size_without_null_terminated(char_type const* cstr,std::size_t n) noexcept +{ + return {cstr,n}; +} + +template +inline constexpr basic_os_str_known_size_without_null_terminated os_str_known_size_without_null_terminated(char_type const* cstr, char_type const* end) noexcept +{ + return {cstr,static_cast<::std::size_t>(end-cstr)}; +} + +inline constexpr void os_str_known_size_without_null_terminated(decltype(nullptr),std::size_t)=delete; + +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/concepts/parse_code.h b/src/fast_io/include/fast_io_core_impl/concepts/parse_code.h new file mode 100644 index 0000000..2501d77 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/concepts/parse_code.h @@ -0,0 +1,24 @@ +#pragma once + +namespace fast_io +{ + +enum class parse_code:char unsigned +{ +ok = 0, +end_of_file = 1, +partial = 2, +invalid = 3, +overflow = 4 +}; + + +template +struct parse_result +{ + using iterator = Iter; + iterator iter; + parse_code code; +}; + +} diff --git a/src/fast_io/include/fast_io_core_impl/concepts/stream.h b/src/fast_io/include/fast_io_core_impl/concepts/stream.h new file mode 100644 index 0000000..0b8e3d3 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/concepts/stream.h @@ -0,0 +1,172 @@ +#pragma once + +namespace fast_io +{ + +template +concept stream = details::input_stream_impl||details::output_stream_impl; + +template +concept input_stream = stream&&details::input_stream_impl; + +template +concept output_stream = stream&&details::output_stream_impl; + +template +concept output_stream_with_writeln = output_stream&&requires(T&& t,typename std::remove_cvref_t::char_type const* p) +{ + writeln(t,p,p); +}; + +template +concept mutex_stream = stream&&details::mutex_stream_impl; + +template +concept random_access_stream = stream&&details::random_access_stream_impl; + +template +concept io_stream = input_stream&&output_stream; + +template +concept flush_output_stream = output_stream&&details::flush_output_stream_impl; + +template +concept buffer_input_stream = input_stream&&details::buffer_input_stream_impl; + +template +concept contiguous_input_stream = buffer_input_stream&&details::contiguous_input_stream_impl; + +template +concept buffer_output_stream = output_stream&&details::buffer_output_stream_impl; + +template +concept constant_buffer_output_stream = buffer_output_stream&&details::constant_buffer_output_stream_impl; + +template +concept contiguous_output_stream = buffer_output_stream&&details::contiguous_output_stream_impl; + +template +concept buffer_io_stream = buffer_input_stream&&buffer_output_stream&&io_stream; + +template +concept dynamic_output_stream = buffer_output_stream&&details::dynamic_output_stream_impl; + +/* +noline_buffer_output_stream ensures obuffer_begin(out)<=obuffer_curr(out)<=obuffer_end(out) +line_buffer_output_stream may end up a situation obuffer_curr(out)>obuffer_end(out), triggering overflow. +That is how glibc implements FILE*. +In fast_io, all fast_io directly supported stream ensures noline_buffer_output_stream +*/ +template +concept noline_buffer_output_stream = buffer_output_stream&&!requires(T t) +{ + {obuffer_is_line_buffering(t)}->std::convertible_to; +}; + +template +concept zero_copy_input_stream = input_stream&&details::zero_copy_input_stream_impl; + +template +concept zero_copy_output_stream = output_stream&&details::zero_copy_output_stream_impl; + +template +concept zero_copy_io_stream = zero_copy_input_stream&&zero_copy_output_stream; + +template +concept scatter_input_stream = input_stream&&details::scatter_input_stream_impl; + +template +concept scatter_output_stream = output_stream&&details::scatter_output_stream_impl; + +template +concept scatter_constant_output_stream = output_stream&&details::scatter_constant_output_stream_impl; + +#if 0 + +template +concept async_stream = details::async_input_stream_impl||details::async_output_stream_impl; + +template +concept async_input_stream = async_stream&&details::async_input_stream_impl; + +template +concept async_output_stream = async_stream&&details::async_output_stream_impl; + +template +concept async_io_stream = async_input_stream&&async_output_stream; + +template +concept async_scatter_input_stream = async_stream&&details::async_scatter_input_stream_impl; + +template +concept async_scatter_output_stream = async_stream&&details::async_scatter_output_stream_impl; + +template +concept async_scatter_io_stream = async_input_stream&&async_scatter_output_stream; + +#endif + +template +concept closable_stream = stream&&requires(T t) +{ + {t.close()}->std::same_as; +}; + +template +concept secure_clear_requirement_stream = stream&&requires(T stm) +{ + require_secure_clear(stm); +}; + +template +concept redirect_stream = stream&&details::redirect_stream_impl; + +template +concept capacity_available_buffer_input_stream = buffer_input_stream&&requires(T stm) +{ + {ibuffer_cap(stm)}->std::convertible_to::char_type*>; +}; + +template +concept value_based_stream = requires(T t) +{ + {io_value_handle(t)}; +}&& +(std::is_trivially_copyable_v || +requires(T t) +{ + typename T::native_handle_type; + t.release(); + t.native_handle(); + requires std::is_trivially_copyable_v; +}); + +template +concept try_get_input_stream=input_stream&&requires(T in) +{ + {try_get(in)}->std::convertible_to>; +}; + +/* +status streams deal with special stream types like streams which need locale +You can define your own behavior with it +*/ + +template +concept status_output_stream = requires(T out) +{ + print_status_define(out,1,1,1,1,1,1,1,1,1,1); + print_status_define(out,1,1,1,1,1,1,1,1,1,1); +}; + +/* +input requires a whole overhual because C++ exception is horrible. +*/ + +template +concept status_input_stream = requires(T in) +{ + {scan_status_define(in)}->std::convertible_to; +}; + +} diff --git a/src/fast_io/include/fast_io_core_impl/concepts/strlike.h b/src/fast_io/include/fast_io_core_impl/concepts/strlike.h new file mode 100644 index 0000000..a1dc430 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/concepts/strlike.h @@ -0,0 +1,81 @@ +#pragma once + +namespace fast_io +{ + +template +struct io_strlike_type_t +{ + explicit constexpr io_strlike_type_t() noexcept = default; +}; + +template +inline constexpr io_strlike_type_t io_strlike_type{}; + +namespace details +{ +template +concept buffer_strlike_impl = requires(T& t) +{ + {strlike_begin(io_strlike_type,t)}; + {strlike_curr(io_strlike_type,t)}; + {strlike_end(io_strlike_type,t)}; + requires requires(decltype(strlike_begin(io_strlike_type,t)) ptr) + { + {strlike_set_curr(io_strlike_type,t,ptr)}; + }; + requires requires(std::size_t n) + { + {strlike_reserve(io_strlike_type,t,n)}; + }; +}; +} + +template +concept strlike = std::integral&&std::is_default_constructible_v&&(requires(char_type const* first) +{ + strlike_construct_define(io_strlike_type,first,first); +}||::fast_io::details::buffer_strlike_impl); + +template +concept single_character_constructible_strlike = strlike&&requires(char_type ch) +{ + strlike_construct_single_character_define(io_strlike_type,ch); +}; + +template +concept alias_strlike = requires(T& t) +{ + strlike_alias_define(io_alias,t); +}; + +template +concept buffer_strlike = strlike && requires(T& t) +{ + {strlike_begin(io_strlike_type,t)}; + {strlike_curr(io_strlike_type,t)}; + {strlike_end(io_strlike_type,t)}; + requires requires(decltype(strlike_begin(io_strlike_type,t)) ptr) + { + {strlike_set_curr(io_strlike_type,t,ptr)}; + }; + requires requires(std::size_t n) + { + {strlike_reserve(io_strlike_type,t,n)}; + }; +}; + +template +concept auxiliary_strlike = strlike && requires(T& t,char_type ch,char_type const* ptr) +{ + strlike_push_back(io_strlike_type,t,ch); + strlike_append(io_strlike_type,t,ptr,ptr); +}; + +template +concept sso_buffer_strlike = buffer_strlike && requires() +{ + {strlike_sso_size(io_strlike_type)}->std::same_as; +}; + +} diff --git a/src/fast_io/include/fast_io_core_impl/concepts/type.h b/src/fast_io/include/fast_io_core_impl/concepts/type.h new file mode 100644 index 0000000..ffb619a --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/concepts/type.h @@ -0,0 +1,91 @@ +#pragma once + +namespace fast_io +{ + +template +struct basic_io_scatter_t +{ + using value_type = T; + T const* base; + std::size_t len; +}; + +//should be binary compatible with POSIX's iovec + +using io_scatter_t = basic_io_scatter_t; +using io_scatters_t = basic_io_scatter_t; + +struct io_scatter_status_t +{ + std::size_t total_size; + std::size_t position; + std::size_t position_in_scatter; +}; + +template +struct basic_message_hdr +{ + T const *name; /* Optional address */ + std::size_t namelen; /* Size of address */ + basic_io_scatter_t const* iov; /* Scatter/gather array */ + std::size_t iovlen; /* # elements in msg_iov */ + T const *control; /* Ancillary data, see below */ + std::size_t controllen; /* Ancillary data buffer len */ + int flags; /* Flags (unused) */ + inline operator basic_message_hdr() const noexcept requires(!std::same_as) + { + return {name,namelen*sizeof(T),iov,iovlen*sizeof(T),control,controllen,flags}; + } +}; + +using message_hdr = basic_message_hdr; +//should be binary compatible with POSIX's msghdr + +template +struct io_type_t +{ +using type = T; +}; +template +inline constexpr io_type_t io_type{}; + +template +struct cross_code_cvt_t +{ + using value_type = char_type; + basic_io_scatter_t scatter; +}; + +template +struct io_reserve_type_t +{ +explicit constexpr io_reserve_type_t() noexcept =default; +}; +template +inline constexpr io_reserve_type_t io_reserve_type{}; + +struct io_alias_t +{ +explicit constexpr io_alias_t() noexcept =default; +}; + +inline constexpr io_alias_t io_alias{}; + +template +struct io_alias_type_t +{ +explicit constexpr io_alias_type_t() noexcept = default; +}; + +template +inline constexpr io_alias_type_t io_alias_type{}; + +template +struct try_get_result +{ + char_type ch; + bool eof; +}; + +} diff --git a/src/fast_io/include/fast_io_core_impl/dll_mode.h b/src/fast_io/include/fast_io_core_impl/dll_mode.h new file mode 100644 index 0000000..aec5696 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/dll_mode.h @@ -0,0 +1,62 @@ +#pragma once + +namespace fast_io +{ + +enum class dll_mode:std::uint_least32_t +{ +none=0, +posix_rtld_lazy=static_cast(1)<<0, +posix_rtld_now=static_cast(1)<<1, +posix_rtld_binding_mask=static_cast(1)<<2, +posix_rtld_global=static_cast(1)<<3, +posix_rtld_local=static_cast(1)<<4, +posix_rtld_nodelete=static_cast(1)<<5, +posix_rtld_noload=static_cast(1)<<6, +posix_rtld_deepbind=static_cast(1)<<7, +win32_dont_resolve_dll_references=static_cast(1)<<10, +win32_load_ignore_code_authz_level=static_cast(1)<<11, +win32_load_library_as_datafile=static_cast(1)<<12, +win32_load_library_as_datafile_exclusive=static_cast(1)<<13, +win32_load_library_as_image_resource=static_cast(1)<<14, +win32_load_library_search_application_dir=static_cast(1)<<15, +win32_load_library_search_default_dirs=static_cast(1)<<16, +win32_load_library_search_dll_load_dir=static_cast(1)<<17, +win32_load_library_search_system32=static_cast(1)<<18, +win32_load_library_search_user_dirs=static_cast(1)<<19, +win32_load_with_altered_search_path=static_cast(1)<<20, +win32_load_library_require_signed_target=static_cast(1)<<21, +win32_load_library_safe_current_dirs=static_cast(1)<<22 +}; + + +constexpr dll_mode operator&(dll_mode x, dll_mode y) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(static_cast(x) & static_cast(y)); +} + +constexpr dll_mode operator|(dll_mode x, dll_mode y) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(static_cast(x) | static_cast(y)); +} + +constexpr dll_mode operator^(dll_mode x, dll_mode y) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(static_cast(x) ^ static_cast(y)); +} + +constexpr dll_mode operator~(dll_mode x) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(~static_cast(x)); +} + +inline constexpr dll_mode& operator&=(dll_mode& x, dll_mode y) noexcept{return x=x&y;} + +inline constexpr dll_mode& operator|=(dll_mode& x, dll_mode y) noexcept{return x=x|y;} + +inline constexpr dll_mode& operator^=(dll_mode& x, dll_mode y) noexcept{return x=x^y;} +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_core_impl/drain.h b/src/fast_io/include/fast_io_core_impl/drain.h new file mode 100644 index 0000000..480ed3e --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/drain.h @@ -0,0 +1,21 @@ +#pragma once + +namespace fast_io +{ + +template +constexpr basic_io_scatter_t::char_type> print_alias_define(io_alias_t,manip::drainage source) +{ + auto bg{obuffer_begin(source.reference)}; + auto curr{obuffer_curr(source.reference)}; + return {bg,static_cast(curr-bg)}; +} + +template +inline constexpr void drain(dest_type&& dest,source_type&& source) +{ + print_freestanding(::std::forward(dest),drainage(source)); +} + + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_core_impl/dynamic_io_buffer.h b/src/fast_io/include/fast_io_core_impl/dynamic_io_buffer.h new file mode 100644 index 0000000..17b3190 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/dynamic_io_buffer.h @@ -0,0 +1,166 @@ +#pragma once +//std::string is not usable in freestanding environments and cause problems for this library +//This is a very simple stuff for internal use + +namespace fast_io +{ + +template +class dynamic_io_buffer +{ +public: + using char_type = ch_type; + using pointer = char_type*; + pointer buffer_begin=nullptr,buffer_curr=nullptr,buffer_end=nullptr; + constexpr dynamic_io_buffer()=default; + dynamic_io_buffer(dynamic_io_buffer const&)=delete; + dynamic_io_buffer& operator=(dynamic_io_buffer const&)=delete; +#if __cpp_constexpr_dynamic_alloc >= 201907L + constexpr +#endif + ~dynamic_io_buffer() + { + details::deallocate_iobuf_space(buffer_begin,buffer_end-buffer_begin); + } +}; + +template +[[nodiscard]] constexpr char_type* obuffer_begin(dynamic_io_buffer& ob) noexcept +{ + return ob.buffer_begin; +} + +template +[[nodiscard]] constexpr char_type* obuffer_curr(dynamic_io_buffer& ob) noexcept +{ + return ob.buffer_curr; +} + +template +[[nodiscard]] constexpr char_type* obuffer_end(dynamic_io_buffer& ob) noexcept +{ + return ob.buffer_end; +} + +template +inline constexpr void obuffer_set_curr(dynamic_io_buffer& ob,char_type* ptr) noexcept +{ + ob.buffer_curr=ptr; +} + +namespace details +{ + +template +inline constexpr void dynamic_io_buffer_oreallocate_impl(dynamic_io_buffer& ob,std::size_t size) noexcept +{ + auto new_space{allocate_iobuf_space(size)}; + std::size_t ptr_diff{static_cast(ob.buffer_curr-ob.buffer_begin)}; + non_overlapped_copy_n(ob.buffer_begin,ptr_diff,new_space); + deallocate_iobuf_space(ob.buffer_begin,ob.buffer_end-ob.buffer_begin); + ob.buffer_begin=new_space; + ob.buffer_curr=new_space+ptr_diff; + ob.buffer_end=new_space+size; +} + +template +inline constexpr void dynamic_io_buffer_grow_with_new_size(dynamic_io_buffer& ob,std::size_t new_size) noexcept +{ + std::size_t new_capacity{static_cast(ob.buffer_end-ob.buffer_begin)}; + constexpr std::size_t cap_max{SIZE_MAX/2}; + if(new_capacity>cap_max) + new_capacity=SIZE_MAX; + else + new_capacity*=2; + if(new_capacity +inline constexpr void dynamic_io_buffer_overflow_impl(dynamic_io_buffer& ob,char_type ch) noexcept +{ + std::size_t new_capacity{static_cast(ob.buffer_end-ob.buffer_begin)}; + constexpr std::size_t cap_max{SIZE_MAX/2}; + if(new_capacity>cap_max) + new_capacity=SIZE_MAX; + else + new_capacity*=2; + dynamic_io_buffer_oreallocate_impl(ob,new_capacity); + *ob.buffer_curr=ch; + ++ob.buffer_curr; +} + +template +inline constexpr void dynamic_io_buffer_write_impl_unhappy_iter(dynamic_io_buffer& ob, + Iter first,std::size_t diff) noexcept +{ + dynamic_io_buffer_grow_with_new_size(ob,ob.buffer_end-ob.buffer_begin+diff); + ob.buffer_curr=non_overlapped_copy_n(first,diff,ob.buffer_curr); +} + +template<::std::forward_iterator Iter> +inline constexpr void dynamic_io_buffer_write_impl_unhappy(dynamic_io_buffer<::std::iter_value_t>& ob, + Iter first,std::size_t diff) noexcept +{ + if constexpr(::std::contiguous_iterator) + { + auto const * ptr{::std::to_address(first)}; + dynamic_io_buffer_write_impl_unhappy_iter(ob,ptr,diff); + } + else + dynamic_io_buffer_write_impl_unhappy_iter(ob,first,diff); +} + +} +template +inline constexpr void oreserve(dynamic_io_buffer& ob,std::size_t new_capacity) noexcept +{ + if(static_cast(ob.buffer_end-ob.buffer_begin)<=new_capacity) + return; + details::dynamic_io_buffer_oreallocate_impl(ob,new_capacity); +} + +template +inline constexpr void oshrink_to_fit(dynamic_io_buffer& ob) noexcept +{ + if(ob.buffer_curr==ob.buffer_end) + return; + details::dynamic_io_buffer_oreallocate_impl(ob,ob.buffer_curr-ob.buffer_begin); +} + +template +inline constexpr void obuffer_overflow(dynamic_io_buffer& ob,ch_type ch) noexcept +{ + details::dynamic_io_buffer_overflow_impl(ob,ch); +} + +template +requires ((std::same_as&&::std::contiguous_iterator)|| + std::same_as>) +inline constexpr void write(dynamic_io_buffer& ob,Iter first,Iter last) noexcept +{ + if constexpr(!std::same_as>) + { + write(ob, + reinterpret_cast(::std::to_address(first)), + reinterpret_cast(::std::to_address(last))); + } + else if constexpr(::std::contiguous_iterator&&!std::is_pointer_v>) + { + write(ob,::std::to_address(first),::std::to_address(last)); + } + else + { + std::size_t diff{static_cast(last-first)}; + std::size_t remain_space{static_cast(ob.buffer_end-ob.buffer_curr)}; + if(remain_space +inline constexpr bool exec_charset_is_ebcdic() noexcept +{ + if constexpr(std::same_as,char>) + { + return static_cast('A')!=u8'A'; + } + else if constexpr(std::same_as,wchar_t>) + { + if constexpr(sizeof(wchar_t)==sizeof(char16_t)) + { + constexpr char16_t value{static_cast(L'A')}; + constexpr char16_t swapped{::fast_io::byte_swap(value)}; + return value!=u'A'&&swapped!=u'A'; + } + else if constexpr(sizeof(wchar_t)==sizeof(char32_t)) + { + constexpr char32_t value{static_cast(L'A')}; + constexpr char32_t swapped{::fast_io::byte_swap(value)}; + return value!=U'A'&&swapped!=U'A'; + } + else + { + return static_cast(L'A')!=U'A'; + } + } + else + { + return false; + } +} + +template +inline constexpr bool is_ebcdic{exec_charset_is_ebcdic()}; + +inline constexpr bool wexec_charset_is_utf_none_native_endian() noexcept +{ + if constexpr(sizeof(wchar_t)==sizeof(char16_t)) + { + constexpr char16_t value{static_cast(L'A')}; + constexpr char16_t swapped{::fast_io::byte_swap(value)}; + return value!=u'A'&&swapped==u'A'; + } + else + { + constexpr char32_t value{static_cast(L'A')}; + constexpr char32_t swapped{::fast_io::byte_swap(value)}; + return value!=U'A'&&swapped==U'A'; + } +} + +inline constexpr bool wide_is_none_utf_endian{wexec_charset_is_utf_none_native_endian()}; + +} diff --git a/src/fast_io/include/fast_io_core_impl/empty.h b/src/fast_io/include/fast_io_core_impl/empty.h new file mode 100644 index 0000000..879df5c --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/empty.h @@ -0,0 +1,6 @@ +#pragma once + +namespace fast_io::details +{ +struct empty{}; +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_core_impl/enums/access_how.h b/src/fast_io/include/fast_io_core_impl/enums/access_how.h new file mode 100644 index 0000000..4188869 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/enums/access_how.h @@ -0,0 +1,44 @@ +#pragma once + +namespace fast_io +{ + +enum class access_how:std::uint_fast8_t +{ +f_ok=0, +x_ok=1, +w_ok=2, +r_ok=4 +}; + +constexpr access_how operator&(access_how x, access_how y) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(static_cast(x) & static_cast(y)); +} + +constexpr access_how operator|(access_how x, access_how y) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(static_cast(x) | static_cast(y)); +} + +constexpr access_how operator^(access_how x, access_how y) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(static_cast(x) ^ static_cast(y)); +} + +constexpr access_how operator~(access_how x) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(~static_cast(x)); +} + +inline constexpr access_how& operator&=(access_how& x, access_how y) noexcept{return x=x&y;} + +inline constexpr access_how& operator|=(access_how& x, access_how y) noexcept{return x=x|y;} + +inline constexpr access_how& operator^=(access_how& x, access_how y) noexcept{return x=x^y;} + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_core_impl/enums/flock.h b/src/fast_io/include/fast_io_core_impl/enums/flock.h new file mode 100644 index 0000000..8c3907f --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/enums/flock.h @@ -0,0 +1,62 @@ +#pragma once + +namespace fast_io +{ + +enum class file_lock_mode:char unsigned +{ +shared_lock, +exclusive_lock, +unlock, +}; + +template +struct basic_flock_request +{ + using int_type = T; + file_lock_mode type=file_lock_mode::exclusive_lock; + seekdir whence=seekdir::cur; + int_type start=0; + int_type len=0; +}; + +using flock_request_l64 = basic_flock_request<::std::int_least64_t>; + +struct nop_file_lock +{ + template + constexpr void lock(RequestType const&) noexcept{} + template + constexpr void unlock(RequestType const&) noexcept{} + template + constexpr bool try_lock(RequestType const&) noexcept + { + return true; + } +}; + +template +requires requires(FilelockT t,RequestT& lk) +{ + t.lock(lk); + t.unlock(lk); +} +struct file_lock_guard +{ + using file_lock_type = FilelockT; + using request_type = RequestT; + file_lock_type lock; + request_type request; + explicit constexpr file_lock_guard(file_lock_type const& lk,request_type const& flk):lock(lk),request(flk) + { + lock.lock(request); + } + file_lock_guard(file_lock_guard const&)=delete; + file_lock_guard& operator=(file_lock_guard const&)=delete; + constexpr ~file_lock_guard() + { + lock.unlock(request); + } +}; + +} diff --git a/src/fast_io/include/fast_io_core_impl/enums/impl.h b/src/fast_io/include/fast_io_core_impl/enums/impl.h new file mode 100644 index 0000000..f7a4870 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/enums/impl.h @@ -0,0 +1,5 @@ +#pragma once + +#include"access_how.h" +#include"utime_flags.h" +#include"flock.h" diff --git a/src/fast_io/include/fast_io_core_impl/enums/utime_flags.h b/src/fast_io/include/fast_io_core_impl/enums/utime_flags.h new file mode 100644 index 0000000..5949d58 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/enums/utime_flags.h @@ -0,0 +1,20 @@ +#pragma once + +namespace fast_io +{ + +enum class utime_flags:std::uint_fast8_t +{ +none,now,omit +}; + +struct unix_timestamp_option +{ + utime_flags flags{utime_flags::omit}; + unix_timestamp timestamp{}; + constexpr unix_timestamp_option() noexcept=default; + constexpr unix_timestamp_option(unix_timestamp ts) noexcept:flags(utime_flags::none),timestamp(ts){} + constexpr unix_timestamp_option(utime_flags fg) noexcept:flags(fg){} +}; + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_core_impl/error.h b/src/fast_io/include/fast_io_core_impl/error.h new file mode 100644 index 0000000..e527741 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/error.h @@ -0,0 +1,80 @@ +#pragma once + +namespace fast_io +{ + +struct error +{ + using value_type = std::uintptr_t; + value_type domain{}; + value_type code{}; +}; + +inline constexpr bool operator==(error e1,error e2) noexcept +{ + return e1.domain==e2.domain&&e1.code==e2.code; +} + +inline constexpr bool operator!=(error e1,error e2) noexcept +{ + return !(e1==e2); +} + +template +struct error_type_t +{ +explicit inline constexpr error_type_t() noexcept = default; +}; + +template +inline constexpr error_type_t error_type{}; + +template +concept error_domain = std::is_trivially_copyable_v && sizeof(T)<=sizeof(std::uintptr_t) && + requires(error e,T t) +{ + {domain_define(error_type)}->std::same_as; + {equivalent_define(error_type,e,t)}->std::same_as; +#if 0 + {to_code_define(error_type,e)}->std::same_as; +#endif +}; + +template +inline constexpr bool is_domain(error e) noexcept +{ + constexpr std::uintptr_t v{error_domain_define(error_type)}; + return v==e.domain; +} + +template +inline constexpr D to_code(error e) noexcept +{ + return to_code_define(error_type,e); +} + +template +inline constexpr bool operator==(error e,D t) noexcept +{ + return equivalent_define(error_type,e,t); +} + +template +inline constexpr bool operator==(D t,error e) noexcept +{ + return equivalent_define(error_type,e,t); +} + +template +inline constexpr bool operator!=(error e,D t) noexcept +{ + return !equivalent_define(error_type,e,t); +} + +template +inline constexpr bool operator!=(D t,error e) noexcept +{ + return !equivalent_define(error_type,e,t); +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/freestanding/addressof.h b/src/fast_io/include/fast_io_core_impl/freestanding/addressof.h new file mode 100644 index 0000000..b85d7a6 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/freestanding/addressof.h @@ -0,0 +1,53 @@ +#pragma once + +/* +Referenced from libstdc++ +https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/include/bits/move.h +*/ +/* +C++ freestanding does not provide ::std::addressof, ::std::move and ::std::forward. We need to define them by ourselves. +*/ + +namespace fast_io::freestanding +{ + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +[[nodiscard]] inline constexpr T * +addressof(T &r) noexcept +{ + return __builtin_addressof(r); // death to compilers which do not support __builtin_addressof +} + +template +T const *addressof(T const &&) = delete; + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +[[nodiscard]] inline constexpr T && +forward(::std::remove_reference_t &t) noexcept +{ + return static_cast(t); +} + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +[[nodiscard]] inline constexpr typename ::std::remove_reference::type && +move(T &&t) noexcept +{ + return static_cast::type &&>(t); +} + +} // namespace fast_io::freestanding diff --git a/src/fast_io/include/fast_io_core_impl/freestanding/algorithm.h b/src/fast_io/include/fast_io_core_impl/freestanding/algorithm.h new file mode 100644 index 0000000..83b687f --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/freestanding/algorithm.h @@ -0,0 +1,847 @@ +#pragma once + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC system_header +#endif +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning(push) +#pragma warning(disable : 4365) +#endif + +#if 0 +//__STDC_HOSTED__==1 && (!defined(_GLIBCXX_HOSTED) || _GLIBCXX_HOSTED==1) +namespace fast_io::freestanding +{ +using ::std::find_if; +using ::std::copy_n; +using ::std::copy; +using ::std::copy_backward; +using ::std::move_backward; +using ::std::fill; +using ::std::fill_n; +} + +#else +namespace fast_io::freestanding +{ + +template <::std::input_iterator Iter, typename predicate> +inline constexpr Iter find_if(Iter first, Iter last, predicate q) +{ + for (; first != last; ++first) + { + if (q(*first)) + { + return first; + } + } + return last; +} + +template <::std::input_iterator input_iter, ::std::input_or_output_iterator output_iter> +inline constexpr output_iter copy_n(input_iter first, ::std::size_t count, output_iter result) +{ + using input_value_type = ::std::iter_value_t; + using output_value_type = ::std::iter_value_t; + for (::std::size_t i{}; i != count; ++i) + { + if constexpr (sizeof(input_value_type) == 1 && + (::std::same_as) && (::std::integral)) + { + *result = static_cast(*first); + } + else if constexpr (sizeof(output_value_type) == 1 && + (::std::same_as) && (::std::integral)) + { + *result = static_cast<::std::byte>(*first); + } + else + { + *result = *first; + } + ++first; + ++result; + } + return result; +} + +template <::std::input_iterator input_iter, ::std::input_or_output_iterator output_iter> +inline constexpr output_iter copy(input_iter first, input_iter last, output_iter result) +{ + using input_value_type = ::std::iter_value_t; + using output_value_type = ::std::iter_value_t; + for (; first != last;) + { + if constexpr (sizeof(input_value_type) == 1 && + (::std::same_as) && (::std::integral)) + { + *result = static_cast(*first); + } + else if constexpr (sizeof(output_value_type) == 1 && + (::std::same_as) && (::std::integral)) + { + *result = static_cast<::std::byte>(*first); + } + ++first; + ++result; + } + return result; +} + +template <::std::input_iterator fwd_iter, typename T> +inline constexpr void fill(fwd_iter first, fwd_iter last, T value) +{ + for (; first != last; ++first) + { + *first = value; + } +} + +template <::std::input_iterator fwd_iter, typename T> +inline constexpr void fill_n(fwd_iter first, ::std::size_t n, T value) +{ + for (::std::size_t i{}; i != n; ++i) + { + *first = value; + ++first; + } +} + +template <::std::bidirectional_iterator BidirIt1, ::std::bidirectional_iterator BidirIt2> +constexpr BidirIt2 copy_backward(BidirIt1 first, BidirIt1 last, BidirIt2 d_last) +{ + for (; first != last; *(--d_last) = *(--last)) + ; + return d_last; +} + +template <::std::bidirectional_iterator BidirIt1, ::std::bidirectional_iterator BidirIt2> +constexpr BidirIt2 move_backward(BidirIt1 first, BidirIt1 last, BidirIt2 d_last) +{ + for (; first != last; *(--d_last) = ::std::move(*(--last))) + ; + return d_last; +} + +} // namespace fast_io::freestanding + +#endif + +namespace fast_io::freestanding +{ + +template <::std::input_iterator Iter, ::std::integral T> +// requires (::std::is_trivially_copyable_v&&sizeof(T)<=sizeof(::std::uintmax_t)) + requires(::std::is_trivially_copyable_v) +inline constexpr Iter find(Iter first, Iter last, T t) +{ + for (; first != last; ++first) + { + if (*first == t) + { + return first; + } + } + return last; +} + +template <::std::input_iterator Iter, ::std::integral T> +// requires (::std::is_trivially_copyable_v&&sizeof(T)<=sizeof(::std::uintmax_t)) + requires(::std::is_trivially_copyable_v) +inline constexpr Iter find_not(Iter first, Iter last, T t) +{ + for (; first != last; ++first) + { + if (*first != t) + { + return first; + } + } + return last; +} + +template <::std::input_iterator Iter, ::std::input_iterator Iter2> +struct mismatch_result +{ + Iter first; + Iter2 second; +}; + +template <::std::input_iterator Iter, ::std::input_iterator Iter2> +inline constexpr mismatch_result my_mismatch(Iter first1, Iter last1, Iter2 first2, Iter2 last2) +{ + for (; first1 != last1 && first2 != last2 && *first1 == *first2; ++first2) + { + ++first1; + } + return {first1, first2}; +} +template <::std::forward_iterator ForwardIt, class T> + requires(::std::is_trivially_copyable_v) +inline constexpr ForwardIt remove(ForwardIt first, ForwardIt last, T value) +{ + first = find(first, last, value); + if (first != last) + { + for (ForwardIt i = first; ++i != last;) + { + if (!(*i == value)) + { + *first = ::std::move(*i); + ++first; + } + } + } + return first; +} +} // namespace fast_io::freestanding + +namespace fast_io::freestanding +{ + +inline +#if defined(__has_builtin) +#if __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) + __builtin_memcpy +#else + ::std::memcpy +#endif +#else + ::std::memcpy +#endif + (dest, src, count); +} + +inline +#if defined(__has_builtin) +#if __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) + __builtin_memmove +#else + ::std::memmove +#endif +#else + ::std::memmove +#endif + (dest, src, count); +} + +inline void *my_memset(void *dest, int ch, ::std::size_t count) noexcept +{ + return +#if defined(__has_builtin) +#if __has_builtin(__builtin_memset) + __builtin_memset +#else + ::std::memset +#endif +#else + ::std::memset +#endif + (dest, ch, count); +} + +inline +#if defined(__has_builtin) +#if __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) + __builtin_memcmp +#else + ::std::memcmp +#endif +#else + ::std::memcmp +#endif + (dest, src, count); +} + +template <::std::input_iterator input_iter, ::std::input_or_output_iterator output_iter> +inline constexpr output_iter non_overlapped_copy_n(input_iter first, ::std::size_t count, output_iter result) +{ +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if (__builtin_is_constant_evaluated()) +#endif + { + return ::fast_io::freestanding::copy_n(first, count, result); + } + else +#endif + { + using input_value_type = ::std::iter_value_t; + using output_value_type = ::std::iter_value_t; + if constexpr (::std::contiguous_iterator && ::std::contiguous_iterator && + ::std::is_trivially_copyable_v && + ::std::is_trivially_copyable_v && + (::std::same_as || + ((::std::integral || ::std::same_as<::std::byte, input_value_type>) && (::std::integral || ::std::same_as<::std::byte, output_value_type>) && sizeof(input_value_type) == sizeof(output_value_type)))) + { + if (count) // to avoid nullptr UB + { + my_memcpy(::std::to_address(result), ::std::to_address(first), + sizeof(::std::iter_value_t) * count); + } + return result += count; + } + else + { + return ::fast_io::freestanding::copy_n(first, count, result); + } + } +} + +template <::std::input_iterator input_iter, ::std::input_or_output_iterator output_iter> +inline constexpr output_iter non_overlapped_copy(input_iter first, input_iter last, output_iter result) +{ +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if (__builtin_is_constant_evaluated()) +#endif + { + return ::fast_io::freestanding::copy(first, last, result); + } + else +#endif + { + using input_value_type = ::std::iter_value_t; + using output_value_type = ::std::iter_value_t; + if constexpr (::std::contiguous_iterator && ::std::contiguous_iterator && + ::std::is_trivially_copyable_v && + ::std::is_trivially_copyable_v && + (::std::same_as || + ((::std::integral || ::std::same_as<::std::byte, input_value_type>) && (::std::integral || ::std::same_as<::std::byte, output_value_type>) && sizeof(input_value_type) == sizeof(output_value_type)))) + { + ::std::size_t count{static_cast<::std::size_t>(last - first)}; + if (count) // to avoid nullptr UB + { + my_memcpy(::std::to_address(result), ::std::to_address(first), + sizeof(::std::iter_value_t) * count); + } + return result += count; + } + else + { + return ::fast_io::freestanding::copy(first, last, result); + } + } +} + +template <::std::input_iterator input_iter, ::std::input_or_output_iterator output_iter> +inline constexpr output_iter my_copy_n(input_iter first, ::std::size_t count, output_iter result) +{ +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if (__builtin_is_constant_evaluated()) +#endif + { + return ::fast_io::freestanding::copy_n(first, count, result); + } + else +#endif + { + using input_value_type = ::std::iter_value_t; + using output_value_type = ::std::iter_value_t; + if constexpr (::std::contiguous_iterator && ::std::contiguous_iterator && + ::std::is_trivially_copyable_v && + ::std::is_trivially_copyable_v && + (::std::same_as || + (::std::integral && ::std::integral && + sizeof(input_value_type) == sizeof(output_value_type)))) + { + if (count) // to avoid nullptr UB + { + my_memmove(::std::to_address(result), ::std::to_address(first), + sizeof(::std::iter_value_t) * count); + } + return result += count; + } + else + { + return ::fast_io::freestanding::copy_n(first, count, result); + } + } +} + +template <::std::input_iterator input_iter, ::std::input_or_output_iterator output_iter> +inline constexpr output_iter my_copy(input_iter first, input_iter second, output_iter result) +{ + using input_value_type = ::std::iter_value_t; + using output_value_type = ::std::iter_value_t; + if constexpr (::std::contiguous_iterator && ::std::contiguous_iterator && + ::std::is_trivially_copyable_v && + ::std::is_trivially_copyable_v && + (::std::same_as || + (::std::integral && ::std::integral && + sizeof(::std::is_trivially_copyable_v) == + sizeof(::std::is_trivially_copyable_v)))) + { + my_copy_n(first, static_cast<::std::size_t>(second - first), result); + return result + (second - first); + } + else + { + return ::fast_io::freestanding::copy(first, second, result); + } +} + +template <::std::bidirectional_iterator input_iter, ::std::bidirectional_iterator output_iter> +inline constexpr output_iter my_copy_backward(input_iter first, input_iter last, output_iter d_last) +{ +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if (__builtin_is_constant_evaluated()) +#endif + { + return ::fast_io::freestanding::copy_backward(first, last, d_last); + } + else +#endif + { + using input_value_type = typename ::std::iter_value_t; + using output_value_type = typename ::std::iter_value_t; + if constexpr (::std::contiguous_iterator && ::std::contiguous_iterator && + ::std::is_trivially_copyable_v && + ::std::is_trivially_copyable_v && + (::std::same_as || + (::std::integral && ::std::integral && + sizeof(input_value_type) == sizeof(output_value_type)))) + { + ::std::size_t const count(last - first); + d_last -= count; + if (count) // to avoid nullptr UB + { + my_memmove(::std::to_address(d_last), ::std::to_address(first), sizeof(input_value_type) * count); + } + return d_last; + } + else + { + return ::fast_io::freestanding::copy_backward(first, last, d_last); + } + } +} + +template <::std::random_access_iterator input_iter, ::std::random_access_iterator output_iter> +inline constexpr bool my_compare_iter_n(input_iter first, ::std::size_t n, output_iter outier) noexcept +{ +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if (__builtin_is_constant_evaluated()) +#endif + { + for (auto last{first + n}; first != last; ++first) + { + if (*first != *outier) + { + return false; + } + ++outier; + } + return true; + } + else +#endif + { + using input_value_type = typename ::std::iter_value_t; + using output_value_type = typename ::std::iter_value_t; + if constexpr (::std::contiguous_iterator && ::std::contiguous_iterator && + ::std::is_trivially_copyable_v && + ::std::is_trivially_copyable_v && + (::std::same_as || + (::std::integral && ::std::integral && + sizeof(input_value_type) == sizeof(output_value_type)))) + { + return my_memcmp(::std::to_address(first), ::std::to_address(outier), n) == 0; + } + else + { + for (auto last{first + n}; first != last; ++first) + { + if (*first != outier) + { + return false; + } + ++outier; + } + return true; + } + } +} + +template <::std::input_iterator InputIt1, ::std::input_iterator InputIt2> +inline constexpr bool lexicographical_compare(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2) +{ + for (; (first1 != last1) && (first2 != last2); ++first2) + { + if (*first1 < *first2) + { + return true; + } + if (*first2 < *first1) + { + return false; + } + ++first1; + } + return (first1 == last1) && (first2 != last2); +} + +template <::std::input_iterator InputIt1, ::std::input_iterator InputIt2> +inline constexpr bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2) +{ + for (; first1 != last1 && first2 != last2 && *first1 == *first2; ++first2) + { + ++first1; + } + return first1 == last1 && first2 == last2; +} + +template <::std::forward_iterator ForwardIt, class T, class Compare> +inline constexpr ForwardIt lower_bound(ForwardIt first, ForwardIt last, T const &value, Compare comp) +{ + ForwardIt it; + typename ::std::iterator_traits::difference_type count, step; + count = last - first; + + while (count > 0) + { + it = first; + step = count / 2; + it += step; + + if (comp(*it, value)) + { + first = ++it; + count -= step + 1; + } + else + { + count = step; + } + } + return first; +} + +template <::std::input_iterator InputIt, ::std::forward_iterator NoThrowForwardIt> +inline constexpr NoThrowForwardIt uninitialized_copy(InputIt first, InputIt last, NoThrowForwardIt d_first) +{ + using T = typename ::std::iterator_traits::value_type; + struct destroyer + { + NoThrowForwardIt d_first; + NoThrowForwardIt current; + constexpr ~destroyer() + { + for (; d_first != current; ++d_first) + { + d_first->~T(); + } + } + }; + using input_iter = InputIt; + using output_iter = NoThrowForwardIt; + using input_value_type = ::std::iter_value_t; + using output_value_type = ::std::iter_value_t; + if constexpr (::std::contiguous_iterator && ::std::contiguous_iterator && + ::std::is_trivially_copyable_v && + ::std::is_trivially_copyable_v && + (::std::same_as || + (::std::integral && ::std::integral && + sizeof(input_value_type) == sizeof(output_value_type)))) + { +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L +#if __cpp_if_consteval >= 202106L + if !consteval +#else + if (!__builtin_is_constant_evaluated()) +#endif + { + ::std::size_t count{static_cast<::std::size_t>(last - first)}; + if (count) // to avoid nullptr UB + { + my_memmove(::std::to_address(d_first), ::std::to_address(first), sizeof(input_value_type) * count); + } + return d_first += count; + } +#endif + } + destroyer d{d_first, d_first}; + for (; first != last; ++first) + { + ::new (__builtin_addressof(*d.current)) T(*first); + ++d.current; + } + NoThrowForwardIt current = d.current; + d.current = d.d_first; + return current; +} + +template <::std::input_iterator InputIt, ::std::forward_iterator NoThrowForwardIt> +inline constexpr NoThrowForwardIt +uninitialized_copy_n(InputIt first, ::std::size_t n, NoThrowForwardIt d_first) noexcept( + ::std::is_nothrow_copy_constructible_v::value_type>) +{ + using T = typename ::std::iterator_traits::value_type; + struct destroyer + { + NoThrowForwardIt d_first; + NoThrowForwardIt current; + constexpr ~destroyer() noexcept + { + for (; d_first != current; ++d_first) + { + d_first->~T(); + } + } + }; + using input_iter = InputIt; + using output_iter = NoThrowForwardIt; + using input_value_type = ::std::iter_value_t; + using output_value_type = ::std::iter_value_t; + if constexpr (::std::contiguous_iterator && ::std::contiguous_iterator && + ::std::is_trivially_copyable_v && + ::std::is_trivially_copyable_v && + (::std::same_as || + (::std::integral && ::std::integral && + sizeof(input_value_type) == sizeof(output_value_type)))) + { +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L +#if __cpp_if_consteval >= 202106L + if !consteval +#else + if (!__builtin_is_constant_evaluated()) +#endif + { + if (n) // to avoid nullptr UB + { + my_memmove(::std::to_address(d_first), ::std::to_address(first), sizeof(input_value_type) * n); + } + return d_first += n; + } +#endif + } + destroyer d{d_first, d_first}; + for (::std::size_t i{}; i != n; ++i) + { + ::std::construct_at(::std::to_address(d.current), *first); + ++d.current; + ++first; + } + NoThrowForwardIt current = d.current; + d.current = d.d_first; + return current; +} + +template <::std::input_iterator InputIt, ::std::forward_iterator NoThrowForwardIt> +inline constexpr NoThrowForwardIt +uninitialized_move_n(InputIt first, ::std::size_t n, NoThrowForwardIt d_first) noexcept( + ::std::is_nothrow_constructible_v::value_type>) // undefined if + // throws +{ + using T = typename ::std::iterator_traits::value_type; + using input_iter = InputIt; + using output_iter = NoThrowForwardIt; + using input_value_type = ::std::iter_value_t; + using output_value_type = ::std::iter_value_t; + if constexpr (::std::contiguous_iterator && ::std::contiguous_iterator && + ::std::is_trivially_copyable_v && + ::std::is_trivially_copyable_v && + (::std::same_as || + (::std::integral && ::std::integral && + sizeof(input_value_type) == sizeof(output_value_type)))) + { +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L +#if __cpp_if_consteval >= 202106L + if !consteval +#else + if (!__builtin_is_constant_evaluated()) +#endif + { + if (n) // to avoid nullptr UB + { + my_memmove(::std::to_address(d_first), ::std::to_address(first), sizeof(input_value_type) * n); + } + return d_first += n; + } +#endif + } + for (::std::size_t i{}; i != n; ++i) + { + ::std::construct_at(::std::to_address(d_first), ::std::move(*first)); + ++d_first; + ++first; + } + return d_first; +} + +template <::std::forward_iterator ForwardIt> +inline constexpr ForwardIt +rotate(ForwardIt first, ForwardIt middle, + ForwardIt last) noexcept(::std::is_nothrow_swappable_v::value_type>) +{ + // copied from cppreference, room for improvements + if (first == middle) + { + return last; + } + if (middle == last) + { + return first; + } + ForwardIt write = first; + ForwardIt next_read = first; // read position for when "read" hits "last" + for (ForwardIt read = middle; read != last; ++write, ++read) + { + if (write == next_read) + { + next_read = read; // track where "first" went + } + ::std::ranges::swap(*write, *read); + } + // rotate the remaining sequence into place + rotate(write, next_read, last); + return write; +} + +template <::std::bidirectional_iterator BidIt1, typename T> +inline constexpr BidIt1 find_not(BidIt1 first, BidIt1 last, T const &val) +{ + for (; first != last && *first == val; ++first) + { + } + return first; +} + +template <::std::bidirectional_iterator BidIt1, typename T> +inline constexpr BidIt1 find_last(BidIt1 first, BidIt1 last, T const &val) +{ + for (auto it = last; it != first;) + { + --it; + if (*it == val) + { + return it; + } + } + return last; +} + +template <::std::bidirectional_iterator BidIt1, typename T> +inline constexpr BidIt1 find_last_not(BidIt1 first, BidIt1 last, T const &val) +{ + for (auto it = last; it != first;) + { + --it; + if (*it != val) + { + return it; + } + } + return last; +} + +template <::std::bidirectional_iterator BidIt1, ::std::bidirectional_iterator BidIt2> +inline constexpr BidIt1 find_first_not_of(BidIt1 first, BidIt1 last, BidIt2 sfirst, BidIt2 slast) +{ + for (; first != last; ++first) + { + auto it2 = sfirst; + for (; it2 != slast && *it2 != *first; ++it2) + { + } + if (it2 == slast) + { + return first; + } + } + return last; +} + +template <::std::bidirectional_iterator BidIt1, ::std::bidirectional_iterator BidIt2> +inline constexpr BidIt1 find_last_of(BidIt1 first, BidIt1 last, BidIt2 sfirst, BidIt2 slast) +{ + for (auto it = last; first != it;) + { + --it; + for (auto it2 = sfirst; it2 != slast; ++it2) + { + if (*it == *it2) + { + return it; + } + } + } + return last; +} + +template <::std::bidirectional_iterator BidIt1, ::std::bidirectional_iterator BidIt2> +inline constexpr BidIt1 find_last_not_of(BidIt1 first, BidIt1 last, BidIt2 sfirst, BidIt2 slast) +{ + for (auto it = last; first != it;) + { + --it; + auto it2 = sfirst; + for (; it2 != slast && *it2 != *it; ++it2) + { + } + if (it2 == slast) + { + return it; + } + } + return last; +} + +} // namespace fast_io::freestanding + +namespace fast_io::details +{ +using ::fast_io::freestanding::my_copy; +using ::fast_io::freestanding::my_copy_backward; +using ::fast_io::freestanding::my_copy_n; +using ::fast_io::freestanding::my_memcpy; +using ::fast_io::freestanding::my_memmove; +using ::fast_io::freestanding::my_memset; +using ::fast_io::freestanding::non_overlapped_copy; +using ::fast_io::freestanding::non_overlapped_copy_n; + +} // namespace fast_io::details + +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning(pop) +#endif diff --git a/src/fast_io/include/fast_io_core_impl/freestanding/allocator.h b/src/fast_io/include/fast_io_core_impl/freestanding/allocator.h new file mode 100644 index 0000000..bf6f541 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/freestanding/allocator.h @@ -0,0 +1,31 @@ +#pragma once + +namespace fast_io::freestanding +{ + +template +struct allocator +{ + constexpr T *allocate([[maybe_unused]] ::std::size_t n) noexcept + { + constexpr ::std::size_t mx{(~static_cast<::std::size_t>(0u)) / sizeof(T)}; + if (n > mx) + { + __builtin_trap(); + } +#if __has_builtin(__builtin_operator_new) + return static_cast(__builtin_operator_new(n * sizeof(T))); +#else + __builtin_trap(); + return nullptr; +#endif + } + 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); +#endif + } +}; + +} // namespace fast_io::freestanding diff --git a/src/fast_io/include/fast_io_core_impl/freestanding/array.h b/src/fast_io/include/fast_io_core_impl/freestanding/array.h new file mode 100644 index 0000000..7c250fe --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/freestanding/array.h @@ -0,0 +1,84 @@ +#pragma once + +namespace fast_io::freestanding +{ + +template + requires(sizeof(N) != 0) +struct array +{ + using value_type = T; + using pointer = T *; + using const_pointer = T const *; + using reference = T &; + using const_reference = T const &; + using size_type = ::std::size_t; + using difference_type = ::std::ptrdiff_t; + T element[N]; + inline constexpr T *data() noexcept + { + return element; + } + inline constexpr T const *data() const noexcept + { + return element; + } + inline constexpr T *begin() noexcept + { + return element; + } + inline constexpr T *end() noexcept + { + return element + N; + } + inline static constexpr bool empty() noexcept + { + return false; + } + inline static constexpr ::std::size_t size() noexcept + { + return N; + } + inline constexpr T const *begin() const noexcept + { + return element; + } + inline constexpr T const *end() const noexcept + { + return element + N; + } + inline constexpr T const *cbegin() const noexcept + { + return element; + } + inline constexpr T const *cend() const noexcept + { + return element + N; + } + inline constexpr T const &front() const noexcept + { + return *element; + } + inline constexpr T &front() noexcept + { + return *element; + } + inline constexpr T const &back() const noexcept + { + return element[N - 1]; + } + inline constexpr T &back() noexcept + { + return element[N - 1]; + } + inline constexpr T const &operator[](::std::size_t i) const noexcept + { + return element[i]; + } + inline constexpr T &operator[](::std::size_t i) noexcept + { + return element[i]; + } +}; + +} // namespace fast_io::freestanding diff --git a/src/fast_io/include/fast_io_core_impl/freestanding/bytes.h b/src/fast_io/include/fast_io_core_impl/freestanding/bytes.h new file mode 100644 index 0000000..e9ff433 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/freestanding/bytes.h @@ -0,0 +1,245 @@ +#pragma once + +namespace fast_io::details +{ +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr ::std::byte *bytes_copy_naive_n_impl(::std::byte const *first, ::std::size_t n, + ::std::byte *dest) noexcept +{ + for (::std::size_t i{}; i != n; ++i) + { + dest[i] = first[i]; + } + return dest + n; +} + +} // namespace fast_io::details + +namespace fast_io::freestanding +{ +#if __has_cpp_attribute(__gnu__::__flatten__) +[[__gnu__::__flatten__]] +#endif +inline constexpr ::std::byte *bytes_copy_n(::std::byte const *first, ::std::size_t n, ::std::byte *dest) noexcept +{ +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L +#if __cpp_if_consteval >= 202106L + if consteval +#elif __cpp_lib_is_constant_evaluated >= 201811L + if (__builtin_is_constant_evaluated()) +#endif + { + return ::fast_io::details::bytes_copy_naive_n_impl(first, n, dest); + } + else +#endif + { + if (n) +#if __has_cpp_attribute(likely) + [[likely]] +#endif + { +#if !defined(__has_builtin) + ::std::memmove(dest, first, n); +#elif __has_builtin(__builtin_memmove) + __builtin_memmove(dest, first, n); +#else + ::std::memmove(dest, first, n); +#endif + } + return dest + n; + } +} + +#if __has_cpp_attribute(__gnu__::__flatten__) +[[__gnu__::__flatten__]] +#endif +inline constexpr ::std::byte *bytes_copy(::std::byte const *first, ::std::byte const *last, ::std::byte *dest) noexcept +{ + return ::fast_io::freestanding::bytes_copy_n(first, static_cast<::std::size_t>(last - first), dest); +} + +inline constexpr ::std::byte *nonoverlapped_bytes_copy_n(::std::byte const * first, ::std::size_t n, + ::std::byte * dest) noexcept +{ +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L +#if __cpp_if_consteval >= 202106L + if consteval +#elif __cpp_lib_is_constant_evaluated >= 201811L + if (__builtin_is_constant_evaluated()) +#endif + { + return ::fast_io::details::bytes_copy_naive_n_impl(first, n, dest); + } + else +#endif + { + if (n) +#if __has_cpp_attribute(likely) + [[likely]] +#endif + { +#if !defined(__has_builtin) + ::std::memcpy(dest, first, n); +#elif __has_builtin(__builtin_memcpy) + __builtin_memcpy(dest, first, n); +#else + ::std::memcpy(dest, first, n); +#endif + } + } + return dest + n; +} + +inline constexpr ::std::byte *nonoverlapped_bytes_copy(::std::byte const *first, ::std::byte const *last, + ::std::byte *__restrict dest) noexcept +{ + return nonoverlapped_bytes_copy_n(first, static_cast<::std::size_t>(last - first), dest); +} + +template +inline constexpr ::std::byte const *type_punning_from_bytes(::std::byte const *__restrict first, + T &__restrict t) noexcept +{ + constexpr ::std::size_t n{sizeof(T)}; + if constexpr (n != 0) + { +#if __cpp_lib_bit_cast >= 201806L && (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) +#if __cpp_if_consteval >= 202106L + if consteval +#elif __cpp_lib_is_constant_evaluated >= 201811L + if (__builtin_is_constant_evaluated()) +#endif + { + ::std::byte buffer[n]; + nonoverlapped_bytes_copy_n(first, n, buffer); + t = ::std::bit_cast(buffer); + } + 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); +#else + ::std::memcpy(__builtin_addressof(t), first, n); +#endif + } + } + return first + n; +} + +template <::std::size_t n, typename T> + requires(n <= sizeof(T)) +inline constexpr ::std::byte *type_punning_to_bytes_n(T const &__restrict first, ::std::byte *__restrict dest) noexcept +{ + if constexpr (n != 0) + { +#if __cpp_lib_bit_cast >= 201806L && (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) +#if __cpp_if_consteval >= 202106L + if consteval +#elif __cpp_lib_is_constant_evaluated >= 201811L + if (__builtin_is_constant_evaluated()) +#endif + { + auto buffer{::std::bit_cast<::fast_io::freestanding::array<::std::byte, sizeof(T)>>(first)}; + nonoverlapped_bytes_copy_n(buffer.data(), n, dest); + } + 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); +#else + ::std::memcpy(dest, __builtin_addressof(first), n); +#endif + } + } + return dest + n; +} + +template +inline constexpr ::std::byte *type_punning_to_bytes(T const &__restrict first, ::std::byte *__restrict dest) noexcept +{ + constexpr ::std::size_t n{sizeof(T)}; + return type_punning_to_bytes_n(first, dest); +} + +inline constexpr ::std::byte *bytes_clear_n(::std::byte *data, ::std::size_t size) noexcept +{ +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L +#if __cpp_if_consteval >= 202106L + if consteval +#elif __cpp_lib_is_constant_evaluated >= 201811L + if (__builtin_is_constant_evaluated()) +#endif + { + for (::std::size_t i{}; i != size; ++i) + { + data[i] = ::std::byte{}; + } + } + else +#endif + { +#if defined(__has_builtin) +#if __has_builtin(__builtin_memset) + __builtin_memset(data, 0, size); +#else + ::std::memset(data, 0, size); +#endif +#else + ::std::memset(data, 0, size); +#endif + } + return data + size; +} + +inline constexpr ::std::byte *bytes_clear(::std::byte *first, ::std::byte *last) noexcept +{ + return bytes_clear_n(first, static_cast<::std::size_t>(last - first)); +} + +inline constexpr ::std::byte *bytes_fill_n(::std::byte *data, ::std::size_t size, ::std::byte val) noexcept +{ +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L +#if __cpp_if_consteval >= 202106L + if consteval +#elif __cpp_lib_is_constant_evaluated >= 201811L + if (__builtin_is_constant_evaluated()) +#endif + { + for (::std::size_t i{}; i != size; ++i) + { + data[i] = val; + } + } + else +#endif + { +#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 +#else + ::std::memset(data, static_cast(val), size); +#endif + } + return data + size; +} + +inline constexpr ::std::byte *bytes_fill(::std::byte *first, ::std::byte *last, ::std::byte val) noexcept +{ + return bytes_fill_n(first, static_cast<::std::size_t>(last - first), val); +} + +} // namespace fast_io::freestanding diff --git a/src/fast_io/include/fast_io_core_impl/freestanding/cstr_len.h b/src/fast_io/include/fast_io_core_impl/freestanding/cstr_len.h new file mode 100644 index 0000000..60164df --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/freestanding/cstr_len.h @@ -0,0 +1,101 @@ +#pragma once + +namespace fast_io +{ + +namespace details +{ + +template <::std::integral char_type> +inline constexpr ::std::size_t dummy_cstr_len(char_type const *cstr) noexcept +{ + ::std::size_t n{}; + for (; *cstr; ++cstr) + { + ++n; + } + return n; +} + +template <::std::integral char_type> +inline constexpr ::std::size_t dummy_cstr_nlen(char_type const *cstr, ::std::size_t maxn) noexcept +{ + ::std::size_t n{}; + for (; n != maxn && cstr[n]; ++n) + ; + return n; +} + +} // namespace details + +template <::std::integral char_type> +inline constexpr ::std::size_t cstr_len(char_type const *cstr) noexcept +{ +#ifdef __cpp_if_consteval + if consteval + { + return details::dummy_cstr_len(cstr); + } +#else + if (__builtin_is_constant_evaluated()) + { + return details::dummy_cstr_len(cstr); + } +#endif + else + { + if constexpr (::std::same_as) + { +#if defined(__has_builtin) +#if __has_builtin(__builtin_strlen) + return __builtin_strlen(cstr); +#else + return ::std::strlen(cstr); +#endif +#else + return ::std::strlen(cstr); +#endif + } + else + { + return details::dummy_cstr_len(cstr); + } + } +} + +template <::std::integral char_type> +inline constexpr ::std::size_t cstr_nlen(char_type const *cstr, ::std::size_t n) noexcept +{ +#ifdef __cpp_if_consteval + if consteval + { + return details::dummy_cstr_nlen(cstr, n); + } +#else + if (__builtin_is_constant_evaluated()) + { + return details::dummy_cstr_nlen(cstr, n); + } +#endif + else + { + if constexpr (::std::same_as) + { +#if defined(__has_builtin) +#if __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 + } + else + { + return details::dummy_cstr_nlen(cstr, n); + } + } +} + +} // namespace fast_io diff --git a/src/fast_io/include/fast_io_core_impl/freestanding/impl.h b/src/fast_io/include/fast_io_core_impl/freestanding/impl.h new file mode 100644 index 0000000..9df74a3 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/freestanding/impl.h @@ -0,0 +1,51 @@ +#pragma once + +/* + +GCC provides more headers in freestanding environment than standard requires because WG21 sucks very badly. +no ::std::array, ::std::copy and others + +*/ +#if defined(__GLIBCXX__) && __has_include() && __has_include() && _GLIBCXX_RELEASE >= 12 +#include +#include +#include +#else +#include +#include +#endif + +#if defined(__GLIBCXX__) && __has_include() +#include +#else +#include +#endif + +#if defined(__GLIBCXX__) && __has_include() +#include +#else +#include +#endif + +#if defined(_LIBCPP_VERSION) && __has_include(<__memory/allocator.h>) +#include <__memory/allocator.h> +#include "std_allocator.h" +#elif defined(__GLIBCXX__) && __has_include() && __has_include() +#include +#include "std_allocator.h" +#elif defined(_MSVC_STL_UPDATE) && __has_include() +#include +#include "std_allocator.h" +#else +#include "allocator.h" +#endif + +#include "noexcept_call.h" +#include "array.h" +#include "cstr_len.h" +#include "bytes.h" +#include "algorithm.h" +#include "relocatable.h" +#include "ranges.h" + +#include diff --git a/src/fast_io/include/fast_io_core_impl/freestanding/noexcept_call.h b/src/fast_io/include/fast_io_core_impl/freestanding/noexcept_call.h new file mode 100644 index 0000000..41c7fab --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/freestanding/noexcept_call.h @@ -0,0 +1,83 @@ +#pragma once + +namespace fast_io +{ + +namespace freestanding +{ + +template +struct make_noexcept +{ +}; + +template +struct make_noexcept +{ + using type = R(Args...) noexcept; +}; + +template +struct make_noexcept +{ + using type = R(Args...) noexcept; +}; + +template +using make_noexcept_t = typename make_noexcept::type; + +template + requires ::std::is_function_v +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr auto noexcept_cast(F *f) noexcept +{ +#if __cpp_lib_bit_cast >= 201806L + return __builtin_bit_cast(make_noexcept_t *, f); +#else + return reinterpret_cast *>(f); +#endif +} + +template + requires ::std::is_function_v +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811 + constexpr +#endif + decltype(auto) noexcept_call(F *f, Args &&...args) noexcept +{ +#if __cpp_if_consteval >= 202106L + if consteval + { + return f(::std::forward(args)...); // EH unwinding does not matter here + } + else + { + return noexcept_cast(f)(::std::forward(args)...); + } +#else +#if __cpp_lib_is_constant_evaluated >= 201811 + if (::std::is_constant_evaluated()) + { + return f(::std::forward(args)...); // EH unwinding does not matter here + } + else +#endif + return noexcept_cast(f)(::std::forward(args)...); +#endif +} + +} + +using ::fast_io::freestanding::noexcept_call; + +} diff --git a/src/fast_io/include/fast_io_core_impl/freestanding/ranges.h b/src/fast_io/include/fast_io_core_impl/freestanding/ranges.h new file mode 100644 index 0000000..8424882 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/freestanding/ranges.h @@ -0,0 +1,17 @@ +#pragma once + +namespace fast_io::freestanding +{ + +#ifdef __cpp_lib_ranges_to_container +using ::std::from_range_t; +using ::std::from_range; +#else +struct from_range_t +{ + explicit constexpr from_range_t() noexcept = default; +}; +inline constexpr ::fast_io::freestanding::from_range_t from_range{}; +#endif + +} // namespace fast_io::freestanding diff --git a/src/fast_io/include/fast_io_core_impl/freestanding/relocatable.h b/src/fast_io/include/fast_io_core_impl/freestanding/relocatable.h new file mode 100644 index 0000000..c16aa77 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/freestanding/relocatable.h @@ -0,0 +1,40 @@ +#pragma once + +namespace fast_io::freestanding +{ + +template +struct is_trivially_relocatable +{ +#if defined(__clang__) && defined(__cpp_impl_trivially_relocatable) + inline static constexpr bool value = __is_trivially_relocatable(T); +#else + inline static constexpr bool value = ::std::is_trivially_copyable_v; +#endif +}; + +template +inline constexpr bool is_trivially_relocatable_v = is_trivially_relocatable::value; + +template +struct is_zero_default_constructible +{ + inline static constexpr bool value = ::std::is_scalar_v || ::std::is_empty_v; +}; + +template +inline constexpr bool is_zero_default_constructible_v = is_zero_default_constructible::value; + +} // namespace fast_io::freestanding + +namespace fast_io +{ + +struct for_overwrite_t +{ + explicit constexpr for_overwrite_t() noexcept = default; +}; + +inline constexpr for_overwrite_t for_overwrite{}; + +} // namespace fast_io diff --git a/src/fast_io/include/fast_io_core_impl/freestanding/std_allocator.h b/src/fast_io/include/fast_io_core_impl/freestanding/std_allocator.h new file mode 100644 index 0000000..a5847f0 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/freestanding/std_allocator.h @@ -0,0 +1,13 @@ +#pragma once + +/* +ugly hack against standard bug +https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111353 +*/ + +namespace fast_io::freestanding +{ + +using ::std::allocator; + +} diff --git a/src/fast_io/include/fast_io_core_impl/http_header.h b/src/fast_io/include/fast_io_core_impl/http_header.h new file mode 100644 index 0000000..b5afc0d --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/http_header.h @@ -0,0 +1,324 @@ +#pragma once + +namespace fast_io +{ + +template +requires (buffer_size>=64u) +struct basic_http_header_buffer +{ + using char_type = ch_type; + std::size_t header_length{}; + std::size_t http_request_end_location{}; + std::size_t http_status_code_start_location{}; + std::size_t http_status_code_end_location{}; + std::size_t http_status_reason_start_location{}; + std::size_t http_status_reason_end_location{}; + char_type buffer[buffer_size]; + inline static constexpr std::size_t size() noexcept + { + return buffer_size; + } + inline constexpr ::fast_io::manipulators::basic_os_str_known_size_without_null_terminated request() const noexcept + { + return ::fast_io::manipulators::os_str_known_size_without_null_terminated(buffer,buffer+http_request_end_location); + } + inline constexpr ::fast_io::manipulators::basic_os_str_known_size_without_null_terminated code() const noexcept + { + return ::fast_io::manipulators::os_str_known_size_without_null_terminated(buffer+http_status_code_start_location,buffer+http_status_code_end_location); + } + inline constexpr ::fast_io::manipulators::basic_os_str_known_size_without_null_terminated reason() const noexcept + { + return ::fast_io::manipulators::os_str_known_size_without_null_terminated(buffer+http_status_reason_start_location,buffer+http_status_reason_end_location); + } +}; + +struct http_buffer_parse_context +{ + std::size_t state{}; +}; + +template +inline constexpr auto scan_context_type(io_reserve_type_t&>>) noexcept +{ + return io_type_t{}; +} + +template +inline constexpr basic_io_scatter_t print_alias_define(io_alias_t,basic_http_header_buffer const& b) noexcept +{ + return {b.buffer,b.header_length}; +} + +namespace details +{ +template +inline bool try_copy_into_buffer(basic_http_header_buffer& b,char_type const* first,char_type const* last) noexcept +{ + std::size_t diff{static_cast(last-first)}; + std::size_t remain_space{static_cast(buffer_size-b.header_length)}; + if(remain_space +inline constexpr parse_code determine_http_header_location(basic_http_header_buffer& b) noexcept +{ + auto i{b.buffer},e{b.buffer+b.header_length}; + if(i!=e&&*i==char_literal_v) + return parse_code::invalid; + { + i=::fast_io::details::find_ch_impl(i,e); + //for(;i!=e&&*i!=char_literal_v;++i); + if(i==e) + { + return parse_code::invalid; + } + b.http_request_end_location=static_cast(i-b.buffer); + } + ++i; + i=::fast_io::details::find_ch_impl(i,e); + //for(;i!=e&&*i==char_literal_v;++i); + if(i==e) + return parse_code::invalid; + b.http_status_code_start_location=static_cast(i-b.buffer); + { + i=::fast_io::details::find_ch_impl(i,e); + //for(;i!=e&&*i!=char_literal_v;++i); + if(i==e) + return parse_code::invalid; + b.http_status_code_end_location=static_cast(i-b.buffer); + } + i=::fast_io::details::find_ch_impl(i,e); + //for(;i!=e&&*i==char_literal_v;++i); + if(i==e) + return parse_code::invalid; + b.http_status_reason_start_location=static_cast(i-b.buffer); + i=::fast_io::details::find_ch_impl(i,e); + //for(;i!=e&&*i!=char_literal_v;++i); + if(i==e) + return parse_code::invalid; + b.http_status_reason_end_location=static_cast(i-b.buffer); + return parse_code::ok; +} + +template<::std::integral char_type,std::size_t buffer_size> +inline constexpr parse_result http_header_scan_context_define_impl(std::size_t& state,char_type const* first1, char_type const* last,basic_http_header_buffer& bufferref) noexcept +{ + auto first{first1}; + if(first==last) + { + return {first,parse_code::partial}; + } + if(state!=0) + { + switch(state) + { + case 1: + { + if(*first!=char_literal_v) + break; + ++first; + if(first==last) + { + state=2u; + if(!::fast_io::details::try_copy_into_buffer(bufferref,first1,last)) + return {first,parse_code::invalid}; + return {first,parse_code::partial}; + } + [[fallthrough]]; + } + case 2: + { + if(*first!=char_literal_v) + break; + ++first; + if(first==last) + { + state=3u; + if(!::fast_io::details::try_copy_into_buffer(bufferref,first1,last)) + return {first,parse_code::invalid}; + return {first,parse_code::partial}; + } + [[fallthrough]]; + } + case 3: + { + if(*first!=char_literal_v) + break; + ++first; + if(!::fast_io::details::try_copy_into_buffer(bufferref,first1,first)) + return {first,parse_code::invalid}; + return {first,::fast_io::details::determine_http_header_location(bufferref)}; + } + } + } + state=0; + for(;;) + { + first=::fast_io::details::find_ch_impl(first,last); + //for(;first!=last&&*first!=char_literal_v;++first); + if(first==last) + { + if(!::fast_io::details::try_copy_into_buffer(bufferref,first1,first)) + return {first,parse_code::invalid}; + state=0u; + return {first,parse_code::partial}; + } + ++first; + if(first==last) + { + if(!::fast_io::details::try_copy_into_buffer(bufferref,first1,first)) + return {first,parse_code::invalid}; + state=1u; + return {first,parse_code::partial}; + } + if(*first!=char_literal_v) + { + return {first,parse_code::invalid}; + } + ++first; + if(first==last) + { + if(!::fast_io::details::try_copy_into_buffer(bufferref,first1,first)) + return {first,parse_code::invalid}; + state=2u; + return {first,parse_code::partial}; + } + if(*first!=char_literal_v) + { + continue; + } + ++first; + if(first==last) + { + if(!::fast_io::details::try_copy_into_buffer(bufferref,first1,first)) + return {first,parse_code::invalid}; + state=3u; + return {first,parse_code::partial}; + } + if(*first!=char_literal_v) + { + return {first,parse_code::invalid}; + } + ++first; + if(!::fast_io::details::try_copy_into_buffer(bufferref,first1,first)) + return {first,parse_code::invalid}; + return {first,::fast_io::details::determine_http_header_location(bufferref)}; + } +} + +} + +template<::std::integral char_type,std::size_t buffer_size> +inline constexpr parse_result scan_context_define(io_reserve_type_t&>>,http_buffer_parse_context& statetp,char_type const* first1,char_type const* last,::fast_io::parameter&> t) noexcept +{ + return ::fast_io::details::http_header_scan_context_define_impl(statetp.state,first1,last,t.reference); +} + +template +inline constexpr parse_code scan_context_eof_define(io_reserve_type_t&>>,http_buffer_parse_context,::fast_io::parameter&>) noexcept +{ + return parse_code::invalid; +} + +using http_header_buffer = basic_http_header_buffer; +using u8http_header_buffer = basic_http_header_buffer; +using u16http_header_buffer = basic_http_header_buffer; +using u32http_header_buffer = basic_http_header_buffer; +using whttp_header_buffer = basic_http_header_buffer; + +template +struct basic_http_line_generator +{ + char_type const* current{}; + char_type const* last{}; + char_type const* key_end{}; + char_type const* value_start{}; + char_type const* value_end{}; +}; + +template +struct basic_http_line +{ + ::fast_io::manipulators::basic_os_str_known_size_without_null_terminated key,value; +}; + +template +inline constexpr basic_http_line_generator line_generator(basic_http_header_buffer& b) noexcept +{ + std::size_t end_loc{b.http_status_reason_end_location}; + char_type const* start{b.buffer+end_loc}; + return {start,b.buffer+b.header_length,start,start,start}; +} + +template +inline constexpr basic_http_line_generator& operator++(basic_http_line_generator& b) noexcept +{ + auto const last{b.last}; + b.current=b.value_end; + if(last-b.current<=4) + { + b.value_end=b.value_start=b.key_end=b.current=last; + return b; + } + b.current = ::fast_io::details::find_ch_impl(b.current,last); +// for(;b.current!=last&&*b.current!=char_literal_v;++b.current); + if(b.current==last) + { + b.value_end=b.value_start=b.key_end=last; + return b; + } + auto line_last{b.current}; + line_last = ::fast_io::details::find_ch_impl(line_last,last); +// for(;line_last!=last&&*line_last!=char_literal_v;++line_last); + ++b.current; + b.current = ::fast_io::details::find_ch_impl(b.current,line_last); +// for(;b.current!=line_last&&*b.current==char_literal_v;++b.current); + auto curr{b.current}; + curr = ::fast_io::details::find_ch_impl(curr,line_last); +// for(;curr!=line_last&&*curr!=char_literal_v;++curr); + b.key_end=curr; + if(curr!=line_last) + ++curr; + curr = ::fast_io::details::find_ch_impl(curr,line_last); +// for(;curr!=line_last&&*curr==char_literal_v;++curr); + b.value_start=curr; + b.value_end=line_last; + return b; +} + +template +inline constexpr basic_http_line_generator& begin(basic_http_line_generator& b) noexcept +{ + return ++b; +} + +template +inline constexpr ::std::default_sentinel_t end(basic_http_line_generator&) noexcept +{ + return {}; +} + +template +inline constexpr bool operator==(basic_http_line_generator& b,::std::default_sentinel_t) +{ + return b.current==b.last; +} + +template +inline constexpr bool operator!=(basic_http_line_generator& b,::std::default_sentinel_t) +{ + return b.current!=b.last; +} + +template +inline constexpr basic_http_line operator*(basic_http_line_generator& b) noexcept +{ + return {::fast_io::manipulators::os_str_known_size_without_null_terminated(b.current,static_cast(b.key_end-b.current)),::fast_io::manipulators::os_str_known_size_without_null_terminated(b.value_start,static_cast(b.value_end-b.value_start))}; +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/igenerator.h b/src/fast_io/include/fast_io_core_impl/igenerator.h new file mode 100644 index 0000000..6f2b2c8 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/igenerator.h @@ -0,0 +1,111 @@ +#pragma once + +namespace fast_io +{ + +template +struct basic_input_buffer_iterator +{ + input *ptr{}; +}; + +namespace details +{ +template +constexpr basic_input_buffer_iterator& deal_with_underflow(basic_input_buffer_iterator& gen) +{ + auto& ref(*gen.ptr); + if(!ibuffer_underflow(ref))[[unlikely]] + { + gen.ptr={}; + return gen; + } + return gen; +} +} +template +inline constexpr auto operator*(basic_input_buffer_iterator& gen) +{ + return *ibuffer_curr(*gen.ptr); +} +template +inline constexpr basic_input_buffer_iterator& operator++(basic_input_buffer_iterator& gen) +{ + ibuffer_set_curr(*gen.ptr,ibuffer_curr(*gen.ptr)+1); + if constexpr(!contiguous_input_stream) + { + if(ibuffer_curr(*gen.ptr)==ibuffer_end(*gen.ptr))[[unlikely]] + return details::deal_with_underflow(gen); + } + return gen; +} + +template +inline constexpr bool operator!=(basic_input_buffer_iterator a, ::std::default_sentinel_t) +{ + if constexpr(contiguous_input_stream) + return ibuffer_curr(*a.ptr)!=ibuffer_end(*a.ptr); + else + return a.ptr; +} + +template +inline constexpr bool operator==(basic_input_buffer_iterator a, ::std::default_sentinel_t) +{ + if constexpr(contiguous_input_stream) + return ibuffer_curr(*a.ptr)==ibuffer_end(*a.ptr); + else + return a.ptr==nullptr; +} + +template +inline constexpr bool operator!=(::std::default_sentinel_t,basic_input_buffer_iterator a) +{ + if constexpr(contiguous_input_stream) + return ibuffer_curr(*a.ptr)!=ibuffer_end(*a.ptr); + else + return a.ptr; +} + +template +inline constexpr bool operator==(::std::default_sentinel_t,basic_input_buffer_iterator a) +{ + if constexpr(contiguous_input_stream) + return ibuffer_curr(*a.ptr)==ibuffer_end(*a.ptr); + else + return a.ptr==nullptr; +} + +template +struct basic_input_buffer_generator +{ + input *ptr{}; +}; + +template +inline constexpr basic_input_buffer_iterator begin(basic_input_buffer_generator a) +{ + return {a.ptr}; +} + +template +inline constexpr ::std::default_sentinel_t end(basic_input_buffer_generator) +{ + return {}; +} + +template +inline constexpr basic_input_buffer_generator igenerator(input& in) +{ + if constexpr(!contiguous_input_stream) + { + if(ibuffer_curr(in)==ibuffer_end(in))[[unlikely]] + { + if(!ibuffer_underflow(in))[[unlikely]] + return {}; + } + } + return {__builtin_addressof(in)}; +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/integers/chrono.h b/src/fast_io/include/fast_io_core_impl/integers/chrono.h new file mode 100644 index 0000000..d5a4c98 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/integers/chrono.h @@ -0,0 +1,193 @@ +#pragma once + +/* + +Time output should strictly following ISO 8601 +2020-11-07T12:50:20Z +2023-02-07T15:53:33+08:00 + +*/ + +namespace fast_io::details +{ + +template +inline constexpr char_type* chrono_one_digit_impl(char_type* it,U uv) noexcept +{ + if constexpr(!unchecked) + { + if(10u<=uv)[[unlikely]] + return print_reserve_integral_define<10>(it,uv); + } + *it=static_cast(uv+arithmetic_char_literal_v); + ++it; + return it; +} + +template +inline constexpr char_type* chrono_two_digits_impl(char_type* it,I i) noexcept +{ + using unsigned_char_type = my_make_unsigned_t; + if constexpr(my_signed_integral) + { + my_make_unsigned_t u{static_cast>(i)}; + if(i<0)[[unlikely]] + { + u = 0u - u; + *it=char_literal_v; + ++it; + } + return chrono_two_digits_impl(it,u); + } + else + { + if constexpr(!unchecked) + { + if(100u<=i)[[unlikely]] + return print_reserve_integral_define<10>(it,i); + } + if constexpr(transparent) + { + constexpr std::uint_least8_t ten{static_cast(10u)}; + if(i; + ++it; + *it = static_cast(static_cast(static_cast(char_literal_v)+i)); + ++it; + return it; + } + } + return non_overlapped_copy_n(digits_table+(i<<1),2,it); + } +} + +template<::std::integral char_type,::std::signed_integral integ> +inline constexpr char_type* chrono_year_impl(char_type* it,integ i) noexcept +{ + using unsigned_type = my_make_unsigned_t>; + unsigned_type u{static_cast(i)}; + if(i<0)[[unlikely]] + { + u = 0u - u; + *it=char_literal_v; + ++it; + } + if(10000u<=u)[[unlikely]] + return print_reserve_integral_define<10>(it,u); + unsigned_type dv(u/100u); + unsigned_type rmd(u%100u); + constexpr auto tb{digits_table}; + it=non_overlapped_copy_n(tb+(dv<<1),2,it); + return non_overlapped_copy_n(tb+(rmd<<1),2,it); +} + +// assert(end - begin >= 2) +template <::std::integral char_type, ::std::integral T> +inline constexpr parse_code chrono_scan_two_digits_unsafe_impl(char_type const* begin, T& t) noexcept +{ + T retval{}; + auto ch{ *begin }; + if (!::fast_io::char_category::is_c_digit(ch)) [[unlikely]] + return parse_code::invalid; + retval += static_cast(ch - char_literal_v) * 10; + ++begin; + ch = *begin; + if (!::fast_io::char_category::is_c_digit(ch)) [[unlikely]] + return parse_code::invalid; + retval += static_cast(ch - char_literal_v); + t = retval; + return parse_code::ok; +} + +template <::std::integral char_type, ::std::signed_integral I> +inline constexpr parse_result chrono_scan_year_impl(char_type const* begin, char_type const* end, I& i) noexcept +{ + I retval{}; + if (end - begin < 20) [[unlikely]] + return { end, parse_code::invalid }; + [[maybe_unused]] bool sign{}; + if (*begin == char_literal_v) [[unlikely]] + { + sign = true; + ++begin; + } + auto itr{ begin }; + for (; itr < begin + 4; ++itr) + if (!details::char_is_digit<10, char_type>(*itr)) [[unlikely]] + return { itr, parse_code::invalid }; + if (details::char_is_digit<10, char_type>(*itr)) [[unlikely]] + { + auto [itr2, ec] = scan_int_contiguous_define_impl<10, true, false, false>(begin, end, retval); + if (ec != parse_code::ok) [[unlikely]] + return { itr, ec }; + begin = itr2; + } + else + { + retval += static_cast<::std::int_least64_t>(*begin++ - char_literal_v) * 1000; + retval += static_cast<::std::int_least64_t>(*begin++ - char_literal_v) * 100; + retval += static_cast<::std::int_least64_t>(*begin++ - char_literal_v) * 10; + retval += static_cast<::std::int_least64_t>(*begin++ - char_literal_v); + } + i = sign ? -retval : retval; + return { begin, parse_code::ok }; +} + +template <::std::integral char_type, my_integral T> +inline constexpr void chrono_scan_decimal_fraction_part_rounding_impl(char_type const* begin, char_type const* end, T& retval) noexcept +{ + if (*begin < char_literal_v); + else if (*begin > char_literal_v) + ++retval; + else [[unlikely]] + { + for (++begin; begin != end; ++begin) + { + // xxxxx500000x0000, then round in + if (*begin != char_literal_v) + { + ++retval; + return; + } + } + // xxxx500000, then it depends on the digit before 5 + if (retval % 2 == 1) + ++retval; + } +} + +template +inline constexpr parse_result chrono_scan_decimal_fraction_part_never_overflow_impl(char_type const* begin, char_type const* end, T& t) noexcept +{ + if (begin == end) [[unlikely]] + return { end, parse_code::invalid }; + T retval{}; + constexpr ::std::size_t digitsm1{ ::std::numeric_limits::digits10 }; + auto new_end{ begin + digitsm1 }; + if (new_end > end) new_end = end; + auto [itr, ec] = scan_int_contiguous_define_impl<10, true, false, true>(begin, new_end, retval); + if (ec != parse_code::ok) [[unlikely]] + return { itr, ec }; + if (begin == itr) [[unlikely]] + return { itr, parse_code::invalid }; + ::std::size_t zero_cnt{ digitsm1 - (itr - begin) }; + for (::std::size_t i{}; i < zero_cnt; ++i) + retval *= 10; + if constexpr (need_rounding) + { + if (itr != end && itr == new_end) [[unlikely]] + { + char_type const* digit_end{ skip_digits<10>(itr, end) }; + if (itr != digit_end) + { + chrono_scan_decimal_fraction_part_rounding_impl(itr, digit_end, retval); + itr = digit_end; + } + } + } + t = retval; + return { itr, parse_code::ok }; +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/integers/crypto_hash.h b/src/fast_io/include/fast_io_core_impl/integers/crypto_hash.h new file mode 100644 index 0000000..7083b09 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/integers/crypto_hash.h @@ -0,0 +1,631 @@ +#pragma once + +namespace fast_io +{ + +namespace details +{ + +template +inline constexpr char_type* crypto_hash_pr_df_impl(std::byte const* first,std::byte const* last,char_type* iter) noexcept +{ + constexpr auto tb{::fast_io::details::digits_table}; + constexpr std::size_t two{2}; + for(;first!=last;++first) + iter=non_overlapped_copy_n(tb+(static_cast(*first)<<1),two,iter); + return iter; +} + +template +inline void update_multiple_blocks(T* __restrict ctx,io_scatter_t const* base,std::size_t n) noexcept +{ + for(std::size_t i{};i!=n;++i) + { + io_scatter_t e{base[i]}; + ctx->update(reinterpret_cast(e.base),reinterpret_cast(e.base)+e.len); + } +} + +template +inline constexpr char_type* pr_rsv_uuid(char_type* iter,std::byte const* uuid) noexcept +{ + auto next_it{uuid+4};//4 + iter=crypto_hash_pr_df_impl(uuid,next_it,iter); + for(std::size_t i{};i!=3;++i)//2*3=6 + { + *iter=char_literal_v; + ++iter; + uuid=next_it; + next_it+=2; + iter=crypto_hash_pr_df_impl(uuid,next_it,iter); + } + *iter=char_literal_v;//6 + ++iter; + return crypto_hash_pr_df_impl(next_it,next_it+6,iter); +} + +inline constexpr std::size_t hex_encoding_prv_size_cal(std::byte const* first,std::byte const* last) noexcept +{ + std::size_t n{static_cast(last-first)}; + constexpr std::size_t mxn{std::numeric_limits::max()/2}; + if(n>mxn) + { + ::fast_io::fast_terminate(); + } + return n<<1; +} + +} + +template +struct basic_hex_encode +{ + using manip_tag = manip_tag_t; + std::byte const* reference{}; + std::byte const* last{}; +}; + +template +inline constexpr std::size_t print_reserve_size( + io_reserve_type_t>, + ::fast_io::basic_hex_encode e) noexcept +{ + return ::fast_io::details::hex_encoding_prv_size_cal(e.reference,e.last); +} + +template +inline constexpr char_type* print_reserve_define( + io_reserve_type_t>, + char_type* iter, + ::fast_io::basic_hex_encode e) noexcept +{ + return ::fast_io::details::crypto_hash_pr_df_impl(e.reference,e.last,iter); +} + +template<::std::integral ch_type,typename T> +struct basic_crypto_hash_as_file +{ + using char_type = ch_type; + using manip_tag = manip_tag_t; + using native_handle_type = T*; + T* ptr{}; +}; + +template<::std::integral ch_type,typename T> +inline constexpr basic_crypto_hash_as_file io_value_handle(basic_crypto_hash_as_file t) noexcept +{ + return t; +} + +template +inline constexpr void require_secure_clear(basic_crypto_hash_as_file) noexcept{} + +template<::std::integral ch_type,typename T,::std::integral char_type> +inline constexpr void write(basic_crypto_hash_as_file t,char_type const* first,char_type const* last) noexcept +{ +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && __cpp_lib_bit_cast >= 201806L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if (__builtin_is_constant_evaluated()) +#endif + { + for(;first!=last;++first) + { + auto a{::std::bit_cast<::fast_io::freestanding::array<::std::byte,sizeof(*first)>>(*first)}; + t.ptr->update(a.data(),a.data()+sizeof(*first)); + } + } + else +#endif + { + t.ptr->update(reinterpret_cast(first), + reinterpret_cast(last)); + } +} + +template<::std::integral ch_type,typename T> +inline void scatter_write(basic_crypto_hash_as_file t,io_scatters_t scatters) noexcept +{ + ::fast_io::details::update_multiple_blocks(t.ptr,scatters.base,scatters.len); +} + +namespace manipulators +{ + +template<::std::contiguous_iterator Iter> +requires std::is_trivially_copyable_v> +inline constexpr ::fast_io::basic_hex_encode hex_encode(Iter first,Iter last) noexcept +{ + if constexpr(std::same_as,std::byte>) + { + return {std::to_address(first),std::to_address(last)}; + } + else + { + return {reinterpret_cast(std::to_address(first)), + reinterpret_cast(std::to_address(last))}; + } +} + +template<::std::contiguous_iterator Iter> +requires std::is_trivially_copyable_v> +inline constexpr ::fast_io::basic_hex_encode hex_encode_upper(Iter first,Iter last) noexcept +{ + if constexpr(std::same_as,std::byte>) + { + return {std::to_address(first),std::to_address(last)}; + } + else + { + return {reinterpret_cast(std::to_address(first)), + reinterpret_cast(std::to_address(last))}; + } +} + +template<::std::ranges::contiguous_range rg> +requires std::is_trivially_copyable_v<::std::ranges::range_value_t> +inline constexpr ::fast_io::basic_hex_encode hex_encode(rg&& r) noexcept +{ + return hex_encode(std::to_address(std::ranges::begin(r)),std::to_address(std::ranges::end(r))); +} + +template<::std::ranges::contiguous_range rg> +requires std::is_trivially_copyable_v<::std::ranges::range_value_t> +inline constexpr ::fast_io::basic_hex_encode hex_encode_upper(rg&& r) noexcept +{ + return hex_encode_upper(std::to_address(std::ranges::begin(r)),std::to_address(std::ranges::end(r))); +} + +template +inline constexpr ::fast_io::basic_crypto_hash_as_file basic_as_file(T& hashctx) noexcept +{ + return {__builtin_addressof(hashctx)}; +} + +template +inline constexpr ::fast_io::basic_crypto_hash_as_file as_file(T& hashctx) noexcept +{ + return {__builtin_addressof(hashctx)}; +} + +template +inline constexpr ::fast_io::basic_crypto_hash_as_file was_file(T& hashctx) noexcept +{ + return {__builtin_addressof(hashctx)}; +} + +template +inline constexpr ::fast_io::basic_crypto_hash_as_file u8as_file(T& hashctx) noexcept +{ + return {__builtin_addressof(hashctx)}; +} + +template +inline constexpr ::fast_io::basic_crypto_hash_as_file u16as_file(T& hashctx) noexcept +{ + return {__builtin_addressof(hashctx)}; +} + +template +inline constexpr ::fast_io::basic_crypto_hash_as_file u32as_file(T& hashctx) noexcept +{ + return {__builtin_addressof(hashctx)}; +} + +} + +namespace manipulators +{ + +template +concept crypto_hash_context = requires(T t,std::byte* ptr) +{ + t.update(ptr,ptr); + t.do_final(); +}; + +template +concept compile_time_size_crypto_hash_context = requires(T t) +{ + std::remove_cvref_t::digest_size; +}; + +template +concept runtime_size_crypto_hash_context = requires(T t) +{ + {t.runtime_digest_size()}->::std::convertible_to; +}; + +enum class digest_format +{ +lower, +upper, +raw_bytes +}; + +template +struct hash_digest_t +{ + using manip_tag = manip_tag_t; + using reference_type = T; + reference_type reference; +}; + +template +inline constexpr hash_digest_t hash_digest(ctx const& r) noexcept +{ + return {r}; +} + +template +inline constexpr hash_digest_t hash_digest_upper(ctx const& r) noexcept +{ + return {r}; +} + +template +inline constexpr hash_digest_t hash_digest_raw_bytes(ctx const& r) noexcept +{ + return {r}; +} + +template +struct hash_compress_t +{ + using manip_tag = manip_tag_t; + using reference_type = T; + std::byte const* base{}; + std::size_t len{}; +}; + +template +requires (::std::is_trivially_copyable_v<::std::ranges::range_value_t>&&!::std::is_array_v) +inline constexpr hash_compress_t hash_compress(T const& t) noexcept +{ + if constexpr(std::same_as<::std::ranges::range_value_t,std::byte>) + { + return {::std::ranges::data(t),::std::ranges::size(t)}; + } + else + { + return {reinterpret_cast(::std::ranges::data(t)),static_cast(::std::ranges::size(t))*sizeof(::std::ranges::range_value_t)}; + } +} + +template +requires (::std::is_trivially_copyable_v<::std::ranges::range_value_t>&&!::std::is_array_v) +inline constexpr hash_compress_t hash_compress_upper(T const& t) noexcept +{ + if constexpr(std::same_as<::std::ranges::range_value_t,std::byte>) + { + return {::std::ranges::data(t),::std::ranges::size(t)}; + } + else + { + return {reinterpret_cast(::std::ranges::data(t)),static_cast(::std::ranges::size(t))*sizeof(T)}; + } +} + +template +requires (::std::is_trivially_copyable_v<::std::ranges::range_value_t>&&!::std::is_array_v) +inline constexpr hash_compress_t hash_compress_raw_bytes(T const& t) noexcept +{ + if constexpr(std::same_as<::std::ranges::range_value_t,std::byte>) + { + return {::std::ranges::data(t),::std::ranges::size(t)}; + } + else + { + return {reinterpret_cast(::std::ranges::data(t)),static_cast(::std::ranges::size(t))*sizeof(T)}; + } +} + +} + +namespace details +{ +template +concept context_digest_to_byte_ptr_runtime_impl = requires(T t,std::byte* ptr) +{ + {t.digest_to_byte_ptr(ptr)}->std::same_as; +}; + +template +concept context_digest_byte_ptr_impl = requires(T t) +{ + {t.digest_byte_ptr()}->std::same_as; +}; + +template<::fast_io::manipulators::digest_format d,std::size_t digest_size> +requires (static_cast(d)(3)) +inline constexpr std::size_t cal_crypto_hash_resrv_size() noexcept +{ + static_assert(digest_size<=SIZE_MAX/2); + constexpr std::size_t v{d==::fast_io::manipulators::digest_format::raw_bytes?digest_size:(digest_size<<1u)}; + return v; +} + +template<::fast_io::manipulators::digest_format d,std::size_t digest_size> +inline constexpr std::size_t crypto_hash_resrv_size_cache{cal_crypto_hash_resrv_size()}; + +template<::fast_io::manipulators::digest_format d,::std::integral char_type> +inline constexpr char_type* copy_to_hash_df_commom_impl(char_type* iter,std::byte const* buffer,std::size_t digest_size) noexcept +{ + if constexpr(d==::fast_io::manipulators::digest_format::raw_bytes) + { +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && __cpp_lib_bit_cast >= 201806L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if(__builtin_is_constant_evaluated()) +#endif + { + for(std::size_t i{};i!=digest_size;++i) + { + *iter=std::to_integer(buffer[i]); + ++iter; + } + return iter; + } + else +#endif + { + return ::fast_io::details::non_overlapped_copy_n(reinterpret_cast(buffer),digest_size,iter); + } + } + else + { + return ::fast_io::details::crypto_hash_pr_df_impl(buffer,buffer+digest_size,iter); + } +} + + +template<::fast_io::manipulators::digest_format d,typename T,::std::integral char_type> +inline constexpr char_type* prv_srv_hash_df_common_impl(char_type* iter,T const& t) noexcept +{ + if constexpr(::fast_io::manipulators::compile_time_size_crypto_hash_context) + { + constexpr std::size_t digest_size{std::remove_cvref_t::digest_size}; + std::byte buffer[digest_size]; + if constexpr(context_digest_to_byte_ptr_runtime_impl) + { + std::size_t diff{static_cast(t.digest_to_byte_ptr(buffer)-buffer)}; + return copy_to_hash_df_commom_impl(iter,buffer,diff); + } + else + { + t.digest_to_byte_ptr(buffer); + return copy_to_hash_df_commom_impl(iter,buffer,digest_size); + } + } + else + { + std::size_t digest_size{t.runtime_digest_size()}; + if constexpr(::fast_io::details::context_digest_byte_ptr_impl) + { + std::byte const* ptr{t.digest_byte_ptr()}; + return copy_to_hash_df_commom_impl(iter,ptr,digest_size); + } + else + { + ::fast_io::details::local_operator_new_array_ptr<::std::byte> bufferf(digest_size); + std::byte *buffer{bufferf.ptr}; + if constexpr(context_digest_to_byte_ptr_runtime_impl) + { + std::size_t diff{static_cast(t.digest_to_byte_ptr(buffer)-buffer)}; + return copy_to_hash_df_commom_impl(iter,buffer,diff); + } + else + { + t.digest_to_byte_ptr(buffer); + return copy_to_hash_df_commom_impl(iter,buffer,digest_size); + } + } + } +} + +// this function may possibly be useless because scan_freestanding will correctly deal with context_scannable +template<::fast_io::manipulators::digest_format d,typename T,::std::random_access_iterator Iter> +inline constexpr Iter prv_srv_hash_df_impl(Iter iter,T const& t) noexcept +{ + if constexpr(::std::contiguous_iterator&&!::std::is_pointer_v) + { + return ::fast_io::details::prv_srv_hash_df_impl(::std::to_address(iter),t)-::std::to_address(iter)+iter; + } + else + { + using char_type = ::std::iter_value_t; + if constexpr(d==::fast_io::manipulators::digest_format::raw_bytes) + { +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if(__builtin_is_constant_evaluated()) +#endif + { + return ::fast_io::details::prv_srv_hash_df_common_impl(iter,t); + } + else +#endif + { + if constexpr(sizeof(char_type)==1&&::std::is_pointer_v) + { + if constexpr(context_digest_to_byte_ptr_runtime_impl) + { + return t.digest_to_byte_ptr(reinterpret_cast(iter)); + } + else + { + constexpr std::size_t digest_size{std::remove_cvref_t::digest_size}; + t.digest_to_byte_ptr(reinterpret_cast(iter)); + return iter+digest_size; + } + } + else + { + return ::fast_io::details::prv_srv_hash_df_common_impl(iter,t); + } + } + } + else + { + return ::fast_io::details::prv_srv_hash_df_common_impl(iter,t); + } + } +} + +template +inline constexpr std::byte* cal_hash_internal_impl(std::byte const* base,std::size_t len,std::byte* buffer) noexcept +{ + T t; + t.update(base,base+len); + t.do_final(); + return t.digest_to_byte_ptr(buffer); +} + +template +inline constexpr void cal_hash_internal(std::byte const* base,std::size_t len,std::byte* buffer) noexcept +{ + T t; + t.update(base,base+len); + t.do_final(); + t.digest_to_byte_ptr(buffer); +} + +template<::fast_io::manipulators::digest_format d,typename T,::std::integral char_type> +inline constexpr char_type* prv_srv_hash_compress_df_impl(char_type* iter,std::byte const* base,std::size_t len) noexcept +{ + constexpr std::size_t digest_size{std::remove_cvref_t::digest_size}; + if constexpr(context_digest_to_byte_ptr_runtime_impl) + { + if constexpr(d==::fast_io::manipulators::digest_format::raw_bytes) + { +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if(__builtin_is_constant_evaluated()) +#endif + { + std::byte buffer[digest_size]; + auto ret{cal_hash_internal_impl(base,len,buffer)}; + return ::fast_io::details::copy_to_hash_df_commom_impl(buffer,iter,static_cast(ret-buffer)); + } + else +#endif + { + if constexpr(sizeof(char_type)==1) + { + return cal_hash_internal_impl(base,len,reinterpret_cast(iter)); + } + else + { + std::byte buffer[digest_size]; + auto p{cal_hash_internal_impl(base,len,buffer)}; + return ::fast_io::details::copy_to_hash_df_commom_impl(iter,buffer,static_cast(p-buffer)); + } + } + } + else + { + std::byte buffer[digest_size]; + auto p{cal_hash_internal_impl(base,len,buffer)}; + return ::fast_io::details::copy_to_hash_df_commom_impl(iter,buffer,static_cast(p-buffer)); + } + } + else + { + if constexpr(d==::fast_io::manipulators::digest_format::raw_bytes) + { +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if(__builtin_is_constant_evaluated()) +#endif + { + std::byte buffer[digest_size]; + cal_hash_internal(base,len,buffer); + return ::fast_io::details::copy_to_hash_df_commom_impl(buffer,iter,digest_size); + } + else +#endif + { + if constexpr(sizeof(char_type)==1) + { + cal_hash_internal(base,len,reinterpret_cast(iter)); + return iter+digest_size; + } + else + { + std::byte buffer[digest_size]; + cal_hash_internal(base,len,buffer); + return ::fast_io::details::copy_to_hash_df_commom_impl(iter,buffer,digest_size); + } + } + } + else + { + std::byte buffer[digest_size]; + cal_hash_internal(base,len,buffer); + return ::fast_io::details::copy_to_hash_df_commom_impl(iter,buffer,digest_size); + } + } +} + +} + +template +requires (static_cast(d)(3)) +inline constexpr std::size_t print_reserve_size(io_reserve_type_t>) noexcept +{ + return ::fast_io::details::crypto_hash_resrv_size_cache::digest_size>; +} + +template +requires (static_cast(d)(3)) +inline constexpr std::size_t print_reserve_size(io_reserve_type_t>,::fast_io::manipulators::hash_digest_t digest) noexcept +{ + if constexpr(d==::fast_io::manipulators::digest_format::raw_bytes) + { + return digest.reference.runtime_digest_size(); + } + else + { + std::size_t dgst_size{digest.reference.runtime_digest_size()}; + constexpr std::size_t half_size{SIZE_MAX/2u}; + if(dgst_size>half_size) + { + fast_terminate(); + } + return dgst_size<<1u; + } +} + +template<::fast_io::manipulators::digest_format d,::fast_io::manipulators::crypto_hash_context T,::std::integral char_type> +inline constexpr char_type* print_reserve_define( + ::fast_io::io_reserve_type_t>, + char_type* iter,::fast_io::manipulators::hash_digest_t t) noexcept +{ + return ::fast_io::details::prv_srv_hash_df_impl(iter,t.reference); +} + + +template +requires (static_cast(d)(3)) +inline constexpr std::size_t print_reserve_size(io_reserve_type_t>) noexcept +{ + return ::fast_io::details::crypto_hash_resrv_size_cache::digest_size>; +} +template<::fast_io::manipulators::digest_format d,::fast_io::manipulators::crypto_hash_context T,::std::integral char_type> +inline constexpr char_type* print_reserve_define( + ::fast_io::io_reserve_type_t>, + char_type* iter,::fast_io::manipulators::hash_compress_t t) noexcept +{ + return ::fast_io::details::prv_srv_hash_compress_df_impl(iter,t.base,t.len); +} +} diff --git a/src/fast_io/include/fast_io_core_impl/integers/digits_table.h b/src/fast_io/include/fast_io_core_impl/integers/digits_table.h new file mode 100644 index 0000000..1f33475 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/integers/digits_table.h @@ -0,0 +1,93 @@ +#pragma once + +namespace fast_io::details +{ + +template<::std::integral char_type,bool upper> +inline constexpr auto charliteralofnumber(char8_t v) noexcept +{ + if(v<10u) + { + return ::fast_io::char_literal_add(v); + } + else if constexpr(::fast_io::details::is_ebcdic) + { + if(v<19u) + { + return ::fast_io::char_literal_add(static_cast(v-UINT8_C(10))); + } + else if(v<28u) + { + return ::fast_io::char_literal_add(static_cast(v-UINT8_C(19))); + } + else + { + return ::fast_io::char_literal_add(static_cast(v-UINT8_C(28))); + } + } + else + { + return ::fast_io::char_literal_add(static_cast(v-UINT8_C(10))); + } +} + +template<::std::integral char_type,::std::size_t base,bool upper> +requires (2<=base&&base<=36) +inline constexpr auto generate_digits_table() noexcept +{ + constexpr char8_t char8base{static_cast(base)}; + constexpr + ::std::size_t n{base*base*2}; + constexpr + ::std::size_t base2{base<<1}; + ::fast_io::freestanding::array tb; + for(char8_t i{};i!=char8base;++i) + { + ::std::size_t const ibase{static_cast<::std::size_t>(i)*base2}; + auto ch0{::fast_io::details::charliteralofnumber(i)}; + for(char8_t j{};j!=char8base;++j) + { + ::std::size_t const jsz{static_cast<::std::size_t>(j)}; + ::std::size_t const ibpjsz{ibase+(jsz<<1)}; + tb[ibpjsz]=ch0; + tb[ibpjsz+1]=::fast_io::details::charliteralofnumber(j); + } + } + return tb; +} + +template<::std::integral char_type,::std::size_t base,bool upper> +inline constexpr auto digits_table_impl{generate_digits_table()}; + +template<::std::integral char_type,::std::size_t base,bool upper> +inline constexpr auto& get_digits_table() noexcept +{ + constexpr bool up{(base<=10u)?false:upper}; + if constexpr(::fast_io::details::is_ebcdic|| + (::std::same_as&&::fast_io::details::wide_is_none_utf_endian)) + { + return ::fast_io::details::digits_table_impl; + } + else if constexpr(sizeof(char_type)==sizeof(char8_t)) + { + return ::fast_io::details::digits_table_impl; + } + else if constexpr(sizeof(char_type)==sizeof(char16_t)) + { + return ::fast_io::details::digits_table_impl; + } + else if constexpr(sizeof(char_type)==sizeof(char32_t)) + { + return ::fast_io::details::digits_table_impl; + } + else + { + return ::fast_io::details::digits_table_impl; + } +} + +template<::std::integral char_type,::std::size_t base,bool upper> +requires (2<=base&&base<=36) +inline constexpr auto const *digits_table{get_digits_table().data()}; + +} diff --git a/src/fast_io/include/fast_io_core_impl/integers/impl.h b/src/fast_io/include/fast_io_core_impl/integers/impl.h new file mode 100644 index 0000000..76df652 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/integers/impl.h @@ -0,0 +1,1771 @@ +#pragma once +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC system_header +#endif + +namespace fast_io +{ + +namespace details +{ + +inline constexpr ::std::size_t method_ptr_size{sizeof(::std::size_t)*2}; + +inline constexpr ::std::size_t method_ptr_hold_size{::fast_io::details::method_ptr_size%sizeof(::std::size_t)==0? + ::fast_io::details::method_ptr_size/sizeof(::std::size_t): + ::fast_io::details::method_ptr_size/sizeof(::std::size_t)+1}; + +struct scalar_manip_detail_tag{}; + +template +concept has_scalar_manip_detail_tag = requires(scalar_type) +{ + typename ::std::remove_cvref_t::scalar_manip_detail_tag; +}; + +} + +namespace manipulators +{ + +enum class scalar_placement:char8_t +{ +none,left,middle,right,internal +}; + +enum class floating_format:char8_t +{ +fixed,general,scientific,decimal,hexfloat +}; + +enum class lc_time_flag:std::uint_least8_t +{ +none, +d_t_fmt, +d_fmt, +t_fmt, +t_fmt_ampm, +date_fmt, +era_d_t_fmt, +era_d_fmt, +era_t_fmt +}; + +struct ip_flags +{ + bool v6shorten{true}; + bool v6uppercase{}; + bool v6bracket{true}; + bool v6full{false}; + bool showport{}; +}; + +inline constexpr ip_flags ip_default_flags{.showport=true}; +inline constexpr ip_flags ip_default_inaddr_flags{}; + +template +struct ip_manip_t +{ + using value_type = T; + using manip_tag = manip_tag_t; +#if 0 + using scalar_manip_detail_tag = ::fast_io::details::scalar_manip_detail_tag; +#endif +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) + [[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) + [[no_unique_address]] +#endif +#endif + T reference; +}; + +struct ip_scan_flags +{ + bool allowv6shorten{true}; + bool allowv6uppercase{true}; + bool allowv6bracket{true}; + bool requirev6full{false}; + bool requireport{false}; +}; + +inline constexpr ip_scan_flags ip_scan_default_flags{.requireport=true}; +inline constexpr ip_scan_flags ip_scan_default_inaddr_flags{}; + +template +struct ip_scan_manip_t +{ + using value_type = T; + using manip_tag = manip_tag_t; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) + [[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) + [[no_unique_address]] +#endif +#endif + T reference; +}; + +struct scalar_flags +{ + std::size_t base{10}; + bool alphabet{}; + bool showbase{}; + bool showpos{}; + bool noskipws{}; + bool uppercase_showbase{}; + bool uppercase{}; + bool uppercase_e{}; +#if 0 + bool showpos_e{true}; +#endif + bool comma{}; + bool full{}; + scalar_placement placement{scalar_placement::none}; + floating_format floating{}; + lc_time_flag time_flag{}; +#if 0 + bool localeparse{}; +#endif + bool line{}; + +}; + +inline constexpr scalar_flags integral_default_scalar_flags{}; +inline constexpr scalar_flags floating_point_default_scalar_flags{.floating=floating_format::decimal}; +inline constexpr scalar_flags address_default_scalar_flags{.base=16,.showbase=true,.full=true}; + +template +struct scalar_manip_t +{ + using value_type = T; + using scalar_flags_type = scalar_flags; + using manip_tag = manip_tag_t; + using scalar_manip_detail_tag = ::fast_io::details::scalar_manip_detail_tag; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) + [[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) + [[no_unique_address]] +#endif +#endif + T reference; +}; + +struct member_function_pointer_holder_t +{ + using manip_tag = manip_tag_t; + ::fast_io::freestanding::array<::std::size_t, + ::fast_io::details::method_ptr_hold_size> reference; +}; + + +template +struct whole_get_t +{ + using value_type = T; + using manip_tag = manip_tag_t; + value_type reference; +}; + +} + +namespace details +{ +template +inline constexpr ::fast_io::manipulators::scalar_flags base_mani_flags_cache{.base=bs,.showbase=shbase,.showpos=showpos,.uppercase_showbase=((bs==2||bs==3||bs==16)?upper:false),.uppercase=((bs<=10)?false:upper),.full=fll}; + +template +inline constexpr ::fast_io::manipulators::scalar_flags boolalpha_mani_flags_cache{.alphabet=true,.uppercase=upper}; + +template +inline constexpr ::fast_io::manipulators::scalar_flags hexafloat_mani_flags_cache{.showbase=true,.uppercase_showbase=uppercase,.uppercase=uppercase,.uppercase_e=uppercase,.comma=comma,.floating=::fast_io::manipulators::floating_format::hexfloat}; + +template +inline constexpr ::fast_io::manipulators::scalar_flags dcmfloat_mani_flags_cache{.uppercase=uppercase,.uppercase_e=uppercase,.comma=comma,.floating=fm}; + +template +inline constexpr ::fast_io::manipulators::scalar_flags cryptohash_mani_flags_cache{.base=16,.showbase=shbase,.uppercase_showbase=uppercase,.uppercase=uppercase}; + +template +inline constexpr ::fast_io::manipulators::scalar_flags base_scan_mani_flags_cache{.base=bs,.showbase=shbase,.noskipws=noskipws,.full=skipzero}; + +template +inline constexpr ::fast_io::manipulators::ip_flags base_ip_prefix_flags_cache{.showport=shport}; + +template +struct unsigned_integer_alias_type_traits_helper +{ + using alias_type = + std::conditional_t<(sizeof(inttype)==sizeof(std::uint_least8_t)),std::uint_least8_t, + std::conditional_t<(sizeof(inttype)==sizeof(std::uint_least16_t)),std::uint_least16_t, + std::conditional_t<(sizeof(inttype)==sizeof(std::uint_least32_t)),std::uint_least32_t, + std::conditional_t<(sizeof(inttype)==sizeof(std::uint_least64_t)),std::uint_least64_t, + inttype>>>>; +}; + +template +struct signed_integer_alias_type_traits_helper +{ + using alias_type = + std::conditional_t<(sizeof(inttype)==sizeof(std::int_least8_t)),std::int_least8_t, + std::conditional_t<(sizeof(inttype)==sizeof(std::int_least16_t)),std::int_least16_t, + std::conditional_t<(sizeof(inttype)==sizeof(std::int_least32_t)),std::int_least32_t, + std::conditional_t<(sizeof(inttype)==sizeof(std::int_least64_t)),std::int_least64_t, + inttype>>>>; +}; + +template +struct integer_alias_type_traits +{ + using alias_type = + std::conditional_t, + std::conditional_t<(sizeof(inttype)::alias_type, + typename unsigned_integer_alias_type_traits_helper::alias_type>, + std::conditional_t<(sizeof(inttype)::alias_type, + typename signed_integer_alias_type_traits_helper::alias_type>>; +}; + +template +using integer_alias_type = typename integer_alias_type_traits>::alias_type; + +using uintptr_alias_type = ::fast_io::details::integer_alias_type; + +template +struct integer_full_alias_type_traits +{ + using alias_type = + std::conditional_t, + typename unsigned_integer_alias_type_traits_helper::alias_type, + typename signed_integer_alias_type_traits_helper::alias_type>; +}; + +template +using integer_full_alias_type = typename integer_full_alias_type_traits>::alias_type; + +using uintptr_full_alias_type = ::fast_io::details::integer_full_alias_type; + +template +struct float_alias_type_traits +{ + using alias_type = flt; +}; + +#ifdef __STDCPP_FLOAT64_T__ +template<> +struct float_alias_type_traits +{ + using alias_type = + std::conditional_t::is_iec559, + _Float64,double>; +}; +#endif + +#ifdef __STDCPP_FLOAT32_T__ +template<> +struct float_alias_type_traits +{ + using alias_type = + std::conditional_t::is_iec559, + _Float32,float>; +}; +#endif + +template<> +struct float_alias_type_traits +{ +#if defined(__SIZEOF_INT128__) && (defined(__STDCPP_FLOAT128_T__)||defined(__FLOAT128__)) +#ifdef __STDCPP_FLOAT128_T__ + using alias_type = _Float128; +#else + using alias_type = __float128; +#endif +#else + using alias_type = typename float_alias_type_traits::alias_type; +#endif +}; + +#if (defined(__SIZEOF_FLOAT16__) || defined(__FLOAT16__)) && defined(__STDCPP_FLOAT16_T__) +template<> +struct float_alias_type_traits<__float16> +{ + using alias_type = _Float16; +}; +#endif + +template +using float_alias_type = typename float_alias_type_traits>::alias_type; + +inline constexpr + ::fast_io::manipulators::scalar_flags compute_bool_scalar_flags_cache(::fast_io::manipulators::scalar_flags flags) noexcept +{ + flags.uppercase=false; + if(!flags.showbase) + { + flags.base=2; + flags.uppercase_showbase=false; + } + return flags; +} + +template<::fast_io::manipulators::scalar_flags cache,typename scalar_type> +inline constexpr auto scalar_flags_int_cache(scalar_type t) noexcept +{ + using scalar_type_nocvref = std::remove_cvref_t; + if constexpr(cache.full) + { + if constexpr(std::same_as) + { + return ::fast_io::manipulators::scalar_manip_t{}; + } + else if constexpr(::std::same_as) + { + return ::fast_io::manipulators::scalar_manip_t{t}; + } + else if constexpr(::std::same_as) + { + using alias_type = integer_full_alias_type; + return ::fast_io::manipulators::scalar_manip_t + {static_cast(t)}; + } + else if constexpr(::fast_io::details::my_integral) + { + using alias_type = integer_full_alias_type; + return ::fast_io::manipulators::scalar_manip_t{static_cast(t)}; + } + else if constexpr(std::is_pointer_v) + { + return ::fast_io::manipulators::scalar_manip_t{static_cast(::std::bit_cast(t))}; + } + else if constexpr(::std::same_as<::fast_io::manipulators::member_function_pointer_holder_t,scalar_type_nocvref>) + { + return ::fast_io::manipulators::scalar_manip_t{t}; + } + else if constexpr(::fast_io::details::has_scalar_manip_detail_tag) + { + return ::fast_io::manipulators::scalar_manip_t{t.reference}; + } + else + { + return ::fast_io::manipulators::scalar_manip_t{static_cast(::std::bit_cast(::std::to_address(t)))}; + } + + } + else + { + if constexpr(std::same_as) + { + return ::fast_io::manipulators::scalar_manip_t{}; + } + else if constexpr(::std::same_as) + { + return ::fast_io::manipulators::scalar_manip_t{t}; + } + else if constexpr(::std::same_as) + { + using alias_type = integer_alias_type; + return ::fast_io::manipulators::scalar_manip_t + {static_cast(t)}; + } + else if constexpr(::fast_io::details::my_integral) + { + using alias_type = integer_alias_type; + return ::fast_io::manipulators::scalar_manip_t{static_cast(t)}; + } + else if constexpr(::std::same_as<::fast_io::manipulators::member_function_pointer_holder_t,scalar_type_nocvref>) + { + return ::fast_io::manipulators::scalar_manip_t{t}; + } + else if constexpr(std::is_pointer_v) + { + return ::fast_io::manipulators::scalar_manip_t{static_cast(::std::bit_cast(t))}; + } + else if constexpr(::fast_io::details::has_scalar_manip_detail_tag) + { + return ::fast_io::manipulators::scalar_manip_t{t.reference}; + } + else + { + return ::fast_io::manipulators::scalar_manip_t{static_cast(::std::bit_cast(::std::to_address(t)))}; + } + } +} + +template +concept scalar_integrals = +::fast_io::details::my_integral|| +::std::same_as<::std::nullptr_t,::std::remove_cvref_t>|| +::std::same_as<::std::byte,::std::remove_cvref_t>|| +::std::same_as>|| +::fast_io::details::has_scalar_manip_detail_tag; + +} + +namespace manipulators +{ + +template +struct scalar_manip_precision_t +{ + using scalar_flags_type = scalar_flags; + using manip_tag = manip_tag_t; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) + [[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) + [[no_unique_address]] +#endif +#endif + T reference; + std::size_t precision; +}; + +template +struct width_t +{ + using manip_tag = manip_tag_t; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) + [[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) + [[no_unique_address]] +#endif +#endif + T reference; + std::size_t width; +}; + +template +struct width_ch_t +{ + using manip_tag = manip_tag_t; + using char_type = ch_type; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) + [[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) + [[no_unique_address]] +#endif +#endif + T reference; + std::size_t width; + char_type ch; +}; + +template +struct width_runtime_t +{ + using manip_tag = manip_tag_t; + scalar_placement placement; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) + [[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) + [[no_unique_address]] +#endif +#endif + T reference; + std::size_t width; +}; + +template +struct width_runtime_ch_t +{ + using manip_tag = manip_tag_t; + using char_type = ch_type; + scalar_placement placement; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) + [[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) + [[no_unique_address]] +#endif +#endif + T reference; + std::size_t width; + char_type ch; +}; + +template +requires ((2<=bs&&bs<=36)&&(::fast_io::details::scalar_integrals)) +inline constexpr auto base(scalar_type t) noexcept +{ + return ::fast_io::details::scalar_flags_int_cache<::fast_io::details::base_mani_flags_cache>(t); +} + +template +requires ((2<=bs&&bs<=36)&&(::fast_io::details::scalar_integrals)) +inline constexpr auto baseupper(scalar_type t) noexcept +{ + return ::fast_io::details::scalar_flags_int_cache<::fast_io::details::base_mani_flags_cache>(t); +} + + +template +requires (::fast_io::details::scalar_integrals) +inline constexpr auto hex(scalar_type t) noexcept +{ + return ::fast_io::details::scalar_flags_int_cache<::fast_io::details::base_mani_flags_cache<16,false,shbase,full>>(t); +} + +template +requires (::fast_io::details::scalar_integrals) +inline constexpr auto hexupper(scalar_type t) noexcept +{ + return ::fast_io::details::scalar_flags_int_cache<::fast_io::details::base_mani_flags_cache<16,true,shbase,full>>(t); +} + +template +requires (::fast_io::details::scalar_integrals) +inline constexpr auto hex0x(scalar_type t) noexcept +{ + return ::fast_io::details::scalar_flags_int_cache<::fast_io::details::base_mani_flags_cache<16,false,true,full>>(t); +} + +template +requires (::fast_io::details::scalar_integrals) +inline constexpr auto hex0xupper(scalar_type t) noexcept +{ + return ::fast_io::details::scalar_flags_int_cache<::fast_io::details::base_mani_flags_cache<16,true,true,full>>(t); +} + +template +requires (::fast_io::details::scalar_integrals) +inline constexpr auto uhexfull(scalar_type t) noexcept +{ + return ::fast_io::details::scalar_flags_int_cache<::fast_io::details::base_mani_flags_cache<16,false,shbase,true>>(t); +} + +template +requires (::fast_io::details::scalar_integrals) +inline constexpr auto addrvw(scalar_type t) noexcept +{ + if constexpr(::fast_io::details::my_signed_integral) + { + return ::fast_io::details::scalar_flags_int_cache<::fast_io::details::base_mani_flags_cache<16,uppercase,true,true,false>>(static_cast<::fast_io::details::my_make_unsigned_t>>(t)); + } + else + { + return ::fast_io::details::scalar_flags_int_cache<::fast_io::details::base_mani_flags_cache<16,uppercase,true,true,false>>(t); + } +} + +template +requires ((::std::is_pointer_v||::std::contiguous_iterator)&& + (!::std::is_function_v>)) +inline constexpr auto pointervw(scalar_type t) noexcept +{ + return ::fast_io::details::scalar_flags_int_cache<::fast_io::details::base_mani_flags_cache<16,uppercase,true,true,false>>(t); +} + +template +requires (::std::is_function_v) +inline constexpr auto funcvw(scalar_type *t) noexcept +{ + return ::fast_io::details::scalar_flags_int_cache<::fast_io::details::base_mani_flags_cache<16,uppercase,true,true,false>>(::std::bit_cast(t)); +} + +template +requires (::std::is_member_function_pointer_v&& +(sizeof(scalar_type)%sizeof(::std::size_t)==0)) +inline constexpr auto methodvw(scalar_type t) noexcept +{ + if constexpr(sizeof(scalar_type)==sizeof(::std::size_t)) + { + return ::fast_io::details::scalar_flags_int_cache<::fast_io::details::base_mani_flags_cache<16,uppercase,true,true,false>>(::std::bit_cast<::std::size_t>(t)); + } + else + { + return ::fast_io::details::scalar_flags_int_cache<::fast_io::details::base_mani_flags_cache<16,uppercase,true,true,false>>(::std::bit_cast<::fast_io::manipulators::member_function_pointer_holder_t>(t)); + } +} + +template +requires ((::std::is_pointer_v&&!::std::is_function_v>)|| + ::std::integral) +inline constexpr auto handlevw(scalar_type t) noexcept +{ + if constexpr(::std::integral) + { + return ::fast_io::details::scalar_flags_int_cache<::fast_io::details::base_mani_flags_cache<10,false,false,false,false>>(t); + } + else + { + return ::fast_io::details::scalar_flags_int_cache<::fast_io::details::base_mani_flags_cache<16,uppercase,true,true,false>>(t); + } +} + +template +requires (::fast_io::details::scalar_integrals) +inline constexpr auto dfvw(scalar_type t) noexcept +{ + return ::fast_io::details::scalar_flags_int_cache<::fast_io::details::base_mani_flags_cache<16,false,true,true,true>>(t); +} + +template +requires (::fast_io::details::scalar_integrals) +inline constexpr auto uhexupperfull(scalar_type t) noexcept +{ + return ::fast_io::details::scalar_flags_int_cache<::fast_io::details::base_mani_flags_cache<16,true,shbase,true>>(t); +} + +template +requires (::fast_io::details::scalar_integrals) +inline constexpr auto dec(scalar_type t) noexcept +{ + return ::fast_io::details::scalar_flags_int_cache<::fast_io::details::base_mani_flags_cache<10,false,shbase,full>>(t); +} + +template +requires (::fast_io::details::scalar_integrals) +inline constexpr auto oct(scalar_type t) noexcept +{ + return ::fast_io::details::scalar_flags_int_cache<::fast_io::details::base_mani_flags_cache<8,false,shbase,full>>(t); +} + +template +requires (::fast_io::details::scalar_integrals) +inline constexpr auto bin(scalar_type t) noexcept +{ + return ::fast_io::details::scalar_flags_int_cache<::fast_io::details::base_mani_flags_cache<2,false,shbase,full>>(t); +} + +template +requires (((2<=flags.base&&flags.base<=36&&(::fast_io::details::scalar_integrals))||(flags.base==10&&::fast_io::details::my_floating_point))) +inline constexpr auto scalar_generic(scalar_type t) noexcept +{ + if constexpr(::fast_io::details::my_floating_point) + { + using float_alias_type = ::fast_io::details::float_alias_type; + return scalar_manip_t{static_cast(t)}; + } + else + { + return ::fast_io::details::scalar_flags_int_cache(t); + } +} + +template +inline constexpr scalar_manip_t<::fast_io::details::boolalpha_mani_flags_cache,bool> boolalpha(bool b) noexcept +{ + return {b}; +} + +template +requires (::fast_io::details::my_floating_point) +inline constexpr auto hexfloat(scalar_type t) noexcept +{ + using float_alias_type = ::fast_io::details::float_alias_type; + return scalar_manip_t<::fast_io::details::hexafloat_mani_flags_cache,float_alias_type>{static_cast(t)}; +} + +template +requires (::fast_io::details::my_floating_point) +inline constexpr auto hexfloat(scalar_type t,std::size_t n) noexcept +{ + using float_alias_type = ::fast_io::details::float_alias_type; + return scalar_manip_precision_t<::fast_io::details::hexafloat_mani_flags_cache,float_alias_type>{static_cast(t),n}; +} + +template +requires (::fast_io::details::my_floating_point) +inline constexpr auto comma_hexfloat(scalar_type t) noexcept +{ + using float_alias_type = ::fast_io::details::float_alias_type; + return scalar_manip_t<::fast_io::details::hexafloat_mani_flags_cache,float_alias_type>{static_cast(t)}; +} + +template +requires (::fast_io::details::my_floating_point) +inline constexpr auto comma_hexfloat(scalar_type t,std::size_t n) noexcept +{ + using float_alias_type = ::fast_io::details::float_alias_type; + return scalar_manip_precision_t<::fast_io::details::hexafloat_mani_flags_cache,float_alias_type>{static_cast(t),n}; +} + +template +requires (::fast_io::details::my_floating_point) +inline constexpr auto decimal(scalar_type t) noexcept +{ + using float_alias_type = ::fast_io::details::float_alias_type; + return scalar_manip_t<::fast_io::details::dcmfloat_mani_flags_cache,float_alias_type>{static_cast(t)}; +} + +template +requires (::fast_io::details::my_floating_point) +inline constexpr auto comma_decimal(scalar_type t) noexcept +{ + using float_alias_type = ::fast_io::details::float_alias_type; + return scalar_manip_t<::fast_io::details::dcmfloat_mani_flags_cache,float_alias_type>{static_cast(t)}; +} + +template +requires (::fast_io::details::my_floating_point) +inline constexpr auto decimal(scalar_type t,std::size_t n) noexcept +{ + using float_alias_type = ::fast_io::details::float_alias_type; + return scalar_manip_precision_t<::fast_io::details::dcmfloat_mani_flags_cache,float_alias_type>{static_cast(t),n}; +} + +template +requires (::fast_io::details::my_floating_point) +inline constexpr auto comma_decimal(scalar_type t,std::size_t n) noexcept +{ + using float_alias_type = ::fast_io::details::float_alias_type; + return scalar_manip_precision_t<::fast_io::details::dcmfloat_mani_flags_cache,float_alias_type>{static_cast(t),n}; +} + + +template +requires (::fast_io::details::my_floating_point) +inline constexpr auto general(scalar_type t) noexcept +{ + using float_alias_type = ::fast_io::details::float_alias_type; + return scalar_manip_t<::fast_io::details::dcmfloat_mani_flags_cache,float_alias_type>{static_cast(t)}; +} + +template +requires (::fast_io::details::my_floating_point) +inline constexpr auto comma_general(scalar_type t) noexcept +{ + using float_alias_type = ::fast_io::details::float_alias_type; + return scalar_manip_t<::fast_io::details::dcmfloat_mani_flags_cache,float_alias_type>{static_cast(t)}; +} + +template +requires (::fast_io::details::my_floating_point) +inline constexpr auto general(scalar_type t,std::size_t n) noexcept +{ + using float_alias_type = ::fast_io::details::float_alias_type; + return scalar_manip_precision_t<::fast_io::details::dcmfloat_mani_flags_cache,float_alias_type>{static_cast(t),n}; +} + +template +requires (::fast_io::details::my_floating_point) +inline constexpr auto comma_general(scalar_type t,std::size_t n) noexcept +{ + using float_alias_type = ::fast_io::details::float_alias_type; + return scalar_manip_precision_t<::fast_io::details::dcmfloat_mani_flags_cache,float_alias_type>{static_cast(t),n}; +} + +template +requires (::fast_io::details::my_floating_point) +inline constexpr auto fixed(scalar_type t) noexcept +{ + using float_alias_type = ::fast_io::details::float_alias_type; + return scalar_manip_t<::fast_io::details::dcmfloat_mani_flags_cache,float_alias_type>{static_cast(t)}; +} + +template +requires (::fast_io::details::my_floating_point) +inline constexpr auto comma_fixed(scalar_type t) noexcept +{ + using float_alias_type = ::fast_io::details::float_alias_type; + return scalar_manip_t<::fast_io::details::dcmfloat_mani_flags_cache,float_alias_type>{static_cast(t)}; +} + + +template +requires (::fast_io::details::my_floating_point) +inline constexpr auto fixed(scalar_type t,std::size_t n) noexcept +{ + using float_alias_type = ::fast_io::details::float_alias_type; + return scalar_manip_precision_t<::fast_io::details::dcmfloat_mani_flags_cache,float_alias_type>{static_cast(t),n}; +} + +template +requires (::fast_io::details::my_floating_point) +inline constexpr auto comma_fixed(scalar_type t,std::size_t n) noexcept +{ + using float_alias_type = ::fast_io::details::float_alias_type; + return scalar_manip_precision_t<::fast_io::details::dcmfloat_mani_flags_cache,float_alias_type>{static_cast(t),n}; +} + +template +requires (::fast_io::details::my_floating_point) +inline constexpr auto scientific(scalar_type t) noexcept +{ + using float_alias_type = ::fast_io::details::float_alias_type; + return scalar_manip_t<::fast_io::details::dcmfloat_mani_flags_cache,float_alias_type>{static_cast(t)}; +} + +template +requires (::fast_io::details::my_floating_point) +inline constexpr auto comma_scientific(scalar_type t) noexcept +{ + using float_alias_type = ::fast_io::details::float_alias_type; + return scalar_manip_t<::fast_io::details::dcmfloat_mani_flags_cache,float_alias_type>{static_cast(t)}; +} + +template +requires (::fast_io::details::my_floating_point) +inline constexpr auto scientific(scalar_type t,std::size_t n) noexcept +{ + using float_alias_type = ::fast_io::details::float_alias_type; + return scalar_manip_precision_t<::fast_io::details::dcmfloat_mani_flags_cache,float_alias_type>{static_cast(t),n}; +} + +template +requires (::fast_io::details::my_floating_point) +inline constexpr auto comma_scientific(scalar_type t,std::size_t n) noexcept +{ + using float_alias_type = ::fast_io::details::float_alias_type; + return scalar_manip_precision_t<::fast_io::details::dcmfloat_mani_flags_cache,float_alias_type>{static_cast(t),n}; +} + +} + +namespace details +{ + +template +inline constexpr auto generate_base_prefix_array() noexcept +{ + static_assert(2<=base&&base<=36); + if constexpr(base<10) + { + //0[9]0000 + return ::fast_io::freestanding::array{char_literal_v,char_literal_v, + ::fast_io::char_literal_add(base),char_literal_v}; + } + else + { + constexpr char8_t decade{static_cast(static_cast(base)/static_cast(10u))}, + unit{static_cast(static_cast(base)%static_cast(10u))}; + return ::fast_io::freestanding::array{char_literal_v,char_literal_v, + ::fast_io::char_literal_add(decade), + ::fast_io::char_literal_add(unit), + char_literal_v}; + } +} + +template +inline constexpr auto base_prefix_array{generate_base_prefix_array()}; + +template +constexpr char_type* print_reserve_show_base_impl(char_type* iter) +{ + static_assert(2<=base&&base<=36); + if constexpr(base==2) + { + if constexpr(uppercase_showbase) + { + if constexpr(std::same_as) + iter=copy_string_literal("0B",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(L"0B",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(u"0B",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(U"0B",iter); + else + iter=copy_string_literal(u8"0B",iter); + } + else + { + if constexpr(std::same_as) + iter=copy_string_literal("0b",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(L"0b",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(u"0b",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(U"0b",iter); + else + iter=copy_string_literal(u8"0b",iter); + } + } + else if constexpr(base==3) + { + if constexpr(uppercase_showbase) + { + if constexpr(std::same_as) + iter=copy_string_literal("0T",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(L"0T",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(u"0T",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(U"0T",iter); + else + iter=copy_string_literal(u8"0T",iter); + } + else + { + if constexpr(std::same_as) + iter=copy_string_literal("0t",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(L"0t",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(u"0t",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(U"0t",iter); + else + iter=copy_string_literal(u8"0t",iter); + } + } + else if constexpr(base==8) + { + *iter=char_literal_v; + ++iter; + } + else if constexpr(base==16) + { + if constexpr(uppercase_showbase) + { + if constexpr(std::same_as) + iter=copy_string_literal("0X",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(L"0X",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(u"0X",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(U"0X",iter); + else + iter=copy_string_literal(u8"0X",iter); + } + else + { + if constexpr(std::same_as) + iter=copy_string_literal("0x",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(L"0x",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(u"0x",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(U"0x",iter); + else + iter=copy_string_literal(u8"0x",iter); + } + } + else if constexpr(base!=10) + { + constexpr auto arr{base_prefix_array}; + constexpr std::size_t sz{arr.size()}; + iter=non_overlapped_copy_n(arr.data(),sz,iter); + } + return iter; +} + +template +constexpr void print_reserve_integral_main_impl(char_type* iter,T t,std::size_t len) +{ + if constexpr(base<=10&&uppercase) + { + print_reserve_integral_main_impl(iter,t,len);//prevent duplications + } + else if constexpr(need_seperate_print) + { + constexpr std::size_t basetdigits{::fast_io::details::cal_max_int_size()}; + constexpr std::size_t sizetdigits{::fast_io::details::cal_max_int_size()}; + static_assert(basetdigits!=0&&sizetdigits!=0); + if constexpr(base==2||base==4||base==16) + { + optimal_print_unsigned_type high; + optimal_print_unsigned_type low{::fast_io::details::intrinsics::unpack_generic(t,high)}; + if(len>sizetdigits) + { + print_reserve_integral_main_impl(iter-sizetdigits,high,len-sizetdigits); + len=sizetdigits; + } + print_reserve_integral_main_impl(iter,low,len); + } + else + { + constexpr std::size_t sizetdigitsm1{sizetdigits-1}; + constexpr std::size_t remain_digits{basetdigits-sizetdigitsm1*2}; + constexpr T maxhighdigits{compile_pow10}; + if constexpr(!ryu_mode&&remain_digits!=0) + { + static_assert(remain_digits<3); + if constexpr(remain_digits==1) + { + if(len==basetdigits) + { + T high{t/maxhighdigits}; + t=t%maxhighdigits; + *(iter-basetdigits)=::fast_io::char_literal_add(high); + --len; + } + } + else + { + constexpr std::size_t least_digits{basetdigits-remain_digits}; + if(len>least_digits) + { + T high{t/maxhighdigits}; + t=t%maxhighdigits; + std::uint_least8_t rem{static_cast(high)}; + if(len==basetdigits) + { + constexpr auto tb{::fast_io::details::digits_table}; + non_overlapped_copy_n(tb+(rem<<1),2,iter-basetdigits); + len-=2u; + } + else + { + *(iter+1-basetdigits)=::fast_io::char_literal_add(high); + --len; + } + } + } + } + optimal_print_unsigned_type low; + if(len>sizetdigitsm1) + { + constexpr T halfdigits{compile_pow10}; + optimal_print_unsigned_type high{static_cast(t/halfdigits)}; + low=static_cast(t%halfdigits); + print_reserve_integral_main_impl(iter-sizetdigitsm1,high,len-sizetdigitsm1); + len=sizetdigitsm1; + } + else + { + low=static_cast(t); + } + print_reserve_integral_main_impl(iter,low,len); + } + } + else + { + if constexpr(ryu_mode) + { + print_reserve_integral_main_impl(iter,t,len); + } + else + { + constexpr auto tb{::fast_io::details::digits_table}; + constexpr T pw{static_cast(base*base)}; + std::size_t const len2{len>>static_cast(1u)}; + for(std::size_t i{};i!=len2;++i) + { + auto const rem{t%pw}; + t/=pw; + non_overlapped_copy_n(tb+(rem<<1),2,iter-=2); + } + if((len&1)) + { + if constexpr(base<=10) + { + *--iter=::fast_io::char_literal_add(t); + } + else + { + *--iter=static_cast(tb[(t<<1)+1]); + } + } + } + } +} + +template +constexpr char_type* print_reserve_integral_withfull_main_impl(char_type* first,T u) +{ + if constexpr(base<=10&&uppercase) + { + return print_reserve_integral_withfull_main_impl(first,u);//prevent duplications + } + else + { + if constexpr(full) + { + constexpr std::size_t sz{::fast_io::details::cal_max_int_size()}; + if constexpr(sizeof(u)<=sizeof(unsigned)) + print_reserve_integral_main_impl(first+=sz,static_cast(u),sz); + else + print_reserve_integral_main_impl(first+=sz,u,sz); + return first; + } + else + { + if constexpr(base==10&&(std::numeric_limits::digits==32u)) + { + if constexpr(false) + { + return ::fast_io::details::uprsv::uprsv_main(first,u); + } + else + { + return ::fast_io::details::jeaiii::jeaiii_main(first,u); + } + } + else + { + std::size_t const sz{chars_len(u)}; + if constexpr(sizeof(u)<=sizeof(unsigned)) + print_reserve_integral_main_impl(first+=sz,static_cast(u),sz); + else + print_reserve_integral_main_impl(first+=sz,u,sz); + return first; + } + } + + } +} + +template +inline constexpr void print_reserve_integral_withfull_precise_main_impl(char_type* last,T u,std::size_t n) +{ + + if constexpr(sizeof(u)<=sizeof(unsigned)&&sizeof(unsigned)<=sizeof(std::size_t)) + print_reserve_integral_main_impl(last,static_cast(u),n); + else + { + print_reserve_integral_main_impl(last,u,n); + } +} + +template +constexpr char_type* print_reserve_integral_define(char_type* first,int_type t) +{ + if constexpr(base<=10&&uppercase) + { + return print_reserve_integral_define(first,t);//prevent duplications + } + else + { + static_assert((2<=base)&&(base<=36)); + if constexpr(std::same_as>) + { + if constexpr(showpos) + { + *first=char_literal_v; + ++first; + } + if constexpr(showbase&&(base!=10)) + first=print_reserve_show_base_impl(first); + *first=t?char_literal_v:char_literal_v; + ++first; + return first; + } + else + { + using unsigned_type = ::fast_io::details::my_make_unsigned_t; + unsigned_type u{static_cast(t)}; + if constexpr(showpos) + { + if constexpr(::fast_io::details::my_unsigned_integral) + { + *first=char_literal_v; + } + else + { + if(t<0) + { + *first=char_literal_v; + constexpr unsigned_type zero{}; + u=zero-u; + } + else + { + *first=char_literal_v; + } + } + ++first; + } + else + { + if constexpr(::fast_io::details::my_signed_integral) + { + if(t<0) + { + *first=char_literal_v; + ++first; + constexpr unsigned_type zero{}; + u=zero-u; + } + } + } + if constexpr(showbase&&(base!=10)) + first=print_reserve_show_base_impl(first); + return print_reserve_integral_withfull_main_impl(first,u); + } + } +} + +template +constexpr void print_reserve_integral_define_precise(char_type* start,std::size_t n,int_type t) +{ + if constexpr(base<=10&&uppercase) + { + return print_reserve_integral_define_precise(start,n,t);//prevent duplications + } + else + { + auto first{start}; + static_assert((2<=base)&&(base<=36)); + if constexpr(std::same_as>) + { + if constexpr(showpos) + { + *first=char_literal_v; + ++first; + } + if constexpr(showbase&&(base!=10)) + first=print_reserve_show_base_impl(first); + *first=t?char_literal_v:char_literal_v; + ++first; + return first; + } + else + { + using unsigned_type = ::fast_io::details::my_make_unsigned_t; + unsigned_type u{static_cast(t)}; + if constexpr(showpos) + { + if constexpr(::fast_io::details::my_unsigned_integral) + { + *first=char_literal_v; + } + else + { + if(t<0) + { + *first=char_literal_v; + constexpr unsigned_type zero{}; + u=zero-u; + } + else + { + *first=char_literal_v; + } + } + ++first; + } + else + { + if constexpr(::fast_io::details::my_signed_integral) + { + if(t<0) + { + *first=char_literal_v; + ++first; + constexpr unsigned_type zero{}; + u=zero-u; + } + } + } + if constexpr(showbase&&(base!=10)) + first=print_reserve_show_base_impl(first); + if constexpr(base==10&&(std::numeric_limits::digits==32u)) + { + return ::fast_io::details::jeaiii::jeaiii_main_len(first,u,static_cast(n)); + } + else + { + auto ed{start+n}; + if constexpr(my_unsigned_integral&&!showbase&&!showpos) + print_reserve_integral_withfull_precise_main_impl(ed,u,n); + else + print_reserve_integral_withfull_precise_main_impl(ed,u,static_cast(ed-first)); + } + } + } +} + +template< +std::size_t base=10, +bool showbase=false, +bool showpos=false, +my_integral T> +inline constexpr std::size_t print_reserve_scalar_size_impl() +{ + std::size_t total_sum{}; + if constexpr(showpos) + ++total_sum; + if constexpr(showbase) + { + if constexpr(base==2||base==3||base==16) + total_sum+=2; //0b 0t 0x + else if constexpr(base==8) + ++total_sum; //0 + else if constexpr(base<10) + total_sum+=4; //0[9] + else if constexpr(10,bool>) + ++total_sum; + else + { + if constexpr(!showpos) + { + if constexpr(my_signed_integral) + ++total_sum; + } + total_sum+=::fast_io::details::cal_max_int_size(); + } + return total_sum; +} + + +template +inline constexpr std::size_t print_integer_reserved_size_cache{print_reserve_scalar_size_impl()}; + + +template< +std::size_t base, +bool showbase, +bool showpos, +bool full, +my_integral T> +inline constexpr std::size_t print_reserve_scalar_cal_precise_cache_size_impl() +{ + std::size_t total_sum{}; + if constexpr(showpos) + ++total_sum; + if constexpr(showbase) + { + if constexpr(base==2||base==3||base==16) + total_sum+=2; //0b 0t 0x + else if constexpr(base==8) + ++total_sum; //0 + else if constexpr(base<10) + total_sum+=4; //0[9] + else if constexpr(10,bool>) + ++total_sum; + else + { + if constexpr(!showpos) + { + if constexpr(my_signed_integral) + ++total_sum; + } + total_sum+=::fast_io::details::cal_max_int_size(); + } + } + } + return total_sum; +} + +template +inline constexpr std::size_t print_integer_reserved_precise_size_cache{print_reserve_scalar_cal_precise_cache_size_impl()}; + + +template< +std::size_t base, +bool showbase, +bool showpos, +bool full, +my_integral T> +inline constexpr std::size_t print_integer_reserved_precise_size(T t) +{ + if constexpr(std::same_as,bool>) + return print_integer_reserved_size_cache; + else if constexpr(full) + { + if constexpr(!showpos&&my_signed_integral) + { + std::size_t total_sum{print_integer_reserved_precise_size_cache}; + if(t<0) + ++total_sum; + return total_sum; + } + else + return print_integer_reserved_precise_size_cache; + } + else + { + std::size_t total_sum{print_integer_reserved_precise_size_cache}; + if constexpr(my_signed_integral) + { + using unsigned_type = my_make_unsigned_t; + unsigned_type u{static_cast(t)}; + if(t<0) + { + ++total_sum; + constexpr unsigned_type zero{}; + u=static_cast(zero-u); + } + return total_sum+chars_len(u); + } + else + { + return total_sum+chars_len(t); + } + } +} + +template +inline constexpr std::size_t nullptr_print_optimization_call_size_impl() noexcept +{ + ::fast_io::freestanding::array> arr; + auto res{print_reserve_integral_define(arr.data(),std::uintptr_t{})}; + return static_cast(res-arr.data()); +} + +template +inline constexpr std::size_t nullptr_print_optimization_call_size_cache{ + nullptr_print_optimization_call_size_impl()}; + +template +inline constexpr auto nullptr_print_optimization_call_impl() noexcept +{ + constexpr std::size_t sz{nullptr_print_optimization_call_size_cache}; + ::fast_io::freestanding::array arr{}; + auto res{print_reserve_integral_define(arr.data(),std::uintptr_t{})}; + return arr; +} + +template +inline constexpr auto nullptr_print_optimization_call_cache{nullptr_print_optimization_call_impl()}; + +template +inline constexpr char_type* print_reserve_boolalpha_impl(char_type* iter,bool b) +{ + if(b) + { + if constexpr(std::same_as) + { + if constexpr(uppercase) + return copy_string_literal("TRUE",iter); + else + return copy_string_literal("true",iter); + } + else if constexpr(std::same_as) + { + if constexpr(uppercase) + return copy_string_literal(L"TRUE",iter); + else + return copy_string_literal(L"true",iter); + } + else if constexpr(std::same_as) + { + if constexpr(uppercase) + return copy_string_literal(u"TRUE",iter); + else + return copy_string_literal(u"true",iter); + } + else if constexpr(std::same_as) + { + if constexpr(uppercase) + return copy_string_literal(U"TRUE",iter); + else + return copy_string_literal(U"true",iter); + } + else + { + if constexpr(uppercase) + return copy_string_literal(u8"TRUE",iter); + else + return copy_string_literal(u8"true",iter); + } + } + else + { + if constexpr(std::same_as) + { + if constexpr(uppercase) + return copy_string_literal("FALSE",iter); + else + return copy_string_literal("false",iter); + } + else if constexpr(std::same_as) + { + if constexpr(uppercase) + return copy_string_literal(L"FALSE",iter); + else + return copy_string_literal(L"false",iter); + } + else if constexpr(std::same_as) + { + if constexpr(uppercase) + return copy_string_literal(u"FALSE",iter); + else + return copy_string_literal(u"false",iter); + } + else if constexpr(std::same_as) + { + if constexpr(uppercase) + return copy_string_literal(U"FALSE",iter); + else + return copy_string_literal(U"false",iter); + } + else + { + if constexpr(uppercase) + return copy_string_literal(u8"FALSE",iter); + else + return copy_string_literal(u8"false",iter); + } + } +} + +template +inline constexpr char_type* print_reserve_nullptr_alphabet_impl(char_type* iter) +{ + if constexpr(std::same_as) + { + if constexpr(uppercase) + return copy_string_literal("NULLPTR",iter); + else + return copy_string_literal("nullptr",iter); + } + else if constexpr(std::same_as) + { + if constexpr(uppercase) + return copy_string_literal(L"NULLPTR",iter); + else + return copy_string_literal(L"nullptr",iter); + } + else if constexpr(std::same_as) + { + if constexpr(uppercase) + return copy_string_literal(u"NULLPTR",iter); + else + return copy_string_literal(u"nullptr",iter); + } + else if constexpr(std::same_as) + { + if constexpr(uppercase) + return copy_string_literal(U"NULLPTR",iter); + else + return copy_string_literal(U"nullptr",iter); + } + else + { + if constexpr(uppercase) + return copy_string_literal(u8"NULLPTR",iter); + else + return copy_string_literal(u8"nullptr",iter); + } +} + + +template +inline constexpr char_type* print_reserve_method_impl(char_type* iter,::fast_io::manipulators::member_function_pointer_holder_t mfph) +{ + if constexpr(base<=10&&uppercase) + { + return print_reserve_method_impl(iter,mfph);//prevent duplications + } + else if constexpr(::fast_io::details::method_ptr_hold_size==0) + return iter; + else + { + iter=details::print_reserve_integral_define(iter,mfph.reference.front()); + using myssizet = ::std::make_signed_t<::std::size_t>; + if constexpr(::fast_io::details::method_ptr_hold_size==2) + { + ::std::size_t backptr{mfph.reference.back()}; + return details::print_reserve_integral_define(iter,static_cast(backptr)); + } + else + { + + ::std::size_t last{::fast_io::details::method_ptr_hold_size}; + for(::std::size_t i{1};i!=last;++i) + { + iter=details::print_reserve_integral_define(iter,static_cast(mfph.reference[i])); + } + return iter; + } + } +} + +} + +template +requires (details::my_integral||::fast_io::details::my_floating_point||std::same_as>) +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr auto print_alias_define(io_alias_t,scalar_type t) noexcept +{ + if constexpr(details::my_integral) + { + using int_alias_type = ::fast_io::details::integer_alias_type; + return manipulators::scalar_manip_t{static_cast(t)}; + } + else if constexpr(details::my_floating_point) + { + using float_alias_type = ::fast_io::details::float_alias_type; + return manipulators::scalar_manip_t{static_cast(t)}; + } + else + { + return manipulators::scalar_manip_t{}; + } +} + +template +requires (details::my_integral||std::same_as,std::byte>) +inline constexpr std::size_t print_reserve_size(io_reserve_type_t) noexcept +{ + if constexpr(std::same_as,std::byte>) + return details::print_integer_reserved_size_cache<10,false,false,char8_t>; + else + return details::print_integer_reserved_size_cache<10,false,false,std::remove_cvref_t>; +} + +template<::std::integral char_type,typename T> +requires (details::my_integral||std::same_as,std::byte>) +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]]//always inline to reduce inline depth in GCC and LLVM clang +#endif +inline constexpr char_type* print_reserve_define(io_reserve_type_t, char_type* iter,T t) noexcept +{ + if constexpr(std::same_as,std::byte>) + return details::print_reserve_integral_define<10,false,false,false,false,false>(iter,static_cast(t)); + else + return details::print_reserve_integral_define<10,false,false,false,false,false>(iter,t); +} + +template +requires (details::my_integral||std::same_as<::std::remove_cv_t,std::byte>||std::same_as,std::nullptr_t>|| +::std::same_as<::std::remove_cv_t,::fast_io::manipulators::member_function_pointer_holder_t>) +inline constexpr std::size_t print_reserve_size(io_reserve_type_t>) noexcept +{ + if constexpr(flags.alphabet) + { + static_assert((std::same_as,bool>||std::same_as,std::nullptr_t>),"only bool and std::nullptr_t support alphabet output"); + if constexpr(std::same_as,bool>) + return 5; // u8"false" + else + return 7; // u8"nullptr" + } + else if constexpr(::std::same_as<::std::remove_cv_t,::fast_io::manipulators::member_function_pointer_holder_t>) + { + constexpr + ::std::size_t method_size{(details::print_integer_reserved_size_cache+1)*::fast_io::details::method_ptr_hold_size-1}; + return method_size; + } + else if constexpr(::std::same_as,std::nullptr_t>) + return details::nullptr_print_optimization_call_size_cache; + else if constexpr(::std::same_as,::std::byte>) + return details::print_integer_reserved_size_cache; + else + return details::print_integer_reserved_size_cache; +} + +template<::std::integral char_type,manipulators::scalar_flags flags,typename T> +requires (details::my_integral||std::same_as,std::byte>||std::same_as,std::nullptr_t>|| +::std::same_as<::std::remove_cv_t,::fast_io::manipulators::member_function_pointer_holder_t>) +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]]//always inline to reduce inline depth in GCC and LLVM clang +#endif +constexpr char_type* print_reserve_define(io_reserve_type_t>, char_type* iter,::fast_io::manipulators::scalar_manip_t t) noexcept +{ + if constexpr(flags.alphabet) + { + static_assert((std::same_as,bool>||std::same_as,std::nullptr_t>),"only bool and std::nullptr_t support alphabet output"); + if constexpr(std::same_as,bool>) + return details::print_reserve_boolalpha_impl(iter,t.reference); + else + return details::print_reserve_nullptr_alphabet_impl(iter); + } + else if constexpr(::std::same_as<::std::remove_cv_t,::fast_io::manipulators::member_function_pointer_holder_t>) + { + return ::fast_io::details::print_reserve_method_impl(iter,t.reference); + } + else if constexpr(std::same_as,std::nullptr_t>) + { + constexpr auto& cache{details::nullptr_print_optimization_call_cache}; + constexpr std::size_t n{cache.size()}; + return details::non_overlapped_copy_n(cache.element,n,iter); + } + else if constexpr(std::same_as,std::byte>) + return details::print_reserve_integral_define(iter,static_cast(t.reference)); + else + return details::print_reserve_integral_define(iter,t.reference); +} + + +template +requires ((details::my_integral||std::same_as,std::byte>) && !flags.alphabet) +inline constexpr std::size_t print_reserve_precise_size(io_reserve_type_t>,manipulators::scalar_manip_t t) noexcept +{ + if constexpr(std::same_as) + return details::print_integer_reserved_precise_size(static_cast(t.reference)); + else + return details::print_integer_reserved_precise_size(t.reference); +} + +template +requires ((details::my_integral||std::same_as,std::byte>) && !flags.alphabet) +inline constexpr void print_reserve_precise_define(io_reserve_type_t>,Iter iter,std::size_t n,manipulators::scalar_manip_t t) noexcept +{ + if constexpr(std::same_as) + details::print_reserve_integral_define_precise(iter,n,static_cast(t.reference)); + else + details::print_reserve_integral_define_precise(iter,n,t.reference); +} + +template +requires ((details::my_integral||std::same_as,std::byte>) && !flags.alphabet&&( + flags.showpos||(details::my_signed_integral&&!std::same_as,bool>) +)) +inline constexpr std::size_t print_define_internal_shift(io_reserve_type_t>,manipulators::scalar_manip_t t) noexcept +{ + if constexpr(flags.showpos) + { + return 1; + } + else + { + return t.reference<0; + } +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/integers/integer.h b/src/fast_io/include/fast_io_core_impl/integers/integer.h new file mode 100644 index 0000000..4592ba5 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/integers/integer.h @@ -0,0 +1,9 @@ +#pragma once + +#include"digits_table.h" +#include"match.h" +#include"jeaiii_method.h" +#include"uprsv/impl.h" +#include"impl.h" +#include"pointer.h" +#include"crypto_hash.h" diff --git a/src/fast_io/include/fast_io_core_impl/integers/jeaiii_method.h b/src/fast_io/include/fast_io_core_impl/integers/jeaiii_method.h new file mode 100644 index 0000000..3b18a47 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/integers/jeaiii_method.h @@ -0,0 +1,612 @@ +#pragma once + +/* +Algorithm: JEAIII +Author: jeaiii +*/ + +namespace fast_io::details::jeaiii +{ + +template +inline constexpr void jeaiii_w(char_type* iter,std::uint_fast32_t u) noexcept +{ + constexpr + auto const *digitstb{digits_table}; + constexpr + ::std::size_t tocopybytes{sizeof(char_type)*2u}; + ::fast_io::details::intrinsics::typed_memcpy(iter,digitstb+(u<<1),tocopybytes); +} + +template +inline constexpr std::uint_least64_t jeaiii_a(char_type* iter,std::uint_least32_t u) noexcept +{ + constexpr std::uint_least64_t one{1}; + constexpr std::uint_least64_t v{n/5*n*53/16}; + constexpr std::uint_least64_t constant{(one<<(32+v))/ + ::fast_io::details::compile_pow10+1+n/6-n/8}; + std::uint_least64_t t{constant*u}; + t>>=v; + constexpr std::uint_least64_t add_factor{n/6*4}; + if constexpr(add_factor!=0u) + t+=add_factor; + jeaiii_w(iter,static_cast(t>>32u)); + return t; +} + +template +inline constexpr void jeaiii_s(char_type* iter,std::uint_least64_t t) noexcept +{ + constexpr std::uint_least64_t ten{10u}; + iter[n]=::fast_io::char_literal_add((ten*static_cast(t))>>32u); +} + +template +inline constexpr auto jeaiii_d(char_type* iter,std::uint_least64_t t) noexcept +{ + constexpr std::uint_least64_t hundred{100u}; + jeaiii_w(iter+n,static_cast((t=hundred*static_cast(t))>>32)); + if constexpr(!last) + return t; +} + + +template +inline constexpr void jeaiii_c(char_type* iter,std::uint_least32_t u) noexcept +{ + if constexpr(n==0) + { + *iter=::fast_io::char_literal_add(u); + } + else if constexpr(n==1) + { + jeaiii_w(iter,u); + } + else if constexpr(n==2) + { + jeaiii_s<2>(iter,jeaiii_a<1>(iter,u)); + } + else if constexpr(n==3) + { + jeaiii_d<2,true>(iter,jeaiii_a<2>(iter,u)); + } + else if constexpr(n==4) + { + jeaiii_s<4>(iter,jeaiii_d<2>(iter,jeaiii_a<3>(iter,u))); + } + else if constexpr(n==5) + { + jeaiii_d<4,true>(iter,jeaiii_d<2>(iter,jeaiii_a<4>(iter,u))); + } + else if constexpr(n==6) + { + jeaiii_s<6>(iter,jeaiii_d<4>(iter,jeaiii_d<2>(iter,jeaiii_a<5>(iter,u)))); + } + else if constexpr(n==7) + { + jeaiii_d<6,true>(iter,jeaiii_d<4>(iter,jeaiii_d<2>(iter,jeaiii_a<6>(iter,u)))); + } + else if constexpr(n==8) + { + std::uint_least64_t t{jeaiii_a<7>(iter,u)}; + t=jeaiii_d<2>(iter,t); + t=jeaiii_d<4>(iter,t); + t=jeaiii_d<6>(iter,t); + jeaiii_s<8>(iter,t); + } + else if constexpr(n==9) + { + std::uint_least64_t t{jeaiii_a<8>(iter,u)}; + t=jeaiii_d<2>(iter,t); + t=jeaiii_d<4>(iter,t); + t=jeaiii_d<6>(iter,t); + jeaiii_d<8,true>(iter,t); + } +} + +template +inline constexpr char_type* jeaiii_f(char_type* iter,std::uint_least32_t u) noexcept +{ + constexpr std::size_t np1{n+1}; + jeaiii_c(iter,u); + return iter+np1; +} + +template +inline constexpr char_type* jeaiii_tree(char_type* iter,std::uint_least32_t u) noexcept +{ + static_assert(left<=right); +/* +binary search tree +*/ +#if 0 + if constexpr(left==0&&right==9) + { + if(u<::fast_io::details::compile_pow10) + { + if(u<::fast_io::details::compile_pow10) + { + *iter=::fast_io::char_literal_add(u); + return iter+1; + } + else + { + return jeaiii_f<1>(iter,u); + } + } + else if(u<::fast_io::details::compile_pow10) + { + if(u<::fast_io::details::compile_pow10) + { + if(u<::fast_io::details::compile_pow10) + { + return jeaiii_f<2>(iter,u); + } + else + { + return jeaiii_f<3>(iter,u); + } + } + else if(u<::fast_io::details::compile_pow10) + { + return jeaiii_f<4>(iter,u); + } + else + { + return jeaiii_f<5>(iter,u); + } + } + else if(u<::fast_io::details::compile_pow10) + { + if(u<::fast_io::details::compile_pow10) + { + return jeaiii_f<6>(iter,u); + } + else + { + return jeaiii_f<7>(iter,u); + } + } + else + { + if(u<::fast_io::details::compile_pow10) + { + return jeaiii_f<8>(iter,u); + } + else + { + return jeaiii_f<9>(iter,u); + } + } + } + else +#endif + { + if constexpr(left==right) + { + return jeaiii_f(iter,u); + } + else if constexpr(left+1==right) + { + if(u<(::fast_io::details::compile_pow10)) + { + return jeaiii_f(iter,u); + } + else + { + return jeaiii_f(iter,u); + } + } + else if constexpr(left+2==right) + { + if(u<(::fast_io::details::compile_pow10)) + { + return jeaiii_f(iter,u); + } + else + { + return jeaiii_tree(iter,u); + } + } + else if constexpr(left==0) + { + if(u<100u) + { + return jeaiii_tree<0,1>(iter,u); + } + else + { + return jeaiii_tree<2,right>(iter,u); + } + } + else + { + constexpr std::size_t middle{(left+right)/2}; + if(u<(::fast_io::details::compile_pow10)) + { + return jeaiii_tree(iter,u); + } + else + { + return jeaiii_tree(iter,u); + } + } + } +} + +template +inline constexpr char_type* jeaiii_main(char_type* iter,U n) noexcept +{ + if constexpr(sizeof(U)>sizeof(std::uint_least64_t)&&sizeof(U)==16)//__uint128_t + { + if(static_cast(n>>64u)==0) + { + return jeaiii_main(iter,static_cast(n)); + } + constexpr std::uint_least64_t divisor{10000000000000000000ull}; + U a{n/divisor}; + std::uint_least64_t u{static_cast(n%divisor)}; + std::uint_least64_t alow{static_cast(a)}; + if constexpr(ryu_mode) + { + iter=jeaiii_main(iter,static_cast(alow)); + } + else + { + if(a!=static_cast(alow)) + { + std::uint_least32_t v{static_cast(a/divisor)}; + std::uint_least64_t m{static_cast(a%divisor)}; + jeaiii_c<0>(iter,v); + ++iter; + alow=m; + iter=jeaiii_main(iter,static_cast(alow)); + } + else + { + iter=jeaiii_main(iter,static_cast(alow)); + } + } + return jeaiii_main(iter,static_cast(u)); + } + else if constexpr(sizeof(U)==sizeof(std::uint_least64_t)) + { + constexpr std::uint_least32_t divisor{1000000000u}; + if constexpr(recursive) + { + std::uint_least64_t high{n/divisor}; + std::uint_least32_t low{static_cast(n%divisor)}; + std::uint_least32_t high_first{static_cast(high/divisor)}; + std::uint_least32_t high_low{static_cast(high%divisor)}; + jeaiii_c<0>(iter,high_first); + ++iter; + iter=jeaiii_f<8>(jeaiii_f<8>(iter,high_low),low); + } + else + { + if(static_cast(n>>32u)==0) + { + return jeaiii_tree<0,9>(iter,static_cast(n)); + } + std::uint_least64_t a{n/divisor}; + std::uint_least32_t u{static_cast(n%divisor)}; + std::uint_least32_t alow{static_cast(a)}; + if constexpr(ryu_mode) + { + iter=jeaiii_tree<0,7>(iter,alow); + } + else + { + if(a!=static_cast(alow)) + { + std::uint_least32_t v{static_cast(a/divisor)}; + alow=static_cast(a%divisor); + if(v<10u) + { + jeaiii_c<0>(iter,v); + ++iter; + } + else + { + jeaiii_w(iter,v); + iter+=2; + } + iter=jeaiii_f<8>(iter,alow); + } + else + { + iter=jeaiii_tree<0,9>(iter,alow); + } + } + iter=jeaiii_f<8>(iter,u); + } + return iter; + } + else + { + static_assert(!recursive); + if constexpr(ryu_mode) + { + return jeaiii_tree<0,8>(iter,n); + } + else + { + return jeaiii_tree<0,9>(iter,n); + } + } +} + +template +inline constexpr void jeaiii_hash(char_type* iter,std::uint_least32_t u,std::uint_least32_t len) noexcept +{ + if constexpr(n==7) + { + switch(len) + { + case 1: + { + jeaiii_c<0>(iter,u); + return; + } + case 2: + { + jeaiii_c<1>(iter,u); + return; + } + case 3: + { + jeaiii_c<2>(iter,u); + return; + } + case 4: + { + jeaiii_c<3>(iter,u); + return; + } + case 5: + { + jeaiii_c<4>(iter,u); + return; + } + case 6: + { + jeaiii_c<5>(iter,u); + return; + } + case 7: + { + jeaiii_c<6>(iter,u); + return; + } + default: + { + jeaiii_c<7>(iter,u); + return; + } + } + } + else if constexpr(n==8) + { + switch(len) + { + case 1: + { + jeaiii_c<0>(iter,u); + return; + } + case 2: + { + jeaiii_c<1>(iter,u); + return; + } + case 3: + { + jeaiii_c<2>(iter,u); + return; + } + case 4: + { + jeaiii_c<3>(iter,u); + return; + } + case 5: + { + jeaiii_c<4>(iter,u); + return; + } + case 6: + { + jeaiii_c<5>(iter,u); + return; + } + case 7: + { + jeaiii_c<6>(iter,u); + return; + } + case 8: + { + jeaiii_c<7>(iter,u); + return; + } + default: + { + jeaiii_c<8>(iter,u); + return; + } + } + } + else if constexpr(n==9) + { + switch(len) + { + case 1: + { + jeaiii_c<0>(iter,u); + return; + } + case 2: + { + jeaiii_c<1>(iter,u); + return; + } + case 3: + { + jeaiii_c<2>(iter,u); + return; + } + case 4: + { + jeaiii_c<3>(iter,u); + return; + } + case 5: + { + jeaiii_c<4>(iter,u); + return; + } + case 6: + { + jeaiii_c<5>(iter,u); + return; + } + case 7: + { + jeaiii_c<6>(iter,u); + return; + } + case 8: + { + jeaiii_c<7>(iter,u); + return; + } + case 9: + { + jeaiii_c<8>(iter,u); + return; + } + default: + { + jeaiii_c<9>(iter,u); + return; + } + } + } + else + { + static_assert(n==SIZE_MAX,"no supported"); + } +} + +template +inline constexpr void jeaiii_main_len(char_type* iter,U n,std::uint_least32_t len) noexcept +{ + if constexpr(sizeof(U)>sizeof(std::uint_least64_t)&&sizeof(U)==16)//__uint128_t + { + if(static_cast(n>>64u)==0) + { + return jeaiii_main_len(iter,static_cast(n),len); + } + constexpr std::uint_least32_t full_length{19u}; + constexpr std::uint_least64_t divisor{10000000000000000000ull}; + U a{n/divisor}; + std::uint_least64_t u{static_cast(n%divisor)}; + std::uint_least64_t alow{static_cast(a)}; + if constexpr(ryu_mode) + { + iter=jeaiii_main_len(iter,static_cast(alow),len-full_length); + } + else + { + if(a!=static_cast(alow)) + { + std::uint_least32_t v{static_cast(a/divisor)}; + std::uint_least64_t m{static_cast(a%divisor)}; + jeaiii_c<0>(iter,v); + ++iter; + alow=m; + jeaiii_main_len(iter,static_cast(alow),full_length); + iter+=full_length; + } + else + { + std::uint_least32_t len_sub{len-full_length}; + jeaiii_main_len(iter,static_cast(alow),len_sub); + iter+=len_sub; + } + } + jeaiii_main_len(iter,static_cast(u),full_length); + } + else if constexpr(sizeof(U)==sizeof(std::uint_least64_t)) + { + constexpr std::uint_least32_t full_length{9u}; + constexpr std::uint_least32_t divisor{1000000000u}; + if constexpr(recursive) + { + std::uint_least64_t high{n/divisor}; + std::uint_least32_t low{static_cast(n%divisor)}; + std::uint_least32_t high_first{static_cast(high/divisor)}; + std::uint_least32_t high_low{static_cast(high%divisor)}; + jeaiii_c<0>(iter,high_first); + ++iter; + iter=jeaiii_f<8>(jeaiii_f<8>(iter,high_low),low); + } + else + { + if(static_cast(n>>32u)==0) + { + return jeaiii_hash<9>(iter,static_cast(n),len); + } + std::uint_least64_t a{n/divisor}; + std::uint_least32_t u{static_cast(n%divisor)}; + std::uint_least32_t alow{static_cast(a)}; + if constexpr(ryu_mode) + { + std::uint_least32_t len_sub{len-full_length}; + jeaiii_hash<7>(iter,alow,len_sub); + iter+=len_sub; + } + else + { + if(a!=static_cast(alow)) + { + std::uint_least32_t v{static_cast(a/divisor)}; + alow=static_cast(a%divisor); + if(v<10u) + { + jeaiii_c<0>(iter,v); + ++iter; + } + else + { + jeaiii_w(iter,v); + iter+=2; + } + jeaiii_f<8>(iter,alow); + iter+=full_length; + } + else + { + std::uint_least32_t len_sub{len-full_length}; + jeaiii_hash<9>(iter,alow,len_sub); + iter+=len_sub; + } + } + jeaiii_f<8>(iter,u); + } + } + else + { + static_assert(!recursive); + if constexpr(ryu_mode) + { + jeaiii_hash<8>(iter,n,len); + } + else + { + jeaiii_hash<9>(iter,n,len); + } + } +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/integers/match.h b/src/fast_io/include/fast_io_core_impl/integers/match.h new file mode 100644 index 0000000..44d9096 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/integers/match.h @@ -0,0 +1,82 @@ +#pragma once + +namespace fast_io +{ + +namespace manipulators +{ +template +struct basic_matcher_t +{ + using manip_tag = manip_tag_t; + T reference; +}; +} + +struct match_context +{ + std::size_t matched{}; +}; + +namespace details +{ + +template<::std::input_iterator Iter> +inline +#if __cpp_lib_is_constant_evaluated >= 201811 +constexpr +#endif +parse_result match_context_impl(std::size_t& matched,Iter first,Iter last,::std::iter_value_t const* base,std::size_t len) noexcept +{ + auto base_ed{base+len-matched}; + auto [first_it,base_it]=::fast_io::freestanding::my_mismatch(first,last,base,base_ed); + matched+=static_cast(base_it-base); + if(first_it==last) + { + if(base_it!=base_ed) + return {first_it,parse_code::partial}; + } + else if(base_it!=base_ed) + return {first_it,parse_code::invalid}; + return {first_it,parse_code::ok}; +} + +} + +template +inline constexpr io_type_t scan_context_type(io_reserve_type_t>>) noexcept +{ + return {}; +} + +template<::std::input_iterator Iter> +inline constexpr parse_result scan_context_define(io_reserve_type_t<::std::iter_value_t,manipulators::basic_matcher_t>>>,match_context& ctx,Iter first,Iter last,manipulators::basic_matcher_t>> t) noexcept +{ + return details::match_context_impl(ctx.matched,first,last,t.reference.base,t.reference.len); +} + +template +inline constexpr parse_code scan_context_eof_define(io_reserve_type_t>>,match_context,manipulators::basic_matcher_t>) noexcept +{ + return parse_code::end_of_file; +} +template +requires(n!=0) +inline constexpr manipulators::basic_matcher_t> scan_alias_define(io_alias_t,char_type const(&s)[n]) noexcept +{ + return {{s,n-1}}; +} + +#if 0 +namespace manipulators +{ +template +//requires (std::integral>) +inline constexpr manipulators::basic_matcher_t>> mtvw(rg&& r) noexcept +{ + return {{std::ranges::data(r),std::ranges::size(r)}}; +} +} +#endif + +} diff --git a/src/fast_io/include/fast_io_core_impl/integers/optimize_size/impl.h b/src/fast_io/include/fast_io_core_impl/integers/optimize_size/impl.h new file mode 100644 index 0000000..7c71a43 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/integers/optimize_size/impl.h @@ -0,0 +1,143 @@ +#pragma once + +namespace fast_io::details +{ + +namespace optimize_size +{ + +namespace with_length +{ +template +inline constexpr void output_unsigned(char_type* str,U value,::std::size_t const len) noexcept +{ + using unsigned_char_type = std::make_unsigned_t; + str+=len; + for(std::size_t i{};i!=len;++i) + { + U const temp(value/base); + char_type const res(value%base); + --str; + if constexpr(base<=10) + { + if constexpr(::fast_io::details::is_ebcdic) + *str=0xF0+res; + else + *str=u8'0'+res; + } + else + { + if constexpr(::fast_io::details::is_ebcdic) + { + if(res<10) + *str=0xF0+res; + else + { + if constexpr(base<=19) + { + if constexpr(uppercase) + *str=(0xC1-10)+res; + else + *str=(0x81-10)+res; + } + else if constexpr(base<=28) + { + if(res<19) + { + if constexpr(uppercase) + *str=(0xC1-10)+res; + else + *str=(0x81-10)+res; + } + else + { + if constexpr(uppercase) + *str=(0xD1-19)+res; + else + *str=(0x91-19)+res; + } + } + else + { + if(res<19) + { + if constexpr(uppercase) + *str=(0xC1-10)+res; + else + *str=(0x81-10)+res; + } + else if(res<28) + { + if constexpr(uppercase) + *str=(0xD1-19)+res; + else + *str=(0x91-19)+res; + } + else + { + if constexpr(uppercase) + *str=(0xE2-28)+res; + else + *str=(0xA2-28)+res; + } + } + } + } + else + { + if(res<10) + *str=u8'0'+res; + else + { + if constexpr(uppercase) + *str=(u8'A'-10)+res; + else + *str=(u8'a'-10)+res; + } + } + } + if constexpr(::std::same_as&&::fast_io::details::wide_is_none_utf_endian) + { + *str=static_cast(::fast_io::details::byte_swap(static_cast(*str))); + } + value = temp; + } +} +} + + + +template +inline constexpr void output_unsigned_dummy(char_type* str,U value) noexcept +{ + if constexpr(sizeof(U)<=sizeof(unsigned)) + with_length::output_unsigned(str,static_cast(value),len); + else + with_length::output_unsigned(str,value,len); +} + +template +inline constexpr std::size_t output_unsigned(char_type* str,U value) noexcept +{ + std::size_t const len{chars_len(value)}; + if constexpr(sizeof(U)<=sizeof(unsigned)) + with_length::output_unsigned(str,static_cast(value),len); + else + with_length::output_unsigned(str,value,len); + return len; +} + +template +inline constexpr char_type* output_unsigned_full(char_type* str,uint_type value) noexcept +{ + constexpr std::size_t len{cal_max_int_size()}; + if constexpr(sizeof(uint_type)<=sizeof(unsigned)) + with_length::output_unsigned(str,static_cast(value),len); + else + with_length::output_unsigned(str,value,len); + return str+len; +} + +} + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_core_impl/integers/pointer.h b/src/fast_io/include/fast_io_core_impl/integers/pointer.h new file mode 100644 index 0000000..99b30ce --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/integers/pointer.h @@ -0,0 +1,252 @@ +#pragma once + +namespace fast_io +{ + + +/* +we do not accept char const* since we never know whether it has null terminator. +This avoids security vulneralbilities for + char * str = 0; + print(str); +Instead, we print out its pointer value + +We extend print pointers to print contiguous_iterator. No we can write things like + +std::vector vec(100,2); +println("vec.begin():",fast_io::mnp::funcvw(vec.begin())," vec.end()",fast_io::mnp::funcvw(vec.end())); +*/ +namespace manipulators +{ +template +struct chvw_t +{ + using manip_tag = manip_tag_t; + T reference; +}; + +template<::std::integral ch_type,::std::size_t N> +struct small_scatter_t +{ + using manip_tag = manip_tag_t; + ch_type const* base{}; + std::size_t len{}; +}; + +template +inline constexpr chvw_t chvw(T ch) noexcept +{ + return {ch}; +} + +template +inline constexpr basic_io_scatter_t print_alias_define(io_alias_t,basic_os_c_str bas) noexcept +{ + auto ptr{bas.ptr}; + return {ptr,::fast_io::cstr_len(ptr)}; +} + +template +inline constexpr basic_io_scatter_t print_alias_define(io_alias_t,basic_os_c_str_with_known_size bas) noexcept +{ + return {bas.ptr,bas.n}; +} + +template +inline constexpr basic_io_scatter_t print_alias_define(io_alias_t,basic_os_str_known_size_without_null_terminated bas) noexcept +{ + return {bas.ptr,bas.n}; +} + +template +inline constexpr basic_os_c_str_with_known_size os_c_str(T const* ch,std::size_t n) noexcept +{ + return {ch,::fast_io::cstr_nlen(ch,n)}; +} + + +template<::std::integral char_type,::std::size_t n> +requires (n!=0) +inline constexpr basic_os_c_str_with_known_size os_c_str_arr(char_type const (&cstr)[n]) noexcept +{ + return os_c_str(cstr,n); +} + +template<::std::integral char_type,::std::size_t n> +requires (n!=0) +inline constexpr auto small_scatter(char_type const (&s)[n]) noexcept +{ + constexpr bool not_char_literal{::std::is_const_v}; + if constexpr(not_char_literal) + { + constexpr std::size_t nm1{n-1}; + constexpr std::size_t boundary{64},boundaryp1{boundary+1}; + if constexpr(n==2) + return manipulators::chvw_t>{*s}; + else if constexpr(n,boundary>{s,nm1}; + } + else + return basic_io_scatter_t>{s,nm1}; + } + else + { +static_assert(not_char_literal,"The type is an array but not char array literal. Reject."); + return; + } +} + +template +inline constexpr void os_c_str(decltype(nullptr),std::size_t) noexcept=delete; + +template<::std::contiguous_iterator Iter> +requires ::std::integral<::std::iter_value_t> +inline constexpr basic_io_scatter_t<::std::remove_cvref_t<::std::iter_value_t>> strvw(Iter first,Iter last) noexcept +{ + return {::std::to_address(first),static_cast(last-first)}; +} + +template<::std::ranges::contiguous_range rg> +requires ::std::integral<::std::ranges::range_value_t> +inline constexpr basic_io_scatter_t<::std::remove_cvref_t<::std::ranges::range_value_t>> strvw(rg&& r) noexcept +{ + return {::std::ranges::data(r),::std::ranges::size(r)}; +} + +template<::std::ranges::contiguous_range rg> +requires (::std::integral<::std::ranges::range_value_t>) +inline constexpr basic_os_c_str_with_known_size<::std::remove_cvref_t<::std::ranges::range_value_t>> os_c_str(rg&& r) noexcept +{ + auto p{::std::ranges::data(r)}; + return {p,::fast_io::cstr_nlen(p,::std::ranges::size(r))}; +} + +template +requires (::std::is_enum_v) +inline constexpr ::std::underlying_type_t enum_int_view(enumtype enm) noexcept +{ + return static_cast<::std::underlying_type_t>(enm); +} + +} + +template +inline constexpr basic_io_scatter_t print_scatter_define(io_reserve_type_t>,basic_io_scatter_t iosc) noexcept +{ + return iosc; +} + +namespace details +{ + +template +struct my_constant_passer +{ + using value_type = T; + static inline constexpr ::std::size_t value{N}; +}; + +template<::std::integral char_type,::std::size_t n> +inline consteval my_constant_passer compute_char_literal_array_type(char_type (&)[n]) noexcept +{ + return {}; +} + +} + +template +requires (::std::is_array_v<::std::remove_reference_t>&& + ::std::integral<::std::remove_extent_t<::std::remove_cvref_t>>&& + requires(T const& s) + { + ::fast_io::details::compute_char_literal_array_type(s); + }) +inline constexpr auto print_alias_define(io_alias_t,T const& s) noexcept +{ + using constanttype = decltype(::fast_io::details::compute_char_literal_array_type(s)); + using char_type = typename constanttype::value_type; + using no_const_char_type = ::std::remove_const_t; + + constexpr bool not_char_literal{::std::is_const_v}; + constexpr + ::std::size_t n{constanttype::value}; + constexpr std::size_t nm1{n-1}; +static_assert(n!=0); +static_assert(not_char_literal,"The type is an array but not char array literal. Reject."); + + if constexpr(n==2) + { + return manipulators::chvw_t{*s}; + } + else + { + return basic_io_scatter_t{s,nm1}; + } +} + +template +requires (::std::ranges::contiguous_range&&requires(T&& t) +{ + t.substr(); +}) +inline constexpr basic_io_scatter_t<::std::remove_cvref_t<::std::ranges::range_value_t>> print_alias_define(io_alias_t,T&& svw) noexcept +{ + return {::std::ranges::data(svw),::std::ranges::size(svw)}; +} + +template +inline constexpr std::size_t print_reserve_size(io_reserve_type_t>) noexcept +{ + return 1; +} + +template +inline constexpr char_type* print_reserve_define(io_reserve_type_t>,char_type* iter,T ch) noexcept +{ + using unsigned_char_type = std::make_unsigned_t; + *iter=static_cast(static_cast(ch.reference)); + return ++iter; +} + +template +inline constexpr std::size_t print_reserve_size(io_reserve_type_t>) noexcept +{ + return N; +} + +namespace details +{ + +template +inline constexpr char_type* small_scatter_print_reserve_define_impl(char_type* iter,char_type const* base,std::size_t len) noexcept +{ + return ::fast_io::details::non_overlapped_copy_n(base,len,iter); +} + +} + +template +inline constexpr char_type* print_reserve_define(io_reserve_type_t>, + char_type* iter, + ::fast_io::manipulators::small_scatter_t scatter) noexcept +{ + + return ::fast_io::details::small_scatter_print_reserve_define_impl(iter,scatter.base,scatter.len); +} + +template +inline constexpr std::size_t print_reserve_precise_size(io_reserve_type_t>, + ::fast_io::manipulators::small_scatter_t scatter) noexcept +{ + return scatter.len; +} + +template +inline constexpr char_type* print_reserve_precise_define(io_reserve_type_t>, + char_type* iter,::std::size_t,::fast_io::manipulators::small_scatter_t scatter) noexcept +{ + return ::fast_io::details::small_scatter_print_reserve_define_impl(iter,scatter.base,scatter.len); +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/integers/sto/sto_contiguous.h b/src/fast_io/include/fast_io_core_impl/integers/sto/sto_contiguous.h new file mode 100644 index 0000000..5dc69c1 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/integers/sto/sto_contiguous.h @@ -0,0 +1,1327 @@ +#pragma once +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning(push) +#pragma warning( disable : 4061 ) +#endif +#include"sto_generate_base_tb.h" + +namespace fast_io +{ + +namespace details +{ + +inline constexpr bool sto_use_table{true}; + +template +requires (2<=base&&base<=36) +inline constexpr bool char_digit_to_literal(my_make_unsigned_t& ch) noexcept +{ + using unsigned_char_type = my_make_unsigned_t; + constexpr bool ebcdic{::fast_io::details::is_ebcdic}; + if constexpr(::std::same_as&&::fast_io::details::wide_is_none_utf_endian) + { + ch=static_cast(::fast_io::byte_swap(static_cast(ch))); + } + if constexpr(base<=10) + { + constexpr unsigned_char_type base_char_type(base); + if constexpr(ebcdic) + ch-=static_cast(240); + else + ch-=static_cast(u8'0'); + return base_char_type<=ch; + } + else + { + if constexpr(sto_use_table) + { + constexpr char8_t mx{std::numeric_limits::max()}; + constexpr bool use_partial{mx<(std::numeric_limits::max())||std::numeric_limits::digits!=8}; + if constexpr(use_partial) + { + constexpr std::size_t n{sto_base_tb.size()}; + static_assert(n<=mx); + constexpr char8_t v{static_cast(n)}; + if(v[static_cast(ch)]}; + if(ret==mx) + { + return true; + } + ch=static_cast(ret); + return false; + } + else if constexpr(ebcdic) + { + + if constexpr(base<=19) + { + constexpr unsigned_char_type mns{base-10}; + unsigned_char_type ch2(ch); + ch2-=0xC1; + unsigned_char_type ch3(ch); + ch3-=0x81; + ch-=0xF0; + if(ch2(10); + else if(ch3(10); + else if(10<=ch) + return true; + return false; + } + else if constexpr(base<=28) + { + constexpr unsigned_char_type mns{base-19}; + unsigned_char_type ch2(ch); + ch2-=0xC1; + unsigned_char_type ch3(ch); + ch3-=0x81; + unsigned_char_type ch4(ch); + ch2-=0xD1; + unsigned_char_type ch5(ch); + ch3-=0x91; + ch-=0xF0; + if(ch4(19); + else if(ch5(19); + else if(ch2<9) + ch=ch2+static_cast(10); + else if(ch3<9) + ch=ch3+static_cast(10); + else if(10<=ch) + return true; + return false; + } + else + { + constexpr unsigned_char_type mns{base-27}; + unsigned_char_type ch2(ch); + ch2-=0xC1; + unsigned_char_type ch3(ch); + ch3-=0x81; + unsigned_char_type ch4(ch); + ch4-=0xD1; + unsigned_char_type ch5(ch); + ch5-=0x91; + unsigned_char_type ch6(ch); + ch6-=0xE2; + unsigned_char_type ch7(ch); + ch7-=0xA2; + ch-=0xF0; + if(ch6(27); + else if(ch7(27); + else if(ch4<9) + ch=ch4+static_cast(19); + else if(ch5<9) + ch=ch5+static_cast(19); + else if(ch2<9) + ch=ch2+static_cast(10); + else if(ch3<9) + ch=ch3+static_cast(10); + else if(10<=ch) + return true; + return false; + } + } + else + { + constexpr unsigned_char_type mns{base-10}; + unsigned_char_type ch2(ch); + ch2-=u8'A'; + unsigned_char_type ch3(ch); + ch3-=u8'a'; + ch-=u8'0'; + if(ch2(10); + else if(ch3(10); + else if(10<=ch) + return true; + return false; + } + } +} + +template +requires (2<=base&&base<=36) +inline constexpr bool char_is_digit(my_make_unsigned_t ch) noexcept +{ + using unsigned_char_type = my_make_unsigned_t; + constexpr bool ebcdic{::fast_io::details::is_ebcdic}; + constexpr unsigned_char_type base_char_type(base); + if constexpr(::std::same_as&&::fast_io::details::wide_is_none_utf_endian) + { + ch=static_cast(::fast_io::byte_swap(static_cast(ch))); + } + if constexpr(base<=10) + { + if constexpr(ebcdic) + ch-=static_cast(240); + else + ch-=static_cast(u8'0'); + return ch::max()}; + constexpr bool use_partial{mx<(std::numeric_limits::max())||std::numeric_limits::digits!=8}; + if constexpr(use_partial) + { + constexpr std::size_t n{sto_base_tb.size()}; + static_assert(n<=mx); + constexpr char8_t v{static_cast(n)}; + if(v[static_cast(ch)]}; + if(ret==mx) + { + return false; + } + return true; + } + else if constexpr(ebcdic) + { + if constexpr(base<=19) + { + constexpr unsigned_char_type mns{base-10}; + unsigned_char_type ch2(ch); + ch2-=0xC1; + unsigned_char_type ch3(ch); + ch3-=0x81; + ch-=0xF0; + return (ch2 +inline constexpr char_type const* find_none_zero_simd_impl(char_type const* first,char_type const* last) noexcept; + +struct simd_parse_result +{ + std::size_t digits; + fast_io::parse_code code; +}; + +inline constexpr char unsigned simd16_shift_table[32]{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, +0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; + +#if defined(__SSE4_1__) && defined(__x86_64__) + +template +inline std::uint_least32_t detect_length(char unsigned const* buffer) noexcept +{ + constexpr char8_t zero_constant{char_execharset?static_cast('0'):u8'0'}; + constexpr char8_t v176_constant{static_cast((zero_constant+static_cast(128))&255u)}; +#if (defined(__GNUC__) || defined(__clang__)) && !defined(__INTEL_COMPILER) + using namespace fast_io::intrinsics; + x86_64_v16qu chunk; + __builtin_memcpy(__builtin_addressof(chunk),buffer,16); + x86_64_v16qu const v176{v176_constant,v176_constant,v176_constant,v176_constant,v176_constant,v176_constant,v176_constant,v176_constant, + v176_constant,v176_constant,v176_constant,v176_constant,v176_constant,v176_constant,v176_constant,v176_constant}; + x86_64_v16qu const t0{chunk-v176}; + x86_64_v16qs const minus118{-118, -118, -118, -118, -118, -118, -118, -118, -118, -118, -118, -118, -118, -118, -118, -118}; + x86_64_v16qs const mask{(x86_64_v16qs)t0(__builtin_ia32_pmovmskb128((x86_64_v16qi)mask))}; +#else + __m128i chunk = _mm_loadu_si128(reinterpret_cast<__m128i const*>(buffer)); + __m128i const t0 = _mm_sub_epi8(chunk, _mm_set1_epi8(v176_constant)); + __m128i const mask = _mm_cmplt_epi8(t0, _mm_set1_epi8(-118)); + std::uint_least16_t v{static_cast(_mm_movemask_epi8(mask))}; +#endif + return static_cast(std::countr_one(v)); +} + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline std::size_t sse_skip_long_overflow_digits(char unsigned const* buffer,char unsigned const* buffer_end) noexcept +{ + auto it{buffer+16}; + for(;16<=buffer_end-it;it+=16) + { + auto new_length{detect_length(it)}; + if(new_length!=16) + return static_cast(it-buffer+new_length); + }; + if(buffer_end==it) + return static_cast(it-buffer); + return static_cast(buffer_end-buffer+detect_length(buffer_end-16)); +} + +template +#if __has_cpp_attribute(__gnu__::__hot__) +[[__gnu__::__hot__]] +#endif +inline simd_parse_result sse_parse(char unsigned const* buffer,char unsigned const* buffer_end,std::uint_least64_t &res) noexcept +{ + constexpr char8_t zero_constant{char_execharset?static_cast('0'):u8'0'}; + constexpr char8_t v176_constant{static_cast((zero_constant+static_cast(128))&255u)}; + using fast_io::parse_code; +#if (defined(__GNUC__) || defined(__clang__)) && !defined(__INTEL_COMPILER) + using namespace fast_io::intrinsics; + x86_64_v16qu chunk; + __builtin_memcpy(__builtin_addressof(chunk),buffer,16); + x86_64_v16qu const v176{v176_constant,v176_constant,v176_constant,v176_constant,v176_constant,v176_constant,v176_constant,v176_constant, + v176_constant,v176_constant,v176_constant,v176_constant,v176_constant,v176_constant,v176_constant,v176_constant}; + x86_64_v16qu const t0{chunk-v176}; + x86_64_v16qs const minus118{-118, -118, -118, -118, -118, -118, -118, -118, -118, -118, -118, -118, -118, -118, -118, -118}; + x86_64_v16qs const mask{(x86_64_v16qs)t0(__builtin_ia32_pmovmskb128((x86_64_v16qi)mask))}; + std::uint_least32_t digits{static_cast(std::countr_one(v))}; + if(digits==0) + return {0,parse_code::invalid}; + x86_64_v16qu const zeros{zero_constant,zero_constant,zero_constant,zero_constant,zero_constant,zero_constant,zero_constant,zero_constant, + zero_constant,zero_constant,zero_constant,zero_constant,zero_constant,zero_constant,zero_constant,zero_constant}; + chunk-=zeros; + x86_64_v16qi shuffle_mask; + __builtin_memcpy(__builtin_addressof(shuffle_mask),simd16_shift_table+digits,sizeof(x86_64_v16qi)); + chunk=(x86_64_v16qu)__builtin_ia32_pshufb128((x86_64_v16qi)chunk,shuffle_mask); + chunk=(x86_64_v16qu)__builtin_ia32_pmaddubsw128((x86_64_v16qi)chunk,x86_64_v16qi{10,1,10,1,10,1,10,1,10,1,10,1,10,1,10,1}); + chunk=(x86_64_v16qu)__builtin_ia32_pmaddwd128((x86_64_v8hi)chunk,x86_64_v8hi{100,1,100,1,100,1,100,1}); + chunk=(x86_64_v16qu)__builtin_ia32_packusdw128((x86_64_v4si)chunk,(x86_64_v4si)chunk); + chunk=(x86_64_v16qu)__builtin_ia32_pmaddwd128((x86_64_v8hi)chunk,x86_64_v8hi{10000,1,10000,1,0,0,0,0}); + std::uint_least64_t chunk0; + __builtin_memcpy(__builtin_addressof(chunk0),__builtin_addressof(chunk),sizeof(chunk0)); +#else + __m128i chunk = _mm_loadu_si128(reinterpret_cast<__m128i const*>(buffer)); + __m128i const t0 = _mm_sub_epi8(chunk, _mm_set1_epi8(v176_constant)); + __m128i const mask = _mm_cmplt_epi8(t0, _mm_set1_epi8(-118)); + std::uint_least16_t v{static_cast(_mm_movemask_epi8(mask))}; + std::uint_least32_t digits{static_cast(std::countr_one(v))}; + if(digits==0) + return {0,parse_code::invalid}; + chunk = _mm_sub_epi8(chunk, _mm_set1_epi8(zero_constant)); + chunk = _mm_shuffle_epi8(chunk,_mm_loadu_si128(reinterpret_cast<__m128i const*>(simd16_shift_table+digits))); + chunk = _mm_maddubs_epi16(chunk, _mm_set_epi8(1,10,1,10,1,10,1,10,1,10,1,10,1,10,1,10)); + chunk = _mm_madd_epi16(chunk, _mm_set_epi16(1,100,1,100,1,100,1,100)); + chunk = _mm_packus_epi32(chunk, chunk); + chunk = _mm_madd_epi16(chunk,_mm_set_epi16(0,0,0,0,1,10000,1,10000)); + std::uint_least64_t chunk0; + std::memcpy(__builtin_addressof(chunk0),__builtin_addressof(chunk),sizeof(chunk0)); +#endif + std::uint_least64_t result{static_cast(((chunk0 & 0xffffffff) * UINT64_C(100000000)) + (chunk0 >> 32))}; + if(digits==16)[[unlikely]] + { + if constexpr(less_than_64_bits) + { + //std::uint_least32_t can never have 16 digits + return {sse_skip_long_overflow_digits(buffer+16,buffer_end)+16,parse_code::overflow}; + } + else + { + std::size_t digits1{detect_length(buffer+16)}; +//18446744073709551615 20 digits + switch(digits1) + { + case 3: + { + res=result*UINT16_C(1000)+((buffer[16]-zero_constant)*UINT16_C(100)+(buffer[17]-zero_constant)*UINT16_C(10) + +(buffer[18]-zero_constant)); + return {19,parse_code::ok}; + } + case 2: + { + res=result*UINT16_C(100)+((buffer[16]-zero_constant)*UINT16_C(10)+static_cast(buffer[17]-zero_constant)); + return {18,parse_code::ok}; + } + case 1: + { + res=result*UINT16_C(10)+(buffer[16]-zero_constant); + return {17,parse_code::ok}; + } + case 0: + { + res=result; + return {16,parse_code::ok}; + } + case 4: + { + constexpr std::uint_least64_t risky_value{UINT_LEAST64_MAX/UINT64_C(10000)}; + constexpr std::uint_fast16_t risky_mod{UINT_LEAST64_MAX%UINT64_C(10000)}; + if(result>risky_value) + return {20,parse_code::overflow}; + std::uint_fast16_t partial{ + static_cast( + static_cast(buffer[16]-zero_constant)*UINT16_C(1000)+ + static_cast(buffer[17]-zero_constant)*UINT16_C(100)+ + static_cast(buffer[18]-zero_constant)*UINT16_C(10)+ + static_cast(buffer[19]-zero_constant))}; + if(result==risky_value&&risky_mod(buffer+16,buffer_end); + [[fallthrough]]; + } + default: + { + return {digits1+16,parse_code::overflow}; + } + } + } + } + res=result; + return {digits,parse_code::ok}; +} + +#endif + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline constexpr char_type const* skip_digits(char_type const* first,char_type const* last) noexcept +{ + using unsigned_char_type = std::make_unsigned_t; + for(;first!=last&&char_is_digit(static_cast(*first));++first); + return first; +} + +template +#if defined(__SSE4_1__) && __has_cpp_attribute(__gnu__::__cold__) && defined(__x86_64__) +[[__gnu__::__cold__]] +#endif +inline constexpr parse_result scan_int_contiguous_none_simd_space_part_define_impl(char_type const* first,char_type const* last,T& res) noexcept +{ + using unsigned_char_type = std::make_unsigned_t; + using unsigned_type = my_make_unsigned_t>; + constexpr unsigned_char_type base_char_type{base}; + constexpr unsigned_type risky_uint_max{static_cast(-1)}; + constexpr unsigned_type risky_value{risky_uint_max/base}; + constexpr unsigned_char_type risky_digit(risky_uint_max%base); + constexpr bool isspecialbase{base==2||base==4||base==16}; + constexpr std::size_t max_size{details::cal_max_int_size()-(!isspecialbase)}; + std::size_t const diff{static_cast(last-first)}; + std::size_t mn_val{max_size}; + if(diff(*first)}; + if(char_digit_to_literal(ch))[[unlikely]] + break; + res*=base_char_type; + res+=ch; + } + bool overflow{}; + if(first!=last)[[likely]] + { + unsigned_char_type ch{static_cast(*first)}; + if constexpr(isspecialbase) + { + if(char_is_digit(ch)) + { + ++first; + first=skip_digits(first,last); + overflow=true; + } + } + else + { + if(!char_digit_to_literal(ch))[[unlikely]] + { + overflow=res>risky_value||(risky_value==res&&ch>risky_digit); + if(!overflow) + { + res*=base_char_type; + res+=ch; + } + ++first; + if(first!=last&&char_is_digit(static_cast(*first))) + { + ++first; + first=skip_digits(first,last); + overflow=true; + } + } + } + } + return {first,(overflow?(parse_code::overflow):(parse_code::ok))}; +} + +inline constexpr parse_code ongoing_parse_code{static_cast(std::numeric_limits::max())}; + +template +inline constexpr parse_result scan_shbase_impl(char_type const* first,char_type const* last) noexcept +{ + if(first==last||*first!=char_literal_v) + { + return {first,parse_code::invalid}; + } + if((++first)==last) + { + return {first,parse_code::invalid}; + } + if constexpr(base==2||base==3||base==16) + { + auto ch{*first}; + if((ch!=char_literal_v<(base==2?u8'B':(base==3?u8't':u8'X')),char_type>)& + (ch!=char_literal_v<(base==2?u8'b':(base==3?u8't':u8'x')),char_type>)) + { + return {first,parse_code::invalid}; + } + ++first; + } + else + { + if(*first!=char_literal_v) + { + return {first,parse_code::invalid}; + } + ++first; + if((++first)==last) + { + return {first,parse_code::invalid}; + } + constexpr auto digit0{char_literal_v< + u8'0'+(base<10?base:base/10),char_type>}; + if(*first!=digit0) + { + return {first,parse_code::invalid}; + } + if((++first)==last) + { + return {first,parse_code::invalid}; + } + if constexpr(10}; + if(*first!=digit1) + { + return {first,parse_code::invalid}; + } + if((++first)==last) + { + return {first,parse_code::invalid}; + } + } + if(*first!=char_literal_v) + { + return {first,parse_code::invalid}; + } + } + return {first,ongoing_parse_code}; +} + +template +inline constexpr char_type const* skip_hexdigits(char_type const* first,char_type const* last) noexcept; + +template +inline constexpr parse_result scan_int_contiguous_none_space_part_define_impl(char_type const* first,char_type const* last,T& t) noexcept +{ + using unsigned_char_type = std::make_unsigned_t; + [[maybe_unused]] bool sign{}; + if constexpr(my_signed_integral) + { + if(first==last) + return {first,parse_code::invalid}; + constexpr auto minus_sign{char_literal_v}; + if((sign=(minus_sign==*first))) + ++first; + if constexpr(shbase&&base!=10) + { + if constexpr(base==8) + { + if(first==last||*first!=char_literal_v) + { + return {first,parse_code::invalid}; + } + ++first; + } + else + { + auto phase_ret = scan_shbase_impl(first,last); + if(phase_ret.code!=ongoing_parse_code) + { + return phase_ret; + } + first=phase_ret.iter; + } + } + } + constexpr auto zero{char_literal_v}; + if(first!=last) + { + auto first_ch{*first}; + if(!char_is_digit(static_cast(first_ch)))[[unlikely]] + return {first,parse_code::invalid}; + else if(first_ch==zero) + { + if constexpr(skipzero) + { + ++first; + first=::fast_io::details::find_none_zero_simd_impl(first,last); + if(first==last) + { + t=0; + return {first,parse_code::ok}; + } + } + else + { + ++first; + if((first==last)||(!char_is_digit(static_cast(*first)))) + { + t={}; + return {first,parse_code::ok}; + } + return {first,parse_code::invalid}; + } + } + } + using unsigned_type = my_make_unsigned_t>; + unsigned_type res{}; + char_type const* it; +#if defined(__SSE4_1__) && defined(__x86_64__) + if constexpr(base==10&&sizeof(char_type)==1&&sizeof(unsigned_type)<=sizeof(std::uint_least64_t)) + { + if( +#if __cpp_lib_is_constant_evaluated >= 201811L + !std::is_constant_evaluated()&& +#endif + last-first>=32)[[likely]] + { + constexpr bool smaller_than_uint64{sizeof(unsigned_type),smaller_than_uint64>(reinterpret_cast(first),reinterpret_cast(last),temp); + it=first+digits; + if(ec!=parse_code::ok)[[unlikely]] + return {it,ec}; + if constexpr(smaller_than_uint64) + { + constexpr unsigned_type umax{static_cast(-1)}; + if(temp>umax) + return {it,parse_code::overflow}; + res=static_cast(temp); + } + else + { + res=temp; + } + } + else[[unlikely]] + { + auto [it2,ec]=scan_int_contiguous_none_simd_space_part_define_impl(first,last,res); + if(ec!=parse_code::ok) + return {it2,ec}; + it=it2; + } + } + else +#endif + { + auto [it2,ec]=scan_int_contiguous_none_simd_space_part_define_impl(first,last,res); + if(ec!=parse_code::ok) + return {it2,ec}; + it=it2; + } + if constexpr(my_signed_integral) + { + constexpr unsigned_type umax{static_cast(-1)}; + constexpr unsigned_type imax{umax>>1}; + if(res>(static_cast>(imax)+sign)) + return {it,parse_code::overflow}; + if(sign) + t=static_cast(static_cast(0)-res); + else + t=static_cast(res); + } + else + { + t=res; + } + return {it,parse_code::ok}; +} + +template +inline constexpr parse_result scan_int_contiguous_define_impl(char_type const* first,char_type const* last,T& t) noexcept +{ + if constexpr(!noskipws) + { + first=::fast_io::details::find_space_common_impl(first,last); + if(first==last) + return {first,parse_code::end_of_file}; + } + if constexpr(my_unsigned_integral) + { + if constexpr(shbase&&base!=10) + { + if constexpr(base==8) + { + if(first==last||*first!=char_literal_v) + { + return {first,parse_code::invalid}; + } + ++first; + } + else + { + auto phase_ret = scan_shbase_impl(first,last); + if(phase_ret.code!=ongoing_parse_code) + { + return phase_ret; + } + first=phase_ret.iter; + } + } + } + return scan_int_contiguous_none_space_part_define_impl),skipzero>(first,last,t); +} +} + +enum class scan_integral_context_phase:std::uint_least8_t +{ +space, +sign, +prefix, +zero, +zero_skip, +zero_invalid, +digit, +overflow +}; + +namespace details +{ +template +inline constexpr auto scan_context_type_impl_int() noexcept +{ + using unsigned_type = details::my_make_unsigned_t>; + constexpr std::size_t max_size{(::fast_io::details::print_integer_reserved_size_cache,unsigned_type>)+2}; + struct scan_integer_context + { + ::fast_io::freestanding::array buffer; + std::uint_least8_t size{}; + scan_integral_context_phase integer_phase{}; + inline constexpr void reset() noexcept + { + size=0; + integer_phase=scan_integral_context_phase::space; + } + }; + return io_type_t{}; +} +} + + +namespace details +{ + +template<::std::integral char_type> +inline constexpr parse_result sc_int_ctx_space_phase(char_type const* first,char_type const* last) noexcept +{ + first=::fast_io::details::find_space_common_impl(first,last); + if(first==last) + return {first,parse_code::partial}; + return {first,ongoing_parse_code}; +} + +template +inline constexpr parse_result sc_int_ctx_sign_phase(State& st,char_type const* first,char_type const* last) noexcept +{ + if(first==last) + { + st.integer_phase=scan_integral_context_phase::sign; + return {first,parse_code::partial}; + } + if constexpr(allow_negative) + { + if constexpr(allow_positive) + { + auto ch{*first}; + if(ch==char_literal_v) + { + *st.buffer.data()=ch; + st.size=1; + ++first; + } + else if(ch==char_literal_v) + { + ++first; + } + } + else + { + if(*first==char_literal_v) + { + *st.buffer.data()=char_literal_v; + st.size=1; + ++first; + } + } + } + else + { + if constexpr(allow_positive) + { + auto ch{*first}; + if(ch==char_literal_v) + { + ++first; + } + } + } + return {first,ongoing_parse_code}; +} + +template +requires (base!=10) +inline constexpr parse_result sc_int_ctx_prefix_phase( + std::uint_least8_t& sz,char_type const* first,char_type const* last) noexcept +{ + if(first==last) + { + return {first,parse_code::partial}; + } + if constexpr(base==8) + { + if(*first!=char_literal_v) + { + return {first,parse_code::invalid}; + } + + } + else + { + std::uint_least8_t size_cache{sz}; + if(size_cache==0) + { + if(*first!=char_literal_v) + { + return {first,parse_code::invalid}; + } + if((++first)==last) + { + sz=1; + return {first,parse_code::partial}; + } + if constexpr(base!=2&&base!=3&&base!=16) + { + size_cache=1; + } + } + if constexpr(base==2||base==3||base==16) + { + auto ch{*first}; + if((ch==char_literal_v<(base==2?u8'B':(base==3?u8't':u8'X')),char_type>)| + (ch==char_literal_v<(base==2?u8'b':(base==3?u8't':u8'x')),char_type>)) + { + sz=0; + ++first; + return {first,ongoing_parse_code}; + } + else + { + return {first,parse_code::invalid}; + } + } + else + { + if(size_cache==1) + { + if(*first!=char_literal_v) + { + return {first,parse_code::invalid}; + } + if((++first)==last) + { + sz=2; + return {first,parse_code::partial}; + } + } + constexpr auto digit0{char_literal_v< + u8'0'+(base<10?base:base/10),char_type>}; + if(size_cache==2) + { + if(*first!=digit0) + { + return {first,parse_code::invalid}; + } + if((++first)==last) + { + sz=3; + return {first,parse_code::partial}; + } + } + if constexpr(10}; + if(size_cache==3) + { + if(*first!=digit1) + { + return {first,parse_code::invalid}; + } + if((++first)==last) + { + sz=4; + return {first,parse_code::partial}; + } + } + } + constexpr + ::std::uint_least8_t last_index{base<10?3:4}; + if(size_cache==last_index) + { + if(*first!=char_literal_v) + { + return {first,parse_code::invalid}; + } + sz=0; + ++first; + } + } + } + return {first,ongoing_parse_code}; +} + +template +inline constexpr parse_result sc_int_ctx_zero_phase(scan_integral_context_phase& integer_phase,char_type const* first,char_type const* last) noexcept +{ + using unsigned_char_type = std::make_unsigned_t; + if(first==last) + { + integer_phase=scan_integral_context_phase::zero; + return {first,parse_code::partial}; + } + constexpr auto zero{char_literal_v}; + auto first_ch{*first}; + if(!char_is_digit(static_cast(first_ch)))[[unlikely]] + { + return {first,parse_code::invalid}; + } + else if(first_ch==zero)[[unlikely]] + { + ++first; + if constexpr(skipzero) + { + first=find_none_zero_simd_impl(first,last); + } + if(first==last) + { + if constexpr(skipzero) + { + integer_phase=scan_integral_context_phase::zero_skip; + } + else + { + integer_phase=scan_integral_context_phase::zero_invalid; + } + return {first,parse_code::partial}; + } + if(!char_is_digit(static_cast(*first))) + { + return {first,parse_code::ok}; + } + if constexpr(!skipzero) + { + return {first,parse_code::invalid}; + } + } + return {first,ongoing_parse_code}; +} + + +template +inline constexpr parse_result sc_int_ctx_digit_phase(State& st,char_type const* first,char_type const* last,T& t) noexcept +{ + auto it{skip_digits(first,last)}; + std::size_t const diff{st.buffer.size()-static_cast(st.size)}; + std::size_t const first_it_diff{static_cast(it-first)}; + if(first_it_diff(first_it_diff); + if(it==last) + { + st.integer_phase=scan_integral_context_phase::digit; + return {it,parse_code::partial}; + } + if(st.size==0) + { + t={}; + return {it,parse_code::ok}; + } + auto [p,ec]=scan_int_contiguous_none_space_part_define_impl(st.buffer.data(),e,t); + return {p-start+first,ec}; + } + else + { + if(it==last) + { + st.integer_phase=scan_integral_context_phase::overflow; + return {it,parse_code::partial}; + } + else + { + return {it,parse_code::overflow}; + } + } +} + +template +inline constexpr parse_result sc_int_ctx_zero_invalid_phase(char_type const* first,char_type const* last) noexcept +{ + using unsigned_char_type = std::make_unsigned_t; + if(first==last) + return {first,parse_code::partial}; + ++first; + if(!char_is_digit(static_cast(*first))) + { + return {first,parse_code::ok}; + } + return {first,parse_code::invalid}; +} + +template +inline constexpr parse_result sc_int_ctx_skip_digits_phase(char_type const* first,char_type const* last) noexcept +{ + first=skip_digits(first,last); + return {first,(first==last)?parse_code::partial:parse_code::invalid}; +} + +template +inline constexpr parse_result scan_context_define_parse_impl(State& st,char_type const* first,char_type const* last,T& t) noexcept +{ + auto phase{st.integer_phase}; +#if __has_cpp_attribute(assume) + if constexpr(noskipws) + { + [[assume(phase!=scan_integral_context_phase::space)]]; + } + if constexpr(my_unsigned_integral) + { + [[assume(phase!=scan_integral_context_phase::sign)]]; + } + if constexpr(!shbase||base==10) + { + [[assume(phase!=scan_integral_context_phase::prefix)]]; + } + if constexpr(skipzero) + { + [[assume(phase!=scan_integral_context_phase::zero_invalid)]]; + } + else + { + [[assume(phase!=scan_integral_context_phase::zero_skip)]]; + } +#endif + switch(phase) + { + case scan_integral_context_phase::space: + { + if constexpr(!noskipws) + { + auto phase_ret = sc_int_ctx_space_phase(first,last); + if(phase_ret.code!=ongoing_parse_code) + { + return phase_ret; + } + first=phase_ret.iter; + } + [[fallthrough]]; + } + case scan_integral_context_phase::sign: + { + if constexpr(my_signed_integral) + { + auto phase_ret = sc_int_ctx_sign_phase(st,first,last); + if(phase_ret.code!=ongoing_parse_code) + { + return phase_ret; + } + first=phase_ret.iter; + } + [[fallthrough]]; + } + case scan_integral_context_phase::prefix: + { + if constexpr(shbase&&base!=10) + { + st.integer_phase=scan_integral_context_phase::prefix; + auto phase_ret = sc_int_ctx_prefix_phase(st.size,first,last); + if(phase_ret.code!=ongoing_parse_code) + { + return phase_ret; + } + first=phase_ret.iter; + } + [[fallthrough]]; + } + case scan_integral_context_phase::zero: + case scan_integral_context_phase::zero_skip: + { + auto phase_ret=sc_int_ctx_zero_phase(st.integer_phase,first,last); + if(phase_ret.code!=ongoing_parse_code) + { + if constexpr(skipzero) + { + if(phase_ret.code==parse_code::ok) + { + t={}; + } + else if(phase_ret.code==parse_code::invalid&&phase==scan_integral_context_phase::zero_skip) + { + t={}; + phase_ret.code=parse_code::ok; + } + } + else + { + if(phase_ret.code==parse_code::ok) + { + t={}; + } + } + return phase_ret; + } + first=phase_ret.iter; + [[fallthrough]]; + } + case scan_integral_context_phase::digit: + { + return sc_int_ctx_digit_phase(st,first,last,t); + } + case scan_integral_context_phase::zero_invalid: + { + if constexpr(skipzero) + { + return {first,parse_code::invalid}; + } + else + { + auto phase_ret=sc_int_ctx_zero_invalid_phase(first,last); + if(phase_ret.code==parse_code::ok) + { + t={}; + } + return phase_ret; + } + } + default: + { + return sc_int_ctx_skip_digits_phase(first,last); + } + } +} + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline constexpr parse_code scan_context_eof_define_parse_impl(State& st,T& t) noexcept +{ + auto phase{st.integer_phase}; +#if __has_cpp_attribute(assume) + if constexpr(!skipzero) + { + [[assume(phase!=scan_integral_context_phase::zero_skip)]]; + } +#endif + switch(phase) + { + case scan_integral_context_phase::space: + { + if constexpr(noskipws) + { + return parse_code::invalid; + } + else + { + return parse_code::end_of_file; + } + } + case scan_integral_context_phase::digit: + return scan_int_contiguous_none_space_part_define_impl(st.buffer.data(),st.buffer.data()+st.size,t).code; + case scan_integral_context_phase::overflow: + return parse_code::overflow; + case scan_integral_context_phase::zero_skip: + case scan_integral_context_phase::zero_invalid: + { + t={}; + return parse_code::ok; + } + default: + return parse_code::invalid; + } +} + +} + + +namespace manipulators +{ + +template +struct ch_get_t +{ + using manip_tag = manip_tag_t; + char_type& reference; +}; + +template<::fast_io::details::my_integral T> +inline constexpr ch_get_t ch_get(T& reference) noexcept +{ + return {reference}; +} + +template +inline constexpr scalar_manip_t<::fast_io::details::base_scan_mani_flags_cache,scalar_type&> base_get(scalar_type& t) noexcept +{ + return {t}; +} + +template +inline constexpr scalar_manip_t<::fast_io::details::base_scan_mani_flags_cache<2,noskipws,false,skipzero>,scalar_type&> bin_get(scalar_type& t) noexcept +{ + return {t}; +} + +template +inline constexpr scalar_manip_t<::fast_io::details::base_scan_mani_flags_cache<16,noskipws,false,skipzero>,scalar_type&> hex_get(scalar_type& t) noexcept +{ + return {t}; +} + +template +inline constexpr scalar_manip_t<::fast_io::details::base_scan_mani_flags_cache<16,noskipws,true,true>,scalar_type&> addrvw_get(scalar_type& t) noexcept +{ + return {t}; +} + +} + +template +inline constexpr ::fast_io::manipulators::scalar_manip_t<::fast_io::details::base_scan_mani_flags_cache<10,false,false,false>,T&> scan_alias_define(io_alias_t,T& t) noexcept +{ + return {t}; +} + +template +inline constexpr auto scan_context_type(io_reserve_type_t>) noexcept +{ + return details::scan_context_type_impl_int(); +} + +template<::std::integral char_type,manipulators::scalar_flags flags,details::my_integral T> +inline constexpr parse_result scan_contiguous_define(io_reserve_type_t>,char_type const* begin,char_type const* end,::fast_io::manipulators::scalar_manip_t t) noexcept +{ + return details::scan_int_contiguous_define_impl(begin,end,t.reference); +} + +template<::std::integral char_type,manipulators::scalar_flags flags,typename State,details::my_integral T> +inline constexpr parse_result scan_context_define(io_reserve_type_t>,State& state,char_type const* begin,char_type const* end,::fast_io::manipulators::scalar_manip_t t) noexcept +{ + return details::scan_context_define_parse_impl(state,begin,end,t.reference); +} + +template<::std::integral char_type,manipulators::scalar_flags flags,typename State,details::my_integral T> +inline constexpr parse_code scan_context_eof_define(io_reserve_type_t>,State& state,::fast_io::manipulators::scalar_manip_t t) noexcept +{ + return details::scan_context_eof_define_parse_impl(state,t.reference); +} + +namespace details +{ +template<::std::integral char_type> +inline constexpr parse_result ch_get_context_impl(char_type const* first,char_type const* last,char_type& t) noexcept +{ + first=::fast_io::details::find_space_common_impl(first,last); + if(first==last) + return {first,parse_code::partial}; + t=*first; + ++first; + return {first,parse_code::ok}; +} +} + +template +inline constexpr io_type_t scan_context_type(io_reserve_type_t>) noexcept +{ + return {}; +} + +template +inline constexpr parse_result scan_context_define(io_reserve_type_t>,details::empty,char_type const* begin,char_type const* end,manipulators::ch_get_t t) noexcept +{ + return details::ch_get_context_impl(begin,end,t.reference); +} + +template +inline constexpr parse_code scan_context_eof_define(io_reserve_type_t>,details::empty,manipulators::ch_get_t) noexcept +{ + return parse_code::end_of_file; +} + +} +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning (pop) +#endif diff --git a/src/fast_io/include/fast_io_core_impl/integers/sto/sto_generate_base_tb.h b/src/fast_io/include/fast_io_core_impl/integers/sto/sto_generate_base_tb.h new file mode 100644 index 0000000..ad42cd0 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/integers/sto/sto_generate_base_tb.h @@ -0,0 +1,170 @@ +#pragma once + +namespace fast_io +{ + +namespace details +{ + +template +requires (2<=base&&base<=36) +inline constexpr bool char_digit_to_literal_impl(char8_t& ch) noexcept +{ + using unsigned_char_type = ::std::make_unsigned_t; + constexpr unsigned_char_type base_char_type(base); + if constexpr(base<=10) + { + if constexpr(ebcdic) + ch-=static_cast(240); + else + ch-=static_cast(u8'0'); + return base_char_type<=ch; + } + else + { + if constexpr(ebcdic) + { + + if constexpr(base<=19) + { + constexpr unsigned_char_type mns{base-10}; + unsigned_char_type ch2(ch); + ch2-=0xC1; + unsigned_char_type ch3(ch); + ch3-=0x81; + ch-=0xF0; + if(ch2(10); + else if(ch3(10); + else if(10<=ch) + return true; + return false; + } + else if constexpr(base<=28) + { + constexpr unsigned_char_type mns{base-19}; + unsigned_char_type ch2(ch); + ch2-=0xC1; + unsigned_char_type ch3(ch); + ch3-=0x81; + unsigned_char_type ch4(ch); + ch2-=0xD1; + unsigned_char_type ch5(ch); + ch3-=0x91; + ch-=0xF0; + if(ch4(19); + else if(ch5(19); + else if(ch2<9) + ch=ch2+static_cast(10); + else if(ch3<9) + ch=ch3+static_cast(10); + else if(10<=ch) + return true; + return false; + } + else + { + constexpr unsigned_char_type mns{base-27}; + unsigned_char_type ch2(ch); + ch2-=0xC1; + unsigned_char_type ch3(ch); + ch3-=0x81; + unsigned_char_type ch4(ch); + ch4-=0xD1; + unsigned_char_type ch5(ch); + ch5-=0x91; + unsigned_char_type ch6(ch); + ch6-=0xE2; + unsigned_char_type ch7(ch); + ch7-=0xA2; + ch-=0xF0; + if(ch6(27); + else if(ch7(27); + else if(ch4<9) + ch=ch4+static_cast(19); + else if(ch5<9) + ch=ch5+static_cast(19); + else if(ch2<9) + ch=ch2+static_cast(10); + else if(ch3<9) + ch=ch3+static_cast(10); + else if(10<=ch) + return true; + return false; + } + } + else + { + constexpr unsigned_char_type mns{base-10}; + unsigned_char_type ch2(ch); + ch2-=u8'A'; + unsigned_char_type ch3(ch); + ch3-=u8'a'; + ch-=u8'0'; + if(ch2(10); + else if(ch3(10); + else if(10<=ch) + return true; + return false; + } + } +} + +template +inline constexpr std::size_t calculate_max_available_sto_tb_size() noexcept +{ + constexpr char8_t mx{std::numeric_limits::max()}; + std::size_t n{static_cast(mx)+1}; + if constexpr(partial) + { + for(;n;--n) + { + char8_t ch{static_cast(n-1)}; + if(!char_digit_to_literal_impl(ch)) + { + break; + } + } + if(n==0) + { + ::fast_io::fast_terminate(); + } + return n; + } + else + { + return mx; + } +} + +template +inline constexpr auto generate_sto_base_tb() noexcept +{ + constexpr char8_t mx{std::numeric_limits::max()}; + + ::fast_io::freestanding::array()> buffer; + for(char16_t i{};i!=buffer.size();++i) + { + char8_t ch{static_cast(i)}; + if(char_digit_to_literal_impl(ch)) + { + ch=mx; + } + buffer[i]=ch; + } + return buffer; +} + +template +inline constexpr auto sto_base_tb{generate_sto_base_tb()}; + +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/integers/uprsv/dec.h b/src/fast_io/include/fast_io_core_impl/integers/uprsv/dec.h new file mode 100644 index 0000000..165f90b --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/integers/uprsv/dec.h @@ -0,0 +1,286 @@ +#pragma once + +namespace fast_io::details::uprsv::decbase +{ + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr char_type* uprsv_handle8_impl(char_type *iter,::std::uint_least32_t first8) noexcept +{ + constexpr + auto const *digitstb{digits_table}; + + constexpr + ::std::size_t tocopybytes{sizeof(char_type)*2u}; + + constexpr + ::std::uint_least32_t mask24{(UINT32_C(1)<(first8*magic24)}; + ::std::uint_least32_t const f2{static_cast<::std::uint_least32_t>(((f0&mask24)*UINT32_C(100))>>UINT32_C(24))}; + ::std::uint_least32_t const f01{static_cast<::std::uint_least32_t>(f0>>UINT32_C(24))}; +#if __has_cpp_attribute(assume) + [[assume(f01>16}; + low = ::fast_io::details::intrinsics::unpack_generic(temp,high); +#if __has_cpp_attribute(assume) + [[assume(high>16}; + ::std::uint_least32_t high; + ::std::uint_least32_t low{::fast_io::details::intrinsics::unpack_generic(temp,high)}; +#if __has_cpp_attribute(assume) + [[assume(high +inline constexpr char_type* uprsv32_impl(char_type *iter,::std::uint_least32_t value) noexcept +{ + constexpr + ::std::uint_least32_t onee8{UINT32_C(100000000)}; + + bool const lessthan1e8{value(iter,first8); + + if(!lessthan1e8) + { +#if __has_cpp_attribute(assume) + [[assume(first8(iter,f0); + } + return iter; +} + +template<::std::integral char_type> +inline constexpr char_type* uprsv64_impl(char_type *iter,::std::uint_least64_t value) noexcept +{ + constexpr + ::std::uint_least32_t onee8{UINT32_C(100000000)}; +#if 0 + constexpr + ::std::uint_least64_t onee16{static_cast<::std::uint_least64_t>(onee8)*static_cast<::std::uint_least64_t>(onee8)}; +#endif + + bool const lessthan1e8{value(lessthan1e16?first16:first16/onee8)}; + + iter = uprsv_handle8_impl(iter,first8); + + if(!lessthan1e8) + { + if(!lessthan1e16) + { + ::std::uint_least64_t const f0{first16%onee8}; +#if __has_cpp_attribute(assume) + [[assume(f0(f0)}; + iter = uprsv_handle8_impl(iter,f032); + } + ::std::uint_least64_t f0{value-first16*onee8}; +#if __has_cpp_attribute(assume) + [[assume(f0(f0)}; + iter = uprsv_handle8_impl(iter,f032); + } + return iter; +} + +#ifdef __SIZEOF_INT128__ + +template<::std::integral char_type> +inline constexpr char_type* uprsv128_18digits_impl(char_type *iter,::std::uint_least64_t value) noexcept +{ + constexpr + auto const *digitstb{digits_table}; + + constexpr + ::std::size_t tocopybytes{sizeof(char_type)*2u}; + + constexpr + ::std::uint_least32_t onee8{UINT32_C(100000000)}; + + ::std::uint_least64_t a12{value/onee8}; + ::std::uint_least32_t a3{static_cast<::std::uint_least32_t>(value%onee8)}; + + ::std::uint_least64_t a1u64{static_cast<::std::uint_least32_t>(a12/onee8)}; + +#if __has_cpp_attribute(assume) + [[assume(a1u64(a1u64)}; + ::std::uint_least32_t a2{static_cast<::std::uint_least32_t>(a12%onee8)}; + + ::fast_io::details::intrinsics::typed_memcpy(iter,digitstb+(a1<<1),tocopybytes); + iter += 2; + iter = uprsv_handle8_impl(iter,a2); + return uprsv_handle8_impl(iter,a3); +} + +template<::std::integral char_type> +inline constexpr char_type* uprsv128_impl(char_type *iter,__uint128_t value) noexcept +{ + ::std::uint_least64_t high; + ::std::uint_least64_t low{::fast_io::details::intrinsics::unpack_generic(value,high)}; + + if(!high) + { + return uprsv64_impl(iter,low); + } + + constexpr + ::std::uint_least64_t onee18{UINT64_C(1000000000000000000)}; + + constexpr + __uint128_t onee36{static_cast<__uint128_t>(onee18)*static_cast<__uint128_t>(onee18)}; + + + if(value < onee36) + { + auto vdiv1_u128{value / onee18}; +#if __has_cpp_attribute(assume) + [[assume(vdiv1_u128(value % onee18); + + iter=uprsv64_impl(iter,static_cast<::std::uint_least64_t>(vdiv1_u128)); + } + else + { + auto vdiv{value / onee36}; + auto vmod{value % onee36}; +#if __has_cpp_attribute(assume) + [[assume(vdiv(vdiv)}; + iter=uprsv32_impl(iter,vvv); + + auto vdiv1_u128{vmod / onee18}; +#if __has_cpp_attribute(assume) + constexpr auto pow10val{::fast_io::details::compile_time_pow<::std::uint_least64_t>(10,18)}; + [[assume(vdiv1_u128(vmod % onee18); + iter=uprsv128_18digits_impl(iter,static_cast<::std::uint_least64_t>(vdiv1_u128)); + } + return uprsv128_18digits_impl(iter,low); +} + +#endif + +} diff --git a/src/fast_io/include/fast_io_core_impl/integers/uprsv/hex.h b/src/fast_io/include/fast_io_core_impl/integers/uprsv/hex.h new file mode 100644 index 0000000..c7063ad --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/integers/uprsv/hex.h @@ -0,0 +1,142 @@ +#pragma once + +namespace fast_io::details::uprsv::hexbase +{ + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr char_type* uprsv_hex_handle8_impl(char_type *iter,::std::uint_least32_t first4) noexcept +{ + constexpr + ::std::uint_least32_t onex2{UINT32_C(0x100)}; + constexpr + ::std::uint_least32_t mask8{onex2-UINT32_C(1)}; + constexpr + ::std::uint_least32_t onex4{UINT32_C(0x10000)}; + constexpr + ::std::uint_least32_t onex6{UINT32_C(0x1000000)}; + + constexpr + auto const *digitstb{digits_table}; + constexpr + ::std::size_t tocopybytes{sizeof(char_type)*2u}; + if constexpr(isfirst) + { + if (first4 < onex4) + { + if(first4 < onex2) + { + bool const lessthan16{first4(first4>>8)}; + ::std::uint_least32_t const f2{static_cast<::std::uint_least32_t>(f0&mask8)}; + bool const lessthan16{f0(first4>>16)}; + ::std::uint_least32_t const f2{static_cast<::std::uint_least32_t>((first4>>8)&mask8)}; + ::std::uint_least32_t const f4{static_cast<::std::uint_least32_t>(first4&mask8)}; + + bool const lessthan16{f0(first4>>24)}; + ::std::uint_least32_t const f2{static_cast<::std::uint_least32_t>((first4>>16)&mask8)}; + ::std::uint_least32_t const f4{static_cast<::std::uint_least32_t>((first4>>8)&mask8)}; + ::std::uint_least32_t const f6{static_cast<::std::uint_least32_t>(first4&mask8)}; + + bool const lessthan16{f0(first4>>24)}; + ::std::uint_least32_t const f2{static_cast<::std::uint_least32_t>((first4>>16)&mask8)}; + ::std::uint_least32_t const f4{static_cast<::std::uint_least32_t>((first4>>8)&mask8)}; + ::std::uint_least32_t const f6{static_cast<::std::uint_least32_t>(first4&mask8)}; + ::fast_io::details::intrinsics::typed_memcpy(iter,digitstb+(f0<<1),tocopybytes); + ::fast_io::details::intrinsics::typed_memcpy(iter+2,digitstb+(f2<<1),tocopybytes); + ::fast_io::details::intrinsics::typed_memcpy(iter+4,digitstb+(f4<<1),tocopybytes); + ::fast_io::details::intrinsics::typed_memcpy(iter+6,digitstb+(f6<<1),tocopybytes); + iter+=8; + } + return iter; +} + +template +inline constexpr char_type* uprsv_hex32_impl(char_type *iter,::std::uint_least32_t value) noexcept +{ + return uprsv_hex_handle8_impl(iter,value); +} + +template +inline constexpr char_type* uprsv_hex64_impl(char_type *iter,::std::uint_least64_t value) noexcept +{ + ::std::uint_least32_t high; + ::std::uint_least32_t low{::fast_io::details::intrinsics::unpack_generic(value,high)}; + ::std::uint_least32_t const first4{high?high:low}; + iter = uprsv_hex_handle8_impl(iter,first4); + if(high) + { + iter = uprsv_hex_handle8_impl(iter,low); + } + return iter; +} + +#ifdef __SIZEOF_INT128__ + +template +inline constexpr char_type* uprsv_hex64_notfirst_impl(char_type *iter,::std::uint_least64_t value) noexcept +{ + ::std::uint_least32_t high; + ::std::uint_least32_t low{::fast_io::details::intrinsics::unpack_generic(value,high)}; + iter = uprsv_hex_handle8_impl(iter,high); + iter = uprsv_hex_handle8_impl(iter,low); + return iter; +} + +template +inline constexpr char_type* uprsv_hex128_impl(char_type *iter,__uint128_t value) noexcept +{ + ::std::uint_least64_t high; + ::std::uint_least64_t low{::fast_io::details::intrinsics::unpack_generic(value,high)}; + ::std::uint_least64_t const first8{high?high:low}; + iter = uprsv_hex64_impl(iter,first8); + if(high) + { + iter = uprsv_hex64_notfirst_impl(iter,low); + } + return iter; +} +#endif + +} diff --git a/src/fast_io/include/fast_io_core_impl/integers/uprsv/impl.h b/src/fast_io/include/fast_io_core_impl/integers/uprsv/impl.h new file mode 100644 index 0000000..8bf9d35 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/integers/uprsv/impl.h @@ -0,0 +1,67 @@ +#pragma once + +/* +fast_io's own uprsv (uint print reserve) algorithm +Referenced from xjkp's MyItoA algorithm: +https://gitee.com/xjkp2283572185/MyStd/blob/master/MyIntegral/MyItoA.hpp +*/ + +#include"dec.h" +#include"hex.h" + +namespace fast_io::details::uprsv +{ + +template<::std::size_t base,bool uppercase,::std::integral char_type,::fast_io::details::my_unsigned_integral uinttype> +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr char_type* uprsv_main(char_type *iter,uinttype value) noexcept +{ + if constexpr(base==10) + { + using namespace ::fast_io::details::uprsv::decbase; + if constexpr(sizeof(uinttype)<=sizeof(::std::uint_least32_t)) + { + return uprsv32_impl(iter,static_cast<::std::uint_least32_t>(value)); + } + else +#ifdef __SIZEOF_INT128__ + if constexpr(sizeof(uinttype)<=sizeof(::std::uint_least64_t)) +#endif + { + return uprsv64_impl(iter,static_cast<::std::uint_least64_t>(value)); + } +#ifdef __SIZEOF_INT128__ + else + { + return uprsv128_impl(iter,static_cast<__uint128_t>(value)); + } +#endif + } + else + { + using namespace ::fast_io::details::uprsv::hexbase; + if constexpr(sizeof(uinttype)<=sizeof(::std::uint_least32_t)) + { + return uprsv_hex32_impl(iter,static_cast<::std::uint_least32_t>(value)); + } + else +#ifdef __SIZEOF_INT128__ + if constexpr(sizeof(uinttype)<=sizeof(::std::uint_least64_t)) +#endif + { + return uprsv_hex64_impl(iter,static_cast<::std::uint_least64_t>(value)); + } +#ifdef __SIZEOF_INT128__ + else + { + return uprsv_hex128_impl(iter,static_cast<__uint128_t>(value)); + } +#endif + } +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/intrinsics.h b/src/fast_io/include/fast_io_core_impl/intrinsics.h new file mode 100644 index 0000000..fe05b9b --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/intrinsics.h @@ -0,0 +1,1060 @@ +#pragma once +#if defined(_MSC_VER) && !defined(__clang__) +#include +#pragma warning(push) +#pragma warning( disable : 4668 ) +#pragma warning( disable : 4800 ) +#endif + +namespace fast_io::details::intrinsics +{ + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && __cpp_lib_bit_cast >= 201806L +constexpr +#endif +void typed_memcpy(T1 *dest, T2 const *src,::std::size_t bytes) noexcept +{ +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && __cpp_lib_bit_cast >= 201806L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if (__builtin_is_constant_evaluated()) +#endif + { + if(dest == nullptr || src == nullptr || sizeof(T1)!=sizeof(T2) || bytes%sizeof(T1)!=0) + { +#if defined(__has_builtin) +#if __has_builtin(__builtin_trap) + __builtin_trap(); +#elif __has_builtin(__builtin_abort) + __builtin_abort(); +#else + ::std::abort(); +#endif +#else + ::std::abort(); +#endif + } + ::std::size_t n{bytes/sizeof(T1)}; + for(::std::size_t i{};i!=n;++i) + { + dest[i] = __builtin_bit_cast(T1,src[i]); + } + } + else +#endif + { +#if defined(__has_builtin) +#if __has_builtin(__builtin_memcpy) + __builtin_memcpy(dest,src,bytes); +#else + memcpy(dest,src,bytes); +#endif +#else + memcpy(dest,src,bytes); +#endif + } +} + +template +#if __cpp_lib_concepts >= 202002L +requires (std::unsigned_integral) +#endif +inline constexpr bool add_carry_naive(bool carry,T a,T b,T& out) noexcept +{ + T temp{carry+a}; + out=temp+b; + return (out < b) | (temp < a); +} + +template +#if __cpp_lib_concepts >= 202002L +requires (std::unsigned_integral) +#endif +inline constexpr bool add_carry(bool carry,T a,T b,T& out) noexcept +{ +#if __cpp_if_consteval >= 202106L + if consteval + { + return add_carry_naive(carry,a,b,out); + } + else +#elif __cpp_lib_is_constant_evaluated >= 201811L + if(std::is_constant_evaluated()) + return add_carry_naive(carry,a,b,out); + else +#endif + { +#if defined(_MSC_VER) && !defined(__clang__) +#if (defined(_M_IX86) || defined(_M_AMD64)) + if constexpr(sizeof(T)==8) + { +#if defined(_M_AMD64) + return _addcarry_u64(carry,a,b,reinterpret_cast(__builtin_addressof(out))); +#else + return _addcarry_u32(_addcarry_u32(carry, + *reinterpret_cast(__builtin_addressof(a)),*reinterpret_cast(__builtin_addressof(b)),reinterpret_cast(__builtin_addressof(out))), + reinterpret_cast(__builtin_addressof(a))[1],reinterpret_cast(__builtin_addressof(b))[1],reinterpret_cast(__builtin_addressof(out))+1); +#endif + } + else if constexpr(sizeof(T)==4) + return _addcarry_u32(carry,a,b,reinterpret_cast(__builtin_addressof(out))); + else if constexpr(sizeof(T)==2) + return _addcarry_u16(carry,a,b,reinterpret_cast(__builtin_addressof(out))); + else if constexpr(sizeof(T)==1) + return _addcarry_u8(carry,a,b,reinterpret_cast(__builtin_addressof(out))); + else + return add_carry_naive(carry,a,b,out); +#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)) + if constexpr(sizeof(T)==sizeof(long long unsigned)) + { + long long unsigned carryout; + out=__builtin_addcll(a,b,carry,__builtin_addressof(carryout)); + return carryout; + } + else if constexpr(sizeof(T)==sizeof(long unsigned)) + { + long unsigned carryout; + out=__builtin_addcl(a,b,carry,__builtin_addressof(carryout)); + return carryout; + } + else if constexpr(sizeof(T)==sizeof(unsigned)) + { + unsigned carryout; + out=__builtin_addc(a,b,carry,__builtin_addressof(carryout)); + return carryout; + } + else if constexpr(sizeof(T)==sizeof(short unsigned)) + { + short unsigned carryout; + out=__builtin_addcs(a,b,carry,__builtin_addressof(carryout)); + return carryout; + } + else if constexpr(sizeof(T)==sizeof(char unsigned)) + { + char unsigned carryout; + out=__builtin_addcb(a,b,carry,__builtin_addressof(carryout)); + return carryout; + } + else + { + 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)) + if constexpr(sizeof(T)==8) + { +#if __has_builtin(__builtin_ia32_addcarryx_u64) + using may_alias_ptr_type + #if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] + #endif + = unsigned long long*; + return __builtin_ia32_addcarryx_u64(carry,a,b,reinterpret_cast(__builtin_addressof(out))); +#elif __has_builtin(__builtin_ia32_addcarry_u64) + using may_alias_ptr_type + #if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] + #endif + = unsigned long long*; + return __builtin_ia32_addcarry_u64(carry,a,b,reinterpret_cast(__builtin_addressof(out))); +#else + std::uint_least32_t a_low; + std::uint_least32_t a_high; + __builtin_memcpy(__builtin_addressof(a_low),__builtin_addressof(a),4); + __builtin_memcpy(__builtin_addressof(a_high),reinterpret_cast(__builtin_addressof(a))+4,4); + std::uint_least32_t b_low; + std::uint_least32_t b_high; + __builtin_memcpy(__builtin_addressof(b_low),__builtin_addressof(b),4); + __builtin_memcpy(__builtin_addressof(b_high),reinterpret_cast(__builtin_addressof(b))+4,4); + using may_alias_ptr_type + #if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] + #endif + = unsigned*; + #if __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) + return __builtin_ia32_addcarry_u32(__builtin_ia32_addcarry_u32(carry,a_low,b_low,reinterpret_cast(__builtin_addressof(out))), + a_high,b_high,reinterpret_cast(__builtin_addressof(out))+1); + #else + return add_carry_naive(carry,a,b,out); + #endif +#endif + } + else if constexpr(sizeof(T)==4) + { + using may_alias_ptr_type + #if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] + #endif + = unsigned*; +#if __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) + return __builtin_ia32_addcarry_u32(carry,a,b,reinterpret_cast(__builtin_addressof(out))); +#else + return add_carry_naive(carry,a,b,out); +#endif + } + else + return add_carry_naive(carry,a,b,out); //16 bit addcarry simply does not exist on gcc and clang +#else + return add_carry_naive(carry,a,b,out); +#endif + } +} + +template +#if __cpp_lib_concepts >= 202002L +requires (std::unsigned_integral) +#endif +inline constexpr bool sub_borrow_naive(bool carry,T a,T b,T& out) noexcept +{ + T temp{a-carry}; + out=temp-b; + return (temp +#if __cpp_lib_concepts >= 202002L +requires (std::unsigned_integral) +#endif +inline constexpr bool sub_borrow(bool borrow,T a,T b,T& out) noexcept +{ +#if __cpp_if_consteval >= 202106L + if consteval + { + return sub_borrow_naive(borrow,a,b,out); + } +#elif __cpp_lib_is_constant_evaluated >= 201811L + if(std::is_constant_evaluated()) + return sub_borrow_naive(borrow,a,b,out); + else +#endif + { +#if defined(_MSC_VER) && !defined(__clang__) +#if (defined(_M_IX86) || defined(_M_AMD64)) + if constexpr(sizeof(T)==8) + { +#if defined(_M_AMD64) + return _subborrow_u64(borrow,a,b,reinterpret_cast(__builtin_addressof(out))); +#else + return _subborrow_u32(_subborrow_u32(borrow, + *reinterpret_cast(__builtin_addressof(a)),*reinterpret_cast(__builtin_addressof(b)),reinterpret_cast(__builtin_addressof(out))), + reinterpret_cast(__builtin_addressof(a))[1],reinterpret_cast(__builtin_addressof(b))[1],reinterpret_cast(__builtin_addressof(out))+1); +#endif + } + else if constexpr(sizeof(T)==4) + return _subborrow_u32(borrow,a,b,reinterpret_cast(__builtin_addressof(out))); + else if constexpr(sizeof(T)==2) + return _subborrow_u16(borrow,a,b,reinterpret_cast(__builtin_addressof(out))); + else if constexpr(sizeof(T)==1) + return _subborrow_u8(borrow,a,b,reinterpret_cast(__builtin_addressof(out))); + else + return sub_borrow_naive(borrow,a,b,out); +#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)) + if constexpr(sizeof(T)==sizeof(long long unsigned)) + { + long long unsigned borrowout; + out=__builtin_subcll(a,b,borrow,__builtin_addressof(borrowout)); + return borrowout; + } + else if constexpr(sizeof(T)==sizeof(long unsigned)) + { + long unsigned borrowout; + out=__builtin_subcl(a,b,borrow,__builtin_addressof(borrowout)); + return borrowout; + } + else if constexpr(sizeof(T)==sizeof(unsigned)) + { + unsigned borrowout; + out=__builtin_subc(a,b,borrow,__builtin_addressof(borrowout)); + return borrowout; + } + else if constexpr(sizeof(T)==sizeof(short unsigned)) + { + short unsigned borrowout; + out=__builtin_subcs(a,b,borrow,__builtin_addressof(borrowout)); + return borrowout; + } + else if constexpr(sizeof(T)==sizeof(char unsigned)) + { + char unsigned borrowout; + out=__builtin_subcb(a,b,borrow,__builtin_addressof(borrowout)); + return borrowout; + } + else + { + 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)) + if constexpr(sizeof(T)==8) + { +#if __has_builtin(__builtin_ia32_sbb_u64) + using may_alias_ptr_type + #if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] + #endif + = unsigned long long*; + return __builtin_ia32_sbb_u64(borrow,a,b,reinterpret_cast(__builtin_addressof(out))); +#elif __has_builtin(__builtin_ia32_subborrow_u64) + using may_alias_ptr_type + #if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] + #endif + = 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) + std::uint_least32_t a_low; + std::uint_least32_t a_high; + __builtin_memcpy(__builtin_addressof(a_low),__builtin_addressof(a),4); + __builtin_memcpy(__builtin_addressof(a_high),reinterpret_cast(__builtin_addressof(a))+4,4); + std::uint_least32_t b_low; + std::uint_least32_t b_high; + __builtin_memcpy(__builtin_addressof(b_low),__builtin_addressof(b),4); + __builtin_memcpy(__builtin_addressof(b_high),reinterpret_cast(__builtin_addressof(b))+4,4); + using may_alias_ptr_type + #if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] + #endif + = unsigned*; +#if __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))), + a_high,b_high,reinterpret_cast(__builtin_addressof(out))+1); +#else + return __builtin_ia32_subborrow_u32(__builtin_ia32_subborrow_u32(borrow,a_low,b_low,reinterpret_cast(__builtin_addressof(out))), + a_high,b_high,reinterpret_cast(__builtin_addressof(out))+1); +#endif +#else + return sub_borrow_naive(borrow,a,b,out); +#endif + } + else if constexpr(sizeof(T)==4) + { +#if __has_builtin(__builtin_ia32_sbb_u32) + using may_alias_ptr_type + #if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] + #endif + = unsigned*; + return __builtin_ia32_sbb_u32(borrow,a,b,reinterpret_cast(__builtin_addressof(out))); +#elif __has_builtin(__builtin_ia32_subborrow_u32) + using may_alias_ptr_type + #if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] + #endif + = unsigned*; + return __builtin_ia32_subborrow_u32(borrow,a,b,reinterpret_cast(__builtin_addressof(out))); +#else + return sub_borrow_naive(borrow,a,b,out); +#endif + } + else + return sub_borrow_naive(borrow,a,b,out); //16 bit subborrow simply does not exist on gcc and clang +#else + return sub_borrow_naive(borrow,a,b,out); +#endif + } +} + +template +struct ul_generic_x2_little_endian +{ + U low,high; +}; +template +struct ul_generic_x2_big_endian +{ + U high,low; +}; + +template +using ul_generic_x2 = std::conditional_t,ul_generic_x2_little_endian>; + +using ul32x2_little_endian=ul_generic_x2_little_endian; +using ul32x2_big_endian=ul_generic_x2_big_endian; +using ul32x2 = ul_generic_x2; + +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 constexpr(std::endian::native==std::endian::little||std::endian::native==std::endian::big) + { + auto ret{__builtin_bit_cast(ul32x2,static_cast(a)*b)}; + high=ret.high; + return ret.low; + } + else +#endif +#endif + { + std::uint_least64_t v{static_cast(a)*b}; + high=static_cast(v>>(::std::numeric_limits<::std::uint_least32_t>::digits)); + return static_cast(v); + } +} + +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 constexpr(std::endian::native==std::endian::little||std::endian::native==std::endian::big) + { + auto ret{__builtin_bit_cast(ul32x2,static_cast(a)*b)}; + return ret.high; + } + else +#endif +#endif + { + std::uint_least64_t v{static_cast(a)*b}; + return static_cast(v>>(::std::numeric_limits<::std::uint_least32_t>::digits)); + } +} + +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 constexpr(std::endian::native==std::endian::little) + { + auto [a0,a1]=__builtin_bit_cast(ul32x2_little_endian,a); //get around gcc bug + high=a1; + return a0; + } + else if constexpr(std::endian::native==std::endian::big) + { + auto [a1,a0]=__builtin_bit_cast(ul32x2_big_endian,a); + high=a1; + return a0; + } + else +#endif +#endif + { + high=static_cast(a>>std::numeric_limits::digits); + return static_cast(a); + } +} + +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 constexpr(std::endian::native==std::endian::little) + { + auto [a0,a1]=__builtin_bit_cast(ul_generic_x2_little_endian,a); //get around gcc bug + high=a1; + return a0; + } + else if constexpr(std::endian::native==std::endian::big) + { + auto [a1,a0]=__builtin_bit_cast(ul_generic_x2_big_endian,a); + high=a1; + return a0; + } + else +#endif +#endif + { + high=static_cast(a>>std::numeric_limits::digits); + return static_cast(a); + } +} + +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 constexpr(std::endian::native==std::endian::little) + { + return __builtin_bit_cast(std::uint_least64_t,ul32x2_little_endian{low,high}); //get around gcc bug + } + else if constexpr(std::endian::native==std::endian::big) + { + return __builtin_bit_cast(std::uint_least64_t,ul32x2_big_endian{high,low}); //get around gcc bug + } + else +#endif +#endif + { + return (static_cast(high)<<32u)|low; + } +} + +inline constexpr std::uint_least64_t umul_least_64_emulated(std::uint_least64_t a,std::uint_least64_t b,std::uint_least64_t& high) noexcept +{ + std::uint_least32_t a1; + std::uint_least32_t a0{unpack_ul64(a,a1)}; + std::uint_least32_t b1; + std::uint_least32_t b0{unpack_ul64(b,b1)}; + std::uint_least32_t c1; + std::uint_least32_t c0{umul_least_32(a0,b0,c1)}; + std::uint_least32_t a0b1h; + std::uint_least32_t a0b1l{umul_least_32(a0,b1,a0b1h)}; + std::uint_least32_t a1b0h; + std::uint_least32_t a1b0l{umul_least_32(a1,b0,a1b0h)}; + std::uint_least32_t c3; + std::uint_least32_t c2{umul_least_32(a1,b1,c3)}; + constexpr std::uint_least32_t zero{}; + bool carry{add_carry(false,c1,a0b1l,c1)}; + carry=add_carry(carry,a0b1h,c2,c2); + add_carry(carry,zero,c3,c3); + carry=add_carry(false,c1,a1b0l,c1); + carry=add_carry(carry,a1b0h,c2,c2); + add_carry(carry,zero,c3,c3); + high=pack_ul64(c2,c3); + return pack_ul64(c0,c1); +} + +inline +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L +constexpr +#endif +std::uint_least64_t umul(std::uint_least64_t a,std::uint_least64_t b,std::uint_least64_t& high) noexcept +{ +#ifdef __SIZEOF_INT128__ +#if __cpp_if_consteval >= 202106L + if consteval + { + __uint128_t res{static_cast<__uint128_t>(a)*b}; + high=static_cast(res>>64u); + return static_cast(res); + } + else +#elif __cpp_lib_is_constant_evaluated >= 201811L + if(std::is_constant_evaluated()) + { + __uint128_t res{static_cast<__uint128_t>(a)*b}; + high=static_cast(res>>64u); + return static_cast(res); + } + else + +#endif + { +#if defined(__has_builtin) + if constexpr(std::endian::native==std::endian::little||std::endian::native==std::endian::big) + { + struct u64x2_little_endian_t + { + std::uint_least64_t low,high; + }; + struct u64x2_big_endian_t + { + std::uint_least64_t high,low; + }; + using u64x2_t = std::conditional_t; + static_assert(sizeof(__uint128_t)==sizeof(u64x2_t)); +#if __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) + __builtin_memcpy(__builtin_addressof(u),__builtin_addressof(res),sizeof(u64x2_t)); +#else + std::memcpy(__builtin_addressof(u),__builtin_addressof(res),sizeof(u64x2_t)); +#endif + high=u.high; + return u.low; +#endif + } + else +#endif + { + __uint128_t res{static_cast<__uint128_t>(a)*b}; + high=static_cast(res>>64u); + return static_cast(res); + } + } +#elif defined(_MSC_VER) && defined(_M_X64) +#if __cpp_if_consteval >= 202106L + if consteval + { + return umul_least_64_emulated(a,b,high); + } + else +#elif __cpp_lib_is_constant_evaluated >= 201811L + if(std::is_constant_evaluated()) + { + return umul_least_64_emulated(a,b,high); + } + else +#endif + { + return _umul128(a,b,__builtin_addressof(high)); + } +#else + return umul_least_64_emulated(a,b,high); +#endif +} + +inline constexpr std::uint_least64_t umul_least64_high_emulated(std::uint_least64_t a,std::uint_least64_t b) noexcept +{ + std::uint_least32_t a1; + std::uint_least32_t a0{unpack_ul64(a,a1)}; + std::uint_least32_t b1; + std::uint_least32_t b0{unpack_ul64(b,b1)}; + std::uint_least32_t c1; + umul_least_32(a0,b0,c1); + std::uint_least32_t a0b1h; + std::uint_least32_t a0b1l{umul_least_32(a0,b1,a0b1h)}; + std::uint_least32_t a1b0h; + std::uint_least32_t a1b0l{umul_least_32(a1,b0,a1b0h)}; + std::uint_least32_t c3; + std::uint_least32_t c2{umul_least_32(a1,b1,c3)}; + constexpr std::uint_least32_t zero{}; + bool carry{add_carry(false,c1,a0b1l,c1)}; + carry=add_carry(carry,a0b1h,c2,c2); + add_carry(carry,zero,c3,c3); + carry=add_carry(false,c1,a1b0l,c1); + carry=add_carry(carry,a1b0h,c2,c2); + add_carry(carry,zero,c3,c3); + return pack_ul64(c2,c3); +} + +inline +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L +constexpr +#endif +std::uint_least64_t umul_least64_high(std::uint_least64_t a,std::uint_least64_t b) noexcept +{ +#ifdef __SIZEOF_INT128__ + constexpr std::uint_least64_t ul64bits{sizeof(std::uint_least64_t)* +#if defined(__CHAR_BIT__) + __CHAR_BIT__ +#else + 8u +#endif + }; + return static_cast((static_cast<__uint128_t>(a)*b)>>ul64bits); +#elif defined(_MSC_VER) && defined(_M_X64) +#if __cpp_if_consteval >= 202106L + if consteval + { + return umul_least64_high_emulated(a,b); + } + else +#elif __cpp_lib_is_constant_evaluated >= 201811L + if(std::is_constant_evaluated()) + { + return umul_least64_high_emulated(a,b); + } + else +#endif + { + return __umulh(a,b); + } +#else + return umul_least64_high_emulated(a,b); +#endif +} + +inline constexpr std::size_t add_or_overflow_die(std::size_t a,std::size_t b) noexcept +{ +#if defined(_MSC_VER) && !defined(__clang__) +#if __cpp_lib_is_constant_evaluated >= 201811L + if(!std::is_constant_evaluated()) + { +#if defined(_M_X64) + std::size_t res; + if(_addcarry_u64(false,a,b,__builtin_addressof(res)))[[unlikely]] + __debugbreak(); + return res; +#elif defined(_M_X32) + std::size_t size{a+b}; + if(size +requires (std::same_as>&&...) +inline constexpr std::size_t add_or_overflow_die_chain(std::size_t size,Args... args) noexcept +{ + if constexpr(sizeof...(Args)==0) + return size; + else + return add_or_overflow_die(size,add_or_overflow_die_chain(args...)); +} + +inline constexpr std::size_t mul_or_overflow_die(std::size_t a,std::size_t b) noexcept +{ +#if defined(_MSC_VER) && !defined(__clang__) + std::size_t const max{SIZE_MAX/b}; + if(max +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr bool sub_underflow_naive(int_type a,int_type b,int_type& c) noexcept +{ + int_type int_type_min{std::numeric_limits::min()}, + int_type_max{std::numeric_limits::max()}; + int_type zero{}; + if(zeroint_type_max) + return true; + c=a-b; + return false; +} + +template +inline constexpr bool sub_underflow(int_type a,int_type b,int_type& c) noexcept +{ +#if defined(_MSC_VER) && !defined(__clang__) + return sub_underflow_naive(a,b,c); +#elif __has_builtin(__builtin_sub_underflow) + return __builtin_sub_underflow(a,b,__builtin_addressof(c)); +#else + return sub_underflow_naive(a,b,c); +#endif +} + +template +requires (std::same_as>&&...) +inline constexpr std::size_t mul_or_overflow_die_chain(std::size_t size,Args... args) noexcept +{ + if constexpr(sizeof...(Args)==0) + return size; + else + return mul_or_overflow_die(size,mul_or_overflow_die_chain(args...)); +} + +template +inline constexpr std::size_t cal_allocation_size_or_die(std::size_t size) noexcept +{ +#if defined(_MSC_VER) && !defined(__clang__) + constexpr std::size_t max_size{SIZE_MAX/sizeof(T)}; + if(size>max_size) + __debugbreak(); + return size*sizeof(T); +#elif __has_builtin(__builtin_mul_overflow) && __has_builtin(__builtin_trap) + if(__builtin_mul_overflow(size,sizeof(T),__builtin_addressof(size)))[[unlikely]] + __builtin_trap(); + return size; +#else + constexpr std::size_t max_size{SIZE_MAX/sizeof(T)}; + if(size>max_size) + fast_terminate(); + return size*sizeof(T); +#endif +} + +template +struct udiv_result +{ + using unsigned_type = U; + U quotient_low,quotient_high; + U remainder_low,remainder_high; +}; + +template +inline constexpr U shiftright_naive(U low_part,U high_part,std::uint_least8_t shift) noexcept +{ + U const value{(static_cast(1)<>shift)|(v<<(bits-shift)); +} + +template +inline constexpr U shiftright(U low_part,U high_part,std::uint_least8_t shift) noexcept +{ +#if __cpp_lib_is_constant_evaluated >= 201811L + if(std::is_constant_evaluated()) + return shiftright_naive(low_part,high_part,shift); + else +#endif + { +#if defined(_MSC_VER) && (defined(_M_X64) || defined(__i386__)) && !defined(__clang__) + if constexpr(sizeof(U)==8&&sizeof(std::size_t)>=8) + { + return __shiftright128(low_part,high_part,shift); + } + else +#endif + { + return shiftright_naive(low_part,high_part,shift); + } + } +} + +/* +https://code.woboq.org/llvm/compiler-rt/lib/builtins/udivmodti4.c.html#__udivmodti4 +*/ +template +inline constexpr udiv_result udivmod(U n_low, U n_high,U d_low,U d_high) noexcept +{ + // special cases, X is unknown, K != 0 + if (n_high == 0) + { + if (d_high == 0) + { + return {n_low/d_low,0,n_low%d_low,0}; + } + return {0,0,n_low,0}; + } + constexpr std::uint_least32_t n_udword_bits{sizeof(U) * 8}; + constexpr std::uint_least32_t n_utword_bits{n_udword_bits<<1}; + constexpr std::uint_least32_t n_udword_bits_m1{n_udword_bits-1}; + constexpr std::uint_least32_t n_udword_bits_m2{n_udword_bits-2}; + // n_high != 0 + U q_low,q_high,r_low,r_high; + std::uint_least32_t sr; + if (d_low == 0) + { + if (d_high == 0) + fast_terminate(); + // d_high != 0 + if (n_low == 0) + { + // K 0 + // --- + // K 0 + return {n_high / d_high,0,0,n_high % d_high}; + } + // K K + // --- + // K 0 + if ((d_high & (d_high - 1)) == 0) + { +#if defined(__has_builtin) +#if __has_builtin(__builtin_ctzll) + return {n_high >> __builtin_ctzll(d_high),0,n_low,n_high & (d_high - 1)}; +#else + return {n_high >> static_cast(std::countl_zero(d_high)),0,n_low,n_high & (d_high - 1)}; +#endif +#else + return {n_high >> static_cast(std::countl_zero(d_high)),0,n_low,n_high & (d_high - 1)}; +#endif + + } + // K K + // --- + // K 0 +#if defined(__has_builtin) +#if __has_builtin(__builtin_ctzll) + sr=static_cast(__builtin_clzll(d_high) - __builtin_clzll(n_high)); +#else + sr=static_cast(std::countl_zero(d_high) - std::countl_zero(n_high)); +#endif +#else + sr=static_cast(std::countl_zero(d_high) - std::countl_zero(n_high)); +#endif + + // 0 <= sr <= n_udword_bits - 2 or sr large + if (sr > n_udword_bits_m2) + return {0,0,n_low,n_high}; + ++sr; + // 1 <= sr <= n_udword_bits - 1 + // q.all = n.all << (n_utword_bits - sr); + q_low=0; + q_high=n_low << (n_udword_bits - sr); + // r.all = n.all >> sr; + r_high=n_high >> sr; + r_low=(n_high << (n_udword_bits - sr)) | (n_low >> sr); + } + else /* d_low != 0 */ + { + if (d_high == 0) + { + // K X + // --- + // 0 K + if ((d_low & (d_low - 1)) == 0) /* if d is a power of 2 */ + { + U rem{n_low & (d_low - 1)}; + if (d_low == 1) + return {n_low,n_high,rem,0}; +#if defined(__has_builtin) +#if __has_builtin(__builtin_ctzll) + sr = static_cast(__builtin_ctzll(d_low)); +#else + sr = static_cast(std::countl_zero(d_low)); +#endif +#else + sr = static_cast(std::countl_zero(d_low)); +#endif + q_high = n_high >> sr; + q_low = (n_high << (n_udword_bits - sr)) | (n_low >> sr); + return {q_low,q_high,rem,0}; + } + // K X + // --- + // 0 K +#if defined(__has_builtin) +#if __has_builtin(__builtin_ctzll) + sr = 1 + n_udword_bits + static_cast(__builtin_clzll(d_low)) - static_cast(__builtin_clzll(n_high)); +#else + sr = 1 + n_udword_bits + static_cast(std::countl_zero(d_low)) - static_cast(std::countl_zero(n_high)); +#endif +#else + sr = 1 + n_udword_bits + static_cast(std::countl_zero(d_low)) - static_cast(std::countl_zero(n_high)); +#endif + // 2 <= sr <= n_utword_bits - 1 + // q.all = n.all << (n_utword_bits - sr); + // r.all = n.all >> sr; + if (sr == n_udword_bits) + { + q_low = 0; + q_high = n_low; + r_high = 0; + r_low = n_high; + } + else if (sr < n_udword_bits) /* 2 <= sr <= n_udword_bits - 1 */ + { + q_low = 0; + q_high = n_low << (n_udword_bits - sr); + r_high = n_high >> sr; + r_low = (n_high << (n_udword_bits - sr)) | (n_low >> sr); + } + else /* n_udword_bits + 1 <= sr <= n_utword_bits - 1 */ + { + q_low = n_low << (n_utword_bits - sr); + q_high = (n_high << (n_utword_bits - sr)) | + (n_low >> (sr - n_udword_bits)); + r_high = 0; + r_low = n_high >> (sr - n_udword_bits); + } + } + else + { + // K X + // --- + // K K +#if defined(__has_builtin) +#if __has_builtin(__builtin_ctzll) + sr = static_cast(__builtin_clzll(d_high)) - static_cast(__builtin_clzll(n_high)); +#else + sr = static_cast(std::countl_zero(d_high)) - static_cast(std::countl_zero(n_high)); +#endif +#else + sr = static_cast(std::countl_zero(d_high)) - static_cast(std::countl_zero(n_high)); +#endif + // 0 <= sr <= n_udword_bits - 1 or sr large + if (sr > n_udword_bits_m1) + return {0,0,n_low,n_high}; + ++sr; + // 1 <= sr <= n_udword_bits + // q.all = n.all << (n_utword_bits - sr); + // r.all = n.all >> sr; + q_low = 0; + if (sr == n_udword_bits) + { + q_high = n_low; + r_high = 0; + r_low = n_high; + } + else + { + r_high = n_high >> sr; + r_low = (n_high << (n_udword_bits - sr)) | (n_low >> sr); + q_high = n_low << (n_udword_bits - sr); + } + } + } + // Not a special case + // q and r are initialized with: + // q.all = n.all << (n_utword_bits - sr); + // r.all = n.all >> sr; + // 1 <= sr <= n_utword_bits - 1 + + std::uint_least8_t carry{}; + for (;sr;--sr) + { + // r:q = ((r:q) << 1) | carry + r_high = (r_high << 1) | (r_low >> n_udword_bits_m1); + r_low = (r_low << 1) | (q_high >> n_udword_bits_m1); + q_high = (q_high << 1) | (q_low >> n_udword_bits_m1); + q_low = (q_low << 1) | static_cast(carry); + + + U s_low,s_high; + sub_borrow(sub_borrow(true,d_low,r_low,s_low),d_high,r_high,s_high); + s_low=shiftright(s_low,s_high,n_udword_bits_m1); + s_high>>=n_udword_bits_m1; + carry = s_low & 1; + s_low&=d_low; + s_high&=d_high; + sub_borrow(sub_borrow(false,r_low,s_low,r_low),r_high,s_high,r_high); +// r.all -= d.all & s; + } + q_high = (q_high << 1) | (q_low >> n_udword_bits_m1); + q_low = (q_low << 1) | carry; + return {q_low,q_high,r_low,r_high}; +} + +} + +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning( pop ) +#endif diff --git a/src/fast_io/include/fast_io_core_impl/intrinsics/carry.h b/src/fast_io/include/fast_io_core_impl/intrinsics/carry.h new file mode 100644 index 0000000..1846bf5 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/intrinsics/carry.h @@ -0,0 +1,174 @@ +#pragma once + +/* +https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html + +GCC document says we can use __builtin_add_overflow for adc pattern. +No need __builtin_addc which is complicated. +*/ + +namespace fast_io +{ + +namespace intrinsics +{ + +template +inline constexpr T addc(T a, T b, bool carryin, bool &carryout) noexcept +{ +#if __has_cpp_attribute(assume) + [[assume(carryin == 0 || carryin == 1)]]; +#endif + +#if defined(__cpp_if_consteval) + if !consteval +#else + if (!__builtin_is_constant_evaluated()) +#endif + { +#if defined(_MSC_VER) && !defined(__clang__) && (defined(_M_IX86) || defined(_M_AMD64)) +#if !__has_cpp_attribute(assume) + __assume(carryin == 0 || carryin == 1); +#endif + if constexpr (sizeof(T) == 1) + { + char unsigned res; + carryout = static_cast(::fast_io::intrinsics::msvc::x86::_addcarry_u8( + static_cast(carryin), a, b, __builtin_addressof(res))); + return res; + } + else if constexpr (sizeof(T) == 2) + { + short unsigned res; + carryout = static_cast(::fast_io::intrinsics::msvc::x86::_addcarry_u16( + static_cast(carryin), a, b, __builtin_addressof(res))); + return res; + } + else if constexpr (sizeof(T) == 4) + { + unsigned res; + carryout = static_cast(::fast_io::intrinsics::msvc::x86::_addcarry_u32( + static_cast(carryin), a, b, __builtin_addressof(res))); + return res; + } + else if constexpr (sizeof(T) == 8) + { + if constexpr (sizeof(::std::uint_least64_t) <= sizeof(::std::size_t)) + { + long long unsigned res; + carryout = static_cast(::fast_io::intrinsics::msvc::x86::_addcarry_u64( + static_cast(carryin), a, b, __builtin_addressof(res))); + return res; + } + else + { + unsigned alow = static_cast(a); + unsigned ahigh = static_cast(a >> 32u); + unsigned blow = static_cast(b); + unsigned bhigh = static_cast(b >> 32u); + unsigned reslow, reshigh; + bool carrytemp{static_cast(::fast_io::intrinsics::msvc::x86::_addcarry_u32( + static_cast(carryin), alow, blow, __builtin_addressof(reslow)))}; + carryout = ::fast_io::intrinsics::msvc::x86::_addcarry_u32(carrytemp, ahigh, bhigh, + __builtin_addressof(reshigh)); + return (static_cast(reshigh) << 32u) | reslow; + } + } +#elif defined(__has_builtin) +#if __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; + carryout = a < b; + a += carryin; + carryout |= a < static_cast(carryin); + return a; +} + +template +inline constexpr T subc(T a, T b, bool carryin, bool &carryout) noexcept +{ +#if __has_cpp_attribute(assume) + [[assume(carryin == 0 || carryin == 1)]]; +#endif + +#if defined(__cpp_if_consteval) + if !consteval +#else + if (!__builtin_is_constant_evaluated()) +#endif + { +#if defined(_MSC_VER) && !defined(__clang__) && (defined(_M_IX86) || defined(_M_AMD64)) +#if !__has_cpp_attribute(assume) + __assume(carryin == 0 || carryin == 1); +#endif + if constexpr (sizeof(T) == 1) + { + char unsigned res; + carryout = static_cast(::fast_io::intrinsics::msvc::x86::_subborrow_u8( + static_cast(carryin), a, b, __builtin_addressof(res))); + return res; + } + else if constexpr (sizeof(T) == 2) + { + short unsigned res; + carryout = static_cast(::fast_io::intrinsics::msvc::x86::_subborrow_u16( + static_cast(carryin), a, b, __builtin_addressof(res))); + return res; + } + else if constexpr (sizeof(T) == 4) + { + unsigned res; + carryout = static_cast(::fast_io::intrinsics::msvc::x86::_subborrow_u32( + static_cast(carryin), a, b, __builtin_addressof(res))); + return res; + } + else if constexpr (sizeof(T) == 8) + { + if constexpr (sizeof(::std::uint_least64_t) <= sizeof(::std::size_t)) + { + long long unsigned res; + carryout = static_cast(::fast_io::intrinsics::msvc::x86::_subborrow_u64( + static_cast(carryin), a, b, __builtin_addressof(res))); + return res; + } + else + { + unsigned alow = static_cast(a); + unsigned ahigh = static_cast(a >> 32u); + unsigned blow = static_cast(b); + unsigned bhigh = static_cast(b >> 32u); + unsigned reslow, reshigh; + bool carrytemp{static_cast(::fast_io::intrinsics::msvc::x86::_subborrow_u32( + static_cast(carryin), alow, blow, __builtin_addressof(reslow)))}; + carryout = static_cast(::fast_io::intrinsics::msvc::x86::_subborrow_u32( + carrytemp, alow, bhigh, __builtin_addressof(reshigh))); + return (static_cast(reshigh) << 32u) | reslow; + } + } +#elif defined(__has_builtin) +#if __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; + carryout = a < b; + a = b - carryin; + carryout |= b < a; + return a; +} + +} // namespace intrinsics + +} // namespace fast_io diff --git a/src/fast_io/include/fast_io_core_impl/intrinsics/impl.h b/src/fast_io/include/fast_io_core_impl/intrinsics/impl.h new file mode 100644 index 0000000..874caec --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/intrinsics/impl.h @@ -0,0 +1,4 @@ +#pragma once + +#include "carry.h" +#include "udivmod.h" diff --git a/src/fast_io/include/fast_io_core_impl/intrinsics/msvc/common.h b/src/fast_io/include/fast_io_core_impl/intrinsics/msvc/common.h new file mode 100644 index 0000000..407cd96 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/intrinsics/msvc/common.h @@ -0,0 +1,6 @@ +#pragma once + +namespace fast_io::intrinsics::msvc +{ + +} diff --git a/src/fast_io/include/fast_io_core_impl/intrinsics/msvc/impl.h b/src/fast_io/include/fast_io_core_impl/intrinsics/msvc/impl.h new file mode 100644 index 0000000..ba41309 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/intrinsics/msvc/impl.h @@ -0,0 +1,5 @@ +#pragma once + +#if defined(_MSC_VER) && !defined(__clang__) +#include "x86.h" +#endif diff --git a/src/fast_io/include/fast_io_core_impl/intrinsics/msvc/x86.h b/src/fast_io/include/fast_io_core_impl/intrinsics/msvc/x86.h new file mode 100644 index 0000000..2ec345b --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/intrinsics/msvc/x86.h @@ -0,0 +1,25 @@ +#pragma once + +namespace fast_io::intrinsics::msvc::x86 +{ + +extern "C" +{ + unsigned __int64 __readgsqword(unsigned long); + unsigned long __readfsdword(unsigned long); + unsigned char _addcarry_u8(unsigned char, unsigned char, unsigned char, unsigned char *); + unsigned char _addcarry_u16(unsigned char, unsigned short, unsigned short, unsigned short *); + unsigned char _addcarry_u32(unsigned char, unsigned int, unsigned int, unsigned int *); + unsigned char _addcarry_u64(unsigned char, unsigned __int64, unsigned __int64, unsigned __int64 *); + + unsigned char _subborrow_u8(unsigned char, unsigned char, unsigned char, unsigned char *); + unsigned char _subborrow_u16(unsigned char, unsigned short, unsigned short, unsigned short *); + unsigned char _subborrow_u32(unsigned char, unsigned int, unsigned int, unsigned int *); + unsigned char _subborrow_u64(unsigned char, unsigned __int64, unsigned __int64, unsigned __int64 *); + + unsigned __int64 _udiv128(unsigned __int64, unsigned __int64, unsigned __int64, unsigned __int64 *); + unsigned __int64 __shiftleft128(unsigned __int64, unsigned __int64, unsigned char); + unsigned __int64 __shiftright128(unsigned __int64, unsigned __int64, unsigned char); +} + +} // namespace fast_io::intrinsics::msvc::x86 diff --git a/src/fast_io/include/fast_io_core_impl/intrinsics/udivmod.h b/src/fast_io/include/fast_io_core_impl/intrinsics/udivmod.h new file mode 100644 index 0000000..a1b0772 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/intrinsics/udivmod.h @@ -0,0 +1,224 @@ +#pragma once + +namespace fast_io +{ + +namespace intrinsics +{ + +template +struct tuint +{ + T quotient, remainder; +}; + +template +struct tuints +{ + T quotientlow, quotienthigh, remainderlow, remainderhigh; +}; + +/* +Referenced from +https://github.com/llvm/llvm-project/blob/main/compiler-rt/lib/builtins/udivmodti4.c +*/ + +template +inline constexpr tuint udivbigbysmalltosmalldefault(T u1, T u0, T v) noexcept +{ +#if defined(__x86_64__) || defined(_M_AMD64) + if constexpr (sizeof(T) == sizeof(::std::uint_least64_t)) + { +#if defined(__cpp_if_consteval) + if !consteval +#else + if (!__builtin_is_constant_evaluated()) +#endif + { +#if defined(_MSC_VER) && !defined(__clang__) + long long unsigned remainder; + auto quotient{::fast_io::intrinsics::msvc::x86::_udiv128(u1, u0, v, __builtin_addressof(remainder))}; +#else + T quotient, remainder; + __asm__("{divq\t%[v]|div\t%[v]}" : "=a"(quotient), "=d"(remainder) : [v] "r"(v), "a"(u0), "d"(u1)); +#endif + return {quotient, remainder}; + } + } +#endif + + constexpr unsigned n_udword_bits = ::std::numeric_limits::digits; + constexpr unsigned n_udword_bitsdv2 = n_udword_bits / 2; + constexpr T one{1u}; + constexpr T b = (one << (n_udword_bits / 2)); // Number base (32 bits) + constexpr T mask = (b - one); + T un1, un0; // Norm. dividend LSD's + T vn1, vn0; // Norm. divisor digits + T q1, q0; // Quotient digits + T un64, un21, un10; // Dividend digit pairs + T rhat; // A remainder + + unsigned s = static_cast(::std::countl_zero(v)); // Shift amount for normalization + if (s) + { + // Normalize the divisor. + v = v << s; + un64 = (u1 << s) | (u0 >> (n_udword_bits - static_cast(s))); + un10 = u0 << s; // Shift dividend left + } + else + { + // Avoid undefined behavior of (u0 >> 64). + un64 = u1; + un10 = u0; + } + // Break divisor up into two 32-bit digits. + vn1 = v >> n_udword_bitsdv2; + vn0 = v & mask; + // Break right half of dividend into two digits. + un1 = un10 >> n_udword_bitsdv2; + un0 = un10 & mask; + // Compute the first quotient digit, q1. + q1 = un64 / vn1; + rhat = un64 - q1 * vn1; + // q1 has at most error 2. No more than 2 iterations. + while (q1 >= b || q1 * vn0 > b * rhat + un1) + { + --q1; + rhat = rhat + vn1; + if (rhat >= b) + { + break; + } + } + un21 = un64 * b + un1 - q1 * v; + // Compute the second quotient digit. + q0 = un21 / vn1; + rhat = un21 - q0 * vn1; + // q0 has at most error 2. No more than 2 iterations. + while (q0 >= b || q0 * vn0 > b * rhat + un0) + { + --q0; + rhat = rhat + vn1; + if (rhat >= b) + { + break; + } + } + + return {q1 * b + q0, ((un21 * b + un0 - q0 * v) >> s)}; +} + +template +inline constexpr T shiftleft(T low, T high, unsigned shift) noexcept +{ +#if defined(_MSC_VER) && !defined(__clang__) && defined(_M_AMD64) + if constexpr (sizeof(T) == sizeof(long long unsigned)) + { +#if defined(__cpp_if_consteval) + if !consteval +#else + if (!__builtin_is_constant_evaluated()) +#endif + { + return ::fast_io::intrinsics::msvc::x86::__shiftleft128(low, high, static_cast(shift)); + } + } +#endif + constexpr unsigned n_udword_bits = ::std::numeric_limits::digits; + if (shift == 0u) + { + return high; + } + unsigned lowshifter{n_udword_bits - shift}; + return (high << shift) | (low >> lowshifter); +} + +template +inline constexpr T shiftright(T low, T high, unsigned shift) noexcept +{ +#if defined(_MSC_VER) && !defined(__clang__) && defined(_M_AMD64) + if constexpr (sizeof(T) == sizeof(long long unsigned)) + { +#if defined(__cpp_if_consteval) + if !consteval +#else + if (!__builtin_is_constant_evaluated()) +#endif + { + return ::fast_io::intrinsics::msvc::x86::__shiftright128(low, high, static_cast(shift)); + } + } +#endif + constexpr unsigned n_udword_bits = ::std::numeric_limits::digits; + if (shift == 0u) + { + return low; + } + unsigned lowshifter{n_udword_bits - shift}; + return (high << lowshifter) | (low >> shift); +} + +template +inline constexpr ::fast_io::intrinsics::tuints udivmod(T dividendlow, T dividendhigh, T divisorlow, + T divisorhigh) noexcept +{ + if (divisorhigh > dividendhigh || (divisorhigh == dividendhigh && divisorlow > dividendlow)) + { + return {0, 0, dividendlow, dividendhigh}; + } + T quotientlow, quotienthigh, remainderlow, remainderhigh; + // When the divisor fits in 64 bits, we can use an optimized path. + if (divisorhigh == 0) + { + remainderhigh = 0; + if (dividendhigh < divisorlow) + { + // The result fits in 64 bits. + auto temp = ::fast_io::intrinsics::udivbigbysmalltosmalldefault(dividendhigh, dividendlow, divisorlow); + quotientlow = temp.quotient; + remainderlow = temp.remainder; + quotienthigh = 0; + } + else + { + // First, divide with the high part to get the remainder in dividendhigh. + // After that dividendhigh < divisorlow. + quotienthigh = dividendhigh / divisorlow; + dividendhigh = dividendhigh % divisorlow; + auto temp = ::fast_io::intrinsics::udivbigbysmalltosmalldefault(dividendhigh, dividendlow, divisorlow); + quotientlow = temp.quotient; + remainderlow = temp.remainder; + } + return {quotientlow, quotienthigh, remainderlow, remainderhigh}; + } + // 0 <= shift <= 63. + auto shift = static_cast(::std::countl_zero(divisorhigh) - ::std::countl_zero(dividendhigh)); + + divisorhigh = ::fast_io::intrinsics::shiftleft(divisorlow, divisorhigh, shift); + divisorlow <<= shift; + + quotientlow = 0; + bool carry; + do + { + carry = 0; + dividendlow = ::fast_io::intrinsics::subc(dividendlow, divisorlow, carry, carry); + dividendhigh = ::fast_io::intrinsics::subc(dividendhigh, divisorhigh, carry, carry); + constexpr T zero{}; + T mask{zero - carry}; + T templow{divisorlow & mask}, temphigh{divisorhigh & mask}; + carry = !carry; + quotientlow = ::fast_io::intrinsics::addc(quotientlow, quotientlow, carry, carry); + carry = 0; + dividendlow = ::fast_io::intrinsics::addc(dividendlow, templow, carry, carry); + dividendhigh = ::fast_io::intrinsics::addc(dividendhigh, temphigh, carry, carry); + divisorlow = ::fast_io::intrinsics::shiftright(divisorlow, divisorhigh, 1u); + divisorhigh >>= 1u; + } while (shift--); + return {quotientlow, 0, dividendlow, dividendhigh}; +} + +} // namespace intrinsics + +} // namespace fast_io diff --git a/src/fast_io/include/fast_io_core_impl/io_deco_ref.h b/src/fast_io/include/fast_io_core_impl/io_deco_ref.h new file mode 100644 index 0000000..7406581 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/io_deco_ref.h @@ -0,0 +1,100 @@ +#pragma once + +namespace fast_io +{ + +template +struct deco_reference_wrapper +{ + using decorator_type = decot; + decorator_type* ptr{}; +}; + +template +constexpr deco_reference_wrapper deco_value_handle(deco_reference_wrapper wrap) noexcept +{ + return wrap; +} + +namespace details +{ +template +concept has_deco_value_handle_impl = requires(decot & deco) +{ + deco_value_handle(deco); +}; +} + +template +inline constexpr auto io_deco_ref(decot& deco) noexcept +{ + if constexpr(details::has_deco_value_handle_impl) + return deco_value_handle(deco); + else + return deco_reference_wrapper>{__builtin_addressof(deco)}; +} + +template +requires requires(decot& dc,std::size_t size) +{ + {deco_reserve_size(io_reserve_type,dc,size)}->std::same_as; +} +constexpr std::size_t deco_reserve_size(io_reserve_type_t>,deco_reference_wrapper deco,std::size_t size) +{ + return deco_reserve_size(io_reserve_type,*deco.ptr,size); +} + +template<::std::random_access_iterator srcIter,::std::random_access_iterator toIter,typename decot> +requires requires(decot& deco,srcIter srcit,toIter toit) +{ + {deco_reserve_define(io_reserve_type<::std::iter_value_t,decot>,deco,srcit,srcit,toit)}->std::convertible_to; +} +constexpr toIter deco_reserve_define(io_reserve_type_t<::std::iter_value_t,deco_reference_wrapper>,deco_reference_wrapper deco,srcIter first,srcIter last,toIter iter) +{ + return deco_reserve_define(io_reserve_type<::std::iter_value_t,decot>,*deco.ptr,first,last,iter); +} + +#if 0 +template +requires requires(decot& deco,fromIter from_it) +{ + {deco_reserve_size(io_reserve_type,deco,from_it,from_it)}->std::same_as; +} +constexpr std::size_t deco_reserve_size(io_reserve_type_t>, + deco_reference_wrapper deco,fromIter from_first,fromIter from_last) +{ + return deco_reserve_size(io_reserve_type,*deco.ptr,from_first,from_last); +}; + +template +requires requires(decot& deco,fromIter from_it,toIter to_it) +{ + {deco_reserve_define(io_reserve_type,deco,from_it,from_it,to_it,to_it)}->std::same_as; +} +constexpr toIter deco_reserve_define(io_reserve_type_t>, + deco_reference_wrapper deco,fromIter from_first,fromIter from_last,toIter to_first,toIter to_last) +{ + return deco_reserve_define(io_reserve_type,*deco.ptr,from_first,from_last,to_first,to_last); +}; + + +template +requires maybe_noop_decorator +constexpr bool deco_maybe_noop(io_reserve_type_t>,deco_reference_wrapper deco) +{ + return deco_maybe_noop(io_reserve_type,*deco.ptr); +}; + +template +requires always_noop_decorator +constexpr void deco_always_noop(io_reserve_type_t>,deco_reference_wrapper deco){}; + +template +requires reserve_inverse_size_decorator +constexpr std::size_t deco_reserve_inverse_size(io_reserve_type_t>,deco_reference_wrapper deco,std::size_t size) +{ + return deco_reserve_inverse_size(io_reserve_type,*deco.ptr,size); +} +#endif +} + diff --git a/src/fast_io/include/fast_io_core_impl/io_ref.h b/src/fast_io/include/fast_io_core_impl/io_ref.h new file mode 100644 index 0000000..189e28b --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/io_ref.h @@ -0,0 +1,236 @@ +#pragma once + +namespace fast_io +{ + +template +requires (!value_based_stream) +struct io_reference_wrapper +{ + using char_type = typename stm::char_type; + using native_handle_type = stm*; + stm* ptr{}; + inline constexpr void lock() requires(mutex_stream) + { + ptr->lock(); + } + inline constexpr void unlock() requires(mutex_stream) + { + ptr->unlock(); + } + inline constexpr decltype(auto) unlocked_handle() requires(mutex_stream) + { + return ptr->unlocked_handle(); + } + inline constexpr stm* native_handle() const noexcept + { + return ptr; + } + inline explicit constexpr operator bool() const noexcept + { + return ptr; + } + inline constexpr stm* release() noexcept + { + auto temp{ptr}; + ptr=nullptr; + return temp; + } +}; + +namespace details +{ +template +concept require_io_value_handle_impl = requires(strm& stm) +{ + io_value_handle(stm); +}; + +} + +template +inline constexpr auto io_ref(strm& stm) noexcept +{ + if constexpr(details::require_io_value_handle_impl) + return io_value_handle(stm); + else + return io_reference_wrapper>{__builtin_addressof(stm)}; +} + +template +constexpr io_reference_wrapper io_value_handle(io_reference_wrapper wrap) noexcept +{ + return wrap; +} + +template +constexpr decltype(auto) write(io_reference_wrapper out,Iter first,Iter last) +{ + return write(*out.ptr,first,last); +} + +template +constexpr void obuffer_overflow(io_reference_wrapper out,typename std::remove_cvref_t::char_type ch) +{ + obuffer_overflow(*out.ptr,ch); +} + +template +constexpr decltype(auto) obuffer_begin(io_reference_wrapper out) +{ + return obuffer_begin(*out.ptr); +} + +template +constexpr decltype(auto) obuffer_curr(io_reference_wrapper out) +{ + return obuffer_curr(*out.ptr); +} + +template +constexpr decltype(auto) obuffer_end(io_reference_wrapper out) +{ + return obuffer_end(*out.ptr); +} + +template +constexpr decltype(auto) zero_copy_out_handle(io_reference_wrapper out) +{ + return zero_copy_out_handle(*out.ptr); +} + +template +constexpr void obuffer_set_curr(io_reference_wrapper out,std::remove_cvref_t ptr) +{ + obuffer_set_curr(*out.ptr,ptr); +} + +template +constexpr void oreserve(io_reference_wrapper out,std::size_t n) +{ + oreserve(*out.ptr,n); +} + +template +constexpr void oshrink_to_fit(io_reference_wrapper out) +{ + oshrink_to_fit(*out.ptr); +} + +template +constexpr decltype(auto) scatter_write(io_reference_wrapper out,io_scatters_t sp) +{ + return scatter_write(*out.ptr,sp); +} + +template +requires requires(output outp) +{ + obuffer_initialize(outp); +} +constexpr void obuffer_initialize(io_reference_wrapper out) +{ + obuffer_initialize(*out.ptr); +} + +template +constexpr Iter read(io_reference_wrapper in,Iter first,Iter last) +{ + return read(*in.ptr,first,last); +} +template +constexpr bool ibuffer_underflow(io_reference_wrapper in) +{ + return ibuffer_underflow(*in.ptr); +} + +template +constexpr decltype(auto) ibuffer_cap(io_reference_wrapper in) +{ + return ibuffer_cap(*in.ptr); +} + +template +constexpr decltype(auto) ibuffer_begin(io_reference_wrapper in) +{ + return ibuffer_begin(*in.ptr); +} + +template +constexpr decltype(auto) ibuffer_curr(io_reference_wrapper in) +{ + return ibuffer_curr(*in.ptr); +} +template +constexpr decltype(auto) ibuffer_end(io_reference_wrapper in) +{ + return ibuffer_end(*in.ptr); +} + +template +constexpr void ibuffer_set_curr(io_reference_wrapper in,std::remove_cvref_t ptr) +{ + ibuffer_set_curr(*in.ptr,ptr); +} + +template +constexpr decltype(auto) zero_copy_in_handle(io_reference_wrapper in) +{ + return zero_copy_in_handle(*in.ptr); +} + +template +constexpr decltype(auto) scatter_read(io_reference_wrapper in,io_scatters_t sp) +{ + return scatter_read(*in.ptr,sp); +} + +template +requires requires(input inp) +{ + ibuffer_initialize(inp); +} +constexpr void ibuffer_initialize(io_reference_wrapper in) +{ + ibuffer_initialize(*in.ptr); +} + +template +constexpr std::uintmax_t seek(io_reference_wrapper rac,std::intmax_t pos=0,seekdir sdir=seekdir::cur) +{ + return seek(*rac.ptr,pos,sdir); +} + +template +constexpr decltype(auto) require_secure_clear(io_reference_wrapper sc) +{ + return require_secure_clear(*sc.ptr); +} + +template +constexpr void ibuffer_underflow_never(io_reference_wrapper){} + +template +constexpr void obuffer_overflow_never(io_reference_wrapper){} + +template +constexpr void flush(io_reference_wrapper co) +{ + flush(*co.ptr); +} + +template +inline constexpr std::size_t obuffer_constant_size( + io_reserve_type_t::char_type, + io_reference_wrapper>) noexcept +{ + return obuffer_constant_size(io_reserve_type); +} + +template +inline constexpr void obuffer_constant_flush_prepare(io_reference_wrapper co) noexcept +{ + obuffer_constant_flush_prepare(*co.ptr); +} + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_core_impl/iso/iso8601.h b/src/fast_io/include/fast_io_core_impl/iso/iso8601.h new file mode 100644 index 0000000..aea0f2c --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/iso/iso8601.h @@ -0,0 +1,1530 @@ +#pragma once + +namespace fast_io +{ + +template +struct basic_timestamp +{ + static inline constexpr std::int_least64_t seconds_offset_to_epoch{off_to_epoch}; + std::int_least64_t seconds{}; + std::uint_least64_t subseconds{}; + template + explicit constexpr operator basic_timestamp() noexcept requires(off_to_epoch!=new_off_to_epoch) + { + constexpr std::int_least64_t diff{off_to_epoch-new_off_to_epoch}; + return {seconds+diff,subseconds}; + } + + template + explicit constexpr operator flt_type() noexcept + { + //I know this is not accurate. but it is better than nothing + constexpr flt_type precision{static_cast(uint_least64_subseconds_per_second)}; + return static_cast(seconds)+static_cast(subseconds)/precision; + } +}; + +template +inline constexpr bool operator==(basic_timestamp a,basic_timestamp b) noexcept +{ + return (a.seconds==b.seconds)&(a.subseconds==b.subseconds); +} + +template +inline constexpr auto operator<=>(basic_timestamp a,basic_timestamp b) noexcept +{ + auto v{a.seconds<=>b.seconds}; + if(v==0) + { + if(a.seconds<0) + return b.subseconds<=>a.subseconds; + return a.subseconds<=>b.subseconds; + } + return v; +} + +namespace details +{ +struct timestamp_u +{ + std::uint_least64_t seconds; + std::uint_least64_t subseconds; +}; + +inline constexpr timestamp_u add_impl(timestamp_u a,timestamp_u b) noexcept +{ + constexpr std::uint_least64_t max_digit{std::numeric_limits::max()/uint_least64_subseconds_per_second}; + std::uint_least64_t res; + bool cf; + if constexpr(max_digit==1) + { + cf=intrinsics::add_carry(false,a.subseconds,b.subseconds,res); + if(uint_least64_subseconds_per_second<=res) + { + res-=uint_least64_subseconds_per_second; + cf=true; + } + } + else + { + if((cf=(uint_least64_subseconds_per_second<=res))) + res-=uint_least64_subseconds_per_second; + } + std::uint_least64_t seconds; + intrinsics::add_carry(cf,a.seconds,b.seconds,seconds); + return {seconds,res}; +} + +inline constexpr timestamp_u sub_impl(timestamp_u a,timestamp_u b) noexcept +{ + std::uint_least64_t res; + std::uint_least64_t seconds; + bool borrow{intrinsics::sub_borrow(false,a.subseconds,b.subseconds,res)}; + intrinsics::sub_borrow(borrow,a.seconds,b.seconds,seconds); + if(borrow) + res+=uint_least64_subseconds_per_second; + return {seconds,res}; +} + +inline constexpr basic_timestamp<0> div_uint(std::int_least64_t rseconds,std::uint_least64_t subseconds,std::uint_least64_t d) noexcept +{ + if(d==0)[[unlikely]] + fast_terminate(); + bool minus{rseconds<0}; + std::uint_least64_t seconds{static_cast(rseconds)}; + constexpr std::uint_least64_t zero{}; + if(minus) + seconds=zero-seconds; +#ifdef __SIZEOF_INT128__ + __uint128_t total_subseconds{static_cast<__uint128_t>(seconds)*uint_least64_subseconds_per_second+subseconds}; + std::uint_least64_t mid{d>>1}; + __uint128_t rr{total_subseconds%d}; + std::uint_least64_t r{static_cast(rr)}; + __uint128_t q{total_subseconds/d}; + if(mid(q/uint_least64_subseconds_per_second)}; + std::uint_least64_t result_subseconds{static_cast(q%uint_least64_subseconds_per_second)}; + if(minus) + result_seconds=zero-result_seconds; + return {static_cast(result_seconds),result_subseconds}; +#else + constexpr std::uint_least64_t one{1}; + std::uint_least64_t total_seconds_high; + std::uint_least64_t total_seconds_low{intrinsics::umul(seconds,uint_least64_subseconds_per_second,total_seconds_high)}; + intrinsics::add_carry(intrinsics::add_carry(false,total_seconds_low,subseconds,total_seconds_low),total_seconds_high,zero,total_seconds_high); + std::uint_least64_t mid{d>>1}; + auto [q_low,q_high,r,r_high]=intrinsics::udivmod(total_seconds_low,total_seconds_high,d,zero); + if(mid(result_seconds_low),result_subseconds_low}; +#endif +} + +} + +template +inline constexpr basic_timestamp operator-(basic_timestamp a) noexcept +{ + std::uint_least64_t high{static_cast(a.seconds)}; + high=0u-high; + return {static_cast(high),a.subseconds}; +} + +template +inline constexpr basic_timestamp operator+(basic_timestamp a,basic_timestamp b) noexcept +{ + if(a.seconds<0) + { + std::uint_least64_t a_abs{static_cast(a.seconds)}; + a_abs=0u-a_abs; + if(b.seconds<0) + { + std::uint_least64_t b_abs{static_cast(b.seconds)}; + b_abs=0u-b_abs; + auto res{details::add_impl({a_abs,a.subseconds}, + {b_abs,b.subseconds})}; + res.seconds=0u-res.seconds; + return {static_cast(res.seconds),res.subseconds}; + } + else + { + std::uint_least64_t b_abs{static_cast(b.seconds)}; + if(a_abs(res.seconds),res.subseconds}; + } + else + { + auto res{details::sub_impl({a_abs,a.subseconds},{b_abs,b.subseconds})}; + res.seconds=0u-res.seconds; + return {static_cast(res.seconds),res.subseconds}; + } + } + } + else + { + std::uint_least64_t a_abs{static_cast(a.seconds)}; + if(b.seconds<0) + { + std::uint_least64_t b_abs{static_cast(b.seconds)}; + b_abs=0u-b_abs; + if(a_abs(res.seconds),res.subseconds}; + } + else + { + auto res{details::sub_impl({a_abs,a.subseconds},{b_abs,b.subseconds})}; + return {static_cast(res.seconds),res.subseconds}; + } + } + else + { + std::uint_least64_t b_abs{static_cast(b.seconds)}; + auto res{details::add_impl({a_abs,a.subseconds}, + {b_abs,b.subseconds})}; + return {static_cast(res.seconds),res.subseconds}; + } + } +} +template +inline constexpr basic_timestamp& operator+=(basic_timestamp& a,basic_timestamp b) noexcept +{ + return a=a+b; +} + +template +inline constexpr basic_timestamp operator-(basic_timestamp a,basic_timestamp b) noexcept +{ + return a+(-b); +} + +template +inline constexpr basic_timestamp& operator-=(basic_timestamp& a,basic_timestamp b) noexcept +{ + return a=a+(-b); +} +template +inline constexpr basic_timestamp operator/(basic_timestamp a,std::uint_least64_t b) noexcept +{ + if constexpr(off_to_epoch==0) + { + return details::div_uint(a.seconds,a.subseconds,b); + } + else + { + auto [seconds,subseconds]=details::div_uint(a.seconds,a.subseconds,b); + return {seconds,subseconds}; + } +} + +template +inline constexpr basic_timestamp& operator/=(basic_timestamp& a,std::uint_least64_t b) noexcept +{ + if constexpr(off_to_epoch==0) + { + return a=details::div_uint(a.seconds,a.subseconds,b); + } + else + { + auto [seconds,subseconds]=details::div_uint(a.seconds,a.subseconds,b); + a.seconds=seconds; + a.subseconds=subseconds; + return a; + } +} +/* +https://www.epochconverter.com/seconds-days-since-y0 +Seconds since year 0 (MySQL compatible) +Seconds since January 1, 1 AD +Days since year 0 (MySQL compatible) +Days since January 1, 1 AD +Days since January 1, 1900, used for Excel DAY functions +Days since January 1, 1904, formerly used for Excel DAY (Macintosh) +Days since January 1, 1970, Unix epoch +*/ + +using unix_timestamp=basic_timestamp<0>; //UNIX +using win32_timestamp=basic_timestamp<-11644473600LL>; //Windows +using csharp_timestamp=basic_timestamp<-62135712000LL>; //C# +using year0_timestamp=basic_timestamp<-62167219200LL>; //0000-01-01 +using universe_timestamp=basic_timestamp<-434602341429235200LL>; //Pesudo timestamp since the big bang of universe +/* +Referenced from: https://81018.com/universeclock/ +*/ + +struct iso8601_timestamp +{ + std::int_least64_t year{}; + std::uint_least8_t month{}; + std::uint_least8_t day{}; + std::uint_least8_t hours{}; + std::uint_least8_t minutes{}; + std::uint_least8_t seconds{}; + std::uint_least64_t subseconds{}; + std::int_least32_t timezone{}; +}; + +template +inline constexpr std::size_t print_reserve_size(io_reserve_type_t>) noexcept +{ + return print_reserve_size(io_reserve_type)+std::numeric_limits::digits10; +} + +namespace details +{ +/* +Referenced from musl libc +https://git.musl-libc.org/cgit/musl/tree/src/time/__secs_to_tm.c +*/ + +inline constexpr char8_t days_in_month[]{31,30,31,30,31,31,30,31,30,31,31,29}; + +inline constexpr std::uint_least32_t secs_through_month[]{ +0, 31*86400, 59*86400, 90*86400, +120*86400, 151*86400, 181*86400, 212*86400, +243*86400, 273*86400, 304*86400, 334*86400 +}; +/* +y2k : 2000-01-01T00:00:00Z +*/ +inline constexpr std::int_least64_t y2k{946684800LL}; +/* +leapoch: 2000-03-01T00:00:00Z +*/ +inline constexpr std::int_least64_t leapoch{y2k + 86400LL*(31LL+29LL)}; + +inline constexpr std::uint_least32_t days_per_400_year{365LL*400LL+97LL}; +inline constexpr std::uint_least32_t days_per_100_year{365LL*100LL+24LL}; +inline constexpr std::uint_least32_t days_per_4_year{365LL*4LL+1LL}; + +template +inline constexpr T sub_overflow(T a,T b) noexcept +{ +#if defined(__has_builtin) +#if __has_builtin(__builtin_sub_overflow) + T c; + if(__builtin_sub_overflow(a,b,__builtin_addressof(c)))[[unlikely]] + fast_terminate(); + return c; +#else + + if(b<=0)[[unlikely]] + { + if(a>std::numeric_limits::max()+b)[[unlikely]] + fast_terminate(); + + } + else + { + if(a::min()+b)[[unlikely]] + fast_terminate(); + } + return a-b; +#endif +#else + if(b<=0)[[unlikely]] + { + if(a>std::numeric_limits::max()+b)[[unlikely]] + fast_terminate(); + } + else + { + if(a::min()+b)[[unlikely]] + fast_terminate(); + } + return a-b; +#endif +} + +#if __has_cpp_attribute(__gnu__::__pure__) +[[__gnu__::__pure__]] +#endif +inline constexpr iso8601_timestamp unix_timestamp_to_iso8601_tsp_impl_internal(std::int_least64_t seconds,std::uint_least64_t subseconds,std::int_least32_t timezone) noexcept +{ + std::int_least64_t secs{sub_overflow(seconds,leapoch)}; + std::int_least64_t days{secs/86400}; + std::int_least64_t remsecs{secs%86400}; + if(remsecs<0) + { + remsecs+=86400; + --days; + } + + std::int_least64_t qc_cycles{days / days_per_400_year}; + std::int_least64_t remdays{days % days_per_400_year}; + if (remdays < 0) + { + remdays += days_per_400_year; + --qc_cycles; + } + std::int_least64_t c_cycles{remdays / days_per_100_year}; + if (c_cycles == 4) + --c_cycles; + remdays -= c_cycles * days_per_100_year; + + std::int_least64_t q_cycles{remdays / days_per_4_year}; + if (q_cycles == 25) + --q_cycles; + remdays -= q_cycles * days_per_4_year; + + std::int_least64_t remyears{remdays / 365}; + if (remyears == 4) + --remyears; + remdays -= remyears * 365; + std::int_least64_t years{remyears + 4*q_cycles + 100*c_cycles + 400*qc_cycles}; + std::uint_least8_t months{}; + for (; days_in_month[months] <= remdays; ++months) + remdays -= days_in_month[months]; + if(months>=10) + { + ++years; + months-=12; + } + return {years+2000, + static_cast(months+3), + static_cast(remdays+1), + static_cast(remsecs/3600), + static_cast(remsecs/60%60), + static_cast(remsecs%60),subseconds,timezone}; +} + +#if __has_cpp_attribute(__gnu__::__pure__) +[[__gnu__::__pure__]] +#endif +inline constexpr iso8601_timestamp unix_timestamp_to_iso8601_tsp_impl(std::int_least64_t t,std::uint_least64_t subseconds) noexcept +{ + return unix_timestamp_to_iso8601_tsp_impl_internal(t,subseconds,0); +} + +#if __has_cpp_attribute(__gnu__::__pure__) +[[__gnu__::__pure__]] +#endif +inline constexpr std::int_least64_t year_month_to_seconds(std::int_least64_t year,std::uint_least8_t month) noexcept +{ + constexpr std::int_least64_t year_min{std::numeric_limits::min()/(365LL*86400LL)}; + constexpr std::int_least64_t year_max{std::numeric_limits::max()/(365LL*86400LL)}; + if(year<=year_min||year>=year_max) + fast_terminate(); + std::int_least64_t leaps{year/4}; + std::int_least64_t leaps_remainder{year%4}; + std::int_least64_t cycles_quotient{year / 400}; + std::int_least64_t cycles_reminder{year % 400}; + std::int_least64_t cycles100_quotient{year / 100}; + std::int_least64_t cycles100_reminder{year % 100}; + bool year_is_leap_year{(!cycles_reminder)||((!leaps_remainder)&&cycles100_reminder)}; + leaps+=cycles_quotient-cycles100_quotient; + --month; + if(11=0&&!year_is_leap_year)) + t+=0x15180; + return (year*365LL+leaps)*86400LL-62167219200LL+static_cast(t); +} + +#if __has_cpp_attribute(__gnu__::__pure__) +[[__gnu__::__pure__]] +#endif +inline constexpr unix_timestamp iso8601_to_unix_timestamp_impl(iso8601_timestamp const& tsp) noexcept +{ + return {static_cast(static_cast(tsp.day-1)*static_cast(86400LL)+ + static_cast(tsp.hours)*static_cast(3600LL)+ + static_cast(tsp.minutes)*static_cast(60LL)+ + static_cast(tsp.seconds)-static_cast(tsp.timezone))+ + year_month_to_seconds(tsp.year,tsp.month) + ,tsp.subseconds}; +} + +} + +template +inline constexpr iso8601_timestamp utc(basic_timestamp timestamp) noexcept +{ + if constexpr(std::same_as,unix_timestamp>) + { + return details::unix_timestamp_to_iso8601_tsp_impl(timestamp.seconds,timestamp.subseconds); + } + else + { + unix_timestamp tsp{static_cast(timestamp)}; + return details::unix_timestamp_to_iso8601_tsp_impl(tsp.seconds,tsp.subseconds); + } +} + +template +inline constexpr basic_timestamp to_timestamp(iso8601_timestamp const& timestamp) noexcept +{ + return details::iso8601_to_unix_timestamp_impl(timestamp); +} + +namespace details +{ +inline constexpr std::uint_least8_t c_weekday_tb[]{0,3,2,5,0,3,5,1,4,6,2,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(); +#endif +#endif + return static_cast(static_cast( + static_cast(year) + static_cast(year/4) - + static_cast(year/100) + static_cast(year/400) + + c_weekday_tb[month_minus1]+day)%7u); +} + +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(); +#endif +#endif + return static_cast(static_cast( + static_cast(year) + static_cast(year/4) - + static_cast(year/100) + static_cast(year/400) + + c_weekday_tb[month_minus1]+day+6u)%7u+1u); +} + +} + +inline constexpr std::uint_least8_t c_weekday(std::int_least64_t year, std::uint_least8_t month, std::uint_least8_t day) noexcept +{ + --month; + if (month < 2u) + year = static_cast(static_cast(year) - 1u); + else if (11u < month) + month %= 12u; + return ::fast_io::details::c_weekday_impl(year, month, day); +} + +inline constexpr std::uint_least8_t c_weekday(iso8601_timestamp const& timestamp) noexcept +{ + return ::fast_io::c_weekday(timestamp.year, timestamp.month, timestamp.day); +} + +inline constexpr std::uint_least8_t weekday(std::int_least64_t year, std::uint_least8_t month, std::uint_least8_t day) noexcept +{ + --month; + if (month < 2u) + year = static_cast(static_cast(year) - 1u); + else if (11u < month) + month %= 12u; + return ::fast_io::details::weekday_impl(year, month, day); +} + +inline constexpr std::uint_least8_t weekday(iso8601_timestamp const& timestamp) noexcept +{ + return ::fast_io::weekday(timestamp.year, timestamp.month, timestamp.day); +} + +namespace details +{ + +template +inline constexpr std::size_t print_reserve_size_timezone_impl_v{print_reserve_size(io_reserve_type)+static_cast(4u)}; + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_timezone_impl(char_type* iter,std::int_least32_t timezone) noexcept +{ + std::uint_least64_t unsigned_tz{static_cast(timezone)}; + if(timezone<0) + { + *iter=char_literal_v; + unsigned_tz=0UL-unsigned_tz; + } + else + { + *iter=char_literal_v; + } + ++iter; + std::uint_least8_t tz_ss{static_cast(unsigned_tz%60)}; + unsigned_tz/=60; + std::uint_least8_t tz_mm{static_cast(unsigned_tz%60)}; + unsigned_tz/=60; + iter=chrono_two_digits_impl(iter,unsigned_tz); + *iter=char_literal_v; + ++iter; + iter=chrono_two_digits_impl(iter,tz_mm); + if(tz_ss) + { + *iter=char_literal_v; + ++iter; + iter=chrono_two_digits_impl(iter,tz_ss); + } + return iter; +} + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_iso8601_timestamp_impl(char_type* iter,iso8601_timestamp const& timestamp) noexcept +{ + iter=chrono_year_impl(iter,timestamp.year); + *iter=char_literal_v; + ++iter; + iter=chrono_two_digits_impl(iter,timestamp.month); + *iter=char_literal_v; + ++iter; + iter=chrono_two_digits_impl(iter,timestamp.day); + *iter=char_literal_v; + ++iter; + iter=chrono_two_digits_impl(iter,timestamp.hours); + *iter=char_literal_v; + ++iter; + iter=chrono_two_digits_impl(iter,timestamp.minutes); + *iter=char_literal_v; + ++iter; + iter=chrono_two_digits_impl(iter,timestamp.seconds); + if(timestamp.subseconds) + iter=output_iso8601_subseconds(iter,timestamp.subseconds); + auto const timezone{timestamp.timezone}; + if(timezone==0) + { + *iter=char_literal_v; + ++iter; + } + else + iter=print_reserve_timezone_impl(iter,timezone); + return iter; +} + +template +inline constexpr char_type* print_reserve_bsc_timestamp_impl(char_type* iter,unix_timestamp timestamp) noexcept +{ + iter=print_reserve_define(io_reserve_type,iter,timestamp.seconds); + if(timestamp.subseconds) + iter=output_iso8601_subseconds(iter,timestamp.subseconds); + return iter; +} + +} + +template +inline constexpr std::size_t print_reserve_size(io_reserve_type_t) noexcept +{ +//ISO 8601 timestamp example : 2021-01-03T10:29:56Z +//ISO 8601 timestamp with timezone : 2021-01-03T10:29:56.999999+99:99 + return print_reserve_size(io_reserve_type)+16+print_reserve_size(io_reserve_type)+::fast_io::details::print_reserve_size_timezone_impl_v+3+2; +} + +template +inline constexpr char_type* print_reserve_define(io_reserve_type_t>, + char_type* iter,basic_timestamp timestamp) noexcept +{ + if constexpr(off_to_epoch==0) + return details::print_reserve_bsc_timestamp_impl(iter,timestamp); + else + return details::print_reserve_bsc_timestamp_impl(iter,{timestamp.seconds,timestamp.subseconds}); +} + +template +inline constexpr char_type* print_reserve_define(io_reserve_type_t,char_type* iter,iso8601_timestamp const& timestamp) noexcept +{ + return details::print_reserve_iso8601_timestamp_impl(iter,timestamp); +} + +inline constexpr win32_timestamp to_win32_timestamp_ftu64(::std::uint_least64_t ftu64) noexcept +{ + ::std::uint_least64_t seconds{ftu64/10000000ULL}; + ::std::uint_least64_t subseconds{ftu64%10000000ULL}; + constexpr ::std::uint_least64_t mul_factor{uint_least64_subseconds_per_second/10000000u}; + return {static_cast<::std::int_least64_t>(seconds),static_cast<::std::uint_least64_t>(subseconds*mul_factor)}; +} + +// warning: relies on the order of the items +enum class scan_timestamp_context_phase : ::std::uint_least8_t +{ + year, + after_year, + month, + after_month, + day, + after_day, + hours, + after_hours, + minutes, + after_minutes, + seconds, + timezone_marker, + after_subseconds_timezone_marker, + timezone_hours, + after_timezone_hours, + timezone_minutes, + subseconds, + waiting_for_five, + waiting_for_numbers, + ok +}; + +inline constexpr scan_timestamp_context_phase& operator++(scan_timestamp_context_phase& e) noexcept +{ + return e = static_cast(static_cast<::std::uint_least8_t>(e)+1); +} +inline constexpr scan_timestamp_context_phase operator++(scan_timestamp_context_phase& e, int) noexcept +{ + auto tmp{ e }; + ++e; + return tmp; +} + +enum class scan_integral_context_phase : ::std::uint_least8_t; + +struct timestamp_scan_context_buffer_max_size_t +{ +private: + template + static inline constexpr auto size_common{ ::fast_io::details::print_integer_reserved_size_cache<10, false, ::fast_io::details::my_signed_integral, T> }; +public: + static inline constexpr auto year_size = size_common<::std::int_least64_t>; + static inline constexpr auto subs_size = size_common<::std::uint_least64_t>; + static inline constexpr ::std::size_t max_size{ year_size > subs_size ? year_size : subs_size }; +}; + +template <::std::integral char_type> +struct timestamp_scan_state_t : private timestamp_scan_context_buffer_max_size_t +{ + using timestamp_scan_context_buffer_max_size_t::max_size; + ::fast_io::freestanding::array buffer; + ::std::uint_least8_t size{}; + scan_timestamp_context_phase tsp_phase{}; + scan_integral_context_phase integer_phase{}; +}; + +namespace details +{ + +template +inline constexpr parse_result scn_cnt_define_unix_timestamp_impl(char_type const* begin, char_type const* end, unix_timestamp& t) noexcept +{ + // TODO: whether to accept C-like floatings such as 2. and .2 + auto [itr, ec] = scan_int_contiguous_define_impl<10, false, false, false>(begin, end, t.seconds); + if (ec != parse_code::ok) [[unlikely]] + return { itr, ec }; + if (itr == end) [[unlikely]] + { + t.subseconds = 0; + return { itr, parse_code::ok }; + } + begin = itr; + if constexpr (comma) + { + if (*begin != char_literal_v) [[unlikely]] + return { begin, parse_code::invalid }; + } + else + { + if (*begin != char_literal_v) [[unlikely]] + return { begin, parse_code::invalid }; + } + ++begin; + return chrono_scan_decimal_fraction_part_never_overflow_impl(begin, end, t.subseconds); +} + +template <::std::integral char_type, ::std::integral T> +inline constexpr parse_result scn_ctx_decimal_fraction_part_never_overflow_impl(timestamp_scan_state_t& state, char_type const* begin, char_type const* end, T& t) noexcept +{ + if (begin == end) + return { begin, parse_code::partial }; + auto itr{ skip_digits<10, char_type>(begin, end) }; + auto frag_length{ static_cast<::std::uint_least8_t>(itr - begin) }; + constexpr auto digitsm1{ ::std::numeric_limits<::std::uint_least64_t>::digits10 }; + auto buffer_begin{ state.buffer.begin() }; + auto buffer_size{ state.size }; + if (itr != end) + { + // know the end of the number + if (buffer_size == 0) + { + auto [itr2, ec] = chrono_scan_decimal_fraction_part_never_overflow_impl(begin, itr, t); + if (ec != parse_code::ok) [[unlikely]] + return { itr, parse_code::invalid }; + if (itr2 != itr) + chrono_scan_decimal_fraction_part_rounding_impl(itr2, itr, t); + return { itr, parse_code::ok }; + } + else + { + if (frag_length > digitsm1 - buffer_size) + { + auto itr_begin{ buffer_begin }; + auto itr_end{ ::fast_io::freestanding::non_overlapped_copy_n(begin, digitsm1 - buffer_size, buffer_begin) }; + auto digit_end{ begin + (digitsm1 - buffer_size) }; + auto [_, ec] = chrono_scan_decimal_fraction_part_never_overflow_impl(itr_begin, itr_end, t); + if (ec != parse_code::ok) [[unlikely]] + return { itr, parse_code::invalid }; + chrono_scan_decimal_fraction_part_rounding_impl(digit_end, itr, t); + return { itr, parse_code::ok }; + } + else + { + auto itr_begin{ buffer_begin }; + auto itr_end{ ::fast_io::freestanding::non_overlapped_copy_n(begin, frag_length, buffer_begin + buffer_size) }; + auto [_, ec] = chrono_scan_decimal_fraction_part_never_overflow_impl(itr_begin, itr_end, t); + if (ec != parse_code::ok) [[unlikely]] + return { itr, parse_code::invalid }; + return { itr, parse_code::ok }; + } + } + } + else if (frag_length > digitsm1 - buffer_size) + { + // longer than the number can hold, so parse + // parse and waiting for the rest of the numbers + char_type const* itr_begin, * itr_end, * digit_end; + if (buffer_size == 0) + { + itr_begin = begin; + itr_end = end; + digit_end = begin + digitsm1; + } + else + { + itr_begin = buffer_begin; + itr_end = ::fast_io::freestanding::non_overlapped_copy_n(begin, digitsm1 - buffer_size, buffer_begin + buffer_size); + digit_end = begin + (digitsm1 - buffer_size); + } + auto [_, ec] = chrono_scan_decimal_fraction_part_never_overflow_impl(itr_begin, itr_end, t); + if (ec != parse_code::ok) [[unlikely]] + return { itr, parse_code::invalid }; + if (*digit_end < char_literal_v) + { + state.size = 0; + state.tsp_phase = scan_timestamp_context_phase::waiting_for_numbers; + return { end, parse_code::partial }; + } + else if (*digit_end > char_literal_v) + { + ++t; + state.size = 0; + state.tsp_phase = scan_timestamp_context_phase::waiting_for_numbers; + return { end, parse_code::partial }; + } + else [[unlikely]] + { + for (++digit_end; digit_end != end; ++digit_end) + { + // xxxxx500000x0000, then round in + if (*digit_end != char_literal_v) + { + ++t; + state.size = 0; + state.tsp_phase = scan_timestamp_context_phase::waiting_for_numbers; + return { end, parse_code::partial }; + } + } + // xxxx500000....(unknown), then it depends on the rest + state.size = 0; + state.tsp_phase = scan_timestamp_context_phase::waiting_for_five; + return { end, parse_code::partial }; + } + } + else + { + // do not know the end of the number + // neither overflow the buffer + // so put it into the buffer + ::fast_io::freestanding::non_overlapped_copy_n(begin, frag_length, buffer_begin + buffer_size); + state.size += static_cast<::std::uint_least8_t>(frag_length); + return { end, parse_code::partial }; + } +} + +template +inline constexpr parse_result scn_ctx_define_unix_timestamp_impl(timestamp_scan_state_t& state, char_type const* begin, char_type const* end, unix_timestamp& t) noexcept +{ +#if __has_cpp_attribute(assume) + [[assume(state.tsp_phase != scan_timestamp_context_phase::after_year)]]; + [[assume(state.tsp_phase != scan_timestamp_context_phase::month)]]; + [[assume(state.tsp_phase != scan_timestamp_context_phase::after_month)]]; + [[assume(state.tsp_phase != scan_timestamp_context_phase::day)]]; + [[assume(state.tsp_phase != scan_timestamp_context_phase::after_day)]]; + [[assume(state.tsp_phase != scan_timestamp_context_phase::hours)]]; + [[assume(state.tsp_phase != scan_timestamp_context_phase::after_hours)]]; + [[assume(state.tsp_phase != scan_timestamp_context_phase::minutes)]]; + [[assume(state.tsp_phase != scan_timestamp_context_phase::after_minutes)]]; + [[assume(state.tsp_phase != scan_timestamp_context_phase::seconds)]]; + [[assume(state.tsp_phase != scan_timestamp_context_phase::after_subseconds_timezone_marker)]]; + [[assume(state.tsp_phase != scan_timestamp_context_phase::timezone_hours)]]; + [[assume(state.tsp_phase != scan_timestamp_context_phase::after_timezone_hours)]]; + [[assume(state.tsp_phase != scan_timestamp_context_phase::timezone_minutes)]]; +#endif + switch (state.tsp_phase) + { + case scan_timestamp_context_phase::year: + { + auto [itr, ec] = scan_context_define_parse_impl<10, false, false, true>(state, begin, end, t.seconds); + if (ec != parse_code::ok) + return { itr, ec }; + begin = itr; + state.size = 0; + state.integer_phase = {}; + state.tsp_phase = scan_timestamp_context_phase::timezone_marker; + [[fallthrough]]; + } + case scan_timestamp_context_phase::timezone_marker: + { + if (begin == end) + return { begin, parse_code::partial }; + else + { + if constexpr (comma) + { + if (*begin++ != char_literal_v) [[unlikely]] + return { begin, parse_code::invalid }; + } + else + { + if (*begin++ != char_literal_v) [[unlikely]] + return { begin, parse_code::invalid }; + } + state.tsp_phase = scan_timestamp_context_phase::subseconds; + } + [[fallthrough]]; + } + case scan_timestamp_context_phase::subseconds: + { + auto result = scn_ctx_decimal_fraction_part_never_overflow_impl(state, begin, end, t.subseconds); + if (result.code == parse_code::ok) + state.tsp_phase = scan_timestamp_context_phase::ok; + return result; + } + case scan_timestamp_context_phase::waiting_for_five: + { + for (; begin != end; ++begin) + { + if (!::fast_io::char_category::is_c_digit(*begin)) + { + if (t.subseconds % 2 == 1) + ++t.subseconds; + state.tsp_phase = scan_timestamp_context_phase::ok; + return { begin, parse_code::ok }; + } + if (*begin != char_literal_v) + { + ++t.subseconds; + state.tsp_phase = scan_timestamp_context_phase::waiting_for_numbers; + break; + } + } + [[fallthrough]]; + } + case scan_timestamp_context_phase::waiting_for_numbers: + { + if (begin == end) + return { end, parse_code::partial }; + auto itr{ skip_digits<10>(begin, end) }; + if (itr == end) + return { end, parse_code::partial }; + state.tsp_phase = scan_timestamp_context_phase::ok; + return { itr, parse_code::ok }; + } + case scan_timestamp_context_phase::ok: + return { begin, parse_code::ok }; + default: break; + } +#ifdef __has_builtin +#if __has_builtin(__builtin_unreachable) + __builtin_unreachable(); +#endif +#endif +} + +template <::std::integral char_type> +inline constexpr parse_code scn_ctx_eof_define_unix_timestamp_impl(timestamp_scan_state_t& state, unix_timestamp& t) noexcept +{ + switch (state.tsp_phase) + { + case scan_timestamp_context_phase::subseconds: + { + auto buffer_begin{ state.buffer.begin() }; + auto buffer_end{ buffer_begin + state.size }; + auto [_, ec] = chrono_scan_decimal_fraction_part_never_overflow_impl(buffer_begin, buffer_end, t.subseconds); + if (ec != parse_code::ok) [[unlikely]] + return parse_code::invalid; + return parse_code::ok; + } + case scan_timestamp_context_phase::waiting_for_five: + if (t.subseconds % 2 == 1) + ++t.subseconds; + [[fallthrough]]; + case scan_timestamp_context_phase::waiting_for_numbers: + case scan_timestamp_context_phase::ok: + return parse_code::ok; + default: + return parse_code::end_of_file; + } +} + +// TODO: remove template comma, because iso8601 doesn't accept comma +template +inline constexpr parse_result scn_cnt_define_iso8601_impl( + char_type const* begin, char_type const* end, + iso8601_timestamp& t) noexcept +{ + iso8601_timestamp retval{}; + begin = ::fast_io::find_none_c_space(begin, end); + if (auto [itr, ec] = chrono_scan_year_impl(begin, end, retval.year); ec != parse_code::ok) [[unlikely]] + return { itr, ec }; + else + begin = itr; + if (end - begin < 16) [[unlikely]] + return { end, parse_code::invalid }; + if (*begin++ != char_literal_v) [[unlikely]] + return { begin, parse_code::invalid }; + if (auto ec = chrono_scan_two_digits_unsafe_impl(begin, retval.month); ec != parse_code::ok) [[unlikely]] + return { begin, ec }; + if (retval.month > 12 || retval.month == 0) [[unlikely]] + return { begin, parse_code::overflow }; + begin += 2; + if (*begin++ != char_literal_v) [[unlikely]] + return { begin, parse_code::invalid }; + if (auto ec = chrono_scan_two_digits_unsafe_impl(begin, retval.day); ec != parse_code::ok) [[unlikely]] + return { begin, ec }; + if (retval.day > 31 || retval.day == 0) [[unlikely]] + return { begin, parse_code::overflow }; + begin += 2; + if (*begin++ != char_literal_v) [[unlikely]] + return { begin, parse_code::invalid }; + if (auto ec = chrono_scan_two_digits_unsafe_impl(begin, retval.hours); ec != parse_code::ok) [[unlikely]] + return { begin, ec }; + if (retval.hours >= 24) [[unlikely]] + return { begin, parse_code::overflow }; + begin += 2; + if (*begin++ != char_literal_v) [[unlikely]] + return { begin, parse_code::invalid }; + if (auto ec = chrono_scan_two_digits_unsafe_impl(begin, retval.minutes); ec != parse_code::ok) [[unlikely]] + return { begin, ec }; + if (retval.minutes >= 60) [[unlikely]] + return { begin, parse_code::overflow }; + begin += 2; + if (*begin++ != char_literal_v) [[unlikely]] + return { begin, parse_code::invalid }; + if (auto ec = chrono_scan_two_digits_unsafe_impl(begin, retval.seconds); ec != parse_code::ok) [[unlikely]] + return { begin, ec }; + if (retval.seconds >= 60) [[unlikely]] + return { begin, parse_code::overflow }; + begin += 2; + bool sign{}; + if (*begin == char_literal_v) + { + ++begin; + t = retval; + return { begin, parse_code::ok }; + } + else if (*begin == char_literal_v) + sign = false; + else if (*begin == char_literal_v) + sign = true; + else if ((!comma && *begin == char_literal_v) || (comma && *begin == char_literal_v)) + { + ++begin; + // parse subseconds + // warning that there is no garantee on end > begin here anymore + auto [itr, ec] = chrono_scan_decimal_fraction_part_never_overflow_impl(begin, end, retval.subseconds); + if (ec != parse_code::ok) [[unlikely]] + return { itr, ec }; + begin = itr; + if (begin == end) [[unlikely]] + return { end, parse_code::invalid }; + if (*begin == char_literal_v) + { + ++begin; + t = retval; + return { begin, parse_code::ok }; + } + else if (*begin == char_literal_v) + sign = false; + else if (*begin == char_literal_v) + sign = true; + else [[unlikely]] + return { begin, parse_code::invalid }; + } + else [[unlikely]] + return { begin, parse_code::invalid }; + // when control flow reaches here, it's to parse time-zone, format HH:MM + if (end - begin < 5) [[unlikely]] + return { end, parse_code::invalid }; + ++begin; + if (auto ec = chrono_scan_two_digits_unsafe_impl(begin, retval.timezone); ec != parse_code::ok) [[unlikely]] + return { begin, ec }; + if (retval.timezone >= 24) [[unlikely]] + return { begin, parse_code::overflow }; + begin += 2; + if (*begin++ != char_literal_v) [[unlikely]] + return { begin, parse_code::invalid }; + ::std::uint8_t timezone_minutes; + if (auto ec = chrono_scan_two_digits_unsafe_impl(begin, timezone_minutes); ec != parse_code::ok) [[unlikely]] + return { begin, ec }; + if (timezone_minutes >= 60) [[unlikely]] + return { begin, parse_code::overflow }; + begin += 2; + retval.timezone *= 3600; + retval.timezone += static_cast<::std::int_least32_t>(timezone_minutes) * 60; + if (sign) retval.timezone = -retval.timezone; + t = retval; + return { begin, parse_code::ok }; +} + +template <::std::integral char_type, ::std::integral T> +inline constexpr parse_result scan_iso8601_context_year_phase(timestamp_scan_state_t& state, char_type const* begin, char_type const* end, T& t) noexcept +{ +#if __has_cpp_attribute(assume) + [[assume(state.integer_phase != scan_integral_context_phase::prefix)]]; +#endif + switch (state.integer_phase) + { + case scan_integral_context_phase::space: + { + auto phase_ret = sc_int_ctx_space_phase(begin, end); + if (phase_ret.code != ongoing_parse_code) + return phase_ret; + begin = phase_ret.iter; + state.integer_phase = scan_integral_context_phase::sign; + [[fallthrough]]; + } + case scan_integral_context_phase::sign: + { + if (begin == end) + return { begin,parse_code::partial }; + if (*begin == char_literal_v) + { + state.buffer.front() = char_literal_v; + state.size = 1; + ++begin; + } + else + state.buffer.front() = 0; + state.integer_phase = scan_integral_context_phase::zero; + [[fallthrough]]; + } + case scan_integral_context_phase::zero: + { + if (begin == end) + return { begin, parse_code::partial }; + auto neg{ state.buffer.front() == char_literal_v }; + if ((state.size == 0 || (neg && state.size == 1)) + && end - begin > 4) + { + auto itr{ begin }; + for (; itr != begin + 4; ++itr) + { + if (!char_is_digit<10, char_type>(*itr)) [[unlikely]] + return { itr, parse_code::invalid }; + } + if (char_is_digit<10, char_type>(*itr)) [[unlikely]] + { + state.integer_phase = scan_integral_context_phase::digit; + return scan_context_define_parse_impl<10, true, false, false>(state, begin, end, t); + } + else + { + t += static_cast(*begin++ - char_literal_v) * 1000; + t += static_cast(*begin++ - char_literal_v) * 100; + t += static_cast(*begin++ - char_literal_v) * 10; + t += static_cast(*begin++ - char_literal_v); + if (state.buffer.front() == '-') + t = -t; + return { begin, parse_code::ok }; + } + } + else + { + auto remain_size{ (neg ? 1 : 0) + 5 - state.size }; +#if __has_cpp_attribute(assume) + [[assume(remain_size != 0)]]; +#endif + if (end - begin < remain_size) + { + for (; begin != end; ++begin) + { + if (!char_is_digit<10, char_type>(*begin)) [[unlikely]] + return { begin, parse_code::invalid }; + state.buffer[state.size++] = *begin; + } + return { begin, parse_code::partial }; + } + else + { + for (auto new_end{ begin + remain_size - 1}; begin != new_end; ++begin) + { + if (!char_is_digit<10, char_type>(*begin)) [[unlikely]] + return { begin, parse_code::invalid }; + state.buffer[state.size++] = *begin; + } + if (char_is_digit<10, char_type>(*begin)) [[unlikely]] + { + state.integer_phase = scan_integral_context_phase::digit; + return scan_context_define_parse_impl<10, true, false, false>(state, begin, end, t); + } + else + { + auto buffer_begin{ state.buffer.begin() + (neg ? 1 : 0) }; + t += static_cast(*buffer_begin++ - char_literal_v) * 1000; + t += static_cast(*buffer_begin++ - char_literal_v) * 100; + t += static_cast(*buffer_begin++ - char_literal_v) * 10; + t += static_cast(*buffer_begin++ - char_literal_v); + if (state.buffer.front() == '-') + t = -t; + return { begin, parse_code::ok }; + } + } + } + } + default: + return scan_context_define_parse_impl<10, true, false, false>(state, begin, end, t); + } +} + +template <::std::integral char_type, ::std::integral T> +inline constexpr parse_result scan_iso8601_context_2_digits_phase(timestamp_scan_state_t& state, char_type const* begin, char_type const* end, T& t) noexcept +{ + auto diff{ end - begin }; + if (diff == 0) + return { begin, parse_code::partial }; + auto buffer_begin{ state.buffer.begin() }; +#if __has_cpp_attribute(assume) + [[assume(state.size == 0 || state.size == 1)]]; +#endif + switch (state.size) + { + case 0: + { + if (diff >= 2) + { + /*no copy to buffer*/ + if (auto ec = chrono_scan_two_digits_unsafe_impl(begin, t); ec != parse_code::ok) [[unlikely]] + return { begin, ec }; + ++state.tsp_phase; + begin += 2; + } + else /*diff == 1*/ + { + ::fast_io::freestanding::non_overlapped_copy_n(begin, 1, buffer_begin); + state.size = 1; + return { end, parse_code::partial }; + } + break; + } + case 1: + { + ::fast_io::freestanding::non_overlapped_copy_n(begin, 1, buffer_begin + 1); + if (auto ec = chrono_scan_two_digits_unsafe_impl(buffer_begin, t); ec != parse_code::ok) [[unlikely]] + return { begin,ec }; + state.size = 0; + ++state.tsp_phase; + ++begin; + break; + } + default:; +#ifdef __has_builtin +#if __has_builtin(__builtin_unreachable) + __builtin_unreachable(); +#endif +#endif + } + return { begin, parse_code::ok }; +} + +template +inline constexpr parse_result scn_ctx_define_iso8601_impl(timestamp_scan_state_t& state, char_type const* begin, char_type const* end, iso8601_timestamp& t) noexcept +{ + // TODO: is it necessary to change macro to function to reuse code? + switch (state.tsp_phase) + { + case scan_timestamp_context_phase::year: + { + t = {}; + auto [itr, ec] = scan_iso8601_context_year_phase(state, begin, end, t.year); + if (ec != parse_code::ok) + return { itr, ec }; + begin = itr; + state.size = 0; + state.integer_phase = {}; + state.tsp_phase = scan_timestamp_context_phase::after_year; + [[fallthrough]]; + } + case scan_timestamp_context_phase::after_year: +#define FAST_IO_SCAN_ISO8601_CONTEXT_TOKEN_PHASE(TOK) \ + { \ + if (begin == end) \ + return { begin, parse_code::partial }; \ + else \ + { \ + if (*begin++ != char_literal_v) [[unlikely]] \ + return { begin, parse_code::invalid }; \ + ++state.tsp_phase; \ + } \ + } \ + + FAST_IO_SCAN_ISO8601_CONTEXT_TOKEN_PHASE(u8'-'); + [[fallthrough]]; + case scan_timestamp_context_phase::month: + if (auto [itr, ec] = scan_iso8601_context_2_digits_phase(state, begin, end, t.month); ec != parse_code::ok) [[unlikely]] + return { itr, ec }; + else + { + if (t.month > 12 || t.month == 0) [[unlikely]] + return { itr, parse_code::overflow }; + begin = itr; + } + [[fallthrough]]; + case scan_timestamp_context_phase::after_month: + FAST_IO_SCAN_ISO8601_CONTEXT_TOKEN_PHASE(u8'-'); + [[fallthrough]]; + case scan_timestamp_context_phase::day: + if (auto [itr, ec] = scan_iso8601_context_2_digits_phase(state, begin, end, t.day); ec != parse_code::ok) [[unlikely]] + return { itr, ec }; + else + { + if (t.day > 31 || t.day == 0) [[unlikely]] + return { itr, parse_code::overflow }; + begin = itr; + } + [[fallthrough]]; + case scan_timestamp_context_phase::after_day: + FAST_IO_SCAN_ISO8601_CONTEXT_TOKEN_PHASE(u8'T'); + [[fallthrough]]; + case scan_timestamp_context_phase::hours: + if (auto [itr, ec] = scan_iso8601_context_2_digits_phase(state, begin, end, t.hours); ec != parse_code::ok) [[unlikely]] + return { itr, ec }; + else + { + if (t.hours >= 24) [[unlikely]] + return { itr, parse_code::overflow }; + begin = itr; + } + [[fallthrough]]; + case scan_timestamp_context_phase::after_hours: + FAST_IO_SCAN_ISO8601_CONTEXT_TOKEN_PHASE(u8':'); + [[fallthrough]]; + case scan_timestamp_context_phase::minutes: + if (auto [itr, ec] = scan_iso8601_context_2_digits_phase(state, begin, end, t.minutes); ec != parse_code::ok) [[unlikely]] + return { itr, ec }; + else + { + if (t.minutes >= 60) [[unlikely]] + return { itr, parse_code::overflow }; + begin = itr; + } + [[fallthrough]]; + case scan_timestamp_context_phase::after_minutes: + FAST_IO_SCAN_ISO8601_CONTEXT_TOKEN_PHASE(u8':'); + [[fallthrough]]; + case scan_timestamp_context_phase::seconds: + if (auto [itr, ec] = scan_iso8601_context_2_digits_phase(state, begin, end, t.seconds); ec != parse_code::ok) [[unlikely]] + return { itr, ec }; + else + { + if (t.seconds >= 60) [[unlikely]] + return { itr, parse_code::overflow }; + begin = itr; + } + [[fallthrough]]; + case scan_timestamp_context_phase::timezone_marker: + case scan_timestamp_context_phase::after_subseconds_timezone_marker: + { + if (begin == end) + return { end, parse_code::partial }; + switch (*begin) + { + case char_literal_v: + t.timezone = 0; + state.tsp_phase = scan_timestamp_context_phase::ok; + return { begin + 1, parse_code::ok }; + case char_literal_v: + ++begin; + state.integer_phase = static_cast(0); + state.size = 0; + state.tsp_phase = scan_timestamp_context_phase::timezone_hours; + break; + case char_literal_v: + ++begin; + state.integer_phase = static_cast(1); + state.size = 0; + state.tsp_phase = scan_timestamp_context_phase::timezone_hours; + break; + case comma ? char_literal_v : char_literal_v: + if (state.tsp_phase == scan_timestamp_context_phase::timezone_marker) + { + state.tsp_phase = scan_timestamp_context_phase::subseconds; + return scn_ctx_define_iso8601_impl(state, begin + 1, end, t); + } + else + [[fallthrough]]; + default: + return { begin, parse_code::invalid }; + } + [[fallthrough]]; + } + case scan_timestamp_context_phase::timezone_hours: + if (auto [itr, ec] = scan_iso8601_context_2_digits_phase(state, begin, end, t.timezone); ec != parse_code::ok) [[unlikely]] + return { itr, ec }; + else + { + if (t.timezone >= 24) [[unlikely]] + return { itr, parse_code::overflow }; + begin = itr; + } + [[fallthrough]]; + case scan_timestamp_context_phase::after_timezone_hours: + FAST_IO_SCAN_ISO8601_CONTEXT_TOKEN_PHASE(u8':'); + [[fallthrough]]; + case scan_timestamp_context_phase::timezone_minutes: + { + ::std::uint8_t timezone_minutes; + if (auto [itr, ec] = scan_iso8601_context_2_digits_phase(state, begin, end, timezone_minutes); ec != parse_code::ok) [[unlikely]] + return { itr, ec }; + else + { + if (timezone_minutes >= 60) [[unlikely]] + return { itr, parse_code::overflow }; + begin = itr; + } + t.timezone *= 3600; + t.timezone += static_cast<::std::int_least32_t>(timezone_minutes) * 60; + if (state.integer_phase == static_cast(1)) + t.timezone = -t.timezone; + state.tsp_phase = scan_timestamp_context_phase::ok; + return { begin, parse_code::ok }; + } + case scan_timestamp_context_phase::subseconds: + { + auto [itr, ec] = scn_ctx_decimal_fraction_part_never_overflow_impl(state, begin, end, t.subseconds); + if (ec == parse_code::ok) + { + state.tsp_phase = scan_timestamp_context_phase::after_subseconds_timezone_marker; + return scn_ctx_define_iso8601_impl(state, itr, end, t); + } + else + return { itr, ec }; + } + case scan_timestamp_context_phase::waiting_for_five: + { + for (; begin != end; ++begin) + { + if (!::fast_io::char_category::is_c_digit(*begin)) + { + if (t.subseconds % 2 == 1) + ++t.subseconds; + state.tsp_phase = scan_timestamp_context_phase::after_subseconds_timezone_marker; + return scn_ctx_define_iso8601_impl(state, begin, end, t); + } + if (*begin != char_literal_v) + { + ++t.subseconds; + state.tsp_phase = scan_timestamp_context_phase::waiting_for_numbers; + break; + } + } + [[fallthrough]]; + } + case scan_timestamp_context_phase::waiting_for_numbers: + { + if (begin == end) + return { end, parse_code::partial }; + auto itr{ skip_digits<10>(begin, end) }; + if (itr == end) + return { end, parse_code::partial }; + state.tsp_phase = scan_timestamp_context_phase::after_subseconds_timezone_marker; + return scn_ctx_define_iso8601_impl(state, itr, end, t); + } + case scan_timestamp_context_phase::ok: + return { begin, parse_code::ok }; + } +#ifdef __has_builtin +#if __has_builtin(__builtin_unreachable) + __builtin_unreachable(); +#endif +#endif +#undef FAST_IO_SCAN_ISO8601_CONTEXT_TOKEN_PHASE +} + +} + +template <::std::integral char_type, ::std::int_least64_t off_to_epoch> +inline constexpr parse_result scan_contiguous_define(io_reserve_type_t&>>, char_type const* begin, char_type const* end, fast_io::parameter&> t) noexcept +{ + if constexpr (off_to_epoch == 0) + return details::scn_cnt_define_unix_timestamp_impl(begin, end, t.reference); + else + { + unix_timestamp retval; + auto result{ details::scn_cnt_define_unix_timestamp_impl(begin, end, retval) }; + t.reference = static_cast>(retval); + return result; + } +} + +template <::std::integral char_type, ::std::int_least64_t off_to_epoch> +inline constexpr io_type_t> scan_context_type(io_reserve_type_t&>>) noexcept +{ + return {}; +} + +template <::std::integral char_type, ::std::int_least64_t off_to_epoch> +inline constexpr parse_result scan_context_define(io_reserve_type_t&>>, timestamp_scan_state_t& state, char_type const* begin, char_type const* end, parameter&> t) noexcept +{ + if constexpr (off_to_epoch == 0) + return details::scn_ctx_define_unix_timestamp_impl(state, begin, end, t.reference); + auto result{ details::scn_ctx_define_unix_timestamp_impl(state, begin, end, *reinterpret_cast(__builtin_addressof(t.reference))) }; + if (result.code == parse_code::ok) + t.reference.seconds -= off_to_epoch; + return result; +} + +template <::std::integral char_type, ::std::int_least64_t off_to_epoch> +inline constexpr parse_code scan_context_eof_define(io_reserve_type_t&>>, timestamp_scan_state_t& state, fast_io::parameter&> t) noexcept +{ + if constexpr (off_to_epoch == 0) + return details::scn_ctx_eof_define_unix_timestamp_impl(state, t.reference); + auto result{ details::scn_ctx_eof_define_unix_timestamp_impl(state, *reinterpret_cast(__builtin_addressof(t.reference))) }; + if (result == parse_code::ok && state.tsp_phase != scan_timestamp_context_phase::ok) + t.reference.seconds -= off_to_epoch; + return result; +} + +template <::std::integral char_type> +inline constexpr parse_result scan_contiguous_define(io_reserve_type_t>, char_type const* begin, char_type const* end, fast_io::parameter t) noexcept +{ + return details::scn_cnt_define_iso8601_impl(begin, end, t.reference); +} + +template <::std::integral char_type> +inline constexpr io_type_t> scan_context_type(io_reserve_type_t>) noexcept +{ + return {}; +} + +template <::std::integral char_type> +inline constexpr parse_result scan_context_define(io_reserve_type_t>, timestamp_scan_state_t& state, char_type const* begin, char_type const* end, fast_io::parameter t) noexcept +{ + return details::scn_ctx_define_iso8601_impl(state, begin, end, t.reference); +} + +template <::std::integral char_type> +inline constexpr parse_code scan_context_eof_define(io_reserve_type_t>, timestamp_scan_state_t& state, fast_io::parameter) noexcept +{ + if (state.tsp_phase == scan_timestamp_context_phase::ok) + return parse_code::ok; + else + return parse_code::end_of_file; +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/iso/isos.h b/src/fast_io/include/fast_io_core_impl/iso/isos.h new file mode 100644 index 0000000..a4efd27 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/iso/isos.h @@ -0,0 +1,55 @@ +#pragma once + +namespace fast_io +{ + +namespace details +{ + +template<::std::integral char_type> +inline constexpr char_type* output_iso8601_subseconds_main(char_type* iter,std::uint_least64_t subseconds) noexcept +{ + constexpr std::size_t digitsm1(std::numeric_limits::digits10); + std::size_t sz(digitsm1); + for(;subseconds%10==0;--sz) + subseconds/=10; + print_reserve_integral_main_impl<10,false>(iter+=sz,subseconds,sz); + return iter; +} + +template +inline constexpr char_type* output_iso8601_subseconds(char_type* iter,std::uint_least64_t subseconds) noexcept +{ + *iter=char_literal_v<(comma?u8',':u8'.'),char_type>; + ++iter; + return output_iso8601_subseconds_main(iter,subseconds); +} + +inline constexpr std::uint_least64_t cal_uint_least64_d10_max() noexcept +{ + std::size_t v(std::numeric_limits::digits10); + std::uint_least64_t value{1}; + for(std::size_t i{};i!=v;++i) + value*=10u; + return value; +} + +template +inline constexpr auto cal_uint_least64_d10_all_table() noexcept +{ + ::fast_io::freestanding::array::digits10> array; + array.back()=1; + for(std::size_t i{array.size()-1};i--;) + array[i]=array[i+1]*10u; + return array; +} + +template +inline constexpr auto d10_reverse_table{cal_uint_least64_d10_all_table()}; +} + +inline constexpr std::uint_least64_t uint_least64_subseconds_per_second{details::cal_uint_least64_d10_max()}; + +} + +#include"iso8601.h" diff --git a/src/fast_io/include/fast_io_core_impl/literals/literal.h b/src/fast_io/include/fast_io_core_impl/literals/literal.h new file mode 100644 index 0000000..d04aa23 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/literals/literal.h @@ -0,0 +1,71 @@ +#pragma once + +namespace fast_io +{ + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr ch_type char_literal(char8_t ch) noexcept +{ +#if 'A' != u8'A' || L'A' !=u8'A' +#include"none_ascii.h" +#endif + { + using unsigned_t = ::std::make_unsigned_t; + return static_cast(static_cast(ch)); + } +} +template +inline constexpr ch_type char_literal_v{char_literal(ch)}; + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr ch_type arithmetic_char_literal(char8_t ch) noexcept +{ + if constexpr(std::same_as&&::fast_io::details::wide_is_none_utf_endian) + { + using unsigned_t = ::std::make_unsigned_t; + return static_cast(static_cast(ch)); + } + else + { + return char_literal(ch); + } +} + +template +inline constexpr ch_type arithmetic_char_literal_v{arithmetic_char_literal(ch)}; + +template +inline constexpr char_type char_literal_add(T offs) noexcept +{ +#if __has_cpp_attribute(assume) + if constexpr(ch==u8'0') + { + [[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) + { + 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))<(static_cast(static_cast(arithmetic_char_literal_v+offs))); + } +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/literals/none_ascii.h b/src/fast_io/include/fast_io_core_impl/literals/none_ascii.h new file mode 100644 index 0000000..3c25e6f --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/literals/none_ascii.h @@ -0,0 +1,19 @@ + if constexpr(::fast_io::details::is_ebcdic&&(std::same_as||std::same_as)) + { + if constexpr(std::same_as) +switch(ch) +{ +case u8'\0':return '\0';case u8'\n':return '\n';case u8'\t':return '\t';case u8' ':return ' ';case u8'!':return '!';case u8'\"':return '\"';case u8'#':return '#';case u8'$':return '$';case u8'%':return '%';case u8'&':return '&';case u8'\'':return '\'';case u8'(':return '(';case u8')':return ')';case u8'*':return '*';case u8'+':return '+';case u8',':return ',';case u8'-':return '-';case u8'.':return '.';case u8'/':return '/';case u8'0':return '0';case u8'1':return '1';case u8'2':return '2';case u8'3':return '3';case u8'4':return '4';case u8'5':return '5';case u8'6':return '6';case u8'7':return '7';case u8'8':return '8';case u8'9':return '9';case u8':':return ':';case u8';':return ';';case u8'<':return '<';case u8'=':return '=';case u8'>':return '>';case u8'?':return '?';case u8'@':return '@';case u8'A':return 'A';case u8'B':return 'B';case u8'C':return 'C';case u8'D':return 'D';case u8'E':return 'E';case u8'F':return 'F';case u8'G':return 'G';case u8'H':return 'H';case u8'I':return 'I';case u8'J':return 'J';case u8'K':return 'K';case u8'L':return 'L';case u8'M':return 'M';case u8'N':return 'N';case u8'O':return 'O';case u8'P':return 'P';case u8'Q':return 'Q';case u8'R':return 'R';case u8'S':return 'S';case u8'T':return 'T';case u8'U':return 'U';case u8'V':return 'V';case u8'W':return 'W';case u8'X':return 'X';case u8'Y':return 'Y';case u8'Z':return 'Z';case u8'[':return '[';case u8'\\':return '\\';case u8']':return ']';case u8'^':return '^';case u8'_':return '_';case u8'`':return '`';case u8'a':return 'a';case u8'b':return 'b';case u8'c':return 'c';case u8'd':return 'd';case u8'e':return 'e';case u8'f':return 'f';case u8'g':return 'g';case u8'h':return 'h';case u8'i':return 'i';case u8'j':return 'j';case u8'k':return 'k';case u8'l':return 'l';case u8'm':return 'm';case u8'n':return 'n';case u8'o':return 'o';case u8'p':return 'p';case u8'q':return 'q';case u8'r':return 'r';case u8's':return 's';case u8't':return 't';case u8'u':return 'u';case u8'v':return 'v';case u8'w':return 'w';case u8'x':return 'x';case u8'y':return 'y';case u8'z':return 'z';case u8'{':return '{';case u8'|':return '|';case u8'}':return '}';case u8'~':return '~';default: return '\0'; +} + else +switch(ch) +{ +case u8'\0':return L'\0';case u8'\n':return L'\n';case u8'\t':return L'\t';case u8' ':return L' ';case u8'!':return L'!';case u8'\"':return L'\"';case u8'#':return L'#';case u8'$':return L'$';case u8'%':return L'%';case u8'&':return L'&';case u8'\'':return L'\'';case u8'(':return L'(';case u8')':return L')';case u8'*':return L'*';case u8'+':return L'+';case u8',':return L',';case u8'-':return L'-';case u8'.':return L'.';case u8'/':return L'/';case u8'0':return L'0';case u8'1':return L'1';case u8'2':return L'2';case u8'3':return L'3';case u8'4':return L'4';case u8'5':return L'5';case u8'6':return L'6';case u8'7':return L'7';case u8'8':return L'8';case u8'9':return L'9';case u8':':return L':';case u8';':return L';';case u8'<':return L'<';case u8'=':return L'=';case u8'>':return L'>';case u8'?':return L'?';case u8'@':return L'@';case u8'A':return L'A';case u8'B':return L'B';case u8'C':return L'C';case u8'D':return L'D';case u8'E':return L'E';case u8'F':return L'F';case u8'G':return L'G';case u8'H':return L'H';case u8'I':return L'I';case u8'J':return L'J';case u8'K':return L'K';case u8'L':return L'L';case u8'M':return L'M';case u8'N':return L'N';case u8'O':return L'O';case u8'P':return L'P';case u8'Q':return L'Q';case u8'R':return L'R';case u8'S':return L'S';case u8'T':return L'T';case u8'U':return L'U';case u8'V':return L'V';case u8'W':return L'W';case u8'X':return L'X';case u8'Y':return L'Y';case u8'Z':return L'Z';case u8'[':return L'[';case u8'\\':return L'\\';case u8']':return L']';case u8'^':return L'^';case u8'_':return L'_';case u8'`':return L'`';case u8'a':return L'a';case u8'b':return L'b';case u8'c':return L'c';case u8'd':return L'd';case u8'e':return L'e';case u8'f':return L'f';case u8'g':return L'g';case u8'h':return L'h';case u8'i':return L'i';case u8'j':return L'j';case u8'k':return L'k';case u8'l':return L'l';case u8'm':return L'm';case u8'n':return L'n';case u8'o':return L'o';case u8'p':return L'p';case u8'q':return L'q';case u8'r':return L'r';case u8's':return L's';case u8't':return L't';case u8'u':return L'u';case u8'v':return L'v';case u8'w':return L'w';case u8'x':return L'x';case u8'y':return L'y';case u8'z':return L'z';case u8'{':return L'{';case u8'|':return L'|';case u8'}':return L'}';case u8'~':return L'~';default: return L'\0'; +} + } + else if constexpr(std::same_as&&::fast_io::details::wide_is_none_utf_endian) + { + using unsigned_char_type = std::make_unsigned_t; + return static_cast(::fast_io::byte_swap(static_cast(ch))); + } + else \ No newline at end of file diff --git a/src/fast_io/include/fast_io_core_impl/local_new_array_ptr.h b/src/fast_io/include/fast_io_core_impl/local_new_array_ptr.h new file mode 100644 index 0000000..322658a --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/local_new_array_ptr.h @@ -0,0 +1,107 @@ +#pragma once + +namespace fast_io::details +{ +template +inline constexpr char_type* allocate_iobuf_space(std::size_t buffer_size) noexcept +{ +#if __cpp_constexpr >=201907L && __cpp_constexpr_dynamic_alloc >= 201907L && (__cpp_lib_is_constant_evaluated >=201811L || __cpp_if_consteval >= 202106L) +#if __cpp_if_consteval >= 202106L + if consteval +#else + if(std::is_constant_evaluated()) +#endif + { + return new char_type[buffer_size]; + } + else +#endif + { + return static_cast(typed_generic_allocator_adapter::allocate(buffer_size)); + } +} + +template +inline void deallocate_with_secure_clear(void* ptr,[[maybe_unused]] std::size_t buffer_bytes) noexcept +{ + if constexpr(nsecure_clear) + secure_clear(ptr,buffer_bytes); + if constexpr(allocator::has_deallocate) + allocator::deallocate(ptr); + else + allocator::deallocate_n(ptr,buffer_bytes); +} + +template +inline constexpr void deallocate_iobuf_space(char_type* ptr,[[maybe_unused]] std::size_t buffer_size) noexcept +{ +#if __cpp_constexpr >=201907L && __cpp_constexpr_dynamic_alloc >= 201907L && (__cpp_lib_is_constant_evaluated >=201811L || __cpp_if_consteval >= 202106L) +#if __cpp_if_consteval >= 202106L + if consteval +#else + if(std::is_constant_evaluated()) +#endif + { + delete[] ptr; + } + else +#endif + { + using typed_allocator = typed_generic_allocator_adapter; + if constexpr(nsecure_clear) + secure_clear(ptr,buffer_size*sizeof(char_type)); + if constexpr(typed_allocator::has_deallocate) + typed_allocator::deallocate(ptr); + else + typed_allocator::deallocate_n(ptr,buffer_size); + } +} + +template +struct buffer_alloc_arr_ptr +{ + using allocator_type = Allocator; + T* ptr{}; + std::size_t size{}; + constexpr buffer_alloc_arr_ptr() noexcept = default; + explicit +#if __cpp_constexpr >=201907L && __cpp_constexpr_dynamic_alloc >= 201907L && (__cpp_lib_is_constant_evaluated >=201811L || __cpp_if_consteval >= 202106L) + constexpr +#endif + buffer_alloc_arr_ptr(std::size_t sz) noexcept:ptr(allocate_iobuf_space(sz)),size(sz){} + + buffer_alloc_arr_ptr(buffer_alloc_arr_ptr const&)=delete; + buffer_alloc_arr_ptr& operator=(buffer_alloc_arr_ptr const&)=delete; + constexpr T* allocate_new(::std::size_t n) noexcept + { + return (ptr=allocate_iobuf_space(size=n)); + } + constexpr T* get() noexcept + { + return ptr; + } + constexpr T const* get() const noexcept + { + return ptr; + } + constexpr T& operator[](std::size_t pos) noexcept + { + return ptr[pos]; + } + constexpr T const& operator[](std::size_t pos) const noexcept + { + return ptr[pos]; + } +#if __cpp_constexpr >=201907L && __cpp_constexpr_dynamic_alloc >= 201907L && (__cpp_lib_is_constant_evaluated >=201811L || __cpp_if_consteval >= 202106L) + constexpr +#endif + ~buffer_alloc_arr_ptr() + { + deallocate_iobuf_space(ptr,size); + } +}; + +template +using local_operator_new_array_ptr=buffer_alloc_arr_ptr; + +} diff --git a/src/fast_io/include/fast_io_core_impl/mode.h b/src/fast_io/include/fast_io_core_impl/mode.h new file mode 100644 index 0000000..e01b551 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/mode.h @@ -0,0 +1,575 @@ +#pragma once + +namespace fast_io +{ + +/* +https://github.com/gcc-mirror/gcc/blob/41d6b10e96a1de98e90a7c0378437c3255814b16/libstdc%2B%2B-v3/include/bits/fs_fwd.h#L73 + +Being binary compatible with libstdc++'s file_type +*/ +enum class file_type : signed char +{ +none = 0, not_found = -1, regular = 1, directory = 2, symlink = 3, +block = 4, character = 5, fifo = 6, socket = 7, unknown = 8, remote = 9 +}; + +template +inline constexpr std::size_t print_reserve_size(io_reserve_type_t) noexcept +{ + return 20; +} + + +namespace details +{ +template +inline constexpr char_type* print_file_status_impl(char_type* it,file_type f) noexcept +{ + if constexpr(std::same_as) + { + switch(f) + { + case file_type::none: + return details::copy_string_literal("none",it); + case file_type::not_found: + return details::copy_string_literal("not_found",it); + case file_type::regular: + return details::copy_string_literal("regular",it); + case file_type::directory: + return details::copy_string_literal("directory",it); + case file_type::symlink: + return details::copy_string_literal("symlink",it); + case file_type::block: + return details::copy_string_literal("block",it); + case file_type::character: + return details::copy_string_literal("character",it); + case file_type::fifo: + return details::copy_string_literal("fifo",it); + case file_type::socket: + return details::copy_string_literal("socket",it); + case file_type::remote: + return details::copy_string_literal("remote",it); + default: + return details::copy_string_literal("unknown",it); + } + } + else if constexpr(std::same_as) + { + switch(f) + { + case file_type::none: + return details::copy_string_literal(L"none",it); + case file_type::not_found: + return details::copy_string_literal(L"not_found",it); + case file_type::regular: + return details::copy_string_literal(L"regular",it); + case file_type::directory: + return details::copy_string_literal(L"directory",it); + case file_type::symlink: + return details::copy_string_literal(L"symlink",it); + case file_type::block: + return details::copy_string_literal(L"block",it); + case file_type::character: + return details::copy_string_literal(L"character",it); + case file_type::fifo: + return details::copy_string_literal(L"fifo",it); + case file_type::socket: + return details::copy_string_literal(L"socket",it); + case file_type::remote: + return details::copy_string_literal(L"remote",it); + default: + return details::copy_string_literal(L"unknown",it); + } + } + else if constexpr(std::same_as) + { + switch(f) + { + case file_type::none: + return details::copy_string_literal(u"none",it); + case file_type::not_found: + return details::copy_string_literal(u"not_found",it); + case file_type::regular: + return details::copy_string_literal(u"regular",it); + case file_type::directory: + return details::copy_string_literal(u"directory",it); + case file_type::symlink: + return details::copy_string_literal(u"symlink",it); + case file_type::block: + return details::copy_string_literal(u"block",it); + case file_type::character: + return details::copy_string_literal(u"character",it); + case file_type::fifo: + return details::copy_string_literal(u"fifo",it); + case file_type::socket: + return details::copy_string_literal(u"socket",it); + case file_type::remote: + return details::copy_string_literal(u"remote",it); + default: + return details::copy_string_literal(u"unknown",it); + } + } + else if constexpr(std::same_as) + { + switch(f) + { + case file_type::none: + return details::copy_string_literal(U"none",it); + case file_type::not_found: + return details::copy_string_literal(U"not_found",it); + case file_type::regular: + return details::copy_string_literal(U"regular",it); + case file_type::directory: + return details::copy_string_literal(U"directory",it); + case file_type::symlink: + return details::copy_string_literal(U"symlink",it); + case file_type::block: + return details::copy_string_literal(U"block",it); + case file_type::character: + return details::copy_string_literal(U"character",it); + case file_type::fifo: + return details::copy_string_literal(U"fifo",it); + case file_type::socket: + return details::copy_string_literal(U"socket",it); + case file_type::remote: + return details::copy_string_literal(U"remote",it); + default: + return details::copy_string_literal(U"unknown",it); + } + } + else + { + switch(f) + { + case file_type::none: + return details::copy_string_literal(u8"none",it); + case file_type::not_found: + return details::copy_string_literal(u8"not_found",it); + case file_type::regular: + return details::copy_string_literal(u8"regular",it); + case file_type::directory: + return details::copy_string_literal(u8"directory",it); + case file_type::symlink: + return details::copy_string_literal(u8"symlink",it); + case file_type::block: + return details::copy_string_literal(u8"block",it); + case file_type::character: + return details::copy_string_literal(u8"character",it); + case file_type::fifo: + return details::copy_string_literal(u8"fifo",it); + case file_type::socket: + return details::copy_string_literal(u8"socket",it); + case file_type::remote: + return details::copy_string_literal(u8"remote",it); + default: + return details::copy_string_literal(u8"unknown",it); + } + } +} +} + +template +inline constexpr char_type* print_reserve_define(io_reserve_type_t,char_type* it,file_type f) noexcept +{ + return details::print_file_status_impl(it,f); +} + +enum class shut{in,out,io}; + +/* +https://www.unix.com/man-page/FreeBSD/2/clock_gettime/ +https://linux.die.net/man/3/clock_gettime +*/ + +enum class posix_clock_id +{ +realtime, +realtime_alarm, +realtime_coarse, +tai, +monotonic, +monotonic_coarse, +monotonic_raw, +monotonic_raw_approx, +boottime, +boottime_alarm, +uptime_raw, +uptime_raw_approx, +process_cputime_id, +thread_cputime_id +}; + +enum class open_mode: + ::std::uint_least64_t +{ +none=0, +// *indicates that the open mode has not been evaluated yet +app=static_cast<::std::uint_least64_t>(1)<<0, +// *["a"]seek to the end of stream before each write. +archive=static_cast<::std::uint_least64_t>(1)<<1, +// [Windows]FILE_ATTRIBUTE_ARCHIVE 0x20 +case_insensitive=static_cast<::std::uint_least64_t>(1)<<2, +// [Windows]NT OBJ_CASE_INSENSITIVE 0x00000040L +compressed=static_cast<::std::uint_least64_t>(1)<<3, +// [Windows]FILE_ATTRIBUTE_COMPRESSED 0x800 +creat=static_cast<::std::uint_least64_t>(1)<<4, +// POSIX O_CREAT +direct=static_cast<::std::uint_least64_t>(1)<<5, +// *POSIX O_DIRECT +directory=static_cast<::std::uint_least64_t>(1)<<6, +// *POSIX O_DIRECTORY. +encrypted=static_cast<::std::uint_least64_t>(1)<<7, +// [Windows]FILE_ATTRIBUTE_ENCRYPTED 0x4000 +excl=static_cast<::std::uint_least64_t>(1)<<8, +noreplace=excl, +// *["x"]POSIX O_EXCL +follow=static_cast<::std::uint_least64_t>(1)<<9, +// *Inverse of POSIX O_NOFOLLOW. +hidden=static_cast<::std::uint_least64_t>(1)<<10, +// [Windows]FILE_ATTRIBUTE_HIDDEN 0x2 +in=static_cast<::std::uint_least64_t>(1)<<11, +// *["r"]open for reading. +inherit=static_cast<::std::uint_least64_t>(1)<<12, +// *Inverse of POSIX O_CLOEXEC. +no_atime=static_cast<::std::uint_least64_t>(1)<<13, +// [Linux]O_NOATIME +no_block=static_cast<::std::uint_least64_t>(1)<<14, +// *POSIX O_NONBLOCK +no_ctty=static_cast<::std::uint_least64_t>(1)<<15, +// [Linux]O_NOCTTY +no_recall=static_cast<::std::uint_least64_t>(1)<<16, +// [Windows]FILE_FLAG_OPEN_NO_RECALL 0x00100000 +no_shared_read=static_cast<::std::uint_least64_t>(1)<<17, +// [WINDOWS]!FILE_SHARE_READ 0x00000001 +no_shared_write=static_cast<::std::uint_least64_t>(1)<<18, +// [WINDOWS]!FILE_SHARE_WRITE 0x00000002 +normal=static_cast<::std::uint_least64_t>(1)<<19, +// [Windows]FILE_ATTRIBUTE_NORMAL 0x80 +offline=static_cast<::std::uint_least64_t>(1)<<20, +// [Windows]FILE_ATTRIBUTE_OFFLINE 0x1000 +out=static_cast<::std::uint_least64_t>(1)<<21, +// *["w"]open for writing. +path=static_cast<::std::uint_least64_t>(1)<<22, +// [Linux]O_PATH +random_access=static_cast<::std::uint_least64_t>(1)<<23, +// [Windows]FILE_FLAG_RANDOM_ACCESS 0x10000000 +search=static_cast<::std::uint_least64_t>(1)<<24, +// POSIX O_SEARCH +session_aware=static_cast<::std::uint_least64_t>(1)<<25, +// [Windows]FILE_FLAG_SESSION_AWARE 0x00800000 +shared_delete=static_cast<::std::uint_least64_t>(1)<<26, +// [WINDOWS]FILE_SHARE_WRITE 0x00000004 +sync=static_cast<::std::uint_least64_t>(1)<<27, +// *POSIX O_SYNC +system=static_cast<::std::uint_least64_t>(1)<<28, +// [Windows]FILE_ATTRIBUTE_SYSTEM 0x4 +temporary=static_cast<::std::uint_least64_t>(1)<<29, +// *[Linux]O_TMPFILE. [Windows]FILE_ATTRIBUTE_TEMPORARY 0x100 + FILE_FLAG_DELETE_ON_CLOSE 0x04000000 +text=static_cast<::std::uint_least64_t>(1)<<30, +// [inverse of "b"]open in text mode. native_file is always binary. The text mode is provided by the POSIX layer or C FILE layer. When native_file is win32_file or nt_file or zw_file or unsupported character type for C FILE* or C++ filebuf, throw invalid arguments eh. +trunc=static_cast<::std::uint_least64_t>(1)<<31, +// *POSIX O_TRUNC +tty_init=static_cast<::std::uint_least64_t>(1)<<32, +// POSIX O_TTY_INIT +}; + +constexpr open_mode operator&(open_mode x, open_mode y) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(static_cast(x) & static_cast(y)); +} + +constexpr open_mode operator|(open_mode x, open_mode y) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(static_cast(x) | static_cast(y)); +} + +constexpr open_mode operator^(open_mode x, open_mode y) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(static_cast(x) ^ static_cast(y)); +} + +constexpr open_mode operator~(open_mode x) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(~static_cast(x)); +} + +inline constexpr open_mode& operator&=(open_mode& x, open_mode y) noexcept{return x=x&y;} + +inline constexpr open_mode& operator|=(open_mode& x, open_mode y) noexcept{return x=x|y;} + +inline constexpr open_mode& operator^=(open_mode& x, open_mode y) noexcept{return x=x^y;} + + + +inline constexpr open_mode c_supported(open_mode m) noexcept +{ +using utype = typename std::underlying_type::type; +constexpr auto c_supported_values{static_cast(open_mode::text)| + static_cast(open_mode::excl)| + static_cast(open_mode::out)| + static_cast(open_mode::app)| + static_cast(open_mode::in)| + static_cast(open_mode::trunc)}; +return static_cast(static_cast(m)&c_supported_values); +} + +inline constexpr char const* to_c_mode(open_mode m) noexcept +{ + using utype = typename std::underlying_type::type; + switch(static_cast(c_supported(m))) + { +//Action if file already exists; Action if file does not exist; c-style mode; Explanation +//Read from start; Failure to open; "r"; Open a file for reading + case static_cast(open_mode::in)|static_cast(open_mode::text): + return "\x72"; +//Destroy contents; Create new; "w"; Create a file for writing + case static_cast(open_mode::out)|static_cast(open_mode::text): + case static_cast(open_mode::out)|static_cast(open_mode::trunc)|static_cast(open_mode::text): + return "\x77"; +//Append to file; Create new; "a"; Append to a file + case static_cast(open_mode::app)|static_cast(open_mode::text): + case static_cast(open_mode::out)|static_cast(open_mode::app)|static_cast(open_mode::text): + return "\x61"; +//Read from start; Error; "r+"; Open a file for read/write + case static_cast(open_mode::out)|static_cast(open_mode::in)|static_cast(open_mode::text): + return "\x72\x2b"; +//Destroy contents; Create new; "w+"; Create a file for read/write + case static_cast(open_mode::out)|static_cast(open_mode::in)|static_cast(open_mode::trunc)|static_cast(open_mode::text): + return "\x77\x2b"; +//Write to end; Create new; "a+"; Open a file for read/write + case static_cast(open_mode::out)|static_cast(open_mode::in)|static_cast(open_mode::app)|static_cast(open_mode::text): + case static_cast(open_mode::in)|static_cast(open_mode::app)|static_cast(open_mode::text): + return "\x61\x2b"; +//Destroy contents; Error; "wx"; Create a file for writing + case static_cast(open_mode::out)|static_cast(open_mode::excl)|static_cast(open_mode::text): + case static_cast(open_mode::out)|static_cast(open_mode::trunc)|static_cast(open_mode::excl)|static_cast(open_mode::text): + return "\x77\x78"; +//Append to file; Error; "ax"; Append to a file + case static_cast(open_mode::app)|static_cast(open_mode::excl)|static_cast(open_mode::text): + case static_cast(open_mode::out)|static_cast(open_mode::app)|static_cast(open_mode::excl)|static_cast(open_mode::text): + return "\x61\x78"; +//Destroy contents; Error; "w+x"; Create a file for read/write + case static_cast(open_mode::out)|static_cast(open_mode::in)|static_cast(open_mode::trunc)|static_cast(open_mode::excl)|static_cast(open_mode::text): + return "\x77\x2b\x78"; +//Write to end; Error; "a+x"; Open a file for read/write + case static_cast(open_mode::out)|static_cast(open_mode::in)|static_cast(open_mode::app)|static_cast(open_mode::excl)|static_cast(open_mode::text): + case static_cast(open_mode::in)|static_cast(open_mode::app)|static_cast(open_mode::excl)|static_cast(open_mode::text): + return "\x61\x2b\x78"; + break; + +//binary support + +//Action if file already exists; Action if file does not exist; c-style mode; Explanation +//Read from start; Failure to open; "rb"; Open a file for reading + case static_cast(open_mode::in): + return "\x72\x62"; +//Destroy contents; Create new; "wb"; Create a file for writing + case static_cast(open_mode::out): + case static_cast(open_mode::out)|static_cast(open_mode::trunc): + return "\x77\x62"; +//Append to file; Create new; "ab"; Append to a file + case static_cast(open_mode::app): + case static_cast(open_mode::out)|static_cast(open_mode::app): + return "\x61\x62"; +//Read from start; Error; "r+b"; Open a file for read/write + case static_cast(open_mode::out)|static_cast(open_mode::in): + return "\x72\x2b\x62"; +//Destroy contents; Create new; "w+b"; Create a file for read/write + case static_cast(open_mode::out)|static_cast(open_mode::in)|static_cast(open_mode::trunc): + return "\x77\x2b\x62"; +//Write to end; Create new; "a+b"; Open a file for read/write + case static_cast(open_mode::out)|static_cast(open_mode::in)|static_cast(open_mode::app): + case static_cast(open_mode::in)|static_cast(open_mode::app): + return "\x61\x2b\x62"; +//Destroy contents; Error; "wxb"; Create a file for writing + case static_cast(open_mode::out)|static_cast(open_mode::excl): + case static_cast(open_mode::out)|static_cast(open_mode::trunc)|static_cast(open_mode::excl): + return "\x77\x78\x62"; +//Append to file; Error; "axb"; Append to a file + case static_cast(open_mode::app)|static_cast(open_mode::excl): + case static_cast(open_mode::out)|static_cast(open_mode::app)|static_cast(open_mode::excl): + return "\x61\x78\x62"; +//Destroy contents; Error; "w+xb"; Create a file for read/write + case static_cast(open_mode::out)|static_cast(open_mode::in)|static_cast(open_mode::trunc)|static_cast(open_mode::excl): + return "\x77\x2b\x78\x62"; +//Write to end; Error; "a+xb"; Open a file for read/write + case static_cast(open_mode::out)|static_cast(open_mode::in)|static_cast(open_mode::app)|static_cast(open_mode::excl): + case static_cast(open_mode::in)|static_cast(open_mode::app)|static_cast(open_mode::excl): + return "\x61\x2b\x78\x62"; + break; + case 0: + if((m&open_mode::directory)!=open_mode::none) + return "\x72"; + [[fallthrough]]; + default: + return ""; + } +} +enum class posix_wait_reason:unsigned char +{ +none,if_exited,if_signaled,if_core_dump,if_core_signal,if_stopped +}; + +template +inline constexpr std::size_t print_reserve_size(io_reserve_type_t) noexcept +{ + return 20; +} + +template +inline constexpr char_type* print_reserve_define(io_reserve_type_t,char_type* iter,posix_wait_reason reason) noexcept +{ + if constexpr(std::same_as) + { + switch(reason) + { + case posix_wait_reason::none: + return details::copy_string_literal("none",iter); + case posix_wait_reason::if_exited: + return details::copy_string_literal("if_exited",iter); + case posix_wait_reason::if_signaled: + return details::copy_string_literal("if_signaled",iter); + case posix_wait_reason::if_core_dump: + return details::copy_string_literal("if_core_dump",iter); + case posix_wait_reason::if_core_signal: + return details::copy_string_literal("if_core_signal",iter); + case posix_wait_reason::if_stopped: + return details::copy_string_literal("if_stopped",iter); + default: + return details::copy_string_literal("unknown",iter); + } + } + else if constexpr(std::same_as) + { + switch(reason) + { + case posix_wait_reason::none: + return details::copy_string_literal(L"none",iter); + case posix_wait_reason::if_exited: + return details::copy_string_literal(L"if_exited",iter); + case posix_wait_reason::if_signaled: + return details::copy_string_literal(L"if_signaled",iter); + case posix_wait_reason::if_core_dump: + return details::copy_string_literal(L"if_core_dump",iter); + case posix_wait_reason::if_core_signal: + return details::copy_string_literal(L"if_core_signal",iter); + case posix_wait_reason::if_stopped: + return details::copy_string_literal(L"if_stopped",iter); + default: + return details::copy_string_literal(L"unknown",iter); + } + } + else if constexpr(std::same_as) + { + switch(reason) + { + case posix_wait_reason::none: + return details::copy_string_literal(u"none",iter); + case posix_wait_reason::if_exited: + return details::copy_string_literal(u"if_exited",iter); + case posix_wait_reason::if_signaled: + return details::copy_string_literal(u"if_signaled",iter); + case posix_wait_reason::if_core_dump: + return details::copy_string_literal(u"if_core_dump",iter); + case posix_wait_reason::if_core_signal: + return details::copy_string_literal(u"if_core_signal",iter); + case posix_wait_reason::if_stopped: + return details::copy_string_literal(u"if_stopped",iter); + default: + return details::copy_string_literal(u"unknown",iter); + } + } + else if constexpr(std::same_as) + { + switch(reason) + { + case posix_wait_reason::none: + return details::copy_string_literal(U"none",iter); + case posix_wait_reason::if_exited: + return details::copy_string_literal(U"if_exited",iter); + case posix_wait_reason::if_signaled: + return details::copy_string_literal(U"if_signaled",iter); + case posix_wait_reason::if_core_dump: + return details::copy_string_literal(U"if_core_dump",iter); + case posix_wait_reason::if_core_signal: + return details::copy_string_literal(U"if_core_signal",iter); + case posix_wait_reason::if_stopped: + return details::copy_string_literal(U"if_stopped",iter); + default: + return details::copy_string_literal(U"unknown",iter); + } + } + else + { + switch(reason) + { + case posix_wait_reason::none: + return details::copy_string_literal(u8"none",iter); + case posix_wait_reason::if_exited: + return details::copy_string_literal(u8"if_exited",iter); + case posix_wait_reason::if_signaled: + return details::copy_string_literal(u8"if_signaled",iter); + case posix_wait_reason::if_core_dump: + return details::copy_string_literal(u8"if_core_dump",iter); + case posix_wait_reason::if_core_signal: + return details::copy_string_literal(u8"if_core_signal",iter); + case posix_wait_reason::if_stopped: + return details::copy_string_literal(u8"if_stopped",iter); + default: + return details::copy_string_literal(u8"unknown",iter); + } + } +} + + + +struct native_interface_t +{ +explicit constexpr native_interface_t() noexcept=default; +}; +inline constexpr native_interface_t native_interface{}; + +struct io_async_t +{ +explicit constexpr io_async_t() noexcept=default; +}; +inline constexpr io_async_t io_async{}; + +struct io_temp_t +{ +explicit constexpr io_temp_t() noexcept=default; +}; +inline constexpr io_temp_t io_temp{}; + +struct io_dup_t +{ +explicit constexpr io_dup_t() noexcept=default; +}; +inline constexpr io_dup_t io_dup{}; + +struct io_kernel_t +{ +explicit constexpr io_kernel_t() noexcept=default; +}; +inline constexpr io_kernel_t io_kernel{}; + +struct posix_at_entry +{ + int fd{-1}; + explicit constexpr posix_at_entry() noexcept=default; + explicit constexpr posix_at_entry(int mfd) noexcept:fd(mfd){} +}; + +struct file_loader_extra_bytes +{ + ::std::size_t n{}; + explicit constexpr file_loader_extra_bytes(::std::size_t nn) noexcept:n(nn) {} +}; + +} + diff --git a/src/fast_io/include/fast_io_core_impl/overflow.h b/src/fast_io/include/fast_io_core_impl/overflow.h new file mode 100644 index 0000000..db5242b --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/overflow.h @@ -0,0 +1,35 @@ +#pragma once + +namespace fast_io +{ + +template +inline constexpr void put(output& out,typename std::remove_cvref_t::char_type ch) +{ + auto curr{obuffer_curr(out)}; + auto end{obuffer_end(out)}; +/* +Referenced from glibc +https://github.com/bminor/glibc/blob/21c3f4b5368686ade28d90d8c7d79c4c95c72c1b/libio/bits/types/struct_FILE.h +*/ + if constexpr(noline_buffer_output_stream) + { + if(curr==end)[[unlikely]] + { + obuffer_overflow(out,ch); + return; + } + } + else + { + if(end<=curr)[[unlikely]] + { + obuffer_overflow(out,ch); + return; + } + } + *curr=ch; + obuffer_set_curr(out,++curr); + +} +} diff --git a/src/fast_io/include/fast_io_core_impl/parse_code.h b/src/fast_io/include/fast_io_core_impl/parse_code.h new file mode 100644 index 0000000..0e85bb6 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/parse_code.h @@ -0,0 +1,138 @@ +#pragma once + +namespace fast_io +{ +namespace details +{ +template<::std::integral char_type> +inline constexpr char_type* print_reserve_parse_code_impl(char_type* iter,parse_code code) noexcept +{ + if constexpr(std::same_as) + { + switch(code) + { + case parse_code::ok: + return copy_string_literal("ok",iter); + case parse_code::end_of_file: + return copy_string_literal("end_of_file",iter); + case parse_code::partial: + return copy_string_literal("partial",iter); + case parse_code::invalid: + return copy_string_literal("invalid",iter); + case parse_code::overflow: + return copy_string_literal("overflow",iter); + default: + return copy_string_literal("unknown",iter); + } + } + else if constexpr(std::same_as) + { + switch(code) + { + case parse_code::ok: + return copy_string_literal(L"ok",iter); + case parse_code::end_of_file: + return copy_string_literal(L"end_of_file",iter); + case parse_code::partial: + return copy_string_literal(L"partial",iter); + case parse_code::invalid: + return copy_string_literal(L"invalid",iter); + case parse_code::overflow: + return copy_string_literal(L"overflow",iter); + default: + return copy_string_literal(L"unknown",iter); + } + } + else if constexpr(std::same_as) + { + switch(code) + { + case parse_code::ok: + return copy_string_literal(u"ok",iter); + case parse_code::end_of_file: + return copy_string_literal(u"end_of_file",iter); + case parse_code::partial: + return copy_string_literal(u"partial",iter); + case parse_code::invalid: + return copy_string_literal(u"invalid",iter); + case parse_code::overflow: + return copy_string_literal(u"overflow",iter); + default: + return copy_string_literal(u"unknown",iter); + } + } + else + { + switch(code) + { + case parse_code::ok: + return copy_string_literal(u8"ok",iter); + case parse_code::end_of_file: + return copy_string_literal(u8"end_of_file",iter); + case parse_code::partial: + return copy_string_literal(u8"partial",iter); + case parse_code::invalid: + return copy_string_literal(u8"invalid",iter); + case parse_code::overflow: + return copy_string_literal(u8"overflow",iter); + default: + return copy_string_literal(u8"unknown",iter); + } + } +} + +} + +template +inline constexpr std::size_t print_reserve_size(io_reserve_type_t) noexcept +{ + return 16; +} + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define(io_reserve_type_t, char_type* iter,parse_code code) noexcept +{ + return details::print_reserve_parse_code_impl(iter,code); +} + +inline constexpr std::uintptr_t domain_define(error_type_t) noexcept +{ + if constexpr(sizeof(std::uintptr_t)<=sizeof(std::uint_least16_t)) + return 19339u; + else if constexpr(sizeof(std::uintptr_t)<=sizeof(std::uint_least32_t)) + return 2666707100u; + else + return 17020429607921007685ULL; +} + +inline constexpr std::uintptr_t parse_domain_value{domain_define(error_type)}; + +[[noreturn]] inline void throw_parse_code([[maybe_unused]] parse_code code) +{ +#ifdef __cpp_exceptions +#if defined(_MSC_VER) && (!defined(_HAS_EXCEPTIONS) || _HAS_EXCEPTIONS == 0) + fast_terminate(); +#else + throw ::fast_io::error{parse_domain_value,static_cast(static_cast(code))}; +#endif +#else + fast_terminate(); +#endif +} + +namespace details +{ + +inline constexpr bool parse_code_equivalent_impl(std::uintptr_t domain,std::uintptr_t code,std::uintptr_t e) noexcept +{ + return domain==parse_domain_value&&code==e; +} + +} + +inline constexpr bool equivalent_define(error_type_t,error e,parse_code code) noexcept +{ + return ::fast_io::details::parse_code_equivalent_impl(e.domain,e.code,static_cast(static_cast(code))); +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/perms.h b/src/fast_io/include/fast_io_core_impl/perms.h new file mode 100644 index 0000000..84085f4 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/perms.h @@ -0,0 +1,123 @@ +#pragma once + +namespace fast_io +{ +//https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/include/bits/fs_fwd.h +enum class perms : std::uint_least32_t +{ +none = 0, +owner_read = 0400, +owner_write = 0200, +owner_exec = 0100, +owner_all = 0700, +group_read = 040, +group_write = 020, +group_exec = 010, +group_all = 070, +others_read = 04, +others_write = 02, +others_exec = 01, +others_all = 07, +all = 0777, +set_uid = 04000, +set_gid = 02000, +sticky_bit = 01000, +mask = 07777, +unknown = 0xFFFF, +add_perms = 0x10000, +remove_perms = 0x20000, +symlink_nofollow= 0x40000 +}; + +constexpr perms operator&(perms x, perms y) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(static_cast(x) & static_cast(y)); +} + +constexpr perms operator|(perms x, perms y) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(static_cast(x) | static_cast(y)); +} + +constexpr perms operator^(perms x, perms y) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(static_cast(x) ^ static_cast(y)); +} + +constexpr perms operator~(perms x) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(~static_cast(x)); +} + +inline constexpr perms& operator&=(perms& x, perms y) noexcept{return x=x&y;} + +inline constexpr perms& operator|=(perms& x, perms y) noexcept{return x=x|y;} + +inline constexpr perms& operator^=(perms& x, perms y) noexcept{return x=x^y;} + +namespace details::perm +{ +template +inline constexpr void print_perm_per_check(char_type* i,perms p,perms checked) noexcept +{ + if((p&checked)==perms::none) + { + *i=char_literal_v; + } + else + { + *i=char_literal_v; + } +} + +} +template +inline constexpr std::size_t print_reserve_size(io_reserve_type_t) noexcept +{ + return 9; +} + +namespace details +{ +template +inline constexpr char_type* print_status_impl(char_type* iter,perms p) noexcept +{ + details::perm::print_perm_per_check(iter,p,perms::owner_read); + details::perm::print_perm_per_check(++iter,p,perms::owner_write); + details::perm::print_perm_per_check(++iter,p,perms::owner_exec); + details::perm::print_perm_per_check(++iter,p,perms::group_read); + details::perm::print_perm_per_check(++iter,p,perms::group_write); + details::perm::print_perm_per_check(++iter,p,perms::group_exec); + details::perm::print_perm_per_check(++iter,p,perms::others_read); + details::perm::print_perm_per_check(++iter,p,perms::others_write); + details::perm::print_perm_per_check(++iter,p,perms::others_exec); + ++iter; + return iter; +} +} + +template +inline constexpr char_type* print_reserve_define(io_reserve_type_t, char_type* iter,perms p) noexcept +{ + return details::print_status_impl(iter,p); +} + +enum class data_sync_flags:std::uint_least8_t +{ +normal=0, +file_data_only=0x00000001, +no_sync=0x00000002, +file_data_sync_only=0x00000004 +}; + +struct open_mode_perms +{ + open_mode om{}; + perms pm{}; +}; + +} diff --git a/src/fast_io/include/fast_io_core_impl/pr_rsv.h b/src/fast_io/include/fast_io_core_impl/pr_rsv.h new file mode 100644 index 0000000..42568a6 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/pr_rsv.h @@ -0,0 +1,182 @@ +#pragma once + +namespace fast_io +{ + +namespace details +{ +template +inline constexpr std::size_t pr_rsv_size_impl() noexcept +{ + using nocvref_t = std::remove_cvref_t; + if constexpr(alias_printable) + { + using alias_type = decltype(print_alias_define(::fast_io::io_alias, + *static_cast(static_cast(nullptr)))); + constexpr bool error{reserve_printable}; + if constexpr(error) + { + constexpr std::size_t sz{print_reserve_size(io_reserve_type)}; + return sz; + } + else + { +static_assert(error,"type is not reserve_printable"); + return 0; + } + } + else + { + constexpr bool error{reserve_printable}; + if constexpr(error) + { + constexpr std::size_t sz{print_reserve_size(io_reserve_type)}; + return sz; + } + else + { +static_assert(error,"type is not reserve_printable"); + return 0; + } + } +} +} + +template +inline constexpr std::size_t pr_rsv_size{::fast_io::details::pr_rsv_size_impl()}; + +template<::std::random_access_iterator Iter,typename T> +inline constexpr Iter pr_rsv_to_iterator_unchecked(Iter it,T&& t) noexcept +{ + using char_type = ::std::iter_value_t; + if constexpr(alias_printable>) + { + using alias_type = decltype(print_alias_define(::fast_io::io_alias,t)); + constexpr bool error{reserve_printable}; + if constexpr(error) + { + return print_reserve_define(io_reserve_type,it, + print_alias_define(::fast_io::io_alias,t)); + } + else + { +static_assert(error,"type is not reserve_printable"); + return it; + } + } + else + { + constexpr bool error{reserve_printable>}; + if constexpr(error) + { + return print_reserve_define(io_reserve_type>,it,t); + } + else + { +static_assert(error,"type is not reserve_printable"); + return it; + } + } +} +template +inline constexpr char_type* pr_rsv_to_c_array(char_type (&buffer)[n],T&& t) noexcept +{ + constexpr bool error{(pr_rsv_size>)<=n}; + if constexpr(error) + { + return pr_rsv_to_iterator_unchecked(buffer,::std::forward(t)); + } + else + { +static_assert(error,"C array size is not enough"); + return buffer; + } +} + +#if defined(_GLIBCXX_ARRAY) || defined(_GLIBCXX_ARRAY) || defined(_ARRAY_) +template +inline constexpr typename ::std::array::iterator pr_rsv_to_array(::std::array &buffer,T&& t) noexcept +{ + constexpr bool error{(pr_rsv_size>)<=n}; + if constexpr(error) + { + return pr_rsv_to_iterator_unchecked(buffer.data(),::std::forward(t))-buffer.data()+buffer.begin(); + } + else + { +static_assert(error,"array size is not enough"); + return buffer.begin(); + } +} +#endif + +namespace details +{ + +template<::std::integral char_type,typename T> +inline constexpr ::fast_io::parse_result parse_by_scan_impl(char_type const* first,char_type const* last,T t) noexcept +{ + if constexpr(::fast_io::precise_reserve_scannable) + { + constexpr std::size_t n{scan_precise_reserve_size(io_reserve_type)}; + std::size_t const diff{static_cast(last-first)}; + if(diff) + { + scan_precise_reserve_define(io_reserve_type,first,t); + return {first+n,::fast_io::parse_code::ok}; + } + else + { + return scan_precise_reserve_define(io_reserve_type,first,t); + } + } + else if constexpr(::fast_io::contiguous_scannable) + { + return scan_contiguous_define(io_reserve_type,first,last,t); + } + else if constexpr(::fast_io::context_scannable) + { + typename std::remove_cvref_t))>::type state; + auto [it,ec]=scan_context_define(io_reserve_type,state,first,last,t); + if(ec!=parse_code::partial) + { + return {it,ec}; + } + ec=scan_context_eof_define(io_reserve_type,state,t); + return {it,ec}; + } + else + { + constexpr bool not_scannable{context_scannable}; + static_assert(not_scannable,"type not scannable. need context_scannable"); + return false; + } +} + +} + +template<::std::integral char_type,typename T> +#if __has_cpp_attribute(nodiscard) +[[nodiscard("NEVER discard return pointer and parse code from parse_by_scan")]] +#endif +inline constexpr ::fast_io::parse_result parse_by_scan(char_type const* first,char_type const* last,T&& t) noexcept +{ + using mytype = decltype(io_scan_forward(io_scan_alias(t))); + constexpr bool allscannable{::fast_io::precise_reserve_scannable|| + ::fast_io::contiguous_scannable|| + ::fast_io::context_scannable}; + if constexpr(allscannable) + { + return ::fast_io::details::parse_by_scan_impl(first,last,io_scan_forward(io_scan_alias(t))); + } + else + { +static_assert(allscannable,"type not scannable. need context_scannable"); + } +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/print_freestanding.h b/src/fast_io/include/fast_io_core_impl/print_freestanding.h new file mode 100644 index 0000000..8fbadcc --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/print_freestanding.h @@ -0,0 +1,837 @@ +#pragma once + +namespace fast_io +{ + +namespace details::decay +{ + +template +inline constexpr void scatter_print_recursive(io_scatter_t* arr,T t) +{ + auto scatter{print_scatter_define(io_reserve_type>,t)}; + *arr={scatter.base,scatter.len*sizeof(char_type)}; +} + +template +inline constexpr void scatter_print_recursive(io_scatter_t* arr,T t, Args ...args) +{ + auto scatter{print_scatter_define(io_reserve_type>,t)}; + *arr={scatter.base,scatter.len*sizeof(char_type)}; + scatter_print_recursive(arr+1,args...); +} + +template +inline constexpr std::size_t calculate_scatter_reserve_size_unit() +{ + using real_type = std::remove_cvref_t; + if constexpr(reserve_printable) + { + constexpr std::size_t sz{print_reserve_size(io_reserve_type)}; + return sz; + } + else + return 0; +} + +template +inline constexpr std::size_t calculate_scatter_reserve_size() +{ + if constexpr(sizeof...(Args)==0) + { + return calculate_scatter_reserve_size_unit(); + } + else + { + return ::fast_io::details::intrinsics::add_or_overflow_die(calculate_scatter_reserve_size_unit(), + calculate_scatter_reserve_size()); + } +} + +template +inline constexpr std::size_t calculate_scatter_dynamic_reserve_size([[maybe_unused]] T t,Args... args) +{ + if constexpr(!reserve_printable&& + dynamic_reserve_printable) + { + std::size_t res{print_reserve_size(io_reserve_type,t)}; + if constexpr(sizeof...(Args)==0) + return res; + else + return ::fast_io::details::intrinsics::add_or_overflow_die(res,calculate_scatter_dynamic_reserve_size(args...)); + } + else + { + if constexpr(sizeof...(Args)==0) + return 0; + else + return calculate_scatter_dynamic_reserve_size(args...); + } +} + + +template +inline constexpr void scatter_print_with_reserve_recursive_unit(char_type*& start_ptr, + io_scatter_t* arr,T t) +{ + using real_type = std::remove_cvref_t; + if constexpr(reserve_printable) + { + if constexpr(::fast_io::details::asan_state::current==::fast_io::details::asan_state::activate) + { + constexpr std::size_t sz{print_reserve_size(io_reserve_type)}; + char_type sanitize_buffer[sz]; + auto dt{print_reserve_define(io_reserve_type,sanitize_buffer,t)}; + auto end_ptr{non_overlapped_copy_n(sanitize_buffer,static_cast(dt-sanitize_buffer),start_ptr)}; + *arr={start_ptr,static_cast(end_ptr-start_ptr)*sizeof(*start_ptr)}; + start_ptr=end_ptr; + } + else + { + auto end_ptr = print_reserve_define(io_reserve_type,start_ptr,t); + *arr={start_ptr,static_cast(end_ptr-start_ptr)*sizeof(*start_ptr)}; + start_ptr=end_ptr; + } + } + else + { + auto scatter{print_scatter_define(io_reserve_type,t)}; + *arr={scatter.base,scatter.len*sizeof(*scatter.base)}; + } +} + +template +inline constexpr void scatter_print_with_reserve_recursive(char_type* ptr, + io_scatter_t* arr,T t) +{ + scatter_print_with_reserve_recursive_unit(ptr,arr,t); +} + +template +inline constexpr void scatter_print_with_reserve_recursive(char_type* ptr, + io_scatter_t* arr,T t, Args ...args) +{ + scatter_print_with_reserve_recursive_unit(ptr,arr,t); + scatter_print_with_reserve_recursive(ptr,arr+1,args...); +} + +template +inline constexpr void scatter_print_with_dynamic_reserve_recursive(io_scatter_t* __restrict arr, + [[maybe_unused]] char_type* __restrict ptr, + [[maybe_unused]] char_type* __restrict dynamic_buffer_ptr,[[maybe_unused]] T t, Args ...args) +{ + + if constexpr(scatter_printable) + { + auto sc{print_scatter_define(io_reserve_type,t)}; + *arr={sc.base,sc.len*sizeof(char_type)}; + } + else if constexpr(reserve_printable) + { + auto end_ptr = print_reserve_define(io_reserve_type,ptr,t); + *arr={ptr,(end_ptr-ptr)*sizeof(*ptr)}; + if constexpr(sizeof...(Args)!=0) + ptr=end_ptr; + } + else if constexpr(dynamic_reserve_printable) + { + auto end_ptr = print_reserve_define(io_reserve_type,dynamic_buffer_ptr,t); + *arr={dynamic_buffer_ptr,(end_ptr-dynamic_buffer_ptr)*sizeof(*dynamic_buffer_ptr)}; + if constexpr(sizeof...(Args)!=0) + dynamic_buffer_ptr = end_ptr; + } + if constexpr(sizeof...(Args)!=0) + scatter_print_with_dynamic_reserve_recursive(arr+1,ptr,dynamic_buffer_ptr,args...); +} + +template +inline constexpr void scatter_print_with_dynamic_only_reserve_recursive(io_scatter_t* __restrict arr, + [[maybe_unused]] char_type* __restrict dynamic_buffer_ptr,[[maybe_unused]] T t, Args ...args) +{ + static_assert(!reserve_printable); + if constexpr(scatter_printable) + { + auto sc{print_scatter_define(io_reserve_type,t)}; + *arr={sc.base,sc.len*sizeof(char_type)}; + } + else if constexpr(dynamic_reserve_printable) + { + auto end_ptr = print_reserve_define(io_reserve_type,dynamic_buffer_ptr,t); + *arr={dynamic_buffer_ptr,(end_ptr-dynamic_buffer_ptr)*sizeof(*dynamic_buffer_ptr)}; + if constexpr(sizeof...(Args)!=0) + dynamic_buffer_ptr = end_ptr; + } + if constexpr(sizeof...(Args)!=0) + scatter_print_with_dynamic_only_reserve_recursive(arr+1,dynamic_buffer_ptr,args...); +} + +template +requires scatter_printable +inline constexpr auto extract_one_scatter(T t) +{ + return print_scatter_define(io_reserve_type>,t); +} + +template +inline constexpr bool constant_buffer_output_stream_require_size_constant_impl = + (N)); + +template +concept constant_buffer_output_stream_require_size_impl = constant_buffer_output_stream + && constant_buffer_output_stream_require_size_constant_impl; + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline constexpr void print_control_dynamic_reserve_bad_path(output out,value_type t,std::size_t sizep1) +{ + using char_type = typename output::char_type; + local_operator_new_array_ptr ptr(sizep1); + auto it{print_reserve_define(io_reserve_type,ptr.ptr,t)}; + if constexpr(line) + { + *it=char_literal_v; + ++it; + } + write(out,ptr.ptr,it); +} + +template +requires (std::is_trivially_copyable_v&&std::is_trivially_copyable_v) +inline constexpr void print_control(output out,T t) +{ + using char_type = typename output::char_type; + using value_type = std::remove_cvref_t; + constexpr auto lfch{char_literal_v}; + constexpr bool asan_activated{::fast_io::details::asan_state::current==::fast_io::details::asan_state::activate}; + if constexpr(scatter_printable) + { + basic_io_scatter_t scatter{print_scatter_define(io_reserve_type,t)}; + if constexpr(line) + { + if constexpr(output_stream_with_writeln) + writeln(out,scatter.base,scatter.base+scatter.len); + else 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(out,curr); + } + else if constexpr(buffer_output_stream) + { + 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(len)) + { + constexpr std::size_t real_size{print_reserve_size(io_reserve_type)}; + constexpr std::size_t size{real_size+static_cast(line)}; + static_assert(real_size) + { + auto bcurr{obuffer_curr(out)}; + auto bend{obuffer_end(out)}; + std::size_t diff{static_cast(bend-bcurr)}; + if(diff,bcurr,t)}; + if constexpr(line) + { + *it=lfch; + ++it; + } + obuffer_set_curr(out,it); + } + else + { + if constexpr(buffer_output_stream&&!asan_activated) + { + char_type* bcurr{obuffer_curr(out)}; + char_type* bend{obuffer_end(out)}; + std::ptrdiff_t const diff(bend-bcurr); + bool smaller{static_cast(size)) + { + if(!smaller)[[unlikely]] + { + obuffer_constant_flush_prepare(out); + bcurr=obuffer_curr(out); + } + bcurr=print_reserve_define(io_reserve_type,bcurr,t); + if constexpr(line) + { + *bcurr=lfch; + ++bcurr; + } + obuffer_set_curr(out,bcurr); + } + else + { + char_type buffer[size]; + if(!smaller)[[unlikely]] + bcurr=buffer; + bcurr=print_reserve_define(io_reserve_type,bcurr,t); + if constexpr(line) + { + *bcurr=lfch; + ++bcurr; + } + if(smaller)[[likely]] + obuffer_set_curr(out,bcurr); + else[[unlikely]] + write(out,buffer,bcurr); + } + } + else + { + char_type buffer[size]; + char_type* i{print_reserve_define(io_reserve_type,buffer,t)}; + if constexpr(line) + { + *i=lfch; + ++i; + } + write(out,buffer,i); + } + } + } + else if constexpr(dynamic_reserve_printable) + { + std::size_t size{print_reserve_size(io_reserve_type,t)}; + if constexpr(line) + { + constexpr std::size_t mx{std::numeric_limits::max()-1}; + if(size>=mx) + fast_terminate(); + ++size; + } + else + { + constexpr std::size_t mx{std::numeric_limits::max()}; + if(mx) + { + auto bcurr{obuffer_curr(out)}; + auto bend{obuffer_end(out)}; + auto it{print_reserve_define(io_reserve_type,bcurr,t,size)}; + std::size_t diff{static_cast(bend-bcurr)}; + if(diff&&!asan_activated) + { + auto curr{obuffer_curr(out)}; + auto ed{obuffer_end(out)}; + std::ptrdiff_t diff(ed-curr); + if(static_cast(size),curr,t)}; + if constexpr(line) + { + *it=lfch; + ++it; + } + obuffer_set_curr(out,it); + return; + } + } + print_control_dynamic_reserve_bad_path(out,t,size); + } + } + else if constexpr(printable) + { + print_define(io_reserve_type,out,t); + if constexpr(line) + put(out,lfch); + } + else + { + constexpr bool no{printable}; + static_assert(no,"type not printable"); + } +} + + +struct print_size_struct +{ + std::size_t n{}; + std::size_t total_size{}; +}; + +inline constexpr std::size_t max_reserve_multiple_parameter_size{512u}; + +template +inline constexpr print_size_struct print_reserve_total_size_para() +{ + if constexpr(reserve_printable) + { + constexpr std::size_t rsvsize{print_reserve_size(io_reserve_type)}; + if constexpr(rsvsize>=max_reserve_multiple_parameter_size) + return {}; + else if constexpr(sizeof...(Args)==0) + { + return {1,rsvsize}; + } + else + { + auto next{print_reserve_total_size_para()}; + std::size_t mx_size{static_cast(SIZE_MAX>>1u)-rsvsize}; + if(next.total_size>=mx_size) + return next; + return {next.n+1,next.total_size+rsvsize}; + } + } + else + { + return {}; + } +} + +template +inline constexpr print_size_struct print_reserve_multiple_parameters_total_size() +{ + constexpr std::size_t t_reserve_size{print_reserve_size(io_reserve_type)}; + static_assert(t_reserve_size<(SIZE_MAX>>1u),"overflow"); + if constexpr((t_reserve_size>=max_reserve_multiple_parameter_size)||(sizeof...(Args)==0)) + { + return {0,t_reserve_size}; + } + else if constexpr(sizeof...(Args)!=0) + { + constexpr print_size_struct sizestrct{print_reserve_total_size_para()}; + constexpr std::size_t overflow_max_size{max_reserve_multiple_parameter_size-t_reserve_size}; + if constexpr(sizestrct.total_size>=overflow_max_size) + return {0,t_reserve_size}; + else + return {sizestrct.n,t_reserve_size+sizestrct.total_size}; + } +} + +template +requires(n!=0) +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr Iter partition_reserve_impl(Iter iter,T t,[[maybe_unused]] Args ...args) +{ + using char_type = ::std::iter_value_t; + iter=print_reserve_define(io_reserve_type,iter,t); + if constexpr(n==1) + { + return iter; + } + else + { + return partition_reserve_impl(iter,args...); + } +} + + +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_multi_impl(output out,T t,Args ...args) +{ + if constexpr(n==0) + { + using char_type = typename output::char_type; + if constexpr(reserve_printable) + { + constexpr auto reserve_paras_info{print_reserve_multiple_parameters_total_size()}; + constexpr std::size_t reserve_paras_n{reserve_paras_info.n}; + if constexpr(reserve_paras_n!=0) + { + static_assert(reserve_paras_info.total_size(PTRDIFF_MAX),"reserve size cannot be zero"); + { + constexpr bool need_output_lf{sizeof...(Args)==reserve_paras_n&&line}; + constexpr std::size_t buffer_size{reserve_paras_info.total_size+static_cast(need_output_lf)}; + if constexpr(buffer_output_stream) + { + auto curr_ptr{obuffer_curr(out)}; + auto end_ptr{obuffer_end(out)}; + std::ptrdiff_t diff{end_ptr-curr_ptr}; + bool const on_io_buffer{static_cast(buffer_size)) + { + if(!on_io_buffer)[[unlikely]] + { + obuffer_constant_flush_prepare(out); + curr_ptr=obuffer_curr(out); + } + curr_ptr=print_reserve_define(io_reserve_type,curr_ptr,t); + curr_ptr=partition_reserve_impl(curr_ptr,args...); + if constexpr(need_output_lf) + { + *curr_ptr=char_literal_v; + ++curr_ptr; + } + obuffer_set_curr(out,curr_ptr); + } + else + { + char_type stack_buffer[buffer_size]; + auto start{stack_buffer}; + auto ptr{print_reserve_define(io_reserve_type,start,t)}; + ptr=partition_reserve_impl(ptr,args...); + if constexpr(need_output_lf) + { + *ptr=char_literal_v; + ++ptr; + } + write(out,start,ptr); + } + } + } + if constexpr(reserve_paras_info.n!=sizeof...(Args)) + print_controls_line_multi_impl(out,args...); + } + else + { + if constexpr(sizeof...(Args)==0) + print_control(out,t); + else + { + print_control(out,t); + print_controls_line_multi_impl(out,args...); + } + } + } + else + { + if constexpr(sizeof...(Args)==0) + print_control(out,t); + else + { + print_control(out,t); + print_controls_line_multi_impl(out,args...); + } + } + } + else + { + print_controls_line_multi_impl(out,args...); + } +} + +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 out,T t,Args... args) +{ + if constexpr(sizeof...(Args)==0) + print_control(out,t); + else + { +#if defined(__OPTIMIZE__) || defined(__OPTIMIZE_SIZE__) + print_controls_line_multi_impl(out,t,args...); +#else + if constexpr(ln) + { + print_control(out,t); + print_controls_line(out,args...); + } + else + { + print_control(out,t); + (print_control(out,args),...); + } +#endif + } +} + +template +inline constexpr void print_fallback(output out,Args ...args) +{ + using char_type = typename output::char_type; + if constexpr(line&&sizeof...(Args)==0) + { + write(out,__builtin_addressof(char_literal_v),__builtin_addressof(char_literal_v)+1); + } + else + { +#if __cpp_if_consteval >= 202106L + if consteval +#else + if(__builtin_is_constant_evaluated()) +#endif + { + temporary_buffer buffer; + buffer.out=out; + auto ref{io_ref(buffer)}; + print_controls_line_multi_impl(ref,args...); + flush(buffer); + } + else + { + if constexpr( + (scatter_output_stream||scatter_constant_output_stream)&& + ((scatter_printable||reserve_printable||dynamic_reserve_printable)&&...)) + { + constexpr std::size_t args_num{sizeof...(Args)}; + constexpr std::size_t n{args_num+static_cast(line)}; + io_scatter_t scatters[n]; + if constexpr((scatter_printable&&...)) + { + scatter_print_recursive(scatters,args...); + if constexpr(line) + { + scatters[args_num]={__builtin_addressof(char_literal_v),sizeof(char_type)}; + } + if constexpr(scatter_constant_output_stream) + { + scatter_constant_write(out,scatters); + } + else + { + scatter_write(out,{scatters,n}); + } + } + else if constexpr(((scatter_printable|| + reserve_printable)&&...)) + { + constexpr std::size_t total_size{calculate_scatter_reserve_size()}; + char_type buffer[total_size]; + scatter_print_with_reserve_recursive(buffer,scatters,args...); + if constexpr(line) + { + scatters[args_num]={__builtin_addressof(char_literal_v),sizeof(char_type)}; + } + if constexpr(scatter_constant_output_stream) + { + scatter_constant_write(out,scatters); + } + else + { + scatter_write(out,{scatters,n}); + } + } + else + { + constexpr std::size_t total_size{calculate_scatter_reserve_size()}; + if constexpr(total_size!=0) + { + char_type buffer[total_size]; + local_operator_new_array_ptr new_ptr(calculate_scatter_dynamic_reserve_size(args...)); + scatter_print_with_dynamic_reserve_recursive(scatters,buffer,new_ptr.ptr,args...); + if constexpr(line) + { + scatters[args_num]={__builtin_addressof(char_literal_v),sizeof(char_type)}; + } + if constexpr(scatter_constant_output_stream) + { + scatter_constant_write(out,scatters); + } + else + { + scatter_write(out,{scatters,n}); + } + } + else + { + local_operator_new_array_ptr new_ptr(calculate_scatter_dynamic_reserve_size(args...)); + scatter_print_with_dynamic_only_reserve_recursive(scatters,new_ptr.ptr,args...); + if constexpr(line) + { + scatters[args_num]={__builtin_addressof(char_literal_v),sizeof(char_type)}; + } + if constexpr(scatter_constant_output_stream) + { + scatter_constant_write(out,scatters); + } + else + { + scatter_write(out,{scatters,n}); + } + } + } + } + else + { + temporary_buffer buffer; + buffer.out=out; + auto ref{io_ref(buffer)}; + print_controls_line_multi_impl(ref,args...); + flush(buffer); + } + } + } +} + +} + +template +concept print_freestanding_decay_okay_character_type_no_status = std::integral&&((std::is_trivially_copyable_v&&(printable||scatter_printable||reserve_printable||dynamic_reserve_printable))&&...); + +template +concept print_freestanding_decay_okay_no_status = std::is_trivially_copyable_v&&print_freestanding_decay_okay_character_type_no_status; + +template +concept print_freestanding_decay_okay = std::is_trivially_copyable_v&&((status_output_stream&&requires(output out,Args ...args) +{ + print_status_define(out,args...); + print_status_define(out,args...); +})||(!status_output_stream&&output_stream&&print_freestanding_decay_okay_no_status)); + +namespace details +{ + +template +requires print_freestanding_decay_okay +inline constexpr void print_freestanding_deacy_okay_dummy(output,Args...) +{ + +} + +} + +template +concept print_freestanding_okay = requires(output&& out,Args&& ...args) +{ + ::fast_io::details::print_freestanding_deacy_okay_dummy(io_ref(out),io_print_forward::char_type>(io_print_alias(args))...); +}; + +template +requires print_freestanding_decay_okay_no_status +inline constexpr void print_freestanding_decay_no_status(output out,Args ...args) +{ + using char_type = typename output::char_type; + if constexpr(sizeof...(Args)==0&&!line) + return; + else if constexpr(mutex_stream) + { + io_lock_guard lg{out}; + decltype(auto) dout{out.unlocked_handle()}; + print_freestanding_decay_no_status(io_ref(dout),args...); + } + else if constexpr(buffer_output_stream) + { + if constexpr(sizeof...(Args)==0&&line) + put(out,char_literal_v); + else + { +#if defined(__OPTIMIZE__) || defined(__OPTIMIZE_SIZE__) + ::fast_io::details::decay::print_controls_line_multi_impl(out,args...); +#else + if constexpr(line) + { + ::fast_io::details::decay::print_controls_line(out,args...); + } + else + { + (::fast_io::details::decay::print_control(out,args),...); + } +#endif + } + } + else if constexpr(sizeof...(Args)==1&& + ((((!line||output_stream_with_writeln)&&((printable||scatter_printable)&&...))|| + ((reserve_printable||dynamic_reserve_printable)&&...)))) + { + if constexpr(line) + { + ::fast_io::details::decay::print_controls_line(out,args...); + } + else + { + (::fast_io::details::decay::print_control(out,args),...); + } + } + else + { + ::fast_io::details::decay::print_fallback(out,args...); + } +} + +template +requires print_freestanding_decay_okay +inline constexpr void print_freestanding_decay(output out,Args ...args) +{ + if constexpr(status_output_stream) + print_status_define(out,args...); + else + print_freestanding_decay_no_status(out,args...); +} + +template +requires print_freestanding_decay_okay +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline constexpr void print_freestanding_decay_cold(output out,Args ...args) +{ + if constexpr(status_output_stream) + print_status_define(out,args...); + else + print_freestanding_decay_no_status(out,args...); +} + +template +requires print_freestanding_okay +inline constexpr void print_freestanding(output&& out,Args&& ...args) +{ + print_freestanding_decay(io_ref(out),io_print_forward::char_type>(io_print_alias(args))...); +} + +template +requires print_freestanding_okay +inline constexpr void println_freestanding(output&& out,Args&& ...args) +{ + print_freestanding_decay(io_ref(out),io_print_forward::char_type>(io_print_alias(args))...); +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/random_access_transmit.h b/src/fast_io/include/fast_io_core_impl/random_access_transmit.h new file mode 100644 index 0000000..fd24004 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/random_access_transmit.h @@ -0,0 +1,115 @@ +#pragma once + +namespace fast_io +{ +namespace details +{ + +#if defined(__linux__)||defined(__BSD_VISIBLE) +template +inline constexpr std::uintmax_t zero_copy_random_access_transmit_impl(output& outp,input& inp,std::intmax_t offset) +{ + auto ret(zero_copy_transmit(outp,inp,offset)); + if(ret.second) + { + offset+=static_cast(ret.first); + return ret.first+bufferred_transmit_impl(outp,inp); + } + return ret.first; +} + +template +inline constexpr std::uintmax_t zero_copy_random_access_transmit_impl(output& outp,input& inp,std::intmax_t offset,std::uintmax_t sz) +{ + auto ret(zero_copy_transmit(outp,inp,offset,sz)); + if(ret.second) + { + offset+=static_cast(ret.first); + return ret.first+bufferred_transmit_impl(outp,inp,sz-ret.first); + } + return ret.first; +} +#endif + +template +inline constexpr auto random_access_transmit_impl(output& outp,input& inp,std::intmax_t offset,Args&& ...args) +{ + if constexpr(mutex_stream) + { + io_lock_guard lg{inp}; + decltype(auto) uh{inp.unlocked_handle()}; + return random_access_transmit_impl(outp,uh,::std::forward(args)...); + } + else + { +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + { + seek(inp,offset); + return bufferred_transmit_impl(outp,inp,::std::forward(args)...); + } + else + { +#endif + if constexpr(zero_copy_output_stream&&zero_copy_input_stream) + { + if constexpr(buffer_input_stream) + { + offset-=end(inp)-begin(inp); + iclear(inp); + } + if constexpr(buffer_output_stream) + flush(outp); +#if defined(__linux__)||defined(__BSD_VISIBLE) + return zero_copy_random_access_transmit_impl(outp,inp,offset,::std::forward(args)...); +#else + return zero_copy_transmit(outp,inp,offset,::std::forward(args)...); +#endif + } + else + { + seek(inp,offset); + return bufferred_transmit_impl(outp,inp,::std::forward(args)...); + } +#ifdef __cpp_lib_is_constant_evaluated + } +#endif + } +} + + +} + +template +requires fast_io::random_access_stream +inline constexpr void print_define(output& outp,manip::random_access_transmission ref) +{ + ref.transmitted=static_cast(details::random_access_transmit_impl(outp,ref.reference,ref.offset)); +} + +template +requires fast_io::random_access_stream +inline constexpr void print_define(output& outp,manip::random_access_transmission_with_size ref) +{ + ref.transmitted=static_cast(details::random_access_transmit_impl(outp,ref.reference,ref.offset,ref.bytes)); +} + +template +requires fast_io::random_access_stream +inline constexpr std::uintmax_t random_access_transmit(output&& outp,offset_type offset,input&& in) +{ + std::uintmax_t transmitted{}; + print_freestanding(::std::forward(outp),manip::random_access_transmission(transmitted,offset,in)); + return transmitted; +} + +template +requires fast_io::random_access_stream +inline constexpr sz_type random_access_transmit(output&& outp,offset_type offset,input&& in,sz_type bytes) +{ + sz_type transmitted{}; + print_freestanding(::std::forward(outp),manip::random_access_transmission_with_size(transmitted,offset,in,bytes)); + return transmitted; +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/range_view.h b/src/fast_io/include/fast_io_core_impl/range_view.h new file mode 100644 index 0000000..62bad2c --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/range_view.h @@ -0,0 +1,147 @@ +#pragma once + +namespace fast_io { +template <::std::integral ch_type, ::std::input_iterator It> +struct sized_range_view_t +{ + using char_type = ch_type; + using iterator = It; + using value_type = decltype(io_print_alias(*(It{}))); + basic_io_scatter_t sep; + iterator begin; + ::std::size_t size; +}; +template <::std::integral char_type, ::std::input_iterator I> +sized_range_view_t(basic_io_scatter_t, I, ::std::size_t)->sized_range_view_t; + +template <::std::integral ch_type, ::std::input_iterator It> +struct range_view_t +{ + using char_type = ch_type; + using iterator = It; + basic_io_scatter_t sep; + iterator begin; + iterator end; +}; +template <::std::integral char_type, ::std::input_iterator I> +range_view_t(basic_io_scatter_t, I, I)->range_view_t; + +template <::std::integral char_type, ::std::input_iterator It> +inline constexpr ::std::size_t print_reserve_size(io_reserve_type_t>, sized_range_view_t t) +{ + if (t.size == 0) return 0; + using T = sized_range_view_t; + if constexpr (reserve_printable) + // print_reserve_size(io_reserve_type) * t.size + t.sep.len * (t.size - 1); + return (print_reserve_size(io_reserve_type) + t.sep.len) * t.size; + else // dynamic_reserve_printable + { + ::std::size_t retval{ t.sep.len * t.size - 1 }; + auto curr_ptr{ t.begin }; + for (::std::size_t i{}; i != t.size; ++i, ++curr_ptr) + retval += print_reserve_size(io_reserve_type, + ::fast_io::io_print_forward(::fast_io::io_print_alias(*curr_ptr))); + return retval; + } +} +template <::std::integral char_type, ::std::input_iterator It> +inline constexpr char_type* print_reserve_define(io_reserve_type_t>, char_type* __restrict ptr, sized_range_view_t t) +{ + if (t.size == 0) return ptr; + using value_type = typename sized_range_view_t::value_type; + auto curr_ptr{ t.begin }; + ptr = print_reserve_define(io_reserve_type, ptr, + ::fast_io::io_print_forward(::fast_io::io_print_alias(*curr_ptr))); + ++curr_ptr; + for (::std::size_t i{}; i != t.size - 1; ++i, ++curr_ptr) + { + ::fast_io::freestanding::non_overlapped_copy_n(t.sep.base, t.sep.len, ptr); + ptr += t.sep.len; + ptr = print_reserve_define(io_reserve_type, ptr, + ::fast_io::io_print_forward(::fast_io::io_print_alias(*curr_ptr))); + } + return ptr; +} + +template <::std::integral char_type, ::std::input_iterator It, output_stream output> +inline constexpr void print_define(io_reserve_type_t>, output out, range_view_t t) +{ + if (t.begin == t.end) return; + auto curr_ptr{ t.begin }; + print_freestanding(out, *curr_ptr); + for (++curr_ptr; curr_ptr != t.end; ++curr_ptr) + { + print_freestanding(out, t.sep, *curr_ptr); + } +} + +namespace manipulators { +template <::std::ranges::range rg, ::std::integral char_type> +inline constexpr auto rgvw(rg&& r, char_type const (&sep)[2]) +{ + using ::std::to_address; + using ::std::ranges::begin; + using ::std::ranges::end; + using ::std::ranges::size; + using ::fast_io::sized_range_view_t; + using ::fast_io::range_view_t; + using value_type = decltype(io_print_alias(*begin(r))); + constexpr bool is_contiguous_range = ::std::ranges::contiguous_range; + constexpr bool is_sized_range = ::std::ranges::sized_range; + auto printed = ::fast_io::basic_io_scatter_t{ reinterpret_cast(__builtin_addressof(sep)), 1 }; + if constexpr (::fast_io::reserve_printable) + { + if constexpr (is_contiguous_range && is_sized_range) + return sized_range_view_t{ printed, to_address(begin(r)), size(r) }; + else if constexpr (is_contiguous_range) + return sized_range_view_t{ printed, to_address(begin(r)), to_address(end(r)) - to_address(begin(r)) }; + else if constexpr (is_sized_range) + return sized_range_view_t{ printed, begin(r), size(r) }; + else + return range_view_t{ printed, begin(r), end(r) }; + } + else + { + if constexpr (is_contiguous_range) + return range_view_t{ printed, to_address(begin(r)), to_address(end(r)) }; + else + return range_view_t{ printed, begin(r), end(r) }; + } +} + +template <::std::ranges::range rg, ::fast_io::constructible_to_os_c_str T> +inline constexpr auto rgvw(rg&& r, T&& sep) +{ + using ::std::to_address; + using ::std::ranges::begin; + using ::std::ranges::end; + using ::std::ranges::size; + using ::fast_io::sized_range_view_t; + using ::fast_io::range_view_t; + using value_type = decltype(io_print_alias(*begin(r))); + constexpr bool is_contiguous_range = ::std::ranges::contiguous_range; + constexpr bool is_sized_range = ::std::ranges::sized_range; + decltype(auto) printed = print_alias_define(io_alias, sep); + using char_type = typename decltype(printed)::value_type; + if constexpr (::fast_io::reserve_printable) + { + if constexpr (is_contiguous_range && is_sized_range) + return sized_range_view_t{ printed, to_address(begin(r)), size(r) }; + else if constexpr (is_contiguous_range) + return sized_range_view_t{ printed, to_address(begin(r)), to_address(end(r)) - to_address(begin(r)) }; + else if constexpr (is_sized_range) + return sized_range_view_t{ printed, begin(r), size(r) }; + else + return range_view_t{ printed, begin(r), end(r) }; + } + else + { + if constexpr (is_contiguous_range) + return range_view_t{ printed, to_address(begin(r)), to_address(end(r)) }; + else + return range_view_t{ printed, begin(r), end(r) }; + } +} + +} +} diff --git a/src/fast_io/include/fast_io_core_impl/read_all.h b/src/fast_io/include/fast_io_core_impl/read_all.h new file mode 100644 index 0000000..7d29e0b --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/read_all.h @@ -0,0 +1,208 @@ +#pragma once + +namespace fast_io +{ +namespace details +{ + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline constexpr ::std::conditional_t read_all_impl_decay_cold(input in,typename input::char_type* first,typename input::char_type* last) +{ + while(first!=last) + { + auto it{read(in,first,last)}; + if(it==first)[[unlikely]] + { + if constexpr(throweh) + { + throw_parse_code(parse_code::end_of_file); + } + else + { + return false; + } + } + first=it; + } + if constexpr(!throweh) + { + return true; + } +} + +#if 0 +template +inline output_iter type_punning_copy(char_type const* first,char_type const* last,output_iter result) +{ + using value_type = ::std::iter_value_t; + if constexpr(sizeof(value_type)==0) + return result; + else if constexpr(sizeof(value_type)==sizeof(char_type)) + { + for(;first!=last;) + { + if constexpr(std::same_as) + *result=*first; + else + { + my_memcpy(__builtin_addressof(result),first,sizeof(value_type)); + } + ++first; + ++result; + } + return result; + } + else + { + static_assert(sizeof(char_type)==1); + for(;first!=last;) + { + my_memcpy(__builtin_addressof(result),first,sizeof(value_type)); + first+=sizeof(value_type); + ++result; + } + return result; + } +} + +template<::fast_io::input_stream input,std::forward_iterator Iter> +inline constexpr void read_all_impl_none_contiguous(input in,Iter first,Iter last) +{ + using char_type = typename input::char_type; + using iter_value_type = ::std::iter_value_t; + if constexpr(::fast_io::buffer_input_stream) + { + auto to_read{::std::distance(first,last)}; + for(;to_read;) + { + auto curr{ibuffer_curr(in)}; + auto ed{ibuffer_end(in)}; + auto remains{ed-curr}; + if constexpr(sizeof(char_type)==sizeof(iter_value_type)) + { + if(to_read(to_read)*sizeof(iter_value_type)}; + if(real_to_read=buffer_size) + { + + } + } + } +} +#endif +template<::fast_io::input_stream input> +inline constexpr void read_all_impl_decay(input in,typename input::char_type* first,typename input::char_type* last) +{ + std::ptrdiff_t diff{last-first}; + if constexpr(buffer_input_stream) + { + auto curr{ibuffer_curr(in)}; + auto end{ibuffer_end(in)}; + std::ptrdiff_t remain_space{end-curr}; + if(diff(diff),first); + curr+=diff; + ibuffer_set_curr(in,curr); + } + else + return read_all_impl_decay_cold(in,first,last); + } + else + { + return read_all_impl_decay_cold(in,first,last); + } +} + +template<::fast_io::input_stream input,std::input_or_output_iterator Iter> +requires std::same_as||std::same_as> +inline constexpr void read_all_impl(input in,Iter first,Iter last) +{ + using iter_char_type = ::std::iter_value_t; +#if 0 + using char_type = typename input::char_type; + if constexpr(::std::contiguous_iterator) + { + if constexpr(std::same_as) + { + read_all_impl_decay(in,::std::to_address(first),::std::to_address(last)); + } + else + { + read_all_impl_decay(in,reinterpret_cast(::std::to_address(first)),reinterpret_cast(::std::to_address(last))); + } + } + else + { + for(;first!=last;++first) + { + auto addr{__builtin_addressof(*first)}; + read_all_impl(in,addr,addr+1); + } + } +#else + static_assert(::std::contiguous_iterator); + if constexpr(std::same_as) + { + read_all_impl_decay(in,::std::to_address(first),::std::to_address(last)); + } + else + { + read_all_impl_decay(in,reinterpret_cast(::std::to_address(first)),reinterpret_cast(::std::to_address(last))); + } +#endif +} + +} + +template +inline constexpr void read_all(input&& in,Iter first,Iter last) +{ + ::fast_io::details::read_all_impl(io_ref(in),first,last); +} + +template +inline constexpr void read_all(input&& in,rg&& r) +{ + ::fast_io::details::read_all_impl(io_ref(in),::std::ranges::begin(r),::std::ranges::end(r)); +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/rwreflect/impl.h b/src/fast_io/include/fast_io_core_impl/rwreflect/impl.h new file mode 100644 index 0000000..8a81081 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/rwreflect/impl.h @@ -0,0 +1,4 @@ +#pragma once + +#include"reflectwrite.h" +#include"reflectread.h" diff --git a/src/fast_io/include/fast_io_core_impl/rwreflect/reflectread.h b/src/fast_io/include/fast_io_core_impl/rwreflect/reflectread.h new file mode 100644 index 0000000..d31eacb --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/rwreflect/reflectread.h @@ -0,0 +1,691 @@ +#pragma once + +namespace fast_io +{ + +namespace details +{ + +namespace streamreflect +{ + +template +concept has_ibuffer_basic_ops = requires(T instm,typename T::char_type *ptr) +{ + ibuffer_begin(instm); + ibuffer_curr(instm); + ibuffer_end(instm); + ibuffer_set_curr(instm,ptr); +}; + +template +concept has_ibuffer_all_ops = has_ibuffer_basic_ops&&(requires(T instm,typename T::char_type *cptr) +{ + ibuffer_read_all_underflow_define(instm,cptr,cptr); +}); + +template +concept has_ibuffer_some_ops = has_ibuffer_basic_ops&&(requires(T instm,typename T::char_type *cptr) +{ + ibuffer_read_all_underflow_define(instm,cptr,cptr); +}); + +template +concept has_ibuffer_ops = has_ibuffer_all_ops||has_ibuffer_some_ops; + +template +concept has_read_some_define = requires(T instm,typename T::char_type* ptr) +{ + read_some_define(instm,ptr,ptr); +}; + +template +concept has_read_all_define = requires(T instm,typename T::char_type* ptr) +{ + read_all_define(instm,ptr,ptr); +}; + +template +concept has_read_some_bytes_define = requires(T instm,::std::byte* ptr) +{ + read_some_bytes_define(instm,ptr,ptr); +}; + +template +concept has_read_all_bytes_define = requires(T instm,::std::byte* ptr) +{ + read_all_bytes_define(instm,ptr,ptr); +}; + +template +concept has_scatter_read_some_bytes_define = requires(T instm,::fast_io::io_scatter_t *scatter,::std::size_t len) +{ + scatter_read_some_bytes_define(instm,scatter,len); +}; + +template +concept has_scatter_read_all_bytes_define = requires(T instm,::fast_io::io_scatter_t *scatter,::std::size_t len) +{ + scatter_read_all_bytes_define(instm,scatter,len); +}; + + +template +concept has_scatter_read_some_define = requires(T instm,::fast_io::basic_io_scatter_t *pscatter,::std::size_t len) +{ + scatter_read_some_define(instm,pscatter,len); +}; + +template +concept has_scatter_read_all_define = requires(T instm,::fast_io::basic_io_scatter_t *pscatter,::std::size_t len) +{ + scatter_read_all_define(instm,pscatter,len); +}; + +} + +template +inline constexpr ::std::byte* read_some_common_chtypeptr_impl(F instm, + ::std::byte* firstbyteptr,::std::byte* lastbyteptr,::std::size_t n) +{ + auto it{firstbyteptr}; + while((it=read_some_bytes_define(instm, + it,lastbyteptr))!=lastbyteptr) + { + ::std::size_t diff{static_cast<::std::size_t>(it-firstbyteptr)}; + if(!(diff%n)) + { + break; + } + } + return it; +} + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline constexpr value_type* read_ibf_some_underflow_impl(F instm,value_type* first,value_type* last) +{ + if constexpr(::fast_io::details::streamreflect::has_ibuffer_some_ops) + { + return ibuffer_read_some_underflow_define(instm,first,last); + } + else + { + ibuffer_read_all_underflow_define(instm,first,last); + return last; + } +} + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline constexpr void read_ibf_all_underflow_impl(F instm,value_type* first,value_type* last) +{ + if constexpr(::fast_io::details::streamreflect::has_ibuffer_all_ops) + { + ibuffer_read_all_underflow_define(instm,first,last); + } + else + { + while((first=ibuffer_read_some_underflow_define(instm,first,last))!=last); + } +} + +template +inline constexpr value_type* read_some_common_chtypeptr_impl(F instm,value_type *first,value_type *last) +{ + using char_type = typename F::char_type; + constexpr bool smtp{::std::same_as}; + if constexpr(smtp&&(::fast_io::details::streamreflect::has_ibuffer_ops)) + { + char_type *curr{ibuffer_curr(instm)}; + char_type *ed{ibuffer_end(instm)}; + auto bufferremain{ed-curr}; + auto itdf{last-first}; + if(itdf(itdf),first); + ibuffer_set_curr(instm,curr+itdf); + return last; + } + return ::fast_io::details::read_ibf_all_underflow_impl(instm,first,last); + } + else if constexpr(smtp&&(::fast_io::details::streamreflect::has_read_some_define)) + { + return read_some_define(instm,first,last); + } + else if constexpr(smtp&&(::fast_io::details::streamreflect::has_scatter_read_some_define)) + { + basic_io_scatter_t scatter + { + first, + static_cast<::std::size_t>(last-first) + }; + auto ret{scatter_read_some_define(instm,__builtin_addressof(scatter),1)}; + return ret.total_size+first; + } + else if constexpr(smtp&&(::fast_io::details::streamreflect::has_read_all_define)) + { + read_all_define(instm,first,last); + return last; + } + else if constexpr(smtp&&(::fast_io::details::streamreflect::has_scatter_read_all_define)) + { + basic_io_scatter_t scatter + { + first, + static_cast<::std::size_t>(last-first) + }; + auto ret{scatter_read_all_define(instm,__builtin_addressof(scatter),1)}; + return last; + } + else if constexpr(::fast_io::details::streamreflect::has_read_some_bytes_define) + { + ::std::byte *firstbyteptr{reinterpret_cast<::std::byte*>(first)}; + ::std::byte *lastbyteptr{reinterpret_cast<::std::byte*>(last)}; + if constexpr(sizeof(char_type)==sizeof(::std::byte)) + { + auto p{read_some_bytes_define(instm, + firstbyteptr, + lastbyteptr)}; + return p-firstbyteptr+first; + } + else + { + auto it{firstbyteptr}; + ::std::size_t n{}; + do + { + it=::fast_io::details::read_some_common_chtypeptr_impl( + instm,it,lastbyteptr,sizeof(value_type)); + n=static_cast<::std::size_t>(it-firstbyteptr); + if(n%sizeof(value_type)==0) + { + break; + } + } + while(it!=lastbyteptr); + ::std::size_t const diff{n/sizeof(value_type)}; + + auto retv{first+diff}; +#if __has_cpp_attribute(assume) + [[assume(reinterpret_cast<::std::byte*>(retv)==it)]]; +#endif + return retv; + } + } + else if constexpr(::fast_io::details::streamreflect::has_read_all_bytes_define) + { + ::std::byte *firstbyteptr{reinterpret_cast<::std::byte*>(first)}; + ::std::byte *lastbyteptr{reinterpret_cast<::std::byte*>(last)}; + read_all_bytes_define(instm,firstbyteptr,lastbyteptr); + return last; + } + else + { + return first; + } +} + +template +inline constexpr Iter read_some_common_iter_impl(outputtype instm,Iter first,Iter last) +{ + using char_type = typename outputtype::char_type; + using value_type = ::std::iter_value_t; + if constexpr(::std::contiguous_iterator) + { + return ::fast_io::details::read_some_common_chtypeptr_impl( + instm, + ::std::to_address(first), + ::std::to_address(last))-::std::to_address(first)+first; + } + else + { + for(;first!=last;++first) + { + auto fptr{__builtin_addressof(*first)}; + auto fptrp1{fptr+1}; + if(::fast_io::details::read_some_common_chtypeptr_impl( + instm,fptr,fptrp1)!=fptrp1) + { + break; + } + } + return first; + } +} + + +template +inline constexpr void read_all_bytes_common_chtypeptr_impl(F instm,::std::byte* firstbyteptr,::std::byte* lastbyteptr) +{ + while((firstbyteptr=read_some_bytes_define(instm, + firstbyteptr, + lastbyteptr))!=lastbyteptr); +} + +template +inline constexpr void read_all_common_chtypeptr_impl(F instm,value_type* first,value_type* last) +{ + using char_type = typename F::char_type; + constexpr bool smtp{::std::same_as}; + if constexpr(smtp&&(::fast_io::details::streamreflect::has_ibuffer_ops)) + { + char_type *curr{ibuffer_curr(instm)}; + char_type *ed{ibuffer_end(instm)}; + auto bufferremain{ed-curr}; + auto itdf{last-first}; + if(itdf(itdf),first); + ibuffer_set_curr(instm,curr+itdf); + } + ::fast_io::details::read_ibf_all_underflow_impl(instm,first,last); + } + else if constexpr(smtp&&(::fast_io::details::streamreflect::has_read_all_define)) + { + read_all_define(instm,first,last); + } + else if constexpr(smtp&&(::fast_io::details::streamreflect::has_scatter_read_all_define)) + { + basic_io_scatter_t scatter + { + first, + static_cast<::std::size_t>(last-first) + }; + scatter_read_all_define(instm,__builtin_addressof(scatter),1); + } + else if constexpr(smtp&&(::fast_io::details::streamreflect::has_read_some_define)) + { + while((first=read_some_define(instm,first,last))!=last); + } + else if constexpr(smtp&&(::fast_io::details::streamreflect::has_scatter_read_some_define)) + { + do + { + basic_io_scatter_t scatter + { + first, + static_cast<::std::size_t>(last-first) + }; + auto ret{scatter_read_some_define(instm,__builtin_addressof(scatter),1)}; + first+=ret.total_size; + } + while(first!=last); + } + else if constexpr(::fast_io::details::streamreflect::has_read_all_bytes_define) + { + ::std::byte *firstbyteptr{reinterpret_cast<::std::byte*>(first)}; + ::std::byte *lastbyteptr{reinterpret_cast<::std::byte*>(last)}; + read_all_bytes_define(instm,firstbyteptr,lastbyteptr); + } + else if constexpr(::fast_io::details::streamreflect::has_read_some_bytes_define) + { + ::std::byte *firstbyteptr{reinterpret_cast<::std::byte*>(first)}; + ::std::byte *lastbyteptr{reinterpret_cast<::std::byte*>(last)}; + read_all_bytes_common_chtypeptr_impl(instm,firstbyteptr,lastbyteptr); + } +} + +template +inline constexpr void read_all_common_iter_impl(outputtype instm,Iter first,Iter last) +{ + using char_type = typename outputtype::char_type; + using value_type = ::std::iter_value_t; + if constexpr(::std::contiguous_iterator) + { + ::fast_io::details::read_all_common_chtypeptr_impl( + instm,::std::to_address(first),::std::to_address(last)); + } + else + { + for(;first!=last;++first) + { + auto fptr{__builtin_addressof(*first)}; + auto fptrp1{fptr+1}; + ::fast_io::details::read_all_common_chtypeptr_impl( + instm,fptr,fptrp1); + } + return first; + } +} + +template +inline constexpr io_scatter_status_t scatter_read_some_bytes_impl(F instm,io_scatter_t *base,::std::size_t len) +{ + using char_type = typename F::char_type; + if constexpr(::fast_io::details::streamreflect::has_scatter_read_some_bytes_define) + { + return scatter_read_some_bytes_define(instm,base,len); + } + else if constexpr(::fast_io::details::streamreflect::has_scatter_read_all_bytes_define) + { + scatter_read_all_bytes_define(instm,base,len); + return {scatter_total_size(base,len),len,0}; + } + else if constexpr(::fast_io::details::streamreflect::has_read_some_bytes_define) + { + ::std::size_t readedn{}; + auto i{base}; + ::std::size_t posinsp{}; + for(auto ed{base+len};i!=ed;++i) + { + auto ele{*i}; + auto basebg{reinterpret_cast<::std::byte*>(const_cast(ele.base))}; + auto baseed{basebg+ele.len}; + auto ret{read_some_bytes_define(instm, + basebg, + baseed)}; + ::std::size_t diff{static_cast<::std::size_t>(ret-basebg)}; + readedn+=diff; + if(ret!=baseed) + { + posinsp=diff; + break; + } + } + return {readedn,static_cast<::std::size_t>(i-base),posinsp}; + } + else if constexpr(::fast_io::details::streamreflect::has_read_all_bytes_define) + { + ::std::size_t readedn{}; + auto i{base}; + for(auto ed{base+len};i!=ed;++i) + { + auto ele{*i}; + auto basebg{reinterpret_cast<::std::byte*>(const_cast(ele.base))}; + auto baseed{basebg+ele.len}; + read_all_bytes_define(instm,basebg,baseed); + ::std::size_t diff{static_cast<::std::size_t>(baseed-basebg)}; + readedn+=diff; + } + return {readedn,len,0}; + } +} + +template +inline constexpr void scatter_read_all_bytes_impl(F instm,io_scatter_t const *base,::std::size_t len) +{ + using char_type = typename F::char_type; + if constexpr(::fast_io::details::streamreflect::has_scatter_read_all_bytes_define) + { + scatter_read_all_bytes_define(instm,base,len); + } + else if constexpr(::fast_io::details::streamreflect::has_scatter_read_some_bytes_define) + { + while(len) + { + auto ret{scatter_read_some_bytes_define(instm,base,len)}; + ::std::size_t position{ret.position}; + ::std::size_t position_in_scatter{ret.position_in_scatter}; + if(position==len) +#if __has_cpp_attribute(likely) + [[likely]] +#endif + { + return; + } + base+=position; + len-=position; + if(!position_in_scatter) + { + continue; + } + auto b{reinterpret_cast<::std::byte*>(const_cast(base->base))}; + ::fast_io::details::read_all_common_chtypeptr_impl(instm, + b+position_in_scatter,b+base->len); + ++base; + --len; + } + } + else if constexpr(::fast_io::details::streamreflect::has_read_some_bytes_define + ||::fast_io::details::streamreflect::has_read_all_bytes_define) + { + for(auto i{base},ed{base+len};i!=ed;++i) + { + auto ele{*i}; + auto basebg{reinterpret_cast<::std::byte*>(const_cast(ele.base))}; + auto baseed{basebg+ele.len}; + ::fast_io::details::read_all_common_chtypeptr_impl(instm,basebg,baseed); + } + } +} + +template +inline constexpr io_scatter_status_t scatter_read_some_impl(F instm,basic_io_scatter_t const *base,::std::size_t len) +{ + using char_type = typename F::char_type; + if constexpr(::fast_io::details::streamreflect::has_scatter_read_some_define) + { + return scatter_read_some_define(instm,base,len); + } + else if constexpr(::fast_io::details::streamreflect::has_scatter_read_all_define) + { + scatter_read_all_define(instm,base,len); + return {scatter_total_size(base,len),len,0}; + } + else if constexpr(sizeof(char_type)==sizeof(::std::byte)) + { + using scatterbyteptr_constaliasptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + +#endif + = io_scatter_t *; + return ::fast_io::details::scatter_read_some_bytes_impl(instm, + reinterpret_cast(base),len); + } + else if constexpr(::fast_io::details::streamreflect::has_read_some_define) + { + ::std::size_t readedn{}; + auto i{base}; + ::std::size_t posinsp{}; + for(auto ed{base+len};i!=ed;++i) + { + auto ele{*i}; + auto basebg{ele.base}; + auto baseed{basebg+ele.len}; + auto ret{read_some_define(instm,basebg,baseed)}; + ::std::size_t diff{static_cast<::std::size_t>(ret-basebg)}; + readedn+=diff; + if(ret!=baseed) + { + posinsp=diff; + break; + } + } + return {readedn,static_cast<::std::size_t>(i-base),posinsp}; + } + else if constexpr(::fast_io::details::streamreflect::has_read_all_define) + { + ::std::size_t readedn{}; + auto i{base}; + for(auto ed{base+len};i!=ed;++i) + { + auto ele{*i}; + auto basebg{ele.base}; + auto baseed{basebg+ele.len}; + read_all_define(instm,basebg,baseed); + ::std::size_t diff{static_cast<::std::size_t>(baseed-basebg)}; + readedn+=diff; + } + return {readedn,len,0}; + } + else if constexpr(::fast_io::details::streamreflect::has_read_some_bytes_define) + { + ::std::size_t readedn{}; + auto i{base}; + ::std::size_t posinsp{}; + for(auto ed{base+len};i!=ed;++i) + { + auto ele{*i}; + auto basebg{ele.base}; + auto baseed{basebg+ele.len}; + auto ret{::fast_io::details::read_some_common_chtypeptr_impl(instm,basebg,baseed)}; + ::std::size_t diff{static_cast<::std::size_t>(ret-basebg)}; + readedn+=diff; + if(ret!=baseed) + { + posinsp=diff; + break; + } + } + return {readedn,static_cast<::std::size_t>(i-base),posinsp}; + } + else if constexpr(::fast_io::details::streamreflect::has_read_all_define) + { + ::std::size_t readedn{}; + auto i{base}; + for(auto ed{base+len};i!=ed;++i) + { + auto ele{*i}; + auto basebg{ele.base}; + auto baseed{basebg+ele.len}; + read_all_define(instm,basebg,baseed); + ::std::size_t diff{static_cast<::std::size_t>(baseed-basebg)}; + readedn+=diff; + } + return {readedn,len,0}; + } +} + +template +inline constexpr void scatter_read_all_impl(F instm,basic_io_scatter_t const *base,::std::size_t len) +{ + using char_type = typename F::char_type; + if constexpr(::fast_io::details::streamreflect::has_scatter_read_all_define) + { + scatter_read_all_define(instm,base,len); + } + else if constexpr(::fast_io::details::streamreflect::has_scatter_read_some_define) + { + while(len) + { + auto ret{scatter_read_define(instm,base,len)}; + ::std::size_t position{ret.position}; + ::std::size_t position_in_scatter{ret.position_in_scatter}; + if(position==len) +#if __has_cpp_attribute(likely) + [[likely]] +#endif + { + return; + } + base+=position; + len-=position; + if(!position_in_scatter) + { + continue; + } + auto b{base->base}; + ::fast_io::details::read_all_common_chtypeptr_impl(instm, + b+position_in_scatter,b+base->len); + ++base; + --len; + } + } + else if constexpr(sizeof(char_type)==sizeof(::std::byte)) + { + using scatterbyteptr_constaliasptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + +#endif + = io_scatter_t *; + ::fast_io::details::scatter_read_all_bytes_impl(instm, + reinterpret_cast(base), + len); + } + else if constexpr(::fast_io::details::streamreflect::has_read_all_define|| + ::fast_io::details::streamreflect::has_read_some_define) + { + for(auto i{base},e{base+len};i!=e;++i) + { + auto [bibs,bilen]{*i}; + ::fast_io::details::read_all_common_chtypeptr_impl(instm, + bibs,bibs+bilen); + } + } +} + +} + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr Iter reads_some(F&& foo,Iter first, Iter last) +{ + return ::fast_io::details::read_some_common_iter_impl(io_ref(foo),first,last); +} + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr void reads_all(F&& foo,Iter first,Iter last) +{ + ::fast_io::details::read_all_common_iter_impl(io_ref(foo),first,last); +} + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr io_scatter_status_t scatter_read_some_bytes(F&& foo, + io_scatter_t const* pscatter,::std::size_t len) +{ + return ::fast_io::details::scatter_read_some_bytes_impl(io_ref(foo),pscatter,len); +} + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr void scatter_read_all_bytes(F&& foo, + io_scatter_t const* pscatter,::std::size_t len) +{ + ::fast_io::details::scatter_read_all_bytes_impl(io_ref(foo),pscatter,len); +} + + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr io_scatter_status_t scatter_read_some(F&& foo, + io_scatter_t const* pscatter,::std::size_t len) +{ + return ::fast_io::details::scatter_read_some_impl(io_ref(foo),pscatter,len); +} + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr void scatter_read_all(F&& foo, + basic_io_scatter_t const* pscatter,::std::size_t len) +{ + return ::fast_io::details::scatter_read_all_impl(io_ref(foo),pscatter,len); +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/rwreflect/reflectwrite.h b/src/fast_io/include/fast_io_core_impl/rwreflect/reflectwrite.h new file mode 100644 index 0000000..463f6ed --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/rwreflect/reflectwrite.h @@ -0,0 +1,713 @@ +#pragma once + +namespace fast_io +{ + +inline constexpr io_scatter_status_t scatter_size_to_status(std::size_t sz,io_scatter_t const *base,::std::size_t len) noexcept +{ + std::size_t total{sz}; + for(std::size_t i{};i!=len;++i) + { + ::std::size_t blen{base[i].len}; + if(total +inline constexpr ::std::size_t scatter_total_size(basic_io_scatter_t const *base,::std::size_t len) noexcept +{ + std::size_t total{}; + for(auto i{base},e{base+len};i!=e;++i) + { + total+=i->len; + } + return total; +} + +namespace details +{ + +namespace streamreflect +{ + +template +concept has_obuffer_basic_ops = requires(T outstm,typename T::char_type *ptr) +{ + obuffer_begin(outstm); + obuffer_curr(outstm); + obuffer_end(outstm); + obuffer_set_curr(outstm,ptr); +}; + +template +concept has_obuffer_all_ops = has_obuffer_basic_ops&&(requires(T outstm,typename T::char_type const *cptr) +{ + obuffer_write_all_overflow_define(outstm,cptr,cptr); +}); + +template +concept has_obuffer_some_ops = has_obuffer_basic_ops&&(requires(T outstm,typename T::char_type const *cptr) +{ + obuffer_write_some_overflow_define(outstm,cptr,cptr); +}); + +template +concept has_obuffer_ops = has_obuffer_all_ops||has_obuffer_some_ops; + +template +concept has_write_some_define = requires(T outstm,typename T::char_type const* ptr) +{ + write_some_define(outstm,ptr,ptr); +}; + +template +concept has_write_all_define = requires(T outstm,typename T::char_type const* ptr) +{ + write_all_define(outstm,ptr,ptr); +}; + +template +concept has_write_some_bytes_define = requires(T outstm,::std::byte const* ptr) +{ + write_some_bytes_define(outstm,ptr,ptr); +}; + +template +concept has_write_all_bytes_define = requires(T outstm,::std::byte const* ptr) +{ + write_all_bytes_define(outstm,ptr,ptr); +}; + +template +concept has_scatter_write_some_bytes_define = requires(T outstm,::fast_io::io_scatter_t const *scatter,::std::size_t len) +{ + scatter_write_some_bytes_define(outstm,scatter,len); +}; + +template +concept has_scatter_write_all_bytes_define = requires(T outstm,::fast_io::io_scatter_t const *scatter,::std::size_t len) +{ + scatter_write_all_bytes_define(outstm,scatter,len); +}; + + +template +concept has_scatter_write_some_define = requires(T outstm,::fast_io::basic_io_scatter_t const *pscatter,::std::size_t len) +{ + scatter_write_some_define(outstm,pscatter,len); +}; + +template +concept has_scatter_write_all_define = requires(T outstm,::fast_io::basic_io_scatter_t const *pscatter,::std::size_t len) +{ + scatter_write_all_define(outstm,pscatter,len); +}; + +} + +template +inline constexpr ::std::byte const* write_some_common_chtypeptr_impl(F outstm, + ::std::byte const* firstbyteptr,::std::byte const* lastbyteptr,::std::size_t n) +{ + auto it{firstbyteptr}; + while((it=write_some_bytes_define(outstm, + it,lastbyteptr))!=lastbyteptr) + { + ::std::size_t diff{static_cast<::std::size_t>(it-firstbyteptr)}; + if(!(diff%n)) + { + break; + } + } + return it; +} + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline constexpr value_type const* write_obf_some_overflow_impl(F outstm,value_type const* first,value_type const* last) +{ + if constexpr(::fast_io::details::streamreflect::has_obuffer_some_ops) + { + return obuffer_write_some_overflow_define(outstm,first,last); + } + else + { + obuffer_write_all_overflow_define(outstm,first,last); + return last; + } +} + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline constexpr void write_obf_all_overflow_impl(F outstm,value_type const* first,value_type const* last) +{ + if constexpr(::fast_io::details::streamreflect::has_obuffer_all_ops) + { + obuffer_write_all_overflow_define(outstm,first,last); + } + else + { + while((first=obuffer_write_some_overflow_define(outstm,first,last))!=last); + } +} + +template +inline constexpr value_type const* write_some_common_chtypeptr_impl(F outstm,value_type const* first,value_type const* last) +{ + using char_type = typename F::char_type; + constexpr bool smtp{::std::same_as}; + if constexpr(smtp&&(::fast_io::details::streamreflect::has_obuffer_ops)) + { + char_type *curr{obuffer_curr(outstm)}; + char_type *ed{obuffer_end(outstm)}; + auto bufferremain{ed-curr}; + auto itdf{last-first}; + if(itdf(itdf),curr)); + return last; + } + return ::fast_io::details::write_obf_some_overflow_impl(outstm,first,last); + } + else if constexpr(smtp&&(::fast_io::details::streamreflect::has_write_some_define)) + { + return write_some_define(outstm,first,last); + } + else if constexpr(smtp&&(::fast_io::details::streamreflect::has_scatter_write_some_define)) + { + basic_io_scatter_t scatter + { + first, + static_cast<::std::size_t>(last-first) + }; + auto ret{scatter_write_some_define(outstm,__builtin_addressof(scatter),1)}; + return ret.total_size+first; + } + else if constexpr(smtp&&(::fast_io::details::streamreflect::has_write_all_define)) + { + write_all_define(outstm,first,last); + return last; + } + else if constexpr(smtp&&(::fast_io::details::streamreflect::has_scatter_write_all_define)) + { + basic_io_scatter_t scatter + { + first, + static_cast<::std::size_t>(last-first) + }; + auto ret{scatter_write_all_define(outstm,__builtin_addressof(scatter),1)}; + return last; + } + else if constexpr(::fast_io::details::streamreflect::has_write_some_bytes_define) + { + ::std::byte const *firstbyteptr{reinterpret_cast<::std::byte const*>(first)}; + ::std::byte const *lastbyteptr{reinterpret_cast<::std::byte const*>(last)}; + if constexpr(sizeof(char_type)==sizeof(::std::byte)) + { + auto p{write_some_bytes_define(outstm, + firstbyteptr, + lastbyteptr)}; + return p-firstbyteptr+first; + } + else + { + auto it{firstbyteptr}; + ::std::size_t n{}; + do + { + it=::fast_io::details::write_some_common_chtypeptr_impl( + outstm,it,lastbyteptr,sizeof(value_type)); + n=static_cast<::std::size_t>(it-firstbyteptr); + if(n%sizeof(value_type)==0) + { + break; + } + } + while(it!=lastbyteptr); + ::std::size_t const diff{n/sizeof(value_type)}; + + auto retv{first+diff}; +#if __has_cpp_attribute(assume) + [[assume(reinterpret_cast<::std::byte const*>(retv)==it)]]; +#endif + return retv; + } + } + else if constexpr(::fast_io::details::streamreflect::has_write_all_bytes_define) + { + ::std::byte const *firstbyteptr{reinterpret_cast<::std::byte const*>(first)}; + ::std::byte const *lastbyteptr{reinterpret_cast<::std::byte const*>(last)}; + write_all_bytes_define(outstm,firstbyteptr,lastbyteptr); + return last; + } + else + { + return first; + } +} + +template +inline constexpr Iter write_some_common_iter_impl(outputtype outstm,Iter first,Iter last) +{ + using char_type = typename outputtype::char_type; + using value_type = ::std::iter_value_t; + if constexpr(::std::contiguous_iterator) + { + return ::fast_io::details::write_some_common_chtypeptr_impl( + outstm, + ::std::to_address(first), + ::std::to_address(last))-::std::to_address(first)+first; + } + else + { + for(;first!=last;++first) + { + auto fptr{__builtin_addressof(*first)}; + auto fptrp1{fptr+1}; + if(::fast_io::details::write_some_common_chtypeptr_impl( + outstm,fptr,fptrp1)!=fptrp1) + { + break; + } + } + return first; + } +} + + +template +inline constexpr void write_all_bytes_common_chtypeptr_impl(F outstm,::std::byte const* firstbyteptr,::std::byte const* lastbyteptr) +{ + while((firstbyteptr=write_some_bytes_define(outstm, + firstbyteptr, + lastbyteptr))!=lastbyteptr); +} + +template +inline constexpr void write_all_common_chtypeptr_impl(F outstm,value_type const* first,value_type const* last) +{ + using char_type = typename F::char_type; + constexpr bool smtp{::std::same_as}; + if constexpr(smtp&&(::fast_io::details::streamreflect::has_obuffer_ops)) + { + char_type *curr{obuffer_curr(outstm)}; + char_type *ed{obuffer_end(outstm)}; + auto bufferremain{ed-curr}; + auto itdf{last-first}; + if(itdf(itdf),curr)); + } + ::fast_io::details::write_obf_all_overflow_impl(outstm,first,last); + } + else if constexpr(smtp&&(::fast_io::details::streamreflect::has_write_all_define)) + { + write_all_define(outstm,first,last); + } + else if constexpr(smtp&&(::fast_io::details::streamreflect::has_scatter_write_all_define)) + { + basic_io_scatter_t scatter + { + first, + static_cast<::std::size_t>(last-first) + }; + scatter_write_all_define(outstm,__builtin_addressof(scatter),1); + } + else if constexpr(smtp&&(::fast_io::details::streamreflect::has_write_some_define)) + { + while((first=write_some_define(outstm,first,last))!=last); + } + else if constexpr(smtp&&(::fast_io::details::streamreflect::has_scatter_write_some_define)) + { + do + { + basic_io_scatter_t scatter + { + first, + static_cast<::std::size_t>(last-first) + }; + auto ret{scatter_write_some_define(outstm,__builtin_addressof(scatter),1)}; + first+=ret.total_size; + } + while(first!=last); + } + else if constexpr(::fast_io::details::streamreflect::has_write_all_bytes_define) + { + ::std::byte const *firstbyteptr{reinterpret_cast<::std::byte const*>(first)}; + ::std::byte const *lastbyteptr{reinterpret_cast<::std::byte const*>(last)}; + write_all_bytes_define(outstm,firstbyteptr,lastbyteptr); + } + else if constexpr(::fast_io::details::streamreflect::has_write_some_bytes_define) + { + ::std::byte const *firstbyteptr{reinterpret_cast<::std::byte const*>(first)}; + ::std::byte const *lastbyteptr{reinterpret_cast<::std::byte const*>(last)}; + write_all_bytes_common_chtypeptr_impl(outstm,firstbyteptr,lastbyteptr); + } +} + +template +inline constexpr void write_all_common_iter_impl(outputtype outstm,Iter first,Iter last) +{ + using char_type = typename outputtype::char_type; + using value_type = ::std::iter_value_t; + if constexpr(::std::contiguous_iterator) + { + ::fast_io::details::write_all_common_chtypeptr_impl( + outstm,::std::to_address(first),::std::to_address(last)); + } + else + { + for(;first!=last;++first) + { + auto fptr{__builtin_addressof(*first)}; + auto fptrp1{fptr+1}; + ::fast_io::details::write_all_common_chtypeptr_impl( + outstm,fptr,fptrp1); + } + return first; + } +} + +template +inline constexpr io_scatter_status_t scatter_write_some_bytes_impl(F outstm,io_scatter_t const *base,::std::size_t len) +{ + using char_type = typename F::char_type; + if constexpr(::fast_io::details::streamreflect::has_scatter_write_some_bytes_define) + { + return scatter_write_some_bytes_define(outstm,base,len); + } + else if constexpr(::fast_io::details::streamreflect::has_scatter_write_all_bytes_define) + { + scatter_write_all_bytes_define(outstm,base,len); + return {scatter_total_size(base,len),len,0}; + } + else if constexpr(::fast_io::details::streamreflect::has_write_some_bytes_define) + { + ::std::size_t written{}; + auto i{base}; + ::std::size_t posinsp{}; + for(auto ed{base+len};i!=ed;++i) + { + auto ele{*i}; + auto basebg{reinterpret_cast<::std::byte const*>(ele.base)}; + auto baseed{basebg+ele.len}; + auto ret{write_some_bytes_define(outstm, + reinterpret_cast<::std::byte const*>(basebg), + reinterpret_cast<::std::byte const*>(baseed))}; + ::std::size_t diff{static_cast<::std::size_t>(ret-basebg)}; + written+=diff; + if(ret!=baseed) + { + posinsp=diff; + break; + } + } + return {written,static_cast<::std::size_t>(i-base),posinsp}; + } + else if constexpr(::fast_io::details::streamreflect::has_write_all_bytes_define) + { + ::std::size_t written{}; + auto i{base}; + for(auto ed{base+len};i!=ed;++i) + { + auto ele{*i}; + auto basebg{reinterpret_cast<::std::byte const*>(ele.base)}; + auto baseed{basebg+ele.len}; + write_all_bytes_define(outstm,basebg,baseed); + ::std::size_t diff{static_cast<::std::size_t>(baseed-basebg)}; + written+=diff; + } + return {written,len,0}; + } +} + +template +inline constexpr void scatter_write_all_bytes_impl(F outstm,io_scatter_t const *base,::std::size_t len) +{ + using char_type = typename F::char_type; + if constexpr(::fast_io::details::streamreflect::has_scatter_write_all_bytes_define) + { + scatter_write_all_bytes_define(outstm,base,len); + } + else if constexpr(::fast_io::details::streamreflect::has_scatter_write_some_bytes_define) + { + while(len) + { + auto ret{scatter_write_some_bytes_define(outstm,base,len)}; + ::std::size_t position{ret.position}; + ::std::size_t position_in_scatter{ret.position_in_scatter}; + if(position==len) +#if __has_cpp_attribute(likely) + [[likely]] +#endif + { + return; + } + base+=position; + len-=position; + if(!position_in_scatter) + { + continue; + } + auto b{reinterpret_cast<::std::byte const*>(base->base)}; + ::fast_io::details::write_all_common_chtypeptr_impl(outstm, + b+position_in_scatter,b+base->len); + ++base; + --len; + } + } + else if constexpr(::fast_io::details::streamreflect::has_write_some_bytes_define + ||::fast_io::details::streamreflect::has_write_all_bytes_define) + { + for(auto i{base},ed{base+len};i!=ed;++i) + { + auto ele{*i}; + auto basebg{reinterpret_cast<::std::byte const*>(ele.base)}; + auto baseed{basebg+ele.len}; + ::fast_io::details::write_all_common_chtypeptr_impl(outstm,basebg,baseed); + } + } +} + +template +inline constexpr io_scatter_status_t scatter_write_some_impl(F outstm,basic_io_scatter_t const *base,::std::size_t len) +{ + using char_type = typename F::char_type; + if constexpr(::fast_io::details::streamreflect::has_scatter_write_some_define) + { + return scatter_write_some_define(outstm,base,len); + } + else if constexpr(::fast_io::details::streamreflect::has_scatter_write_all_define) + { + scatter_write_all_define(outstm,base,len); + return {scatter_total_size(base,len),len,0}; + } + else if constexpr(sizeof(char_type)==sizeof(::std::byte)) + { + using scatterbyteptr_constaliasptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + +#endif + = io_scatter_t const *; + return ::fast_io::details::scatter_write_some_bytes_impl(outstm, + reinterpret_cast(base),len); + } + else if constexpr(::fast_io::details::streamreflect::has_write_some_define) + { + ::std::size_t written{}; + auto i{base}; + ::std::size_t posinsp{}; + for(auto ed{base+len};i!=ed;++i) + { + auto ele{*i}; + auto basebg{ele.base}; + auto baseed{basebg+ele.len}; + auto ret{write_some_define(outstm,basebg,baseed)}; + ::std::size_t diff{static_cast<::std::size_t>(ret-basebg)}; + written+=diff; + if(ret!=baseed) + { + posinsp=diff; + break; + } + } + return {written,static_cast<::std::size_t>(i-base),posinsp}; + } + else if constexpr(::fast_io::details::streamreflect::has_write_all_define) + { + ::std::size_t written{}; + auto i{base}; + for(auto ed{base+len};i!=ed;++i) + { + auto ele{*i}; + auto basebg{ele.base}; + auto baseed{basebg+ele.len}; + write_all_define(outstm,basebg,baseed); + ::std::size_t diff{static_cast<::std::size_t>(baseed-basebg)}; + written+=diff; + } + return {written,len,0}; + } + else if constexpr(::fast_io::details::streamreflect::has_write_some_bytes_define) + { + ::std::size_t written{}; + auto i{base}; + ::std::size_t posinsp{}; + for(auto ed{base+len};i!=ed;++i) + { + auto ele{*i}; + auto basebg{ele.base}; + auto baseed{basebg+ele.len}; + auto ret{::fast_io::details::write_some_common_chtypeptr_impl(outstm,basebg,baseed)}; + ::std::size_t diff{static_cast<::std::size_t>(ret-basebg)}; + written+=diff; + if(ret!=baseed) + { + posinsp=diff; + break; + } + } + return {written,static_cast<::std::size_t>(i-base),posinsp}; + } + else if constexpr(::fast_io::details::streamreflect::has_write_all_define) + { + ::std::size_t written{}; + auto i{base}; + for(auto ed{base+len};i!=ed;++i) + { + auto ele{*i}; + auto basebg{ele.base}; + auto baseed{basebg+ele.len}; + write_all_define(outstm,basebg,baseed); + ::std::size_t diff{static_cast<::std::size_t>(baseed-basebg)}; + written+=diff; + } + return {written,len,0}; + } +} + +template +inline constexpr void scatter_write_all_impl(F outstm,basic_io_scatter_t const *base,::std::size_t len) +{ + using char_type = typename F::char_type; + if constexpr(::fast_io::details::streamreflect::has_scatter_write_all_define) + { + scatter_write_all_define(outstm,base,len); + } + else if constexpr(::fast_io::details::streamreflect::has_scatter_write_some_define) + { + while(len) + { + auto ret{scatter_write_define(outstm,base,len)}; + ::std::size_t position{ret.position}; + ::std::size_t position_in_scatter{ret.position_in_scatter}; + if(position==len) +#if __has_cpp_attribute(likely) + [[likely]] +#endif + { + return; + } + base+=position; + len-=position; + if(!position_in_scatter) + { + continue; + } + auto b{base->base}; + ::fast_io::details::write_all_common_chtypeptr_impl(outstm, + b+position_in_scatter,b+base->len); + ++base; + --len; + } + } + else if constexpr(sizeof(char_type)==sizeof(::std::byte)) + { + using scatterbyteptr_constaliasptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + +#endif + = io_scatter_t const *; + ::fast_io::details::scatter_write_all_bytes_impl(outstm, + reinterpret_cast(base), + len); + } + else if constexpr(::fast_io::details::streamreflect::has_write_all_define|| + ::fast_io::details::streamreflect::has_write_some_define) + { + for(auto i{base},e{base+len};i!=e;++i) + { + auto [bibs,bilen]{*i}; + ::fast_io::details::write_all_common_chtypeptr_impl(outstm, + bibs,bibs+bilen); + } + } +} + +} + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr Iter write_some(F&& foo,Iter first, Iter last) +{ + return ::fast_io::details::write_some_common_iter_impl(io_ref(foo),first,last); +} + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr void write_all(F&& foo,Iter first,Iter last) +{ + ::fast_io::details::write_all_common_iter_impl(io_ref(foo),first,last); +} + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr io_scatter_status_t scatter_write_some_bytes(F&& foo, + io_scatter_t const* pscatter,::std::size_t len) +{ + return ::fast_io::details::scatter_write_some_bytes_impl(io_ref(foo),pscatter,len); +} + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr void scatter_write_all_bytes(F&& foo, + io_scatter_t const* pscatter,::std::size_t len) +{ + ::fast_io::details::scatter_write_all_bytes_impl(io_ref(foo),pscatter,len); +} + + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr io_scatter_status_t scatter_write_some(F&& foo, + io_scatter_t const* pscatter,::std::size_t len) +{ + return ::fast_io::details::scatter_write_some_impl(io_ref(foo),pscatter,len); +} + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr void scatter_write_all(F&& foo, + basic_io_scatter_t const* pscatter,::std::size_t len) +{ + return ::fast_io::details::scatter_write_all_impl(io_ref(foo),pscatter,len); +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/scan_freestanding.h b/src/fast_io/include/fast_io_core_impl/scan_freestanding.h new file mode 100644 index 0000000..42c556b --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/scan_freestanding.h @@ -0,0 +1,479 @@ +#pragma once + +namespace fast_io +{ + +template +requires std::is_trivially_copyable_v +struct unget_temp_buffer +{ + using char_type = typename T::char_type; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif + T input; + typename T::char_type buffer; + char8_t pos{}; + char8_t pos_end{}; + constexpr unget_temp_buffer(T in):input(in){} + unget_temp_buffer(unget_temp_buffer const&)=delete; + unget_temp_buffer& operator=(unget_temp_buffer const&)=delete; +#ifdef __clang__ + constexpr ~unget_temp_buffer() + { + if constexpr(requires() + { + try_unget(input,buffer); + }) + { +#ifdef __cpp_exceptions + if constexpr(noexcept(try_unget(input,buffer))) + { + if(pos!=pos_end) + try_unget(input,buffer); + } + else + { + try + { + if(pos!=pos_end) + try_unget(input,buffer); + } + catch(...) + { + } + } +#else + if(pos!=pos_end) + try_unget(input,buffer); +#endif + } + } +#else + +#if __cpp_constexpr_dynamic_alloc >= 201907L + constexpr +#endif + ~unget_temp_buffer() requires requires() + { + try_unget(input,buffer); + } + { +#ifdef __cpp_exceptions + if constexpr(noexcept(try_unget(input,buffer))) + { + if(pos!=pos_end) + try_unget(input,buffer); + } + else + { + try + { + if(pos!=pos_end) + try_unget(input,buffer); + } + catch(...) + { + } + } +#else + if(pos!=pos_end) + try_unget(input,buffer); +#endif + } +#if __cpp_constexpr_dynamic_alloc >= 201907L + constexpr +#endif + ~unget_temp_buffer() = default; +#endif +}; + +template +inline constexpr Iter read(unget_temp_buffer& in,Iter begin, Iter end) +{ + if(begin==end) + return begin; + if(in.pos!=in.pos_end) + { + *begin=in.buffer; + ++begin; + } + if(begin!=end) + begin=read(in.input,begin,end); + in.pos=in.pos_end={}; + return begin; +} + +template +inline constexpr auto ibuffer_begin(unget_temp_buffer& in) noexcept +{ + return __builtin_addressof(in.buffer); +} + +template +inline constexpr auto ibuffer_curr(unget_temp_buffer& in) noexcept +{ + return __builtin_addressof(in.buffer)+in.pos; +} + +template +inline constexpr auto ibuffer_end(unget_temp_buffer& in) noexcept +{ + return __builtin_addressof(in.buffer)+in.pos_end; +} + +template +inline constexpr auto ibuffer_set_curr(unget_temp_buffer& in,typename T::char_type* ptr) noexcept +{ + in.pos=ptr-__builtin_addressof(in.buffer); +} + +template +inline constexpr bool ibuffer_underflow(unget_temp_buffer& in) +{ + if constexpr(try_get_input_stream) + { + auto ret{try_get(in.input)}; + in.buffer=ret.first; + in.pos={}; + in.pos_end=ret.second; + return ret.second; + } + else + { + bool not_eof{read(in.input,__builtin_addressof(in.buffer),__builtin_addressof(in.buffer)+1)!=__builtin_addressof(in.buffer)}; + in.pos={}; + in.pos_end=not_eof; + return not_eof; + } +} +namespace details +{ +#if 0 +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline constexpr bool scan_single_status_impl(input in,T& state_machine,P arg) +{ + for(;state_machine.code==parse_code::partial;) + { + if(!ibuffer_underflow(in)) + { + if(!state_machine.test_eof(arg)) + return false; + if(state_machine.code==parse_code{})[[likely]] + return true; + break; + } + auto curr{ibuffer_curr(in)}; + auto end{ibuffer_end(in)}; + state_machine(curr,end,arg); + ibuffer_set_curr(in, state_machine.iter); + if(state_machine.code==parse_code::ok)[[likely]] + return true; + } + throw_parse_code(state_machine.code); +} +#endif + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline constexpr bool scan_context_status_impl(input in,P arg) +{ + using char_type = typename input::char_type; + for(typename std::remove_cvref_t))>::type state;;) + { + auto curr{ibuffer_curr(in)}; + auto end{ibuffer_end(in)}; + auto [it,ec]=scan_context_define(io_reserve_type,state,curr,end,arg); + if constexpr(std::same_as) + { + ibuffer_set_curr(in,it); + } + else + { + ibuffer_set_curr(in,it-curr+curr); + } + if(ec==parse_code::ok) + { + return true; + } + else if(ec!=parse_code::partial) + throw_parse_code(ec); + if(!ibuffer_underflow(in))[[unlikely]] + { + ec=scan_context_eof_define(io_reserve_type,state,arg); + if(ec==parse_code::ok) + return true; + else if(ec==parse_code::end_of_file) + break; + throw_parse_code(ec); + } + } + return false; +} + +template +inline constexpr bool type_not_scannable=false; + +template +[[nodiscard]] inline constexpr bool scan_single_impl(input in,T arg) +{ + using char_type = typename input::char_type; + if constexpr(contiguous_input_stream) + { + if constexpr(precise_reserve_scannable) + { + constexpr std::size_t n{scan_precise_reserve_size(io_reserve_type)}; + auto curr_ptr{ibuffer_curr(in)}; + char_type const* curr{curr_ptr}; + char_type const* end{ibuffer_end(in)}; + std::size_t const diff{static_cast(end-curr)}; + if(diff) + { + scan_precise_reserve_define(io_reserve_type,curr,arg); + } + else + { + auto ret{scan_precise_reserve_define(io_reserve_type,curr,arg)}; + if(ret!=parse_code::ok) + { + if(ret==parse_code::end_of_file) + { + return false; + } + throw_parse_code(ret); + } + } + ibuffer_set_curr(in,curr_ptr+n); + return true; + } + else if constexpr(contiguous_scannable) + { + auto curr{ibuffer_curr(in)}; + auto end{ibuffer_end(in)}; + auto [it,ec] = scan_contiguous_define(io_reserve_type,curr,end,arg); + if constexpr(std::same_as) + { + ibuffer_set_curr(in,it); + } + else + { + ibuffer_set_curr(in,it-curr+curr); + } + if(ec!=parse_code::ok) + { + if(ec==parse_code::end_of_file) + return false; + throw_parse_code(ec); + } + return true; + } + else if constexpr(context_scannable) + { + typename std::remove_cvref_t))>::type state; + auto curr{ibuffer_curr(in)}; + auto end{ibuffer_end(in)}; + auto [it,ec]=scan_context_define(io_reserve_type,state,curr,end,arg); + if constexpr(std::same_as) + { + ibuffer_set_curr(in,it); + } + else + { + ibuffer_set_curr(in,it-curr+curr); + } + if(ec==parse_code::ok) + return true; + else if(ec!=parse_code::partial) + throw_parse_code(ec); + ec=scan_context_eof_define(io_reserve_type,state,arg); + if(ec==parse_code::ok) + return true; + else if(ec!=parse_code::end_of_file) + throw_parse_code(ec); + return false; + } + else + { + constexpr bool not_scannable{context_scannable}; + static_assert(not_scannable,"type not scannable. need context_scannable"); + return false; + } + } + else + { + if constexpr(precise_reserve_scannable) + { + constexpr std::size_t n{scan_precise_reserve_size(io_reserve_type)}; + char_type buffer[n]; + if constexpr(::fast_io::details::asan_state::current==::fast_io::details::asan_state::activate) + { + char_type const* p{buffer}; + bool ef{::fast_io::details::read_all_impl_decay_cold(in,buffer,buffer+n)}; + if(!ef) + { + return false; + } + if constexpr(precise_reserve_scannable_no_error) + { + scan_precise_reserve_define(io_reserve_type,p,arg); + } + else + { + auto ret{scan_precise_reserve_define(io_reserve_type,p,arg)}; + if(ret!=parse_code::ok) + { + if(ret==parse_code::end_of_file) + { + return false; + } + throw_parse_code(ret); + } + } + } + else + { + auto curr_ptr{ibuffer_curr(in)}; + char_type const* curr{curr_ptr}; + char_type const* end{ibuffer_end(in)}; + char_type const* p{curr}; + std::size_t const diff{static_cast(end-curr)}; + bool inbuffer{diff(in,buffer,buffer+n)}; + if(!ef) + { + return false; + } + p=buffer; + } + if constexpr(precise_reserve_scannable_no_error) + { + scan_precise_reserve_define(io_reserve_type,p,arg); + } + else + { + auto ret{scan_precise_reserve_define(io_reserve_type,p,arg)}; + if(ret!=parse_code::ok) + { + if(ret==parse_code::end_of_file) + { + return false; + } + throw_parse_code(ret); + } + } + if(!inbuffer)[[likely]] + { + ibuffer_set_curr(in,curr_ptr+n); + } + } + return true; + } + else if constexpr(contiguous_scannable&&context_scannable) + { + auto curr{ibuffer_curr(in)}; + auto end{ibuffer_end(in)}; + auto [it,ec] = scan_contiguous_define(io_reserve_type,curr,end,arg); + if(it==end) + return scan_context_status_impl(in,arg); + else + { + if constexpr(std::same_as) + { + ibuffer_set_curr(in,it); + } + else + { + ibuffer_set_curr(in,it-curr+curr); + } + if(ec!=parse_code::ok) + throw_parse_code(ec); + } + return true; + } + else if constexpr(context_scannable) + { + for(typename std::remove_cvref_t))>::type state;;) + { + auto curr{ibuffer_curr(in)}; + auto end{ibuffer_end(in)}; + auto [it,ec]=scan_context_define(io_reserve_type,state,curr,end,arg); + if constexpr(std::same_as) + { + ibuffer_set_curr(in,it); + } + else + { + ibuffer_set_curr(in,it-curr+curr); + } + if(ec==parse_code::ok) + return true; + else if(ec!=parse_code::partial) + throw_parse_code(ec); + if(!ibuffer_underflow(in))[[unlikely]] + { + ec=scan_context_eof_define(io_reserve_type,state,arg); + if(ec==parse_code::ok) + return true; + else if(ec==parse_code::end_of_file) + break; + throw_parse_code(ec); + } + } + return false; + } + else + { + constexpr bool not_scannable{context_scannable}; + static_assert(not_scannable,"type not scannable. need context_scannable"); + return false; + } + } +} +} + +template +requires (status_input_stream||input_stream) +[[nodiscard]] inline constexpr bool scan_freestanding_decay(input in,Args... args) +{ + if constexpr(status_input_stream) + return scan_status_define(in,args...); + else if constexpr(mutex_stream) + { + io_lock_guard lg{in}; + decltype(auto) unlocked_in{in.unlocked_handle()}; + return scan_freestanding_decay(io_ref(unlocked_in),args...); + } + else if constexpr(buffer_input_stream) + { + return (details::scan_single_impl(in,args)&&...); + } + else + { + unget_temp_buffer in_buffer(io_ref(in)); + return scan_freestanding_decay(io_ref(in_buffer),args...); + } +} + +template +requires (status_input_stream||input_stream) +[[nodiscard("scan does not require checking return value but scan_freestanding requires")]] inline constexpr bool scan_freestanding(input&& in,Args&& ...args) +{ + return scan_freestanding_decay(io_ref(in),io_scan_forward::char_type>(io_scan_alias(args))...); +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/secure_clear_guard.h b/src/fast_io/include/fast_io_core_impl/secure_clear_guard.h new file mode 100644 index 0000000..840d627 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/secure_clear_guard.h @@ -0,0 +1,196 @@ +#pragma once + +namespace fast_io +{ + +/* +Based on security paper Dead Store Elimination (Still) Considered Harmful + +https://www.usenix.org/system/files/conference/usenixsecurity17/sec17-yang.pdf + +https://www.usenix.org/sites/default/files/conference/protected-files/usenixsecurity17_slides_zhaomo_yang.pdf + +Existing Technique: Using memory barrier +GCC supports a memory barrier expressed using an inline assembly statement. +According to GCC’s documentation, the clobber argument "memory" tells the +compiler that the inline assembly statement may read or write memory that is not +specified in the input or output arguments. + +Used in: zap from Kerberos, memzero_explicit from Linux. +Availability: GCC and Clang. +Effectiveness: effective +Not effective on Clang: + std::memset(data,0,size); + __asm__ __volatile__("" ::: "memory"); + + +Effective on Clang + std::memset(data,0,size); + __asm__ __volatile__("" ::"r"(data): "memory"); + +How difficult to create a reliable scrubbing function +However, it does not work with Clang. +A more reliable and portable memory barrier is shown below (which is also used +used in memzero_explicit): + + +*/ + +inline +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L +constexpr +#endif +void none_secure_clear(std::byte* data,std::size_t size) noexcept +{ +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L +#if __cpp_if_consteval >= 202106L + if consteval +#elif __cpp_lib_is_constant_evaluated >= 201811L + if (__builtin_is_constant_evaluated()) +#endif + { + for(std::size_t i{};i!=size;++i) + data[i]=std::byte{}; + } + else +#endif + { +#if defined(__has_builtin) +#if __has_builtin(__builtin_memset) + __builtin_memset(data,0,size); +#else + ::std::memset(data,0,size); +#endif +#else + ::std::memset(data,0,size); +#endif + } +} + +inline void secure_clear(void* data,std::size_t size) noexcept +{ +#if defined(_MSC_VER) && !defined(__clang__) +/* +Referenced from Microsoft's winnt.h. +forceinline for this is nonsense +*/ + +#if defined(_M_AMD64) + __stosb(__builtin_bit_cast(unsigned char*,data), 0, size); +#else + volatile char *vptr = (volatile char *)data; + while (size) + { +#if !defined(_M_CEE) && (defined(_M_ARM) || defined(_M_ARM64)) + __iso_volatile_store8(vptr, 0); +#else + *vptr = 0; +#endif + ++vptr; + --size; + } +#endif // _M_AMD64 +#else +/* +https://github.com/bminor/glibc/blob/master/string/explicit_bzero.c +Referenced from glibc + +*/ + details::my_memset(data,0,size); + __asm__ __volatile__("" ::"r"(data): "memory"); +#endif +} + +namespace freestanding +{ + + +inline constexpr ::std::byte* bytes_secure_clear_n(::std::byte* data,std::size_t size) noexcept +{ +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L +#if __cpp_if_consteval >= 202106L + if consteval +#elif __cpp_lib_is_constant_evaluated >= 201811L + if (__builtin_is_constant_evaluated()) +#endif + { + for(std::size_t i{};i!=size;++i) + data[i]=std::byte{}; + } + else +#endif + { +#if defined(_MSC_VER) && !defined(__clang__) +/* +Referenced from Microsoft's winnt.h. +forceinline for this is nonsense +*/ + +#if defined(_M_AMD64) + __stosb(__builtin_bit_cast(unsigned char*,data), 0, size); +#else + volatile char *vptr = (volatile char *)data; + while (size) + { +#if !defined(_M_CEE) && (defined(_M_ARM) || defined(_M_ARM64)) + __iso_volatile_store8(vptr, 0); +#else + *vptr = 0; +#endif + ++vptr; + --size; + } +#endif // _M_AMD64 +#else +/* +https://github.com/bminor/glibc/blob/master/string/explicit_bzero.c +Referenced from glibc +*/ +#if defined(__has_builtin) +#if __has_builtin(__builtin_memset) + __builtin_memset(data,0,size); +#else + ::std::memset(data,0,size); +#endif +#else + ::std::memset(data,0,size); +#endif + __asm__ __volatile__("" ::"r"(data): "memory"); +#endif + } + return data+size; +} + +inline constexpr ::std::byte* bytes_secure_clear(::std::byte* first,::std::byte const* last) noexcept +{ + return bytes_secure_clear_n(first,static_cast(last-first)); +} + +} + +template +class secure_clear_guard +{ +public: + T* region; + std::size_t count; + secure_clear_guard(T* rg,std::size_t bts):region(rg),count(bts){} + secure_clear_guard(secure_clear_guard const&)=delete; + secure_clear_guard& operator=(secure_clear_guard const&)=delete; + ~secure_clear_guard() + { + secure_clear(region,count*sizeof(T)); + } +}; + +template +class secure_clear_no_op +{ +public: + constexpr secure_clear_no_op(T*,std::size_t){}; +}; + +template +using conditional_secure_clear_guard=std::conditional_t,secure_clear_no_op>; + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_core_impl/seek.h b/src/fast_io/include/fast_io_core_impl/seek.h new file mode 100644 index 0000000..a7d7ed5 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/seek.h @@ -0,0 +1,35 @@ +#pragma once + +namespace fast_io +{ + +enum class seekdir:std::uint_fast8_t +{ +beg = 0, //SEEK_SET +cur = 1, //SEEK_CUR +end = 2, //SEEK_END +}; + +template +struct seek_type_t +{ +inline constexpr explicit seek_type_t() = default; +}; + +template +inline constexpr seek_type_t seek_type{}; + +template +inline constexpr void rewind(stream&& stm) +{ + seek(stm,0,fast_io::seekdir::beg); +} + + +template struct io_cookie_type_t{}; + +template +inline constexpr io_cookie_type_t io_cookie_type{}; + + +} diff --git a/src/fast_io/include/fast_io_core_impl/simd/cpu_flags.h b/src/fast_io/include/fast_io_core_impl/simd/cpu_flags.h new file mode 100644 index 0000000..6f1cc08 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/simd/cpu_flags.h @@ -0,0 +1,87 @@ +#pragma once + +namespace fast_io::details::cpu_flags +{ + +inline constexpr bool sse2_supported +{ +#if defined(__SSE2__) || (defined(_MSC_VER)&&!defined(__clang__)&&(((defined(__x86_64__) || defined(_M_AMD64))&&!defined(_KERNEL_MODE))||defined(__AVX__))) +true +#elif defined(_M_IX86_FP) && defined(_MSC_VER)&&!defined(__clang__)&&!defined(_KERNEL_MODE) +#if _M_IX86_FP == 2 +true +#endif +#endif +}; + +inline constexpr bool sse4_2_supported +{ +#if defined(__AVX__) || defined(__SSE4_2__) +true +#endif +}; + +inline constexpr bool sse3_supported +{ +#if defined(__AVX__) || defined(__SSE3__) || defined(__SSE4_2__) +true +#endif +}; + +inline constexpr bool avx_supported +{ +#if defined(__AVX__) || defined(__AVX2__) +true +#endif +}; + +inline constexpr bool avx2_supported +{ +#if defined(__AVX2__) +true +#endif +}; + +inline constexpr bool avx512bw_supported +{ +#if defined(__AVX512BW__) +true +#endif +}; + +inline constexpr bool avx512vl_supported +{ +#if defined(__AVX512VL__) +true +#endif +}; + +inline constexpr bool avx512dq_supported +{ +#if defined(__AVX512DQ__) +true +#endif +}; + +inline constexpr bool avx512f_supported +{ +#if defined(__AVX512F__) +true +#endif +}; + +inline constexpr bool wasmsimd128_supported +{ +#if defined(__wasm_simd128__) +true +#endif +}; + +inline constexpr bool armneon_supported +{ +#if defined(__ARM_NEON) || ((defined(_MSC_VER)&&!defined(__clang__)) && defined(_M_ARM64) &&!defined(_KERNEL_MODE)) +true +#endif +}; + +} diff --git a/src/fast_io/include/fast_io_core_impl/simd/gcc_clang.h b/src/fast_io/include/fast_io_core_impl/simd/gcc_clang.h new file mode 100644 index 0000000..13dd105 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/simd/gcc_clang.h @@ -0,0 +1,648 @@ +#pragma once + +#ifdef __GNUC__ +#pragma GCC system_header +#endif + +namespace fast_io +{ + +namespace intrinsics +{ + +inline constexpr bool simd_shuffle_size_is_supported(std::size_t n) noexcept +{ + if(n==16) + { +#if __has_builtin(__builtin_ia32_pshufb128) + return true; +#else + return false; +#endif + } + else if(n==32) + { +#if __has_builtin(__builtin_ia32_pshufb256) + return true; +#else + return false; +#endif + } + return false; +} + +template +struct simd_vector +{ + using value_type = T; + using vec_type [[__gnu__::__vector_size__ (N*sizeof(T))]] = T; + vec_type value; + constexpr T const* data() const noexcept + { + return __builtin_addressof(value[0]); + } + constexpr T* data() noexcept + { + return __builtin_addressof(value[0]); + } + inline static constexpr std::size_t size() noexcept + { + return N; + } +#if __has_cpp_attribute(__gnu__::__always_inline__) + [[__gnu__::__always_inline__]] +#endif + inline void load(void const* address) noexcept + { + __builtin_memcpy(__builtin_addressof(value),address,sizeof(value)); + } +#if __has_cpp_attribute(__gnu__::__always_inline__) + [[__gnu__::__always_inline__]] +#endif + inline void store(void* address) noexcept + { + __builtin_memcpy(address,__builtin_addressof(value),sizeof(value)); + } + inline constexpr value_type front() const noexcept + { + return value[0]; + } + inline constexpr value_type back() const noexcept + { + constexpr std::size_t nm1{N-1}; + return value[nm1]; + } + + inline static constexpr bool empty() noexcept + { + return !N; + } + inline static constexpr std::size_t max_size() noexcept + { + constexpr std::size_t v{static_cast(-1)/sizeof(value_type)}; + return v; + } + inline constexpr value_type operator[](std::size_t n) const noexcept + { + return value[n]; + } + + inline constexpr simd_vector& operator+=(simd_vector const& other) noexcept + { + value+=other.value; + return *this; + } + inline constexpr simd_vector& operator-=(simd_vector const& other) noexcept + { + value-=other.value; + return *this; + } + inline constexpr simd_vector& operator*=(simd_vector const& other) noexcept + { + value*=other.value; + return *this; + } + inline constexpr simd_vector& operator/=(simd_vector const& other) noexcept + { + value/=other.value; + return *this; + } + inline constexpr simd_vector operator-() const noexcept + { + return {-value}; + } + + template + requires ((sizeof(T2)==sizeof(T)*N)&&std::is_trivially_copyable_v) + inline +#if __has_builtin(__builtin_bit_cast) + constexpr +#endif + void wrap_add_assign(T2 const& b) noexcept requires(std::integral) + { + if constexpr(std::same_as,T2>&&std::unsigned_integral) + { + value+=b.value; + } + else + { + using unsigned_type = std::make_unsigned_t; + using unsigned_vec_type = typename simd_vector::vec_type; +#if __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 + unsigned_vec_type asv; + __builtin_memcpy(__builtin_addressof(asv),this,sizeof(unsigned_vec_type)); + unsigned_vec_type bsv; + __builtin_memcpy(__builtin_addressof(bsv),__builtin_addressof(b),sizeof(unsigned_vec_type)); + asv+=bsv; + __builtin_memcpy(this,__builtin_addressof(asv),sizeof(unsigned_vec_type)); +#endif + } + } + + template + requires ((sizeof(T2)==sizeof(T)*N)&&std::is_trivially_copyable_v) + inline +#if __has_builtin(__builtin_bit_cast) + constexpr +#endif + void wrap_sub_assign(T2 const& b) noexcept requires(std::integral) + { + if constexpr(std::same_as,T2>&&std::unsigned_integral) + { + value-=b.value; + } + else + { + using unsigned_type = std::make_unsigned_t; + using unsigned_vec_type = typename simd_vector::vec_type; +#if __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 + unsigned_vec_type asv; + __builtin_memcpy(__builtin_addressof(asv),this,sizeof(unsigned_vec_type)); + unsigned_vec_type bsv; + __builtin_memcpy(__builtin_addressof(bsv),__builtin_addressof(b),sizeof(unsigned_vec_type)); + asv-=bsv; + __builtin_memcpy(this,__builtin_addressof(asv),sizeof(unsigned_vec_type)); +#endif + } + } + inline constexpr simd_vector& operator&=(simd_vector const& other) noexcept + { + value&=other.value; + return *this; + } + inline constexpr simd_vector& operator^=(simd_vector const& other) noexcept + { + value^=other.value; + return *this; + } + inline constexpr simd_vector& operator|=(simd_vector const& other) noexcept + { + value|=other.value; + return *this; + } + inline constexpr simd_vector& operator<<=(simd_vector const& other) noexcept + { + value<<=other.value; + return *this; + } + inline constexpr simd_vector& operator>>=(simd_vector const& other) noexcept + { + value<<=other.value; + return *this; + } + + template + inline constexpr simd_vector& operator<<=(I other) noexcept + { + value<<=other; + return *this; + } + template + inline constexpr simd_vector& operator>>=(I other) noexcept + { + value>>=other; + return *this; + } + inline constexpr simd_vector operator~() const noexcept + { + return {~value}; + } + template + requires (sizeof(T1)*N1==sizeof(T)*N&&!std::same_as) + explicit +#if __has_builtin(__builtin_bit_cast) + constexpr +#endif + operator simd_vector() const noexcept + { +#if __has_builtin(__builtin_bit_cast) + return __builtin_bit_cast(simd_vector,*this); +#else + simd_vector v; + __builtin_memcpy(__builtin_addressof(v),this,sizeof(v)); + return v; +#endif + } + constexpr operator vec_type const&() const noexcept + { + return value; + } + inline constexpr simd_vector& operator=(vec_type const& b) noexcept + { + value=b; + return *this; + } + inline +#if __has_builtin(__builtin_bit_cast) + constexpr +#endif + void swap_endian() noexcept requires(::std::integral&&(sizeof(value_type)<=sizeof(std::uint_least64_t))&&(N*sizeof(T)==16||N*sizeof(T)==32||N*sizeof(T)==64)) + { + if constexpr(sizeof(T)==1) + { + return; + } + else if constexpr(N*sizeof(T)==64) + { + using temp_vec_type [[__gnu__::__vector_size__ (64)]] = char; +#if __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 constexpr(sizeof(T)==8) + { + temp_vec=__builtin_shufflevector(temp_vec,temp_vec, + 7,6,5,4,3,2,1,0,15,14,13,12,11,10,9,8, + 23,22,21,20,19,18,17,16,31,30,29,28,27,26,25,24, + 39,38,37,36,35,34,33,32,47,46,45,44,43,42,41,40, + 55,54,53,52,51,50,49,48,63,62,61,60,59,58,57,56); + } + else if constexpr(sizeof(T)==4) + { + temp_vec=__builtin_shufflevector(temp_vec,temp_vec, + 3,2,1,0,7,6,5,4,11,10,9,8,15,14,13,12, + 19,18,17,16,23,22,21,20,27,26,25,24,31,30,29,28, + 35,34,33,32,39,38,37,36,43,42,41,40,47,46,45,44, + 51,50,49,48,55,54,53,52,59,58,57,56,63,62,61,60); + } + else if constexpr(sizeof(T)==2) + { + temp_vec=__builtin_shufflevector(temp_vec,temp_vec, + 1,0,3,2,5,4,7,6,9,8,11,10,13,12,15,14, + 17,16,19,18,21,20,23,22,25,24,27,26,29,28,31,30, + 33,32,35,34,37,36,39,38,41,40,43,42,45,44,47,46, + 49,48,51,50,53,52,55,54,57,56,59,58,61,60,63,62); + } +#elif __has_builtin(__builtin_ia32_pshufb512) + if constexpr(sizeof(T)==8) + { + constexpr temp_vec_type mask{7,6,5,4,3,2,1,0,15,14,13,12,11,10,9,8, + 23,22,21,20,19,18,17,16,31,30,29,28,27,26,25,24, + 39,38,37,36,35,34,33,32,47,46,45,44,43,42,41,40, + 55,54,53,52,51,50,49,48,63,62,61,60,59,58,57,56}; + temp_vec=__builtin_ia32_pshufb512(temp_vec,mask); + } + else if constexpr(sizeof(T)==4) + { + constexpr temp_vec_type mask{3,2,1,0,7,6,5,4,11,10,9,8,15,14,13,12, + 19,18,17,16,23,22,21,20,27,26,25,24,31,30,29,28, + 35,34,33,32,39,38,37,36,43,42,41,40,47,46,45,44, + 51,50,49,48,55,54,53,52,59,58,57,56,63,62,61,60}; + temp_vec=__builtin_ia32_pshufb512(temp_vec,mask); + } + else if constexpr(sizeof(T)==2) + { + constexpr temp_vec_type mask{1,0,3,2,5,4,7,6,9,8,11,10,13,12,15,14, + 17,16,19,18,21,20,23,22,25,24,27,26,29,28,31,30, + 33,32,35,34,37,36,39,38,41,40,43,42,45,44,47,46, + 49,48,51,50,53,52,55,54,57,56,59,58,61,60,63,62}; + temp_vec=__builtin_ia32_pshufb512(temp_vec,mask); + } +#endif +#if __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)); +#endif + } + else if constexpr(N*sizeof(T)==32) + { + using temp_vec_type [[__gnu__::__vector_size__ (32)]] = char; +#if __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 constexpr(sizeof(T)==8) + { + temp_vec=__builtin_shufflevector(temp_vec,temp_vec, + 7,6,5,4,3,2,1,0,15,14,13,12,11,10,9,8, + 23,22,21,20,19,18,17,16,31,30,29,28,27,26,25,24); + } + else if constexpr(sizeof(T)==4) + { + temp_vec=__builtin_shufflevector(temp_vec,temp_vec, + 3,2,1,0,7,6,5,4,11,10,9,8,15,14,13,12, + 19,18,17,16,23,22,21,20,27,26,25,24,31,30,29,28); + } + else if constexpr(sizeof(T)==2) + { + temp_vec=__builtin_shufflevector(temp_vec,temp_vec, + 1,0,3,2,5,4,7,6,9,8,11,10,13,12,15,14, + 17,16,19,18,21,20,23,22,25,24,27,26,29,28,31,30); + } +#elif __has_builtin(__builtin_ia32_pshufb256) + if constexpr(sizeof(T)==8) + { + constexpr temp_vec_type mask{7,6,5,4,3,2,1,0,15,14,13,12,11,10,9,8, + 23,22,21,20,19,18,17,16,31,30,29,28,27,26,25,24}; + temp_vec=__builtin_ia32_pshufb256(temp_vec,mask); + } + else if constexpr(sizeof(T)==4) + { + constexpr temp_vec_type mask{3,2,1,0,7,6,5,4,11,10,9,8,15,14,13,12, + 19,18,17,16,23,22,21,20,27,26,25,24,31,30,29,28}; + temp_vec=__builtin_ia32_pshufb256(temp_vec,mask); + } + else if constexpr(sizeof(T)==2) + { + constexpr temp_vec_type mask{1,0,3,2,5,4,7,6,9,8,11,10,13,12,15,14, + 17,16,19,18,21,20,23,22,25,24,27,26,29,28,31,30}; + temp_vec=__builtin_ia32_pshufb256(temp_vec,mask); + } +#endif +#if __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)); +#endif + } + else + { + using temp_vec_type [[__gnu__::__vector_size__ (16)]] = char; +#if __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__))||(!defined(__GNUC__)||defined(__clang__))||defined(__SSE4_2__)) + if constexpr(sizeof(T)==8) + { + temp_vec=__builtin_shufflevector(temp_vec,temp_vec,7,6,5,4,3,2,1,0,15,14,13,12,11,10,9,8); + } + else if constexpr(sizeof(T)==4) + { + temp_vec=__builtin_shufflevector(temp_vec,temp_vec,3,2,1,0,7,6,5,4,11,10,9,8,15,14,13,12); + } + else if constexpr(sizeof(T)==2) + { + temp_vec=__builtin_shufflevector(temp_vec,temp_vec,1,0,3,2,5,4,7,6,9,8,11,10,13,12,15,14); + } +#elif __has_builtin(__builtin_ia32_pshufb128) && defined(__SSE3__) + if constexpr(sizeof(T)==8) + { + constexpr temp_vec_type mask{7,6,5,4,3,2,1,0,15,14,13,12,11,10,9,8}; + temp_vec=__builtin_ia32_pshufb128(temp_vec,mask); + } + else if constexpr(sizeof(T)==4) + { + constexpr temp_vec_type mask{3,2,1,0,7,6,5,4,11,10,9,8,15,14,13,12}; + temp_vec=__builtin_ia32_pshufb128(temp_vec,mask); + } + else if constexpr(sizeof(T)==2) + { + constexpr temp_vec_type mask{1,0,3,2,5,4,7,6,9,8,11,10,13,12,15,14}; + temp_vec=__builtin_ia32_pshufb128(temp_vec,mask); + } +#elif defined(__SSE2__) && __has_builtin(__builtin_ia32_punpcklbw128) && __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; + constexpr x86_64_v16qi zero{}; + if constexpr(sizeof(T)==8) + { + auto res0{__builtin_ia32_punpcklbw128(temp_vec,zero)}; + auto res1{__builtin_ia32_pshufd((x86_64_v4si)res0,78)}; + auto res2{__builtin_ia32_pshuflw((x86_64_v8hi)res1,27)}; + auto res3{__builtin_ia32_pshufhw(res2,27)}; + auto res4{__builtin_ia32_punpckhbw128(temp_vec,zero)}; + auto res5{__builtin_ia32_pshufd((x86_64_v4si)res4,78)}; + auto res6{__builtin_ia32_pshuflw((x86_64_v8hi)res5,27)}; + auto res7{__builtin_ia32_pshufhw(res6,27)}; + temp_vec=__builtin_ia32_packuswb128(res3,res7); + } + else if constexpr(sizeof(T)==4) + { + auto res0{__builtin_ia32_punpcklbw128(temp_vec,zero)}; + auto res2{__builtin_ia32_pshuflw((x86_64_v8hi)res0,27)}; + auto res3{__builtin_ia32_pshufhw(res2,27)}; + auto res4{__builtin_ia32_punpckhbw128(temp_vec,zero)}; + auto res6{__builtin_ia32_pshuflw((x86_64_v8hi)res4,27)}; + auto res7{__builtin_ia32_pshufhw(res6,27)}; + temp_vec=__builtin_ia32_packuswb128(res3,res7); + } + else if constexpr(sizeof(T)==2) + { + using x86_64_v8hu [[__gnu__::__vector_size__ (16)]] = unsigned short; + auto res0{(x86_64_v8hu)temp_vec}; + temp_vec=(x86_64_v16qi)((res0>>8)|(res0<<8)); + } +#endif +#if __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)); +#endif + } + } + template + requires (simd_shuffle_size_is_supported(sizeof(vec_type))&&sizeof(simd_vector)==sizeof(vec_type)&&sizeof(T1)==1) + inline constexpr void shuffle([[maybe_unused]] simd_vector const& mask) noexcept + { + if constexpr(sizeof(mask)==16) + { +#if __has_builtin(__builtin_ia32_pshufb128) + using value_type2 [[__gnu__::__vector_size__ (16)]] = char; +#if __has_builtin(__builtin_bit_cast) + value=__builtin_bit_cast(vec_type,__builtin_ia32_pshufb128(__builtin_bit_cast(value_type2,value),mask.value)); +#else + value_type2 v; + __builtin_memcpy(__builtin_addressof(v),__builtin_addressof(mask),sizeof(value_type2)); + v=__builtin_ia32_pshufb128(v,mask.value); + __builtin_memcpy(__builtin_addressof(value),__builtin_addressof(v),sizeof(value_type2)); +#endif +#endif + } + else if constexpr(sizeof(mask)==32) + { +#if __has_builtin(__builtin_ia32_pshufb256) + using value_type2 [[__gnu__::__vector_size__ (32)]] = char; +#if __has_builtin(__builtin_bit_cast) + value=__builtin_bit_cast(vec_type,__builtin_ia32_pshufb256(__builtin_bit_cast(value_type2,value),mask.value)); +#else + value_type2 v; + __builtin_memcpy(__builtin_addressof(v),__builtin_addressof(mask),sizeof(value_type2)); + v=__builtin_ia32_pshufb256(v,mask.value); + __builtin_memcpy(__builtin_addressof(value),__builtin_addressof(v),sizeof(value_type2)); +#endif +#endif + } + } +}; + +template +inline constexpr simd_vector operator+(simd_vector const& a,simd_vector const& b) noexcept +{ + return {a.value+b.value}; +} + +template +inline constexpr simd_vector operator-(simd_vector const& a,simd_vector const& b) noexcept +{ + return {a.value-b.value}; +} + +template +inline constexpr simd_vector operator*(simd_vector const& a,simd_vector const& b) noexcept +{ + return {a.value*b.value}; +} + +template +inline constexpr simd_vector operator/(simd_vector const& a,simd_vector const& b) noexcept +{ + return {a.value/b.value}; +} + +template +inline constexpr simd_vector operator&(simd_vector const& a,simd_vector const& b) noexcept +{ + return {a.value&b.value}; +} + +template +inline constexpr simd_vector operator|(simd_vector const& a,simd_vector const& b) noexcept +{ + return {a.value|b.value}; +} + +template +inline constexpr simd_vector operator^(simd_vector const& a,simd_vector const& b) noexcept +{ + return {a.value^b.value}; +} + +template +inline constexpr simd_vector operator<<(simd_vector const& a,simd_vector const& b) noexcept +{ + return {a.value< +inline constexpr simd_vector operator>>(simd_vector const& a,simd_vector const& b) noexcept +{ + return {a.value>>b.value}; +} + +template +inline constexpr simd_vector operator<<(simd_vector const& a,I i) noexcept +{ + return {a.value< +inline constexpr simd_vector operator>>(simd_vector const& a,I i) noexcept +{ + return {a.value>>i}; +} + +template +inline constexpr simd_vector operator<(simd_vector const& a,simd_vector const& b) noexcept +{ + return {a.value +inline constexpr simd_vector operator>(simd_vector const& a,simd_vector const& b) noexcept +{ + return {a.value>b.value}; +} + +template +inline constexpr simd_vector operator<=(simd_vector const& a,simd_vector const& b) noexcept +{ + return {a.value<=b.value}; +} + +template +inline constexpr simd_vector operator>=(simd_vector const& a,simd_vector const& b) noexcept +{ + return {a.value>=b.value}; +} + +template +inline constexpr simd_vector operator==(simd_vector const& a,simd_vector const& b) noexcept +{ + return {a.value==b.value}; +} + +template +inline constexpr simd_vector operator!=(simd_vector const& a,simd_vector const& b) noexcept +{ + return {a.value!=b.value}; +} + +template +inline +#if __has_builtin(__builtin_bit_cast) +constexpr +#endif +simd_vector wrap_add(simd_vector a,simd_vector b) noexcept +{ + if constexpr(std::signed_integral) + { + using unsigned_type = std::make_unsigned_t; + using vec_type = typename simd_vector::vec_type; +#if __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; + __builtin_memcpy(__builtin_addressof(asv),__builtin_addressof(a),sizeof(asv)); + vec_type bsv; + __builtin_memcpy(__builtin_addressof(bsv),__builtin_addressof(b),sizeof(bsv)); + asv+=bsv; + simd_vector res; + __builtin_memcpy(__builtin_addressof(res),__builtin_addressof(asv),sizeof(asv)); + return res; +#endif + } + else + { + return a+b; + } +} + +template +inline +#if __has_builtin(__builtin_bit_cast) +constexpr +#endif +simd_vector wrap_sub(simd_vector a,simd_vector b) noexcept +{ + if constexpr(std::signed_integral) + { + using unsigned_type = std::make_unsigned_t; + using vec_type = typename simd_vector::vec_type; +#if __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; + __builtin_memcpy(__builtin_addressof(asv),__builtin_addressof(a),sizeof(asv)); + vec_type bsv; + __builtin_memcpy(__builtin_addressof(bsv),__builtin_addressof(b),sizeof(bsv)); + asv-=bsv; + simd_vector res; + __builtin_memcpy(__builtin_addressof(res),__builtin_addressof(asv),sizeof(asv)); + return res; +#endif + } + else + { + return a-b; + } +} + +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/simd/generic.h b/src/fast_io/include/fast_io_core_impl/simd/generic.h new file mode 100644 index 0000000..8e9f365 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/simd/generic.h @@ -0,0 +1,285 @@ +#pragma once + +namespace fast_io +{ + +namespace intrinsics +{ + +template +struct +#if defined(__has_declspec_attribute) +#if __has_declspec_attribute(intrin_type) +__declspec(intrin_type) +#endif +#if __has_declspec_attribute(align) +__declspec(align(sizeof(T)*N/2)) +#endif +#elif defined(_MSC_VER) +__declspec(intrin_type) __declspec(align(sizeof(T)*N/2)) +#endif +simd_vector +{ + using value_type = T; + using vec_type = value_type[N]; + vec_type value; + constexpr T const* data() const noexcept + { + return __builtin_addressof(value[0]); + } + constexpr T* data() noexcept + { + return __builtin_addressof(value[0]); + } +#if __has_cpp_attribute(__gnu__::__always_inline__) + [[__gnu__::__always_inline__]] +#endif + inline void load(void const* address) noexcept + { +#if defined(__has_builtin) +#if __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 + } + inline static constexpr std::size_t size() noexcept + { + return N; + } +#if __has_cpp_attribute(__gnu__::__always_inline__) + [[__gnu__::__always_inline__]] +#endif + inline void store(void* address) noexcept + { +#if defined(__has_builtin) +#if __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 + } + inline constexpr value_type front() const noexcept + { + return value[0]; + } + inline constexpr value_type back() const noexcept + { + constexpr std::size_t nm1{N-1}; + return value[nm1]; + } + + inline static constexpr bool empty() noexcept + { + return !N; + } + inline static constexpr std::size_t max_size() noexcept + { + constexpr std::size_t v{static_cast(-1)/sizeof(value_type)}; + return v; + } + inline constexpr value_type operator[](std::size_t n) const noexcept + { + return value[n]; + } + + inline constexpr simd_vector& operator+=(simd_vector const& other) noexcept + { + return (*this)=(*this+other); + } + inline constexpr simd_vector& operator-=(simd_vector const& other) noexcept + { + return (*this)=(*this-other); + } + inline constexpr void wrap_add_assign(simd_vector const& other) noexcept + { + (*this)=::fast_io::details::wrap_add_common(*this,other); + } + inline constexpr simd_vector& operator*=(simd_vector const& other) noexcept + { + return *this=(*this)*other; + } + inline constexpr simd_vector& operator/=(simd_vector const& other) noexcept + { + return *this=(*this)/other; + } + inline constexpr simd_vector operator-() const noexcept + { + return ::fast_io::details::wrap_minus_common(::fast_io::details::all_zero_simd_vector_mask,*this); + } + + template + requires (sizeof(T1)*N1==sizeof(T)*N&&!std::same_as) + explicit constexpr operator simd_vector() const noexcept + { + return __builtin_bit_cast(simd_vector,*this); + } + inline constexpr simd_vector& operator&=(simd_vector const& other) noexcept + { + return *this=(*this)&other; + } + inline constexpr simd_vector& operator^=(simd_vector const& other) noexcept + { + return *this=(*this)^other; + } + inline constexpr simd_vector& operator|=(simd_vector const& other) noexcept + { + return *this=(*this)|other; + } + inline constexpr simd_vector& operator<<=(simd_vector const& other) noexcept + { + return *this=(*this)<& operator>>=(simd_vector const& other) noexcept + { + return *this=(*this)>>other; + } + inline constexpr simd_vector& operator<<=(unsigned v) noexcept + { + return *this=(*this)<& operator>>=(unsigned v) noexcept + { + return *this=(*this)>>v; + } + inline constexpr simd_vector operator~() const noexcept + { + constexpr bool using_simd{(sizeof(vec_type)==16&&::fast_io::details::cpu_flags::sse2_supported)||(sizeof(vec_type)==32&&::fast_io::details::cpu_flags::avx2_supported) + ||(sizeof(vec_type)==64&&(::fast_io::details::cpu_flags::avx512dq_supported||::fast_io::details::cpu_flags::avx512f_supported))}; + if constexpr(using_simd) + { + return (::fast_io::details::all_one_simd_vector_mask)^(*this); + } + else + { + return ::fast_io::details::generic_simd_self_create_op_impl(*this,[](T v) noexcept + { + return ~v; + }); + } + } +#if __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif + inline constexpr void swap_endian() noexcept requires(::std::integral&&(N*sizeof(T)==16||N*sizeof(T)==32)) + { + if constexpr(sizeof(value_type)==1) + { + return; + } + else + { +#if __cpp_if_consteval >= 202106L + if !consteval +#else + if (!__builtin_is_constant_evaluated()) +#endif + { +#if (defined(__x86_64__) || defined(_M_AMD64) || defined(__i386__) || defined(_M_IX86)) + if constexpr(sizeof(vec_type)==16&&::fast_io::details::cpu_flags::sse2_supported) + { + if constexpr(::fast_io::details::cpu_flags::sse3_supported) + { + __m128i temp_vec = __builtin_bit_cast(__m128i,*this); + __m128i mask = __builtin_bit_cast(__m128i,::fast_io::details::simd_byte_swap_shuffle_mask); + temp_vec = _mm_shuffle_epi8(temp_vec,mask); + *this=__builtin_bit_cast(simd_vector,temp_vec); + return; + } + else + { + __m128i temp_vec = __builtin_bit_cast(__m128i,*this); + __m128i const zero{}; + if constexpr(sizeof(T)==8) + { + auto res0{_mm_unpacklo_epi8(temp_vec,zero)}; + auto res1{_mm_shuffle_epi32(res0,78)}; + auto res2{_mm_shufflelo_epi16(res1,27)}; + auto res3{_mm_shufflehi_epi16(res2,27)}; + auto res4{_mm_unpackhi_epi8(temp_vec,zero)}; + auto res5{_mm_shuffle_epi32(res4,78)}; + auto res6{_mm_shufflelo_epi16(res5,27)}; + auto res7{_mm_shufflehi_epi16(res6,27)}; + temp_vec=_mm_packus_epi16(res3,res7); + } + else if constexpr(sizeof(T)==4) + { + auto res0{_mm_unpacklo_epi8(temp_vec,zero)}; + auto res2{_mm_shufflelo_epi16(res0,27)}; + auto res3{_mm_shufflehi_epi16(res2,27)}; + auto res4{_mm_unpackhi_epi8(temp_vec,zero)}; + auto res6{_mm_shufflelo_epi16(res4,27)}; + auto res7{_mm_shufflehi_epi16(res6,27)}; + temp_vec=_mm_packus_epi16(res3,res7); + } + else if constexpr(sizeof(T)==2) + { + __m128i a = _mm_srli_epi16(temp_vec,8); + __m128i b = _mm_slli_epi16(temp_vec,8); + __m128 aa = __builtin_bit_cast(__m128,a); + __m128 bb = __builtin_bit_cast(__m128,b); + temp_vec=__builtin_bit_cast(__m128i,_mm_or_ps(aa,bb)); + } + *this=__builtin_bit_cast(simd_vector,temp_vec); + return; + } + } + else if constexpr(sizeof(vec_type)==32&&::fast_io::details::cpu_flags::avx2_supported) + { + __m256i temp_vec = __builtin_bit_cast(__m256i,*this); + __m256i mask = __builtin_bit_cast(__m256i,::fast_io::details::simd_byte_swap_shuffle_mask); + temp_vec = _mm256_shuffle_epi8(temp_vec,mask); + *this=__builtin_bit_cast(simd_vector,temp_vec); + return; + } + else + { + __m512i temp_vec = __builtin_bit_cast(__m512i,*this); + __m512i mask = __builtin_bit_cast(__m512i,::fast_io::details::simd_byte_swap_shuffle_mask); + temp_vec = _mm512_shuffle_epi8(temp_vec,mask); + *this=__builtin_bit_cast(simd_vector,temp_vec); + return; + } +#elif defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) || defined(__arm__) || defined(_M_ARM) + if constexpr(sizeof(vec_type)==16&&::fast_io::details::cpu_flags::armneon_supported) + { + if constexpr(sizeof(T)==8) + { + poly8x16_t temp_vec = __builtin_bit_cast(poly8x16_t,*this); + temp_vec=vrev64q_p8(temp_vec); + *this=__builtin_bit_cast(simd_vector,temp_vec); + } + else if constexpr(sizeof(T)==4) + { + uint32x4_t temp_vec = __builtin_bit_cast(uint32x4_t,*this); + temp_vec=vrev32q_p8(temp_vec); + *this=__builtin_bit_cast(simd_vector,temp_vec); + } + else if constexpr(sizeof(T)==2) + { + uint16x8_t temp_vec = __builtin_bit_cast(uint16x8_t,*this); + temp_vec=vrev16q_p8(temp_vec); + *this=__builtin_bit_cast(simd_vector,temp_vec); + } + return; + } +#endif + } + ::fast_io::details::generic_simd_self_op_impl(*this,[](T& t) + { + t=::fast_io::byte_swap(t); + }); + } + } +}; + +} + + +} diff --git a/src/fast_io/include/fast_io_core_impl/simd/generic_operations.h b/src/fast_io/include/fast_io_core_impl/simd/generic_operations.h new file mode 100644 index 0000000..fc77a5c --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/simd/generic_operations.h @@ -0,0 +1,4245 @@ +#pragma once + +#if !defined(_MSC_VER) || defined(__clang__) +#if defined(__x86_64__) || defined(__i386__) +#include +#elif defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) || defined(__arm__) || defined(_M_ARM) +#include +#endif +#endif + +namespace fast_io +{ + +namespace intrinsics +{ +template +struct +#if defined(__has_declspec_attribute) +#if __has_declspec_attribute(intrin_type) +__declspec(intrin_type) +#endif +#if __has_declspec_attribute(align) +__declspec(align(sizeof(T)*N/2)) +#endif +#elif defined(_MSC_VER) +__declspec(intrin_type) __declspec(align(sizeof(T)*N/2)) +#endif +simd_vector; +} +namespace details +{ + +template +inline constexpr void generic_simd_operation_impl(T& selfval,T const& other,Func func) noexcept +{ + constexpr std::size_t N{std::remove_cvref_t::size()}; + for(std::size_t i{};i!=N;++i) + { + func(selfval.value[i],other.value[i]); + } +} + +template +inline constexpr void generic_simd_self_op_impl(T& selfval,Func func) noexcept +{ + constexpr std::size_t N{std::remove_cvref_t::size()}; + for(std::size_t i{};i!=N;++i) + { + func(selfval.value[i]); + } +} + +template +inline constexpr std::remove_cvref_t generic_simd_self_create_op_impl(T const& selfval,Func func) noexcept +{ + std::remove_cvref_t newval; + constexpr std::size_t N{std::remove_cvref_t::size()}; + for(std::size_t i{};i!=N;++i) + { + newval.value[i]=func(selfval.value[i]); + } + return newval; +} + +template +inline constexpr std::remove_cvref_t generic_simd_create_op_impl(T const& a,T const& b,Func func) noexcept +{ + constexpr std::size_t N{std::remove_cvref_t::size()}; + std::remove_cvref_t newval; + for(std::size_t i{};i!=N;++i) + { + newval.value[i]=func(a.value[i],b.value[i]); + } + return newval; +} + +template +inline constexpr auto create_value_mx() noexcept +{ + ::fast_io::freestanding::array arr; + for(auto& e : arr) + { + e=std::numeric_limits::max(); + } + return std::bit_cast(arr); +} + +template +inline constexpr T generic_simd_comparision_common_impl(T const& a, + T const& b,Func func) noexcept +{ + using value_type = typename std::remove_cvref_t::value_type; + return ::fast_io::details::generic_simd_create_op_impl(a,b,[&](value_type va,value_type vb) noexcept ->value_type + { + bool t{func(va,vb)}; + constexpr auto mx{create_value_mx()}; + if(t) + { + return mx; + } + return {}; + }); +} + +template +inline constexpr ::fast_io::intrinsics::simd_vector all_zero_simd_vector_mask{}; + +template +inline constexpr ::fast_io::intrinsics::simd_vector all_one_simd_vector_mask{create_value_mx<::fast_io::intrinsics::simd_vector>()}; + +template +inline constexpr ::fast_io::intrinsics::simd_vector wrap_add_common(::fast_io::intrinsics::simd_vector const& a,::fast_io::intrinsics::simd_vector const& b) noexcept +{ +#if __cpp_if_consteval >= 202106L + if !consteval +#else + if (!__builtin_is_constant_evaluated()) +#endif + { +#if (defined(__x86_64__) || defined(_M_AMD64) || defined(__i386__) || defined(_M_IX86)) + using vec_type = ::fast_io::intrinsics::simd_vector; + if constexpr(sizeof(vec_type)==16&&::fast_io::details::cpu_flags::sse2_supported) + { + if constexpr(std::integral) + { + __m128i amm = __builtin_bit_cast(__m128i,a); + __m128i bmm = __builtin_bit_cast(__m128i,b); + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm_add_epi8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm_add_epi16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm_add_epi32(amm,bmm)); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm_add_epi64(amm,bmm)); + } + } + else if constexpr(std::floating_point) + { +#if !defined(__clang__) + if constexpr(sizeof(T)==sizeof(float)/2) + { + __m128h amm = __builtin_bit_cast(__m128h,a); + __m128h bmm = __builtin_bit_cast(__m128h,b); + return __builtin_bit_cast(vec_type,_mm_add_ph(amm,bmm)); + } + else +#endif + if constexpr(sizeof(T)==sizeof(float)) + { + __m128 amm = __builtin_bit_cast(__m128,a); + __m128 bmm = __builtin_bit_cast(__m128,b); + return __builtin_bit_cast(vec_type,_mm_add_ps(amm,bmm)); + } + else if constexpr(sizeof(T)==sizeof(double)) + { + __m128d amm = __builtin_bit_cast(__m128d,a); + __m128d bmm = __builtin_bit_cast(__m128d,b); + return __builtin_bit_cast(vec_type,_mm_add_pd(amm,bmm)); + } + } + } + else if constexpr(sizeof(vec_type)==32&&::fast_io::details::cpu_flags::avx2_supported) + { + if constexpr(std::integral) + { + __m256i amm = __builtin_bit_cast(__m256i,a); + __m256i bmm = __builtin_bit_cast(__m256i,b); + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm256_add_epi8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm256_add_epi16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm256_add_epi32(amm,bmm)); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm256_add_epi64(amm,bmm)); + } + } + else if constexpr(std::floating_point) + { +#if !defined(__clang__) + if constexpr(sizeof(T)==sizeof(float)/2) + { + __m256h amm = __builtin_bit_cast(__m256h,a); + __m256h bmm = __builtin_bit_cast(__m256h,b); + return __builtin_bit_cast(vec_type,_mm256_add_ph(amm,bmm)); + } + else +#endif + if constexpr(sizeof(T)==sizeof(float)) + { + __m256 amm = __builtin_bit_cast(__m256,a); + __m256 bmm = __builtin_bit_cast(__m256,b); + return __builtin_bit_cast(vec_type,_mm256_add_ps(amm,bmm)); + } + else if constexpr(sizeof(T)==sizeof(double)) + { + __m256d amm = __builtin_bit_cast(__m256d,a); + __m256d bmm = __builtin_bit_cast(__m256d,b); + return __builtin_bit_cast(vec_type,_mm256_add_pd(amm,bmm)); + } + } + } + else if constexpr(sizeof(vec_type)==64) + { + if constexpr(std::integral&&::fast_io::details::cpu_flags::avx512bw_supported) + { + __m512i amm = __builtin_bit_cast(__m512i,a); + __m512i bmm = __builtin_bit_cast(__m512i,b); + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm512_add_epi8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm512_add_epi16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm512_add_epi32(amm,bmm)); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm512_add_epi64(amm,bmm)); + } + } + else if constexpr(std::floating_point&&::fast_io::details::cpu_flags::avx512f_supported) + { +#if !defined(__clang__) + if constexpr(sizeof(T)==sizeof(float)/2) + { + __m512h amm = __builtin_bit_cast(__m512h,a); + __m512h bmm = __builtin_bit_cast(__m512h,b); + return __builtin_bit_cast(vec_type,_mm512_add_ph(amm,bmm)); + } + else +#endif + if constexpr(sizeof(T)==sizeof(float)) + { + __m512 amm = __builtin_bit_cast(__m512,a); + __m512 bmm = __builtin_bit_cast(__m512,b); + return __builtin_bit_cast(vec_type,_mm512_add_ps(amm,bmm)); + } + else if constexpr(sizeof(T)==sizeof(double)) + { + __m512d amm = __builtin_bit_cast(__m512d,a); + __m512d bmm = __builtin_bit_cast(__m512d,b); + return __builtin_bit_cast(vec_type,_mm512_add_pd(amm,bmm)); + } + } + } +#elif defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) || defined(__arm__) || defined(_M_ARM) + using vec_type = ::fast_io::intrinsics::simd_vector; + if constexpr(::fast_io::details::cpu_flags::armneon_supported) + { + if constexpr(std::integral) + { + if constexpr(sizeof(vec_type)==8) + { + if constexpr(sizeof(T)==1) + { + uint8x8_t amm = __builtin_bit_cast(uint8x8_t,a); + uint8x8_t bmm = __builtin_bit_cast(uint8x8_t,b); + return __builtin_bit_cast(vec_type,vadd_u8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x4_t amm = __builtin_bit_cast(uint16x4_t,a); + uint16x4_t bmm = __builtin_bit_cast(uint16x4_t,b); + return __builtin_bit_cast(vec_type,vadd_u16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x2_t amm = __builtin_bit_cast(uint32x2_t,a); + uint32x2_t bmm = __builtin_bit_cast(uint32x2_t,b); + return __builtin_bit_cast(vec_type,vadd_u32(amm,bmm)); + } + else if constexpr(sizeof(T)==8) + { + uint64x1_t amm = __builtin_bit_cast(uint64x1_t,a); + uint64x1_t bmm = __builtin_bit_cast(uint64x1_t,b); + return __builtin_bit_cast(vec_type,vadd_u64(amm,bmm)); + } + } + else if constexpr(sizeof(vec_type)==16) + { + if constexpr(sizeof(T)==1) + { + uint8x16_t amm = __builtin_bit_cast(uint8x16_t,a); + uint8x16_t bmm = __builtin_bit_cast(uint8x16_t,b); + return __builtin_bit_cast(vec_type,vaddq_u8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x8_t amm = __builtin_bit_cast(uint16x8_t,a); + uint16x8_t bmm = __builtin_bit_cast(uint16x8_t,b); + return __builtin_bit_cast(vec_type,vaddq_u16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x4_t amm = __builtin_bit_cast(uint32x4_t,a); + uint32x4_t bmm = __builtin_bit_cast(uint32x4_t,b); + return __builtin_bit_cast(vec_type,vaddq_u32(amm,bmm)); + } + else if constexpr(sizeof(T)==8) + { + uint64x2_t amm = __builtin_bit_cast(uint64x2_t,a); + uint64x2_t bmm = __builtin_bit_cast(uint64x2_t,b); + return __builtin_bit_cast(vec_type,vaddq_u64(amm,bmm)); + } + } + } + else if constexpr(std::floating_point) + { + if constexpr(sizeof(vec_type)==8) + { + if constexpr(sizeof(T)==sizeof(float)) + { + float32x2_t amm = __builtin_bit_cast(float32x2_t,a); + float32x2_t bmm = __builtin_bit_cast(float32x2_t,b); + return __builtin_bit_cast(vec_type,vadd_f32(amm,bmm)); + } +#if defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) + else if constexpr(sizeof(T)==sizeof(double)) + { + float64x1_t amm = __builtin_bit_cast(float64x1_t,a); + float64x1_t bmm = __builtin_bit_cast(float64x1_t,b); + return __builtin_bit_cast(vec_type,vadd_f64(amm,bmm)); + } +#endif + } + else if constexpr(sizeof(vec_type)==16) + { + if constexpr(sizeof(T)==sizeof(float)) + { + float32x4_t amm = __builtin_bit_cast(float32x4_t,a); + float32x4_t bmm = __builtin_bit_cast(float32x4_t,b); + return __builtin_bit_cast(vec_type,vaddq_f32(amm,bmm)); + } +#if defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) + else if constexpr(sizeof(T)==sizeof(double)) + { + float64x2_t amm = __builtin_bit_cast(float64x2_t,a); + float64x2_t bmm = __builtin_bit_cast(float64x2_t,b); + return __builtin_bit_cast(vec_type,vaddq_f64(amm,bmm)); + } +#endif + } + } + } +#endif + } + return ::fast_io::details::generic_simd_create_op_impl(a,b,[](T va,T vb) noexcept -> T + { + if constexpr(std::signed_integral) + { + using unsignedtype = std::make_unsigned_t; + return static_cast(static_cast(va)+static_cast(vb)); + } + else + { + return static_cast(va+vb); + } + }); +} + +template +inline constexpr ::fast_io::intrinsics::simd_vector wrap_minus_common(::fast_io::intrinsics::simd_vector const& a,::fast_io::intrinsics::simd_vector const& b) noexcept +{ +#if __cpp_if_consteval >= 202106L + if !consteval +#else + if (!__builtin_is_constant_evaluated()) +#endif + { +#if (defined(__x86_64__) || defined(_M_AMD64) || defined(__i386__) || defined(_M_IX86)) + + using vec_type = ::fast_io::intrinsics::simd_vector; + if constexpr(sizeof(vec_type)==16&&::fast_io::details::cpu_flags::sse2_supported) + { + if constexpr(std::integral) + { + __m128i amm = __builtin_bit_cast(__m128i,a); + __m128i bmm = __builtin_bit_cast(__m128i,b); + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm_sub_epi8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm_sub_epi16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm_sub_epi32(amm,bmm)); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm_sub_epi64(amm,bmm)); + } + } + else if constexpr(std::floating_point) + { +#if !defined(__clang__) + if constexpr(sizeof(T)==sizeof(float)/2) + { + __m128h amm = __builtin_bit_cast(__m128h,a); + __m128h bmm = __builtin_bit_cast(__m128h,b); + return __builtin_bit_cast(vec_type,_mm_sub_ph(amm,bmm)); + } + else +#endif + if constexpr(sizeof(T)==sizeof(float)) + { + __m128 amm = __builtin_bit_cast(__m128,a); + __m128 bmm = __builtin_bit_cast(__m128,b); + return __builtin_bit_cast(vec_type,_mm_sub_ps(amm,bmm)); + } + else if constexpr(sizeof(T)==sizeof(double)) + { + __m128d amm = __builtin_bit_cast(__m128d,a); + __m128d bmm = __builtin_bit_cast(__m128d,b); + return __builtin_bit_cast(vec_type,_mm_sub_pd(amm,bmm)); + } + } + } + else if constexpr(sizeof(vec_type)==32&&::fast_io::details::cpu_flags::avx2_supported) + { + if constexpr(std::integral) + { + __m256i amm = __builtin_bit_cast(__m256i,a); + __m256i bmm = __builtin_bit_cast(__m256i,b); + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm256_sub_epi8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm256_sub_epi16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm256_sub_epi32(amm,bmm)); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm256_sub_epi64(amm,bmm)); + } + } + else if constexpr(std::floating_point) + { +#if !defined(__clang__) + if constexpr(sizeof(T)==sizeof(float)/2) + { + __m256h amm = __builtin_bit_cast(__m256h,a); + __m256h bmm = __builtin_bit_cast(__m256h,b); + return __builtin_bit_cast(vec_type,_mm256_sub_ph(amm,bmm)); + } + else +#endif + if constexpr(sizeof(T)==sizeof(float)) + { + __m256 amm = __builtin_bit_cast(__m256,a); + __m256 bmm = __builtin_bit_cast(__m256,b); + return __builtin_bit_cast(vec_type,_mm256_sub_ps(amm,bmm)); + } + else if constexpr(sizeof(T)==sizeof(double)) + { + __m256d amm = __builtin_bit_cast(__m256d,a); + __m256d bmm = __builtin_bit_cast(__m256d,b); + return __builtin_bit_cast(vec_type,_mm256_sub_pd(amm,bmm)); + } + } + } + else if constexpr(sizeof(vec_type)==64) + { + if constexpr(std::integral&&::fast_io::details::cpu_flags::avx512bw_supported) + { + __m512i amm = __builtin_bit_cast(__m512i,a); + __m512i bmm = __builtin_bit_cast(__m512i,b); + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm512_sub_epi8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm512_sub_epi16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm512_sub_epi32(amm,bmm)); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm512_sub_epi64(amm,bmm)); + } + } + else if constexpr(std::floating_point&&::fast_io::details::cpu_flags::avx512f_supported) + { +#if !defined(__clang__) + if constexpr(sizeof(T)==sizeof(float)/2) + { + __m512h amm = __builtin_bit_cast(__m512h,a); + __m512h bmm = __builtin_bit_cast(__m512h,b); + return __builtin_bit_cast(vec_type,_mm512_sub_ph(amm,bmm)); + } + else +#endif + if constexpr(sizeof(T)==sizeof(float)) + { + __m512 amm = __builtin_bit_cast(__m512,a); + __m512 bmm = __builtin_bit_cast(__m512,b); + return __builtin_bit_cast(vec_type,_mm512_sub_ps(amm,bmm)); + } + else if constexpr(sizeof(T)==sizeof(double)) + { + __m512d amm = __builtin_bit_cast(__m512d,a); + __m512d bmm = __builtin_bit_cast(__m512d,b); + return __builtin_bit_cast(vec_type,_mm512_sub_pd(amm,bmm)); + } + } + } +#elif defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) || defined(__arm__) || defined(_M_ARM) + using vec_type = ::fast_io::intrinsics::simd_vector; + if constexpr(::fast_io::details::cpu_flags::armneon_supported) + { + if constexpr(std::integral) + { + if constexpr(sizeof(vec_type)==8) + { + if constexpr(sizeof(T)==1) + { + uint8x8_t amm = __builtin_bit_cast(uint8x8_t,a); + uint8x8_t bmm = __builtin_bit_cast(uint8x8_t,b); + return __builtin_bit_cast(vec_type,vsub_u8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x4_t amm = __builtin_bit_cast(uint16x4_t,a); + uint16x4_t bmm = __builtin_bit_cast(uint16x4_t,b); + return __builtin_bit_cast(vec_type,vsub_u16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x2_t amm = __builtin_bit_cast(uint32x2_t,a); + uint32x2_t bmm = __builtin_bit_cast(uint32x2_t,b); + return __builtin_bit_cast(vec_type,vsub_u32(amm,bmm)); + } + else if constexpr(sizeof(T)==8) + { + uint64x1_t amm = __builtin_bit_cast(uint64x1_t,a); + uint64x1_t bmm = __builtin_bit_cast(uint64x1_t,b); + return __builtin_bit_cast(vec_type,vsub_u64(amm,bmm)); + } + } + else if constexpr(sizeof(vec_type)==16) + { + if constexpr(sizeof(T)==1) + { + uint8x16_t amm = __builtin_bit_cast(uint8x16_t,a); + uint8x16_t bmm = __builtin_bit_cast(uint8x16_t,b); + return __builtin_bit_cast(vec_type,vsubq_u8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x8_t amm = __builtin_bit_cast(uint16x8_t,a); + uint16x8_t bmm = __builtin_bit_cast(uint16x8_t,b); + return __builtin_bit_cast(vec_type,vsubq_u16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x4_t amm = __builtin_bit_cast(uint32x4_t,a); + uint32x4_t bmm = __builtin_bit_cast(uint32x4_t,b); + return __builtin_bit_cast(vec_type,vsubq_u32(amm,bmm)); + } + else if constexpr(sizeof(T)==8) + { + uint64x2_t amm = __builtin_bit_cast(uint64x2_t,a); + uint64x2_t bmm = __builtin_bit_cast(uint64x2_t,b); + return __builtin_bit_cast(vec_type,vsubq_u64(amm,bmm)); + } + } + } + else if constexpr(std::floating_point) + { + if constexpr(sizeof(vec_type)==8) + { + if constexpr(sizeof(T)==sizeof(float)) + { + float32x2_t amm = __builtin_bit_cast(float32x2_t,a); + float32x2_t bmm = __builtin_bit_cast(float32x2_t,b); + return __builtin_bit_cast(vec_type,vsub_f32(amm,bmm)); + } +#if defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) + else if constexpr(sizeof(T)==sizeof(double)) + { + float64x1_t amm = __builtin_bit_cast(float64x1_t,a); + float64x1_t bmm = __builtin_bit_cast(float64x1_t,b); + return __builtin_bit_cast(vec_type,vsub_f64(amm,bmm)); + } +#endif + } + else if constexpr(sizeof(vec_type)==16) + { + if constexpr(sizeof(T)==sizeof(float)) + { + float32x4_t amm = __builtin_bit_cast(float32x4_t,a); + float32x4_t bmm = __builtin_bit_cast(float32x4_t,b); + return __builtin_bit_cast(vec_type,vsubq_f32(amm,bmm)); + } +#if defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) + else if constexpr(sizeof(T)==sizeof(double)) + { + float64x2_t amm = __builtin_bit_cast(float64x2_t,a); + float64x2_t bmm = __builtin_bit_cast(float64x2_t,b); + return __builtin_bit_cast(vec_type,vsubq_f32(amm,bmm)); + } +#endif + } + } + } +#endif + } + return ::fast_io::details::generic_simd_create_op_impl(a,b,[](T va,T vb) noexcept -> T + { + if constexpr(std::signed_integral) + { + using unsignedtype = std::make_unsigned_t; + return static_cast(static_cast(va)-static_cast(vb)); + } + else + { + return static_cast(va-vb); + } + }); +} + +template +requires (sizeoft*N< + ::std::numeric_limits::max()&&(sizeoft<=sizeof(std::uint_least64_t))) +inline constexpr auto create_byte_swap_mask() noexcept +{ + using T= + std::conditional_t>>; + constexpr std::size_t totaln{sizeoft*N}; + constexpr char unsigned resn{totaln}; + ::fast_io::freestanding::array v1; + for(char unsigned i{};i!=resn;++i) + { + v1[i]=i; + } + auto v2=__builtin_bit_cast(::fast_io::freestanding::array,v1); + for(auto & e : v2) + { + e=::fast_io::byte_swap(e); + } + return __builtin_bit_cast(::fast_io::intrinsics::simd_vector,v2); +} +template +inline constexpr auto simd_byte_swap_shuffle_mask{create_byte_swap_mask()}; + +} + +namespace intrinsics +{ + +template +inline constexpr simd_vector operator+(simd_vector const& a,simd_vector const& b) noexcept +{ + return ::fast_io::details::wrap_add_common(a,b); +} + +template +inline constexpr simd_vector wrap_add(simd_vector const& a,simd_vector const& b) noexcept +{ + return ::fast_io::details::wrap_add_common(a,b); +} + +template +inline constexpr simd_vector operator-(simd_vector const& a,simd_vector const& b) noexcept +{ + return ::fast_io::details::wrap_minus_common(a,b); +} + +template +inline constexpr simd_vector wrap_minus(simd_vector const& a,simd_vector const& b) noexcept +{ + return ::fast_io::details::wrap_minus_common(a,b); +} + +template +inline constexpr simd_vector operator*(simd_vector const& a,simd_vector const& b) noexcept +{ +#if __cpp_if_consteval >= 202106L + if !consteval +#else + if (!__builtin_is_constant_evaluated()) +#endif + { +#if (defined(__x86_64__) || defined(_M_AMD64) || defined(__i386__) || defined(_M_IX86)) + using vec_type = simd_vector; + if constexpr(sizeof(vec_type)==16&&::fast_io::details::cpu_flags::sse2_supported) + { + if constexpr(std::integral) + { + __m128i amm = __builtin_bit_cast(__m128i,a); + __m128i bmm = __builtin_bit_cast(__m128i,b); + if constexpr(std::signed_integral) + { + if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm_mul_epi32(amm,bmm)); + } + } + else + { + if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm_mul_epu32(amm,bmm)); + } + } + } + else if constexpr(std::floating_point) + { +#if !defined(__clang__) + if constexpr(sizeof(T)==sizeof(float)/2) + { + __m128h amm = __builtin_bit_cast(__m128h,a); + __m128h bmm = __builtin_bit_cast(__m128h,b); + return __builtin_bit_cast(vec_type,_mm_mul_ph(amm,bmm)); + } + else +#endif + if constexpr(sizeof(T)==sizeof(float)) + { + __m128 amm = __builtin_bit_cast(__m128,a); + __m128 bmm = __builtin_bit_cast(__m128,b); + return __builtin_bit_cast(vec_type,_mm_mul_ps(amm,bmm)); + } + else if constexpr(sizeof(T)==sizeof(double)) + { + __m128d amm = __builtin_bit_cast(__m128d,a); + __m128d bmm = __builtin_bit_cast(__m128d,b); + return __builtin_bit_cast(vec_type,_mm_mul_pd(amm,bmm)); + } + } + } + else if constexpr(sizeof(vec_type)==32&&::fast_io::details::cpu_flags::avx2_supported) + { + if constexpr(std::integral) + { + __m256i amm = __builtin_bit_cast(__m256i,a); + __m256i bmm = __builtin_bit_cast(__m256i,b); + if constexpr(std::signed_integral) + { + if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm256_mul_epi32(amm,bmm)); + } + } + else + { + if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm256_mul_epu32(amm,bmm)); + } + } + } + else if constexpr(std::floating_point) + { +#if !defined(__clang__) + if constexpr(sizeof(T)==sizeof(float)/2) + { + __m256h amm = __builtin_bit_cast(__m256h,a); + __m256h bmm = __builtin_bit_cast(__m256h,b); + return __builtin_bit_cast(vec_type,_mm256_mul_ph(amm,bmm)); + } + else +#endif + if constexpr(sizeof(T)==sizeof(float)) + { + __m256 amm = __builtin_bit_cast(__m256,a); + __m256 bmm = __builtin_bit_cast(__m256,b); + return __builtin_bit_cast(vec_type,_mm256_mul_ps(amm,bmm)); + } + else if constexpr(sizeof(T)==sizeof(double)) + { + __m256d amm = __builtin_bit_cast(__m256d,a); + __m256d bmm = __builtin_bit_cast(__m256d,b); + return __builtin_bit_cast(vec_type,_mm256_mul_pd(amm,bmm)); + } + } + } + else if constexpr(sizeof(vec_type)==64) + { + if constexpr(std::integral&&::fast_io::details::cpu_flags::avx512bw_supported) + { + __m512i amm = __builtin_bit_cast(__m512i,a); + __m512i bmm = __builtin_bit_cast(__m512i,b); + if constexpr(std::signed_integral) + { + if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm512_mul_epi32(amm,bmm)); + } + } + else + { + if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm512_mul_epu32(amm,bmm)); + } + } + } + else if constexpr(std::floating_point&&::fast_io::details::cpu_flags::avx512f_supported) + { +#if !defined(__clang__) + if constexpr(sizeof(T)==sizeof(float)/2) + { + __m512h amm = __builtin_bit_cast(__m512h,a); + __m512h bmm = __builtin_bit_cast(__m512h,b); + return __builtin_bit_cast(vec_type,_mm512_mul_ph(amm,bmm)); + } + else +#endif + if constexpr(sizeof(T)==sizeof(float)) + { + __m512 amm = __builtin_bit_cast(__m512,a); + __m512 bmm = __builtin_bit_cast(__m512,b); + return __builtin_bit_cast(vec_type,_mm512_mul_ps(amm,bmm)); + } + else if constexpr(sizeof(T)==sizeof(double)) + { + __m512d amm = __builtin_bit_cast(__m512d,a); + __m512d bmm = __builtin_bit_cast(__m512d,b); + return __builtin_bit_cast(vec_type,_mm512_mul_pd(amm,bmm)); + } + } + } +#elif defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) || defined(__arm__) || defined(_M_ARM) + using vec_type = simd_vector; + if constexpr(::fast_io::details::cpu_flags::armneon_supported) + { + if constexpr(std::unsigned_integral) + { + if constexpr(sizeof(vec_type)==8) + { + if constexpr(sizeof(T)==1) + { + uint8x8_t amm = __builtin_bit_cast(uint8x8_t,a); + uint8x8_t bmm = __builtin_bit_cast(uint8x8_t,b); + return __builtin_bit_cast(vec_type,vmul_u8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x4_t amm = __builtin_bit_cast(uint16x4_t,a); + uint16x4_t bmm = __builtin_bit_cast(uint16x4_t,b); + return __builtin_bit_cast(vec_type,vmul_u16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x2_t amm = __builtin_bit_cast(uint32x2_t,a); + uint32x2_t bmm = __builtin_bit_cast(uint32x2_t,b); + return __builtin_bit_cast(vec_type,vmul_u32(amm,bmm)); + } + } + else if constexpr(sizeof(vec_type)==16) + { + if constexpr(sizeof(T)==1) + { + uint8x16_t amm = __builtin_bit_cast(uint8x16_t,a); + uint8x16_t bmm = __builtin_bit_cast(uint8x16_t,b); + return __builtin_bit_cast(vec_type,vmulq_u8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x8_t amm = __builtin_bit_cast(uint16x8_t,a); + uint16x8_t bmm = __builtin_bit_cast(uint16x8_t,b); + return __builtin_bit_cast(vec_type,vmulq_u16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x4_t amm = __builtin_bit_cast(uint32x4_t,a); + uint32x4_t bmm = __builtin_bit_cast(uint32x4_t,b); + return __builtin_bit_cast(vec_type,vmulq_u32(amm,bmm)); + } + } + } + else if constexpr(std::signed_integral) + { + if constexpr(sizeof(vec_type)==8) + { + if constexpr(sizeof(T)==1) + { + int8x8_t amm = __builtin_bit_cast(int8x16_t,a); + int8x8_t bmm = __builtin_bit_cast(int8x16_t,b); + return __builtin_bit_cast(vec_type,vmul_s8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + int16x4_t amm = __builtin_bit_cast(int16x4_t,a); + int16x4_t bmm = __builtin_bit_cast(int16x4_t,b); + return __builtin_bit_cast(vec_type,vmul_s16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + int32x2_t amm = __builtin_bit_cast(int32x2_t,a); + int32x2_t bmm = __builtin_bit_cast(int32x2_t,b); + return __builtin_bit_cast(vec_type,vmul_s32(amm,bmm)); + } + } + else if constexpr(sizeof(vec_type)==16) + { + if constexpr(sizeof(T)==1) + { + int8x16_t amm = __builtin_bit_cast(int8x16_t,a); + int8x16_t bmm = __builtin_bit_cast(int8x16_t,b); + return __builtin_bit_cast(vec_type,vmulq_s8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + int16x8_t amm = __builtin_bit_cast(int16x8_t,a); + int16x8_t bmm = __builtin_bit_cast(int16x8_t,b); + return __builtin_bit_cast(vec_type,vmulq_s16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + int32x4_t amm = __builtin_bit_cast(int32x4_t,a); + int32x4_t bmm = __builtin_bit_cast(int32x4_t,b); + return __builtin_bit_cast(vec_type,vmulq_s32(amm,bmm)); + } + } + } + else if constexpr(std::floating_point) + { + if constexpr(sizeof(vec_type)==8) + { + if constexpr(sizeof(T)==sizeof(float)) + { + float32x2_t amm = __builtin_bit_cast(float32x2_t,a); + float32x2_t bmm = __builtin_bit_cast(float32x2_t,b); + return __builtin_bit_cast(vec_type,vmul_f32(amm,bmm)); + } +#if defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) + else if constexpr(sizeof(T)==sizeof(double)) + { + float64x1_t amm = __builtin_bit_cast(float64x1_t,a); + float64x1_t bmm = __builtin_bit_cast(float64x1_t,b); + return __builtin_bit_cast(vec_type,vmul_f64(amm,bmm)); + } +#endif + } + else if constexpr(sizeof(vec_type)==16) + { + if constexpr(sizeof(T)==sizeof(float)) + { + float32x4_t amm = __builtin_bit_cast(float32x4_t,a); + float32x4_t bmm = __builtin_bit_cast(float32x4_t,b); + return __builtin_bit_cast(vec_type,vmulq_f32(amm,bmm)); + } +#if defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) + else if constexpr(sizeof(T)==sizeof(double)) + { + float64x2_t amm = __builtin_bit_cast(float64x2_t,a); + float64x2_t bmm = __builtin_bit_cast(float64x2_t,b); + return __builtin_bit_cast(vec_type,vmulq_f64(amm,bmm)); + } +#endif + } + } + } +#endif + } + return ::fast_io::details::generic_simd_create_op_impl(a,b,[](T va,T vb) noexcept -> T + { + return va*vb; + }); +} + +template +inline constexpr simd_vector operator/(simd_vector const& a,simd_vector const& b) noexcept +{ +#if __cpp_if_consteval >= 202106L + if !consteval +#else + if (!__builtin_is_constant_evaluated()) +#endif + { +#if (defined(__x86_64__) || defined(_M_AMD64) || defined(__i386__) || defined(_M_IX86)) + using vec_type = simd_vector; + if constexpr(sizeof(vec_type)==16&&::fast_io::details::cpu_flags::sse2_supported) + { + if constexpr(std::integral) + { +#if __has_cpp_attribute(__gnu__::__vector_size__) + using vec2_type [[__gnu__::__vector_size__ (N*sizeof(T))]] = T; + vec2_type amm = __builtin_bit_cast(vec2_type,a); + vec2_type bmm = __builtin_bit_cast(vec2_type,b); + return __builtin_bit_cast(vec_type,(a/b)); +#else + __m128i amm = __builtin_bit_cast(__m128i,a); + __m128i bmm = __builtin_bit_cast(__m128i,b); + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm_div_epi8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm_div_epi16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm_div_epi32(amm,bmm)); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm_div_epi64(amm,bmm)); + } +#endif + } + else if constexpr(std::floating_point) + { +#if !defined(__clang__) + if constexpr(sizeof(T)==sizeof(float)/2) + { + __m128h amm = __builtin_bit_cast(__m128h,a); + __m128h bmm = __builtin_bit_cast(__m128h,b); + return __builtin_bit_cast(vec_type,_mm_div_ph(amm,bmm)); + } + else +#endif + if constexpr(sizeof(T)==sizeof(float)) + { + __m128 amm = __builtin_bit_cast(__m128,a); + __m128 bmm = __builtin_bit_cast(__m128,b); + return __builtin_bit_cast(vec_type,_mm_div_ps(amm,bmm)); + } + else if constexpr(sizeof(T)==sizeof(double)) + { + __m128d amm = __builtin_bit_cast(__m128d,a); + __m128d bmm = __builtin_bit_cast(__m128d,b); + return __builtin_bit_cast(vec_type,_mm_div_pd(amm,bmm)); + } + } + } + else if constexpr(sizeof(vec_type)==32&&::fast_io::details::cpu_flags::avx2_supported) + { + if constexpr(std::integral) + { +#if __has_cpp_attribute(__gnu__::__vector_size__) + using vec2_type [[__gnu__::__vector_size__ (N*sizeof(T))]] = T; + vec2_type amm = __builtin_bit_cast(vec2_type,a); + vec2_type bmm = __builtin_bit_cast(vec2_type,b); + return __builtin_bit_cast(vec_type,(a/b)); +#else + __m256i amm = __builtin_bit_cast(__m256i,a); + __m256i bmm = __builtin_bit_cast(__m256i,b); + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm256_div_epi8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm256_div_epi16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm256_div_epi32(amm,bmm)); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm256_div_epi64(amm,bmm)); + } +#endif + } + else if constexpr(std::floating_point) + { +#if !defined(__clang__) + if constexpr(sizeof(T)==sizeof(float)/2) + { + __m256h amm = __builtin_bit_cast(__m256h,a); + __m256h bmm = __builtin_bit_cast(__m256h,b); + return __builtin_bit_cast(vec_type,_mm256_div_ph(amm,bmm)); + } + else +#endif + if constexpr(sizeof(T)==sizeof(float)) + { + __m256 amm = __builtin_bit_cast(__m256,a); + __m256 bmm = __builtin_bit_cast(__m256,b); + return __builtin_bit_cast(vec_type,_mm256_div_ps(amm,bmm)); + } + else if constexpr(sizeof(T)==sizeof(double)) + { + __m256d amm = __builtin_bit_cast(__m256d,a); + __m256d bmm = __builtin_bit_cast(__m256d,b); + return __builtin_bit_cast(vec_type,_mm256_div_pd(amm,bmm)); + } + } + } + else if constexpr(sizeof(vec_type)==64) + { + if constexpr(std::integral&&::fast_io::details::cpu_flags::avx512bw_supported) + { +#if __has_cpp_attribute(__gnu__::__vector_size__) + using vec2_type [[__gnu__::__vector_size__ (N*sizeof(T))]] = T; + vec2_type amm = __builtin_bit_cast(vec2_type,a); + vec2_type bmm = __builtin_bit_cast(vec2_type,b); + return __builtin_bit_cast(vec_type,(a/b)); +#else + __m512i amm = __builtin_bit_cast(__m512i,a); + __m512i bmm = __builtin_bit_cast(__m512i,b); + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm512_div_epi8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm512_div_epi16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm512_div_epi32(amm,bmm)); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm512_div_epi64(amm,bmm)); + } +#endif + } + else if constexpr(std::floating_point&&::fast_io::details::cpu_flags::avx512f_supported) + { +#if !defined(__clang__) + if constexpr(sizeof(T)==sizeof(float)/2) + { + __m512h amm = __builtin_bit_cast(__m512h,a); + __m512h bmm = __builtin_bit_cast(__m512h,b); + return __builtin_bit_cast(vec_type,_mm512_div_ph(amm,bmm)); + } + else +#endif + if constexpr(sizeof(T)==sizeof(float)) + { + __m512 amm = __builtin_bit_cast(__m512,a); + __m512 bmm = __builtin_bit_cast(__m512,b); + return __builtin_bit_cast(vec_type,_mm512_div_ps(amm,bmm)); + } + else if constexpr(sizeof(T)==sizeof(double)) + { + __m512d amm = __builtin_bit_cast(__m512d,a); + __m512d bmm = __builtin_bit_cast(__m512d,b); + return __builtin_bit_cast(vec_type,_mm512_div_pd(amm,bmm)); + } + } + } +#elif defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) || defined(__arm__) || defined(_M_ARM) + using vec_type = simd_vector; + if constexpr(::fast_io::details::cpu_flags::armneon_supported) + { +#if defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) + if constexpr(std::floating_point) + { + if constexpr(sizeof(vec_type)==8) + { + if constexpr(sizeof(T)==sizeof(float)) + { + float32x2_t amm = __builtin_bit_cast(float32x2_t,a); + float32x2_t bmm = __builtin_bit_cast(float32x2_t,b); + return __builtin_bit_cast(vec_type,vdiv_f32(amm,bmm)); + } + else if constexpr(sizeof(T)==sizeof(double)) + { + float64x1_t amm = __builtin_bit_cast(float64x1_t,a); + float64x1_t bmm = __builtin_bit_cast(float64x1_t,b); + return __builtin_bit_cast(vec_type,vdiv_f64(amm,bmm)); + } + } + else if constexpr(sizeof(vec_type)==16) + { + if constexpr(sizeof(T)==sizeof(float)) + { + float32x4_t amm = __builtin_bit_cast(float32x4_t,a); + float32x4_t bmm = __builtin_bit_cast(float32x4_t,b); + return __builtin_bit_cast(vec_type,vdivq_f32(amm,bmm)); + } + else if constexpr(sizeof(T)==sizeof(double)) + { + float64x2_t amm = __builtin_bit_cast(float64x2_t,a); + float64x2_t bmm = __builtin_bit_cast(float64x2_t,b); + return __builtin_bit_cast(vec_type,vdivq_f64(amm,bmm)); + } + } + } +#endif + } +#endif + } + return ::fast_io::details::generic_simd_create_op_impl(a,b,[](T va,T vb) noexcept -> T + { + return va/vb; + }); +} + +template +inline constexpr simd_vector operator&(simd_vector const& a,simd_vector const& b) noexcept +{ +#if __cpp_if_consteval >= 202106L + if !consteval +#else + if (!__builtin_is_constant_evaluated()) +#endif + { +#if (defined(__x86_64__) || defined(_M_AMD64) || defined(__i386__) || defined(_M_IX86)) + using vec_type = simd_vector; + if constexpr(sizeof(vec_type)==16&&::fast_io::details::cpu_flags::sse2_supported) + { + __m128 amm = __builtin_bit_cast(__m128,a); + __m128 bmm = __builtin_bit_cast(__m128,b); + return __builtin_bit_cast(vec_type,_mm_and_ps(amm,bmm)); + } + else if constexpr(sizeof(vec_type)==32&&::fast_io::details::cpu_flags::avx_supported) + { + __m256 amm = __builtin_bit_cast(__m256,a); + __m256 bmm = __builtin_bit_cast(__m256,b); + return __builtin_bit_cast(vec_type,_mm256_and_ps(amm,bmm)); + } + else if constexpr(sizeof(vec_type)==64) + { + if constexpr(::fast_io::details::cpu_flags::avx512dq_supported) + { + __m512 amm = __builtin_bit_cast(__m512,a); + __m512 bmm = __builtin_bit_cast(__m512,b); + return __builtin_bit_cast(vec_type,_mm512_and_ps(amm,bmm)); + } + else if constexpr(::fast_io::details::cpu_flags::avx512f_supported) + { + __m512i amm = __builtin_bit_cast(__m512i,a); + __m512i bmm = __builtin_bit_cast(__m512i,b); + return __builtin_bit_cast(vec_type,_mm512_and_epi32(amm,bmm)); + } + } +#elif defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) || defined(__arm__) || defined(_M_ARM) + using vec_type = simd_vector; + if constexpr(::fast_io::details::cpu_flags::armneon_supported) + { + if constexpr(std::signed_integral) + { + if constexpr(sizeof(vec_type)==8) + { + if constexpr(sizeof(T)==1) + { + uint8x8_t amm = __builtin_bit_cast(uint8x8_t,a); + uint8x8_t bmm = __builtin_bit_cast(uint8x8_t,b); + return __builtin_bit_cast(vec_type,vand_s8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x4_t amm = __builtin_bit_cast(uint16x4_t,a); + uint16x4_t bmm = __builtin_bit_cast(uint16x4_t,b); + return __builtin_bit_cast(vec_type,vand_s16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x2_t amm = __builtin_bit_cast(uint32x2_t,a); + uint32x2_t bmm = __builtin_bit_cast(uint32x2_t,b); + return __builtin_bit_cast(vec_type,vand_s32(amm,bmm)); + } + else if constexpr(sizeof(T)==8) + { + uint64x1_t amm = __builtin_bit_cast(uint64x1_t,a); + uint64x1_t bmm = __builtin_bit_cast(uint64x1_t,b); + return __builtin_bit_cast(vec_type,vand_s64(amm,bmm)); + } + } + else if constexpr(sizeof(vec_type)==16) + { + if constexpr(sizeof(T)==1) + { + uint8x16_t amm = __builtin_bit_cast(uint8x16_t,a); + uint8x16_t bmm = __builtin_bit_cast(uint8x16_t,b); + return __builtin_bit_cast(vec_type,vandq_s8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x8_t amm = __builtin_bit_cast(uint16x8_t,a); + uint16x8_t bmm = __builtin_bit_cast(uint16x8_t,b); + return __builtin_bit_cast(vec_type,vandq_s16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x4_t amm = __builtin_bit_cast(uint32x4_t,a); + uint32x4_t bmm = __builtin_bit_cast(uint32x4_t,b); + return __builtin_bit_cast(vec_type,vandq_s32(amm,bmm)); + } + else if constexpr(sizeof(T)==8) + { + uint64x2_t amm = __builtin_bit_cast(uint64x2_t,a); + uint64x2_t bmm = __builtin_bit_cast(uint64x2_t,b); + return __builtin_bit_cast(vec_type,vandq_s64(amm,bmm)); + } + } + } + else if constexpr(std::unsigned_integral) + { + if constexpr(sizeof(vec_type)==8) + { + if constexpr(sizeof(T)==1) + { + uint8x8_t amm = __builtin_bit_cast(uint8x8_t,a); + uint8x8_t bmm = __builtin_bit_cast(uint8x8_t,b); + return __builtin_bit_cast(vec_type,vand_u8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x4_t amm = __builtin_bit_cast(uint16x4_t,a); + uint16x4_t bmm = __builtin_bit_cast(uint16x4_t,b); + return __builtin_bit_cast(vec_type,vand_u16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x2_t amm = __builtin_bit_cast(uint32x2_t,a); + uint32x2_t bmm = __builtin_bit_cast(uint32x2_t,b); + return __builtin_bit_cast(vec_type,vand_u32(amm,bmm)); + } + else if constexpr(sizeof(T)==8) + { + uint64x1_t amm = __builtin_bit_cast(uint64x1_t,a); + uint64x1_t bmm = __builtin_bit_cast(uint64x1_t,b); + return __builtin_bit_cast(vec_type,vand_u64(amm,bmm)); + } + } + else if constexpr(sizeof(vec_type)==16) + { + if constexpr(sizeof(T)==1) + { + uint8x16_t amm = __builtin_bit_cast(uint8x16_t,a); + uint8x16_t bmm = __builtin_bit_cast(uint8x16_t,b); + return __builtin_bit_cast(vec_type,vandq_u8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x8_t amm = __builtin_bit_cast(uint16x8_t,a); + uint16x8_t bmm = __builtin_bit_cast(uint16x8_t,b); + return __builtin_bit_cast(vec_type,vandq_u16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x4_t amm = __builtin_bit_cast(uint32x4_t,a); + uint32x4_t bmm = __builtin_bit_cast(uint32x4_t,b); + return __builtin_bit_cast(vec_type,vandq_u32(amm,bmm)); + } + else if constexpr(sizeof(T)==8) + { + uint64x2_t amm = __builtin_bit_cast(uint64x2_t,a); + uint64x2_t bmm = __builtin_bit_cast(uint64x2_t,b); + return __builtin_bit_cast(vec_type,vandq_u64(amm,bmm)); + } + } + } + } +#endif + } + return ::fast_io::details::generic_simd_create_op_impl(a,b,[](T va,T vb) noexcept -> T + { + return va&vb; + }); +} + +template +inline constexpr simd_vector operator|(simd_vector const& a,simd_vector const& b) noexcept +{ +#if __cpp_if_consteval >= 202106L + if !consteval +#else + if (!__builtin_is_constant_evaluated()) +#endif + { +#if (defined(__x86_64__) || defined(_M_AMD64) || defined(__i386__) || defined(_M_IX86)) + using vec_type = simd_vector; + if constexpr(sizeof(vec_type)==16&&::fast_io::details::cpu_flags::sse2_supported) + { + __m128 amm = __builtin_bit_cast(__m128,a); + __m128 bmm = __builtin_bit_cast(__m128,b); + return __builtin_bit_cast(vec_type,_mm_or_ps(amm,bmm)); + } + else if constexpr(sizeof(vec_type)==32&&::fast_io::details::cpu_flags::avx_supported) + { + __m256 amm = __builtin_bit_cast(__m256,a); + __m256 bmm = __builtin_bit_cast(__m256,b); + return __builtin_bit_cast(vec_type,_mm256_or_ps(amm,bmm)); + } + else if constexpr(sizeof(vec_type)==64) + { + if constexpr(::fast_io::details::cpu_flags::avx512dq_supported) + { + __m512 amm = __builtin_bit_cast(__m512,a); + __m512 bmm = __builtin_bit_cast(__m512,b); + return __builtin_bit_cast(vec_type,_mm512_or_ps(amm,bmm)); + } + else if constexpr(::fast_io::details::cpu_flags::avx512f_supported) + { + __m512i amm = __builtin_bit_cast(__m512i,a); + __m512i bmm = __builtin_bit_cast(__m512i,b); + return __builtin_bit_cast(vec_type,_mm512_or_epi32(amm,bmm)); + } + } +#elif defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) || defined(__arm__) || defined(_M_ARM) + using vec_type = simd_vector; + if constexpr(::fast_io::details::cpu_flags::armneon_supported) + { + if constexpr(std::signed_integral) + { + if constexpr(sizeof(vec_type)==8) + { + if constexpr(sizeof(T)==1) + { + uint8x8_t amm = __builtin_bit_cast(uint8x8_t,a); + uint8x8_t bmm = __builtin_bit_cast(uint8x8_t,b); + return __builtin_bit_cast(vec_type,vorr_s8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x4_t amm = __builtin_bit_cast(uint16x4_t,a); + uint16x4_t bmm = __builtin_bit_cast(uint16x4_t,b); + return __builtin_bit_cast(vec_type,vorr_s16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x2_t amm = __builtin_bit_cast(uint32x2_t,a); + uint32x2_t bmm = __builtin_bit_cast(uint32x2_t,b); + return __builtin_bit_cast(vec_type,vorr_s32(amm,bmm)); + } + else if constexpr(sizeof(T)==8) + { + uint64x1_t amm = __builtin_bit_cast(uint64x1_t,a); + uint64x1_t bmm = __builtin_bit_cast(uint64x1_t,b); + return __builtin_bit_cast(vec_type,vorr_s64(amm,bmm)); + } + } + else if constexpr(sizeof(vec_type)==16) + { + if constexpr(sizeof(T)==1) + { + uint8x16_t amm = __builtin_bit_cast(uint8x16_t,a); + uint8x16_t bmm = __builtin_bit_cast(uint8x16_t,b); + return __builtin_bit_cast(vec_type,vorrq_s8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x8_t amm = __builtin_bit_cast(uint16x8_t,a); + uint16x8_t bmm = __builtin_bit_cast(uint16x8_t,b); + return __builtin_bit_cast(vec_type,vorrq_s16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x4_t amm = __builtin_bit_cast(uint32x4_t,a); + uint32x4_t bmm = __builtin_bit_cast(uint32x4_t,b); + return __builtin_bit_cast(vec_type,vorrq_s32(amm,bmm)); + } + else if constexpr(sizeof(T)==8) + { + uint64x2_t amm = __builtin_bit_cast(uint64x2_t,a); + uint64x2_t bmm = __builtin_bit_cast(uint64x2_t,b); + return __builtin_bit_cast(vec_type,vorrq_s64(amm,bmm)); + } + } + } + else if constexpr(std::unsigned_integral) + { + if constexpr(sizeof(vec_type)==8) + { + if constexpr(sizeof(T)==1) + { + uint8x8_t amm = __builtin_bit_cast(uint8x8_t,a); + uint8x8_t bmm = __builtin_bit_cast(uint8x8_t,b); + return __builtin_bit_cast(vec_type,vorr_u8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x4_t amm = __builtin_bit_cast(uint16x4_t,a); + uint16x4_t bmm = __builtin_bit_cast(uint16x4_t,b); + return __builtin_bit_cast(vec_type,vorr_u16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x2_t amm = __builtin_bit_cast(uint32x2_t,a); + uint32x2_t bmm = __builtin_bit_cast(uint32x2_t,b); + return __builtin_bit_cast(vec_type,vorr_u32(amm,bmm)); + } + else if constexpr(sizeof(T)==8) + { + uint64x1_t amm = __builtin_bit_cast(uint64x1_t,a); + uint64x1_t bmm = __builtin_bit_cast(uint64x1_t,b); + return __builtin_bit_cast(vec_type,vorr_u64(amm,bmm)); + } + } + else if constexpr(sizeof(vec_type)==16) + { + if constexpr(sizeof(T)==1) + { + uint8x16_t amm = __builtin_bit_cast(uint8x16_t,a); + uint8x16_t bmm = __builtin_bit_cast(uint8x16_t,b); + return __builtin_bit_cast(vec_type,vorrq_u8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x8_t amm = __builtin_bit_cast(uint16x8_t,a); + uint16x8_t bmm = __builtin_bit_cast(uint16x8_t,b); + return __builtin_bit_cast(vec_type,vorrq_u16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x4_t amm = __builtin_bit_cast(uint32x4_t,a); + uint32x4_t bmm = __builtin_bit_cast(uint32x4_t,b); + return __builtin_bit_cast(vec_type,vorrq_u32(amm,bmm)); + } + else if constexpr(sizeof(T)==8) + { + uint64x2_t amm = __builtin_bit_cast(uint64x2_t,a); + uint64x2_t bmm = __builtin_bit_cast(uint64x2_t,b); + return __builtin_bit_cast(vec_type,vorrq_u64(amm,bmm)); + } + } + } + } +#endif + } + return ::fast_io::details::generic_simd_create_op_impl(a,b,[](T va,T vb) noexcept -> T + { + return va|vb; + }); +} + +template +inline constexpr simd_vector operator^(simd_vector const& a,simd_vector const& b) noexcept +{ +#if __cpp_if_consteval >= 202106L + if !consteval +#else + if (!__builtin_is_constant_evaluated()) +#endif + { +#if (defined(__x86_64__) || defined(_M_AMD64) || defined(__i386__) || defined(_M_IX86)) + using vec_type = simd_vector; + if constexpr(sizeof(vec_type)==16&&::fast_io::details::cpu_flags::sse2_supported) + { + __m128 amm = __builtin_bit_cast(__m128,a); + __m128 bmm = __builtin_bit_cast(__m128,b); + return __builtin_bit_cast(vec_type,_mm_xor_ps(amm,bmm)); + } + else if constexpr(sizeof(vec_type)==32&&::fast_io::details::cpu_flags::avx_supported) + { + __m256 amm = __builtin_bit_cast(__m256,a); + __m256 bmm = __builtin_bit_cast(__m256,b); + return __builtin_bit_cast(vec_type,_mm256_xor_ps(amm,bmm)); + } + else if constexpr(sizeof(vec_type)==64) + { + if constexpr(::fast_io::details::cpu_flags::avx512dq_supported) + { + __m512 amm = __builtin_bit_cast(__m512,a); + __m512 bmm = __builtin_bit_cast(__m512,b); + return __builtin_bit_cast(vec_type,_mm512_xor_ps(amm,bmm)); + } + else if constexpr(::fast_io::details::cpu_flags::avx512f_supported) + { + __m512i amm = __builtin_bit_cast(__m512i,a); + __m512i bmm = __builtin_bit_cast(__m512i,b); + return __builtin_bit_cast(vec_type,_mm512_xor_epi32(amm,bmm)); + } + } +#elif defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) || defined(__arm__) || defined(_M_ARM) + using vec_type = simd_vector; + if constexpr(::fast_io::details::cpu_flags::armneon_supported) + { + if constexpr(std::signed_integral) + { + if constexpr(sizeof(vec_type)==8) + { + if constexpr(sizeof(T)==1) + { + uint8x8_t amm = __builtin_bit_cast(uint8x8_t,a); + uint8x8_t bmm = __builtin_bit_cast(uint8x8_t,b); + return __builtin_bit_cast(vec_type,veor_s8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x4_t amm = __builtin_bit_cast(uint16x4_t,a); + uint16x4_t bmm = __builtin_bit_cast(uint16x4_t,b); + return __builtin_bit_cast(vec_type,veor_s16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x2_t amm = __builtin_bit_cast(uint32x2_t,a); + uint32x2_t bmm = __builtin_bit_cast(uint32x2_t,b); + return __builtin_bit_cast(vec_type,veor_s32(amm,bmm)); + } + else if constexpr(sizeof(T)==8) + { + uint64x1_t amm = __builtin_bit_cast(uint64x1_t,a); + uint64x1_t bmm = __builtin_bit_cast(uint64x1_t,b); + return __builtin_bit_cast(vec_type,veor_s64(amm,bmm)); + } + } + else if constexpr(sizeof(vec_type)==16) + { + if constexpr(sizeof(T)==1) + { + uint8x16_t amm = __builtin_bit_cast(uint8x16_t,a); + uint8x16_t bmm = __builtin_bit_cast(uint8x16_t,b); + return __builtin_bit_cast(vec_type,veorq_s8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x8_t amm = __builtin_bit_cast(uint16x8_t,a); + uint16x8_t bmm = __builtin_bit_cast(uint16x8_t,b); + return __builtin_bit_cast(vec_type,veorq_s16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x4_t amm = __builtin_bit_cast(uint32x4_t,a); + uint32x4_t bmm = __builtin_bit_cast(uint32x4_t,b); + return __builtin_bit_cast(vec_type,veorq_s32(amm,bmm)); + } + else if constexpr(sizeof(T)==8) + { + uint64x2_t amm = __builtin_bit_cast(uint64x2_t,a); + uint64x2_t bmm = __builtin_bit_cast(uint64x2_t,b); + return __builtin_bit_cast(vec_type,veorq_s64(amm,bmm)); + } + } + } + else if constexpr(std::unsigned_integral) + { + if constexpr(sizeof(vec_type)==8) + { + if constexpr(sizeof(T)==1) + { + uint8x8_t amm = __builtin_bit_cast(uint8x8_t,a); + uint8x8_t bmm = __builtin_bit_cast(uint8x8_t,b); + return __builtin_bit_cast(vec_type,veor_u8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x4_t amm = __builtin_bit_cast(uint16x4_t,a); + uint16x4_t bmm = __builtin_bit_cast(uint16x4_t,b); + return __builtin_bit_cast(vec_type,veor_u16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x2_t amm = __builtin_bit_cast(uint32x2_t,a); + uint32x2_t bmm = __builtin_bit_cast(uint32x2_t,b); + return __builtin_bit_cast(vec_type,veor_u32(amm,bmm)); + } + else if constexpr(sizeof(T)==8) + { + uint64x1_t amm = __builtin_bit_cast(uint64x1_t,a); + uint64x1_t bmm = __builtin_bit_cast(uint64x1_t,b); + return __builtin_bit_cast(vec_type,veor_u64(amm,bmm)); + } + } + else if constexpr(sizeof(vec_type)==16) + { + if constexpr(sizeof(T)==1) + { + uint8x16_t amm = __builtin_bit_cast(uint8x16_t,a); + uint8x16_t bmm = __builtin_bit_cast(uint8x16_t,b); + return __builtin_bit_cast(vec_type,veorq_u8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x8_t amm = __builtin_bit_cast(uint16x8_t,a); + uint16x8_t bmm = __builtin_bit_cast(uint16x8_t,b); + return __builtin_bit_cast(vec_type,veorq_u16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x4_t amm = __builtin_bit_cast(uint32x4_t,a); + uint32x4_t bmm = __builtin_bit_cast(uint32x4_t,b); + return __builtin_bit_cast(vec_type,veorq_u32(amm,bmm)); + } + else if constexpr(sizeof(T)==8) + { + uint64x2_t amm = __builtin_bit_cast(uint64x2_t,a); + uint64x2_t bmm = __builtin_bit_cast(uint64x2_t,b); + return __builtin_bit_cast(vec_type,veorq_u64(amm,bmm)); + } + } + } + } +#endif + } + return ::fast_io::details::generic_simd_create_op_impl(a,b,[](T va,T vb) noexcept -> T + { + return va^vb; + }); +} + +template +inline constexpr simd_vector operator<<(simd_vector const& a,simd_vector const& b) noexcept +{ +#if __cpp_if_consteval >= 202106L + if !consteval +#else + if (!__builtin_is_constant_evaluated()) +#endif + { +#if (defined(__x86_64__) || defined(_M_AMD64) || defined(__i386__) || defined(_M_IX86)) +#elif defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) || defined(__arm__) || defined(_M_ARM) + using vec_type = simd_vector; + if constexpr(::fast_io::details::cpu_flags::armneon_supported) + { + if constexpr(std::signed_integral) + { + if constexpr(sizeof(vec_type)==8) + { + if constexpr(sizeof(T)==1) + { + uint8x8_t amm = __builtin_bit_cast(uint8x8_t,a); + uint8x8_t bmm = __builtin_bit_cast(uint8x8_t,b); + return __builtin_bit_cast(vec_type,vshl_s8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x4_t amm = __builtin_bit_cast(uint16x4_t,a); + uint16x4_t bmm = __builtin_bit_cast(uint16x4_t,b); + return __builtin_bit_cast(vec_type,vshl_s16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x2_t amm = __builtin_bit_cast(uint32x2_t,a); + uint32x2_t bmm = __builtin_bit_cast(uint32x2_t,b); + return __builtin_bit_cast(vec_type,vshl_s32(amm,bmm)); + } + else if constexpr(sizeof(T)==8) + { + uint64x1_t amm = __builtin_bit_cast(uint64x1_t,a); + uint64x1_t bmm = __builtin_bit_cast(uint64x1_t,b); + return __builtin_bit_cast(vec_type,vshl_s64(amm,bmm)); + } + } + else if constexpr(sizeof(vec_type)==16) + { + if constexpr(sizeof(T)==1) + { + uint8x16_t amm = __builtin_bit_cast(uint8x16_t,a); + uint8x16_t bmm = __builtin_bit_cast(uint8x16_t,b); + return __builtin_bit_cast(vec_type,vshlq_s8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x8_t amm = __builtin_bit_cast(uint16x8_t,a); + uint16x8_t bmm = __builtin_bit_cast(uint16x8_t,b); + return __builtin_bit_cast(vec_type,vshlq_s16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x4_t amm = __builtin_bit_cast(uint32x4_t,a); + uint32x4_t bmm = __builtin_bit_cast(uint32x4_t,b); + return __builtin_bit_cast(vec_type,vshlq_s32(amm,bmm)); + } + else if constexpr(sizeof(T)==8) + { + uint64x2_t amm = __builtin_bit_cast(uint64x2_t,a); + uint64x2_t bmm = __builtin_bit_cast(uint64x2_t,b); + return __builtin_bit_cast(vec_type,vshlq_s64(amm,bmm)); + } + } + } + else if constexpr(std::unsigned_integral) + { + if constexpr(sizeof(vec_type)==8) + { + if constexpr(sizeof(T)==1) + { + uint8x8_t amm = __builtin_bit_cast(uint8x8_t,a); + uint8x8_t bmm = __builtin_bit_cast(uint8x8_t,b); + return __builtin_bit_cast(vec_type,vshl_u8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x4_t amm = __builtin_bit_cast(uint16x4_t,a); + uint16x4_t bmm = __builtin_bit_cast(uint16x4_t,b); + return __builtin_bit_cast(vec_type,vshl_u16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x2_t amm = __builtin_bit_cast(uint32x2_t,a); + uint32x2_t bmm = __builtin_bit_cast(uint32x2_t,b); + return __builtin_bit_cast(vec_type,vshl_u32(amm,bmm)); + } + else if constexpr(sizeof(T)==8) + { + uint64x1_t amm = __builtin_bit_cast(uint64x1_t,a); + uint64x1_t bmm = __builtin_bit_cast(uint64x1_t,b); + return __builtin_bit_cast(vec_type,vshl_u64(amm,bmm)); + } + } + else if constexpr(sizeof(vec_type)==16) + { + if constexpr(sizeof(T)==1) + { + uint8x16_t amm = __builtin_bit_cast(uint8x16_t,a); + uint8x16_t bmm = __builtin_bit_cast(uint8x16_t,b); + return __builtin_bit_cast(vec_type,vshlq_u8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x8_t amm = __builtin_bit_cast(uint16x8_t,a); + uint16x8_t bmm = __builtin_bit_cast(uint16x8_t,b); + return __builtin_bit_cast(vec_type,vshlq_u16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x4_t amm = __builtin_bit_cast(uint32x4_t,a); + uint32x4_t bmm = __builtin_bit_cast(uint32x4_t,b); + return __builtin_bit_cast(vec_type,vshlq_u32(amm,bmm)); + } + else if constexpr(sizeof(T)==8) + { + uint64x2_t amm = __builtin_bit_cast(uint64x2_t,a); + uint64x2_t bmm = __builtin_bit_cast(uint64x2_t,b); + return __builtin_bit_cast(vec_type,vshlq_u64(amm,bmm)); + } + } + } + } +#endif + } + return ::fast_io::details::generic_simd_create_op_impl(a,b,[](T va,T vb) noexcept -> T + { + return va< +inline constexpr simd_vector operator>>(simd_vector const& a,simd_vector const& b) noexcept +{ +#if __cpp_if_consteval >= 202106L + if !consteval +#else + if (!__builtin_is_constant_evaluated()) +#endif + { + } + return ::fast_io::details::generic_simd_create_op_impl(a,b,[](T va,T vb) noexcept -> T + { + return va>>vb; + }); +} + +template +inline constexpr simd_vector operator<<(simd_vector const& a,unsigned i) noexcept +{ +#if __cpp_if_consteval >= 202106L + if !consteval +#else + if (!__builtin_is_constant_evaluated()) +#endif + { +#if (defined(__x86_64__) || defined(_M_AMD64) || defined(__i386__) || defined(_M_IX86)) + using vec_type = simd_vector; + if constexpr(2<=sizeof(T)&&sizeof(T)<=8) + { + if constexpr(sizeof(vec_type)==16&&::fast_io::details::cpu_flags::sse2_supported) + { + __m128i amm = __builtin_bit_cast(__m128i,a); + if constexpr(sizeof(T)==2) + { + amm = _mm_slli_epi16(amm,i); + } + else if constexpr(sizeof(T)==4) + { + amm = _mm_slli_epi32(amm,i); + } + else if constexpr(sizeof(T)==8) + { + amm = _mm_slli_epi64(amm,i); + } + return __builtin_bit_cast(vec_type,amm); + } + else if constexpr(sizeof(vec_type)==32) + { + if constexpr(::fast_io::details::cpu_flags::avx2_supported) + { + __m256i amm = __builtin_bit_cast(__m256i,a); + if constexpr(sizeof(T)==2) + { + amm = _mm256_slli_epi16(amm,i); + } + else if constexpr(sizeof(T)==4) + { + amm = _mm256_slli_epi32(amm,i); + } + else if constexpr(sizeof(T)==8) + { + amm = _mm256_slli_epi64(amm,i); + } + return __builtin_bit_cast(vec_type,amm); + } + else if constexpr(::fast_io::details::cpu_flags::avx_supported) + { + __m256i amm = __builtin_bit_cast(__m256i,a); + __m128i alow = _mm256_castsi256_si128(amm); + __m128i ahigh = _mm256_extractf128_si256(amm,1); + if constexpr(sizeof(T)==2) + { + alow = _mm_slli_epi16(alow,i); + ahigh = _mm_slli_epi16(ahigh,i); + } + else if constexpr(sizeof(T)==4) + { + alow = _mm_slli_epi32(alow,i); + ahigh = _mm_slli_epi32(ahigh,i); + } + else if constexpr(sizeof(T)==8) + { + alow = _mm_slli_epi64(alow,i); + ahigh = _mm_slli_epi64(ahigh,i); + } + __m256i res = _mm256_castsi128_si256(alow); + res = _mm256_insertf128_si256(res,ahigh,1); + return __builtin_bit_cast(vec_type,res); + } + } + else if constexpr(sizeof(vec_type)==64) + { + if constexpr(::fast_io::details::cpu_flags::avx512bw_supported) + { + __m512i amm = __builtin_bit_cast(__m512i,a); + if constexpr(sizeof(T)==2) + { + amm = _mm512_slli_epi16(amm,i); + } + else if constexpr(sizeof(T)==4) + { + amm = _mm512_slli_epi32(amm,i); + } + else if constexpr(sizeof(T)==8) + { + amm = _mm512_slli_epi64(amm,i); + } + return __builtin_bit_cast(vec_type,amm); + } + } + } +#elif defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) || defined(__arm__) || defined(_M_ARM) + using vec_type = simd_vector; + if constexpr(::fast_io::details::cpu_flags::armneon_supported) + { + if constexpr(std::signed_integral) + { + if constexpr(sizeof(vec_type)==8) + { + if constexpr(sizeof(T)==1) + { + uint8x8_t amm = __builtin_bit_cast(uint8x8_t,a); + return __builtin_bit_cast(vec_type,vshl_n_s8(amm,static_cast(i))); + } + else if constexpr(sizeof(T)==2) + { + uint16x4_t amm = __builtin_bit_cast(uint16x4_t,a); + return __builtin_bit_cast(vec_type,vshl_n_s16(amm,static_cast(i))); + } + else if constexpr(sizeof(T)==4) + { + uint32x2_t amm = __builtin_bit_cast(uint32x2_t,a); + return __builtin_bit_cast(vec_type,vshl_n_s32(amm,static_cast(i))); + } + else if constexpr(sizeof(T)==8) + { + uint64x1_t amm = __builtin_bit_cast(uint64x1_t,a); + return __builtin_bit_cast(vec_type,vshl_n_s64(amm,static_cast(i))); + } + } + else if constexpr(sizeof(vec_type)==16) + { + if constexpr(sizeof(T)==1) + { + uint8x16_t amm = __builtin_bit_cast(uint8x16_t,a); + return __builtin_bit_cast(vec_type,vshlq_n_s8(amm,static_cast(i))); + } + else if constexpr(sizeof(T)==2) + { + uint16x8_t amm = __builtin_bit_cast(uint16x8_t,a); + return __builtin_bit_cast(vec_type,vshlq_n_s16(amm,static_cast(i))); + } + else if constexpr(sizeof(T)==4) + { + uint32x4_t amm = __builtin_bit_cast(uint32x4_t,a); + return __builtin_bit_cast(vec_type,vshlq_n_s32(amm,static_cast(i))); + } + else if constexpr(sizeof(T)==8) + { + uint64x2_t amm = __builtin_bit_cast(uint64x2_t,a); + return __builtin_bit_cast(vec_type,vshlq_n_s64(amm,static_cast(i))); + } + } + } + else if constexpr(std::unsigned_integral) + { + if constexpr(sizeof(vec_type)==8) + { + if constexpr(sizeof(T)==1) + { + uint8x8_t amm = __builtin_bit_cast(uint8x8_t,a); + return __builtin_bit_cast(vec_type,vshl_n_u8(amm,static_cast(i))); + } + else if constexpr(sizeof(T)==2) + { + uint16x4_t amm = __builtin_bit_cast(uint16x4_t,a); + return __builtin_bit_cast(vec_type,vshl_n_u16(amm,static_cast(i))); + } + else if constexpr(sizeof(T)==4) + { + uint32x2_t amm = __builtin_bit_cast(uint32x2_t,a); + return __builtin_bit_cast(vec_type,vshl_n_u32(amm,static_cast(i))); + } + else if constexpr(sizeof(T)==8) + { + uint64x1_t amm = __builtin_bit_cast(uint64x1_t,a); + return __builtin_bit_cast(vec_type,vshl_n_u64(amm,static_cast(i))); + } + } + else if constexpr(sizeof(vec_type)==16) + { + if constexpr(sizeof(T)==1) + { + uint8x16_t amm = __builtin_bit_cast(uint8x16_t,a); + return __builtin_bit_cast(vec_type,vshlq_n_u8(amm,static_cast(i))); + } + else if constexpr(sizeof(T)==2) + { + uint16x8_t amm = __builtin_bit_cast(uint16x8_t,a); + return __builtin_bit_cast(vec_type,vshlq_n_u16(amm,static_cast(i))); + } + else if constexpr(sizeof(T)==4) + { + uint32x4_t amm = __builtin_bit_cast(uint32x4_t,a); + return __builtin_bit_cast(vec_type,vshlq_n_u32(amm,static_cast(i))); + } + else if constexpr(sizeof(T)==8) + { + uint64x2_t amm = __builtin_bit_cast(uint64x2_t,a); + return __builtin_bit_cast(vec_type,vshlq_n_u64(amm,static_cast(i))); + } + } + } + } +#endif + } + return ::fast_io::details::generic_simd_self_create_op_impl(a,[i](T va) + { + return va< +inline constexpr simd_vector operator>>(simd_vector const& a,unsigned i) noexcept +{ +#if __cpp_if_consteval >= 202106L + if !consteval +#else + if (!__builtin_is_constant_evaluated()) +#endif + { +#if (defined(__x86_64__) || defined(_M_AMD64) || defined(__i386__) || defined(_M_IX86)) + using vec_type = simd_vector; + if constexpr(2<=sizeof(T)&&sizeof(T)<=8) + { + if constexpr(sizeof(vec_type)==16&&::fast_io::details::cpu_flags::sse2_supported) + { + __m128i amm = __builtin_bit_cast(__m128i,a); + if constexpr(sizeof(T)==2) + { + amm = _mm_srli_epi16(amm,i); + } + else if constexpr(sizeof(T)==4) + { + amm = _mm_srli_epi32(amm,i); + } + else if constexpr(sizeof(T)==8) + { + amm = _mm_srli_epi64(amm,i); + } + return __builtin_bit_cast(vec_type,amm); + } + else if constexpr(sizeof(vec_type)==32) + { + if constexpr(::fast_io::details::cpu_flags::avx2_supported) + { + __m256i amm = __builtin_bit_cast(__m256i,a); + if constexpr(sizeof(T)==2) + { + amm = _mm256_srli_epi16(amm,i); + } + else if constexpr(sizeof(T)==4) + { + amm = _mm256_srli_epi32(amm,i); + } + else if constexpr(sizeof(T)==8) + { + amm = _mm256_srli_epi64(amm,i); + } + return __builtin_bit_cast(vec_type,amm); + } + else if constexpr(::fast_io::details::cpu_flags::avx_supported) + { + __m256i amm = __builtin_bit_cast(__m256i,a); + __m128i alow = _mm256_castsi256_si128(amm); + __m128i ahigh = _mm256_extractf128_si256(amm,1); + if constexpr(sizeof(T)==2) + { + alow = _mm_srli_epi16(alow,i); + ahigh = _mm_srli_epi16(ahigh,i); + } + else if constexpr(sizeof(T)==4) + { + alow = _mm_srli_epi32(alow,i); + ahigh = _mm_srli_epi32(ahigh,i); + } + else if constexpr(sizeof(T)==8) + { + alow = _mm_srli_epi64(alow,i); + ahigh = _mm_srli_epi64(ahigh,i); + } + __m256i res = _mm256_castsi128_si256(alow); + res = _mm256_insertf128_si256(res,ahigh,1); + return __builtin_bit_cast(vec_type,res); + } + } + else if constexpr(sizeof(vec_type)==64) + { + if constexpr(::fast_io::details::cpu_flags::avx512bw_supported) + { + __m512i amm = __builtin_bit_cast(__m512i,a); + if constexpr(sizeof(T)==2) + { + amm = _mm512_srli_epi16(amm,i); + } + else if constexpr(sizeof(T)==4) + { + amm = _mm512_srli_epi32(amm,i); + } + else if constexpr(sizeof(T)==8) + { + amm = _mm512_srli_epi64(amm,i); + } + return __builtin_bit_cast(vec_type,amm); + } + } + } +#elif defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) || defined(__arm__) || defined(_M_ARM) + using vec_type = simd_vector; + if constexpr(::fast_io::details::cpu_flags::armneon_supported) + { + if constexpr(std::signed_integral) + { + if constexpr(sizeof(vec_type)==8) + { + if constexpr(sizeof(T)==1) + { + uint8x8_t amm = __builtin_bit_cast(uint8x8_t,a); + return __builtin_bit_cast(vec_type,vshr_n_s8(amm,static_cast(i))); + } + else if constexpr(sizeof(T)==2) + { + uint16x4_t amm = __builtin_bit_cast(uint16x4_t,a); + return __builtin_bit_cast(vec_type,vshr_n_s16(amm,static_cast(i))); + } + else if constexpr(sizeof(T)==4) + { + uint32x2_t amm = __builtin_bit_cast(uint32x2_t,a); + return __builtin_bit_cast(vec_type,vshr_n_s32(amm,static_cast(i))); + } + else if constexpr(sizeof(T)==8) + { + uint64x1_t amm = __builtin_bit_cast(uint64x1_t,a); + return __builtin_bit_cast(vec_type,vshr_n_s64(amm,static_cast(i))); + } + } + else if constexpr(sizeof(vec_type)==16) + { + if constexpr(sizeof(T)==1) + { + uint8x16_t amm = __builtin_bit_cast(uint8x16_t,a); + return __builtin_bit_cast(vec_type,vshrq_n_s8(amm,static_cast(i))); + } + else if constexpr(sizeof(T)==2) + { + uint16x8_t amm = __builtin_bit_cast(uint16x8_t,a); + return __builtin_bit_cast(vec_type,vshrq_n_s16(amm,static_cast(i))); + } + else if constexpr(sizeof(T)==4) + { + uint32x4_t amm = __builtin_bit_cast(uint32x4_t,a); + return __builtin_bit_cast(vec_type,vshrq_n_s32(amm,static_cast(i))); + } + else if constexpr(sizeof(T)==8) + { + uint64x2_t amm = __builtin_bit_cast(uint64x2_t,a); + return __builtin_bit_cast(vec_type,vshrq_n_s64(amm,static_cast(i))); + } + } + } + else if constexpr(std::unsigned_integral) + { + if constexpr(sizeof(vec_type)==8) + { + if constexpr(sizeof(T)==1) + { + uint8x8_t amm = __builtin_bit_cast(uint8x8_t,a); + return __builtin_bit_cast(vec_type,vshr_n_u8(amm,static_cast(i))); + } + else if constexpr(sizeof(T)==2) + { + uint16x4_t amm = __builtin_bit_cast(uint16x4_t,a); + return __builtin_bit_cast(vec_type,vshr_n_u16(amm,static_cast(i))); + } + else if constexpr(sizeof(T)==4) + { + uint32x2_t amm = __builtin_bit_cast(uint32x2_t,a); + return __builtin_bit_cast(vec_type,vshr_n_u32(amm,static_cast(i))); + } + else if constexpr(sizeof(T)==8) + { + uint64x1_t amm = __builtin_bit_cast(uint64x1_t,a); + return __builtin_bit_cast(vec_type,vshr_n_u64(amm,static_cast(i))); + } + } + else if constexpr(sizeof(vec_type)==16) + { + if constexpr(sizeof(T)==1) + { + uint8x16_t amm = __builtin_bit_cast(uint8x16_t,a); + return __builtin_bit_cast(vec_type,vshrq_n_u8(amm,static_cast(i))); + } + else if constexpr(sizeof(T)==2) + { + uint16x8_t amm = __builtin_bit_cast(uint16x8_t,a); + return __builtin_bit_cast(vec_type,vshrq_n_u16(amm,static_cast(i))); + } + else if constexpr(sizeof(T)==4) + { + uint32x4_t amm = __builtin_bit_cast(uint32x4_t,a); + return __builtin_bit_cast(vec_type,vshrq_n_u32(amm,static_cast(i))); + } + else if constexpr(sizeof(T)==8) + { + uint64x2_t amm = __builtin_bit_cast(uint64x2_t,a); + return __builtin_bit_cast(vec_type,vshrq_n_u64(amm,static_cast(i))); + } + } + } + } +#endif + } + return ::fast_io::details::generic_simd_self_create_op_impl(a,[i](T va) + { + return va>>i; + }); +} + +template +inline constexpr simd_vector operator<(simd_vector const& a,simd_vector const& b) noexcept +{ +#if __cpp_if_consteval >= 202106L + if !consteval +#else + if (!__builtin_is_constant_evaluated()) +#endif + { +#if (defined(__x86_64__) || defined(_M_AMD64) || defined(__i386__) || defined(_M_IX86)) + using vec_type = ::fast_io::intrinsics::simd_vector; + if constexpr(sizeof(vec_type)==16&&::fast_io::details::cpu_flags::sse2_supported) + { + if constexpr(std::integral) + { + if constexpr(::fast_io::details::cpu_flags::avx512vl_supported&& + ::fast_io::details::cpu_flags::avx512bw_supported) + { + __m128i amm = __builtin_bit_cast(__m128i,a); + __m128i bmm = __builtin_bit_cast(__m128i,b); + if constexpr(std::signed_integral) + { + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm_movm_epi8(_mm_cmplt_epi8_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm_movm_epi16(_mm_cmplt_epi16_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm_movm_epi32(_mm_cmplt_epi32_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm_movm_epi64(_mm_cmplt_epi64_mask(amm,bmm))); + } + } + else + { + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm_movm_epi8(_mm_cmplt_epu8_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm_movm_epi16(_mm_cmplt_epu16_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm_movm_epi32(_mm_cmplt_epu32_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm_movm_epi64(_mm_cmplt_epu64_mask(amm,bmm))); + } + } + } + else if constexpr(sizeof(T)<=4) + { + __m128i amm = __builtin_bit_cast(__m128i,a); + __m128i bmm = __builtin_bit_cast(__m128i,b); + if constexpr(std::unsigned_integral) + { + __m128i mask; + if constexpr(sizeof(T)==1) + { + constexpr auto mn{INT_LEAST8_MIN}; + mask=_mm_set1_epi8(mn); + } + else if constexpr(sizeof(T)==2) + { + constexpr auto mn{INT_LEAST16_MIN}; + mask=_mm_set1_epi16(mn); + } + else if constexpr(sizeof(T)==4) + { + constexpr auto mn{INT_LEAST32_MIN}; + mask=_mm_set1_epi32(mn); + } + amm=_mm_xor_si128(amm,mask); + bmm=_mm_xor_si128(bmm,mask); + } + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm_cmplt_epi8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm_cmplt_epi16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm_cmplt_epi32(amm,bmm)); + } + } + } + else if constexpr(std::floating_point) + { + if constexpr(sizeof(T)==sizeof(float)) + { + __m256 amm = __builtin_bit_cast(__m256,a); + __m256 bmm = __builtin_bit_cast(__m256,b); + return __builtin_bit_cast(vec_type,_mm256_cmp_ps(amm,bmm,_CMP_LT_OS)); + } + else if constexpr(sizeof(T)==sizeof(double)) + { + __m256d amm = __builtin_bit_cast(__m256d,a); + __m256d bmm = __builtin_bit_cast(__m256d,b); + return __builtin_bit_cast(vec_type,_mm256_cmp_pd(amm,bmm,_CMP_LT_OS)); + } + } + } + else if constexpr(sizeof(vec_type)==32&&::fast_io::details::cpu_flags::avx2_supported) + { + if constexpr(std::integral) + { + if constexpr(::fast_io::details::cpu_flags::avx512vl_supported&& + ::fast_io::details::cpu_flags::avx512bw_supported) + { + __m256i amm = __builtin_bit_cast(__m256i,a); + __m256i bmm = __builtin_bit_cast(__m256i,b); + if constexpr(std::signed_integral) + { + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm256_movm_epi8(_mm256_cmplt_epi8_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm256_movm_epi16(_mm256_cmplt_epi16_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm256_movm_epi32(_mm256_cmplt_epi32_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm256_movm_epi64(_mm256_cmplt_epi64_mask(amm,bmm))); + } + } + else + { + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm256_movm_epi8(_mm256_cmplt_epu8_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm256_movm_epi16(_mm256_cmplt_epu16_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm256_movm_epi32(_mm256_cmplt_epu32_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm256_movm_epi64(_mm256_cmplt_epu64_mask(amm,bmm))); + } + } + } + else if constexpr(sizeof(T)<=4) + { + __m256i amm = __builtin_bit_cast(__m256i,a); + __m256i bmm = __builtin_bit_cast(__m256i,b); + if constexpr(std::unsigned_integral) + { + __m256i mask; + if constexpr(sizeof(T)==1) + { + constexpr auto mn{INT_LEAST8_MIN}; + mask=_mm256_set1_epi8(mn); + } + else if constexpr(sizeof(T)==2) + { + constexpr auto mn{INT_LEAST16_MIN}; + mask=_mm256_set1_epi16(mn); + } + else if constexpr(sizeof(T)==4) + { + constexpr auto mn{INT_LEAST32_MIN}; + mask=_mm256_set1_epi32(mn); + } + amm=_mm256_xor_si256(amm,mask); + bmm=_mm256_xor_si256(bmm,mask); + } + __m128i alow = _mm256_castsi256_si128(amm); + __m128i blow = _mm256_castsi256_si128(bmm); + __m128i ahigh = _mm256_extractf128_si256(amm,1); + __m128i bhigh = _mm256_extractf128_si256(bmm,1); + + if constexpr(sizeof(T)==1) + { + alow = _mm_cmplt_epi8(alow,blow); + ahigh = _mm_cmplt_epi8(ahigh,bhigh); + } + else if constexpr(sizeof(T)==2) + { + alow = _mm_cmplt_epi16(alow,blow); + ahigh = _mm_cmplt_epi16(ahigh,bhigh); + } + else if constexpr(sizeof(T)==4) + { + alow = _mm_cmplt_epi32(alow,blow); + ahigh = _mm_cmplt_epi32(ahigh,bhigh); + } + __m256i res = _mm256_castsi128_si256(alow); + res = _mm256_insertf128_si256(res,ahigh,1); + return __builtin_bit_cast(vec_type,res); + } + } + else if constexpr(std::floating_point) + { + if constexpr(sizeof(T)==sizeof(float)) + { + __m256 amm = __builtin_bit_cast(__m256,a); + __m256 bmm = __builtin_bit_cast(__m256,b); + return __builtin_bit_cast(vec_type,_mm256_cmp_ps(amm,bmm,_CMP_LT_OS)); + } + else if constexpr(sizeof(T)==sizeof(double)) + { + __m256d amm = __builtin_bit_cast(__m256d,a); + __m256d bmm = __builtin_bit_cast(__m256d,b); + return __builtin_bit_cast(vec_type,_mm256_cmp_pd(amm,bmm,_CMP_LT_OS)); + } + } + } + else if constexpr(sizeof(vec_type)==64) + { + if constexpr(std::integral&&::fast_io::details::cpu_flags::avx512bw_supported) + { + __m512i amm = __builtin_bit_cast(__m512i,a); + __m512i bmm = __builtin_bit_cast(__m512i,b); + if constexpr(std::signed_integral) + { + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi8(_mm512_cmplt_epi8_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi16(_mm512_cmplt_epi16_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi32(_mm512_cmplt_epi32_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi64(_mm512_cmplt_epi64_mask(amm,bmm))); + } + } + else + { + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi8(_mm512_cmplt_epu8_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi16(_mm512_cmplt_epu16_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi32(_mm512_cmplt_epu32_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi64(_mm512_cmplt_epu64_mask(amm,bmm))); + } + } + } + else if constexpr(std::floating_point&&::fast_io::details::cpu_flags::avx512f_supported) + { + if constexpr(sizeof(T)==sizeof(float)) + { + __m512 amm = __builtin_bit_cast(__m512,a); + __m512 bmm = __builtin_bit_cast(__m512,b); + return __builtin_bit_cast(vec_type,_mm512_movm_epi32(_mm512_cmplt_ps_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==sizeof(double)) + { + __m512d amm = __builtin_bit_cast(__m512d,a); + __m512d bmm = __builtin_bit_cast(__m512d,b); + return __builtin_bit_cast(vec_type,_mm512_movm_epi64(_mm512_cmplt_pd_mask(amm,bmm))); + } + } + } +#elif defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) || defined(__arm__) || defined(_M_ARM) + using vec_type = simd_vector; + if constexpr(::fast_io::details::cpu_flags::armneon_supported) + { + if constexpr(std::signed_integral) + { + if constexpr(sizeof(vec_type)==8) + { + if constexpr(sizeof(T)==1) + { + uint8x8_t amm = __builtin_bit_cast(uint8x8_t,a); + uint8x8_t bmm = __builtin_bit_cast(uint8x8_t,b); + return __builtin_bit_cast(vec_type,vclt_s8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x4_t amm = __builtin_bit_cast(uint16x4_t,a); + uint16x4_t bmm = __builtin_bit_cast(uint16x4_t,b); + return __builtin_bit_cast(vec_type,vclt_s16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x2_t amm = __builtin_bit_cast(uint32x2_t,a); + uint32x2_t bmm = __builtin_bit_cast(uint32x2_t,b); + return __builtin_bit_cast(vec_type,vclt_s32(amm,bmm)); + } +#if defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) + else if constexpr(sizeof(T)==8) + { + uint64x1_t amm = __builtin_bit_cast(uint64x1_t,a); + uint64x1_t bmm = __builtin_bit_cast(uint64x1_t,b); + return __builtin_bit_cast(vec_type,vclt_s64(amm,bmm)); + } +#endif + } + else if constexpr(sizeof(vec_type)==16) + { + if constexpr(sizeof(T)==1) + { + uint8x16_t amm = __builtin_bit_cast(uint8x16_t,a); + uint8x16_t bmm = __builtin_bit_cast(uint8x16_t,b); + return __builtin_bit_cast(vec_type,vcltq_s8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x8_t amm = __builtin_bit_cast(uint16x8_t,a); + uint16x8_t bmm = __builtin_bit_cast(uint16x8_t,b); + return __builtin_bit_cast(vec_type,vcltq_s16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x4_t amm = __builtin_bit_cast(uint32x4_t,a); + uint32x4_t bmm = __builtin_bit_cast(uint32x4_t,b); + return __builtin_bit_cast(vec_type,vcltq_s32(amm,bmm)); + } +#if defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) + else if constexpr(sizeof(T)==8) + { + uint64x2_t amm = __builtin_bit_cast(uint64x2_t,a); + uint64x2_t bmm = __builtin_bit_cast(uint64x2_t,b); + return __builtin_bit_cast(vec_type,vcltq_s64(amm,bmm)); + } +#endif + } + } + else if constexpr(std::unsigned_integral) + { + if constexpr(sizeof(vec_type)==8) + { + if constexpr(sizeof(T)==1) + { + uint8x8_t amm = __builtin_bit_cast(uint8x8_t,a); + uint8x8_t bmm = __builtin_bit_cast(uint8x8_t,b); + return __builtin_bit_cast(vec_type,vclt_u8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x4_t amm = __builtin_bit_cast(uint16x4_t,a); + uint16x4_t bmm = __builtin_bit_cast(uint16x4_t,b); + return __builtin_bit_cast(vec_type,vclt_u16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x2_t amm = __builtin_bit_cast(uint32x2_t,a); + uint32x2_t bmm = __builtin_bit_cast(uint32x2_t,b); + return __builtin_bit_cast(vec_type,vclt_u32(amm,bmm)); + } +#if defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) + else if constexpr(sizeof(T)==8) + { + uint64x1_t amm = __builtin_bit_cast(uint64x1_t,a); + uint64x1_t bmm = __builtin_bit_cast(uint64x1_t,b); + return __builtin_bit_cast(vec_type,vclt_u64(amm,bmm)); + } +#endif + } + else if constexpr(sizeof(vec_type)==16) + { + if constexpr(sizeof(T)==1) + { + uint8x16_t amm = __builtin_bit_cast(uint8x16_t,a); + uint8x16_t bmm = __builtin_bit_cast(uint8x16_t,b); + return __builtin_bit_cast(vec_type,vcltq_u8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x8_t amm = __builtin_bit_cast(uint16x8_t,a); + uint16x8_t bmm = __builtin_bit_cast(uint16x8_t,b); + return __builtin_bit_cast(vec_type,vcltq_u16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x4_t amm = __builtin_bit_cast(uint32x4_t,a); + uint32x4_t bmm = __builtin_bit_cast(uint32x4_t,b); + return __builtin_bit_cast(vec_type,vcltq_u32(amm,bmm)); + } +#if defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) + else if constexpr(sizeof(T)==8) + { + uint64x2_t amm = __builtin_bit_cast(uint64x2_t,a); + uint64x2_t bmm = __builtin_bit_cast(uint64x2_t,b); + return __builtin_bit_cast(vec_type,vcltq_u64(amm,bmm)); + } +#endif + } + } + } +#endif + } + return ::fast_io::details::generic_simd_comparision_common_impl(a,b,[](T va,T vb) noexcept -> bool + { + return va +inline constexpr simd_vector operator>(simd_vector const& a,simd_vector const& b) noexcept +{ +#if __cpp_if_consteval >= 202106L + if !consteval +#else + if (!__builtin_is_constant_evaluated()) +#endif + { +#if (defined(__x86_64__) || defined(_M_AMD64) || defined(__i386__) || defined(_M_IX86)) + using vec_type = ::fast_io::intrinsics::simd_vector; + if constexpr(sizeof(vec_type)==16&&::fast_io::details::cpu_flags::sse2_supported) + { + if constexpr(std::integral) + { + if constexpr(::fast_io::details::cpu_flags::avx512vl_supported&& + ::fast_io::details::cpu_flags::avx512bw_supported) + { + __m128i amm = __builtin_bit_cast(__m128i,a); + __m128i bmm = __builtin_bit_cast(__m128i,b); + if constexpr(std::signed_integral) + { + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm_movm_epi8(_mm_cmpgt_epi8_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm_movm_epi16(_mm_cmpgt_epi16_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm_movm_epi32(_mm_cmpgt_epi32_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm_movm_epi64(_mm_cmpgt_epi64_mask(amm,bmm))); + } + } + else + { + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm_movm_epi8(_mm_cmpgt_epu8_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm_movm_epi16(_mm_cmpgt_epu16_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm_movm_epi32(_mm_cmpgt_epu32_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm_movm_epi64(_mm_cmpgt_epu64_mask(amm,bmm))); + } + } + } + else if constexpr(sizeof(T)<=4) + { + __m128i amm = __builtin_bit_cast(__m128i,a); + __m128i bmm = __builtin_bit_cast(__m128i,b); + if constexpr(std::unsigned_integral) + { + __m128i mask; + if constexpr(sizeof(T)==1) + { + constexpr auto mn{INT_LEAST8_MIN}; + mask=_mm_set1_epi8(mn); + } + else if constexpr(sizeof(T)==2) + { + constexpr auto mn{INT_LEAST16_MIN}; + mask=_mm_set1_epi16(mn); + } + else if constexpr(sizeof(T)==4) + { + constexpr auto mn{INT_LEAST32_MIN}; + mask=_mm_set1_epi32(mn); + } + amm=_mm_xor_si128(amm,mask); + bmm=_mm_xor_si128(bmm,mask); + } + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm_cmpgt_epi8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm_cmpgt_epi16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm_cmpgt_epi32(amm,bmm)); + } + } + } + else if constexpr(std::floating_point) + { + if constexpr(sizeof(T)==sizeof(float)) + { + __m256 amm = __builtin_bit_cast(__m256,a); + __m256 bmm = __builtin_bit_cast(__m256,b); + return __builtin_bit_cast(vec_type,_mm256_cmp_ps(amm,bmm,_CMP_GT_OS)); + } + else if constexpr(sizeof(T)==sizeof(double)) + { + __m256d amm = __builtin_bit_cast(__m256d,a); + __m256d bmm = __builtin_bit_cast(__m256d,b); + return __builtin_bit_cast(vec_type,_mm256_cmp_pd(amm,bmm,_CMP_GT_OS)); + } + } + } + else if constexpr(sizeof(vec_type)==32&&::fast_io::details::cpu_flags::avx2_supported) + { + if constexpr(std::integral) + { + if constexpr(::fast_io::details::cpu_flags::avx512vl_supported&& + ::fast_io::details::cpu_flags::avx512bw_supported) + { + __m256i amm = __builtin_bit_cast(__m256i,a); + __m256i bmm = __builtin_bit_cast(__m256i,b); + if constexpr(std::signed_integral) + { + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm256_movm_epi8(_mm256_cmpgt_epi8_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm256_movm_epi16(_mm256_cmpgt_epi16_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm256_movm_epi32(_mm256_cmpgt_epi32_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm256_movm_epi64(_mm256_cmpgt_epi64_mask(amm,bmm))); + } + } + else + { + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm256_movm_epi8(_mm256_cmpgt_epu8_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm256_movm_epi16(_mm256_cmpgt_epu16_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm256_movm_epi32(_mm256_cmpgt_epu32_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm256_movm_epi64(_mm256_cmpgt_epu64_mask(amm,bmm))); + } + } + } + else if constexpr(sizeof(T)<=4) + { + __m256i amm = __builtin_bit_cast(__m256i,a); + __m256i bmm = __builtin_bit_cast(__m256i,b); + if constexpr(std::unsigned_integral) + { + __m256i mask; + if constexpr(sizeof(T)==1) + { + constexpr auto mn{INT_LEAST8_MIN}; + mask=_mm256_set1_epi8(mn); + } + else if constexpr(sizeof(T)==2) + { + constexpr auto mn{INT_LEAST16_MIN}; + mask=_mm256_set1_epi16(mn); + } + else if constexpr(sizeof(T)==4) + { + constexpr auto mn{INT_LEAST32_MIN}; + mask=_mm256_set1_epi32(mn); + } + amm=_mm256_xor_si256(amm,mask); + bmm=_mm256_xor_si256(bmm,mask); + } + __m128i alow = _mm256_castsi256_si128(amm); + __m128i blow = _mm256_castsi256_si128(bmm); + __m128i ahigh = _mm256_extractf128_si256(amm,1); + __m128i bhigh = _mm256_extractf128_si256(bmm,1); + + if constexpr(sizeof(T)==1) + { + alow = _mm_cmpgt_epi8(alow,blow); + ahigh = _mm_cmpgt_epi8(ahigh,bhigh); + } + else if constexpr(sizeof(T)==2) + { + alow = _mm_cmpgt_epi16(alow,blow); + ahigh = _mm_cmpgt_epi16(ahigh,bhigh); + } + else if constexpr(sizeof(T)==4) + { + alow = _mm_cmpgt_epi32(alow,blow); + ahigh = _mm_cmpgt_epi32(ahigh,bhigh); + } + __m256i res = _mm256_castsi128_si256(alow); + res = _mm256_insertf128_si256(res,ahigh,1); + return __builtin_bit_cast(vec_type,res); + } + } + else if constexpr(std::floating_point) + { + if constexpr(sizeof(T)==sizeof(float)) + { + __m256 amm = __builtin_bit_cast(__m256,a); + __m256 bmm = __builtin_bit_cast(__m256,b); + return __builtin_bit_cast(vec_type,_mm256_cmp_ps(amm,bmm,_CMP_GT_OS)); + } + else if constexpr(sizeof(T)==sizeof(double)) + { + __m256d amm = __builtin_bit_cast(__m256d,a); + __m256d bmm = __builtin_bit_cast(__m256d,b); + return __builtin_bit_cast(vec_type,_mm256_cmp_pd(amm,bmm,_CMP_GT_OS)); + } + } + } + else if constexpr(sizeof(vec_type)==64) + { + if constexpr(std::integral&&::fast_io::details::cpu_flags::avx512bw_supported) + { + __m512i amm = __builtin_bit_cast(__m512i,a); + __m512i bmm = __builtin_bit_cast(__m512i,b); + if constexpr(std::signed_integral) + { + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi8(_mm512_cmpgt_epi8_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi16(_mm512_cmpgt_epi16_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi32(_mm512_cmpgt_epi32_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi64(_mm512_cmpgt_epi64_mask(amm,bmm))); + } + } + else + { + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi8(_mm512_cmpgt_epu8_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi16(_mm512_cmpgt_epu16_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi32(_mm512_cmpgt_epu32_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi64(_mm512_cmpgt_epu64_mask(amm,bmm))); + } + } + } + else if constexpr(std::floating_point&&::fast_io::details::cpu_flags::avx512f_supported) + { + if constexpr(sizeof(T)==sizeof(float)) + { + __m512 amm = __builtin_bit_cast(__m512,a); + __m512 bmm = __builtin_bit_cast(__m512,b); + return __builtin_bit_cast(vec_type,_mm512_movm_epi32(_mm512_cmp_ps_mask(amm,bmm,_CMP_GT_OS))); + } + else if constexpr(sizeof(T)==sizeof(double)) + { + __m512d amm = __builtin_bit_cast(__m512d,a); + __m512d bmm = __builtin_bit_cast(__m512d,b); + return __builtin_bit_cast(vec_type,_mm512_movm_epi64(_mm512_cmp_pd_mask(amm,bmm,_CMP_GT_OS))); + } + } + } +#elif defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) || defined(__arm__) || defined(_M_ARM) + using vec_type = simd_vector; + if constexpr(::fast_io::details::cpu_flags::armneon_supported) + { + if constexpr(std::signed_integral) + { + if constexpr(sizeof(vec_type)==8) + { + if constexpr(sizeof(T)==1) + { + uint8x8_t amm = __builtin_bit_cast(uint8x8_t,a); + uint8x8_t bmm = __builtin_bit_cast(uint8x8_t,b); + return __builtin_bit_cast(vec_type,vcgt_s8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x4_t amm = __builtin_bit_cast(uint16x4_t,a); + uint16x4_t bmm = __builtin_bit_cast(uint16x4_t,b); + return __builtin_bit_cast(vec_type,vcgt_s16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x2_t amm = __builtin_bit_cast(uint32x2_t,a); + uint32x2_t bmm = __builtin_bit_cast(uint32x2_t,b); + return __builtin_bit_cast(vec_type,vcgt_s32(amm,bmm)); + } +#if defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) + else if constexpr(sizeof(T)==8) + { + uint64x1_t amm = __builtin_bit_cast(uint64x1_t,a); + uint64x1_t bmm = __builtin_bit_cast(uint64x1_t,b); + return __builtin_bit_cast(vec_type,vcgt_s64(amm,bmm)); + } +#endif + } + else if constexpr(sizeof(vec_type)==16) + { + if constexpr(sizeof(T)==1) + { + uint8x16_t amm = __builtin_bit_cast(uint8x16_t,a); + uint8x16_t bmm = __builtin_bit_cast(uint8x16_t,b); + return __builtin_bit_cast(vec_type,vcgtq_s8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x8_t amm = __builtin_bit_cast(uint16x8_t,a); + uint16x8_t bmm = __builtin_bit_cast(uint16x8_t,b); + return __builtin_bit_cast(vec_type,vcgtq_s16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x4_t amm = __builtin_bit_cast(uint32x4_t,a); + uint32x4_t bmm = __builtin_bit_cast(uint32x4_t,b); + return __builtin_bit_cast(vec_type,vcgtq_s32(amm,bmm)); + } +#if defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) + else if constexpr(sizeof(T)==8) + { + uint64x2_t amm = __builtin_bit_cast(uint64x2_t,a); + uint64x2_t bmm = __builtin_bit_cast(uint64x2_t,b); + return __builtin_bit_cast(vec_type,vcgtq_s64(amm,bmm)); + } +#endif + } + } + else if constexpr(std::unsigned_integral) + { + if constexpr(sizeof(vec_type)==8) + { + if constexpr(sizeof(T)==1) + { + uint8x8_t amm = __builtin_bit_cast(uint8x8_t,a); + uint8x8_t bmm = __builtin_bit_cast(uint8x8_t,b); + return __builtin_bit_cast(vec_type,vcgt_u8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x4_t amm = __builtin_bit_cast(uint16x4_t,a); + uint16x4_t bmm = __builtin_bit_cast(uint16x4_t,b); + return __builtin_bit_cast(vec_type,vcgt_u16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x2_t amm = __builtin_bit_cast(uint32x2_t,a); + uint32x2_t bmm = __builtin_bit_cast(uint32x2_t,b); + return __builtin_bit_cast(vec_type,vcgt_u32(amm,bmm)); + } +#if defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) + else if constexpr(sizeof(T)==8) + { + uint64x1_t amm = __builtin_bit_cast(uint64x1_t,a); + uint64x1_t bmm = __builtin_bit_cast(uint64x1_t,b); + return __builtin_bit_cast(vec_type,vcgt_u64(amm,bmm)); + } +#endif + } + else if constexpr(sizeof(vec_type)==16) + { + if constexpr(sizeof(T)==1) + { + uint8x16_t amm = __builtin_bit_cast(uint8x16_t,a); + uint8x16_t bmm = __builtin_bit_cast(uint8x16_t,b); + return __builtin_bit_cast(vec_type,vcgtq_u8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x8_t amm = __builtin_bit_cast(uint16x8_t,a); + uint16x8_t bmm = __builtin_bit_cast(uint16x8_t,b); + return __builtin_bit_cast(vec_type,vcgtq_u16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x4_t amm = __builtin_bit_cast(uint32x4_t,a); + uint32x4_t bmm = __builtin_bit_cast(uint32x4_t,b); + return __builtin_bit_cast(vec_type,vcgtq_u32(amm,bmm)); + } +#if defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) + else if constexpr(sizeof(T)==8) + { + uint64x2_t amm = __builtin_bit_cast(uint64x2_t,a); + uint64x2_t bmm = __builtin_bit_cast(uint64x2_t,b); + return __builtin_bit_cast(vec_type,vcgtq_u64(amm,bmm)); + } +#endif + } + } + } +#endif + } + return ::fast_io::details::generic_simd_comparision_common_impl(a,b,[](T va,T vb) noexcept -> bool + { + return va>vb; + }); +} + +template +inline constexpr simd_vector operator<=(simd_vector const& a,simd_vector const& b) noexcept +{ +#if __cpp_if_consteval >= 202106L + if !consteval +#else + if (!__builtin_is_constant_evaluated()) +#endif + { +#if (defined(__x86_64__) || defined(_M_AMD64) || defined(__i386__) || defined(_M_IX86)) + using vec_type = ::fast_io::intrinsics::simd_vector; + if constexpr(sizeof(vec_type)==16&&::fast_io::details::cpu_flags::sse2_supported) + { + if constexpr(std::integral) + { + if constexpr(::fast_io::details::cpu_flags::avx512vl_supported&& + ::fast_io::details::cpu_flags::avx512bw_supported) + { + __m128i amm = __builtin_bit_cast(__m128i,a); + __m128i bmm = __builtin_bit_cast(__m128i,b); + if constexpr(std::signed_integral) + { + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm_movm_epi8(_mm_cmple_epi8_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm_movm_epi16(_mm_cmple_epi16_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm_movm_epi32(_mm_cmple_epi32_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm_movm_epi64(_mm_cmple_epi64_mask(amm,bmm))); + } + } + else + { + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm_movm_epi8(_mm_cmple_epu8_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm_movm_epi16(_mm_cmple_epu16_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm_movm_epi32(_mm_cmple_epu32_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm_movm_epi64(_mm_cmple_epu64_mask(amm,bmm))); + } + } + } + else if constexpr(sizeof(T)<=4) + { + return b>a; + } + } + else if constexpr(std::floating_point) + { + if constexpr(sizeof(T)==sizeof(float)) + { + __m256 amm = __builtin_bit_cast(__m256,a); + __m256 bmm = __builtin_bit_cast(__m256,b); + return __builtin_bit_cast(vec_type,_mm256_cmp_ps(amm,bmm,_CMP_LE_OS)); + } + else if constexpr(sizeof(T)==sizeof(double)) + { + __m256d amm = __builtin_bit_cast(__m256d,a); + __m256d bmm = __builtin_bit_cast(__m256d,b); + return __builtin_bit_cast(vec_type,_mm256_cmp_pd(amm,bmm,_CMP_LE_OS)); + } + } + } + else if constexpr(sizeof(vec_type)==32&&::fast_io::details::cpu_flags::avx2_supported) + { + if constexpr(std::integral) + { + if constexpr(::fast_io::details::cpu_flags::avx512vl_supported&& + ::fast_io::details::cpu_flags::avx512bw_supported) + { + __m256i amm = __builtin_bit_cast(__m256i,a); + __m256i bmm = __builtin_bit_cast(__m256i,b); + if constexpr(std::signed_integral) + { + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm256_movm_epi8(_mm256_cmple_epi8_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm256_movm_epi16(_mm256_cmple_epi16_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm256_movm_epi32(_mm256_cmple_epi32_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm256_movm_epi64(_mm256_cmple_epi64_mask(amm,bmm))); + } + } + else + { + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm256_movm_epi8(_mm256_cmple_epu8_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm256_movm_epi16(_mm256_cmple_epu16_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm256_movm_epi32(_mm256_cmple_epu32_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm256_movm_epi64(_mm256_cmple_epu64_mask(amm,bmm))); + } + } + } + } + else if constexpr(std::floating_point) + { + if constexpr(sizeof(T)==sizeof(float)) + { + __m256 amm = __builtin_bit_cast(__m256,a); + __m256 bmm = __builtin_bit_cast(__m256,b); + return __builtin_bit_cast(vec_type,_mm256_cmp_ps(amm,bmm,_CMP_LE_OS)); + } + else if constexpr(sizeof(T)==sizeof(double)) + { + __m256d amm = __builtin_bit_cast(__m256d,a); + __m256d bmm = __builtin_bit_cast(__m256d,b); + return __builtin_bit_cast(vec_type,_mm256_cmp_pd(amm,bmm,_CMP_LE_OS)); + } + } + } + else if constexpr(sizeof(vec_type)==64) + { + if constexpr(std::integral&&::fast_io::details::cpu_flags::avx512bw_supported) + { + __m512i amm = __builtin_bit_cast(__m512i,a); + __m512i bmm = __builtin_bit_cast(__m512i,b); + if constexpr(std::signed_integral) + { + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi8(_mm512_cmple_epi8_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi16(_mm512_cmple_epi16_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi32(_mm512_cmple_epi32_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi64(_mm512_cmple_epi64_mask(amm,bmm))); + } + } + else + { + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi8(_mm512_cmple_epu8_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi16(_mm512_cmple_epu16_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi32(_mm512_cmple_epu32_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi64(_mm512_cmple_epu64_mask(amm,bmm))); + } + } + } + else if constexpr(std::floating_point&&::fast_io::details::cpu_flags::avx512f_supported) + { + if constexpr(sizeof(T)==sizeof(float)) + { + __m512 amm = __builtin_bit_cast(__m512,a); + __m512 bmm = __builtin_bit_cast(__m512,b); + return __builtin_bit_cast(vec_type,_mm512_movm_epi32(_mm512_cmp_ps_mask(amm,bmm,_CMP_LE_OS))); + } + else if constexpr(sizeof(T)==sizeof(double)) + { + __m512d amm = __builtin_bit_cast(__m512d,a); + __m512d bmm = __builtin_bit_cast(__m512d,b); + return __builtin_bit_cast(vec_type,_mm512_movm_epi64(_mm512_cmp_pd_mask(amm,bmm,_CMP_LE_OS))); + } + } + } +#elif defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) || defined(__arm__) || defined(_M_ARM) + using vec_type = simd_vector; + if constexpr(::fast_io::details::cpu_flags::armneon_supported) + { + if constexpr(std::signed_integral) + { + if constexpr(sizeof(vec_type)==8) + { + if constexpr(sizeof(T)==1) + { + uint8x8_t amm = __builtin_bit_cast(uint8x8_t,a); + uint8x8_t bmm = __builtin_bit_cast(uint8x8_t,b); + return __builtin_bit_cast(vec_type,vcle_s8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x4_t amm = __builtin_bit_cast(uint16x4_t,a); + uint16x4_t bmm = __builtin_bit_cast(uint16x4_t,b); + return __builtin_bit_cast(vec_type,vcle_s16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x2_t amm = __builtin_bit_cast(uint32x2_t,a); + uint32x2_t bmm = __builtin_bit_cast(uint32x2_t,b); + return __builtin_bit_cast(vec_type,vcle_s32(amm,bmm)); + } +#if defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) + else if constexpr(sizeof(T)==8) + { + uint64x1_t amm = __builtin_bit_cast(uint64x1_t,a); + uint64x1_t bmm = __builtin_bit_cast(uint64x1_t,b); + return __builtin_bit_cast(vec_type,vcle_s64(amm,bmm)); + } +#endif + } + else if constexpr(sizeof(vec_type)==16) + { + if constexpr(sizeof(T)==1) + { + uint8x16_t amm = __builtin_bit_cast(uint8x16_t,a); + uint8x16_t bmm = __builtin_bit_cast(uint8x16_t,b); + return __builtin_bit_cast(vec_type,vcleq_s8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x8_t amm = __builtin_bit_cast(uint16x8_t,a); + uint16x8_t bmm = __builtin_bit_cast(uint16x8_t,b); + return __builtin_bit_cast(vec_type,vcleq_s16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x4_t amm = __builtin_bit_cast(uint32x4_t,a); + uint32x4_t bmm = __builtin_bit_cast(uint32x4_t,b); + return __builtin_bit_cast(vec_type,vcleq_s32(amm,bmm)); + } +#if defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) + else if constexpr(sizeof(T)==8) + { + uint64x2_t amm = __builtin_bit_cast(uint64x2_t,a); + uint64x2_t bmm = __builtin_bit_cast(uint64x2_t,b); + return __builtin_bit_cast(vec_type,vcleq_s64(amm,bmm)); + } +#endif + } + } + else if constexpr(std::unsigned_integral) + { + if constexpr(sizeof(vec_type)==8) + { + if constexpr(sizeof(T)==1) + { + uint8x8_t amm = __builtin_bit_cast(uint8x8_t,a); + uint8x8_t bmm = __builtin_bit_cast(uint8x8_t,b); + return __builtin_bit_cast(vec_type,vcle_u8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x4_t amm = __builtin_bit_cast(uint16x4_t,a); + uint16x4_t bmm = __builtin_bit_cast(uint16x4_t,b); + return __builtin_bit_cast(vec_type,vcle_u16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x2_t amm = __builtin_bit_cast(uint32x2_t,a); + uint32x2_t bmm = __builtin_bit_cast(uint32x2_t,b); + return __builtin_bit_cast(vec_type,vcle_u32(amm,bmm)); + } +#if defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) + else if constexpr(sizeof(T)==8) + { + uint64x1_t amm = __builtin_bit_cast(uint64x1_t,a); + uint64x1_t bmm = __builtin_bit_cast(uint64x1_t,b); + return __builtin_bit_cast(vec_type,vcle_u64(amm,bmm)); + } +#endif + } + else if constexpr(sizeof(vec_type)==16) + { + if constexpr(sizeof(T)==1) + { + uint8x16_t amm = __builtin_bit_cast(uint8x16_t,a); + uint8x16_t bmm = __builtin_bit_cast(uint8x16_t,b); + return __builtin_bit_cast(vec_type,vcleq_u8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x8_t amm = __builtin_bit_cast(uint16x8_t,a); + uint16x8_t bmm = __builtin_bit_cast(uint16x8_t,b); + return __builtin_bit_cast(vec_type,vcleq_u16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x4_t amm = __builtin_bit_cast(uint32x4_t,a); + uint32x4_t bmm = __builtin_bit_cast(uint32x4_t,b); + return __builtin_bit_cast(vec_type,vcleq_u32(amm,bmm)); + } +#if defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) + else if constexpr(sizeof(T)==8) + { + uint64x2_t amm = __builtin_bit_cast(uint64x2_t,a); + uint64x2_t bmm = __builtin_bit_cast(uint64x2_t,b); + return __builtin_bit_cast(vec_type,vcleq_u64(amm,bmm)); + } +#endif + } + } + } +#endif + } + return ::fast_io::details::generic_simd_comparision_common_impl(a,b,[](T va,T vb) noexcept -> bool + { + return va<=vb; + }); +} + +template +inline constexpr simd_vector operator>=(simd_vector const& a,simd_vector const& b) noexcept +{ +#if __cpp_if_consteval >= 202106L + if !consteval +#else + if (!__builtin_is_constant_evaluated()) +#endif + { +#if (defined(__x86_64__) || defined(_M_AMD64) || defined(__i386__) || defined(_M_IX86)) + using vec_type = ::fast_io::intrinsics::simd_vector; + if constexpr(sizeof(vec_type)==16&&::fast_io::details::cpu_flags::sse2_supported) + { + if constexpr(std::integral) + { + if constexpr(::fast_io::details::cpu_flags::avx512vl_supported&& + ::fast_io::details::cpu_flags::avx512bw_supported) + { + __m128i amm = __builtin_bit_cast(__m128i,a); + __m128i bmm = __builtin_bit_cast(__m128i,b); + if constexpr(std::signed_integral) + { + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm_movm_epi8(_mm_cmpge_epi8_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm_movm_epi16(_mm_cmpge_epi16_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm_movm_epi32(_mm_cmpge_epi32_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm_movm_epi64(_mm_cmpge_epi64_mask(amm,bmm))); + } + } + else + { + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm_movm_epi8(_mm_cmpge_epu8_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm_movm_epi16(_mm_cmpge_epu16_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm_movm_epi32(_mm_cmpge_epu32_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm_movm_epi64(_mm_cmpge_epu64_mask(amm,bmm))); + } + } + } + else if constexpr(sizeof(T)<=4) + { + return b) + { + if constexpr(sizeof(T)==sizeof(float)) + { + __m256 amm = __builtin_bit_cast(__m256,a); + __m256 bmm = __builtin_bit_cast(__m256,b); + return __builtin_bit_cast(vec_type,_mm256_cmp_ps(amm,bmm,_CMP_GE_OS)); + } + else if constexpr(sizeof(T)==sizeof(double)) + { + __m256d amm = __builtin_bit_cast(__m256d,a); + __m256d bmm = __builtin_bit_cast(__m256d,b); + return __builtin_bit_cast(vec_type,_mm256_cmp_pd(amm,bmm,_CMP_GE_OS)); + } + } + } + else if constexpr(sizeof(vec_type)==32&&::fast_io::details::cpu_flags::avx2_supported) + { + if constexpr(std::integral) + { + if constexpr(::fast_io::details::cpu_flags::avx512vl_supported&& + ::fast_io::details::cpu_flags::avx512bw_supported) + { + __m256i amm = __builtin_bit_cast(__m256i,a); + __m256i bmm = __builtin_bit_cast(__m256i,b); + if constexpr(std::signed_integral) + { + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm256_movm_epi8(_mm256_cmpge_epi8_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm256_movm_epi16(_mm256_cmpge_epi16_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm256_movm_epi32(_mm256_cmpge_epi32_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm256_movm_epi64(_mm256_cmpge_epi64_mask(amm,bmm))); + } + } + else + { + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm256_movm_epi8(_mm256_cmpge_epu8_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm256_movm_epi16(_mm256_cmpge_epu16_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm256_movm_epi32(_mm256_cmpge_epu32_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm256_movm_epi64(_mm256_cmpge_epu64_mask(amm,bmm))); + } + } + } + else if constexpr(sizeof(T)<=4) + { + return b) + { + if constexpr(sizeof(T)==sizeof(float)) + { + __m256 amm = __builtin_bit_cast(__m256,a); + __m256 bmm = __builtin_bit_cast(__m256,b); + return __builtin_bit_cast(vec_type,_mm256_cmp_ps(amm,bmm,_CMP_GE_OS)); + } + else if constexpr(sizeof(T)==sizeof(double)) + { + __m256d amm = __builtin_bit_cast(__m256d,a); + __m256d bmm = __builtin_bit_cast(__m256d,b); + return __builtin_bit_cast(vec_type,_mm256_cmp_pd(amm,bmm,_CMP_GE_OS)); + } + } + } + else if constexpr(sizeof(vec_type)==64) + { + if constexpr(std::integral&&::fast_io::details::cpu_flags::avx512bw_supported) + { + __m512i amm = __builtin_bit_cast(__m512i,a); + __m512i bmm = __builtin_bit_cast(__m512i,b); + if constexpr(std::signed_integral) + { + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi8(_mm512_cmpge_epi8_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi16(_mm512_cmpge_epi16_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi32(_mm512_cmpge_epi32_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi64(_mm512_cmpge_epi64_mask(amm,bmm))); + } + } + else + { + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi8(_mm512_cmpge_epu8_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi16(_mm512_cmpge_epu16_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi32(_mm512_cmpge_epu32_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi64(_mm512_cmpge_epu64_mask(amm,bmm))); + } + } + } + else if constexpr(std::floating_point&&::fast_io::details::cpu_flags::avx512f_supported) + { + if constexpr(sizeof(T)==sizeof(float)) + { + __m512 amm = __builtin_bit_cast(__m512,a); + __m512 bmm = __builtin_bit_cast(__m512,b); + return __builtin_bit_cast(vec_type,_mm512_movm_epi32(_mm512_cmp_ps_mask(amm,bmm,_CMP_GE_OS))); + } + else if constexpr(sizeof(T)==sizeof(double)) + { + __m512d amm = __builtin_bit_cast(__m512d,a); + __m512d bmm = __builtin_bit_cast(__m512d,b); + return __builtin_bit_cast(vec_type,_mm512_movm_epi64(_mm512_cmp_pd_mask(amm,bmm,_CMP_GE_OS))); + } + } + } +#elif defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) || defined(__arm__) || defined(_M_ARM) + using vec_type = simd_vector; + if constexpr(::fast_io::details::cpu_flags::armneon_supported) + { + if constexpr(std::signed_integral) + { + if constexpr(sizeof(vec_type)==8) + { + if constexpr(sizeof(T)==1) + { + uint8x8_t amm = __builtin_bit_cast(uint8x8_t,a); + uint8x8_t bmm = __builtin_bit_cast(uint8x8_t,b); + return __builtin_bit_cast(vec_type,vcge_s8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x4_t amm = __builtin_bit_cast(uint16x4_t,a); + uint16x4_t bmm = __builtin_bit_cast(uint16x4_t,b); + return __builtin_bit_cast(vec_type,vcge_s16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x2_t amm = __builtin_bit_cast(uint32x2_t,a); + uint32x2_t bmm = __builtin_bit_cast(uint32x2_t,b); + return __builtin_bit_cast(vec_type,vcge_s32(amm,bmm)); + } +#if defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) + else if constexpr(sizeof(T)==8) + { + uint64x1_t amm = __builtin_bit_cast(uint64x1_t,a); + uint64x1_t bmm = __builtin_bit_cast(uint64x1_t,b); + return __builtin_bit_cast(vec_type,vcge_s64(amm,bmm)); + } +#endif + } + else if constexpr(sizeof(vec_type)==16) + { + if constexpr(sizeof(T)==1) + { + uint8x16_t amm = __builtin_bit_cast(uint8x16_t,a); + uint8x16_t bmm = __builtin_bit_cast(uint8x16_t,b); + return __builtin_bit_cast(vec_type,vcgeq_s8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x8_t amm = __builtin_bit_cast(uint16x8_t,a); + uint16x8_t bmm = __builtin_bit_cast(uint16x8_t,b); + return __builtin_bit_cast(vec_type,vcgeq_s16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x4_t amm = __builtin_bit_cast(uint32x4_t,a); + uint32x4_t bmm = __builtin_bit_cast(uint32x4_t,b); + return __builtin_bit_cast(vec_type,vcgeq_s32(amm,bmm)); + } +#if defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) + else if constexpr(sizeof(T)==8) + { + uint64x2_t amm = __builtin_bit_cast(uint64x2_t,a); + uint64x2_t bmm = __builtin_bit_cast(uint64x2_t,b); + return __builtin_bit_cast(vec_type,vcgeq_s64(amm,bmm)); + } +#endif + } + } + else if constexpr(std::unsigned_integral) + { + if constexpr(sizeof(vec_type)==8) + { + if constexpr(sizeof(T)==1) + { + uint8x8_t amm = __builtin_bit_cast(uint8x8_t,a); + uint8x8_t bmm = __builtin_bit_cast(uint8x8_t,b); + return __builtin_bit_cast(vec_type,vcge_u8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x4_t amm = __builtin_bit_cast(uint16x4_t,a); + uint16x4_t bmm = __builtin_bit_cast(uint16x4_t,b); + return __builtin_bit_cast(vec_type,vcge_u16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x2_t amm = __builtin_bit_cast(uint32x2_t,a); + uint32x2_t bmm = __builtin_bit_cast(uint32x2_t,b); + return __builtin_bit_cast(vec_type,vcge_u32(amm,bmm)); + } +#if defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) + else if constexpr(sizeof(T)==8) + { + uint64x1_t amm = __builtin_bit_cast(uint64x1_t,a); + uint64x1_t bmm = __builtin_bit_cast(uint64x1_t,b); + return __builtin_bit_cast(vec_type,vcge_u64(amm,bmm)); + } +#endif + } + else if constexpr(sizeof(vec_type)==16) + { + if constexpr(sizeof(T)==1) + { + uint8x16_t amm = __builtin_bit_cast(uint8x16_t,a); + uint8x16_t bmm = __builtin_bit_cast(uint8x16_t,b); + return __builtin_bit_cast(vec_type,vcgeq_u8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x8_t amm = __builtin_bit_cast(uint16x8_t,a); + uint16x8_t bmm = __builtin_bit_cast(uint16x8_t,b); + return __builtin_bit_cast(vec_type,vcgeq_u16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x4_t amm = __builtin_bit_cast(uint32x4_t,a); + uint32x4_t bmm = __builtin_bit_cast(uint32x4_t,b); + return __builtin_bit_cast(vec_type,vcgeq_u32(amm,bmm)); + } +#if defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) + else if constexpr(sizeof(T)==8) + { + uint64x2_t amm = __builtin_bit_cast(uint64x2_t,a); + uint64x2_t bmm = __builtin_bit_cast(uint64x2_t,b); + return __builtin_bit_cast(vec_type,vcgeq_u64(amm,bmm)); + } +#endif + } + } + } +#endif + } + return ::fast_io::details::generic_simd_comparision_common_impl(a,b,[](T va,T vb) noexcept -> bool + { + return va>=vb; + }); +} + +template +inline constexpr simd_vector operator==(simd_vector const& a,simd_vector const& b) noexcept +{ +#if __cpp_if_consteval >= 202106L + if !consteval +#else + if (!__builtin_is_constant_evaluated()) +#endif + { +#if (defined(__x86_64__) || defined(_M_AMD64) || defined(__i386__) || defined(_M_IX86)) + using vec_type = simd_vector; + if constexpr(sizeof(vec_type)==16&&::fast_io::details::cpu_flags::sse2_supported) + { + __m128i amm = __builtin_bit_cast(__m128i,a); + __m128i bmm = __builtin_bit_cast(__m128i,b); + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm_cmpeq_epi8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm_cmpeq_epi16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm_cmpeq_epi32(amm,bmm)); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm_cmpeq_epi64(amm,bmm)); + } + } + else if constexpr(sizeof(vec_type)==32&&::fast_io::details::cpu_flags::avx2_supported) + { + __m256i amm = __builtin_bit_cast(__m256i,a); + __m256i bmm = __builtin_bit_cast(__m256i,b); + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm256_cmpeq_epi8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm256_cmpeq_epi16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm256_cmpeq_epi32(amm,bmm)); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm256_cmpeq_epi64(amm,bmm)); + } + } + else if constexpr(sizeof(vec_type)==64&&::fast_io::details::cpu_flags::avx512f_supported) + { + __m512i amm = __builtin_bit_cast(__m512i,a); + __m512i bmm = __builtin_bit_cast(__m512i,b); + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi8(_mm512_cmpeq_epi8_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi16(_mm512_cmpeq_epi16_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi32(_mm512_cmpeq_epi32_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi64(_mm512_cmpeq_epi64_mask(amm,bmm))); + } + } +#elif defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) || defined(__arm__) || defined(_M_ARM) + using vec_type = simd_vector; + if constexpr(::fast_io::details::cpu_flags::armneon_supported) + { + if constexpr(std::signed_integral) + { + if constexpr(sizeof(vec_type)==8) + { + if constexpr(sizeof(T)==1) + { + uint8x8_t amm = __builtin_bit_cast(uint8x8_t,a); + uint8x8_t bmm = __builtin_bit_cast(uint8x8_t,b); + return __builtin_bit_cast(vec_type,vceq_s8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x4_t amm = __builtin_bit_cast(uint16x4_t,a); + uint16x4_t bmm = __builtin_bit_cast(uint16x4_t,b); + return __builtin_bit_cast(vec_type,vceq_s16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x2_t amm = __builtin_bit_cast(uint32x2_t,a); + uint32x2_t bmm = __builtin_bit_cast(uint32x2_t,b); + return __builtin_bit_cast(vec_type,vceq_s32(amm,bmm)); + } +#if defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) + else if constexpr(sizeof(T)==8) + { + uint64x1_t amm = __builtin_bit_cast(uint64x1_t,a); + uint64x1_t bmm = __builtin_bit_cast(uint64x1_t,b); + return __builtin_bit_cast(vec_type,vceq_s64(amm,bmm)); + } +#endif + } + else if constexpr(sizeof(vec_type)==16) + { + if constexpr(sizeof(T)==1) + { + uint8x16_t amm = __builtin_bit_cast(uint8x16_t,a); + uint8x16_t bmm = __builtin_bit_cast(uint8x16_t,b); + return __builtin_bit_cast(vec_type,vceqq_s8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x8_t amm = __builtin_bit_cast(uint16x8_t,a); + uint16x8_t bmm = __builtin_bit_cast(uint16x8_t,b); + return __builtin_bit_cast(vec_type,vceqq_s16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x4_t amm = __builtin_bit_cast(uint32x4_t,a); + uint32x4_t bmm = __builtin_bit_cast(uint32x4_t,b); + return __builtin_bit_cast(vec_type,vceqq_s32(amm,bmm)); + } +#if defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) + else if constexpr(sizeof(T)==8) + { + uint64x2_t amm = __builtin_bit_cast(uint64x2_t,a); + uint64x2_t bmm = __builtin_bit_cast(uint64x2_t,b); + return __builtin_bit_cast(vec_type,vceqq_s64(amm,bmm)); + } +#endif + } + } + else if constexpr(std::unsigned_integral) + { + if constexpr(sizeof(vec_type)==8) + { + if constexpr(sizeof(T)==1) + { + uint8x8_t amm = __builtin_bit_cast(uint8x8_t,a); + uint8x8_t bmm = __builtin_bit_cast(uint8x8_t,b); + return __builtin_bit_cast(vec_type,vceq_u8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x4_t amm = __builtin_bit_cast(uint16x4_t,a); + uint16x4_t bmm = __builtin_bit_cast(uint16x4_t,b); + return __builtin_bit_cast(vec_type,vceq_u16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x2_t amm = __builtin_bit_cast(uint32x2_t,a); + uint32x2_t bmm = __builtin_bit_cast(uint32x2_t,b); + return __builtin_bit_cast(vec_type,vceq_u32(amm,bmm)); + } +#if defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) + else if constexpr(sizeof(T)==8) + { + uint64x1_t amm = __builtin_bit_cast(uint64x1_t,a); + uint64x1_t bmm = __builtin_bit_cast(uint64x1_t,b); + return __builtin_bit_cast(vec_type,vceq_u64(amm,bmm)); + } +#endif + } + else if constexpr(sizeof(vec_type)==16) + { + if constexpr(sizeof(T)==1) + { + uint8x16_t amm = __builtin_bit_cast(uint8x16_t,a); + uint8x16_t bmm = __builtin_bit_cast(uint8x16_t,b); + return __builtin_bit_cast(vec_type,vceqq_u8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x8_t amm = __builtin_bit_cast(uint16x8_t,a); + uint16x8_t bmm = __builtin_bit_cast(uint16x8_t,b); + return __builtin_bit_cast(vec_type,vceqq_u16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x4_t amm = __builtin_bit_cast(uint32x4_t,a); + uint32x4_t bmm = __builtin_bit_cast(uint32x4_t,b); + return __builtin_bit_cast(vec_type,vceqq_u32(amm,bmm)); + } +#if defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) + else if constexpr(sizeof(T)==8) + { + uint64x2_t amm = __builtin_bit_cast(uint64x2_t,a); + uint64x2_t bmm = __builtin_bit_cast(uint64x2_t,b); + return __builtin_bit_cast(vec_type,vceqq_u64(amm,bmm)); + } +#endif + } + } + } +#endif + } + return ::fast_io::details::generic_simd_comparision_common_impl(a,b,[](T va,T vb) noexcept -> bool + { + return va==vb; + }); +} + +template +inline constexpr simd_vector operator!=(simd_vector const& a,simd_vector const& b) noexcept +{ + using vec_type = simd_vector; + constexpr bool using_avx512{::fast_io::details::cpu_flags::avx512f_supported&&::fast_io::details::cpu_flags::avx512bw_supported&&::fast_io::details::cpu_flags::avx512vl_supported}; + constexpr bool using_simd{(sizeof(vec_type)==16&&::fast_io::details::cpu_flags::sse2_supported)||(sizeof(vec_type)==32&&::fast_io::details::cpu_flags::avx2_supported)}; + if constexpr(using_simd&&(!using_avx512)) + { + return (::fast_io::details::all_zero_simd_vector_mask)==(a==b); + } + else + { +#if __cpp_if_consteval >= 202106L + if !consteval +#else + if (!__builtin_is_constant_evaluated()) +#endif + { +#if (defined(__x86_64__) || defined(_M_AMD64) || defined(__i386__) || defined(_M_IX86)) + if constexpr(using_avx512) + { + if constexpr(sizeof(vec_type)==16&&::fast_io::details::cpu_flags::sse2_supported) + { + __m128i amm = __builtin_bit_cast(__m128i,a); + __m128i bmm = __builtin_bit_cast(__m128i,b); + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm_movm_epi8(_mm_cmpneq_epi8_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm_movm_epi16(_mm_cmpneq_epi16_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm_movm_epi32(_mm_cmpneq_epi32_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm_movm_epi64(_mm_cmpneq_epi64_mask(amm,bmm))); + } + } + else if constexpr(sizeof(vec_type)==32) + { + __m256i amm = __builtin_bit_cast(__m256i,a); + __m256i bmm = __builtin_bit_cast(__m256i,b); + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm256_movm_epi8(_mm256_cmpneq_epi8_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm256_movm_epi16(_mm256_cmpneq_epi16_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm256_movm_epi32(_mm256_cmpneq_epi32_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm256_movm_epi64(_mm256_cmpneq_epi64_mask(amm,bmm))); + } + } + else if constexpr(sizeof(vec_type)==64) + { + __m512i amm = __builtin_bit_cast(__m512i,a); + __m512i bmm = __builtin_bit_cast(__m512i,b); + if constexpr(sizeof(T)==1) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi8(_mm512_cmpneq_epi8_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==2) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi16(_mm512_cmpneq_epi16_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==4) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi32(_mm512_cmpneq_epi32_mask(amm,bmm))); + } + else if constexpr(sizeof(T)==8) + { + return __builtin_bit_cast(vec_type,_mm512_movm_epi64(_mm512_cmpneq_epi64_mask(amm,bmm))); + } + } + } +#elif defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) || defined(__arm__) || defined(_M_ARM) + using vec_type = simd_vector; + if constexpr(std::signed_integral) + { + if constexpr(sizeof(vec_type)==8) + { + if constexpr(sizeof(T)==1) + { + uint8x8_t amm = __builtin_bit_cast(uint8x8_t,a); + uint8x8_t bmm = __builtin_bit_cast(uint8x8_t,b); + return __builtin_bit_cast(vec_type,vtst_s8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x4_t amm = __builtin_bit_cast(uint16x4_t,a); + uint16x4_t bmm = __builtin_bit_cast(uint16x4_t,b); + return __builtin_bit_cast(vec_type,vtst_s16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x2_t amm = __builtin_bit_cast(uint32x2_t,a); + uint32x2_t bmm = __builtin_bit_cast(uint32x2_t,b); + return __builtin_bit_cast(vec_type,vtst_s32(amm,bmm)); + } +#if defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) + else if constexpr(sizeof(T)==8) + { + uint64x1_t amm = __builtin_bit_cast(uint64x1_t,a); + uint64x1_t bmm = __builtin_bit_cast(uint64x1_t,b); + return __builtin_bit_cast(vec_type,vtst_s64(amm,bmm)); + } +#endif + } + else if constexpr(sizeof(vec_type)==16) + { + if constexpr(sizeof(T)==1) + { + uint8x16_t amm = __builtin_bit_cast(uint8x16_t,a); + uint8x16_t bmm = __builtin_bit_cast(uint8x16_t,b); + return __builtin_bit_cast(vec_type,vtstq_s8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x8_t amm = __builtin_bit_cast(uint16x8_t,a); + uint16x8_t bmm = __builtin_bit_cast(uint16x8_t,b); + return __builtin_bit_cast(vec_type,vtstq_s16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x4_t amm = __builtin_bit_cast(uint32x4_t,a); + uint32x4_t bmm = __builtin_bit_cast(uint32x4_t,b); + return __builtin_bit_cast(vec_type,vtstq_s32(amm,bmm)); + } +#if defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) + else if constexpr(sizeof(T)==8) + { + uint64x2_t amm = __builtin_bit_cast(uint64x2_t,a); + uint64x2_t bmm = __builtin_bit_cast(uint64x2_t,b); + return __builtin_bit_cast(vec_type,vtstq_s64(amm,bmm)); + } +#endif + } + } + else if constexpr(std::unsigned_integral) + { + if constexpr(sizeof(vec_type)==8) + { + if constexpr(sizeof(T)==1) + { + uint8x8_t amm = __builtin_bit_cast(uint8x8_t,a); + uint8x8_t bmm = __builtin_bit_cast(uint8x8_t,b); + return __builtin_bit_cast(vec_type,vtst_u8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x4_t amm = __builtin_bit_cast(uint16x4_t,a); + uint16x4_t bmm = __builtin_bit_cast(uint16x4_t,b); + return __builtin_bit_cast(vec_type,vtst_u16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x2_t amm = __builtin_bit_cast(uint32x2_t,a); + uint32x2_t bmm = __builtin_bit_cast(uint32x2_t,b); + return __builtin_bit_cast(vec_type,vtst_u32(amm,bmm)); + } +#if defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) + else if constexpr(sizeof(T)==8) + { + uint64x1_t amm = __builtin_bit_cast(uint64x1_t,a); + uint64x1_t bmm = __builtin_bit_cast(uint64x1_t,b); + return __builtin_bit_cast(vec_type,vtst_u64(amm,bmm)); + } +#endif + } + else if constexpr(sizeof(vec_type)==16) + { + if constexpr(sizeof(T)==1) + { + uint8x16_t amm = __builtin_bit_cast(uint8x16_t,a); + uint8x16_t bmm = __builtin_bit_cast(uint8x16_t,b); + return __builtin_bit_cast(vec_type,vtstq_u8(amm,bmm)); + } + else if constexpr(sizeof(T)==2) + { + uint16x8_t amm = __builtin_bit_cast(uint16x8_t,a); + uint16x8_t bmm = __builtin_bit_cast(uint16x8_t,b); + return __builtin_bit_cast(vec_type,vtstq_u16(amm,bmm)); + } + else if constexpr(sizeof(T)==4) + { + uint32x4_t amm = __builtin_bit_cast(uint32x4_t,a); + uint32x4_t bmm = __builtin_bit_cast(uint32x4_t,b); + return __builtin_bit_cast(vec_type,vtstq_u32(amm,bmm)); + } +#if defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) + else if constexpr(sizeof(T)==8) + { + uint64x2_t amm = __builtin_bit_cast(uint64x2_t,a); + uint64x2_t bmm = __builtin_bit_cast(uint64x2_t,b); + return __builtin_bit_cast(vec_type,vtstq_u64(amm,bmm)); + } +#endif + } + } +#endif + } + return ::fast_io::details::generic_simd_comparision_common_impl(a,b,[](T va,T vb) noexcept -> bool + { + return va!=vb; + }); + } +} + +} +} diff --git a/src/fast_io/include/fast_io_core_impl/simd/impl.h b/src/fast_io/include/fast_io_core_impl/simd/impl.h new file mode 100644 index 0000000..cd5e0ab --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/simd/impl.h @@ -0,0 +1,14 @@ +#pragma once + +#include"cpu_flags.h" +#if __has_cpp_attribute(__gnu__::__vector_size__) +#include"gcc_clang.h" +#else +#include"generic_operations.h" +#include"generic.h" +#endif +#include"x86_64.h" + +#include"prrsv.h" +#include"is_all_zeros.h" +#include"mask_countr.h" diff --git a/src/fast_io/include/fast_io_core_impl/simd/is_all_zeros.h b/src/fast_io/include/fast_io_core_impl/simd/is_all_zeros.h new file mode 100644 index 0000000..45c81db --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/simd/is_all_zeros.h @@ -0,0 +1,215 @@ +#pragma once + +namespace fast_io +{ + +namespace details +{ + +inline constexpr bool calculate_can_simd_vector_run_with_cpu_instruction(std::size_t sizeofsimdvector) noexcept +{ + if(sizeofsimdvector==16) + { + if constexpr( + ::fast_io::details::cpu_flags::wasmsimd128_supported|| + ::fast_io::details::cpu_flags::sse2_supported|| + ::fast_io::details::cpu_flags::armneon_supported) + { + return true; + } + } + else if(sizeofsimdvector==32) + { + if constexpr(::fast_io::details::cpu_flags::avx2_supported) + { + return true; + } + } + else if(sizeofsimdvector==64) + { + if constexpr(::fast_io::details::cpu_flags::avx512f_supported + ||::fast_io::details::cpu_flags::avx512vl_supported + ||::fast_io::details::cpu_flags::avx512bw_supported) + { + return true; + } + } + return false; +} + +template +inline constexpr bool can_simd_vector_run_with_cpu_instruction +{ +calculate_can_simd_vector_run_with_cpu_instruction(sizeofsimdvector) +}; + +inline constexpr std::size_t optimal_simd_vector_run_with_cpu_instruction_size +{ +can_simd_vector_run_with_cpu_instruction<64>?64: +(can_simd_vector_run_with_cpu_instruction<32>?32: +(can_simd_vector_run_with_cpu_instruction<16>?16:0)) +}; + +template +inline constexpr bool is_all_zeros_recursive_impl(T const& v2) noexcept +{ + constexpr std::size_t N{sizeof(T)/sizeof(std::uint_least64_t)}; + static_assert(N!=0); + std::uint_least64_t element{v2[pos]}; + if constexpr(pos+2==N) + { + constexpr unsigned posp1{pos+1}; + return !element&&!v2[posp1]; + } + else if constexpr(pos!=N-1) + { + return !element&&is_all_zeros_recursive_impl(v2); + } + else + { + return !element; + } +} + +template +inline +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L +constexpr +#endif +bool is_all_zeros_impl(::fast_io::intrinsics::simd_vector const& vec) noexcept +{ +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L +#if __cpp_if_consteval >= 202106L + if !consteval +#elif __cpp_lib_is_constant_evaluated >= 201811L + if (!std::is_constant_evaluated()) +#endif + { + 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) + 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)); +#else + return __builtin_ia32_ptestz128((x86_64_v2di)vec.value,(x86_64_v2di)vec.value); +#endif + +#elif defined(__x86_64__) && __has_builtin(__builtin_ia32_pmovmskb128) && defined(__SSE2__) + using x86_64_v16qi [[__gnu__::__vector_size__ (16)]] = char; +#if __has_builtin(__builtin_bit_cast) + return !__builtin_ia32_pmovmskb128(__builtin_bit_cast(x86_64_v16qi,vec.value)); +#else + return !__builtin_ia32_pmovmskb128((x86_64_v16qi)vec.value); +#endif + +#elif defined(__wasm_simd128__) && __has_builtin(__builtin_wasm_bitmask_i8x16) + using wasmsimd128_i8x16 [[__gnu__::__vector_size__ (16)]] = char; + return !__builtin_wasm_bitmask_i8x16(static_cast(vec.value)); +#elif (defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64)) && __has_builtin(__builtin_neon_vmaxvq_u32) + using armneon_uint32x4 [[__gnu__::__vector_size__ (16)]] = unsigned; + if constexpr(::fast_io::details::cpu_flags::armneon_supported) + { + return __builtin_neon_vmaxvq_u32(__builtin_bit_cast(armneon_uint32x4,vec.value))==0; + } +#elif (defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64)) && __has_builtin(__builtin_aarch64_reduc_umax_scal_v4si_uu) + using armneon_uint32x4 [[__gnu__::__vector_size__ (16)]] = unsigned; + if constexpr(::fast_io::details::cpu_flags::armneon_supported) + { +#if __has_builtin(__builtin_bit_cast) + return __builtin_aarch64_reduc_umax_scal_v4si_uu(__builtin_bit_cast(armneon_uint32x4,vec.value))==0; +#else + return __builtin_aarch64_reduc_umax_scal_v4si_uu((armneon_uint32x4)vec.value)==0; +#endif + } +#endif +#elif (defined(__x86_64__) || defined(_M_AMD64) || defined(__i386__) || defined(_M_IX86)) + if constexpr(::fast_io::details::cpu_flags::sse4_2_supported) + { + __m128i a = __builtin_bit_cast(__m128i,vec); + return _mm_testz_si128(a,a); + } + else if constexpr(::fast_io::details::cpu_flags::sse2_supported) + { + __m128i a = __builtin_bit_cast(__m128i,vec); + return !_mm_movemask_epi8(a); + } +#elif defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM64) + if constexpr(::fast_io::details::cpu_flags::armneon_supported) + { + uint32x4_t a = __builtin_bit_cast(uint32x4_t,vec); + return vmaxvq_u32(a)==0; + } +#endif + } + else if constexpr(sizeof(::fast_io::intrinsics::simd_vector)==32) + { +#if defined(__has_builtin) && __has_cpp_attribute(__gnu__::__vector_size__) +#if defined(__AVX2__) && defined(__x86_64__) && __has_builtin(__builtin_ia32_ptestz256) + using x86_64_v4di [[__gnu__::__vector_size__ (32)]] = long long; +#if __has_builtin(__builtin_bit_cast) + return __builtin_ia32_ptestz256(__builtin_bit_cast(x86_64_v4di,vec),__builtin_bit_cast(x86_64_v4di,vec)); +#else + return __builtin_ia32_ptestz256((x86_64_v4di)vec.value,(x86_64_v4di)vec.value); +#endif +#elif defined(__AVX2__) && defined(__x86_64__) && __has_builtin(__builtin_ia32_pmovmskb256) + using x86_64_v32qi [[__gnu__::__vector_size__ (32)]] = char; +#if __has_builtin(__builtin_bit_cast) + return !__builtin_ia32_pmovmskb256(__builtin_bit_cast(x86_64_v32qi,vec.value)); +#else + return !__builtin_ia32_pmovmskb256((x86_64_v32qi)vec.value); +#endif + +#endif +#elif (defined(__x86_64__) || defined(_M_AMD64) || defined(__i386__) || defined(_M_IX86)) + if constexpr(::fast_io::details::cpu_flags::avx_supported) + { + __m256i a = __builtin_bit_cast(__m256i,vec); + return _mm256_testz_si256(a,a); + } +#endif + } + else if constexpr(sizeof(::fast_io::intrinsics::simd_vector)==64) + { +#if defined(__has_builtin) && __has_cpp_attribute(__gnu__::__vector_size__) + #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), + __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); + #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); + } +#endif + } + } +#endif + constexpr std::size_t N{sizeof(::fast_io::intrinsics::simd_vector)/sizeof(std::uint_least64_t)}; + return is_all_zeros_recursive_impl<0>(static_cast<::fast_io::intrinsics::simd_vector>(vec)); +} + +} + +namespace intrinsics +{ + +template +inline constexpr bool is_all_zeros(simd_vector const& vec) noexcept +{ + return ::fast_io::details::is_all_zeros_impl(vec); +} + +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/simd/mask_countr.h b/src/fast_io/include/fast_io_core_impl/simd/mask_countr.h new file mode 100644 index 0000000..512902c --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/simd/mask_countr.h @@ -0,0 +1,224 @@ +#pragma once + +namespace fast_io +{ + +namespace details +{ + +template +requires (std::same_as::value_type,std::uint_least64_t>) +inline constexpr unsigned vector_mask_countr_recursive_impl(T const& v2) noexcept +{ + constexpr std::uint_least64_t mx{std::numeric_limits::max()}; + constexpr unsigned digits{std::numeric_limits::digits}; + constexpr unsigned digitspos{digits*pos}; + constexpr std::size_t N{sizeof(T)/sizeof(std::uint_least64_t)}; + static_assert(N!=0); + std::uint_least64_t element{v2[pos]}; + if constexpr(pos!=N-1) + { + if constexpr(ctzero) + { + if(!element) + { + return vector_mask_countr_recursive_impl(v2); + } + } + else + { + if(element==mx) + { + return vector_mask_countr_recursive_impl(v2); + } + } + } + if constexpr(pos) + { + if constexpr(ctzero) + { + + return digitspos+static_cast(std::countr_zero(element)); + } + else + { + return digitspos+static_cast(std::countr_one(element)); + } + } + else + { + if constexpr(ctzero) + { + return static_cast(std::countr_zero(element)); + } + else + { + return static_cast(std::countr_one(element)); + } + } +} + +template +inline constexpr unsigned vector_mask_countr_common_no_intrinsics_impl(::fast_io::intrinsics::simd_vector const& vec) noexcept +{ + constexpr std::size_t N{sizeof(::fast_io::intrinsics::simd_vector)/sizeof(std::uint_least64_t)}; + unsigned d{vector_mask_countr_recursive_impl(static_cast<::fast_io::intrinsics::simd_vector>(vec))}; + constexpr unsigned shift{static_cast(std::bit_width(sizeof(T)*::std::numeric_limits::digits))}; + d>>=shift; +#if __has_cpp_attribute(assume) + [[assume(d<=n)]]; +#endif + return d; +} + +inline constexpr bool calculate_can_intrinsics_accelerate_mask_countr(std::size_t sizeofsimdvector) noexcept +{ + if(sizeofsimdvector<=32) + { + return ::fast_io::details::calculate_can_simd_vector_run_with_cpu_instruction(sizeofsimdvector); + } + return false; +} + + +template +inline constexpr bool can_intrinsics_accelerate_mask_countr +{ +calculate_can_intrinsics_accelerate_mask_countr(sizeofsimdvector) +}; + +template +inline +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L +constexpr +#endif +unsigned vector_mask_countr_common_intrinsics_impl(::fast_io::intrinsics::simd_vector const& vec) noexcept +{ +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L +#if __cpp_if_consteval >= 202106L + if consteval +#elif __cpp_lib_is_constant_evaluated >= 201811L + if (std::is_constant_evaluated()) +#endif + { + return vector_mask_countr_common_no_intrinsics_impl(vec); + } +#endif + unsigned d{}; + if constexpr(sizeof(::fast_io::intrinsics::simd_vector)==16) + { +#if defined(__has_builtin) && __has_cpp_attribute(__gnu__::__vector_size__) +#if defined(__SSE2__) && defined(__x86_64__) && __has_builtin(__builtin_ia32_pmovmskb128) + using x86_64_v16qi [[__gnu__::__vector_size__ (16)]] = char; + std::uint_least16_t const value{static_cast(__builtin_ia32_pmovmskb128((x86_64_v16qi)vec.value))}; + if constexpr(ctzero) + { + d=static_cast(std::countr_zero(value)); + } + else + { + d=static_cast(std::countr_one(value)); + } +#elif defined(__wasm_simd128__) && __has_builtin(__builtin_wasm_bitmask_i8x16) + using wasmsimd128_i8x16 [[__gnu__::__vector_size__ (16)]] = char; + ::std::uint_least16_t const value{static_cast<::std::uint_least16_t>(__builtin_wasm_bitmask_i8x16(static_cast(vec.value)))}; + if constexpr(ctzero) + { + d=static_cast(std::countr_zero(value)); + } + else + { + d=static_cast(std::countr_one(value)); + } +#endif +#elif (defined(__x86_64__) || defined(_M_AMD64) || defined(__i386__) || defined(_M_IX86)) + if constexpr(::fast_io::details::cpu_flags::sse2_supported) + { + __m128i a = __builtin_bit_cast(__m128i,vec); + std::uint_least16_t const value{static_cast(_mm_movemask_epi8(a,a))}; + if constexpr(ctzero) + { + d=static_cast(std::countr_zero(value)); + } + else + { + d=static_cast(std::countr_one(value)); + } + } +#endif + } + else if constexpr(sizeof(::fast_io::intrinsics::simd_vector)==32) + { +#if defined(__has_builtin) && __has_cpp_attribute(__gnu__::__vector_size__) +#if defined(__AVX__) && defined(__x86_64__) && __has_builtin(__builtin_ia32_pmovmskb256) + using x86_64_v32qi [[__gnu__::__vector_size__ (32)]] = char; + std::uint_least32_t const value{static_cast(__builtin_ia32_pmovmskb256((x86_64_v32qi)vec.value))}; + if constexpr(ctzero) + { + d=static_cast(std::countr_zero(value)); + } + else + { + d=static_cast(std::countr_one(value)); + } +#endif +#elif (defined(__x86_64__) || defined(_M_AMD64) || defined(__i386__) || defined(_M_IX86)) + if constexpr(::fast_io::details::cpu_flags::avx2_supported) + { + __m256i a = __builtin_bit_cast(__m256i,vec); + std::uint_least32_t const value{static_cast(_mm256_movemask_epi8(a,a))}; + if constexpr(ctzero) + { + d=static_cast(std::countr_zero(value)); + } + else + { + d=static_cast(std::countr_one(value)); + } + } +#endif + } + if constexpr(sizeof(T)==1) + { + return d; + } + else + { + constexpr unsigned shift{static_cast(std::bit_width(sizeof(T)*::std::numeric_limits::digits)-3)}; + return d>>shift; + } +} + +template +inline constexpr unsigned vector_mask_countr_common_impl(::fast_io::intrinsics::simd_vector const& vec) noexcept +{ + if constexpr(can_intrinsics_accelerate_mask_countr) + { + return vector_mask_countr_common_intrinsics_impl(vec); + } + else + { + return vector_mask_countr_common_no_intrinsics_impl(vec); + } +} + +} + +namespace intrinsics +{ + +template +inline constexpr auto vector_mask_countr_one(simd_vector const& vec) noexcept +{ + return ::fast_io::details::vector_mask_countr_common_impl(vec); +} + +template +inline constexpr auto vector_mask_countr_zero(simd_vector const& vec) noexcept +{ + return ::fast_io::details::vector_mask_countr_common_impl(vec); +} + +} + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_core_impl/simd/prrsv.h b/src/fast_io/include/fast_io_core_impl/simd/prrsv.h new file mode 100644 index 0000000..ccf909d --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/simd/prrsv.h @@ -0,0 +1,43 @@ +#pragma once + +namespace fast_io +{ +namespace details +{ + +template<::std::forward_iterator Iter,typename T,std::size_t size> +inline constexpr Iter print_reserve_df_mm_impl(Iter iter,::fast_io::intrinsics::simd_vector const& mm) noexcept +{ + if constexpr(size==0) + return iter; + using char_type = ::std::iter_value_t; + *iter=char_literal_v; + ++iter; + iter=print_reserve_define(io_reserve_type,iter,mm[0]); + for(std::size_t i{1};i!=size;++i) + { + *iter=char_literal_v; + ++iter; + iter=print_reserve_define(io_reserve_type,iter,mm[i]); + } + *iter=char_literal_v; + ++iter; + return iter; +} + +} + + +template +inline constexpr std::size_t print_reserve_size(io_reserve_type_t>) noexcept +{ + constexpr std::size_t p{print_reserve_size(io_reserve_type)}; + constexpr std::size_t sz{(1+p)*n+1}; + return sz; +} +template<::std::forward_iterator Iter,typename T,std::size_t n> +inline constexpr Iter print_reserve_define(io_reserve_type_t<::std::iter_value_t,intrinsics::simd_vector>,Iter iter,intrinsics::simd_vector const& t) noexcept +{ + return details::print_reserve_df_mm_impl(iter,t); +} +} diff --git a/src/fast_io/include/fast_io_core_impl/simd/x86_64.h b/src/fast_io/include/fast_io_core_impl/simd/x86_64.h new file mode 100644 index 0000000..e2f317a --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/simd/x86_64.h @@ -0,0 +1,35 @@ +#pragma once + +namespace fast_io::intrinsics +{ +#if __has_cpp_attribute(__gnu__::__vector_size__) +using x86_64_m128 [[__gnu__::__vector_size__(16),__gnu__::__may_alias__]] = float; +using x86_64_m128d [[__gnu__::__vector_size__(16),__gnu__::__may_alias__]] = double; +using x86_64_m128i [[__gnu__::__vector_size__ (16),__gnu__::__may_alias__]] = long long; +using x86_64_v16qi [[__gnu__::__vector_size__ (16)]] = char; +using x86_64_v16qs [[__gnu__::__vector_size__ (16)]] = char signed; +using x86_64_v16qu [[__gnu__::__vector_size__ (16)]] = char unsigned; +using x86_64_v8hi [[__gnu__::__vector_size__ (16)]] = short; +using x86_64_v8hu [[__gnu__::__vector_size__ (16)]] = short unsigned; +using x86_64_v4si [[__gnu__::__vector_size__ (16)]] = int; +using x86_64_v4su [[__gnu__::__vector_size__ (16)]] = int unsigned; + +using x86_64_m256 [[__gnu__::__vector_size__(32),__gnu__::__may_alias__]] = float; +using x86_64_m256i [[__gnu__::__vector_size__ (32),__gnu__::__may_alias__]] = long long; +using x86_64_m256d [[__gnu__::__vector_size__(32),__gnu__::__may_alias__]] = double; +using x86_64_m512 [[__gnu__::__vector_size__(64),__gnu__::__may_alias__]] = float; +using x86_64_m512i [[__gnu__::__vector_size__ (64),__gnu__::__may_alias__]] = long long; +using x86_64_m512d [[__gnu__::__vector_size__(64),__gnu__::__may_alias__]] = double; +#elif (defined(__x86_64__) || defined(_M_AMD64) || defined(__i386__) || defined(_M_IX86)) +using x86_64_m128 = __m128; +using x86_64_m128i = __m128i; +using x86_64_m128d = __m128d; +using x86_64_m256 = __m256; +using x86_64_m256i = __m256i; +using x86_64_m256d = __m256d; +using x86_64_m512 = __m512; +using x86_64_m512i = __m512i; +using x86_64_m512d = __m512d; + +#endif +} diff --git a/src/fast_io/include/fast_io_core_impl/simd_find.h b/src/fast_io/include/fast_io_core_impl/simd_find.h new file mode 100644 index 0000000..26f96e6 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/simd_find.h @@ -0,0 +1,684 @@ +#pragma once + +namespace fast_io::details +{ +template +inline constexpr auto create_find_simd_vector_with_unsigned_toggle(char_type value) noexcept +{ + ::fast_io::freestanding::array arr; + using signed_char_type = ::std::make_signed_t; + using unsigned_char_type = ::std::make_signed_t; + constexpr unsigned_char_type signed_min_unsigned_val{static_cast(::std::numeric_limits::min())}; + if constexpr(signed_disposition) + { + value=static_cast(static_cast(value)+signed_min_unsigned_val); + } + for(auto& e : arr) + { + e=value; + } + return arr; +} + +template +inline constexpr + ::fast_io::freestanding::array characters_array_impl{ + create_find_simd_vector_with_unsigned_toggle(lfch)}; + +template +inline constexpr + ::fast_io::freestanding::array wide_characters_array_impl{ + create_find_simd_vector_with_unsigned_toggle(lfch)}; + +template +inline constexpr T create_simd_vector_with_all_masks() noexcept +{ + T t{}; + return ~t; +} + +template +requires (sizeof(char_type)<=vec_size)&&(vec_size%sizeof(char_type)==0) +inline constexpr char_type const* find_simd_common_condition_impl(char_type const* first,char_type const* last,Func func) noexcept +{ + constexpr unsigned N{vec_size/sizeof(char_type)}; + using simd_vector_type = ::fast_io::intrinsics::simd_vector; + simd_vector_type simdvec; + for(;N<=static_cast(last-first);first+=N) + { + simdvec.load(first); + if(func(simdvec)) + { + break; + } + } + return first; +} + +template +requires (sizeof(char_type)<=vec_size)&&(vec_size%sizeof(char_type)==0) +inline constexpr char_type const* find_simd_common_all_impl(char_type const* first,char_type const* last,Func func) noexcept +{ + constexpr unsigned N{vec_size/sizeof(char_type)}; + using simd_vector_type = ::fast_io::intrinsics::simd_vector; + if constexpr(findnot) + { + constexpr simd_vector_type zero_vecs{}; + return find_simd_common_condition_impl(first,last,[&](simd_vector_type const& simdvec) noexcept -> bool + { + return !is_all_zeros(func(simdvec)==zero_vecs); + }); + } + else + { + return find_simd_common_condition_impl(first,last,[&](simd_vector_type const& simdvec) noexcept -> bool + { + return !is_all_zeros(func(simdvec)); + }); + } +} + +template +inline constexpr char_type const* find_simd_constant_simd_common_all_impl(char_type const* first,char_type const* last,simd_vector_type const& charsvec) noexcept +{ + return find_simd_common_condition_impl(first,last,[&](simd_vector_type const& simdvec) noexcept -> bool + { + if constexpr(findnot) + { + return !is_all_zeros(simdvec!=charsvec); + } + else + { + return !is_all_zeros(simdvec==charsvec); + } + }); +} + +template +inline constexpr char_type const* find_simd_constant_simd_common_impl(char_type const* first,char_type const* last) noexcept +{ + constexpr char_type lfchct{char_literal_v>}; + constexpr unsigned N{vec_size/sizeof(char_type)}; + using simd_vector_type = ::fast_io::intrinsics::simd_vector; +#if (__cpp_lib_bit_cast >= 201806L) && !defined(__clang__) + constexpr + simd_vector_type charsvec{ + std::bit_cast(characters_array_impl)}; +#else + simd_vector_type charsvec; + charsvec.load(characters_array_impl.data()); +#endif + return find_simd_constant_simd_common_all_impl(first,last,charsvec); +} + +//Change to architectures when they may have efficient unsigned comparison support. Although i do not know any of them. +inline constexpr bool use_signed_vector_type{true}; + +template +inline constexpr wchar_t const* find_space_simd_common_wide_none_utf_encoding_impl(wchar_t const* first,wchar_t const* last) noexcept +{ + using char_type = wchar_t; + using unsigned_char_type = std::make_unsigned_t>; + using signed_char_type = std::make_unsigned_t; + constexpr char_type spacech{L' '}; + constexpr char_type horizontaltab{arithmetic_char_literal_v}; + constexpr char_type verticaltab{L'\v'}; + constexpr unsigned N{vec_size/sizeof(char_type)}; + using simd_vector_type = ::fast_io::intrinsics::simd_vector; + using unsigned_simd_vector_type = ::fast_io::intrinsics::simd_vector; + using signed_simd_vector_type = ::fast_io::intrinsics::simd_vector; + using decision_simd_vector_type = std::conditional_t; + + constexpr char_type five{5}; +#if (__cpp_lib_bit_cast >= 201806L) && !defined(__clang__) + constexpr + decision_simd_vector_type fives{ + std::bit_cast(wide_characters_array_impl)}; + constexpr + decision_simd_vector_type horizontaltabs{ + std::bit_cast(wide_characters_array_impl)}; +#else + decision_simd_vector_type fives; + fives.load(wide_characters_array_impl.data()); + + decision_simd_vector_type horizontaltabs; + horizontaltabs.load(wide_characters_array_impl.data()); +#endif +#if (__cpp_lib_bit_cast >= 201806L) && !defined(__clang__) + constexpr + simd_vector_type spaces{ + std::bit_cast(wide_characters_array_impl)}; +#else + simd_vector_type spaces; + spaces.load(wide_characters_array_impl.data()); +#endif + if constexpr(ishtml) + { +#if (__cpp_lib_bit_cast >= 201806L) && !defined(__clang__) + constexpr + simd_vector_type verticaltabs{ + std::bit_cast(wide_characters_array_impl)}; +#else + + simd_vector_type verticaltabs; + verticaltabs.load(wide_characters_array_impl.data()); +#endif + return find_simd_common_all_impl(first,last,[&](simd_vector_type const& simdvec) noexcept + { + if constexpr(::std::same_as&&wide_is_none_utf_endian) + { + simd_vector_type simdvec_reverse{simdvec}; + simdvec_reverse.swap_endian(); + return (spaces==simdvec)^(static_cast((static_cast(simdvec_reverse)-horizontaltabs)((static_cast(simdvec)-horizontaltabs)(first,last,[&](simd_vector_type const& simdvec) noexcept + { + if constexpr(::std::same_as&&wide_is_none_utf_endian) + { + simd_vector_type simdvec_reverse{simdvec}; + simdvec_reverse.swap_endian(); + return (spaces==simdvec)^(static_cast((static_cast(simdvec_reverse)-horizontaltabs)((static_cast(simdvec)-horizontaltabs) +inline constexpr char_type const* find_space_simd_common_impl(char_type const* first,char_type const* last) noexcept +{ + if constexpr(::std::same_as&&::fast_io::details::wide_is_none_utf_endian) + { + return find_space_simd_common_wide_none_utf_encoding_impl(first,last); + } + else + { + using unsigned_char_type = std::make_unsigned_t>; + using signed_char_type = std::make_unsigned_t; + constexpr char_type spacech{char_literal_v>}; + constexpr char_type horizontaltab{char_literal_v>}; + constexpr char_type verticaltab{char_literal_v>}; + constexpr unsigned N{vec_size/sizeof(char_type)}; + using simd_vector_type = ::fast_io::intrinsics::simd_vector; + using unsigned_simd_vector_type = ::fast_io::intrinsics::simd_vector; + using signed_simd_vector_type = ::fast_io::intrinsics::simd_vector; + + using decision_simd_vector_type = std::conditional_t; + + +#if (__cpp_lib_bit_cast >= 201806L) && !defined(__clang__) + constexpr + simd_vector_type spaces{ + std::bit_cast(characters_array_impl)}; +#else + simd_vector_type spaces; + spaces.load(characters_array_impl.data()); +#endif + if constexpr(is_ebcdic) + { +/* +For EBCDIC NL should also get supported. +ASCII: horizontal tab (0x09, '\t'), EBCDIC:5 +ASCII: vertical tab (0x0b, '\v'), EBCDIC:11 +ASCII: form feed (0x0c, '\f'), EBCDIC:12 +ASCII: carriage return (0x0d, '\r'), EBCDIC:13 +EBCDIC specific: NL:21 +ASCII: line feed (0x0a, '\n'), EBCDIC:37 +ASCII: space (0x20, ' '), EBCDIC:64 +*/ + constexpr char_type three{3}; + constexpr char_type ebcdic_specific_nl{21}; + constexpr char_type linefeed{char_literal_v>}; +#if (__cpp_lib_bit_cast >= 201806L) && !defined(__clang__) + constexpr + simd_vector_type ebcdic_specific_nls{ + std::bit_cast(characters_array_impl)}; + constexpr + simd_vector_type linefeeds{ + std::bit_cast(characters_array_impl)}; + constexpr + simd_vector_type horizontaltabs{ + std::bit_cast(characters_array_impl)}; +#else + simd_vector_type ebcdic_specific_nls,linefeeds,horizontaltabs; + + ebcdic_specific_nls.load(characters_array_impl.data()); + linefeeds.load(characters_array_impl.data()); + horizontaltabs.load(characters_array_impl.data()); +#endif + + if constexpr(ishtml) + { + constexpr char_type formfeed{char_literal_v>}; + constexpr char_type carriagereturn{char_literal_v>}; +#if (__cpp_lib_bit_cast >= 201806L) && !defined(__clang__) + constexpr + simd_vector_type formfeeds{ + std::bit_cast(characters_array_impl)}; + constexpr + simd_vector_type carriagereturns{ + std::bit_cast(characters_array_impl)}; +#else + simd_vector_type formfeeds,carriagereturns; + formfeeds.load(characters_array_impl.data()); + carriagereturns.load(characters_array_impl.data()); +#endif + return find_simd_common_all_impl(first,last,[&](simd_vector_type const& simdvec) noexcept + { + return (horizontaltabs==simdvec)^(formfeeds==simdvec)^(carriagereturns==simdvec)^ + (ebcdic_specific_nls==simdvec)^(linefeeds==simdvec)^(spaces==simdvec); + }); + } + else + { +#if (__cpp_lib_bit_cast >= 201806L) && !defined(__clang__) + constexpr + decision_simd_vector_type threes{ + std::bit_cast(characters_array_impl)}; + constexpr + decision_simd_vector_type verticaltabs{ + std::bit_cast(characters_array_impl)}; +#else + decision_simd_vector_type threes,verticaltabs; + threes.load(characters_array_impl.data()); + verticaltabs.load(characters_array_impl.data()); +#endif + return find_simd_common_all_impl(first,last,[&](simd_vector_type const& simdvec) noexcept + { + return (horizontaltabs==simdvec)^ + static_cast((static_cast(simdvec)-verticaltabs)= 201806L) && !defined(__clang__) + constexpr + decision_simd_vector_type fives{ + std::bit_cast(characters_array_impl)}; + constexpr + decision_simd_vector_type horizontaltabs{ + std::bit_cast(characters_array_impl)}; +#else + decision_simd_vector_type fives; + fives.load(characters_array_impl.data()); + + decision_simd_vector_type horizontaltabs; + horizontaltabs.load(characters_array_impl.data()); +#endif + + if constexpr(ishtml) + { +#if (__cpp_lib_bit_cast >= 201806L) && !defined(__clang__) + constexpr + simd_vector_type verticaltabs{ + std::bit_cast(characters_array_impl)}; +#else + + simd_vector_type verticaltabs; + verticaltabs.load(characters_array_impl.data()); +#endif + return find_simd_common_all_impl(first,last,[&](simd_vector_type const& simdvec) noexcept + { + return (spaces==simdvec)^(static_cast((static_cast(simdvec)-horizontaltabs)(first,last,[&](simd_vector_type const& simdvec) noexcept + { + return (spaces==simdvec)^(static_cast((static_cast(simdvec)-horizontaltabs) +https://github.com/bminor/musl/blob/master/src/string/memchr.c +*/ +template +inline constexpr char unsigned const* find_characters_musl(char unsigned const* first,char unsigned const* last,char unsigned ch) noexcept +{ +#if __cpp_if_consteval >= 202106L + if !consteval +#else + if(!std::is_constant_evaluated()) +#endif + { + constexpr std::size_t diff{sizeof(std::size_t)}; + + constexpr char unsigned ucharmx{std::numeric_limits::max()}; + constexpr std::size_t ones{std::numeric_limits::max()/ucharmx}; + constexpr std::size_t highs{ones*(ucharmx/2+1)}; + if(first!=last&&*first!=ch) + { + for(std::size_t const constantk{ones*ch};diff<=static_cast(last-first);first+=diff) + { + + std::size_t x; +#if defined(_MSC_VER) && !defined(__clang__) + std::memcpy(__builtin_addressof(x),first,diff); +#else + __builtin_memcpy(__builtin_addressof(x),first,diff); +#endif + x^=constantk; + std::size_t v{(x-ones)&(~x)&highs}; + if constexpr(findnot) + { + if(v!=highs) + { + break; + } + + } + else + { + if(v) + { + break; + } + } + } + } + } + if constexpr(findnot) + { + for(;first!=last&&*first==ch;++first); + } + else + { + for(;first!=last&&*first!=ch;++first); + } + return first; +} + +template +inline constexpr char_type const* find_simd_constant_common_cold_impl(char_type const* first,char_type const* last) noexcept +{ + constexpr char_type lfchct{char_literal_v>}; +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L +#if __cpp_if_consteval >= 202106L + if !consteval +#else + if(!std::is_constant_evaluated()) +#endif + { + constexpr bool use_builtin_memchr{ +#if (__STDC_HOSTED__==1 && (!defined(_GLIBCXX_HOSTED) || _GLIBCXX_HOSTED==1)) && !defined(_LIBCPP_FREESTANDING) +#if defined(__GLIBC__) && defined(__GLIBC_MINOR__) +#if (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 26)) +//For glibc >= 2.26, we use glibc's memchr implementation under hosted environment + !findnot +#endif +#endif +#endif + }; + if constexpr(use_builtin_memchr&&(sizeof(char_type)==1||(sizeof(char_type)==4&&sizeof(wchar_t)==4))) + { + std::size_t diff{static_cast(last-first)}; + if(diff==0) +#if __has_cpp_attribute(likely) + [[likely]] +#endif + { + return first; + } + void* ret; + if constexpr(sizeof(char_type)==1) + { + ret = __builtin_memchr(first,lfchct,diff); + } + else + { + ret = __builtin_wmemchr(first,lfchct,diff); + } + if(ret==nullptr) + { + return last; + } + return reinterpret_cast(ret); + } + else if constexpr(::fast_io::details::optimal_simd_vector_run_with_cpu_instruction_size) + { + first=find_simd_constant_simd_common_impl(first,last); + } + else if constexpr(sizeof(char_type)==1) + { + char unsigned const* firstconstptr{reinterpret_cast(first)}; + return find_characters_musl(firstconstptr,reinterpret_cast(last),lfchct)-firstconstptr+first; + } + } +#endif + if constexpr(findnot) + { + return ::fast_io::freestanding::find_not(first,last,lfchct); + } + else + { + return ::fast_io::freestanding::find(first,last,lfchct); + } +} + +template +inline constexpr char_type const* find_simd_small_optimization_common_impl(char_type const* first,char_type const* last,Pred pred,Func func) noexcept +{ + constexpr std::size_t initialdiffn{::fast_io::details::optimal_simd_vector_run_with_cpu_instruction_size? + ::fast_io::details::optimal_simd_vector_run_with_cpu_instruction_size: + (secondlevelopt?sizeof(std::size_t):0)}; + if constexpr(sizeof(std::uint_least16_t)(last-first)}; + if(initialdiffn +inline constexpr char_type const* find_simd_constant_common_impl(char_type const* first,char_type const* last) noexcept +{ + return find_simd_small_optimization_common_impl(first,last,[](char_type ch) noexcept + { + constexpr char_type lfchct{char_literal_v>}; + if constexpr(findnot) + { + return ch==lfchct; + } + else + { + return ch!=lfchct; + } + },[](char_type const* first2,char_type const* last2) noexcept + { + return find_simd_constant_common_cold_impl(first2,last2); + }); +} + +template +requires (::std::integral<::std::iter_value_t>) +inline constexpr Iter find_space_common_iterator_generic_impl(Iter begin,Iter end) +{ + if constexpr(ishtml) + { + if constexpr(findnot) + { + for(;begin!=end&&fast_io::char_category::is_html_whitespace(*begin);++begin); + } + else + { + for(;begin!=end&&!fast_io::char_category::is_html_whitespace(*begin);++begin); + } + } + else + { + if constexpr(findnot) + { + for(;begin!=end&&fast_io::char_category::is_c_space(*begin);++begin); + } + else + { + for(;begin!=end&&!fast_io::char_category::is_c_space(*begin);++begin); + } + } + return begin; +} + +template +inline constexpr char_type const* find_space_common_cold_impl(char_type const* first,char_type const* last) noexcept +{ +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L +#if __cpp_if_consteval >= 202106L + if !consteval +#else + if(!std::is_constant_evaluated()) +#endif + { + if constexpr(::fast_io::details::optimal_simd_vector_run_with_cpu_instruction_size) + { + first=find_space_simd_common_impl(first,last); + } + } +#endif + return find_space_common_iterator_generic_impl(first,last); +} + +template +inline constexpr char_type const* find_space_common_impl(char_type const* first,char_type const* last) noexcept +{ + return find_simd_small_optimization_common_impl(first,last,[](char_type ch) noexcept + { + if constexpr(ishtml) + { + if constexpr(findnot) + { + return fast_io::char_category::is_html_whitespace(ch); + } + else + { + return !fast_io::char_category::is_html_whitespace(ch); + } + } + else + { + if constexpr(findnot) + { + return fast_io::char_category::is_c_space(ch); + } + else + { + return !fast_io::char_category::is_c_space(ch); + } + } + },[](char_type const* first2,char_type const* last2) noexcept + { + return find_space_common_cold_impl(first2,last2); + }); +} + +template +inline constexpr char_type const* find_lf_simd_impl(char_type const* first,char_type const* last) noexcept +{ + return find_simd_constant_common_impl(first,last); +} + +template +inline constexpr char_type const* find_none_zero_simd_impl(char_type const* first,char_type const* last) noexcept +{ + return find_simd_constant_common_impl(first,last); +} + +template +requires (::std::integral<::std::iter_value_t>) +inline constexpr Iter find_space_impl(Iter first,Iter last) +{ + using value_type = ::std::iter_value_t; + if constexpr(!::std::is_volatile_v&&::std::contiguous_iterator) + { + if constexpr(::std::same_as const>) + { + return ::fast_io::details::find_space_common_impl(first,last); + } + else if constexpr(::std::is_pointer_v) + { + ::std::remove_cvref_t const* first_const_ptr{first}; + return ::fast_io::details::find_space_common_impl(first_const_ptr,last)-first_const_ptr+first; + } + else + { + ::std::remove_cvref_t const* first_const_ptr{std::to_address(first)}; + return ::fast_io::details::find_space_common_impl(first_const_ptr,std::to_address(last))-first_const_ptr+first; + } + } + else + { + return find_space_common_iterator_generic_impl(first,last); + } +} + +template +requires (::std::integral<::std::iter_value_t>) +inline constexpr Iter find_ch_impl(Iter first,Iter last) +{ + using value_type = ::std::iter_value_t; + if constexpr(!::std::is_volatile_v&&::std::contiguous_iterator) + { + if constexpr(::std::same_as const>) + { + return ::fast_io::details::find_simd_constant_common_impl(first,last); + } + else if constexpr(::std::is_pointer_v) + { + ::std::remove_cvref_t const* first_const_ptr{first}; + return ::fast_io::details::find_simd_constant_common_impl(first_const_ptr,last)-first_const_ptr+first; + } + else + { + ::std::remove_cvref_t const* first_const_ptr{std::to_address(first)}; + return ::fast_io::details::find_simd_constant_common_impl(first_const_ptr,std::to_address(last))-first_const_ptr+first; + } + } + else + { + constexpr auto lfchct{char_literal_v>}; + if constexpr(findnot) + { + return ::fast_io::freestanding::find_not(first,last,lfchct); + } + else + { + return ::fast_io::freestanding::find(first,last,lfchct); + } + } +} + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_core_impl/socket/addrprt.h b/src/fast_io/include/fast_io_core_impl/socket/addrprt.h new file mode 100644 index 0000000..8b9ae94 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/socket/addrprt.h @@ -0,0 +1,387 @@ +#pragma once + +namespace fast_io +{ + +namespace details +{ + +template<::std::integral char_type> +inline constexpr char_type* prtrsv_inaddr_common_define_impl(char_type* it,char unsigned const * __restrict start) noexcept +{ + for(auto i{start},e{start+4};i!=e;++i) + { + if(i!=start) + { + *it=::fast_io::char_literal_v; + ++it; + } + it=print_reserve_integral_define<10>(it,*i); + } + return it; +} + +template +inline constexpr char_type* prtrsv_in6addr_common_define_impl(char_type *it,::std::uint_least16_t const * __restrict start) noexcept +{ + if constexpr(showv6bracket) + { + *it = ::fast_io::char_literal_v; + ++it; + it = prtrsv_in6addr_common_define_impl(it,start); + *it = ::fast_io::char_literal_v; + ++it; + } + else if constexpr(shorten) + { + auto const e{start+8}; + auto maxposition{e},maxposition_end{e}; + for(auto i{start};i!=e;) + { + if(*i==0) + { + auto j{i+1}; + for(;j!=e&&*j==0;++j); + ::std::size_t diff{static_cast<::std::size_t>(j-i)}; + if(1(maxposition_end-maxposition)}; + if(max_last) + { + it = copy_string_literal("::",it); + } + else if constexpr(::std::same_as) + { + it = copy_string_literal(L"::",it); + } + else if constexpr(::std::same_as) + { + it = copy_string_literal(u"::",it); + } + else if constexpr(::std::same_as) + { + it = copy_string_literal(U"::",it); + } + else + { + it = copy_string_literal(u8"::",it); + } + i = maxposition_end; + } + else + { + if(i!=start&&i!=maxposition_end) + { + *it=::fast_io::char_literal_v; + ++it; + } + it=print_reserve_integral_define<16,false,false,false,uppercase,full>(it,::fast_io::big_endian(*i)); + ++i; + } + } + } + else + { + for(auto i{start},e{start+8};i!=e;++i) + { + if(i!=start) + { + *it=::fast_io::char_literal_v; + ++it; + } + it=print_reserve_integral_define<16,false,false,false,uppercase,full>(it,::fast_io::big_endian(*i)); + } + } + return it; +} + +template<::std::integral char_type,::std::unsigned_integral porttype> +inline constexpr char_type* prtrsv_ipport_define_impl(char_type* it,porttype port) noexcept +{ + *it=::fast_io::char_literal_v; + ++it; + return ::fast_io::details::print_reserve_integral_define<10>(it,port); +} + +template<::std::integral char_type> +inline constexpr char_type* prtrsv_ipport_zero_define_impl(char_type* it) noexcept +{ + if constexpr(::std::same_as) + { + return copy_string_literal(":0",it); + } + else if constexpr(::std::same_as) + { + return copy_string_literal(L":0",it); + } + else if constexpr(::std::same_as) + { + return copy_string_literal(u":0",it); + } + else if constexpr(::std::same_as) + { + return copy_string_literal(U":0",it); + } + else + { + return copy_string_literal(u8":0",it); + } +} + +template +inline constexpr char_type* prtrsv_inaddr_define_impl(char_type* it,::fast_io::posix_in_addr v) noexcept +{ + it = prtrsv_inaddr_common_define_impl(it,v.address); + if constexpr(showport) + { + it = prtrsv_ipport_zero_define_impl(it); + } + return it; +} + +template +inline constexpr char_type* prtrsv_ipv4_define_impl(char_type* it,::fast_io::ipv4 v) noexcept +{ + it = prtrsv_inaddr_common_define_impl(it,v.address.address); + if constexpr(showport) + { + it = prtrsv_ipport_define_impl(it,v.port); + } + return it; +} + +template +inline constexpr char_type* prtrsv_inaddr6_define_impl(char_type* it,::fast_io::posix_in6_addr v) noexcept +{ + it = prtrsv_in6addr_common_define_impl(it,v.address); + if constexpr(showport) + { + it = prtrsv_ipport_zero_define_impl(it); + } + return it; +} + +template +inline constexpr char_type* prtrsv_ipv6_define_impl(char_type* it,::fast_io::ipv6 v) noexcept +{ + it = prtrsv_in6addr_common_define_impl(it,v.address.address); + if constexpr(showport) + { + it = prtrsv_ipport_define_impl(it,v.port); + } + return it; +} + +template +inline constexpr char_type* prtrsv_ip_address_define_impl(char_type *it,::fast_io::ip_address v) noexcept +{ + if constexpr(showport) + { + it = prtrsv_ip_address_define_impl(it,v); + return prtrsv_ipport_zero_define_impl(it); + } + else + { + if(v.isv4) + { + it = prtrsv_inaddr_common_define_impl(it,v.address.v4.address); + } + else + { + it = prtrsv_in6addr_common_define_impl(it,v.address.v6.address); + } + return it; + } +} + +template +inline constexpr char_type* prtrsv_ip_define_impl(char_type* it,::fast_io::ip v) noexcept +{ + it = prtrsv_ip_address_define_impl(it,v.address); + if constexpr(showport) + { + it = prtrsv_ipport_define_impl(it,v.port); + } + return it; +} + +template +concept inaddrnocvrefimpl = ::std::same_as|| + ::std::same_as|| + ::std::same_as; + +template +concept iptypesnocvrefimpl = ::fast_io::details::inaddrnocvrefimpl|| + ::std::same_as|| + ::std::same_as|| + ::std::same_as; + +template +concept inaddrimpl = ::fast_io::details::inaddrnocvrefimpl<::std::remove_cvref_t>; + +template +concept iptypesimpl = ::fast_io::details::iptypesnocvrefimpl<::std::remove_cvref_t>; + +} + +template<::fast_io::details::iptypesimpl iptype> +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr ::fast_io::manipulators::ip_manip_t< + ::fast_io::details::inaddrimpl? + ::fast_io::manipulators::ip_default_inaddr_flags + : + ::fast_io::manipulators::ip_default_flags,::std::remove_cvref_t> print_alias_define(io_alias_t,iptype t) noexcept +{ + return {t}; +} + +template<::std::integral char_type,::fast_io::manipulators::ip_flags flags,::fast_io::details::iptypesimpl iptype> +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr ::std::size_t + print_reserve_size(::fast_io::io_reserve_type_t>) noexcept +{ + using nocvreftype = ::std::remove_cvref_t; + + + constexpr + ::std::size_t portsize{::fast_io::details::print_integer_reserved_size_cache<10,false,false,::std::uint_least16_t>}; + + constexpr + ::std::size_t v4intsize{::fast_io::details::print_integer_reserved_size_cache<10,false,false,char unsigned>}; + + constexpr + ::std::size_t v4totalsize{(v4intsize+1)*4-1}; + + constexpr + ::std::size_t v4sizewithport{v4totalsize+portsize+1}; + + //constexpr + // ::std::size_t prefixlength{v4intsize+portsize+1}; + + + if constexpr(::std::same_as|| + ::std::same_as) + { + if constexpr(flags.showport) + { + return v4sizewithport; + } + else + { + return v4totalsize; + } + } + else + { + constexpr + ::std::size_t v6intsize{portsize}; + + constexpr + ::std::size_t v6totalsize{(v6intsize+1)*8-1}; + + constexpr + ::std::size_t v6totalsizebracket{v6totalsize+2}; + + constexpr + ::std::size_t v6sizewithport{v6totalsizebracket+2+portsize}; + + static_assert(v4intsize +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr char_type* print_reserve_define(::fast_io::io_reserve_type_t>,char_type* iter,::fast_io::manipulators::ip_manip_t val) noexcept +{ + //using nocvreftype = ::std::remove_cvref_t; + if constexpr(::std::same_as) + { + return ::fast_io::details::prtrsv_inaddr_define_impl(iter,val.reference); + } + else if constexpr(::std::same_as) + { + return ::fast_io::details::prtrsv_ipv4_define_impl(iter,val.reference); + } + else if constexpr(::std::same_as) + { + return ::fast_io::details::prtrsv_inaddr6_define_impl(iter,val.reference); + } + else if constexpr(::std::same_as) + { + return ::fast_io::details::prtrsv_ipv6_define_impl(iter,val.reference); + } + else if constexpr(::std::same_as) + { + return ::fast_io::details::prtrsv_ip_address_define_impl(iter,val.reference); + } + else + { + return ::fast_io::details::prtrsv_ip_define_impl(iter,val.reference); + } +} + + +namespace manipulators +{ + +template +inline constexpr ip_manip_t> ip_generic(iptype ipaddr) noexcept +{ + return {ipaddr}; +} + +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/socket/addrscn.h b/src/fast_io/include/fast_io_core_impl/socket/addrscn.h new file mode 100644 index 0000000..6057310 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/socket/addrscn.h @@ -0,0 +1,668 @@ +#pragma once + +namespace fast_io +{ + +enum class scan_ipv4_context_phase : ::std::uint_least8_t +{ + addr0, + dot0, + addr1, + dot1, + addr2, + dot2, + addr3 +}; + +enum class scan_ipv6_context_phase : ::std::uint_least8_t +{ + nothing, +}; + +enum class scan_integral_context_phase : ::std::uint_least8_t; +template +struct ip_scan_state_t +{ + // TODO: to find out why +1 is needed here + static inline constexpr auto max_size{ ::fast_io::details::print_integer_reserved_size_cache<10, false, false, ::std::uint_least16_t> +1 }; + ::fast_io::freestanding::array buffer; + scan_integral_context_phase integer_phase{}; + ::std::uint_least8_t size{}; + phase_t ip_phase{}; + static inline constexpr ::std::uint_least8_t port_mark = -1; + static inline constexpr ::std::uint_least8_t port = -2; +}; +template <::std::integral char_type> +using ipv4_scan_state_t = ip_scan_state_t; +template <::std::integral char_type> +using ipv6_scan_state_t = ip_scan_state_t; +template <::std::integral char_type> +using ip_port_scan_state_t = ip_scan_state_t<::std::uint_least8_t, char_type>; + +namespace details { + +template <::std::integral char_type> +inline constexpr parse_result scn_cnt_define_inaddr_impl(char_type const* begin, char_type const* end, posix_in_addr& t) noexcept +{ + if (end - begin < 7) [[unlikely]] + return { begin, parse_code::invalid }; + auto [itr0, ec0] = scan_int_contiguous_define_impl<10, true, false, false>(begin, begin + 3, t.address[0]); + if (ec0 != parse_code::ok) [[unlikely]] + return { itr0, ec0 }; + if constexpr (sizeof(decltype(t.address[0])) != 1) + { + if (t.address[0] >= 256u) [[unlikely]] + return { itr0, parse_code::overflow }; + } + begin = itr0; + if (begin == end || *begin != char_literal_v) [[unlikely]] + return { begin, parse_code::invalid }; + ++begin; + auto [itr1, ec1] = scan_int_contiguous_define_impl<10, true, false, false>(begin, begin + 3, t.address[1]); + if (ec1 != parse_code::ok) [[unlikely]] + return { itr1, ec1 }; + if constexpr (sizeof(decltype(t.address[1])) != 1) + { + if (t.address[1] >= 256u) [[unlikely]] + return { itr1, parse_code::overflow }; + } + begin = itr1; + if (begin == end || *begin != char_literal_v) [[unlikely]] + return { begin, parse_code::invalid }; + ++begin; + if (end - begin < 3) [[unlikely]] + return { begin, parse_code::invalid }; + auto [itr2, ec2] = scan_int_contiguous_define_impl<10, true, false, false>(begin, begin + 3, t.address[2]); + if (ec2 != parse_code::ok) [[unlikely]] + return { itr2, ec2 }; + if constexpr (sizeof(decltype(t.address[2])) != 1) + { + if (t.address[2] >= 256u) [[unlikely]] + return { itr2, parse_code::overflow }; + } + begin = itr2; + if (begin == end || *begin != char_literal_v) [[unlikely]] + return { begin, parse_code::invalid }; + ++begin; + auto [itr3, ec3] = scan_int_contiguous_define_impl<10, true, false, false>(begin, end, t.address[3]); + if (ec3 != parse_code::ok) [[unlikely]] + return { itr3, ec3 }; + if constexpr (sizeof(decltype(t.address[3])) != 1) + { + if (t.address[3] >= 256u) [[unlikely]] + return { itr3, parse_code::overflow }; + } + begin = itr3; + return { begin, parse_code::ok }; +} + +template <::std::integral char_type> +inline constexpr parse_result scn_ctx_define_inaddr_impl(ipv4_scan_state_t& state, char_type const* begin, char_type const* end, posix_in_addr& t) noexcept +{ + switch (state.ip_phase) + { + case scan_ipv4_context_phase::addr0: + { + if (begin == end) + return { begin, parse_code::partial }; + auto [itr, ec] = scan_context_define_parse_impl<10, false, false, false>(state, begin, end, t.address[0]); + if (ec != parse_code::ok) [[unlikely]] + return { itr, ec }; + if constexpr (sizeof(decltype(t.address[0])) != 1) + { + if (t.address[0] >= 256) [[unlikely]] + return { itr, parse_code::overflow }; + } + state.size = 0; + state.integer_phase = scan_integral_context_phase::zero; + begin = itr; + state.ip_phase = scan_ipv4_context_phase::dot0; + [[fallthrough]]; + } + case scan_ipv4_context_phase::dot0: + { + if (begin == end) + return { begin, parse_code::partial }; + if (*begin != char_literal_v) [[unlikely]] + return { begin, parse_code::invalid }; + ++begin; + state.ip_phase = scan_ipv4_context_phase::addr1; + [[fallthrough]]; + } + case scan_ipv4_context_phase::addr1: + { + if (begin == end) + return { begin, parse_code::partial }; + auto [itr, ec] = scan_context_define_parse_impl<10, true, false, false>(state, begin, end, t.address[1]); + if (ec != parse_code::ok) [[unlikely]] + return { itr, ec }; + if constexpr (sizeof(decltype(t.address[1])) != 1) + { + if (t.address[1] >= 256) [[unlikely]] + return { itr, parse_code::overflow }; + } + state.size = 0; + state.integer_phase = scan_integral_context_phase::zero; + begin = itr; + state.ip_phase = scan_ipv4_context_phase::dot1; + [[fallthrough]]; + } + case scan_ipv4_context_phase::dot1: + { + if (begin == end) + return { begin, parse_code::partial }; + if (*begin != char_literal_v) [[unlikely]] + return { begin, parse_code::invalid }; + ++begin; + state.ip_phase = scan_ipv4_context_phase::addr2; + [[fallthrough]]; + } + case scan_ipv4_context_phase::addr2: + { + if (begin == end) + return { begin, parse_code::partial }; + auto [itr, ec] = scan_context_define_parse_impl<10, true, false, false>(state, begin, end, t.address[2]); + if (ec != parse_code::ok) [[unlikely]] + return { itr, ec }; + if constexpr (sizeof(decltype(t.address[2])) != 1) + { + if (t.address[2] >= 256) [[unlikely]] + return { itr, parse_code::overflow }; + } + state.size = 0; + state.integer_phase = scan_integral_context_phase::zero; + begin = itr; + state.ip_phase = scan_ipv4_context_phase::dot2; + [[fallthrough]]; + } + case scan_ipv4_context_phase::dot2: + { + if (begin == end) + return { begin, parse_code::partial }; + if (*begin != char_literal_v) [[unlikely]] + return { begin, parse_code::invalid }; + ++begin; + state.ip_phase = scan_ipv4_context_phase::addr3; + [[fallthrough]]; + } + case scan_ipv4_context_phase::addr3: + { + if (begin == end) + return { begin, parse_code::partial }; + auto [itr, ec] = scan_context_define_parse_impl<10, true, false, false>(state, begin, end, t.address[3]); + if (ec != parse_code::ok) [[unlikely]] + return { itr, ec }; + if constexpr (sizeof(decltype(t.address[3])) != 1) + { + if (t.address[3] >= 256) [[unlikely]] + return { itr, parse_code::overflow }; + } + begin = itr; + return { begin, parse_code::ok }; + } + } +#ifdef __has_builtin +#if __has_builtin(__builtin_unreachable) + __builtin_unreachable(); +#endif +#endif +} + +template <::std::integral char_type> +inline constexpr parse_result scn_cnt_define_port_impl(char_type const* begin, char_type const* end, ::std::uint_least16_t& t) noexcept +{ + if (begin == end) [[unlikely]] + return { begin, parse_code::invalid }; + if (*begin != char_literal_v) [[unlikely]] + return { begin, parse_code::invalid }; + ++begin; + return scan_int_contiguous_define_impl<10, true, false, false>(begin, end, t); +} + +template <::std::integral char_type> +inline constexpr parse_result scn_ctx_define_port_impl(ip_port_scan_state_t& state, char_type const* begin, char_type const* end, ::std::uint_least16_t& t) noexcept +{ + switch (state.ip_phase) + { + case state.port_mark: + if (begin == end) + return { begin, parse_code::partial }; + if (*begin != char_literal_v) [[unlikely]] + return { begin, parse_code::invalid }; + ++begin; + state.ip_phase = state.port; + [[fallthrough]]; + case state.port: + if (begin == end) + return { begin, parse_code::partial }; + 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 + } +} + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr parse_result scn_ctx_define_port_type_general_impl(state_t& state, char_type const* begin, char_type const* end, ::std::uint_least16_t& t) noexcept +{ + auto new_state{ ::std::bit_cast>(state) }; + auto result{ scn_ctx_define_port_impl(new_state, begin, end, t) }; + state = ::std::bit_cast(new_state); + return result; +} + +template +inline constexpr parse_result scn_cnt_define_in6addr_4_digits_impl(char_type const* begin, char_type const* end, ::std::uint_least16_t& t) noexcept +{ + constexpr bool big_endian{ ::std::endian::native == ::std::endian::big }; + using unsigned_char_type = ::std::make_unsigned_t; + ::std::uint_least8_t retval[2]; + if (begin == end) [[unlikely]] + return { begin, parse_code::invalid }; + if (*begin == char_literal_v) [[unlikely]] + // use eof here to represent shorten case. should be handled from the caller. + return { begin, parse_code::end_of_file }; + bool zero_started{}; + // loop unrolled, because each time the return changes a bit + auto result{ static_cast(*begin) }; + if (char_digit_to_literal<16, char_type>(result)) [[unlikely]] + return { begin, parse_code::invalid }; + if (result == 0) + zero_started = true; + retval[0] = result; + ++begin; + if (begin == end) + { + if constexpr (big_endian) + t = retval[0]; + else + t = retval[0] << 8; + return { begin, parse_code::ok }; + } + result = *begin; + if (char_digit_to_literal<16, char_type>(result)) + { + if constexpr (big_endian) + t = retval[0]; + else + t = retval[0] << 8; + return { begin, parse_code::ok }; + } + retval[0] *= 16; + retval[0] += result; + ++begin; + if (begin == end) + { + if (zero_started) [[unlikely]] + return { begin, parse_code::invalid }; + else + { + if constexpr (big_endian) + t = retval[0]; + else + t = retval[0] << 8; + return { begin, parse_code::ok }; + } + } + result = *begin; + if (char_digit_to_literal<16, char_type>(result)) + { + if (zero_started) [[unlikely]] + return { begin, parse_code::invalid }; + else + { + if constexpr (big_endian) + t = retval[0]; + else + t = retval[0] << 8; + return { begin, parse_code::ok }; + } + } + retval[1] = result; + ++begin; + if (begin == end) + { + if (zero_started) [[unlikely]] + return { begin, parse_code::invalid }; + else + { + if constexpr (big_endian) + t = retval[0] | retval[1] << 8; + else + t = retval[0] << 8 | retval[1]; + return { begin, parse_code::ok }; + } + } + result = *begin; + if (char_digit_to_literal<16, char_type>(result)) + { + if (zero_started) [[unlikely]] + return { begin, parse_code::invalid }; + else + { + if constexpr (big_endian) + t = retval[0] | retval[1] << 8; + else + t = retval[0] << 8 | retval[1]; + return { begin, parse_code::ok }; + } + } + retval[1] *= 16; + retval[1] += result; + ++begin; + if (begin != end && char_is_digit<16, char_type>(*begin)) [[unlikely]] + return { begin, parse_code::overflow }; + if constexpr (big_endian) + t = retval[0] | retval[1] << 8; + else + t = retval[0] << 8 | retval[1]; + return { begin, parse_code::ok }; +} + +template +inline constexpr parse_result scn_cnt_define_in6addr_shorten_impl(char_type const* begin, char_type const* end, posix_in6_addr& t) noexcept +{ + struct in6addr_scan_basic_state_t + { + ::std::uint_least8_t seg_cnt{}; + ::std::uint_least8_t shorten_begin_index{}; + ::std::uint_least8_t cur_zero_len{}; + ::std::uint_least8_t max_zero_len{}; + }; + in6addr_scan_basic_state_t state; + while (state.seg_cnt < 8) + { + ::std::uint_least16_t addrvalue; + auto [itr, ec] = scn_cnt_define_in6addr_4_digits_impl(begin, end, addrvalue); + begin = itr; + if (ec == parse_code::ok) + { + t.address[state.seg_cnt] = addrvalue; + if (addrvalue != 0) + { + if (state.cur_zero_len > state.max_zero_len) [[unlikely]] + { + state.max_zero_len = state.cur_zero_len; + state.cur_zero_len = 0; + } + ++state.seg_cnt; + continue; + } + else + { + ++state.cur_zero_len; + ++state.seg_cnt; + continue; + } + } + else if (ec == parse_code::end_of_file) + { + if (state.shorten_begin_index != 0) [[unlikely]] + return { begin, parse_code::invalid }; + // TODO + } + else [[unlikely]] + return { itr, ec }; + } +} + +template +inline constexpr parse_result scn_cnt_define_in6addr_nonshorten_impl(char_type const* begin, char_type const* end, posix_in6_addr& t) noexcept +{ + for (::std::size_t i{}; i < 7; ++i) + { + auto [itr, ec] = scn_cnt_define_in6addr_4_digits_impl(begin, end, t.address[i]); + if (ec != parse_code::ok) [[unlikely]] + { + if (ec == parse_code::end_of_file) + return { itr, parse_code::invalid }; + else + return { itr, ec }; + } + if (*itr != char_literal_v) [[unlikely]] + return { itr, parse_code::invalid }; + begin = itr + 1; + } + auto [itr, ec] = scn_cnt_define_in6addr_4_digits_impl(begin, end, t.address[7]); + if (ec != parse_code::ok) [[unlikely]] + { + if (ec == parse_code::end_of_file) + return { itr, parse_code::invalid }; + else + return { itr, ec }; + } + return { itr, parse_code::ok }; +} + +template +inline constexpr parse_result scn_cnt_define_in6addr_full_impl(char_type const* begin, char_type const* end, posix_in6_addr& t) noexcept +{ + if constexpr (true) + return scn_cnt_define_in6addr_nonshorten_impl(begin, end, t); +} + +template +inline constexpr parse_result scn_cnt_define_in6addr_impl(char_type const* begin, char_type const* end, posix_in6_addr& t) noexcept +{ + begin = ::fast_io::details::find_space_common_impl(begin, end); + if constexpr (allowv6bracket) + { + if (begin == end) [[unlikely]] + return { begin, parse_code::invalid }; + if (*begin != char_literal_v) [[unlikely]] + return scn_cnt_define_in6addr_impl(begin, end, t); + ++begin; + auto result = scn_cnt_define_in6addr_impl(begin, end, t); + if (result.code != parse_code::ok) [[unlikely]] + return result; + begin = result.iter; + if (begin == end) [[unlikely]] + return { begin, parse_code::invalid }; + if (*begin != char_literal_v) [[unlikely]] + return { begin, parse_code::invalid }; + return { begin + 1, parse_code::ok }; + } + if constexpr (allowv6shorten) + return scn_cnt_define_in6addr_shorten_impl(begin, end, t); + else if constexpr (requirev6full) + return scn_cnt_define_in6addr_full_impl(begin, end, t); + else + return scn_cnt_define_in6addr_nonshorten_impl(begin, end, t); +} + +} + +namespace manipulators +{ + +template +inline constexpr ip_scan_manip_t*> ip_scan_generic(iptype& ipaddr) noexcept +{ + return { __builtin_addressof(ipaddr) }; +} + +} + +#if 0 +inline constexpr mnp::ip_scan_manip_t scan_alias_define(io_alias_t, posix_in6_addr& t) noexcept +{ + return { __builtin_addressof(t) }; +} +#else +template<::fast_io::details::iptypesimpl iptype> +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr ::fast_io::manipulators::ip_scan_manip_t< + ::fast_io::details::inaddrimpl ? + ::fast_io::manipulators::ip_scan_default_inaddr_flags + : + ::fast_io::manipulators::ip_scan_default_flags, ::std::remove_cvref_t*> scan_alias_define(io_alias_t, iptype& t) noexcept +{ + return { __builtin_addressof(t) }; +} +#endif + +template<::std::integral char_type, ::fast_io::manipulators::ip_scan_flags flags, ::fast_io::details::iptypesimpl iptype> +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr parse_result scan_contiguous_define(io_reserve_type_t>, char_type const* begin, char_type const* end, manipulators::ip_scan_manip_t val) noexcept +{ + if constexpr (::std::same_as) + { + auto result{ details::scn_cnt_define_inaddr_impl(begin, end, *val.reference) }; + if constexpr (flags.requireport == true) + { + if (result.code != parse_code::ok) [[unlikely]] + return result; + ::std::uint_least16_t port; + return details::scn_cnt_define_port_impl(result.iter, end, port); + } + return result; + } + else if constexpr (::std::same_as) + { + auto result{ ::fast_io::details::scn_cnt_define_inaddr_impl(begin, end, val.reference->address) }; + if (result.code != parse_code::ok) [[unlikely]] + return result; + begin = result.iter; + if constexpr (flags.requireport == false) + { + val.reference->port = 0; + return result; + } + else + return ::fast_io::details::scn_cnt_define_port_impl(begin, end, val.reference->port); + } + else if constexpr (::std::same_as) + { + auto result{ details::scn_cnt_define_in6addr_impl(begin, end, *val.reference) }; + if constexpr (flags.requireport == true) + { + if (result.code != parse_code::ok) [[unlikely]] + return result; + ::std::uint_least16_t port; + return details::scn_cnt_define_port_impl(result.iter, end, port); + } + return result; + } + else if constexpr (::std::same_as) + { + //return ::fast_io::details::prtrsv_ipv6_define_impl(iter, val.reference); + return {}; + } + else if constexpr (::std::same_as) + { + //return ::fast_io::details::prtrsv_ip_address_define_impl(iter, val.reference); + return {}; + } + else + { + //return ::fast_io::details::prtrsv_ip_define_impl(iter, val.reference); + return {}; + } +} + +template<::std::integral char_type, ::fast_io::manipulators::ip_scan_flags flags> +inline constexpr io_type_t> scan_context_type(io_reserve_type_t>) noexcept +{ + return {}; +} + +template<::std::integral char_type, ::fast_io::manipulators::ip_scan_flags flags> +inline constexpr parse_result scan_context_define(::fast_io::io_reserve_type_t>, ipv4_scan_state_t& state, char_type const* begin, char_type const* end, ::fast_io::manipulators::ip_scan_manip_t t) noexcept +{ + return details::scn_ctx_define_inaddr_impl(state, begin, end, *t.reference); +} + +template<::std::integral char_type, ::fast_io::manipulators::ip_scan_flags flags> +inline constexpr parse_code scan_context_eof_define(::fast_io::io_reserve_type_t>, ipv4_scan_state_t& state, ::fast_io::manipulators::ip_scan_manip_t t) noexcept +{ + if (state.ip_phase != scan_ipv4_context_phase::addr3) + return parse_code::end_of_file; + else + return details::scan_int_contiguous_none_space_part_define_impl<10>(state.buffer.data(), state.buffer.data() + state.size, t.reference->address[3]).code; +} + +template<::std::integral char_type, ::fast_io::manipulators::ip_scan_flags flags> +inline constexpr io_type_t> scan_context_type(io_reserve_type_t>) noexcept +{ + return {}; +} + +template<::std::integral char_type, ::fast_io::manipulators::ip_scan_flags flags> +inline constexpr parse_result scan_context_define(::fast_io::io_reserve_type_t>, ipv4_scan_state_t& state, char_type const* begin, char_type const* end, ::fast_io::manipulators::ip_scan_manip_t t) noexcept +{ + switch (state.ip_phase) + { + case scan_ipv4_context_phase::addr0: + case scan_ipv4_context_phase::dot0: + case scan_ipv4_context_phase::addr1: + case scan_ipv4_context_phase::dot1: + case scan_ipv4_context_phase::addr2: + case scan_ipv4_context_phase::dot2: + case scan_ipv4_context_phase::addr3: + { + auto result{ details::scn_ctx_define_inaddr_impl(state, begin, end, t.reference->address) }; + if (result.code != parse_code::ok) + return result; + begin = result.iter; + state.integer_phase = scan_integral_context_phase::zero; + state.size = 0; + state.ip_phase = ::std::bit_cast(state.port_mark); + [[fallthrough]]; + } + // clang bug for std::bit_cast is not a constexpr expression +#if !defined(__clang__) + case ::std::bit_cast(state.port_mark) : + case ::std::bit_cast(state.port) : + return { details::scn_ctx_define_port_type_general_impl(state, begin, end, t.reference->port) }; + default:; +#else + default: + if (state.ip_phase == ::std::bit_cast(state.port_mark) || + state.ip_phase == ::std::bit_cast(state.port)) [[likely]] + return { details::scn_ctx_define_port_type_general_impl(state, begin, end, t.reference->port) }; +#endif +#ifdef __has_builtin +#if __has_builtin(__builtin_unreachable) + __builtin_unreachable(); +#endif +#endif + } +} + +template<::std::integral char_type, ::fast_io::manipulators::ip_scan_flags flags> +inline constexpr parse_code scan_context_eof_define(::fast_io::io_reserve_type_t>, ipv4_scan_state_t& state, ::fast_io::manipulators::ip_scan_manip_t t) noexcept +{ + if (state.ip_phase != ::std::bit_cast(state.port)) + return parse_code::end_of_file; + else + return details::scan_int_contiguous_none_space_part_define_impl<10>(state.buffer.data(), state.buffer.data() + state.size, t.reference->port).code; +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/socket/impl.h b/src/fast_io/include/fast_io_core_impl/socket/impl.h new file mode 100644 index 0000000..c620aea --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/socket/impl.h @@ -0,0 +1,23 @@ +#pragma once + +#include"sock_family.h" +#include"sock_protocol.h" +#include"sock_type.h" +#include"posix_sockaddr.h" +#include"ip.h" + +#include"addrprt.h" +#if 0 +#include"addrscn.h" +#endif + +namespace fast_io +{ +struct +#if __has_cpp_attribute(maybe_unused) +[[maybe_unused]] +#endif +posix_empty_network_service{}; +//a dummy service to make serivce work with windows at a cross platform level + +} diff --git a/src/fast_io/include/fast_io_core_impl/socket/ip.h b/src/fast_io/include/fast_io_core_impl/socket/ip.h new file mode 100644 index 0000000..c89f580 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/socket/ip.h @@ -0,0 +1,48 @@ +#pragma once + +namespace fast_io +{ + +struct ipv4 +{ + posix_in_addr address{}; + std::uint_least16_t port{}; +}; + +struct ipv6 +{ + posix_in6_addr address{}; + std::uint_least16_t port{}; +}; + +struct ip_address +{ + union + { + posix_in_addr v4; + posix_in6_addr v6; + }address{.v6={}}; + bool isv4{}; +}; + +struct ip +{ + ip_address address; + std::uint_least16_t port{}; + + inline constexpr bool is_ipv4() const noexcept + { + return address.isv4; + } + inline constexpr bool is_ipv6() const noexcept + { + return !address.isv4; + } + + explicit constexpr ip() noexcept = default; + explicit constexpr ip(ipv4 add):address{.address={.v4=add.address},.isv4=true},port(add.port){} + explicit constexpr ip(ipv6 add):address{.address={.v6=add.address}},port(add.port){} + explicit constexpr ip(ip_address addr,::std::uint_least16_t prt):address{addr},port{prt}{} +}; + +} diff --git a/src/fast_io/include/fast_io_core_impl/socket/posix_sockaddr.h b/src/fast_io/include/fast_io_core_impl/socket/posix_sockaddr.h new file mode 100644 index 0000000..7654508 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/socket/posix_sockaddr.h @@ -0,0 +1,68 @@ +#pragma once + +namespace fast_io +{ +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning(push, _STL_WARNING_LEVEL) +#pragma warning(disable : 4324) +#endif +struct +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +alignas(16) +posix_sockaddr +{ + std::uint_least16_t sa_family{}; +}; + + +struct posix_in_addr +{ + unsigned char address[4]{}; +}; + +struct +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +alignas(16) +posix_sockaddr_in +{ + std::uint_least16_t sin_family{}; + std::uint_least16_t sin_port{}; + posix_in_addr sin_addr{}; +}; + +struct posix_in6_addr +{ + ::std::uint_least16_t address[8]{}; +}; + +struct +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +posix_sockaddr_in6 +{ + std::uint_least16_t sin6_family{}; + std::uint_least16_t sin6_port{}; + std::uint_least32_t sin6_flowinfo{}; + posix_in6_addr sin6_addr{}; + std::uint_least32_t sin6_scoped_id{}; +}; + +struct +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +alignas(128) +posix_sockaddr_storage +{ + std::uint_least16_t ss_family{}; +}; + +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning(pop) +#endif +} diff --git a/src/fast_io/include/fast_io_core_impl/socket/sock_family.h b/src/fast_io/include/fast_io_core_impl/socket/sock_family.h new file mode 100644 index 0000000..45a2bfd --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/socket/sock_family.h @@ -0,0 +1,94 @@ +#pragma once + +namespace fast_io +{ + +enum class sock_family +{ +unspec=-1, /* Unspec */ +alg=0, /* Algorithm sockets. */ +appletalk, /* Appletalk DDP. */ +arp, /* Address Resolution Protocol */ +ash, /* Ash. */ +atm, /* ATM */ +atmpvc, /* ATM PVCs. */ +atmsvc, /* ATM SVCs. */ +ax25, /* Amateur Radio AX.25. */ +ban, /* Banyan address. */ +bluetooth, /* Bluetooth sockets. */ +bridge, /* Multiprotocol bridge. */ +caif, /* CAIF sockets. */ +can, /* Controller Area Network. */ +ccitt, /* CCITT protocols, X.25 etc */ +chaos, /* mit CHAOS protocols */ +cluster, /* Address for Microsoft cluster products. */ +cnt, /* Computer Network Technology */ +coip, /* connection-oriented IP, aka ST II */ +datakit, /* datakit protocols */ +decnet, /* Reserved for DECnet project. */ +dli, /* DEC Direct data link interface */ +ecma, /* European computer manufacturers */ +econet, /* Acorn Econet. */ +firefox, /* FireFox address. */ +hylink, /* NSC Hyperchannel */ +hyperv, /* HyperV sockets */ +ib, /* Native InfiniBand address. */ +iclfxbm, +ieee12844, /* IEEE 1284.4 workgroup address. */ +ieee80211, /* IEEE 802.11 protocol */ +ieee802154, /* IEEE 802.15.4 sockets. */ +implink, /* arpanet imp addresses */ +inet, /* IP protocol family. */ +inet6, /* IP version 6. */ +inet6_sdp, /* OFED Socket Direct Protocol ipv6 */ +inet_sdp, /* OFED Socket Direct Protocol ipv4 */ +ipx, /* Novell Internet Protocol. */ +irda, /* IRDA sockets. */ +isdn, /* mISDN sockets. */ +iso, /* ISO protocols */ +iucv, /* IUCV sockets. */ +kcm, /* Kernel Connection Multiplexor. */ +key, /* PF_KEY key management API. */ +lat, /* LAT */ +link, /* Link layer interface */ +llc, /* Linux LLC. */ +local, /* Local to host (pipes and file-domain). */ +mpls, /* MPLS. */ +natm, /* native ATM access */ +netbeui, /* Reserved for 802.2LLC project. */ +netbios, /* SMB protocols */ +netdes, /* Address for Network Designers OSI gateway-enabled protocols. */ +netgraph, /* Netgraph sockets */ +netrom, /* Amateur radio NetROM. */ +nfc, /* NFC sockets. */ +packet, /* Packet family. */ +phonet, /* Phonet sockets. */ +pppox, /* PPPoX sockets. */ +pseudo_hdrcmplt, /* Used by BPF to not rewrite headers * in interface output routine */ +pseudo_key, /* Internal key-management function */ +pseudo_pip, /* Help Identify PIP packets */ +pseudo_rtip, /* Help Identify RTIP packets */ +pseudo_xtp, /* eXpress Transfer Protocol (no AF) */ +pup, /* pup protocols: e.g. BSP */ +qipcrtr, /* Qualcomm IPC Router. */ +rds, /* RDS sockets. */ +rose, /* Amateur Radio X.25 PLP. */ +route, /* Internal Routing Protocol */ +rxrpc, /* RxRPC sockets. */ +scluster, /* Sitara cluster protocol */ +security, /* Security callback pseudo AF. */ +sip, /* Simple Internet Protocol */ +slow, /* 802.3ad slow protocol */ +smc, /* SMC sockets. */ +sna, /* IBM SNA */ +tcnmessage, +tcnprocess, +tipc, /* TIPC sockets. */ +voiceview, /* VoiceView address. */ +vsock, /* vSockets. */ +wanpipe, /* Wanpipe API sockets. */ +x25, /* Reserved for X.25 project. */ +xdp, /* XDP sockets. */ +}; + +} diff --git a/src/fast_io/include/fast_io_core_impl/socket/sock_protocol.h b/src/fast_io/include/fast_io_core_impl/socket/sock_protocol.h new file mode 100644 index 0000000..03f77de --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/socket/sock_protocol.h @@ -0,0 +1,66 @@ +#pragma once + +namespace fast_io +{ + +/* +https://github.com/mirror/mingw-w64/blob/99b840e52d6e46f689b9cd086d925fad88db2b17/mingw-w64-headers/include/winsock2.h +*/ + +enum class sock_protocol +{ +ah, /* authentication header. */ +beetph, /* IP option pseudo header for BEET. */ +carp, +cbt, +comp, /* Compression Header Protocol. */ +dccp, /* Datagram Congestion Control Protocol. */ +dstopts, /* IPv6 destination options */ +egp, /* Exterior Gateway Protocol. */ +eigrp, /* Cisco/GXS IGRP */ +encap, /* Encapsulation Header. */ +esp, /* encapsulating security payload. */ +ethernet, /* Ethernet-within-IPv6 Encapsulation. */ +fragment, /* IPv6 fragmentation header */ +ggp, +gre, /* General Routing Encapsulation. */ +hopopts, /* IPv6 hop-by-hop options */ +iclfxbm, +icmp, /* Internet Control Message Protocol. */ +icmpv6, /* ICMPv6 */ +idp, /* XNS IDP protocol. */ +igmp, /* Internet Group Management Protocol. */ +igp, +ip, /* Dummy protocol for TCP. */ +ipcomp, +ipip, /* IPIP tunnels (older KA9Q tunnels use 94). */ +ipv4, +ipv6, /* IPv6 header. */ +l2tp, +mobile, +mobility, +mobility_old, +mpls, /* MPLS in IP. */ +mptcp, /* Multipath TCP connection. */ +mtp, /* Multicast Transport Protocol. */ +nd, /* Sun net disk proto (temp.) */ +none, /* IPv6 no next header */ +ospf, +pgm, +pigp, +pim, /* Protocol Independent Multicast. */ +pup, /* PUP protocol. */ +raw, /* Raw IP packets. */ +rdp, +routing, /* IPv6 routing header */ +rsvp, /* Reservation Protocol. */ +sctp, /* Stream Control Transmission Protocol. */ +st, +tcp, /* Transmission Control Protocol. */ +tp, /* SO Transport Protocol Class 4. */ +udp, /* User Datagram Protocol. */ +udplite, /* UDP-Lite protocol. */ +vrrp +}; + +} diff --git a/src/fast_io/include/fast_io_core_impl/socket/sock_type.h b/src/fast_io/include/fast_io_core_impl/socket/sock_type.h new file mode 100644 index 0000000..99a490e --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/socket/sock_type.h @@ -0,0 +1,16 @@ +#pragma once + +namespace fast_io +{ + +enum class sock_type:char8_t +{ +stream, +dgram, +seqpacket, +raw, +rdm, +packet +}; + +} diff --git a/src/fast_io/include/fast_io_core_impl/socket_enum.h b/src/fast_io/include/fast_io_core_impl/socket_enum.h new file mode 100644 index 0000000..424cf4c --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/socket_enum.h @@ -0,0 +1,61 @@ +#pragma once + +//https://github.com/bminor/glibc/blob/5f72f9800b250410cad3abfeeb09469ef12b2438/sysdeps/unix/sysv/linux/bits/socket.h +//https://github.com/freebsd/freebsd/blob/230874c33e0e80cfe736ebb023cd26102b0572e2/sys/sys/socket.h + +namespace fast_io +{ + +enum class protocol_family: std::uint_least32_t +{ + unspec = 0, + local = 1, + inet = 2, + ax25 = 3, + ipx = 4, + appletalk = 5, + netrom = 6, + bridge = 7, + atmpvc = 8, + x25 = 9, + inet6 = 10, + rose = 11, + decnet = 12, + netbeui = 13, + security = 14, + key = 15, + netlink = 16, + route = 16, + packet = 17, + ash = 18, + econet = 19, + atmsvc = 20, + rds = 21, + sna = 22, + irda = 23, + pppox = 24, + wanpipe = 25, + llc = 26, + ib = 27, + mpls = 28, + can = 29, + tipc = 30, + bluetooth = 31, + iucv = 32, + rxrpc = 33, + isdn = 34, + phonet = 35, + ieee802154 = 36, + caif = 37, + alg = 38, + nfc = 39, + vsock = 40, + kcm = 41, + qipcrtr = 42, + smc = 43, + xdp = 44 +}; + +using address_family = protocol_family; + +} diff --git a/src/fast_io/include/fast_io_core_impl/source_location.h b/src/fast_io/include/fast_io_core_impl/source_location.h new file mode 100644 index 0000000..c819e6a --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/source_location.h @@ -0,0 +1,66 @@ +#pragma once + +namespace fast_io +{ + +struct source_location_scatter +{ + basic_io_scatter_t file_name; + basic_io_scatter_t function_name; + std::uint_least32_t line; + std::uint_least32_t column; +}; + +namespace details +{ + +inline constexpr std::size_t print_reserve_size_source_location_impl(source_location_scatter location) noexcept +{ + constexpr std::size_t uint32_rsv_size{print_reserve_size(io_reserve_type)}; + constexpr std::size_t total_uint_least32_t_rsv_size{uint32_rsv_size*2+3}; + return intrinsics::add_or_overflow_die_chain(location.file_name.len,location.function_name.len,total_uint_least32_t_rsv_size); +} + +inline constexpr char* print_reserve_define_source_location_impl(char* iter,source_location_scatter location) noexcept +{ + *(iter=non_overlapped_copy_n(location.file_name.base,location.file_name.len,iter))=':'; + *(iter=print_reserve_define(io_reserve_type,++iter,location.line))=':'; + *(iter=print_reserve_define(io_reserve_type,++iter,location.column))=':'; + return non_overlapped_copy_n(location.function_name.base,location.function_name.len,++iter); +} + +inline constexpr source_location_scatter print_alias_define_source_location_impl(std::source_location location) noexcept +{ + return {{location.file_name(),cstr_len(location.file_name())}, + {location.function_name(),cstr_len(location.function_name())}, + location.line(),location.column()}; +} + +} + +inline constexpr std::size_t print_reserve_size(io_reserve_type_t,source_location_scatter location) noexcept +{ + return details::print_reserve_size_source_location_impl(location); +} + +inline constexpr char* print_reserve_define(io_reserve_type_t, char* iter,source_location_scatter location) noexcept +{ + return details::print_reserve_define_source_location_impl(iter,location); +} + +inline constexpr source_location_scatter print_alias_define(io_alias_t,std::source_location location) noexcept +{ + return details::print_alias_define_source_location_impl(location); +} + +namespace manipulators +{ + +inline constexpr ::std::source_location cur_src_loc(::std::source_location loc=::std::source_location::current()) noexcept +{ + return loc; +} + +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/temporary_buffer.h b/src/fast_io/include/fast_io_core_impl/temporary_buffer.h new file mode 100644 index 0000000..88d5675 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/temporary_buffer.h @@ -0,0 +1,171 @@ +#pragma once + +namespace fast_io::details +{ + +template +requires (output_stream) +struct temporary_buffer +{ + using char_type = typename output::char_type; + static inline constexpr std::size_t buffer_size{512}; + std::size_t pos{}; + char_type buffer[buffer_size]; + output out{}; +}; + +template +inline constexpr typename output::char_type* obuffer_begin(temporary_buffer& out) noexcept +{ + return out.buffer; +} + +template +inline constexpr typename output::char_type* obuffer_curr(temporary_buffer& out) noexcept +{ + return out.buffer+out.pos; +} + +template +inline constexpr typename output::char_type* obuffer_end(temporary_buffer& out) noexcept +{ + return out.buffer+temporary_buffer::buffer_size; +} + +template +inline constexpr void obuffer_set_curr(temporary_buffer& out,typename output::char_type* ptr) noexcept +{ + out.pos=static_cast(ptr-out.buffer); +} + +template +inline constexpr void flush(temporary_buffer& out) +{ + auto start{out.buffer}; + if(out.pos==0) + return; + write(out.out,start,start+out.pos); + out.pos=0; +} + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline constexpr void obuffer_overflow(temporary_buffer& out,typename output::char_type ch) +{ + auto start{out.buffer}; + write(out.out,start,start+temporary_buffer::buffer_size); + *start=ch; + out.pos=1; +} + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline constexpr void temporary_buffer_write_cold_path(temporary_buffer& out, + typename output::char_type const* first, + typename output::char_type const* last) +{ + using char_type = typename output::char_type; + auto start{out.buffer}; + std::size_t const pos{out.pos}; + constexpr std::size_t buffsz{temporary_buffer::buffer_size}; + constexpr std::size_t buffszm1{buffsz-1}; + std::size_t const remain_space{static_cast(buffsz-pos)}; + if constexpr(line) + { + std::size_t diff{static_cast(last-first)}; + std::size_t diffp1{diff}; + ++diffp1; + if(diffp1==remain_space) + { + non_overlapped_copy_n(first,diff,start+pos); + out.buffer[buffszm1]=char_literal_v; + write(out,start,start+buffsz); + out.pos=0; + return; + } + + } + non_overlapped_copy_n(first,remain_space,start+pos); + first+=remain_space; + write(out.out,start,start+buffsz); + out.pos=0; + std::size_t const new_diff{static_cast(last-first)}; + if constexpr(line) + { + if(new_diff; + ++out.pos; + } + else + { + if constexpr(output_stream_with_writeln) + { + writeln(out.out,first,last); + } + else + { + write(out.out,first,last); + *out.buffer=char_literal_v; + out.pos=0; + } + } + } + else + { + if(new_diff +inline constexpr void write(temporary_buffer& out, + typename output::char_type const* first, + typename output::char_type const* last) +{ + std::size_t const pos{out.pos}; + std::size_t const remain_space{temporary_buffer::buffer_size-pos}; + std::size_t const ptr_diff{static_cast(last-first)}; + if(remain_space<=ptr_diff) +#if __has_cpp_attribute(unlikely) +[[unlikely]] +#endif + return temporary_buffer_write_cold_path(out,first,last); + auto start{out.buffer}; + non_overlapped_copy_n(first,ptr_diff,start+pos); + out.pos+=ptr_diff; +} + +template +inline constexpr void writeln(temporary_buffer& out, + typename output::char_type const* first, + typename output::char_type const* last) +{ + using char_type = typename output::char_type; + std::size_t const pos{out.pos}; + std::size_t const remain_space{temporary_buffer::buffer_size-pos}; + std::size_t const ptr_diff{static_cast(last-first)}; + if(remain_space(out,first,last); + auto start{out.buffer}; + non_overlapped_copy_n(first,ptr_diff,start+pos); + *(out.pos+=ptr_diff)=char_literal_v; + ++out.pos; +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/terminate.h b/src/fast_io/include/fast_io_core_impl/terminate.h new file mode 100644 index 0000000..dcb546b --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/terminate.h @@ -0,0 +1,26 @@ +#pragma once +#if defined(_MSC_VER)&&!defined(__clang__) +#include +#endif + +namespace fast_io +{ + + +[[noreturn]] inline void fast_terminate() noexcept +{ +//https://llvm.org/doxygen/Compiler_8h_source.html +#if defined(__has_builtin) +#if __has_builtin(__builtin_trap) + __builtin_trap(); +#elif __has_builtin(__builtin_abort) + __builtin_abort(); +#else + std::abort(); +#endif +#else + std::abort(); +#endif +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/timestamp_counter.h b/src/fast_io/include/fast_io_core_impl/timestamp_counter.h new file mode 100644 index 0000000..476e845 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/timestamp_counter.h @@ -0,0 +1,23 @@ +#pragma once + +namespace fast_io +{ + +inline auto current_processor_timestamp_counter() noexcept +{ +#if defined(__has_builtin) +#if __has_builtin(__builtin_ia32_rdtsc) + return __builtin_ia32_rdtsc(); +#else + return static_cast(0); +#endif +#elif defined(_MSC_VER) && defined(_M_IX86) + return __rdtsc(); +#else + return static_cast(0); +#endif +} + +using current_processor_timestamp_counter_t = decltype(current_processor_timestamp_counter()); + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_core_impl/to.h b/src/fast_io/include/fast_io_core_impl/to.h new file mode 100644 index 0000000..2d89a2e --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/to.h @@ -0,0 +1,540 @@ +#pragma once + +namespace fast_io +{ + +namespace details +{ + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr void inplace_to_decay_context_impl(io_reference_wrapper> buffer,state& s,T t,Arg1 arg,Args... args) +{ + ::fast_io::details::decay::print_control(buffer,arg); + char_type *buffer_beg{buffer.ptr->buffer_begin}; + char_type const *buffer_begin{buffer_beg}; + char_type const *buffer_curr{buffer.ptr->buffer_curr}; + auto [it,ec]=scan_context_define(io_reserve_type,s,buffer_begin,buffer_curr,t); + if(it!=buffer_curr) + { + if(ec!=::fast_io::parse_code::ok) + ::fast_io::throw_parse_code(ec); + return; + } + if constexpr(sizeof...(Args)!=0) + { + buffer.ptr->buffer_curr=buffer_beg; + inplace_to_decay_context_impl(buffer,s,t,args...); + } + else + { + ::fast_io::parse_code p{scan_context_eof_define(io_reserve_type,s,t)}; + if(p!=::fast_io::parse_code::ok) + ::fast_io::throw_parse_code(p); + } +} + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr void inplace_to_decay_buffer_scatter_context_impl(state& s,T t,Arg1 arg,Args... args) +{ + basic_io_scatter_t scatter{print_scatter_define(io_reserve_type,arg)}; + char_type const* buffer_begin{scatter.base}; + char_type const* buffer_curr{buffer_begin+scatter.len}; + auto [it,ec]=scan_context_define(io_reserve_type,s,buffer_begin,buffer_curr,t); + if(it!=buffer_curr) + { + if(ec!=::fast_io::parse_code::ok) + throw_parse_code(ec); + return; + } + if constexpr(sizeof...(Args)!=0) + { + inplace_to_decay_buffer_scatter_context_impl(s,t,args...); + } + else + { + ::fast_io::parse_code p{scan_context_eof_define(io_reserve_type,s,t)}; + if(p!=::fast_io::parse_code::ok) + throw_parse_code(p); + } +} + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr void inplace_to_decay_buffer_context_impl(char_type* buffer,state& s,T t,Arg1 arg,Args... args) +{ + if constexpr(scatter_printable&&((scatter_printable&&...))) + { + inplace_to_decay_buffer_scatter_context_impl(s,t,arg,args...); + } + else + { + char_type const* buffer_begin; + char_type const* buffer_curr; + if constexpr(scatter_printable) + { + auto scatter{print_scatter_define(io_reserve_type,arg)}; + buffer_begin=scatter.base; + buffer_curr=buffer_begin+scatter.len; + } + else + { + + buffer_curr=print_reserve_define(io_reserve_type,buffer,arg); + buffer_begin=buffer; + } + auto [it,ec]=scan_context_define(io_reserve_type,s,buffer_begin,buffer_curr,t); + if(it!=buffer_curr) + { + if(ec!=::fast_io::parse_code::ok) + throw_parse_code(ec); + return; + } + if constexpr(sizeof...(Args)!=0) + { + inplace_to_decay_buffer_context_impl(buffer,s,t,args...); + } + else + { + parse_code p{scan_context_eof_define(io_reserve_type,s,t)}; + if(p!=parse_code::ok) + throw_parse_code(p); + } + } +} + +template +inline constexpr std::size_t calculate_print_normal_maxium_size_main(std::size_t mx_value) noexcept +{ + std::size_t val{}; + if constexpr(ln&&(sizeof...(Args)==0)) + ++val; + if constexpr(reserve_printable) + { + constexpr std::size_t size{print_reserve_size(io_reserve_type)}; + static_assert(size!=SIZE_MAX,"overflow"); + val+=size; + } + if(mx_value(mx_value); +} + +template +inline constexpr std::size_t calculate_print_normal_maxium_size() noexcept +{ + return calculate_print_normal_maxium_size_main(0); +} + +template +inline constexpr std::size_t calculate_print_normal_dynamic_maxium_main(std::size_t mx_value,T t,Args... args) noexcept +{ + if constexpr(dynamic_reserve_printable) + { + std::size_t size{print_reserve_size(io_reserve_type,t)}; + if constexpr(ln&&(sizeof...(Args)==0)) + { + if(size==SIZE_MAX) + fast_terminate(); + ++size; + } + if(mx_value(mx_value,args...); +} + +template +inline constexpr void deal_with_single_to(char_type const* buffer_begin,char_type const* buffer_end,T t) +{ + auto code{scan_contiguous_define(io_reserve_type,buffer_begin,buffer_end,t).code}; + if(code!=parse_code::ok) + throw_parse_code(code); +} + +template +inline constexpr void to_deal_with_contiguous_single_scatter(T t,Arg arg) +{ + basic_io_scatter_t scatter{print_scatter_define(io_reserve_type,arg)}; + auto base{scatter.base}; + deal_with_single_to(base,base+scatter.len,t); +} + +template +inline constexpr char_type* to_impl_with_reserve_recursive(char_type* p,T t,Args ...args) +{ + if constexpr(scatter_printable) + { + p=copy_scatter(print_scatter_define(io_reserve_type,t),p); + } + else + { + p=print_reserve_define(io_reserve_type,p,t); + } + if constexpr(sizeof...(Args)==0) + { + return p; + } + else + { + return to_impl_with_reserve_recursive(p,args...); + } +} + + +template +inline constexpr std::size_t calculate_scatter_dynamic_reserve_size_with_scatter([[maybe_unused]] T t,Args... args) +{ + if constexpr(dynamic_reserve_printable) + { + std::size_t res{print_reserve_size(io_reserve_type,t)}; + if constexpr(sizeof...(Args)==0) + return res; + else + return ::fast_io::details::intrinsics::add_or_overflow_die(res,calculate_scatter_dynamic_reserve_size_with_scatter(args...)); + } + else if constexpr(scatter_printable) + { + std::size_t res{print_scatter_define(io_reserve_type>,t).len}; + if constexpr(sizeof...(Args)==0) + return res; + else + return ::fast_io::details::intrinsics::add_or_overflow_die(res,calculate_scatter_dynamic_reserve_size_with_scatter(args...)); + } + else + { + if constexpr(sizeof...(Args)==0) + return 0; + else + return calculate_scatter_dynamic_reserve_size_with_scatter(args...); + } +} + +template +concept inplace_to_decay_detect = std::integral&&(sizeof...(Args)!=0&&print_freestanding_decay_okay_character_type_no_status&&(contiguous_scannable||context_scannable)); + +} + +template +inline constexpr void basic_inplace_to_decay(T t,Args... args) +{ + constexpr bool failed{::fast_io::details::inplace_to_decay_detect}; + if constexpr(failed) + { + if constexpr(((reserve_printable||dynamic_reserve_printable||scatter_printable)&&...)) + { + constexpr bool all_scatters{((scatter_printable)&&...)}; + constexpr bool no_need_dynamic_reserve{((reserve_printable||scatter_printable)&&...)}; + if constexpr(context_scannable&&(!(contiguous_scannable&&sizeof...(args)==1))) + { + typename std::remove_cvref_t))>::type state; + if constexpr(all_scatters) + { + ::fast_io::details::inplace_to_decay_buffer_scatter_context_impl(state,t,args...); + } + else if constexpr(no_need_dynamic_reserve) + { + constexpr std::size_t maximum_reserve_size{::fast_io::details::calculate_print_normal_maxium_size()}; + char_type buffer[maximum_reserve_size]; + ::fast_io::details::inplace_to_decay_buffer_context_impl(buffer,state,t,args...); + } + else + { + std::size_t const maximum_reserve_size{::fast_io::details::calculate_print_normal_dynamic_maxium_main(0,args...)}; + ::fast_io::details::local_operator_new_array_ptr heap_buffer(maximum_reserve_size); + ::fast_io::details::inplace_to_decay_buffer_context_impl(heap_buffer.ptr,state,t,args...); + } + } + else if constexpr(contiguous_scannable) + { + if constexpr(all_scatters&&sizeof...(Args)==1)//crucial for performance + { + ::fast_io::details::to_deal_with_contiguous_single_scatter(t,args...); + } + else if constexpr(((reserve_printable)&&...)) + { + constexpr std::size_t total_size{::fast_io::details::decay::calculate_scatter_reserve_size()}; + char_type buffer[total_size]; + auto ret{::fast_io::details::to_impl_with_reserve_recursive(buffer,args...)}; + ::fast_io::details::deal_with_single_to(buffer,ret,t); + } + else + { + std::size_t const maximum_reserve_size{::fast_io::details::calculate_scatter_dynamic_reserve_size_with_scatter(args...)}; + ::fast_io::details::local_operator_new_array_ptr heap_buffer(maximum_reserve_size); + auto ret{::fast_io::details::to_impl_with_reserve_recursive(heap_buffer.ptr,args...)}; + ::fast_io::details::deal_with_single_to(heap_buffer.ptr,ret,t); + } + } + } + else + { + dynamic_io_buffer buffer; + auto ref{io_ref(buffer)}; + if constexpr(context_scannable&&(!(contiguous_scannable&&sizeof...(args)==1))) + { + typename std::remove_cvref_t))>::type state; + ::fast_io::details::inplace_to_decay_context_impl(ref,state,t,args...); + } + else if constexpr(contiguous_scannable) + { + ::fast_io::print_freestanding_decay_no_status(ref,args...); + ::fast_io::details::deal_with_single_to(buffer.buffer_begin,buffer.buffer_curr,t); + } + else + { + constexpr bool type_error{context_scannable}; + static_assert(type_error,"scan type error"); + } + } + } + else + { +static_assert(failed,"either somes args not printable or some type not detectable"); + } +} + +namespace details +{ + +template +requires ::fast_io::details::inplace_to_decay_detect +inline constexpr void basic_inplace_to_decay_model(T,Args...) +{ + +} + +template +concept can_do_inplace_to = requires(T& t,Args&& ...args) +{ + ::fast_io::details::basic_inplace_to_decay_model(::fast_io::io_scan_forward(::fast_io::io_scan_alias(t)),io_print_forward(io_print_alias(args))...); +}; + +} + +template +inline constexpr void basic_inplace_to(T&& t,Args&& ...args) +{ + constexpr bool failed{::fast_io::details::can_do_inplace_to}; + if constexpr(failed) + { + ::fast_io::basic_inplace_to_decay(::fast_io::io_scan_forward(::fast_io::io_scan_alias(t)),io_print_forward(io_print_alias(args))...); + } + else + { +static_assert(failed,"either somes args not printable or some type not detectable"); + } +} + +template +inline constexpr void inplace_to(T&& t,Args&& ...args) +{ + constexpr bool failed{::fast_io::details::can_do_inplace_to}; + if constexpr(failed) + { + ::fast_io::basic_inplace_to_decay(::fast_io::io_scan_forward(::fast_io::io_scan_alias(t)),io_print_forward(io_print_alias(args))...); + } + else + { +static_assert(failed,"either somes args not printable or some type not detectable"); + } +} + +template +inline constexpr void winplace_to(T&& t,Args&& ...args) +{ + constexpr bool failed{::fast_io::details::can_do_inplace_to}; + if constexpr(failed) + { + ::fast_io::basic_inplace_to_decay(::fast_io::io_scan_forward(::fast_io::io_scan_alias(t)),io_print_forward(io_print_alias(args))...); + } + else + { +static_assert(failed,"either somes args not printable or some type not detectable"); + } +} + +template +inline constexpr void u8inplace_to(T&& t,Args&& ...args) +{ + constexpr bool failed{::fast_io::details::can_do_inplace_to}; + if constexpr(failed) + { + ::fast_io::basic_inplace_to_decay(::fast_io::io_scan_forward(::fast_io::io_scan_alias(t)),io_print_forward(io_print_alias(args))...); + } + else + { +static_assert(failed,"either somes args not printable or some type not detectable"); + } +} + +template +inline constexpr T u16inplace_to(T&& t,Args&& ...args) +{ + constexpr bool failed{::fast_io::details::can_do_inplace_to}; + if constexpr(failed) + { + ::fast_io::basic_inplace_to_decay(::fast_io::io_scan_forward(::fast_io::io_scan_alias(t)),io_print_forward(io_print_alias(args))...); + } + else + { +static_assert(failed,"either somes args not printable or some type not detectable"); + return T(); + } +} + +template +inline constexpr T u32inplace_to(T&& t,Args&& ...args) +{ + constexpr bool failed{::fast_io::details::can_do_inplace_to}; + if constexpr(failed) + { + ::fast_io::basic_inplace_to_decay(::fast_io::io_scan_forward(::fast_io::io_scan_alias(t)),io_print_forward(io_print_alias(args))...); + } + else + { +static_assert(failed,"either somes args not printable or some type not detectable"); + return T(); + } +} + +template +inline constexpr T basic_to_decay(Args... args) +{ + constexpr bool failed{::fast_io::details::can_do_inplace_to}; + if constexpr(sizeof...(Args)==0) + { + return T(); + } + else if constexpr(failed) + { + if constexpr(std::is_scalar_v) + { + T v{}; + basic_inplace_to_decay(::fast_io::io_scan_forward(::fast_io::io_scan_alias(v)),args...); + return v; + } + else + { + T v; + basic_inplace_to_decay(::fast_io::io_scan_forward(::fast_io::io_scan_alias(v)),args...); + return v; + } + } + else + { +static_assert(failed,"either somes args not printable or some type not detectable"); + return T(); + } +} + +template +inline constexpr T basic_to(Args&& ...args) +{ + constexpr bool failed{::fast_io::details::can_do_inplace_to}; + if constexpr(failed) + { + return ::fast_io::basic_to_decay(io_print_forward(io_print_alias(args))...); + } + else + { +static_assert(failed,"either somes args not printable or some type not detectable"); + return T(); + } +} + +template +[[nodiscard]] inline constexpr T to(Args&& ...args) +{ + constexpr bool failed{::fast_io::details::can_do_inplace_to}; + if constexpr(failed) + { + return ::fast_io::basic_to_decay(io_print_forward(io_print_alias(args))...); + } + else + { +static_assert(failed,"either somes args not printable or some type not detectable"); + return T(); + } +} + +template +[[nodiscard]] inline constexpr T wto(Args&& ...args) +{ + constexpr bool failed{::fast_io::details::can_do_inplace_to}; + if constexpr(failed) + { + return ::fast_io::basic_to_decay(io_print_forward(io_print_alias(args))...); + } + else + { +static_assert(failed,"either somes args not printable or some type not detectable"); + return T(); + } +} + +template +[[nodiscard]] inline constexpr T u8to(Args&& ...args) +{ + constexpr bool failed{::fast_io::details::can_do_inplace_to}; + if constexpr(failed) + { + return ::fast_io::basic_to_decay(io_print_forward(io_print_alias(args))...); + } + else + { +static_assert(failed,"either somes args not printable or some type not detectable"); + return T(); + } +} + +template +[[nodiscard]] inline constexpr T u16to(Args&& ...args) +{ + constexpr bool failed{::fast_io::details::can_do_inplace_to}; + if constexpr(failed) + { + return ::fast_io::basic_to_decay(io_print_forward(io_print_alias(args))...); + } + else + { +static_assert(failed,"either somes args not printable or some type not detectable"); + return T(); + } +} + +template +[[nodiscard]] inline constexpr T u32to(Args&& ...args) +{ + constexpr bool failed{::fast_io::details::can_do_inplace_to}; + if constexpr(failed) + { + return ::fast_io::basic_to_decay(io_print_forward(io_print_alias(args))...); + } + else + { +static_assert(failed,"either somes args not printable or some type not detectable"); + return T(); + } +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/transmit/impl.h b/src/fast_io/include/fast_io_core_impl/transmit/impl.h new file mode 100644 index 0000000..4a060ff --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/transmit/impl.h @@ -0,0 +1,4 @@ +#pragma once + +#include"transmit.h" +#include"scanner.h" diff --git a/src/fast_io/include/fast_io_core_impl/transmit/scanner.h b/src/fast_io/include/fast_io_core_impl/transmit/scanner.h new file mode 100644 index 0000000..01f64b6 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/transmit/scanner.h @@ -0,0 +1,251 @@ +#pragma once + +namespace fast_io +{ + +namespace details +{ + +template<::fast_io::input_stream input,typename context_type,typename sccontext> +inline constexpr void basic_scanner_context_next_common(input handle,context_type& context,sccontext& scnctx) +{ + using input_handle_type = input; + using char_type = typename std::remove_cvref_t::char_type; + if constexpr(mutex_stream) + { + basic_scanner_context_next_common(handle.unlocked_handle(),context,scnctx); + } + else + { + if constexpr(iterative_scannable||iterative_contiguous_scannable) + { + if constexpr(contiguous_input_stream) + { + auto curr_ptr{ibuffer_curr(handle)}; + auto end_ptr{ibuffer_end(handle)}; + if constexpr(iterative_contiguous_scannable) + { + auto [it,ec]=scan_iterative_contiguous_define(io_reserve_type>,context,curr_ptr,end_ptr); + ibuffer_set_curr(handle,it); + if(ec!=parse_code::ok) + { + if(ec==parse_code::end_of_file) + { + scnctx.ptr=nullptr; + return; + } + throw_parse_code(ec); + } + } + else + { + scan_iterative_init_define(io_reserve_type>,context); + auto [p,code]{scan_iterative_next_define(io_reserve_type>,context,curr_ptr,end_ptr)}; + ibuffer_set_curr(handle,p); + if(code!=parse_code::ok)[[unlikely]] + { + if(code!=parse_code::partial) + { + throw_parse_code(code); + } + auto eofcode{scan_iterative_eof_define(io_reserve_type>,context)}; + if(eofcode!=parse_code::ok) + { + throw_parse_code(eofcode); + } + } + } + } + else + { + for(scan_iterative_init_define(io_reserve_type>,context);;) + { + auto curr_ptr{ibuffer_curr(handle)}; + auto end_ptr{ibuffer_end(handle)}; + if(curr_ptr==end_ptr) + { + if(scnctx.last_is_eof) + { + scnctx.ptr=nullptr; + break; + } + bool u{ibuffer_underflow(handle)}; + if(!u) + { + auto code{scan_iterative_eof_define(io_reserve_type>,context)}; + if(code==parse_code::ok) + { + scnctx.last_is_eof=true; + break; + } + else if(code==parse_code::end_of_file) + { + scnctx.ptr=nullptr; + break; + } + else + { + throw_parse_code(code); + } + } + continue; + } + auto [p,code]{scan_iterative_next_define(io_reserve_type>,context,curr_ptr,end_ptr)}; + ibuffer_set_curr(handle,p-curr_ptr+curr_ptr); + if(code==parse_code::ok)[[likely]] + { + break; + } + else if(code==parse_code::partial) + { + continue; + } + throw_parse_code(code); + } + } + } + else + { + static_assert(iterative_scannable); + if(!scan_iterative_context_define(handle,context))[[unlikely]] + { + scnctx.ptr=nullptr; + } + } + } +} + +template +struct basic_scanner_context_iterator +{ + using input_handle_type = typename T::input_handle_type; + using char_type = typename T::char_type; + using context_type = typename T::context_type; + T* ptr{}; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif + std::conditional_t<::fast_io::contiguous_input_stream,::fast_io::details::empty,bool> last_is_eof{}; + inline constexpr context_type& operator*() const noexcept + { + return ptr->context; + } + inline constexpr basic_scanner_context_iterator& operator++() + { + basic_scanner_context_next_common(ptr->handle,ptr->context,*this); + return *this; + } +}; + +template +inline constexpr bool operator==(basic_scanner_context_iterator it,::std::default_sentinel_t) noexcept +{ + return it.ptr==nullptr; +} + +template +inline constexpr bool operator!=(basic_scanner_context_iterator it,::std::default_sentinel_t) noexcept +{ + return it.ptr!=nullptr; +} + +template +inline constexpr bool operator==(::std::default_sentinel_t,basic_scanner_context_iterator it) noexcept +{ + return it.ptr==nullptr; +} + +template +inline constexpr bool operator!=(::std::default_sentinel_t,basic_scanner_context_iterator it) noexcept +{ + return it.ptr!=nullptr; +} + +} + +template<::fast_io::buffer_input_stream input,typename T> +requires std::is_trivially_copyable_v +struct basic_scanner_context +{ + using input_handle_type = input; + using char_type = typename std::remove_cvref_t::char_type; + using context_type = T; + using iterator = ::fast_io::details::basic_scanner_context_iterator>; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif + input_handle_type handle{}; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif + context_type context{}; + inline constexpr iterator begin() + { + return ++iterator{this}; + } + inline constexpr ::std::default_sentinel_t end() const noexcept + { + return {}; + } +}; + +template<::fast_io::input_stream input,typename T> +requires (std::is_trivially_copyable_v&&mutex_stream) +struct basic_scanner_context_mutex +{ + using input_handle_type = input; + using char_type = typename std::remove_cvref_t::char_type; + using context_type = T; + using iterator = ::fast_io::details::basic_scanner_context_iterator>; + #ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif + input_handle_type handle{}; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif + context_type context{}; + explicit constexpr basic_scanner_context_mutex(input_handle_type h):handle(h) + { + handle.lock(); + } +#if __cpp_constexpr_dynamic_alloc >= 201907L + constexpr +#endif + ~basic_scanner_context_mutex() + { + handle.unlock(); + } + basic_scanner_context_mutex(basic_scanner_context_mutex const&)=delete; + basic_scanner_context_mutex& operator=(basic_scanner_context_mutex const&)=delete; + inline constexpr iterator begin() + { + return ++iterator{this}; + } + inline constexpr ::std::default_sentinel_t end() const noexcept + { + return {}; + } +}; + +} diff --git a/src/fast_io/include/fast_io_core_impl/transmit/transmit.h b/src/fast_io/include/fast_io_core_impl/transmit/transmit.h new file mode 100644 index 0000000..dbcbd1f --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/transmit/transmit.h @@ -0,0 +1,296 @@ +#pragma once + + +namespace fast_io +{ + +template +concept status_transmitable = requires(T&& t,P&& p) +{ + status_transmit_define(io_alias,::std::forward(t),::std::forward

(p)); +}; + +template +concept zero_copy_transmitable = zero_copy_output_stream&&zero_copy_input_stream

&&requires(T t,P p) +{ + zero_copy_transmit_define(io_alias,zero_copy_out_handle(t),zero_copy_in_handle(t)); +}; + +namespace details +{ + +template +inline constexpr std::size_t calculate_transmit_buffer_size() noexcept +{ +#ifdef FAST_IO_BUFFER_SIZE + static_assert(sizeof(char_type)>=FAST_IO_BUFFER_SIZE); + static_assert(FAST_IO_BUFFER_SIZE +inline constexpr std::size_t transmit_buffer_size_cache{calculate_transmit_buffer_size()}; + +} + +template +inline constexpr std::uintmax_t raw_transmit_decay(output outs,input ins) +{ + if constexpr(contiguous_input_stream) + { + auto curr{ibuffer_curr(ins)}; + auto ed{ibuffer_end(ins)}; + write(outs,curr,ed); + auto diff{ed-curr}; + ibuffer_set_curr(ins,ed); + return static_cast(static_cast(diff)); + } + else if constexpr(buffer_input_stream) + { + std::uintmax_t chars{}; + do + { + auto curr{ibuffer_curr(ins)}; + auto ed{ibuffer_end(ins)}; + if(curr==ed)[[unlikely]] + continue; + write(outs,curr,ed); + chars+=static_cast(ed-curr); + ibuffer_set_curr(ins,ed); + } + while(ibuffer_underflow(ins)); + return chars; + } + else + { + using input_char_type = typename input::char_type; + std::uintmax_t chars{}; + constexpr std::size_t buffer_size{details::transmit_buffer_size_cache}; + ::fast_io::details::buffer_alloc_arr_ptr||secure_clear_requirement_stream> array_ptr(buffer_size); + auto array_start{array_ptr.ptr},array_end{array_ptr.ptr+buffer_size}; + for(;;) + { + auto ed{read(ins,array_start,array_end)}; + if(array_start==ed)[[unlikely]] + break; + write(outs,array_start,ed); + chars+=static_cast(ed-array_start); + } + return chars; + } +} + +template +inline constexpr decltype(auto) transmit_decay(output outs,input ins) +{ + if constexpr(mutex_stream) + { + io_lock_guard lg{ins}; + decltype(auto) uh{ins.unlocked_handle()}; + return transmit_decay(outs,io_ref(uh)); + } + else if constexpr(mutex_stream) + { + io_lock_guard lg{outs}; + decltype(auto) uh{outs.unlocked_handle()}; + return transmit_decay(io_ref(uh),ins); + } + else if constexpr(zero_copy_transmitable) + { + if constexpr(buffer_output_stream&&!flush_output_stream) + return raw_transmit_decay(outs,ins); + else + { + std::uintmax_t chars{}; + if constexpr(buffer_input_stream) + { + auto curr{ibuffer_curr(ins)}; + auto ed{ibuffer_end(ins)}; + write(outs,curr,ed); + chars+=static_cast(ed-curr); + ibuffer_set_curr(ins,ed); + } + if constexpr(buffer_output_stream) + flush(outs); + return chars+zero_copy_transmit_define(io_alias,zero_copy_out_handle(outs),zero_copy_in_handle(ins)); + } + } + else if constexpr(output_stream&&input_stream) + return raw_transmit_decay(outs,ins); + else + { + constexpr bool no{output_stream&&input_stream}; + static_assert(no,"transmit must happen to output stream from input stream"); + } +} + +template +requires (std::is_trivially_copyable_v&&std::is_trivially_copyable_v) +inline constexpr std::uint_least64_t raw_transmit64_decay(output outs,input ins,std::uint_least64_t characters) +{ + if constexpr(contiguous_input_stream) + { + auto curr{ibuffer_curr(ins)}; + auto ed{ibuffer_end(ins)}; + std::uint_least64_t this_round{static_cast(ed-curr)}; + if(characters<=this_round) + { + this_round=characters; + } + ed=curr+this_round; + write(outs,curr,ed); + auto diff{ed-curr}; + ibuffer_set_curr(ins,ed); + return this_round; + } + else if constexpr(buffer_input_stream) + { + std::uint_least64_t chars{}; + do + { + auto curr{ibuffer_curr(ins)}; + auto ed{ibuffer_end(ins)}; + if(curr==ed)[[unlikely]] + continue; + std::uint_least64_t this_round{static_cast(ed-curr)}; + bool transmit_enough_characters{characters<=this_round}; + if(transmit_enough_characters) + this_round=characters; + ed=curr+this_round; + write(outs,curr,ed); + ibuffer_set_curr(ins,ed); + chars+=this_round; + characters-=this_round; + if(characters==0) + break; + } + while(ibuffer_underflow(ins)); + return chars; + } + else + { + using input_char_type = typename input::char_type; + std::uint_least64_t chars{}; + constexpr std::size_t buffer_size{details::transmit_buffer_size_cache}; + std::size_t to_allocate{buffer_size}; + if(characters(characters); + ::fast_io::details::buffer_alloc_arr_ptr||secure_clear_requirement_stream> array_ptr(to_allocate); + auto array_start{array_ptr.ptr}; + for(;;) + { + std::uint_least64_t this_round{to_allocate}; + bool transmit_enough_characters{characters<=this_round}; + if(transmit_enough_characters) + this_round=characters; + if(this_round==0) + break; + auto ed{read(ins,array_start,array_start+this_round)}; + if(array_start==ed)[[unlikely]] + break; + write(outs,array_start,ed); + std::uint_least64_t real_transmit_this_round{static_cast(static_cast(ed-array_start))}; + chars+=real_transmit_this_round; + characters-=real_transmit_this_round; + if(characters==0) + break; + } + return chars; + } +} + +template +requires (std::is_trivially_copyable_v&&std::is_trivially_copyable_v) +inline constexpr decltype(auto) transmit64_decay(output outs,input ins,std::uint_least64_t characters) +{ + if constexpr(mutex_stream) + { + io_lock_guard lg{ins}; + decltype(auto) uh{ins.unlocked_handle()}; + return transmit64_decay(outs,io_ref(uh),characters); + } + else if constexpr(mutex_stream) + { + io_lock_guard lg{outs}; + decltype(auto) uh{outs.unlocked_handle()}; + return transmit64_decay(io_ref(uh),ins,characters); + } + else if constexpr(zero_copy_transmitable) + { + if constexpr(buffer_output_stream&&!flush_output_stream) + return raw_transmit64_decay(outs,ins,characters); + else + { + std::uint_least64_t chars{}; + if constexpr(buffer_input_stream) + { + auto curr{ibuffer_curr(ins)}; + auto ed{ibuffer_end(ins)}; + std::size_t diff{static_cast(ed-curr)}; + bool const no_need_further_transmit{characters<=diff}; + if(no_need_further_transmit) + { + diff=static_cast(characters); + } + auto ed_ptr{curr+diff}; + write(outs,curr,curr+diff); + chars+=diff; + characters-=diff; + ibuffer_set_curr(ins,ed_ptr); + if(no_need_further_transmit) + return chars; + } + if constexpr(buffer_output_stream) + flush(outs); + return chars+zero_copy_transmit64_define(io_alias,zero_copy_out_handle(outs),zero_copy_in_handle(ins),characters); + } + } + else if constexpr(output_stream&&input_stream) + return raw_transmit64_decay(outs,ins,characters); + else + { + constexpr bool no{output_stream&&input_stream}; + static_assert(no,"transmit must happen to output stream from input stream"); + } +} + + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr decltype(auto) transmit(output&& outs,input&& ins) +{ + if constexpr(status_transmitable) + return status_transmit_define(io_alias,::std::forward(outs),::std::forward(ins)); + else + return transmit_decay(fast_io::io_ref(outs),fast_io::io_ref(ins)); +} + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr decltype(auto) transmit64(output&& outs,input&& ins,std::uint_least64_t characters=UINT_LEAST64_MAX) +{ + if constexpr(status_transmitable) + return status_transmit64_define(io_alias,::std::forward(outs),::std::forward(ins),characters); + else + return transmit64_decay(fast_io::io_ref(outs),fast_io::io_ref(ins),characters); +} + +} diff --git a/src/fast_io/include/fast_io_core_impl/unit_character_input_buffer.h b/src/fast_io/include/fast_io_core_impl/unit_character_input_buffer.h new file mode 100644 index 0000000..e1d233f --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/unit_character_input_buffer.h @@ -0,0 +1,73 @@ +#pragma once + +namespace fast_io +{ + +template +requires (!buffer_input_stream) +struct single_character_input_buffer +{ +public: + using char_type = typename input::char_type; + input& reference{}; + char_type single_character{}; + bool pos{}; + bool pos_end{}; +}; + +template +requires (std::same_as>||std::same_as) +constexpr Iter read(single_character_input_buffer& in,Iter begin,Iter end) +{ + if constexpr(std::same_as>) + { + if(in.pos!=in.pos_end) + { + if(begin==end) + return begin; + details::non_overlapped_copy_n(__builtin_addressof(in.single_character),1,::std::to_address(begin)); + in.pos=in.pos_end; + ++begin; + } + return read(in.reference,begin,end); + } + else + { + return read(in,reinterpret_cast(::std::to_address(begin)),reinterpret_cast(::std::to_address(end))); + } +} + +template +constexpr auto ibuffer_begin(single_character_input_buffer& in) +{ + return __builtin_addressof(in.single_character); +} +template +constexpr auto ibuffer_curr(single_character_input_buffer& in) +{ + return __builtin_addressof(in.single_character)+static_cast(in.pos); +} +template +constexpr auto ibuffer_end(single_character_input_buffer& in) +{ + return __builtin_addressof(in.single_character)+static_cast(in.pos_end); +} + +template +constexpr void ibuffer_set_curr(single_character_input_buffer& in,typename input::char_type* ptr) +{ + in.pos=(ptr!=__builtin_addressof(in.single_character)); +} + +template +constexpr bool ibuffer_underflow(single_character_input_buffer& in) +{ + in.pos_end=(read(in.reference,__builtin_addressof(in.single_character),__builtin_addressof(in.single_character)+1)!=__builtin_addressof(in.single_character)); + in.pos={}; + return in.pos_end; +} + +template +constexpr void avoid_scan_reserve(single_character_input_buffer&){} + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_core_impl/utils.h b/src/fast_io/include/fast_io_core_impl/utils.h new file mode 100644 index 0000000..ae71072 --- /dev/null +++ b/src/fast_io/include/fast_io_core_impl/utils.h @@ -0,0 +1,951 @@ +#pragma once + +#if defined(__GNUC__) && !defined(__clang__) +#pragma GCC system_header +#endif + +namespace fast_io +{ + +// All compilers have supported bit_cast but most people are stick with GCC 10. We provide emulation currently. +template + requires(sizeof(To) == sizeof(From) && ::std::is_trivially_copyable_v && ::std::is_trivial_v) +inline +#if __cpp_lib_bit_cast >= 201806L + constexpr +#endif + To + bit_cast(From const &src) noexcept +{ +#if __cpp_lib_bit_cast >= 201806L + return ::std::bit_cast(src); +#else + To dst; +#if defined(__has_builtin) +#if __has_builtin(__builtin_memcpy) + __builtin_memcpy +#else + ::std::memcpy +#endif +#else + ::std::memcpy +#endif + (__builtin_addressof(dst), __builtin_addressof(src), sizeof(To)); + return dst; +#endif +} + +/* +Since many toolchains do not provide lock_guard. Let's implement it by ourselves based on libstdc++'s lock_guard +https://github.com/gcc-mirror/gcc/blob/53046f072c6e92aa4ba4594c992fe31d89e223ed/libstdc%2B%2B-v3/include/bits/std_mutex.h#L152 +*/ + +template +struct io_lock_guard +{ + using mutex_type = mutx_type; + mutex_type &device; + explicit constexpr io_lock_guard(mutex_type &m) noexcept + : device(m) + { + device.lock(); + } + +#if __cpp_constexpr >= 201907L + constexpr +#endif + ~io_lock_guard() noexcept + { + device.unlock(); + } + + io_lock_guard(io_lock_guard const &) = delete; + io_lock_guard &operator=(io_lock_guard const &) = delete; +}; + +template +struct io_flush_guard +{ + using handle_type = stream_type; + handle_type &device; + explicit constexpr io_flush_guard(handle_type &m) noexcept + : device(m) + {} + +#if __cpp_constexpr >= 201907L + constexpr +#endif + ~io_flush_guard() noexcept + { +#if (defined(_MSC_VER) && _HAS_EXCEPTIONS != 0) || (!defined(_MSC_VER) && __cpp_exceptions) +#if __cpp_exceptions + try + { +#endif +#endif + flush(device); +#if (defined(_MSC_VER) && _HAS_EXCEPTIONS != 0) || (!defined(_MSC_VER) && __cpp_exceptions) +#if __cpp_exceptions + } + catch (...) + { + } +#endif +#endif + } + io_flush_guard(io_flush_guard const &) = delete; + io_flush_guard &operator=(io_flush_guard const &) = delete; +}; + +namespace details +{ + +template +using my_make_signed_t = +#ifdef __SIZEOF_INT128__ + ::std::conditional_t< + ::std::same_as<::std::remove_cv_t, __int128_t> || ::std::same_as<::std::remove_cv_t, __uint128_t>, + ::std::conditional_t< + ::std::same_as<::std::remove_cv_t, __int128_t>, T, + ::std::conditional_t<::std::same_as, __int128_t const volatile, + ::std::conditional_t<::std::same_as, __int128_t const, + ::std::conditional_t<::std::same_as, + __int128_t volatile, __int128_t>>>>, + ::std::make_signed_t<::std::conditional_t<::std::same_as<::std::remove_cv_t, __int128_t> || + ::std::same_as<::std::remove_cv_t, __uint128_t>, + int, T>>>; +#else + ::std::make_signed_t; +#endif +template +using my_make_unsigned_t = +#ifdef __SIZEOF_INT128__ + ::std::conditional_t< + ::std::same_as<::std::remove_cv_t, __int128_t> || ::std::same_as<::std::remove_cv_t, __uint128_t>, + ::std::conditional_t< + ::std::same_as<::std::remove_cv_t, __uint128_t>, T, + ::std::conditional_t<::std::same_as, __uint128_t const volatile, + ::std::conditional_t<::std::same_as, __uint128_t const, + ::std::conditional_t<::std::same_as, + __uint128_t volatile, __uint128_t>>>>, + ::std::make_unsigned_t<::std::conditional_t<::std::same_as<::std::remove_cv_t, __int128_t> || + ::std::same_as<::std::remove_cv_t, __uint128_t>, + int, T>>>; +#else + ::std::make_unsigned_t; +#endif + +template +concept my_integral = + ::std::integral +#ifdef __SIZEOF_INT128__ + || ::std::same_as<::std::remove_cv_t, __uint128_t> || ::std::same_as<::std::remove_cv_t, __int128_t> +#endif + ; + +template +concept my_signed_integral = ::std::signed_integral +#ifdef __SIZEOF_INT128__ + || ::std::same_as<::std::remove_cv_t, __int128_t> +#endif + ; +template +concept my_unsigned_integral = my_integral && !my_signed_integral; + +template +concept my_floating_point = ::std::floating_point +#ifdef __SIZEOF_FLOAT16__ + || ::std::same_as<::std::remove_cv_t, __float16> +#endif +#ifdef __SIZEOF_FLOAT80__ + || ::std::same_as<::std::remove_cv_t, __float80> +#endif +#ifdef __SIZEOF_FLOAT128__ + || ::std::same_as<::std::remove_cv_t, __float128> +#endif +#ifdef __STDCPP_BFLOAT16_T__ + || ::std::same_as<::std::remove_cv_t, decltype(0.0bf16)> +#endif +#ifdef __STDCPP_FLOAT16_T__ + || ::std::same_as<::std::remove_cv_t, _Float16> +#endif +#ifdef __STDCPP_FLOAT32_T__ + || ::std::same_as<::std::remove_cv_t, _Float32> +#endif +#ifdef __STDCPP_FLOAT64_T__ + || ::std::same_as<::std::remove_cv_t, _Float64> +#endif +#ifdef __STDCPP_FLOAT128_T__ + || ::std::same_as<::std::remove_cv_t, _Float128> +#endif + ; + +#ifdef __SIZEOF_INT128__ +inline constexpr __uint128_t calculate_byteswap_ff(::std::size_t v) noexcept +{ + return static_cast<__uint128_t>(0xff) << (v * 8); +} +template <::std::size_t v> +inline constexpr __uint128_t uint128_t_bsv{calculate_byteswap_ff(v)}; +#endif + +template + requires(sizeof(U) == 1 || sizeof(U) == 2 || sizeof(U) == 4 || sizeof(U) == 8 +#ifdef __SIZEOF_INT128__ + || sizeof(U) == 16 +#endif + ) +inline constexpr U byte_swap_naive_impl(U a) noexcept +{ +#ifdef __SIZEOF_INT128__ + if constexpr (sizeof(U) == 16) + { + return ((a & uint128_t_bsv<15>) >> 120) | ((a & uint128_t_bsv<14>) >> 104) | ((a & uint128_t_bsv<13>) >> 88) | + ((a & uint128_t_bsv<12>) >> 72) | ((a & uint128_t_bsv<11>) >> 56) | ((a & uint128_t_bsv<10>) >> 40) | + ((a & uint128_t_bsv<9>) >> 24) | ((a & uint128_t_bsv<8>) >> 8) | ((a & uint128_t_bsv<7>) << 8) | + ((a & uint128_t_bsv<6>) << 24) | ((a & uint128_t_bsv<5>) << 40) | ((a & uint128_t_bsv<4>) << 56) | + ((a & uint128_t_bsv<3>) << 72) | ((a & uint128_t_bsv<2>) << 88) | ((a & uint128_t_bsv<1>) << 104) | + ((a & uint128_t_bsv<0>) << 120); + } + else +#endif + if constexpr (sizeof(U) == 8) + { + return ((a & 0xff00000000000000ULL) >> 56) | ((a & 0x00ff000000000000ULL) >> 40) | + ((a & 0x0000ff0000000000ULL) >> 24) | ((a & 0x000000ff00000000ULL) >> 8) | + ((a & 0x00000000ff000000ULL) << 8) | ((a & 0x0000000000ff0000ULL) << 24) | + ((a & 0x000000000000ff00ULL) << 40) | ((a & 0x00000000000000ffULL) << 56); + } + else if constexpr (sizeof(U) == 4) + { + return ((a & 0xff000000U) >> 24) | ((a & 0x00ff0000U) >> 8) | ((a & 0x0000ff00U) << 8) | + ((a & 0x000000ffU) << 24); + } + else if constexpr (sizeof(U) == 2) + { + return static_cast(static_cast(((a & 0xff00) >> 8) | ((a & 0x00ff) << 8))); + } + else + { + return a; + } +} + +} // namespace details + +template +inline constexpr U byte_swap(U a) noexcept +{ + if constexpr (sizeof(U) == 1) + { + return a; + } + else + { +#if (defined(__GNUC__) || defined(__clang__)) +#ifdef __SIZEOF_INT128__ + if constexpr (sizeof(U) == 16) +#if __has_builtin(__builtin_bswap128) + return __builtin_bswap128(a); +#else + { + ::std::uint_least64_t high(__builtin_bswap64(static_cast<::std::uint_least64_t>(a >> 64))); + ::std::uint_least64_t low(__builtin_bswap64(static_cast<::std::uint_least64_t>(a))); + return (static_cast<__uint128_t>(low) << 64) | static_cast<__uint128_t>(high); + } +#endif + else +#endif + if constexpr (sizeof(U) == 8) + { + return __builtin_bswap64(a); + } + else if constexpr (sizeof(U) == 4) + { + return __builtin_bswap32(a); + } + else + { + return __builtin_bswap16(a); + } +#else + +#if __cpp_lib_is_constant_evaluated >= 201811L + if (::std::is_constant_evaluated()) + { + return details::byte_swap_naive_impl(a); + } + else +#endif + { +#if defined(_MSC_VER) + if constexpr (sizeof(U) == 8) + { + return _byteswap_uint64(a); + } + else if constexpr (sizeof(U) == 4) + { + return _byteswap_ulong(a); + } + else + { + return _byteswap_ushort(a); + } +#else + return details::byte_swap_naive_impl(a); +#endif + } +#endif + } +} + +template +inline constexpr U big_endian(U u) noexcept +{ + if constexpr (sizeof(U) == 1 || ::std::endian::big == ::std::endian::native) + { + return u; + } + else if constexpr (::std::endian::little == ::std::endian::native) + { + return byte_swap(u); + } + else + { + return details::byte_swap_naive_impl(u); // support architectures like PDP11 + } +} + +template +inline constexpr U little_endian(U u) noexcept +{ + if constexpr (sizeof(U) == 1 || ::std::endian::little == ::std::endian::native) + { + return u; + } + else if constexpr (::std::endian::big == ::std::endian::native) + { + return byte_swap(u); + } + else + { + return details::byte_swap_naive_impl(u); // support architectures like PDP11 + } +} + +namespace details +{ + +template +inline +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && __cpp_lib_bit_cast >= 201806L + constexpr +#endif + void + compile_time_type_punning_copy_n(range_type const *first, ::std::size_t bytes, ::std::byte *out) +{ +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && __cpp_lib_bit_cast >= 201806L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if (__builtin_is_constant_evaluated()) +#endif + { + if constexpr (::std::same_as) + { + for (auto i{first}, e{first + bytes}; i != e; ++i) + { + *out = *i; + ++out; + } + } + else + { + auto j{out}; + auto first_end{first + bytes / sizeof(range_type)}; + for (auto i{first}; i != first_end; ++i) + { + ::fast_io::freestanding::array<::std::byte, sizeof(range_type)> arr{ + ::std::bit_cast<::fast_io::freestanding::array<::std::byte, sizeof(range_type)>>(*i)}; + j = non_overlapped_copy_n(arr.data(), arr.size(), j); + } + } + } + else +#endif + { + if (bytes) [[likely]] + { + my_memcpy(out, first, bytes); + } + } +} + +template <::std::input_or_output_iterator output_iter, typename T> + requires(::std::is_trivially_copyable_v && sizeof(T) <= sizeof(::std::uintmax_t)) +inline constexpr output_iter my_fill_n(output_iter first, ::std::size_t count, T value) +{ +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if (__builtin_is_constant_evaluated()) +#endif + { + ::fast_io::freestanding::fill_n(first, count, value); + } + else +#endif + { + using output_value_type = ::std::iter_value_t; + if constexpr (::std::contiguous_iterator && ::std::is_trivially_copyable_v && + ::std::integral && sizeof(output_value_type) == 1) + { + if (count) [[likely]] + { + my_memset(::std::to_address(first), static_cast(value), count); + } + return first + count; + } + else + { + ::fast_io::freestanding::fill_n(first, count, value); + } + } + return first + count; +} + +template <::std::forward_iterator fwd_iter, typename T> + requires(::std::is_trivially_copyable_v && sizeof(T) <= sizeof(::std::uintmax_t)) +inline constexpr void my_fill(fwd_iter first, fwd_iter last, T value) +{ + using fwd_iter_value_type = ::std::iter_value_t; + if constexpr (::std::contiguous_iterator && ::std::is_trivially_copyable_v && + ::std::integral && sizeof(fwd_iter_value_type) == 1) + { + ::fast_io::freestanding::fill_n(first, last - first, value); + } + else + { + ::fast_io::freestanding::fill(first, last, value); + } +} + +template <::std::integral char_type, ::std::size_t n> + requires(n != 0) +inline constexpr ::std::size_t string_literal_size(char_type const (&)[n]) +{ + return n - 1; +} + +template <::std::integral char_type, ::std::size_t n, ::std::random_access_iterator output_iter> + requires(n != 0) +inline constexpr output_iter copy_string_literal(char_type const (&s)[n], output_iter result) +{ + details::non_overlapped_copy_n(s, n - 1, result); + return result + (n - 1); +} + +template <::std::input_or_output_iterator output_iter> +inline constexpr output_iter copy_scatter(basic_io_scatter_t<::std::iter_value_t> scatter, + output_iter result) +{ + return details::non_overlapped_copy_n(scatter.base, scatter.len, result); +} + +template +inline constexpr T compile_time_pow(T base, ::std::size_t pow) noexcept +{ + T t = 1; + for (::std::size_t i{}; i != pow; ++i) + { + t *= base; + } + return t; +} + +template +inline constexpr T compile_pow10{::fast_io::details::compile_time_pow<::std::remove_cvref_t>(10, pow)}; + +template +inline constexpr T compile_pow5{::fast_io::details::compile_time_pow<::std::remove_cvref_t>(5, pow)}; + +template +inline constexpr T compile_pow2{::fast_io::details::compile_time_pow<::std::remove_cvref_t>(2, pow)}; + +inline constexpr bool is_wasi_environment{ +#if __wasi__ + true +#endif +}; + +using optimal_print_unsigned_type = + ::std::conditional_t>; + +template +inline constexpr bool need_seperate_print{(sizeof(T) > sizeof(optimal_print_unsigned_type)) && + (sizeof(T) % sizeof(optimal_print_unsigned_type) == 0) && + (sizeof(T) / sizeof(optimal_print_unsigned_type) == 2)}; + +template <::std::uint_least32_t base, bool ryu_mode = false, + ::std::size_t mx_size = ::std::numeric_limits<::std::size_t>::max(), my_unsigned_integral U> +constexpr ::std::size_t chars_len(U value) noexcept +{ + if constexpr (base == 10 && sizeof(U) <= 16) + { + if constexpr (15 < sizeof(U)) + { + using M = ::std::remove_cvref_t; + if constexpr (16 < sizeof(M) || !ryu_mode) + { + if constexpr (39 <= mx_size) + { + if (compile_pow10 <= value) + { + return 39; + } + } + if constexpr (38 <= mx_size) + { + if (compile_pow10 <= value) + { + return 38; + } + } + if constexpr (37 <= mx_size) + { + if (compile_pow10 <= value) + { + return 37; + } + } + } + if constexpr (36 <= mx_size) + { + if (compile_pow10 <= value) + { + return 36; + } + } + if constexpr (35 <= mx_size) + { + if (compile_pow10 <= value) + { + return 35; + } + } + if constexpr (34 <= mx_size) + { + if (compile_pow10 <= value) + { + return 34; + } + } + if constexpr (33 <= mx_size) + { + if (compile_pow10 <= value) + { + return 33; + } + } + if constexpr (32 <= mx_size) + { + if (compile_pow10 <= value) + { + return 32; + } + } + if constexpr (31 <= mx_size) + { + if (compile_pow10 <= value) + { + return 31; + } + } + if constexpr (30 <= mx_size) + { + if (compile_pow10 <= value) + { + return 30; + } + } + if constexpr (29 <= mx_size) + { + if (compile_pow10 <= value) + { + return 29; + } + } + if constexpr (28 <= mx_size) + { + if (compile_pow10 <= value) + { + return 28; + } + } + if constexpr (27 <= mx_size) + { + if (compile_pow10 <= value) + { + return 27; + } + } + if constexpr (26 <= mx_size) + { + if (compile_pow10 <= value) + { + return 26; + } + } + if constexpr (25 <= mx_size) + { + if (compile_pow10 <= value) + { + return 25; + } + } + if constexpr (24 <= mx_size) + { + if (compile_pow10 <= value) + { + return 24; + } + } + if constexpr (23 <= mx_size) + { + if (compile_pow10 <= value) + { + return 23; + } + } + if constexpr (22 <= mx_size) + { + if (compile_pow10 <= value) + { + return 22; + } + } + if constexpr (21 <= mx_size) + { + if (compile_pow10 <= value) + { + return 21; + } + } + } + if constexpr (7 < sizeof(U)) + { + if constexpr (8 < sizeof(U) || !ryu_mode) + { + if constexpr (20 <= mx_size) + { + if (10000000000000000000ULL <= value) + { + return 20; + } + } + if constexpr (19 <= mx_size) + { + if (1000000000000000000ULL <= value) + { + return 19; + } + } + if constexpr (18 <= mx_size) + { + if (100000000000000000ULL <= value) + { + return 18; + } + } + } + if constexpr (17 <= mx_size) + { + if (10000000000000000ULL <= value) + { + return 17; + } + } + if constexpr (16 <= mx_size) + { + if (1000000000000000ULL <= value) + { + return 16; + } + } + if constexpr (15 <= mx_size) + { + if (100000000000000ULL <= value) + { + return 15; + } + } + if constexpr (14 <= mx_size) + { + if (10000000000000ULL <= value) + { + return 14; + } + } + if constexpr (13 <= mx_size) + { + if (1000000000000ULL <= value) + { + return 13; + } + } + if constexpr (12 <= mx_size) + { + if (100000000000ULL <= value) + { + return 12; + } + } + if constexpr (11 <= mx_size) + { + if (10000000000ULL <= value) + { + return 11; + } + } + } + if constexpr (3 < sizeof(U)) + { + if constexpr (4 < sizeof(U) || !ryu_mode) + { + if constexpr (10 <= mx_size) + { + if (1000000000U <= value) + { + return 10; + } + } + } + if constexpr (9 <= mx_size) + { + if (100000000U <= value) + { + return 9; + } + } + if constexpr (8 <= mx_size) + { + if (10000000U <= value) + { + return 8; + } + } + if constexpr (7 <= mx_size) + { + if (1000000U <= value) + { + return 7; + } + } + if constexpr (6 <= mx_size) + { + if (100000U <= value) + { + return 6; + } + } + } + if constexpr (1 < sizeof(U)) + { + if constexpr (5 <= mx_size) + { + if (10000U <= value) + { + return 5; + } + } + if constexpr (4 <= mx_size) + { + if (1000U <= value) + { + return 4; + } + } + } + if constexpr (3 <= mx_size) + { + if (100U <= value) + { + return 3; + } + } + if constexpr (2 <= mx_size) + { + if (10U <= value) + { + return 2; + } + } + return 1; + } + else if constexpr (base == 2u || base == 4u || base == 8u || base == 16u || base == 32u) + { + constexpr ::std::size_t bits{sizeof(U) * 8u}; +#if defined(__SIZEOF_INT128__) + if constexpr (sizeof(U) == sizeof(__uint128_t)) + { + ::std::uint_least64_t high{static_cast<::std::uint_least64_t>(value >> 64u)}; + constexpr ::std::uint_least64_t zero{}; + ::std::size_t base2len; + if (high == zero) + { + constexpr ::std::uint_least64_t one_constant{1}; + ::std::uint_least64_t low{static_cast<::std::uint_least64_t>(value) | one_constant}; + constexpr ::std::size_t bitsdv2{bits >> 1u}; + base2len = bitsdv2 - static_cast<::std::size_t>(::std::countl_zero(low)); + } + else + { + base2len = bits - static_cast<::std::size_t>(::std::countl_zero(high)); + } + if constexpr (base == 2) + { + return base2len; + } + else + { + constexpr ::std::size_t one{1}; + constexpr ::std::size_t log2base{static_cast<::std::size_t>(::std::countr_zero(base))}; + return (base2len - one) / log2base + one; + } + } + else +#endif + { + constexpr U one_constant{1}; + ::std::size_t const base2len{ + bits - static_cast<::std::size_t>(::std::countl_zero(static_cast(value | one_constant)))}; + if constexpr (base == 2) + { + return base2len; + } + else + { + constexpr ::std::size_t one{1}; + constexpr ::std::size_t log2base{static_cast<::std::size_t>(::std::countr_zero(base))}; + return (base2len - one) / log2base + one; + } + } + } + else + { + constexpr ::std::uint_least32_t base2(base * base); + constexpr ::std::uint_least32_t base3(base2 * base); + constexpr ::std::uint_least32_t base4(base3 * base); + for (::std::size_t n(1);; n += 4) + { + if (value < base) + { + return n; + } + if (value < base2) + { + return n + 1; + } + if (value < base3) + { + return n + 2; + } + if (value < base4) + { + return n + 3; + } + value /= base4; + } + } +} + +template +inline constexpr my_make_unsigned_t cal_int_max() noexcept +{ +#if defined(_MSC_VER) && !defined(__clang__) + return static_cast>(::std::numeric_limits::max()); +#else + my_make_unsigned_t n{}; + --n; + if constexpr (my_signed_integral) + { + n >>= 1; + } + return n; +#endif +} +template +inline constexpr T get_int_max() noexcept +{ + constexpr T v{static_cast(cal_int_max())}; + return v; +} +template +inline constexpr auto get_int_max_unsigned() noexcept +{ + constexpr my_make_unsigned_t<::std::remove_cvref_t> v{ + static_cast>>(cal_int_max<::std::remove_cvref_t>())}; + return v; +} +template +inline constexpr ::std::size_t cal_max_int_size() noexcept +{ + ::std::size_t i{}; + auto n(get_int_max_unsigned()); + for (; n; ++i) + { + n /= base; + } + return i; +} + +// static_assert(cal_max_int_size<::std::uint_least64_t,10>()==20); +// static_assert(cal_max_int_size<::std::uint_least32_t,10>()==10); +template +inline constexpr basic_io_scatter_t tsc(char_type const (&a)[N]) noexcept +{ + return {a, N - 1}; +} + +template +inline constexpr ::std::size_t cal_array_size(char_type const (&)[N]) noexcept +{ + return N - 1; +} + +template <::std::integral char_type, bool iobuf = false> +inline constexpr ::std::size_t cal_buffer_size() +{ +#ifdef FAST_IO_BUFFER_SIZE + static_assert(sizeof(char_type) <= FAST_IO_BUFFER_SIZE); +#endif + if constexpr (iobuf) + { + return +#ifdef FAST_IO_BUFFER_SIZE + FAST_IO_BUFFER_SIZE +#else + 131072u +#endif + / sizeof(char_type); + } + else + { + return +#ifdef FAST_IO_BUFFER_SIZE + FAST_IO_BUFFER_SIZE // avoid BUFSIZ macro since it is a cancer and often set incorrectly +#else +#ifdef FAST_IO_TRANSMIT_ON_STACK + 4096 +#else + 131072u +#endif +#endif + / sizeof(char_type); + } +} +} // namespace details + +} // namespace fast_io diff --git a/src/fast_io/include/fast_io_crypto.h b/src/fast_io/include/fast_io_crypto.h new file mode 100644 index 0000000..bdc9f87 --- /dev/null +++ b/src/fast_io/include/fast_io_crypto.h @@ -0,0 +1,32 @@ +#pragma once + +//fast_io_crypto.h defines what you could use for cryptography +//It is likely usable in a freestanding environment +#if !defined(__cplusplus) +#error "You are not using a C++ compiler" +#endif + +#if !defined(__cpp_concepts) +#error "fast_io requires at least C++20 standard compiler." +#else + +#include"fast_io_core.h" + +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning(push) +#pragma warning( disable : 4514 ) +#pragma warning( disable : 4623 ) +#pragma warning( disable : 4710 ) +#pragma warning( disable : 4668 ) +#endif + +//#include"fast_io_crypto/symmetric_crypto.h" +//#include"fast_io_crypto/hash/intrin_include.h" +#include"fast_io_crypto/hash/impl.h" + +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning(pop) +#endif + + +#endif diff --git a/src/fast_io/include/fast_io_crypto/cipher/aes.h b/src/fast_io/include/fast_io_crypto/cipher/aes.h new file mode 100644 index 0000000..e0c2af8 --- /dev/null +++ b/src/fast_io/include/fast_io_crypto/cipher/aes.h @@ -0,0 +1,130 @@ +#pragma once + +#if defined(__AES__) +#include +#endif + +namespace fast_io +{ + +namespace details::aes +{ +inline __m128i aes_128_key_exp_common(__m128i key) noexcept { + key = _mm_xor_si128(key, _mm_slli_si128(key, 4)); + key = _mm_xor_si128(key, _mm_slli_si128(key, 4)); + key = _mm_xor_si128(key, _mm_slli_si128(key, 4)); + return key; +} + +inline __m128i aes_128_key_expansion(__m128i key, __m128i keygened) noexcept { + keygened = _mm_shuffle_epi32(keygened, _MM_SHUFFLE(3, 3, 3, 3)); + key = aes_128_key_exp_common(key); + return _mm_xor_si128(key, keygened); +} + +inline __m128i aes_128_key_exp(__m128i k, int rcon) noexcept { + return aes_128_key_expansion(k, _mm_aeskeygenassist_si128(k, rcon)); +} + +inline __m128i aes_192_key_exp_2(__m128i key, __m128i key2) noexcept { + key = _mm_shuffle_epi32(key, 0xff); + key2 = _mm_xor_si128(key2, _mm_slli_si128(key2, 4)); + return _mm_xor_si128(key, key2); +} +inline __m128i aes_192_key_exp(__m128i key, __m128i key2, int I) noexcept { + return _mm_xor_si128(aes_128_key_exp_common(key), _mm_shuffle_epi32(_mm_aeskeygenassist_si128(key2, I), 0x55)); +} + +inline __m128i aes_256_key_exp(__m128i key, __m128i key2, int I) noexcept { + return _mm_xor_si128(aes_128_key_exp_common(key), _mm_shuffle_epi32(_mm_aeskeygenassist_si128(key2, I), 0xff)); +} + +inline __m128i aes_256_key_exp_2(__m128i key, __m128i key2) noexcept { + return _mm_xor_si128(aes_128_key_exp_common(key), _mm_shuffle_epi32(_mm_aeskeygenassist_si128(key2, 0x00), 0xff)); +} + +} + +template +requires (keysize==16||keysize==24||keysize==32) +struct aes +{ + inline static constexpr std::size_t block_size = 16; + inline static constexpr std::size_t key_size = keysize; + inline static constexpr std::size_t key_schedule_size = keysize==16?10:(keysize==24?12:15); + __m128i key_schedule[key_schedule_size]; + explicit aes(std::span key_span) noexcept + { + using namespace details::aes; + std::byte const* key{key_span.data()}; + if constexpr(keysize==16) + { + key_schedule[0] = _mm_loadu_si128(reinterpret_cast<__m128i const*>(key)); + key_schedule[1] = aes_128_key_exp(key_schedule[0], 0x01); + key_schedule[2] = aes_128_key_exp(key_schedule[1], 0x02); + key_schedule[3] = aes_128_key_exp(key_schedule[2], 0x04); + key_schedule[4] = aes_128_key_exp(key_schedule[3], 0x08); + key_schedule[5] = aes_128_key_exp(key_schedule[4], 0x10); + key_schedule[6] = aes_128_key_exp(key_schedule[5], 0x20); + key_schedule[7] = aes_128_key_exp(key_schedule[6], 0x40); + key_schedule[8] = aes_128_key_exp(key_schedule[7], 0x80); + key_schedule[9] = aes_128_key_exp(key_schedule[8], 0x1B); + key_schedule[10] = aes_128_key_exp(key_schedule[9], 0x36); + } + else if constexpr(keysize==24) + { + key_schedule[0] = _mm_loadu_si128(reinterpret_cast<__m128i const*>(key)); // load 16 bytes + key_schedule[1] = _mm_loadu_si128(reinterpret_cast<__m128i const*>(key + 8)); // load 8 bytes + key_schedule[1] = _mm_srli_si128(key_schedule[1], 8); // right shift 64 bits + __m128i temp[2]; + temp[0] = aes_192_key_exp(key_schedule[0], key_schedule[1], 0x01); + temp[1] = aes_192_key_exp_2(temp[0], key_schedule[1]); + key_schedule[1] = reinterpret_cast<__m128i>(_mm_shuffle_pd(reinterpret_cast<__m128d>(key_schedule[1]), reinterpret_cast<__m128d>(temp[0]), 0)); + key_schedule[2] = reinterpret_cast<__m128i>(_mm_shuffle_pd(reinterpret_cast<__m128d>(temp[0]), reinterpret_cast<__m128d>(temp[1]), 1)); + key_schedule[3] = aes_192_key_exp(temp[0], temp[1], 0x02); + key_schedule[4] = aes_192_key_exp_2(key_schedule[3], temp[1]); + temp[0] = aes_192_key_exp(key_schedule[3], key_schedule[4], 0x04); + temp[1] = aes_192_key_exp_2(temp[0], key_schedule[4]); + key_schedule[4] = reinterpret_cast<__m128i>(_mm_shuffle_pd(reinterpret_cast<__m128d>(key_schedule[4]), reinterpret_cast<__m128d>(temp[0]), 0)); + key_schedule[5] = reinterpret_cast<__m128i>(_mm_shuffle_pd(reinterpret_cast<__m128d>(temp[0]), reinterpret_cast<__m128d>(temp[1]), 1)); + key_schedule[6] = aes_192_key_exp(temp[0], temp[1], 0x08); + key_schedule[7] = aes_192_key_exp_2(key_schedule[6], temp[1]); + temp[0] = aes_192_key_exp(key_schedule[6], key_schedule[7], 0x10); + temp[1] = aes_192_key_exp_2(temp[0], key_schedule[7]); + key_schedule[7] = reinterpret_cast<__m128i>(_mm_shuffle_pd(reinterpret_cast<__m128d>(key_schedule[7]), reinterpret_cast<__m128d>(temp[0]), 0)); + key_schedule[8] = reinterpret_cast<__m128i>(_mm_shuffle_pd(reinterpret_cast<__m128d>(temp[0]), reinterpret_cast<__m128d>(temp[1]), 1)); + key_schedule[9] = aes_192_key_exp(temp[0], temp[1], 0x20); + key_schedule[10] = aes_192_key_exp_2(key_schedule[9], temp[1]); + temp[0] = aes_192_key_exp(key_schedule[9], key_schedule[10], 0x40); + temp[1] = aes_192_key_exp_2(temp[0], key_schedule[10]); + key_schedule[10] = reinterpret_cast<__m128i>(_mm_shuffle_pd(reinterpret_cast<__m128d>(key_schedule[10]), reinterpret_cast<__m128d>(temp[0]), 0)); + key_schedule[11] = reinterpret_cast<__m128i>(_mm_shuffle_pd(reinterpret_cast<__m128d>(temp[0]),reinterpret_cast<__m128d>(temp[1]), 1)); + key_schedule[12] = aes_192_key_exp(temp[0], temp[1], 0x80); + secure_clear(temp,sizeof(temp)); + } + else + { + key_schedule[0] = _mm_loadu_si128(reinterpret_cast<__m128i const*>(key)); + key_schedule[1] = _mm_loadu_si128(reinterpret_cast<__m128i const*>(key + 16)); + key_schedule[2] = aes_256_key_exp(key_schedule[0], key_schedule[1], 0x01); + key_schedule[3] = aes_256_key_exp_2(key_schedule[1], key_schedule[2]); + key_schedule[4] = aes_256_key_exp(key_schedule[2], key_schedule[3], 0x02); + key_schedule[5] = aes_256_key_exp_2(key_schedule[3], key_schedule[4]); + key_schedule[6] = aes_256_key_exp(key_schedule[4], key_schedule[5], 0x04); + key_schedule[7] = aes_256_key_exp_2(key_schedule[5], key_schedule[6]); + key_schedule[8] = aes_256_key_exp(key_schedule[6], key_schedule[7], 0x08); + key_schedule[9] = aes_256_key_exp_2(key_schedule[7], key_schedule[8]); + key_schedule[10] = aes_256_key_exp(key_schedule[8], key_schedule[9], 0x10); + key_schedule[11] = aes_256_key_exp_2(key_schedule[9], key_schedule[10]); + key_schedule[12] = aes_256_key_exp(key_schedule[10], key_schedule[11], 0x20); + key_schedule[13] = aes_256_key_exp_2(key_schedule[11], key_schedule[12]); + key_schedule[14] = aes_256_key_exp(key_schedule[12], key_schedule[13], 0x40); + } + } + void operator()(std::byte const* from,std::size_t blocks,std::byte* to) noexcept + { + + } +}; + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_crypto/hash/crc32.h b/src/fast_io/include/fast_io_crypto/hash/crc32.h new file mode 100644 index 0000000..5eeee9b --- /dev/null +++ b/src/fast_io/include/fast_io_crypto/hash/crc32.h @@ -0,0 +1,94 @@ +#pragma once + +namespace fast_io +{ + +namespace details +{ + +enum class crc32_option +{ +crc32, +crc32c +}; + +inline constexpr void crc32_to_byte_ptr_commom_impl(std::uint_least32_t crc,std::byte* ptr) noexcept +{ + crc=~crc; + if constexpr(std::endian::big!=std::endian::native) + { + crc=::fast_io::byte_swap(crc); + } +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && __cpp_lib_bit_cast >= 201806L +#if __cpp_if_consteval >= 202106L + if consteval +#elif __cpp_lib_is_constant_evaluated >= 201811L + if(std::is_constant_evaluated()) +#endif + { + auto a{::std::bit_cast<::fast_io::freestanding::array>(crc)}; + ::fast_io::freestanding::nonoverlapped_bytes_copy_n(a.data(),a.size(),ptr); + } + else +#endif + { + ::fast_io::freestanding::nonoverlapped_bytes_copy_n(reinterpret_cast(__builtin_addressof(crc)),sizeof(std::uint_least32_t),ptr); + } +} + +inline constexpr std::uint_least32_t calculate_crc32_common(std::uint_least32_t crc,std::byte const* i,std::byte const* ed,std::uint_least32_t const* crctb) noexcept +{ + for(;i!=ed;++i) + { + crc=crctb[(static_cast(*i)^crc)&0xff]^(crc>>8); + } + return crc; +} +inline constexpr std::uint_least32_t crc32_tb[256]{0x0,0x77073096,0xee0e612c,0x990951ba,0x76dc419,0x706af48f,0xe963a535,0x9e6495a3,0xedb8832,0x79dcb8a4,0xe0d5e91e,0x97d2d988,0x9b64c2b,0x7eb17cbd,0xe7b82d07,0x90bf1d91,0x1db71064,0x6ab020f2,0xf3b97148,0x84be41de,0x1adad47d,0x6ddde4eb,0xf4d4b551,0x83d385c7,0x136c9856,0x646ba8c0,0xfd62f97a,0x8a65c9ec,0x14015c4f,0x63066cd9,0xfa0f3d63,0x8d080df5,0x3b6e20c8,0x4c69105e,0xd56041e4,0xa2677172,0x3c03e4d1,0x4b04d447,0xd20d85fd,0xa50ab56b,0x35b5a8fa,0x42b2986c,0xdbbbc9d6,0xacbcf940,0x32d86ce3,0x45df5c75,0xdcd60dcf,0xabd13d59,0x26d930ac,0x51de003a,0xc8d75180,0xbfd06116,0x21b4f4b5,0x56b3c423,0xcfba9599,0xb8bda50f,0x2802b89e,0x5f058808,0xc60cd9b2,0xb10be924,0x2f6f7c87,0x58684c11,0xc1611dab,0xb6662d3d,0x76dc4190,0x1db7106,0x98d220bc,0xefd5102a,0x71b18589,0x6b6b51f,0x9fbfe4a5,0xe8b8d433,0x7807c9a2,0xf00f934,0x9609a88e,0xe10e9818,0x7f6a0dbb,0x86d3d2d,0x91646c97,0xe6635c01,0x6b6b51f4,0x1c6c6162,0x856530d8,0xf262004e,0x6c0695ed,0x1b01a57b,0x8208f4c1,0xf50fc457,0x65b0d9c6,0x12b7e950,0x8bbeb8ea,0xfcb9887c,0x62dd1ddf,0x15da2d49,0x8cd37cf3,0xfbd44c65,0x4db26158,0x3ab551ce,0xa3bc0074,0xd4bb30e2,0x4adfa541,0x3dd895d7,0xa4d1c46d,0xd3d6f4fb,0x4369e96a,0x346ed9fc,0xad678846,0xda60b8d0,0x44042d73,0x33031de5,0xaa0a4c5f,0xdd0d7cc9,0x5005713c,0x270241aa,0xbe0b1010,0xc90c2086,0x5768b525,0x206f85b3,0xb966d409,0xce61e49f,0x5edef90e,0x29d9c998,0xb0d09822,0xc7d7a8b4,0x59b33d17,0x2eb40d81,0xb7bd5c3b,0xc0ba6cad,0xedb88320,0x9abfb3b6,0x3b6e20c,0x74b1d29a,0xead54739,0x9dd277af,0x4db2615,0x73dc1683,0xe3630b12,0x94643b84,0xd6d6a3e,0x7a6a5aa8,0xe40ecf0b,0x9309ff9d,0xa00ae27,0x7d079eb1,0xf00f9344,0x8708a3d2,0x1e01f268,0x6906c2fe,0xf762575d,0x806567cb,0x196c3671,0x6e6b06e7,0xfed41b76,0x89d32be0,0x10da7a5a,0x67dd4acc,0xf9b9df6f,0x8ebeeff9,0x17b7be43,0x60b08ed5,0xd6d6a3e8,0xa1d1937e,0x38d8c2c4,0x4fdff252,0xd1bb67f1,0xa6bc5767,0x3fb506dd,0x48b2364b,0xd80d2bda,0xaf0a1b4c,0x36034af6,0x41047a60,0xdf60efc3,0xa867df55,0x316e8eef,0x4669be79,0xcb61b38c,0xbc66831a,0x256fd2a0,0x5268e236,0xcc0c7795,0xbb0b4703,0x220216b9,0x5505262f,0xc5ba3bbe,0xb2bd0b28,0x2bb45a92,0x5cb36a04,0xc2d7ffa7,0xb5d0cf31,0x2cd99e8b,0x5bdeae1d,0x9b64c2b0,0xec63f226,0x756aa39c,0x26d930a,0x9c0906a9,0xeb0e363f,0x72076785,0x5005713,0x95bf4a82,0xe2b87a14,0x7bb12bae,0xcb61b38,0x92d28e9b,0xe5d5be0d,0x7cdcefb7,0xbdbdf21,0x86d3d2d4,0xf1d4e242,0x68ddb3f8,0x1fda836e,0x81be16cd,0xf6b9265b,0x6fb077e1,0x18b74777,0x88085ae6,0xff0f6a70,0x66063bca,0x11010b5c,0x8f659eff,0xf862ae69,0x616bffd3,0x166ccf45,0xa00ae278,0xd70dd2ee,0x4e048354,0x3903b3c2,0xa7672661,0xd06016f7,0x4969474d,0x3e6e77db,0xaed16a4a,0xd9d65adc,0x40df0b66,0x37d83bf0,0xa9bcae53,0xdebb9ec5,0x47b2cf7f,0x30b5ffe9,0xbdbdf21c,0xcabac28a,0x53b39330,0x24b4a3a6,0xbad03605,0xcdd70693,0x54de5729,0x23d967bf,0xb3667a2e,0xc4614ab8,0x5d681b02,0x2a6f2b94,0xb40bbe37,0xc30c8ea1,0x5a05df1b,0x2d02ef8d}; + +inline constexpr std::uint_least32_t crc32c_tb[256]{0x0,0xf26b8303,0xe13b70f7,0x1350f3f4,0xc79a971f,0x35f1141c,0x26a1e7e8,0xd4ca64eb,0x8ad958cf,0x78b2dbcc,0x6be22838,0x9989ab3b,0x4d43cfd0,0xbf284cd3,0xac78bf27,0x5e133c24,0x105ec76f,0xe235446c,0xf165b798,0x30e349b,0xd7c45070,0x25afd373,0x36ff2087,0xc494a384,0x9a879fa0,0x68ec1ca3,0x7bbcef57,0x89d76c54,0x5d1d08bf,0xaf768bbc,0xbc267848,0x4e4dfb4b,0x20bd8ede,0xd2d60ddd,0xc186fe29,0x33ed7d2a,0xe72719c1,0x154c9ac2,0x61c6936,0xf477ea35,0xaa64d611,0x580f5512,0x4b5fa6e6,0xb93425e5,0x6dfe410e,0x9f95c20d,0x8cc531f9,0x7eaeb2fa,0x30e349b1,0xc288cab2,0xd1d83946,0x23b3ba45,0xf779deae,0x5125dad,0x1642ae59,0xe4292d5a,0xba3a117e,0x4851927d,0x5b016189,0xa96ae28a,0x7da08661,0x8fcb0562,0x9c9bf696,0x6ef07595,0x417b1dbc,0xb3109ebf,0xa0406d4b,0x522bee48,0x86e18aa3,0x748a09a0,0x67dafa54,0x95b17957,0xcba24573,0x39c9c670,0x2a993584,0xd8f2b687,0xc38d26c,0xfe53516f,0xed03a29b,0x1f682198,0x5125dad3,0xa34e59d0,0xb01eaa24,0x42752927,0x96bf4dcc,0x64d4cecf,0x77843d3b,0x85efbe38,0xdbfc821c,0x2997011f,0x3ac7f2eb,0xc8ac71e8,0x1c661503,0xee0d9600,0xfd5d65f4,0xf36e6f7,0x61c69362,0x93ad1061,0x80fde395,0x72966096,0xa65c047d,0x5437877e,0x4767748a,0xb50cf789,0xeb1fcbad,0x197448ae,0xa24bb5a,0xf84f3859,0x2c855cb2,0xdeeedfb1,0xcdbe2c45,0x3fd5af46,0x7198540d,0x83f3d70e,0x90a324fa,0x62c8a7f9,0xb602c312,0x44694011,0x5739b3e5,0xa55230e6,0xfb410cc2,0x92a8fc1,0x1a7a7c35,0xe811ff36,0x3cdb9bdd,0xceb018de,0xdde0eb2a,0x2f8b6829,0x82f63b78,0x709db87b,0x63cd4b8f,0x91a6c88c,0x456cac67,0xb7072f64,0xa457dc90,0x563c5f93,0x82f63b7,0xfa44e0b4,0xe9141340,0x1b7f9043,0xcfb5f4a8,0x3dde77ab,0x2e8e845f,0xdce5075c,0x92a8fc17,0x60c37f14,0x73938ce0,0x81f80fe3,0x55326b08,0xa759e80b,0xb4091bff,0x466298fc,0x1871a4d8,0xea1a27db,0xf94ad42f,0xb21572c,0xdfeb33c7,0x2d80b0c4,0x3ed04330,0xccbbc033,0xa24bb5a6,0x502036a5,0x4370c551,0xb11b4652,0x65d122b9,0x97baa1ba,0x84ea524e,0x7681d14d,0x2892ed69,0xdaf96e6a,0xc9a99d9e,0x3bc21e9d,0xef087a76,0x1d63f975,0xe330a81,0xfc588982,0xb21572c9,0x407ef1ca,0x532e023e,0xa145813d,0x758fe5d6,0x87e466d5,0x94b49521,0x66df1622,0x38cc2a06,0xcaa7a905,0xd9f75af1,0x2b9cd9f2,0xff56bd19,0xd3d3e1a,0x1e6dcdee,0xec064eed,0xc38d26c4,0x31e6a5c7,0x22b65633,0xd0ddd530,0x417b1db,0xf67c32d8,0xe52cc12c,0x1747422f,0x49547e0b,0xbb3ffd08,0xa86f0efc,0x5a048dff,0x8ecee914,0x7ca56a17,0x6ff599e3,0x9d9e1ae0,0xd3d3e1ab,0x21b862a8,0x32e8915c,0xc083125f,0x144976b4,0xe622f5b7,0xf5720643,0x7198540,0x590ab964,0xab613a67,0xb831c993,0x4a5a4a90,0x9e902e7b,0x6cfbad78,0x7fab5e8c,0x8dc0dd8f,0xe330a81a,0x115b2b19,0x20bd8ed,0xf0605bee,0x24aa3f05,0xd6c1bc06,0xc5914ff2,0x37faccf1,0x69e9f0d5,0x9b8273d6,0x88d28022,0x7ab90321,0xae7367ca,0x5c18e4c9,0x4f48173d,0xbd23943e,0xf36e6f75,0x105ec76,0x12551f82,0xe03e9c81,0x34f4f86a,0xc69f7b69,0xd5cf889d,0x27a40b9e,0x79b737ba,0x8bdcb4b9,0x988c474d,0x6ae7c44e,0xbe2da0a5,0x4c4623a6,0x5f16d052,0xad7d5351}; + +template +inline constexpr std::uint_least32_t calculate_crc32(std::uint_least32_t crc,std::byte const* i,std::byte const* ed) noexcept +{ + if constexpr(opt==crc32_option::crc32) + { + return calculate_crc32_common(crc,i,ed,crc32_tb); + } + else + { + return calculate_crc32_common(crc,i,ed,crc32c_tb); + } +} + +template +class basic_crc32_scalar_context +{ + std::uint_least32_t crcv{0xffffffff}; +public: + static inline constexpr std::size_t digest_size{sizeof(std::uint_least32_t)}; + inline constexpr void update(std::byte const* first,std::byte const* last) noexcept + { + crcv=calculate_crc32(crcv,first,last); + } + inline constexpr void reset() noexcept + { + crcv=0xffffffff; + } + inline constexpr std::uint_least32_t digest_value() const noexcept + { + return ~crcv; + } + inline constexpr void do_final() const noexcept + {} + inline constexpr void digest_to_byte_ptr(std::byte* ptr) const noexcept + { + ::fast_io::details::crc32_to_byte_ptr_commom_impl(crcv,ptr); + } +}; +} + +using crc32_context = ::fast_io::details::basic_crc32_scalar_context<::fast_io::details::crc32_option::crc32>; +using crc32c_context = ::fast_io::details::basic_crc32_scalar_context<::fast_io::details::crc32_option::crc32c>; + +} diff --git a/src/fast_io/include/fast_io_crypto/hash/impl.h b/src/fast_io/include/fast_io_crypto/hash/impl.h new file mode 100644 index 0000000..3cf8237 --- /dev/null +++ b/src/fast_io/include/fast_io_crypto/hash/impl.h @@ -0,0 +1,7 @@ +#pragma once +#include"md5_sha_hash_context.h" +#include"md5.h" +#include"sha1.h" +#include"sha256.h" +#include"sha512.h" +#include"crc32.h" \ No newline at end of file diff --git a/src/fast_io/include/fast_io_crypto/hash/md5.h b/src/fast_io/include/fast_io_crypto/hash/md5.h new file mode 100644 index 0000000..0be4d59 --- /dev/null +++ b/src/fast_io/include/fast_io_crypto/hash/md5.h @@ -0,0 +1,409 @@ +#pragma once + +namespace fast_io::details::md5 +{ + +enum class operation +{ +F,G,H,I +}; + +template +inline constexpr auto unit(auto const x,auto const y,auto const z) noexcept +{ + if constexpr(op==operation::F) + { + if constexpr(true) + { + return (x&(y^z))^z; + } + else + { + return (x&y) + ((~x)&z); + } + } + else if constexpr(op==operation::G) + { + if constexpr(false) + { + return (z&(x^y))^y; + } + else + { + return (z&x) + ((~z)&y); + } + } + else if constexpr(op==operation::H) + return x^y^z; + else + { + return y^(x|(~z)); + } +} + +template +inline constexpr void uu(auto& a,auto b,auto c,auto d,auto x,auto s,auto ac) noexcept +{ + x+=ac; + x+=a; + x+=unit(b,c,d); + a=std::rotl(x,s)+b; +} + +template +inline constexpr void uutmp(auto& tmp,auto& a,auto b,auto d,auto x,auto s,auto ac) noexcept +{ + x+=ac; + x+=a; + if constexpr(op==operation::H) + { + tmp^=b; + x+=tmp; + tmp^=d; + } + else + { + auto t2{~b}; + d&=t2; + d^=tmp; + tmp=t2; + x+=d; + } + a=std::rotl(x,s)+b; +} + +inline +#if __cpp_lib_is_constant_evaluated >= 201811L +constexpr +#endif +void md5_main(std::uint_least32_t * __restrict state,std::byte const* __restrict block,std::byte const* __restrict ed) noexcept +{ + std::uint_least32_t a{*state},b{state[1]},c{state[2]},d{state[3]}; + + using ul32_may_alias +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = std::uint_least32_t; + + constexpr std::size_t block_size{64}; + std::uint_least32_t x[16]; + std::uint_least32_t tmp; + for(;block!=ed;block+=block_size) + { +#if __cpp_lib_is_constant_evaluated >= 201811L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if(__builtin_is_constant_evaluated()) +#endif + { + for(std::size_t j{};j!=16;++j) + { + auto dj{block+j*4}; + x[j]=(std::to_integer(*dj))|(std::to_integer(dj[1])<<8)| + (std::to_integer(dj[2])<<16)|std::to_integer(dj[3]<<24); + } + uu(a, b, c, d, x[ 0], 7, 0xd76aa478u); + uu(d, a, b, c, x[ 1], 12, 0xe8c7b756u); + uu(c, d, a, b, x[ 2], 17, 0x242070dbu); + uu(b, c, d, a, x[ 3], 22, 0xc1bdceeeu); + uu(a, b, c, d, x[ 4], 7, 0xf57c0fafu); + uu(d, a, b, c, x[ 5], 12, 0x4787c62au); + uu(c, d, a, b, x[ 6], 17, 0xa8304613u); + uu(b, c, d, a, x[ 7], 22, 0xfd469501u); + uu(a, b, c, d, x[ 8], 7, 0x698098d8u); + uu(d, a, b, c, x[ 9], 12, 0x8b44f7afu); + uu(c, d, a, b, x[10], 17, 0xffff5bb1u); + uu(b, c, d, a, x[11], 22, 0x895cd7beu); + uu(a, b, c, d, x[12], 7, 0x6b901122u); + uu(d, a, b, c, x[13], 12, 0xfd987193u); + uu(c, d, a, b, x[14], 17, 0xa679438eu); + uu(b, c, d, a, x[15], 22, 0x49b40821u); + } + else +#endif + { + ul32_may_alias const* w{reinterpret_cast(block)}; + uu(a, b, c, d, x[ 0]=little_endian(w[0]), 7, 0xd76aa478u); + uu(d, a, b, c, x[ 1]=little_endian(w[1]), 12, 0xe8c7b756u); + uu(c, d, a, b, x[ 2]=little_endian(w[2]), 17, 0x242070dbu); + uu(b, c, d, a, x[ 3]=little_endian(w[3]), 22, 0xc1bdceeeu); + uu(a, b, c, d, x[ 4]=little_endian(w[4]), 7, 0xf57c0fafu); + uu(d, a, b, c, x[ 5]=little_endian(w[5]), 12, 0x4787c62au); + uu(c, d, a, b, x[ 6]=little_endian(w[6]), 17, 0xa8304613u); + uu(b, c, d, a, x[ 7]=little_endian(w[7]), 22, 0xfd469501u); + uu(a, b, c, d, x[ 8]=little_endian(w[8]), 7, 0x698098d8u); + uu(d, a, b, c, x[ 9]=little_endian(w[9]), 12, 0x8b44f7afu); + uu(c, d, a, b, x[10]=little_endian(w[10]), 17, 0xffff5bb1u); + uu(b, c, d, a, x[11]=little_endian(w[11]), 22, 0x895cd7beu); + uu(a, b, c, d, x[12]=little_endian(w[12]), 7, 0x6b901122u); + uu(d, a, b, c, x[13]=little_endian(w[13]), 12, 0xfd987193u); + uu(c, d, a, b, x[14]=little_endian(w[14]), 17, 0xa679438eu); + uu(b, c, d, a, x[15]=little_endian(w[15]), 22, 0x49b40821u); + } + /* Round 2 */ + uu(a, b, c, d, x[ 1], 5, 0xf61e2562u); + uu(d, a, b, c, x[ 6], 9, 0xc040b340u); + uu(c, d, a, b, x[11], 14, 0x265e5a51u); + uu(b, c, d, a, x[ 0], 20, 0xe9b6c7aau); + uu(a, b, c, d, x[ 5], 5, 0xd62f105du); + uu(d, a, b, c, x[10], 9, 0x2441453u); + uu(c, d, a, b, x[15], 14, 0xd8a1e681u); + uu(b, c, d, a, x[ 4], 20, 0xe7d3fbc8u); + uu(a, b, c, d, x[ 9], 5, 0x21e1cde6u); + uu(d, a, b, c, x[14], 9, 0xc33707d6u); + uu(c, d, a, b, x[ 3], 14, 0xf4d50d87u); + uu(b, c, d, a, x[ 8], 20, 0x455a14edu); + uu(a, b, c, d, x[13], 5, 0xa9e3e905u); + uu(d, a, b, c, x[ 2], 9, 0xfcefa3f8u); + uu(c, d, a, b, x[ 7], 14, 0x676f02d9u); + uu(b, c, d, a, x[12], 20, 0x8d2a4c8au); + + /* Round 3 */ + tmp=c^d; + uutmp(tmp, a, b, d, x[ 5], 4, 0xfffa3942u); + uutmp(tmp, d, a, c, x[ 8], 11, 0x8771f681u); + uutmp(tmp, c, d, b, x[11], 16, 0x6d9d6122u); + uutmp(tmp, b, c, a, x[14], 23, 0xfde5380cu); + uutmp(tmp, a, b, d, x[ 1], 4, 0xa4beea44u); + uutmp(tmp, d, a, c, x[ 4], 11, 0x4bdecfa9u); + uutmp(tmp, c, d, b, x[ 7], 16, 0xf6bb4b60u); + uutmp(tmp, b, c, a, x[10], 23, 0xbebfbc70u); + uutmp(tmp, a, b, d, x[13], 4, 0x289b7ec6u); + uutmp(tmp, d, a, c, x[ 0], 11, 0xeaa127fau); + uutmp(tmp, c, d, b, x[ 3], 16, 0xd4ef3085u); + uutmp(tmp, b, c, a, x[ 6], 23, 0x4881d05u); + uutmp(tmp, a, b, d, x[ 9], 4, 0xd9d4d039u); + uutmp(tmp, d, a, c, x[12], 11, 0xe6db99e5u); + uutmp(tmp, c, d, b, x[15], 16, 0x1fa27cf8u); + uutmp(tmp, b, c, a, x[ 2], 23, 0xc4ac5665u); + + /* Round 4 */ + if constexpr(false) + { + tmp=~c; + uutmp(tmp, a, b, d, x[ 0], 6, 0xf4292244u); + uutmp(tmp, d, a, c, x[ 7], 10, 0x432aff97u); + uutmp(tmp, c, d, b, x[14], 15, 0xab9423a7u); + uutmp(tmp, b, c, a, x[ 5], 21, 0xfc93a039u); + uutmp(tmp, a, b, d, x[12], 6, 0x655b59c3u); + uutmp(tmp, d, a, c, x[ 3], 10, 0x8f0ccc92u); + uutmp(tmp, c, d, b, x[10], 15, 0xffeff47du); + uutmp(tmp, b, c, a, x[ 1], 21, 0x85845dd1u); + uutmp(tmp, a, b, d, x[ 8], 6, 0x6fa87e4fu); + uutmp(tmp, d, a, c, x[15], 10, 0xfe2ce6e0u); + uutmp(tmp, c, d, b, x[ 6], 15, 0xa3014314u); + uutmp(tmp, b, c, a, x[13], 21, 0x4e0811a1u); + uutmp(tmp, a, b, d, x[ 4], 6, 0xf7537e82u); + uutmp(tmp, d, a, c, x[11], 10, 0xbd3af235u); + uutmp(tmp, c, d, b, x[ 2], 15, 0x2ad7d2bbu); + uutmp(tmp, b, c, a, x[ 9], 21, 0xeb86d391u); + } + else + { + uu(a, b, c, d, x[ 0], 6, 0xf4292244u); + uu(d, a, b, c, x[ 7], 10, 0x432aff97u); + uu(c, d, a, b, x[14], 15, 0xab9423a7u); + uu(b, c, d, a, x[ 5], 21, 0xfc93a039u); + uu(a, b, c, d, x[12], 6, 0x655b59c3u); + uu(d, a, b, c, x[ 3], 10, 0x8f0ccc92u); + uu(c, d, a, b, x[10], 15, 0xffeff47du); + uu(b, c, d, a, x[ 1], 21, 0x85845dd1u); + uu(a, b, c, d, x[ 8], 6, 0x6fa87e4fu); + uu(d, a, b, c, x[15], 10, 0xfe2ce6e0u); + uu(c, d, a, b, x[ 6], 15, 0xa3014314u); + uu(b, c, d, a, x[13], 21, 0x4e0811a1u); + uu(a, b, c, d, x[ 4], 6, 0xf7537e82u); + uu(d, a, b, c, x[11], 10, 0xbd3af235u); + uu(c, d, a, b, x[ 2], 15, 0x2ad7d2bbu); + uu(b, c, d, a, x[ 9], 21, 0xeb86d391u); + } + + a=(*state+=a); + b=(state[1]+=b); + c=(state[2]+=c); + d=(state[3]+=d); + } +} + + +inline +#if __cpp_lib_is_constant_evaluated >= 201811L +constexpr +#endif +void md5_main_le(std::uint_least32_t * __restrict state,std::byte const* __restrict block,std::byte const* __restrict ed) noexcept +{ + std::uint_least32_t a{*state},b{state[1]},c{state[2]},d{state[3]}; + + using ul32_may_alias +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = std::uint_least32_t; + + constexpr std::size_t block_size{64}; + std::uint_least32_t tmp; + for(;block!=ed;block+=block_size) + { + ul32_may_alias const* x{reinterpret_cast(block)}; + + /* Round 1 */ + uu(a, b, c, d, x[ 0], 7, 0xd76aa478u); + uu(d, a, b, c, x[ 1], 12, 0xe8c7b756u); + uu(c, d, a, b, x[ 2], 17, 0x242070dbu); + uu(b, c, d, a, x[ 3], 22, 0xc1bdceeeu); + uu(a, b, c, d, x[ 4], 7, 0xf57c0fafu); + uu(d, a, b, c, x[ 5], 12, 0x4787c62au); + uu(c, d, a, b, x[ 6], 17, 0xa8304613u); + uu(b, c, d, a, x[ 7], 22, 0xfd469501u); + uu(a, b, c, d, x[ 8], 7, 0x698098d8u); + uu(d, a, b, c, x[ 9], 12, 0x8b44f7afu); + uu(c, d, a, b, x[10], 17, 0xffff5bb1u); + uu(b, c, d, a, x[11], 22, 0x895cd7beu); + uu(a, b, c, d, x[12], 7, 0x6b901122u); + uu(d, a, b, c, x[13], 12, 0xfd987193u); + uu(c, d, a, b, x[14], 17, 0xa679438eu); + uu(b, c, d, a, x[15], 22, 0x49b40821u); + + /* Round 2 */ + uu(a, b, c, d, x[ 1], 5, 0xf61e2562u); + uu(d, a, b, c, x[ 6], 9, 0xc040b340u); + uu(c, d, a, b, x[11], 14, 0x265e5a51u); + uu(b, c, d, a, x[ 0], 20, 0xe9b6c7aau); + uu(a, b, c, d, x[ 5], 5, 0xd62f105du); + uu(d, a, b, c, x[10], 9, 0x2441453u); + uu(c, d, a, b, x[15], 14, 0xd8a1e681u); + uu(b, c, d, a, x[ 4], 20, 0xe7d3fbc8u); + uu(a, b, c, d, x[ 9], 5, 0x21e1cde6u); + uu(d, a, b, c, x[14], 9, 0xc33707d6u); + uu(c, d, a, b, x[ 3], 14, 0xf4d50d87u); + uu(b, c, d, a, x[ 8], 20, 0x455a14edu); + uu(a, b, c, d, x[13], 5, 0xa9e3e905u); + uu(d, a, b, c, x[ 2], 9, 0xfcefa3f8u); + uu(c, d, a, b, x[ 7], 14, 0x676f02d9u); + uu(b, c, d, a, x[12], 20, 0x8d2a4c8au); + + /* Round 3 */ + tmp=c^d; + uutmp(tmp, a, b, d, x[ 5], 4, 0xfffa3942u); + uutmp(tmp, d, a, c, x[ 8], 11, 0x8771f681u); + uutmp(tmp, c, d, b, x[11], 16, 0x6d9d6122u); + uutmp(tmp, b, c, a, x[14], 23, 0xfde5380cu); + uutmp(tmp, a, b, d, x[ 1], 4, 0xa4beea44u); + uutmp(tmp, d, a, c, x[ 4], 11, 0x4bdecfa9u); + uutmp(tmp, c, d, b, x[ 7], 16, 0xf6bb4b60u); + uutmp(tmp, b, c, a, x[10], 23, 0xbebfbc70u); + uutmp(tmp, a, b, d, x[13], 4, 0x289b7ec6u); + uutmp(tmp, d, a, c, x[ 0], 11, 0xeaa127fau); + uutmp(tmp, c, d, b, x[ 3], 16, 0xd4ef3085u); + uutmp(tmp, b, c, a, x[ 6], 23, 0x4881d05u); + uutmp(tmp, a, b, d, x[ 9], 4, 0xd9d4d039u); + uutmp(tmp, d, a, c, x[12], 11, 0xe6db99e5u); + uutmp(tmp, c, d, b, x[15], 16, 0x1fa27cf8u); + uutmp(tmp, b, c, a, x[ 2], 23, 0xc4ac5665u); + + /* Round 4 */ + if constexpr(false) + { + tmp=~c; + uutmp(tmp, a, b, d, x[ 0], 6, 0xf4292244u); + uutmp(tmp, d, a, c, x[ 7], 10, 0x432aff97u); + uutmp(tmp, c, d, b, x[14], 15, 0xab9423a7u); + uutmp(tmp, b, c, a, x[ 5], 21, 0xfc93a039u); + uutmp(tmp, a, b, d, x[12], 6, 0x655b59c3u); + uutmp(tmp, d, a, c, x[ 3], 10, 0x8f0ccc92u); + uutmp(tmp, c, d, b, x[10], 15, 0xffeff47du); + uutmp(tmp, b, c, a, x[ 1], 21, 0x85845dd1u); + uutmp(tmp, a, b, d, x[ 8], 6, 0x6fa87e4fu); + uutmp(tmp, d, a, c, x[15], 10, 0xfe2ce6e0u); + uutmp(tmp, c, d, b, x[ 6], 15, 0xa3014314u); + uutmp(tmp, b, c, a, x[13], 21, 0x4e0811a1u); + uutmp(tmp, a, b, d, x[ 4], 6, 0xf7537e82u); + uutmp(tmp, d, a, c, x[11], 10, 0xbd3af235u); + uutmp(tmp, c, d, b, x[ 2], 15, 0x2ad7d2bbu); + uutmp(tmp, b, c, a, x[ 9], 21, 0xeb86d391u); + } + else + { + uu(a, b, c, d, x[ 0], 6, 0xf4292244u); + uu(d, a, b, c, x[ 7], 10, 0x432aff97u); + uu(c, d, a, b, x[14], 15, 0xab9423a7u); + uu(b, c, d, a, x[ 5], 21, 0xfc93a039u); + uu(a, b, c, d, x[12], 6, 0x655b59c3u); + uu(d, a, b, c, x[ 3], 10, 0x8f0ccc92u); + uu(c, d, a, b, x[10], 15, 0xffeff47du); + uu(b, c, d, a, x[ 1], 21, 0x85845dd1u); + uu(a, b, c, d, x[ 8], 6, 0x6fa87e4fu); + uu(d, a, b, c, x[15], 10, 0xfe2ce6e0u); + uu(c, d, a, b, x[ 6], 15, 0xa3014314u); + uu(b, c, d, a, x[13], 21, 0x4e0811a1u); + uu(a, b, c, d, x[ 4], 6, 0xf7537e82u); + uu(d, a, b, c, x[11], 10, 0xbd3af235u); + uu(c, d, a, b, x[ 2], 15, 0x2ad7d2bbu); + uu(b, c, d, a, x[ 9], 21, 0xeb86d391u); + } + a=(*state+=a); + b=(state[1]+=b); + c=(state[2]+=c); + d=(state[3]+=d); + } +} + +class md5 +{ +public: + using state_value_type = std::uint_least32_t; + static inline constexpr std::size_t block_size{64}; + static inline constexpr std::endian hash_endian{std::endian::little}; + static inline constexpr std::size_t state_size{4}; + state_value_type state[state_size]; +#if __cpp_lib_is_constant_evaluated >= 201811L + constexpr +#endif + void update_blocks(std::byte const* block_start,std::byte const* block_last) noexcept + { +#if __cpp_lib_is_constant_evaluated >= 201811L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if(__builtin_is_constant_evaluated()) +#endif + { + ::fast_io::details::md5::md5_main(this->state,block_start,block_last); + } + else +#endif + { + if constexpr(std::endian::native==std::endian::little) + { + ::fast_io::details::md5::md5_main_le(this->state,block_start,block_last); + } + else + { + ::fast_io::details::md5::md5_main(this->state,block_start,block_last); + } + } + } +}; + +struct md5_initializer +{ + static inline constexpr std::size_t digest_size{16}; + static inline constexpr ::fast_io::details::md5::md5 initialize_value{{0x67452301,0xefcdab89,0x98badcfe,0x10325476}}; + static inline constexpr void digest_to_byte_ptr(std::uint_least32_t const* digest,std::byte* ptr) noexcept + { + hash_digest_to_byte_ptr_common<::std::uint_least32_t,digest_size,std::endian::little>(digest,ptr); + } +}; + +} + +namespace fast_io +{ +using md5_context +#ifndef FAST_IO_NO_WARNING_DEPRECATED_CRYPTO_ALGOS +[[deprecated("The weaknesses of MD5 have been exploited in the field, most infamously by the Flame malware in 2012. See wikipedia https://en.wikipedia.org/wiki/MD5")]] +#endif += ::fast_io::details::basic_md5_sha_context_impl<::fast_io::details::md5::md5,::fast_io::details::md5::md5_initializer,64>; +} diff --git a/src/fast_io/include/fast_io_crypto/hash/md5_sha_hash_context.h b/src/fast_io/include/fast_io_crypto/hash/md5_sha_hash_context.h new file mode 100644 index 0000000..ad1b709 --- /dev/null +++ b/src/fast_io/include/fast_io_crypto/hash/md5_sha_hash_context.h @@ -0,0 +1,313 @@ +#pragma once + +namespace fast_io::details +{ + +struct pesudo_uint_least128_little_endian_t +{ + std::uint_least64_t low{},high{}; +}; + +struct pesudo_uint_least128_big_endian_t +{ + std::uint_least64_t high{},low{}; +}; + +using pesudo_uint_least128_t=std::conditional_t<::std::endian::native==::std::endian::big,pesudo_uint_least128_big_endian_t,pesudo_uint_least128_little_endian_t>; + +template +requires (counterbits==64||counterbits==128) +struct md5_sha_common_impl +{ + static inline constexpr std::size_t block_size{T::block_size}; + static inline constexpr std::endian hash_endian{T::hash_endian}; + using counter_type = std::conditional_t; + T hasher; + counter_type counter; + std::size_t buffer_offset; + std::byte buffer[block_size]; + constexpr void update_impl(std::byte const* first,std::size_t blocks_bytes) noexcept + { + this->hasher.update_blocks(first,first+blocks_bytes); + if constexpr(std::same_as) + { + static_assert(sizeof(std::size_t)<=sizeof(std::uint_least64_t)); + std::uint_least64_t const blocks_bytes_u64{static_cast(blocks_bytes)}; + using namespace ::fast_io::details::intrinsics; + constexpr std::uint_least64_t zero{}; + add_carry(add_carry(false,counter.low,blocks_bytes_u64,counter.low),counter.high,zero,counter.high); + } + else + { + counter+=static_cast(blocks_bytes); + } + } + constexpr void update_cold_impl(std::byte const* first,std::size_t diff) noexcept + { + std::size_t const buffer_space{static_cast(buffer_offset)}; + std::size_t const buffer_remain_space{static_cast(block_size-buffer_offset)}; + if(buffer_remain_space!=block_size) + { + ::fast_io::details::non_overlapped_copy_n(first,buffer_remain_space,buffer+buffer_space); + diff-=buffer_remain_space; + first+=buffer_remain_space; + this->update_impl(buffer,block_size); + } + std::size_t const blocks_bytes{(diff/block_size)*block_size}; + this->update_impl(first,blocks_bytes); + first+=blocks_bytes; + diff-=blocks_bytes; + ::fast_io::details::non_overlapped_copy_n(first,diff,buffer); + buffer_offset=diff; + } +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && __cpp_lib_bit_cast >= 201806L + constexpr +#endif + void append_sentinal(std::size_t final_block_offset) noexcept + { + counter_type ct{counter}; + std::uint_least64_t const val{static_cast(final_block_offset)}; + if constexpr(std::same_as) + { + using namespace ::fast_io::details::intrinsics; + constexpr std::uint_least64_t zero{}; + add_carry(add_carry(false,ct.low,val,ct.low),ct.high,zero,ct.high); + add_carry(add_carry(false,ct.low,ct.low,ct.low),ct.high,ct.high,ct.high);//*2 + add_carry(add_carry(false,ct.low,ct.low,ct.low),ct.high,ct.high,ct.high);//*4 + add_carry(add_carry(false,ct.low,ct.low,ct.low),ct.high,ct.high,ct.high);//*8 + } + else + { + ct+=val; + ct*=8u; + } + if constexpr(std::endian::native!=hash_endian) + { + if constexpr(std::same_as) + { + auto t{::fast_io::byte_swap(ct.low)}; + ct.low=::fast_io::byte_swap(ct.high); + ct.high=t; + } + else + { + ct=::fast_io::byte_swap(ct); + } + } + constexpr std::size_t start_pos{block_size-sizeof(counter_type)}; + ::fast_io::freestanding::type_punning_to_bytes(ct,buffer+start_pos); + this->hasher.update_blocks(buffer,buffer+block_size); + } + inline constexpr void update(std::byte const* block_first,std::byte const* block_last) noexcept + { + std::size_t const diff{static_cast(block_last-block_first)}; + std::size_t const buffer_remain_space{static_cast(block_size-buffer_offset)}; + if(diff=block_size) + __builtin_unreachable(); +#endif +#endif + ::fast_io::details::non_overlapped_copy_n(block_first,diff,buffer+buffer_offset); + buffer_offset+=diff; + } + else + { + this->update_cold_impl(block_first,diff); + } + } + +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && __cpp_lib_bit_cast >= 201806L + constexpr +#endif + void do_final() noexcept + { + constexpr std::size_t counter_type_size{sizeof(counter)}; + constexpr std::size_t sz{block_size-counter_type_size}; + std::size_t const buffer_offs{this->buffer_offset}; + std::size_t buffer_off{buffer_offs}; + buffer[buffer_off]=std::byte{0x80}; + ++buffer_off; + if(buffer_off<=sz) + { + std::size_t const to_fill{static_cast(sz-buffer_off)}; +#if defined(__has_builtin) +#if __has_builtin(__builtin_unreachable) + if(to_fill>sz) + __builtin_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(block_size-buffer_off)}; +#if defined(__has_builtin) +#if __has_builtin(__builtin_unreachable) + if(to_fill>counter_type_size) + __builtin_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); + this->append_sentinal(buffer_offs); + } +}; + +template +class basic_md5_sha_context_impl +{ + md5_sha_common_impl hasher; +public: + explicit constexpr basic_md5_sha_context_impl() noexcept + { + this->reset(); + } + static inline constexpr std::size_t digest_size{initializer::digest_size}; + constexpr void update(std::byte const* block_first,std::byte const* block_last) noexcept + { + hasher.update(block_first,block_last); + } + constexpr void reset() noexcept + { + hasher.hasher=initializer::initialize_value; + hasher.counter={}; + hasher.buffer_offset=0; + } + constexpr void do_final() noexcept + { + hasher.do_final(); + } + constexpr void digest_to_byte_ptr(std::byte* digest) const noexcept + { + initializer::digest_to_byte_ptr(hasher.hasher.state,digest); + } +}; + +template +inline +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L +constexpr +#endif +void hash_digest_to_byte_ptr_common_impl(U const* digest,std::size_t n,std::byte* ptr) noexcept +{ + constexpr std::size_t usz{sizeof(U)}; +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if(__builtin_is_constant_evaluated()) +#endif + { + for(std::size_t i{};i!=n;++i) + { + U v{digest[i]}; + if constexpr(::std::endian::native==end) + { + v=::fast_io::byte_swap(v); + } + ::fast_io::freestanding::array<::std::byte,usz> va{::fast_io::bit_cast<::fast_io::freestanding::array<::std::byte,usz>>(digest[i])}; + ptr=::fast_io::freestanding::nonoverlapped_bytes_copy_n(va.data(),usz,ptr); + } + } + else +#endif + { + if constexpr(::std::endian::native==end) + { + ::fast_io::details::my_memcpy(ptr,digest,n*sizeof(U)); + } + else + { + for(std::size_t i{};i!=n;++i) + { + auto v{::fast_io::byte_swap(digest[i])}; + ::fast_io::details::my_memcpy(ptr,__builtin_addressof(v),usz); + ptr+=usz; + } + } + } +} + + +#if (!defined(_MSC_VER) || defined(__clang__)) && (defined(__SSE4_2__) || defined(__wasm_simd128__)) + +template +inline constexpr void hash_digest_to_byte_ptr_simd16_impl(U const* digest,std::size_t n,std::byte* ptr) noexcept +{ + constexpr std::size_t usz{sizeof(U)}; +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if(__builtin_is_constant_evaluated()) +#endif + { + hash_digest_to_byte_ptr_common_impl(digest,n,ptr); + } + else +#endif + { + if constexpr(::std::endian::native==end) + { + ::fast_io::details::my_memcpy(ptr,digest,n*sizeof(U)); + } + else + { + constexpr std::size_t sixteen{16u}; + constexpr std::size_t factor{sixteen/usz}; + static_assert(sixteen%usz==0&&usz!=sixteen); + ::fast_io::intrinsics::simd_vector s; + std::byte const* i{reinterpret_cast(digest)}; + std::byte const* e{reinterpret_cast(digest+n)}; + for(;i!=e;i+=sixteen) + { + s.load(i); + s.swap_endian(); + s.store(ptr); + ptr+=sixteen; + } + } + } +} +#endif + +template +inline constexpr void hash_digest_to_byte_ptr_common(digest_value_type const* digest,std::byte* ptr) noexcept +{ + constexpr std::size_t sz{digest_size/sizeof(digest_value_type)}; + static_assert(sz!=0); +#if (!defined(_MSC_VER) || defined(__clang__)) && (defined(__SSE4_2__) || defined(__wasm_simd128__)) + if constexpr(sz%16u==0) + { + hash_digest_to_byte_ptr_simd16_impl(digest,sz,ptr); + } + else +#endif + { + hash_digest_to_byte_ptr_common_impl(digest,sz,ptr); + } + constexpr std::size_t remainder{digest_size%sizeof(digest_value_type)}; + if constexpr(remainder!=0) + { + constexpr std::size_t szmul{sz*sizeof(digest_value_type)}; + ptr+=szmul; + digest_value_type v{digest[sz]}; + if constexpr(end!=std::endian::native) + { + v=::fast_io::byte_swap(v); + } + ::fast_io::freestanding::type_punning_to_bytes_n(v,ptr); + } +} + +} diff --git a/src/fast_io/include/fast_io_crypto/hash/sha1.h b/src/fast_io/include/fast_io_crypto/hash/sha1.h new file mode 100644 index 0000000..cb5a05f --- /dev/null +++ b/src/fast_io/include/fast_io_crypto/hash/sha1.h @@ -0,0 +1,767 @@ +#pragma once + +namespace fast_io::details::sha1 +{ +//from https://github.com/vog/sha1/blob/master/sha1.cpp +inline constexpr std::uint_least32_t blk(std::uint_least32_t* __restrict block,std::size_t const i) noexcept +{ + return std::rotl(block[(i+13)&15] ^ block[(i+8)&15] ^ block[(i+2)&15] ^ block[i], 1); +} + +inline constexpr void R0(std::uint_least32_t* __restrict block, std::uint_least32_t const v, std::uint_least32_t &w, std::uint_least32_t const x, std::uint_least32_t const y, std::uint_least32_t &z, std::size_t i) noexcept +{ + z += ((w&(x^y))^y) + block[i] + 0x5a827999 + std::rotl(v, 5); + w = std::rotl(w, 30); +} + +inline constexpr void R1(std::uint_least32_t* __restrict block, std::uint_least32_t const v, std::uint_least32_t &w, std::uint_least32_t const x, std::uint_least32_t const y, std::uint_least32_t &z, std::size_t i) noexcept +{ + block[i] = blk(block, i); + z += ((w&(x^y))^y) + block[i] + 0x5a827999 + std::rotl(v, 5); + w = std::rotl(w, 30); +} + + +inline constexpr void R2(std::uint_least32_t* __restrict block, std::uint_least32_t const v, std::uint_least32_t &w, std::uint_least32_t const x, std::uint_least32_t const y, std::uint_least32_t &z, std::size_t i) noexcept +{ + block[i] = blk(block, i); + z += (w^x^y) + block[i] + 0x6ed9eba1 + std::rotl(v, 5); + w = std::rotl(w, 30); +} + + +inline constexpr void R3(std::uint_least32_t* __restrict block, std::uint_least32_t const v, std::uint_least32_t &w, std::uint_least32_t const x, std::uint_least32_t const y, std::uint_least32_t &z, std::size_t i) noexcept +{ + block[i] = blk(block, i); + z += (((w|x)&y)|(w&x)) + block[i] + 0x8f1bbcdc + std::rotl(v, 5); + w = std::rotl(w, 30); +} + + +inline constexpr void R4(std::uint_least32_t* __restrict block, std::uint_least32_t const v, std::uint_least32_t &w, std::uint_least32_t const x, std::uint_least32_t const y, std::uint_least32_t &z, std::size_t i) noexcept +{ + block[i] = blk(block, i); + z += (w^x^y) + block[i] + 0xca62c1d6 + std::rotl(v, 5); + w = std::rotl(w, 30); +} + + +inline +#if __cpp_lib_is_constant_evaluated >= 201811L +constexpr +#endif +void sha1_do_constexpr_function(std::uint_least32_t* __restrict state,std::byte const* __restrict blocks_start,std::size_t blocks_bytes) noexcept +{ + std::uint_least32_t a{state[0]}, b{state[1]}, c{state[2]}, d{state[3]}, e{state[4]}; + std::uint_least32_t X[16]; + constexpr std::size_t block_size{64}; + for(std::byte const* data(blocks_start),*ed(blocks_start+blocks_bytes);data!=ed;data+=block_size) + { +#if __cpp_lib_is_constant_evaluated >= 201811L + if(std::is_constant_evaluated()) + { + for(std::size_t j{};j!=16;++j) + { + auto dj{data+j*4}; + X[j]=(std::to_integer(*dj)<<24)|(std::to_integer(dj[1])<<16)| + (std::to_integer(dj[2])<<8)|std::to_integer(dj[3]); + } + } + else +#endif + { + my_memcpy(X,data,block_size); + if constexpr(std::endian::big!=std::endian::native) + { + for(auto& ele : X) + ele=big_endian(ele); + } + } + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(X, a, b, c, d, e, 0); + R0(X, e, a, b, c, d, 1); + R0(X, d, e, a, b, c, 2); + R0(X, c, d, e, a, b, 3); + R0(X, b, c, d, e, a, 4); + R0(X, a, b, c, d, e, 5); + R0(X, e, a, b, c, d, 6); + R0(X, d, e, a, b, c, 7); + R0(X, c, d, e, a, b, 8); + R0(X, b, c, d, e, a, 9); + R0(X, a, b, c, d, e, 10); + R0(X, e, a, b, c, d, 11); + R0(X, d, e, a, b, c, 12); + R0(X, c, d, e, a, b, 13); + R0(X, b, c, d, e, a, 14); + R0(X, a, b, c, d, e, 15); + R1(X, e, a, b, c, d, 0); + R1(X, d, e, a, b, c, 1); + R1(X, c, d, e, a, b, 2); + R1(X, b, c, d, e, a, 3); + R2(X, a, b, c, d, e, 4); + R2(X, e, a, b, c, d, 5); + R2(X, d, e, a, b, c, 6); + R2(X, c, d, e, a, b, 7); + R2(X, b, c, d, e, a, 8); + R2(X, a, b, c, d, e, 9); + R2(X, e, a, b, c, d, 10); + R2(X, d, e, a, b, c, 11); + R2(X, c, d, e, a, b, 12); + R2(X, b, c, d, e, a, 13); + R2(X, a, b, c, d, e, 14); + R2(X, e, a, b, c, d, 15); + R2(X, d, e, a, b, c, 0); + R2(X, c, d, e, a, b, 1); + R2(X, b, c, d, e, a, 2); + R2(X, a, b, c, d, e, 3); + R2(X, e, a, b, c, d, 4); + R2(X, d, e, a, b, c, 5); + R2(X, c, d, e, a, b, 6); + R2(X, b, c, d, e, a, 7); + R3(X, a, b, c, d, e, 8); + R3(X, e, a, b, c, d, 9); + R3(X, d, e, a, b, c, 10); + R3(X, c, d, e, a, b, 11); + R3(X, b, c, d, e, a, 12); + R3(X, a, b, c, d, e, 13); + R3(X, e, a, b, c, d, 14); + R3(X, d, e, a, b, c, 15); + R3(X, c, d, e, a, b, 0); + R3(X, b, c, d, e, a, 1); + R3(X, a, b, c, d, e, 2); + R3(X, e, a, b, c, d, 3); + R3(X, d, e, a, b, c, 4); + R3(X, c, d, e, a, b, 5); + R3(X, b, c, d, e, a, 6); + R3(X, a, b, c, d, e, 7); + R3(X, e, a, b, c, d, 8); + R3(X, d, e, a, b, c, 9); + R3(X, c, d, e, a, b, 10); + R3(X, b, c, d, e, a, 11); + R4(X, a, b, c, d, e, 12); + R4(X, e, a, b, c, d, 13); + R4(X, d, e, a, b, c, 14); + R4(X, c, d, e, a, b, 15); + R4(X, b, c, d, e, a, 0); + R4(X, a, b, c, d, e, 1); + R4(X, e, a, b, c, d, 2); + R4(X, d, e, a, b, c, 3); + R4(X, c, d, e, a, b, 4); + R4(X, b, c, d, e, a, 5); + R4(X, a, b, c, d, e, 6); + R4(X, e, a, b, c, d, 7); + R4(X, d, e, a, b, c, 8); + R4(X, c, d, e, a, b, 9); + R4(X, b, c, d, e, a, 10); + R4(X, a, b, c, d, e, 11); + R4(X, e, a, b, c, d, 12); + R4(X, d, e, a, b, c, 13); + R4(X, c, d, e, a, b, 14); + R4(X, b, c, d, e, a, 15); + + /* Add the working vars back into state[] */ + a=(state[0] += a); + b=(state[1] += b); + c=(state[2] += c); + d=(state[3] += d); + e=(state[4] += e); + } +} + +#if defined(FAST_IO_ARM_SHA) && ( defined(__arm__) || defined(__aarch32__) || defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM) ) +inline void sha1_arm_function(std::uint_least32_t* __restrict state,std::byte const* __restrict blocks_start,std::size_t blocks_bytes) noexcept +{ + uint32x4_t ABCD, ABCD_SAVED; + uint32x4_t TMP0, TMP1; + uint32x4_t MSG0, MSG1, MSG2, MSG3; + uint_least32_t E0, E0_SAVED, E1; + + ABCD = vld1q_u32(state); + + for(auto data(blocks),ed(blocks+blocks_bytes);data!=ed;data+=block_size) + { + ABCD_SAVED = ABCD; + E0_SAVED = E0; + + /* Load message */ + MSG0 = vld1q_u32(reinterpret_cast(data + 0)); + MSG1 = vld1q_u32(reinterpret_cast(data + 16)); + MSG2 = vld1q_u32(reinterpret_cast(data + 32)); + MSG3 = vld1q_u32(reinterpret_cast(data + 48)); + + /* Reverse for little endian */ + MSG0 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(MSG0))); + MSG1 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(MSG1))); + MSG2 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(MSG2))); + MSG3 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(MSG3))); + + TMP0 = vaddq_u32(MSG0, vdupq_n_u32(0x5A827999)); + TMP1 = vaddq_u32(MSG1, vdupq_n_u32(0x5A827999)); + + /* Rounds 0-3 */ + E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1cq_u32(ABCD, E0, TMP0); + TMP0 = vaddq_u32(MSG2, vdupq_n_u32(0x5A827999)); + MSG0 = vsha1su0q_u32(MSG0, MSG1, MSG2); + + /* Rounds 4-7 */ + E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1cq_u32(ABCD, E1, TMP1); + TMP1 = vaddq_u32(MSG3, vdupq_n_u32(0x5A827999)); + MSG0 = vsha1su1q_u32(MSG0, MSG3); + MSG1 = vsha1su0q_u32(MSG1, MSG2, MSG3); + + /* Rounds 8-11 */ + E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1cq_u32(ABCD, E0, TMP0); + TMP0 = vaddq_u32(MSG0, vdupq_n_u32(0x5A827999)); + MSG1 = vsha1su1q_u32(MSG1, MSG0); + MSG2 = vsha1su0q_u32(MSG2, MSG3, MSG0); + + /* Rounds 12-15 */ + E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1cq_u32(ABCD, E1, TMP1); + TMP1 = vaddq_u32(MSG1, vdupq_n_u32(0x6ED9EBA1)); + MSG2 = vsha1su1q_u32(MSG2, MSG1); + MSG3 = vsha1su0q_u32(MSG3, MSG0, MSG1); + + /* Rounds 16-19 */ + E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1cq_u32(ABCD, E0, TMP0); + TMP0 = vaddq_u32(MSG2, vdupq_n_u32(0x6ED9EBA1)); + MSG3 = vsha1su1q_u32(MSG3, MSG2); + MSG0 = vsha1su0q_u32(MSG0, MSG1, MSG2); + + /* Rounds 20-23 */ + E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1pq_u32(ABCD, E1, TMP1); + TMP1 = vaddq_u32(MSG3, vdupq_n_u32(0x6ED9EBA1)); + MSG0 = vsha1su1q_u32(MSG0, MSG3); + MSG1 = vsha1su0q_u32(MSG1, MSG2, MSG3); + + /* Rounds 24-27 */ + E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1pq_u32(ABCD, E0, TMP0); + TMP0 = vaddq_u32(MSG0, vdupq_n_u32(0x6ED9EBA1)); + MSG1 = vsha1su1q_u32(MSG1, MSG0); + MSG2 = vsha1su0q_u32(MSG2, MSG3, MSG0); + + /* Rounds 28-31 */ + E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1pq_u32(ABCD, E1, TMP1); + TMP1 = vaddq_u32(MSG1, vdupq_n_u32(0x6ED9EBA1)); + MSG2 = vsha1su1q_u32(MSG2, MSG1); + MSG3 = vsha1su0q_u32(MSG3, MSG0, MSG1); + + /* Rounds 32-35 */ + E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1pq_u32(ABCD, E0, TMP0); + TMP0 = vaddq_u32(MSG2, vdupq_n_u32(0x8F1BBCDC)); + MSG3 = vsha1su1q_u32(MSG3, MSG2); + MSG0 = vsha1su0q_u32(MSG0, MSG1, MSG2); + + /* Rounds 36-39 */ + E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1pq_u32(ABCD, E1, TMP1); + TMP1 = vaddq_u32(MSG3, vdupq_n_u32(0x8F1BBCDC)); + MSG0 = vsha1su1q_u32(MSG0, MSG3); + MSG1 = vsha1su0q_u32(MSG1, MSG2, MSG3); + + /* Rounds 40-43 */ + E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1mq_u32(ABCD, E0, TMP0); + TMP0 = vaddq_u32(MSG0, vdupq_n_u32(0x8F1BBCDC)); + MSG1 = vsha1su1q_u32(MSG1, MSG0); + MSG2 = vsha1su0q_u32(MSG2, MSG3, MSG0); + + /* Rounds 44-47 */ + E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1mq_u32(ABCD, E1, TMP1); + TMP1 = vaddq_u32(MSG1, vdupq_n_u32(0x8F1BBCDC)); + MSG2 = vsha1su1q_u32(MSG2, MSG1); + MSG3 = vsha1su0q_u32(MSG3, MSG0, MSG1); + + /* Rounds 48-51 */ + E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1mq_u32(ABCD, E0, TMP0); + TMP0 = vaddq_u32(MSG2, vdupq_n_u32(0x8F1BBCDC)); + MSG3 = vsha1su1q_u32(MSG3, MSG2); + MSG0 = vsha1su0q_u32(MSG0, MSG1, MSG2); + + /* Rounds 52-55 */ + E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1mq_u32(ABCD, E1, TMP1); + TMP1 = vaddq_u32(MSG3, vdupq_n_u32(0xCA62C1D6)); + MSG0 = vsha1su1q_u32(MSG0, MSG3); + MSG1 = vsha1su0q_u32(MSG1, MSG2, MSG3); + + /* Rounds 56-59 */ + E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1mq_u32(ABCD, E0, TMP0); + TMP0 = vaddq_u32(MSG0, vdupq_n_u32(0xCA62C1D6)); + MSG1 = vsha1su1q_u32(MSG1, MSG0); + MSG2 = vsha1su0q_u32(MSG2, MSG3, MSG0); + + /* Rounds 60-63 */ + E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1pq_u32(ABCD, E1, TMP1); + TMP1 = vaddq_u32(MSG1, vdupq_n_u32(0xCA62C1D6)); + MSG2 = vsha1su1q_u32(MSG2, MSG1); + MSG3 = vsha1su0q_u32(MSG3, MSG0, MSG1); + + /* Rounds 64-67 */ + E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1pq_u32(ABCD, E0, TMP0); + TMP0 = vaddq_u32(MSG2, vdupq_n_u32(0xCA62C1D6)); + MSG3 = vsha1su1q_u32(MSG3, MSG2); + MSG0 = vsha1su0q_u32(MSG0, MSG1, MSG2); + + /* Rounds 68-71 */ + E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1pq_u32(ABCD, E1, TMP1); + TMP1 = vaddq_u32(MSG3, vdupq_n_u32(0xCA62C1D6)); + MSG0 = vsha1su1q_u32(MSG0, MSG3); + + /* Rounds 72-75 */ + E1 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1pq_u32(ABCD, E0, TMP0); + + /* Rounds 76-79 */ + E0 = vsha1h_u32(vgetq_lane_u32(ABCD, 0)); + ABCD = vsha1pq_u32(ABCD, E1, TMP1); + + /* Combine state */ + E0 += E0_SAVED; + ABCD = vaddq_u32(ABCD_SAVED, ABCD); + } + vst1q_u32(state, ABCD); + state[4] = E0; +} +#endif + +inline void sha1_do_function(std::uint_least32_t* __restrict state,std::byte const* __restrict blocks_start,std::size_t blocks_bytes) noexcept +{ + [[maybe_unused]] constexpr std::size_t block_size{64}; +#if defined(__has_builtin) +#if __has_builtin(__builtin_ia32_sha1rnds4)&& \ +__has_builtin(__builtin_ia32_sha1nexte)&& \ +__has_builtin(__builtin_ia32_sha1msg1) && \ +__has_builtin(__builtin_ia32_pshufb128) && (!defined(__clang__)||(defined(__SSE4_2__)&&defined(__SHA__))) + using namespace ::fast_io::intrinsics; + constexpr simd_vector mask{15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0}; + simd_vector abcdstate{static_cast(state[3]),static_cast(state[2]), + static_cast(state[1]),static_cast(*state)}; + simd_vector estate{0,0,0,static_cast(state[4])}; + simd_vector abcd=abcdstate; + simd_vector e0=estate; + simd_vector msg0,msg1,msg2,msg3; + for(auto block(blocks_start),ed(blocks_start+blocks_bytes);block!=ed;block+=block_size) + { + // Rounds 0-3 + msg0.load(block); + msg0.shuffle(mask); + e0.wrap_add_assign(msg0); + simd_vector e1=abcd; + abcd = __builtin_ia32_sha1rnds4(abcd,e0,0); + + // Rounds 4-7 + msg1.load(block+16); + msg1.shuffle(mask); + e1 = __builtin_ia32_sha1nexte(e1,msg1); + e0 = abcd; + abcd = __builtin_ia32_sha1rnds4(abcd,e1,0); + msg0 = __builtin_ia32_sha1msg1(msg0,msg1); + + // Rounds 8-11 + msg2.load(block+32); + msg2.shuffle(mask); + e0 = __builtin_ia32_sha1nexte(e0,msg2); + e1 = abcd; + abcd = __builtin_ia32_sha1rnds4(abcd,e0,0); + msg1 = __builtin_ia32_sha1msg1(msg1,msg2); + msg0^=msg2; + + // Rounds 12-15 + msg3.load(block+48); + msg3.shuffle(mask); + e1 = __builtin_ia32_sha1nexte(e1,msg3); + e0 = abcd; + msg0 = __builtin_ia32_sha1msg2(msg0,msg3); + abcd = __builtin_ia32_sha1rnds4(abcd,e1,0); + msg2 = __builtin_ia32_sha1msg1(msg2,msg3); + msg1^=msg3; + + // Rounds 16-19 + e0 = __builtin_ia32_sha1nexte(e0,msg0); + e1 = abcd; + msg1 = __builtin_ia32_sha1msg2(msg1,msg0); + abcd = __builtin_ia32_sha1rnds4(abcd,e0,0); + msg3 = __builtin_ia32_sha1msg1(msg3,msg0); + msg2^=msg0; + + // Rounds 20-23 + e1 = __builtin_ia32_sha1nexte(e1,msg1); + e0 = abcd; + msg2 = __builtin_ia32_sha1msg2(msg2,msg1); + abcd = __builtin_ia32_sha1rnds4(abcd,e1,1); + msg0 = __builtin_ia32_sha1msg1(msg0,msg1); + msg3^=msg1; + + // Rounds 24-27 + e0 = __builtin_ia32_sha1nexte(e0,msg2); + e1 = abcd; + msg3 = __builtin_ia32_sha1msg2(msg3,msg2); + abcd = __builtin_ia32_sha1rnds4(abcd,e0,1); + msg1 = __builtin_ia32_sha1msg1(msg1,msg2); + msg0^=msg2; + + // Rounds 28-31 + e1 = __builtin_ia32_sha1nexte(e1,msg3); + e0 = abcd; + msg0 = __builtin_ia32_sha1msg2(msg0,msg3); + abcd = __builtin_ia32_sha1rnds4(abcd,e1,1); + msg2 = __builtin_ia32_sha1msg1(msg2,msg3); + msg1^=msg3; + + // Rounds 32-35 + e0 = __builtin_ia32_sha1nexte(e0,msg0); + e1 = abcd; + msg1 = __builtin_ia32_sha1msg2(msg1,msg0); + abcd = __builtin_ia32_sha1rnds4(abcd,e0,1); + msg3 = __builtin_ia32_sha1msg1(msg3,msg0); + msg2^=msg0; + + // Rounds 36-39 + e1 = __builtin_ia32_sha1nexte(e1,msg1); + e0 = abcd; + msg2 = __builtin_ia32_sha1msg2(msg2,msg1); + abcd = __builtin_ia32_sha1rnds4(abcd,e1,1); + msg0 = __builtin_ia32_sha1msg1(msg0,msg1); + msg3^=msg1; + + // Rounds 40-43 + e0 = __builtin_ia32_sha1nexte(e0,msg2); + e1 = abcd; + msg3 = __builtin_ia32_sha1msg2(msg3,msg2); + abcd = __builtin_ia32_sha1rnds4(abcd,e0,2); + msg1 = __builtin_ia32_sha1msg1(msg1,msg2); + msg0^=msg2; + + // Rounds 44-47 + e1 = __builtin_ia32_sha1nexte(e1,msg3); + e0 = abcd; + msg0 = __builtin_ia32_sha1msg2(msg0,msg3); + abcd = __builtin_ia32_sha1rnds4(abcd,e1,2); + msg2 = __builtin_ia32_sha1msg1(msg2,msg3); + msg1^=msg3; + + // Rounds 48-51 + e0 = __builtin_ia32_sha1nexte(e0,msg0); + e1 = abcd; + msg1 = __builtin_ia32_sha1msg2(msg1,msg0); + abcd = __builtin_ia32_sha1rnds4(abcd,e0,2); + msg3 = __builtin_ia32_sha1msg1(msg3,msg0); + msg2^=msg0; + + // Rounds 52-55 + e1 = __builtin_ia32_sha1nexte(e1,msg1); + e0 = abcd; + msg2 = __builtin_ia32_sha1msg2(msg2,msg1); + abcd = __builtin_ia32_sha1rnds4(abcd,e1,2); + msg0 = __builtin_ia32_sha1msg1(msg0,msg1); + msg3^=msg1; + + // Rounds 56-59 + e0 = __builtin_ia32_sha1nexte(e0,msg2); + e1 = abcd; + msg3 = __builtin_ia32_sha1msg2(msg3,msg2); + abcd = __builtin_ia32_sha1rnds4(abcd,e0,2); + msg1 = __builtin_ia32_sha1msg1(msg1,msg2); + msg0^=msg2; + + // Rounds 60-63 + e1 = __builtin_ia32_sha1nexte(e1,msg3); + e0 = abcd; + msg0 = __builtin_ia32_sha1msg2(msg0,msg3); + abcd = __builtin_ia32_sha1rnds4(abcd,e1,3); + msg2 = __builtin_ia32_sha1msg1(msg2,msg3); + msg1^=msg3; + + // Rounds 64-67 + e0 = __builtin_ia32_sha1nexte(e0,msg0); + e1 = abcd; + msg1 = __builtin_ia32_sha1msg2(msg1,msg0); + abcd = __builtin_ia32_sha1rnds4(abcd,e0,3); + msg3 = __builtin_ia32_sha1msg1(msg3,msg0); + msg2^=msg0; + + // Rounds 68-71 + e1 = __builtin_ia32_sha1nexte(e1,msg1); + e0=abcd; + msg2 = __builtin_ia32_sha1msg2(msg2,msg1); + abcd = __builtin_ia32_sha1rnds4(abcd,e1,3); + msg3^=msg1; + + + // Rounds 72-75 + e0 = __builtin_ia32_sha1nexte(e0,msg2); + e1 = abcd; + msg3 = __builtin_ia32_sha1msg2(msg3,msg2); + abcd = __builtin_ia32_sha1rnds4(abcd,e0,3); + + // Rounds 76-79 + e1 = __builtin_ia32_sha1nexte(e1,msg3); + e0 = abcd; + abcd = __builtin_ia32_sha1rnds4(abcd,e1,3); + + // Add values back to state + e0 = ( estate = __builtin_ia32_sha1nexte(e0, estate)); + abcdstate.wrap_add_assign(abcd); + abcd = abcdstate; + } + simd_vector{abcd[3],abcd[2],abcd[1],abcd[0]}.store(state); + state[4]=static_cast(e0.back()); +#elif defined(FAST_IO_ARM_SHA) && ( defined(__arm__) || defined(__aarch32__) || defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM) ) + sha1_arm_function(state,blocks_start,blocks_bytes); +#else + sha1_do_constexpr_function(state,blocks_start,blocks_bytes); +#endif +#elif (defined(_MSC_VER)&&!defined(__clang__)) && (defined(__AVX__) || (defined(__SSE_4_2__)&&defined(__SHA__)) ) +//https://stackoverflow.com/questions/21107350/how-can-i-access-sha-intrinsic + __m128i ABCD, ABCD_SAVE, E0, E0_SAVE, E1; + __m128i MASK, MSG0, MSG1, MSG2, MSG3; +//Clearly it is a violation of strict aliasing rule. +//However, the library will mark them as mayalias. We can safely use them. + + // Load initial values + ABCD = _mm_loadu_si128((__m128i*) state); + E0 = _mm_set_epi32(state[4], 0, 0, 0); + ABCD = _mm_shuffle_epi32(ABCD, 0x1B); + MASK = _mm_set_epi64x(0x0001020304050607ULL, 0x08090a0b0c0d0e0fULL); + for(auto block(blocks_start),ed(blocks_start+blocks_bytes);block!=ed;block+=block_size) + { + // Save current hash + ABCD_SAVE = ABCD; + E0_SAVE = E0; + + // Rounds 0-3 + MSG0 = _mm_loadu_si128((__m128i*) block); + MSG0 = _mm_shuffle_epi8(MSG0, MASK); + E0 = _mm_add_epi32(E0, MSG0); + E1 = ABCD; + ABCD = _mm_sha1rnds4_epu32(ABCD, E0, 0); + + // Rounds 4-7 + MSG1 = _mm_loadu_si128((__m128i*) (block+16)); + MSG1 = _mm_shuffle_epi8(MSG1, MASK); + E1 = _mm_sha1nexte_epu32(E1, MSG1); + E0 = ABCD; + ABCD = _mm_sha1rnds4_epu32(ABCD, E1, 0); + MSG0 = _mm_sha1msg1_epu32(MSG0, MSG1); + + // Rounds 8-11 + MSG2 = _mm_loadu_si128((__m128i*) (block+32)); + MSG2 = _mm_shuffle_epi8(MSG2, MASK); + E0 = _mm_sha1nexte_epu32(E0, MSG2); + E1 = ABCD; + ABCD = _mm_sha1rnds4_epu32(ABCD, E0, 0); + MSG1 = _mm_sha1msg1_epu32(MSG1, MSG2); + MSG0 = _mm_xor_si128(MSG0, MSG2); + + // Rounds 12-15 + MSG3 = _mm_loadu_si128((__m128i*) (block+48)); + MSG3 = _mm_shuffle_epi8(MSG3, MASK); + E1 = _mm_sha1nexte_epu32(E1, MSG3); + E0 = ABCD; + MSG0 = _mm_sha1msg2_epu32(MSG0, MSG3); + ABCD = _mm_sha1rnds4_epu32(ABCD, E1, 0); + MSG2 = _mm_sha1msg1_epu32(MSG2, MSG3); + MSG1 = _mm_xor_si128(MSG1, MSG3); + + // Rounds 16-19 + E0 = _mm_sha1nexte_epu32(E0, MSG0); + E1 = ABCD; + MSG1 = _mm_sha1msg2_epu32(MSG1, MSG0); + ABCD = _mm_sha1rnds4_epu32(ABCD, E0, 0); + MSG3 = _mm_sha1msg1_epu32(MSG3, MSG0); + MSG2 = _mm_xor_si128(MSG2, MSG0); + + // Rounds 20-23 + E1 = _mm_sha1nexte_epu32(E1, MSG1); + E0 = ABCD; + MSG2 = _mm_sha1msg2_epu32(MSG2, MSG1); + ABCD = _mm_sha1rnds4_epu32(ABCD, E1, 1); + MSG0 = _mm_sha1msg1_epu32(MSG0, MSG1); + MSG3 = _mm_xor_si128(MSG3, MSG1); + + // Rounds 24-27 + E0 = _mm_sha1nexte_epu32(E0, MSG2); + E1 = ABCD; + MSG3 = _mm_sha1msg2_epu32(MSG3, MSG2); + ABCD = _mm_sha1rnds4_epu32(ABCD, E0, 1); + MSG1 = _mm_sha1msg1_epu32(MSG1, MSG2); + MSG0 = _mm_xor_si128(MSG0, MSG2); + + // Rounds 28-31 + E1 = _mm_sha1nexte_epu32(E1, MSG3); + E0 = ABCD; + MSG0 = _mm_sha1msg2_epu32(MSG0, MSG3); + ABCD = _mm_sha1rnds4_epu32(ABCD, E1, 1); + MSG2 = _mm_sha1msg1_epu32(MSG2, MSG3); + MSG1 = _mm_xor_si128(MSG1, MSG3); + + // Rounds 32-35 + E0 = _mm_sha1nexte_epu32(E0, MSG0); + E1 = ABCD; + MSG1 = _mm_sha1msg2_epu32(MSG1, MSG0); + ABCD = _mm_sha1rnds4_epu32(ABCD, E0, 1); + MSG3 = _mm_sha1msg1_epu32(MSG3, MSG0); + MSG2 = _mm_xor_si128(MSG2, MSG0); + + // Rounds 36-39 + E1 = _mm_sha1nexte_epu32(E1, MSG1); + E0 = ABCD; + MSG2 = _mm_sha1msg2_epu32(MSG2, MSG1); + ABCD = _mm_sha1rnds4_epu32(ABCD, E1, 1); + MSG0 = _mm_sha1msg1_epu32(MSG0, MSG1); + MSG3 = _mm_xor_si128(MSG3, MSG1); + + // Rounds 40-43 + E0 = _mm_sha1nexte_epu32(E0, MSG2); + E1 = ABCD; + MSG3 = _mm_sha1msg2_epu32(MSG3, MSG2); + ABCD = _mm_sha1rnds4_epu32(ABCD, E0, 2); + MSG1 = _mm_sha1msg1_epu32(MSG1, MSG2); + MSG0 = _mm_xor_si128(MSG0, MSG2); + + // Rounds 44-47 + E1 = _mm_sha1nexte_epu32(E1, MSG3); + E0 = ABCD; + MSG0 = _mm_sha1msg2_epu32(MSG0, MSG3); + ABCD = _mm_sha1rnds4_epu32(ABCD, E1, 2); + MSG2 = _mm_sha1msg1_epu32(MSG2, MSG3); + MSG1 = _mm_xor_si128(MSG1, MSG3); + + // Rounds 48-51 + E0 = _mm_sha1nexte_epu32(E0, MSG0); + E1 = ABCD; + MSG1 = _mm_sha1msg2_epu32(MSG1, MSG0); + ABCD = _mm_sha1rnds4_epu32(ABCD, E0, 2); + MSG3 = _mm_sha1msg1_epu32(MSG3, MSG0); + MSG2 = _mm_xor_si128(MSG2, MSG0); + + // Rounds 52-55 + E1 = _mm_sha1nexte_epu32(E1, MSG1); + E0 = ABCD; + MSG2 = _mm_sha1msg2_epu32(MSG2, MSG1); + ABCD = _mm_sha1rnds4_epu32(ABCD, E1, 2); + MSG0 = _mm_sha1msg1_epu32(MSG0, MSG1); + MSG3 = _mm_xor_si128(MSG3, MSG1); + + // Rounds 56-59 + E0 = _mm_sha1nexte_epu32(E0, MSG2); + E1 = ABCD; + MSG3 = _mm_sha1msg2_epu32(MSG3, MSG2); + ABCD = _mm_sha1rnds4_epu32(ABCD, E0, 2); + MSG1 = _mm_sha1msg1_epu32(MSG1, MSG2); + MSG0 = _mm_xor_si128(MSG0, MSG2); + + // Rounds 60-63 + E1 = _mm_sha1nexte_epu32(E1, MSG3); + E0 = ABCD; + MSG0 = _mm_sha1msg2_epu32(MSG0, MSG3); + ABCD = _mm_sha1rnds4_epu32(ABCD, E1, 3); + MSG2 = _mm_sha1msg1_epu32(MSG2, MSG3); + MSG1 = _mm_xor_si128(MSG1, MSG3); + + // Rounds 64-67 + E0 = _mm_sha1nexte_epu32(E0, MSG0); + E1 = ABCD; + MSG1 = _mm_sha1msg2_epu32(MSG1, MSG0); + ABCD = _mm_sha1rnds4_epu32(ABCD, E0, 3); + MSG3 = _mm_sha1msg1_epu32(MSG3, MSG0); + MSG2 = _mm_xor_si128(MSG2, MSG0); + + // Rounds 68-71 + E1 = _mm_sha1nexte_epu32(E1, MSG1); + E0 = ABCD; + MSG2 = _mm_sha1msg2_epu32(MSG2, MSG1); + ABCD = _mm_sha1rnds4_epu32(ABCD, E1, 3); + MSG3 = _mm_xor_si128(MSG3, MSG1); + + // Rounds 72-75 + E0 = _mm_sha1nexte_epu32(E0, MSG2); + E1 = ABCD; + MSG3 = _mm_sha1msg2_epu32(MSG3, MSG2); + ABCD = _mm_sha1rnds4_epu32(ABCD, E0, 3); + + // Rounds 76-79 + E1 = _mm_sha1nexte_epu32(E1, MSG3); + E0 = ABCD; + ABCD = _mm_sha1rnds4_epu32(ABCD, E1, 3); + // Add values back to state + E0 = _mm_sha1nexte_epu32(E0, E0_SAVE); + ABCD = _mm_add_epi32(ABCD, ABCD_SAVE); + } + // Save state + ABCD = _mm_shuffle_epi32(ABCD, 0x1B); + _mm_storeu_si128((__m128i*) state, ABCD); + state[4] = _mm_extract_epi32(E0, 3); +#elif defined(FAST_IO_ARM_SHA) && ( defined(__arm__) || defined(__aarch32__) || defined(__arm64__) || defined(__aarch64__) || defined(_M_ARM) ) + sha1_arm_function(state,blocks_start,blocks_bytes); +#else + sha1_do_constexpr_function(state,blocks_start,blocks_bytes); +#endif +} + +class sha1 +{ +public: + using state_value_type = std::uint_least32_t; + static inline constexpr std::size_t block_size{64}; + static inline constexpr std::endian hash_endian{std::endian::big}; + static inline constexpr std::size_t state_size{5}; + state_value_type state[state_size]; +#if __cpp_lib_is_constant_evaluated >= 201811L + constexpr +#endif + void update_blocks(std::byte const* __restrict blocks_start,std::byte const* __restrict blocks_last) noexcept + { + std::size_t const blocks_bytes{static_cast(blocks_last-blocks_start)}; +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if(__builtin_is_constant_evaluated()) +#endif + { + ::fast_io::details::sha1::sha1_do_constexpr_function(this->state,blocks_start,blocks_bytes); + } + else +#endif + { + ::fast_io::details::sha1::sha1_do_function(this->state,blocks_start,blocks_bytes); + } + } +}; + +struct sha1_initializer +{ + static inline constexpr std::size_t digest_size{20}; + static inline constexpr ::fast_io::details::sha1::sha1 initialize_value{{0x67452301,0xefcdab89,0x98badcfe,0x10325476,0xc3d2e1f0}}; + static inline constexpr void digest_to_byte_ptr(std::uint_least32_t const* digest,std::byte* ptr) noexcept + { + hash_digest_to_byte_ptr_common<::std::uint_least32_t,digest_size,std::endian::big>(digest,ptr); + } +}; + +} + +namespace fast_io +{ +using sha1_context +#ifndef FAST_IO_NO_WARNING_DEPRECATED_CRYPTO_ALGOS +[[deprecated("SHA1 is no longer a secure algorithm. See wikipedia https://en.wikipedia.org/wiki/SHA-1")]] +#endif += ::fast_io::details::basic_md5_sha_context_impl<::fast_io::details::sha1::sha1,::fast_io::details::sha1::sha1_initializer,64>; +} diff --git a/src/fast_io/include/fast_io_crypto/hash/sha256.h b/src/fast_io/include/fast_io_crypto/hash/sha256.h new file mode 100644 index 0000000..060beb7 --- /dev/null +++ b/src/fast_io/include/fast_io_crypto/hash/sha256.h @@ -0,0 +1,232 @@ +#pragma once +/* +https://github.com/noloader/SHA-Intrinsics/blob/master/sha256-x86.c +*/ + +namespace fast_io::details::sha256 +{ + +inline constexpr std::uint_least32_t K256[] +{ +0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, +0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, +0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, +0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, +0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, +0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, +0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, +0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, +0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, +0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, +0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, +0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, +0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, +0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, +0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, +0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2 +}; + +inline constexpr auto Sigma0(auto x) noexcept +{ + return std::rotr(x,2)^std::rotr(x,13)^std::rotr(x,22); +} +inline constexpr auto Sigma1(auto x) noexcept +{ + return std::rotr(x,6)^std::rotr(x,11)^std::rotr(x,25); +} +inline constexpr auto sigma0(auto x) noexcept +{ + return std::rotr(x,7)^std::rotr(x,18)^(x>>3); +} +inline constexpr auto sigma1(auto x) noexcept +{ + return std::rotr(x,17)^std::rotr(x,19)^(x>>10); +} +inline constexpr auto Ch(auto x,auto y,auto z) noexcept +{ + return ((y^z)&x)^z; +} +inline constexpr auto Maj(auto x,auto y,auto z) noexcept +{ + return (x&y)^(x&z)^(y&z); +} + +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr void sha256_scalar_round(std::uint_least32_t T1k,std::uint_least32_t a,std::uint_least32_t b,std::uint_least32_t& __restrict d, + std::uint_least32_t e,std::uint_least32_t f,std::uint_least32_t g,std::uint_least32_t& __restrict h,std::uint_least32_t& __restrict bpc) noexcept +{ + T1k+=h+Sigma1(e)+Ch(e,f,g); + h=Sigma0(a); + std::uint_least32_t apb{a^b}; + h+=(apb&bpc)^b; + bpc=apb; + d+=T1k; + h+=T1k; +} + +inline constexpr std::uint_least32_t B2U32(std::byte val, std::uint_least8_t sh) noexcept +{ + return (static_cast(val)) << sh; +} + +inline +#if __cpp_lib_is_constant_evaluated >= 201811L +constexpr +#endif +void sha256_do_constexpr_function(std::uint_least32_t* __restrict state,std::byte const* __restrict data,std::byte const* __restrict blocks_last) noexcept +{ + std::uint_least32_t a{state[0]}, b{state[1]}, c{state[2]}, d{state[3]}, e{state[4]}, f{state[5]}, g{state[6]}, h{state[7]}, s0, s1, T1, T2; + std::uint_least32_t X[16]; + using namespace fast_io::details::sha256; + while(data!=blocks_last) + { + std::uint_least32_t i{}; + for (; i < 16; ++i) + { +#if __cpp_lib_is_constant_evaluated >= 201811L + if (std::is_constant_evaluated()) + { + X[i] = B2U32(data[0], 24) | B2U32(data[1], 16) | B2U32(data[2], 8) | B2U32(data[3], 0); + } + else +#endif + { + std::uint_least32_t value; + ::fast_io::details::my_memcpy(__builtin_addressof(value),data,4); + X[i] = big_endian(value); + } + data += 4; + + T1 = h; + T1 += Sigma1(e); + T1 += Ch(e, f, g); + T1 += K256[i]; + T1 += X[i]; + + T2 = Sigma0(a); + T2 += Maj(a, b, c); + + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + } + + for (; i < 64; ++i) + { + s0 = X[(i + 1) & 0x0f]; + s0 = sigma0(s0); + s1 = X[(i + 14) & 0x0f]; + s1 = sigma1(s1); + + T1 = X[i & 0xf] += s0 + s1 + X[(i + 9) & 0xf]; + T1 += h + Sigma1(e) + Ch(e, f, g) + K256[i]; + T2 = Sigma0(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + } + + a=(state[0] += a); + b=(state[1] += b); + c=(state[2] += c); + d=(state[3] += d); + e=(state[4] += e); + f=(state[5] += f); + g=(state[6] += g); + h=(state[7] += h); + } +} + +#if (!defined(_MSC_VER) || defined(__clang__)) +#if defined(__SSE2__) && (!defined(__SHA__) || !defined(__SSSE3__)) && __has_cpp_attribute(__gnu__::__target__) && !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) && (!defined(__clang__)||(defined(__SSE4_2__)&&defined(__SHA__))) +#include"sha256_x86_sha_extensions.h" +#elif defined(__SSE2__) || defined(__wasm_simd128__) +#include"sha256_simd16.h" +#else +#include"sha256_scalar.h" +#endif +#elif (defined(_MSC_VER)&&!defined(__clang__)) && (defined(__AVX__) || (defined(__SSE_4_2__)&&defined(__SHA__)) ) +#include"sha256_x86_sha_extensions_msvc.h" +#else +#include"sha256_scalar.h" +#endif + +class sha256 +{ +public: + using state_value_type = std::uint_least32_t; + static inline constexpr std::size_t block_size{64}; + static inline constexpr std::endian hash_endian{std::endian::big}; + static inline constexpr std::size_t state_size{8}; + state_value_type state[state_size]{0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19}; +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L + constexpr +#endif + void update_blocks(std::byte const* blocks_start,std::byte const* blocks_last) noexcept + { +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if(__builtin_is_constant_evaluated()) +#endif + { + ::fast_io::details::sha256::sha256_do_constexpr_function(this->state,blocks_start,blocks_last); + } + else +#endif + { + ::fast_io::details::sha256::sha256_runtime_routine(this->state,blocks_start,blocks_last); + } + } +}; + +struct sha224_initializer +{ + static inline constexpr std::size_t digest_size{28}; + static inline constexpr ::fast_io::details::sha256::sha256 initialize_value{{0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4}}; + static inline constexpr void digest_to_byte_ptr(std::uint_least32_t const* digest,std::byte* ptr) noexcept + { + hash_digest_to_byte_ptr_common<::std::uint_least32_t,digest_size,std::endian::big>(digest,ptr); + } +}; + +struct sha256_initializer +{ + static inline constexpr std::size_t digest_size{32}; + static inline constexpr ::fast_io::details::sha256::sha256 initialize_value{{0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19}}; + static inline constexpr void digest_to_byte_ptr(std::uint_least32_t const* digest,std::byte* ptr) noexcept + { + hash_digest_to_byte_ptr_common<::std::uint_least32_t,digest_size,std::endian::big>(digest,ptr); + } +}; + +} + +namespace fast_io +{ +using sha224_context = ::fast_io::details::basic_md5_sha_context_impl<::fast_io::details::sha256::sha256,::fast_io::details::sha256::sha224_initializer,64>; +using sha256_context = ::fast_io::details::basic_md5_sha_context_impl<::fast_io::details::sha256::sha256,::fast_io::details::sha256::sha256_initializer,64>; +} diff --git a/src/fast_io/include/fast_io_crypto/hash/sha256_scalar.h b/src/fast_io/include/fast_io_crypto/hash/sha256_scalar.h new file mode 100644 index 0000000..2471fb1 --- /dev/null +++ b/src/fast_io/include/fast_io_crypto/hash/sha256_scalar.h @@ -0,0 +1,99 @@ +#pragma once + +inline constexpr auto create_k256scalar() noexcept +{ + constexpr std::size_t n{sizeof(K256)/sizeof(std::uint_least32_t)}; + constexpr std::size_t nsub16{n-16u}; + ::fast_io::freestanding::array a; + for(std::size_t i{};i!=nsub16;++i) + { + a[i]=K256[i+16u]; + } + return a; +} + +inline constexpr auto k256scalar{create_k256scalar()}; + +#if __has_cpp_attribute(__gnu__::__flatten__) +[[__gnu__::__flatten__]] +#endif +#if __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr void sha256_round(std::uint_least32_t T1,std::uint_least32_t a,std::uint_least32_t b,std::uint_least32_t& __restrict d, + std::uint_least32_t e,std::uint_least32_t f,std::uint_least32_t g,std::uint_least32_t& __restrict h, + std::uint_least32_t& __restrict bpc,std::uint_least32_t k) noexcept +{ + sha256_scalar_round(T1+k,a,b,d,e,f,g,h,bpc); +} + +#if __has_cpp_attribute(__gnu__::__flatten__) +[[__gnu__::__flatten__]] +#endif +inline void sha256_runtime_routine(std::uint_least32_t* __restrict state,std::byte const* __restrict blocks_start,std::byte const* __restrict blocks_last) noexcept +{ + using ul32_may_alias +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = std::uint_least32_t; + std::uint_least32_t a{state[0]}; + std::uint_least32_t b{state[1]}; + std::uint_least32_t c{state[2]}; + std::uint_least32_t d{state[3]}; + std::uint_least32_t e{state[4]}; + std::uint_least32_t f{state[5]}; + std::uint_least32_t g{state[6]}; + std::uint_least32_t h{state[7]}; + std::uint_least32_t x[16]; + constexpr std::uint_least32_t const* k5_start{k256scalar.element}; + constexpr std::uint_least32_t const* k5_last{k256scalar.element+k256scalar.size()}; + for(;blocks_start!=blocks_last;blocks_start+=64) + { + ul32_may_alias const* W{reinterpret_cast(blocks_start)}; + std::uint_least32_t bpc{b^c}; + sha256_round(x[0]=big_endian(W[0]),a,b,d,e,f,g,h,bpc,0x428A2F98); + sha256_round(x[1]=big_endian(W[1]),h,a,c,d,e,f,g,bpc,0x71374491); + sha256_round(x[2]=big_endian(W[2]),g,h,b,c,d,e,f,bpc,0xB5C0FBCF); + sha256_round(x[3]=big_endian(W[3]),f,g,a,b,c,d,e,bpc,0xE9B5DBA5); + sha256_round(x[4]=big_endian(W[4]),e,f,h,a,b,c,d,bpc,0x3956C25B); + sha256_round(x[5]=big_endian(W[5]),d,e,g,h,a,b,c,bpc,0x59F111F1); + sha256_round(x[6]=big_endian(W[6]),c,d,f,g,h,a,b,bpc,0x923F82A4); + sha256_round(x[7]=big_endian(W[7]),b,c,e,f,g,h,a,bpc,0xAB1C5ED5); + sha256_round(x[8]=big_endian(W[8]),a,b,d,e,f,g,h,bpc,0xD807AA98); + sha256_round(x[9]=big_endian(W[9]),h,a,c,d,e,f,g,bpc,0x12835B01); + sha256_round(x[10]=big_endian(W[10]),g,h,b,c,d,e,f,bpc,0x243185BE); + sha256_round(x[11]=big_endian(W[11]),f,g,a,b,c,d,e,bpc,0x550C7DC3); + sha256_round(x[12]=big_endian(W[12]),e,f,h,a,b,c,d,bpc,0x72BE5D74); + sha256_round(x[13]=big_endian(W[13]),d,e,g,h,a,b,c,bpc,0x80DEB1FE); + sha256_round(x[14]=big_endian(W[14]),c,d,f,g,h,a,b,bpc,0x9BDC06A7); + sha256_round(x[15]=big_endian(W[15]),b,c,e,f,g,h,a,bpc,0xC19BF174); + for(std::uint_least32_t const *k5{k5_start};k5!=k5_last;k5+=16) + { + sha256_round((x[0]+=sigma0(x[1])+sigma1(x[14])+x[9]),a,b,d,e,f,g,h,bpc,*k5); + sha256_round((x[1]+=sigma0(x[2])+sigma1(x[15])+x[10]),h,a,c,d,e,f,g,bpc,k5[1]); + sha256_round((x[2]+=sigma0(x[3])+sigma1(x[0])+x[11]),g,h,b,c,d,e,f,bpc,k5[2]); + sha256_round((x[3]+=sigma0(x[4])+sigma1(x[1])+x[12]),f,g,a,b,c,d,e,bpc,k5[3]); + sha256_round((x[4]+=sigma0(x[5])+sigma1(x[2])+x[13]),e,f,h,a,b,c,d,bpc,k5[4]); + sha256_round((x[5]+=sigma0(x[6])+sigma1(x[3])+x[14]),d,e,g,h,a,b,c,bpc,k5[5]); + sha256_round((x[6]+=sigma0(x[7])+sigma1(x[4])+x[15]),c,d,f,g,h,a,b,bpc,k5[6]); + sha256_round((x[7]+=sigma0(x[8])+sigma1(x[5])+x[0]),b,c,e,f,g,h,a,bpc,k5[7]); + sha256_round((x[8]+=sigma0(x[9])+sigma1(x[6])+x[1]),a,b,d,e,f,g,h,bpc,k5[8]); + sha256_round((x[9]+=sigma0(x[10])+sigma1(x[7])+x[2]),h,a,c,d,e,f,g,bpc,k5[9]); + sha256_round((x[10]+=sigma0(x[11])+sigma1(x[8])+x[3]),g,h,b,c,d,e,f,bpc,k5[10]); + sha256_round((x[11]+=sigma0(x[12])+sigma1(x[9])+x[4]),f,g,a,b,c,d,e,bpc,k5[11]); + sha256_round((x[12]+=sigma0(x[13])+sigma1(x[10])+x[5]),e,f,h,a,b,c,d,bpc,k5[12]); + sha256_round((x[13]+=sigma0(x[14])+sigma1(x[11])+x[6]),d,e,g,h,a,b,c,bpc,k5[13]); + sha256_round((x[14]+=sigma0(x[15])+sigma1(x[12])+x[7]),c,d,f,g,h,a,b,bpc,k5[14]); + sha256_round((x[15]+=sigma0(x[0])+sigma1(x[13])+x[8]),b,c,e,f,g,h,a,bpc,k5[15]); + } + a=(*state+=a); + b=(state[1]+=b); + c=(state[2]+=c); + d=(state[3]+=d); + e=(state[4]+=e); + f=(state[5]+=f); + g=(state[6]+=g); + h=(state[7]+=h); + } +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_crypto/hash/sha256_simd16.h b/src/fast_io/include/fast_io_crypto/hash/sha256_simd16.h new file mode 100644 index 0000000..9c19b56 --- /dev/null +++ b/src/fast_io/include/fast_io_crypto/hash/sha256_simd16.h @@ -0,0 +1,155 @@ +#pragma once + +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#endif +inline void sha256_simd16_byte_swap_message_4rounds(::fast_io::intrinsics::simd_vector& __restrict s1, + std::byte const* __restrict blocks_start,std::uint_least32_t* __restrict w,std::uint_least32_t* __restrict wt,std::size_t round) noexcept +{ + using namespace ::fast_io::intrinsics; + simd_vector s0; + s1.load(blocks_start+(round*4u)); + s0.load(K256+round); + if constexpr(std::endian::native==std::endian::little) + { + s1.swap_endian(); + } + s1.store(w+round); + s0.wrap_add_assign(s1); + s0.store(wt+round); +} + +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#endif +inline void sha256_simd16_compute_message_4rounds(::fast_io::intrinsics::simd_vector& __restrict s1, + std::uint_least32_t* __restrict w,std::uint_least32_t* __restrict wt,std::size_t round) noexcept +{ +/* +s0(w[t])=(w[t-15]>>7) ^ (w[t-15]<<25)^ (w[t-15]>>18) ^ (w[t-15]<<14) ^ (w[t-15]>>3) +s1(w[t])=(w[t-2]>>17) ^ (w[t-2]<<15) ^ (w[t-2]>>19) ^ (w[t-2]<<13) ^ (w[t-2]>>10) +w[i] = w[i-16] + w[i-7] + s0[i] + s1[i] +wt[r,r+1,r+2,r+3]=wt[r-16,r-15,r-14,r-13]+wt[r-7,r-6,r-5,r-4] +*/ + using namespace ::fast_io::intrinsics; + simd_vector s10{s1[2],s1[3],0,0}; + simd_vector s0; + s0.load(w+(round-15)); + if constexpr(true) + { + s10=(s10>>17)^(s10<<15)^(s10>>19)^(s10<<13)^(s10>>10); + s0=(s0>>7)^(s0<<25)^(s0>>18)^(s0<<14)^(s0>>3); + } + else if constexpr(false) + { + s10=(((((s10>>2)^s10)>>7)^s10)>>10)^(((s10<<2)^s10)<<13); + s0=(((((s0>>11)^s0)>>4)^s0)>>3)^(((s0<<11)^s0)<<14); + } + else + { + s10=wrap_add((s10>>17),(s10<<15))^wrap_add((s10>>19),(s10<<13))^(s10>>10); + s0=wrap_add((s0>>7),(s0<<25))^wrap_add((s0>>18),(s0<<14))^(s0>>3); + } + s10.wrap_add_assign(s0); + s0.load(w+(round-16)); + s10.wrap_add_assign(s0); + s0.load(w+(round-7)); + s10.wrap_add_assign(s0); + s1=simd_vector{0,0,s10[0],s10[1]}; + if constexpr(false) + { + s1=(s1>>17)^(s1<<15)^(s1>>19)^(s1<<13)^(s1>>10); + } + else + { + s1=(((((s1>>2)^s1)>>7)^s1)>>10)^(((s1<<2)^s1)<<13); + } + s1.wrap_add_assign(s10); + s1.store(w+round); + s0.load(::fast_io::details::sha256::K256+round); + s0.wrap_add_assign(s1); + s0.store(wt+round); +} + +#if defined(__SSE2__) && (!defined(__SHA__) || !defined(__SSSE3__)) && __has_cpp_attribute(__gnu__::__target__) && !defined(__clang__) && defined(__ELF__) && defined(FAST_IO_RUNTIME_DISPATCH) +[[__gnu__::__target__("default")]] +#elif __has_cpp_attribute(__gnu__::__flatten__) +[[__gnu__::__flatten__]] +#endif +inline void sha256_runtime_routine(std::uint_least32_t* __restrict state,std::byte const* __restrict blocks_start,std::byte const* __restrict blocks_last) noexcept +{ + using namespace fast_io::intrinsics; + using namespace fast_io::details::sha256; + + simd_vector simd; + + std::uint_least32_t wt[64]; + std::uint_least32_t w[64]; + std::uint_least32_t a{state[0]}; + std::uint_least32_t b{state[1]}; + std::uint_least32_t c{state[2]}; + std::uint_least32_t d{state[3]}; + std::uint_least32_t e{state[4]}; + std::uint_least32_t f{state[5]}; + std::uint_least32_t g{state[6]}; + std::uint_least32_t h{state[7]}; + + for(;blocks_start!=blocks_last;blocks_start+=64) + { + sha256_simd16_byte_swap_message_4rounds(simd,blocks_start,w,wt,0); + std::uint_least32_t bpc{b^c}; + sha256_scalar_round(wt[0],a,b,d,e,f,g,h,bpc); + sha256_scalar_round(wt[1],h,a,c,d,e,f,g,bpc); + sha256_simd16_byte_swap_message_4rounds(simd,blocks_start,w,wt,4); + sha256_scalar_round(wt[2],g,h,b,c,d,e,f,bpc); + sha256_scalar_round(wt[3],f,g,a,b,c,d,e,bpc); + sha256_scalar_round(wt[4],e,f,h,a,b,c,d,bpc); + sha256_scalar_round(wt[5],d,e,g,h,a,b,c,bpc); + sha256_simd16_byte_swap_message_4rounds(simd,blocks_start,w,wt,8); + sha256_scalar_round(wt[6],c,d,f,g,h,a,b,bpc); + sha256_scalar_round(wt[7],b,c,e,f,g,h,a,bpc); + sha256_scalar_round(wt[8],a,b,d,e,f,g,h,bpc); + sha256_scalar_round(wt[9],h,a,c,d,e,f,g,bpc); + sha256_simd16_byte_swap_message_4rounds(simd,blocks_start,w,wt,12); + sha256_scalar_round(wt[10],g,h,b,c,d,e,f,bpc); + sha256_scalar_round(wt[11],f,g,a,b,c,d,e,bpc); + for(std::uint_fast8_t i{12};i!=60;i+=16) + { + std::uint_least32_t const* const p{wt+i}; + sha256_scalar_round(*p,e,f,h,a,b,c,d,bpc); + sha256_scalar_round(p[1],d,e,g,h,a,b,c,bpc); + sha256_simd16_compute_message_4rounds(simd,w,wt,i+4); + sha256_scalar_round(p[2],c,d,f,g,h,a,b,bpc); + sha256_scalar_round(p[3],b,c,e,f,g,h,a,bpc); + sha256_scalar_round(p[4],a,b,d,e,f,g,h,bpc); + sha256_scalar_round(p[5],h,a,c,d,e,f,g,bpc); + sha256_simd16_compute_message_4rounds(simd,w,wt,i+8); + sha256_scalar_round(p[6],g,h,b,c,d,e,f,bpc); + sha256_scalar_round(p[7],f,g,a,b,c,d,e,bpc); + + sha256_scalar_round(p[8],e,f,h,a,b,c,d,bpc); + sha256_scalar_round(p[9],d,e,g,h,a,b,c,bpc); + sha256_simd16_compute_message_4rounds(simd,w,wt,i+12); + sha256_scalar_round(p[10],c,d,f,g,h,a,b,bpc); + sha256_scalar_round(p[11],b,c,e,f,g,h,a,bpc); + sha256_scalar_round(p[12],a,b,d,e,f,g,h,bpc); + sha256_scalar_round(p[13],h,a,c,d,e,f,g,bpc); + sha256_simd16_compute_message_4rounds(simd,w,wt,i+16); + sha256_scalar_round(p[14],g,h,b,c,d,e,f,bpc); + sha256_scalar_round(p[15],f,g,a,b,c,d,e,bpc); + } + sha256_scalar_round(wt[60],e,f,h,a,b,c,d,bpc); + sha256_scalar_round(wt[61],d,e,g,h,a,b,c,bpc); + sha256_scalar_round(wt[62],c,d,f,g,h,a,b,bpc); + sha256_scalar_round(wt[63],b,c,e,f,g,h,a,bpc); + + a=(*state+=a); + b=(state[1]+=b); + c=(state[2]+=c); + d=(state[3]+=d); + e=(state[4]+=e); + f=(state[5]+=f); + g=(state[6]+=g); + h=(state[7]+=h); + } +} diff --git a/src/fast_io/include/fast_io_crypto/hash/sha256_x86_sha_extensions.h b/src/fast_io/include/fast_io_crypto/hash/sha256_x86_sha_extensions.h new file mode 100644 index 0000000..bca9003 --- /dev/null +++ b/src/fast_io/include/fast_io_crypto/hash/sha256_x86_sha_extensions.h @@ -0,0 +1,249 @@ +#pragma once + + +#if defined(__SSE2__) && (!defined(__SHA__) || !defined(__SSSE3__)) && __has_cpp_attribute(__gnu__::__target__) && !defined(__clang__) && defined(__ELF__) && defined(FAST_IO_RUNTIME_DISPATCH) +[[__gnu__::__target__("ssse3,sha")]] +#elif __has_cpp_attribute(__gnu__::__flatten__) +[[__gnu__::__flatten__]] +#endif +inline void sha256_runtime_routine(std::uint_least32_t* __restrict state,std::byte const* __restrict block,std::byte const* __restrict blocks_last) noexcept +{ + constexpr std::size_t block_size{64}; + using ::fast_io::intrinsics::simd_vector; + simd_vector state0st{static_cast(state[5]),static_cast(state[4]), + static_cast(state[1]),static_cast(state[0])}; + simd_vector state1st{static_cast(state[7]),static_cast(state[6]), + static_cast(state[3]),static_cast(state[2])}; + simd_vector state0=state0st; + simd_vector state1=state1st; + simd_vector msg,msg0,msg1,msg2,msg3; + constexpr int compiler_magic{ +#if defined(__clang__) +4 //clang and gcc disagree with __builtin_ia32_palignr128 +#else +32 +#endif + }; + for(;block!=blocks_last;block+=block_size) + { + /* Rounds 0-3 */ + msg0.load(block); + msg0.swap_endian(); + { + //0xE9B5DBA5B5C0FBCFULL, 0x71374491428A2F98ULL + constexpr simd_vector constant{1116352408,1899447441,-1245643825,-373957723}; + msg=wrap_add(msg0,constant); + } + state1 = __builtin_ia32_sha256rnds2(state1,state0,msg); + msg = __builtin_ia32_pshufd(msg, 0x0E); + state0 = __builtin_ia32_sha256rnds2(state0,state1,msg); + + /* Rounds 4-7 */ + msg1.load(block+16); + msg1.swap_endian(); + { + //0xAB1C5ED5923F82A4ULL, 0x59F111F13956C25BULL + constexpr simd_vector constant{961987163,1508970993,-1841331548,-1424204075}; + msg=wrap_add(msg1,constant); + } + state1 = __builtin_ia32_sha256rnds2(state1,state0,msg); + msg = __builtin_ia32_pshufd(msg, 0x0E); + state0 = __builtin_ia32_sha256rnds2(state0,state1,msg); + msg0 = __builtin_ia32_sha256msg1(msg0,msg1); + + /* Rounds 8-11 */ + msg2.load(block+32); + msg2.swap_endian(); + { + constexpr simd_vector constant{-670586216,310598401,607225278,1426881987}; + msg = wrap_add(msg2,constant); + } + state1 = __builtin_ia32_sha256rnds2(state1,state0,msg); + msg = __builtin_ia32_pshufd(msg, 0x0E); + state0 = __builtin_ia32_sha256rnds2(state0,state1,msg); + msg1 = __builtin_ia32_sha256msg1(msg1,msg2); + + /* Rounds 12-15 */ + msg3.load(block+48); + msg3.swap_endian(); + { + constexpr simd_vector constant{1925078388,-2132889090,-1680079193,-1046744716}; + msg = wrap_add(msg3,constant); + } + state1 = __builtin_ia32_sha256rnds2(state1,state0,msg); + msg0.wrap_add_assign(__builtin_ia32_palignr128( + static_cast>(msg3), + static_cast>(msg2),compiler_magic)); + msg0=__builtin_ia32_sha256msg2(msg0,msg3); + msg = __builtin_ia32_pshufd(msg, 0x0E); + state0 = __builtin_ia32_sha256rnds2(state0,state1,msg); + msg2 = __builtin_ia32_sha256msg1(msg2,msg3); + + /* Rounds 16-19 */ + { + constexpr simd_vector constant{-459576895,-272742522,264347078,604807628}; + msg = wrap_add(msg0,constant); + } + state1 = __builtin_ia32_sha256rnds2(state1,state0,msg); + + msg1.wrap_add_assign(__builtin_ia32_palignr128(static_cast>(msg0), + static_cast>(msg3),compiler_magic)); + + msg1=__builtin_ia32_sha256msg2(msg1,msg0); + msg = __builtin_ia32_pshufd(msg, 0x0E); + state0 = __builtin_ia32_sha256rnds2(state0,state1,msg); + msg3 = __builtin_ia32_sha256msg1(msg3,msg0); + + /* Rounds 20-23 */ + { + constexpr simd_vector constant{770255983,1249150122,1555081692,1996064986}; + msg = wrap_add(msg1,constant); + } + state1 = __builtin_ia32_sha256rnds2(state1,state0,msg); + msg2.wrap_add_assign(__builtin_ia32_palignr128(static_cast>(msg1), + static_cast>(msg0),compiler_magic)); + msg2=__builtin_ia32_sha256msg2(msg2,msg1); + msg = __builtin_ia32_pshufd(msg, 0x0E); + state0 = __builtin_ia32_sha256rnds2(state0,state1,msg); + msg0 = __builtin_ia32_sha256msg1(msg0,msg1); + + /* Rounds 24-27 */ + { + constexpr simd_vector constant{-1740746414,-1473132947,-1341970488,-1084653625}; + msg = wrap_add(msg2,constant); + } + state1 = __builtin_ia32_sha256rnds2(state1,state0,msg); + msg3.wrap_add_assign(__builtin_ia32_palignr128(static_cast>(msg2), + static_cast>(msg1),compiler_magic)); + msg3=__builtin_ia32_sha256msg2(msg3,msg2); + msg = __builtin_ia32_pshufd(msg, 0x0E); + state0 = __builtin_ia32_sha256rnds2(state0,state1,msg); + msg1 = __builtin_ia32_sha256msg1(msg1,msg2); + + /* Rounds 28-31 */ + { + constexpr simd_vector constant{-958395405,-710438585,113926993,338241895}; + msg = wrap_add(msg3,constant); + } + state1 = __builtin_ia32_sha256rnds2(state1,state0,msg); + msg0.wrap_add_assign(__builtin_ia32_palignr128(static_cast>(msg3), + static_cast>(msg2),compiler_magic)); + msg0=__builtin_ia32_sha256msg2(msg0,msg3); + msg = __builtin_ia32_pshufd(msg, 0x0E); + state0 = __builtin_ia32_sha256rnds2(state0,state1,msg); + msg2 = __builtin_ia32_sha256msg1(msg2,msg3); + + /* Rounds 32-35 */ + { + constexpr simd_vector constant{666307205,773529912,1294757372,1396182291}; + msg = wrap_add(msg0,constant); + } + state1 = __builtin_ia32_sha256rnds2(state1,state0,msg); + msg1.wrap_add_assign(__builtin_ia32_palignr128(static_cast>(msg0), + static_cast>(msg3),compiler_magic)); + msg1=__builtin_ia32_sha256msg2(msg1,msg0); + msg = __builtin_ia32_pshufd(msg, 0x0E); + state0 = __builtin_ia32_sha256rnds2(state0,state1,msg); + msg3 = __builtin_ia32_sha256msg1(msg3,msg0); + + /* Rounds 36-39 */ + { + constexpr simd_vector constant{1695183700,1986661051,-2117940946,-1838011259}; + msg = wrap_add(msg1,constant); + } + state1 = __builtin_ia32_sha256rnds2(state1,state0,msg); + msg2.wrap_add_assign(__builtin_ia32_palignr128(static_cast>(msg1), + static_cast>(msg0),compiler_magic)); + msg2 = __builtin_ia32_sha256msg2(msg2,msg1); + msg = __builtin_ia32_pshufd(msg,0x0E); + state0 = __builtin_ia32_sha256rnds2(state0,state1,msg); + msg0 = __builtin_ia32_sha256msg1(msg0,msg1); + + /* Rounds 40-43 */ + { + constexpr simd_vector constant{-1564481375,-1474664885,-1035236496,-949202525}; + msg = wrap_add(msg2,constant); + } + state1 = __builtin_ia32_sha256rnds2(state1,state0,msg); + msg3.wrap_add_assign(__builtin_ia32_palignr128(static_cast>(msg2), + static_cast>(msg1),compiler_magic)); + msg3 = __builtin_ia32_sha256msg2(msg3,msg2); + msg = __builtin_ia32_pshufd(msg,0x0E); + state0 = __builtin_ia32_sha256rnds2(state0,state1,msg); + msg1 = __builtin_ia32_sha256msg1(msg1,msg2); + + /* Rounds 44-47 */ + { + constexpr simd_vector constant{-778901479,-694614492,-200395387,275423344}; + msg = wrap_add(msg3,constant); + } + state1 = __builtin_ia32_sha256rnds2(state1,state0,msg); + msg0.wrap_add_assign(__builtin_ia32_palignr128(static_cast>(msg3), + static_cast>(msg2),compiler_magic)); + msg0 = __builtin_ia32_sha256msg2(msg0,msg3); + msg = __builtin_ia32_pshufd(msg,0x0E); + state0 = __builtin_ia32_sha256rnds2(state0,state1,msg); + msg2 = __builtin_ia32_sha256msg1(msg2,msg3); + + /* Rounds 48-51 */ + { + constexpr simd_vector constant{430227734,506948616,659060556,883997877}; + msg = wrap_add(msg0,constant); + } + state1 = __builtin_ia32_sha256rnds2(state1,state0,msg); + msg1.wrap_add_assign(__builtin_ia32_palignr128(static_cast>(msg0), + static_cast>(msg3),compiler_magic)); + msg1 = __builtin_ia32_sha256msg2(msg1,msg0); + msg = __builtin_ia32_pshufd(msg,0x0E); + state0 = __builtin_ia32_sha256rnds2(state0,state1,msg); + msg3 = __builtin_ia32_sha256msg1(msg3,msg0); + + /* Rounds 52-55 */ + { + constexpr simd_vector constant{958139571,1322822218,1537002063,1747873779}; + msg = wrap_add(msg1,constant); + } + state1 = __builtin_ia32_sha256rnds2(state1,state0,msg); + msg2.wrap_add_assign(__builtin_ia32_palignr128(static_cast>(msg1), + static_cast>(msg0),compiler_magic)); + msg2 = __builtin_ia32_sha256msg2(msg2,msg1); + msg = __builtin_ia32_pshufd(msg,0x0E); + state0 = __builtin_ia32_sha256rnds2(state0,state1,msg); + + /* Rounds 56-59 */ + { + constexpr simd_vector constant{1955562222,2024104815,-2067236844,-1933114872}; + msg = wrap_add(msg2,constant); + } + state1 = __builtin_ia32_sha256rnds2(state1,state0,msg); + msg3.wrap_add_assign(__builtin_ia32_palignr128(static_cast>(msg2), + static_cast>(msg1),compiler_magic)); + msg3 = __builtin_ia32_sha256msg2(msg3,msg2); + msg = __builtin_ia32_pshufd(msg,0x0E); + state0 = __builtin_ia32_sha256rnds2(state0,state1,msg); + + /* Rounds 60-63 */ + { + constexpr simd_vector constant{-1866530822,-1538233109,-1090935817,-965641998}; + msg = wrap_add(msg3,constant); + } + state1 = __builtin_ia32_sha256rnds2(state1,state0,msg); + msg = __builtin_ia32_pshufd(msg,0x0E); + state0 = __builtin_ia32_sha256rnds2(state0,state1,msg); + + + /* Combine state */ + state0st.wrap_add_assign(state0); + state0 = state0st; + state1st.wrap_add_assign(state1); + state1 = state1st; + } + state[0]=static_cast(state0[3]); + state[1]=static_cast(state0[2]); + state[2]=static_cast(state1[3]); + state[3]=static_cast(state1[2]); + state[4]=static_cast(state0[1]); + state[5]=static_cast(state0[0]); + state[6]=static_cast(state1[1]); + state[7]=static_cast(state1[0]); +} diff --git a/src/fast_io/include/fast_io_crypto/hash/sha256_x86_sha_extensions_msvc.h b/src/fast_io/include/fast_io_crypto/hash/sha256_x86_sha_extensions_msvc.h new file mode 100644 index 0000000..c3ca043 --- /dev/null +++ b/src/fast_io/include/fast_io_crypto/hash/sha256_x86_sha_extensions_msvc.h @@ -0,0 +1,193 @@ +#pragma once + +#if __has_cpp_attribute(__gnu__::__flatten__) +[[__gnu__::__flatten__]] +#endif +inline void sha256_runtime_routine(std::uint_least32_t* __restrict state,std::byte const* __restrict block,std::byte const* __restrict blocks_last) noexcept +{ + constexpr std::size_t block_size{64}; + __m128i STATE0, STATE1; + __m128i MSG, TMP; + __m128i MSG0, MSG1, MSG2, MSG3; + __m128i ABEF_SAVE, CDGH_SAVE; + __m128i const MASK = _mm_set_epi64x(0x0c0d0e0f08090a0bULL, 0x0405060700010203ULL); + + /* Load initial values */ + TMP = _mm_loadu_si128((__m128i const*) state); + STATE1 = _mm_loadu_si128((__m128i const*) (state+4)); + + TMP = _mm_shuffle_epi32(TMP, 0xB1); /* CDAB */ + STATE1 = _mm_shuffle_epi32(STATE1, 0x1B); /* EFGH */ + STATE0 = _mm_alignr_epi8(TMP, STATE1, 8); /* ABEF */ + STATE1 = _mm_blend_epi16(STATE1, TMP, 0xF0); /* CDGH */ + for(;block!=blocks_last;block+=block_size) + { + /* Save current state */ + ABEF_SAVE = STATE0; + CDGH_SAVE = STATE1; + + /* Rounds 0-3 */ + MSG = _mm_loadu_si128((__m128i const*) block); + MSG0 = _mm_shuffle_epi8(MSG, MASK); + MSG = _mm_add_epi32(MSG0, _mm_set_epi64x(0xE9B5DBA5B5C0FBCFULL, 0x71374491428A2F98ULL)); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + + /* Rounds 4-7 */ + MSG1 = _mm_loadu_si128((__m128i const*) (block+16)); + MSG1 = _mm_shuffle_epi8(MSG1, MASK); + MSG = _mm_add_epi32(MSG1, _mm_set_epi64x(0xAB1C5ED5923F82A4ULL, 0x59F111F13956C25BULL)); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + MSG0 = _mm_sha256msg1_epu32(MSG0, MSG1); + + /* Rounds 8-11 */ + MSG2 = _mm_loadu_si128((__m128i const*) (block+32)); + MSG2 = _mm_shuffle_epi8(MSG2, MASK); + MSG = _mm_add_epi32(MSG2, _mm_set_epi64x(0x550C7DC3243185BEULL, 0x12835B01D807AA98ULL)); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + MSG1 = _mm_sha256msg1_epu32(MSG1, MSG2); + + + /* Rounds 12-15 */ + MSG3 = _mm_loadu_si128((__m128i const*) (block+48)); + MSG3 = _mm_shuffle_epi8(MSG3, MASK); + MSG = _mm_add_epi32(MSG3, _mm_set_epi64x(0xC19BF1749BDC06A7ULL, 0x80DEB1FE72BE5D74ULL)); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + TMP = _mm_alignr_epi8(MSG3, MSG2, 4); + MSG0 = _mm_add_epi32(MSG0, TMP); + MSG0 = _mm_sha256msg2_epu32(MSG0, MSG3); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + MSG2 = _mm_sha256msg1_epu32(MSG2, MSG3); + + /* Rounds 16-19 */ + MSG = _mm_add_epi32(MSG0, _mm_set_epi64x(0x240CA1CC0FC19DC6ULL, 0xEFBE4786E49B69C1ULL)); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + TMP = _mm_alignr_epi8(MSG0, MSG3, 4); + MSG1 = _mm_add_epi32(MSG1, TMP); + MSG1 = _mm_sha256msg2_epu32(MSG1, MSG0); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + MSG3 = _mm_sha256msg1_epu32(MSG3, MSG0); + + /* Rounds 20-23 */ + MSG = _mm_add_epi32(MSG1, _mm_set_epi64x(0x76F988DA5CB0A9DCULL, 0x4A7484AA2DE92C6FULL)); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + TMP = _mm_alignr_epi8(MSG1, MSG0, 4); + MSG2 = _mm_add_epi32(MSG2, TMP); + MSG2 = _mm_sha256msg2_epu32(MSG2, MSG1); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + MSG0 = _mm_sha256msg1_epu32(MSG0, MSG1); + + /* Rounds 24-27 */ + MSG = _mm_add_epi32(MSG2, _mm_set_epi64x(0xBF597FC7B00327C8ULL, 0xA831C66D983E5152ULL)); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + TMP = _mm_alignr_epi8(MSG2, MSG1, 4); + MSG3 = _mm_add_epi32(MSG3, TMP); + MSG3 = _mm_sha256msg2_epu32(MSG3, MSG2); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + MSG1 = _mm_sha256msg1_epu32(MSG1, MSG2); + + /* Rounds 28-31 */ + MSG = _mm_add_epi32(MSG3, _mm_set_epi64x(0x1429296706CA6351ULL, 0xD5A79147C6E00BF3ULL)); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + TMP = _mm_alignr_epi8(MSG3, MSG2, 4); + MSG0 = _mm_add_epi32(MSG0, TMP); + MSG0 = _mm_sha256msg2_epu32(MSG0, MSG3); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + MSG2 = _mm_sha256msg1_epu32(MSG2, MSG3); + + /* Rounds 32-35 */ + MSG = _mm_add_epi32(MSG0, _mm_set_epi64x(0x53380D134D2C6DFCULL, 0x2E1B213827B70A85ULL)); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + TMP = _mm_alignr_epi8(MSG0, MSG3, 4); + MSG1 = _mm_add_epi32(MSG1, TMP); + MSG1 = _mm_sha256msg2_epu32(MSG1, MSG0); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + MSG3 = _mm_sha256msg1_epu32(MSG3, MSG0); + + /* Rounds 36-39 */ + MSG = _mm_add_epi32(MSG1, _mm_set_epi64x(0x92722C8581C2C92EULL, 0x766A0ABB650A7354ULL)); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + TMP = _mm_alignr_epi8(MSG1, MSG0, 4); + MSG2 = _mm_add_epi32(MSG2, TMP); + MSG2 = _mm_sha256msg2_epu32(MSG2, MSG1); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + MSG0 = _mm_sha256msg1_epu32(MSG0, MSG1); + + /* Rounds 40-43 */ + MSG = _mm_add_epi32(MSG2, _mm_set_epi64x(0xC76C51A3C24B8B70ULL, 0xA81A664BA2BFE8A1ULL)); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + TMP = _mm_alignr_epi8(MSG2, MSG1, 4); + MSG3 = _mm_add_epi32(MSG3, TMP); + MSG3 = _mm_sha256msg2_epu32(MSG3, MSG2); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + MSG1 = _mm_sha256msg1_epu32(MSG1, MSG2); + + /* Rounds 44-47 */ + MSG = _mm_add_epi32(MSG3, _mm_set_epi64x(0x106AA070F40E3585ULL, 0xD6990624D192E819ULL)); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + TMP = _mm_alignr_epi8(MSG3, MSG2, 4); + MSG0 = _mm_add_epi32(MSG0, TMP); + MSG0 = _mm_sha256msg2_epu32(MSG0, MSG3); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + MSG2 = _mm_sha256msg1_epu32(MSG2, MSG3); + + /* Rounds 48-51 */ + MSG = _mm_add_epi32(MSG0, _mm_set_epi64x(0x34B0BCB52748774CULL, 0x1E376C0819A4C116ULL)); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + TMP = _mm_alignr_epi8(MSG0, MSG3, 4); + MSG1 = _mm_add_epi32(MSG1, TMP); + MSG1 = _mm_sha256msg2_epu32(MSG1, MSG0); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + MSG3 = _mm_sha256msg1_epu32(MSG3, MSG0); + + /* Rounds 52-55 */ + MSG = _mm_add_epi32(MSG1, _mm_set_epi64x(0x682E6FF35B9CCA4FULL, 0x4ED8AA4A391C0CB3ULL)); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + TMP = _mm_alignr_epi8(MSG1, MSG0, 4); + MSG2 = _mm_add_epi32(MSG2, TMP); + MSG2 = _mm_sha256msg2_epu32(MSG2, MSG1); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + + /* Rounds 56-59 */ + MSG = _mm_add_epi32(MSG2, _mm_set_epi64x(0x8CC7020884C87814ULL, 0x78A5636F748F82EEULL)); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + TMP = _mm_alignr_epi8(MSG2, MSG1, 4); + MSG3 = _mm_add_epi32(MSG3, TMP); + MSG3 = _mm_sha256msg2_epu32(MSG3, MSG2); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + + /* Rounds 60-63 */ + MSG = _mm_add_epi32(MSG3, _mm_set_epi64x(0xC67178F2BEF9A3F7ULL, 0xA4506CEB90BEFFFAULL)); + STATE1 = _mm_sha256rnds2_epu32(STATE1, STATE0, MSG); + MSG = _mm_shuffle_epi32(MSG, 0x0E); + STATE0 = _mm_sha256rnds2_epu32(STATE0, STATE1, MSG); + + /* Combine state */ + STATE0 = _mm_add_epi32(STATE0, ABEF_SAVE); + STATE1 = _mm_add_epi32(STATE1, CDGH_SAVE); + } + TMP = _mm_shuffle_epi32(STATE0, 0x1B); /* FEBA */ + STATE1 = _mm_shuffle_epi32(STATE1, 0xB1); /* DCHG */ + STATE0 = _mm_blend_epi16(TMP, STATE1, 0xF0); /* DCBA */ + STATE1 = _mm_alignr_epi8(STATE1, TMP, 8); /* ABEF */ + /* Save state */ + _mm_storeu_si128((__m128i*) (state), STATE0); + _mm_storeu_si128((__m128i*) (state+4), STATE1); +} diff --git a/src/fast_io/include/fast_io_crypto/hash/sha512.h b/src/fast_io/include/fast_io_crypto/hash/sha512.h new file mode 100644 index 0000000..3e36947 --- /dev/null +++ b/src/fast_io/include/fast_io_crypto/hash/sha512.h @@ -0,0 +1,289 @@ +#pragma once +/* +https://github.com/noloader/SHA-Intrinsics/blob/master/sha256-x86.c +*/ + +namespace fast_io::details::sha512 +{ + +inline constexpr std::uint_least64_t K512[] +{ +0x428a2f98d728ae22, 0x7137449123ef65cd, +0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, +0x3956c25bf348b538, 0x59f111f1b605d019, +0x923f82a4af194f9b, 0xab1c5ed5da6d8118, +0xd807aa98a3030242, 0x12835b0145706fbe, +0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, +0x72be5d74f27b896f, 0x80deb1fe3b1696b1, +0x9bdc06a725c71235, 0xc19bf174cf692694, +0xe49b69c19ef14ad2, 0xefbe4786384f25e3, +0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, +0x2de92c6f592b0275, 0x4a7484aa6ea6e483, +0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, +0x983e5152ee66dfab, 0xa831c66d2db43210, +0xb00327c898fb213f, 0xbf597fc7beef0ee4, +0xc6e00bf33da88fc2, 0xd5a79147930aa725, +0x06ca6351e003826f, 0x142929670a0e6e70, +0x27b70a8546d22ffc, 0x2e1b21385c26c926, +0x4d2c6dfc5ac42aed, 0x53380d139d95b3df, +0x650a73548baf63de, 0x766a0abb3c77b2a8, +0x81c2c92e47edaee6, 0x92722c851482353b, +0xa2bfe8a14cf10364, 0xa81a664bbc423001, +0xc24b8b70d0f89791, 0xc76c51a30654be30, +0xd192e819d6ef5218, 0xd69906245565a910, +0xf40e35855771202a, 0x106aa07032bbd1b8, +0x19a4c116b8d2d0c8, 0x1e376c085141ab53, +0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, +0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, +0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, +0x748f82ee5defb2fc, 0x78a5636f43172f60, +0x84c87814a1f0ab72, 0x8cc702081a6439ec, +0x90befffa23631e28, 0xa4506cebde82bde9, +0xbef9a3f7b2c67915, 0xc67178f2e372532b, +0xca273eceea26619c, 0xd186b8c721c0c207, +0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, +0x06f067aa72176fba, 0x0a637dc5a2c898a6, +0x113f9804bef90dae, 0x1b710b35131c471b, +0x28db77f523047d84, 0x32caab7b40c72493, +0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c, +0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, +0x5fcb6fab3ad6faec, 0x6c44198c4a475817 +}; + +#if __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr auto Sigma0(auto x) noexcept +{ + return std::rotr(x,28)^std::rotr(x,34)^std::rotr(x,39); +} + +#if __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr auto Sigma1(auto x) noexcept +{ + return std::rotr(x,14)^std::rotr(x,18)^std::rotr(x,41); +} + +inline constexpr auto sigma0(auto x) noexcept +{ + return std::rotr(x,1)^std::rotr(x,8)^(x>>7); +} + +inline constexpr auto sigma1(auto x) noexcept +{ + return std::rotr(x,19)^std::rotr(x,61)^(x>>6); +} + +#if __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr auto Ch(auto x,auto y,auto z) noexcept +{ + return (x&(y^z))^z; +} + +inline constexpr auto Maj(auto x,auto y,auto z) noexcept +{ + return (x&y)^(x&z)^(y&z); +} + +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr void sha512_scalar_round(std::uint_least64_t T1k,std::uint_least64_t a,std::uint_least64_t b,std::uint_least64_t& __restrict d, + std::uint_least64_t e,std::uint_least64_t f,std::uint_least64_t g,std::uint_least64_t& __restrict h,std::uint_least64_t& __restrict bpc) noexcept +{ + T1k+=h+Sigma1(e)+Ch(e,f,g); + h=Sigma0(a); + std::uint_least64_t apb{a^b}; + h+=(apb&bpc)^b; + bpc=apb; + d+=T1k; + h+=T1k; +} + +inline constexpr void sha512_do_constexpr_function(std::uint_least64_t* __restrict state,std::byte const* __restrict data,std::byte const* __restrict ed) noexcept +{ + std::uint_least64_t a{state[0]}, b{state[1]}, c{state[2]}, d{state[3]}, e{state[4]}, f{state[5]}, g{state[6]}, h{state[7]}, s0, s1, T1, T2; + std::uint_least64_t X[16]; + while(data!=ed) + { + std::uint_least32_t i{}; + for (; i < 16; ++i) + { + if (std::is_constant_evaluated()) + { + std::uint_least64_t value{}; + for(std::size_t j{};j!=8;++j) + { + value<<=8u; + value|=std::to_integer(data[j]); + } + X[i] = value; + } + else + { + std::uint_least64_t value; + ::fast_io::details::my_memcpy(__builtin_addressof(value),data,8); + X[i] = big_endian(value); + } + data += 8; + + T1 = h; + T1 += Sigma1(e); + T1 += Ch(e, f, g); + T1 += K512[i]; + T1 += X[i]; + + T2 = Sigma0(a); + T2 += Maj(a, b, c); + + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + } + + for (i = 16; i < 80; ++i) + { + s0 = X[(i + 1) & 0x0f]; + s0 = sigma0(s0); + s1 = X[(i + 14) & 0x0f]; + s1 = sigma1(s1); + + T1 = X[i & 0xf] += s0 + s1 + X[(i + 9) & 0xf]; + T1 += h + Sigma1(e) + Ch(e, f, g) + K512[i]; + T2 = Sigma0(a) + Maj(a, b, c); + + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + } + + a=(state[0] += a); + b=(state[1] += b); + c=(state[2] += c); + d=(state[3] += d); + e=(state[4] += e); + f=(state[5] += f); + g=(state[6] += g); + h=(state[7] += h); + } +} + +#if !(defined(_MSC_VER) && !defined(__clang__)) +#if defined(__SSE2__) && !defined(__AVX2__) && __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) +#include"sha512_simd32_shuffle.h" +#elif defined(__SSE2__) || defined(__wasm_simd128__) +#include"sha512_simd16.h" +#else +#include"sha512_scalar.h" +#endif +#else +#if (defined(__SSE2__) ||defined(__AVX2__)) || ((defined(_MSC_VER)&&!defined(__clang__)) && !defined(_KERNEL_MODE) && defined(_M_X64)) +#include"sha512_simd16.h" +#elif defined(_M_IX86_FP) +#if _M_IX86_FP == 2 +#include"sha512_simd16.h" +#endif +#else +#include"sha512_scalar.h" +#endif +#endif + +class sha512 +{ +public: + using state_value_type = std::uint_least64_t; + static inline constexpr std::size_t block_size{128}; + static inline constexpr std::endian hash_endian{std::endian::big}; + static inline constexpr std::size_t state_size{8}; + state_value_type state[state_size]; + inline +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L + constexpr +#endif + void update_blocks(std::byte const* blocks_start,std::byte const* blocks_last) noexcept + { +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if(__builtin_is_constant_evaluated()) +#endif + { + ::fast_io::details::sha512::sha512_do_constexpr_function(state,blocks_start,blocks_last); + } + else +#endif + { + ::fast_io::details::sha512::sha512_runtime_routine(state,blocks_start,blocks_last); + } + } +}; + +struct sha512_initializer +{ + static inline constexpr std::size_t digest_size{64}; + static inline constexpr ::fast_io::details::sha512::sha512 initialize_value{{0x6a09e667f3bcc908, 0xbb67ae8584caa73b,0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,0x510e527fade682d1, 0x9b05688c2b3e6c1f,0x1f83d9abfb41bd6b, 0x5be0cd19137e2179}}; + static inline constexpr void digest_to_byte_ptr(std::uint_least64_t const* digest,std::byte* ptr) noexcept + { + hash_digest_to_byte_ptr_common<::std::uint_least64_t,digest_size,std::endian::big>(digest,ptr); + } +}; + +struct sha512_224_initializer +{ + static inline constexpr std::size_t digest_size{28}; + static inline constexpr ::fast_io::details::sha512::sha512 initialize_value{{0x8c3d37c819544da2,0x73e1996689dcd4d6,0x1dfab7ae32ff9c82,0x679dd514582f9fcf,0x0f6d2b697bd44da8,0x77e36f7304c48942,0x3f9d85a86a1d36c8,0x1112e6ad91d692a1}}; + static inline constexpr void digest_to_byte_ptr(std::uint_least64_t const* digest,std::byte* ptr) noexcept + { + hash_digest_to_byte_ptr_common<::std::uint_least64_t,digest_size,std::endian::big>(digest,ptr); + } +}; + +struct sha512_256_initializer +{ + static inline constexpr std::size_t digest_size{32}; + static inline constexpr ::fast_io::details::sha512::sha512 initialize_value{{0x22312194fc2bf72c,0x9f555fa3c84c64c2,0x2393b86b6f53b151,0x963877195940eabd,0x96283ee2a88effe3,0xbe5e1e2553863992,0x2b0199fc2c85b8aa,0x0eb72ddc81c52ca2}}; + static inline constexpr void digest_to_byte_ptr(std::uint_least64_t const* digest,std::byte* ptr) noexcept + { + hash_digest_to_byte_ptr_common<::std::uint_least64_t,digest_size,std::endian::big>(digest,ptr); + } +}; + +struct sha384_initializer +{ + static inline constexpr std::size_t digest_size{48}; + static inline constexpr ::fast_io::details::sha512::sha512 initialize_value{{0xcbbb9d5dc1059ed8,0x629a292a367cd507,0x9159015a3070dd17,0x152fecd8f70e5939,0x67332667ffc00b31,0x8eb44a8768581511,0xdb0c2e0d64f98fa7,0x47b5481dbefa4fa4}}; + static inline constexpr void digest_to_byte_ptr(std::uint_least64_t const* digest,std::byte* ptr) noexcept + { + hash_digest_to_byte_ptr_common<::std::uint_least64_t,digest_size,::std::endian::big>(digest,ptr); + } +}; + +} + +namespace fast_io +{ +using sha512_224_context = ::fast_io::details::basic_md5_sha_context_impl<::fast_io::details::sha512::sha512,::fast_io::details::sha512::sha512_224_initializer,128>; +using sha512_256_context = ::fast_io::details::basic_md5_sha_context_impl<::fast_io::details::sha512::sha512,::fast_io::details::sha512::sha512_256_initializer,128>; +using sha384_context = ::fast_io::details::basic_md5_sha_context_impl<::fast_io::details::sha512::sha512,::fast_io::details::sha512::sha384_initializer,128>; +using sha512_context = ::fast_io::details::basic_md5_sha_context_impl<::fast_io::details::sha512::sha512,::fast_io::details::sha512::sha512_initializer,128>; +} diff --git a/src/fast_io/include/fast_io_crypto/hash/sha512_scalar.h b/src/fast_io/include/fast_io_crypto/hash/sha512_scalar.h new file mode 100644 index 0000000..c5b89f2 --- /dev/null +++ b/src/fast_io/include/fast_io_crypto/hash/sha512_scalar.h @@ -0,0 +1,99 @@ +#pragma once + +inline constexpr auto create_k512scalar() noexcept +{ + constexpr std::size_t n{sizeof(K512)/sizeof(std::uint_least64_t)}; + constexpr std::size_t nsub16{n-16u}; + ::fast_io::freestanding::array a; + for(std::size_t i{};i!=nsub16;++i) + { + a[i]=K512[i+16u]; + } + return a; +} + +inline constexpr auto k512scalar{create_k512scalar()}; + +#if __has_cpp_attribute(__gnu__::__flatten__) +[[__gnu__::__flatten__]] +#endif +#if __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr void sha512_round(std::uint_least64_t T1,std::uint_least64_t a,std::uint_least64_t b,std::uint_least64_t& __restrict d, + std::uint_least64_t e,std::uint_least64_t f,std::uint_least64_t g,std::uint_least64_t& __restrict h, + std::uint_least64_t& __restrict bpc,std::uint_least64_t k) noexcept +{ + sha512_scalar_round(T1+k,a,b,d,e,f,g,h,bpc); +} + +#if __has_cpp_attribute(__gnu__::__flatten__) +[[__gnu__::__flatten__]] +#endif +inline void sha512_runtime_routine(std::uint_least64_t* __restrict state,std::byte const* __restrict blocks_start,std::byte const* __restrict blocks_last) noexcept +{ + using ul64_may_alias +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = std::uint_least64_t; + std::uint_least64_t a{state[0]}; + std::uint_least64_t b{state[1]}; + std::uint_least64_t c{state[2]}; + std::uint_least64_t d{state[3]}; + std::uint_least64_t e{state[4]}; + std::uint_least64_t f{state[5]}; + std::uint_least64_t g{state[6]}; + std::uint_least64_t h{state[7]}; + std::uint_least64_t x[16]; + constexpr std::uint_least64_t const* k5_start{k512scalar.element}; + constexpr std::uint_least64_t const* k5_last{k512scalar.element+k512scalar.size()}; + for(;blocks_start!=blocks_last;blocks_start+=128) + { + ul64_may_alias const* W{reinterpret_cast(blocks_start)}; + std::uint_least64_t bpc{b^c}; + sha512_round(x[0]=big_endian(W[0]),a,b,d,e,f,g,h,bpc,0x428a2f98d728ae22); + sha512_round(x[1]=big_endian(W[1]),h,a,c,d,e,f,g,bpc,0x7137449123ef65cd); + sha512_round(x[2]=big_endian(W[2]),g,h,b,c,d,e,f,bpc,0xb5c0fbcfec4d3b2f); + sha512_round(x[3]=big_endian(W[3]),f,g,a,b,c,d,e,bpc,0xe9b5dba58189dbbc); + sha512_round(x[4]=big_endian(W[4]),e,f,h,a,b,c,d,bpc,0x3956c25bf348b538); + sha512_round(x[5]=big_endian(W[5]),d,e,g,h,a,b,c,bpc,0x59f111f1b605d019); + sha512_round(x[6]=big_endian(W[6]),c,d,f,g,h,a,b,bpc,0x923f82a4af194f9b); + sha512_round(x[7]=big_endian(W[7]),b,c,e,f,g,h,a,bpc,0xab1c5ed5da6d8118); + sha512_round(x[8]=big_endian(W[8]),a,b,d,e,f,g,h,bpc,0xd807aa98a3030242); + sha512_round(x[9]=big_endian(W[9]),h,a,c,d,e,f,g,bpc,0x12835b0145706fbe); + sha512_round(x[10]=big_endian(W[10]),g,h,b,c,d,e,f,bpc,0x243185be4ee4b28c); + sha512_round(x[11]=big_endian(W[11]),f,g,a,b,c,d,e,bpc,0x550c7dc3d5ffb4e2); + sha512_round(x[12]=big_endian(W[12]),e,f,h,a,b,c,d,bpc,0x72be5d74f27b896f); + sha512_round(x[13]=big_endian(W[13]),d,e,g,h,a,b,c,bpc,0x80deb1fe3b1696b1); + sha512_round(x[14]=big_endian(W[14]),c,d,f,g,h,a,b,bpc,0x9bdc06a725c71235); + sha512_round(x[15]=big_endian(W[15]),b,c,e,f,g,h,a,bpc,0xc19bf174cf692694); + for(std::uint_least64_t const *k5{k5_start};k5!=k5_last;k5+=16) + { + sha512_round((x[0]+=sigma0(x[1])+sigma1(x[14])+x[9]),a,b,d,e,f,g,h,bpc,*k5); + sha512_round((x[1]+=sigma0(x[2])+sigma1(x[15])+x[10]),h,a,c,d,e,f,g,bpc,k5[1]); + sha512_round((x[2]+=sigma0(x[3])+sigma1(x[0])+x[11]),g,h,b,c,d,e,f,bpc,k5[2]); + sha512_round((x[3]+=sigma0(x[4])+sigma1(x[1])+x[12]),f,g,a,b,c,d,e,bpc,k5[3]); + sha512_round((x[4]+=sigma0(x[5])+sigma1(x[2])+x[13]),e,f,h,a,b,c,d,bpc,k5[4]); + sha512_round((x[5]+=sigma0(x[6])+sigma1(x[3])+x[14]),d,e,g,h,a,b,c,bpc,k5[5]); + sha512_round((x[6]+=sigma0(x[7])+sigma1(x[4])+x[15]),c,d,f,g,h,a,b,bpc,k5[6]); + sha512_round((x[7]+=sigma0(x[8])+sigma1(x[5])+x[0]),b,c,e,f,g,h,a,bpc,k5[7]); + sha512_round((x[8]+=sigma0(x[9])+sigma1(x[6])+x[1]),a,b,d,e,f,g,h,bpc,k5[8]); + sha512_round((x[9]+=sigma0(x[10])+sigma1(x[7])+x[2]),h,a,c,d,e,f,g,bpc,k5[9]); + sha512_round((x[10]+=sigma0(x[11])+sigma1(x[8])+x[3]),g,h,b,c,d,e,f,bpc,k5[10]); + sha512_round((x[11]+=sigma0(x[12])+sigma1(x[9])+x[4]),f,g,a,b,c,d,e,bpc,k5[11]); + sha512_round((x[12]+=sigma0(x[13])+sigma1(x[10])+x[5]),e,f,h,a,b,c,d,bpc,k5[12]); + sha512_round((x[13]+=sigma0(x[14])+sigma1(x[11])+x[6]),d,e,g,h,a,b,c,bpc,k5[13]); + sha512_round((x[14]+=sigma0(x[15])+sigma1(x[12])+x[7]),c,d,f,g,h,a,b,bpc,k5[14]); + sha512_round((x[15]+=sigma0(x[0])+sigma1(x[13])+x[8]),b,c,e,f,g,h,a,bpc,k5[15]); + } + a=(*state+=a); + b=(state[1]+=b); + c=(state[2]+=c); + d=(state[3]+=d); + e=(state[4]+=e); + f=(state[5]+=f); + g=(state[6]+=g); + h=(state[7]+=h); + } +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_crypto/hash/sha512_simd16.h b/src/fast_io/include/fast_io_crypto/hash/sha512_simd16.h new file mode 100644 index 0000000..98752aa --- /dev/null +++ b/src/fast_io/include/fast_io_crypto/hash/sha512_simd16.h @@ -0,0 +1,163 @@ +#pragma once + +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline void sha512_simd16_byte_swap_message_2rounds(::fast_io::intrinsics::simd_vector& __restrict s1, + std::byte const* __restrict blocks_start,std::uint_least64_t* __restrict w,std::uint_least64_t* __restrict wt,std::uint_fast16_t round) noexcept +{ + using namespace ::fast_io::intrinsics; + simd_vector s0; + s1.load(blocks_start+(round<<3u)); + s0.load(::fast_io::details::sha512::K512+round); + if constexpr(std::endian::native==std::endian::little) + { + s1.swap_endian(); + } + s1.store(w+round); + s0.wrap_add_assign(s1); + s0.store(wt); +} + +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline void sha512_simd16_compute_message_2rounds( + ::fast_io::intrinsics::simd_vector& __restrict s1, + std::uint_least64_t* __restrict w,std::uint_least64_t* __restrict wt,std::uint_fast8_t round) noexcept +{ + using namespace ::fast_io::intrinsics; + simd_vector s0; + s0.load(w+(round-15)); + if constexpr(true) + { + s1=(((((s1>>42)^s1)>>13)^s1)>>6)^(((s1<<42)^s1)<<3); + s0=(((((s0>>1)^s0)>>6)^s0)>>1)^(((s0<<7)^s0)<<56); + } + else if constexpr(false) + { + s1=(s1>>19)^(s1<<45)^(s1>>61)^(s1<<3)^(s1>>6); + s0=(s0>>1)^(s0<<63)^(s0>>8)^(s0<<56)^(s0>>7); + } + else + { + s1=wrap_add((s1>>19),(s1<<45))^wrap_add((s1>>61),(s1<<3))^(s1>>6); + s0=wrap_add((s0>>1),(s0<<63))^wrap_add((s0>>8),(s0<<56))^(s0>>7); + } + s1.wrap_add_assign(s0); + s0.load(w+(round-16)); + s1.wrap_add_assign(s0); + s0.load(w+(round-7)); + s1.wrap_add_assign(s0); + s1.store(w+round); + s0.load(::fast_io::details::sha512::K512+round); + s0.wrap_add_assign(s1); + s0.store(wt); +} + + +#if __has_cpp_attribute(__gnu__::__target__) && __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 +inline void sha512_runtime_routine(std::uint_least64_t* __restrict state,std::byte const* __restrict blocks_start,std::byte const* __restrict blocks_last) noexcept +{ + using namespace fast_io::intrinsics; + using namespace fast_io::details::sha512; + + simd_vector simd; + + std::uint_least64_t w[80]; + std::uint_least64_t wt0[2],wt1[2]; + std::uint_least64_t a{state[0]}; + std::uint_least64_t b{state[1]}; + std::uint_least64_t c{state[2]}; + std::uint_least64_t d{state[3]}; + std::uint_least64_t e{state[4]}; + std::uint_least64_t f{state[5]}; + std::uint_least64_t g{state[6]}; + std::uint_least64_t h{state[7]}; + + for(;blocks_start!=blocks_last;blocks_start+=128) + { + sha512_simd16_byte_swap_message_2rounds(simd,blocks_start,w,wt0,0); + sha512_simd16_byte_swap_message_2rounds(simd,blocks_start,w,wt1,2); + std::uint_least64_t bpc{b^c}; + sha512_scalar_round(wt0[0],a,b,d,e,f,g,h,bpc); + sha512_scalar_round(wt0[1],h,a,c,d,e,f,g,bpc); + + sha512_simd16_byte_swap_message_2rounds(simd,blocks_start,w,wt0,4); + sha512_scalar_round(wt1[0],g,h,b,c,d,e,f,bpc); + sha512_scalar_round(wt1[1],f,g,a,b,c,d,e,bpc); + + sha512_simd16_byte_swap_message_2rounds(simd,blocks_start,w,wt1,6); + sha512_scalar_round(wt0[0],e,f,h,a,b,c,d,bpc); + sha512_scalar_round(wt0[1],d,e,g,h,a,b,c,bpc); + + sha512_simd16_byte_swap_message_2rounds(simd,blocks_start,w,wt0,8); + sha512_scalar_round(wt1[0],c,d,f,g,h,a,b,bpc); + sha512_scalar_round(wt1[1],b,c,e,f,g,h,a,bpc); + + sha512_simd16_byte_swap_message_2rounds(simd,blocks_start,w,wt1,10); + sha512_scalar_round(wt0[0],a,b,d,e,f,g,h,bpc); + sha512_scalar_round(wt0[1],h,a,c,d,e,f,g,bpc); + + sha512_simd16_byte_swap_message_2rounds(simd,blocks_start,w,wt0,12); + sha512_scalar_round(wt1[0],g,h,b,c,d,e,f,bpc); + sha512_scalar_round(wt1[1],f,g,a,b,c,d,e,bpc); + + sha512_simd16_byte_swap_message_2rounds(simd,blocks_start,w,wt1,14); + sha512_scalar_round(wt0[0],e,f,h,a,b,c,d,bpc); + sha512_scalar_round(wt0[1],d,e,g,h,a,b,c,bpc); + + for(std::uint_fast8_t i{14};i!=78;i+=16) + { + sha512_simd16_compute_message_2rounds(simd,w,wt0,i+2); + sha512_scalar_round(wt1[0],c,d,f,g,h,a,b,bpc); + sha512_scalar_round(wt1[1],b,c,e,f,g,h,a,bpc); + + sha512_simd16_compute_message_2rounds(simd,w,wt1,i+4); + sha512_scalar_round(wt0[0],a,b,d,e,f,g,h,bpc); + sha512_scalar_round(wt0[1],h,a,c,d,e,f,g,bpc); + + sha512_simd16_compute_message_2rounds(simd,w,wt0,i+6); + sha512_scalar_round(wt1[0],g,h,b,c,d,e,f,bpc); + sha512_scalar_round(wt1[1],f,g,a,b,c,d,e,bpc); + + sha512_simd16_compute_message_2rounds(simd,w,wt1,i+8); + sha512_scalar_round(wt0[0],e,f,h,a,b,c,d,bpc); + sha512_scalar_round(wt0[1],d,e,g,h,a,b,c,bpc); + + sha512_simd16_compute_message_2rounds(simd,w,wt0,i+10); + sha512_scalar_round(wt1[0],c,d,f,g,h,a,b,bpc); + sha512_scalar_round(wt1[1],b,c,e,f,g,h,a,bpc); + + sha512_simd16_compute_message_2rounds(simd,w,wt1,i+12); + sha512_scalar_round(wt0[0],a,b,d,e,f,g,h,bpc); + sha512_scalar_round(wt0[1],h,a,c,d,e,f,g,bpc); + + sha512_simd16_compute_message_2rounds(simd,w,wt0,i+14); + sha512_scalar_round(wt1[0],g,h,b,c,d,e,f,bpc); + sha512_scalar_round(wt1[1],f,g,a,b,c,d,e,bpc); + + sha512_simd16_compute_message_2rounds(simd,w,wt1,i+16); + sha512_scalar_round(wt0[0],e,f,h,a,b,c,d,bpc); + sha512_scalar_round(wt0[1],d,e,g,h,a,b,c,bpc); + } + sha512_scalar_round(wt1[0],c,d,f,g,h,a,b,bpc); + sha512_scalar_round(wt1[1],b,c,e,f,g,h,a,bpc); + a=(*state+=a); + b=(state[1]+=b); + c=(state[2]+=c); + d=(state[3]+=d); + e=(state[4]+=e); + f=(state[5]+=f); + g=(state[6]+=g); + h=(state[7]+=h); + } +} diff --git a/src/fast_io/include/fast_io_crypto/hash/sha512_simd32.h b/src/fast_io/include/fast_io_crypto/hash/sha512_simd32.h new file mode 100644 index 0000000..6ba930c --- /dev/null +++ b/src/fast_io/include/fast_io_crypto/hash/sha512_simd32.h @@ -0,0 +1,154 @@ +#pragma once + +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#endif +inline void sha512_simd32_byte_swap_message_4rounds(::fast_io::intrinsics::simd_vector& __restrict s1, + std::byte const* __restrict blocks_start,std::uint_least64_t* __restrict w,std::uint_least64_t* __restrict wt,std::size_t round) noexcept +{ + using namespace ::fast_io::intrinsics; + simd_vector s0; + s1.load(blocks_start+(round*8u)); + s0.load(K512+round); + if constexpr(std::endian::native==std::endian::little) + { + s1.swap_endian(); + } + s1.store(w+round); + s0.wrap_add_assign(s1); + s0.store(wt); +} + +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#endif +inline void sha512_simd32_compute_message_4rounds(::fast_io::intrinsics::simd_vector& __restrict s1, + std::uint_least64_t* __restrict w,std::uint_least64_t* __restrict wt,std::size_t round) noexcept +{ +/* +s0(w[t])=(w[t-15]>>1) ^ (w[t-15]<<63)^ (w[t-15]>>8) ^ (w[t-15]<<56) ^ (w[t-15]>>7) +s1(w[t])=(w[t-2]>>19) ^ (w[t-2]<<45) ^ (w[t-2]>>61) ^ (w[t-2]<<3) ^ (w[t-2]>>6) +w[i] = w[i-16] + w[i-7] + s0[i] + s1[i] +wt[r,r+1,r+2,r+3]=wt[r-16,r-15,r-14,r-13]+wt[r-7,r-6,r-5,r-4] +*/ + using namespace ::fast_io::intrinsics; + simd_vector s0; + s0.load(w+(round-15)); + +#if 0 + s1=(s1>>19)^(s1<<45)^(s1>>61)^(s1<<3)^(s1>>6); + s0=(s0>>1)^(s0<<63)^(s0>>8)^(s0<<56)^(s0>>7); +#else + s1=(((((s1>>42)^s1)>>13)^s1)>>6)^(((s1<<42)^s1)<<3); + s0=(((((s0>>1)^s0)>>6)^s0)>>1)^(((s0<<7)^s0)<<56); +#endif + + simd_vector s2; + s2.load(w+(round-16));//s2=w[i-16] + s2.wrap_add_assign(s0);//s2=s0[i]+w[i-16] + s0.load(w+(round-7));//s0=w[i-7] + s2.wrap_add_assign(s0);//s2=w[i-16]+w[i-7]+s0[i] + + simd_vector s2low{__builtin_shufflevector(s2.value,s2.value,0,1)}; + + s2low.wrap_add_assign(s1);//s2low=w[i-16]+w[i-7]+s0[i]+s1[i] + s1.value=__builtin_shufflevector(s2.value,s2.value,2,3); + + simd_vector s3{s2low}; +#if 0 + s3=(s3>>19)^(s3<<45)^(s3>>61)^(s3<<3)^(s3>>6); +#else + s3=(((((s3>>42)^s3)>>13)^s3)>>6)^(((s3<<42)^s3)<<3); +#endif + + s1.wrap_add_assign(s3); + s2.value=__builtin_shufflevector(s2low.value,s1.value,0,1,2,3); + s2.store(w+round); + s0.load(::fast_io::details::sha512::K512+round); + s0.wrap_add_assign(s2); + s0.store(wt); +} + +#if __has_cpp_attribute(__gnu__::__target__) && __has_builtin(__builtin_shufflevector) && defined(__SSE2__) && !defined(__AVX2__) && defined(__ELF__) +[[__gnu__::__target__("avx2")]] +#elif __has_cpp_attribute(__gnu__::__flatten__) +[[__gnu__::__flatten__]] +#endif +inline void sha512_runtime_routine(std::uint_least64_t* __restrict state,std::byte const* __restrict blocks_start,std::byte const* __restrict blocks_last) noexcept +{ + using namespace fast_io::intrinsics; + using namespace fast_io::details::sha512; + + simd_vector simd; + + std::uint_least64_t w[80]; + std::uint_least64_t wt0[4],wt1[4]; + std::uint_least64_t a{state[0]}; + std::uint_least64_t b{state[1]}; + std::uint_least64_t c{state[2]}; + std::uint_least64_t d{state[3]}; + std::uint_least64_t e{state[4]}; + std::uint_least64_t f{state[5]}; + std::uint_least64_t g{state[6]}; + std::uint_least64_t h{state[7]}; + + for(;blocks_start!=blocks_last;blocks_start+=128) + { + sha512_simd32_byte_swap_message_4rounds(simd,blocks_start,w,wt0,0); + sha512_simd32_byte_swap_message_4rounds(simd,blocks_start,w,wt1,4); + std::uint_least64_t bpc{b^c}; + sha512_scalar_round(wt0[0],a,b,d,e,f,g,h,bpc); + sha512_scalar_round(wt0[1],h,a,c,d,e,f,g,bpc); + sha512_scalar_round(wt0[2],g,h,b,c,d,e,f,bpc); + sha512_scalar_round(wt0[3],f,g,a,b,c,d,e,bpc); + sha512_simd32_byte_swap_message_4rounds(simd,blocks_start,w,wt0,8); + sha512_scalar_round(wt1[0],e,f,h,a,b,c,d,bpc); + sha512_scalar_round(wt1[1],d,e,g,h,a,b,c,bpc); + sha512_scalar_round(wt1[2],c,d,f,g,h,a,b,bpc); + sha512_scalar_round(wt1[3],b,c,e,f,g,h,a,bpc); + sha512_simd32_byte_swap_message_4rounds(simd,blocks_start,w,wt1,12); + sha512_scalar_round(wt0[0],a,b,d,e,f,g,h,bpc); + sha512_scalar_round(wt0[1],h,a,c,d,e,f,g,bpc); + sha512_scalar_round(wt0[2],g,h,b,c,d,e,f,bpc); + sha512_scalar_round(wt0[3],f,g,a,b,c,d,e,bpc); + simd_vector simd2{__builtin_shufflevector(simd.value,simd.value,2,3)}; + for(std::uint_fast8_t i{12};i!=76;i+=16) + { + sha512_simd32_compute_message_4rounds(simd2,w,wt0,i+4); + sha512_scalar_round(wt1[0],e,f,h,a,b,c,d,bpc); + sha512_scalar_round(wt1[1],d,e,g,h,a,b,c,bpc); + sha512_scalar_round(wt1[2],c,d,f,g,h,a,b,bpc); + sha512_scalar_round(wt1[3],b,c,e,f,g,h,a,bpc); + sha512_simd32_compute_message_4rounds(simd2,w,wt1,i+8); + sha512_scalar_round(wt0[0],a,b,d,e,f,g,h,bpc); + sha512_scalar_round(wt0[1],h,a,c,d,e,f,g,bpc); + sha512_scalar_round(wt0[2],g,h,b,c,d,e,f,bpc); + sha512_scalar_round(wt0[3],f,g,a,b,c,d,e,bpc); + + sha512_simd32_compute_message_4rounds(simd2,w,wt0,i+12); + sha512_scalar_round(wt1[0],e,f,h,a,b,c,d,bpc); + sha512_scalar_round(wt1[1],d,e,g,h,a,b,c,bpc); + sha512_scalar_round(wt1[2],c,d,f,g,h,a,b,bpc); + sha512_scalar_round(wt1[3],b,c,e,f,g,h,a,bpc); + sha512_simd32_compute_message_4rounds(simd2,w,wt1,i+16); + sha512_scalar_round(wt0[0],a,b,d,e,f,g,h,bpc); + sha512_scalar_round(wt0[1],h,a,c,d,e,f,g,bpc); + sha512_scalar_round(wt0[2],g,h,b,c,d,e,f,bpc); + sha512_scalar_round(wt0[3],f,g,a,b,c,d,e,bpc); + + } + sha512_scalar_round(wt1[0],e,f,h,a,b,c,d,bpc); + sha512_scalar_round(wt1[1],d,e,g,h,a,b,c,bpc); + sha512_scalar_round(wt1[2],c,d,f,g,h,a,b,bpc); + sha512_scalar_round(wt1[3],b,c,e,f,g,h,a,bpc); + + a=(*state+=a); + b=(state[1]+=b); + c=(state[2]+=c); + d=(state[3]+=d); + e=(state[4]+=e); + f=(state[5]+=f); + g=(state[6]+=g); + h=(state[7]+=h); + } +} diff --git a/src/fast_io/include/fast_io_crypto/hash/sha512_simd32_shuffle.h b/src/fast_io/include/fast_io_crypto/hash/sha512_simd32_shuffle.h new file mode 100644 index 0000000..391604c --- /dev/null +++ b/src/fast_io/include/fast_io_crypto/hash/sha512_simd32_shuffle.h @@ -0,0 +1,410 @@ +#pragma once + +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#endif +inline void sha512_simd32_byte_swap_message_4rounds(::fast_io::intrinsics::simd_vector& __restrict s1, + std::byte const* __restrict blocks_start,std::uint_least64_t* __restrict w,std::uint_least64_t* __restrict wt,std::size_t round) noexcept +{ + using namespace ::fast_io::intrinsics; + simd_vector s0; + s1.load(blocks_start+(round*8u)); + s0.load(K512+round); + if constexpr(std::endian::native==std::endian::little) + { + s1.swap_endian(); + } + s1.store(w+round); + s0.wrap_add_assign(s1); + s0.store(wt); +} + +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#endif +inline void sha512_simd32_compute_message_4rounds( + ::fast_io::intrinsics::simd_vector& __restrict s1, + std::uint_least64_t* __restrict w,std::uint_least64_t* __restrict wt + ,std::uint_least64_t* __restrict wt1,std::size_t round, + + std::uint_least64_t& a,std::uint_least64_t& b, + std::uint_least64_t& c,std::uint_least64_t& d, + std::uint_least64_t& e,std::uint_least64_t& f, + std::uint_least64_t& g,std::uint_least64_t& h, + std::uint_least64_t& bpc + ) noexcept +{ +/* +s0(w[t])=(w[t-15]>>1) ^ (w[t-15]<<63)^ (w[t-15]>>8) ^ (w[t-15]<<56) ^ (w[t-15]>>7) +s1(w[t])=(w[t-2]>>19) ^ (w[t-2]<<45) ^ (w[t-2]>>61) ^ (w[t-2]<<3) ^ (w[t-2]>>6) +w[i] = w[i-16] + w[i-7] + s0[i] + s1[i] +wt[r,r+1,r+2,r+3]=wt[r-16,r-15,r-14,r-13]+wt[r-7,r-6,r-5,r-4] +*/ + + using namespace ::fast_io::intrinsics; + simd_vector s0,s2,s0temp,s0temp2; + simd_vector s2low,s3,s1temp,s1temp2; + std::uint_least64_t temp,temp1,T1k,apb; + if constexpr(false) + { + s0.load(w+(round-15)); + s1temp=s1>>19; + s1temp2=s1<<45; + s1temp^=s1temp2; + s1temp2=s1>>61; + s1temp^=s1temp2; + s1temp2=s1<<3; + s1temp^=s1temp2; + s1temp2=s1>>6; + s1=s1temp^s1temp2; + s0temp=s0>>1; + s0temp2=s0<<63; + s0temp^=s0temp2; + s0temp2=s0>>8; + s0temp^=s0temp2; + s0temp2=s0<<56; + s0temp^=s0temp2; + s0temp2=s0>>7; + s0=s0temp^s0temp2; + s2.load(w+(round-16)); + s2.wrap_add_assign(s0); + s0.load(w+(round-7)); + s2.wrap_add_assign(s0); + s2low.value=__builtin_shufflevector(s2.value,s2.value,0,1); + s2low.wrap_add_assign(s1); + s1.value=__builtin_shufflevector(s2.value,s2.value,2,3); + s1temp=s2low>>19; + s1temp2=s2low<<45; + s1temp^=s1temp2; + s1temp2=s2low>>61; + s1temp^=s1temp2; + s1temp2=s2low<<3; + s1temp^=s1temp2; + s1temp2=s2low>>6; + s3=s1temp^s1temp2; + s1.wrap_add_assign(s3); + s2.value=__builtin_shufflevector(s2low.value,s1.value,0,1,2,3); + s2.store(w+round); + s0.load(::fast_io::details::sha512::K512+round); + s0.wrap_add_assign(s2); + s0.store(wt1); + + T1k=h; + T1k+=wt[0]; + temp=std::rotr(e,14); + temp1=std::rotr(e,18); + temp^=temp1; + temp1=std::rotr(e,41); + temp^=temp1; + T1k+=temp; + temp=f^g; + temp&=e; + temp^=g; + T1k+=temp; + temp=std::rotr(a,28); + temp1=std::rotr(a,34); + temp^=temp1; + temp1=std::rotr(a,39); + h=temp^temp1; + apb=a^b; + temp=apb&bpc; + bpc=apb; + temp^=b; + h+=temp; + bpc=apb; + d+=T1k; + h+=T1k; + + T1k=g; + T1k+=wt[1]; + temp=std::rotr(d,14); + temp1=std::rotr(d,18); + temp^=temp1; + temp1=std::rotr(d,41); + temp^=temp1; + T1k+=temp; + temp=e^f; + temp&=d; + temp^=f; + T1k+=temp; + temp=std::rotr(h,28); + temp1=std::rotr(h,34); + temp^=temp1; + temp1=std::rotr(h,39); + g=temp^temp1; + apb=h^a; + temp=apb&bpc; + bpc=apb; + temp^=a; + g+=temp; + bpc=apb; + c+=T1k; + g+=T1k; + + T1k=f; + T1k+=wt[2]; + temp=std::rotr(c,14); + temp1=std::rotr(c,18); + temp^=temp1; + temp1=std::rotr(c,41); + temp^=temp1; + T1k+=temp; + temp=d^e; + temp&=c; + temp^=e; + T1k+=temp; + temp=std::rotr(g,28); + temp1=std::rotr(g,34); + temp^=temp1; + temp1=std::rotr(g,39); + f=temp^temp1; + apb=g^h; + temp=apb&bpc; + bpc=apb; + temp^=h; + f+=temp; + bpc=apb; + b+=T1k; + f+=T1k; + + T1k=e; + T1k+=wt[3]; + temp=std::rotr(b,14); + temp1=std::rotr(b,18); + temp^=temp1; + temp1=std::rotr(b,41); + temp^=temp1; + T1k+=temp; + temp=c^d; + temp&=b; + temp^=d; + T1k+=temp; + temp=std::rotr(f,28); + temp1=std::rotr(f,34); + temp^=temp1; + temp1=std::rotr(f,39); + e=temp^temp1; + apb=f^g; + temp=apb&bpc; + bpc=apb; + temp^=g; + e+=temp; + bpc=apb; + a+=T1k; + e+=T1k; + } + else + { + s0.load(w+(round-15)); + T1k=h; + T1k+=wt[0]; + s1temp=s1>>19; + temp=std::rotr(e,14); + temp1=std::rotr(e,18); + s1temp2=s1<<45; + temp^=temp1; + temp1=std::rotr(e,41); + s1temp^=s1temp2; + temp^=temp1; + T1k+=temp; + s1temp2=s1>>61; + temp=f^g; + temp&=e; + s1temp^=s1temp2; + temp^=g; + T1k+=temp; + s1temp2=s1<<3; + temp=std::rotr(a,28); + temp1=std::rotr(a,34); + s1temp^=s1temp2; + temp^=temp1; + temp1=std::rotr(a,39); + s1temp2=s1>>6; + h=temp^temp1; + apb=a^b; + s1=s1temp^s1temp2; + temp=apb&bpc; + bpc=apb; + s0temp=s0>>1; + temp^=b; + h+=temp; + s0temp2=s0<<63; + bpc=apb; + d+=T1k; + s0temp^=s0temp2; + h+=T1k; + T1k=g; + s0temp2=s0>>8; + T1k+=wt[1]; + temp=std::rotr(d,14); + s0temp^=s0temp2; + temp1=std::rotr(d,18); + temp^=temp1; + s0temp2=s0<<56; + temp1=std::rotr(d,41); + temp^=temp1; + s0temp^=s0temp2; + T1k+=temp; + temp=e^f; + s0temp2=s0>>7; + temp&=d; + temp^=f; + s0=s0temp^s0temp2; + T1k+=temp; + temp=std::rotr(h,28); + s2.load(w+(round-16)); + temp1=std::rotr(h,34); + temp^=temp1; + s2.wrap_add_assign(s0); + temp1=std::rotr(h,39); + g=temp^temp1; + s0.load(w+(round-7)); + apb=h^a; + temp=apb&bpc; + s2.wrap_add_assign(s0); + bpc=apb; + temp^=a; + s2low.value=__builtin_shufflevector(s2.value,s2.value,0,1); + g+=temp; + bpc=apb; + s2low.wrap_add_assign(s1); + c+=T1k; + g+=T1k; + s1.value=__builtin_shufflevector(s2.value,s2.value,2,3); + T1k=f; + T1k+=wt[2]; + s1temp=s2low>>19; + temp=std::rotr(c,14); + temp1=std::rotr(c,18); + s1temp2=s2low<<45; + temp^=temp1; + temp1=std::rotr(c,41); + s1temp^=s1temp2; + temp^=temp1; + T1k+=temp; + s1temp2=s2low>>61; + temp=d^e; + temp&=c; + s1temp^=s1temp2; + temp^=e; + T1k+=temp; + s1temp2=s2low<<3; + temp=std::rotr(g,28); + temp1=std::rotr(g,34); + s1temp^=s1temp2; + temp^=temp1; + temp1=std::rotr(g,39); + s1temp2=s2low>>6; + f=temp^temp1; + apb=g^h; + s3=s1temp^s1temp2; + temp=apb&bpc; + bpc=apb; + s1.wrap_add_assign(s3); + temp^=h; + f+=temp; + s2.value=__builtin_shufflevector(s2low.value,s1.value,0,1,2,3); + bpc=apb; + b+=T1k; + s2.store(w+round); + f+=T1k; + T1k=e; + s0.load(::fast_io::details::sha512::K512+round); + T1k+=wt[3]; + temp=std::rotr(b,14); + s0.wrap_add_assign(s2); + temp1=std::rotr(b,18); + temp^=temp1; + s0.store(wt1); + temp1=std::rotr(b,41); + temp^=temp1; + T1k+=temp; + temp=c^d; + temp&=b; + temp^=d; + T1k+=temp; + temp=std::rotr(f,28); + temp1=std::rotr(f,34); + temp^=temp1; + temp1=std::rotr(f,39); + e=temp^temp1; + apb=f^g; + temp=apb&bpc; + bpc=apb; + temp^=g; + e+=temp; + bpc=apb; + a+=T1k; + e+=T1k; + } +} + +#if __has_cpp_attribute(__gnu__::__target__) && __has_builtin(__builtin_shufflevector) && defined(__SSE2__) && !defined(__AVX2__) && defined(__ELF__) && defined(FAST_IO_RUNTIME_DISPATCH) +[[__gnu__::__target__("avx2")]] +#elif __has_cpp_attribute(__gnu__::__flatten__) +[[__gnu__::__flatten__]] +#endif +inline void sha512_runtime_routine(std::uint_least64_t* __restrict state,std::byte const* __restrict blocks_start,std::byte const* __restrict blocks_last) noexcept +{ + using namespace fast_io::intrinsics; + using namespace fast_io::details::sha512; + + simd_vector simd; + + std::uint_least64_t wt0[4],wt1[4]; + std::uint_least64_t w[80]; + std::uint_least64_t a{state[0]}; + std::uint_least64_t b{state[1]}; + std::uint_least64_t c{state[2]}; + std::uint_least64_t d{state[3]}; + std::uint_least64_t e{state[4]}; + std::uint_least64_t f{state[5]}; + std::uint_least64_t g{state[6]}; + std::uint_least64_t h{state[7]}; + + for(;blocks_start!=blocks_last;blocks_start+=128) + { + sha512_simd32_byte_swap_message_4rounds(simd,blocks_start,w,wt0,0); + sha512_simd32_byte_swap_message_4rounds(simd,blocks_start,w,wt1,4); + std::uint_least64_t bpc{b^c}; + sha512_scalar_round(wt0[0],a,b,d,e,f,g,h,bpc); + sha512_scalar_round(wt0[1],h,a,c,d,e,f,g,bpc); + sha512_scalar_round(wt0[2],g,h,b,c,d,e,f,bpc); + sha512_scalar_round(wt0[3],f,g,a,b,c,d,e,bpc); + sha512_simd32_byte_swap_message_4rounds(simd,blocks_start,w,wt0,8); + sha512_scalar_round(wt1[0],e,f,h,a,b,c,d,bpc); + sha512_scalar_round(wt1[1],d,e,g,h,a,b,c,bpc); + sha512_scalar_round(wt1[2],c,d,f,g,h,a,b,bpc); + sha512_scalar_round(wt1[3],b,c,e,f,g,h,a,bpc); + sha512_simd32_byte_swap_message_4rounds(simd,blocks_start,w,wt1,12); + sha512_scalar_round(wt0[0],a,b,d,e,f,g,h,bpc); + sha512_scalar_round(wt0[1],h,a,c,d,e,f,g,bpc); + sha512_scalar_round(wt0[2],g,h,b,c,d,e,f,bpc); + sha512_scalar_round(wt0[3],f,g,a,b,c,d,e,bpc); + simd_vector simd2{__builtin_shufflevector(simd.value,simd.value,2,3)}; + for(std::uint_fast8_t i{16};i!=80;i+=16) + { + sha512_simd32_compute_message_4rounds(simd2,w,wt1,wt0,i, + e,f,g,h,a,b,c,d,bpc); + sha512_simd32_compute_message_4rounds(simd2,w,wt0,wt1,i+4, + a,b,c,d,e,f,g,h,bpc); + sha512_simd32_compute_message_4rounds(simd2,w,wt1,wt0,i+8, + e,f,g,h,a,b,c,d,bpc); + sha512_simd32_compute_message_4rounds(simd2,w,wt0,wt1,i+12, + a,b,c,d,e,f,g,h,bpc); + } + sha512_scalar_round(wt1[0],e,f,h,a,b,c,d,bpc); + sha512_scalar_round(wt1[1],d,e,g,h,a,b,c,bpc); + sha512_scalar_round(wt1[2],c,d,f,g,h,a,b,bpc); + sha512_scalar_round(wt1[3],b,c,e,f,g,h,a,bpc); + + a=(*state+=a); + b=(state[1]+=b); + c=(state[2]+=c); + d=(state[3]+=d); + e=(state[4]+=e); + f=(state[5]+=f); + g=(state[6]+=g); + h=(state[7]+=h); + } +} diff --git a/src/fast_io/include/fast_io_crypto/padding/padding.h b/src/fast_io/include/fast_io_crypto/padding/padding.h new file mode 100644 index 0000000..4bdb34e --- /dev/null +++ b/src/fast_io/include/fast_io_crypto/padding/padding.h @@ -0,0 +1,4 @@ +#pragma once + +#include "zero_padding.h" +#include "pkcs7_padding.h" diff --git a/src/fast_io/include/fast_io_crypto/padding/pkcs7_padding.h b/src/fast_io/include/fast_io_crypto/padding/pkcs7_padding.h new file mode 100644 index 0000000..c3573f1 --- /dev/null +++ b/src/fast_io/include/fast_io_crypto/padding/pkcs7_padding.h @@ -0,0 +1,20 @@ + +#pragma once + +namespace fast_io::crypto +{ + +template +struct pkcs7_padding +{ + auto operator()(std::span inp, std::size_t remaining_length) + { + std::byte pad(static_cast(static_cast(remaining_length & 0xFF))); + ::fast_io::freestanding::array text{}; + details::my_copy(inp.begin(), inp.end(), text.data()); + for (std::size_t i(block_size - 1); i >= block_size - remaining_length; --i) + text[i] = pad; + return text; + } +}; +}; diff --git a/src/fast_io/include/fast_io_crypto/padding/zero_padding.h b/src/fast_io/include/fast_io_crypto/padding/zero_padding.h new file mode 100644 index 0000000..f12b68d --- /dev/null +++ b/src/fast_io/include/fast_io_crypto/padding/zero_padding.h @@ -0,0 +1,17 @@ + +#pragma once + +namespace fast_io::crypto +{ + +template +struct zero_padding +{ + auto operator()(std::span inp, std::size_t remaining_length) + { + ::fast_io::freestanding::array text{}; + details::my_copy(inp.begin(), inp.end(), text.data()); + return text; + } +}; +}; diff --git a/src/fast_io/include/fast_io_crypto/platforms/impl.h b/src/fast_io/include/fast_io_crypto/platforms/impl.h new file mode 100644 index 0000000..c8bafe5 --- /dev/null +++ b/src/fast_io/include/fast_io_crypto/platforms/impl.h @@ -0,0 +1,22 @@ +#pragma once + +#if (defined(_WIN32) && !defined(__WINE__)) || defined(__CYGWIN__) +#include"win32/impl.h" +#include"nt_bcrypt.h" +#endif + +#if __has_include() +#include +#include"ossl_evp.h" +#endif + +namespace fast_io +{ + +#if (defined(_WIN32) && !defined(__WINE__)) || defined(__CYGWIN__) +using native_hash_file = nt_bcrypt_hash_file; +#elif __has_include() +using native_hash_file = ossl_evp_hash_file; +#endif + +} diff --git a/src/fast_io/include/fast_io_crypto/platforms/nt_bcrypt.h b/src/fast_io/include/fast_io_crypto/platforms/nt_bcrypt.h new file mode 100644 index 0000000..f0ced06 --- /dev/null +++ b/src/fast_io/include/fast_io_crypto/platforms/nt_bcrypt.h @@ -0,0 +1,193 @@ +#pragma once + +namespace fast_io +{ + +class nt_bcrypt_hash_file; + +namespace details +{ +inline void create_bcrypt_common_hash_impl(nt_bcrypt_hash_file& g,char16_t const* name); + +template +inline void create_nt_bcrypt_impl(nt_bcrypt_hash_file& h,T const& t); + +inline void ntbcrypt_update_impl(void* hashHandle,::std::byte const* first,::std::byte const* last); + +inline void ntbcrypt_do_final_impl(void* hashhandle,::std::byte* buffer,::std::uint_least32_t bcrypt_size); +} + +class nt_bcrypt_hash_file +{ +public: + using native_handle_type = void*; + native_handle_type phAlgorithm{}; + native_handle_type hashHandle{}; + ::std::uint_least32_t bcrypt_size{}; + std::byte* digest_buffer{}; + constexpr nt_bcrypt_hash_file() noexcept = default; + template + explicit nt_bcrypt_hash_file(T const& s) + { + ::fast_io::details::create_nt_bcrypt_impl(*this,s); + } + nt_bcrypt_hash_file(nt_bcrypt_hash_file const&)=delete; + nt_bcrypt_hash_file& operator=(nt_bcrypt_hash_file const&)=delete; + ~nt_bcrypt_hash_file() + { + if(digest_buffer) + { + ::fast_io::details::deallocate_with_secure_clear(digest_buffer,bcrypt_size); + } + if(this->hashHandle) + { + ::fast_io::win32::BCryptDestroyHash(this->hashHandle); + } + if(this->phAlgorithm) + { + ::fast_io::win32::BCryptCloseAlgorithmProvider(this->phAlgorithm,0u); + } + } + void update(::std::byte const* first,::std::byte const* last) + { + ::fast_io::details::ntbcrypt_update_impl(this->hashHandle,first,last); + } + void do_final() + { + ::fast_io::details::ntbcrypt_do_final_impl(this->hashHandle,digest_buffer,bcrypt_size); + } + void reset() + { + this->do_final(); + } + constexpr std::size_t runtime_digest_size() const noexcept + { + return bcrypt_size; + } + constexpr std::byte const* digest_byte_ptr() const noexcept + { + return digest_buffer; + } +}; + +namespace details +{ + +struct bcrypt_algo_guard +{ + void* phalgo{}; + explicit constexpr bcrypt_algo_guard() noexcept = default; + bcrypt_algo_guard(bcrypt_algo_guard const&)=delete; + bcrypt_algo_guard& operator=(bcrypt_algo_guard const&)=delete; + ~bcrypt_algo_guard() + { + if(this->phalgo) + { + ::fast_io::win32::BCryptCloseAlgorithmProvider(this->phalgo,0u); + } + } + void* release() noexcept + { + auto temp{this->phalgo}; + this->phalgo=nullptr; + return temp; + } +}; + +inline void create_bcrypt_common_hash_impl(nt_bcrypt_hash_file& g,char16_t const* name) +{ + void* phalgo{}; + ::std::uint_least32_t status{::fast_io::win32::BCryptOpenAlgorithmProvider(__builtin_addressof(phalgo),name,nullptr,0u)}; + if(status) + { + throw_nt_error(status); + } + bcrypt_algo_guard guard; + guard.phalgo=phalgo; + ::std::uint_least32_t hash_digest_length{},result_length{}; + status=::fast_io::win32::BCryptGetProperty(phalgo,u"HashDigestLength",__builtin_addressof(hash_digest_length), + sizeof(hash_digest_length),__builtin_addressof(result_length),0u); + if(status) + { + throw_nt_error(status); + } + ::fast_io::details::local_operator_new_array_ptr<::std::byte> locarr(hash_digest_length); + void* hash_handle{}; + status=::fast_io::win32::BCryptCreateHash(phalgo,__builtin_addressof(hash_handle),nullptr,0u,nullptr,0u,0x00000020); + if(status) + { + throw_nt_error(status); + } + g.phAlgorithm=guard.release(); + g.hashHandle=hash_handle; + g.bcrypt_size=static_cast<::std::uint_least32_t>(hash_digest_length); + g.digest_buffer=locarr.ptr; + locarr.ptr=nullptr; + locarr.size=0u; +} + +struct bcrypt_common +{ + nt_bcrypt_hash_file* fl{}; + inline void operator()(char16_t const* name) const + { + using char16_t_may_alias_const_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = char16_t const*; + create_bcrypt_common_hash_impl(*(this->fl),reinterpret_cast(name)); + } +}; + +template +inline void create_nt_bcrypt_impl(nt_bcrypt_hash_file& h,T const& t) +{ + nt_api_common(t,bcrypt_common{__builtin_addressof(h)}); +} + +inline void ntbcrypt_update_impl(void* hashHandle,::std::byte const* first,::std::byte const* last) +{ + if constexpr(sizeof(::std::ptrdiff_t)<=sizeof(::std::uint_least32_t)) + { + ::std::uint_least32_t ntstatus{::fast_io::win32::BCryptHashData(hashHandle,first, + static_cast<::std::uint_least32_t>(static_cast(last-first)),0u)}; + if(ntstatus) + { + throw_nt_error(ntstatus); + } + } + else + { + constexpr std::size_t ul32_max{static_cast(std::numeric_limits::max())}; + for(std::size_t sz{static_cast(last-first)};sz;) + { + std::size_t mn{sz}; + if(ul32_max(mn),0u)}; + if(ntstatus) + { + throw_nt_error(ntstatus); + } + sz-=mn; + first+=mn; + } + } +} + +inline void ntbcrypt_do_final_impl(void* hashhandle,::std::byte* buffer,::std::uint_least32_t bcrypt_size) +{ + ::std::uint_least32_t ntstatus{::fast_io::win32::BCryptFinishHash(hashhandle,buffer,bcrypt_size,0u)}; + if(ntstatus) + { + throw_nt_error(ntstatus); + } +} + +} + +} diff --git a/src/fast_io/include/fast_io_crypto/platforms/ossl_evp.h b/src/fast_io/include/fast_io_crypto/platforms/ossl_evp.h new file mode 100644 index 0000000..6036a41 --- /dev/null +++ b/src/fast_io/include/fast_io_crypto/platforms/ossl_evp.h @@ -0,0 +1,122 @@ +#pragma once + +namespace fast_io +{ + +namespace details +{ + +class ossl_evp_guard +{ +public: + EVP_MD_CTX* pmdctx{}; + ossl_evp_guard():pmdctx{noexcept_call(EVP_MD_CTX_new)} + { + if(this->pmdctx==nullptr) + { + throw_posix_error(EINVAL); + } + } + ossl_evp_guard(ossl_evp_guard const&)=delete; + ossl_evp_guard& operator=(ossl_evp_guard const&)=delete; + EVP_MD_CTX* release() noexcept + { + auto temp{pmdctx}; + this->pmdctx=nullptr; + return temp; + } + ~ossl_evp_guard() + { + if(this->pmdctx) + { + noexcept_call(EVP_MD_CTX_free,this->pmdctx); + } + } +}; + +inline EVP_MD_CTX* create_ossl_evp_hash_impl(char const* name) +{ + auto md{noexcept_call(EVP_get_digestbyname,name)}; + if(md==nullptr) + { + throw_posix_error(EINVAL); + } + ossl_evp_guard guard; + if(!noexcept_call(EVP_DigestInit_ex,guard.pmdctx,md,nullptr)) + { + throw_posix_error(EINVAL); + } + return guard.release(); +} + +struct ossl_evp_common +{ + inline EVP_MD_CTX* operator()(char const* name) const + { + return create_ossl_evp_hash_impl(name); + } +}; + +template +inline EVP_MD_CTX* create_ossl_evp_hash_impl(T const& t) +{ + return posix_api_common(t,ossl_evp_common{}); +} + +} + +class ossl_evp_hash_file +{ +public: + using native_handle_type = EVP_MD_CTX*; + static inline constexpr std::size_t evp_max_md_size{EVP_MAX_MD_SIZE}; + native_handle_type pmdctx{}; + std::size_t evp_size{}; + ::std::byte digest_buffer[evp_max_md_size]; + constexpr ossl_evp_hash_file() noexcept = default; + template + explicit ossl_evp_hash_file(T const& s):pmdctx{::fast_io::details::create_ossl_evp_hash_impl(s)}{} + ossl_evp_hash_file(ossl_evp_hash_file const&)=delete; + ossl_evp_hash_file& operator=(ossl_evp_hash_file const&)=delete; + ~ossl_evp_hash_file() + { + if(this->pmdctx) + { + noexcept_call(EVP_MD_CTX_free,this->pmdctx); + } + } + void update(std::byte const* first,std::byte const* last) + { + if(!noexcept_call(EVP_DigestUpdate,this->pmdctx,first,static_cast(last-first))) + { + throw_posix_error(EINVAL); + } + } + void reset() + { + noexcept_call(EVP_MD_CTX_reset,this->pmdctx); + } + inline constexpr native_handle_type native_handle() const noexcept + { + return this->pmdctx; + } + void do_final() + { + int unsigned u{}; + if(!noexcept_call(EVP_DigestFinal_ex,this->pmdctx,reinterpret_cast(digest_buffer),__builtin_addressof(u))) + { + throw_posix_error(EINVAL); + } + evp_size=static_cast(u); + } + constexpr std::size_t runtime_digest_size() const noexcept + { + return evp_size; + } + constexpr std::byte const* digest_byte_ptr() const noexcept + { + return digest_buffer; + } +}; + +} diff --git a/src/fast_io/include/fast_io_crypto/platforms/win32/apis.h b/src/fast_io/include/fast_io_crypto/platforms/win32/apis.h new file mode 100644 index 0000000..7aee100 --- /dev/null +++ b/src/fast_io/include/fast_io_crypto/platforms/win32/apis.h @@ -0,0 +1,189 @@ +#pragma once + +namespace fast_io::win32 +{ + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern ::std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +BCryptOpenAlgorithmProvider(void**,char16_t const*,char16_t const*,::std::uint_least32_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("BCryptOpenAlgorithmProvider@16") +#else +__asm__("_BCryptOpenAlgorithmProvider@16") +#endif +#else +__asm__("BCryptOpenAlgorithmProvider") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern ::std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +BCryptCloseAlgorithmProvider(void*,::std::uint_least32_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("BCryptCloseAlgorithmProvider@8") +#else +__asm__("_BCryptCloseAlgorithmProvider@8") +#endif +#else +__asm__("BCryptCloseAlgorithmProvider") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern ::std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +BCryptGetProperty(void*,char16_t const*,void*,::std::uint_least32_t,::std::uint_least32_t*,::std::uint_least32_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("BCryptGetProperty@24") +#else +__asm__("_BCryptGetProperty@24") +#endif +#else +__asm__("BCryptGetProperty") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern ::std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +BCryptCreateHash(void*,void**,void*,::std::uint_least32_t,void*,::std::uint_least32_t,::std::uint_least32_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("BCryptCreateHash@28") +#else +__asm__("_BCryptCreateHash@28") +#endif +#else +__asm__("BCryptCreateHash") +#endif +#endif +; + + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern ::std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +BCryptHashData(void*,void const*,::std::uint_least32_t,::std::uint_least32_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("BCryptHashData@16") +#else +__asm__("_BCryptHashData@16") +#endif +#else +__asm__("BCryptHashData") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern ::std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +BCryptFinishHash(void*,void*,::std::uint_least32_t,::std::uint_least32_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("BCryptFinishHash@16") +#else +__asm__("_BCryptFinishHash@16") +#endif +#else +__asm__("BCryptFinishHash") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern ::std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +BCryptDestroyHash(void*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("BCryptDestroyHash@4") +#else +__asm__("_BCryptDestroyHash@4") +#endif +#else +__asm__("BCryptDestroyHash") +#endif +#endif +; + +} diff --git a/src/fast_io/include/fast_io_crypto/platforms/win32/impl.h b/src/fast_io/include/fast_io_crypto/platforms/win32/impl.h new file mode 100644 index 0000000..15f70b1 --- /dev/null +++ b/src/fast_io/include/fast_io_crypto/platforms/win32/impl.h @@ -0,0 +1,6 @@ +#pragma once + +#include"apis.h" +#if defined(_MSC_VER) && !defined(__clang__) +#include"msvc_linker.h" +#endif diff --git a/src/fast_io/include/fast_io_crypto/platforms/win32/msvc_linker.h b/src/fast_io/include/fast_io_crypto/platforms/win32/msvc_linker.h new file mode 100644 index 0000000..54d279d --- /dev/null +++ b/src/fast_io/include/fast_io_crypto/platforms/win32/msvc_linker.h @@ -0,0 +1,9 @@ +#pragma once + +#if SIZE_MAX > UINT_LEAST32_MAX +#include"msvc_linker_64.h" +#elif defined(__x86__) || defined(_M_IX86) || defined(__i386__) +#include"msvc_linker_32_i686.h" +#else +#include"msvc_linker_32.h" +#endif diff --git a/src/fast_io/include/fast_io_crypto/platforms/win32/msvc_linker_32.h b/src/fast_io/include/fast_io_crypto/platforms/win32/msvc_linker_32.h new file mode 100644 index 0000000..4c706ec --- /dev/null +++ b/src/fast_io/include/fast_io_crypto/platforms/win32/msvc_linker_32.h @@ -0,0 +1,9 @@ +#pragma once + +#pragma comment(linker,"/alternatename:__imp_?BCryptOpenAlgorithmProvider@win32@fast_io@@YAIPAPAXPB_S1I@Z=__imp_BCryptOpenAlgorithmProvider") +#pragma comment(linker,"/alternatename:__imp_?BCryptCloseAlgorithmProvider@win32@fast_io@@YAIPAXI@Z=__imp_BCryptCloseAlgorithmProvider") +#pragma comment(linker,"/alternatename:__imp_?BCryptGetProperty@win32@fast_io@@YAIPAXPB_S0IPAII@Z=__imp_BCryptGetProperty") +#pragma comment(linker,"/alternatename:__imp_?BCryptCreateHash@win32@fast_io@@YAIPAXPAPAX0I0II@Z=__imp_BCryptCreateHash") +#pragma comment(linker,"/alternatename:__imp_?BCryptHashData@win32@fast_io@@YAIPAXPBXII@Z=__imp_BCryptHashData") +#pragma comment(linker,"/alternatename:__imp_?BCryptFinishHash@win32@fast_io@@YAIPAX0II@Z=__imp_BCryptFinishHash") +#pragma comment(linker,"/alternatename:__imp_?BCryptDestroyHash@win32@fast_io@@YAIPAX@Z=__imp_BCryptDestroyHash") diff --git a/src/fast_io/include/fast_io_crypto/platforms/win32/msvc_linker_32_i686.h b/src/fast_io/include/fast_io_crypto/platforms/win32/msvc_linker_32_i686.h new file mode 100644 index 0000000..1bfe15b --- /dev/null +++ b/src/fast_io/include/fast_io_crypto/platforms/win32/msvc_linker_32_i686.h @@ -0,0 +1,9 @@ +#pragma once + +#pragma comment(linker,"/alternatename:__imp_?BCryptOpenAlgorithmProvider@win32@fast_io@@YGIPAPAXPB_S1I@Z=__imp__BCryptOpenAlgorithmProvider@16") +#pragma comment(linker,"/alternatename:__imp_?BCryptCloseAlgorithmProvider@win32@fast_io@@YGIPAXI@Z=__imp__BCryptCloseAlgorithmProvider@8") +#pragma comment(linker,"/alternatename:__imp_?BCryptGetProperty@win32@fast_io@@YGIPAXPB_S0IPAII@Z=__imp__BCryptGetProperty@24") +#pragma comment(linker,"/alternatename:__imp_?BCryptCreateHash@win32@fast_io@@YGIPAXPAPAX0I0II@Z=__imp__BCryptCreateHash@28") +#pragma comment(linker,"/alternatename:__imp_?BCryptHashData@win32@fast_io@@YGIPAXPBXII@Z=__imp__BCryptHashData@16") +#pragma comment(linker,"/alternatename:__imp_?BCryptFinishHash@win32@fast_io@@YGIPAX0II@Z=__imp__BCryptFinishHash@16") +#pragma comment(linker,"/alternatename:__imp_?BCryptDestroyHash@win32@fast_io@@YGIPAX@Z=__imp__BCryptDestroyHash@4") diff --git a/src/fast_io/include/fast_io_crypto/platforms/win32/msvc_linker_64.h b/src/fast_io/include/fast_io_crypto/platforms/win32/msvc_linker_64.h new file mode 100644 index 0000000..2c00493 --- /dev/null +++ b/src/fast_io/include/fast_io_crypto/platforms/win32/msvc_linker_64.h @@ -0,0 +1,9 @@ +#pragma once + +#pragma comment(linker,"/alternatename:__imp_?BCryptOpenAlgorithmProvider@win32@fast_io@@YAIPEAPEAXPEB_S1I@Z=__imp_BCryptOpenAlgorithmProvider") +#pragma comment(linker,"/alternatename:__imp_?BCryptCloseAlgorithmProvider@win32@fast_io@@YAIPEAXI@Z=__imp_BCryptCloseAlgorithmProvider") +#pragma comment(linker,"/alternatename:__imp_?BCryptGetProperty@win32@fast_io@@YAIPEAXPEB_S0IPEAII@Z=__imp_BCryptGetProperty") +#pragma comment(linker,"/alternatename:__imp_?BCryptCreateHash@win32@fast_io@@YAIPEAXPEAPEAX0I0II@Z=__imp_BCryptCreateHash") +#pragma comment(linker,"/alternatename:__imp_?BCryptHashData@win32@fast_io@@YAIPEAXPEBXII@Z=__imp_BCryptHashData") +#pragma comment(linker,"/alternatename:__imp_?BCryptFinishHash@win32@fast_io@@YAIPEAX0II@Z=__imp_BCryptFinishHash") +#pragma comment(linker,"/alternatename:__imp_?BCryptDestroyHash@win32@fast_io@@YAIPEAX@Z=__imp_BCryptDestroyHash") diff --git a/src/fast_io/include/fast_io_crypto/streamcipher/chacha/impl.h b/src/fast_io/include/fast_io_crypto/streamcipher/chacha/impl.h new file mode 100644 index 0000000..9fb13ec --- /dev/null +++ b/src/fast_io/include/fast_io_crypto/streamcipher/chacha/impl.h @@ -0,0 +1,35 @@ +#pragma once + +#include"scalar.h" +#if (defined(__GNUC__) || defined(__clang__)) && (defined(__SSE__)||defined(__wasm_simd128__)) +#if __has_builtin(__builtin_shufflevector) +#include"simd16.h" +#else +#include"runtime.h" +#endif +#else +#include"runtime.h" +#endif + + +namespace fast_io +{ +#if 0 +struct chacha +{ + using state_value_type = std::uint_least32_t; + static inline constexpr std::size_t block_size{64}; + static inline constexpr std::endian cipher_endian{std::endian::little}; + static inline constexpr std::size_t state_size{16}; + state_value_type state[state_size]; +#if __cpp_lib_is_constant_evaluated >= 201811L + constexpr +#endif + void update_block(::std::byte* __restrict outdata, + ::std::uint_least32_t const* __restrict indata) noexcept + { + + } +} +#endif +} diff --git a/src/fast_io/include/fast_io_crypto/streamcipher/chacha/runtime.h b/src/fast_io/include/fast_io_crypto/streamcipher/chacha/runtime.h new file mode 100644 index 0000000..f596be0 --- /dev/null +++ b/src/fast_io/include/fast_io_crypto/streamcipher/chacha/runtime.h @@ -0,0 +1,13 @@ +#pragma once + +namespace fast_io::details::chacha +{ +#if __has_cpp_attribute(__gnu__::__flatten__) +[[__gnu__::__flatten__]] +#endif +inline constexpr void chacha_runtime_routine(::std::byte* __restrict outdata, + ::std::uint_least32_t const* __restrict indata) noexcept +{ + chacha_main_routine(outdata,indata); +} +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_crypto/streamcipher/chacha/scalar.h b/src/fast_io/include/fast_io_crypto/streamcipher/chacha/scalar.h new file mode 100644 index 0000000..dd1d238 --- /dev/null +++ b/src/fast_io/include/fast_io_crypto/streamcipher/chacha/scalar.h @@ -0,0 +1,110 @@ +#pragma once +/* +https://en.wikipedia.org/wiki/Salsa20#ChaCha_variant +*/ +namespace fast_io +{ + +namespace details::chacha +{ + +inline constexpr void chachaqr(::std::uint_least32_t& __restrict a, + ::std::uint_least32_t& __restrict b, + ::std::uint_least32_t& __restrict c, + ::std::uint_least32_t& __restrict d) noexcept +{ + a += b; + d ^= a; + d = ::std::rotl(d,16); + + c += d; + b ^= c; + b = ::std::rotl(b,12); + + a += b; + d ^= a; + d = ::std::rotl(d, 8); + + c += d; + b ^= c; + b = ::std::rotl(b, 7); +} + +#if __has_cpp_attribute(__gnu__::__flatten__) +[[__gnu__::__flatten__]] +#endif +inline +#if (__cpp_lib_is_constant_evaluated >=201811L || __cpp_if_consteval >= 202106L) && __cpp_lib_bit_cast >= 201806L +constexpr +#endif +void chacha_main_routine(::std::byte* __restrict outdata, + ::std::uint_least32_t const* __restrict indata) noexcept +{ + constexpr + ::std::size_t n{16}; + ::std::uint_least32_t x[n]; +#if __cpp_lib_is_constant_evaluated >=201811L || __cpp_if_consteval >= 202106L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if(std::is_constant_evaluated()) +#endif + { + for(std::size_t i{};i!=n;++i) + x[i]=indata[i]; + } + else +#endif + { + __builtin_memcpy(x,indata,sizeof(x)); + } + constexpr + ::std::uint_least8_t rounds{20}; + constexpr + ::std::uint_least8_t roundsdiv2{rounds/2}; + for (::std::uint_fast8_t i{}; i != roundsdiv2; ++i) + { + // Odd round + chachaqr(x[0], x[4], x[ 8], x[12]); // column 0 + chachaqr(x[1], x[5], x[ 9], x[13]); // column 1 + chachaqr(x[2], x[6], x[10], x[14]); // column 2 + chachaqr(x[3], x[7], x[11], x[15]); // column 3 + // Even round + chachaqr(x[0], x[5], x[10], x[15]); // diagonal 1 (main diagonal) + chachaqr(x[1], x[6], x[11], x[12]); // diagonal 2 + chachaqr(x[2], x[7], x[ 8], x[13]); // diagonal 3 + chachaqr(x[3], x[4], x[ 9], x[14]); // diagonal 4 + } + + for(::std::size_t i{};i!=n;++i) + { + std::uint_least32_t res{x[i]+indata[i]}; + if constexpr(::std::endian::little!=::std::endian::native) + { + res=::fast_io::byte_swap(res); + } +#if __cpp_lib_is_constant_evaluated >=201811L || __cpp_if_consteval >= 202106L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if(std::is_constant_evaluated()) +#endif + { + auto v{::std::bit_cast<::fast_io::freestanding::array<::std::byte,sizeof(::std::uint_least32_t)>>(res)}; + for(::std::size_t j{};j!=sizeof(::std::uint_least32_t);++j) + { + outdata[i*sizeof(::std::uint_least32_t)+j]=v[j]; + } + } + else +#endif + { + __builtin_memcpy(outdata+i*sizeof(::std::uint_least32_t),__builtin_addressof(res),sizeof(::std::uint_least32_t)); + } + } + +} + +} + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_crypto/streamcipher/chacha/simd16.h b/src/fast_io/include/fast_io_crypto/streamcipher/chacha/simd16.h new file mode 100644 index 0000000..372166e --- /dev/null +++ b/src/fast_io/include/fast_io_crypto/streamcipher/chacha/simd16.h @@ -0,0 +1,97 @@ +#pragma once + +namespace fast_io::details::chacha +{ + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +#if __has_cpp_attribute(__gnu__::__flatten__) +[[__gnu__::__flatten__]] +#endif +inline void chacha_simd16_qr4_round_impl( +::fast_io::intrinsics::simd_vector<::std::uint_least32_t,4>& __restrict a, +::fast_io::intrinsics::simd_vector<::std::uint_least32_t,4>& __restrict b, +::fast_io::intrinsics::simd_vector<::std::uint_least32_t,4>& __restrict c, +::fast_io::intrinsics::simd_vector<::std::uint_least32_t,4>& __restrict d +) noexcept +{ + if constexpr(evenround) + { + b.value=__builtin_shufflevector(b.value,b.value,3,0,1,2); + c.value=__builtin_shufflevector(c.value,c.value,2,3,0,1); + d.value=__builtin_shufflevector(d.value,d.value,1,2,3,0); + chacha_simd16_qr4_round_impl<0>(a,b,c,d); + b.value=__builtin_shufflevector(b.value,b.value,1,2,3,0); + c.value=__builtin_shufflevector(c.value,c.value,2,3,0,1); + d.value=__builtin_shufflevector(d.value,d.value,3,0,1,2); + } + else + { + a += b; + d ^= a; + d = (d<<16)+(d>>16); + + c += d; + b ^= c; + b = (b<<12)+(b>>20); + + a += b; + d ^= a; + d = (d<<8)+(d>>24); + + c += d; + b ^= c; + b = (b<<7)+(b>>25); + } + +} + +#if __has_cpp_attribute(__gnu__::__flatten__) +[[__gnu__::__flatten__]] +#endif +inline void chacha_runtime_routine(::std::byte* __restrict outdata, + ::std::uint_least32_t const* __restrict indata) noexcept +{ + constexpr + ::std::uint_least8_t rounds{20}; + constexpr + ::std::uint_least8_t roundsdiv4{rounds/4}; + ::fast_io::intrinsics::simd_vector<::std::uint_least32_t,4> a,b,c,d; + a.load(indata); + b.load(indata+4); + c.load(indata+8); + d.load(indata+12); + for(::std::uint_fast8_t i{};i!=roundsdiv4;++i) + { + chacha_simd16_qr4_round_impl<0>(a,b,c,d); + chacha_simd16_qr4_round_impl<1>(a,b,c,d); + chacha_simd16_qr4_round_impl<0>(a,b,c,d); + chacha_simd16_qr4_round_impl<1>(a,b,c,d); + } + ::fast_io::intrinsics::simd_vector<::std::uint_least32_t,4> t; + t.load(indata); + a+=t; + t.load(indata+4); + b+=t; + t.load(indata+8); + c+=t; + t.load(indata+12); + d+=t; + if constexpr(::std::endian::little!=::std::endian::native) + { + a.swap_endian(); + b.swap_endian(); + c.swap_endian(); + d.swap_endian(); + } + a.store(outdata); + b.store(outdata+4*sizeof(::std::uint_least32_t)); + c.store(outdata+8*sizeof(::std::uint_least32_t)); + d.store(outdata+12*sizeof(::std::uint_least32_t)); +} + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_crypto/tls/cipher_suite.h b/src/fast_io/include/fast_io_crypto/tls/cipher_suite.h new file mode 100644 index 0000000..31a50a9 --- /dev/null +++ b/src/fast_io/include/fast_io_crypto/tls/cipher_suite.h @@ -0,0 +1,166 @@ +#pragma once + +namespace fast_io::tls::cipher_suite +{ + + +struct cipher_suite_type +{ + ::fast_io::freestanding::array array{}; +}; + +inline constexpr bool operator==(cipher_suite_type const& a,cipher_suite_type const& b) +{ + return a.array==b.array; +} +inline constexpr bool operator!=(cipher_suite_type const& a,cipher_suite_type const& b) +{ + return a.array!=b.array; +} + +/* + +No TLS support before 1.2 +TLS 1.2 +rfc5246 +page 74 +https://tools.ietf.org/html/rfc5246 +*/ + +inline constexpr cipher_suite_type tls_rsa_with_null_null {{ std::byte(0x00),std::byte(0x00) }}; +inline constexpr cipher_suite_type tls_rsa_with_null_md5 {{ std::byte(0x00),std::byte(0x01) }}; +inline constexpr cipher_suite_type tls_rsa_with_null_sha {{ std::byte(0x00),std::byte(0x02) }}; +inline constexpr cipher_suite_type tls_rsa_with_null_sha256 {{ std::byte(0x00),std::byte(0x3B) }}; +inline constexpr cipher_suite_type tls_rsa_with_rc4_128_md5 {{ std::byte(0x00),std::byte(0x04) }}; +inline constexpr cipher_suite_type tls_rsa_with_rc4_128_sha {{ std::byte(0x00),std::byte(0x05) }}; +inline constexpr cipher_suite_type tls_rsa_with_3des_ede_cbc_sha {{ std::byte(0x00),std::byte(0x0A) }}; +inline constexpr cipher_suite_type tls_rsa_with_aes_128_cbc_sha {{ std::byte(0x00),std::byte(0x2F) }}; +inline constexpr cipher_suite_type tls_rsa_with_aes_256_cbc_sha {{ std::byte(0x00),std::byte(0x35) }}; +inline constexpr cipher_suite_type tls_rsa_with_aes_128_cbc_sha256 {{ std::byte(0x00),std::byte(0x3C) }}; +inline constexpr cipher_suite_type tls_rsa_with_aes_256_cbc_sha256 {{ std::byte(0x00),std::byte(0x3D) }}; + +inline constexpr cipher_suite_type tls_dh_dss_with_3des_ede_cbc_sha {{ std::byte(0x00),std::byte(0x0D) }}; +inline constexpr cipher_suite_type tls_dh_rsa_with_3des_ede_cbc_sha {{ std::byte(0x00),std::byte(0x10) }}; +inline constexpr cipher_suite_type tls_dhe_dss_with_3des_ede_cbc_sha {{ std::byte(0x00),std::byte(0x13) }}; +inline constexpr cipher_suite_type tls_dhe_rsa_with_3des_ede_cbc_sha {{ std::byte(0x00),std::byte(0x16) }}; +inline constexpr cipher_suite_type tls_dh_dss_with_aes_128_cbc_sha {{ std::byte(0x00),std::byte(0x30) }}; +inline constexpr cipher_suite_type tls_dh_rsa_with_aes_128_cbc_sha {{ std::byte(0x00),std::byte(0x31) }}; +inline constexpr cipher_suite_type tls_dhe_dss_with_aes_128_cbc_sha {{ std::byte(0x00),std::byte(0x32) }}; +inline constexpr cipher_suite_type tls_dhe_rsa_with_aes_128_cbc_sha {{ std::byte(0x00),std::byte(0x33) }}; +inline constexpr cipher_suite_type tls_dh_dss_with_aes_256_cbc_sha {{ std::byte(0x00),std::byte(0x36) }}; +inline constexpr cipher_suite_type tls_dh_rsa_with_aes_256_cbc_sha {{ std::byte(0x00),std::byte(0x37) }}; +inline constexpr cipher_suite_type tls_dhe_dss_with_aes_256_cbc_sha {{ std::byte(0x00),std::byte(0x38) }}; +inline constexpr cipher_suite_type tls_dhe_rsa_with_aes_256_cbc_sha {{ std::byte(0x00),std::byte(0x39) }}; +inline constexpr cipher_suite_type tls_dh_dss_with_aes_128_cbc_sha256 {{ std::byte(0x00),std::byte(0x3e) }}; +inline constexpr cipher_suite_type tls_dh_rsa_with_aes_128_cbc_sha256 {{ std::byte(0x00),std::byte(0x3f) }}; +inline constexpr cipher_suite_type tls_dhe_dss_with_aes_128_cbc_sha256 {{ std::byte(0x00),std::byte(0x40) }}; +inline constexpr cipher_suite_type tls_dhe_rsa_with_aes_128_cbc_sha256 {{ std::byte(0x00),std::byte(0x67) }}; +inline constexpr cipher_suite_type tls_dh_dss_with_aes_256_cbc_sha256 {{ std::byte(0x00),std::byte(0x68) }}; +inline constexpr cipher_suite_type tls_dh_rsa_with_aes_256_cbc_sha256 {{ std::byte(0x00),std::byte(0x69) }}; +inline constexpr cipher_suite_type tls_dhe_dss_with_aes_256_cbc_sha256 {{ std::byte(0x00),std::byte(0x6a) }}; +inline constexpr cipher_suite_type tls_dhe_rsa_with_aes_256_cbc_sha256 {{ std::byte(0x00),std::byte(0x6b) }}; +/* +TLS 1.3 +rfc +https://tools.ietf.org/html/rfc8446#page-133 + +------------------------------+-------------+ + | Description | Value | + +------------------------------+-------------+ + | TLS_AES_128_GCM_SHA256 | {0x13,0x01} | + | | | + | TLS_AES_256_GCM_SHA384 | {0x13,0x02} | + | | | + | TLS_CHACHA20_POLY1305_SHA256 | {0x13,0x03} | + | | | + | TLS_AES_128_CCM_SHA256 | {0x13,0x04} | + | | | + | TLS_AES_128_CCM_8_SHA256 | {0x13,0x05} | + +------------------------------+-------------+ +*/ + +inline constexpr cipher_suite_type tls_aes_128_gcm_sha256{{std::byte(0x13),std::byte(0x01)}}; +inline constexpr cipher_suite_type tls_aes_256_gcm_sha256{{std::byte(0x13),std::byte(0x02)}}; +inline constexpr cipher_suite_type tls_chacha20_poly1305_sha256{{std::byte(0x13),std::byte(0x03)}}; +inline constexpr cipher_suite_type tls_aes_128_ccm_sha256{{std::byte(0x13),std::byte(0x04)}}; +inline constexpr cipher_suite_type tls_aes_128_ccm_8_sha256{{std::byte(0x13),std::byte(0x05)}}; + +template +inline constexpr void print_define(output& outp,cipher_suite_type const& e) +{ + if(e==tls_rsa_with_null_null) + print_freestanding(outp,u8"TLS_RSA_WITH_NULL_NULL{0x00,0x00}"); + else if(e==tls_rsa_with_null_md5) + print_freestanding(outp,u8"TLS_RSA_WITH_NULL_MD5{0x00,0x01}"); + else if(e==tls_rsa_with_null_sha) + print_freestanding(outp,u8"TLS_RSA_WITH_NULL_SHA{0x00,0x02}"); + else if(e==tls_rsa_with_null_sha256) + print_freestanding(outp,u8"TLS_RSA_WITH_NULL_SHA256{0x00,0x3B}"); + else if(e==tls_rsa_with_rc4_128_md5) + print_freestanding(outp,u8"TLS_RSA_WITH_RC4_128_MD5{0x00,0x04}"); + else if(e==tls_rsa_with_rc4_128_sha) + print_freestanding(outp,u8"TLS_RSA_WITH_RC4_128_SHA{0x00,0x05}"); + else if(e==tls_rsa_with_3des_ede_cbc_sha) + print_freestanding(outp,u8"TLS_RSA_WITH_3DES_EDE_CBC_SHA{0x00,0x0A}"); + else if(e==tls_rsa_with_aes_128_cbc_sha) + print_freestanding(outp,u8"TLS_RSA_WITH_AES_128_CBC_SHA{0x00,0x2F}"); + else if(e==tls_rsa_with_aes_256_cbc_sha) + print_freestanding(outp,u8"TLS_RSA_WITH_AES_256_CBC_SHA{0x00,0x35}"); + else if(e==tls_rsa_with_aes_128_cbc_sha256) + print_freestanding(outp,u8"TLS_RSA_WITH_AES_128_CBC_SHA256{0x00,0x3C}"); + else if(e==tls_rsa_with_aes_256_cbc_sha256) + print_freestanding(outp,u8"TLS_RSA_WITH_AES_256_CBC_SHA256{0x00,0x3D}"); + else if(e==tls_dh_dss_with_3des_ede_cbc_sha) + print_freestanding(outp,u8"TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA{0x00,0x0D}"); + else if(e==tls_dh_rsa_with_3des_ede_cbc_sha) + print_freestanding(outp,u8"TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA{0x00,0x10}"); + else if(e==tls_dhe_dss_with_3des_ede_cbc_sha) + print_freestanding(outp,u8"TLS_DHE_RSS_WITH_3DES_EDE_CBC_SHA{0x00,0x13}"); + else if(e==tls_dhe_rsa_with_3des_ede_cbc_sha) + print_freestanding(outp,u8"TLS_DHE_RSS_WITH_3DES_EDE_CBC_SHA{0x00,0x16}"); + else if(e==tls_dh_dss_with_aes_128_cbc_sha) + print_freestanding(outp,u8"TLS_DH_DSS_WITH_AES_128_CBC_SHA{0x00,0x30}"); + else if(e==tls_dh_rsa_with_aes_128_cbc_sha) + print_freestanding(outp,u8"TLS_DH_RSA_WITH_AES_128_CBC_SHA{0x00,0x31}"); + else if(e==tls_dhe_dss_with_aes_128_cbc_sha) + print_freestanding(outp,u8"TLS_DHE_DSS_WITH_AES_128_CBC_SHA{0x00,0x32}"); + else if(e==tls_dhe_rsa_with_aes_128_cbc_sha) + print_freestanding(outp,u8"TLS_DHE_RSA_WITH_AES_128_CBC_SHA{0x00,0x33}"); + else if(e==tls_dh_dss_with_aes_256_cbc_sha) + print_freestanding(outp,u8"TLS_DH_DSS_WITH_AES_256_CBC_SHA{0x00,0x36}"); + else if(e==tls_dh_rsa_with_aes_256_cbc_sha) + print_freestanding(outp,u8"TLS_DH_RSA_WITH_AES_256_CBC_SHA{0x00,0x37}"); + else if(e==tls_dhe_dss_with_aes_256_cbc_sha) + print_freestanding(outp,u8"TLS_DHE_DSS_WITH_AES_256_CBC_SHA{0x00,0x38}"); + else if(e==tls_dhe_rsa_with_aes_256_cbc_sha) + print_freestanding(outp,u8"TLS_DHE_RSA_WITH_AES_256_CBC_SHA{0x00,0x39}"); + else if(e==tls_dh_dss_with_aes_128_cbc_sha256) + print_freestanding(outp,u8"TLS_DH_DSS_WITH_AES_128_CBC_SHA256{0x00,0x3e}"); + else if(e==tls_dh_rsa_with_aes_128_cbc_sha256) + print_freestanding(outp,u8"TLS_DH_RSA_WITH_AES_128_CBC_SHA256{0x00,0x3f}"); + else if(e==tls_dhe_dss_with_aes_128_cbc_sha256) + print_freestanding(outp,u8"TLS_DHE_DSS_WITH_AES_128_CBC_SHA256{0x00,0x40}"); + else if(e==tls_dhe_rsa_with_aes_128_cbc_sha256) + print_freestanding(outp,u8"TLS_DHE_RSA_WITH_AES_128_CBC_SHA256{0x00,0x67}"); + else if(e==tls_dh_dss_with_aes_256_cbc_sha256) + print_freestanding(outp,u8"TLS_DH_DSS_WITH_AES_256_CBC_SHA256{0x00,0x68}"); + else if(e==tls_dh_rsa_with_aes_256_cbc_sha256) + print_freestanding(outp,u8"TLS_DH_RSA_WITH_AES_256_CBC_SHA256{0x00,0x69}"); + else if(e==tls_dhe_dss_with_aes_256_cbc_sha256) + print_freestanding(outp,u8"TLS_DHE_DSS_WITH_AES_256_CBC_SHA256{0x00,0x6a}"); + else if(e==tls_dhe_rsa_with_aes_256_cbc_sha256) + print_freestanding(outp,u8"TLS_DHE_RSA_WITH_AES_256_CBC_SHA256{0x00,0x6b}"); + else if(e==tls_aes_128_gcm_sha256) + print_freestanding(outp,u8"TLS_AES_128_GCM_SHA256{0x13,0x01}"); + else if(e==tls_aes_256_gcm_sha256) + print_freestanding(outp,u8"TLS_AES_256_GCM_SHA256{0x13,0x02}"); + else if(e==tls_chacha20_poly1305_sha256) + print_freestanding(outp,u8"TLS_CHACHA20_POLY1305_SHA256{0x13,0x03}"); + else if(e==tls_aes_128_ccm_sha256) + print_freestanding(outp,u8"TLS_AES_128_CCM_SHA256{0x13,0x04}"); + else if(e==tls_aes_128_ccm_8_sha256) + print_freestanding(outp,u8"TLS_AES_128_CCM_8_SHA256{0x13,0x05}"); + else + print_freestanding(outp,u8"Unknown TLS cipher suite{",e.array.front(),fast_io::manipulators::chvw(u8','),e.array.back(),fast_io::manipulators::chvw(u8'}')); +} + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_crypto/tls/client_hello.h b/src/fast_io/include/fast_io_crypto/tls/client_hello.h new file mode 100644 index 0000000..82c1f1c --- /dev/null +++ b/src/fast_io/include/fast_io_crypto/tls/client_hello.h @@ -0,0 +1,20 @@ +#pragma once + +namespace fast_io::tls +{ + +struct client_hello +{ +std::uint_least8_t handshake_type=0x01; +::fast_io::freestanding::array size={0x00,0x01,0xFC}; +std::uint_least16_t protocal_version=0x0303; //TLS v1.2. IT MUST BE 0x0303 even for TLS v1.3 to prevent downgrade attack. +::fast_io::freestanding::array random{}; +std::uint_least8_t session_id_length{32}; +::fast_io::freestanding::array session_id{}; +::fast_io::freestanding::array cipher_suite_length={0x00,0x02}; +cipher_suite::cipher_suite_type cipher_suite{cipher_suite::tls_aes_256_gcm_sha256}; +std::uint_least8_t number_of_compression_length={0x01}; +std::uint_least8_t compression_method={}; +}; + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_crypto/tls/tls.h b/src/fast_io/include/fast_io_crypto/tls/tls.h new file mode 100644 index 0000000..4584d8f --- /dev/null +++ b/src/fast_io/include/fast_io_crypto/tls/tls.h @@ -0,0 +1,7 @@ +#pragma once + +#include"version.h" +#if 0 +#include"cipher_suite.h" +#include"client_hello.h" +#endif \ No newline at end of file diff --git a/src/fast_io/include/fast_io_crypto/tls/version.h b/src/fast_io/include/fast_io_crypto/tls/version.h new file mode 100644 index 0000000..550f270 --- /dev/null +++ b/src/fast_io/include/fast_io_crypto/tls/version.h @@ -0,0 +1,22 @@ +#pragma once + +namespace fast_io::tls +{ +/* +template +inline constexpr void print_define(output& outp,version tls) +{ + switch(tls) + { + case version::tls1_2: + print_freestanding(outp,u8"TLS 1.2"); + break; + case version::tls1_3: + print_freestanding(outp,u8"TLS 1.3"); + break; + default: + print_freestanding(outp,u8"TLS unknown version"); + } +} +*/ +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_device.h b/src/fast_io/include/fast_io_device.h new file mode 100644 index 0000000..17eb458 --- /dev/null +++ b/src/fast_io/include/fast_io_device.h @@ -0,0 +1,292 @@ +#pragma once +#if !defined(__cplusplus) +#error "You are not using a C++ compiler" +#endif + +#if !defined(__cpp_concepts) +#error "fast_io requires at least C++20 standard compiler." +#else +//fast_io_devices.h defines commonly used io devices and their correlated mutex verisons. +#include"fast_io_hosted.h" + + +#if ((__STDC_HOSTED__==1 && (!defined(_GLIBCXX_HOSTED) || _GLIBCXX_HOSTED==1) && !defined(_LIBCPP_FREESTANDING)) || defined(FAST_IO_ENABLE_HOSTED_FEATURES)) &&!defined(__AVR__) +namespace fast_io +{ + +/* +Special file type region. They are usually not used for I/O but for other purpose like I/O redirection. +However, they are still capable of doing I/O. +*/ + +using dir_file = directory_file_wrapper>; +using pipe = basic_native_pipe; + +/* +template region +*/ + +template +using basic_ibuf_pipe = basic_ibuf>; +template +using basic_obuf_pipe = basic_obuf>; +template +using basic_iobuf_pipe = basic_iobuf>; + +template +using basic_inative_file = input_file_wrapper>; +template +using basic_onative_file = output_file_wrapper>; + +template +using basic_ibuf_file = basic_ibuf>; +template +using basic_obuf_file = basic_obuf>; +template +using basic_iobuf_file = basic_iobuf>; + +template +using basic_ibuf_file_mutex = basic_iomutex>; +template +using basic_obuf_file_mutex = basic_iomutex>; +template +using basic_iobuf_file_mutex = basic_iomutex>; +/* +char region +*/ +using ibuf_pipe = basic_ibuf_pipe; +using obuf_pipe = basic_obuf_pipe; +using iobuf_pipe = basic_iobuf_pipe; + +using inative_file = basic_inative_file; +using onative_file = basic_onative_file; + +using ibuf_file = basic_ibuf_file; +using obuf_file = basic_obuf_file; +using iobuf_file = basic_iobuf_file; + +using ibuf_file_mutex = basic_ibuf_file_mutex; +using obuf_file_mutex = basic_obuf_file_mutex; +using iobuf_file_mutex = basic_iobuf_file_mutex; + +/* +wchar_t region +*/ +/* +libstdc++ bug on GCC 10. wchar_t does not satisfy the std::integral concept on MSDOS DJGPP toolchain. +Remove restriction after GCC 11.0 is released. +*/ +using wibuf_pipe = basic_ibuf_pipe; +using wobuf_pipe = basic_obuf_pipe; +using wiobuf_pipe = basic_iobuf_pipe; + +using winative_file = basic_inative_file; +using wonative_file = basic_onative_file; + +using wibuf_file = basic_ibuf_file; +using wobuf_file = basic_obuf_file; +using wiobuf_file = basic_iobuf_file; + +using wibuf_file_mutex = basic_ibuf_file_mutex; +using wobuf_file_mutex = basic_obuf_file_mutex; +using wiobuf_file_mutex = basic_iobuf_file_mutex; + +/* +char8_t region +*/ +using u8ibuf_pipe = basic_ibuf_pipe; +using u8obuf_pipe = basic_obuf_pipe; +using u8iobuf_pipe = basic_iobuf_pipe; + +using u8inative_file = basic_inative_file; +using u8onative_file = basic_onative_file; + +using u8ibuf_file = basic_ibuf_file; +using u8obuf_file = basic_obuf_file; +using u8iobuf_file = basic_iobuf_file; + +using u8ibuf_file_mutex = basic_ibuf_file_mutex; +using u8obuf_file_mutex = basic_obuf_file_mutex; +using u8iobuf_file_mutex = basic_iobuf_file_mutex; + +/* +char16_t region +*/ +using u16ibuf_pipe = basic_ibuf_pipe; +using u16obuf_pipe = basic_obuf_pipe; +using u16iobuf_pipe = basic_iobuf_pipe; + +using u16inative_file = basic_inative_file; +using u16onative_file = basic_onative_file; + +using u16ibuf_file = basic_ibuf_file; +using u16obuf_file = basic_obuf_file; +using u16iobuf_file = basic_iobuf_file; + +using u16ibuf_file_mutex = basic_ibuf_file_mutex; +using u16obuf_file_mutex = basic_obuf_file_mutex; +using u16iobuf_file_mutex = basic_iobuf_file_mutex; + +/* +char32_t region +*/ +using u32ibuf_pipe = basic_ibuf_pipe; +using u32obuf_pipe = basic_obuf_pipe; +using u32iobuf_pipe = basic_iobuf_pipe; + +using u32inative_file = basic_inative_file; +using u32onative_file = basic_onative_file; + +using u32ibuf_file = basic_ibuf_file; +using u32obuf_file = basic_obuf_file; +using u32iobuf_file = basic_iobuf_file; + +using u32ibuf_file_mutex = basic_ibuf_file_mutex; +using u32obuf_file_mutex = basic_obuf_file_mutex; +using u32iobuf_file_mutex = basic_iobuf_file_mutex; + +#ifndef FAST_IO_DISABLE_CODECVT +/* +code_cvt file template region +*/ + +template +using basic_icode_cvt_file = basic_ibuf_code_cvt,internal_scheme,external_scheme>; +template +using basic_ocode_cvt_file = basic_obuf_code_cvt,internal_scheme,external_scheme>; +template +using basic_code_cvt_file = basic_iobuf_code_cvt,internal_scheme,external_scheme>; + + + +/* +UTF-8 region +*/ + +template +using basic_iutf8_file = std::conditional_t,basic_ibuf>,basic_icode_cvt_file>; +using iutf8_file = basic_iutf8_file; +using wiutf8_file = basic_iutf8_file; +using u8iutf8_file = basic_iutf8_file; +using u16iutf8_file = basic_iutf8_file; +using u32iutf8_file = basic_iutf8_file; + +template +using basic_outf8_file = std::conditional_t,basic_obuf>,basic_ocode_cvt_file>; +using outf8_file = basic_outf8_file; +using woutf8_file = basic_outf8_file; +using u8outf8_file = basic_outf8_file; +using u16outf8_file = basic_outf8_file; +using u32outf8_file = basic_outf8_file; + +template +using basic_utf8_file = std::conditional_t,basic_iobuf>,basic_code_cvt_file>; +using utf8_file = basic_utf8_file; +using wutf8_file = basic_utf8_file; +using u8utf8_file = basic_utf8_file; +using u16utf8_file = basic_utf8_file; +using u32utf8_file = basic_utf8_file; + + +/* +GB18030 region +*/ + +template +using basic_igb18030_file = std::conditional_t +&&execution_charset_encoding_scheme()==encoding_scheme::gb18030, +basic_ibuf>, +basic_icode_cvt_file>; +using igb18030_file = basic_igb18030_file; +using wigb18030_file = basic_igb18030_file; +using u8igb18030_file = basic_igb18030_file; +using u16igb18030_file = basic_igb18030_file; +using u32igb18030_file = basic_igb18030_file; + +template +using basic_ogb18030_file = std::conditional_t +&&execution_charset_encoding_scheme()==encoding_scheme::gb18030, +basic_obuf>, +basic_ocode_cvt_file>; +using ogb18030_file = basic_ogb18030_file; +using wogb18030_file = basic_ogb18030_file; +using u8ogb18030_file = basic_ogb18030_file; +using u16ogb18030_file = basic_ogb18030_file; +using u32ogb18030_file = basic_ogb18030_file; + +template +using basic_gb18030_file = std::conditional_t +&&execution_charset_encoding_scheme()==encoding_scheme::gb18030, +basic_iobuf>, +basic_code_cvt_file>; +using gb18030_file = basic_gb18030_file; +using wgb18030_file = basic_gb18030_file; +using u8gb18030_file = basic_gb18030_file; +using u16gb18030_file = basic_gb18030_file; +using u32gb18030_file = basic_gb18030_file; + +template +using basic_iutf_ebcdic_file = std::conditional_t +&&execution_charset_encoding_scheme()==encoding_scheme::utf_ebcdic, +basic_ibuf>, +basic_icode_cvt_file>; + +using iutf_ebcdic_file = basic_iutf_ebcdic_file; +using wiutf_ebcdic_file = basic_iutf_ebcdic_file; +using u8iutf_ebcdic_file = basic_iutf_ebcdic_file; +using u16iutf_ebcdic_file = basic_iutf_ebcdic_file; +using u32iutf_ebcdic_file = basic_iutf_ebcdic_file; + +template +using basic_outf_ebcdic_file = std::conditional_t +&&execution_charset_encoding_scheme()==encoding_scheme::utf_ebcdic, +basic_obuf>, +basic_ocode_cvt_file>; +using outf_ebcdic_file = basic_outf_ebcdic_file; +using woutf_ebcdic_file = basic_outf_ebcdic_file; +using u8outf_ebcdic_file = basic_outf_ebcdic_file; +using u16outf_ebcdic_file = basic_outf_ebcdic_file; +using u32outf_ebcdic_file = basic_outf_ebcdic_file; + +template +using basic_utf_ebcdic_file = std::conditional_t +&&execution_charset_encoding_scheme()==encoding_scheme::utf_ebcdic, +basic_iobuf>, +basic_code_cvt_file>; +using utf_ebcdic_file = basic_utf_ebcdic_file; +using wutf_ebcdic_file = basic_utf_ebcdic_file; +using u8utf_ebcdic_file = basic_utf_ebcdic_file; +using u16utf_ebcdic_file = basic_utf_ebcdic_file; +using u32utf_ebcdic_file = basic_utf_ebcdic_file; +#endif + +#if defined(_WIN32) || (__has_include() && __has_include() && !defined(__wasi__)) + +template +using basic_iobuf_socket_file = basic_iobuf>; + +using iobuf_socket_file = basic_iobuf_socket_file; +using wiobuf_socket_file = basic_iobuf_socket_file; +using u8iobuf_socket_file = basic_iobuf_socket_file; +using u16iobuf_socket_file = basic_iobuf_socket_file; +using u32iobuf_socket_file = basic_iobuf_socket_file; + +#endif + +} +#endif + +#endif diff --git a/src/fast_io/include/fast_io_driver/asio_driver.h b/src/fast_io/include/fast_io_driver/asio_driver.h new file mode 100644 index 0000000..dfdac83 --- /dev/null +++ b/src/fast_io/include/fast_io_driver/asio_driver.h @@ -0,0 +1,20 @@ +#pragma once +#include +#include"asio_driver/socket_io_observer.h" + +namespace fast_io::asio_driver +{ + +template +using basic_ip_tcp_socket_io_observer = basic_socket_io_observer; + +using ip_tcp_socket_io_observer=basic_ip_tcp_socket_io_observer; +using ibuf_ip_tcp_socket_io_observer=fast_io::basic_ibuf>; + +using u8ip_tcp_socket_io_observer=basic_ip_tcp_socket_io_observer; +using u8ibuf_ip_tcp_socket_io_observer=fast_io::basic_ibuf>; + +using wip_tcp_socket_io_observer=basic_ip_tcp_socket_io_observer; +using wibuf_ip_tcp_socket_io_observer=fast_io::basic_ibuf>; + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_driver/asio_driver/socket_io_observer.h b/src/fast_io/include/fast_io_driver/asio_driver/socket_io_observer.h new file mode 100644 index 0000000..4a8075d --- /dev/null +++ b/src/fast_io/include/fast_io_driver/asio_driver/socket_io_observer.h @@ -0,0 +1,53 @@ +#pragma once + +namespace fast_io::asio_driver +{ + +template +class basic_socket_io_observer +{ +public: + using char_type = ch_type; + using native_handle_type = T*; + native_handle_type handle{}; + + constexpr operator bool() const noexcept + { + return handle; + } + constexpr auto& native_handle() const noexcept + { + return handle; + } + + constexpr auto& native_handle() noexcept + { + return handle; + } + inline constexpr native_handle_type release() noexcept + { + auto temp{handle}; + handle=nullptr; + return temp; + } +}; +template +inline Iter read(basic_socket_io_observer iob,Iter begin,Iter end) +{ + std::error_code ec{};//WTF??? WHY?? WHY??WHY??WHY??WHY??WHY??WHY??WHY?? FUCK YOU ASIO + std::size_t sz{iob.handle->read_some(asio::buffer(::std::to_address(begin), (end-begin)*sizeof(*begin)),ec)}; + if(ec==asio::error::eof) //This is BRAINDEAD RETARDED. HOW COULD THIS SHIT GET ADDED INTO ISO C++? + return begin; + else if(ec) + throw std::system_error(ec); + return begin+sz/sizeof(*begin); +} + +template +inline Iter write(basic_socket_io_observer iob,Iter begin,Iter end) +{ + return begin+iob.handle->write_some(asio::buffer(::std::to_address(begin), (end-begin)*sizeof(*begin)))/sizeof(*begin); +} +template +inline constexpr void flush(basic_socket_io_observer){} +} diff --git a/src/fast_io/include/fast_io_driver/avformat/avio.h b/src/fast_io/include/fast_io_driver/avformat/avio.h new file mode 100644 index 0000000..d3c791f --- /dev/null +++ b/src/fast_io/include/fast_io_driver/avformat/avio.h @@ -0,0 +1,413 @@ +#pragma once + +extern "C" { +#include +#include +} + +namespace fast_io +{ + +template +requires (sizeof(ch_type) == 1) +class basic_avio_context_io_observer +{ +public: + using char_type = ch_type; + using native_handle_type = ::AVIOContext*; + native_handle_type avios{}; + + constexpr native_handle_type native_handle() const noexcept + { + return avios; + } + constexpr ::AVIOContext* release() noexcept + { + auto temp{this->avios}; + this->avios=nullptr; + return temp; + } +}; + +template +inline void write(basic_avio_context_io_observer baciob,char_type const* first,char_type const* last) +{ + baciob.avios->error=0; + if constexpr(INT_MAX(last-first)}; + if(diff(last-first)); + } + if(baciob.avios->error) + { + throw_posix_error(EINVAL); + } +} + +template +inline char_type* read(basic_avio_context_io_observer baciob,char_type* first,char_type* last) +{ + baciob.avios->error=0; + int ret; + if constexpr(INT_MAX(last-first)}; + if(diff(last-first)); + } + if(baciob.avios->error) + { + throw_posix_error(EINVAL); + } + return ret; +} + +template +requires (sizeof(ch_type) == 1) +inline constexpr basic_avio_context_io_observer io_value_handle(basic_avio_context_io_observer baciob) noexcept +{ + return baciob; +} + +#if 0 + +template +inline char_type* ibuffer_begin(basic_avio_context_io_observer baciob) noexcept +{ + return reinterpret_cast(baciob.avios.buffer); +} + +template +inline char_type* ibuffer_curr(basic_avio_context_io_observer baciob) noexcept +{ + return reinterpret_cast(baciob.avios.buf_ptr); +} + +template +inline char_type* ibuffer_end(basic_avio_context_io_observer baciob) noexcept +{ + return reinterpret_cast(baciob.avios.buf_end); +} + +template +inline bool ibuffer_underflow(basic_avio_context_io_observer baciob) noexcept +{ + baciob.avios.buf_ptr = baciob.avios.buf_end<=baciob.avios.buf_ptr; + + return; +} + +template +inline char_type* ibuffer_begin(basic_avio_context_io_observer baciob) noexcept +{ + return reinterpret_cast(baciob.avios.buffer); +} + +template +inline char_type* ibuffer_curr(basic_avio_context_io_observer baciob) noexcept +{ + return reinterpret_cast(baciob.avios.buf_ptr); +} + +template +inline char_type* ibuffer_end(basic_avio_context_io_observer baciob) noexcept +{ + return reinterpret_cast(baciob.avios.buf_end); +} + +#endif + +template +requires (sizeof(ch_type) == 1) +class basic_avio_context_file:public basic_avio_context_io_observer +{ +public: + using char_type = ch_type; + using native_handle_type = ::AVIOContext*; + explicit constexpr basic_avio_context_file(::AVIOContext *ctxx) noexcept:basic_avio_context_io_observer{ctxx}{} + void close() noexcept + { + if(this->avios==nullptr) + { + return; + } + fast_io::noexcept_call(::av_free,this->avios); + this->avios=nullptr; + } + basic_avio_context_file(basic_avio_context_file const&)=delete; + basic_avio_context_file& operator=(basic_avio_context_file const&)=delete; + basic_avio_context_file(basic_avio_context_file&& other) noexcept:basic_avio_context_io_observer{other.avios} + { + other.avios=nullptr; + } + basic_avio_context_file& operator=(basic_avio_context_file&& other) noexcept + { + this->close(); + this->avios=other.avios; + other.avios=nullptr; + return *this; + } + ~basic_avio_context_file() + { + this->close(); + } +}; + +struct avio_buffer +{ + void* buffer{}; + explicit constexpr avio_buffer() = default; + explicit constexpr avio_buffer(void* bf) noexcept:buffer(bf){} + void close() noexcept + { + if(buffer==nullptr) + { + return; + } + ::fast_io::noexcept_call(::av_free,buffer); + this->buffer=nullptr; + } + avio_buffer(avio_buffer const&)=delete; + avio_buffer& operator=(avio_buffer const&)=delete; + avio_buffer(avio_buffer&& other):buffer(other.buffer) + { + other.buffer=nullptr; + } + avio_buffer& operator=(avio_buffer&& other) noexcept + { + this->close(); + this->buffer=other.buffer; + other.buffer=nullptr; + return *this; + } + ~avio_buffer() + { + this->close(); + } +}; + +template +requires (sizeof(char_type) == 1) +struct basic_avio_buffer_context +{ + basic_avio_context_file avioctx; + avio_buffer aviobuffer; + inline constexpr ::AVIOContext* context() const noexcept + { + return avioctx.native_handle(); + } +}; + +namespace details +{ + +template +concept has_file_status_impl = requires(T t) +{ + {status(t)}->std::same_as<::fast_io::posix_file_status>; +}; + +template +inline basic_avio_buffer_context create_avio_context_impl(rftype rf) +{ + using char_type = typename rftype::char_type; + constexpr int buffersize{16384}; + auto bfptr{::fast_io::noexcept_call(::av_malloc,buffersize)}; + if(bfptr==nullptr) + { + ::fast_io::fast_terminate(); + } + avio_buffer bufferwrap(bfptr); + ::AVIOContext* ctx; + using char_type_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = char_type*; + using char_type_const_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = char_type const*; + static_assert(sizeof(rftype)<=sizeof(void*)); + void *ptr{}; + ::memcpy(__builtin_addressof(ptr),__builtin_addressof(rf),sizeof(rftype)); + ctx=::avio_alloc_context(reinterpret_cast(bfptr),buffersize,AVIO_FLAG_WRITE,ptr, + [](void* opaque,uint8_t* ptr,int bufsize) noexcept ->int + { + rftype rft; + ::memcpy(__builtin_addressof(rft),__builtin_addressof(opaque),sizeof(rftype)); + try + { + auto ret{read(rft,reinterpret_cast(ptr),reinterpret_cast(ptr)+bufsize)-reinterpret_cast(ptr)}; + return static_cast(ret); + } + catch(...) + { + return -1; + } + }, + [](void* opaque,uint8_t* ptr,int bufsize) noexcept ->int + { + rftype rft; + ::memcpy(__builtin_addressof(rft),__builtin_addressof(opaque),sizeof(rftype)); + try + { + write(rft,reinterpret_cast(ptr),reinterpret_cast(ptr)+bufsize); + } + catch(...) + { + return -1; + } + return bufsize; + }, + [](void* opaque,int64_t offset,int whence) noexcept ->::std::int64_t + { + rftype rft; + ::memcpy(__builtin_addressof(rft),__builtin_addressof(opaque),sizeof(rftype)); + try + { + if(whence==AVSEEK_SIZE) + { + if constexpr(has_file_status_impl) + { + auto sz{status(rft).size}; + if constexpr(std::numeric_limits::max()>INT64_MAX) + { + if(sz>INT64_MAX) + { + return -1; + } + } + return static_cast<::std::int64_t>(sz); + } + else + { + return -1; + } + } + return seek(rft,offset,static_cast<::fast_io::seekdir>(whence)); + } + catch(...) + { + return -1; + } + }); + if(ctx==nullptr) + { + ::fast_io::fast_terminate(); + } + return basic_avio_buffer_context{basic_avio_context_file(ctx),::std::move(bufferwrap)}; +} + +} + +template +requires (io_stream<::std::remove_cvref_t>&&random_access_stream<::std::remove_cvref_t>&& + sizeof(typename ::std::remove_cvref_t::char_type)==1) +inline basic_avio_buffer_context::char_type> create_avio_context(stm& sm) +{ + return ::fast_io::details::create_avio_context_impl(io_ref(sm)); +} + +using avio_context_io_observer = basic_avio_context_io_observer; +using u8avio_context_io_observer = basic_avio_context_io_observer; +using avio_context_file = basic_avio_context_file; +using u8avio_context_file = basic_avio_context_file; + +struct avformat_context_guard +{ + ::AVFormatContext* pFormatCtx{}; + + explicit constexpr avformat_context_guard(::AVFormatContext* p) noexcept:pFormatCtx{p}{} + + avformat_context_guard(avformat_context_guard const&)=delete; + avformat_context_guard& operator=(avformat_context_guard const&)=delete; + + constexpr ::AVFormatContext* release() noexcept + { + auto temp{this->pFormatCtx}; + this->pFormatCtx=nullptr; + return temp; + } + + void close() noexcept + { + if(this->pFormatCtx==nullptr) + { + return; + } + ::fast_io::noexcept_call(avformat_free_context,pFormatCtx); + this->pFormatCtx=nullptr; + } + + ~avformat_context_guard() + { + this->close(); + } +}; + +struct avformat_input_guard +{ + ::AVFormatContext** ppFormatCtx{}; + + explicit constexpr avformat_input_guard(::AVFormatContext** pp) noexcept:ppFormatCtx{pp}{} + + avformat_input_guard(avformat_input_guard const&)=delete; + avformat_input_guard& operator=(avformat_input_guard const&)=delete; + + constexpr ::AVFormatContext** release() noexcept + { + auto temp{this->ppFormatCtx}; + this->ppFormatCtx=nullptr; + return temp; + } + + void close() noexcept + { + if(ppFormatCtx==nullptr) + { + return; + } + ::fast_io::noexcept_call(avformat_close_input,ppFormatCtx); + this->ppFormatCtx=nullptr; + } + + ~avformat_input_guard() + { + this->close(); + } +}; + +} diff --git a/src/fast_io/include/fast_io_driver/avr/console.h b/src/fast_io/include/fast_io_driver/avr/console.h new file mode 100644 index 0000000..ae73d27 --- /dev/null +++ b/src/fast_io/include/fast_io_driver/avr/console.h @@ -0,0 +1,84 @@ +#pragma once + +#include +#include + +namespace fast_io +{ +inline constexpr std::uint_least32_t avr_band_rate{9600}; +inline constexpr std::uint_least32_t avr_f_cpu{ +#if defined(F_CPU) +F_CPU +#else +16000000 +#endif +}; + +inline constexpr std::uint_least32_t avr_band_prescale{avr_f_cpu/16/avr_band_rate-1}; + +inline void avr_usart_initialize() noexcept +{ + UBRR0H = (avr_band_prescale >> 8); + UBRR0L = avr_band_prescale; + UCSR0B = (1< +struct basic_avr_console +{ + using char_type = ch_type; +}; + +inline void avr_usart_console_write(char const* first,char const* last) noexcept +{ + for(;first!=last;++first) + avr_usart_send_byte(static_cast(*first)); +} + +inline void avr_usart_console_writev(fast_io::io_scatter_t const* scatter,std::size_t n) noexcept +{ + for(std::size_t i{};i!=n;++i) + { + auto b{reinterpret_cast(scatter[i].base)}; + avr_usart_console_write(b,b+scatter[i].len); + } +} + +template +inline constexpr basic_avr_console io_value_handle(basic_avr_console) noexcept +{ + return {}; +} + +template +inline void write(basic_avr_console,Iter first,Iter last) noexcept +{ + avr_usart_console_write(reinterpret_cast(::std::to_address(first)),reinterpret_cast(::std::to_address(last))); +} + +template +inline void scatter_write(basic_avr_console,io_scatters_t scatters) noexcept +{ + avr_usart_console_writev(scatters.base,scatters.len); +} + +using avr_console = basic_avr_console; +using wavr_console = basic_avr_console; +using u16avr_console = basic_avr_console; +using u32avr_console = basic_avr_console; +using u8avr_console = basic_avr_console; + +} diff --git a/src/fast_io/include/fast_io_driver/boost/graph.h b/src/fast_io/include/fast_io_driver/boost/graph.h new file mode 100644 index 0000000..f422eee --- /dev/null +++ b/src/fast_io/include/fast_io_driver/boost/graph.h @@ -0,0 +1,19 @@ +#pragma once + +namespace fast_io +{ + +#ifdef BOOST_GRAPH_DETAIL_EDGE_HPP + +template +inline constexpr void print_define(io_reserve_type_t>, + bos b, + ::boost::detail::edge_desc_impl const& e) +{ + print_freestanding(b,fast_io::mnp::chvw(char_literal_v),e.m_source, + fast_io::mnp::chvw(char_literal_v),e.m_target, + fast_io::mnp::chvw(char_literal_v)); +} + +#endif +} diff --git a/src/fast_io/include/fast_io_driver/boost/uuid.h b/src/fast_io/include/fast_io_driver/boost/uuid.h new file mode 100644 index 0000000..3f936e1 --- /dev/null +++ b/src/fast_io/include/fast_io_driver/boost/uuid.h @@ -0,0 +1,52 @@ +#pragma once +#ifndef BOOST_UUID_HPP +#include +#endif + +namespace fast_io +{ + +template +inline constexpr std::size_t print_reserve_size(io_reserve_type_t) noexcept +{ + constexpr std::size_t sz{36}; + static_assert(boost::uuids::uuid::static_size()==16); + return sz; +} + +namespace details +{ + +template +inline constexpr char_type* pr_rsv_boost_uuid(char_type* iter,boost::uuids::uuid const& u) noexcept +{ + static_assert(::std::contiguous_iterator); + auto first{::std::to_address(u.begin())}; +#if __cpp_if_consteval >= 202106L + if consteval +#else + if(std::is_constant_evaluated()) +#endif + { + std::byte buffer[16]; + for(std::size_t i{};i!=16;++i) + { + buffer[i]=static_cast(first[i]); + } + return pr_rsv_uuid(iter,buffer); + } + else + { + return pr_rsv_uuid(iter,reinterpret_cast(first)); + } +} + +} + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define(io_reserve_type_t,Iter iter,boost::uuids::uuid const& u) noexcept +{ + return ::fast_io::details::pr_rsv_boost_uuid(iter,u); +} + +} diff --git a/src/fast_io/include/fast_io_driver/boost_iostreams.h b/src/fast_io/include/fast_io_driver/boost_iostreams.h new file mode 100644 index 0000000..8e5e541 --- /dev/null +++ b/src/fast_io/include/fast_io_driver/boost_iostreams.h @@ -0,0 +1,88 @@ +#pragma once +#include +#include"../fast_io_core_impl/seek.h" + +namespace fast_io +{ + +template +concept boost_iostreams_input_device=requires(src_type& src,char* s,std::streamsize n) +{ + {src.read(s,n)}->std::same_as; +}; + +template +concept boost_iostreams_output_device=requires(src_type& src,char const* s,std::streamsize n) +{ + {src.write(s,n)}->std::same_as; +}; + +template +concept boost_iostreams_any_device=boost_iostreams_input_device||boost_iostreams_output_device; + +template +concept boost_iostreams_io_device=boost_iostreams_input_device&&boost_iostreams_output_device; + +template +concept boost_iostreams_flushable_device=boost_iostreams_any_device&&requires(src_type& src) +{ + {src.flush()}; +}; + +template +concept boost_iostream_seekable_device=boost_iostreams_any_device&&requires(src_type& src,std::intmax_t offset,std::ios::seekdir dir) +{ + {src.seek(offset,dir)}->std::convertible_to; +}; + +template +class basic_boost_iostreams +{ +public: + using char_type = ch_type; + using source_type = src_type; + source_type source; +}; + +template +inline Iter read(basic_boost_iostreams& in_device,Iter begin,Iter end) +{ + auto ret{in_device.source.read(reinterpret_cast(::std::to_address(begin)),(end-begin)*sizeof(*begin))}; + if(ret==-1) + return begin; + return begin+ret/sizeof(*begin); +} + +template +inline Iter write(basic_boost_iostreams& out_device,Iter begin,Iter end) +{ + auto ret{out_device.source.write(reinterpret_cast(::std::to_address(begin)),(end-begin)*sizeof(*begin))}; + if(ret==-1) + return begin; + return begin+ret/sizeof(*begin); +} +template +inline void flush(basic_boost_iostreams& out_device) +{ + out_device.source.flush(); +} + +template +inline auto seek(basic_boost_iostreams& dev,seek_type_t,U i,seekdir s=seekdir::beg) +{ + return dev.seek(seek_precondition(i),static_cast(static_cast(s))); +} + +template +inline auto seek(basic_boost_iostreams cfhd,U i,seekdir s=seekdir::beg) +{ + return seek(cfhd,seek_type,i,s); +} + +template +using boost_iostreams = basic_boost_iostreams; +template +using u8boost_iostreams = basic_boost_iostreams; +template +using wboost_iostreams = basic_boost_iostreams; +} diff --git a/src/fast_io/include/fast_io_driver/bootloader/stvl2.h b/src/fast_io/include/fast_io_driver/bootloader/stvl2.h new file mode 100644 index 0000000..6121784 --- /dev/null +++ b/src/fast_io/include/fast_io_driver/bootloader/stvl2.h @@ -0,0 +1,447 @@ +#pragma once +#include +#include +#include +#include + +/* +https://github.com/stivale/stivale + +we just call it stvl2 to avoid naming collision with stivale2 +*/ + +namespace stvl2 +{ + +static_assert(sizeof(void*)==4||sizeof(void*)==8); +static_assert(std::endian::little==std::endian::native); +struct +#if __has_cpp_attribute(__gnu__::__packed__) +[[__gnu__::__packed__]] +#endif +stvl2_pointer_padding +{ +struct stvl2_empty{}; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif +std::conditional_t pad{}; +}; + +enum class stvl2_header_tag:std::uint_least64_t +{ +framebuffer_id=0x3ecc1bc43d0f7971, +fb_mtrr_id=0x4c7bb07731282e00, +smp_id=0x1ab015085f3273df +}; + +enum class stvl2_struct_tag:std::uint_least64_t +{ +cmdline_id=0xe5e76a1b4597a781, +memmap_id=0x2187f79e8612de07, +framebuffer_id=0x506461d2950408fa, +fb_mtrr_id=0x6bc1a78ebe871172, +modules_id=0x4b6fe466aade04ce, +rsdp_id=0x9e1786930a375e78, +epoch_id=0x566a7bed888e1407, +firmware_id=0x359d837855e3858c, +smp_id=0x34d1d96339647025, +pxe_server_info=0x29d1e96239247032, +mmio32_uart=0xb813f9b8dbc78797, +dtb=0xabb29bd49a2833fa, +vmap=0xb0ed257db18cb58f +}; + +enum class stvl2_mmap_type:std::uint_least32_t +{ +usable=1, +reserved=2, +acpi_reclaimable=3, +acpi_nvs=4, +bad_memory=5, +bootloader_reclaimable=0x1000, +kernel_and_modules=0x1001 +}; + +enum class stvl2_firmware_flags:std::uint_least64_t +{ +bios=1<<0 +}; + +/* +use stvl2 instead of stivale2 to avoid collision with stivale2.h +*/ +struct +#if __has_cpp_attribute(__gnu__::__packed__) +[[__gnu__::__packed__]] +#endif +stvl2_tag +{ + stvl2_header_tag identifier{}; + stvl2_tag* next{}; +}; + +struct +#if __has_cpp_attribute(__gnu__::__packed__) +[[__gnu__::__packed__]] +#endif +stvl2_header +{ +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif + stvl2_pointer_padding entry_point_pointer_padding{}; + void* entry_point{}; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif + stvl2_pointer_padding stack_pointer_padding{}; + void* stack{}; + std::uint_least64_t flags{}; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif + stvl2_pointer_padding tags_root_padding{}; + stvl2_tag* tags_root{}; +}; + +struct +#if __has_cpp_attribute(__gnu__::__packed__) +[[__gnu__::__packed__]] +#endif +stvl2_header_tag_framebuffer : stvl2_tag +{ + std::uint_least16_t framebuffer_width{}; + std::uint_least16_t framebuffer_height{}; + std::uint_least16_t framebuffer_bpp{}; +}; + +struct +#if __has_cpp_attribute(__gnu__::__packed__) +[[__gnu__::__packed__]] +#endif +stvl2_header_tag_smp : stvl2_tag +{ + std::uint_least64_t flags{}; +}; + +struct +#if __has_cpp_attribute(__gnu__::__packed__) +[[__gnu__::__packed__]] +#endif +stvl2_struct +{ + inline static constexpr std::size_t bootloader_brand_size{64}; + inline static constexpr std::size_t bootloader_version_size{64}; + char8_t bootloader_brand[bootloader_brand_size]; + char8_t bootloader_version[bootloader_version_size]; + stvl2_tag* tags_root{}; +}; + +struct +#if __has_cpp_attribute(__gnu__::__packed__) +[[__gnu__::__packed__]] +#endif +stvl2_struct_tag_cmdline:stvl2_tag +{ + std::uint_least64_t cmdline{}; +}; + +struct +#if __has_cpp_attribute(__gnu__::__packed__) +[[__gnu__::__packed__]] +#endif +stvl2_mmap_entry +{ +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif + stvl2_pointer_padding base_pointer_padding; + void* base{}; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif + stvl2_pointer_padding length_padding; + std::size_t length{}; + stvl2_mmap_type type{}; + std::uint_least32_t unused{}; +}; + +struct +#if __has_cpp_attribute(__gnu__::__packed__) +[[__gnu__::__packed__]] +#endif +stvl2_struct_tag_memmap:stvl2_tag +{ + std::uint_least64_t entries{}; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif + stvl2_mmap_entry memmaps[]; +}; + +struct +#if __has_cpp_attribute(__gnu__::__packed__) +[[__gnu__::__packed__]] +#endif +stvl2_struct_tag_framebuffer:stvl2_tag +{ +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif + stvl2_pointer_padding framebuffer_addr_pointer_padding; + void* framebuffer_addr{}; + std::uint_least16_t framebuffer_width{}; + std::uint_least16_t framebuffer_height{}; + std::uint_least16_t framebuffer_pitch{}; + std::uint_least16_t framebuffer_bpp{}; + std::uint_least8_t memory_model{}; + std::uint_least8_t red_mask_size{}; + std::uint_least8_t red_mask_shift{}; + std::uint_least8_t green_mask_size{}; + std::uint_least8_t green_mask_shift{}; + std::uint_least8_t blue_mask_size{}; + std::uint_least8_t blue_mask_shift{}; +}; + +struct +#if __has_cpp_attribute(__gnu__::__packed__) +[[__gnu__::__packed__]] +#endif +stvl2_module +{ +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif + stvl2_pointer_padding module_begin_pointer_padding; + void* module_begin{}; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif + stvl2_pointer_padding module_end_pointer_padding; + void* module_end{}; + static inline constexpr std::size_t module_string_size{128}; + char8_t module_string[module_string_size]; +}; + +struct +#if __has_cpp_attribute(__gnu__::__packed__) +[[__gnu__::__packed__]] +#endif +stvl2_struct_tag_modules:stvl2_tag +{ +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif + stvl2_pointer_padding module_count_padding; + std::size_t module_count{}; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif + stvl2_module modules[]; +}; + +struct +#if __has_cpp_attribute(__gnu__::__packed__) +[[__gnu__::__packed__]] +#endif +stvl2_struct_tag_rsdp:stvl2_tag +{ + std::uint_least64_t rdsp{}; +}; + +struct +#if __has_cpp_attribute(__gnu__::__packed__) +[[__gnu__::__packed__]] +#endif +stvl2_struct_tag_epoch:stvl2_tag +{ + std::uint_least64_t epoch{}; +}; + +struct +#if __has_cpp_attribute(__gnu__::__packed__) +[[__gnu__::__packed__]] +#endif +stvl2_struct_tag_firmware:stvl2_tag +{ + stvl2_firmware_flags tag{}; +}; + +struct +#if __has_cpp_attribute(__gnu__::__packed__) +[[__gnu__::__packed__]] +#endif +stvl2_smp_info +{ + std::uint_least32_t process_id{}; + std::uint_least32_t lapic_id{}; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif + stvl2_pointer_padding target_stack_pointer_padding; + void* target_stack{}; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif + stvl2_pointer_padding goto_address_pointer_padding; + void* goto_address{}; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif + stvl2_pointer_padding extra_argument_pointer_padding; + void* extra_argument{}; +}; + +struct +#if __has_cpp_attribute(__gnu__::__packed__) +[[__gnu__::__packed__]] +#endif +stvl2_struct_tag_smp:stvl2_tag +{ + std::uint_least64_t flags{}; + std::uint_least32_t bsp_lapic_id{}; + std::uint_least32_t unused{}; + std::uint_least64_t cpu_count{}; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif + stvl2_smp_info smp_info[]; +}; + +struct +#if __has_cpp_attribute(__gnu__::__packed__) +[[__gnu__::__packed__]] +#endif +stvl2_struct_tag_pxe_server_info:stvl2_tag +{ + std::uint_least32_t server_ip{}; +}; + +struct +#if __has_cpp_attribute(__gnu__::__packed__) +[[__gnu__::__packed__]] +#endif +stvl2_struct_tag_mmio32_uart:stvl2_tag +{ +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif + stvl2_pointer_padding addr_padding{}; + void* addr{}; +}; + +struct +#if __has_cpp_attribute(__gnu__::__packed__) +[[__gnu__::__packed__]] +#endif +stvl2_struct_tag_dtb:stvl2_tag +{ +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif + stvl2_pointer_padding addr_padding{}; + void* addr{}; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif + stvl2_pointer_padding size_padding{}; + std::size_t size{}; +}; + +struct +#if __has_cpp_attribute(__gnu__::__packed__) +[[__gnu__::__packed__]] +#endif +stvl2_struct_vmap:stvl2_tag +{ +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif + stvl2_pointer_padding addr_padding{}; + void* addr{}; +}; + +} + +#include"stvl2_struct_iterator.h" diff --git a/src/fast_io/include/fast_io_driver/bootloader/stvl2_struct_iterator.h b/src/fast_io/include/fast_io_driver/bootloader/stvl2_struct_iterator.h new file mode 100644 index 0000000..cf8e8ff --- /dev/null +++ b/src/fast_io/include/fast_io_driver/bootloader/stvl2_struct_iterator.h @@ -0,0 +1,54 @@ +#pragma once + +namespace stvl2 +{ + +struct stvl2_struct_iterator +{ + using value_type = stvl2_tag; + using difference_type = std::ptrdiff_t; + stvl2_tag* ptr{}; + inline constexpr stvl2_tag* operator->() const noexcept + { + return ptr; + } + inline constexpr stvl2_tag& operator*() const noexcept + { + return *ptr; + } + inline constexpr stvl2_struct_iterator& operator++() noexcept + { + ptr=ptr->next; + return *this; + } + inline constexpr stvl2_struct_iterator operator++(int) noexcept + { + auto tmp{*this}; + ++*this; + return tmp; + } +}; + +inline constexpr bool operator==(stvl2_struct_iterator first,stvl2_struct_iterator second) noexcept +{ + return first.ptr==second.ptr; +} + +inline constexpr bool operator!=(stvl2_struct_iterator first,stvl2_struct_iterator second) noexcept +{ + return first.ptr!=second.ptr; +} + +static_assert(::std::forward_iterator); + +inline constexpr stvl2_struct_iterator begin(stvl2_struct& s) noexcept +{ + return {s.tags_root}; +} + +inline constexpr stvl2_struct_iterator end(stvl2_struct& s) noexcept +{ + return {nullptr}; +} + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_driver/capstone.h b/src/fast_io/include/fast_io_driver/capstone.h new file mode 100644 index 0000000..9edccd7 --- /dev/null +++ b/src/fast_io/include/fast_io_driver/capstone.h @@ -0,0 +1,219 @@ +#pragma once + +#include + +namespace fast_io::capstone +{ + +struct cs_error +{ + cs_err e{}; +}; + +inline void throw_cs_error(cs_err e[[maybe_unused]]) +{ +#ifdef __cpp_exceptions +#if defined(_MSC_VER) && (!defined(_HAS_EXCEPTIONS) || _HAS_EXCEPTIONS == 0) + fast_terminate(); +#else + throw cs_error{e}; +#endif +#else + fast_terminate(); +#endif +} + +namespace details +{ + +inline void cs_option_wrapper_impl(std::size_t csh,cs_opt_type t,std::size_t value) +{ + auto ret{::fast_io::noexcept_call(::cs_option,csh,t,value)}; + if(ret!=CS_ERR_OK) + throw_cs_error(ret); +} + +} + +class cs_io_observer +{ +public: + std::size_t csh{}; + void option(cs_opt_type t,std::size_t value) const + { + ::fast_io::capstone::details::cs_option_wrapper_impl(this->csh,t,value); + } +}; + +class cs_file:public cs_io_observer +{ +public: + constexpr cs_file() noexcept = default; + template + requires std::same_as + explicit constexpr cs_file(T cs) noexcept:cs_io_observer{cs}{} + cs_file(cs_file const&)=delete; + cs_file& operator=(cs_file const&)=delete; + constexpr cs_file(cs_file&& __restrict other) noexcept: cs_io_observer{other.csh} + { + other.csh=0; + } + cs_file& operator=(cs_file&& __restrict c) noexcept + { + if(this->csh)[[likely]] + ::fast_io::noexcept_call(cs_close,__builtin_addressof(this->csh)); + this->csh=c.csh; + c.csh=0; + return *this; + } + cs_file(cs_arch arch, cs_mode mode) + { + auto ret{::fast_io::noexcept_call(cs_open,arch,mode,__builtin_addressof(this->csh))}; + if(ret!=CS_ERR_OK) + throw_cs_error(ret); + } + ~cs_file() + { + if(this->csh)[[likely]] + ::fast_io::noexcept_call(cs_close,__builtin_addressof(this->csh)); + } +}; + +class cs_insn_range +{ +public: + cs_insn* ins{}; + std::size_t count{}; + + using value_type = cs_insn; + using pointer = cs_insn*; + using const_pointer = cs_insn const*; + using const_iterator = const_pointer; + using iterator = pointer; + using reference = cs_insn&; + using const_reference = cs_insn const&; + using size_type = std::size_t; + using difference_type = std::ptrdiff_t; + using const_reverse_iterator = std::reverse_iterator; + using reverse_iterator = std::reverse_iterator; + + constexpr cs_insn_range() noexcept = default; + + explicit cs_insn_range(cs_io_observer csiob,char const* buffer,std::size_t code_size,std::uint_least64_t address,std::size_t c) noexcept + { + count=noexcept_call(cs_disasm,csiob.csh,reinterpret_cast(buffer),code_size,address,c,__builtin_addressof(ins)); + } + cs_insn_range(cs_insn_range const&)=delete; + cs_insn_range& operator=(cs_insn_range const&)=delete; + cs_insn_range(cs_insn_range&& __restrict other) noexcept:ins{other.ins},count{other.count} + { + other.ins=nullptr; + other.count=0; + } + cs_insn_range& operator=(cs_insn_range&& __restrict other) noexcept + { + if(this->ins)[[likely]] + ::fast_io::noexcept_call(cs_free,this->ins,this->count); + this->ins=other.ins; + this->count=other.count; + other.ins=nullptr; + other.count=0; + return *this; + } + ~cs_insn_range() + { + if(this->ins)[[likely]] + ::fast_io::noexcept_call(cs_free,this->ins,this->count); + } + constexpr pointer data() const noexcept + { + return ins; + } + constexpr bool empty() const noexcept + { + return !this->count; + } + constexpr std::size_t size() const noexcept + { + return this->count; + } + constexpr const_iterator cbegin() const noexcept + { + return ins; + } + constexpr const_iterator begin() const noexcept + { + return ins; + } + constexpr iterator begin() noexcept + { + return ins; + } + constexpr const_iterator cend() const noexcept + { + return ins+this->count; + } + constexpr const_iterator end() const noexcept + { + return ins+this->count; + } + constexpr iterator end() noexcept + { + return ins+this->count; + } + constexpr std::size_t max_size() const noexcept + { + constexpr std::size_t mx_size{SIZE_MAX/sizeof(value_type)}; + return mx_size; + } + constexpr const_reverse_iterator crbegin() const noexcept + { + return const_reverse_iterator{ins+this->count}; + } + constexpr reverse_iterator rbegin() noexcept + { + return reverse_iterator{ins+this->count}; + } + constexpr const_reverse_iterator rbegin() const noexcept + { + return const_reverse_iterator{ins+this->count}; + } + constexpr const_reverse_iterator crend() const noexcept + { + return const_reverse_iterator{ins}; + } + constexpr reverse_iterator rend() noexcept + { + return reverse_iterator{ins}; + } + constexpr const_reverse_iterator rend() const noexcept + { + return const_reverse_iterator{ins}; + } + constexpr const_reference front() const noexcept + { + return *ins; + } + constexpr reference front() noexcept + { + return *ins; + } + constexpr const_reference back() const noexcept + { + return ins[this->count-1]; + } + constexpr reference back() noexcept + { + return ins[this->count-1]; + } + inline constexpr reference operator[](size_type size) noexcept + { + return ins[size]; + } + inline constexpr const_reference operator[](size_type size) const noexcept + { + return ins[size]; + } +}; + +} diff --git a/src/fast_io/include/fast_io_driver/cppwinrt.h b/src/fast_io/include/fast_io_driver/cppwinrt.h new file mode 100644 index 0000000..0d0f04f --- /dev/null +++ b/src/fast_io/include/fast_io_driver/cppwinrt.h @@ -0,0 +1,4 @@ +#pragma once + +#include"../fast_io_concept.h" +#include"cppwinrt_impl/impl.h" diff --git a/src/fast_io/include/fast_io_driver/cppwinrt_impl/hstring.h b/src/fast_io/include/fast_io_driver/cppwinrt_impl/hstring.h new file mode 100644 index 0000000..f003cd6 --- /dev/null +++ b/src/fast_io/include/fast_io_driver/cppwinrt_impl/hstring.h @@ -0,0 +1,40 @@ +#pragma once + +namespace fast_io +{ + +inline cross_code_cvt_t<::winrt::hstring::value_type> print_alias_define(io_alias_t,::winrt::hstring const& hstr) noexcept +{ + return {{hstr.c_str(),hstr.size()}}; +} + +inline ::winrt::hstring strlike_construct_define(io_strlike_type_t,wchar_t const* first,wchar_t const* last) +{ + std::size_t diff{static_cast(last-first)}; + if constexpr(sizeof(std::uint_least32_t)(diff)); +} + +template +inline ::winrt::hstring wconcat_winrt_hstring(Args&& ...args) +{ + return ::fast_io::basic_general_concat(::std::forward(args)...); +} + +template +inline ::winrt::hstring wconcatln_winrt_hstring(Args&& ...args) +{ + return ::fast_io::basic_general_concat(::std::forward(args)...); +} + +inline constexpr io_strlike_reference_wrapper<::winrt::hstring::value_type,::winrt::hstring> io_strlike_ref(::fast_io::io_alias_t,::winrt::hstring& hstr) noexcept +{ + return {__builtin_addressof(hstr)}; +} + +} diff --git a/src/fast_io/include/fast_io_driver/cppwinrt_impl/impl.h b/src/fast_io/include/fast_io_driver/cppwinrt_impl/impl.h new file mode 100644 index 0000000..2ddd82a --- /dev/null +++ b/src/fast_io/include/fast_io_driver/cppwinrt_impl/impl.h @@ -0,0 +1,4 @@ +#pragma once +#if defined(WINRT_BASE_H) +#include"hstring.h" +#endif diff --git a/src/fast_io/include/fast_io_driver/cryptopp_driver.h b/src/fast_io/include/fast_io_driver/cryptopp_driver.h new file mode 100644 index 0000000..889f61b --- /dev/null +++ b/src/fast_io/include/fast_io_driver/cryptopp_driver.h @@ -0,0 +1,41 @@ +#pragma once + +namespace fast_io::cryptopp +{ + +template +requires requires(T handle, + char unsigned const* constptr, + char unsigned* ptr,std::size_t n) +{ + T::DIGESTSIZE; + handle.Update(constptr,n); + handle.Restart(); + handle.Final(ptr); +} +class iterated_hash_context +{ +public: + using native_handle_type = T; + native_handle_type handle; + static inline constexpr std::size_t digest_size{static_cast(native_handle_type::DIGESTSIZE)}; + std::byte digest_buffer[digest_size]; + void update(std::byte const* first,std::byte const* last) + { + handle.Update(reinterpret_cast(first),static_cast(last-first)); + } + void reset() + { + handle.Restart(); + } + void do_final() + { + handle.Final(reinterpret_cast(digest_buffer)); + } + constexpr void digest_to_byte_ptr(std::byte* __restrict dest) const noexcept + { + ::fast_io::freestanding::nonoverlapped_bytes_copy_n(digest_buffer,digest_size,dest); + } +}; + +} diff --git a/src/fast_io/include/fast_io_driver/fast_io_async.h b/src/fast_io/include/fast_io_driver/fast_io_async.h new file mode 100644 index 0000000..cd93d2b --- /dev/null +++ b/src/fast_io/include/fast_io_driver/fast_io_async.h @@ -0,0 +1,3 @@ +#pragma once +#include"fast_io_hosted.h" +//#include"fast_io_async/model.h" \ No newline at end of file diff --git a/src/fast_io/include/fast_io_driver/kernel.h b/src/fast_io/include/fast_io_driver/kernel.h new file mode 100644 index 0000000..551cc5c --- /dev/null +++ b/src/fast_io/include/fast_io_driver/kernel.h @@ -0,0 +1,127 @@ +#pragma once + +namespace fast_io::kernel +{ +template +struct terminal +{ + using char_type = char; + static inline constexpr std::size_t vga_width=wd; + static inline constexpr std::size_t vga_height=ht; + std::size_t row{}; + std::size_t column{}; + void clear() noexcept + { + auto ptr=(char volatile*)0xb8000; + constexpr std::size_t resolution{vga_width*vga_height}; + for(std::size_t i{};i!=resolution;++i) + { + *ptr=u8' '; + ptr+=2; + } + } + terminal() noexcept + { + clear(); + } +}; +namespace details +{ +template +inline void clear_line(terminal& tem) noexcept +{ + auto ptr=(char volatile*)0xb8000+((vga_width*tem.row)<<1); + for(std::size_t i{};i!=vga_width;++i) + { + *ptr=u8' '; + ptr+=2; + } +} + +template +inline void next_line(terminal& tem) noexcept +{ + if(++tem.row==ht)[[unlikely]] + tem.row={}; + clear_line(tem); +} +template +inline void next_character(terminal& tem) noexcept +{ + if (++tem.column == terminal::vga_width)[[unlikely]] + { + tem.column={}; + next_line(tem); + } +} +} + +template +inline void put(terminal& tem,char ch) noexcept +{ + auto ptr=(char volatile*)0xb8000; + switch(ch) + { + case u8'\n': + tem.column={}; + details::next_line(tem); + return; + break; + case u8'\t': + { + if(tem.column==wd) + { + tem.column={}; + ++tem.row; + details::clear_line(tem); + break; + } + std::size_t col{tem.column}; + auto pos=ptr+(((tem.row*wd)+col)<<1); + for(std::size_t i(col%8);i!=8;++i) + { + *pos=u8' '; + pos+=2; + ++tem.column; + } + if(tem.column==wd) + { + tem.column={}; + details::next_line(tem); + } + } + break; + default: + ptr[((tem.row*wd)+tem.column)<<1]=ch; + details::next_character(tem); + } +} + +namespace details +{ +template +constexpr inline void write_impl(terminal& tem,char const* b,char const* e) noexcept +{ + for(;b!=e;++b) + put(tem,*b); +} + +} + +template +constexpr inline void write(terminal& tem,Iter begin, Iter end) noexcept +{ + if constexpr(std::same_as<::std::iter_value_t,char>) + details::write_impl(tem,::std::to_address(begin),::std::to_address(end)); + else + details::write_impl(tem,reinterpret_cast(::std::to_address(begin)),reinterpret_cast(::std::to_address(end))); +} + +template +constexpr inline void scatter_write(terminal& tem,std::span sp) noexcept +{ + for(auto const& e : sp) + details::write_impl(tem,reinterpret_cast(e.base),reinterpret_cast(e.base)+e.len); +} + +} diff --git a/src/fast_io/include/fast_io_driver/limine/kernel_console.h b/src/fast_io/include/fast_io_driver/limine/kernel_console.h new file mode 100644 index 0000000..18c0b0c --- /dev/null +++ b/src/fast_io/include/fast_io_driver/limine/kernel_console.h @@ -0,0 +1,50 @@ +#pragma once + +namespace fast_io::limine +{ + +template +requires (sizeof(ch_type)==1) +struct basic_kernel_console +{ + using char_type = ch_type; + using function_ptr_type = void(*)(void const*, size_t) noexcept; + function_ptr_type func_ptr{}; +}; + +template +inline constexpr basic_kernel_console io_value_handle(basic_kernel_console con) noexcept +{ + return con; +} + +using kernel_console = basic_kernel_console; +using u8kernel_console = basic_kernel_console; + +template +inline void write(basic_kernel_console console,Iter first,Iter last) noexcept +{ + (console.func_ptr)(::std::to_address(first),static_cast(last-first)*sizeof(*first)); +} + +namespace details +{ + +inline void kconsole_scatter_write_impl(::fast_io::limine::kernel_console::function_ptr_type func_ptr,io_scatter_t const* pscatters,std::size_t n) noexcept +{ + for(std::size_t i{};i!=n;++i) + { + auto scatter{pscatters[i]}; + (func_ptr)(scatter.base,scatter.len); + } +} + +} + +template +inline void scatter_write(basic_kernel_console console,io_scatters_t scatters) noexcept +{ + ::fast_io::limine::details::kconsole_scatter_write_impl(console.func_ptr,scatters.base,scatters.len); +} + +} diff --git a/src/fast_io/include/fast_io_driver/linux_kernel.h b/src/fast_io/include/fast_io_driver/linux_kernel.h new file mode 100644 index 0000000..a183690 --- /dev/null +++ b/src/fast_io/include/fast_io_driver/linux_kernel.h @@ -0,0 +1,4 @@ +#pragma once + +#include"../fast_io.h" +#include"linux_kernel_impl/kpr.h" diff --git a/src/fast_io/include/fast_io_driver/linux_kernel_impl/kpr.h b/src/fast_io/include/fast_io_driver/linux_kernel_impl/kpr.h new file mode 100644 index 0000000..dbb51d8 --- /dev/null +++ b/src/fast_io/include/fast_io_driver/linux_kernel_impl/kpr.h @@ -0,0 +1,337 @@ +#pragma once + +namespace fast_io +{ + +extern int linux_kernel_printk(char const* fmt, ...) noexcept __asm__("_printk"); + +enum class kern +{ +emerg, +alert, +crit, +warning, +notice, +info, +debug, +default_value, +cont +}; + +template +struct basic_kpr +{ + using char_type = ch_type; + kern level{kern::default_value}; +}; + +template +inline constexpr char8_t const* kern_to_fmt(kern k) noexcept +{ + if constexpr(line) + { + switch(k) + { + case kern::emerg: + return u8"\0010%.*s\n"; + case kern::alert: + return u8"\0011%.*s\n"; + case kern::crit: + return u8"\0012%.*s\n"; + case kern::warning: + return u8"\0013%.*s\n"; + case kern::notice: + return u8"\0014%.*s\n"; + case kern::info: + return u8"\0015%.*s\n"; + case kern::debug: + return u8"\0016%.*s\n"; + case kern::cont: + return u8"\001c%.*s\n"; + break; + default: + return u8"%.*s\n"; + } + } + else + { + switch(k) + { + case kern::emerg: + return u8"\0010%.*s"; + case kern::alert: + return u8"\0011%.*s"; + case kern::crit: + return u8"\0012%.*s"; + case kern::warning: + return u8"\0013%.*s"; + case kern::notice: + return u8"\0014%.*s"; + case kern::info: + return u8"\0015%.*s"; + case kern::debug: + return u8"\0016%.*s"; + case kern::cont: + return u8"\001c%.*s"; + break; + default: + return u8"%.*s"; + } + } +} + +namespace details +{ + +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline void linux_kpr_raw_write_fmt(char const* fmt,void const* start,void const* last) noexcept +{ + char const* start_char_ptr{reinterpret_cast(start)}; + char const* last_char_ptr{reinterpret_cast(last)}; + + std::size_t diff{static_cast(last_char_ptr-start_char_ptr)}; + constexpr int int_max{std::numeric_limits::max()}; + if constexpr(int_max<=std::numeric_limits::max()) + { + constexpr std::size_t int_max_size_val{static_cast(int_max)}; + if(diff>int_max_size_val)//linux kernel ring buffer has restricted size. discard >=INT_MAX bytes + diff=int_max_size_val; + } + ::fast_io::linux_kernel_printk(fmt,static_cast(diff),start_char_ptr); +} + +template +inline void linux_kpr_raw_write(::fast_io::kern k,void const* start,void const* last) noexcept +{ + linux_kpr_raw_write_fmt(reinterpret_cast(kern_to_fmt(k)),start,last); +} + +template +inline constexpr void print_status_define_single_line_impl(basic_kpr kpr,T t) +{ + basic_io_scatter_t scatter{print_scatter_define(io_reserve_type,t)}; + auto base{scatter.base}; + linux_kpr_raw_write(kpr.level,base,base+scatter.len); +} + +template +requires (static_cast(k)<=static_cast(kern::cont)) +inline constexpr auto linux_kernel_printk_formatter_cal() noexcept +{ + static_assert(n<=(SIZE_MAX-256u)/4u); + constexpr std::size_t start{(k==kern::default_value?0:2)}; + ::fast_io::freestanding::array(line)> fmts; + + if constexpr(k!=kern::default_value) + { + fmts[0]=1; + if constexpr(k(u8'0'+static_cast(k)); + } + else + fmts[1]=u8'c'; + } + for(std::size_t i{};i!=n;++i) + { + std::size_t j{start+i*4}; + fmts[j]=u8'%'; + fmts[j+1]=u8'.'; + fmts[j+2]=u8'*'; + fmts[j+3]=u8's'; + } + if constexpr(line) + { + fmts[fmts.size()-2]=u8'\n'; + } + fmts.back()=0; + return fmts; +} + +template +inline constexpr auto kfmtcache{linux_kernel_printk_formatter_cal()}; + +template +inline constexpr char8_t const* cal_kpr_fmt(kern k) noexcept +{ + switch(k) + { + case kern::emerg: + return kfmtcache.element; + case kern::alert: + return kfmtcache.element; + case kern::crit: + return kfmtcache.element; + case kern::warning: + return kfmtcache.element; + case kern::notice: + return kfmtcache.element; + case kern::info: + return kfmtcache.element; + case kern::debug: + return kfmtcache.element; + case kern::cont: + return kfmtcache.element; + break; + default: + return kfmtcache.element; + } +} + +struct kpr_scatter_struct +{ + char const* ptr; + int bytes; +}; + +template +inline void kpr_scatter_print_recursive(kpr_scatter_struct* p,T t,Args ...args) +{ + auto scatter{print_scatter_define(io_reserve_type,t)}; + std::size_t len{scatter.len*sizeof(char_type)}; + constexpr int int_max{std::numeric_limits::max()}; + if(len>int_max) + len=int_max; + *--p={reinterpret_cast(scatter.base),static_cast(len)}; + if constexpr(sizeof...(Args)!=0) + kpr_scatter_print_recursive(p,args...); +} + +template +inline void kpr_scatter_reserve_print_recursive(kpr_scatter_struct* p,char_type* buffer,T t,Args ...args) +{ + if constexpr(scatter_printable) + { + auto scatter{print_scatter_define(io_reserve_type,t)}; + std::size_t len{scatter.len*sizeof(char_type)}; + constexpr int int_max{std::numeric_limits::max()}; + if(len>int_max) + len=int_max; + *--p={reinterpret_cast(scatter.base),static_cast(len)}; + } + else + { + auto newbufferptr{print_reserve_define(io_reserve_type,buffer,t)}; + *--p={reinterpret_cast(buffer),static_cast(newbufferptr-buffer)}; + buffer=newbufferptr; + } + if constexpr(sizeof...(Args)!=0) + { + if constexpr((scatter_printable&&...)) + kpr_scatter_print_recursive(p,args...); + else + kpr_scatter_reserve_print_recursive(p,buffer,args...); + } +} + + +template +inline void deal_with_kpr_fmt_real(char const* fmt_str,kpr_scatter_struct* s,Args ...args) +{ + if constexpr(n==0) + ::fast_io::linux_kernel_printk(fmt_str,args...); + else + deal_with_kpr_fmt_real(fmt_str,s+1,s->bytes,s->ptr,args...); +} + +template +inline constexpr bool kpr_total_print_reserve_size_less_or_equal_than512(std::size_t size) noexcept +{ + if constexpr(reserve_printable) + { + constexpr std::size_t this_size{print_reserve_size(io_reserve_type)}; + if constexpr(this_size>=std::numeric_limits::max()) + return false; + if(__builtin_add_overflow(size,this_size,__builtin_addressof(size))) + return false; + if(size>512) + return false; + } + else if constexpr(!scatter_printable) + return false; + if constexpr(sizeof...(Args)==0) + { + return true; + } + else + { + return kpr_total_print_reserve_size_less_or_equal_than512(size); + } +} +template +inline constexpr bool kpr_total_print_reserve_size_less_or_equal_than512(std::size_t size) noexcept +{ + return size<=512; +} + +template +inline void deal_with_kpr_ignore_line(char const* fmt_str,Args ...args) +{ + constexpr std::size_t n{sizeof...(Args)}; + if constexpr(n==0) + { + ::fast_io::linux_kernel_printk(fmt_str); + } + else + { + kpr_scatter_struct buffer[n]; + if constexpr((scatter_printable&&...)) + { + kpr_scatter_print_recursive(buffer+n,args...); + deal_with_kpr_fmt_real(fmt_str,buffer); + } + else + { + constexpr std::size_t reserve_size{::fast_io::details::decay::calculate_scatter_reserve_size()}; + char_type reserve_buffer[reserve_size]; + kpr_scatter_reserve_print_recursive(buffer+n,reserve_buffer,args...); + deal_with_kpr_fmt_real(fmt_str,buffer); + } + } +} + +template +inline void deal_with_kpr_common(basic_kpr kpr,Args ...args) +{ + constexpr std::size_t n{sizeof...(Args)}; + if constexpr(n==0&&!line) + { + if(kpr.level==kern::default_value) + return; + } + deal_with_kpr_ignore_line(reinterpret_cast(cal_kpr_fmt(kpr.level)),args...); +} + +} + +template +inline void write(basic_kpr kpr,Iter first,Iter last) noexcept +{ + details::linux_kpr_raw_write(kpr.level,::std::to_address(first),::std::to_address(last)); +} + +template +inline constexpr basic_kpr io_value_handle(basic_kpr linuxkpr) noexcept +{ + return linuxkpr; +} + +using kpr = basic_kpr; +using wkpr = basic_kpr; +using u8kpr = basic_kpr; +using u16kpr = basic_kpr; +using u32kpr = basic_kpr; + +template +requires (print_freestanding_decay_okay_character_type_no_status&&sizeof(ch_type)==1&&(!::fast_io::details::is_ebcdic)) +inline constexpr void print_status_define(basic_kpr k,Args ...args) +{ + if constexpr((::fast_io::details::kpr_total_print_reserve_size_less_or_equal_than512(0))) + ::fast_io::details::deal_with_kpr_common(k,args...); + else + print_freestanding_decay_no_status(k,args...); +} + +} diff --git a/src/fast_io/include/fast_io_driver/llvm.h b/src/fast_io/include/fast_io_driver/llvm.h new file mode 100644 index 0000000..9db196a --- /dev/null +++ b/src/fast_io/include/fast_io_driver/llvm.h @@ -0,0 +1,9 @@ +#pragma once + +#include"../fast_io.h" +#include +#include"llvm_impl/hack_buffer_ptr.h" +#include"llvm_impl/raw_ostream_io_observer.h" +#if !defined(__AVR__) +#include"llvm_impl/raw_fd_ostream_file.h" +#endif diff --git a/src/fast_io/include/fast_io_driver/llvm_impl/hack_buffer_ptr.h b/src/fast_io/include/fast_io_driver/llvm_impl/hack_buffer_ptr.h new file mode 100644 index 0000000..8cbca23 --- /dev/null +++ b/src/fast_io/include/fast_io_driver/llvm_impl/hack_buffer_ptr.h @@ -0,0 +1,84 @@ +#pragma once + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC system_header +#endif + +namespace fast_io::llvm::details +{ + +class llvm_raw_ostream_model { +public: + void* ptr{}; + ::llvm::raw_ostream::OStreamKind Kind; + char *OutBufStart, *OutBufEnd, *OutBufCur; + bool ColorEnabled = false; + + /// Optional stream this stream is tied to. If this stream is written to, the + /// tied-to stream will be flushed first. + ::llvm::raw_ostream *TiedStream = nullptr; +}; + +template +requires (position<3u) +inline constexpr std::size_t llvm_raw_ostream_cal_obuffer_ptr_position() noexcept +{ + constexpr std::size_t offset{__builtin_offsetof(llvm_raw_ostream_model,OutBufStart)}; + if constexpr(position==0u) + return offset; + else if constexpr(position==1u) + return offset+2*sizeof(char*); + else + return offset+sizeof(char*); +} + +template +requires (position<3u) +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char_type* llvm_raw_ostream_obuffer_ptr(::llvm::raw_ostream* os) noexcept +{ + constexpr std::size_t offset{llvm_raw_ostream_cal_obuffer_ptr_position()}; + char_type* ptr; + ::fast_io::details::my_memcpy(__builtin_addressof(ptr),reinterpret_cast(os)+offset,sizeof(char_type*)); + return ptr; +} + +inline void llvm_raw_ostream_set_obuffer_curr_ptr(::llvm::raw_ostream* os,char* vdptr) +{ + constexpr std::size_t offset{llvm_raw_ostream_cal_obuffer_ptr_position<1>()}; + ::fast_io::details::my_memcpy(reinterpret_cast(os)+offset,__builtin_addressof(vdptr),sizeof(char*)); +} + +inline void llvm_raw_ostream_overflow(::llvm::raw_ostream* os,char ch) +{ + os->flush(); + constexpr std::size_t one{1u}; + os->write(__builtin_addressof(ch),one); +} + +class raw_fd_ostream_model : public ::llvm::raw_pwrite_stream +{ +public: +int FD; +bool ShouldClose; +bool SupportsSeeking = false; +}; +inline constexpr std::size_t fdoffset{__builtin_offsetof(raw_fd_ostream_model,FD)}; + +inline int hack_fd_from_llvm_raw_fd_ostream(::llvm::raw_fd_ostream* os) noexcept +{ + if(os==nullptr) + return -1; + int fd; + ::fast_io::details::my_memcpy(__builtin_addressof(fd),reinterpret_cast(os)+fdoffset,sizeof(int)); + return fd; +} + +inline void hack_set_fd_to_llvm_raw_fd_ostream(::llvm::raw_fd_ostream* os,int fd) noexcept +{ + ::fast_io::details::my_memcpy(reinterpret_cast(os)+fdoffset,__builtin_addressof(fd),sizeof(int)); +} + +} diff --git a/src/fast_io/include/fast_io_driver/llvm_impl/raw_fd_ostream_file.h b/src/fast_io/include/fast_io_driver/llvm_impl/raw_fd_ostream_file.h new file mode 100644 index 0000000..01ffab5 --- /dev/null +++ b/src/fast_io/include/fast_io_driver/llvm_impl/raw_fd_ostream_file.h @@ -0,0 +1,117 @@ +#pragma once + +namespace fast_io::llvm +{ + +namespace details +{ + +inline ::llvm::raw_fd_ostream* open_llvm_raw_fd_ostream_from_fd(int fd) +{ + return new ::llvm::raw_fd_ostream(fd,true); +} + +inline ::llvm::raw_fd_ostream* open_llvm_raw_fd_ostream_from_fd_dup(::llvm::raw_fd_ostream* f) +{ + return open_llvm_raw_fd_ostream_from_fd(::fast_io::details::sys_dup(hack_fd_from_llvm_raw_fd_ostream(f))); +} + +inline ::llvm::raw_fd_ostream* open_llvm_raw_fd_ostream_from_fd_dup2(::llvm::raw_fd_ostream* thisfdos,::llvm::raw_fd_ostream* otherfdos) +{ + if(thisfdos==nullptr) + return open_llvm_raw_fd_ostream_from_fd_dup(otherfdos); + hack_set_fd_to_llvm_raw_fd_ostream(thisfdos,::fast_io::details::sys_dup2(hack_fd_from_llvm_raw_fd_ostream(otherfdos),hack_fd_from_llvm_raw_fd_ostream(thisfdos))); + return thisfdos; +} + +} + +template +requires (sizeof(ch_type)==1) +class basic_raw_fd_ostream_file:public basic_raw_fd_ostream_io_observer +{ +public: + using char_type = ch_type; + using native_handle_type = typename basic_raw_fd_ostream_io_observer::native_handle_type; + explicit constexpr basic_raw_fd_ostream_file() noexcept = default; + + constexpr basic_raw_fd_ostream_file(basic_raw_fd_ostream_io_observer) noexcept=delete; + constexpr basic_raw_fd_ostream_file& operator=(basic_raw_fd_ostream_io_observer) noexcept=delete; + + template + requires std::same_as + explicit constexpr basic_raw_fd_ostream_file(T* p) noexcept:basic_raw_fd_ostream_io_observer{p}{} + constexpr basic_raw_fd_ostream_file(basic_raw_fd_ostream_file&& __restrict other) noexcept:basic_raw_fd_ostream_io_observer{other.os} + { + other.os=nullptr; + } + basic_raw_fd_ostream_file& operator=(basic_raw_fd_ostream_file&& __restrict other) noexcept + { + delete this->os; + this->os=other.os; + other.os=nullptr; + } + basic_raw_fd_ostream_file(basic_raw_fd_ostream_file const& other):basic_raw_fd_ostream_io_observer{open_llvm_raw_fd_ostream_from_fd_dup(other.os)}{} + basic_raw_fd_ostream_file& operator=(basic_raw_fd_ostream_file const& other) + { + this->os=::fast_io::llvm::details::open_llvm_raw_fd_ostream_from_fd_dup2(this->os,other.os); + return *this; + } + basic_raw_fd_ostream_file(basic_posix_file&& pioh,::fast_io::open_mode): + basic_raw_fd_ostream_io_observer{new ::llvm::raw_fd_ostream(pioh.fd,true)} + { + pioh.fd=-1; + } +#if (defined(_WIN32)&&!defined(__WINE__)) || defined(__CYGWIN__) +//windows specific. open posix file from win32 io handle + template + basic_raw_fd_ostream_file(basic_win32_family_file&& win32_handle,open_mode mode): + basic_raw_fd_ostream_file(basic_posix_file(::std::move(win32_handle),mode),mode) + { + } + template + basic_raw_fd_ostream_file(basic_nt_family_file&& nt_handle,open_mode mode): + basic_raw_fd_ostream_file(basic_posix_file(::std::move(nt_handle),mode),mode) + { + } +#endif + void close() + { + if(this->os) + { + struct destroy + { + native_handle_type& hd; + + + ~destroy() + { + delete hd; + hd=nullptr; + } + }des{this->os}; + this->os.close(); + } + } + ~basic_raw_fd_ostream_file() + { + delete this->os; + } + + basic_raw_fd_ostream_file(native_fs_dirent fsdirent,open_mode om,perms pm=static_cast(436)): + basic_raw_fd_ostream_file(basic_posix_file(fsdirent,om,pm),om) + {} + template<::fast_io::constructible_to_os_c_str T> + basic_raw_fd_ostream_file(T const& file,open_mode om,perms pm=static_cast(436)): + basic_raw_fd_ostream_file(basic_posix_file(file,om,pm),om) + {} + template<::fast_io::constructible_to_os_c_str T> + basic_raw_fd_ostream_file(native_at_entry nate,T const& file,open_mode om,perms pm=static_cast(436)): + basic_raw_fd_ostream_file(basic_posix_file(nate,file,om,pm),om) + {} +}; + +using raw_fd_ostream_file=basic_raw_fd_ostream_file; +using u8raw_fd_ostream_file=basic_raw_fd_ostream_file; + +} diff --git a/src/fast_io/include/fast_io_driver/llvm_impl/raw_ostream_io_observer.h b/src/fast_io/include/fast_io_driver/llvm_impl/raw_ostream_io_observer.h new file mode 100644 index 0000000..a8c02b7 --- /dev/null +++ b/src/fast_io/include/fast_io_driver/llvm_impl/raw_ostream_io_observer.h @@ -0,0 +1,141 @@ +#pragma once + +namespace fast_io::llvm +{ + +template +requires (std::derived_from&&sizeof(ch_type)==1) +class basic_general_raw_ostream_io_observer +{ +public: + using char_type = ch_type; + using native_handle_type = T*; + native_handle_type os{}; + inline constexpr native_handle_type release() noexcept + { + auto temp{os}; + os=nullptr; + return temp; + } + inline constexpr native_handle_type native_handle() const noexcept + { + return os; + } + inline explicit constexpr operator bool() const noexcept + { + return os; + } +#if !defined(__AVR__) + explicit operator basic_posix_io_observer() const noexcept requires(std::derived_from) + { + return {::fast_io::llvm::details::hack_fd_from_llvm_raw_fd_ostream(this->os)}; + } +#if (defined(_WIN32)&&!defined(__WINE__)) || defined(__CYGWIN__) + explicit operator basic_win32_io_observer() const noexcept requires(std::derived_from) + { + return static_cast> + (static_cast>(*this)); + } + template + explicit operator basic_nt_family_io_observer() const noexcept requires(std::derived_from) + { + return static_cast> + (static_cast>(*this)); + } +#endif +#endif +}; + +template +inline constexpr basic_general_raw_ostream_io_observer io_value_handle(basic_general_raw_ostream_io_observer osiob) noexcept +{ + return osiob; +} + +namespace details +{ + +inline void llvm_ostream_write_impl(::llvm::raw_ostream* os,void const* first_vptr,void const* last_vptr) +{ + char const* first{reinterpret_cast(first_vptr)}; + char const* last{reinterpret_cast(last_vptr)}; + std::size_t const n{static_cast(last-first)}; + auto os_obuffer_curr_ptr{llvm_raw_ostream_obuffer_ptr<1,char>(os)}; + auto os_obuffer_end_ptr{llvm_raw_ostream_obuffer_ptr<2,char>(os)}; + std::size_t const remain_size{static_cast(os_obuffer_end_ptr-os_obuffer_curr_ptr)}; + if(nwrite(first,n); +} + +} + +template +inline constexpr void write(basic_general_raw_ostream_io_observer osiob,Iter first,Iter last) +{ + ::fast_io::llvm::details::llvm_ostream_write_impl(osiob.os,::std::to_address(first),::std::to_address(last)); +} + +template +inline constexpr void flush(basic_general_raw_ostream_io_observer osiob) +{ + osiob.os->flush(); +} + +template +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char_type* obuffer_begin(basic_general_raw_ostream_io_observer osiob) noexcept +{ + return ::fast_io::llvm::details::llvm_raw_ostream_obuffer_ptr<0,char_type>(osiob.os); +} + +template +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char_type* obuffer_curr(basic_general_raw_ostream_io_observer osiob) noexcept +{ + return ::fast_io::llvm::details::llvm_raw_ostream_obuffer_ptr<1,char_type>(osiob.os); +} + +template +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char_type* obuffer_end(basic_general_raw_ostream_io_observer osiob) noexcept +{ + return ::fast_io::llvm::details::llvm_raw_ostream_obuffer_ptr<2,char_type>(osiob.os); +} + +template +inline void obuffer_set_curr(basic_general_raw_ostream_io_observer osiob, +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +char_type* ptr) noexcept +{ + ::fast_io::llvm::details::llvm_raw_ostream_set_obuffer_curr_ptr(osiob.os,reinterpret_cast(ptr)); +} + +template +inline void obuffer_overflow(basic_general_raw_ostream_io_observer osiob,char_type ch) noexcept +{ + ::fast_io::llvm::details::llvm_raw_ostream_overflow(osiob.os,static_cast(ch)); +} + +template +using basic_raw_ostream_io_observer=basic_general_raw_ostream_io_observer; +using raw_ostream_io_observer=basic_raw_ostream_io_observer; +using u8raw_ostream_io_observer=basic_raw_ostream_io_observer; + +template +using basic_raw_fd_ostream_io_observer=basic_general_raw_ostream_io_observer; +using raw_fd_ostream_io_observer=basic_raw_fd_ostream_io_observer; +using u8raw_fd_ostream_io_observer=basic_raw_fd_ostream_io_observer; + +} diff --git a/src/fast_io/include/fast_io_driver/mangling.h b/src/fast_io/include/fast_io_driver/mangling.h new file mode 100644 index 0000000..faa81c0 --- /dev/null +++ b/src/fast_io/include/fast_io_driver/mangling.h @@ -0,0 +1,98 @@ +#pragma once +#if __has_include() +#include +#endif +#include + +namespace fast_io +{ + +struct cxa_demangle +{ + char* buffer{}; + std::size_t length{}; + explicit cxa_demangle(char const* mangled_name) noexcept + { +#if __has_include() + int status{}; + buffer=static_cast( + abi::__cxa_demangle(mangled_name, + nullptr,__builtin_addressof(length), + __builtin_addressof(status))); + if(buffer!=nullptr) + { + length=strlen(buffer); + } + else +#endif + { + length=strlen(mangled_name); + std::size_t lengthp1{length+1}; + auto newp{malloc(lengthp1)}; + if(newp==nullptr) + { + fast_terminate(); + } + memcpy(newp,mangled_name,lengthp1); + buffer=reinterpret_cast(newp); + } + } + cxa_demangle(cxa_demangle const& other) noexcept: + buffer(reinterpret_cast(malloc(other.length+1))), + length(other.length) + { + if(buffer==nullptr) + fast_terminate(); + ::fast_io::details::my_memcpy(buffer,other.buffer,length); + buffer[length]=0; + } + cxa_demangle& operator=(cxa_demangle const& other) noexcept + { + auto newp{reinterpret_cast(malloc(other.length+1))}; + if(newp==nullptr) + fast_terminate(); + ::fast_io::details::my_memcpy(newp,other.buffer,other.length); + newp[other.length]=0; + free(buffer); + buffer=newp; + length=other.length; + return *this; + } + constexpr cxa_demangle(cxa_demangle&& __restrict other) noexcept:buffer(other.buffer),length(other.length) + { + other.buffer=nullptr; + other.length=0; + } + cxa_demangle& operator=(cxa_demangle&& __restrict other) noexcept + { + free(buffer); + buffer=other.buffer; + length=other.length; + other.buffer=nullptr; + other.length=0; + return *this; + } + char const* data() const noexcept + { + return buffer; + } + char const* begin() const noexcept + { + return buffer; + } + char const* end() const noexcept + { + return buffer+length; + } + ~cxa_demangle() + { + free(buffer); + } +}; + +inline constexpr basic_io_scatter_t print_alias_define(io_alias_t,cxa_demangle const& man) noexcept +{ + return {man.buffer,man.length}; +} + +} diff --git a/src/fast_io/include/fast_io_driver/mfc.h b/src/fast_io/include/fast_io_driver/mfc.h new file mode 100644 index 0000000..85b407a --- /dev/null +++ b/src/fast_io/include/fast_io_driver/mfc.h @@ -0,0 +1,14 @@ +#pragma once + +#if defined(__ATLSTR_H__) +#include"../fast_io_core.h" +#include"mfc_impl/atl_cstring.h" +#endif +#if defined(__AFX_H__) +#include"../fast_io_hosted.h" +#include"mfc_impl/mfc_file.h" +#endif +#if defined(__ATLFILE_H__) +#include"../fast_io_hosted.h" +#include"mfc_impl/atl_file.h" +#endif diff --git a/src/fast_io/include/fast_io_driver/mfc_impl/atl_cstring.h b/src/fast_io/include/fast_io_driver/mfc_impl/atl_cstring.h new file mode 100644 index 0000000..0bcac9e --- /dev/null +++ b/src/fast_io/include/fast_io_driver/mfc_impl/atl_cstring.h @@ -0,0 +1,38 @@ +#pragma once + +namespace fast_io +{ + +template +inline constexpr cross_code_cvt_t print_alias_define(::fast_io::io_alias_t,::ATL::CStringT const& atl_mfccstr) noexcept +{ + return {{static_cast(atl_mfccstr),static_cast(atl_mfccstr.GetLength())}}; +} + + +template +inline ::ATL::CStringT strlike_construct_define(io_strlike_type_t>,cross_ch_type const* first,cross_ch_type const* last) +{ + std::size_t diff{static_cast(last-first)}; + if constexpr(sizeof(std::uint_least32_t)(first,static_cast(static_cast(diff))); +} + +template +inline CString concat_atl_cstring(Args&& ...args) +{ + return ::fast_io::basic_general_concat(::std::forward(args)...); +} + +template +inline CString concatln_atl_cstring(Args&& ...args) +{ + return ::fast_io::basic_general_concat(::std::forward(args)...); +} + +} diff --git a/src/fast_io/include/fast_io_driver/mfc_impl/atl_file.h b/src/fast_io/include/fast_io_driver/mfc_impl/atl_file.h new file mode 100644 index 0000000..e8a7635 --- /dev/null +++ b/src/fast_io/include/fast_io_driver/mfc_impl/atl_file.h @@ -0,0 +1,236 @@ +#pragma once + +namespace fast_io +{ + +template +class basic_atl_io_observer +{ +public: + using char_type = T; + using native_handle_type = CAtlFile*; + native_handle_type phandle{}; + explicit constexpr operator bool() const noexcept + { + return phandle; + } + template + explicit operator basic_win32_family_io_observer() const noexcept + { + return {phandle->m_hFile}; + } + + template + explicit operator basic_nt_family_io_observer() const noexcept + { + return {phandle->m_hFile}; + } + constexpr native_handle_type native_handle() const noexcept + { + return phandle; + } + inline constexpr native_handle_type release() noexcept + { + auto temp{phandle}; + phandle=nullptr; + return temp; + } +}; + +template +inline constexpr basic_atl_io_observer io_value_handle(basic_atl_io_observer t) noexcept +{ + return t; +} + +struct com_error +{ + HRESULT hr{}; +}; + +namespace details +{ + +inline void throw_com_error(HRESULT hr) +{ +#ifdef __cpp_exceptions +#if defined(_MSC_VER) && (!defined(_HAS_EXCEPTIONS) || _HAS_EXCEPTIONS == 0) + fast_terminate(); +#else + throw com_error{hr}; +#endif +#else + fast_terminate(); +#endif +} + +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline void atl_write_n_impl(CAtlFile* cfp,std::byte const* first_ptr,std::size_t n) +{ + if constexpr(sizeof(std::size_t)>sizeof(std::uint_least32_t)) + { + while(n) + { + constexpr std::size_t sz_max{static_cast(UINT_LEAST32_MAX)}; + std::size_t write_this_round{n}; + if(sz_maxWrite(first_ptr,static_cast(write_this_round))}; + if(hresult!=S_OK) + throw_com_error(hresult); + n-=write_this_round; + } + } + else + { + cfp->Write(first_ptr,static_cast(n)); + } +} + +inline void atl_write_impl(CAtlFile* cfp,void const* first,void const* last) +{ + char const* first_ptr{reinterpret_cast(first)}; + char const* last_ptr{reinterpret_cast(last)}; + atl_write_n_impl(cfp,reinterpret_cast(first_ptr),static_cast(last_ptr-first_ptr)); +} + +inline std::size_t atl_read_impl(CAtlFile* cfp,void* first,std::size_t to_read) +{ + if constexpr(sizeof(std::size_t)>4) + if(static_cast(UINT_LEAST32_MAX)(UINT_LEAST32_MAX); + DWORD ret{}; + auto hr{cfp->Read(first,static_cast(to_read),ret)}; + if(hr!=S_OK) + throw_com_error(hr); + return static_cast(ret); +} + +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline void atl_scatter_write_impl(CAtlFile* cfp,io_scatter_t const* scats,std::size_t n) +{ + auto i{scats}; + auto e{scats+n}; + for(;i!=e;++i) + { + atl_write_n_impl(cfp,reinterpret_cast(scats->base),scats->len); + } +} + +} + +template +inline void write(basic_atl_io_observer hd,Iter first,Iter last) +{ + ::fast_io::details::atl_write_impl(hd.phandle,::std::to_address(first),::std::to_address(last)); +} + +template +inline void scatter_write(basic_atl_io_observer hd,io_scatters_t scatters) +{ + ::fast_io::details::atl_scatter_write_impl(hd.phandle,scatters.base,scatters.len); +} + +template +inline void flush(basic_atl_io_observer hd) +{ + hd.phandle->Flush(); +} + +template +inline Iter read(basic_atl_io_observer hd,Iter first,Iter last) +{ + return first+atl_read_impl(hd.phandle,::std::to_address(first),(last-first)*sizeof(*first))/sizeof(T); +} + +template +class basic_atl_file:public basic_atl_io_observer +{ +public: + using char_type = ch_type; + using native_handle_type = CAtlFile*; + constexpr basic_atl_file() noexcept=default; + template + requires std::same_as + explicit constexpr basic_atl_file(T hd) noexcept:basic_atl_io_observer{hd}{} + explicit constexpr basic_atl_file(decltype(nullptr)) noexcept = delete; + + constexpr basic_atl_file(basic_atl_io_observer) noexcept=delete; + constexpr basic_atl_file& operator=(basic_atl_io_observer) noexcept=delete; + template + explicit basic_atl_file(basic_win32_family_file&& hd,open_mode): + basic_atl_io_observer{new CAtlFile(hd.handle)} + { + hd.release(); + } + template + explicit basic_atl_file(basic_nt_family_file&& hd,open_mode): + basic_atl_io_observer{new CAtlFile(hd.handle)} + { + hd.release(); + } + basic_atl_file(nt_fs_dirent fsdirent,open_mode om,perms pm=static_cast(436)): + basic_atl_file(basic_win32_file(fsdirent,om,pm),om) + {} + template<::fast_io::constructible_to_os_c_str T> + basic_atl_file(T const& t,open_mode om,perms pm=static_cast(436)): + basic_atl_file(basic_win32_file(t,om,pm),om) + {} + template<::fast_io::constructible_to_os_c_str T> + basic_atl_file(nt_at_entry nate,T const& t,open_mode om,perms pm=static_cast(436)): + basic_atl_file(basic_win32_file(nate,t,om,pm),om) + {} + + basic_atl_file(basic_atl_file const& mcf):basic_atl_io_observer{mcf.phandle->Duplicate()}{} + basic_atl_file& operator=(basic_atl_file const& mcf) + { + auto temp{mcf.phandle->Duplicate()}; + delete this->phandle; + this->phandle=temp; + return *this; + } + basic_atl_file(basic_atl_file&& mcf) noexcept:basic_atl_io_observer{mcf.phandle} + { + mcf.phandle=nullptr; + } + basic_atl_file& operator=(basic_atl_file&& __restrict mcf) noexcept + { + delete this->phandle; + this->phandle=mcf.phandle; + mcf.phandle=nullptr; + return *this; + } + void close() noexcept + { + delete this->phandle; + this->phandle=nullptr; + } + inline constexpr void reset(native_handle_type newhandle=nullptr) noexcept + { + delete this->phandle; + this->phandle=newhandle; + } + ~basic_atl_file() + { + delete this->phandle; + } +}; + +using atl_io_observer=basic_atl_io_observer; +using atl_file=basic_atl_file; +using u8atl_io_observer=basic_atl_io_observer; +using u8atl_file=basic_atl_file; +using watl_io_observer=basic_atl_io_observer; +using watl_file=basic_atl_file; +using u16atl_io_observer=basic_atl_io_observer; +using u16atl_file=basic_atl_file; +using u32atl_io_observer=basic_atl_io_observer; +using u32atl_file=basic_atl_file; + +} diff --git a/src/fast_io/include/fast_io_driver/mfc_impl/mfc_file.h b/src/fast_io/include/fast_io_driver/mfc_impl/mfc_file.h new file mode 100644 index 0000000..490f590 --- /dev/null +++ b/src/fast_io/include/fast_io_driver/mfc_impl/mfc_file.h @@ -0,0 +1,211 @@ +#pragma once + +namespace fast_io +{ + +template +class basic_mfc_io_observer +{ +public: + using char_type = T; + using native_handle_type = CFile*; + native_handle_type phandle{}; + explicit constexpr operator bool() const noexcept + { + return phandle; + } + template + explicit operator basic_win32_family_io_observer() const noexcept + { + return {phandle->m_hFile}; + } + + template + explicit operator basic_nt_family_io_observer() const noexcept + { + return {phandle->m_hFile}; + } + constexpr native_handle_type native_handle() const noexcept + { + return phandle; + } + inline constexpr native_handle_type release() noexcept + { + auto temp{phandle}; + phandle=nullptr; + return temp; + } +}; + +template +inline constexpr basic_mfc_io_observer io_value_handle(basic_mfc_io_observer t) noexcept +{ + return t; +} + +namespace details +{ +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline void mfc_write_n_impl(CFile* cfp,std::byte const* first_ptr,std::size_t n) +{ + if constexpr(sizeof(std::size_t)>sizeof(std::uint_least32_t)) + { + while(n) + { + constexpr std::size_t sz_max{static_cast(UINT_LEAST32_MAX)}; + std::size_t write_this_round{n}; + if(sz_maxWrite(first_ptr,static_cast(write_this_round)); + n-=write_this_round; + } + } + else + { + cfp->Write(first_ptr,static_cast(n)); + } +} + +inline void mfc_write_impl(CFile* cfp,void const* first,void const* last) +{ + char const* first_ptr{reinterpret_cast(first)}; + char const* last_ptr{reinterpret_cast(last)}; + mfc_write_n_impl(cfp,reinterpret_cast(first_ptr),static_cast(last_ptr-first_ptr)); +} + +inline std::size_t mfc_read_impl(CFile* cfp,void* first,std::size_t to_read) +{ + if constexpr(sizeof(std::size_t)>4) + if(static_cast(UINT_LEAST32_MAX)(UINT_LEAST32_MAX); + return cfp->Read(first,static_cast(to_read)); +} + +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline void mfc_scatter_write_impl(CFile* cfp,io_scatter_t const* scats,std::size_t n) +{ + auto i{scats}; + auto e{scats+n}; + for(;i!=e;++i) + { + mfc_write_n_impl(cfp,reinterpret_cast(scats->base),scats->len); + } +} + +} + +template +inline void write(basic_mfc_io_observer hd,Iter first,Iter last) +{ + ::fast_io::details::mfc_write_impl(hd.phandle,::std::to_address(first),::std::to_address(last)); +} + +template +inline void scatter_write(basic_mfc_io_observer hd,io_scatters_t scatters) +{ + ::fast_io::details::mfc_scatter_write_impl(hd.phandle,scatters.base,scatters.len); +} + +template +inline void flush(basic_mfc_io_observer hd) +{ + hd.phandle->Flush(); +} + +template +inline Iter read(basic_mfc_io_observer hd,Iter first,Iter last) +{ + return first+mfc_read_impl(hd.phandle,::std::to_address(first),(last-first)*sizeof(*first))/sizeof(T); +} + +template +class basic_mfc_file:public basic_mfc_io_observer +{ +public: + using char_type = ch_type; + using native_handle_type = CFile*; + constexpr basic_mfc_file() noexcept=default; + template + requires std::same_as + explicit constexpr basic_mfc_file(T hd) noexcept:basic_mfc_io_observer{hd}{} + explicit constexpr basic_mfc_file(decltype(nullptr)) noexcept = delete; + + constexpr basic_mfc_file(basic_mfc_io_observer) noexcept=delete; + constexpr basic_mfc_file& operator=(basic_mfc_io_observer) noexcept=delete; + + basic_mfc_file(basic_mfc_file const& mcf):basic_mfc_io_observer{mcf.phandle->Duplicate()}{} + basic_mfc_file& operator=(basic_mfc_file const& mcf) + { + auto temp{mcf.phandle->Duplicate()}; + delete this->phandle; + this->phandle=temp; + return *this; + } + basic_mfc_file(basic_mfc_file&& __restrict mcf) noexcept:basic_mfc_io_observer{mcf.phandle} + { + mcf.phandle=nullptr; + } + basic_mfc_file& operator=(basic_mfc_file&& __restrict mcf) noexcept + { + delete this->phandle; + this->phandle=mcf.phandle; + mcf.phandle=nullptr; + return *this; + } + void close() noexcept + { + delete this->phandle; + this->phandle=nullptr; + } + inline constexpr void reset(native_handle_type newhandle=nullptr) noexcept + { + delete this->phandle; + this->phandle=newhandle; + } + template + explicit basic_mfc_file(basic_win32_family_file&& hd,open_mode): + basic_mfc_io_observer{new CFile(hd.handle)} + { + hd.release(); + } + template + explicit basic_mfc_file(basic_nt_family_file&& hd,open_mode): + basic_mfc_io_observer{new CFile(hd.handle)} + { + hd.release(); + } + basic_mfc_file(nt_fs_dirent fsdirent,open_mode om,perms pm=static_cast(436)): + basic_mfc_file(basic_win32_file(fsdirent,om,pm),om) + {} + template<::fast_io::constructible_to_os_c_str T> + basic_mfc_file(T const& t,open_mode om,perms pm=static_cast(436)): + basic_mfc_file(basic_win32_file(t,om,pm),om) + {} + template<::fast_io::constructible_to_os_c_str T> + basic_mfc_file(nt_at_entry nate,T const& t,open_mode om,perms pm=static_cast(436)): + basic_mfc_file(basic_win32_file(nate,t,om,pm),om) + {} + ~basic_mfc_file() + { + delete this->phandle; + } +}; + +using mfc_io_observer=basic_mfc_io_observer; +using mfc_file=basic_mfc_file; +using u8mfc_io_observer=basic_mfc_io_observer; +using u8mfc_file=basic_mfc_file; +using wmfc_io_observer=basic_mfc_io_observer; +using wmfc_file=basic_mfc_file; +using u16mfc_io_observer=basic_mfc_io_observer; +using u16mfc_file=basic_mfc_file; +using u32mfc_io_observer=basic_mfc_io_observer; +using u32mfc_file=basic_mfc_file; + +} diff --git a/src/fast_io/include/fast_io_driver/nt_kernel.h b/src/fast_io/include/fast_io_driver/nt_kernel.h new file mode 100644 index 0000000..14fcd05 --- /dev/null +++ b/src/fast_io/include/fast_io_driver/nt_kernel.h @@ -0,0 +1,4 @@ +#pragma once + +#include"../fast_io.h" +#include"nt_kernel_impl/driver_object.h" diff --git a/src/fast_io/include/fast_io_driver/nt_kernel_impl/driver_object.h b/src/fast_io/include/fast_io_driver/nt_kernel_impl/driver_object.h new file mode 100644 index 0000000..57a02a6 --- /dev/null +++ b/src/fast_io/include/fast_io_driver/nt_kernel_impl/driver_object.h @@ -0,0 +1,24 @@ +#pragma once + +namespace fast_io::win32::nt +{ + +struct driver_object +{ +std::int_least16_t Type; +std::int_least16_t Size; +driver_object* DeviceObject; +std::uint_least32_t Flags; +void* DriverStart; +std::uint_least32_t DriverSize; +void* DriverSection; +void* DriverExtension; +utf16_string DriverName; +utf16_string* HardwareDatabase; +void* FastIoDispatch; +void* DriverInit; +void* DriverStartIo; +void* DriverUnload; +void* MajorFunction[28]; +}; +} diff --git a/src/fast_io/include/fast_io_driver/openssl_driver.h b/src/fast_io/include/fast_io_driver/openssl_driver.h new file mode 100644 index 0000000..8b8fac0 --- /dev/null +++ b/src/fast_io/include/fast_io_driver/openssl_driver.h @@ -0,0 +1,31 @@ +#pragma once +#include +#ifdef OSSL_DEPRECATEDIN_3_0 +#undef OSSL_DEPRECATEDIN_3_0 +#define OSSL_DEPRECATEDIN_3_0 +#endif +#include +#include +#include +#include +#include +#include +#if __cpp_rtti +#include +#endif + +#include"../fast_io_hosted.h" +#include"../fast_io_legacy_impl/c/impl.h" +#include"openssl_driver/init.h" +#include"openssl_driver/observer.h" +#include"openssl_driver/error.h" +#include"openssl_driver/bio.h" +#if 0 +#include"openssl_driver/ossl_lib_context.h" +#include"openssl_driver/context.h" +#include"openssl_driver/ssl.h" +#endif +#include"openssl_driver/hash.h" +#if 0 +#include"openssl_driver/evp.h" +#endif diff --git a/src/fast_io/include/fast_io_driver/openssl_driver/bio.h b/src/fast_io/include/fast_io_driver/openssl_driver/bio.h new file mode 100644 index 0000000..c5c281a --- /dev/null +++ b/src/fast_io/include/fast_io_driver/openssl_driver/bio.h @@ -0,0 +1,490 @@ +#pragma once +struct bio_method_st +{ +int type; +char const *name; +int (*bwrite) (BIO *, const char *, size_t, size_t *) noexcept; +int (*bwrite_old) (BIO *, const char *, int) noexcept; +int (*bread) (BIO *, char *, size_t, size_t *) noexcept; +int (*bread_old) (BIO *, char *, int) noexcept; +int (*bputs) (BIO *, const char *) noexcept; +int (*bgets) (BIO *, char *, int) noexcept; +long (*ctrl) (BIO *, int, long, void *) noexcept; +int (*create) (BIO *) noexcept; +int (*destroy) (BIO *) noexcept; +long (*callback_ctrl) (BIO *, int, BIO_info_cb *) noexcept; +}; + +namespace fast_io +{ + +namespace details +{ +template +inline constexpr int calculate_bio_new_fp_flags(open_mode om) +{ + int flag{BIO_CLOSE}; + if constexpr(!detach) + flag=BIO_NOCLOSE; + if((om&open_mode::text)!=open_mode::none) + flag|=BIO_FP_TEXT; + return flag; +} + +template +struct bio_new_fp_flags +{ + inline static constexpr int value=calculate_bio_new_fp_flags(om); +}; + + +inline FILE* bio_to_fp(BIO* bio) noexcept +{ + FILE* fp{}; + ::fast_io::noexcept_call(BIO_ctrl,bio,BIO_C_GET_FILE_PTR,0,reinterpret_cast(__builtin_addressof(fp))); + return fp; +} + +inline int bio_to_fd(BIO* bio) noexcept +{ + auto fp{bio_to_fp(bio)}; + if(fp==nullptr) + { + int fd{-1}; + ::fast_io::noexcept_call(::BIO_ctrl,bio,BIO_C_GET_FD,0,reinterpret_cast(__builtin_addressof(fd))); + return fd; + } + return ::fast_io::details::fp_to_fd(fp); +} + +template +inline decltype(auto) get_cookie_data_from_void_ptr_data(void* data) noexcept +{ + if constexpr(::std::is_trivially_copyable_v&&sizeof(stm)<=sizeof(void*)) + { +#if __cpp_lib_bit_cast >= 201806L + alignas(alignof(stm)) ::fast_io::freestanding::array a; + my_memcpy(a.data(),__builtin_addressof(data),sizeof(stm)); + return __builtin_bit_cast(stm,a); +#else + stm s; + my_memcpy(s,__builtin_addressof(data),sizeof(stm)); + return s; +#endif + } + else + { + return *reinterpret_cast(data); + } +} + +template +inline decltype(auto) get_cookie_data_from_bio_data(BIO* bio) noexcept +{ + return get_cookie_data_from_void_ptr_data(noexcept_call(BIO_get_data,bio)); +} + +} + +template +requires (stream>) +struct bio_io_cookie_functions_t +{ + using native_functions_type = bio_method_st; + native_functions_type functions{}; + explicit bio_io_cookie_functions_t() + { + using value_type = std::remove_reference_t; + if constexpr(input_stream) + { + functions.bread=[](BIO* bbio,char* buf,std::size_t size,std::size_t* readd) noexcept->int + { +#ifdef __cpp_exceptions + try + { +#endif + *readd=read(::fast_io::details::get_cookie_data_from_bio_data(bbio),buf,buf+size)-buf; + return 1; +#ifdef __cpp_exceptions + } + catch(...) + { + return -1; + } +#endif + }; + } + if constexpr(output_stream) + { + functions.bwrite=[](BIO* bbio,char const* buf,std::size_t size,std::size_t* written) noexcept->int + { +#ifdef __cpp_exceptions + try + { +#endif + decltype(auto) v{::fast_io::details::get_cookie_data_from_bio_data(bbio)}; + if constexpr(std::same_as) + { + write(v,buf,buf+size); + *written=size; + } + else + *written=write(v,buf,buf+size)-buf; + return 1; +#ifdef __cpp_exceptions + } + catch(...) + { + return -1; + } +#endif + }; + } + if constexpr(!std::is_reference_v&&!std::is_trivially_copyable_v) + functions.destroy=[](BIO* bbio) noexcept -> int + { + delete reinterpret_cast(noexcept_call(BIO_get_data,bbio)); + return 1; + }; +#if __cpp_rtti + functions.name=typeid(stm).name(); + constexpr int value(BIO_TYPE_DESCRIPTOR-BIO_TYPE_START); + static_assert(0(typeid(stm).hash_code()%value+BIO_TYPE_START); +#else + functions.name=reinterpret_cast(u8"unknown"); + constexpr int value(BIO_TYPE_DESCRIPTOR-BIO_TYPE_START); + static_assert(0(BIO_TYPE_START); +#endif + } +}; + +template +inline bio_io_cookie_functions_t const bio_io_cookie_functions{}; + +namespace details +{ + +inline BIO* bio_new_stream_type(bio_method_st const* methods) +{ + auto bio{::fast_io::noexcept_call(BIO_new,methods)}; + if(bio==nullptr) + throw_openssl_error(); + return bio; +} + + +template +inline BIO* construct_bio_by_t(void* ptr) +{ + auto bp{bio_new_stream_type(__builtin_addressof(bio_io_cookie_functions.functions))}; + ::fast_io::noexcept_call(BIO_set_data,bp,ptr); + return bp; +} + +template +requires (std::is_trivially_copyable_v&&sizeof(stm)<=sizeof(void*)) +inline void* construct_cookie_by_args_trivial(Args&& ...args) +{ + stm s{::std::forward(args)...}; +#if __cpp_lib_bit_cast >= 201806L + if constexpr(sizeof(stm)==sizeof(void*)) + return __builtin_bit_cast(void*,s); + else +#endif + { + void* p{}; + __builtin_memcpy(__builtin_addressof(p),s,sizeof(stm)); + return p; + } +} + +template +struct bio_stm_scope_ptr +{ + stream* s{}; + explicit constexpr bio_stm_scope_ptr() noexcept = default; + explicit constexpr bio_stm_scope_ptr(stream *p) noexcept:s{p}{} + bio_stm_scope_ptr(bio_stm_scope_ptr const&)=delete; + bio_stm_scope_ptr& operator=(bio_stm_scope_ptr const&)=delete; + ~bio_stm_scope_ptr() + { + delete s; + } +}; + +template +inline BIO* construct_bio_by_phase2(stream* smptr) +{ + bio_stm_scope_ptr s(smptr); + return construct_bio_by_t(smptr); +} + +template +inline BIO* construct_bio_by_args(Args&&... args) +{ + if constexpr(std::is_trivially_copyable_v&&sizeof(stm)<=sizeof(void*)) + { + return construct_bio_by_t(construct_cookie_by_args_trivial(::std::forward(args)...)); + } + else + { + return construct_bio_by_phase2(new stm(::std::forward(args)...)); + } +} + +inline BIO* open_bio_with_fp_phase2(FILE* fp,int om) +{ + auto bio{::fast_io::noexcept_call(BIO_new_fp,fp,om)}; + if(bio==nullptr)[[unlikely]] + throw_openssl_error(); + return bio; +} + +inline BIO* open_bio_with_fp(FILE* fp,::fast_io::open_mode om) +{ + return open_bio_with_fp_phase2(fp,calculate_bio_new_fp_flags(om)); +} + +} + +template +class basic_bio_io_observer +{ +public: + using native_handle_type = BIO*; + using char_type = ch_type; + native_handle_type bio{}; + explicit constexpr operator bool() const noexcept + { + return bio; + } + constexpr native_handle_type native_handle() const noexcept + { + return bio; + } + constexpr native_handle_type release() noexcept + { + auto temp{bio}; + bio=nullptr; + return temp; + } + template<::fast_io::c_family family> + explicit operator basic_c_family_io_observer() const noexcept + { + return {details::bio_to_fp(bio)}; + } +#if !defined(__AVR__) + explicit operator basic_posix_io_observer() const noexcept + { + return {details::bio_to_fd(bio)}; + } +#if (defined(_WIN32) && !defined(__WINE__)) || defined(__CYGWIN__) + template<::fast_io::win32_family family> + explicit operator basic_win32_family_io_observer() const noexcept + { + return basic_win32_io_observer(static_cast>(*this)); + } + template + explicit operator basic_nt_family_io_observer() const noexcept + { + return basic_nt_family_io_observer(static_cast>(*this)); + } +#endif +#endif +}; +template +class basic_bio_file:public basic_bio_io_observer +{ +public: + using native_handle_type = BIO*; + using char_type = ch_type; + constexpr basic_bio_file()=default; + template + requires std::same_as> + explicit constexpr basic_bio_file(native_hd bio) noexcept:basic_bio_io_observer{bio}{} + + explicit constexpr basic_bio_file(decltype(nullptr)) noexcept=delete; + + constexpr basic_bio_file(basic_bio_io_observer) noexcept=delete; + constexpr basic_bio_file& operator=(basic_bio_io_observer) noexcept=delete; + + template + requires (!std::is_reference_v&&std::constructible_from) + basic_bio_file(::fast_io::io_cookie_type_t,Args&& ...args): + basic_bio_io_observer{details::construct_bio_by_args(::std::forward(args)...)} + { + } + template + basic_bio_file(basic_c_family_file&& bmv,fast_io::open_mode om): + basic_bio_io_observer{::fast_io::details::open_bio_with_fp(bmv.fp,om)} + { + bmv.fp=nullptr; + } + basic_bio_file(basic_posix_file&& bmv,fast_io::open_mode om): + basic_bio_file(basic_c_file(::std::move(bmv),om),om){} +#if (defined(_WIN32)&&!defined(__WINE__)) || defined(__CYGWIN__) + template + basic_bio_file(basic_win32_family_file&& win32_handle,fast_io::open_mode om): + basic_bio_file(basic_posix_file(::std::move(win32_handle),om),om) + { + } + template + basic_bio_file(basic_nt_family_file&& nt_handle,open_mode om): + basic_bio_file(basic_posix_file(::std::move(nt_handle),om),to_native_c_mode(om)) + { + } +#endif + template<::fast_io::constructible_to_os_c_str T> + basic_bio_file(T const& file,open_mode om,perms pm=static_cast(436)): + basic_bio_file(basic_c_file(file,om,pm),om) + {} + template<::fast_io::constructible_to_os_c_str T> + basic_bio_file(native_at_entry nate,T const& file,open_mode om,perms pm=static_cast(436)): + basic_bio_file(basic_c_file(nate,file,om,pm),om) + {} + inline constexpr void reset(native_handle_type newhandle=nullptr) noexcept + { + if(this->bio)[[likely]] + noexcept_call(BIO_free,this->bio); + this->bio=newhandle; + } + basic_bio_file(basic_bio_file const&)=delete; + basic_bio_file& operator=(basic_bio_file const&)=delete; + constexpr basic_bio_file(basic_bio_file&& __restrict bf) noexcept:basic_bio_io_observer(bf.bio) + { + bf.bio=nullptr; + } + basic_bio_file& operator=(basic_bio_file&& __restrict bf) noexcept + { + if(this->bio)[[likely]] + noexcept_call(BIO_free,this->bio); + this->bio=bf.bio; + bf.bio=nullptr; + return *this; + } + void close() + { + if(this->bio)[[likely]] + { + int ret{noexcept_call(BIO_free,this->bio)}; + this->bio=nullptr; + if(!ret)[[unlikely]] + throw_openssl_error(); + } + } + ~basic_bio_file() + { + if(this->bio)[[likely]] + noexcept_call(BIO_free,this->bio); + } +}; + +using bio_io_observer = basic_bio_io_observer; +using bio_file = basic_bio_file; +using wbio_io_observer = basic_bio_io_observer; +using wbio_file = basic_bio_file; +using u8bio_io_observer = basic_bio_io_observer; +using u8bio_file = basic_bio_file; +using u16bio_io_observer = basic_bio_io_observer; +using u16bio_file = basic_bio_file; +using u32bio_io_observer = basic_bio_io_observer; +using u32bio_file = basic_bio_file; + +namespace details +{ +inline std::size_t bio_read_impl(BIO* bio,void* address,std::size_t size) +{ + std::size_t read_bytes{}; + if(::fast_io::noexcept_call(BIO_read_ex,bio,address,size,__builtin_addressof(read_bytes))==-1) + throw_openssl_error(); + return read_bytes; +} + +inline std::size_t bio_write_impl(BIO* bio,void const* address,std::size_t size) +{ + std::size_t written_bytes{}; + if(::fast_io::noexcept_call(BIO_write_ex,bio,address,size,__builtin_addressof(written_bytes))==-1) + throw_openssl_error(); + return written_bytes; +} +#if 0 +inline posix_file_status bio_status_impl(BIO* bio) +{ + return status(posix_io_observer{::fast_io::details::bio_to_fd(bio)}); +} +#endif +} + +template +inline Iter read(basic_bio_io_observer iob,Iter begin,Iter end) +{ + return begin+details::bio_read_impl(iob.bio,::std::to_address(begin),static_cast(end-begin)*sizeof(*begin))/sizeof(*begin); +} + +template +inline Iter write(basic_bio_io_observer iob,Iter begin,Iter end) +{ + return begin+details::bio_write_impl(iob.bio,::std::to_address(begin),static_cast(end-begin)*sizeof(*begin))/sizeof(*begin); +} + +#if __cpp_lib_three_way_comparison >= 201907L +template +inline constexpr bool operator==(basic_bio_io_observer a,basic_bio_io_observer b) noexcept +{ + return a.bio==b.bio; +} + +template +inline constexpr auto operator<=>(basic_bio_io_observer a,basic_bio_io_observer b) noexcept +{ + return a.bio<=>b.bio; +} +#endif + +template +inline constexpr basic_bio_io_observer io_value_handle(basic_bio_io_observer other) noexcept +{ + return other; +} + +template +inline constexpr posix_at_entry at(basic_bio_io_observer bio) noexcept +{ + return posix_at_entry{details::bio_to_fd(bio.bio)}; +} +#if 0 +template +inline constexpr posix_file_status status(basic_bio_io_observer bio) +{ + return details::bio_status_impl(bio.bio); +} +#endif +namespace details +{ + +template +inline void print_define_openssl_error(output out) +{ + if constexpr(std::same_as) + { + ::fast_io::noexcept_call(ERR_print_errors,out.bio); + } + else + { + bio_file bf(io_cookie_type,out); + ::fast_io::noexcept_call(ERR_print_errors,bf.bio); + } +} + +} + +template +requires (std::is_trivially_copyable_v&&std::same_as) +inline void print_define(io_reserve_type_t,output out,openssl_error) +{ + ::fast_io::details::print_define_openssl_error(out); +} + +} diff --git a/src/fast_io/include/fast_io_driver/openssl_driver/context.h b/src/fast_io/include/fast_io_driver/openssl_driver/context.h new file mode 100644 index 0000000..eaccb96 --- /dev/null +++ b/src/fast_io/include/fast_io_driver/openssl_driver/context.h @@ -0,0 +1,76 @@ +#pragma once + +namespace fast_io +{ + +using ssl_context_observer = details::observer; + +enum class tls_method +{ +tls, +tls_server, +tls_client, +datagram_tls, +datagram_server, +datagram_client, +}; + +namespace details +{ +inline SSL_METHOD const* get_method(tls_method m) +{ + switch(m) + { + case tls_method::tls: + return TLS_method(); + case tls_method::tls_server: + return TLS_server_method(); + case tls_method::tls_client: + return TLS_client_method(); + case tls_method::datagram_tls: + return DTLS_method(); + case tls_method::datagram_server: + return DTLS_server_method(); + case tls_method::datagram_client: + return DTLS_client_method(); + default: + throw_openssl_error(); + }; +} +} + +class ssl_context:public ssl_context_observer +{ +public: + ssl_context(ossl_lib_context_observer ocob,cstring_view view,tls_method m):ssl_context_observer(SSL_CTX_new_ex(ocob.native_handle(),view.data(),details::get_method(m))) + { + if(this->native_handle()==nullptr) + throw_openssl_error(); + } + ssl_context(tls_method m):ssl_context_observer(SSL_CTX_new(details::get_method(m))) + { + if(this->native_handle()==nullptr) + throw_openssl_error(); + } + ssl_context(ssl_context const&) = delete; + ssl_context& operator=(ssl_context const&) = delete; + constexpr ssl_context(ssl_context&& __restrict bmv) noexcept:ssl_context_observer(bmv.native_handle()) + { + bmv.native_handle()=nullptr; + } + ssl_context& operator=(ssl_context&& __restrict bmv) noexcept + { + if(this->native_handle())[[likely]] + SSL_CTX_free(this->native_handle()); + this->native_handle()=bmv.native_handle(); + bmv.native_handle()=nullptr; + return *this; + } + ~ssl_context() + { + if(this->native_handle())[[likely]] + SSL_CTX_free(this->native_handle()); + } +}; + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_driver/openssl_driver/crypto.h b/src/fast_io/include/fast_io_driver/openssl_driver/crypto.h new file mode 100644 index 0000000..47490a4 --- /dev/null +++ b/src/fast_io/include/fast_io_driver/openssl_driver/crypto.h @@ -0,0 +1,22 @@ +#pragma once + +namespace fast_io +{ + +class crypto +{ +public: + crypto(std::uint_least64_t opts,settings_observer sob) + { + if(!OPENSSL_init_crypto(opt,sob.native_handle())) + throw_openssl_error(); + } + crypto(crypto const&)=delete; + crypto const& operator=(crypto const&)=delete; + ~crypto() + { + OPENSSL_cleanup(); + } +}; + +}; \ No newline at end of file diff --git a/src/fast_io/include/fast_io_driver/openssl_driver/error.h b/src/fast_io/include/fast_io_driver/openssl_driver/error.h new file mode 100644 index 0000000..95c883c --- /dev/null +++ b/src/fast_io/include/fast_io_driver/openssl_driver/error.h @@ -0,0 +1,25 @@ +#pragma once + +namespace fast_io +{ + +class openssl_error +{ +public: +}; + + +inline void throw_openssl_error() +{ +#ifdef __cpp_exceptions +#if defined(_MSC_VER) && (!defined(_HAS_EXCEPTIONS) || _HAS_EXCEPTIONS == 0) + fast_terminate(); +#else + throw openssl_error(); +#endif +#else + fast_terminate(); +#endif +} + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_driver/openssl_driver/evp.h b/src/fast_io/include/fast_io_driver/openssl_driver/evp.h new file mode 100644 index 0000000..d17aa08 --- /dev/null +++ b/src/fast_io/include/fast_io_driver/openssl_driver/evp.h @@ -0,0 +1,246 @@ +#pragma once + +namespace fast_io +{ + +/* +https://www.openssl.org/docs/man1.1.0/man3/EVP_PKEY_keygen.html + #include + + int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx); + int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey); + int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx); + int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey); + + typedef int EVP_PKEY_gen_cb(EVP_PKEY_CTX *ctx); + + void EVP_PKEY_CTX_set_cb(EVP_PKEY_CTX *ctx, EVP_PKEY_gen_cb *cb); + EVP_PKEY_gen_cb *EVP_PKEY_CTX_get_cb(EVP_PKEY_CTX *ctx); + + int EVP_PKEY_CTX_get_keygen_info(EVP_PKEY_CTX *ctx, int idx); + + void EVP_PKEY_CTX_set_app_data(EVP_PKEY_CTX *ctx, void *data); + void *EVP_PKEY_CTX_get_app_data(EVP_PKEY_CTX *ctx); + + +*/ + +class evp_pkey_observer +{ +public: + using native_handle_type = EVP_PKEY*; + native_handle_type key{}; + constexpr auto& native_handle() const noexcept + { + return key; + } + constexpr auto& native_handle() noexcept + { + return key; + } + constexpr operator bool() noexcept + { + return key; + } + constexpr auto release() noexcept + { + auto temp{key}; + key=nullptr; + return temp; + } + std::size_t use_count() const noexcept + { + return EVP_PKEY_up_ref(key); + } +}; + +class evp_pkey:public evp_pkey_observer +{ +public: + using native_handle_type = EVP_PKEY*; + constexpr evp_pkey()=default; + constexpr evp_pkey(native_handle_type ctx):evp_pkey_observer{ctx}{} + evp_pkey(native_interface_t):evp_pkey_observer{EVP_PKEY_new()} + { + if(this->native_handle()==nullptr)[[unlikely]] + throw_openssl_error(); + } + evp_pkey(evp_pkey const&)=delete; + evp_pkey& operator=(evp_pkey const&)=delete; + constexpr evp_pkey(evp_pkey&& __restrict other) noexcept: evp_pkey_observer{other.native_handle()} + { + other.native_handle()=nullptr; + } + evp_pkey& operator=(evp_pkey&& __restrict other) noexcept + { + if(this->native_handle())[[likely]] + EVP_PKEY_free(this->native_handle()); + this->native_handle()=other.native_handle(); + other.native_handle()=nullptr; + return *this; + } + inline constexpr void reset(native_handle_type newhandle=nullptr) noexcept + { + if(this->native_handle())[[likely]] + EVP_PKEY_free(this->native_handle()); + this->native_handle()=newhandle; + } + + ~evp_pkey() + { + if(this->native_handle())[[likely]] + EVP_PKEY_free(this->native_handle()); + } +}; + + +class evp_pkey_ctx_observer +{ +public: + using native_handle_type = EVP_PKEY_CTX*; + native_handle_type ctx{}; + constexpr auto& native_handle() const noexcept + { + return ctx; + } + constexpr auto& native_handle() noexcept + { + return ctx; + } + constexpr operator bool() noexcept + { + return ctx; + } + constexpr auto release() noexcept + { + auto temp{ctx}; + ctx=nullptr; + return temp; + } +}; + +class evp_pkey_ctx:public evp_pkey_ctx_observer +{ +public: + using native_handle_type = EVP_PKEY_CTX*; + constexpr evp_pkey_ctx()=default; + constexpr evp_pkey_ctx(native_handle_type ctx):evp_pkey_ctx_observer{ctx}{} + evp_pkey_ctx(native_interface_t,EVP_PKEY *pkey, ENGINE *e):evp_pkey_ctx_observer{EVP_PKEY_CTX_new(pkey,e)} + { + if(this->native_handle()==nullptr)[[unlikely]] + throw_openssl_error(); + } + evp_pkey_ctx(native_interface_t,int id, ENGINE *e):evp_pkey_ctx_observer{EVP_PKEY_CTX_new_id(id,e)} + { + if(this->native_handle()==nullptr)[[unlikely]] + throw_openssl_error(); + } + evp_pkey_ctx(evp_pkey_ctx const& other):evp_pkey_ctx_observer{EVP_PKEY_CTX_dup(other.native_handle())} + { + if(this->native_handle()==nullptr)[[unlikely]] + throw_openssl_error(); + } + evp_pkey_ctx& operator=(evp_pkey_ctx const& other) + { + auto newp{EVP_PKEY_CTX_dup(other.native_handle())}; + if(newp==nullptr)[[unlikely]] + throw_openssl_error(); + if(this->native_handle())[[likely]] + EVP_PKEY_CTX_free(this->native_handle()); + this->native_handle()=newp; + return *this; + } + constexpr evp_pkey_ctx(evp_pkey_ctx&& __restrict other) noexcept: evp_pkey_ctx_observer{other.native_handle()} + { + other.native_handle()=nullptr; + } + evp_pkey_ctx& operator=(evp_pkey_ctx&& __restrict other) noexcept + { + if(this->native_handle())[[likely]] + EVP_PKEY_CTX_free(this->native_handle()); + this->native_handle()=other.native_handle(); + other.native_handle()=nullptr; + return *this; + } + void reset(native_handle_type newctx=nullptr) noexcept + { + if(this->native_handle())[[likely]] + EVP_PKEY_CTX_free(this->native_handle()); + this->native_handle()=newctx; + } + ~evp_pkey_ctx() + { + if(this->native_handle())[[likely]] + EVP_PKEY_CTX_free(this->native_handle()); + } +}; + + +inline void keygen_init(evp_pkey_ctx_observer evob) +{ + if(EVP_PKEY_keygen_init(evob.ctx)<=0) + throw_openssl_error(); +} + +inline evp_pkey keygen(evp_pkey_ctx_observer evob) +{ + EVP_PKEY* add{}; + if(EVP_PKEY_keygen(evob.ctx,__builtin_addressof(add))<=0) + throw_openssl_error(); + return evp_pkey(add); +} + +struct private_key +{ + evp_pkey_observer x{}; + EVP_CIPHER const * enc{}; + unsigned char *kstr{}; + int klen{}; + pem_password_cb *cb{}; + void *u{}; +}; + +struct public_key +{ + evp_pkey_observer x{}; +}; + +/* +https://linux.die.net/man/3/pem_read_rsa_pubkey +*/ + + +template +requires (std::same_as::char_type,char>&&(std::derived_from,bio_io_observer>||buffer_output_stream>)) +inline void print_define(io_reserve_type_t,output out,private_key const& key) +{ + if constexpr(std::derived_from,bio_io_observer>) + { + if(!noexcept_call(PEM_write_bio_PrivateKey,out.bio,key.x.key,key.enc,key.kstr,key.klen,key.cb,key.u)) + throw_openssl_error(); + } + else + { + bio_file bf(io_cookie_type,out); + print_freestanding(bf,key); + } +} + +template +requires (std::same_as::char_type,char>&&(std::derived_from,bio_io_observer>||buffer_output_stream>)) +inline void print_define(io_reserve_type_t,output out,public_key key) +{ + if constexpr(std::derived_from,bio_io_observer>) + { + if(!noexcept_call(PEM_write_bio_PUBKEY,out.bio,key.x.key)) + throw_openssl_error(); + } + else + { + bio_file bf(io_cookie,out); + print_freestanding(bf,key); + } +} + + +} diff --git a/src/fast_io/include/fast_io_driver/openssl_driver/hash.h b/src/fast_io/include/fast_io_driver/openssl_driver/hash.h new file mode 100644 index 0000000..9359880 --- /dev/null +++ b/src/fast_io/include/fast_io_driver/openssl_driver/hash.h @@ -0,0 +1,168 @@ +#pragma once + +namespace fast_io::ossl +{ + +template +struct basic_ossl_hash_context +{ + using meta_info_type = metainfotype; + using native_handle_type = typename meta_info_type::ctx_type; + native_handle_type handle; + static inline constexpr std::size_t digest_size{meta_info_type::digest_length}; + std::byte digest_buffer[digest_size]; + explicit basic_ossl_hash_context() noexcept + { + this->reset(); + } +//let contract violation dies. Programming bug should just die. C++ EH is a historical mistake. + void reset() noexcept + { + if(meta_info_type::init_function(__builtin_addressof(handle))==0)[[unlikely]] + ::fast_io::fast_terminate(); + } + constexpr void digest_to_byte_ptr(std::byte* dest) const noexcept + { + ::fast_io::freestanding::nonoverlapped_bytes_copy_n(digest_buffer,digest_size,dest); + } + void update(std::byte const* first, std::byte const* last) noexcept + { + if(meta_info_type::update_function(__builtin_addressof(handle),first,static_cast(last-first))==0)[[unlikely]] + ::fast_io::fast_terminate(); + } + void do_final() noexcept + { + if(meta_info_type::final_function(reinterpret_cast(digest_buffer),__builtin_addressof(handle))==0)[[unlikely]] + ::fast_io::fast_terminate(); + } +}; + +struct md5_meta_info +{ + using ctx_type = MD5_CTX; + static inline constexpr std::size_t digest_length{MD5_DIGEST_LENGTH}; + static inline int init_function(ctx_type* c) noexcept + { + return ::fast_io::noexcept_call(MD5_Init,c); + } + static inline int update_function(ctx_type* c,void const* data,std::size_t len) noexcept + { + return ::fast_io::noexcept_call(MD5_Update,c,data,len); + } + static inline int final_function(char unsigned* md,ctx_type* c) noexcept + { + return ::fast_io::noexcept_call(MD5_Final,md,c); + } +}; + +using md5_context +#ifndef FAST_IO_NO_WARNING_DEPRECATED_CRYPTO_ALGOS +[[deprecated("The weaknesses of MD5 have been exploited in the field, most infamously by the Flame malware in 2012. See wikipedia https://en.wikipedia.org/wiki/MD5")]] +#endif += basic_ossl_hash_context; + +struct sha1_meta_info +{ + using ctx_type = SHA_CTX; + static inline constexpr std::size_t digest_length{SHA_DIGEST_LENGTH}; + static inline int init_function(ctx_type* c) noexcept + { + return ::fast_io::noexcept_call(SHA1_Init,c); + } + static inline int update_function(ctx_type* c,void const* data,std::size_t len) noexcept + { + return ::fast_io::noexcept_call(SHA1_Update,c,data,len); + } + static inline int final_function(char unsigned* md,ctx_type* c) noexcept + { + return ::fast_io::noexcept_call(SHA1_Final,md,c); + } +}; + +using sha1_context +#ifndef FAST_IO_NO_WARNING_DEPRECATED_CRYPTO_ALGOS +[[deprecated("SHA1 is no longer a secure algorithm. See wikipedia https://en.wikipedia.org/wiki/SHA-1")]] +#endif += basic_ossl_hash_context; + +struct sha224_meta_info +{ + using ctx_type = SHA256_CTX; + static inline constexpr std::size_t digest_length{SHA224_DIGEST_LENGTH}; + static inline int init_function(ctx_type* c) noexcept + { + return ::fast_io::noexcept_call(SHA224_Init,c); + } + static inline int update_function(ctx_type* c,void const* data,std::size_t len) noexcept + { + return ::fast_io::noexcept_call(SHA224_Update,c,data,len); + } + static inline int final_function(char unsigned* md,ctx_type* c) noexcept + { + return ::fast_io::noexcept_call(SHA224_Final,md,c); + } +}; + +using sha224_context = basic_ossl_hash_context; + +struct sha256_meta_info +{ + using ctx_type = SHA256_CTX; + static inline constexpr std::size_t digest_length{SHA256_DIGEST_LENGTH}; + static inline int init_function(ctx_type* c) noexcept + { + return ::fast_io::noexcept_call(SHA256_Init,c); + } + static inline int update_function(ctx_type* c,void const* data,std::size_t len) noexcept + { + return ::fast_io::noexcept_call(SHA256_Update,c,data,len); + } + static inline int final_function(char unsigned* md,ctx_type* c) noexcept + { + return ::fast_io::noexcept_call(SHA256_Final,md,c); + } +}; + +using sha256_context = basic_ossl_hash_context; + +struct sha384_meta_info +{ + using ctx_type = SHA512_CTX; + static inline constexpr std::size_t digest_length{SHA384_DIGEST_LENGTH}; + static inline int init_function(ctx_type* c) noexcept + { + return ::fast_io::noexcept_call(SHA384_Init,c); + } + static inline int update_function(ctx_type* c,void const* data,std::size_t len) noexcept + { + return ::fast_io::noexcept_call(SHA384_Update,c,data,len); + } + static inline int final_function(char unsigned* md,ctx_type* c) noexcept + { + return ::fast_io::noexcept_call(SHA384_Final,md,c); + } +}; + +using sha384_context = basic_ossl_hash_context; + +struct sha512_meta_info +{ + using ctx_type = SHA512_CTX; + static inline constexpr std::size_t digest_length{SHA512_DIGEST_LENGTH}; + static inline int init_function(ctx_type* c) noexcept + { + return ::fast_io::noexcept_call(SHA512_Init,c); + } + static inline int update_function(ctx_type* c,void const* data,std::size_t len) noexcept + { + return ::fast_io::noexcept_call(SHA512_Update,c,data,len); + } + static inline int final_function(char unsigned* md,ctx_type* c) noexcept + { + return ::fast_io::noexcept_call(SHA512_Final,md,c); + } +}; + +using sha512_context = basic_ossl_hash_context; + +} diff --git a/src/fast_io/include/fast_io_driver/openssl_driver/init.h b/src/fast_io/include/fast_io_driver/openssl_driver/init.h new file mode 100644 index 0000000..7c6b9c2 --- /dev/null +++ b/src/fast_io/include/fast_io_driver/openssl_driver/init.h @@ -0,0 +1,16 @@ +#pragma once + +namespace fast_io +{ + +class global_initializer +{ +public: + explicit global_initializer() noexcept + { + SSL_library_init(); + } +}; + + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_driver/openssl_driver/observer.h b/src/fast_io/include/fast_io_driver/openssl_driver/observer.h new file mode 100644 index 0000000..7af69b3 --- /dev/null +++ b/src/fast_io/include/fast_io_driver/openssl_driver/observer.h @@ -0,0 +1,36 @@ +#pragma once + +namespace fast_io::details +{ + +template +class observer +{ +public: + using native_handle_type = T; + native_handle_type handle{}; + constexpr operator bool() noexcept + { + return handle; + } + constexpr auto& native_handle() const noexcept + { + return handle; + } + constexpr auto& native_handle() noexcept + { + return handle; + } + constexpr void reset(native_handle_type newhandle=nullptr) noexcept + { + handle=newhandle; + } + constexpr native_handle_type release() noexcept + { + auto temp{handle}; + handle=nullptr; + return temp; + } +}; + +} diff --git a/src/fast_io/include/fast_io_driver/openssl_driver/ossl_lib_context.h b/src/fast_io/include/fast_io_driver/openssl_driver/ossl_lib_context.h new file mode 100644 index 0000000..375c1f6 --- /dev/null +++ b/src/fast_io/include/fast_io_driver/openssl_driver/ossl_lib_context.h @@ -0,0 +1,37 @@ +#pragma once + +namespace fast_io +{ + +using ossl_lib_context_observer = details::observer; + +class openssl_context:public ossl_lib_context_observer +{ +public: + openssl_context():ossl_lib_context_observer(OSSL_LIB_CTX_new()) + { + if(this->native_handle()==nullptr) + throw_openssl_error(); + } + openssl_context(openssl_context const&) = delete; + openssl_context& operator=(openssl_context const&) = delete; + constexpr openssl_context(openssl_context&& __restrict bmv) noexcept:ossl_lib_context_observer(bmv.native_handle()) + { + bmv.native_handle()=nullptr; + } + openssl_context& operator=(openssl_context&& __restrict bmv) noexcept + { + if(this->native_handle())[[likely]] + OSSL_LIB_CTX_free(this->native_handle()); + this->native_handle()=bmv.native_handle(); + bmv.native_handle()=nullptr; + return *this; + } + ~openssl_context() + { + if(this->native_handle())[[likely]] + OSSL_LIB_CTX_free(this->native_handle()); + } +}; + +}; \ No newline at end of file diff --git a/src/fast_io/include/fast_io_driver/openssl_driver/settings.h b/src/fast_io/include/fast_io_driver/openssl_driver/settings.h new file mode 100644 index 0000000..596a215 --- /dev/null +++ b/src/fast_io/include/fast_io_driver/openssl_driver/settings.h @@ -0,0 +1,45 @@ +#pragma once + +namespace fast_io +{ + +class settings +{ +public: + using native_handle_type = OPENSSL_INIT_SETTINGS*; + native_handle_type ptr{}; + constexpr operator native_handle_type() noexcept + { + return ptr; + } + constexpr settings(native_handle_type handle):settings_observer(handle){} + settings():settings_observer(OPENSSL_INIT_new()){} + settings(settings const&) = delete; + settings& operator=(settings const&) = delete; + + constexpr settings(settings&& __restrict bmv) noexcept:settings_observer(bmv.handle) + { + bmv.handle=nullptr; + } + settings& operator=(settings&& __restrict bmv) noexcept + { + if(this->native_handle())[[likely]] + OPENSSL_INIT_free(this->native_handle()); + this->native_handle()=bmv->native_handle(); + bmv->native_handle()=nullptr; + return *this; + } + constexpr auto release() noexcept + { + auto temp{this->native_handle()}; + this->native_handle()=nullptr; + return temp; + } + ~settings() + { + if(this->native_handle())[[likely]] + OPENSSL_INIT_free(this->native_handle()); + } +}; + +}; \ No newline at end of file diff --git a/src/fast_io/include/fast_io_driver/openssl_driver/ssl.h b/src/fast_io/include/fast_io_driver/openssl_driver/ssl.h new file mode 100644 index 0000000..14494f0 --- /dev/null +++ b/src/fast_io/include/fast_io_driver/openssl_driver/ssl.h @@ -0,0 +1,197 @@ +#pragma once + +namespace fast_io +{ + +template +class basic_ssl_io_observer +{ +public: + using char_type = ch_type; + using native_handle_type = SSL*; + native_handle_type ssl{}; + constexpr native_handle_type const& native_handle() const noexcept + { + return ssl; + } + constexpr native_handle_type& native_handle() noexcept + { + return ssl; + } + explicit constexpr operator bool() noexcept + { + return ssl; + } + constexpr native_handle_type release() noexcept + { + auto temp{ssl}; + ssl={}; + return temp; + } +}; + +template +inline void set_bio(basic_ssl_io_observer siob,basic_bio_file&& rbio,basic_bio_file&& wbio) noexcept +{ + ::fast_io::noexcept_call(SSL_set_bio,siob.ssl,rbio.bio,wbio.bio); + rbio.bio=nullptr; + wbio.bio=nullptr; +} + +template +inline std::size_t use_count(basic_ssl_io_observer siob) +{ + return static_cast(SSL_up_ref(siob.s)); +} + +template +inline void connect(basic_ssl_io_observer siob) +{ + if(::fast_io::noexcept_call(SSL_connect,siob.ssl)==-1) + throw_openssl_error(); +} + +template +inline void attach(basic_ssl_io_observer siob,stm& sm) +{ + if(!SSL_set_fd(siob.native_handle(),zero_copy_in_handle(sm))) + throw_openssl_error(); +} + +template +inline void attach(basic_ssl_io_observer siob, + basic_bio_io_observer bio1, + basic_bio_io_observer bio2) +{ + SSL_set_bio(siob.native_handle(),bio1.native_handle(),bio2.native_handle()); +} + +template +class basic_ssl_io_handle:public basic_ssl_io_observer +{ +public: + using char_type = ch_type; + using native_handle_type = SSL*; + constexpr basic_ssl_io_handle()=default; + constexpr basic_ssl_io_handle(native_handle_type s):basic_ssl_io_observer(s){} + basic_ssl_io_handle(basic_ssl_io_handle const& h):basic_ssl_io_observer(SSL_dup(h.native_handle())) + { + if(this->native_handle()==nullptr)[[unlikely]] + throw_openssl_error(); + } + basic_ssl_io_handle& operator=(basic_ssl_io_handle const& h) + { + auto temp{SSL_dup(h.native_handle())}; + if(temp==nullptr)[[unlikely]] + throw_openssl_error(); + if(this->native_handle())[[likely]] + SSL_free(this->native_handle()); + this->native_handle()=temp; + return *this; + } + constexpr basic_ssl_io_handle(basic_ssl_io_handle&& __restrict h) noexcept:basic_ssl_io_observer(h.native_handle()) + { + h.native_handle()=nullptr; + } + inline void reset(native_handle_type newhandle=nullptr) noexcept + { + if(this->native_handle())[[likely]] + SSL_free(this->native_handle()); + this->native_handle()=newhandle; + } + void close() noexcept + { + if(this->ssl)[[likely]] + { + SSL_free(this->ssl); + this->ssl=nullptr; + } + } + basic_ssl_io_handle& operator=(basic_ssl_io_handle&& __restrict h) noexcept + { + if(this->native_handle())[[likely]] + SSL_free(this->native_handle()); + this->native_handle()=h.native_handle(); + h.native_handle()=nullptr; + return *this; + } +}; + + +template +class basic_ssl_file:public basic_ssl_io_handle +{ +public: + using char_type = ch_type; + using native_handle_type = SSL*; + constexpr basic_ssl_file()=default; + constexpr basic_ssl_file(native_handle_type s):basic_ssl_io_handle(s){} + basic_ssl_file(io_cookie_t,ssl_context_observer ssl_ctx_ob):basic_ssl_io_handle(SSL_new(ssl_ctx_ob.native_handle())) + { + if(this->native_handle()==nullptr) + throw_openssl_error(); + } + template + basic_ssl_file(ssl_context_observer ssl_ctx_ob,Args&& ...args):basic_ssl_io_handle(SSL_new(ssl_ctx_ob.native_handle())) + { + if(this->native_handle()==nullptr) + throw_openssl_error(); + basic_ssl_file self(this->native_handle()); + attach(*this,::std::forward(args)...); + connect(*this); + self.release(); + } + constexpr basic_ssl_file(basic_ssl_file const&)=default; + constexpr basic_ssl_file& operator=(basic_ssl_file const&)=default; + constexpr basic_ssl_file(basic_ssl_file && __restrict) noexcept=default; + constexpr basic_ssl_file& operator=(basic_ssl_file && __restrict) noexcept=default; + ~basic_ssl_file() + { + if(this->native_handle())[[likely]] + SSL_free(this->native_handle()); + } +}; + +template +inline Iter read(basic_ssl_io_observer iob,Iter begin,Iter end) +{ + std::size_t read_bytes{}; + auto ret(SSL_read_ex(iob.native_handle(),::std::to_address(begin),sizeof(*begin)*(end-begin),__builtin_addressof(read_bytes))); + if(ret<=0) + { + int error{SSL_get_error(iob.native_handle(),ret)}; + if(error == SSL_ERROR_ZERO_RETURN || error == SSL_ERROR_NONE || error == SSL_ERROR_WANT_READ) + throw_openssl_error(); + read_bytes=0; + } + return begin+read_bytes/sizeof(*begin); +} + +template +inline Iter write(basic_ssl_io_observer iob,Iter begin,Iter end) +{ + std::size_t written_bytes{}; + auto ret(SSL_write_ex(iob.native_handle(),::std::to_address(begin),sizeof(*begin)*(end-begin),__builtin_addressof(written_bytes))); + if(ret<=0) + { + int error{SSL_get_error(iob.native_handle(),ret)}; + if(error == SSL_ERROR_ZERO_RETURN || error == SSL_ERROR_NONE || error == SSL_ERROR_WANT_WRITE) + throw_openssl_error(); + written_bytes=0; + } + return begin+written_bytes/sizeof(*begin); +} + +using ssl_io_observer = basic_ssl_io_observer; +using ssl_file = basic_ssl_file; + +template +using basic_ibuf_ssl_io_observer = basic_ibuf>; +template +using basic_ibuf_ssl_file = basic_ibuf>; + +using ibuf_ssl_io_observer = basic_ibuf_ssl_io_observer; +using ibuf_ssl_file = basic_ibuf_ssl_file; + +static_assert(input_stream); +} diff --git a/src/fast_io/include/fast_io_driver/posix_iconv.h b/src/fast_io/include/fast_io_driver/posix_iconv.h new file mode 100644 index 0000000..5abe938 --- /dev/null +++ b/src/fast_io/include/fast_io_driver/posix_iconv.h @@ -0,0 +1,41 @@ +#pragma once +#include"../fast_io_device.h" +#include"posix_iconv_impl/impl.h" + +namespace fast_io +{ + +template +using basic_oiconv_file = basic_io_buffer>; + +template +using basic_iiconv_file = basic_io_buffer>; + +template +using basic_iconv_file = basic_io_buffer>; + +using iiconv_file = basic_iiconv_file; +using wiiconv_file = basic_iiconv_file; +using u8iiconv_file = basic_iiconv_file; +using u16iiconv_file = basic_iiconv_file; +using u32iiconv_file = basic_iiconv_file; + +using oiconv_file = basic_oiconv_file; +using woiconv_file = basic_oiconv_file; +using u8oiconv_file = basic_oiconv_file; +using u16oiconv_file = basic_oiconv_file; +using u32oiconv_file = basic_oiconv_file; + +using iconv_file = basic_iconv_file; +using wiconv_file = basic_iconv_file; +using u8iconv_file = basic_iconv_file; +using u16iconv_file = basic_iconv_file; +using u32iconv_file = basic_iconv_file; + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_driver/posix_iconv_impl/impl.h b/src/fast_io/include/fast_io_driver/posix_iconv_impl/impl.h new file mode 100644 index 0000000..68f767f --- /dev/null +++ b/src/fast_io/include/fast_io_driver/posix_iconv_impl/impl.h @@ -0,0 +1,318 @@ +#pragma once + +#include + +namespace fast_io +{ + +class posix_iconv_io_observer +{ +public: + using native_handle_type = iconv_t; + iconv_t cd{std::bit_cast(static_cast(-1))}; + + constexpr auto& native_handle() noexcept + { + return cd; + } + constexpr auto& native_handle() const noexcept + { + return cd; + } + constexpr iconv_t release() noexcept + { + auto temp{cd}; + cd = std::bit_cast(static_cast(-1)); + return temp; + } +}; + +struct iconv_deco_t +{ + iconv_t cd{std::bit_cast(static_cast(-1))}; + char buffer[32]{}; + std::size_t len{}; + iconv_deco_t(posix_iconv_io_observer piiob) noexcept:cd(piiob.cd){} +}; + +inline constexpr posix_iconv_io_observer deco_value_handle(posix_iconv_io_observer piiob) noexcept +{ + return piiob; +} + +namespace details +{ + +struct iconv_deco_from_chars_result +{ + char const* from; + char* to; +}; + +inline iconv_deco_from_chars_result iconv_do_impl(iconv_t cd, + char const* from_first2, + char const* from_last2, + char* to_first, + char* to_last) noexcept +{ + char* from_first{const_cast(from_first2)}; + char* from_last{const_cast(from_last2)}; + while(from_first!=from_last) + { + std::size_t inbytes_left{static_cast(from_last-from_first)}; + std::size_t outbytes_left{static_cast(to_last-to_first)}; + std::size_t ret{iconv(cd, + __builtin_addressof(from_first), + __builtin_addressof(inbytes_left), + __builtin_addressof(to_first), + __builtin_addressof(outbytes_left))}; + from_first=from_last-inbytes_left; + to_first=to_last-outbytes_left; + if(ret!=static_cast(-1)) + break; + switch(errno) + { + case EINVAL: + goto lable_end; + case EILSEQ: + if(from_first==from_last) + break; + *to_first=0; + ++to_first; + ++from_first; + break; + default: + fast_terminate(); + }; + } +lable_end: + if(16(last-first)}; + + if(len) + { + std::size_t to_copy{32-len}; + if(diff(src_it-icdt.buffer)}; + if(converted(buffer_total_ed-src_it)}; + my_copy_n(src_it,remained,icdt.buffer); + return dst_it; + } + else + { + icdt.len=0; + first+=converted-len; + dst_first=dst_it; + } + } + auto [src2_it,dst2_it]=iconv_do_impl(icdt.cd,first,last,dst_first,dst_last); + diff=static_cast(last-src2_it); + non_overlapped_copy_n(src2_it,diff,icdt.buffer); + icdt.len=diff; + return dst2_it; +} + +inline std::size_t iconv_deco_reserve_define_impl(iconv_deco_t& icdt, + char const* first,std::size_t insize,char* outbyteptr,std::size_t size) +{ + return iconv_dst_impl(icdt,first,first+insize,outbyteptr,outbyteptr+size*8)-outbyteptr; +} + + +} + +template +inline constexpr std::size_t deco_reserve_size(io_reserve_type_t, + iconv_deco_t& icdt,std::size_t size) noexcept +{ + constexpr std::size_t factor{8/sizeof(to_char_type)}; + return details::intrinsics::mul_or_overflow_die( + details::intrinsics::add_or_overflow_die(size,32),factor); +} + +template<::std::contiguous_iterator fromIter,::std::contiguous_iterator toIter> +inline toIter deco_reserve_define(io_reserve_type_t<::std::iter_value_t,iconv_deco_t>, + iconv_deco_t& icdt,fromIter first,fromIter last,toIter iter) +{ + using to_char_type = ::std::iter_value_t; + using from_char_type = ::std::iter_value_t; + constexpr std::size_t factor{8/sizeof(to_char_type)}; + std::size_t dis{static_cast(last-first)}; + std::size_t inbytes{sizeof(from_char_type)*dis}; + std::size_t const allocated_bytes{(inbytes+32)*8}; + return iter+details::iconv_deco_reserve_define_impl(icdt, + reinterpret_cast(::std::to_address(first)), + inbytes, + reinterpret_cast(::std::to_address(iter)), + allocated_bytes)/sizeof(to_char_type); +} + +namespace details +{ + +inline iconv_t my_iconv_open(char const* tocode,char const* fromcode) +{ + auto cd{iconv_open(tocode,fromcode)}; + if(cd==std::bit_cast(static_cast(-1))) + throw_posix_error(); + return cd; +} + +} + +class posix_iconv_file:public posix_iconv_io_observer +{ +public: + using native_handle_type = iconv_t; + constexpr posix_iconv_file() noexcept = default; + constexpr posix_iconv_file(iconv_t icv) noexcept : posix_iconv_io_observer{icv}{} + + posix_iconv_file(cstring_view tocode,cstring_view fromcode): + posix_iconv_io_observer{details::my_iconv_open(tocode.c_str(),fromcode.c_str())} + {} + posix_iconv_file(u8cstring_view tocode,u8cstring_view fromcode): + posix_iconv_io_observer{ + details::my_iconv_open(reinterpret_cast(tocode.c_str()), + reinterpret_cast(fromcode.c_str()))} + {} + posix_iconv_file(posix_iconv_file const&)=delete; + posix_iconv_file& operator=(posix_iconv_file const&)=delete; + constexpr posix_iconv_file(posix_iconv_file&& __restrict other) noexcept:posix_iconv_io_observer{other.release()}{} + posix_iconv_file& operator=(posix_iconv_file&& __restrict other) noexcept + { + iconv_close(this->cd); + this->cd=other.release(); + return *this; + } + void close() + { + if(iconv_close(this->cd)==-1) + throw_posix_error(); + } + ~posix_iconv_file() + { + iconv_close(this->cd); + } +}; + +namespace details +{ +inline std::size_t do_iconv_impl(iconv_t cd, + char** __restrict__ inbuf,std::size_t* __restrict__ inbytesleft, + char** __restrict__ outbuf,std::size_t* __restrict__ outbytesleft) +{ + std::size_t res{iconv(cd,inbuf,inbytesleft, + outbuf,outbytesleft)}; + if(res==static_cast(-1)) + throw_posix_error(); + return res; +} +} + +inline std::size_t do_iconv(posix_iconv_io_observer piciob, + char** __restrict__ inbuf,std::size_t* __restrict__ inbytesleft, + char** __restrict__ outbuf,std::size_t* __restrict__ outbytesleft) +{ + return details::do_iconv_impl(piciob.cd,inbuf,inbytesleft,outbuf,outbytesleft); +} + +inline void reset_state(posix_iconv_io_observer piciob) +{ + if(iconv(piciob.cd,nullptr,0,nullptr,nullptr)==static_cast(-1)) + throw_posix_error(); +} + +namespace manipulators +{ + +template +struct iconv_code_cvt_t +{ + using manip_tag = manip_tag_t; + iconv_t cd; + T reference; +}; + +template +constexpr iconv_code_cvt_t iconv_code_cvt(posix_iconv_io_observer piiob,basic_io_scatter_t scatter) noexcept +{ + return {piiob.cd,scatter}; +} + +template +requires (std::ranges::contiguous_range>&&std::integral>>) +constexpr iconv_code_cvt_t iconv_code_cvt(posix_iconv_io_observer piiob,rg&& t) +{ + if constexpr(std::is_array_v>) + return {piiob.cd,{std::ranges::data(t),sizeof(std::ranges::range_value_t>)*(std::ranges::size(t)-1)}}; + else + return {piiob.cd,{std::ranges::data(t),sizeof(std::ranges::range_value_t>)*std::ranges::size(t)}}; +} + +template +constexpr iconv_code_cvt_t iconv_code_cvt(posix_iconv_io_observer piiob,chvw_t t) noexcept +{ + ::fast_io::freestanding::basic_string_view view(t.reference); + return {piiob.cd,{view.data(),sizeof(char_type)*view.size()}}; +} +template +inline std::size_t print_reserve_size( + io_reserve_type_t>,iconv_code_cvt_t v) noexcept +{ + static_assert(sizeof(char_type)<=8); + constexpr std::size_t maximum_size_sentinel{std::numeric_limits::max()/8*sizeof(char_type)}; + if(v.reference.len>maximum_size_sentinel)[[unlikely]] + fast_terminate(); + return v.reference.len*8/sizeof(char_type); +} + +template<::std::integral char_type> +inline Iter print_reserve_define(io_reserve_type_t>, + Iter iter,iconv_code_cvt_t v) noexcept +{ + std::size_t const sz{::fast_io::details::iconv_print_reserve_define_impl(v.cd, + reinterpret_cast(::std::to_address(v.reference.base)), + v.reference.len,reinterpret_cast(::std::to_address(iter)))}; + return iter+sz/sizeof(char_type); +} +} + + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_driver/pulseaudio.h b/src/fast_io/include/fast_io_driver/pulseaudio.h new file mode 100644 index 0000000..2a0cbaa --- /dev/null +++ b/src/fast_io/include/fast_io_driver/pulseaudio.h @@ -0,0 +1,135 @@ +#pragma once +#include +#include +#include"../fast_io_hosted.h" + +namespace fast_io +{ + +class pulse_audio_error +{ +public: + int error{}; + pulse_audio_error(int e=PA_OK):error(e){} +#if 0 + void report(error_reporter& err) const override + { + print_freestanding(err,manipulators::os_c_str(pa_strerror(error))); + } +#endif +}; + +inline void throw_pulse_audio_error(int ec=PA_OK) +{ +#ifdef __cpp_exceptions + throw pulse_audio_error(ec); +#else + fast_terminate(); +#endif +} + +template +class basic_pulseaudio_simple_io_observer +{ +public: + using char_type = ch_type; + using native_handle_type = pa_simple*; + native_handle_type s{}; + constexpr auto& native_handle() const noexcept + { + return s; + } + constexpr auto& native_handle() noexcept + { + return s; + } + constexpr auto release() noexcept + { + auto temp{s}; + s={}; + return temp; + } +}; + +template +class basic_pulseaudio_simple_file:public basic_pulseaudio_simple_io_observer +{ +public: + using char_type = ch_type; + using native_handle_type = pa_simple*; + constexpr basic_pulseaudio_simple_file(){} + constexpr basic_pulseaudio_simple_file(native_handle_type sf):basic_pulseaudio_simple_io_observer{sf}{} + + basic_pulseaudio_simple_file(native_interface_t, + char const* server, + char const* name, + pa_stream_direction_t dir, + char const * dev, + char const * stream_name, + pa_sample_spec const * ss, + pa_channel_map const * map, + pa_buffer_attr const * attr) + { + int err{}; + this->native_handle()=pa_simple_new(server,name,dir,dev,stream_name,ss,map,attr,__builtin_addressof(err)); + if(this->native_handle()==nullptr) + throw_pulse_audio_error(err); + } + basic_pulseaudio_simple_file(basic_pulseaudio_simple_file const&)=delete; + basic_pulseaudio_simple_file& operator=(basic_pulseaudio_simple_file const&)=delete; + constexpr basic_pulseaudio_simple_file(basic_pulseaudio_simple_file&& __restrict hd) noexcept:basic_pulseaudio_simple_file(hd.native_handle()) + { + hd.native_handle()=nullptr; + } + basic_pulseaudio_simple_file& operator=(basic_pulseaudio_simple_file&& __restrict hd) noexcept + { + if(this->native_handle())[[likely]] + pa_simple_free(this->native_handle()); + this->native_handle()=hd.native_handle(); + hd.native_handle()=nullptr; + return *this; + } + inline void reset(native_handle_type newhandle=nullptr) noexcept + { + if(this->native_handle())[[likely]] + pa_simple_free(this->native_handle()); + this->native_handle()=newhandle; + } + ~basic_pulseaudio_simple_file() + { + if(this->native_handle())[[likely]] + pa_simple_free(this->native_handle()); + } +}; + +template +inline Iter read(basic_pulseaudio_simple_io_observer bpsiob,Iter begin,Iter end) +{ + int err{}; + if(pa_simple_read(bpsiob.native_handle(),::std::to_address(begin),sizeof(*begin)*(end-begin),__builtin_addressof(err))<0)[[unlikely]] + throw_pulse_audio_error(err); + return end; +} + +template +inline Iter write(basic_pulseaudio_simple_io_observer bpsiob,Iter begin,Iter end) +{ + int err{}; + if(pa_simple_write(bpsiob.native_handle(),::std::to_address(begin),sizeof(*begin)*(end-begin),__builtin_addressof(err))<0)[[unlikely]] + throw_pulse_audio_error(err); + return end; +} + + +template +inline void flush(basic_pulseaudio_simple_io_observer bpsiob) +{ + int err{}; + if(pa_simple_flush(bpsiob.native_handle(),__builtin_addressof(err))<0)[[unlikely]] + throw_pulse_audio_error(err); +} + +using pulseaudio_simple_io_observer = basic_pulseaudio_simple_io_observer; +using pulseaudio_simple_file = basic_pulseaudio_simple_file; + +} diff --git a/src/fast_io/include/fast_io_driver/python/pyobject.h b/src/fast_io/include/fast_io_driver/python/pyobject.h new file mode 100644 index 0000000..ee3273d --- /dev/null +++ b/src/fast_io/include/fast_io_driver/python/pyobject.h @@ -0,0 +1,224 @@ +#pragma once + +/* +Create python's PyBytesObject by using fast_io's api +*/ +#include"../../fast_io_core.h" +#include +#include + +namespace fast_io +{ + +class pyobject_io_observer +{ +public: + using native_handle_type = PyObject*; + native_handle_type p{}; + constexpr native_handle_type native_handle() const noexcept + { + return p; + } + constexpr native_handle_type release() noexcept + { + auto temp{p}; + this->p = nullptr; + return temp; + } +}; + +namespace details +{ + +template +inline void py_inc_dec_ref_model_impl(void *p) +{ + if constexpr(dec) + { + Py_DECREF(p); + } + else + { + Py_INCREF(p); + } +} + +template +inline void py_inc_dec_ref_impl(void * p) noexcept +{ + if(p==nullptr) + return; + ::fast_io::noexcept_call(py_inc_dec_ref_model_impl,p); +} + +inline PyObject* pybytes_fromstringandsize_model_impl(char const *v, Py_ssize_t len) +{ + return PyBytes_FromStringAndSize(v,len); +} + +inline PyObject* pybytes_fromstringandsize_impl(char const *v, Py_ssize_t len) noexcept +{ + auto p{::fast_io::noexcept_call(pybytes_fromstringandsize_model_impl,v,len)}; + if(p==nullptr) + { + ::fast_io::fast_terminate(); + } + return p; +} + +inline PyObject* pyobject_repr_model_impl(PyObject* p) +{ + return PyObject_Repr(p); +} + +inline PyObject* pyunicode_asencodedstring_model_impl(PyObject *self, char const *name, char const *value) +{ + return PyUnicode_AsEncodedString(self,name,value); +} + +inline PyObject* pyunicode_asencodedstring_impl(PyObject *self, char const *name, char const *value) noexcept +{ + if(self==nullptr) + { + return nullptr; + } + return ::fast_io::noexcept_call(pyunicode_asencodedstring_model_impl,self,name,value); +} + + +inline int pybytes_asstringandsize_model_impl(PyObject *self, char** p,Py_ssize_t* len) +{ + return PyBytes_AsStringAndSize(self,p,len); +} + +inline basic_io_scatter_t pybytes_asstringandsize_impl(PyObject *self) noexcept +{ + char* s{}; + Py_ssize_t len{}; + if(self!=nullptr) +#if __has_cpp_attribute(likely) + [[likely]] +#endif + { + if(::fast_io::noexcept_call(pybytes_asstringandsize_model_impl,self,__builtin_addressof(s),__builtin_addressof(len))<0) + { + s=nullptr; + len=0; + } + } + return {s,static_cast<::std::size_t>(len)}; +} + +} + +class pyobject_file:public pyobject_io_observer +{ +public: + using typename pyobject_io_observer::native_handle_type; + + constexpr pyobject_file() noexcept = default; + explicit constexpr pyobject_file(native_handle_type pp) noexcept:pyobject_io_observer{pp} + { + } + pyobject_file(pyobject_io_observer) noexcept = delete; + pyobject_file(pyobject_file const& pob) noexcept:pyobject_io_observer{pob.p} + { + ::fast_io::details::py_inc_dec_ref_impl(this->p); + } + pyobject_file& operator=(pyobject_file const & pob) noexcept + { + ::fast_io::details::py_inc_dec_ref_impl(this->p); + ::fast_io::details::py_inc_dec_ref_impl(this->p=pob.p); + return *this; + } + constexpr pyobject_file(pyobject_file&& pob) noexcept:pyobject_io_observer{pob.p} + { + pob.p = nullptr; + } + pyobject_file& operator=(pyobject_file&& pob) noexcept + { + ::fast_io::details::py_inc_dec_ref_impl(this->p); + this->p=pob.p; + pob.p=nullptr; + return *this; + } + ~pyobject_file() + { + ::fast_io::details::py_inc_dec_ref_impl(this->p); + } +}; + +inline constexpr pyobject_io_observer io_strlike_ref(io_alias_t,pyobject_io_observer pyiob) noexcept +{ + return pyiob; +} + +inline pyobject_file strlike_construct_define(io_strlike_type_t,char const* first,char const* last) noexcept +{ + std::size_t diff{static_cast(last-first)}; + if constexpr(::std::numeric_limits::max()<::std::numeric_limits<::std::size_t>::max()) + { + constexpr Py_ssize_t max_sz{static_cast(std::numeric_limits::max()/static_cast(sizeof(char)))}; + if(max_sz(diff))}; + ::fast_io::details::py_inc_dec_ref_impl(p); + return pyobject_file(p); +} + +template +inline pyobject_file concat_pyobject_file(Args&& ...args) +{ + return ::fast_io::basic_general_concat(::std::forward(args)...); +} + +template +inline pyobject_file concatln_pyobject_file(Args&& ...args) +{ + return ::fast_io::basic_general_concat(::std::forward(args)...); +} + +inline pyobject_file print_alias_define(io_alias_t,pyobject_io_observer pyiob) noexcept +{ + pyobject_file pyob_repr{::fast_io::noexcept_call(::fast_io::details::pyobject_repr_model_impl,pyiob.p)}; + return pyobject_file(::fast_io::details::pyunicode_asencodedstring_impl( + pyob_repr.p,reinterpret_cast(u8"utf-8"),reinterpret_cast(u8"~E~"))); +} + +template +inline std::conditional_t,manipulators::code_cvt_t> status_io_print_forward(io_alias_type_t,pyobject_io_observer piob) noexcept +{ + using char_type_may_alias_const_ptr +#if __has_cpp_attribute(gnu::may_alias) + [[gnu::may_alias]] +#endif + = char_type const*; + if constexpr(::std::same_as) + { + return ::fast_io::details::pybytes_asstringandsize_impl(piob.p); + } + else if constexpr(sizeof(char)==sizeof(char_type)) + { + auto ret{::fast_io::details::pybytes_asstringandsize_impl(piob.p)}; + return {reinterpret_cast(ret.base),ret.len}; + } + else + { + auto ret{::fast_io::details::pybytes_asstringandsize_impl(piob.p)}; + return {{reinterpret_cast(ret.base),ret.len}}; + } +} + +namespace manipulators +{ + +inline constexpr pyobject_io_observer pyobj(PyObject* p) noexcept +{ + return {p}; +} + +} + +} + diff --git a/src/fast_io/include/fast_io_driver/qt.h b/src/fast_io/include/fast_io_driver/qt.h new file mode 100644 index 0000000..a2271b3 --- /dev/null +++ b/src/fast_io/include/fast_io_driver/qt.h @@ -0,0 +1,29 @@ +#pragma once + +#if __has_include() +#include +#else +#include +#endif +#if __has_include() +#include +#else +#include +#endif +#if __has_include() +#include +#else +#include +#endif +#if __has_include() +#include +#else +#include +#endif + +#include"qt_impl/qstring.h" +#include"qt_impl/qiodevice.h" +#include"qt_impl/qfile.h" +#if defined(QDEBUG_H) +#include"qt_impl/qdebug.h" +#endif diff --git a/src/fast_io/include/fast_io_driver/qt_impl/qdebug.h b/src/fast_io/include/fast_io_driver/qt_impl/qdebug.h new file mode 100644 index 0000000..2551ebb --- /dev/null +++ b/src/fast_io/include/fast_io_driver/qt_impl/qdebug.h @@ -0,0 +1,79 @@ +#pragma once + +namespace fast_io +{ + +template +struct basic_qt_qdebug +{ + using char_type = ch_type; + QDebug pqdbg; +}; + +using qt_qdebug = basic_qt_qdebug; +using wqt_qdebug = basic_qt_qdebug; +using u8qt_qdebug = basic_qt_qdebug; +using u16qt_qdebug = basic_qt_qdebug; +using u32qt_qdebug = basic_qt_qdebug; + +namespace manipulators +{ + +inline ::fast_io::qt_qdebug qtdbg(QDebug qdbg) +{ + return {qdbg}; +} + +inline ::fast_io::wqt_qdebug wqtdbg(QDebug qdbg) +{ + return {qdbg}; +} + +inline ::fast_io::u8qt_qdebug u8qtdbg(QDebug qdbg) +{ + return {qdbg}; +} + +inline ::fast_io::u16qt_qdebug u16qtdbg(QDebug qdbg) +{ + return {qdbg}; +} + +inline ::fast_io::u32qt_qdebug u32qtdbg(QDebug qdbg) +{ + return {qdbg}; +} + +} + +namespace details +{ + +inline void qtdbg_write_impl(QDebug& qdb,char const* first,char const* last) +{ + qdb<(i->base),reinterpret_cast(i->base)+i->len); + } +} + +} + +template +inline void write(basic_qt_qdebug qdbg,char_type const* first,char_type const* last) +{ + ::fast_io::details::qtdbg_write_impl(qdbg.pqdbg,reinterpret_cast(first),reinterpret_cast(last)); +} + +template +inline void scatter_write(basic_qt_qdebug qdbg,io_scatters_t scatters) +{ + ::fast_io::details::qtdbg_scatter_write_impl(qdbg.pqdbg,scatters.base,scatters.len); +} + +} diff --git a/src/fast_io/include/fast_io_driver/qt_impl/qfile.h b/src/fast_io/include/fast_io_driver/qt_impl/qfile.h new file mode 100644 index 0000000..ac6c724 --- /dev/null +++ b/src/fast_io/include/fast_io_driver/qt_impl/qfile.h @@ -0,0 +1,185 @@ +#pragma once + +namespace fast_io +{ + +namespace details +{ + +inline constexpr int to_qt_open_mode(open_mode mode) noexcept +{ + int res{}; + if((mode&open_mode::in)==open_mode::in) + res|=QIODevice::ReadOnly; + if((mode&open_mode::out)==open_mode::out) + res|=QIODevice::WriteOnly; + if((mode&open_mode::app)==open_mode::app) + res|=QIODevice::Append; + if((mode&open_mode::trunc)==open_mode::trunc) + res|=QIODevice::Truncate; + if((mode&open_mode::text)==open_mode::text) + res|=QIODevice::Text; + if((mode&open_mode::excl)==open_mode::excl) + res|=QIODevice::NewOnly; + if((mode&open_mode::directory)==open_mode::directory) + { + if((mode&open_mode::in)!=open_mode::in) + res|=QIODevice::ReadOnly; + } + return res; +} + +struct qfile_scoped_guard +{ + QFile* qf{new QFile}; + explicit qfile_scoped_guard() = default; + qfile_scoped_guard(qfile_scoped_guard const&)=delete; + qfile_scoped_guard& operator=(qfile_scoped_guard const&)=delete; + inline constexpr QFile* release() noexcept + { + auto temp{qf}; + qf=nullptr; + return temp; + } + ~qfile_scoped_guard() + { + if(qf) + delete qf; + } +}; + +inline QFile* open_qfile_with_fp_internal(FILE* fp,QIODevice::OpenModeFlag mode) +{ + qfile_scoped_guard guard; + guard.qf->open(fp,mode,QFileDevice::AutoCloseHandle); + return guard.release(); +} + +inline QFile* open_qfile_with_fp(FILE* fp,open_mode mode) +{ + return open_qfile_with_fp_internal(fp,static_cast(to_qt_open_mode(mode))); +} + +inline QFile* open_qfile_with_fd_internal(int fd,QIODevice::OpenModeFlag mode) +{ + qfile_scoped_guard guard; + guard.qf->open(fd,mode,QFileDevice::AutoCloseHandle); + return guard.release(); +} + +inline QFile* open_qfile_with_fd(int fd,open_mode mode) +{ + return open_qfile_with_fd_internal(fd,static_cast(to_qt_open_mode(mode))); +} + +} + +template +class basic_qt_file:public basic_qt_io_observer +{ +public: + using char_type = ch_type; + using native_handle_type = typename basic_qt_io_observer::native_handle_type; + constexpr basic_qt_file()=default; + template + requires std::same_as> + explicit constexpr basic_qt_file(native_hd qdevice):basic_qt_io_observer{qdevice}{} + + explicit constexpr basic_qt_file(decltype(nullptr)) noexcept=delete; + + constexpr basic_qt_file(basic_qt_io_observer) noexcept=delete; + constexpr basic_qt_file& operator=(basic_qt_io_observer) noexcept=delete; + + template + basic_qt_file(basic_c_family_file&& cioh,open_mode mode):basic_qt_io_observer{::fast_io::details::open_qfile_with_fp(cioh.fp,mode)} + { + cioh.fp=nullptr; + } +#if !defined(__AVR__) + basic_qt_file(basic_posix_file&& pioh,open_mode mode):basic_qt_io_observer{::fast_io::details::open_qfile_with_fd(pioh.fd,mode)} + { + pioh.fd=-1; + } +#if (defined(_WIN32) && !defined(__WINE__)) || defined(__CYGWIN__) + template + basic_qt_file(basic_win32_family_file&& wioh,open_mode mode): + basic_qt_file(basic_posix_file(::std::move(wioh),mode),mode) + {} + template + basic_qt_file(basic_nt_family_file&& wioh,open_mode mode): + basic_qt_file(basic_posix_file(::std::move(wioh),mode),mode) + {} +#endif + basic_qt_file(native_fs_dirent fsdirent,open_mode om,perms pm=static_cast(436)): + basic_qt_file(basic_posix_file(fsdirent,om,pm),om) + {} + template<::fast_io::constructible_to_os_c_str T> + basic_qt_file(T const& file,open_mode om,perms pm=static_cast(436)): + basic_qt_file(basic_posix_file(file,om,pm),om) + {} + template<::fast_io::constructible_to_os_c_str T> + basic_qt_file(native_at_entry nate,T const& file,open_mode om,perms pm=static_cast(436)): + basic_qt_file(basic_posix_file(nate,file,om,pm),om) + {} +#endif + basic_qt_file(basic_qt_file const&)=delete; + basic_qt_file& operator=(basic_qt_file const&)=delete; + + void close() + { + if(this->qdevice)[[likely]] + { + struct delete_guard + { + native_handle_type& qdevicer; + delete_guard(native_handle_type& qdevice):qdevicer(qdevice){} + delete_guard(delete_guard const&)=delete; + delete_guard& operator=(delete_guard const&)=delete; + ~delete_guard() + { + delete qdevicer; + qdevicer=nullptr; + } + }guard{this->qdevice}; + this->qdevice->close(); + } + } +private: + void close_nothrow() noexcept + { +#ifdef __cpp_exceptions + try + { +#endif + this->close(); +#ifdef __cpp_exceptions + } + catch(...) + { + } +#endif + } +public: + + constexpr basic_qt_file(basic_qt_file&& __restrict other) noexcept: + basic_qt_io_observer{other.release()} + {} + basic_qt_file& operator=(basic_qt_file&& __restrict other) noexcept + { + close_nothrow(); + this->qdevice=other.release(); + return *this; + } + ~basic_qt_file() + { + close_nothrow(); + } +}; + +using qt_file = basic_qt_file; +using wqt_file = basic_qt_file; +using u8qt_file = basic_qt_file; +using u16qt_file = basic_qt_file; +using u32qt_file = basic_qt_file; + +} diff --git a/src/fast_io/include/fast_io_driver/qt_impl/qiodevice.h b/src/fast_io/include/fast_io_driver/qt_impl/qiodevice.h new file mode 100644 index 0000000..18c7ddb --- /dev/null +++ b/src/fast_io/include/fast_io_driver/qt_impl/qiodevice.h @@ -0,0 +1,157 @@ +#pragma once +namespace fast_io +{ + +template +class basic_general_qdevice_io_observer +{ +public: + using char_type = ch_type; + using value_type = T; + using native_handle_type = T*; + native_handle_type qdevice{}; + + inline constexpr native_handle_type native_handle() const noexcept + { + return qdevice; + } + inline constexpr native_handle_type release() noexcept + { + auto temp{qdevice}; + qdevice=nullptr; + return temp; + } + + inline operator basic_posix_io_observer() requires requires() + { + {this->qdevice->handle()}->std::same_as; + } + { + return basic_posix_io_observer{this->qdevice->handle()}; + } +#if (defined(_WIN32) && !defined(__WINE__)) || defined(__CYGWIN__) + inline operator basic_win32_io_observer() requires requires() + { + {this->qdevice->handle()}->std::same_as; + } + { + return static_cast>( + static_cast>(*this) + ); + } + template + inline operator basic_nt_family_io_observer() requires requires() + { + {this->qdevice->handle()}->std::same_as; + } + { + return static_cast>( + static_cast>(*this) + ); + } +#endif +}; + +namespace details +{ + +inline std::size_t qio_device_write_impl(QIODevice* __restrict qdevice,void const* data,std::size_t bytes) +{ + std::int_least64_t res{qdevice->write(reinterpret_cast(data),static_cast(bytes))}; + if(res<0) + throw_qt_error(qdevice->errorString()); + return static_cast(res); +} + +inline std::size_t qio_device_read_impl(QIODevice* __restrict qdevice,void* data,std::size_t bytes) +{ + std::int_least64_t res{qdevice->read(reinterpret_cast(data),static_cast(bytes))}; + if(res<0) + throw_qt_error(qdevice->errorString()); + return static_cast(res); +} + + +inline std::uintmax_t qio_device_seek_impl(QIODevice* __restrict qdevice,std::intmax_t offset,seekdir dir) +{ + if(dir==seekdir::beg) + offset=static_cast(qdevice->pos())+offset; + else if(dir==seekdir::end) + offset=static_cast(qdevice->size()-qdevice->pos())+offset; + if(!qdevice->seek(static_cast(offset))) + throw_qt_error(qdevice->errorString()); + return static_cast(qdevice->pos()); +} + +} + +template +inline Iter write(basic_general_qdevice_io_observer qiob,Iter begin,Iter end) +{ + return begin+details::qio_device_write_impl(qiob.qdevice,::std::to_address(begin), + static_cast(::std::to_address(end)-::std::to_address(begin))*sizeof(*begin))/sizeof(*begin); +} + +template +inline Iter read(basic_general_qdevice_io_observer qiob,Iter begin,Iter end) +{ + return begin+details::qio_device_read_impl(qiob.qdevice,::std::to_address(begin), + static_cast(::std::to_address(end)-::std::to_address(begin))*sizeof(*begin))/sizeof(*begin); +} + +template +requires (sizeof(ch_type)==1) +inline std::pair try_get(basic_general_qdevice_io_observer qiob) +{ + char ch; + bool ef{qiob.qdevice->getChar(&ch)}; + return {static_cast(ch),ef}; +} + +template +requires (sizeof(ch_type)==1) +inline void try_unget(basic_general_qdevice_io_observer qiob,ch_type ch) noexcept +{ + qiob.qdevice->ungetChar(ch); +} + +template +inline std::uintmax_t seek(basic_general_qdevice_io_observer qiob,std::intmax_t offset=0,seekdir s=seekdir::cur) +{ + return qio_device_seek_impl(qiob->qdevice,offset,s); +} +template +using basic_qiodevice_io_observer = basic_general_qdevice_io_observer; +template +using basic_qt_io_observer = basic_general_qdevice_io_observer; + +template +inline constexpr basic_qiodevice_io_observer io_value_handle(basic_general_qdevice_io_observer gqiob) noexcept +{ + return {gqiob.qdevice}; +} + +template +requires requires(basic_general_qdevice_io_observer piob) +{ + {piob.qdevice->handle()}->std::same_as; +} +inline constexpr posix_at_entry at(basic_general_qdevice_io_observer piob) noexcept +{ + return posix_at_entry{piob.qdevice->handle()}; +} + +using qiodevice_io_observer = basic_qiodevice_io_observer; +using wqiodevice_io_observer = basic_qiodevice_io_observer; +using u8qiodevice_io_observer = basic_qiodevice_io_observer; +using u16qiodevice_io_observer = basic_qiodevice_io_observer; +using u32qiodevice_io_observer = basic_qiodevice_io_observer; + +using qt_io_observer = basic_qt_io_observer; +using wqt_io_observer = basic_qt_io_observer; +using u8qt_io_observer = basic_qt_io_observer; +using u16qt_io_observer = basic_qt_io_observer; +using u32qt_io_observer = basic_qt_io_observer; + +} + diff --git a/src/fast_io/include/fast_io_driver/qt_impl/qstring.h b/src/fast_io/include/fast_io_driver/qt_impl/qstring.h new file mode 100644 index 0000000..fd252d2 --- /dev/null +++ b/src/fast_io/include/fast_io_driver/qt_impl/qstring.h @@ -0,0 +1,150 @@ +#pragma once + +namespace fast_io +{ + +class qt_error +{ +public: + QString qstr; + template + requires std::constructible_from + qt_error(Args&& ...args):qstr(::std::forward(args)...){} + + QChar* data() noexcept + { + return qstr.data(); + } + QChar const* data() const noexcept + { + return qstr.data(); + } + std::size_t size() const noexcept + { + return static_cast(qstr.size()); + } +}; + +namespace details +{ + +template +concept qt_qstring_view_like_impl = std::same_as,QString>||std::same_as,qt_error>; + +template +concept qt_convertible_to_qstring_impl = requires(T const& e) +{ + {e.toString()}->std::same_as; +}; + +} + +template +requires std::constructible_from +inline void throw_qt_error([[maybe_unused]] Args&& ...args) +{ +#ifdef __cpp_exceptions +#if defined(_MSC_VER) && (!defined(_HAS_EXCEPTIONS) || _HAS_EXCEPTIONS == 0) + fast_terminate(); +#else + throw qt_error(::std::forward(args)...); +#endif +#else + fast_terminate(); +#endif +} + +template +requires (details::qt_qstring_view_like_impl) +constexpr std::conditional_t,manipulators::code_cvt_t> status_io_print_forward(io_alias_type_t,T const& hstr) noexcept +{ + if constexpr(sizeof(char_type)==sizeof(char16_t)) + { + using general_utf16_may_alias_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = char_type const*; + return {reinterpret_cast(hstr.data()),static_cast(hstr.size())}; + } + else + { + using char16_may_alias_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = char16_t const*; + return {{reinterpret_cast(hstr.data()),static_cast(hstr.size())}}; + } +} + +template +requires (details::qt_convertible_to_qstring_impl) +inline QString print_alias_define(io_alias_t,T const& hstr) noexcept +{ + return {hstr.toString()}; +} + +inline QString strlike_construct_define(io_strlike_type_t,char16_t const* first,char16_t const* last) +{ + std::size_t diff{static_cast(last-first)}; + if constexpr(sizeof(unsigned)(first),static_cast(static_cast(diff))); +} + +inline QString strlike_single_character_construct_define(io_strlike_type_t,char16_t ch) +{ + return QString(ch); +} + +template +inline QString u16concat_qt_qstring(Args&& ...args) +{ + return ::fast_io::basic_general_concat(::std::forward(args)...); +} + +template +inline QString u16concatln_qt_qstring(Args&& ...args) +{ + return ::fast_io::basic_general_concat(::std::forward(args)...); +} + +inline constexpr io_strlike_reference_wrapper io_strlike_ref(::fast_io::io_alias_t,QString& hstr) noexcept +{ + return {__builtin_addressof(hstr)}; +} + +namespace manipulators +{ + +template +inline auto qt_as_filename(T const& hstr) noexcept +{ + using char16_may_alias_const_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = char16_t const*; + if constexpr(::std::same_as<::std::remove_cvref_t,QString>) + { + return ::fast_io::manipulators::basic_os_c_str_with_known_size{reinterpret_cast(hstr.data()),static_cast(hstr.size())}; + } + else + { + return ::fast_io::manipulators::basic_os_str_known_size_without_null_terminated{reinterpret_cast(hstr.data()),static_cast(hstr.size())}; + } +} + +} + +} diff --git a/src/fast_io/include/fast_io_driver/refterm.h b/src/fast_io/include/fast_io_driver/refterm.h new file mode 100644 index 0000000..8c09a02 --- /dev/null +++ b/src/fast_io/include/fast_io_driver/refterm.h @@ -0,0 +1,52 @@ +#pragma once + +namespace fast_io +{ + +namespace details +{ + +inline constexpr ::fast_io::manipulators::scalar_flags fast_pipe_hex_scl_flg{.base=16,.floating=::fast_io::manipulators::floating_format::fixed}; + +template +inline void* win32_family_refterm_fast_pipe_impl(open_mode mode,perms pm) +{ + std::uint_least32_t process_id{::fast_io::win32::GetCurrentProcessId()}; + using type = ::fast_io::mnp::scalar_manip_t; + if constexpr(family==win32_family::wide_nt) + { + char16_t buffer[256]=u"\\\\.\\pipe\\fastpipe"; + constexpr std::size_t sz{sizeof(u"\\\\.\\pipe\\fastpipe")/sizeof(char16_t)-1}; + char16_t* res{print_reserve_define(io_reserve_type,buffer+sz,{process_id})}; + *res=0; + return win32_file_ntw(::fast_io::mnp::os_c_str(buffer),mode,pm).release(); + } + else + { + char8_t buffer[256]=u8"\\\\.\\pipe\\fastpipe"; + constexpr std::size_t sz{sizeof(u8"\\\\.\\pipe\\fastpipe")/sizeof(char8_t)-1}; + char8_t* res{print_reserve_define(io_reserve_type,buffer+sz,{process_id})}; + *res=0; + return win32_file_9xa(::fast_io::mnp::os_c_str(buffer),mode,pm).release(); + } + +} + +} + +inline win32_file_factory win32_refterm_fast_pipe_9xa(open_mode mode=open_mode::in|open_mode::out|open_mode::excl,perms pm=static_cast(436)) +{ + return win32_file_factory{details::win32_family_refterm_fast_pipe_impl(mode,pm)}; +} + +inline win32_file_factory win32_refterm_fast_pipe_ntw(open_mode mode=open_mode::in|open_mode::out|open_mode::excl,perms pm=static_cast(436)) +{ + return win32_file_factory{details::win32_family_refterm_fast_pipe_impl(mode,pm)}; +} + +inline win32_file_factory win32_refterm_fast_pipe(open_mode mode=open_mode::in|open_mode::out|open_mode::excl,perms pm=static_cast(436)) +{ + return win32_file_factory{details::win32_family_refterm_fast_pipe_impl(mode,pm)}; +} + +} diff --git a/src/fast_io/include/fast_io_driver/stvl2.h b/src/fast_io/include/fast_io_driver/stvl2.h new file mode 100644 index 0000000..484d7e2 --- /dev/null +++ b/src/fast_io/include/fast_io_driver/stvl2.h @@ -0,0 +1,1521 @@ +#pragma once +#include"../fast_io_concept.h" +#include"bootloader/stvl2.h" + +namespace fast_io +{ + +namespace details +{ + +template +inline constexpr std::size_t cal_stvl2_cstr_reserved_size(std::size_t sz) noexcept +{ + constexpr bool ebcdic{::fast_io::details::is_ebcdic}; + if constexpr(sizeof(char_type)==1&&!ebcdic) + return sz; + else + return cal_full_reserve_size<1,sizeof(char_type)>(sz); +} + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define_impl_for_stvl2_header_tag(char_type* iter,stvl2::stvl2_header_tag tg) noexcept +{ + using enum stvl2::stvl2_header_tag; + if constexpr(std::same_as) + { + switch(tg) + { + case framebuffer_id: + return copy_string_literal("framebuffer_id",iter); + case fb_mtrr_id: + return copy_string_literal("fb_mtrr_id",iter); + case smp_id: + return copy_string_literal("smp_id",iter); + default: + return copy_string_literal("unknown",iter); + } + } + else if constexpr(std::same_as) + { + switch(tg) + { + case framebuffer_id: + return copy_string_literal(L"framebuffer_id",iter); + case fb_mtrr_id: + return copy_string_literal(L"fb_mtrr_id",iter); + case smp_id: + return copy_string_literal(L"smp_id",iter); + default: + return copy_string_literal(L"unknown",iter); + } + } + else if constexpr(std::same_as) + { + switch(tg) + { + case framebuffer_id: + return copy_string_literal(u"framebuffer_id",iter); + case fb_mtrr_id: + return copy_string_literal(u"fb_mtrr_id",iter); + case smp_id: + return copy_string_literal(u"smp_id",iter); + default: + return copy_string_literal(u"unknown",iter); + } + } + else if constexpr(std::same_as) + { + switch(tg) + { + case framebuffer_id: + return copy_string_literal(U"framebuffer_id",iter); + case fb_mtrr_id: + return copy_string_literal(U"fb_mtrr_id",iter); + case smp_id: + return copy_string_literal(U"smp_id",iter); + default: + return copy_string_literal(U"unknown",iter); + } + } + else + { + switch(tg) + { + case framebuffer_id: + return copy_string_literal(u8"framebuffer_id",iter); + case fb_mtrr_id: + return copy_string_literal(u8"fb_mtrr_id",iter); + case smp_id: + return copy_string_literal(u8"smp_id",iter); + default: + return copy_string_literal(u8"unknown",iter); + } + } +} + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define_impl_for_stvl2_tag(char_type* iter,stvl2::stvl2_tag tg) noexcept +{ + if constexpr(std::same_as) + { + iter=copy_string_literal("identifier: ",iter); + iter=print_reserve_define_impl_for_stvl2_header_tag(iter,tg.identifier); + iter=copy_string_literal("\nnext: ",iter); + } + else if constexpr(std::same_as) + { + iter=copy_string_literal(L"identifier: ",iter); + iter=print_reserve_define_impl_for_stvl2_header_tag(iter,tg.identifier); + iter=copy_string_literal(L"\nnext: ",iter); + } + else if constexpr(std::same_as) + { + iter=copy_string_literal(u"identifier: ",iter); + iter=print_reserve_define_impl_for_stvl2_header_tag(iter,tg.identifier); + iter=copy_string_literal(u"\nnext: ",iter); + } + else if constexpr(std::same_as) + { + iter=copy_string_literal(U"identifier: ",iter); + iter=print_reserve_define_impl_for_stvl2_header_tag(iter,tg.identifier); + iter=copy_string_literal(U"\nnext: ",iter); + } + else + { + iter=copy_string_literal(u8"identifier: ",iter); + iter=print_reserve_define_impl_for_stvl2_header_tag(iter,tg.identifier); + iter=copy_string_literal(u8"\nnext: ",iter); + } + return print_reserve_define(io_reserve_type,iter,tg.next); +} + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define_impl_for_stvl2_header(char_type* iter,stvl2::stvl2_header tg) noexcept +{ + if constexpr(std::same_as) + { + iter=copy_string_literal("entry_point: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.entry_point); + iter=copy_string_literal("\nstack: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.stack); + iter=copy_string_literal("\nflags: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.flags); + iter=copy_string_literal("\ntags_root: ",iter); + } + else if constexpr(std::same_as) + { + iter=copy_string_literal(L"entry_point: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.entry_point); + iter=copy_string_literal(L"\nstack: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.stack); + iter=copy_string_literal(L"\nflags: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.flags); + iter=copy_string_literal(L"\ntags_root: ",iter); + } + else if constexpr(std::same_as) + { + iter=copy_string_literal(u"entry_point: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.entry_point); + iter=copy_string_literal(u"\nstack: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.stack); + iter=copy_string_literal(u"\nflags: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.flags); + iter=copy_string_literal(u"\ntags_root: ",iter); + } + else if constexpr(std::same_as) + { + iter=copy_string_literal(U"entry_point: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.entry_point); + iter=copy_string_literal(U"\nstack: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.stack); + iter=copy_string_literal(U"\nflags: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.flags); + iter=copy_string_literal(U"\ntags_root: ",iter); + } + else + { + iter=copy_string_literal(u8"entry_point: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.entry_point); + iter=copy_string_literal(u8"\nstack: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.stack); + iter=copy_string_literal(u8"\nflags: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.flags); + iter=copy_string_literal(u8"\ntags_root: ",iter); + } + return print_reserve_define(io_reserve_type,iter,tg.tags_root); +} + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define_impl_for_stvl2_header_tag_framebuffer(char_type* iter,stvl2::stvl2_header_tag_framebuffer tg) noexcept +{ + iter=print_reserve_define_impl_for_stvl2_tag(iter,tg); + if constexpr(std::same_as) + { + iter=copy_string_literal("\nframebuffer_width: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.framebuffer_width); + iter=copy_string_literal("\nframebuffer_height: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.framebuffer_height); + iter=copy_string_literal("\nframebuffer_bpp: ",iter); + } + else if constexpr(std::same_as) + { + iter=copy_string_literal(L"\nframebuffer_width: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.framebuffer_width); + iter=copy_string_literal(L"\nframebuffer_height: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.framebuffer_height); + iter=copy_string_literal(L"\nframebuffer_bpp: ",iter); + } + else if constexpr(std::same_as) + { + iter=copy_string_literal(u"\nframebuffer_width: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.framebuffer_width); + iter=copy_string_literal(u"\nframebuffer_height: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.framebuffer_height); + iter=copy_string_literal(u"\nframebuffer_bpp: ",iter); + } + else if constexpr(std::same_as) + { + iter=copy_string_literal(U"\nframebuffer_width: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.framebuffer_width); + iter=copy_string_literal(U"\nframebuffer_height: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.framebuffer_height); + iter=copy_string_literal(U"\nframebuffer_bpp: ",iter); + } + else + { + iter=copy_string_literal(u8"\nframebuffer_width: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.framebuffer_width); + iter=copy_string_literal(u8"\nframebuffer_height: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.framebuffer_height); + iter=copy_string_literal(u8"\nframebuffer_bpp: ",iter); + } + return print_reserve_define(io_reserve_type,iter,tg.framebuffer_bpp); +} + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define_impl_for_stvl2_header_tag_smp(char_type* iter,stvl2::stvl2_header_tag_smp tg) noexcept +{ + iter=print_reserve_define_impl_for_stvl2_tag(iter,tg); + if constexpr(std::same_as) + iter=copy_string_literal("\nflags: ",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(L"\nflags: ",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(u"\nflags: ",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(U"\nflags: ",iter); + else + iter=copy_string_literal(u8"\nflags: ",iter); + return print_reserve_define(io_reserve_type,iter,tg.flags); +} + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define_impl_for_stvl2_struct_tag(char_type* iter,stvl2::stvl2_struct_tag tg) noexcept +{ + using enum stvl2::stvl2_struct_tag; + if constexpr(std::same_as) + { + switch(tg) + { + case cmdline_id:return copy_string_literal("cmdline_id",iter); + case memmap_id:return copy_string_literal("memmap_id",iter); + case framebuffer_id:return copy_string_literal("framebuffer_id",iter); + case fb_mtrr_id:return copy_string_literal("fb_mtrr_id",iter); + case modules_id:return copy_string_literal("modules_id",iter); + case rsdp_id:return copy_string_literal("rsdp_id",iter); + case epoch_id:return copy_string_literal("epoch_id",iter); + case firmware_id:return copy_string_literal("firmware_id",iter); + case smp_id:return copy_string_literal("smp_id",iter); + case pxe_server_info:return copy_string_literal("pxe_server_info",iter); + case mmio32_uart:return copy_string_literal("mmio32_uart",iter); + case dtb:return copy_string_literal("dtb",iter); + case vmap:return copy_string_literal("vmap",iter); + default:return copy_string_literal("unknown",iter); + } + } + else if constexpr(std::same_as) + { + switch(tg) + { + case cmdline_id:return copy_string_literal(L"cmdline_id",iter); + case memmap_id:return copy_string_literal(L"memmap_id",iter); + case framebuffer_id:return copy_string_literal(L"framebuffer_id",iter); + case fb_mtrr_id:return copy_string_literal(L"fb_mtrr_id",iter); + case modules_id:return copy_string_literal(L"modules_id",iter); + case rsdp_id:return copy_string_literal(L"rsdp_id",iter); + case epoch_id:return copy_string_literal(L"epoch_id",iter); + case firmware_id:return copy_string_literal(L"firmware_id",iter); + case smp_id:return copy_string_literal(L"smp_id",iter); + case pxe_server_info:return copy_string_literal(L"pxe_server_info",iter); + case mmio32_uart:return copy_string_literal(L"mmio32_uart",iter); + case dtb:return copy_string_literal(L"dtb",iter); + case vmap:return copy_string_literal(L"vmap",iter); + default:return copy_string_literal(L"unknown",iter); + } + } + else if constexpr(std::same_as) + { + switch(tg) + { + case cmdline_id:return copy_string_literal(u"cmdline_id",iter); + case memmap_id:return copy_string_literal(u"memmap_id",iter); + case framebuffer_id:return copy_string_literal(u"framebuffer_id",iter); + case fb_mtrr_id:return copy_string_literal(u"fb_mtrr_id",iter); + case modules_id:return copy_string_literal(u"modules_id",iter); + case rsdp_id:return copy_string_literal(u"rsdp_id",iter); + case epoch_id:return copy_string_literal(u"epoch_id",iter); + case firmware_id:return copy_string_literal(u"firmware_id",iter); + case smp_id:return copy_string_literal(u"smp_id",iter); + case pxe_server_info:return copy_string_literal(u"pxe_server_info",iter); + case mmio32_uart:return copy_string_literal(u"mmio32_uart",iter); + case dtb:return copy_string_literal(u"dtb",iter); + case vmap:return copy_string_literal(u"vmap",iter); + default:return copy_string_literal(u"unknown",iter); + } + } + else if constexpr(std::same_as) + { + switch(tg) + { + case cmdline_id:return copy_string_literal(U"cmdline_id",iter); + case memmap_id:return copy_string_literal(U"memmap_id",iter); + case framebuffer_id:return copy_string_literal(U"framebuffer_id",iter); + case fb_mtrr_id:return copy_string_literal(U"fb_mtrr_id",iter); + case modules_id:return copy_string_literal(U"modules_id",iter); + case rsdp_id:return copy_string_literal(U"rsdp_id",iter); + case epoch_id:return copy_string_literal(U"epoch_id",iter); + case firmware_id:return copy_string_literal(U"firmware_id",iter); + case smp_id:return copy_string_literal(U"smp_id",iter); + case pxe_server_info:return copy_string_literal(U"pxe_server_info",iter); + case mmio32_uart:return copy_string_literal(U"mmio32_uart",iter); + case dtb:return copy_string_literal(U"dtb",iter); + case vmap:return copy_string_literal(U"vmap",iter); + default:return copy_string_literal(U"unknown",iter); + } + } + else + { + switch(tg) + { + case cmdline_id:return copy_string_literal(u8"cmdline_id",iter); + case memmap_id:return copy_string_literal(u8"memmap_id",iter); + case framebuffer_id:return copy_string_literal(u8"framebuffer_id",iter); + case fb_mtrr_id:return copy_string_literal(u8"fb_mtrr_id",iter); + case modules_id:return copy_string_literal(u8"modules_id",iter); + case rsdp_id:return copy_string_literal(u8"rsdp_id",iter); + case epoch_id:return copy_string_literal(u8"epoch_id",iter); + case firmware_id:return copy_string_literal(u8"firmware_id",iter); + case smp_id:return copy_string_literal(u8"smp_id",iter); + case pxe_server_info:return copy_string_literal(u8"pxe_server_info",iter); + case mmio32_uart:return copy_string_literal(u8"mmio32_uart",iter); + case dtb:return copy_string_literal(u8"dtb",iter); + case vmap:return copy_string_literal(u8"vmap",iter); + default:return copy_string_literal(u8"unknown",iter); + } + } +} + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define_impl_for_stvl2_mmap_type(char_type* iter,stvl2::stvl2_mmap_type tg) noexcept +{ + using enum stvl2::stvl2_mmap_type; + if constexpr(std::same_as) + { + switch(tg) + { + case usable:return copy_string_literal("usable",iter); + case reserved:return copy_string_literal("reserved",iter); + case acpi_reclaimable:return copy_string_literal("acpi_reclaimable",iter); + case acpi_nvs:return copy_string_literal("acpi_nvs",iter); + case bad_memory:return copy_string_literal("bad_memory",iter); + case bootloader_reclaimable:return copy_string_literal("bootloader_reclaimable",iter); + case kernel_and_modules:return copy_string_literal("kernel_and_modules",iter); + default:return copy_string_literal("unknown",iter); + } + } + else if constexpr(std::same_as) + { + switch(tg) + { + case usable:return copy_string_literal(L"usable",iter); + case reserved:return copy_string_literal(L"reserved",iter); + case acpi_reclaimable:return copy_string_literal(L"acpi_reclaimable",iter); + case acpi_nvs:return copy_string_literal(L"acpi_nvs",iter); + case bad_memory:return copy_string_literal(L"bad_memory",iter); + case bootloader_reclaimable:return copy_string_literal(L"bootloader_reclaimable",iter); + case kernel_and_modules:return copy_string_literal(L"kernel_and_modules",iter); + default:return copy_string_literal(L"unknown",iter); + } + } + else if constexpr(std::same_as) + { + switch(tg) + { + case usable:return copy_string_literal(u"usable",iter); + case reserved:return copy_string_literal(u"reserved",iter); + case acpi_reclaimable:return copy_string_literal(u"acpi_reclaimable",iter); + case acpi_nvs:return copy_string_literal(u"acpi_nvs",iter); + case bad_memory:return copy_string_literal(u"bad_memory",iter); + case bootloader_reclaimable:return copy_string_literal(u"bootloader_reclaimable",iter); + case kernel_and_modules:return copy_string_literal(u"kernel_and_modules",iter); + default:return copy_string_literal(u"unknown",iter); + } + } + else if constexpr(std::same_as) + { + switch(tg) + { + case usable:return copy_string_literal(U"usable",iter); + case reserved:return copy_string_literal(U"reserved",iter); + case acpi_reclaimable:return copy_string_literal(U"acpi_reclaimable",iter); + case acpi_nvs:return copy_string_literal(U"acpi_nvs",iter); + case bad_memory:return copy_string_literal(U"bad_memory",iter); + case bootloader_reclaimable:return copy_string_literal(U"bootloader_reclaimable",iter); + case kernel_and_modules:return copy_string_literal(U"kernel_and_modules",iter); + default:return copy_string_literal(U"unknown",iter); + } + } + else + { + switch(tg) + { + case usable:return copy_string_literal(u8"usable",iter); + case reserved:return copy_string_literal(u8"reserved",iter); + case acpi_reclaimable:return copy_string_literal(u8"acpi_reclaimable",iter); + case acpi_nvs:return copy_string_literal(u8"acpi_nvs",iter); + case bad_memory:return copy_string_literal(u8"bad_memory",iter); + case bootloader_reclaimable:return copy_string_literal(u8"bootloader_reclaimable",iter); + case kernel_and_modules:return copy_string_literal(u8"kernel_and_modules",iter); + default:return copy_string_literal(u8"unknown",iter); + } + } +} + + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define_impl_for_stvl2_firmware_flags(char_type* iter,stvl2::stvl2_firmware_flags tg) noexcept +{ + using enum stvl2::stvl2_firmware_flags;\ + if constexpr(std::same_as) + { + switch(tg) + { + case bios:return copy_string_literal("bios",iter); + default:return copy_string_literal("unknown",iter); + } + } + else if constexpr(std::same_as) + { + switch(tg) + { + case bios:return copy_string_literal(L"bios",iter); + default:return copy_string_literal(L"unknown",iter); + } + } + else if constexpr(std::same_as) + { + switch(tg) + { + case bios:return copy_string_literal(u"bios",iter); + default:return copy_string_literal(u"unknown",iter); + } + } + else if constexpr(std::same_as) + { + switch(tg) + { + case bios:return copy_string_literal(U"bios",iter); + default:return copy_string_literal(U"unknown",iter); + } + } + else + { + switch(tg) + { + case bios:return copy_string_literal(u8"bios",iter); + default:return copy_string_literal(u8"unknown",iter); + } + } +} + +inline constexpr std::size_t constexpr_stvl2_u8strlen(char8_t const* strlen) noexcept +{ + if(std::is_constant_evaluated()) + { + std::size_t len{}; + for(;strlen[len];++len); + return len; + } + else + { + return std::strlen(reinterpret_cast(strlen)); + } +} + +template<::std::integral char_type> +inline constexpr char_type* deal_with_stvl2_cstr(char_type* iter,char8_t const* u8cstr) noexcept +{ + constexpr bool ebcdic{::fast_io::details::is_ebcdic}; + if constexpr(sizeof(char_type)==1&&!ebcdic) + return non_overlapped_copy_n(u8cstr,constexpr_stvl2_u8strlen(u8cstr),iter); + else + { + std::size_t sz{constexpr_stvl2_u8strlen(u8cstr)}; + return codecvt::general_code_cvt_full(u8cstr,u8cstr+sz,iter); + } +} + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define_impl_for_stvl2_struct(char_type* iter,stvl2::stvl2_struct const& st) noexcept +{ + if constexpr(std::same_as) + { + iter=copy_string_literal("bootloader_brand: ",iter); + iter=deal_with_stvl2_cstr(iter,st.bootloader_brand); + iter=copy_string_literal("\nbootloader_version: ",iter); + iter=deal_with_stvl2_cstr(iter,st.bootloader_version); + iter=copy_string_literal("\ntags_root: ",iter); + } + else if constexpr(std::same_as) + { + iter=copy_string_literal(L"bootloader_brand: ",iter); + iter=deal_with_stvl2_cstr(iter,st.bootloader_brand); + iter=copy_string_literal(L"\nbootloader_version: ",iter); + iter=deal_with_stvl2_cstr(iter,st.bootloader_version); + iter=copy_string_literal(L"\ntags_root: ",iter); + } + else if constexpr(std::same_as) + { + iter=copy_string_literal(u"bootloader_brand: ",iter); + iter=deal_with_stvl2_cstr(iter,st.bootloader_brand); + iter=copy_string_literal(u"\nbootloader_version: ",iter); + iter=deal_with_stvl2_cstr(iter,st.bootloader_version); + iter=copy_string_literal(u"\ntags_root: ",iter); + } + else if constexpr(std::same_as) + { + iter=copy_string_literal(U"bootloader_brand: ",iter); + iter=deal_with_stvl2_cstr(iter,st.bootloader_brand); + iter=copy_string_literal(U"\nbootloader_version: ",iter); + iter=deal_with_stvl2_cstr(iter,st.bootloader_version); + iter=copy_string_literal(U"\ntags_root: ",iter); + } + else + { + iter=copy_string_literal(u8"bootloader_brand: ",iter); + iter=deal_with_stvl2_cstr(iter,st.bootloader_brand); + iter=copy_string_literal(u8"\nbootloader_version: ",iter); + iter=deal_with_stvl2_cstr(iter,st.bootloader_version); + iter=copy_string_literal(u8"\ntags_root: ",iter); + } + return print_reserve_define(io_reserve_type,iter,st.tags_root); +} + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define_impl_for_stvl2_struct_tag_cmdline(char_type* iter,stvl2::stvl2_struct_tag_cmdline st) noexcept +{ + iter=print_reserve_define_impl_for_stvl2_tag(iter,st); + if constexpr(std::same_as) + iter=copy_string_literal("\ncmdline: ",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(L"\ncmdline: ",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(u"\ncmdline: ",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(U"\ncmdline: ",iter); + else + iter=copy_string_literal(u8"\ncmdline: ",iter); + return print_reserve_define(io_reserve_type,iter,st.cmdline); +} + +template<::std::integral char_type,typename T> +requires ( + std::same_as|| + std::same_as|| + std::same_as|| + std::same_as|| + std::same_as|| + std::same_as|| + std::same_as|| + std::same_as|| + std::same_as) +inline constexpr char_type* print_reserve_define_impl_for_stvl2_struct_tag_single(char_type* iter,T st) noexcept +{ + iter=print_reserve_define_impl_for_stvl2_tag(iter,st); + if constexpr(std::same_as) + { + if constexpr(std::same_as) + iter=copy_string_literal("\nmodule_count: ",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(L"\nmodule_count: ",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(u"\nmodule_count: ",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(U"\nmodule_count: ",iter); + else + iter=copy_string_literal(u8"\nmodule_count: ",iter); + return print_reserve_define(io_reserve_type,iter,st.module_count); + } + else if constexpr(std::same_as) + { + if constexpr(std::same_as) + iter=copy_string_literal("\nentries: ",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(L"\nentries: ",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(u"\nentries: ",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(U"\nentries: ",iter); + else + iter=copy_string_literal(u8"\nentries: ",iter); + return print_reserve_define(io_reserve_type,iter,st.entries); + } + else if constexpr(std::same_as) + { + if constexpr(std::same_as) + iter=copy_string_literal("\nrdsp: ",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(L"\nrdsp: ",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(u"\nrdsp: ",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(U"\nrdsp: ",iter); + else + iter=copy_string_literal(u8"\nrdsp: ",iter); + return print_reserve_define(io_reserve_type,iter,st.rdsp); + } + else if constexpr(std::same_as) + { + if constexpr(std::same_as) + iter=copy_string_literal("\nepoch: ",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(L"\nepoch: ",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(u"\nepoch: ",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(U"\nepoch: ",iter); + else + iter=copy_string_literal(u8"\nepoch: ",iter); + return print_reserve_define(io_reserve_type,iter,st.epoch); + } + else if constexpr(std::same_as) + { + if constexpr(std::same_as) + iter=copy_string_literal("\ntag: ",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(L"\ntag: ",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(u"\ntag: ",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(U"\ntag: ",iter); + else + iter=copy_string_literal(u8"\ntag: ",iter); + return print_reserve_define_impl_for_stvl2_firmware_flags(iter,st.tag); + } + else if constexpr(std::same_as) + { + if constexpr(std::same_as) + iter=copy_string_literal("\nserver_ip: ",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(L"\nserver_ip: ",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(u"\nserver_ip: ",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(U"\nserver_ip: ",iter); + else + iter=copy_string_literal(u8"\nserver_ip: ",iter); + return print_reserve_define(io_reserve_type,iter,st.server_ip); + } + else if constexpr(std::same_as|| + std::same_as|| + std::same_as) + { + if constexpr(std::same_as) + iter=copy_string_literal("\naddr: ",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(L"\naddr: ",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(u"\naddr: ",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(U"\naddr: ",iter); + else + iter=copy_string_literal(u8"\naddr: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.addr); + if constexpr(std::same_as) + { + if constexpr(std::same_as) + iter=copy_string_literal("\nsize: ",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(L"\nsize: ",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(u"\nsize: ",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(U"\nsize: ",iter); + else + iter=copy_string_literal(u8"\nsize: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.size); + } + return iter; + } +} + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define_impl_for_stvl2_struct_tag_framebuffer(char_type* iter,stvl2::stvl2_struct_tag_framebuffer tg) noexcept +{ + iter=print_reserve_define_impl_for_stvl2_tag(iter,tg); + if constexpr(std::same_as) + { + iter=copy_string_literal("\nframebuffer_addr: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.framebuffer_addr); + iter=copy_string_literal("\nframebuffer_width: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.framebuffer_width); + iter=copy_string_literal("\nframebuffer_height: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.framebuffer_height); + iter=copy_string_literal("\nframebuffer_pitch: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.framebuffer_pitch); + iter=copy_string_literal("\nframebuffer_bpp: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.framebuffer_bpp); + iter=copy_string_literal("\nmemory_model: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.memory_model); + iter=copy_string_literal("\nred_mask_size: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.red_mask_size); + iter=copy_string_literal("\nred_mask_shift: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.red_mask_shift); + iter=copy_string_literal("\ngreen_mask_size: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.green_mask_size); + iter=copy_string_literal("\ngreen_mask_shift: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.green_mask_shift); + iter=copy_string_literal("\nblue_mask_size: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.blue_mask_size); + iter=copy_string_literal("\nblue_mask_shift: ",iter); + } + else if constexpr(std::same_as) + { + iter=copy_string_literal(L"\nframebuffer_addr: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.framebuffer_addr); + iter=copy_string_literal(L"\nframebuffer_width: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.framebuffer_width); + iter=copy_string_literal(L"\nframebuffer_height: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.framebuffer_height); + iter=copy_string_literal(L"\nframebuffer_pitch: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.framebuffer_pitch); + iter=copy_string_literal(L"\nframebuffer_bpp: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.framebuffer_bpp); + iter=copy_string_literal(L"\nmemory_model: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.memory_model); + iter=copy_string_literal(L"\nred_mask_size: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.red_mask_size); + iter=copy_string_literal(L"\nred_mask_shift: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.red_mask_shift); + iter=copy_string_literal(L"\ngreen_mask_size: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.green_mask_size); + iter=copy_string_literal(L"\ngreen_mask_shift: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.green_mask_shift); + iter=copy_string_literal(L"\nblue_mask_size: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.blue_mask_size); + iter=copy_string_literal(L"\nblue_mask_shift: ",iter); + } + else if constexpr(std::same_as) + { + iter=copy_string_literal(u"\nframebuffer_addr: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.framebuffer_addr); + iter=copy_string_literal(u"\nframebuffer_width: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.framebuffer_width); + iter=copy_string_literal(u"\nframebuffer_height: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.framebuffer_height); + iter=copy_string_literal(u"\nframebuffer_pitch: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.framebuffer_pitch); + iter=copy_string_literal(u"\nframebuffer_bpp: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.framebuffer_bpp); + iter=copy_string_literal(u"\nmemory_model: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.memory_model); + iter=copy_string_literal(u"\nred_mask_size: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.red_mask_size); + iter=copy_string_literal(u"\nred_mask_shift: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.red_mask_shift); + iter=copy_string_literal(u"\ngreen_mask_size: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.green_mask_size); + iter=copy_string_literal(u"\ngreen_mask_shift: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.green_mask_shift); + iter=copy_string_literal(u"\nblue_mask_size: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.blue_mask_size); + iter=copy_string_literal(u"\nblue_mask_shift: ",iter); + } + else if constexpr(std::same_as) + { + iter=copy_string_literal(U"\nframebuffer_addr: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.framebuffer_addr); + iter=copy_string_literal(U"\nframebuffer_width: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.framebuffer_width); + iter=copy_string_literal(U"\nframebuffer_height: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.framebuffer_height); + iter=copy_string_literal(U"\nframebuffer_pitch: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.framebuffer_pitch); + iter=copy_string_literal(U"\nframebuffer_bpp: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.framebuffer_bpp); + iter=copy_string_literal(U"\nmemory_model: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.memory_model); + iter=copy_string_literal(U"\nred_mask_size: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.red_mask_size); + iter=copy_string_literal(U"\nred_mask_shift: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.red_mask_shift); + iter=copy_string_literal(U"\ngreen_mask_size: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.green_mask_size); + iter=copy_string_literal(U"\ngreen_mask_shift: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.green_mask_shift); + iter=copy_string_literal(U"\nblue_mask_size: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.blue_mask_size); + iter=copy_string_literal(U"\nblue_mask_shift: ",iter); + } + else + { + iter=copy_string_literal(u8"\nframebuffer_addr: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.framebuffer_addr); + iter=copy_string_literal(u8"\nframebuffer_width: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.framebuffer_width); + iter=copy_string_literal(u8"\nframebuffer_height: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.framebuffer_height); + iter=copy_string_literal(u8"\nframebuffer_pitch: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.framebuffer_pitch); + iter=copy_string_literal(u8"\nframebuffer_bpp: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.framebuffer_bpp); + iter=copy_string_literal(u8"\nmemory_model: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.memory_model); + iter=copy_string_literal(u8"\nred_mask_size: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.red_mask_size); + iter=copy_string_literal(u8"\nred_mask_shift: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.red_mask_shift); + iter=copy_string_literal(u8"\ngreen_mask_size: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.green_mask_size); + iter=copy_string_literal(u8"\ngreen_mask_shift: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.green_mask_shift); + iter=copy_string_literal(u8"\nblue_mask_size: ",iter); + iter=print_reserve_define(io_reserve_type,iter,tg.blue_mask_size); + iter=copy_string_literal(u8"\nblue_mask_shift: ",iter); + } + return print_reserve_define(io_reserve_type,iter,tg.blue_mask_shift); +} + + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define_impl_for_stvl2_module(char_type* iter,stvl2::stvl2_module st) noexcept +{ + if constexpr(std::same_as) + { + iter=copy_string_literal("module_begin: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.module_begin); + iter=copy_string_literal("\nmodule_end: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.module_end); + iter=copy_string_literal("\nmodule_string: ",iter); + } + else if constexpr(std::same_as) + { + iter=copy_string_literal(L"module_begin: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.module_begin); + iter=copy_string_literal(L"\nmodule_end: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.module_end); + iter=copy_string_literal(L"\nmodule_string: ",iter); + } + else if constexpr(std::same_as) + { + iter=copy_string_literal(u"module_begin: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.module_begin); + iter=copy_string_literal(u"\nmodule_end: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.module_end); + iter=copy_string_literal(u"\nmodule_string: ",iter); + } + else if constexpr(std::same_as) + { + iter=copy_string_literal(U"module_begin: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.module_begin); + iter=copy_string_literal(U"\nmodule_end: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.module_end); + iter=copy_string_literal(U"\nmodule_string: ",iter); + } + else + { + iter=copy_string_literal(u8"module_begin: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.module_begin); + iter=copy_string_literal(u8"\nmodule_end: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.module_end); + iter=copy_string_literal(u8"\nmodule_string: ",iter); + } + return deal_with_stvl2_cstr(iter,st.module_string); +} + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define_impl_for_stvl2_mmap_entry(char_type* iter,stvl2::stvl2_mmap_entry st) noexcept +{ + if constexpr(std::same_as) + { + iter=copy_string_literal("base: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.base); + iter=copy_string_literal("\nlength: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.length); + iter=copy_string_literal("\ntype: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.type); + iter=copy_string_literal("\nunused: ",iter); + } + else if constexpr(std::same_as) + { + iter=copy_string_literal(L"base: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.base); + iter=copy_string_literal(L"\nlength: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.length); + iter=copy_string_literal(L"\ntype: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.type); + iter=copy_string_literal(L"\nunused: ",iter); + } + else if constexpr(std::same_as) + { + iter=copy_string_literal(u"base: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.base); + iter=copy_string_literal(u"\nlength: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.length); + iter=copy_string_literal(u"\ntype: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.type); + iter=copy_string_literal(u"\nunused: ",iter); + } + else if constexpr(std::same_as) + { + iter=copy_string_literal(U"base: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.base); + iter=copy_string_literal(U"\nlength: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.length); + iter=copy_string_literal(U"\ntype: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.type); + iter=copy_string_literal(U"\nunused: ",iter); + } + else + { + iter=copy_string_literal(u8"base: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.base); + iter=copy_string_literal(u8"\nlength: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.length); + iter=copy_string_literal(u8"\ntype: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.type); + iter=copy_string_literal(u8"\nunused: ",iter); + } + return print_reserve_define(io_reserve_type,iter,st.unused); +} + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define_impl_for_stvl2_smp_info(char_type* iter,stvl2::stvl2_smp_info st) noexcept +{ + if constexpr(std::same_as) + { + iter=copy_string_literal("process_id: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.process_id); + iter=copy_string_literal("\nlapic_id: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.lapic_id); + iter=copy_string_literal("\ntarget_stack: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.target_stack); + iter=copy_string_literal("\ngoto_address: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.goto_address); + iter=copy_string_literal("\nextra_argument: ",iter); + } + else if constexpr(std::same_as) + { + iter=copy_string_literal(L"process_id: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.process_id); + iter=copy_string_literal(L"\nlapic_id: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.lapic_id); + iter=copy_string_literal(L"\ntarget_stack: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.target_stack); + iter=copy_string_literal(L"\ngoto_address: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.goto_address); + iter=copy_string_literal(L"\nextra_argument: ",iter); + } + else if constexpr(std::same_as) + { + iter=copy_string_literal(u"process_id: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.process_id); + iter=copy_string_literal(u"\nlapic_id: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.lapic_id); + iter=copy_string_literal(u"\ntarget_stack: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.target_stack); + iter=copy_string_literal(u"\ngoto_address: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.goto_address); + iter=copy_string_literal(u"\nextra_argument: ",iter); + } + else if constexpr(std::same_as) + { + iter=copy_string_literal(U"process_id: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.process_id); + iter=copy_string_literal(U"\nlapic_id: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.lapic_id); + iter=copy_string_literal(U"\ntarget_stack: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.target_stack); + iter=copy_string_literal(U"\ngoto_address: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.goto_address); + iter=copy_string_literal(U"\nextra_argument: ",iter); + } + else + { + iter=copy_string_literal(u8"process_id: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.process_id); + iter=copy_string_literal(u8"\nlapic_id: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.lapic_id); + iter=copy_string_literal(u8"\ntarget_stack: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.target_stack); + iter=copy_string_literal(u8"\ngoto_address: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.goto_address); + iter=copy_string_literal(u8"\nextra_argument: ",iter); + } + return print_reserve_define(io_reserve_type,iter,st.extra_argument); +} + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define_impl_for_stvl2_struct_tag_smp(char_type* iter,stvl2::stvl2_struct_tag_smp st) noexcept +{ + iter=print_reserve_define_impl_for_stvl2_tag(iter,st); + if constexpr(std::same_as) + { + iter=copy_string_literal("\nflags: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.flags); + iter=copy_string_literal("\nbsp_lapic_id: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.bsp_lapic_id); + iter=copy_string_literal("\nunused: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.unused); + iter=copy_string_literal("\ncpu_count: ",iter); + } + else if constexpr(std::same_as) + { + iter=copy_string_literal(L"\nflags: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.flags); + iter=copy_string_literal(L"\nbsp_lapic_id: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.bsp_lapic_id); + iter=copy_string_literal(L"\nunused: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.unused); + iter=copy_string_literal(L"\ncpu_count: ",iter); + } + else if constexpr(std::same_as) + { + iter=copy_string_literal(u"\nflags: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.flags); + iter=copy_string_literal(u"\nbsp_lapic_id: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.bsp_lapic_id); + iter=copy_string_literal(u"\nunused: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.unused); + iter=copy_string_literal(u"\ncpu_count: ",iter); + } + else if constexpr(std::same_as) + { + iter=copy_string_literal(U"\nflags: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.flags); + iter=copy_string_literal(U"\nbsp_lapic_id: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.bsp_lapic_id); + iter=copy_string_literal(U"\nunused: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.unused); + iter=copy_string_literal(U"\ncpu_count: ",iter); + } + else + { + iter=copy_string_literal(u8"\nflags: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.flags); + iter=copy_string_literal(u8"\nbsp_lapic_id: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.bsp_lapic_id); + iter=copy_string_literal(u8"\nunused: ",iter); + iter=print_reserve_define(io_reserve_type,iter,st.unused); + iter=copy_string_literal(u8"\ncpu_count: ",iter); + } + return print_reserve_define(io_reserve_type,iter,st.cpu_count); +} + +} + +template +requires (std::same_as||std::same_as|| + std::same_as||std::same_as) +inline constexpr std::size_t print_reserve_size(io_reserve_type_t) noexcept +{ + return 32; +} + +template +inline constexpr std::size_t print_reserve_size(io_reserve_type_t) noexcept +{ + constexpr std::size_t number_size + { + print_reserve_size(io_reserve_type)+ + print_reserve_size(io_reserve_type) + }; + if constexpr(std::same_as) + return number_size+details::string_literal_size("identifier: \nnext: "); + else if constexpr(std::same_as) + return number_size+details::string_literal_size(L"identifier: \nnext: "); + else + return number_size+details::string_literal_size(u8"identifier: \nnext: "); +} + +template +inline constexpr std::size_t print_reserve_size(io_reserve_type_t) noexcept +{ + constexpr std::size_t tag_size{print_reserve_size(io_reserve_type) + +print_reserve_size(io_reserve_type)*3 + +print_reserve_size(io_reserve_type)}; + if constexpr(std::same_as) + return tag_size+details::string_literal_size("entry_point: \nstack: \nflags: \ntags_root: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(L"entry_point: \nstack: \nflags: \ntags_root: "); + else + return tag_size+details::string_literal_size(u8"entry_point: \nstack: \nflags: \ntags_root: "); +} + +template +inline constexpr std::size_t print_reserve_size(io_reserve_type_t) noexcept +{ + constexpr std::size_t tag_size + { + print_reserve_size(io_reserve_type)+ + print_reserve_size(io_reserve_type)*3 + }; + if constexpr(std::same_as) + return tag_size+details::string_literal_size("\nframebuffer_width: \nframebuffer_height: \nframebuffer_bpp: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(L"\nframebuffer_width: \nframebuffer_height: \nframebuffer_bpp: "); + else + return tag_size+details::string_literal_size(u8"\nframebuffer_width: \nframebuffer_height: \nframebuffer_bpp: "); +} + +template +inline constexpr std::size_t print_reserve_size(io_reserve_type_t) noexcept +{ + constexpr std::size_t tag_size + { + print_reserve_size(io_reserve_type)+ + print_reserve_size(io_reserve_type) + }; + if constexpr(std::same_as) + return tag_size+details::string_literal_size("\nflags: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(L"\nflags: "); + else + return tag_size+details::string_literal_size(u8"\nflags: "); +} + +template +inline constexpr std::size_t print_reserve_size(io_reserve_type_t) noexcept +{ + constexpr std::size_t tag_size{ + print_reserve_size(io_reserve_type)+ + details::cal_stvl2_cstr_reserved_size(stvl2::stvl2_struct::bootloader_brand_size)*2 + }; + if constexpr(std::same_as) + return tag_size+details::string_literal_size("bootloader_brand: \nbootloader_version: \ntags_root: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(L"bootloader_brand: \nbootloader_version: \ntags_root: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(u"bootloader_brand: \nbootloader_version: \ntags_root: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(U"bootloader_brand: \nbootloader_version: \ntags_root: "); + else + return tag_size+details::string_literal_size(u8"bootloader_brand: \nbootloader_version: \ntags_root: "); +} + +template +inline constexpr std::size_t print_reserve_size(io_reserve_type_t) noexcept +{ + constexpr std::size_t tag_size{print_reserve_size(io_reserve_type) + +print_reserve_size(io_reserve_type)}; + if constexpr(std::same_as) + return tag_size+details::string_literal_size("\ncmdline: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(L"\ncmdline: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(u"\ncmdline: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(U"\ncmdline: "); + else + return tag_size+details::string_literal_size(u8"\ncmdline: "); +} + +template +requires (std::same_as|| + std::same_as|| + std::same_as|| + std::same_as|| + std::same_as|| + std::same_as|| + std::same_as|| + std::same_as|| + std::same_as) +inline constexpr std::size_t print_reserve_size(io_reserve_type_t) noexcept +{ + constexpr std::size_t tagbase_size{print_reserve_size(io_reserve_type)}; + if constexpr(std::same_as) + { + constexpr std::size_t tag_size{tagbase_size+print_reserve_size(io_reserve_type)}; + if constexpr(std::same_as) + return tag_size+details::string_literal_size("\nmodule_count: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(L"\nmodule_count: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(u"\nmodule_count: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(U"\nmodule_count: "); + else + return tag_size+details::string_literal_size(u8"\nmodule_count: "); + } + else if constexpr(std::same_as|| + std::same_as|| + std::same_as + ) + { + constexpr std::size_t tag_size{tagbase_size+print_reserve_size(io_reserve_type)}; + if constexpr(std::same_as) + { + if constexpr(std::same_as) + return tag_size+details::string_literal_size("\nentries: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(L"\nentries: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(u"\nentries: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(U"\nentries: "); + else + return tag_size+details::string_literal_size(u8"\nentries: "); + } + else if constexpr(std::same_as) + { + if constexpr(std::same_as) + return tag_size+details::string_literal_size("\nrdsp: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(L"\nrdsp: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(u"\nrdsp: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(U"\nrdsp: "); + else + return tag_size+details::string_literal_size(u8"\nrdsp: "); + } + else if constexpr(std::same_as) + { + if constexpr(std::same_as) + return tag_size+details::string_literal_size("\nepoch: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(L"\nepoch: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(u"\nepoch: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(U"\nepoch: "); + else + return tag_size+details::string_literal_size(u8"\nepoch: "); + } + } + else if constexpr(std::same_as) + { + constexpr std::size_t tag_size{tagbase_size+print_reserve_size(io_reserve_type)}; + if constexpr(std::same_as) + return tag_size+details::string_literal_size("\ntag: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(L"\ntag: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(u"\ntag: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(U"\ntag: "); + else + return tag_size+details::string_literal_size(u8"\ntag: "); + } + else if constexpr(std::same_as) + { + constexpr std::size_t tag_size{tagbase_size+print_reserve_size(io_reserve_type)}; + if constexpr(std::same_as) + return tag_size+details::string_literal_size("\nserver_ip: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(L"\nserver_ip: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(u"\nserver_ip: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(U"\nserver_ip: "); + else + return tag_size+details::string_literal_size(u8"\nserver_ip: "); + } + else if constexpr(std::same_as|| + std::same_as) + { + constexpr std::size_t tag_size{tagbase_size+print_reserve_size(io_reserve_type)}; + if constexpr(std::same_as) + return tag_size+details::string_literal_size("\naddr: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(L"\naddr: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(u"\naddr: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(U"\naddr: "); + else + return tag_size+details::string_literal_size(u8"\naddr: "); + } + else if constexpr(std::same_as) + { + constexpr std::size_t tag_size{tagbase_size+print_reserve_size(io_reserve_type)}; + if constexpr(std::same_as) + return tag_size+details::string_literal_size("\naddr: \nsize: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(L"\naddr: \nsize: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(u"\naddr: \nsize: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(U"\naddr: \nsize: "); + else + return tag_size+details::string_literal_size(u8"\naddr: \nsize: "); + } +} + +template +inline constexpr std::size_t print_reserve_size(io_reserve_type_t) noexcept +{ + constexpr std::size_t tag_size{ + print_reserve_size(io_reserve_type) + +print_reserve_size(io_reserve_type)*7+ + +print_reserve_size(io_reserve_type)*4 + +print_reserve_size(io_reserve_type)}; + if constexpr(std::same_as) + return tag_size+details::string_literal_size("\nframebuffer_addr: \nframebuffer_width: \nframebuffer_height: \nframebuffer_pitch: \nframebuffer_bpp: \nmemory_model: \nred_mask_size: \nred_mask_shift: \ngreen_mask_size: \ngreen_mask_shift: \nblue_mask_size: \nblue_mask_shift: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(L"\nframebuffer_addr: \nframebuffer_width: \nframebuffer_height: \nframebuffer_pitch: \nframebuffer_bpp: \nmemory_model: \nred_mask_size: \nred_mask_shift: \ngreen_mask_size: \ngreen_mask_shift: \nblue_mask_size: \nblue_mask_shift: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(u"\nframebuffer_addr: \nframebuffer_width: \nframebuffer_height: \nframebuffer_pitch: \nframebuffer_bpp: \nmemory_model: \nred_mask_size: \nred_mask_shift: \ngreen_mask_size: \ngreen_mask_shift: \nblue_mask_size: \nblue_mask_shift: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(U"\nframebuffer_addr: \nframebuffer_width: \nframebuffer_height: \nframebuffer_pitch: \nframebuffer_bpp: \nmemory_model: \nred_mask_size: \nred_mask_shift: \ngreen_mask_size: \ngreen_mask_shift: \nblue_mask_size: \nblue_mask_shift: "); + else + return tag_size+details::string_literal_size(u8"\nframebuffer_addr: \nframebuffer_width: \nframebuffer_height: \nframebuffer_pitch: \nframebuffer_bpp: \nmemory_model: \nred_mask_size: \nred_mask_shift: \ngreen_mask_size: \ngreen_mask_shift: \nblue_mask_size: \nblue_mask_shift: "); +} + +template +inline constexpr std::size_t print_reserve_size(io_reserve_type_t) noexcept +{ + constexpr std::size_t tag_size{ + details::cal_stvl2_cstr_reserved_size(stvl2::stvl2_module::module_string_size) + +print_reserve_size(io_reserve_type)*2}; + if constexpr(std::same_as) + return tag_size+details::string_literal_size("module_begin: \nmodule_end: \nmodule_string: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(L"module_begin: \nmodule_end: \nmodule_string: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(u"module_begin: \nmodule_end: \nmodule_string: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(U"module_begin: \nmodule_end: \nmodule_string: "); + else + return tag_size+details::string_literal_size(u8"module_begin: \nmodule_end: \nmodule_string: "); +} + +template +inline constexpr std::size_t print_reserve_size(io_reserve_type_t) noexcept +{ + constexpr std::size_t tag_size{ + print_reserve_size(io_reserve_type) + +print_reserve_size(io_reserve_type) + +print_reserve_size(io_reserve_type) + +print_reserve_size(io_reserve_type)}; + if constexpr(std::same_as) + return tag_size+details::string_literal_size("base: \nlength: \ntype: \nunused: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(L"base: \nlength: \ntype: \nunused: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(u"base: \nlength: \ntype: \nunused: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(U"base: \nlength: \ntype: \nunused: "); + else + return tag_size+details::string_literal_size(u8"base: \nlength: \ntype: \nunused: "); +} + +template +inline constexpr std::size_t print_reserve_size(io_reserve_type_t) noexcept +{ + constexpr std::size_t tag_size{ + print_reserve_size(io_reserve_type)*3 + +print_reserve_size(io_reserve_type)*2}; + if constexpr(std::same_as) + return tag_size+details::string_literal_size("process_id: \nlapic_id: \ntarget_stack: \ngoto_address: \nextra_argument: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(L"process_id: \nlapic_id: \ntarget_stack: \ngoto_address: \nextra_argument: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(u"process_id: \nlapic_id: \ntarget_stack: \ngoto_address: \nextra_argument: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(U"process_id: \nlapic_id: \ntarget_stack: \ngoto_address: \nextra_argument: "); + else + return tag_size+details::string_literal_size(u8"process_id: \nlapic_id: \ntarget_stack: \ngoto_address: \nextra_argument: "); +} + +template +inline constexpr std::size_t print_reserve_size(io_reserve_type_t) noexcept +{ + constexpr std::size_t tag_size{ + print_reserve_size(io_reserve_type) + +print_reserve_size(io_reserve_type)*2 + +print_reserve_size(io_reserve_type)*2}; + if constexpr(std::same_as) + return tag_size+details::string_literal_size("\nflags: \nbsp_lapic_id: \nunused: \ncpu_count: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(L"\nflags: \nbsp_lapic_id: \nunused: \ncpu_count: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(u"\nflags: \nbsp_lapic_id: \nunused: \ncpu_count: "); + else if constexpr(std::same_as) + return tag_size+details::string_literal_size(U"\nflags: \nbsp_lapic_id: \nunused: \ncpu_count: "); + else + return tag_size+details::string_literal_size(u8"\nflags: \nbsp_lapic_id: \nunused: \ncpu_count: "); +} + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define(io_reserve_type_t,char_type* iter,stvl2::stvl2_tag tg) noexcept +{ + return details::print_reserve_define_impl_for_stvl2_tag(iter,tg); +} + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define(io_reserve_type_t,char_type* iter,stvl2::stvl2_header_tag hd) noexcept +{ + return details::print_reserve_define_impl_for_stvl2_header_tag(iter,hd); +} + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define(io_reserve_type_t,char_type* iter,stvl2::stvl2_header hd) noexcept +{ + return details::print_reserve_define_impl_for_stvl2_header(iter,hd); +} + +static_assert(reserve_printable); + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define(io_reserve_type_t,char_type* iter,stvl2::stvl2_header_tag_framebuffer hd) noexcept +{ + return details::print_reserve_define_impl_for_stvl2_header_tag_framebuffer(iter,hd); +} +static_assert(reserve_printable); + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define(io_reserve_type_t,char_type* iter,stvl2::stvl2_header_tag_smp hd) noexcept +{ + return details::print_reserve_define_impl_for_stvl2_header_tag_smp(iter,hd); +} +static_assert(reserve_printable); + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define(io_reserve_type_t,char_type* iter,stvl2::stvl2_struct_tag hd) noexcept +{ + return details::print_reserve_define_impl_for_stvl2_struct_tag(iter,hd); +} +static_assert(reserve_printable); + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define(io_reserve_type_t,char_type* iter,stvl2::stvl2_struct const& hd) noexcept +{ + return details::print_reserve_define_impl_for_stvl2_struct(iter,hd); +} +static_assert(reserve_printable); + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define(io_reserve_type_t,char_type* iter,stvl2::stvl2_struct_tag_cmdline hd) noexcept +{ + return details::print_reserve_define_impl_for_stvl2_struct_tag_cmdline(iter,hd); +} +static_assert(reserve_printable); + +template<::std::integral char_type,typename T> +requires (std::same_as|| + std::same_as|| + std::same_as|| + std::same_as|| + std::same_as|| + std::same_as|| + std::same_as|| + std::same_as|| + std::same_as) +inline constexpr char_type* print_reserve_define(io_reserve_type_t,char_type* iter,T hd) noexcept +{ + return details::print_reserve_define_impl_for_stvl2_struct_tag_single(iter,hd); +} +static_assert(reserve_printable); + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define(io_reserve_type_t,char_type* iter,stvl2::stvl2_struct_tag_framebuffer hd) noexcept +{ + return details::print_reserve_define_impl_for_stvl2_struct_tag_framebuffer(iter,hd); +} +static_assert(reserve_printable); + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define(io_reserve_type_t,char_type* iter,stvl2::stvl2_mmap_type hd) noexcept +{ + return details::print_reserve_define_impl_for_stvl2_mmap_type(iter,hd); +} +static_assert(reserve_printable); + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define(io_reserve_type_t,char_type* iter,stvl2::stvl2_firmware_flags hd) noexcept +{ + return details::print_reserve_define_impl_for_stvl2_firmware_flags(iter,hd); +} +static_assert(reserve_printable); + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define(io_reserve_type_t,char_type* iter,stvl2::stvl2_module hd) noexcept +{ + return details::print_reserve_define_impl_for_stvl2_module(iter,hd); +} +static_assert(reserve_printable); +static_assert(reserve_printable); + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define(io_reserve_type_t,char_type* iter,stvl2::stvl2_mmap_entry hd) noexcept +{ + return details::print_reserve_define_impl_for_stvl2_mmap_entry(iter,hd); +} +static_assert(reserve_printable); + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define(io_reserve_type_t,Iter iter,stvl2::stvl2_smp_info hd) noexcept +{ + return details::print_reserve_define_impl_for_stvl2_smp_info(iter,hd); +} +static_assert(reserve_printable); + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define(io_reserve_type_t,char_type* iter,stvl2::stvl2_struct_tag_smp hd) noexcept +{ + return details::print_reserve_define_impl_for_stvl2_struct_tag_smp(iter,hd); +} +static_assert(reserve_printable); +} diff --git a/src/fast_io/include/fast_io_driver/timer.h b/src/fast_io/include/fast_io_driver/timer.h new file mode 100644 index 0000000..38182c3 --- /dev/null +++ b/src/fast_io/include/fast_io_driver/timer.h @@ -0,0 +1,25 @@ +#pragma once +#include + +namespace fast_io +{ + +struct timer +{ + std::u8string_view s; + unix_timestamp t0; + #if __has_cpp_attribute(__gnu__::__cold__) + [[__gnu__::__cold__]] + #endif + explicit timer(std::u8string_view strvw):s(strvw),t0(posix_clock_gettime(posix_clock_id::monotonic_raw)){} + timer(timer const &)=delete; + timer& operator=(timer const &)=delete; + #if __has_cpp_attribute(__gnu__::__cold__) + [[__gnu__::__cold__]] + #endif + ~timer() + { + ::fast_io::io::perr(fast_io::u8err(),s, u8":", posix_clock_gettime(posix_clock_id::monotonic_raw)-t0,u8"s\n"); + } +}; +} diff --git a/src/fast_io/include/fast_io_driver/tsc_timer.h b/src/fast_io/include/fast_io_driver/tsc_timer.h new file mode 100644 index 0000000..db27c01 --- /dev/null +++ b/src/fast_io/include/fast_io_driver/tsc_timer.h @@ -0,0 +1,36 @@ +#pragma once +#include +namespace fast_io +{ + +inline std::uint_least64_t current_tsc() noexcept +{ +#if defined(_MSC_VER)&&!defined(__clang__) + return __rdtsc(); +#elif __has_builtin(__builtin_ia32_rdtsc) + return __builtin_ia32_rdtsc(); +#else + return 0; +#endif +} + +struct tsc_timer +{ + std::u8string_view s; + std::uint_least64_t t0; + #if __has_cpp_attribute(__gnu__::__cold__) + [[__gnu__::__cold__]] + #endif + explicit tsc_timer(std::u8string_view strvw):s(strvw),t0(current_tsc()){} + tsc_timer(tsc_timer const &)=delete; + tsc_timer& operator=(tsc_timer const &)=delete; + #if __has_cpp_attribute(__gnu__::__cold__) + [[__gnu__::__cold__]] + #endif + ~tsc_timer() + { + ::fast_io::io::perr(fast_io::u8err(),s, u8":", current_tsc()-t0,u8" cycles\n"); + } +}; + +} diff --git a/src/fast_io/include/fast_io_driver/win32_internet.h b/src/fast_io/include/fast_io_driver/win32_internet.h new file mode 100644 index 0000000..edbb34e --- /dev/null +++ b/src/fast_io/include/fast_io_driver/win32_internet.h @@ -0,0 +1,178 @@ +#pragma once +#include +#include + +#undef min +#undef max +#undef interface + +namespace fast_io +{ + + +class win32_internet_handle +{ +public: + void* handle{}; + constexpr win32_internet_handle(){} + constexpr win32_internet_handle(void* value):handle(value){} + + constexpr win32_internet_handle(win32_internet_handle&& __restrict bmv) noexcept:handle(bmv.handle) + { + bmv.handle={}; + } + void close() + { + if(handle) + { + if(!InternetCloseHandle(handle)) + throw fast_io::win32_error(); + handle=nullptr; + } + } + win32_internet_handle& operator=(win32_internet_handle&& __restrict bmv) noexcept + { + if(handle) + InternetCloseHandle(handle); + handle=bmv.handle; + bmv.handle={}; + return *this; + } + win32_internet_handle(win32_internet_handle const&) = delete; + win32_internet_handle& operator=(win32_internet_handle const&) = delete; + ~win32_internet_handle() + { + if(handle) + InternetCloseHandle(handle); + } +}; + +template +requires requires(Args&& ...args) +{ + InternetOpenA(::std::forward(args)...); +} +inline win32_internet_handle win32_internet_open(Args&& ...args) +{ + auto ptr(InternetOpenA(::std::forward(args)...)); + if(ptr==nullptr) + throw fast_io::win32_error(); + return win32_internet_handle(ptr); +} + + +template +requires requires(win32_internet_handle& handle,Args&& ...args) +{ + InternetConnectA(handle.handle,::std::forward(args)...); +} +inline win32_internet_handle win32_internet_connect(win32_internet_handle& handle,Args&& ...args) +{ + auto ptr(InternetConnectA(handle.handle,::std::forward(args)...)); + if(ptr==nullptr) + throw fast_io::win32_error(); + return win32_internet_handle(ptr); +} + +template +requires requires(win32_internet_handle& handle,Args&& ...args) +{ + HttpOpenRequestA(handle.handle,::std::forward(args)...); +} +inline win32_internet_handle win32_http_open_request(win32_internet_handle& handle,Args&& ...args) +{ + auto ptr(HttpOpenRequestA(handle.handle,::std::forward(args)...)); + if(ptr==nullptr) + throw fast_io::win32_error(); + return win32_internet_handle(ptr); +} + +inline void win32_http_send_request(win32_internet_handle& handle) +{ + if(!HttpSendRequestA(handle.handle,nullptr,0,nullptr,0)) + throw fast_io::win32_error(); +} + +inline void win32_http_send_request(win32_internet_handle& handle,cstring_view sview) +{ + if(!HttpSendRequestA(handle.handle,sview.data(),sview.size(),nullptr,0)) + throw fast_io::win32_error(); +} +inline void win32_http_send_request(win32_internet_handle& handle,cstring_view sview,std::span extra) +{ + if(!HttpSendRequestA(handle.handle,sview.data(),sview.size(),extra.data(),extra.size())) + throw fast_io::win32_error(); +} + +template +class basic_win32_internet_io_observer +{ +public: + using char_type = ch_type; + using native_handle_type = void*; + native_handle_type handle{}; + constexpr operator bool() noexcept + { + return handle; + } + constexpr auto& native_handle() noexcept + { + return handle; + } + constexpr auto& native_handle() const noexcept + { + return handle; + } +}; + +template +class basic_win32_internet_https_client:public basic_win32_internet_io_observer +{ +public: + using char_type = ch_type; + using native_handle_type = basic_win32_internet_io_observer::native_handle_type; + win32_internet_handle session; + win32_internet_handle connection; + win32_internet_handle request; + constexpr basic_win32_internet_https_client()=default; + basic_win32_internet_https_client(cstring_view host,cstring_view method,cstring_view object_name,std::uint_least32_t port=443): + session(win32_internet_open("Microsoft Internet Explorer",INTERNET_OPEN_TYPE_PRECONFIG,nullptr,nullptr,0)), + connection(win32_internet_connect(session,host.data(),port,nullptr,nullptr,INTERNET_SERVICE_HTTP,0,0)), + request(win32_http_open_request(connection,method.data(),object_name.data(),HTTP_VERSION,nullptr,nullptr, + INTERNET_FLAG_RELOAD | INTERNET_FLAG_SECURE | INTERNET_FLAG_KEEP_CONNECTION | + INTERNET_FLAG_NO_AUTO_REDIRECT | INTERNET_FLAG_READ_PREFETCH | INTERNET_FLAG_NO_COOKIES | + INTERNET_FLAG_NO_AUTH | INTERNET_FLAG_RESTRICTED_ZONE | INTERNET_FLAG_CACHE_IF_NET_FAIL | + INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP | INTERNET_FLAG_IGNORE_CERT_CN_INVALID | INTERNET_FLAG_NO_UI, + 0)) + { + win32_http_send_request(request); + this->native_handle()=request.handle; + } +}; + +template +inline Iter read(basic_win32_internet_io_observer iob,Iter begin,Iter end) +{ + unsigned long readed{}; + if(!InternetReadFile(iob.handle,::std::to_address(begin),sizeof(*begin)*(end-begin),__builtin_addressof(readed))) + throw fast_io::win32_error(); + return begin+readed/sizeof(begin); +} + +template +inline Iter write(basic_win32_internet_io_observer iob,Iter begin,Iter end) +{ + unsigned long written{}; + if(!InternetWriteFile(iob.handle,::std::to_address(begin),sizeof(*begin)*(end-begin),__builtin_addressof(written))) + throw fast_io::win32_error(); + return begin+written/sizeof(begin); +} + +using win32_internet_io_observer = basic_win32_internet_io_observer; + +using ibuf_win32_internet_io_observer = fast_io::basic_ibuf; + +using win32_internet_https_client = basic_win32_internet_https_client; + +using ibuf_win32_internet_https_client = fast_io::basic_ibuf; +} diff --git a/src/fast_io/include/fast_io_driver/win32_memory.h b/src/fast_io/include/fast_io_driver/win32_memory.h new file mode 100644 index 0000000..20126e7 --- /dev/null +++ b/src/fast_io/include/fast_io_driver/win32_memory.h @@ -0,0 +1,500 @@ +#pragma once +#include"../fast_io_hosted.h" +namespace fast_io +{ + +//https://github.com/MicrosoftDocs/windows-driver-docs/issues/1736 + +enum class win32_memory_page_protect:std::uint_least32_t +{ +executed = 0x10, +executed_read = 0x20, +executed_readwrite = 0x40, +executed_writecopy = 0x80, +noaccess = 0x01, +readonly = 0x02, +readwrite = 0x04, +writecopy = 0x08, +graphics_noaccess = 0x0800, +graphics_readonly = 0x1000, +graphics_readwrite = 0x2000, +graphics_execute = 0x4000, +graphics_execute_read = 0x8000, +graphics_execute_readwrite = 0x10000, +graphics_coherent = 0x20000, +targets_invalid = 0x40000000, +targets_no_update = 0x40000000, +guard = 0x100, +nocache = 0x200, +writecombine = 0x400, +enclave_thread_control = 0x80000000, +revert_to_file_map = 0x80000000, +enclave_unvalidated = 0x20000000, +enclave_no_change = 0x20000000, +enclave_nodecommit = 0x10000000, +}; +#if 0 +template +constexpr void print_define(output& out,win32_memory_page_protect info) +{ + switch(info) + { + case win32_memory_page_protect::executed: + print_freestanding(out,"executed"); + break; + case win32_memory_page_protect::executed_read: + print_freestanding(out,"executed_read"); + break; + case win32_memory_page_protect::executed_readwrite: + print_freestanding(out,"executed_readwrite"); + break; + case win32_memory_page_protect::executed_writecopy: + print_freestanding(out,"executed_writecopy"); + break; + case win32_memory_page_protect::noaccess: + print_freestanding(out,"noaccess"); + break; + case win32_memory_page_protect::readonly: + print_freestanding(out,"readonly"); + break; + case win32_memory_page_protect::readwrite: + print_freestanding(out,"readwrite"); + break; + case win32_memory_page_protect::writecopy: + print_freestanding(out,"writecopy"); + break; + + case win32_memory_page_protect::graphics_noaccess: + print_freestanding(out,"graphics_noaccess"); + break; + case win32_memory_page_protect::graphics_readonly: + print_freestanding(out,"graphics_readonly"); + break; + case win32_memory_page_protect::graphics_readwrite: + print_freestanding(out,"graphics_readwrite"); + break; +// case win32_memory_page_protect::graphics_writecopy: +// print_freestanding(out,"graphics_writecopy"); +// break; + case win32_memory_page_protect::graphics_execute: + print_freestanding(out,"graphics_execute"); + break; + case win32_memory_page_protect::graphics_execute_read: + print_freestanding(out,"graphics_execute_read"); + break; + case win32_memory_page_protect::graphics_execute_readwrite: + print_freestanding(out,"graphics_execute_readwrite"); + break; + case win32_memory_page_protect::graphics_coherent: + print_freestanding(out,"graphics_coherent"); + break; + + case win32_memory_page_protect::targets_invalid: + print_freestanding(out,"targets_invalid/targets_no_update"); + break; + + case win32_memory_page_protect::guard: + print_freestanding(out,"guard"); + break; + case win32_memory_page_protect::nocache: + print_freestanding(out,"nocache"); + break; + + case win32_memory_page_protect::writecombine: + print_freestanding(out,"writecombine"); + break; + + case win32_memory_page_protect::enclave_thread_control: + print_freestanding(out,"enclave_thread_control/revert_to_file_map/enclave_unvalidated"); + break; + + case win32_memory_page_protect::enclave_no_change: + print_freestanding(out,"enclave_no_change/enclave_nodecommit"); + break; + default: + print_freestanding(out,"unknown(",static_cast(info),")"); + } +} +#endif + +constexpr win32_memory_page_protect operator&(win32_memory_page_protect x, win32_memory_page_protect y) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(static_cast(x) & static_cast(y)); +} + +constexpr win32_memory_page_protect operator|(win32_memory_page_protect x, win32_memory_page_protect y) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(static_cast(x) | static_cast(y)); +} + +constexpr win32_memory_page_protect operator^(win32_memory_page_protect x, win32_memory_page_protect y) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(static_cast(x) ^ static_cast(y)); +} + +constexpr win32_memory_page_protect operator~(win32_memory_page_protect x) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(~static_cast(x)); +} + +inline constexpr win32_memory_page_protect& operator&=(win32_memory_page_protect& x, win32_memory_page_protect y) noexcept{return x=x&y;} + +inline constexpr win32_memory_page_protect& operator|=(win32_memory_page_protect& x, win32_memory_page_protect y) noexcept{return x=x|y;} + +inline constexpr win32_memory_page_protect& operator^=(win32_memory_page_protect& x, win32_memory_page_protect y) noexcept{return x=x^y;} + +struct win32_memory_basic_information +{ + std::uintptr_t base_address{}; + std::uintptr_t allocation_base{}; + win32_memory_page_protect allocation_protect{}; + std::size_t region_size{}; + std::uint_least32_t state{}; + std::uint_least32_t protect{}; + std::uint_least32_t type{}; +}; +#if 0 +template +constexpr void print_define(output& out,win32_memory_basic_information const& info) +{ + print_freestanding(out,"win32_memory_basic_information:" + "\nbase address:",info.base_address, + "\nallocation base:",info.allocation_base, + "\nallocation protect:",info.allocation_protect, + "\nregion size:",info.region_size, + "\nstate:",info.state, + "\nprotect:",info.protect, + "\ntype:",info.type); +} +#endif +namespace win32 +{ +extern "C" void* +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +OpenProcess(std::uint_least32_t,int,std::uint_least32_t); +extern "C" int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +WriteProcessMemory(void*,void*,void const*,std::size_t,std::size_t*); +extern "C" int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +ReadProcessMemory(void*,void const*,void*,std::size_t,std::size_t*); +extern "C" int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +VirtualQueryEx(void*,void const*,win32_memory_basic_information*,std::size_t); +extern "C" int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +VirtualProtectEx(void*,void const*,std::size_t,std::uint_least32_t,std::uint_least32_t*); +extern "C" void* +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +FindWindowA(char const*,char const*); +extern "C" std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +GetWindowThreadProcessId(void*,std::uint_least32_t*); +} + +template +class basic_win32_memory_io_observer +{ +public: + using native_handle_type = void*; + using base_address_type = std::uintptr_t; + using char_type = ch_type; + native_handle_type handle{}; + base_address_type base_addr{}; + constexpr native_handle_type release() noexcept + { + auto temp{handle}; + handle=nullptr; + return temp; + } + constexpr operator bool() const noexcept + { + return handle; + } + constexpr auto& native_handle() const noexcept + { + return handle; + } + constexpr auto& native_handle() noexcept + { + return handle; + } + constexpr auto& base_address() const noexcept + { + return base_addr; + } + constexpr auto& base_address() noexcept + { + return base_addr; + } +}; + +template +class basic_win32_memory_io_handle: public basic_win32_memory_io_observer +{ +public: + using native_handle_type = basic_win32_memory_io_observer::native_handle_type; + using base_address_type = basic_win32_memory_io_observer::base_address_type; + using char_type = ch_type; + constexpr basic_win32_memory_io_handle()=default; + constexpr basic_win32_memory_io_handle(native_handle_type hd,base_address_type base):basic_win32_memory_io_observer(hd,base){} + basic_win32_memory_io_handle(basic_win32_memory_io_handle const& other) + { + auto const current_process(win32::GetCurrentProcess()); + if (!win32::DuplicateHandle(current_process, other.native_handle(), current_process, __builtin_addressof(this->native_handle()), 0, true, 2/*DUPLICATE_SAME_ACCESS*/)) + throw_win32_error(); + this->base_address()=other.base_address(); + } + basic_win32_memory_io_handle& operator=(basic_win32_memory_io_handle const& other) + { + auto const current_process(win32::GetCurrentProcess()); + void* new_handle{}; + if(!win32::DuplicateHandle(current_process,other.native_handle(),current_process,__builtin_addressof(new_handle), 0, true, 2/*DUPLICATE_SAME_ACCESS*/)) + throw_win32_error(); + if(this->native_handle())[[likely]] + fast_io::win32::CloseHandle(this->native_handle()); + this->native_handle()=new_handle; + this->base_address()=other.base_address(); + return *this; + } + basic_win32_memory_io_handle& operator=(basic_win32_memory_io_handle&& __restrict other) noexcept + { + if(this->native_handle())[[likely]] + fast_io::win32::CloseHandle(this->native_handle()); + this->native_handle()=other.native_handle(); + this->base_address()=other.base_address(); + other.native_handle()=nullptr; + other.base_address()={}; + return *this; + } + constexpr basic_win32_memory_io_handle(basic_win32_memory_io_handle&& __restrict other) noexcept:basic_win32_memory_io_observer(other.native_handle(),other.base_address()) + { + other.native_handle()=nullptr; + other.base_address()={}; + } +}; + +enum class win32_desired_access:std::uint_least32_t +{ +del = 0x00010000L, +read_control = 0x00020000L, +synchroize = 0x00100000L, +write_dac = 0x00040000L, +write_owner = 0x00080000L, +process_all_access = 0x1F0FFF, +process_create_process = 0x0080, +process_create_thread = 0x0002, +process_dup_handle = 0x0040, +process_query_information = 0x0400, +process_query_limited_information = 0x1000, +process_set_information = 0x0200, +process_set_quota = 0x0100, +process_suspend_resume = 0x0800, +process_terminate = 0x0001, +process_vm_operation = 0x0008, +process_vm_read = 0x0010, +process_vm_write = 0x0020, +}; + +constexpr win32_desired_access operator&(win32_desired_access x, win32_desired_access y) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(static_cast(x) & static_cast(y)); +} + +constexpr win32_desired_access operator|(win32_desired_access x, win32_desired_access y) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(static_cast(x) | static_cast(y)); +} + +constexpr win32_desired_access operator^(win32_desired_access x, win32_desired_access y) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(static_cast(x) ^ static_cast(y)); +} + +constexpr win32_desired_access operator~(win32_desired_access x) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(~static_cast(x)); +} + +inline constexpr win32_desired_access& operator&=(win32_desired_access& x, win32_desired_access y) noexcept{return x=x&y;} + +inline constexpr win32_desired_access& operator|=(win32_desired_access& x, win32_desired_access y) noexcept{return x=x|y;} + +inline constexpr win32_desired_access& operator^=(win32_desired_access& x, win32_desired_access y) noexcept{return x=x^y;} + +inline std::uint_least32_t get_process_id_from_window_name(cstring_view name) +{ + void* hwnd {win32::FindWindowA(nullptr,name.data())}; + if(hwnd==nullptr) + throw_win32_error(); + std::uint_least32_t process_id{}; + win32::GetWindowThreadProcessId(hwnd,__builtin_addressof(process_id)); + return process_id; +} + +template +class basic_win32_memory_file: public basic_win32_memory_io_handle +{ +public: + using native_handle_type = basic_win32_memory_io_observer::native_handle_type; + using base_address_type = basic_win32_memory_io_observer::base_address_type; + using char_type = ch_type; + constexpr basic_win32_memory_file()=default; + constexpr basic_win32_memory_file(native_handle_type hd,base_address_type base): + basic_win32_memory_io_handle(hd,base){} + basic_win32_memory_file(win32_desired_access dw_desired_access,bool inherit_handle,std::uint_least32_t process_id, + base_address_type base_addr={}): + basic_win32_memory_io_handle(win32::OpenProcess(static_cast(dw_desired_access),inherit_handle,process_id),base_addr) + { + if(this->native_handle()==nullptr) + throw_win32_error(); + } + void close() + { + if(this->native_handle())[[likely]] + { + if(!fast_io::win32::CloseHandle(this->native_handle()))[[unlikely]] + throw_win32_error(); + this->native_handle()=nullptr; + this->base_address()={}; + } + } + constexpr basic_win32_memory_file(basic_win32_memory_file const&)=default; + constexpr basic_win32_memory_file& operator=(basic_win32_memory_file const&)=default; + constexpr basic_win32_memory_file(basic_win32_memory_file&& __restrict) noexcept=default; + constexpr basic_win32_memory_file& operator=(basic_win32_memory_file&& __restrict) noexcept=default; + ~basic_win32_memory_file() + { + if(this->native_handle())[[likely]] + fast_io::win32::CloseHandle(this->native_handle()); + } +}; + +template +[[nodiscard]] inline Iter read(basic_win32_memory_io_observer& iob,Iter begin,Iter end) +{ + std::size_t readed{}; + if(!win32::ReadProcessMemory(iob.handle,bit_cast(iob.base_addr),::std::to_address(begin),(end-begin)*sizeof(*begin),__builtin_addressof(readed))) + throw_win32_error(); + iob.base_addr+=readed; + return begin+readed/sizeof(*begin); +} +template +[[nodiscard]] inline auto find_read_start(basic_win32_memory_io_observer iob) +{ + std::size_t readed{}; + for(std::byte ch{};!win32::ReadProcessMemory(iob.handle,bit_cast(iob.base_addr),__builtin_addressof(ch),1,__builtin_addressof(readed));++iob.base_addr); + return iob; +} +template +inline Iter write(basic_win32_memory_io_observer& iob,Iter begin,Iter end) +{ + std::size_t written{}; + if(!win32::WriteProcessMemory(iob.handle,bit_cast(iob.base_addr), + ::std::to_address(begin),(end-begin)*sizeof(*begin),__builtin_addressof(written))) + throw_win32_error(); + iob.base_addr+=written; + return begin+written/sizeof(*begin); +} +using win32_memory_io_observer = basic_win32_memory_io_observer; +using win32_memory_io_handle = basic_win32_memory_io_handle; +using win32_memory_file = basic_win32_memory_file; + +static_assert(input_stream); +static_assert(output_stream); + +template +inline win32_memory_basic_information win32_virtual_query(basic_win32_memory_io_observer iob) +{ + win32_memory_basic_information mem{}; + if(win32::VirtualQueryEx(iob.handle,bit_cast(iob.base_addr),__builtin_addressof(mem),sizeof(mem))!=sizeof(mem)) + throw_win32_error(); + return mem; +} + +template +inline win32_memory_page_protect win32_virtual_protect(basic_win32_memory_io_observer iob, + std::size_t size, + win32_memory_page_protect new_protect) +{ + std::uint_least32_t old_protect{}; + if(!win32::VirtualProtectEx(iob.handle,bit_cast(iob.base_addr), + size,static_cast(new_protect),__builtin_addressof(old_protect))) + throw_win32_error(); + return static_cast(old_protect); +} + +template +[[nodiscard]] inline auto find_usable_region(basic_win32_memory_io_observer wmf) +{ + for(;;) + { + auto mem_info{fast_io::win32_virtual_query(wmf)}; + if(static_cast(mem_info.allocation_protect)==0) + { + std::size_t rsize{mem_info.region_size}; + if(rsize==0)[[unlikely]] + break; + wmf.base_address()+=rsize; + } + else + break; + } + return wmf; +} + + +class win32_virtual_protect_guard +{ + void* process_handle{}; + std::uintptr_t address{}; + std::size_t region_size{}; + win32_memory_page_protect oprotect{}; +public: + template + win32_virtual_protect_guard(basic_win32_memory_io_observer iob, + std::size_t size, + win32_memory_page_protect new_protect): + process_handle(iob.native_handle()), + address(iob.base_addr), + region_size(size), + oprotect(win32_virtual_protect(iob,size,new_protect)) + { + } + constexpr auto old_protect() const noexcept + { + return oprotect; + } + win32_virtual_protect_guard(win32_virtual_protect_guard const&)=delete; + win32_virtual_protect_guard& operator=(win32_virtual_protect_guard const&)=delete; + ~win32_virtual_protect_guard() + { + std::uint_least32_t useless{}; + win32::VirtualProtectEx(process_handle,bit_cast(address), + region_size,static_cast(oprotect),__builtin_addressof(useless)); + } +}; + +} diff --git a/src/fast_io/include/fast_io_driver/zlib_driver.h b/src/fast_io/include/fast_io_driver/zlib_driver.h new file mode 100644 index 0000000..559ed7b --- /dev/null +++ b/src/fast_io/include/fast_io_driver/zlib_driver.h @@ -0,0 +1,9 @@ +#pragma once +#include +#include"zlib_driver/gzfile.h" + +namespace fast_io +{ + + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_driver/zlib_driver/gzfile.h b/src/fast_io/include/fast_io_driver/zlib_driver/gzfile.h new file mode 100644 index 0000000..65cc224 --- /dev/null +++ b/src/fast_io/include/fast_io_driver/zlib_driver/gzfile.h @@ -0,0 +1,225 @@ +#pragma once + +namespace fast_io::zlib +{ + +namespace details +{ + +struct gz_state_model{ + /* exposed contents for gzgetc() macro */ + struct gzFile_s x; /* "x" for exposed */ + /* x.have: number of bytes available at x.next */ + /* x.next: next output data to deliver or write */ + /* x.pos: current position in uncompressed data */ + /* used for both reading and writing */ + int mode; /* see gzip modes above */ + int fd; /* file descriptor */ + char *path; /* path or fd for error messages */ + unsigned size; /* buffer size, zero if not allocated yet */ + unsigned want; /* requested buffer size, default is GZBUFSIZE */ + unsigned char *in; /* input buffer */ + unsigned char *out; /* output buffer (double-sized when reading) */ + int direct; /* 0 if processing gzip, 1 if transparent */ + /* just for reading */ + int how; /* 0: get header, 1: copy, 2: decompress */ + z_off64_t start; /* where the gzip data started, for rewinding */ + int eof; /* true if end of input file reached */ + int past; /* true if read requested past end */ + /* just for writing */ + int level; /* compression level */ + int strategy; /* compression strategy */ + /* seek request */ + z_off64_t skip; /* amount to skip (already rewound if backwards) */ + int seek; /* true if seek request pending */ + /* error information */ + int err; /* error code */ + char *msg; /* error message */ + /* zlib inflate or deflate stream */ + z_stream strm; /* stream structure in-place (not a pointer) */ +}; + +inline int hack_gz_file_fd(gzFile gzfile) +{ + int fdn; + ::fast_io::details::my_memcpy(__builtin_addressof(fdn),reinterpret_cast(gzfile)+offsetof(gz_state_model,fd),sizeof(int)); + return fdn; +} +/* +inline char* hack_gz_file_in(gzFile gzfile) +{ + char* ptr; + ::fast_io::details::my_memcpy(__builtin_addressof(ptr),reinterpret_cast(gzfile)+offsetof(gz_state_model,in),sizeof(char *)); + return ptr; +} +inline char* hack_gz_file_out(gzFile gzfile) +{ + char* ptr; + ::fast_io::details::my_memcpy(__builtin_addressof(ptr),reinterpret_cast(gzfile)+offsetof(gz_state_model,out),sizeof(char *)); + return ptr; +} +*/ +} + +template +class basic_gz_io_observer +{ +public: + using native_handle_type = gzFile; + using char_type = ch_type; + native_handle_type gzfile{}; + constexpr auto& native_handle() noexcept + { + return gzfile; + } + constexpr auto& native_handle() const noexcept + { + return gzfile; + } + explicit operator bool() const noexcept + { + return gzfile; + } + explicit operator basic_posix_io_observer() const noexcept + { + return {details::hack_gz_file_fd(gzfile)}; + } +#if defined(__WINNT__) || defined(_MSC_VER) + explicit operator basic_win32_io_observer() const + { + return static_cast>(static_cast>(*this)); + } +#endif +}; + +template +class basic_gz_file:public basic_gz_io_observer +{ +public: + using native_handle_type = gzFile; + using char_type = ch_type; + constexpr basic_gz_file()=default; + constexpr basic_gz_file(native_handle_type hd) noexcept:basic_gz_io_observer(hd){} + basic_gz_file(basic_gz_file const&)=delete; + basic_gz_file& operator=(basic_gz_file const&)=delete; + constexpr basic_gz_file(basic_gz_file&& __restrict bmv) noexcept:basic_gz_io_observer(bmv.native_handle()) + { + bmv.native_handle()=nullptr; + } + basic_gz_file& operator=(basic_gz_file&& __restrict bmv) noexcept + { + if(this->native_handle())[[likely]] + gzclose(this->native_handle()); + this->native_handle()=bmv.native_handle(); + bmv.native_handle()=nullptr; + return *this; + } + ~basic_gz_file() + { + if(this->native_handle())[[likely]] + gzclose(this->native_handle()); + } + + + basic_gz_file(native_interface_t,int fd,char const* mode): + basic_gz_io_observer(gzdopen(pfd,mode.data())) + { + if(this->native_handle()==nullptr) + throw_posix_error(); + posix_handle.release(); + } + + basic_gz_file(basic_posix_file&& posix_handle,open_mode om): + basic_gz_file(native_interface,posix_handle.fd,to_native_c_mode(om)) + { + posix_handle.release(); + } + +#ifdef _WIN32 +//windows specific. open posix file from win32 io handle + template + basic_gz_file(basic_win32_family_file&& win32_handle,open_mode om): + basic_gz_file(basic_posix_file(::std::move(win32_handle),om),to_native_c_mode(om)) + { + } + template + basic_gz_file(basic_nt_family_file&& nt_handle,open_mode om): + basic_gz_file(basic_posix_file(::std::move(nt_handle),om),to_native_c_mode(om)) + { + } +#endif + + inline void reset(native_handle_type hd) noexcept + { + if(this->native_handle())[[likely]] + gzclose(this->native_handle()); + this->native_handle()=hd; + } + + basic_gz_file(cstring_view file,open_mode om,perms pm=static_cast(436)): + basic_gz_file(basic_posix_file(file,om,pm),om) + {} + basic_gz_file(native_at_entry nate,cstring_view file,open_mode om,perms pm=static_cast(436)): + basic_gz_file(basic_posix_file(nate,file,om,pm),om) + {} +}; + +using gz_io_observer = basic_gz_io_observer; +using gz_file = basic_gz_file; + + +template +requires (std::same_as>||std::same_as) +inline Iter read(basic_gz_io_observer giob,Iter b,Iter e) +{ + if constexpr(std::same_as>) + { + std::size_t to_read((e-b)*sizeof(*b)); + if constexpr(sizeof(unsigned)(std::numeric_limits::max())::max(); + int readed{gzread(giob.gzfile,::std::to_address(b),static_cast(to_read))}; + if(readed==-1) + throw_posix_error(); + return b+static_cast(readed)/sizeof(*b); + } + else + return b+(read(giob,reinterpret_cast(::std::to_address(b)),reinterpret_cast(::std::to_address(e)))-reinterpret_cast(::std::to_address(b)))/sizeof(*b); +} + +template +requires (std::same_as>||std::same_as) +inline Iter write(basic_gz_io_observer giob,Iter b,Iter e) +{ + if constexpr(std::same_as>) + { + std::size_t to_write((e-b)*sizeof(*b)); + if constexpr(sizeof(unsigned)(std::numeric_limits::max())::max(); + int written{gzwrite(giob.gzfile,::std::to_address(b),static_cast(to_write))}; + if(written<0) + throw_posix_error(); + return b+static_cast(written)/sizeof(*b); + } + else + return b+(write(giob,reinterpret_cast(::std::to_address(b)),reinterpret_cast(::std::to_address(e)))-reinterpret_cast(::std::to_address(b)))/sizeof(*b); +} + +template +inline void flush(basic_gz_io_observer giob) +{ + if(gzflush(giob.gzfile)) + throw_posix_error(); +} + +static_assert(input_stream); +static_assert(output_stream); + + +template +using basic_ibuf_gz_file=basic_ibuf>; + +using ibuf_gz_file = basic_ibuf_gz_file; + +} diff --git a/src/fast_io/include/fast_io_dsal/impl/common.h b/src/fast_io/include/fast_io_dsal/impl/common.h new file mode 100644 index 0000000..2a14c55 --- /dev/null +++ b/src/fast_io/include/fast_io_dsal/impl/common.h @@ -0,0 +1,131 @@ +#pragma once + +namespace fast_io +{ + +namespace containers +{ + +inline constexpr ::std::size_t npos{::std::numeric_limits<::std::size_t>::max()}; + +} + +using ::fast_io::containers::npos; + +} // namespace fast_io + +namespace fast_io::containers::details +{ +template +concept is_trivally_stored_allocator_handle = ::fast_io::freestanding::is_zero_default_constructible_v && + ::fast_io::freestanding::is_trivially_relocatable_v && + ::std::is_trivially_copy_constructible_v && + sizeof(handle) <= sizeof(handle *) && alignof(handle) <= alignof(handle *); + +template +struct handle_holder +{ + using handle_type = handle; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) + [[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) + [[no_unique_address]] +#endif +#endif + ::std::conditional_t, handle, handle *> value; + constexpr handle_holder() noexcept + : value{} + {} + constexpr handle_holder(decltype(nullptr)) noexcept = delete; + constexpr handle_holder(handle small_object) noexcept + requires(is_trivally_stored_allocator_handle) + : value(small_object) + {} + constexpr handle_holder(handle *small_object) noexcept + requires is_trivally_stored_allocator_handle + : value(*small_object) + {} + template + constexpr handle_holder(A &&large_object) noexcept + requires(::std::same_as<::std::remove_cvref_t, handle> && !is_trivally_stored_allocator_handle) + { + value = ::fast_io::typed_generic_allocator_adapter::handle_allocate(large_object, 1); + ::std::construct_at(value, ::std::forward(large_object)); + } + constexpr handle_holder(handle *large_object) noexcept + requires(!is_trivally_stored_allocator_handle) + : value(large_object) + {} + constexpr handle_holder(handle_holder const &) noexcept = default; + constexpr handle_holder &operator=(handle_holder const &) noexcept = default; + constexpr handle_holder(handle_holder &&) noexcept = default; + constexpr handle_holder &operator=(handle_holder &&) noexcept = default; +#if __has_cpp_attribute(__gnu__::__always_inline__) + [[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) + [[msvc::forceinline]] +#endif + inline constexpr handle const &get() const noexcept + { + if constexpr (is_trivally_stored_allocator_handle) + { + return value; + } + else + { + return *value; + } + } +#if __has_cpp_attribute(__gnu__::__always_inline__) + [[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) + [[msvc::forceinline]] +#endif + inline constexpr handle &get() noexcept + { + if constexpr (is_trivally_stored_allocator_handle) + { + return value; + } + else + { + return *value; + } + } +}; +template <::std::equality_comparable handle> +inline constexpr auto operator==(handle_holder left, handle_holder right) noexcept +{ + return left.get() == right.get(); +} + +template <::std::size_t size, bool trivial> +inline constexpr ::std::size_t cal_grow_twice_size(::std::size_t cap) noexcept +{ + constexpr ::std::size_t mx_value2{::std::numeric_limits<::std::size_t>::max() / size}; + constexpr ::std::size_t mx_value{trivial ? mx_value2 * size : mx_value2}; + constexpr ::std::size_t mx_half_value{mx_value >> 1u}; + if (cap == mx_value) + { + ::fast_io::fast_terminate(); + } + else if (cap > mx_half_value) + { + if constexpr (trivial) + { + return mx_value; + } + else + { + return 1; + } + } + else if (cap == 0) + { + return size; + } + return static_cast<::std::size_t>(cap << 1); +} + +} // namespace fast_io::containers::details diff --git a/src/fast_io/include/fast_io_dsal/impl/freestanding.h b/src/fast_io/include/fast_io_dsal/impl/freestanding.h new file mode 100644 index 0000000..4ae27f2 --- /dev/null +++ b/src/fast_io/include/fast_io_dsal/impl/freestanding.h @@ -0,0 +1,173 @@ +#pragma once + +namespace fast_io::freestanding +{ + +/* +uninitialized_relocate requires two range are not overlapped. +*/ +template <::std::input_or_output_iterator Iter1, ::std::input_or_output_iterator Iter2> +constexpr Iter2 uninitialized_relocate(Iter1 first, Iter1 last, Iter2 dest) noexcept +{ + if constexpr (::std::contiguous_iterator && !::std::is_pointer_v && ::std::contiguous_iterator && !::std::is_pointer_v) + { + return uninitialized_relocate(::std::to_address(first), ::std::to_address(last), + ::std::to_address(dest)) - + ::std::to_address(dest) + dest; + } + else if constexpr (::std::contiguous_iterator && !::std::is_pointer_v) + { + return uninitialized_relocate(::std::to_address(first), ::std::to_address(last), + dest); + } + else if constexpr (::std::contiguous_iterator && !::std::is_pointer_v) + { + return uninitialized_relocate(first, last, ::std::to_address(dest)) - + ::std::to_address(dest) + dest; + } + else + { + using iter1valuetype = ::std::iter_value_t; + using iter2valuetype = ::std::iter_value_t; + if constexpr (::std::is_pointer_v && ::std::is_pointer_v && + (::fast_io::freestanding::is_trivially_relocatable_v && + ::fast_io::freestanding::is_trivially_relocatable_v && + (::std::same_as || + ((::std::integral || ::std::same_as) && + (::std::integral || ::std::same_as) && + sizeof(iter1valuetype) == sizeof(iter2valuetype))))) + { +#if __cpp_if_consteval >= 202106L + if !consteval +#else + if (!__builtin_is_constant_evaluated()) +#endif + { + return reinterpret_cast(::fast_io::freestanding::bytes_copy(reinterpret_cast<::std::byte const *>(first), reinterpret_cast<::std::byte const *>(last), reinterpret_cast<::std::byte *>(dest))); + } + } + // we do not allow move constructor to throw EH. + while (first != last) + { + ::std::construct_at(dest, ::std::move(*first)); + if constexpr(!::std::is_trivially_destructible_v) + { + if constexpr(::std::is_pointer_v) + { + ::std::destroy_at(first); + } + else + { + ::std::destroy_at(__builtin_addressof(*first)); + } + } + ++first; + ++dest; + } + return dest; + } +} + +template <::std::input_or_output_iterator Iter1, ::std::input_or_output_iterator Iter2> +constexpr Iter2 uninitialized_move(Iter1 first, Iter1 last, Iter2 dest) noexcept +{ + if constexpr (::std::contiguous_iterator && !::std::is_pointer_v && ::std::contiguous_iterator && !::std::is_pointer_v) + { + return uninitialized_move(::std::to_address(first), ::std::to_address(last), + ::std::to_address(dest)) - + ::std::to_address(dest) + dest; + } + else if constexpr (::std::contiguous_iterator && !::std::is_pointer_v) + { + return uninitialized_move(::std::to_address(first), ::std::to_address(last), + dest); + } + else if constexpr (::std::contiguous_iterator && !::std::is_pointer_v) + { + return uninitialized_move(first, last, ::std::to_address(dest)) - + ::std::to_address(dest) + dest; + } + else + { + using iter1valuetype = ::std::iter_value_t; + using iter2valuetype = ::std::iter_value_t; + if constexpr (::std::is_pointer_v && ::std::is_pointer_v && + (::fast_io::freestanding::is_trivially_relocatable_v && + ::fast_io::freestanding::is_trivially_relocatable_v && + (::std::same_as || + ((::std::integral || ::std::same_as) && + (::std::integral || ::std::same_as) && + sizeof(iter1valuetype) == sizeof(iter2valuetype))))) + { +#if __cpp_if_consteval >= 202106L + if !consteval +#else + if (!__builtin_is_constant_evaluated()) +#endif + { + return reinterpret_cast(::fast_io::freestanding::bytes_copy(reinterpret_cast<::std::byte const *>(first), reinterpret_cast<::std::byte const *>(last), reinterpret_cast<::std::byte *>(dest))); + } + } + // we do not allow move constructor to throw EH. + while (first != last) + { + ::std::construct_at(dest, ::std::move(*first)); + ++first; + ++dest; + } + return dest; + } +} + +template <::std::bidirectional_iterator Iter1, ::std::bidirectional_iterator Iter2> +constexpr Iter2 uninitialized_move_backward(Iter1 first, Iter1 last, Iter2 d_last) noexcept +{ + // we do not allow move constructor to throw EH. + if constexpr (::std::contiguous_iterator && !::std::is_pointer_v && ::std::contiguous_iterator && !::std::is_pointer_v) + { + return uninitialized_move_backward(::std::to_address(first), ::std::to_address(last), + ::std::to_address(d_last)) - + ::std::to_address(d_last) + d_last; + } + else if constexpr (::std::contiguous_iterator && !::std::is_pointer_v) + { + return uninitialized_move_backward(::std::to_address(first), ::std::to_address(last), + d_last); + } + else if constexpr (::std::contiguous_iterator && !::std::is_pointer_v) + { + return uninitialized_move_backward(first, last, ::std::to_address(d_last)) - + ::std::to_address(d_last) + d_last; + } + else + { + using iter1valuetype = ::std::iter_value_t; + using iter2valuetype = ::std::iter_value_t; + if constexpr (::std::is_pointer_v && ::std::is_pointer_v && + (::fast_io::freestanding::is_trivially_relocatable_v && + ::fast_io::freestanding::is_trivially_relocatable_v && + (::std::same_as || + ((::std::integral || ::std::same_as) && + (::std::integral || ::std::same_as) && + sizeof(iter1valuetype) == sizeof(iter2valuetype))))) + { +#ifdef __cpp_if_consteval + if !consteval +#else + if (!__builtin_is_constant_evaluated()) +#endif + { + auto d_start{d_last - (last-first)}; + ::fast_io::freestanding::bytes_copy(reinterpret_cast<::std::byte const *>(first), reinterpret_cast<::std::byte const *>(last), reinterpret_cast<::std::byte *>(d_start)); + return d_start; + } + } + while (first != last) + { + ::std::construct_at(--d_last, std::move(*(--last))); + } + return d_last; + } +} + +} // namespace fast_io::freestanding diff --git a/src/fast_io/include/fast_io_dsal/impl/vector.h b/src/fast_io/include/fast_io_dsal/impl/vector.h new file mode 100644 index 0000000..959aafe --- /dev/null +++ b/src/fast_io/include/fast_io_dsal/impl/vector.h @@ -0,0 +1,1099 @@ +#pragma once +namespace fast_io +{ + +namespace containers +{ + +namespace details +{ + +struct +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + vector_model +{ + ::std::byte *begin_ptr; + ::std::byte *curr_ptr; + ::std::byte *end_ptr; +}; + +namespace vector +{ + +namespace detemplate +{ + +template +inline void *grow_to_byte_size_iter_impl(vector_model &imp, void *iter, ::std::size_t newcap, ::std::size_t gap, ::std::size_t size, ::std::size_t alignment) noexcept +{ + ::std::byte *old_begin_ptr{imp.begin_ptr}; + ::std::byte *old_curr_ptr{imp.curr_ptr}; + ::std::size_t const old_size{static_cast<::std::size_t>(old_curr_ptr - old_begin_ptr)}; + ::std::size_t const old_capacity{static_cast<::std::size_t>(imp.end_ptr - old_begin_ptr)}; + + auto newres = allocator::allocate_aligned_at_least(alignment, newcap); + auto begin_ptr = reinterpret_cast<::std::byte *>(newres.ptr); + auto newiter = ::fast_io::freestanding::nonoverlapped_bytes_copy(reinterpret_cast<::std::byte const *>(old_begin_ptr), reinterpret_cast<::std::byte const *>(iter), + reinterpret_cast<::std::byte *>(begin_ptr)); + ::fast_io::freestanding::nonoverlapped_bytes_copy(reinterpret_cast<::std::byte const *>(iter), reinterpret_cast<::std::byte const *>(old_curr_ptr), + reinterpret_cast<::std::byte *>(newiter + gap)); + allocator::deallocate_aligned_n(old_begin_ptr, alignment, old_capacity); + imp.begin_ptr = begin_ptr; + imp.curr_ptr = begin_ptr + old_size; + imp.end_ptr = begin_ptr + (newres.count/size*size); + return newiter; +} + +template +inline void *grow_to_size_iter_impl(vector_model &imp, void *iter, ::std::size_t newcap, ::std::size_t size, ::std::size_t alignment) noexcept +{ +#if defined(_MSC_VER) && !defined(__clang__) + ::std::size_t mx{SIZE_MAX / size}; + if (newcap > mx) [[unlikely]] + { + ::fast_io::fast_terminate(); + } + newcap *= size; +#else + if (__builtin_mul_overflow(size, newcap, __builtin_addressof(newcap))) [[unlikely]] + { + __builtin_trap(); + } +#endif + return grow_to_byte_size_iter_impl(imp, iter, newcap, size, size, alignment); +} + +template +inline void *grow_to_size_impl(vector_model &imp, ::std::size_t newcap, ::std::size_t size, ::std::size_t alignment) noexcept +{ + return grow_to_size_iter_impl(imp, imp.curr_ptr, newcap, size, alignment); +} + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline constexpr void *grow_twice_iter_impl(vector_model &imp, void *iter, ::std::size_t size, ::std::size_t alignment) noexcept +{ + auto begin_ptr{imp.begin_ptr}; + auto end_ptr{imp.end_ptr}; + ::std::size_t toallocate{size}; + ::std::size_t diff{static_cast<::std::size_t>(end_ptr - begin_ptr)}; + if (diff) [[likely]] + { +#if defined(_MSC_VER) && !defined(__clang__) + constexpr ::std::size_t mx{SIZE_MAX / 2}; + if (diff > mx) [[unlikely]] + { + ::fast_io::fast_terminate(); + } + toallocate = (diff << 1u); +#else + if (__builtin_mul_overflow(diff, 2u, __builtin_addressof(toallocate))) [[unlikely]] + { + __builtin_trap(); + } +#endif + } + return grow_to_byte_size_iter_impl(imp, iter, toallocate, size, size, alignment); +} + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline constexpr void *grow_twice_impl(vector_model &imp, ::std::size_t size, ::std::size_t alignment) noexcept +{ + return grow_twice_iter_impl(imp, imp.curr_ptr, size, alignment); +} + +template +inline constexpr void *move_backward_impl(vector_model &imp, void *iter, ::std::size_t size, ::std::size_t alignment) noexcept +{ + if (imp.curr_ptr == imp.end_ptr) [[unlikely]] + { + return grow_twice_iter_impl(imp, iter, size, alignment); + } + auto currptr{imp.curr_ptr}; + auto currptrp1{currptr + size}; + ::fast_io::freestanding::uninitialized_move_backward(reinterpret_cast<::std::byte *>(iter), currptr, currptrp1); + return iter; +} + +} // namespace detemplate + +template +inline constexpr void *grow_to_size_iter_impl(vector_model &imp, void *iter, ::std::size_t newcap) noexcept +{ + if constexpr (alignment < allocator::default_alignment) + { + return ::fast_io::containers::details::vector::grow_to_size_iter_impl(imp, iter, newcap); + } + else + { + return ::fast_io::containers::details::vector::detemplate::grow_to_size_iter_impl(imp, iter, newcap, size, alignment); + } +} + +template +inline constexpr void *grow_to_size_impl(vector_model &imp, ::std::size_t newcap) noexcept +{ + if constexpr (alignment < allocator::default_alignment) + { + return ::fast_io::containers::details::vector::grow_to_size_impl(imp, newcap); + } + else + { + return ::fast_io::containers::details::vector::detemplate::grow_to_size_impl(imp, newcap, size, alignment); + } +} + +template +inline constexpr void *grow_twice_impl(vector_model &imp) noexcept +{ + if constexpr (alignment < allocator::default_alignment) + { + return ::fast_io::containers::details::vector::grow_twice_impl(imp); + } + else + { + return ::fast_io::containers::details::vector::detemplate::grow_twice_impl(imp, size, alignment); + } +} + +template +inline constexpr void *grow_twice_iter_impl(vector_model &imp, void *iter) noexcept +{ + if constexpr (alignment < allocator::default_alignment) + { + return ::fast_io::containers::details::vector::grow_twice_iter_impl(imp, iter); + } + else + { + return ::fast_io::containers::details::vector::detemplate::grow_twice_iter_impl(imp, iter, size, alignment); + } +} + +template +inline constexpr void *move_backward_impl(vector_model &imp, void *iter) noexcept +{ + if constexpr (alignment < allocator::default_alignment) + { + return ::fast_io::containers::details::vector::move_backward_impl(imp, iter); + } + else + { + return ::fast_io::containers::details::vector::detemplate::move_backward_impl(imp, iter, size, alignment); + } +} + +} // namespace vector + +template +struct vector_internal +{ + T *begin_ptr{}; + T *curr_ptr{}; + T *end_ptr{}; +}; + +} // namespace details + +template <::std::movable T, typename allocator> +class vector +{ +public: + using allocator_type = allocator; + using value_type = T; + +private: + using typed_allocator_type = typed_generic_allocator_adapter; + +public: + using pointer = value_type *; + using const_pointer = value_type const *; + + using reference = value_type &; + using const_reference = value_type const &; + + using iterator = value_type *; + using const_iterator = value_type const *; + + using reverse_iterator = ::std::reverse_iterator; + using const_reverse_iterator = ::std::reverse_iterator; + + using size_type = ::std::size_t; + using difference_type = ::std::ptrdiff_t; + ::fast_io::containers::details::vector_internal imp; + + explicit constexpr vector() noexcept = default; + +private: + constexpr void destroy() noexcept + { + clear(); + if constexpr (!typed_allocator_type::has_deallocate) + { + typed_allocator_type::deallocate(imp.begin_ptr); + } + else + { + typed_allocator_type::deallocate_n(imp.begin_ptr, + static_cast<::std::size_t>(imp.end_ptr - imp.begin_ptr)); + } + } + struct run_destroy + { + vector *thisvec{}; + constexpr run_destroy() noexcept = default; + explicit constexpr run_destroy(vector *p) noexcept + : thisvec(p) + {} + run_destroy(run_destroy const &) = delete; + run_destroy &operator=(run_destroy const &) = delete; + constexpr ~run_destroy() + { + if (thisvec) + { + thisvec->destroy(); + } + } + }; + + constexpr void default_construct_impl(size_type n) + { + auto e{this->imp.end_ptr = (this->imp.curr_ptr = this->imp.begin_ptr = + typed_allocator_type::allocate(n)) + + n}; + run_destroy des(this); + for (; this->imp.curr_ptr != e; ++this->imp.curr_ptr) + { + ::std::construct_at(this->imp.curr_ptr); + } + des.thisvec = nullptr; + } + + template + constexpr void construct_vector_common_impl(Iter first, Sentinel last) + { + using rvaluetype = ::std::iter_value_t; + if constexpr (::std::same_as && ::std::contiguous_iterator && !::std::is_pointer_v) + { + this->construct_vector_common_impl(::std::to_address(first), ::std::to_address(last)); + } + else + { + if constexpr (::std::forward_iterator) + { + size_type n{static_cast(::std::ranges::distance(first, last))}; + auto e{this->imp.end_ptr = (this->imp.curr_ptr = this->imp.begin_ptr = + typed_allocator_type::allocate(n)) + + n}; + if constexpr ( + ::std::is_pointer_v && + ::std::is_trivially_constructible_v && + ::std::same_as<::std::remove_cvref_t, ::std::remove_cvref_t>) + { + if (n) [[likely]] + { +#if defined(_MSC_VER) && !defined(__clang__) + ::std::memcpy +#else + __builtin_memcpy +#endif + (this->imp.curr_ptr, first, n * sizeof(value_type)); + } + this->imp.curr_ptr = e; + } + else if constexpr (::std::is_nothrow_constructible_v) + { + auto curr{this->imp.begin_ptr}; + for (; curr != e; ++curr) + { + ::std::construct_at(curr, *first); + ++first; + } + this->imp.curr_ptr = e; + } + else + { + run_destroy des(this); + for (; this->imp.curr_ptr != e; ++this->imp.curr_ptr) + { + ::std::construct_at(this->imp.curr_ptr, *first); + ++first; + } + des.thisvec = nullptr; + } + } + else + { + run_destroy des(this); + for (; first != last; ++first) + { + this->emplace_back(*first); + } + des.thisvec = nullptr; + } + } + } + +public: + explicit constexpr vector(size_type n) noexcept(::fast_io::freestanding::is_zero_default_constructible_v || noexcept(value_type())) + { + if constexpr (::fast_io::freestanding::is_zero_default_constructible_v) + { + imp.begin_ptr = typed_allocator_type::allocate_zero(n); + imp.end_ptr = imp.curr_ptr = imp.begin_ptr + n; + } + else + { + this->default_construct_impl(n); + } + } + + explicit constexpr vector(size_type n, ::fast_io::for_overwrite_t) noexcept(::std::is_trivially_default_constructible_v || ::fast_io::freestanding::is_zero_default_constructible_v || noexcept(value_type())) + { + if constexpr (::std::is_trivially_default_constructible_v) + { + imp.begin_ptr = typed_allocator_type::allocate(n); + imp.end_ptr = imp.curr_ptr = imp.begin_ptr + n; + } + else if constexpr (::fast_io::freestanding::is_zero_default_constructible_v) + { + imp.begin_ptr = typed_allocator_type::allocate_zero(n); + imp.end_ptr = imp.curr_ptr = imp.begin_ptr + n; + } + else + { + this->default_construct_impl(n); + } + } + + explicit constexpr vector(size_type n, const_reference val) noexcept(::std::is_nothrow_copy_constructible_v) + { + auto e{this->imp.end_ptr = (this->imp.curr_ptr = this->imp.begin_ptr = + typed_allocator_type::allocate(n)) + + n}; + run_destroy des(this); + for (; this->imp.curr_ptr != e; ++this->imp.curr_ptr) + { + ::std::construct_at(this->imp.curr_ptr, val); + } + des.thisvec = nullptr; + } + + template <::std::ranges::range R> + explicit constexpr vector(::fast_io::freestanding::from_range_t, R &&rg) + { + this->construct_vector_common_impl(::std::ranges::begin(rg), ::std::ranges::end(rg)); + } + + explicit constexpr vector(::std::initializer_list ilist) noexcept(::std::is_nothrow_move_constructible_v) + { + this->construct_vector_common_impl(ilist.begin(), ilist.end()); + } + + constexpr vector(vector const &vec) + requires(::std::copyable) + { + std::size_t const vecsize{static_cast(vec.imp.curr_ptr - vec.imp.begin_ptr)}; + if (vecsize == 0) + { + return; + } + imp.begin_ptr = typed_allocator_type::allocate(vecsize); + if constexpr (::std::is_trivially_copyable_v) + { +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && __cpp_constexpr_dynamic_alloc >= 201907L +#if __cpp_if_consteval >= 202106L + if !consteval +#else + if (!__builtin_is_constant_evaluated()) +#endif +#endif + { + ::fast_io::freestanding::nonoverlapped_bytes_copy( + reinterpret_cast<::std::byte const *>(vec.imp.begin_ptr), + reinterpret_cast<::std::byte const *>(vec.imp.curr_ptr), + reinterpret_cast<::std::byte *>(this->imp.begin_ptr)); + imp.end_ptr = imp.curr_ptr = imp.begin_ptr + vecsize; + return; + } + } + run_destroy des(this); + this->imp.curr_ptr = this->imp.begin_ptr; + this->imp.end_ptr = this->imp.begin_ptr + vecsize; + for (auto i{vec.imp.begin_ptr}; i != vec.imp.curr_ptr; ++i) + { + ::std::construct_at(this->imp.curr_ptr, *i); + ++this->imp.curr_ptr; + } + des.thisvec = nullptr; + } + constexpr vector(vector const &vec) = delete; + constexpr vector &operator=(vector const &vec) + requires(::std::copyable) + { + vector newvec(vec); + this->operator=(::std::move(newvec)); + return *this; + } + constexpr vector &operator=(vector const &vec) = delete; + constexpr vector(vector &&vec) noexcept + : imp(vec.imp) + { + vec.imp = {}; + } + constexpr vector &operator=(vector &&vec) noexcept + { + this->destroy(); + this->imp = vec.imp; + vec.imp = nullptr; + return *this; + } + constexpr ~vector() + { + destroy(); + } + + template + requires std::constructible_from + constexpr reference emplace_back_unchecked(Args &&...args) noexcept(::std::is_nothrow_constructible_v) + { + auto p{::std::construct_at(imp.curr_ptr, ::std::forward(args)...)}; + ++imp.curr_ptr; + return *p; + } + +private: + inline constexpr pointer grow_to_size_iter_impl(size_type newcap, pointer iter, size_type n) noexcept + { + if constexpr (::fast_io::freestanding::is_trivially_relocatable_v) + { +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && __cpp_constexpr_dynamic_alloc >= 201907L +#if __cpp_if_consteval >= 202106L + if !consteval +#else + if (!__builtin_is_constant_evaluated()) +#endif +#endif + { + return reinterpret_cast(::fast_io::containers::details::vector::grow_to_size_iter_impl(*reinterpret_cast<::fast_io::containers::details::vector_model *>(__builtin_addressof(imp)), + iter, n)); + } + } + auto newres = typed_allocator_type::allocate_at_least(newcap); + auto new_begin_ptr = newres.ptr; + auto old_begin_ptr{imp.begin_ptr}; + auto old_curr_ptr{imp.curr_ptr}; + size_type const old_size{static_cast(old_curr_ptr - old_begin_ptr)}; + auto newiter{::fast_io::freestanding::uninitialized_relocate(old_begin_ptr, iter, new_begin_ptr)}; + ::fast_io::freestanding::uninitialized_relocate(iter, old_curr_ptr, newiter + n); + if constexpr (typed_allocator_type::has_deallocate) + { + typed_allocator_type::deallocate(old_begin_ptr); + } + else + { + typed_allocator_type::deallocate_n(old_begin_ptr, static_cast(imp.end_ptr - old_begin_ptr)); + } + imp.begin_ptr = new_begin_ptr; + imp.curr_ptr = new_begin_ptr + old_size; + imp.end_ptr = new_begin_ptr + newres.count; + return newiter; + } + +#if __has_cpp_attribute(__gnu__::__cold__) + [[__gnu__::__cold__]] +#endif + inline constexpr pointer grow_twice_iter_impl(pointer iter) noexcept + { + if constexpr (::fast_io::freestanding::is_trivially_relocatable_v) + { +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && __cpp_constexpr_dynamic_alloc >= 201907L +#if __cpp_if_consteval >= 202106L + if !consteval +#else + if (!__builtin_is_constant_evaluated()) +#endif +#endif + { + return reinterpret_cast(::fast_io::containers::details::vector::grow_twice_iter_impl(*reinterpret_cast<::fast_io::containers::details::vector_model *>(__builtin_addressof(imp)), + iter)); + } + } + std::size_t const cap{static_cast(imp.end_ptr - imp.begin_ptr)}; + return this->grow_to_size_iter_impl(::fast_io::containers::details::cal_grow_twice_size(cap), iter, 1); + } + constexpr pointer move_backward_common_impl(pointer iter) noexcept + { + if constexpr (::fast_io::freestanding::is_trivially_relocatable_v) + { +#ifdef __cpp_if_consteval + if !consteval +#else + if (!__builtin_is_constant_evaluated()) +#endif + { + return reinterpret_cast(::fast_io::containers::details::vector::move_backward_impl( + *reinterpret_cast<::fast_io::containers::details::vector_model *>(__builtin_addressof(imp)), + iter)); + } + } + if (imp.curr_ptr == imp.end_ptr) [[unlikely]] + { + return this->grow_twice_iter_impl(iter); + } + auto currptr{imp.curr_ptr}; + auto currptrp1{currptr + 1}; + ::fast_io::freestanding::uninitialized_move_backward(iter, currptr, currptrp1); + return iter; + } + + inline constexpr void grow_to_size_impl(size_type newcap) noexcept + { + if constexpr (::fast_io::freestanding::is_trivially_relocatable_v) + { +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && __cpp_constexpr_dynamic_alloc >= 201907L +#if __cpp_if_consteval >= 202106L + if !consteval +#else + if (!__builtin_is_constant_evaluated()) +#endif +#endif + { + ::fast_io::containers::details::vector::grow_to_size_impl( + *reinterpret_cast<::fast_io::containers::details::vector_model *>(__builtin_addressof(imp)), newcap); + return; + } + } + this->grow_to_size_iter_impl(newcap, imp.curr_ptr, 1); + } +#if __has_cpp_attribute(__gnu__::__cold__) + [[__gnu__::__cold__]] +#endif + inline constexpr void grow_twice_impl() noexcept + { + if constexpr (::fast_io::freestanding::is_trivially_relocatable_v) + { +#if (__cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L) && __cpp_constexpr_dynamic_alloc >= 201907L +#if __cpp_if_consteval >= 202106L + if !consteval +#else + if (!__builtin_is_constant_evaluated()) +#endif +#endif + { + ::fast_io::containers::details::vector::grow_twice_impl( + *reinterpret_cast<::fast_io::containers::details::vector_model *>(__builtin_addressof(imp))); + return; + } + } + std::size_t const cap{static_cast(imp.end_ptr - imp.begin_ptr)}; + grow_to_size_impl(::fast_io::containers::details::cal_grow_twice_size(cap)); + } + +public: + constexpr void reserve(size_type n) noexcept + { + if (n <= static_cast(imp.end_ptr - imp.begin_ptr)) + { + return; + } + grow_to_size_impl(n); + } + + constexpr void shrink_to_fit() noexcept + { + if (imp.curr_ptr == imp.end_ptr) + { + return; + } + grow_to_size_impl(static_cast(imp.curr_ptr - imp.begin_ptr)); + } +#if __has_cpp_attribute(__gnu__::__always_inline__) + [[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) + [[msvc::forceinline]] +#endif + constexpr void pop_back() noexcept + { + if (imp.curr_ptr == imp.begin_ptr) [[unlikely]] + { + ::fast_io::fast_terminate(); + } + (--imp.curr_ptr)->~value_type(); + } + + constexpr void pop_back_unchecked() noexcept + { + (--imp.curr_ptr)->~value_type(); + } + + constexpr void push_back(T const &value) noexcept(::std::is_nothrow_copy_constructible_v) + { + this->emplace_back(value); + } + constexpr void push_back(T &&value) noexcept(::std::is_nothrow_move_constructible_v) + { + this->emplace_back(::std::move(value)); + } + constexpr void push_back_unchecked(T const &value) noexcept(::std::is_nothrow_copy_constructible_v) + { + this->emplace_back_unchecked(value); + } + constexpr void push_back_unchecked(T &&value) noexcept(::std::is_nothrow_move_constructible_v) + { + this->emplace_back_unchecked(::std::move(value)); + } + + [[nodiscard]] constexpr pointer data() noexcept + { + return imp.begin_ptr; + } + [[nodiscard]] constexpr const_pointer data() const noexcept + { + return imp.begin_ptr; + } + [[nodiscard]] constexpr bool is_empty() const noexcept + { + return imp.begin_ptr == imp.curr_ptr; + } + + [[nodiscard]] constexpr bool empty() const noexcept + { + return imp.begin_ptr == imp.curr_ptr; + } + constexpr void clear() noexcept + { + if constexpr (!::std::is_trivially_destructible_v) + { + ::std::destroy(imp.begin_ptr, imp.curr_ptr); + } + imp.curr_ptr = imp.begin_ptr; + } + [[nodiscard]] constexpr size_type size() const noexcept + { + return static_cast(imp.curr_ptr - imp.begin_ptr); + } + [[nodiscard]] constexpr size_type size_bytes() const noexcept + { + return static_cast(imp.curr_ptr - imp.begin_ptr) * sizeof(value_type); + } + [[nodiscard]] constexpr size_type capacity() const noexcept + { + return static_cast(imp.end_ptr - imp.begin_ptr); + } + [[nodiscard]] constexpr size_type capacity_bytes() const noexcept + { + return static_cast(imp.end_ptr - imp.begin_ptr) * sizeof(value_type); + } + [[nodiscard]] static inline constexpr size_type max_size() noexcept + { + constexpr size_type mx{::std::numeric_limits::max() / sizeof(value_type)}; + return mx; + } + [[nodiscard]] static inline constexpr size_type max_size_bytes() noexcept + { + constexpr size_type mx{::std::numeric_limits::max() / sizeof(value_type) * sizeof(value_type)}; + return mx; + } + [[nodiscard]] constexpr const_reference index_unchecked(size_type pos) const noexcept + { + return imp.begin_ptr[pos]; + } + [[nodiscard]] constexpr reference index_unchecked(size_type pos) noexcept + { + return imp.begin_ptr[pos]; + } + +#if __has_cpp_attribute(__gnu__::__always_inline__) + [[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) + [[msvc::forceinline]] +#endif + [[nodiscard]] constexpr const_reference + operator[](size_type pos) const noexcept + { + auto begin_ptr{imp.begin_ptr}, curr_ptr{imp.curr_ptr}; + if (static_cast<::std::size_t>(curr_ptr - begin_ptr) <= pos) [[unlikely]] + { + ::fast_io::fast_terminate(); + } + return begin_ptr[pos]; + } +#if __has_cpp_attribute(__gnu__::__always_inline__) + [[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) + [[msvc::forceinline]] +#endif + [[nodiscard]] constexpr reference + operator[](size_type pos) noexcept + { + auto begin_ptr{imp.begin_ptr}, curr_ptr{imp.curr_ptr}; + if (static_cast<::std::size_t>(curr_ptr - begin_ptr) <= pos) [[unlikely]] + { + ::fast_io::fast_terminate(); + } + return begin_ptr[pos]; + } + +#if __has_cpp_attribute(__gnu__::__always_inline__) + [[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) + [[msvc::forceinline]] +#endif + [[nodiscard]] constexpr const_reference + front() const noexcept + { + auto begin_ptr{imp.begin_ptr}, curr_ptr{imp.curr_ptr}; + if (begin_ptr == curr_ptr) [[unlikely]] + { + ::fast_io::fast_terminate(); + } + return *begin_ptr; + } +#if __has_cpp_attribute(__gnu__::__always_inline__) + [[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) + [[msvc::forceinline]] +#endif + [[nodiscard]] constexpr reference + front() noexcept + { + auto begin_ptr{imp.begin_ptr}, curr_ptr{imp.curr_ptr}; + if (begin_ptr == curr_ptr) [[unlikely]] + { + ::fast_io::fast_terminate(); + } + return *begin_ptr; + } +#if __has_cpp_attribute(__gnu__::__always_inline__) + [[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) + [[msvc::forceinline]] +#endif + [[nodiscard]] constexpr const_reference + back() const noexcept + { + auto begin_ptr{imp.begin_ptr}, curr_ptr{imp.curr_ptr}; + if (begin_ptr == curr_ptr) [[unlikely]] + { + ::fast_io::fast_terminate(); + } + return curr_ptr[-1]; + } +#if __has_cpp_attribute(__gnu__::__always_inline__) + [[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) + [[msvc::forceinline]] +#endif + [[nodiscard]] constexpr reference + back() noexcept + { + auto begin_ptr{imp.begin_ptr}, curr_ptr{imp.curr_ptr}; + if (begin_ptr == curr_ptr) [[unlikely]] + { + ::fast_io::fast_terminate(); + } + return curr_ptr[-1]; + } + + [[nodiscard]] constexpr const_reference front_unchecked() const noexcept + { + return *imp.begin_ptr; + } + [[nodiscard]] constexpr reference front_unchecked() noexcept + { + return *imp.begin_ptr; + } + [[nodiscard]] constexpr const_reference back_unchecked() const noexcept + { + return imp.curr_ptr[-1]; + } + [[nodiscard]] constexpr reference back_unchecked() noexcept + { + return imp.curr_ptr[-1]; + } + + [[nodiscard]] constexpr iterator begin() noexcept + { + return imp.begin_ptr; + } + [[nodiscard]] constexpr iterator end() noexcept + { + return imp.curr_ptr; + } + [[nodiscard]] constexpr const_iterator begin() const noexcept + { + return imp.begin_ptr; + } + [[nodiscard]] constexpr const_iterator end() const noexcept + { + return imp.curr_ptr; + } + [[nodiscard]] constexpr const_iterator cbegin() const noexcept + { + return imp.begin_ptr; + } + [[nodiscard]] constexpr const_iterator cend() const noexcept + { + return imp.curr_ptr; + } + + [[nodiscard]] constexpr reverse_iterator rbegin() noexcept + { + return reverse_iterator{imp.curr_ptr}; + } + [[nodiscard]] constexpr reverse_iterator rend() noexcept + { + return reverse_iterator{imp.begin_ptr}; + } + [[nodiscard]] constexpr const_reverse_iterator rbegin() const noexcept + { + return const_reverse_iterator{imp.curr_ptr}; + } + [[nodiscard]] constexpr const_reverse_iterator rend() const noexcept + { + return const_reverse_iterator{imp.begin_ptr}; + } + [[nodiscard]] constexpr const_reverse_iterator crbegin() const noexcept + { + return const_reverse_iterator{imp.curr_ptr}; + } + [[nodiscard]] constexpr const_reverse_iterator crend() const noexcept + { + return const_reverse_iterator{imp.begin_ptr}; + } + + constexpr void clear_destroy() noexcept + { + this->destroy(); + imp = {}; + } + + template + requires std::constructible_from + constexpr reference emplace_back(Args &&...args) noexcept(::std::is_nothrow_constructible_v) + { + if (imp.curr_ptr == imp.end_ptr) +#if __has_cpp_attribute(unlikely) + [[unlikely]] +#endif + { + grow_twice_impl(); + } + auto p{::std::construct_at(imp.curr_ptr, ::std::forward(args)...)}; + ++imp.curr_ptr; + return *p; + } + +private: + constexpr iterator insert_impl(pointer iter, value_type &&tmp) noexcept + { + auto ret = ::std::construct_at(this->move_backward_common_impl(iter), ::std::move(tmp)); + ++imp.curr_ptr; + return ret; + } + +public: + template + requires std::constructible_from + constexpr iterator emplace(const_iterator iter, Args &&...args) noexcept(::std::is_nothrow_constructible_v) + { + if constexpr (::std::is_nothrow_constructible_v) + { + pointer ret; +#ifdef __cpp_if_consteval + if consteval +#else + if (__builtin_is_constant_evaluated()) +#endif + { + auto beginptr{imp.begin_ptr}; + ret = ::std::construct_at(this->move_backward_common_impl(iter - beginptr + beginptr), ::std::forward(args)...); + } + else + { + ret = ::std::construct_at(this->move_backward_common_impl(const_cast(iter)), ::std::forward(args)...); + } + ++imp.curr_ptr; + return ret; + } + else + { +#ifdef __cpp_if_consteval + if consteval +#else + if (__builtin_is_constant_evaluated()) +#endif + { + auto beginptr{imp.begin_ptr}; + return this->insert_impl(iter - beginptr + beginptr, value_type(::std::forward(args)...)); + } + else + { + return this->insert_impl(const_cast(iter), value_type(::std::forward(args)...)); + } + } + } + + template + requires std::constructible_from + constexpr reference emplace_index(size_type idx, Args &&...args) noexcept(::std::is_nothrow_constructible_v) + { + auto beginptr{imp.begin_ptr}; + size_type sz{static_cast(imp.curr_ptr - beginptr)}; + if (sz < idx) + { + ::fast_io::fast_terminate(); + } + return *this->emplace(beginptr + idx, ::std::forward(args)...); + } + + constexpr iterator insert(const_iterator iter, const_reference val) noexcept(::std::is_nothrow_copy_constructible_v) + { + return this->emplace(iter, val); + } + + constexpr iterator insert(const_iterator iter, value_type &&val) noexcept(::std::is_nothrow_move_constructible_v) + { + return this->emplace(iter, ::std::move(val)); + } + + constexpr reference insert_index(size_type idx, const_reference val) noexcept(::std::is_nothrow_copy_constructible_v) + { + return this->emplace_index(idx, val); + } + + constexpr reference insert_index(size_type idx, value_type &&val) noexcept(::std::is_nothrow_move_constructible_v) + { + return this->emplace_index(idx, ::std::move(val)); + } + +private: + constexpr pointer erase_common(pointer it) noexcept + { + auto lastele{imp.curr_ptr}; + if constexpr (!::std::is_trivially_destructible_v) + { + ::std::destroy_at(it); + } + ::fast_io::freestanding::uninitialized_relocate(it + 1, lastele, it); + imp.curr_ptr = lastele; + return it; + } + + constexpr pointer erase_iters_common(pointer first, pointer last) noexcept + { + auto currptr{imp.curr_ptr}; + if constexpr (!::std::is_trivially_destructible_v) + { + ::std::destroy(first, last); + } + imp.curr_ptr = ::fast_io::freestanding::uninitialized_relocate(last, currptr, first); + return first; + } + +public: + constexpr iterator erase(const_iterator it) noexcept + { +#ifdef __cpp_if_consteval + if consteval +#else + if (__builtin_is_constant_evaluated()) +#endif + { + return this->erase_common(it - imp.begin_ptr + imp.begin_ptr); + } + else + { + return this->erase_common(const_cast(it)); + } + } + + constexpr void erase_index(size_type idx) noexcept + { + auto beginptr{imp.begin_ptr}; + auto currptr{imp.curr_ptr}; + size_type sz{static_cast(currptr - beginptr)}; + if (sz <= idx) + { + ::fast_io::fast_terminate(); + } + this->erase_common(beginptr + idx); + } + + constexpr iterator erase(const_iterator first, const_iterator last) noexcept + { +#ifdef __cpp_if_consteval + if consteval +#else + if (__builtin_is_constant_evaluated()) +#endif + { + return this->erase_iters_common(first - imp.begin_ptr + imp.begin_ptr, last - imp.begin_ptr + imp.begin_ptr); + } + else + { + return this->erase_iters_common(const_cast(first), const_cast(last)); + } + } + + constexpr void erase_index(size_type firstidx, size_type lastidx) noexcept + { + auto beginptr{imp.begin_ptr}; + auto currptr{imp.curr_ptr}; + size_type sz{static_cast(currptr - beginptr)}; + if (lastidx < firstidx || sz <= lastidx) + { + ::fast_io::fast_terminate(); + } + this->erase_iters_common(beginptr + firstidx, beginptr + lastidx); + } +}; + +template + requires ::std::equality_comparable +constexpr bool operator==(vector const &lhs, vector const &rhs) noexcept +{ + return ::std::equal(lhs.imp.begin_ptr, lhs.imp.curr_ptr, rhs.imp.begin_ptr, rhs.imp.curr_ptr); +} + +#if defined(__cpp_lib_three_way_comparison) +template + requires ::std::three_way_comparable +constexpr auto operator<=>(vector const &lhs, vector const &rhs) noexcept +{ + return ::std::lexicographical_compare_three_way(lhs.imp.begin_ptr, lhs.imp.curr_ptr, rhs.imp.begin_ptr, rhs.imp.curr_ptr, ::std::compare_three_way{}); +} +#endif + +template +constexpr void swap(vector &lhs, vector &rhs) noexcept +{ + lhs.swap(rhs); +} + +} // namespace containers + +namespace freestanding +{ + +template +struct is_trivially_relocatable<::fast_io::containers::vector> +{ + inline static constexpr bool value = true; +}; + +template +struct is_zero_default_constructible<::fast_io::containers::vector> +{ + inline static constexpr bool value = true; +}; + +} // namespace freestanding +} // namespace fast_io diff --git a/src/fast_io/include/fast_io_dsal/vector.h b/src/fast_io/include/fast_io_dsal/vector.h new file mode 100644 index 0000000..66585b7 --- /dev/null +++ b/src/fast_io/include/fast_io_dsal/vector.h @@ -0,0 +1,76 @@ +#pragma once +#undef min +#undef max + +#if !defined(__cplusplus) +#error "You must be using a C++ compiler" +#endif +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning(push) +#pragma warning(disable : 4464) +#pragma warning(disable : 4514) +#pragma warning(disable : 4623) +#pragma warning(disable : 4626) +#pragma warning(disable : 4668) +#pragma warning(disable : 4710) +#pragma warning(disable : 4820) +#pragma warning(disable : 5027) +#pragma warning(disable : 5045) +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../fast_io_core_impl/freestanding/impl.h" +#include "../fast_io_core_impl/terminate.h" +#include "../fast_io_core_impl/intrinsics/msvc/impl.h" +#include "../fast_io_core_impl/allocation/impl.h" +#include "../fast_io_core_impl/asan_support.h" + +#include "impl/freestanding.h" +#include "impl/common.h" +#include "impl/vector.h" + +#if ((__STDC_HOSTED__ == 1 && (!defined(_GLIBCXX_HOSTED) || _GLIBCXX_HOSTED == 1) && \ + !defined(_LIBCPP_FREESTANDING)) || \ + defined(FAST_IO_ENABLE_HOSTED_FEATURES)) + +namespace fast_io +{ + +template +using vector = ::fast_io::containers::vector; + +namespace containers +{ + +template <::std::input_iterator InputIt> +vector(InputIt, InputIt) -> vector::value_type, ::fast_io::native_global_allocator>; +#ifdef __cpp_lib_containers_ranges +template <::std::ranges::input_range R> +vector(::std::from_range_t, R &&) -> vector<::std::ranges::range_value_t, ::fast_io::native_global_allocator>; +#endif +} // namespace containers + +namespace tlc +{ +template +using vector = ::fast_io::containers::vector; +} + +} // namespace fast_io + +#endif + +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning(pop) +#endif diff --git a/src/fast_io/include/fast_io_freestanding.h b/src/fast_io/include/fast_io_freestanding.h new file mode 100644 index 0000000..6fe7009 --- /dev/null +++ b/src/fast_io/include/fast_io_freestanding.h @@ -0,0 +1,87 @@ +#pragma once + +//fast_io_freestanding.h is usable when the underlining system implements dynamic memory allocations and exceptions +#if !defined(__cplusplus) +#error "You are not using a C++ compiler" +#endif + +#if !defined(__cpp_concepts) +#error "fast_io requires at least C++20 standard compiler." +#else + +#include"fast_io_core.h" + +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning(push) +#pragma warning( disable : 4514 ) +#pragma warning( disable : 4554 ) +#pragma warning( disable : 4668 ) +#pragma warning( disable : 4820 ) +#pragma warning( disable : 4710 ) +#endif + +#include"fast_io_freestanding_impl/exception.h" +//#include"fast_io_freestanding_impl/posix_error.h" +//compile floating point is slow since it requires algorithms like ryu +#ifndef FAST_IO_DISABLE_FLOATING_POINT +#include"fast_io_unit/floating/impl.h" +#endif +#include"fast_io_freestanding_impl/io_buffer/impl.h" +#include"fast_io_freestanding_impl/auto_indent.h" +#include"fast_io_freestanding_impl/serializations/impl.h" +#include"fast_io_freestanding_impl/space_reserve.h" +#include"fast_io_freestanding_impl/width.h" +#include"fast_io_freestanding_impl/scanners/impl.h" +#include"fast_io_freestanding_impl/cond.h" + +#if defined(_GLIBCXX_BITSET) +#include"fast_io_unit/bitset.h" +#endif + +namespace fast_io +{ + +template +using basic_ibuf = basic_io_buffer; +template +using basic_obuf = basic_io_buffer; +template +using basic_iobuf = basic_io_buffer; +#if !defined(FAST_IO_DISABLE_CODECVT) +template +using basic_ibuf_code_cvt = basic_io_buffer, + empty_decorator>>; + +template +using basic_obuf_code_cvt = basic_io_buffer>>; + +template +using basic_iobuf_code_cvt = basic_io_buffer, + basic_code_converter>>; +#endif + +} + +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning(pop) +#endif +#endif diff --git a/src/fast_io/include/fast_io_freestanding_impl/auto_indent.h b/src/fast_io/include/fast_io_freestanding_impl/auto_indent.h new file mode 100644 index 0000000..866067b --- /dev/null +++ b/src/fast_io/include/fast_io_freestanding_impl/auto_indent.h @@ -0,0 +1,168 @@ +#pragma once + +namespace fast_io +{ + +namespace manipulators +{ +template +struct auto_indent_t +{ + using container_type = containe; + std::size_t total_size; + char_type const* first; + char_type const* last; + container_type container; +}; +} + +namespace details +{ + +template +inline constexpr char_type get_horizontal_exec_char() noexcept +{ + if constexpr(op==2) + { + if constexpr(std::same_as) + return ' '; + else if constexpr(std::same_as) + return L' '; + else + return u8' '; + } + else if constexpr(op==1) + { + if constexpr(std::same_as) + return '\n'; + else if constexpr(std::same_as) + return L'\n'; + else + return u8'\n'; + } + else + { + if constexpr(std::same_as) + return '\t'; + else if constexpr(std::same_as) + return L'\t'; + else + return u8'\t'; + } +} + +template +inline ::fast_io::manipulators::auto_indent_t + calculate_auto_width_result(char_type const* first2,char_type const* last) +{ + auto first{first2}; + containe cont; + constexpr auto slasht{get_horizontal_exec_char()}; + constexpr auto lf{get_horizontal_exec_char()}; + std::size_t pos_this_line{}; + std::size_t lines{}; + auto last_tab{first}; + for(;first!=last;++first) + if((*first==slasht)|(*first==lf)) + { + std::size_t this_tab_width{static_cast(first-last_tab)}; + if(pos_this_line(last-last_tab)}; + if(pos_this_line(1)); + total_length=intrinsics::mul_or_overflow_die(total_length,lines); + return {total_length,first2,last,::std::move(cont)}; +} + +template<::std::integral char_type,typename containe> +inline constexpr char_type* print_reserve_define_auto_indent(char_type* iter, + ::fast_io::manipulators::auto_indent_t const& indent) noexcept +{ + constexpr auto slasht{get_horizontal_exec_char()}; + constexpr auto lf{get_horizontal_exec_char()}; + constexpr auto space{get_horizontal_exec_char()}; + auto first{indent.first}; + auto last{indent.last}; + auto line_ptr{indent.container.data()}; + auto line_size{indent.container.size()}; + auto last_tab{first}; + for(std::size_t pos_this_line{};first!=last;++first) + { + bool const slt{*first==slasht}; + if((slt)|(*first==lf))[[unlikely]] + { + std::size_t diff{static_cast(first-last_tab)}; + iter=non_overlapped_copy_n(last_tab,diff,iter); + last_tab=first+1; + if(slt)[[likely]] + { + iter=my_fill_n(iter,line_ptr[pos_this_line]-diff,space); + *iter=slasht; + ++iter; + ++pos_this_line; + } + else + { + *iter=lf; + ++iter; + pos_this_line=0; + } + } + } + if(last_tab!=last) + iter=non_overlapped_copy(last_tab,first,iter); + return iter; +} + +} + +namespace manipulators +{ + +template +inline constexpr std::size_t print_reserve_size( + io_reserve_type_t>, + auto_indent_t const& indent) noexcept +{ + return indent.total_size; +} + +template<::std::integral char_type,typename containe> +inline constexpr char_type* print_reserve_define( + io_reserve_type_t>, + char_type* iter, + auto_indent_t const& indent) noexcept +{ + return ::fast_io::details::print_reserve_define_auto_indent(iter,indent); +} + +} + +} diff --git a/src/fast_io/include/fast_io_freestanding_impl/cond.h b/src/fast_io/include/fast_io_freestanding_impl/cond.h new file mode 100644 index 0000000..e207c58 --- /dev/null +++ b/src/fast_io/include/fast_io_freestanding_impl/cond.h @@ -0,0 +1,175 @@ +#pragma once + +namespace fast_io +{ + +namespace manipulators +{ + +template +struct condition +{ + using manip_tag = manip_tag_t; + using alias_type1 = T1; + using alias_type2 = T2; + alias_type1 t1; + alias_type2 t2; + bool pred; +}; + +template +inline constexpr auto cond(bool pred,T1&& t1,T2&& t2) noexcept +{ + using t1aliastype=::std::remove_cvref_t; + using t2aliastype=::std::remove_cvref_t; + constexpr bool type_match{::std::same_as}; + if constexpr(type_match) + { + if(pred) + { + return fast_io::io_print_alias(t1); + } + else + { + return fast_io::io_print_alias(t2); + } + } + else + { + if constexpr(sizeof(t1aliastype){::fast_io::io_print_alias(t2),::fast_io::io_print_alias(t1),!pred}; + } + else + { + return condition{::fast_io::io_print_alias(t1),::fast_io::io_print_alias(t2),pred}; + } + } +} + +} + +template +requires (reserve_printable&&reserve_printable) +inline constexpr ::std::size_t print_reserve_size(io_reserve_type_t>) noexcept +{ + constexpr std::size_t s1{print_reserve_size(io_reserve_type)}; + constexpr std::size_t s2{print_reserve_size(io_reserve_type)}; + if constexpr(s1 +requires (scatter_printable&&scatter_printable) +inline constexpr basic_io_scatter_t print_scatter_define(io_reserve_type_t>,::fast_io::manipulators::condition c) +{ + if(c.pred) + { + return {print_scatter_define(io_reserve_type,c.t1)}; + } + else + { + return {print_scatter_define(io_reserve_type,c.t2)}; + } +} + +namespace details +{ + +template +concept cond_ok_dynamic_rsv_printable_impl= + reserve_printable||dynamic_reserve_printable||scatter_printable; + +template +concept cond_ok_printable_impl= + cond_ok_dynamic_rsv_printable_impl||printable; + +template +inline constexpr ::std::size_t cond_print_reserve_size_impl(T1 t1) +{ + if constexpr(scatter_printable) + { + return print_scatter_define(io_reserve_type,t1).len; + } + else if constexpr(reserve_printable) + { + constexpr std::size_t sz{print_reserve_size(io_reserve_type)}; + return sz; + } + else + { + return print_reserve_size(io_reserve_type,t1); + } +} + +template +inline constexpr char_type* cond_print_reserve_define_impl(char_type* iter,T1 t1) +{ + if constexpr(scatter_printable) + { + return copy_scatter(print_scatter_define(io_reserve_type,t1),iter); + } + else + { + return print_reserve_define(io_reserve_type,iter,t1); + } +} + +} + +template +requires ((details::cond_ok_dynamic_rsv_printable_impl&& + details::cond_ok_dynamic_rsv_printable_impl) + &&(!(scatter_printable&&scatter_printable))) +inline constexpr ::std::size_t print_reserve_size(io_reserve_type_t>,::fast_io::manipulators::condition c) +{ + if(c.pred) + { + return ::fast_io::details::cond_print_reserve_size_impl(c.t1); + } + else + { + return ::fast_io::details::cond_print_reserve_size_impl(c.t2); + } +} + +template +requires ((details::cond_ok_dynamic_rsv_printable_impl&& + details::cond_ok_dynamic_rsv_printable_impl) + &&(!(scatter_printable&&scatter_printable))) +inline constexpr char_type* print_reserve_define(io_reserve_type_t>,char_type* iter,::fast_io::manipulators::condition c) +{ + if(c.pred) + { + return ::fast_io::details::cond_print_reserve_define_impl(iter,c.t1); + } + else + { + return ::fast_io::details::cond_print_reserve_define_impl(iter,c.t2); + } +} + +template<::std::integral char_type,typename T1,typename T2,::fast_io::buffer_output_stream bop> +requires ((details::cond_ok_printable_impl&&details::cond_ok_printable_impl) + &&(!(details::cond_ok_dynamic_rsv_printable_impl&& + details::cond_ok_dynamic_rsv_printable_impl))) +inline constexpr void print_define(io_reserve_type_t>,bop b,::fast_io::manipulators::condition c) +{ + if(c.pred) + { + print_freestanding(b,c.t1); + } + else + { + print_freestanding(b,c.t2); + } +} + +} + diff --git a/src/fast_io/include/fast_io_freestanding_impl/exception.h b/src/fast_io/include/fast_io_freestanding_impl/exception.h new file mode 100644 index 0000000..b66d85a --- /dev/null +++ b/src/fast_io/include/fast_io_freestanding_impl/exception.h @@ -0,0 +1,36 @@ +#pragma once + +namespace fast_io +{ + +namespace details +{ + +inline cross_code_cvt_t ehvw_common_impl(char const* c_str) noexcept +{ + using char8_const_may_alias_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif + = char8_t const*; + return {{reinterpret_cast(c_str),cstr_len(c_str)}}; + +} + +} + +namespace manipulators +{ +template +requires requires(T const& eh) +{ + {eh.what()}->std::same_as; +} +inline cross_code_cvt_t ehvw(T const& eh) noexcept +{ + return ::fast_io::details::ehvw_common_impl(eh.what()); +} +} + +} + diff --git a/src/fast_io/include/fast_io_freestanding_impl/generator.h b/src/fast_io/include/fast_io_freestanding_impl/generator.h new file mode 100644 index 0000000..fdd1a66 --- /dev/null +++ b/src/fast_io/include/fast_io_freestanding_impl/generator.h @@ -0,0 +1,199 @@ +#pragma once +//https://github.com/lewissbaker/cppcoro/blob/master/include/cppcoro/generator.hpp +namespace fast_io +{ + +template +class generator; + +namespace details +{ +template +class generator_promise +{ +public: + using element_type = T; + using value_type = std::remove_cvref_t; + using reference = std::remove_reference_t&; + using const_reference = std::remove_reference_t const&; + using pointer = value_type*; + using const_pointer = value_type const*; + element_type ptr{}; +#ifdef __cpp_exceptions + std::exception_ptr ex_ptr; +#endif + generator get_return_object() noexcept; + + constexpr std::suspend_always initial_suspend() const noexcept { return {}; } + constexpr std::suspend_always final_suspend() const noexcept { return {}; } +// template +// requires std::same_as,std::remove_reference_t> + constexpr std::suspend_always yield_value(T value) noexcept + { + ptr=value; +// ptr = __builtin_addressof(value); + return {}; + } + constexpr void unhandled_exception() noexcept + { +#ifdef __cpp_exceptions + ex_ptr = std::current_exception(); +#else + std::terminate(); +#endif + } + constexpr void return_void() noexcept + { + } + template + std::suspend_never await_transform(U&& value) = delete; + + void rethrow_if_exception() + { +#ifdef __cpp_exceptions + if (ex_ptr) + std::rethrow_exception(ex_ptr); +#endif + } +}; + +template +class generator_iterator +{ +public: + using coroutine_handle_type = std::coroutine_handle>; + using iterator_category = ::std::output_iterator_tag; + coroutine_handle_type handle{}; +/* + inline constexpr auto operator->() + { + handle.resume(); +#ifdef __cpp_exceptions + if (handle.done()) + handle.promise().rethrow_if_exception(); +#endif + return handle.promise().ptr; + } +*/ + inline constexpr auto operator*() + { + return handle.promise().ptr; + } + +}; + +template +inline constexpr bool operator==(::std::default_sentinel_t, generator_iterator const& b) noexcept +{ + return b.handle.done(); +} + +template +inline constexpr bool operator==(generator_iterator const& b,::std::default_sentinel_t) noexcept +{ + return b.handle.done(); +} +template +inline constexpr bool operator!=(::std::default_sentinel_t s, generator_iterator const& b) noexcept +{ + return !(s==b); +} + +template +inline constexpr bool operator!=(generator_iterator const& b,::std::default_sentinel_t s) noexcept +{ + return !(s==b); +} + +template +inline constexpr generator_iterator& operator++(generator_iterator& b) +{ + b.handle.resume(); +#ifdef __cpp_exceptions + if (b.handle.done()) + b.handle.promise().rethrow_if_exception(); +#endif + return b; +} +template +inline constexpr void operator++(generator_iterator& b,int) +{ + b.handle.resume(); +#ifdef __cpp_exceptions + if (b.handle.done()) + b.handle.promise().rethrow_if_exception(); +#endif +} + +} + +template +class [[nodiscard]] generator +{ +public: + using promise_type = details::generator_promise; + std::coroutine_handle handle; + constexpr generator(std::coroutine_handle v):handle(v){} + constexpr generator(generator const&) noexcept=delete; + constexpr generator& operator=(generator const&) noexcept=delete; + constexpr ~generator() + { + handle.destroy(); + } +}; +template +inline constexpr details::generator_iterator begin(generator& gen) +{ + gen.handle.resume(); +#ifdef __cpp_exceptions + if (gen.handle.done()) + gen.handle.promise().rethrow_if_exception(); +#endif + return {gen.handle}; +} +template +inline constexpr ::std::default_sentinel_t end(generator& gen) +{ + return {}; +} +template +inline constexpr details::generator_iterator cbegin(generator const& gen) +{ + gen.handle.resume(); +#ifdef __cpp_exceptions + if (gen.handle.done()) + gen.handle.promise().rethrow_if_exception(); +#endif + return {gen.handle}; +} +template +inline constexpr ::std::default_sentinel_t cend(generator const& gen) +{ + return {}; +} +template +inline constexpr details::generator_iterator begin(generator const& gen) +{ + gen.handle.resume(); +#ifdef __cpp_exceptions + if (gen.handle.done()) + gen.handle.promise().rethrow_if_exception(); +#endif + return {gen.handle}; +} +template +inline constexpr ::std::default_sentinel_t end(generator const& gen) +{ + return {}; +} + +namespace details +{ +template +inline generator generator_promise::get_return_object() noexcept +{ + using coroutine_handle = std::coroutine_handle>; + return { coroutine_handle::from_promise(*this) }; +} +} +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_freestanding_impl/io_buffer/general.h b/src/fast_io/include/fast_io_freestanding_impl/io_buffer/general.h new file mode 100644 index 0000000..72b2b9f --- /dev/null +++ b/src/fast_io/include/fast_io_freestanding_impl/io_buffer/general.h @@ -0,0 +1,47 @@ +#pragma once + +namespace fast_io +{ + +template +inline constexpr void flush(basic_io_buffer& bios) +{ + if constexpr((mde&buffer_mode::out)==buffer_mode::out) + { + if constexpr(details::has_external_decorator_impl) + details::iobuf_output_flush_impl_deco::need_secure_clear>(io_ref(bios.handle),external_decorator(bios.decorators),bios.obuffer,bfs); + else + details::iobuf_output_flush_impl(io_ref(bios.handle),bios.obuffer); + } + if constexpr((mde&buffer_mode::in)==buffer_mode::in) + bios.ibuffer.buffer_end=bios.ibuffer.buffer_curr=bios.ibuffer.buffer_begin; +} + +template +requires ((mde&buffer_mode::secure_clear)==buffer_mode::secure_clear) +inline constexpr void require_secure_clear(basic_io_buffer&){} + +template +inline constexpr std::size_t obuffer_constant_size(fast_io::io_reserve_type_t::char_type,basic_io_buffer>) noexcept +{ + return bfs; +} + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline constexpr void obuffer_constant_flush_prepare(basic_io_buffer& bios) noexcept +{ + if constexpr((mde&buffer_mode::out)==buffer_mode::out) + { + if constexpr(details::has_external_decorator_impl) + details::iobuf_output_constant_flush_prepare_impl_deco::need_secure_clear>(io_ref(bios.handle),external_decorator(bios.decorators),bios.obuffer,bfs); + else + details::iobuf_output_constant_flush_prepare_impl(io_ref(bios.handle),bios.obuffer,bfs); + } + if constexpr((mde&buffer_mode::in)==buffer_mode::in) + bios.ibuffer.buffer_end=bios.ibuffer.buffer_curr=bios.ibuffer.buffer_begin; +} + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_freestanding_impl/io_buffer/impl.h b/src/fast_io/include/fast_io_freestanding_impl/io_buffer/impl.h new file mode 100644 index 0000000..8836e76 --- /dev/null +++ b/src/fast_io/include/fast_io_freestanding_impl/io_buffer/impl.h @@ -0,0 +1,7 @@ +#pragma once + +#include"mode.h" +#include"main.h" +#include"output.h" +#include"input.h" +#include"general.h" diff --git a/src/fast_io/include/fast_io_freestanding_impl/io_buffer/input.h b/src/fast_io/include/fast_io_freestanding_impl/io_buffer/input.h new file mode 100644 index 0000000..4fca3bb --- /dev/null +++ b/src/fast_io/include/fast_io_freestanding_impl/io_buffer/input.h @@ -0,0 +1,207 @@ +#pragma once +#include"input_normal.h" +#include"input_deco.h" + +namespace fast_io +{ + +template +requires ((mde&buffer_mode::in)==buffer_mode::in&&!details::has_internal_decorator_impl) +inline constexpr decltype(auto) zero_copy_in_handle(basic_io_buffer& bios) +{ + return zero_copy_in_handle(bios.handle); +} + +template +requires ((mde&buffer_mode::in)==buffer_mode::in) +inline constexpr auto ibuffer_begin(basic_io_buffer& bios) noexcept +{ + return bios.ibuffer.buffer_begin; +} + +template +requires ((mde&buffer_mode::in)==buffer_mode::in) +inline constexpr auto ibuffer_curr(basic_io_buffer& bios) noexcept +{ + return bios.ibuffer.buffer_curr; +} + +template +requires ((mde&buffer_mode::in)==buffer_mode::in) +inline constexpr auto ibuffer_end(basic_io_buffer& bios) noexcept +{ + return bios.ibuffer.buffer_end; +} + +template +requires ((mde&buffer_mode::in)==buffer_mode::in) +inline constexpr void ibuffer_set_curr(basic_io_buffer& bios,typename basic_io_buffer::char_type* ptr) noexcept +{ + bios.ibuffer.buffer_curr=ptr; +} + + +template +requires ((mde&buffer_mode::in)==buffer_mode::in) +inline constexpr bool ibuffer_underflow(basic_io_buffer& bios) +{ + if constexpr(((mde&buffer_mode::out)==buffer_mode::out)&& + ((mde&buffer_mode::tie)==buffer_mode::tie)) + { + if constexpr(details::has_external_decorator_impl) + details::iobuf_output_flush_impl_deco::need_secure_clear>(io_ref(bios.handle),external_decorator(bios.decorators),bios.obuffer,bfs); + else + details::iobuf_output_flush_impl(io_ref(bios.handle),bios.obuffer); + } + if constexpr(details::has_internal_decorator_impl) + return details::ibuffer_underflow_impl_deco::need_secure_clear,bfs>(io_ref(bios.handle),internal_decorator(bios.decorators),bios.ibuffer,bios.ibuffer_external); + else + return details::ibuffer_underflow_impl(io_ref(bios.handle),bios.ibuffer); +} + +namespace details +{ + + +template +inline constexpr Iter iobuf_read_unhappy_impl(T& bios,Iter first,Iter last) +{ + if constexpr(((T::mode&buffer_mode::out)==buffer_mode::out)&&((T::mode&buffer_mode::tie)==buffer_mode::tie)) + { + if constexpr(details::has_external_decorator_impl) + iobuf_output_flush_impl_deco(io_ref(bios.handle), + external_decorator(bios.decorators), + bios.obuffer, + bios.obuffer_external, + T::buffer_size); + else + iobuf_output_flush_impl(io_ref(bios.handle),bios.obuffer); + } + first=non_overlapped_copy(bios.ibuffer.buffer_curr,bios.ibuffer.buffer_end,first); + bios.ibuffer.buffer_curr=bios.ibuffer.buffer_end; + if constexpr(details::has_internal_decorator_impl) + return iobuf_read_unhappy_decay_impl_deco(io_ref(bios.handle), + internal_decorator(bios.decorators), + bios.ibuffer,bios.ibuffer_external, + first,last,T::buffer_size); + else + return iobuf_read_unhappy_decay_impl(io_ref(bios.handle),bios.ibuffer,first,last,T::buffer_size); +} + +} + +template +requires (((mde&buffer_mode::in)==buffer_mode::in)&&details::allow_iobuf_punning) +[[nodiscard]] +inline constexpr Iter read(basic_io_buffer& bios,Iter first,Iter last) +{ + using iter_char_type = ::std::iter_value_t; + using char_type = typename decorators::internal_type; + if constexpr(std::same_as) + { + if constexpr(::std::contiguous_iterator&&!std::is_pointer_v) + { + return first+(read(bios,::std::to_address(first),::std::to_address(last))-::std::to_address(first)); + } + else + { + std::size_t diff(static_cast(last-first)); + std::size_t remain_space(static_cast(bios.ibuffer.buffer_end-bios.ibuffer.buffer_curr)); + if(remain_space(::std::to_address(first))}; + auto ret{read(bios,newb, + reinterpret_cast(::std::to_address(last)))}; + return first+static_cast(ret-newb)/sizeof(*first); + } +} + + + +template +requires ((mde&buffer_mode::in)!=buffer_mode::in||!details::has_internal_decorator_impl) +inline constexpr std::uintmax_t seek(basic_io_buffer& bios,std::intmax_t pos=0,seekdir sdir=seekdir::cur) +{ + if constexpr((mde&buffer_mode::out)==buffer_mode::out) + { + if constexpr(details::has_external_decorator_impl) + details::iobuf_output_flush_impl_deco::need_secure_clear>(io_ref(bios.handle),external_decorator(bios.decorators),bios.obuffer,bfs); + else + details::iobuf_output_flush_impl(io_ref(bios.handle),bios.obuffer); + } + if constexpr((mde&buffer_mode::in)==buffer_mode::in) + { + if(sdir==seekdir::cur) + { + std::size_t offset{static_cast(bios.ibuffer.buffer_end-bios.ibuffer.buffer_curr)*sizeof(typename basic_io_buffer::char_type)}; +#if defined(_MSC_VER) + if(pos(static_cast(offset))) + { + pos=0; + sdir=seekdir::beg; + } + else + { + pos-=static_cast(static_cast(offset)); + } +#else +#if defined(__has_builtin) && __has_builtin(__builtin_sub_overflow) + if(__builtin_sub_overflow(pos,static_cast(offset),__builtin_addressof(pos))) + { + pos=0; + sdir=seekdir::beg; + } +#else + if(pos(static_cast(offset))) + { + pos=0; + sdir=seekdir::beg; + } + else + { + pos-=static_cast(static_cast(offset)); + } +#endif +#endif + } + } + std::uintmax_t new_position{seek(bios.handle,pos,sdir)}; + if constexpr((mde&buffer_mode::in)==buffer_mode::in) + { + bios.ibuffer.buffer_end=bios.ibuffer.buffer_curr=bios.ibuffer.buffer_begin; + } + return new_position; +} + +} diff --git a/src/fast_io/include/fast_io_freestanding_impl/io_buffer/input_deco.h b/src/fast_io/include/fast_io_freestanding_impl/io_buffer/input_deco.h new file mode 100644 index 0000000..c772063 --- /dev/null +++ b/src/fast_io/include/fast_io_freestanding_impl/io_buffer/input_deco.h @@ -0,0 +1,129 @@ +#pragma once + +namespace fast_io::details +{ + +template +inline constexpr bool ibuffer_underflow_rl_impl_deco(T t,decot deco, + basic_io_buffer_pointers_with_cap& ibuffer, + basic_io_buffer_pointers_only_begin& ibuffer_external, + std::size_t bfsz) +{ + using external_char_type = typename T::char_type; + if(ibuffer_external.buffer_begin==nullptr) + ibuffer_external.buffer_begin=allocate_iobuf_space(bfsz); + auto buffer_begin{ibuffer_external.buffer_begin}; + auto buffer_end{buffer_begin+bfsz}; + auto readed=buffer_begin; + for(;readed!=buffer_end;) + { + auto readed_after_this_round=read(t,readed,buffer_end); + if(readed_after_this_round==readed) + { + if(readed==buffer_begin) + return false; + break; + } + readed=readed_after_this_round; + } + using decot_nocvref_t = std::remove_cvref_t; + std::size_t readed_size{static_cast(readed-buffer_begin)}; + std::size_t new_size{deco_reserve_size(io_reserve_type,deco,readed_size)}; + std::size_t cap{static_cast(ibuffer.buffer_cap-ibuffer.buffer_begin)}; + if(cap(ibuffer.buffer_begin,cap); + ibuffer.buffer_cap=ibuffer.buffer_end=ibuffer.buffer_curr=ibuffer.buffer_begin=nullptr; + ibuffer.buffer_cap=(ibuffer.buffer_end=ibuffer.buffer_curr=ibuffer.buffer_begin= + allocate_iobuf_space(new_size))+new_size; + } + else + ibuffer.buffer_end=ibuffer.buffer_curr=ibuffer.buffer_begin; + using decot_nocvref_t = std::remove_cvref_t; + ibuffer.buffer_end=deco_reserve_define(io_reserve_type,deco,buffer_begin,readed,ibuffer.buffer_begin); + if(ibuffer.buffer_begin==ibuffer.buffer_end) + return false; + return true; +} + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline constexpr bool ibuffer_underflow_impl_deco(T t,decot deco,basic_io_buffer_pointers_with_cap& ibuffer, + basic_io_buffer_pointers_only_begin& ibuffer_external) +{ +#if 0 + if constexpr(maybe_noop_decorator) + { + + } +#endif + return ibuffer_underflow_rl_impl_deco(t,deco,ibuffer,ibuffer_external,bfsz); +} + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline constexpr Iter iobuf_read_unhappy_decay_impl_deco(T t,decot deco, + basic_io_buffer_pointers_with_cap& ibuffer, + basic_io_buffer_pointers_only_begin& ibuffer_external, + Iter first,Iter last,std::size_t bfsz) +{ + using external_char_type = typename T::char_type; + using internal_char_type = char_type; + if(ibuffer_external.buffer_begin==nullptr) + ibuffer_external.buffer_begin=allocate_iobuf_space(bfsz); + auto buffer_begin{ibuffer_external.buffer_begin}; + auto buffer_end{buffer_begin+bfsz}; + for(;first!=last;) + { + auto read_this_round{buffer_begin}; + for(;read_this_round!=buffer_end;) + { + auto readed_after_this_round=read(t,read_this_round,buffer_end); + if(readed_after_this_round==read_this_round) + { + if(read_this_round==buffer_begin) + return first; + break; + } + read_this_round=readed_after_this_round; + } + std::size_t readed_size{static_cast(read_this_round-buffer_begin)}; + using decot_nocvref_t = std::remove_cvref_t; + std::size_t new_size{deco_reserve_size(io_reserve_type,deco,readed_size)}; + std::size_t diff{static_cast(last-first)}; + if(new_size,deco,buffer_begin,read_this_round,first); + } + else + { + std::size_t cap{static_cast(ibuffer.buffer_cap-ibuffer.buffer_begin)}; + if(cap(ibuffer.buffer_begin,cap); + ibuffer.buffer_cap=ibuffer.buffer_end=ibuffer.buffer_curr=ibuffer.buffer_begin=nullptr; + ibuffer.buffer_cap=(ibuffer.buffer_end=ibuffer.buffer_curr=ibuffer.buffer_begin= + allocate_iobuf_space(new_size))+new_size; + } + else + ibuffer.buffer_end=ibuffer.buffer_curr=ibuffer.buffer_begin; + ibuffer.buffer_end=deco_reserve_define(io_reserve_type,deco, + buffer_begin,read_this_round,ibuffer.buffer_begin); + std::size_t need_to_copy{static_cast(ibuffer.buffer_end-ibuffer.buffer_begin)}; + if(need_to_copy==0) + return first; + if(diff +inline constexpr bool ibuffer_underflow_rl_impl(T t,basic_io_buffer_pointers& ibuffer,std::size_t bfsz) +{ + if(ibuffer.buffer_begin==nullptr) + ibuffer.buffer_end=ibuffer.buffer_curr=ibuffer.buffer_begin=allocate_iobuf_space(bfsz); + ibuffer.buffer_end=read(t,ibuffer.buffer_begin,ibuffer.buffer_begin+bfsz); + ibuffer.buffer_curr=ibuffer.buffer_begin; + return ibuffer.buffer_begin!=ibuffer.buffer_end; +} + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline constexpr bool ibuffer_underflow_impl(T t,basic_io_buffer_pointers& ibuffer) +{ + return ibuffer_underflow_rl_impl(t,ibuffer,bfsz); +} + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline constexpr Iter iobuf_read_unhappy_decay_impl(T t,basic_io_buffer_pointers& ibuffer,Iter first,Iter last,std::size_t buffer_size) +{ + std::size_t iter_diff(static_cast(last-first)); + if(buffer_size<=iter_diff) + return read(t,first,last); + if(ibuffer.buffer_begin==nullptr) + { + ibuffer.buffer_end=ibuffer.buffer_begin= + allocate_iobuf_space(buffer_size); + } + ibuffer.buffer_end=read(t,ibuffer.buffer_begin,ibuffer.buffer_begin+buffer_size); + ibuffer.buffer_curr=ibuffer.buffer_begin; + std::size_t diff(static_cast(ibuffer.buffer_end-ibuffer.buffer_begin)); + if(diff +struct basic_decorators +{ + using internal_type = ch_type; + using internal_decorator_type=internaltype; + using external_decorator_type=externaltype; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif + internal_decorator_type internal_decorator; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif + external_decorator_type external_decorator; +}; + +template +requires (!std::same_as) +inline constexpr auto internal_decorator(basic_decorators& decos) noexcept +{ + return io_deco_ref(decos.internal_decorator); +} + +template +requires (!std::same_as) +inline constexpr auto external_decorator(basic_decorators& decos) noexcept +{ + return io_deco_ref(decos.external_decorator); +} + +namespace details +{ + +template +inline constexpr void write_with_deco(T t,decot deco,Iter first,Iter last, + basic_io_buffer_pointers_no_curr& external_buffer, + std::size_t buffer_size) +{ + using external_char_type = typename T::char_type; + using decot_no_cvref_t = std::remove_cvref_t; +#if 0 + if constexpr(requires() + { + deco_reserve_size(io_reserve_type,deco,first,last) + }) + { + for(;first!=last;) + { + std::size_t this_round{buffer_size}; + std::size_t diff{static_cast(last-first)}; + if(diff,deco,first,last)}; + std::size_t current_buffer_size{external_buffer.buffer_end-external_buffer.buffer_begin}; + if(current_buffer_size(size)}; + deallocate_iobuf_space(external_buffer.buffer_begin,current_buffer_size); + } + } + } + else +#endif + { + if(external_buffer.buffer_begin==nullptr) + { + std::size_t size{deco_reserve_size(io_reserve_type,deco,buffer_size)}; + external_buffer.buffer_begin=allocate_iobuf_space(size); + external_buffer.buffer_end=external_buffer.buffer_begin+size; + } + for(auto buffer_begin{external_buffer.buffer_begin};first!=last;) + { + std::size_t this_round{buffer_size}; + std::size_t diff{static_cast(last-first)}; + if(diff,deco,first,first+this_round,buffer_begin)); + first+=this_round; + } + } +} + +template +concept has_internal_decorator_impl = requires(decorators_type&& decos) +{ + internal_decorator(decos); +}; + +template +concept has_external_decorator_impl = requires(decorators_type&& decos) +{ + external_decorator(decos); +}; + + +template +concept iobuffer_reopenable_impl = requires(handle_type handle,Args&& ...args) +{ + handle.reopen(::std::forward(args)...); +}; + +} + +template, +std::size_t bfs = io_default_buffer_size> +requires (details::constraint_buffer_mode(mde)) +class basic_io_buffer +{ +public: + using handle_type = handletype; + using decorators_type = decoratorstypr; + using char_type = typename decorators_type::internal_type; + using external_char_type = typename handle_type::char_type; + using pointer = char_type*; + using const_pointer = char_type const*; + inline static constexpr buffer_mode mode = mde; + inline static constexpr std::size_t buffer_size = bfs; + inline static constexpr bool need_secure_clear = (mode&buffer_mode::secure_clear)==buffer_mode::secure_clear; + inline static constexpr bool has_ibuffer=(mode&buffer_mode::in)==buffer_mode::in; + inline static constexpr bool has_obuffer=(mode&buffer_mode::out)==buffer_mode::out; + inline static constexpr bool has_internal_decorator = details::has_internal_decorator_impl; + inline static constexpr bool has_external_decorator = details::has_external_decorator_impl; + + using ibuffer_type = std::conditional_t,basic_io_buffer_pointers>, + empty_buffer_pointers>; + + using obuffer_type =std::conditional_t,empty_buffer_pointers>; + + using ibuffer_external_type = std::conditional_t, + basic_io_buffer_pointers_only_begin, + empty_buffer_pointers>; + + using obuffer_external_type = std::conditional_t<( + has_obuffer&& + details::has_external_decorator_impl), + basic_io_buffer_pointers_no_curr, + empty_buffer_pointers>; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif + ibuffer_type ibuffer; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif + obuffer_type obuffer; + +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif + ibuffer_external_type ibuffer_external; + +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif + obuffer_external_type obuffer_external; + +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif + handle_type handle; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif + decorators_type decorators; +private: + constexpr void close_throw_impl() + { + if constexpr((mode&buffer_mode::out)==buffer_mode::out&& + (mode&buffer_mode::deco_out_no_internal)!=buffer_mode::deco_out_no_internal) + { + if(obuffer.buffer_begin!=obuffer.buffer_curr) + { + if constexpr(details::has_external_decorator_impl) + { + details::write_with_deco(io_ref(handle), + external_decorator(decorators), + obuffer.buffer_begin,obuffer.buffer_curr, + obuffer_external,bfs); + } + else + { + write(io_ref(handle),obuffer.buffer_begin,obuffer.buffer_curr); + } + } + } + } + constexpr void close_impl() noexcept + { + if constexpr((mode&buffer_mode::out)==buffer_mode::out) + { +#if (defined(_MSC_VER)&&_HAS_EXCEPTIONS!=0) || (!defined(_MSC_VER)&&__cpp_exceptions) +#if __cpp_exceptions + try + { +#endif +#endif + close_throw_impl(); +#if (defined(_MSC_VER)&&_HAS_EXCEPTIONS!=0) || (!defined(_MSC_VER)&&__cpp_exceptions) +#if __cpp_exceptions + } + catch(...) + { + } +#endif +#endif + } + } + constexpr void cleanup_impl() noexcept + { + if constexpr((mode&buffer_mode::out)==buffer_mode::out) + { + if constexpr((mode&buffer_mode::deco_out_no_internal)!=buffer_mode::deco_out_no_internal) + { + if(obuffer.buffer_begin) + details::deallocate_iobuf_space(obuffer.buffer_begin,buffer_size); + } + if constexpr(details::has_external_decorator_impl) + { + if(obuffer_external.buffer_begin) + details::deallocate_iobuf_space( + obuffer_external.buffer_begin, + obuffer_external.buffer_end-obuffer_external.buffer_begin); + } + } + if constexpr((mode&buffer_mode::in)==buffer_mode::in) + { + if(ibuffer.buffer_begin) + { + if constexpr(details::has_internal_decorator_impl) + { + std::size_t real_buffer_cap{static_cast(ibuffer.buffer_cap-ibuffer.buffer_begin)}; + details::deallocate_iobuf_space(ibuffer.buffer_begin,real_buffer_cap); + } + else + { + details::deallocate_iobuf_space(ibuffer.buffer_begin,buffer_size); + } + } + if constexpr(details::has_internal_decorator_impl) + { + if(ibuffer_external.buffer_begin) + details::deallocate_iobuf_space( + ibuffer_external.buffer_begin, + buffer_size); + } + } + } +public: + + constexpr basic_io_buffer()=default; + template + requires (((mode&buffer_mode::construct_decorator)!=buffer_mode::construct_decorator)&&std::constructible_from) + explicit constexpr basic_io_buffer(Args&& ...args):handle(::std::forward(args)...){} + + template + requires (((mode&buffer_mode::construct_decorator)==buffer_mode::construct_decorator) + &&std::constructible_from) + explicit constexpr basic_io_buffer(decorators_type&& decos,Args&& ...args):handle(::std::forward(args)...), + decorators(::std::move(decos)){} + + constexpr basic_io_buffer(basic_io_buffer const& other) requires std::copyable:handle(other.handle),decorators(other.decorators){} + constexpr basic_io_buffer(basic_io_buffer const&)=delete; + constexpr basic_io_buffer& operator=(basic_io_buffer const& other) requires std::copyable + { + close_throw_impl(); + if constexpr((mode&buffer_mode::in)==buffer_mode::in) + ibuffer.buffer_curr=ibuffer.buffer_end; + if constexpr((mode&buffer_mode::out)==buffer_mode::out&& + (mode&buffer_mode::deco_out_no_internal)!=buffer_mode::deco_out_no_internal) + obuffer.buffer_curr=obuffer.buffer_begin; + handle=other.handle; + decorators=other.decorators; + return *this; + } + constexpr basic_io_buffer& operator=(basic_io_buffer const&)=delete; + template + requires (std::movable&&std::constructible_from)||(details::iobuffer_reopenable_impl) + constexpr void reopen(Args&& ...args) + { + close_impl(); + if constexpr((mode&buffer_mode::in)==buffer_mode::in) + ibuffer.buffer_curr=ibuffer.buffer_end; + if constexpr((mode&buffer_mode::out)==buffer_mode::out) + obuffer.buffer_curr=obuffer.buffer_begin; + if constexpr(details::iobuffer_reopenable_impl) + handle.reopen(::std::forward(args)...); + else + handle=handle_type(::std::forward(args)...); + } + constexpr void close() requires requires() + { + handle.close(); + } + { + close_throw_impl(); + if constexpr((mode&buffer_mode::in)==buffer_mode::in) + ibuffer.buffer_curr=ibuffer.buffer_end; + if constexpr((mode&buffer_mode::out)==buffer_mode::out&& + (mode&buffer_mode::deco_out_no_internal)!=buffer_mode::deco_out_no_internal) + obuffer.buffer_curr=obuffer.buffer_begin; + handle.close(); + } + constexpr basic_io_buffer(basic_io_buffer&& other) noexcept requires(std::movable): + ibuffer(other.ibuffer),obuffer(other.obuffer), + ibuffer_external(other.ibuffer_external),obuffer_external(other.obuffer_external), + handle(::std::move(other.handle)),decorators(::std::move(other.decorators)) + { + other.ibuffer={}; + other.obuffer={}; + other.ibuffer_external={}; + other.obuffer_external={}; + } + constexpr basic_io_buffer(basic_io_buffer&&) noexcept=delete; +#if __cpp_constexpr_dynamic_alloc >= 201907L + constexpr +#endif + basic_io_buffer& operator=(basic_io_buffer&& __restrict other) noexcept requires(std::movable) + { + if constexpr((mode&buffer_mode::out)==buffer_mode::out) + close_impl(); + cleanup_impl(); + ibuffer=other.ibuffer; + other.ibuffer={}; + obuffer=other.obuffer; + other.obuffer={}; + ibuffer_external=other.ibuffer_external; + other.ibuffer_external={}; + obuffer_external=other.obuffer_external; + other.obuffer_external={}; + handle=::std::move(other.handle); + decorators=::std::move(other.decorators); + return *this; + } + constexpr basic_io_buffer& operator=(basic_io_buffer&& __restrict)=delete; + constexpr void swap(basic_io_buffer&& other) noexcept requires std::swappable + { + std::ranges::swap(ibuffer,other.ibuffer); + std::ranges::swap(obuffer,other.obuffer); + std::ranges::swap(ibuffer_external,other.ibuffer_external); + std::ranges::swap(obuffer_external,other.obuffer_external); + std::ranges::swap(handle,other.handle); + std::ranges::swap(decorators,other.decorators); + } +#if __cpp_constexpr_dynamic_alloc >= 201907L + constexpr +#endif + ~basic_io_buffer() + { + if constexpr((mode&buffer_mode::out)==buffer_mode::out) + close_impl(); + cleanup_impl(); + } +}; + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_freestanding_impl/io_buffer/mode.h b/src/fast_io/include/fast_io_freestanding_impl/io_buffer/mode.h new file mode 100644 index 0000000..f725b96 --- /dev/null +++ b/src/fast_io/include/fast_io_freestanding_impl/io_buffer/mode.h @@ -0,0 +1,109 @@ +#pragma once + +namespace fast_io +{ + +enum class buffer_mode +{ +in=1<<0, +out=1<<1, +tie=1<<2, +io=in|out|tie, +secure_clear=1<<3, +construct_decorator=1<<4, +deco_out_no_internal=(1<<5)|(out) +}; + +inline constexpr buffer_mode operator&(buffer_mode x, buffer_mode y) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(static_cast(x) & static_cast(y)); +} + +inline constexpr buffer_mode operator|(buffer_mode x, buffer_mode y) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(static_cast(x) | static_cast(y)); +} + +inline constexpr buffer_mode operator^(buffer_mode x, buffer_mode y) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(static_cast(x) ^ static_cast(y)); +} + +inline constexpr buffer_mode operator~(buffer_mode x) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(~static_cast(x)); +} + +inline constexpr buffer_mode& operator&=(buffer_mode& x, buffer_mode y) noexcept{return x=x&y;} + +inline constexpr buffer_mode& operator|=(buffer_mode& x, buffer_mode y) noexcept{return x=x|y;} + +inline constexpr buffer_mode& operator^=(buffer_mode& x, buffer_mode y) noexcept{return x=x^y;} + + +template +inline constexpr std::size_t io_default_buffer_size = details::cal_buffer_size(); + +struct empty_buffer_pointers +{}; + +template +struct basic_io_buffer_pointers +{ + using value_type = T; + using pointer = T*; + pointer buffer_begin{},buffer_curr{},buffer_end{}; +}; + +template +struct basic_io_buffer_pointers_with_cap +{ + using value_type = T; + using pointer = T*; + pointer buffer_begin{},buffer_curr{},buffer_end{},buffer_cap{}; +}; + +template +struct basic_io_buffer_pointers_only_begin +{ + using value_type = T; + using pointer = T*; + pointer buffer_begin{}; +}; + +template +struct basic_io_buffer_pointers_no_curr +{ + using value_type = T; + using pointer = T*; + pointer buffer_begin{},buffer_end{}; +}; + +namespace details +{ +template +inline +#if __cpp_consteval >= 201811L +consteval +#else +constexpr +#endif +bool constraint_buffer_mode(buffer_mode mode) noexcept +{ + if(((mode&buffer_mode::in)==buffer_mode::in)&&(!input_stream)) + return false; + if(((mode&buffer_mode::out)==buffer_mode::out)&&(!output_stream)) + return false; + if constexpr(secure_clear_requirement_stream) + if((mode&buffer_mode::secure_clear)!=buffer_mode::secure_clear) + return false; + return true; +} + +} + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_freestanding_impl/io_buffer/output.h b/src/fast_io/include/fast_io_freestanding_impl/io_buffer/output.h new file mode 100644 index 0000000..02ce039 --- /dev/null +++ b/src/fast_io/include/fast_io_freestanding_impl/io_buffer/output.h @@ -0,0 +1,231 @@ +#pragma once +#include"output_normal.h" +#include"output_deco.h" + +namespace fast_io +{ + +namespace details +{ + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline constexpr void iobuf_write_unhappy_impl(T& t,Iter first,Iter last) +{ + if constexpr(has_external_decorator_impl) + iobuf_write_unhappy_decay_impl_deco(io_ref(t.handle), + external_decorator(t.decorators), + t.obuffer, + t.obuffer_external, + first,last); + else + iobuf_write_unhappy_decay_impl(io_ref(t.handle),t.obuffer,first,last); +} + +} + +template +requires (((mde&buffer_mode::out)==buffer_mode::out)&&details::allow_iobuf_punning) +inline constexpr void write(basic_io_buffer& bios,Iter first,Iter last) +{ + using iter_char_type = ::std::iter_value_t; + using char_type = typename decorators::internal_type; + if constexpr(std::same_as) + { + if constexpr(::std::contiguous_iterator&&!std::is_pointer_v) + write(bios,::std::to_address(first),::std::to_address(last)); + else + { + if constexpr((mde&buffer_mode::deco_out_no_internal)==buffer_mode::deco_out_no_internal) + { + details::write_with_deco(io_ref(bios.handle), + external_decorator(bios.decorators), + first,last, + bios.obuffer_external,bfs); + } + else + { + std::size_t diff{static_cast(last-first)}; + std::size_t remain_space{static_cast(bios.obuffer.buffer_end-bios.obuffer.buffer_curr)}; + if(remain_space(::std::to_address(first)), + reinterpret_cast(::std::to_address(last))); +} + + +template +requires ((mde&buffer_mode::out)==buffer_mode::out&& +(mde&buffer_mode::deco_out_no_internal)!=buffer_mode::deco_out_no_internal) +inline constexpr auto obuffer_begin(basic_io_buffer& bios) noexcept +{ + return bios.obuffer.buffer_begin; +} + + +template +requires ((mde&buffer_mode::out)==buffer_mode::out&& +(mde&buffer_mode::deco_out_no_internal)!=buffer_mode::deco_out_no_internal) +inline constexpr auto obuffer_curr(basic_io_buffer& bios) noexcept +{ + return bios.obuffer.buffer_curr; +} + +template +requires ((mde&buffer_mode::out)==buffer_mode::out) +inline constexpr auto obuffer_end(basic_io_buffer& bios) noexcept +{ + return bios.obuffer.buffer_end; +} + +template +requires ((mde&buffer_mode::out)==buffer_mode::out&& +(mde&buffer_mode::deco_out_no_internal)!=buffer_mode::deco_out_no_internal) +inline constexpr void obuffer_set_curr(basic_io_buffer& bios,typename basic_io_buffer::char_type* ptr) noexcept +{ + bios.obuffer.buffer_curr=ptr; +} + +template +requires ((mde&buffer_mode::out)==buffer_mode::out&& +(mde&buffer_mode::deco_out_no_internal)!=buffer_mode::deco_out_no_internal) +inline constexpr void obuffer_overflow(basic_io_buffer& bios, + typename basic_io_buffer::char_type ch) +{ + if constexpr(details::has_external_decorator_impl) + details::iobuf_overflow_impl_deco(io_ref(bios.handle),external_decorator(bios.decorators),bios.obuffer,bios.obuffer_external,ch,bfs); + else + details::iobuf_overflow_impl(io_ref(bios.handle),bios.obuffer,ch,bfs); +} + +template +requires ((mde&buffer_mode::out)==buffer_mode::out&&!details::has_external_decorator_impl) +inline constexpr decltype(auto) zero_copy_out_handle(basic_io_buffer& bios) +{ + return zero_copy_out_handle(bios.handle); +} + +namespace details +{ + +template +concept has_file_lock_type_impl = requires(T t) +{ + file_lock(io_ref(t)); +}; + +} + +template +struct basic_io_buffer_file_lock +{ + basic_io_buffer* ptr{}; + template + constexpr void lock(RequestType& req) + { + flush(*ptr); + if constexpr(::fast_io::details::has_file_lock_type_impl) + { + file_lock(io_ref(ptr->handle)).lock(req); + } + } + template + constexpr void unlock(RequestType& req) noexcept + { +#if (defined(_MSC_VER)&&_HAS_EXCEPTIONS!=0) || (!defined(_MSC_VER)&&__cpp_exceptions) +#if __cpp_exceptions + try + { +#endif +#endif + flush(*ptr); +#if (defined(_MSC_VER)&&_HAS_EXCEPTIONS!=0) || (!defined(_MSC_VER)&&__cpp_exceptions) +#if __cpp_exceptions + } + catch(...) + { + } +#endif +#endif + if constexpr(::fast_io::details::has_file_lock_type_impl) + { + file_lock(io_ref(ptr->handle)).unlock(req); + } + } + template + constexpr bool try_lock(RequestType& req) + { +#if (defined(_MSC_VER)&&_HAS_EXCEPTIONS!=0) || (!defined(_MSC_VER)&&__cpp_exceptions) +#if __cpp_exceptions + try + { +#endif +#endif + flush(*ptr); +#if (defined(_MSC_VER)&&_HAS_EXCEPTIONS!=0) || (!defined(_MSC_VER)&&__cpp_exceptions) +#if __cpp_exceptions + } + catch(...) + { + return false; + } +#endif +#endif + if constexpr(::fast_io::details::has_file_lock_type_impl) + { + return file_lock(io_ref(ptr->handle)).try_lock(req); + } + else + { + return true; + } + } +}; + +template +inline constexpr decltype(auto) file_lock(basic_io_buffer& bios) +{ + return basic_io_buffer_file_lock{__builtin_addressof(bios)}; +} + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_freestanding_impl/io_buffer/output_deco.h b/src/fast_io/include/fast_io_freestanding_impl/io_buffer/output_deco.h new file mode 100644 index 0000000..fa89140 --- /dev/null +++ b/src/fast_io/include/fast_io_freestanding_impl/io_buffer/output_deco.h @@ -0,0 +1,88 @@ +#pragma once + +namespace fast_io::details +{ + +template +inline constexpr void iobuf_write_unhappy_decay_no_alloc_impl_deco(T t,decot deco, + basic_io_buffer_pointers& pointers, + basic_io_buffer_pointers_no_curr& external_buffer, + Iter first,Iter last,std::size_t buffer_size) +{ + std::size_t const remain_space(pointers.buffer_end-pointers.buffer_curr); + non_overlapped_copy_n(first,remain_space,pointers.buffer_curr); + first+=remain_space; + write_with_deco(t,deco,pointers.buffer_begin,pointers.buffer_end, + external_buffer,buffer_size); + pointers.buffer_curr=pointers.buffer_begin; + std::size_t const new_remain_space(last-first); + if(buffer_size +inline constexpr void iobuf_write_unhappy_decay_impl_deco( + T t,decot deco, + basic_io_buffer_pointers& pointers, + basic_io_buffer_pointers_no_curr& external_buffer, + Iter first,Iter last) +{ + std::size_t const diff(static_cast(last-first)); + if(pointers.buffer_begin==nullptr) + { + if(diff +inline constexpr void iobuf_output_flush_impl_deco(T handle,decot deco, + basic_io_buffer_pointers& pointers, + basic_io_buffer_pointers_no_curr& external_buffer,std::size_t bfsz) +{ + if(pointers.buffer_curr==pointers.buffer_begin) + return; + write_with_deco(handle,deco, + pointers.buffer_begin, + pointers.buffer_curr, + external_buffer,bfsz); + pointers.buffer_curr=pointers.buffer_begin; +} + +template +inline constexpr void iobuf_output_constant_flush_prepare_impl_deco(T handle,decot deco, + basic_io_buffer_pointers& pointers, + basic_io_buffer_pointers_no_curr& external_buffer, + std::size_t bfsz) +{ + if(pointers.buffer_begin==nullptr) + { + iobuf_write_allocate_buffer_impl(pointers,bfsz); + } + else + { + iobuf_output_flush_impl_deco(handle,deco,pointers,external_buffer,bfsz); + } +} + +template +inline constexpr void iobuf_overflow_impl_deco(T handle,decot deco, + basic_io_buffer_pointers& pointers, + basic_io_buffer_pointers_no_curr& external_buffer, + char_type ch,std::size_t bfsz) +{ + iobuf_output_constant_flush_prepare_impl_deco(handle,deco,pointers,external_buffer,bfsz); + *pointers.buffer_curr=ch; + ++pointers.buffer_curr; +} + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_freestanding_impl/io_buffer/output_normal.h b/src/fast_io/include/fast_io_freestanding_impl/io_buffer/output_normal.h new file mode 100644 index 0000000..6a5ced0 --- /dev/null +++ b/src/fast_io/include/fast_io_freestanding_impl/io_buffer/output_normal.h @@ -0,0 +1,124 @@ +#pragma once + +namespace fast_io::details +{ + + +template +concept allow_iobuf_punning = ::std::contiguous_iterator&& +//temporary only allow contiguous_iterator before we finish this part +(std::same_as>|| +(std::same_as&&::std::contiguous_iterator)); + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline constexpr void iobuf_write_allocate_buffer_impl(basic_io_buffer_pointers& obuffer,std::size_t buffer_size) +{ + obuffer.buffer_end=(obuffer.buffer_curr=obuffer.buffer_begin= + allocate_iobuf_space(buffer_size))+buffer_size; +} + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline constexpr void iobuf_write_unhappy_nullptr_case_impl(basic_io_buffer_pointers& obuffer,Iter first,Iter last,std::size_t buffer_size) +{ + iobuf_write_allocate_buffer_impl(obuffer,buffer_size); + obuffer.buffer_curr=non_overlapped_copy(first,last,obuffer.buffer_curr); +} + +template +inline constexpr void iobuf_write_unhappy_decay_no_alloc_impl(T t,basic_io_buffer_pointers& pointers,Iter first,Iter last,std::size_t buffer_size) +{ + if constexpr(false) + { + std::size_t const remain_space{static_cast(pointers.buffer_end-pointers.buffer_curr)}; + non_overlapped_copy_n(first,remain_space,pointers.buffer_curr); + first+=remain_space; + write(t,pointers.buffer_begin,pointers.buffer_end); + pointers.buffer_curr=pointers.buffer_begin; + std::size_t const new_remain_space{static_cast(last-first)}; + if(buffer_size) + { + io_scatter_t scatters[2]{ + {pointers.buffer_begin, + static_cast(pointers.buffer_curr-pointers.buffer_begin)*sizeof(char_type)}, + { + first, + static_cast(last-first)*sizeof(char_type) + }}; + scatter_write(t,io_scatters_t{scatters,2}); + } + else + { + write(t,pointers.buffer_begin,pointers.buffer_curr); + write(t,first,last); + } + pointers.buffer_curr=pointers.buffer_begin; + } +} + +template +inline constexpr void iobuf_write_unhappy_decay_impl(T t,basic_io_buffer_pointers& pointers,Iter first,Iter last) +{ + std::size_t const diff{static_cast(last-first)}; + if(pointers.buffer_begin==nullptr) + { + if(diff +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline constexpr void iobuf_output_flush_impl(T handle, + basic_io_buffer_pointers& pointers) +{ + if(pointers.buffer_curr==pointers.buffer_begin) + return; + write(handle,pointers.buffer_begin,pointers.buffer_curr); + pointers.buffer_curr=pointers.buffer_begin; +} + +template +inline constexpr void iobuf_output_constant_flush_prepare_impl(T handle, + basic_io_buffer_pointers& pointers,std::size_t buffer_size) +{ + if(pointers.buffer_begin==nullptr) + { + iobuf_write_allocate_buffer_impl(pointers,buffer_size); + } + else + { + iobuf_output_flush_impl(handle,pointers); + } +} + +template +inline constexpr void iobuf_overflow_impl(T handle, + basic_io_buffer_pointers& pointers,char_type ch,std::size_t bfsz) +{ + iobuf_output_constant_flush_prepare_impl(handle,pointers,bfsz); + *pointers.buffer_curr=ch; + ++pointers.buffer_curr; +} + +} diff --git a/src/fast_io/include/fast_io_freestanding_impl/scanners/impl.h b/src/fast_io/include/fast_io_freestanding_impl/scanners/impl.h new file mode 100644 index 0000000..408820d --- /dev/null +++ b/src/fast_io/include/fast_io_freestanding_impl/scanners/impl.h @@ -0,0 +1,3 @@ +#pragma once + +#include"line_scanner.h" diff --git a/src/fast_io/include/fast_io_freestanding_impl/scanners/line_scanner.h b/src/fast_io/include/fast_io_freestanding_impl/scanners/line_scanner.h new file mode 100644 index 0000000..a417b5b --- /dev/null +++ b/src/fast_io/include/fast_io_freestanding_impl/scanners/line_scanner.h @@ -0,0 +1,243 @@ +#pragma once + +namespace fast_io +{ + +template +struct basic_line_scanner_buffer +{ + struct buffer_type + { + char_type *begin_ptr{}; + char_type *curr_ptr{}; + char_type *end_ptr{}; + constexpr buffer_type() noexcept:begin_ptr(nullptr),curr_ptr(nullptr),end_ptr(nullptr) + {} + buffer_type(buffer_type const&)=delete; + buffer_type& operator=(buffer_type const&)=delete; + constexpr buffer_type(buffer_type&& __restrict other) noexcept:begin_ptr(other.begin_ptr),curr_ptr(other.curr_ptr),end_ptr(other.end_ptr) + { + other.end_ptr=other.curr_ptr=other.begin_ptr=nullptr; + } + constexpr buffer_type& operator=(buffer_type&& __restrict other) noexcept + { + ::fast_io::details::deallocate_iobuf_space(this->begin_ptr,static_cast(this->end_ptr-this->begin_ptr)); + this->begin_ptr=other.begin_ptr; + this->curr_ptr=other.curr_ptr; + this->end_ptr=other.end_ptr; + other.end_ptr=other.curr_ptr=other.begin_ptr=nullptr; + } + constexpr ~buffer_type() + { + ::fast_io::details::deallocate_iobuf_space(this->begin_ptr,static_cast(this->end_ptr-this->begin_ptr)); + } + }; + buffer_type buffer; + char_type const* view_begin_ptr{}; + char_type const* view_end_ptr{}; + bool inbuffer{}; + constexpr char_type const* begin() const noexcept + { + return view_begin_ptr; + } + constexpr char_type const* end() const noexcept + { + return view_end_ptr; + } +}; + +template +struct basic_line_scanner_contiguous_view +{ + char_type const* view_begin_ptr{}; + char_type const* view_end_ptr{}; + constexpr char_type const* begin() const noexcept + { + return view_begin_ptr; + } + constexpr char_type const* end() const noexcept + { + return view_end_ptr; + } +}; + +namespace details +{ + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline constexpr void copy_to_next_line_buffer_internal_impl(basic_line_scanner_buffer& __restrict buf,char_type const* first,std::size_t sz) noexcept +{ + auto bg_ptr{buf.buffer.begin_ptr}; + std::size_t const elements{static_cast(buf.buffer.curr_ptr-bg_ptr)}; + std::size_t const elementswithnewbuff{elements+sz}; + std::size_t const old_capacity{static_cast(buf.buffer.end_ptr-bg_ptr)}; + constexpr std::size_t szmx{std::numeric_limits::max()/sizeof(char_type)}; + constexpr std::size_t szmxhalf{szmx/static_cast(2u)}; + std::size_t new_capacity; + if(old_capacity>=szmxhalf) + { + new_capacity=szmx; + } + else + { + new_capacity=old_capacity; + new_capacity<<=1u; + } + if(new_capacity(new_capacity)}; + auto new_curr_ptr{non_overlapped_copy_n(bg_ptr,elements,new_begin_ptr)}; + new_curr_ptr=non_overlapped_copy_n(first,sz,new_curr_ptr); + ::fast_io::details::deallocate_iobuf_space(bg_ptr,old_capacity); + buf.buffer.begin_ptr=new_begin_ptr; + buf.buffer.curr_ptr=new_curr_ptr; + buf.buffer.end_ptr=new_begin_ptr+new_capacity; +} + +template +inline constexpr void copy_to_next_line_buffer_impl(basic_line_scanner_buffer& __restrict buf,char_type const* first,char_type const* last) noexcept +{ + auto curr_ptr{buf.buffer.curr_ptr}; + std::size_t bfsz{static_cast(buf.buffer.end_ptr-curr_ptr)}; + std::size_t diff{static_cast(last-first)}; + if(bfsz +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline constexpr parse_result scan_iterative_next_line_define_partial(basic_line_scanner_buffer& __restrict buf,char_type const* first,char_type const* last) noexcept +{ + if(!buf.inbuffer) + { + buf.inbuffer=true; + buf.buffer.curr_ptr=buf.buffer.begin_ptr; + } + copy_to_next_line_buffer_impl(buf,first,last); + return {last,::fast_io::parse_code::partial}; +} + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline constexpr parse_result scan_iterative_next_line_define_inbuffer(basic_line_scanner_buffer& __restrict buf,char_type const* first,char_type const* it) noexcept +{ + copy_to_next_line_buffer_impl(buf,first,it); + buf.view_begin_ptr=buf.buffer.begin_ptr; + buf.view_end_ptr=buf.buffer.curr_ptr; + return {it+1,::fast_io::parse_code::ok}; +} + +template +inline constexpr parse_result scan_iterative_next_line_define_impl( + basic_line_scanner_buffer& __restrict buf,char_type const* first,char_type const* last) noexcept +{ + auto it{::fast_io::find_lf(first,last)}; + if(it==last)[[unlikely]] + { + return scan_iterative_next_line_define_partial(buf,first,last); + } + if(buf.inbuffer)[[unlikely]] + { + return scan_iterative_next_line_define_inbuffer(buf,first,it); + } + buf.view_begin_ptr=first; + buf.view_end_ptr=it; + return {it+1,::fast_io::parse_code::ok}; +} + +template +inline constexpr parse_code scan_iterative_eof_define_line_internal(basic_line_scanner_buffer& __restrict buf) noexcept +{ + if(buf.inbuffer) + { + buf.view_begin_ptr=buf.buffer.begin_ptr; + buf.view_end_ptr=buf.buffer.curr_ptr; + return parse_code::ok; + } + else + { + buf.view_end_ptr=buf.view_begin_ptr=nullptr; + return parse_code::end_of_file; + } +} + +template +inline constexpr parse_result scan_iterative_contiguous_line_define_impl( + basic_line_scanner_contiguous_view& __restrict buf,char_type const* first,char_type const* last) noexcept +{ + auto it{::fast_io::find_lf(first,last)}; + if(it==last)[[unlikely]] + { + if(first==it) + { + return {it,parse_code::end_of_file}; + } + return {it,parse_code::ok}; + } + buf.view_begin_ptr=first; + buf.view_end_ptr=it; + return {it+1,parse_code::ok}; +} + +} + +template +inline constexpr void scan_iterative_init_define(io_reserve_type_t>, + basic_line_scanner_buffer& __restrict buf) noexcept +{ + buf.inbuffer=false; +} + +template +inline constexpr parse_result scan_iterative_next_define(io_reserve_type_t>, + basic_line_scanner_buffer& __restrict buf,char_type const* first,char_type const* last) noexcept +{ + return ::fast_io::details::scan_iterative_next_line_define_impl(buf,first,last); +} + +template +inline constexpr parse_code scan_iterative_eof_define(io_reserve_type_t>, + basic_line_scanner_buffer& __restrict buf) noexcept +{ + return ::fast_io::details::scan_iterative_eof_define_line_internal(buf); +} + +template +inline constexpr parse_result scan_iterative_contiguous_define(io_reserve_type_t>, + basic_line_scanner_contiguous_view& __restrict buf,char_type const* first,char_type const* last) noexcept +{ + return ::fast_io::details::scan_iterative_contiguous_line_define_impl(buf,first,last); +} + +template +inline constexpr auto line_scanner(input&& in) noexcept(noexcept(io_ref(in))) +{ + using char_type = typename std::remove_cvref_t::char_type; + if constexpr(mutex_stream) + { + return basic_scanner_context_mutex>(io_ref(in)); + } + else if constexpr(contiguous_input_stream) + { + return basic_scanner_context>{io_ref(in)}; + } + else + { + return basic_scanner_context>{io_ref(in)}; + } +} + +} diff --git a/src/fast_io/include/fast_io_freestanding_impl/serializations/impl.h b/src/fast_io/include/fast_io_freestanding_impl/serializations/impl.h new file mode 100644 index 0000000..1aeda1d --- /dev/null +++ b/src/fast_io/include/fast_io_freestanding_impl/serializations/impl.h @@ -0,0 +1,7 @@ +#pragma once + +#include"lebe.h" +#include"leb128.h" +#include"str_get.h" +#include"strlike_get.h" +#include"wasm.h" diff --git a/src/fast_io/include/fast_io_freestanding_impl/serializations/leb128.h b/src/fast_io/include/fast_io_freestanding_impl/serializations/leb128.h new file mode 100644 index 0000000..461aa44 --- /dev/null +++ b/src/fast_io/include/fast_io_freestanding_impl/serializations/leb128.h @@ -0,0 +1,291 @@ +#pragma once + +namespace fast_io +{ + +namespace manipulators +{ + +template +struct basic_leb128_get_put +{ + using manip_tag = manip_tag_t; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) + [[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) + [[no_unique_address]] +#endif +#endif + value_type reference; +}; + +template<::fast_io::details::my_integral T> +inline constexpr auto leb128_put(T t) noexcept +{ + if constexpr(::fast_io::details::my_unsigned_integral) + { + if constexpr(sizeof(T)<=sizeof(unsigned)) + { + return ::fast_io::manipulators::basic_leb128_get_put{static_cast(t)}; + } + else if constexpr(sizeof(T)<=sizeof(::std::size_t)) + { + return ::fast_io::manipulators::basic_leb128_get_put<::std::size_t>{static_cast<::std::size_t>(t)}; + } + else + { + return ::fast_io::manipulators::basic_leb128_get_put>{t}; + } + } + else + { + if constexpr(sizeof(T)<=sizeof(int)) + { + return ::fast_io::manipulators::basic_leb128_get_put{static_cast(t)}; + } + else if constexpr(sizeof(T)<=sizeof(::std::ptrdiff_t)) + { + return ::fast_io::manipulators::basic_leb128_get_put<::std::ptrdiff_t>{static_cast<::std::ptrdiff_t>(t)}; + } + else + { + return ::fast_io::manipulators::basic_leb128_get_put>{t}; + } + } +} + +template<::fast_io::details::my_integral T> +inline constexpr auto leb128_get(T & t) noexcept +{ + return basic_leb128_get_put{ __builtin_addressof(t) }; +} + +} + +namespace details +{ + +template<::fast_io::details::my_integral T> +inline constexpr std::size_t print_reserve_size_leb128_length() noexcept +{ + constexpr std::size_t digits{ + ::std::numeric_limits::digits*sizeof(T)}; + constexpr std::size_t seven{7}; + constexpr std::size_t digitsdiv7{digits/seven}; + constexpr bool notsevenmul{(digits%seven)!=0}; + constexpr std::size_t urret{notsevenmul+digitsdiv7}; + return urret; +} + +template<::fast_io::details::my_integral T> +inline constexpr std::size_t leb128_length_val{print_reserve_size_leb128_length()}; + +} + +template +inline constexpr std::size_t print_reserve_size(io_reserve_type_t>) noexcept +{ + return ::fast_io::details::leb128_length_val; +} + +namespace details +{ + +template +inline constexpr char_type* pr_rsv_leb128_impl(char_type* iter,T value) noexcept +{ + using unsigned_char_type = + ::std::make_unsigned_t; + for(;;++iter) + { + unsigned_char_type temp{static_cast(value&0x7f)}; + value >>= 7; + if constexpr(::fast_io::details::my_unsigned_integral) + { + if(!value) + { + *iter=temp; + return ++iter; + } + } + else + { + bool iszero{!value}; + if(iszero|(value==-1)) + { + bool const m{(temp&0x40)!=0}; + if(iszero!=m) + { + *iter=temp; + return ++iter; + } + } + } + *iter=static_cast(static_cast(temp|0x80)); + } +} + +} + +template +inline constexpr char_type* print_reserve_define( + io_reserve_type_t>, + char_type *iter, + ::fast_io::manipulators::basic_leb128_get_put v) noexcept +{ + return ::fast_io::details::pr_rsv_leb128_impl(iter,v.reference); +} + +struct leb128_scan_state_t +{ + std::size_t group_count{}; +}; + +template +inline constexpr +io_type_t scan_context_type(io_reserve_type_t>) noexcept +{ + return {}; +} + +namespace details +{ +template +inline constexpr parse_result scn_ctx_define_leb128_impl( + std::size_t& group_count, + char_type const* begin, char_type const* end, + I& t) noexcept +{ + using unsigned_char_type = std::make_unsigned_t; + using U = ::fast_io::details::my_make_unsigned_t; + constexpr auto digits{ std::numeric_limits::digits }; + constexpr auto remains{ digits % 7 }; + U tmp{}; + std::size_t cnt{ group_count }; + if (cnt == 0) + t = 0; + for (; begin != end; cnt += 7) + { + if constexpr(8<::std::numeric_limits::digits) + { + constexpr unsigned_char_type digits256{static_cast(256)}; + if(digits256<=static_cast(*begin)) + { + return { begin, parse_code::invalid}; + } + } + bool sign = static_cast(*begin) & 0x80; + std::uint_fast8_t byte{static_cast(static_cast(*begin) & 0x7f)}; + ++begin; + if constexpr (::fast_io::details::my_signed_integral) + { + constexpr auto lower_limit{ remains ? 1u << (remains - 1) : 0 }; + constexpr auto upper_limit{ remains ? (0xffu << (remains - 1)) & 0x7f : 0x7f }; + if (cnt > digits - 7 && (cnt > digits || (byte >= lower_limit && byte < upper_limit))) [[unlikely]] + return { begin, parse_code::overflow }; + } + else + { + if (cnt > digits - 7 && (cnt > digits || byte >= (1u << remains))) [[unlikely]] + return { begin, parse_code::overflow }; + } + tmp |= static_cast(byte) << cnt; + if (!sign) + { + if constexpr (::fast_io::details::my_signed_integral) + { + if (byte & 0x40 && cnt < digits - 7) + tmp |= static_cast(-1) << (cnt + 7); + } + t |= tmp; + return { begin, parse_code::ok }; + } + } + t |= tmp; + group_count = cnt; + return { begin, parse_code::partial }; +} + +template +inline constexpr parse_result + scn_cnt_define_leb128_impl(char_type const* begin, char_type const* end,I& t) noexcept +{ + using unsigned_char_type = std::make_unsigned_t; + using U = ::fast_io::details::my_make_unsigned_t; + constexpr auto digits{ std::numeric_limits::digits }; + constexpr auto remains{ digits % 7 }; + U tmp{}; + std::size_t cnt{}; + t = 0; + for (; begin != end; cnt += 7) + { + if constexpr(8<::std::numeric_limits::digits) + { + constexpr unsigned_char_type digits256{static_cast(256)}; + if(digits256<=static_cast(*begin)) + { + return { begin, parse_code::invalid}; + } + } + bool sign = static_cast(*begin) & 0x80; + std::uint_fast8_t byte{static_cast(static_cast(*begin) & 0x7f)}; + ++begin; + if constexpr (::fast_io::details::my_signed_integral) + { + constexpr auto lower_limit{ remains ? 1u << (remains - 1) : 0 }; + constexpr auto upper_limit{ remains ? (0xffu << (remains - 1)) & 0x7f : 0x7f }; + if (cnt > digits - 7 && (cnt > digits || (byte >= lower_limit && byte < upper_limit))) [[unlikely]] + return { begin, parse_code::overflow }; + } + else + { + if (cnt > digits - 7 && (cnt > digits || byte >= (1u << remains))) [[unlikely]] + return { begin, parse_code::overflow }; + } + tmp |= static_cast(byte) << cnt; + if (!sign) + { + if constexpr (::fast_io::details::my_signed_integral) + { + if (byte & 0x40 && cnt < digits - 7) + tmp |= static_cast(-1) << (cnt + 7); + } + t |= tmp; + return { begin, parse_code::ok }; + } + } + return { begin, parse_code::invalid }; +} + +} + +template +inline constexpr parse_result scan_context_define( + io_reserve_type_t>, + leb128_scan_state_t& state, + char_type const* begin, char_type const* end, + manipulators::basic_leb128_get_put t) noexcept +{ + return ::fast_io::details::scn_ctx_define_leb128_impl(state.group_count,begin,end,*t.reference); +} + +template +inline constexpr parse_code scan_context_eof_define(io_reserve_type_t>, leb128_scan_state_t&, manipulators::basic_leb128_get_put) noexcept +{ + return parse_code::end_of_file; +} + +template +inline constexpr +parse_result scan_contiguous_define( + io_reserve_type_t>, + char_type const* begin, char_type const* end, + manipulators::basic_leb128_get_put t) noexcept +{ + return ::fast_io::details::scn_cnt_define_leb128_impl(begin,end,*t.reference); +} + +} diff --git a/src/fast_io/include/fast_io_freestanding_impl/serializations/lebe.h b/src/fast_io/include/fast_io_freestanding_impl/serializations/lebe.h new file mode 100644 index 0000000..98e5362 --- /dev/null +++ b/src/fast_io/include/fast_io_freestanding_impl/serializations/lebe.h @@ -0,0 +1,615 @@ +#pragma once + +namespace fast_io::details +{ + +template<::std::size_t sz> +inline constexpr bool supported_lebe_size{sz==8||sz==16||sz==32||sz==64||sz==128}; + +#ifdef __SIZEOF_INT128__ +using pesudo_int128type = __uint128_t; +#else +struct pesudo_int128type +{ + ::std::uint_least64_t uarr[2]; +}; +#endif + +template +inline constexpr ::std::size_t cal_size_lebe_floatsize() noexcept +{ + using nocvref = ::std::remove_cvref_t; + if constexpr(::std::same_as) + { + return 32; + } + else if constexpr(::std::same_as) + { + return 64; + } + else if constexpr(::std::same_as) + { + return 128; + } + else if constexpr(sizeof(nocvref)==sizeof(::std::uint_least8_t)) + { + return 8; + } + else if constexpr(sizeof(nocvref)==sizeof(::std::uint_least16_t)) + { + return 16; + } + else if constexpr(sizeof(nocvref)==sizeof(::std::uint_least32_t)) + { + return 32; + } + else if constexpr(sizeof(nocvref)==sizeof(::std::uint_least64_t)) + { + return 64; + } + else if constexpr(sizeof(nocvref)==sizeof(pesudo_int128type)) + { + return 128; + } + else + { + return 0; + } +} + +template +inline constexpr ::std::size_t size_lebe_float_size{::fast_io::details::cal_size_lebe_floatsize()}; + +} + +namespace fast_io::manipulators +{ + +template +struct basic_lebe_get_integral +{ + value_type* pointer; +}; + +template +struct basic_lebe_put_integral +{ + using manip_tag = manip_tag_t; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) + [[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) + [[no_unique_address]] +#endif +#endif + value_type value; +}; + + +template<::std::endian end,typename value_type> +struct basic_lebe_get_put +{ + using manip_tag = manip_tag_t; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) + [[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) + [[no_unique_address]] +#endif +#endif + value_type reference; +}; + +template<::std::endian en,::std::size_t sz,::fast_io::details::my_integral int_type> +requires (!::std::is_const_v&&::fast_io::details::supported_lebe_size) +inline constexpr auto lebe_get(int_type& t) noexcept +{ + return basic_lebe_get_put>{{__builtin_addressof(t)}}; +} + +template<::std::size_t sz,::fast_io::details::my_integral int_type> +requires (!::std::is_const_v&&::fast_io::details::supported_lebe_size) +inline constexpr auto le_get(int_type& t) noexcept +{ + return basic_lebe_get_put<::std::endian::little,basic_lebe_get_integral>{{__builtin_addressof(t)}}; +} + +template<::std::size_t sz,::fast_io::details::my_integral int_type> +requires (!::std::is_const_v&&::fast_io::details::supported_lebe_size) +inline constexpr auto be_get(int_type& t) noexcept +{ + return basic_lebe_get_put<::std::endian::big,basic_lebe_get_integral>{{__builtin_addressof(t)}}; +} + +template<::std::endian en,::std::size_t sz,::fast_io::details::my_integral int_type> +requires ::fast_io::details::supported_lebe_size +inline constexpr auto lebe_put(int_type t) noexcept((::std::numeric_limits<::fast_io::details::my_make_unsigned_t<::std::remove_cvref_t>>::digits)<=sz) +{ + using uint_type = ::fast_io::details::my_make_unsigned_t<::std::remove_cvref_t>; + uint_type u{static_cast(t)}; + if constexpr(sz<(::std::numeric_limits::digits)) + { + constexpr uint_type mx_value_halfm1{static_cast((static_cast(1) << static_cast(sz-1)))}; + constexpr uint_type mx_value{static_cast(static_cast(mx_value_halfm1-static_cast(1))+mx_value_halfm1)}; + if(u>mx_value) + throw_parse_code(::fast_io::parse_code::invalid); + } + using proxy_type = + ::std::conditional_t<(sz==128),::fast_io::details::pesudo_int128type, + ::std::conditional_t<(sz==64),::std::uint_least64_t, + ::std::conditional_t<(sz==32),::std::uint_least32_t, + ::std::conditional_t<(sz==16),::std::uint_least16_t, + ::std::conditional_t<(sz==8),::std::uint_least8_t,void>>>>>; + return basic_lebe_get_put>{{static_cast(static_cast(u))}}; +} + +template<::std::size_t sz,::fast_io::details::my_integral int_type> +requires ::fast_io::details::supported_lebe_size +inline constexpr auto le_put(int_type t) noexcept(noexcept(lebe_put<::std::endian::little,sz>(t))) +{ + return lebe_put<::std::endian::little,sz>(t); +} + +template<::std::size_t sz,::fast_io::details::my_integral int_type> +requires ::fast_io::details::supported_lebe_size +inline constexpr auto be_put(int_type t) noexcept(noexcept(lebe_put<::std::endian::big,sz>(t))) +{ + return lebe_put<::std::endian::big,sz>(t); +} + +template<::std::endian en,::std::floating_point T> +inline constexpr auto iec559_lebe_put(T t) +{ + constexpr + bool isiec559{::std::numeric_limits::is_iec559}; + using nocvref = ::std::remove_cvref_t; + + if constexpr(::std::same_as) + { + if constexpr(isiec559) + { + return ::fast_io::manipulators::lebe_put(::std::bit_cast<::std::uint_least32_t>(static_cast(t))); + } + else + { +#if __STDCPP_FLOAT32_T__ + return ::fast_io::manipulators::lebe_put(::std::bit_cast<::std::uint_least32_t>(static_cast<_Float32>(t))); +#else +static_assert(isiec559,"float is not iec60559"); +#endif + } + } + else if constexpr(::std::same_as) + { + if constexpr(isiec559) + { + return ::fast_io::manipulators::lebe_put(::std::bit_cast<::std::uint_least64_t>(static_cast(t))); + } + else + { +#if __STDCPP_FLOAT64_T__ + return ::fast_io::manipulators::lebe_put(::std::bit_cast<::std::uint_least64_t>(static_cast<_Float64>(t))); +#else +static_assert(isiec559,"double is not iec60559"); +#endif + } + } + else if constexpr(::std::same_as) + { +#if __STDCPP_FLOAT128_T__ + using proxy_type = ::fast_io::details::pesudo_int128type; + return ::fast_io::manipulators::basic_lebe_get_put>{{::std::bit_cast<::fast_io::details::pesudo_int128type>(static_cast<_Float128>(t))}}; +#else +static_assert(sizeof(double)!=sizeof(long)&&isiec559,"long double is not iec60559 or sizeof(double) == sizeof(long double)"); +#endif + } + else if constexpr(sizeof(T)==sizeof(::std::uint_least8_t)) + { + return ::fast_io::manipulators::lebe_put(::std::bit_cast<::std::uint_least8_t>(static_cast(t))); + } + else if constexpr(sizeof(T)==sizeof(::std::uint_least16_t)) + { + return ::fast_io::manipulators::lebe_put(::std::bit_cast<::std::uint_least16_t>(static_cast(t))); + } + else if constexpr(sizeof(T)==sizeof(::std::uint_least32_t)) + { + return ::fast_io::manipulators::lebe_put(::std::bit_cast<::std::uint_least32_t>(static_cast(t))); + } + else if constexpr(sizeof(T)==sizeof(::std::uint_least64_t)) + { + return ::fast_io::manipulators::lebe_put(::std::bit_cast<::std::uint_least64_t>(static_cast(t))); + } + else if constexpr(sizeof(T)==sizeof(::fast_io::details::pesudo_int128type)) + { + using proxy_type = ::fast_io::details::pesudo_int128type; + return ::fast_io::manipulators::basic_lebe_get_put>{{::std::bit_cast<::fast_io::details::pesudo_int128type>(static_cast(t))}}; + } +} + +/* +WASM standard uses this format. +*/ +template<::std::floating_point T> +inline constexpr auto iec559_le_put(T t) +{ + return ::fast_io::manipulators::iec559_lebe_put<::std::endian::little>(t); +} + +template<::std::floating_point T> +inline constexpr auto iec559_be_put(T t) +{ + return ::fast_io::manipulators::iec559_lebe_put<::std::endian::big>(t); +} + +template<::std::endian en,::std::floating_point T> +requires (!::std::is_const_v) +inline constexpr auto iec559_lebe_get(T& t) noexcept +{ + using nocvreft = ::std::remove_cvref_t; + return ::fast_io::manipulators::basic_lebe_get_put(),T>>{{__builtin_addressof(t)}}; +} + +template<::std::floating_point T> +inline constexpr auto iec559_le_get(T& t) +{ + return ::fast_io::manipulators::iec559_lebe_get<::std::endian::little>(t); +} + +template<::std::floating_point T> +inline constexpr auto iec559_be_get(T& t) +{ + return ::fast_io::manipulators::iec559_lebe_get<::std::endian::big>(t); +} + +} + +namespace fast_io +{ + +namespace details +{ + +template +struct parse_lebeget_int_result +{ + bool failed; + int_type itp; +}; + +template<::std::endian endn,typename int_type,::std::integral char_type> +requires (1= 201806L && (__cpp_if_consteval >= 202106L ||__cpp_lib_is_constant_evaluated >= 201811L) +constexpr +#endif +parse_lebeget_int_result scan_precise_reserve_define_integer_common_largechartype_impl(char_type const* iter) noexcept +{ + constexpr std::size_t n{sizeof(int_type)}; + static_assert(n!=0); + int_type t; + + using unsigned_char_type = ::std::make_unsigned_t; + constexpr + unsigned_char_type mx{static_cast(::std::numeric_limits::max())}; + + char unsigned buffer[n]; + for(auto bit{buffer},bie{buffer+n};bit!=bie;++bit) + { + auto val{static_cast(*iter)}; + if(mx < val) + { + return {true,t}; + } + *bit=static_cast(val); + ++iter; + } +#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) + __builtin_memcpy(__builtin_addressof(t),buffer,n); +#else + ::std::memcpy(__builtin_addressof(t),buffer,n); +#endif + if constexpr(::std::endian::native!=endn) + { + if constexpr(::fast_io::details::my_unsigned_integral) + { + t=::fast_io::byte_swap(t); + } + else + { + ::std::uint_least64_t low{t.low}; + ::std::uint_least64_t high{t.high}; + t.low=::fast_io::byte_swap(high); + t.high=::fast_io::byte_swap(low); + } + } + return {false,t}; +} + +template<::std::endian endn,typename int_type,::std::integral char_type> +requires (sizeof(char_type)==1) +inline +#if __cpp_lib_bit_cast >= 201806L && (__cpp_if_consteval >= 202106L ||__cpp_lib_is_constant_evaluated >= 201811L) +constexpr +#endif +auto scan_precise_reserve_define_integer_common_impl(char_type const* iter) noexcept +{ + constexpr std::size_t n{sizeof(int_type)}; + static_assert(n!=0); + int_type t; + +#if __cpp_lib_bit_cast >= 201806L && (__cpp_if_consteval >= 202106L ||__cpp_lib_is_constant_evaluated >= 201811L) +#if __cpp_if_consteval >= 202106L + if consteval +#elif __cpp_lib_is_constant_evaluated >= 201811L + if (__builtin_is_constant_evaluated()) +#endif + { + char_type buffer[n]; + non_overlapped_copy_n(iter,n,buffer); + t=::std::bit_cast(buffer); + } + else +#endif + { +#if !defined(__has_builtin) + ::std::memcpy(__builtin_addressof(t),iter,sizeof(int_type)); +#elif __has_builtin(__builtin_memcpy) + __builtin_memcpy(__builtin_addressof(t),iter,sizeof(int_type)); +#else + ::std::memcpy(__builtin_addressof(t),iter,sizeof(int_type)); +#endif + } + if constexpr(::std::endian::native!=endn) + { + if constexpr(::fast_io::details::my_unsigned_integral) + { + t=::fast_io::byte_swap(t); + } + else + { + ::std::uint_least64_t low{t.low}; + ::std::uint_least64_t high{t.high}; + t.low=::fast_io::byte_swap(high); + t.high=::fast_io::byte_swap(low); + } + } + return t; +} + +template<::std::endian endn,std::size_t n,::fast_io::details::my_integral int_type,::std::integral char_type> +inline constexpr ::std::conditional_t<(1 scan_precise_reserve_define_integer_impl(char_type const* iter,int_type& t) noexcept +{ + static_assert(n<=128); + using proxy_type = + ::std::conditional_t<(n==128),::fast_io::details::pesudo_int128type, + ::std::conditional_t<(n==64),::std::uint_least64_t, + ::std::conditional_t<(n==32),::std::uint_least32_t, + ::std::conditional_t<(n==16),::std::uint_least16_t, + ::std::conditional_t<(n==8),::std::uint_least8_t,void>>>>>; + proxy_type temp; + if constexpr(1(iter); + if(cd) + { + return parse_code::invalid; + } + temp = tp; + } + else + { + temp = scan_precise_reserve_define_integer_common_impl(iter); + } + using my_unsigned_type = ::fast_io::details::my_make_unsigned_t; + constexpr std::size_t digits{::std::numeric_limits::digits}; + if constexpr(digits::max()}; + if(mx_value(static_cast(temp)); + return parse_code::ok; + } + else + { + t=static_cast(static_cast(temp)); + } + if constexpr(1 +inline constexpr ::std::conditional_t<(1 scan_precise_reserve_define_lebe_float_get_impl(char_type const* iter,flttypef& t) noexcept +{ + using flttype = + ::std::remove_cvref_t; + constexpr + ::std::size_t n{::fast_io::details::size_lebe_float_size}; + using proxy_type = + ::std::conditional_t<(n==128),::fast_io::details::pesudo_int128type, + ::std::conditional_t<(n==64),::std::uint_least64_t, + ::std::conditional_t<(n==32),::std::uint_least32_t, + ::std::conditional_t<(n==16),::std::uint_least16_t, + ::std::conditional_t<(n==8),::std::uint_least8_t,void>>>>>; + proxy_type temp; + if constexpr(1(iter); + if(cd) + { + return parse_code::invalid; + } + temp = tp; + } + else + { + temp = scan_precise_reserve_define_integer_common_impl(iter); + } + constexpr + bool isiec559{::std::numeric_limits::is_iec559}; + if constexpr(::std::same_as) + { + if constexpr(isiec559) + { + t=static_cast(std::bit_cast(temp)); + } + else + { +#if __STDCPP_FLOAT32_T__ + t=static_cast(std::bit_cast<_Float32>(temp)); +#else +static_assert(isiec559,"float is not iec60559"); +#endif + } + } + else if constexpr(::std::same_as) + { + if constexpr(isiec559) + { + t=static_cast(std::bit_cast(temp)); + } + else + { +#if __STDCPP_FLOAT64_T__ + t=static_cast(std::bit_cast<_Float64>(temp)); +#else +static_assert(isiec559,"double is not iec60559"); +#endif + } + } + else if constexpr(::std::same_as) + { +#if __STDCPP_FLOAT128_T__ + t=static_cast(std::bit_cast<_Float128>(temp)); +#else +static_assert(sizeof(double)!=sizeof(long)&&isiec559,"long double is not iec60559 or sizeof(double) == sizeof(long double)"); +#endif + } + else + { + t=static_cast(std::bit_cast(temp)); + } + if constexpr(1 +inline +#if __cpp_lib_bit_cast >= 201806L && (__cpp_if_consteval >= 202106L ||__cpp_lib_is_constant_evaluated >= 201811L) +constexpr +#endif +char_type* print_reserve_define_integer_lebe_common_impl(char_type* iter,uint_type u) noexcept +{ + constexpr std::size_t n{sizeof(uint_type)}; + static_assert(n!=0); + if constexpr(::std::endian::native!=endn) + { + if constexpr(::fast_io::details::my_unsigned_integral) + { + u=::fast_io::byte_swap(u); + } + else + { + ::std::uint_least64_t low{u.low}; + ::std::uint_least64_t high{u.high}; + u.low=::fast_io::byte_swap(high); + u.high=::fast_io::byte_swap(low); + } + } +#if __cpp_lib_bit_cast >= 201806L && (__cpp_if_consteval >= 202106L ||__cpp_lib_is_constant_evaluated >= 201811L) +#if __cpp_if_consteval >= 202106L + if consteval +#elif __cpp_lib_is_constant_evaluated >= 201811L + if (__builtin_is_constant_evaluated()) +#endif + { + ::fast_io::freestanding::array buffer{::std::bit_cast<::fast_io::freestanding::array>(u)}; + non_overlapped_copy_n(buffer.data(),n,iter); + } + else +#endif + { + if constexpr(1>(u)}; + non_overlapped_copy_n(buffer.data(),n,iter); + } + else + { +#if !defined(__has_builtin) + ::std::memcpy(iter,__builtin_addressof(u),n); +#elif __has_builtin(__builtin_memcpy) + __builtin_memcpy(iter,__builtin_addressof(u),n); +#else + ::std::memcpy(iter,__builtin_addressof(u),n); +#endif + } + } + return iter+n; +} + + +} + +template<::std::integral char_type,::std::endian end,::std::size_t sz,typename int_type> +requires (((sz%(::std::numeric_limits::digits))==0)&&!::std::is_const_v + &&(::fast_io::details::my_integral|| + (::std::floating_point&&(::fast_io::details::size_lebe_float_size)==sz))) +inline constexpr std::size_t scan_precise_reserve_size(io_reserve_type_t>>) noexcept +{ + constexpr std::size_t cache{sz/(::std::numeric_limits::digits)}; + return cache; +} + +template<::std::endian en,::std::size_t sz,::std::integral char_type,typename int_type> +requires (((sz%(::std::numeric_limits::digits))==0)&&!::std::is_const_v + &&(::fast_io::details::my_integral|| + (::std::floating_point&&(::fast_io::details::size_lebe_float_size)==sz))) +inline constexpr auto scan_precise_reserve_define(io_reserve_type_t>>, + char_type const* iter, + ::fast_io::manipulators::basic_lebe_get_put> t) noexcept +{ + if constexpr(::std::floating_point) + { + return ::fast_io::details::scan_precise_reserve_define_lebe_float_get_impl(iter,*t.reference.pointer); + } + else + { + return ::fast_io::details::scan_precise_reserve_define_integer_impl(iter,*t.reference.pointer); + } +} + +template<::std::integral char_type,::std::endian end,::std::size_t sz,typename int_type> +requires (((sz%(::std::numeric_limits::digits))==0)&& + (::fast_io::details::my_unsigned_integral||::std::same_as)) +inline constexpr std::size_t print_reserve_size(io_reserve_type_t>>) noexcept +{ + constexpr std::size_t cache{sz/(::std::numeric_limits::digits)}; + return cache; +} + +template<::std::integral char_type,::std::endian end,::std::size_t sz,typename int_type> +requires (((sz%(::std::numeric_limits::digits))==0)&& + (::fast_io::details::my_unsigned_integral||::std::same_as)) +inline constexpr auto print_reserve_define(io_reserve_type_t>>,char_type* iter, + ::fast_io::manipulators::basic_lebe_get_put> v) noexcept +{ + return ::fast_io::details::print_reserve_define_integer_lebe_common_impl(iter,v.reference.value); +} + +} diff --git a/src/fast_io/include/fast_io_freestanding_impl/serializations/str_get.h b/src/fast_io/include/fast_io_freestanding_impl/serializations/str_get.h new file mode 100644 index 0000000..09deef7 --- /dev/null +++ b/src/fast_io/include/fast_io_freestanding_impl/serializations/str_get.h @@ -0,0 +1,119 @@ +#pragma once + +namespace fast_io +{ + +namespace manipulators +{ + +template +struct basic_str_get_all +{ + using manip_tag = manip_tag_t; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) + [[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) + [[no_unique_address]] +#endif +#endif + T reference; + std::size_t n; +}; + +template +inline constexpr auto str_get_all(T& reference,std::size_t n) noexcept +{ + return basic_str_get_all{io_strlike_ref(io_alias,reference),n}; +} + +} + +namespace details +{ +struct str_get_all_context +{ + bool copying{}; +}; + +template<::std::integral char_type,typename T> +inline constexpr parse_result scan_context_define_str_get_all_buffer_common_impl(char_type const* first,char_type const* last,io_strlike_reference_wrapper output,std::size_t n) +{ + auto bg{obuffer_begin(output)}; + auto curr{obuffer_curr(output)}; + std::size_t elements{static_cast(curr-bg)}; + std::size_t remain_characters{static_cast(n-elements)}; + std::size_t itdiff{static_cast(last-first)}; + std::size_t to_copy{remain_characters}; + bool not_enough{itdiff +inline constexpr parse_result scan_context_define_str_get_all_buffer_strlike_impl(char_type const* first,char_type const* last,io_strlike_reference_wrapper output,std::size_t n,bool& ctx) +{ + if(!ctx) + { + obuffer_set_curr(output,obuffer_begin(output)); + strlike_reserve(io_strlike_type,*output.ptr,n); + ctx=true; + } + return scan_context_define_str_get_all_buffer_common_impl(first,last,output,n); +} + +template<::std::integral char_type,typename T> +inline constexpr parse_result scan_context_define_str_get_all_general_strlike_impl(char_type const* first,char_type const* last,io_strlike_reference_wrapper output,std::size_t n,::fast_io::details::basic_concat_buffer& ctx) +{ + auto ret{scan_context_define_str_get_all_buffer_common_impl(first,last,io_strlike_ref(ctx),n)}; + if(ret.code==parse_code::ok) + { + *output.ptr=strlike_construct_define(io_strlike_type,ctx.buffer_begin,ctx.buffer_curr);; + } + return ret; +} +} + +template<::std::integral char_type,typename T> +inline constexpr io_type_t<::std::conditional_t<::fast_io::buffer_strlike,::fast_io::details::str_get_all_context, + ::fast_io::details::basic_concat_buffer>> + scan_context_type(io_reserve_type_t>>) noexcept +{ + return {}; +} + +template<::std::integral char_type,typename ctxtype,typename T> +inline constexpr parse_result scan_context_define( + io_reserve_type_t>>, + ctxtype& ctx, + char_type const* first,char_type const* last, + ::fast_io::manipulators::basic_str_get_all> str) +{ + if constexpr(::fast_io::buffer_strlike) + { + return ::fast_io::details::scan_context_define_str_get_all_buffer_strlike_impl(first,last,str.reference,str.n,ctx.copying); + } + else + { + return ::fast_io::details::scan_context_define_str_get_all_general_strlike_impl(first,last,str.reference,str.n,ctx); + } +} + +template +inline constexpr parse_code scan_context_eof_define(io_reserve_type_t>>, + ctxtype&, + ::fast_io::manipulators::basic_str_get_all>) +{ + return parse_code::end_of_file; +} + +} diff --git a/src/fast_io/include/fast_io_freestanding_impl/serializations/strlike_get.h b/src/fast_io/include/fast_io_freestanding_impl/serializations/strlike_get.h new file mode 100644 index 0000000..e50ecb6 --- /dev/null +++ b/src/fast_io/include/fast_io_freestanding_impl/serializations/strlike_get.h @@ -0,0 +1,325 @@ +#pragma once + +namespace fast_io +{ + +namespace details +{ + +template +inline constexpr ::fast_io::manipulators::scalar_flags strlike_default_scalar_flags{.noskipws=noskipws,.line=line}; + +} + +namespace manipulators +{ + +template +struct basic_strlike_get +{ + using value_type = T; + using manip_tag = manip_tag_t; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) + [[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) + [[no_unique_address]] +#endif +#endif + T reference; +}; + +template +inline constexpr auto strlike_get(T& reference) noexcept +{ + return ::fast_io::manipulators::scalar_manip_t<::fast_io::details::strlike_default_scalar_flags, + ::fast_io::manipulators::basic_strlike_get> + {{io_strlike_ref(io_alias,reference)}}; +} + +template +inline constexpr auto strlike_line_get(T& reference) noexcept +{ + return ::fast_io::manipulators::scalar_manip_t<::fast_io::details::strlike_default_scalar_flags, + ::fast_io::manipulators::basic_strlike_get> + {{io_strlike_ref(io_alias,reference)}}; +} + +template +inline constexpr auto strlike_whole_get(T& reference) noexcept +{ + return ::fast_io::manipulators::whole_get_t<::fast_io::manipulators::basic_strlike_get> + {{io_strlike_ref(io_alias,reference)}}; +} + +} + +namespace details +{ + +template +inline constexpr ::fast_io::parse_result scan_context_define_strlike_impl(std::conditional_t skip_space_done,char_type const* first,char_type const* last, + T ref) +{ + auto it{first}; + if constexpr(!noskipws&&!line) + { + if(!skip_space_done) + { + it=::fast_io::find_none_c_space(it,last); + if(it==last) + return {it,::fast_io::parse_code::partial}; + skip_space_done=true; + obuffer_set_curr(ref,obuffer_begin(ref)); + } + } + auto it_space{it}; + if constexpr(line) + it_space=::fast_io::find_lf(it_space,last); + else + it_space=::fast_io::find_c_space(it_space,last); + if constexpr(noskipws||line) + { + if(!skip_space_done) + { + obuffer_set_curr(ref,obuffer_begin(ref)); + } + write(ref,it,it_space); + skip_space_done=true; + } + else + { + write(ref,it,it_space); + } + if(it_space==last) + return {it_space,::fast_io::parse_code::partial}; + if constexpr(line) + ++it_space; + return {it_space,::fast_io::parse_code::ok}; +} + +template +inline constexpr ::fast_io::parse_result scan_context_define_strlike_getall_impl(std::conditional_t skip_space_done,char_type const* first,char_type const* last, + T ref) +{ + if(!skip_space_done) + { + obuffer_set_curr(ref,obuffer_begin(ref)); + skip_space_done=true; + } + write(ref,first,last); + return {last,::fast_io::parse_code::partial}; +} + +inline constexpr ::fast_io::parse_code scan_context_eof_strlike_define_impl(bool skip_space_done) noexcept +{ + if(skip_space_done) + return ::fast_io::parse_code::ok; + else + return ::fast_io::parse_code::end_of_file; +} + +} + +template +inline constexpr io_type_t<::std::conditional_t< + (::fast_io::buffer_strlike::value_type> + &&::std::same_as::char_type,char_type>), + ::fast_io::details::str_get_all_context, + ::fast_io::details::basic_concat_buffer>> scan_context_type( + io_reserve_type_t>>) noexcept +{ + return {}; +} + +template<::std::integral char_type,::fast_io::manipulators::scalar_flags flags,typename ctx_type,typename T> +inline constexpr parse_result scan_context_define( + io_reserve_type_t>>, + ctx_type& ctx, + char_type const* first,char_type const* last, + ::fast_io::manipulators::scalar_manip_t> ref) +{ + using value_type = std::remove_cvref_t; + using undefttype_char_type = typename std::remove_cvref_t::char_type; + if constexpr(::fast_io::buffer_strlike::value_type>&&std::same_as) + { + return ::fast_io::details::scan_context_define_strlike_impl(ctx.copying,first,last,ref.reference.reference); + } + else + { + bool b{ctx.buffer_begin!=ctx.buffer_curr}; + auto [it,ec]=::fast_io::details::scan_context_define_strlike_impl(b, + first,last,io_strlike_ref(io_alias,ctx)); + if(ec==::fast_io::parse_code::ok) + { + using ioreftype = typename value_type::value_type; + if constexpr(::std::same_as) + { + *ref.reference.reference.ptr=strlike_construct_define(io_strlike_type,ctx.buffer_begin,ctx.buffer_curr); + } + else + { + *ref.reference.reference.ptr=::fast_io::basic_general_concat(::fast_io::manipulators::code_cvt(::fast_io::manipulators::strvw(ctx.buffer_begin,ctx.buffer_curr))); + } + } + return {it,ec}; + } +} + +template<::fast_io::manipulators::scalar_flags flags,std::integral char_type,typename ctx_type,typename T> +inline constexpr ::fast_io::parse_code scan_context_eof_define( + io_reserve_type_t>>, + ctx_type& ctx, + ::fast_io::manipulators::scalar_manip_t> ref) +{ + using value_type = std::remove_cvref_t; + using undefttype_char_type = typename std::remove_cvref_t::char_type; + if constexpr(flags.line||flags.noskipws) + { + if constexpr(::fast_io::buffer_strlike::value_type>&&std::same_as) + { + if(obuffer_begin(ref.reference.reference)==obuffer_curr(ref.reference.reference)) + { + return ::fast_io::parse_code::end_of_file; + } + else + { + return ::fast_io::parse_code::ok; + } + } + else + { + if(ctx.buffer_begin==ctx.buffer_curr) + { + return ::fast_io::parse_code::end_of_file; + } + else + { + using ioreftype = typename value_type::value_type; + if constexpr(::std::same_as) + { + *ref.reference.reference.ptr=strlike_construct_define(io_strlike_type,ctx.buffer_begin,ctx.buffer_curr); + } + else + { + *ref.reference.reference.ptr=::fast_io::basic_general_concat(::fast_io::manipulators::code_cvt(::fast_io::manipulators::strvw(ctx.buffer_begin,ctx.buffer_curr))); + } + return ::fast_io::parse_code::ok; + } + } + } + else + { + if constexpr(::fast_io::buffer_strlike::value_type>&&std::same_as) + { + return ::fast_io::details::scan_context_eof_strlike_define_impl(ctx.copying); + } + else + { + if(ctx.buffer_begin!=ctx.buffer_curr) + { + using ioreftype = typename value_type::value_type; + if constexpr(::std::same_as) + { + *ref.reference.reference.ptr=strlike_construct_define(io_strlike_type,ctx.buffer_begin,ctx.buffer_curr); + } + else + { + *ref.reference.reference.ptr=::fast_io::basic_general_concat(::fast_io::manipulators::code_cvt(::fast_io::manipulators::strvw(ctx.buffer_begin,ctx.buffer_curr))); + } + return ::fast_io::parse_code::ok; + } + else + { + return ::fast_io::parse_code::end_of_file; + } + } + } +} + + +template +inline constexpr io_type_t<::std::conditional_t< + (::fast_io::buffer_strlike::value_type> + &&::std::same_as::char_type,char_type>), + ::fast_io::details::str_get_all_context, + ::fast_io::details::basic_concat_buffer>> scan_context_type( + io_reserve_type_t>>) noexcept +{ + return {}; +} + +template<::std::integral char_type,typename ctx_type,typename T> +inline constexpr parse_result scan_context_define( + io_reserve_type_t>>, + ctx_type& ctx, + char_type const* first,char_type const* last, + ::fast_io::manipulators::whole_get_t<::fast_io::manipulators::basic_strlike_get> ref) +{ + using value_type = std::remove_cvref_t; + using undefttype_char_type = typename std::remove_cvref_t::char_type; + if constexpr(::fast_io::buffer_strlike::value_type>&&std::same_as) + { + return ::fast_io::details::scan_context_define_strlike_getall_impl(ctx.copying,first,last,ref.reference.reference); + } + else + { + bool b{ctx.buffer_begin!=ctx.buffer_curr}; + auto [it,ec]=::fast_io::details::scan_context_define_strlike_getall_impl(b, + first,last,io_strlike_ref(io_alias,ctx)); + if(ec==::fast_io::parse_code::ok) + { + using ioreftype = typename value_type::value_type; + if constexpr(::std::same_as) + { + *ref.reference.reference.ptr=strlike_construct_define(io_strlike_type,ctx.buffer_begin,ctx.buffer_curr); + } + else + { + *ref.reference.reference.ptr=::fast_io::basic_general_concat(::fast_io::manipulators::code_cvt(::fast_io::manipulators::strvw(ctx.buffer_begin,ctx.buffer_curr))); + } + } + return {it,ec}; + } +} + +template +inline constexpr ::fast_io::parse_code scan_context_eof_define( + io_reserve_type_t>>, + ctx_type& ctx, + ::fast_io::manipulators::whole_get_t<::fast_io::manipulators::basic_strlike_get> ref) +{ + + using value_type = std::remove_cvref_t; + using undefttype_char_type = typename std::remove_cvref_t::char_type; + if constexpr(::fast_io::buffer_strlike::value_type>&&std::same_as) + { + if(!ctx.copying) + { + obuffer_set_curr(ref.reference.reference,obuffer_begin(ref.reference.reference)); + } + } + else + { + using ioreftype = typename value_type::value_type; + if constexpr(::std::same_as) + { + *ref.reference.reference.ptr=strlike_construct_define(io_strlike_type,ctx.buffer_begin,ctx.buffer_curr); + } + else + { *ref.reference.reference.ptr=::fast_io::basic_general_concat(::fast_io::manipulators::code_cvt(::fast_io::manipulators::strvw(ctx.buffer_begin,ctx.buffer_curr))); + } + } + return ::fast_io::parse_code::ok; +} + +} + diff --git a/src/fast_io/include/fast_io_freestanding_impl/serializations/wasm.h b/src/fast_io/include/fast_io_freestanding_impl/serializations/wasm.h new file mode 100644 index 0000000..14f1bd5 --- /dev/null +++ b/src/fast_io/include/fast_io_freestanding_impl/serializations/wasm.h @@ -0,0 +1,59 @@ +#pragma once + +/* +Referenced from +https://github.com/sunfishcode/wasm-reference-manual/blob/master/WebAssembly.md#primitive-encoding-types +*/ + +namespace fast_io::manipulators +{ + +template<::std::floating_point T> +inline constexpr auto wasm_float_put(T t) +{ + return ::fast_io::manipulators::iec559_le_put(t); +} + +template<::std::floating_point T> +inline constexpr auto wasm_float_get(T& t) +{ + return ::fast_io::manipulators::iec559_le_get(t); +} + +template<::fast_io::details::my_integral T> +inline constexpr auto wasm_varint_put(T t) +{ + return ::fast_io::manipulators::leb128_put(t); +} + +template<::fast_io::details::my_integral T> +inline constexpr auto wasm_varint_get(T& t) +{ + return ::fast_io::manipulators::leb128_get(t); +} + +template<::fast_io::details::my_integral T> +inline constexpr auto wasm_uint32_put(T t) +{ + return ::fast_io::manipulators::le_put<32>(t); +} + +template<::fast_io::details::my_integral T> +inline constexpr auto wasm_uint32_get(T& t) +{ + return ::fast_io::manipulators::le_get<32>(t); +} + +template<::fast_io::details::my_integral T> +inline constexpr auto wasm_uint64_put(T t) +{ + return ::fast_io::manipulators::le_put<64>(t); +} + +template<::fast_io::details::my_integral T> +inline constexpr auto wasm_uint64_get(T& t) +{ + return ::fast_io::manipulators::le_get<64>(t); +} + +} diff --git a/src/fast_io/include/fast_io_freestanding_impl/space_reserve.h b/src/fast_io/include/fast_io_freestanding_impl/space_reserve.h new file mode 100644 index 0000000..c28b0a1 --- /dev/null +++ b/src/fast_io/include/fast_io_freestanding_impl/space_reserve.h @@ -0,0 +1,33 @@ +#pragma once + +namespace fast_io +{ + +template +struct space_reserve +{ + using function_type = Function; + std::size_t size{}; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif + function_type func{}; +}; + +template +inline constexpr std::size_t print_reserve_size(::fast_io::io_reserve_type_t>,::fast_io::space_reserve const& t) noexcept +{ + return t.size; +} + +template +inline constexpr char_type* print_reserve_define(::fast_io::io_reserve_type_t>, char_type* iter,::fast_io::space_reserve const& t) +{ + return t.func(iter,iter+t.size); +} + +} diff --git a/src/fast_io/include/fast_io_freestanding_impl/width.h b/src/fast_io/include/fast_io_freestanding_impl/width.h new file mode 100644 index 0000000..6f1e827 --- /dev/null +++ b/src/fast_io/include/fast_io_freestanding_impl/width.h @@ -0,0 +1,547 @@ +#pragma once + +namespace fast_io +{ + +namespace manipulators +{ + +template +inline constexpr auto width(scalar_placement placement,T&& t,std::size_t n) noexcept +{ + using noref = std::remove_cvref_t; + if constexpr(alias_printable>) + { + return width_runtime_t(t)))>{placement,print_alias_define(io_alias,::std::forward(t)),n}; + } + else if constexpr((manipulator||std::is_trivially_copyable_v)&& +#if defined(_MSC_VER) || (defined(_WIN32)&&!defined(__WINE__)) || defined(__CYGWIN__) + sizeof(noref)<=8u +#else + sizeof(noref)<=(sizeof(std::uintptr_t)*2) +#endif + ) + { + return width_runtime_t{placement,t,n}; + } + else + { + return width_runtime_t{placement,t,n}; + } +} + + +template +inline constexpr auto width(scalar_placement placement,T&& t,std::size_t n,char_type ch) noexcept +{ + using noref = std::remove_cvref_t; + if constexpr(alias_printable>) + { + return width_runtime_ch_t(t))),char_type>{placement,print_alias_define(io_alias,::std::forward(t)),n,ch}; + } + else if constexpr((manipulator||std::is_trivially_copyable_v)&& +#if defined(_MSC_VER) || (defined(_WIN32)&&!defined(__WINE__)) || defined(__CYGWIN__) + sizeof(noref)<=8u +#else + sizeof(noref)<=(sizeof(std::uintptr_t)*2) +#endif + ) + + return width_runtime_ch_t{placement,t,n,ch}; + else + { + return width_runtime_ch_t{placement,t,n,ch}; + } +} + +template +inline constexpr auto left(T&& t,std::size_t n) noexcept +{ + using noref = std::remove_cvref_t; + if constexpr(alias_printable>) + { + return width_t(t)))>{print_alias_define(io_alias,::std::forward(t)),n}; + } + else if constexpr((manipulator||std::is_trivially_copyable_v)&& +#if defined(_MSC_VER) || (defined(_WIN32)&&!defined(__WINE__)) || defined(__CYGWIN__) + sizeof(noref)<=8u +#else + sizeof(noref)<=(sizeof(std::uintptr_t)*2) +#endif + ) + + return width_t{t,n}; + else + { + return width_t{t,n}; + } +} + +template +inline constexpr auto middle(T&& t,std::size_t n) noexcept +{ + using noref = std::remove_cvref_t; + if constexpr(alias_printable>) + { + return width_t(t)))>{print_alias_define(io_alias,::std::forward(t)),n}; + } + else if constexpr((manipulator||std::is_trivially_copyable_v)&& +#if defined(_MSC_VER) || (defined(_WIN32)&&!defined(__WINE__)) || defined(__CYGWIN__) + sizeof(noref)<=8u +#else + sizeof(noref)<=(sizeof(std::uintptr_t)*2) +#endif + ) + + return width_t{t,n}; + else + { + return width_t{t,n}; + } +} + +template +inline constexpr auto right(T&& t,std::size_t n) noexcept +{ + using noref = std::remove_cvref_t; + if constexpr(alias_printable>) + { + return width_t(t)))>{print_alias_define(io_alias,::std::forward(t)),n}; + } + else if constexpr((manipulator||std::is_trivially_copyable_v)&& +#if defined(_MSC_VER) || (defined(_WIN32)&&!defined(__WINE__)) || defined(__CYGWIN__) + sizeof(noref)<=8u +#else + sizeof(noref)<=(sizeof(std::uintptr_t)*2) +#endif + ) + + return width_t{t,n}; + else + { + return width_t{t,n}; + } +} + + +template +inline constexpr auto internal(T&& t,std::size_t n) noexcept +{ + using noref = std::remove_cvref_t; + if constexpr(alias_printable>) + { + return width_t(t)))>{print_alias_define(io_alias,::std::forward(t)),n}; + } + else if constexpr((manipulator||std::is_trivially_copyable_v)&& +#if defined(_MSC_VER) || (defined(_WIN32)&&!defined(__WINE__)) || defined(__CYGWIN__) + sizeof(noref)<=8u +#else + sizeof(noref)<=(sizeof(std::uintptr_t)*2) +#endif + ) + + return width_t{t,n}; + else + { + return width_t{t,n}; + } +} + + +template +inline constexpr auto left(T&& t,std::size_t n,char_type ch) noexcept +{ + using noref = std::remove_cvref_t; + if constexpr(alias_printable>) + { + return width_ch_t(t))),char_type>{print_alias_define(io_alias,::std::forward(t)),n,ch}; + } + else if constexpr((manipulator||std::is_trivially_copyable_v)&& +#if defined(_MSC_VER) || (defined(_WIN32)&&!defined(__WINE__)) || defined(__CYGWIN__) + sizeof(noref)<=8u +#else + sizeof(noref)<=(sizeof(std::uintptr_t)*2) +#endif + ) + + return width_ch_t{t,n,ch}; + else + { + return width_ch_t{t,n}; + } +} + +template +inline constexpr auto middle(T&& t,std::size_t n,char_type ch) noexcept +{ + using noref = std::remove_cvref_t; + if constexpr(alias_printable>) + { + return width_ch_t(t))),char_type>{print_alias_define(io_alias,::std::forward(t)),n,ch}; + } + else if constexpr((manipulator||std::is_trivially_copyable_v)&& +#if defined(_MSC_VER) || (defined(_WIN32)&&!defined(__WINE__)) || defined(__CYGWIN__) + sizeof(noref)<=8u +#else + sizeof(noref)<=(sizeof(std::uintptr_t)*2) +#endif + ) + return width_ch_t{t,n,ch}; + else + { + return width_ch_t{t,n,ch}; + } +} + +template +inline constexpr auto right(T&& t,std::size_t n,char_type ch) noexcept +{ + using noref = std::remove_cvref_t; + if constexpr(alias_printable>) + { + return width_ch_t(t))),char_type>{print_alias_define(io_alias,::std::forward(t)),n,ch}; + } + else if constexpr((manipulator||std::is_trivially_copyable_v)&& +#if defined(_MSC_VER) || (defined(_WIN32)&&!defined(__WINE__)) || defined(__CYGWIN__) + sizeof(noref)<=8u +#else + sizeof(noref)<=(sizeof(std::uintptr_t)*2) +#endif + ) + return width_ch_t{t,n,ch}; + else + { + return width_ch_t{t,n,ch}; + } +} + +template +inline constexpr auto internal(T&& t,std::size_t n,char_type ch) noexcept +{ + using noref = std::remove_cvref_t; + if constexpr(alias_printable>) + { + return width_ch_t(t))),char_type>{print_alias_define(io_alias,::std::forward(t)),n,ch}; + } + else if constexpr((manipulator||std::is_trivially_copyable_v)&& +#if defined(_MSC_VER) || (defined(_WIN32)&&!defined(__WINE__)) || defined(__CYGWIN__) + sizeof(noref)<=8u +#else + sizeof(noref)<=(sizeof(std::uintptr_t)*2) +#endif + ) + return width_ch_t{t,n,ch}; + else + { + return width_ch_t{t,n,ch}; + } +} + +} + +namespace details +{ + +template +inline constexpr std::size_t print_reserve_size_width_impl(T t,std::size_t wid) +{ + if constexpr(reserve_printable>) + { + constexpr std::size_t sz{print_reserve_size(io_reserve_type>)}; + if(wid>) + { + std::size_t sz{print_reserve_size(io_reserve_type>,t)}; + if(wid>) + { + auto sz{print_scatter_define(io_reserve_type>,t).len}; + if(wid +inline constexpr char_type* handle_common_ch(char_type* first, char_type* last,std::size_t wd, char_type fillch) +{ + std::size_t const diff{static_cast(last-first)}; + if(wd<=diff) + return last; + std::size_t const to_fill_chs{wd-diff}; + if constexpr(placement==::fast_io::manipulators::scalar_placement::left) + { + my_fill_n(last,to_fill_chs,fillch); + } + else if constexpr(placement==::fast_io::manipulators::scalar_placement::middle) + { + constexpr std::size_t one{1}; + std::size_t const left_indent{static_cast(to_fill_chs>>one)}; + std::size_t const right_indent{to_fill_chs-left_indent}; + my_copy(first,last,first+left_indent); + my_fill_n(first,left_indent,fillch); + my_fill_n(first+wd-right_indent,right_indent,fillch); + } + else + { + my_copy(first,last,first+to_fill_chs); + my_fill_n(first,to_fill_chs,fillch); + } + return first+wd; +} + +template<::std::integral char_type> +inline constexpr char_type* handle_common_internal_ch(char_type* first, char_type* last,std::size_t wd, char_type fillch,std::size_t internal_len) +{ + std::size_t const diff1{static_cast(last-first)}; + if(wd<=diff1||diff1(last-first)}; + std::size_t const to_fill_chs{wd-diff}; + my_copy(first,last,first+to_fill_chs); + my_fill_n(first,to_fill_chs,fillch); + return first+wd; +} + +template<::fast_io::manipulators::scalar_placement placement,::std::integral char_type,typename T> +inline constexpr char_type* print_reserve_define_width_ch_impl(char_type* iter,T t,std::size_t wdt, char_type fillch) +{ + using value_type = std::remove_cvref_t; + if constexpr(placement==::fast_io::manipulators::scalar_placement::internal) + { + if constexpr(printable_internal_shift) + { + if constexpr(scatter_printable) + { + auto sc{print_scatter_define(io_reserve_type,t)}; + auto it{copy_scatter(sc,iter)}; + return handle_common_internal_ch(iter,it,wdt,fillch,print_define_internal_shift(io_reserve_type,t)); + } + else + { + char_type* it{print_reserve_define(io_reserve_type,iter,t)}; + return handle_common_internal_ch(iter,it,wdt,fillch,print_define_internal_shift(io_reserve_type,t)); + } + } + else + { + return print_reserve_define_width_ch_impl<::fast_io::manipulators::scalar_placement::right>(iter,t,wdt,fillch); + } + } + else + { + if constexpr(scatter_printable) + { + auto sc{print_scatter_define(io_reserve_type,t)}; + auto it{copy_scatter(sc,iter)}; + return handle_common_ch(iter,it,wdt,fillch); + } + else + { + char_type* it{print_reserve_define(io_reserve_type,iter,t)}; + return handle_common_ch(iter,it,wdt,fillch); + } + } +} + +template<::fast_io::manipulators::scalar_placement placement,::std::integral char_type,typename T> +requires std::is_trivially_copyable_v +inline constexpr char_type* print_reserve_define_width_impl(char_type* iter,T t,std::size_t wdt) +{ + return print_reserve_define_width_ch_impl(iter,t,wdt,char_literal_v); +} + +template<::std::integral char_type> +inline constexpr char_type* handle_common_rt_ch(::fast_io::manipulators::scalar_placement placement,char_type* first, char_type* last,std::size_t wd, char_type fillch) +{ + std::size_t const diff{static_cast(last-first)}; + if(wd<=diff) + return last; + std::size_t const to_fill_chs{wd-diff}; + if(placement==::fast_io::manipulators::scalar_placement::left) + { + my_fill_n(last,to_fill_chs,fillch); + return first+wd; + } + else if(placement==::fast_io::manipulators::scalar_placement::middle) + { + std::size_t one{1}; + std::size_t const left_indent{static_cast(to_fill_chs>>one)}; + std::size_t const right_indent{to_fill_chs-left_indent}; + my_copy(first,last,first+left_indent); + my_fill_n(first,left_indent,fillch); + my_fill_n(first+wd-right_indent,right_indent,fillch); + return first+wd; + } + else if(placement==::fast_io::manipulators::scalar_placement::right) + { + my_copy(first,last,first+to_fill_chs); + my_fill_n(first,to_fill_chs,fillch); + return first+wd; + } + else + { + return last; + } +} + +template<::std::integral char_type,typename T> +inline constexpr char_type* print_reserve_define_width_rt_ch_impl(char_type* iter, + ::fast_io::manipulators::scalar_placement placement,T t,std::size_t wdt, char_type fillch) +{ + using value_type = std::remove_cvref_t; + if(placement==::fast_io::manipulators::scalar_placement::internal) + { + if constexpr(printable_internal_shift) + { + if constexpr(scatter_printable) + { + auto sc{print_scatter_define(io_reserve_type,t)}; + auto it{copy_scatter(sc,iter)}; + return handle_common_internal_ch(iter,it,wdt,fillch,print_define_internal_shift(io_reserve_type,t)); + } + else + { + char_type* it{print_reserve_define(io_reserve_type,iter,t)}; + return handle_common_internal_ch(iter,it,wdt,fillch,print_define_internal_shift(io_reserve_type,t)); + } + } + else + { + placement=::fast_io::manipulators::scalar_placement::right; + } + } + if constexpr(scatter_printable) + { + auto sc{print_scatter_define(io_reserve_type,t)}; + auto it{copy_scatter(sc,iter)}; + return handle_common_rt_ch(placement,iter,it,wdt,fillch); + } + else + { + char_type* it{print_reserve_define(io_reserve_type,iter,t)}; + return handle_common_rt_ch(placement,iter,it,wdt,fillch); + } +} + + +template<::std::integral char_type,typename T> +requires std::is_trivially_copyable_v +inline constexpr char_type* print_reserve_define_rt_width_impl(char_type* iter, + ::fast_io::manipulators::scalar_placement placement, + T t,std::size_t wdt) +{ + return print_reserve_define_width_rt_ch_impl(iter,placement,t,wdt,char_literal_v); +} + +} + +template +requires ((reserve_printable>||dynamic_reserve_printable> + ||scatter_printable>)&& + (static_cast(static_cast(placement)-static_cast(1u))(4u))) +constexpr std::size_t print_reserve_size(io_reserve_type_t>, + ::fast_io::manipulators::width_t t) noexcept +{ + if constexpr(std::is_reference_v) + return ::fast_io::details::print_reserve_size_width_impl(parameter{t.reference},t.width); + else + return ::fast_io::details::print_reserve_size_width_impl(t.reference,t.width); +} + +template<::std::integral char_type,::fast_io::manipulators::scalar_placement placement,typename T> +requires ((reserve_printable>||dynamic_reserve_printable> + ||scatter_printable>)&& + (static_cast(static_cast(placement)-static_cast(1u))(4u))) +constexpr char_type* print_reserve_define(io_reserve_type_t>, char_type* iter, + ::fast_io::manipulators::width_t t) noexcept +{ + if constexpr(std::is_reference_v) + return ::fast_io::details::print_reserve_define_width_impl(iter,parameter{t.reference},t.width); + else + return ::fast_io::details::print_reserve_define_width_impl(iter,t.reference,t.width); +} + +template +requires ((reserve_printable>||dynamic_reserve_printable> + ||scatter_printable>)&& + (static_cast(static_cast(placement)-static_cast(1u))(4u))) +constexpr std::size_t print_reserve_size(io_reserve_type_t>,::fast_io::manipulators::width_ch_t t) noexcept +{ + if constexpr(std::is_reference_v) + return ::fast_io::details::print_reserve_size_width_impl(parameter{t.reference},t.width); + else + return ::fast_io::details::print_reserve_size_width_impl(t.reference,t.width); +} + +template<::std::integral char_type,::fast_io::manipulators::scalar_placement placement,typename T> +requires ((reserve_printable>||dynamic_reserve_printable> + ||scatter_printable>)&& + (static_cast(static_cast(placement)-static_cast(1u))(4u))) +constexpr char_type* print_reserve_define(io_reserve_type_t>, + char_type* iter,::fast_io::manipulators::width_ch_t t) noexcept +{ + if constexpr(std::is_reference_v) + return ::fast_io::details::print_reserve_define_width_ch_impl(iter,parameter{t.reference},t.width,t.ch); + else + return ::fast_io::details::print_reserve_define_width_ch_impl(iter,t.reference,t.width,t.ch); +} + + +template +requires (reserve_printable>||dynamic_reserve_printable> + ||scatter_printable>) +constexpr std::size_t print_reserve_size(io_reserve_type_t>, + ::fast_io::manipulators::width_runtime_t t) noexcept +{ + if constexpr(std::is_reference_v) + return ::fast_io::details::print_reserve_size_width_impl(parameter{t.reference},t.width); + else + return ::fast_io::details::print_reserve_size_width_impl(t.reference,t.width); +} + +template<::std::integral char_type,typename T> +requires (reserve_printable>||dynamic_reserve_printable> + ||scatter_printable>) +constexpr char_type* print_reserve_define(io_reserve_type_t>, char_type* iter, + ::fast_io::manipulators::width_runtime_t t) noexcept +{ + if constexpr(std::is_reference_v) + return ::fast_io::details::print_reserve_define_rt_width_impl(iter,t.placement,parameter{t.reference},t.width); + else + return ::fast_io::details::print_reserve_define_rt_width_impl(iter,t.placement,t.reference,t.width); +} + +template +requires (reserve_printable>||dynamic_reserve_printable> + ||scatter_printable>) +constexpr std::size_t print_reserve_size(io_reserve_type_t>, + ::fast_io::manipulators::width_runtime_ch_t t) noexcept +{ + if constexpr(std::is_reference_v) + return ::fast_io::details::print_reserve_size_width_impl(parameter{t.reference},t.width); + else + return ::fast_io::details::print_reserve_size_width_impl(t.reference,t.width); +} + +template<::std::integral char_type,typename T> +requires (reserve_printable>||dynamic_reserve_printable> + ||scatter_printable>) +constexpr char_type* print_reserve_define(io_reserve_type_t>, char_type* iter, + ::fast_io::manipulators::width_runtime_ch_t t) noexcept +{ + if constexpr(std::is_reference_v) + return ::fast_io::details::print_reserve_define_width_rt_ch_impl(iter,t.placement,parameter{t.reference},t.width,t.ch); + else + return ::fast_io::details::print_reserve_define_width_rt_ch_impl(iter,t.placement,t.reference,t.width,t.ch); +} + + +} diff --git a/src/fast_io/include/fast_io_hosted.h b/src/fast_io/include/fast_io_hosted.h new file mode 100644 index 0000000..98b8945 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted.h @@ -0,0 +1,132 @@ +#pragma once +/* +https://en.cppreference.com/w/cpp/freestanding +There are two kinds of implementations defined by the C++ standard: +hosted and freestanding implementations. +For hosted implementations the set of standard library headers required by the C++ standard is much larger than for freestanding ones. +*/ +//fast_io_hosted defines what we could use in a hosted environment. + +#if !defined(__cplusplus) +#error "You are not using a C++ compiler" +#endif + +#if !defined(__cpp_concepts) +#error "fast_io requires at least C++20 standard compiler." +#else +#include"fast_io_freestanding.h" + +#if ((__STDC_HOSTED__==1 && (!defined(_GLIBCXX_HOSTED) || _GLIBCXX_HOSTED==1) && !defined(_LIBCPP_FREESTANDING)) || defined(FAST_IO_ENABLE_HOSTED_FEATURES)) + +#if __has_include() +#if __has_include() +#include +#include"fast_io_hosted/platforms/errc_default_impl.h" +#elif __has_include(<__errc>) && !defined(__clang__) +#include<__errc> +#include"fast_io_hosted/platforms/errc_default_impl.h" +#elif __has_include() && !defined(__BIONIC__) +#include +#include"fast_io_hosted/platforms/errc_default_impl.h" +#elif __has_include() +#include +#include"fast_io_hosted/platforms/errc_default_impl.h" +#else +#include"fast_io_hosted/platforms/errc_impl.h" +#endif + +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning(push) +#pragma warning( disable : 4061 ) +#pragma warning( disable : 4514 ) +#pragma warning( disable : 4623 ) +#pragma warning( disable : 4626 ) +#pragma warning( disable : 4668 ) +#pragma warning( disable : 4710 ) +#pragma warning( disable : 4820 ) +#pragma warning( disable : 5027 ) +#pragma warning( disable : 5045 ) +#endif + +#include"fast_io_hosted/posix_error_scatter/impl.h" +#include"fast_io_hosted/posix_error.h" +#ifdef __MSDOS__ +#undef __STRICT_ANSI__ +#endif + +#include"fast_io_hosted/api_encoding_converter/impl.h" +#include"fast_io_hosted/mmap.h" +#include"fast_io_hosted/posix_status.h" +#if __has_include() +#include +#include"fast_io_unit/timespec.h" +#elif __has_include() +#include +#include"fast_io_unit/timespec.h" +#endif + +#if !defined(__AVR__) +#include"fast_io_hosted/platforms/native.h" +#include"fast_io_hosted/file_loaders/impl.h" +#include"fast_io_hosted/wrapper.h" +#include"fast_io_hosted/white_hole/white_hole.h" +#include"fast_io_hosted/dbg/impl.h" +#endif +#if __has_include() || __has_include() +#include"fast_io_hosted/timeutil/impl.h" +#endif + +#include"fast_io_hosted/threads/mutex/impl.h" +#include"fast_io_hosted/iomutex.h" + +#include "fast_io_dsal/impl/common.h" +#include "fast_io_dsal/impl/vector.h" + +#include"fast_io_hosted/filesystem/native.h" +#include"fast_io_hosted/dll/dll.h" +#include"fast_io_hosted/process_revamp/native.h" +#if defined(_MSVC_EXECUTION_CHARACTER_SET) +#if _MSVC_EXECUTION_CHARACTER_SET == 936 || _MSVC_EXECUTION_CHARACTER_SET == 54936 +#include"fast_io_unit/gb18030.h" +#endif +#endif + +#if defined(_WIN32) || defined(__CYGWIN__) +#include"fast_io_hosted/box.h" +#endif + +#if defined(_GLIBCXX_STRING) || defined(_LIBCPP_STRING) || defined(_STRING_) +#include"fast_io_unit/string.h" +#endif + +#if defined(_GLIBCXX_CHRONO) || defined(_LIBCPP_CHRONO) || defined(_CHRONO_) +#include"fast_io_unit/chrono.h" +#endif + +#if defined(_GLIBCXX_COMPLEX) || defined(_LIBCPP_COMPLEX) || defined(_COMPLEX_) +#include"fast_io_unit/complex.h" +#endif + +#if defined(_GLIBCXX_FILESYSTEM) || defined(_LIBCPP_FILESYSTEM) || defined(_FILESYSTEM_) +#include"fast_io_unit/filesystem.h" +#endif + +#if defined(_LIBCPP_BITSET) || defined(_BITSET_) +#include"fast_io_unit/bitset.h" +#endif + +#if defined(_WIN32) && defined(WINRT_BASE_H) +#if __has_include() +#include"fast_io_driver/cppwinrt_impl/impl.h" +#endif +#endif + +#endif + +#endif + +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning(pop) +#endif + +#endif diff --git a/src/fast_io/include/fast_io_hosted/api_encoding_converter/impl.h b/src/fast_io/include/fast_io_hosted/api_encoding_converter/impl.h new file mode 100644 index 0000000..d39142b --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/api_encoding_converter/impl.h @@ -0,0 +1,47 @@ +#pragma once + +#include"std_filesystem_pseudo.h" +#include"nt.h" +#include"posix.h" + +#if defined(_WIN32) || defined(__CYGWIN__) +namespace fast_io +{ +enum class win32_family +{ +ansi_9x, +wide_nt, +#ifdef _WIN32_WINDOWS +native = ansi_9x +#else +native = wide_nt +#endif +}; + +template +using basic_win32_family_api_encoding_converter=std::conditional_t, + basic_nt_api_encoding_converter>; + +template +using win32_family_api_encoding_converter = basic_win32_family_api_encoding_converter>; + +template +using basic_win32_api_encoding_converter = basic_win32_family_api_encoding_converter; + +using win32_api_encoding_converter = basic_win32_api_encoding_converter::allocator_type>; + +#if defined(__CYGWIN__) || defined(__WINE__) +using native_char_type = char; +#else +using native_char_type = std::conditional_t; +#endif + +} +#include"win32.h" +#else +namespace fast_io +{ +using native_char_type = char; +} +#endif diff --git a/src/fast_io/include/fast_io_hosted/api_encoding_converter/nt.h b/src/fast_io/include/fast_io_hosted/api_encoding_converter/nt.h new file mode 100644 index 0000000..18548d0 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/api_encoding_converter/nt.h @@ -0,0 +1,71 @@ +#pragma once + +namespace fast_io +{ +template +struct basic_nt_api_encoding_converter +{ + using allocator_type = Allocator; + using char_type = char16_t; + std::size_t buffer_capacity; + char_type* buffer_data; + char_type* buffer_data_end; + template + requires (sizeof(from_char_type)!=2) +#if __cpp_constexpr >=201907L && __cpp_constexpr_dynamic_alloc >= 201907L && __cpp_lib_is_constant_evaluated >=201811L + constexpr +#endif + basic_nt_api_encoding_converter(from_char_type const* p,std::size_t sz) noexcept: + buffer_capacity(details::cal_decorated_reserve_size(sz)), + buffer_data(details::allocate_iobuf_space(details::intrinsics::add_or_overflow_die(buffer_capacity,1))), + buffer_data_end(details::codecvt::general_code_cvt_full(p,p+sz,buffer_data)) + { + *buffer_data_end=0; + } + template + requires (sizeof(from_char_type)==2) +#if __cpp_constexpr >=201907L && __cpp_constexpr_dynamic_alloc >= 201907L && __cpp_lib_is_constant_evaluated >=201811L + constexpr +#endif + basic_nt_api_encoding_converter(from_char_type const* p,std::size_t sz) noexcept: + buffer_capacity(sz), + buffer_data(details::allocate_iobuf_space(::fast_io::details::intrinsics::add_or_overflow_die(sz,1))), + buffer_data_end(details::codecvt::general_code_cvt_full(p,p+sz,buffer_data)) + { + *buffer_data_end=0; + } + inline constexpr char_type const* c_str() const noexcept + { + return buffer_data; + } +#if defined(_WIN32) || defined(__CYGWIN__) +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + inline char16_t const* native_c_str() const noexcept + { + return reinterpret_cast(buffer_data); + } +#endif + inline constexpr std::size_t size() const noexcept + { + return static_cast(buffer_data_end-buffer_data); + } + inline constexpr std::size_t capacity() const noexcept + { + return buffer_capacity; + } + basic_nt_api_encoding_converter(basic_nt_api_encoding_converter const&)=delete; + basic_nt_api_encoding_converter& operator=(basic_nt_api_encoding_converter const&)=delete; +#if __cpp_constexpr >=201907L && __cpp_constexpr_dynamic_alloc >= 201907L && __cpp_lib_is_constant_evaluated >=201811L + constexpr +#endif + ~basic_nt_api_encoding_converter() + { + details::deallocate_iobuf_space(buffer_data,buffer_capacity+1); + } +}; +#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(__WINE__) +using nt_api_encoding_converter = basic_nt_api_encoding_converter>; +#endif +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_hosted/api_encoding_converter/posix.h b/src/fast_io/include/fast_io_hosted/api_encoding_converter/posix.h new file mode 100644 index 0000000..5a32818 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/api_encoding_converter/posix.h @@ -0,0 +1,164 @@ +#pragma once + +namespace fast_io +{ + +template +struct basic_posix_api_encoding_converter +{ + using allocator_type = Allocator; + using char_type = char8_t; + std::size_t buffer_capacity; + char_type* buffer_data; + char_type* buffer_data_end; + template + requires (sizeof(from_char_type)!=1) +#if __cpp_constexpr >=201907L && __cpp_constexpr_dynamic_alloc >= 201907L && __cpp_lib_is_constant_evaluated >=201811L + constexpr +#endif + basic_posix_api_encoding_converter(from_char_type const* p,std::size_t sz) noexcept: + buffer_capacity(details::cal_decorated_reserve_size(sz)), + buffer_data(details::allocate_iobuf_space(::fast_io::details::intrinsics::add_or_overflow_die(buffer_capacity,1))), + buffer_data_end(details::codecvt::general_code_cvt_full(p,p+sz,buffer_data)) + { + *buffer_data_end=0; + } + template + requires (sizeof(from_char_type)==1) +#if __cpp_constexpr >=201907L && __cpp_constexpr_dynamic_alloc >= 201907L && __cpp_lib_is_constant_evaluated >=201811L + constexpr +#endif + basic_posix_api_encoding_converter(from_char_type const* p,std::size_t sz) noexcept: + buffer_capacity(sz), + buffer_data(details::allocate_iobuf_space(::fast_io::details::intrinsics::add_or_overflow_die(buffer_capacity,1))), + buffer_data_end(details::non_overlapped_copy_n(p,sz,buffer_data)) + { + *buffer_data_end=0; + } + inline constexpr char_type const* c_str() const noexcept + { + return buffer_data; + } + inline char const* native_c_str() const noexcept + { + return reinterpret_cast(buffer_data); + } + inline constexpr std::size_t capacity() const noexcept + { + return buffer_capacity; + } + inline constexpr std::size_t size() const noexcept + { + return static_cast(buffer_data_end-buffer_data); + } + basic_posix_api_encoding_converter(basic_posix_api_encoding_converter const&)=delete; + basic_posix_api_encoding_converter& operator=(basic_posix_api_encoding_converter const&)=delete; +#if __cpp_constexpr >=201907L && __cpp_constexpr_dynamic_alloc >= 201907L && __cpp_lib_is_constant_evaluated >=201811L + constexpr +#endif + ~basic_posix_api_encoding_converter() + { + details::deallocate_iobuf_space(buffer_data,buffer_capacity+1); + } +}; + +using posix_api_encoding_converter = basic_posix_api_encoding_converter>; + +namespace details +{ +template +requires (sizeof(char_type)!=sizeof(char)) +inline auto posix_api_common_codecvt_impl(char_type const* filename_c_str,std::size_t filename_c_str_len,Func callback) +{ + basic_posix_api_encoding_converter converter(filename_c_str,filename_c_str_len); + if constexpr(::fast_io::details::api_common_has_size_overload) + return callback(converter.native_c_str(),converter.size()); + else + return callback(converter.native_c_str()); +} + +} + +template +requires (::fast_io::constructible_to_os_c_str) +inline auto posix_api_common(T const& t,Func callback) +{ + constexpr bool has_size_overload{::fast_io::details::api_common_has_size_overload}; + if constexpr(::std::is_array_v) + { + using cstr_char_type = std::remove_extent_t; + static_assert(::std::integral); + auto p{t}; + if constexpr(sizeof(cstr_char_type)==sizeof(char)) + { + if constexpr(has_size_overload) + return callback(reinterpret_cast(p),::fast_io::details::cal_array_size(t)); + else + return callback(reinterpret_cast(p)); + } + else + { + return ::fast_io::details::posix_api_common_codecvt_impl(p,::fast_io::details::cal_array_size(t),callback); + } + } + else if constexpr(type_has_c_str_method) + { + using cstr_char_type = std::remove_pointer_t; + if constexpr(sizeof(cstr_char_type)==sizeof(char)) + { + if constexpr(has_size_overload) + { + if constexpr(::std::ranges::contiguous_range>) + { + return callback(reinterpret_cast(::std::ranges::data(t)),::std::ranges::size(t)); + } + else if constexpr(::fast_io::details::cxx_std_filesystem_pseudo_concept>) + { + auto const& native{t.native()}; + return callback(reinterpret_cast(native.c_str()),native.size()); + } + else + { + auto ptr{t.c_str()}; + return callback(reinterpret_cast(ptr),::fast_io::cstr_len(ptr)); + } + } + else + { + return callback(reinterpret_cast(t.c_str())); + } + } + else + { + if constexpr(::std::ranges::contiguous_range>) + { + return ::fast_io::details::posix_api_common_codecvt_impl(::std::ranges::data(t),::std::ranges::size(t),callback); + } + else if constexpr(::fast_io::details::cxx_std_filesystem_pseudo_concept>) + { + auto const& native{t.native()}; + return ::fast_io::details::posix_api_common_codecvt_impl(native.c_str(),native.size(),callback); + } + else + { + auto ptr{t.c_str()}; + return ::fast_io::details::posix_api_common_codecvt_impl(ptr,::fast_io::cstr_len(ptr),callback); + } + } + } + else //types like std::basic_string_view, we must allocate new space to hold that type + { + using strvw_char_type = std::remove_pointer_t; + if constexpr(sizeof(strvw_char_type)==sizeof(char)) + { + return ::fast_io::details::api_common_copy_append0_strvw_case_impl(reinterpret_cast(t.data()),t.length(),callback); + } + else + { + return ::fast_io::details::posix_api_common_codecvt_impl(t.data(),t.length(),callback); + } + } +} +} diff --git a/src/fast_io/include/fast_io_hosted/api_encoding_converter/std_filesystem_pseudo.h b/src/fast_io/include/fast_io_hosted/api_encoding_converter/std_filesystem_pseudo.h new file mode 100644 index 0000000..a545809 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/api_encoding_converter/std_filesystem_pseudo.h @@ -0,0 +1,36 @@ +#pragma once + +namespace fast_io::details +{ + +template +concept cxx_std_filesystem_pseudo_concept = requires(T t) +{ + typename T::value_type; + {t.native().c_str()}->std::same_as; + {t.native().size()}->std::unsigned_integral; + {t.root_name()}; +}; + +template +concept api_common_has_size_overload = requires(Func callback,char_type const* cstr,std::size_t size) +{ + callback(cstr,size); +}; + +template +inline auto api_common_copy_append0_strvw_case_impl(os_char_type const* filename_strvw_str,std::size_t filename_strvw_len,Func callback) +{ + std::size_t const filename_strvw_len_p1{::fast_io::details::intrinsics::add_or_overflow_die(filename_strvw_len,1)}; + ::fast_io::details::buffer_alloc_arr_ptr temp(filename_strvw_len_p1); + auto ptr{temp.ptr}; + non_overlapped_copy_n(filename_strvw_str,filename_strvw_len,ptr); + ptr[filename_strvw_len]=0; + if constexpr(::fast_io::details::api_common_has_size_overload) + return callback(ptr,filename_strvw_len); + else + return callback(ptr); +} + +} diff --git a/src/fast_io/include/fast_io_hosted/api_encoding_converter/win32.h b/src/fast_io/include/fast_io_hosted/api_encoding_converter/win32.h new file mode 100644 index 0000000..b1a8f5a --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/api_encoding_converter/win32.h @@ -0,0 +1,135 @@ +#pragma once + +namespace fast_io +{ + +namespace details +{ +template +requires (sizeof(char_type)!=sizeof(char16_t)) +inline auto nt_api_common_code_cvt_impl(char_type const* filename_c_str,std::size_t filename_c_str_len,Func callback) +{ + basic_nt_api_encoding_converter converter(filename_c_str,filename_c_str_len); + if constexpr(::fast_io::details::api_common_has_size_overload) + return callback(converter.native_c_str(),converter.size()); + else + return callback(converter.native_c_str()); +} + +} + +template +requires (::fast_io::constructible_to_os_c_str) +inline auto nt_api_common(T const& t,Func callback) +{ + using char16_const_may_alias_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = char16_t const*; + constexpr bool has_size_overload{::fast_io::details::api_common_has_size_overload}; + if constexpr(::std::is_array_v) + { + using cstr_char_type = std::remove_extent_t; + auto p{t}; + if constexpr(sizeof(cstr_char_type)==sizeof(char16_t)) + { + if constexpr(has_size_overload) + return callback(reinterpret_cast(p),::fast_io::details::cal_array_size(t)); + else + return callback(reinterpret_cast(p)); + } + else + { + return ::fast_io::details::nt_api_common_code_cvt_impl(p,::fast_io::details::cal_array_size(t),callback); + } + } + else if constexpr(type_has_c_str_method) + { + using cstr_char_type = std::remove_pointer_t; + if constexpr(sizeof(cstr_char_type)==sizeof(char16_t)) + { + if constexpr(has_size_overload) + { + if constexpr(::std::ranges::contiguous_range>) + { + return callback(reinterpret_cast(t.c_str()),::std::ranges::size(t)); + } + else if constexpr(::fast_io::details::cxx_std_filesystem_pseudo_concept>) + { + auto const& native{t.native()}; + return callback(reinterpret_cast(native.c_str()),native.size()); + } + else + { + auto ptr{t.c_str()}; + return callback(reinterpret_cast(ptr),::fast_io::cstr_len(ptr)); + } + } + else + { + return callback(reinterpret_cast(t.c_str())); + } + } + else if constexpr(::std::ranges::contiguous_range>) + { + return ::fast_io::details::nt_api_common_code_cvt_impl(::std::ranges::data(t),::std::ranges::size(t),callback); + } + else if constexpr(::fast_io::details::cxx_std_filesystem_pseudo_concept>) + { + auto const& native{t.native()}; + return ::fast_io::details::nt_api_common_code_cvt_impl(native.c_str(),native.size(),callback); + } + else + { + auto ptr{t.c_str()}; + return ::fast_io::details::nt_api_common_code_cvt_impl(ptr,::fast_io::cstr_len(ptr),callback); + } + } + else //types like std::basic_string_view, we must allocate new space to hold that type + { + using strvw_char_type = std::remove_pointer_t; + if constexpr(sizeof(strvw_char_type)==sizeof(char16_t)) + { + return ::fast_io::details::api_common_copy_append0_strvw_case_impl(reinterpret_cast(t.data()),t.length(),callback); + } + else + { + return ::fast_io::details::nt_api_common_code_cvt_impl(t.data(),t.length(),callback); + } + } +} + +template +requires (::fast_io::constructible_to_os_c_str) +inline auto win32_api_common_9xa(T const& t,Func callback) +{ + return posix_api_common(t,callback); +} + +template +requires (::fast_io::constructible_to_os_c_str) +inline auto win32_api_common(T const& t,Func callback) +{ + if constexpr(::fast_io::win32_family::native==win32_family::ansi_9x) + return posix_api_common(t,callback); + else + return nt_api_common(t,callback); +} + +template +requires (::fast_io::constructible_to_os_c_str) +inline auto win32_family_api_common(T const& t,Func callback) +{ + if constexpr(family==win32_family::ansi_9x) + return posix_api_common(t,callback); + else + return nt_api_common(t,callback); +} + +} diff --git a/src/fast_io/include/fast_io_hosted/async_coro.h b/src/fast_io/include/fast_io_hosted/async_coro.h new file mode 100644 index 0000000..c8bbe8b --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/async_coro.h @@ -0,0 +1,182 @@ +#pragma once + +namespace fast_io +{ +//This is DAMN bullshit +struct task +{ +struct promise_type +{ +constexpr auto get_return_object() { return task{}; } +constexpr auto initial_suspend() { return std::suspend_never{}; } +constexpr auto final_suspend() { return std::suspend_never{}; } +void unhandled_exception() { std::terminate(); } +constexpr void return_void() {} +}; +}; + +namespace details +{ + +template +requires ((write&&async_output_stream)||(!write&&async_input_stream)) +class async_io_coroutine +{ +public: + typename io_async_scheduler_t::type& scheduler; + stm& stream; + Iter first,last; + std::ptrdiff_t offset{write?-1:0}; + std::size_t transferred_bytes{}; + int err{}; + typename io_async_overlapped_t::type overlapped; + constexpr bool await_ready() const { return false; } + constexpr Iter await_resume() const + { + if(err) + throw_posix_error(err); + return first+transferred_bytes/sizeof(*first); + } + void await_suspend(std::coroutine_handle<> handle) + { + overlapped=typename io_async_overlapped_t::type(std::in_place,[handle,this](std::size_t calb,int errn) + { + this->transferred_bytes=calb; + this->err=errn; + handle.resume(); + }); + if constexpr(write) + async_read_callback(scheduler,stream,first,last,overlapped,offset); + else + async_write_callback(scheduler,stream,first,last,overlapped,offset); + } +}; + + + + + +template +requires ((write&&async_scatter_output_stream)||(!write&&async_scatter_input_stream)) +class async_scatter_io_coroutine +{ +public: + typename io_async_scheduler_t::type& scheduler; + stm& stream; + std::span scatters; + std::ptrdiff_t offset{write?-1:0}; + typename io_async_overlapped_t::type overlapped; + std::size_t transferred_bytes{}; + int err{}; + constexpr bool await_ready() const { return false; } + constexpr std::size_t await_resume() const + { + if(err) + throw_posix_error(err); + return transferred_bytes; + } + void await_suspend(std::coroutine_handle<> handle) + { + overlapped=typename io_async_overlapped_t::type(std::in_place,[handle,this](std::size_t calb,int errn) + { + this->transferred_bytes=calb; + this->err=errn; + handle.resume(); + }); + if constexpr(write) + async_scatter_read_callback(scheduler,stream,scatters,overlapped,offset); + else + async_scatter_write_callback(scheduler,stream,scatters,overlapped,offset); + } +}; + + +template +class async_print_coroutine +{ +public: + typename io_async_scheduler_t::type& scheduler; + stm& stream; + std::ptrdiff_t offset{}; + typename io_async_overlapped_t::type overlapped; + std::size_t transferred_bytes{}; + int err{}; + dynamic_io_buffer buffer; + template + async_print_coroutine(typename io_async_scheduler_t::type& sh,std::ptrdiff_t off,stm& s,Args&& ...args):scheduler(sh),stream(s) + { + if constexpr(line) + println_freestanding(buffer,std::forward(args)...); + else + print_freestanding(buffer,std::forward(args)...); + } + constexpr bool await_ready() const { return false; } + constexpr std::size_t await_resume() const + { + if(err) + throw_posix_error(err); + return transferred_bytes; + } + void await_suspend(std::coroutine_handle<> handle) + { + overlapped=typename io_async_overlapped_t::type(std::in_place,[handle,this](std::size_t calb,int errn) + { + this->transferred_bytes=calb; + this->err=errn; + handle.resume(); + }); + async_write_callback(scheduler,stream,buffer.beg_ptr,buffer.end_ptr,overlapped,offset); + } +}; +} + +template +constexpr inline details::async_io_coroutine async_read(typename io_async_scheduler_t::type& scheduler,stm& sm,Iter begin,Iter end,std::ptrdiff_t offset=0) +{ + return {scheduler,sm,begin,end,offset}; +} + +template +constexpr inline details::async_io_coroutine async_write(typename io_async_scheduler_t::type& scheduler,stm& sm,Iter begin,Iter end,std::ptrdiff_t offset=-1) +{ + return {scheduler,sm,begin,end,offset}; +} + +template +constexpr inline details::async_scatter_io_coroutine async_scatter_read(typename io_async_scheduler_t::type& scheduler,stm& sm,std::span sc,std::ptrdiff_t offset=0) +{ + return {scheduler,sm,sc,offset}; +} + +template +constexpr inline details::async_scatter_io_coroutine async_scatter_write(typename io_async_scheduler_t::type& scheduler,stm& sm,std::span sc,std::ptrdiff_t offset=-1) +{ + return {scheduler,sm,sc,offset}; +} + + +template +constexpr inline details::async_print_coroutine async_print(typename io_async_scheduler_t::type& scheduler,stm& sm,Args&& ...args) +{ + return details::async_print_coroutine(scheduler,-1,sm,std::forward(args)...); +} +template +constexpr inline details::async_print_coroutine async_println(typename io_async_scheduler_t::type& scheduler,stm& sm,Args&& ...args) +{ + return details::async_print_coroutine(scheduler,-1,sm,std::forward(args)...); +} + +template +constexpr inline details::async_print_coroutine async_print(typename io_async_scheduler_t::type& scheduler,std::ptrdiff_t offset,stm& sm,Args&& ...args) +{ + return details::async_print_coroutine(scheduler,offset,sm,std::forward(args)...); +} +template +constexpr inline details::async_print_coroutine async_println(typename io_async_scheduler_t::type& scheduler,std::ptrdiff_t offset,stm& sm,Args&& ...args) +{ + return details::async_print_coroutine(scheduler,offset,sm,std::forward(args)...); +} + + + +} diff --git a/src/fast_io/include/fast_io_hosted/auto_indent.h b/src/fast_io/include/fast_io_hosted/auto_indent.h new file mode 100644 index 0000000..6ac71e5 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/auto_indent.h @@ -0,0 +1,19 @@ +#pragma once + +namespace fast_io +{ + +template> +requires std::integral> +inline constexpr auto auto_indent(rg&& r) +{ + if constexpr(std::is_array_v>) + return ::fast_io::details::calculate_auto_width_result( + std::ranges::data(r),std::ranges::data(r)+(std::ranges::size(r)-1) + ); + else + return ::fast_io::details::calculate_auto_width_result( + std::ranges::data(r),std::ranges::data(r)+std::ranges::size(r)); +} + +} diff --git a/src/fast_io/include/fast_io_hosted/box.h b/src/fast_io/include/fast_io_hosted/box.h new file mode 100644 index 0000000..f7cbd13 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/box.h @@ -0,0 +1,89 @@ +#pragma once + +#if defined(_MSC_VER) && !defined(_KERNEL_MODE) +#pragma comment(lib,"user32.lib") +#endif + +namespace fast_io +{ + +template +struct basic_win32_family_box_t +{ + using char_type = ch_type; + explicit constexpr basic_win32_family_box_t() noexcept = default; +}; + +template +using basic_win32_box_9xa_t = basic_win32_family_box_t; +using win32_box_9xa_t = basic_win32_box_9xa_t; +using wwin32_box_9xa_t = basic_win32_box_9xa_t; +using u8win32_box_9xa_t = basic_win32_box_9xa_t; +using u16win32_box_9xa_t = basic_win32_box_9xa_t; +using u32win32_box_9xa_t = basic_win32_box_9xa_t; + +template +using basic_win32_box_ntw_t = basic_win32_family_box_t; +using win32_box_ntw_t = basic_win32_box_ntw_t; +using wwin32_box_ntw_t = basic_win32_box_ntw_t; +using u8win32_box_ntw_t = basic_win32_box_ntw_t; +using u16win32_box_ntw_t = basic_win32_box_ntw_t; +using u32win32_box_ntw_t = basic_win32_box_ntw_t; + +template +using basic_win32_box_t = basic_win32_family_box_t; +using win32_box_t = basic_win32_box_t; +using wwin32_box_t = basic_win32_box_t; +using u8win32_box_t = basic_win32_box_t; +using u16win32_box_t = basic_win32_box_t; +using u32win32_box_t = basic_win32_box_t; + +namespace details +{ + +template +requires (family==win32_family::wide_nt) +inline void win32_box_write_impl(char16_t* first,char16_t* last) +{ + *::fast_io::freestanding::remove(first,last,0)=0; + using char16_may_alias_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = char16_t const*; + if(!::fast_io::win32::MessageBoxW(nullptr, + reinterpret_cast(first), + reinterpret_cast(u"fast_io"), + 0x00000040L /*MB_ICONINFORMATION*/)) + throw_win32_error(); +} + +template +requires (family==win32_family::ansi_9x) +inline void win32_box_write_impl(char8_t* first,char8_t* last) +{ + *::fast_io::freestanding::remove(first,last,0)=0; + if(!::fast_io::win32::MessageBoxA(nullptr, + reinterpret_cast(first), + reinterpret_cast(u8"fast_io"), + 0x00000040L /*MB_ICONINFORMATION*/)) + throw_win32_error(); +} + +template +inline void win32_box_converter_path_impl(char_type const* first,char_type const* last) +{ + win32_family_api_encoding_converter converter(first,static_cast(last-first)); + win32_box_write_impl(converter.buffer_data,converter.buffer_data_end); +} + +} + +template +requires std::same_as> +inline void write(basic_win32_family_box_t,Iter first,Iter last) +{ + details::win32_box_converter_path_impl(::std::to_address(first),::std::to_address(last)); +} + +} diff --git a/src/fast_io/include/fast_io_hosted/dbg/android.h b/src/fast_io/include/fast_io_hosted/dbg/android.h new file mode 100644 index 0000000..84248d0 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/dbg/android.h @@ -0,0 +1,255 @@ +#pragma once + +namespace fast_io +{ + +struct android_logmessage_meta_base +{ + std::int_least32_t priority{4}; + char const* tag{""}; +}; + +struct android_logmessage_meta_v30 +{ + std::int_least32_t buffer_id{}; + std::int_least32_t priority{4}; + char const* tag{""}; + char const* file{""}; + std::uint_least32_t line{}; +}; + +enum class android_logger_family_tag +{ +base, +v30, +#if defined(__ANDROID__) && __ANDROID_API__ < 30 +native=base, +#else +native=v30, +#endif +}; + +template +struct basic_android_family_logger +{ + using char_type = ch_type; + std::conditional_t meta{}; +}; + +template +requires (sizeof(basic_android_family_logger)<=(sizeof(std::size_t)*2)) +inline constexpr basic_android_family_logger io_value_handle(basic_android_family_logger lg) noexcept +{ + return lg; +}; + +template +using basic_android_logger=basic_android_family_logger; + +using android_logger = basic_android_logger; +using wandroid_logger = basic_android_logger; +using u8android_logger = basic_android_logger; +using u16android_logger = basic_android_logger; +using u32android_logger = basic_android_logger; + +namespace details +{ + +struct cstr_ptr +{ + void* p{}; + constexpr cstr_ptr() noexcept = default; + explicit cstr_ptr(std::size_t n) noexcept + { + if(n==SIZE_MAX) + __builtin_trap(); + p=__builtin_malloc(n+1u); + if(p==nullptr) + __builtin_trap(); + reinterpret_cast(p)[n]=0; + } + cstr_ptr(cstr_ptr const&)=delete; + cstr_ptr& operator=(cstr_ptr const&)=delete; + ~cstr_ptr() + { + __builtin_free(p); + } +}; + +inline void copy_to_cstr_buffer(void* buffer,void const* source,std::size_t n) noexcept +{ + if(n) + __builtin_memcpy(buffer,source,n); +} + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline void cstr_concat_write_impl(void const* first,std::size_t n,callback func) +{ + cstr_ptr p{n}; + copy_to_cstr_buffer(p.p,first,n); + func(reinterpret_cast(p.p)); +} + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline void cstr_concat_writev_impl(io_scatter_t const* first,std::size_t n,callback func) +{ + std::size_t total_len{}; + for(auto i{first},e{i+n};i!=e;++i) + total_len=::fast_io::details::intrinsics::add_or_overflow_die(total_len,i->len); + if(total_len==SIZE_MAX) + __builtin_trap(); + cstr_ptr p{total_len}; + std::byte* start{reinterpret_cast(p.p)}; + for(auto i{first},e{i+n};i!=e;++i) + { + copy_to_cstr_buffer(start,i->base,i->len); + start+=i->len; + } + func(reinterpret_cast(p.p)); +} + +template +inline constexpr bool android_smaller_than_pass_by_mem_size{sizeof(basic_android_family_logger)<=(sizeof(std::size_t)*2)}; + +extern int my_android_log_write(std::int_least32_t,char const*,char const*) noexcept __asm__("__android_log_write"); + +struct android_logmessage_v30 +{ + std::size_t size{sizeof(android_logmessage_v30)}; + std::int_least32_t buffer_id{}; + std::int_least32_t priority{4}; + char const* tag{""}; + char const* file{""}; + std::uint_least32_t line{}; + char const* text; +}; + +extern void my_android_log_write_log_message(android_logmessage_v30* log_message) noexcept __asm__("__android_log_write_log_message"); + +inline void my_android_log_write_impl(std::int_least32_t prio,char const* tag,char const* text) noexcept +{ + my_android_log_write(prio,tag,text); +} + +inline void my_android_log_write_message_impl(android_logmessage_meta_v30 const* meta,char const* text) noexcept +{ + android_logmessage_v30 v{.buffer_id=meta->buffer_id,.priority=meta->priority,.tag=meta->tag,.file=meta->file,.line=meta->line,.text=text}; + my_android_log_write_log_message(__builtin_addressof(v)); +} + + +struct my_android_log_write_common +{ + android_logmessage_meta_base b{}; + void operator()(char const* text) + { + my_android_log_write_impl(b.priority,b.tag,text); + } +}; + +inline void android_logger_write_impl(android_logmessage_meta_base b,void const* base,std::size_t n) +{ + cstr_concat_write_impl(base,n,my_android_log_write_common{b}); +} + +inline void android_logger_writev_impl(android_logmessage_meta_base b,io_scatter_t const* first,std::size_t n) +{ + cstr_concat_writev_impl(first,n,my_android_log_write_common{b}); +} + +struct my_android_log_write_v30_common +{ + android_logmessage_meta_v30 const* pmeta{}; + void operator()(char const* text) + { + my_android_log_write_message_impl(pmeta,text); + } +}; + +inline void android_logger_write_impl(android_logmessage_meta_v30 const& meta,void const* base,std::size_t n) +{ + cstr_concat_write_impl(base,n,my_android_log_write_v30_common{__builtin_addressof(meta)}); +} + +inline void android_logger_writev_impl(android_logmessage_meta_v30 const& meta,io_scatter_t const* first,std::size_t n) +{ + cstr_concat_writev_impl(first,n,my_android_log_write_v30_common{__builtin_addressof(meta)}); +} +} + +template +inline void write(basic_android_family_logger const& b,Iter first,Iter last) +{ + ::fast_io::details::android_logger_write_impl(b.meta,::std::to_address(first),static_cast(last-first)*sizeof(*first)); +} + +template +inline void scatter_write(basic_android_family_logger const& b,io_scatters_t scatters) +{ + ::fast_io::details::android_logger_writev_impl(b.meta,scatters.base,scatters.len); +} + +#if (!defined(__ANDROID__) || __ANDROID_API__ > 30) && __cpp_lib_source_location >= 201907 + +namespace details +{ + +template +inline constexpr auto android_dbg_impl(std::int_least32_t priorit,char const* tg,std::source_location const& loc) +{ + return basic_android_logger{.meta={.priority=priorit,.tag=tg,.file=loc.file_name(),.line=static_cast(loc.line())}}; +} + +} + +inline constexpr auto dbg(std::int_least32_t priority=4,char const* tg="",std::source_location loc=std::source_location::current()) noexcept +{ + return ::fast_io::details::android_dbg_impl(priority,tg,loc); +} +inline constexpr auto wdbg(std::int_least32_t priority=4,char const* tg="",std::source_location loc=std::source_location::current()) noexcept +{ + return ::fast_io::details::android_dbg_impl(priority,tg,loc); +} +inline constexpr auto u8dbg(std::int_least32_t priority=4,char const* tg="",std::source_location loc=std::source_location::current()) noexcept +{ + return ::fast_io::details::android_dbg_impl(priority,tg,loc); +} +inline constexpr auto u16dbg(std::int_least32_t priority=4,char const* tg="",std::source_location loc=std::source_location::current()) noexcept +{ + return ::fast_io::details::android_dbg_impl(priority,tg,loc); +} +inline constexpr auto u32dbg(std::int_least32_t priority=4,char const* tg="",std::source_location loc=std::source_location::current()) noexcept +{ + return ::fast_io::details::android_dbg_impl(priority,tg,loc); +} + +#else +inline constexpr auto dbg(std::int_least32_t priorit=4,char const* tg="") noexcept +{ + return android_logger{.meta={.priority=priorit,.tag=tg}}; +} +inline constexpr auto wdbg(std::int_least32_t priorit=4,char const* tg="") noexcept +{ + return wandroid_logger{.meta={.priority=priorit,.tag=tg}}; +} +inline constexpr auto u8dbg(std::int_least32_t priorit=4,char const* tg="") noexcept +{ + return u8android_logger{.meta={.priority=priorit,.tag=tg}}; +} +inline constexpr auto u16dbg(std::int_least32_t priorit=4,char const* tg="") noexcept +{ + return u16android_logger{.meta={.priority=priorit,.tag=tg}}; +} +inline constexpr auto u32dbg(std::int_least32_t priorit=4,char const* tg="") noexcept +{ + return u32android_logger{.meta={.priority=priorit,.tag=tg}}; +} +#endif + +} diff --git a/src/fast_io/include/fast_io_hosted/dbg/common.h b/src/fast_io/include/fast_io_hosted/dbg/common.h new file mode 100644 index 0000000..c3d07e2 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/dbg/common.h @@ -0,0 +1,13 @@ +#pragma once + +namespace fast_io +{ + +enum class cfmt_format +{ +stdio, +stdio_no_floating, +windows_nt, +}; + +} diff --git a/src/fast_io/include/fast_io_hosted/dbg/err.h b/src/fast_io/include/fast_io_hosted/dbg/err.h new file mode 100644 index 0000000..6ae7b97 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/dbg/err.h @@ -0,0 +1,25 @@ +#pragma once + +namespace fast_io +{ +inline auto dbg() noexcept +{ + return native_stderr(); +} +inline auto wdbg() noexcept +{ + return native_stderr(); +} +inline auto u8dbg() noexcept +{ + return native_stderr(); +} +inline auto u16dbg() noexcept +{ + return native_stderr(); +} +inline auto u32dbg() noexcept +{ + return native_stderr(); +} +} diff --git a/src/fast_io/include/fast_io_hosted/dbg/impl.h b/src/fast_io/include/fast_io_hosted/dbg/impl.h new file mode 100644 index 0000000..3bc53d4 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/dbg/impl.h @@ -0,0 +1,11 @@ +#pragma once +#if defined(__BIONIC__) && __has_include() +#include"android.h" +#elif ((defined(_WIN32)&&!defined(__WINE__)) || defined(__CYGWIN__)) +#include"nt_dbg.h" +#if defined(_WIN32_WINDOWS) +#include"err.h" +#endif +#else +#include"err.h" +#endif diff --git a/src/fast_io/include/fast_io_hosted/dbg/nt_dbg.h b/src/fast_io/include/fast_io_hosted/dbg/nt_dbg.h new file mode 100644 index 0000000..b5ec68e --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/dbg/nt_dbg.h @@ -0,0 +1,184 @@ +#pragma once + +namespace fast_io +{ + +template +struct basic_nt_dbg +{ + using char_type = ch_type; + std::uint_least32_t component_id{UINT_LEAST32_MAX}; + std::uint_least32_t level{}; + static inline constexpr std::size_t output_buffer_alignment_size{512u}; +}; + +template +inline constexpr basic_nt_dbg io_value_handle(basic_nt_dbg serv) noexcept +{ + return {serv}; +} + +using nt_dbg = basic_nt_dbg; +using wnt_dbg = basic_nt_dbg; +using u8nt_dbg = basic_nt_dbg; +using u16nt_dbg = basic_nt_dbg; +using u32nt_dbg = basic_nt_dbg; + +namespace details +{ + +template +inline constexpr std::size_t calculate_nt_dbg_fmt_string_size() noexcept +{ + if constexpr(iswide) + { + static_assert((SIZE_MAX-1/3)>n); + return 3*n+1;//%wZ + } + else + { + static_assert((SIZE_MAX-1/2)>n); + return 2*n+1;//%Z + } +} + +template +inline constexpr auto calculate_nt_dbg_fmt() noexcept +{ + ::fast_io::freestanding::array()> fmt_arr; + for(std::size_t i{};i!=n;++i) + { + if constexpr(iswide) + { + std::size_t threei{i*3}; + fmt_arr[threei]=u8'%'; + fmt_arr[threei+1]=u8'w'; + fmt_arr[threei+2]=u8'Z'; + } + else + { + std::size_t threei{i*2}; + fmt_arr[threei]=u8'%'; + fmt_arr[threei+1]=u8'Z'; + } + } + fmt_arr.back()=0; + return fmt_arr; +} + +template +inline constexpr auto nt_fmt_cache{calculate_nt_dbg_fmt()}; + +struct nt_dbg_carrier +{ + std::uint_least32_t component_id{UINT_LEAST32_MAX}; + std::uint_least32_t level{}; +}; + +template +inline void nt_fmt_dbg_forward([[maybe_unused]] nt_dbg_carrier carr,char8_t const* fmt,io_scatter_t const* arg,Args const* ... args) noexcept +{ + if constexpr(n==0) + { +#if _WIN32_WINNT >= 0x0501 + ::fast_io::win32::nt::DbgPrintEx(carr.component_id,carr.level,reinterpret_cast(fmt),args...); +#else + ::fast_io::win32::nt::DbgPrint(reinterpret_cast(fmt),args...); +#endif + } + else + { + --arg; + void const* arg_n_ptr{arg->base}; + std::size_t arg_n_len{arg->len}; + if(UINT_LEAST16_MAX(arg_n_len)}; + ::fast_io::win32::nt::ansi_string astr{u16argnlen,u16argnlen,const_cast(reinterpret_cast(arg_n_ptr))}; + nt_fmt_dbg_forward(carr,fmt,arg,__builtin_addressof(astr),args...); + } +} + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline void nt_dbg_write_impl([[maybe_unused]] nt_dbg_carrier carr,char const* first,char const* last) noexcept +{ + std::size_t arg_n_len{static_cast(last-first)}; + if(UINT_LEAST16_MAX(arg_n_len)}; + ::fast_io::win32::nt::ansi_string astr{u16argnlen,u16argnlen,const_cast(first)}; +#if _WIN32_WINNT >= 0x0501 + ::fast_io::win32::nt::DbgPrintEx(carr.component_id,carr.level, + reinterpret_cast(nt_fmt_cache.element), + __builtin_addressof(astr)); +#else + ::fast_io::win32::nt::DbgPrint(reinterpret_cast(nt_fmt_cache.element),__builtin_addressof(astr)); +#endif + +} + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline void nt_dbg_scatter_constant_write_impl(nt_dbg_carrier carr,io_scatter_t const* scatters) noexcept +{ + if constexpr(n==0) + { + return; + } + else + { + nt_fmt_dbg_forward(carr,nt_fmt_cache.element,scatters+n); + } +} + +} + +template +inline void write(basic_nt_dbg d,Iter first,Iter last) noexcept +{ + constexpr bool is_wide{sizeof(ch_type)==2&&std::same_as<::std::iter_value_t,ch_type>}; + ::fast_io::details::nt_dbg_write_impl({d.component_id,d.level}, + reinterpret_cast(::std::to_address(first)), + reinterpret_cast(::std::to_address(last))); +} + +template +inline void scatter_constant_write(basic_nt_dbg d,io_scatter_t const* pscatters) noexcept +{ + constexpr bool is_wide{sizeof(ch_type)==2}; + ::fast_io::details::nt_dbg_scatter_constant_write_impl({d.component_id,d.level},pscatters); +} + +#if !defined(_WIN32_WINDOWS) +inline auto dbg(std::uint_least32_t component_id=UINT_LEAST32_MAX,std::uint_least32_t level=0) noexcept +{ + return nt_dbg{component_id,level}; +} +inline auto wdbg(std::uint_least32_t component_id=UINT_LEAST32_MAX,std::uint_least32_t level=0) noexcept +{ + return wnt_dbg{component_id,level}; +} +inline auto u8dbg(std::uint_least32_t component_id=UINT_LEAST32_MAX,std::uint_least32_t level=0) noexcept +{ + return u8nt_dbg{component_id,level}; +} +inline auto u16dbg(std::uint_least32_t component_id=UINT_LEAST32_MAX,std::uint_least32_t level=0) noexcept +{ + return u16nt_dbg{component_id,level}; +} +inline auto u32dbg(std::uint_least32_t component_id=UINT_LEAST32_MAX,std::uint_least32_t level=0) noexcept +{ + return u32nt_dbg{component_id,level}; +} +#endif + +} diff --git a/src/fast_io/include/fast_io_hosted/dll/dll.h b/src/fast_io/include/fast_io_hosted/dll/dll.h new file mode 100644 index 0000000..0e298c8 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/dll/dll.h @@ -0,0 +1,9 @@ +#pragma once + +#if defined(_WIN32) || defined(__CYGWIN__) +#include "win32.h" +#endif +#if (!defined(_WIN32)|| defined(__WINE__)) && (__has_include()&&(defined(__CYGWIN__) || (!defined(__NEWLIB__)&&!defined(__wasi__)))) +#include +#include "posix.h" +#endif diff --git a/src/fast_io/include/fast_io_hosted/dll/posix.h b/src/fast_io/include/fast_io_hosted/dll/posix.h new file mode 100644 index 0000000..baae328 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/dll/posix.h @@ -0,0 +1,233 @@ +#pragma once + +namespace fast_io +{ + +inline constexpr int dll_mode_to_posix_rtld_mode(dll_mode mode) noexcept +{ + int m{}; +#if defined(RTLD_LAZY) + if((mode&dll_mode::posix_rtld_lazy)==dll_mode::posix_rtld_lazy) + m|=RTLD_LAZY; +#endif +#if defined(RTLD_NOW) + if((mode&dll_mode::posix_rtld_now)==dll_mode::posix_rtld_now) + m|=RTLD_NOW; +#endif +#if defined(RTLD_BINDING_MASK) + if((mode&dll_mode::posix_rtld_binding_mask)==dll_mode::posix_rtld_binding_mask) + m|=RTLD_BINDING_MASK; +#endif +#if defined(RTLD_GLOBAL) + if((mode&dll_mode::posix_rtld_global)==dll_mode::posix_rtld_global) + m|=RTLD_GLOBAL; +#endif +#if defined(RTLD_LOCAL) + if((mode&dll_mode::posix_rtld_local)==dll_mode::posix_rtld_local) + m|=RTLD_LOCAL; +#endif +#if defined(RTLD_NODELETE) + if((mode&dll_mode::posix_rtld_nodelete)==dll_mode::posix_rtld_nodelete) + m|=RTLD_NODELETE; +#endif +#if defined(RTLD_NOLOAD) + if((mode&dll_mode::posix_rtld_noload)==dll_mode::posix_rtld_noload) + m|=RTLD_NOLOAD; +#endif +#if defined(RTLD_DEEPBIND) + if((mode&dll_mode::posix_rtld_deepbind)==dll_mode::posix_rtld_deepbind) + m|=RTLD_DEEPBIND; +#endif + return m; +} + +class posix_dll_io_observer +{ +public: + using native_handle_type = void*; + native_handle_type rtld_handle{}; + inline constexpr native_handle_type native_handle() const noexcept + { + return rtld_handle; + } + explicit constexpr operator bool() const noexcept + { + return rtld_handle; + } + inline constexpr native_handle_type release() noexcept + { + auto temp{rtld_handle}; + rtld_handle=nullptr; + return temp; + } +}; + +namespace details +{ + +[[noreturn]] inline void throw_posix_rtld_error(int err=EINVAL) +{ + int en{errno}; + if(!en) + { + en=err; + } + throw_posix_error(en); +} + +inline void* create_posix_rtld(char const* filename,dll_mode mode) +{ + errno={}; + auto hd{noexcept_call(dlopen,filename,::fast_io::dll_mode_to_posix_rtld_mode(mode))}; + if(hd==nullptr) + { + ::fast_io::details::throw_posix_rtld_error( +#if defined(ENOENT) + ENOENT +#endif + ); + } + return hd; +} + +struct posix_rtld_impl_context +{ + dll_mode mode{}; + inline void* operator()(char const* filename) const + { + return create_posix_rtld(filename,mode); + } +}; + +template +inline void* create_posix_rtld_impl(T const& t,dll_mode mode) +{ + return ::fast_io::posix_api_common(t,posix_rtld_impl_context{mode}); +} + +} + +class +#if __has_cpp_attribute(clang::trivially_relocatable) +[[clang::trivially_relocatable]] +#endif +posix_dll_file:public posix_dll_io_observer +{ +public: + using native_handle_type = void*; + constexpr posix_dll_file()=default; + template + requires std::same_as> + explicit constexpr posix_dll_file(native_hd handle) noexcept:posix_dll_io_observer{handle}{} + explicit constexpr posix_dll_file(decltype(nullptr)) noexcept = delete; + + constexpr posix_dll_file(posix_dll_io_observer) noexcept=delete; + constexpr posix_dll_file& operator=(posix_dll_io_observer) noexcept=delete; + template<::fast_io::constructible_to_os_c_str T> + explicit posix_dll_file(T const& t,dll_mode mode):posix_dll_io_observer{::fast_io::details::create_posix_rtld_impl(t,mode)}{} + posix_dll_file(posix_dll_file const&)=delete; + posix_dll_file& operator=(posix_dll_file const&)=delete; + constexpr posix_dll_file(posix_dll_file&& __restrict other) noexcept:posix_dll_io_observer{other.rtld_handle} + { + other.rtld_handle=nullptr; + } + posix_dll_file& operator=(posix_dll_file&& __restrict other) noexcept + { + if(this->rtld_handle)[[likely]] + noexcept_call(dlclose,this->rtld_handle); + this->rtld_handle=other.rtld_handle; + other.rtld_handle=nullptr; + return *this; + } + void close() + { + if(this->rtld_handle)[[likely]] + { + errno={}; + auto ret{noexcept_call(dlclose,this->rtld_handle)}; + this->rtld_handle=nullptr; + if(ret) + { + ::fast_io::details::throw_posix_rtld_error(); + } + } + } + ~posix_dll_file() + { + if(this->rtld_handle)[[likely]] + noexcept_call(dlclose,this->rtld_handle); + } +}; + +namespace details +{ + +inline void* posix_dll_load_symbol_impl(void* rtld_handle,char const* symbol) +{ + auto ptr{noexcept_call(dlsym,rtld_handle,symbol)}; + if(ptr==nullptr)[[unlikely]] + throw_posix_error(EINVAL); + return ptr; +} + +struct posix_dll_load_impl_context +{ + void* rtld_handle{}; + inline void* operator()(char const* symbol) const + { + return posix_dll_load_symbol_impl(rtld_handle,symbol); + } +}; + +#if defined(__GLIBC__) && defined(__GLIBC_PREREQ) +#if __GLIBC_PREREQ(2,0) +inline void* posix_dll_load_vers_symbol_impl(void* rtld_handle,char const* symbol,char const* vers) +{ + auto ptr{noexcept_call(dlvsym,rtld_handle,symbol,vers)}; + if(ptr==nullptr)[[unlikely]] + throw_posix_error(EINVAL); + return ptr; +} + +struct posix_dll_load_versioned_symbol_impl_context +{ + void* rtld_handle{}; + char const* vers{}; + inline void* operator()(char const* symbol) const + { + return posix_dll_load_vers_symbol_impl(rtld_handle,symbol,vers); + } +}; + +#endif +#endif + +} + +template<::fast_io::constructible_to_os_c_str T> +inline void* dll_load_symbol(posix_dll_io_observer pdliob,T const& symbol) +{ + return ::fast_io::posix_api_common(symbol,::fast_io::details::posix_dll_load_impl_context{pdliob.rtld_handle}); +} + +template<::fast_io::constructible_to_os_c_str T,::fast_io::constructible_to_os_c_str T1> +inline void* dll_load_versioned_symbol(posix_dll_io_observer pdliob,T const& symbol,[[maybe_unused]] T1 const& vers) +{ +#if defined(__GLIBC__) && defined(__GLIBC_PREREQ) +#if __GLIBC_PREREQ(2,0) + return ::fast_io::posix_api_common(vers,[&](char const* ver) + { + return ::fast_io::posix_api_common(symbol,::fast_io::details::posix_dll_load_versioned_symbol_impl_context{pdliob.rtld_handle,ver}); + }); +#else + return ::fast_io::posix_api_common(symbol,::fast_io::details::posix_dll_load_impl_context{pdliob.rtld_handle}); +#endif +#else + return ::fast_io::posix_api_common(symbol,::fast_io::details::posix_dll_load_impl_context{pdliob.rtld_handle}); +#endif +} + +using native_dll_io_observer = posix_dll_io_observer; +using native_dll_file = posix_dll_file; + +} diff --git a/src/fast_io/include/fast_io_hosted/dll/win32.h b/src/fast_io/include/fast_io_hosted/dll/win32.h new file mode 100644 index 0000000..7c1ab90 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/dll/win32.h @@ -0,0 +1,209 @@ +#pragma once + +namespace fast_io +{ + +inline constexpr std::uint_least32_t dll_mode_to_win32_ex_flags(dll_mode mode) noexcept +{ + std::uint_least32_t flags{}; + if((mode&dll_mode::win32_dont_resolve_dll_references)==dll_mode::win32_dont_resolve_dll_references) + flags|=0x00000001; + if((mode&dll_mode::win32_load_ignore_code_authz_level)==dll_mode::win32_load_ignore_code_authz_level) + flags|=0x00000010; + if((mode&dll_mode::win32_load_library_as_datafile)==dll_mode::win32_load_library_as_datafile) + flags|=0x00000002; + if((mode&dll_mode::win32_load_library_as_datafile_exclusive)==dll_mode::win32_load_library_as_datafile_exclusive) + flags|=0x00000040; + if((mode&dll_mode::win32_load_library_as_image_resource)==dll_mode::win32_load_library_as_image_resource) + flags|=0x00000020; + if((mode&dll_mode::win32_load_library_search_application_dir)==dll_mode::win32_load_library_search_application_dir) + flags|=0x00000200; + if((mode&dll_mode::win32_load_library_search_default_dirs)==dll_mode::win32_load_library_search_default_dirs) + flags|=0x00001000; + if((mode&dll_mode::win32_load_library_search_dll_load_dir)==dll_mode::win32_load_library_search_dll_load_dir) + flags|=0x00000100; + if((mode&dll_mode::win32_load_library_search_system32)==dll_mode::win32_load_library_search_system32) + flags|=0x00000800; + if((mode&dll_mode::win32_load_library_search_user_dirs)==dll_mode::win32_load_library_search_user_dirs) + flags|=0x00000400; + if((mode&dll_mode::win32_load_with_altered_search_path)==dll_mode::win32_load_with_altered_search_path) + flags|=0x00000008; + if((mode&dll_mode::win32_load_library_require_signed_target)==dll_mode::win32_load_library_require_signed_target) + flags|=0x00000080; + if((mode&dll_mode::win32_load_library_safe_current_dirs)==dll_mode::win32_load_library_safe_current_dirs) + flags|=0x00002000; + return flags; +} + +template +class win32_family_dll_io_observer +{ +public: + using native_handle_type = void*; + native_handle_type hmodule{}; + inline constexpr native_handle_type native_handle() const noexcept + { + return hmodule; + } + explicit constexpr operator bool() const noexcept + { + return hmodule!=nullptr; + } + inline constexpr native_handle_type release() noexcept + { + auto temp{hmodule}; + hmodule=nullptr; + return temp; + } +}; + +namespace details +{ + +inline void* create_win32_dll_9xa(char const* filename) //9x kernel does not support Ex apis +{ + auto hmodule{::fast_io::win32::LoadLibraryA(filename)}; + if(hmodule==nullptr) + throw_win32_error(); + return hmodule; +} +inline void* create_win32_dll_ntw(char16_t const* filename,[[maybe_unused]] dll_mode mode) +{ + auto hmodule{ +#if defined(_WIN32_WINNT) && _WIN32_WINNT <= 0x0500 +//Windows 2000 does not support Ex apis +::fast_io::win32::LoadLibraryW(filename) +#else +::fast_io::win32::LoadLibraryExW(filename,nullptr,dll_mode_to_win32_ex_flags(mode)) +#endif +}; + if(hmodule==nullptr) + throw_win32_error(); + return hmodule; +} + +template +struct win32_family_win32_dll_parameter +{ + using family_char_type = std::conditional_t; + dll_mode mode{}; + inline void* operator()(family_char_type const* filename_c_str) + { + if constexpr(family==win32_family::wide_nt) + { + return create_win32_dll_ntw(filename_c_str,mode); + } + else + { + return create_win32_dll_9xa(filename_c_str); + } + } +}; + +template +requires (::fast_io::constructible_to_os_c_str) +inline void* create_win32_family_dll_impl(T const& t,dll_mode mode) +{ + return ::fast_io::win32_family_api_common(t,win32_family_win32_dll_parameter{mode}); +} + +} + +template +class +#if __has_cpp_attribute(clang::trivially_relocatable) +[[clang::trivially_relocatable]] +#endif +win32_family_dll_file:public win32_family_dll_io_observer +{ +public: + using native_handle_type = void*; + constexpr win32_family_dll_file()=default; + template + requires std::same_as> + explicit constexpr win32_family_dll_file(native_hd handle) noexcept:win32_family_dll_io_observer{handle}{} + explicit constexpr win32_family_dll_file(decltype(nullptr)) noexcept = delete; + + constexpr win32_family_dll_file(win32_family_dll_io_observer) noexcept=delete; + constexpr win32_family_dll_file& operator=(win32_family_dll_io_observer) noexcept=delete; + template<::fast_io::constructible_to_os_c_str T> + explicit win32_family_dll_file(T const& t,dll_mode mode):win32_family_dll_io_observer{::fast_io::details::create_win32_family_dll_impl(t,mode)}{} + win32_family_dll_file(win32_family_dll_file const&)=delete; + win32_family_dll_file& operator=(win32_family_dll_file const&)=delete; + constexpr win32_family_dll_file(win32_family_dll_file&& __restrict other) noexcept:win32_family_dll_io_observer{other.hmodule} + { + other.hmodule=nullptr; + } + win32_family_dll_file& operator=(win32_family_dll_file&& __restrict other) noexcept + { + if(this->hmodule)[[likely]] + win32::FreeLibrary(this->hmodule); + this->hmodule=other.hmodule; + other.hmodule=nullptr; + return *this; + } + void close() + { + if(this->hmodule)[[likely]] + { + auto ret{win32::FreeLibrary(this->hmodule)}; + this->hmodule=nullptr; + if(!ret) + throw_win32_error(); + } + } + ~win32_family_dll_file() + { + if(this->hmodule)[[likely]] + win32::FreeLibrary(this->hmodule); + } +}; + +namespace details +{ +inline void* win32_dll_load_symbol_impl(void* hmodule,char const* symbol) +{ + auto ptr{::fast_io::win32::GetProcAddress(hmodule,symbol)}; + if(ptr==nullptr)[[unlikely]] + throw_win32_error(); + return reinterpret_cast(ptr); +} + +struct win32_dll_load_impl_context +{ + void* hmodule{}; + inline void* operator()(char const* symbol) const + { + return win32_dll_load_symbol_impl(hmodule,symbol); + } +}; + +} + +template +inline void* dll_load_symbol(win32_family_dll_io_observer pdliob,T const& symbol) +{ + return ::fast_io::posix_api_common(symbol,::fast_io::details::win32_dll_load_impl_context{pdliob.hmodule}); +} + +template +inline void* dll_load_versioned_symbol(win32_family_dll_io_observer pdliob,T const& symbol,[[maybe_unused]] T1 const&) +{ + return ::fast_io::posix_api_common(symbol,::fast_io::details::win32_dll_load_impl_context{pdliob.hmodule}); +} + +using win32_dll_io_observer_9xa = win32_family_dll_io_observer; +using win32_dll_file_9xa = win32_family_dll_file; + +using win32_dll_io_observer_ntw = win32_family_dll_io_observer; +using win32_dll_file_ntw = win32_family_dll_file; + +using win32_dll_io_observer = win32_family_dll_io_observer; +using win32_dll_file = win32_family_dll_file; + +#if !defined(__CYGWIN__) && !defined(__WINE__) +using native_dll_io_observer = win32_dll_io_observer; +using native_dll_file = win32_dll_file; +#endif + +} diff --git a/src/fast_io/include/fast_io_hosted/file_loaders/allocation_file_loader.h b/src/fast_io/include/fast_io_hosted/file_loaders/allocation_file_loader.h new file mode 100644 index 0000000..9b30f82 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/file_loaders/allocation_file_loader.h @@ -0,0 +1,215 @@ +#pragma once +/* +Unfinished due to some issues +*/ +namespace fast_io +{ + +namespace details +{ + +template +inline constexpr posix_file_loader_return_value_t allocation_load_file_common_impl(posix_at_entry pate) +{ + auto fsize{posix_loader_get_file_size(pate.fd)}; + buffer_alloc_arr_ptr ptr; + return {}; +} + +#if (defined(_WIN32) && !defined(__WINE__)) || defined(__CYGWIN__) + +template +inline constexpr posix_file_loader_return_value_t allocation_load_file_common_impl( pate) +{ + auto filesize{posix_loader_get_file_size(pate.fd)}; + + + posix_io_observer piob(pate); + + read_all(piob,); +} + +template +inline constexpr posix_file_loader_return_value_t allocation_load_file_impl(native_fs_dirent fsdirent,open_mode om,perms pm) +{ + +} + +#endif + +} + +template +class basic_allocation_file_loader +{ +public: + using file_type = file_type; + using allocator_type = Allocator; + using value_type = char; + using pointer = char*; + using const_pointer = char const*; + using const_iterator = const_pointer; + using iterator = pointer; + using reference = char&; + using const_reference = char const&; + using size_type = std::size_t; + using difference_type = std::ptrdiff_t; + using const_reverse_iterator = std::reverse_iterator; + using reverse_iterator = std::reverse_iterator; + + pointer address_begin{}; + pointer address_end{}; + inline constexpr basic_allocation_file_loader() noexcept=default; + + inline explicit basic_allocation_file_loader(native_fs_dirent fsdirent,open_mode om = open_mode::in, perms pm=static_cast(436)) + { + auto ret{posix_load_file_impl(fsdirent,om,pm)}; + address_begin=ret.address_begin; + address_end=ret.address_end; + } + template<::fast_io::constructible_to_os_c_str T> + inline explicit basic_allocation_file_loader(T const& filename,open_mode om = open_mode::in,perms pm=static_cast(436)) + { + auto ret{posix_load_file_impl(filename,om,pm)}; + address_begin=ret.address_begin; + address_end=ret.address_end; + } + template<::fast_io::constructible_to_os_c_str T> + inline explicit basic_allocation_file_loader(posix_at_entry ent,T const& filename,open_mode om = open_mode::in,perms pm=static_cast(436)) + { + auto ret{posix_load_file_impl(ent,filename,om,pm)}; + address_begin=ret.address_begin; + address_end=ret.address_end; + } + basic_allocation_file_loader(basic_allocation_file_loader const&)=delete; + basic_allocation_file_loader& operator=(basic_allocation_file_loader const&)=delete; + constexpr basic_allocation_file_loader(posix_file_loader_impl&& __restrict other) noexcept:address_begin(other.address_begin),address_end(other.address_end) + { + other.address_end=other.address_begin=nullptr; + } + basic_allocation_file_loader& operator=(basic_allocation_file_loader && __restrict other) noexcept + { + posix_unload_address(address_begin,static_cast(address_end-address_begin)); + address_begin=other.address_begin; + address_end=other.address_end; + if constexpr(allocation) + other.address_end=other.address_begin=nullptr; + else + other.address_end=other.address_begin=(char*)-1; + return *this; + } + constexpr pointer data() const noexcept + { + return address_begin; + } + constexpr bool empty() const noexcept + { + return address_begin==address_end; + } + constexpr std::size_t size() const noexcept + { + return static_cast(address_end-address_begin); + } + constexpr const_iterator cbegin() const noexcept + { + return address_begin; + } + constexpr const_iterator begin() const noexcept + { + return address_begin; + } + constexpr iterator begin() noexcept + { + return address_begin; + } + constexpr const_iterator cend() const noexcept + { + return address_end; + } + constexpr const_iterator end() const noexcept + { + return address_end; + } + constexpr iterator end() noexcept + { + return address_end; + } + constexpr std::size_t max_size() const noexcept + { + return SIZE_MAX; + } + constexpr const_reverse_iterator crbegin() const noexcept + { + return const_reverse_iterator{address_end}; + } + constexpr reverse_iterator rbegin() noexcept + { + return reverse_iterator{address_end}; + } + constexpr const_reverse_iterator rbegin() const noexcept + { + return const_reverse_iterator{address_end}; + } + constexpr const_reverse_iterator crend() const noexcept + { + return const_reverse_iterator{address_begin}; + } + constexpr reverse_iterator rend() noexcept + { + return reverse_iterator{address_begin}; + } + constexpr const_reverse_iterator rend() const noexcept + { + return const_reverse_iterator{address_begin}; + } + constexpr const_reference front() const noexcept + { + return *address_begin; + } + constexpr reference front() noexcept + { + return *address_begin; + } + constexpr const_reference back() const noexcept + { + return address_end[-1]; + } + constexpr reference back() noexcept + { + return address_end[-1]; + } + inline constexpr reference operator[](size_type size) noexcept + { + return address_begin[size]; + } + inline constexpr const_reference operator[](size_type size) const noexcept + { + return address_begin[size]; + } + inline void close() + { + posix_unload_address(address_begin,static_cast(address_end-address_begin)); + if constexpr(allocation) + address_end=address_begin=nullptr; + else + address_end=address_begin=(char*)-1; + } +#if __has_cpp_attribute(nodiscard) + [[nodiscard]] +#endif + inline constexpr pointer release() noexcept + { + pointer temp{address_begin}; + if constexpr(allocation) + address_end=address_begin=nullptr; + else + address_end=address_begin=(char*)-1; + return temp; + } + ~posix_file_loader_impl() + { + posix_unload_address(address_begin,static_cast(address_end-address_begin)); + } +} + +} diff --git a/src/fast_io/include/fast_io_hosted/file_loaders/impl.h b/src/fast_io/include/fast_io_hosted/file_loaders/impl.h new file mode 100644 index 0000000..f3c917d --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/file_loaders/impl.h @@ -0,0 +1,22 @@ +#pragma once +#if !(defined(_WIN32)&&defined(__BIONIC__)) +#include"posix_file_loader.h" +#endif +#if defined(_WIN32) || defined(__CYGWIN__) +#include"win32_file_loader.h" +#endif + + +namespace fast_io +{ + +#if defined(_WIN32) && !defined(__WINE__) +using native_file_loader = win32_file_loader; +#elif (!defined(__NEWLIB__)||defined(__CYGWIN__)) && !defined(__MSDOS__) && !defined(__wasm__) && !defined(_PICOLIBC__) +using native_file_loader = posix_file_loader; +#else +using native_file_loader = allocation_file_loader; +#endif + + +} diff --git a/src/fast_io/include/fast_io_hosted/file_loaders/posix_file_loader.h b/src/fast_io/include/fast_io_hosted/file_loaders/posix_file_loader.h new file mode 100644 index 0000000..7758c0f --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/file_loaders/posix_file_loader.h @@ -0,0 +1,540 @@ +#pragma once + +#if defined(__has_builtin) +#if !__has_builtin(__builtin_malloc) || !__has_builtin(__builtin_free) +#include +#endif +#elif !defined(_MSC_VER) +#include +#endif + +namespace fast_io +{ +#if (defined(_WIN32) && !defined(__BIONIC__)) || defined(__CYGWIN__) +namespace win32::details +{ +inline std::size_t win32_load_file_get_file_size(void* handle) +{ + by_handle_file_information bhdi; + if(!GetFileInformationByHandle(handle,__builtin_addressof(bhdi))) + throw_win32_error(); + if constexpr(sizeof(std::size_t)static_cast(SIZE_MAX)) + throw_win32_error(0x000000DF); + } + return static_cast(bhdi.nFileSizeLow); + } + else + { + return static_cast((static_cast(bhdi.nFileSizeHigh)<<32)|bhdi.nFileSizeLow); + } +} +} +#endif + +namespace details +{ + +struct linux_statx_timestamp { +::std::int_least64_t tv_sec; +::std::uint_least32_t tv_nsec, pad; +}; + +struct linux_struct_statx { +::std::uint_least32_t stx_mask; +::std::uint_least32_t stx_blksize; +::std::uint_least64_t stx_attributes; +::std::uint_least32_t stx_nlink; +::std::uint_least32_t stx_uid; +::std::uint_least32_t stx_gid; +::std::uint_least16_t stx_mode; +::std::uint_least16_t pad0[1]; +::std::uint_least64_t stx_ino; +::std::uint_least64_t stx_size; +::std::uint_least64_t stx_blocks; +::std::uint_least64_t stx_attributes_mask; +::fast_io::details::linux_statx_timestamp stx_atime; +::fast_io::details::linux_statx_timestamp stx_btime; +::fast_io::details::linux_statx_timestamp stx_ctime; +::fast_io::details::linux_statx_timestamp stx_mtime; +::std::uint_least32_t stx_rdev_major; +::std::uint_least32_t stx_rdev_minor; +::std::uint_least32_t stx_dev_major; +::std::uint_least32_t stx_dev_minor; +::std::uint_least64_t pad1[14]; +}; + +inline constexpr ::std::uint_least32_t linux_statx_size{0x200U}; + +inline std::size_t posix_loader_get_file_size(int fd) +{ +#if defined(_WIN32) && !defined(__BIONIC__)&&!defined(__WINE__) +//windows 95 and windows 98 msvcrt do not provide struct __stat64. Directly invoke win32 api + return ::fast_io::win32::details::win32_load_file_get_file_size(reinterpret_cast(noexcept_call(_get_osfhandle,fd))); +#elif defined(__linux__) && defined(__NR_statx) +//Linux kernel provides new __NR_statx syscall. That allows us to only extract part of information and avoid libc braindeath beneath. + linux_struct_statx statxbuf; + system_call_throw_error(system_call<__NR_statx,int>(fd,reinterpret_cast(u8""), +#if defined(AT_EMPTY_PATH) + AT_EMPTY_PATH +#else + 0x1000 //AT_EMPTY_PATH requires _GNU_SOURCE gets defined which might not be available for all libcs +#endif + ,linux_statx_size,__builtin_addressof(statxbuf))); + using stx_size_unsigned_type = std::make_unsigned_t; + if constexpr(sizeof(stx_size_unsigned_type)>sizeof(std::size_t)) + { + if(static_cast(statxbuf.stx_size)>static_cast(SIZE_MAX)) + throw_posix_error(EINVAL); + } + return static_cast(statxbuf.stx_size); +#else +#if defined(__linux__) && !defined(__MLIBC_O_CLOEXEC) + struct stat64 st; +#else + struct stat st; +#endif + if( +#if defined(__linux__) && !defined(__MLIBC_O_CLOEXEC) +fstat64 +#else +fstat +#endif + (fd,__builtin_addressof(st))<0) + throw_posix_error(); + using st_size_unsigned_type = std::make_unsigned_t; + if constexpr(sizeof(st_size_unsigned_type)>sizeof(std::size_t)) + { + if(static_cast(st.st_size)>static_cast(SIZE_MAX)) + throw_posix_error(EINVAL); + } + return static_cast(st.st_size); +#endif +} + + +struct load_file_allocation_guard +{ + void* address{}; + explicit load_file_allocation_guard(std::size_t file_size):address( +#if defined(__has_builtin) +#if __has_builtin(__builtin_malloc) +__builtin_malloc +#else +malloc +#endif +#else +malloc +#endif +(file_size)) + { + if(address==nullptr) + throw_posix_error(EINVAL); + } + load_file_allocation_guard(load_file_allocation_guard const&)=delete; + load_file_allocation_guard& operator=(load_file_allocation_guard const&)=delete; + ~load_file_allocation_guard() + { +#if defined(__has_builtin) +#if __has_builtin(__builtin_free) + __builtin_free(address); +#else + free(address); +#endif +#else + free(address); +#endif + } +}; + +template +inline char* posix_load_address(int fd,std::size_t file_size) +{ + if constexpr(allocation) + { + if(file_size==0) + return nullptr; + load_file_allocation_guard guard{file_size}; + posix_io_observer piob{fd}; + auto addr{reinterpret_cast(guard.address)}; + auto addr_ed{addr+file_size}; + for(auto i{addr};i!=addr_ed;) + { + auto after{read(piob,i,addr_ed)}; + if(after==i) + throw_posix_error(); + i=after; + } + guard.address=nullptr; + return addr; + } + else + { +#if defined(_WIN32) || (defined(__NEWLIB__)&&!defined(__CYGWIN__)) || defined(__MSDOS__) || defined(_PICOLIBC__) || (defined(__wasm__)&&!defined(_WASI_EMULATED_MMAN)) + static_assert(allocation); +#else + if(file_size==0) + return (char*)-1; + return reinterpret_cast( +sys_mmap(nullptr,file_size,PROT_READ|PROT_WRITE,MAP_PRIVATE +#if defined(MAP_POPULATE) +|MAP_POPULATE +#endif +,fd,0)); +#endif + } +} + +inline char* posix_load_address_extra(int fd,std::size_t file_size,std::size_t exsz) +{ + ::std::size_t mxsz{SIZE_MAX-exsz}; + if(file_size>mxsz) + { + throw_posix_error(EINVAL); + } + load_file_allocation_guard guard{file_size+exsz}; + posix_io_observer piob{fd}; + auto addr{reinterpret_cast(guard.address)}; + auto addr_ed{addr+file_size}; + for(auto i{addr};i!=addr_ed;) + { + auto after{read(piob,i,addr_ed)}; + if(after==i) + throw_posix_error(); + i=after; + } +#if defined(__has_builtin) +#if __has_builtin(__builtin_memset) +__builtin_memset +#else +memset +#endif +#else +memset +#endif + (addr_ed,0,exsz); + guard.address=nullptr; + return addr; +} + + +template +inline void posix_unload_address(void* address,[[maybe_unused]] std::size_t file_size) noexcept +{ + if constexpr(allocation) + { +#if defined(__has_builtin) +#if __has_builtin(__builtin_free) + __builtin_free(address); +#else + free(address); +#endif +#else + free(address); +#endif + } + else + { +#if defined(_WIN32) || (defined(__NEWLIB__)&&!defined(__CYGWIN__)) || defined(_PICOLIBC__) || defined(__MSDOS__) || defined(__wasm__) + static_assert(allocation); +#else + if(address!=(void*)-1)[[likely]] + sys_munmap(address,file_size); +#endif + } +} + +struct posix_file_loader_return_value_t +{ + char* address_begin; + char* address_end; +}; + +template +inline posix_file_loader_return_value_t posix_load_address_impl(int fd) +{ + std::size_t size{posix_loader_get_file_size(fd)}; + auto add{posix_load_address(fd,size)}; + return {add,add+size}; +} + +template +inline auto posix_load_file_impl(native_fs_dirent fsdirent,open_mode om,perms pm) +{ + posix_file pf(fsdirent,om,pm); + return posix_load_address_impl(pf.fd); +} + +template +inline auto posix_load_file_impl(T const& str,open_mode om,perms pm) +{ + posix_file pf(str,om,pm); + return posix_load_address_impl(pf.fd); +} + +template +inline auto posix_load_file_impl(native_at_entry ent,T const& str,open_mode om,perms pm) +{ + posix_file pf(ent,str,om,pm); + return posix_load_address_impl(pf.fd); +} + + +inline posix_file_loader_return_value_t posix_load_address_allocation_extra_impl(::std::size_t exsz,int fd) +{ + std::size_t size{posix_loader_get_file_size(fd)}; + auto add{posix_load_address_extra(fd,size,exsz)}; + return {add,add+size}; +} + +inline auto posix_load_file_allocation_extra_impl(::std::size_t exsz,native_fs_dirent fsdirent,open_mode om,perms pm) +{ + posix_file pf(fsdirent,om,pm); + return posix_load_address_allocation_extra_impl(exsz,pf.fd); +} + +template<::fast_io::constructible_to_os_c_str T> +inline auto posix_load_file_allocation_extra_impl(::std::size_t exsz,T const& str,open_mode om,perms pm) +{ + posix_file pf(str,om,pm); + return posix_load_address_allocation_extra_impl(exsz,pf.fd); +} + +template<::fast_io::constructible_to_os_c_str T> +inline auto posix_load_file_allocation_extra_impl(::std::size_t exsz,native_at_entry ent,T const& str,open_mode om,perms pm) +{ + posix_file pf(ent,str,om,pm); + return posix_load_address_allocation_extra_impl(exsz,pf.fd); +} + + + +template +class posix_file_loader_impl +{ +public: + using value_type = char; + using pointer = char*; + using const_pointer = char const*; + using const_iterator = const_pointer; + using iterator = pointer; + using reference = char&; + using const_reference = char const&; + using size_type = std::size_t; + using difference_type = std::ptrdiff_t; + using const_reverse_iterator = std::reverse_iterator; + using reverse_iterator = std::reverse_iterator; + + pointer address_begin{}; + pointer address_end{}; + inline constexpr posix_file_loader_impl() noexcept requires(allocation)=default; + inline constexpr posix_file_loader_impl() noexcept : address_begin((char*)-1),address_end((char*)-1){} + inline explicit posix_file_loader_impl(posix_at_entry pate) + { + auto ret{posix_load_address_impl(pate.fd)}; + address_begin=ret.address_begin; + address_end=ret.address_end; + } + inline explicit posix_file_loader_impl(native_fs_dirent fsdirent,open_mode om = open_mode::in, perms pm=static_cast(436)) + { + auto ret{posix_load_file_impl(fsdirent,om,pm)}; + address_begin=ret.address_begin; + address_end=ret.address_end; + } + template<::fast_io::constructible_to_os_c_str T> + inline explicit posix_file_loader_impl(T const& filename,open_mode om = open_mode::in,perms pm=static_cast(436)) + { + auto ret{posix_load_file_impl(filename,om,pm)}; + address_begin=ret.address_begin; + address_end=ret.address_end; + } + template<::fast_io::constructible_to_os_c_str T> + inline explicit posix_file_loader_impl(native_at_entry ent,T const& filename,open_mode om = open_mode::in,perms pm=static_cast(436)) + { + auto ret{posix_load_file_impl(ent,filename,om,pm)}; + address_begin=ret.address_begin; + address_end=ret.address_end; + } + posix_file_loader_impl(posix_file_loader_impl const&)=delete; + posix_file_loader_impl& operator=(posix_file_loader_impl const&)=delete; + constexpr posix_file_loader_impl(posix_file_loader_impl&& __restrict other) noexcept:address_begin(other.address_begin),address_end(other.address_end) + { + if constexpr(allocation) + other.address_end=other.address_begin=nullptr; + else + other.address_end=other.address_begin=(char*)-1; + } + posix_file_loader_impl& operator=(posix_file_loader_impl && __restrict other) noexcept + { + posix_unload_address(address_begin,static_cast(address_end-address_begin)); + address_begin=other.address_begin; + address_end=other.address_end; + if constexpr(allocation) + other.address_end=other.address_begin=nullptr; + else + other.address_end=other.address_begin=(char*)-1; + return *this; + } + + + inline explicit posix_file_loader_impl(file_loader_extra_bytes exb,posix_at_entry pate) requires(allocation) + { + auto ret{posix_load_address_allocation_extra_impl(exb.n,pate.fd)}; + address_begin=ret.address_begin; + address_end=ret.address_end; + } + inline explicit posix_file_loader_impl(file_loader_extra_bytes exb,native_fs_dirent fsdirent,open_mode om = open_mode::in, perms pm=static_cast(436)) requires(allocation) + { + auto ret{posix_load_file_allocation_extra_impl(exb.n,fsdirent,om,pm)}; + address_begin=ret.address_begin; + address_end=ret.address_end; + } + template<::fast_io::constructible_to_os_c_str T> + inline explicit posix_file_loader_impl(file_loader_extra_bytes exb,T const& filename,open_mode om = open_mode::in,perms pm=static_cast(436)) requires(allocation) + { + auto ret{posix_load_file_allocation_extra_impl(exb.n,filename,om,pm)}; + address_begin=ret.address_begin; + address_end=ret.address_end; + } + template<::fast_io::constructible_to_os_c_str T> + inline explicit posix_file_loader_impl(file_loader_extra_bytes exb,native_at_entry ent,T const& filename,open_mode om = open_mode::in,perms pm=static_cast(436)) requires(allocation) + { + auto ret{posix_load_file_allocation_extra_impl(exb.n,ent,filename,om,pm)}; + address_begin=ret.address_begin; + address_end=ret.address_end; + } + + constexpr pointer data() const noexcept + { + return address_begin; + } + constexpr bool empty() const noexcept + { + return address_begin==address_end; + } + constexpr std::size_t size() const noexcept + { + return static_cast(address_end-address_begin); + } + constexpr const_iterator cbegin() const noexcept + { + return address_begin; + } + constexpr const_iterator begin() const noexcept + { + return address_begin; + } + constexpr iterator begin() noexcept + { + return address_begin; + } + constexpr const_iterator cend() const noexcept + { + return address_end; + } + constexpr const_iterator end() const noexcept + { + return address_end; + } + constexpr iterator end() noexcept + { + return address_end; + } + constexpr std::size_t max_size() const noexcept + { + return SIZE_MAX; + } + constexpr const_reverse_iterator crbegin() const noexcept + { + return const_reverse_iterator{address_end}; + } + constexpr reverse_iterator rbegin() noexcept + { + return reverse_iterator{address_end}; + } + constexpr const_reverse_iterator rbegin() const noexcept + { + return const_reverse_iterator{address_end}; + } + constexpr const_reverse_iterator crend() const noexcept + { + return const_reverse_iterator{address_begin}; + } + constexpr reverse_iterator rend() noexcept + { + return reverse_iterator{address_begin}; + } + constexpr const_reverse_iterator rend() const noexcept + { + return const_reverse_iterator{address_begin}; + } + constexpr const_reference front() const noexcept + { + return *address_begin; + } + constexpr reference front() noexcept + { + return *address_begin; + } + constexpr const_reference back() const noexcept + { + return address_end[-1]; + } + constexpr reference back() noexcept + { + return address_end[-1]; + } + inline constexpr reference operator[](size_type size) noexcept + { + return address_begin[size]; + } + inline constexpr const_reference operator[](size_type size) const noexcept + { + return address_begin[size]; + } + inline void close() + { + posix_unload_address(address_begin,static_cast(address_end-address_begin)); + if constexpr(allocation) + address_end=address_begin=nullptr; + else + address_end=address_begin=(char*)-1; + } +#if __has_cpp_attribute(nodiscard) + [[nodiscard]] +#endif + inline constexpr pointer release() noexcept + { + pointer temp{address_begin}; + if constexpr(allocation) + address_end=address_begin=nullptr; + else + address_end=address_begin=(char*)-1; + return temp; + } + ~posix_file_loader_impl() + { + posix_unload_address(address_begin,static_cast(address_end-address_begin)); + } +}; + +template +inline constexpr basic_io_scatter_t print_alias_define(io_alias_t,posix_file_loader_impl const& load) noexcept +{ + return {load.data(),load.size()}; +} + +} + +#if (!defined(_WIN32) || defined(__WINE__)) && (!defined(__NEWLIB__)||defined(__CYGWIN__)) && !defined(__MSDOS__) && !defined(__wasm__) && !defined(_PICOLIBC__) +using posix_file_loader = details::posix_file_loader_impl; +#endif + +using allocation_file_loader = details::posix_file_loader_impl; + +} diff --git a/src/fast_io/include/fast_io_hosted/file_loaders/win32_file_loader.h b/src/fast_io/include/fast_io_hosted/file_loaders/win32_file_loader.h new file mode 100644 index 0000000..b8f7902 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/file_loaders/win32_file_loader.h @@ -0,0 +1,244 @@ +#pragma once + +namespace fast_io +{ + +namespace win32::details +{ + +struct win32_file_loader_return_value_t +{ + char* address_begin; + char* address_end; +}; + +inline win32_file_loader_return_value_t win32_load_address_common_impl(void* hfilemappingobj,std::size_t file_size) +{ + if(hfilemappingobj==nullptr) + throw_win32_error(); + win32_file map_hd{hfilemappingobj}; + auto base_ptr{MapViewOfFile(hfilemappingobj,1,0,0,file_size)}; + if(base_ptr==nullptr) + throw_win32_error(); + return {reinterpret_cast(base_ptr),reinterpret_cast(base_ptr)+file_size}; +} + +template +inline win32_file_loader_return_value_t win32_load_address_impl(void* handle) +{ + std::size_t file_size{win32_load_file_get_file_size(handle)}; + if(file_size==0) + return {nullptr,nullptr}; + if constexpr(family==win32_family::wide_nt) + return win32_load_address_common_impl(CreateFileMappingW(handle,nullptr,0x08,0,0,nullptr),file_size); + else + return win32_load_address_common_impl(CreateFileMappingA(handle,nullptr,0x08,0,0,nullptr),file_size); +} + +template +inline auto win32_load_file_impl(nt_fs_dirent fsdirent,open_mode om,perms pm) +{ + basic_win32_family_file wf(fsdirent,om,pm); + return win32_load_address_impl(wf.handle); +} + +template +inline auto win32_load_file_impl(T const& str,open_mode om,perms pm) +{ + basic_win32_family_file wf(str,om,pm); + return win32_load_address_impl(wf.handle); +} + +template +inline auto win32_load_file_impl(nt_at_entry ent,T const& str,open_mode om,perms pm) +{ + basic_win32_family_file wf(ent,str,om,pm); + return win32_load_address_impl(wf.handle); +} + +inline void win32_unload_address(void const* address) noexcept +{ + if(address) + UnmapViewOfFile(address); +} + +} + +template +class win32_family_file_loader +{ +public: + using value_type = char; + using pointer = char*; + using const_pointer = char const*; + using const_iterator = const_pointer; + using iterator = pointer; + using reference = char&; + using const_reference = char const&; + using size_type = std::size_t; + using difference_type = std::ptrdiff_t; + using const_reverse_iterator = std::reverse_iterator; + using reverse_iterator = std::reverse_iterator; + + pointer address_begin{}; + pointer address_end{}; + inline constexpr win32_family_file_loader() noexcept=default; + inline explicit win32_family_file_loader(nt_at_entry ent) + { + auto ret{win32::details::win32_load_address_impl(ent.handle)}; + address_begin=ret.address_begin; + address_end=ret.address_end; + } + inline explicit win32_family_file_loader(nt_fs_dirent fsdirent,open_mode om = open_mode::in,perms pm=static_cast(436)) + { + auto ret{win32::details::win32_load_file_impl(fsdirent,om,pm)}; + address_begin=ret.address_begin; + address_end=ret.address_end; + } + template<::fast_io::constructible_to_os_c_str T> + inline explicit win32_family_file_loader(T const& filename,open_mode om = open_mode::in,perms pm=static_cast(436)) + { + auto ret{win32::details::win32_load_file_impl(filename,om,pm)}; + address_begin=ret.address_begin; + address_end=ret.address_end; + } + template<::fast_io::constructible_to_os_c_str T> + inline explicit win32_family_file_loader(nt_at_entry ent,T const& filename,open_mode om = open_mode::in,perms pm=static_cast(436)) + { + auto ret{win32::details::win32_load_file_impl(ent,filename,om,pm)}; + address_begin=ret.address_begin; + address_end=ret.address_end; + } + win32_family_file_loader(win32_family_file_loader const&)=delete; + win32_family_file_loader& operator=(win32_family_file_loader const&)=delete; + constexpr win32_family_file_loader(win32_family_file_loader&& __restrict other) noexcept:address_begin(other.address_begin),address_end(other.address_end) + { + other.address_end=other.address_begin=nullptr; + } + win32_family_file_loader& operator=(win32_family_file_loader&& __restrict other) noexcept + { + win32::details::win32_unload_address(address_begin); + address_begin=other.address_begin; + address_end=other.address_end; + other.address_end=other.address_begin=nullptr; + return *this; + } + constexpr pointer data() const noexcept + { + return address_begin; + } + constexpr bool empty() const noexcept + { + return address_begin==address_end; + } + constexpr std::size_t size() const noexcept + { + return static_cast(address_end-address_begin); + } + constexpr std::size_t max_size() const noexcept + { + return SIZE_MAX; + } + constexpr const_iterator cbegin() const noexcept + { + return address_begin; + } + constexpr const_iterator begin() const noexcept + { + return address_begin; + } + constexpr iterator begin() noexcept + { + return address_begin; + } + constexpr const_iterator cend() const noexcept + { + return address_end; + } + constexpr const_iterator end() const noexcept + { + return address_end; + } + constexpr iterator end() noexcept + { + return address_end; + } + constexpr const_reverse_iterator crbegin() const noexcept + { + return const_reverse_iterator{address_end}; + } + constexpr reverse_iterator rbegin() noexcept + { + return reverse_iterator{address_end}; + } + constexpr const_reverse_iterator rbegin() const noexcept + { + return const_reverse_iterator{address_end}; + } + constexpr const_reverse_iterator crend() const noexcept + { + return const_reverse_iterator{address_begin}; + } + constexpr reverse_iterator rend() noexcept + { + return reverse_iterator{address_begin}; + } + constexpr const_reverse_iterator rend() const noexcept + { + return const_reverse_iterator{address_begin}; + } + constexpr const_reference front() const noexcept + { + return *address_begin; + } + constexpr reference front() noexcept + { + return *address_begin; + } + constexpr const_reference back() const noexcept + { + return address_end[-1]; + } + constexpr reference back() noexcept + { + return address_end[-1]; + } +#if __has_cpp_attribute(nodiscard) + [[nodiscard]] +#endif + constexpr pointer release() noexcept + { + auto temp{this->address_begin}; + this->address_end=this->address_begin = nullptr; + return temp; + } + inline constexpr reference operator[](size_type size) noexcept + { + return address_begin[size]; + } + inline constexpr const_reference operator[](size_type size) const noexcept + { + return address_begin[size]; + } + inline void close() + { + win32::details::win32_unload_address(address_begin); + address_end=address_begin=nullptr; + } + ~win32_family_file_loader() + { + win32::details::win32_unload_address(address_begin); + } +}; + +template +inline constexpr basic_io_scatter_t print_alias_define(io_alias_t,win32_family_file_loader const& load) noexcept +{ + return {load.data(),load.size()}; +} + +using win32_file_loader_9xa=win32_family_file_loader; +using win32_file_loader_ntw=win32_family_file_loader; +using win32_file_loader=win32_family_file_loader; + +} diff --git a/src/fast_io/include/fast_io_hosted/filesystem/apis.h b/src/fast_io/include/fast_io_hosted/filesystem/apis.h new file mode 100644 index 0000000..be29d4c --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/filesystem/apis.h @@ -0,0 +1,27 @@ +#pragma once + +namespace fast_io::details +{ + +enum class posix_api_22 +{ +renameat, +linkat +}; +enum class posix_api_12 +{ +symlinkat +}; +enum class posix_api_1x +{ +faccessat, +utimensat, +fchmodat, +fchownat, +fstatat, +mkdirat, +mknodat, +unlinkat +}; + +} diff --git a/src/fast_io/include/fast_io_hosted/filesystem/fsutils.h b/src/fast_io/include/fast_io_hosted/filesystem/fsutils.h new file mode 100644 index 0000000..cbfd36c --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/filesystem/fsutils.h @@ -0,0 +1,67 @@ +#pragma once + +namespace fast_io::details +{ + +template +inline constexpr char_type const* my_rfind_dot(char_type const* first,char_type const* last) noexcept +{ + for(;first!=last;--last) + { + auto fp1{last}; + --fp1; + if(*fp1==u8'.') + return last; + } + return first; +} + +template +requires (sizeof(return_char_type)==sizeof(char_type)) +inline constexpr std::conditional_t, + ::fast_io::manipulators::basic_os_c_str_with_known_size> + find_dot_and_sep(char_type const* beg_ptr,std::size_t namlen) noexcept +{ + if constexpr(std::same_as) + { + char_type const* ed_ptr{beg_ptr+namlen}; + char_type const* f{my_rfind_dot(beg_ptr,ed_ptr)}; + std::size_t diff{static_cast(f-beg_ptr)}; + if(diff<2||(diff==2&&2(ed_ptr-f)}; + return {f,retdiff}; + } + } + else + { + using return_char_type_const_may_alias_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif + = return_char_type const*; + auto rtval{find_dot_and_sep(beg_ptr,namlen)}; + return {reinterpret_cast(rtval.ptr),rtval.n}; + } +} + +} diff --git a/src/fast_io/include/fast_io_hosted/filesystem/native.h b/src/fast_io/include/fast_io_hosted/filesystem/native.h new file mode 100644 index 0000000..1a1db28 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/filesystem/native.h @@ -0,0 +1,14 @@ +#pragma once + +#include"apis.h" +#include"fsutils.h" + +#if (!defined(__NEWLIB__)||defined(__CYGWIN__)) && !defined(_WIN32) && !defined(__MSDOS__) && __has_include() && !defined(_PICOLIBC__) +#include"posix.h" +#include"posix_at.h" +#endif + +#if defined(_WIN32) || defined(__CYGWIN__) +#include"nt.h" +#include"nt_at.h" +#endif diff --git a/src/fast_io/include/fast_io_hosted/filesystem/nt.h b/src/fast_io/include/fast_io_hosted/filesystem/nt.h new file mode 100644 index 0000000..e05beb8 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/filesystem/nt.h @@ -0,0 +1,556 @@ +#pragma once + +namespace fast_io +{ + +/* +https://github.com/reactos/reactos/blob/7ffb6a09c370ef51de554a1ce913f871d72b76ca/dll/win32/kernel32/client/file/find.c#L647 + +HANDLE +WINAPI +FindFirstFileExW(IN LPCWSTR lpFileName, + IN FINDEX_INFO_LEVELS fInfoLevelId, + OUT LPVOID lpFindFileData, + IN FINDEX_SEARCH_OPS fSearchOp, + LPVOID lpSearchFilter, + IN DWORD dwAdditionalFlags) + +*/ + +struct nt_dirent +{ + void* d_handle{}; + file_type d_type{}; + char16_t native_d_name[0x2001]; + std::size_t native_d_namlen{}; + char8_t u8d_name[0x8004]; + std::size_t u8d_namlen{}; +}; + +namespace win32::nt::details +{ + +template +struct nt_dirent_space_guard +{ + using pointer = T*; + pointer ptr{}; + constexpr nt_dirent_space_guard() noexcept = default; + nt_dirent_space_guard(nt_dirent_space_guard const&)=delete; + nt_dirent_space_guard& operator=(nt_dirent_space_guard const&)=delete; + constexpr T* release() noexcept + { + pointer temp{ptr}; + this->ptr=nullptr; + return temp; + } + ~nt_dirent_space_guard() + { + if(ptr) + { + typed_generic_allocator_adapter::deallocate_n(ptr,1); + } + } +}; + +template +inline +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L +constexpr +#endif +nt_dirent* new_nt_dirent() noexcept +{ +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if(__builtin_is_constant_evaluated()) +#endif + { + return new nt_dirent; + } + else +#endif + { + nt_dirent_space_guard guard; + guard.ptr=typed_generic_allocator_adapter::allocate(1); + ::new (guard.ptr) nt_dirent; + return guard.release(); + } +} + +template +inline +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L +constexpr +#endif +void delete_nt_dirent(nt_dirent* ptr) noexcept +{ +#if __cpp_if_consteval >= 202106L || __cpp_lib_is_constant_evaluated >= 201811L +#if __cpp_if_consteval >= 202106L + if consteval +#else + if(__builtin_is_constant_evaluated()) +#endif + { + delete ptr; + } + else +#endif + { + if(ptr==nullptr) + { + return; + } + ptr->~nt_dirent(); + typed_generic_allocator_adapter::deallocate_n(ptr, 1); + } +} + +template +inline nt_dirent* set_nt_dirent(nt_dirent* entry,bool start) +{ + io_status_block block{}; + constexpr std::uint_least32_t ul32_buffer_size{0x4000}; + std::byte buffer[ul32_buffer_size]; + ::fast_io::win32::nt::dir_information d_info{buffer}; + auto status{nt_query_directory_file(entry->d_handle,nullptr,nullptr,nullptr, + __builtin_addressof(block),d_info.DirInfo, + ul32_buffer_size,file_information_class::FileFullDirectoryInformation, + true,nullptr,start)}; + if(status) + { + if(status==2147483654)[[likely]] + return nullptr; + throw_nt_error(status); + } + auto ful_dir_info{d_info.FullDirInfo}; + entry->native_d_namlen=ful_dir_info->FileNameLength/sizeof(char16_t); + + ::fast_io::freestanding::nonoverlapped_bytes_copy_n( + reinterpret_cast(ful_dir_info->FileName),ful_dir_info->FileNameLength, + reinterpret_cast(entry->native_d_name)); + entry->native_d_name[entry->native_d_namlen]=0; + + char16_t const* enstart{entry->native_d_name}; + char16_t const* enend{enstart+entry->native_d_namlen}; + entry->u8d_namlen=static_cast(::fast_io::details::codecvt::general_code_cvt_full(enstart,enend,entry->u8d_name)-entry->u8d_name); + entry->u8d_name[entry->u8d_namlen]=0; +/* +Referenced from win32 port dirent.h +https://github.com/win32ports/dirent_h/blob/5a40afce928f1780058f44e0dda37553c662a8a7/dirent.h#L249 + if (((w32fd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == FILE_ATTRIBUTE_REPARSE_POINT) && __islink(wname, buffer)) + data->entries[data->index].d_type = DT_LNK; + else if ((w32fd.dwFileAttributes & FILE_ATTRIBUTE_DEVICE) == FILE_ATTRIBUTE_DEVICE) + data->entries[data->index].d_type = DT_CHR; + else if ((w32fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY) + data->entries[data->index].d_type = DT_DIR; + else + data->entries[data->index].d_type = DT_REG; +*/ + + std::uint_least32_t attribute{ful_dir_info->FileAttributes}; + if(attribute&0x400) + entry->d_type=file_type::symlink; + else if(attribute&0x40) + entry->d_type=file_type::character; + else if(attribute&0x10) + entry->d_type=file_type::directory; + else if(attribute&0x1000) + entry->d_type=file_type::remote; + else + entry->d_type=file_type::regular; + return entry; +} + +template +inline nt_dirent* set_nt_dirent_first(nt_dirent* entry) +{ + return set_nt_dirent(entry,true); +} + +template +inline nt_dirent* nt_dirent_next(nt_dirent* entry) +{ + return set_nt_dirent(entry,false); +} + +} + +struct nt_directory_entry +{ + using native_char_type = char16_t; + using char_type = char8_t; + nt_dirent* entry{}; + template + explicit constexpr operator basic_nt_family_io_observer() const noexcept + { + return {entry->d_handle}; + } + template + explicit constexpr operator basic_win32_family_io_observer() const noexcept + { + return {entry->d_handle}; + } +}; + +inline constexpr nt_at_entry at(nt_directory_entry ndet) noexcept +{ + return nt_at_entry{ndet.entry->d_handle}; +} + +inline constexpr ::fast_io::manipulators::basic_os_c_str_with_known_size native_filename(nt_directory_entry pioe) noexcept +{ + auto& ent{*pioe.entry}; + return {ent.native_d_name,ent.native_d_namlen}; +} + +inline constexpr nt_fs_dirent drt(nt_directory_entry pioe) noexcept +{ + auto& ent{*pioe.entry}; + return nt_fs_dirent{ent.d_handle,{ent.native_d_name,ent.native_d_namlen}}; +} + +inline constexpr ::fast_io::manipulators::basic_os_c_str_with_known_size u8filename(nt_directory_entry pioe) noexcept +{ + auto& ent{*pioe.entry}; + return {ent.u8d_name,ent.u8d_namlen}; +} + +inline constexpr std::uint_least64_t inode_ul64(nt_directory_entry) noexcept +{ + return 0; +} + +inline constexpr file_type type(nt_directory_entry pioe) noexcept +{ + return pioe.entry->d_type; +} + +template +struct nt_family_directory_iterator +{ + nt_dirent* entry{}; +}; + +template +inline nt_directory_entry operator*(nt_family_directory_iterator pdit) noexcept +{ + return {pdit.entry}; +} + +template +inline nt_family_directory_iterator& operator++(nt_family_directory_iterator& pdit) +{ + pdit.entry=win32::nt::details::nt_dirent_next(pdit.entry); + return pdit; +} + +template +inline constexpr bool operator==(::std::default_sentinel_t, nt_family_directory_iterator b) noexcept +{ + return b.entry==nullptr; +} + +template +inline constexpr bool operator==(nt_family_directory_iterator b, ::std::default_sentinel_t other) noexcept +{ + return other==b; +} + +template +inline constexpr bool operator!=(::std::default_sentinel_t other,nt_family_directory_iterator b) noexcept +{ + return !(other==b); +} + +template +inline constexpr bool operator!=(nt_family_directory_iterator b, ::std::default_sentinel_t other) noexcept +{ + return !(other==b); +} + +template +struct basic_nt_family_directory_generator +{ + using allocator_type = Allocator; + nt_dirent* entry{}; + constexpr basic_nt_family_directory_generator() noexcept=default; + explicit constexpr basic_nt_family_directory_generator(void* directory_handle) noexcept:entry(::fast_io::win32::nt::details::new_nt_dirent()) + { + entry->d_handle=directory_handle; + } + + basic_nt_family_directory_generator(basic_nt_family_directory_generator const&)=delete; + basic_nt_family_directory_generator& operator=(basic_nt_family_directory_generator const&)=delete; + constexpr basic_nt_family_directory_generator(basic_nt_family_directory_generator&& __restrict other) noexcept:entry(other.entry) + { + other.entry=nullptr; + } + constexpr basic_nt_family_directory_generator& operator=(basic_nt_family_directory_generator&& __restrict other) noexcept + { + ::fast_io::win32::nt::details::delete_nt_dirent(entry); + entry=other.entry; + other.entry=nullptr; + return *this; + } + constexpr ~basic_nt_family_directory_generator() + { + ::fast_io::win32::nt::details::delete_nt_dirent(entry); + } +}; + +template +using nt_family_directory_generator = basic_nt_family_directory_generator; + +template +inline nt_family_directory_iterator begin(basic_nt_family_directory_generator const& pdg) +{ + return {win32::nt::details::set_nt_dirent_first(pdg.entry)}; +} + +template +inline ::std::default_sentinel_t end(basic_nt_family_directory_generator const&) noexcept +{ + return {}; +} + +using nt_directory_generator = nt_family_directory_generator; +using zw_directory_generator = nt_family_directory_generator; + +inline nt_directory_generator current(nt_at_entry nate) +{ + return nt_directory_generator(nate.handle); +} + +inline zw_directory_generator current(zw_at_entry nate) +{ + return zw_directory_generator(nate.handle); +} + +template +struct basic_nt_family_recursive_directory_iterator +{ + using stack_type = StackType; + void* root_handle{}; + nt_dirent* entry{}; + stack_type stack; + constexpr basic_nt_family_recursive_directory_iterator()=default; + basic_nt_family_recursive_directory_iterator(void* root_han,nt_dirent* ent):root_handle(root_han),entry(ent){} + basic_nt_family_recursive_directory_iterator(basic_nt_family_recursive_directory_iterator const&)=delete; + basic_nt_family_recursive_directory_iterator& operator=(basic_nt_family_recursive_directory_iterator const&)=delete; + basic_nt_family_recursive_directory_iterator(basic_nt_family_recursive_directory_iterator&& __restrict) noexcept=default; + basic_nt_family_recursive_directory_iterator& operator=(basic_nt_family_recursive_directory_iterator&& __restrict) noexcept=default; +}; + +template +struct basic_nt_family_recursive_directory_generator +{ + using allocator_type = Allocator; + using stack_type = StackType; + void* root_handle{}; + nt_dirent* entry{}; + constexpr basic_nt_family_recursive_directory_generator()=default; + explicit constexpr basic_nt_family_recursive_directory_generator(void* rhd):root_handle(rhd),entry(::fast_io::win32::nt::details::new_nt_dirent()){} + basic_nt_family_recursive_directory_generator(basic_nt_family_recursive_directory_generator const&)=delete; + basic_nt_family_recursive_directory_generator& operator=(basic_nt_family_recursive_directory_generator const&)=delete; + constexpr basic_nt_family_recursive_directory_generator(basic_nt_family_recursive_directory_generator&& __restrict other) noexcept:root_handle(other.root_handle),entry(other.entry) + { + other.root_handle=nullptr; + entry=nullptr; + } + constexpr basic_nt_family_recursive_directory_generator& operator=(basic_nt_family_recursive_directory_generator&& __restrict other) noexcept + { + ::fast_io::win32::nt::details::delete_nt_dirent(this->entry); + root_handle=other.root_handle; + entry=other.entry; + return *this; + } + constexpr ~basic_nt_family_recursive_directory_generator() + { + ::fast_io::win32::nt::details::delete_nt_dirent(this->entry); + } +}; + +template +inline std::size_t depth(basic_nt_family_recursive_directory_iterator const& prdit) noexcept +{ + return prdit.stack.size(); +} + +template +inline basic_nt_family_recursive_directory_iterator& operator++(basic_nt_family_recursive_directory_iterator& prdit) +{ + for(;;) + { + if(prdit.stack.empty()) + { + prdit.entry->d_handle=prdit.root_handle; + prdit.entry=win32::nt::details::nt_dirent_next(prdit.entry); + if(prdit.entry==nullptr) + return prdit; + } + else + { + prdit.entry->d_handle=prdit.stack.back().handle; + auto entry=win32::nt::details::nt_dirent_next(prdit.entry); + if(entry==nullptr) + { + prdit.stack.pop_back(); + continue; + } + prdit.entry=entry; + } + if(prdit.entry->d_type==file_type::directory) + { + std::size_t const native_d_namlen{prdit.entry->native_d_namlen}; + char16_t const *native_d_name_ptr{prdit.entry->native_d_name}; + if((native_d_namlen==1&&*native_d_name_ptr==u'.')||(native_d_namlen==2&&*native_d_name_ptr==u'.'&&native_d_name_ptr[1]==u'.')) + continue; + prdit.stack.emplace_back(nt_at_entry{prdit.stack.empty()?prdit.root_handle:prdit.stack.back().handle}, + ::fast_io::manipulators::basic_os_c_str_with_known_size{native_d_name_ptr,native_d_namlen}, + open_mode::directory); + } + return prdit; + } + return prdit; +} + +template +inline void pop(basic_nt_family_recursive_directory_iterator& prdit) +{ + if(prdit.stack.empty()) + prdit.entry=nullptr; + else + { + prdit.stack.pop_back(); + ++prdit; + } +} + +template +inline basic_nt_family_recursive_directory_iterator begin(basic_nt_family_recursive_directory_generator const& prg) noexcept +{ + basic_nt_family_recursive_directory_iterator prdit{prg.root_handle,prg.entry}; + prdit.entry->d_handle=prg.root_handle; + prdit.entry=win32::nt::details::set_nt_dirent_first(prdit.entry); + if(prdit.entry&&prdit.entry->d_type==file_type::directory) + { + auto& ent{*prdit.entry}; + char16_t const *native_d_name_ptr{ent.native_d_name}; + std::size_t const native_d_namlen{ent.native_d_namlen}; + if((native_d_namlen==1&&*native_d_name_ptr==u'.')||(native_d_namlen==2&&*native_d_name_ptr==u'.'&&native_d_name_ptr[1]==u'.')) + { + ++prdit; + } + else + { + prdit.stack.emplace_back(nt_at_entry{prdit.root_handle}, + ::fast_io::manipulators::basic_os_c_str_with_known_size{native_d_name_ptr,native_d_namlen}, + open_mode::directory); + } + } + return prdit; +} + +template +inline ::std::default_sentinel_t end(basic_nt_family_recursive_directory_generator const&) noexcept +{ + return {}; +} + +template +inline nt_directory_entry operator*(basic_nt_family_recursive_directory_iterator const& prdit) noexcept +{ + return {prdit.entry}; +} + +template +inline bool operator==(::std::default_sentinel_t, basic_nt_family_recursive_directory_iterator const& b) noexcept +{ + return b.stack.empty()&&b.entry == nullptr; +} + +template +inline bool operator==(basic_nt_family_recursive_directory_iterator const& b, ::std::default_sentinel_t sntnl) noexcept +{ + return sntnl==b; +} + +template +inline bool operator!=(::std::default_sentinel_t sntnl, basic_nt_family_recursive_directory_iterator const& b) noexcept +{ + return !(sntnl==b); +} + +template +inline bool operator!=(basic_nt_family_recursive_directory_iterator const& b, ::std::default_sentinel_t sntnl) noexcept +{ + return sntnl!=b; +} + +template +using nt_family_recursive_directory_generator = basic_nt_family_recursive_directory_generator,typename nt_directory_generator::allocator_type>>; + +using nt_recursive_directory_generator = nt_family_recursive_directory_generator; +using zw_recursive_directory_generator = nt_family_recursive_directory_generator; + +inline nt_recursive_directory_generator recursive(nt_at_entry nate) +{ + return nt_recursive_directory_generator{nate.handle}; +} + +inline zw_recursive_directory_generator recursive(zw_at_entry zate) +{ + return zw_recursive_directory_generator{zate.handle}; +} + +inline auto native_extension(nt_directory_entry ent) noexcept +{ + auto& et{*ent.entry}; + return ::fast_io::details::find_dot_and_sep(et.native_d_name,et.native_d_namlen); +} + +inline auto native_stem(nt_directory_entry ent) noexcept +{ + auto& et{*ent.entry}; + return ::fast_io::details::find_dot_and_sep(et.native_d_name,et.native_d_namlen); +} + +inline auto u8extension(nt_directory_entry ent) noexcept +{ + auto& et{*ent.entry}; + return ::fast_io::details::find_dot_and_sep(et.u8d_name,et.u8d_namlen); +} + +inline auto u8stem(nt_directory_entry ent) noexcept +{ + auto& et{*ent.entry}; + return ::fast_io::details::find_dot_and_sep(et.u8d_name,et.u8d_namlen); +} + +template +inline constexpr auto status_io_print_forward(io_alias_type_t,nt_directory_entry ent) noexcept +{ + auto& et{*ent.entry}; + if constexpr(sizeof(char_type)==1||(std::same_as&& + ::fast_io::execution_charset_encoding_scheme()==::fast_io::encoding_scheme::utf)) + { + return status_io_print_forward(io_alias_type, + ::fast_io::cross_code_cvt_t{{et.u8d_name,et.u8d_namlen}}); + } + else + { + return status_io_print_forward(io_alias_type, + ::fast_io::cross_code_cvt_t{{et.native_d_name,et.native_d_namlen}}); + } +} + + +#ifndef __CYGWIN__ +using native_directory_entry = nt_directory_entry; +#endif + +} diff --git a/src/fast_io/include/fast_io_hosted/filesystem/nt_at.h b/src/fast_io/include/fast_io_hosted/filesystem/nt_at.h new file mode 100644 index 0000000..13e5e4a --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/filesystem/nt_at.h @@ -0,0 +1,304 @@ +#pragma once + +namespace fast_io +{ + +enum class nt_at_flags:std::uint_least32_t +{ +eaccess=static_cast(1), +symlink_nofollow=static_cast(1)<<1, +no_automount=static_cast(1)<<2, +removedir=static_cast(1)<<3, +empty_path=static_cast(1)<<4 +}; + + +constexpr nt_at_flags operator&(nt_at_flags x, nt_at_flags y) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(static_cast(x) & static_cast(y)); +} + +constexpr nt_at_flags operator|(nt_at_flags x, nt_at_flags y) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(static_cast(x) | static_cast(y)); +} + +constexpr nt_at_flags operator^(nt_at_flags x, nt_at_flags y) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(static_cast(x) ^ static_cast(y)); +} + +constexpr nt_at_flags operator~(nt_at_flags x) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(~static_cast(x)); +} + +inline constexpr nt_at_flags& operator&=(nt_at_flags& x, nt_at_flags y) noexcept{return x=x&y;} + +inline constexpr nt_at_flags& operator|=(nt_at_flags& x, nt_at_flags y) noexcept{return x=x|y;} + +inline constexpr nt_at_flags& operator^=(nt_at_flags& x, nt_at_flags y) noexcept{return x=x^y;} + +namespace win32::nt::details +{ + +inline constexpr nt_open_mode calculate_nt_delete_flag(nt_at_flags flags) noexcept +{ + nt_open_mode mode{ + .DesiredAccess=0x00010000, //FILE_GENERIC_READ + .FileAttributes=0x80, //FILE_READ_ATTRIBUTES + .ShareAccess=0x00000007, //FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE + .CreateDisposition=0x00000001, /*OPEN_EXISTING => FILE_OPEN*/ + .CreateOptions=0x00001000 /*FILE_DELETE_ON_CLOSE*/ + }; + if((flags&nt_at_flags::symlink_nofollow)!=nt_at_flags::symlink_nofollow) + { + mode.CreateOptions |= 0x00200000;//FILE_FLAG_OPEN_REPARSE_POINT => FILE_OPEN_REPARSE_POINT (0x00200000) + } + if((flags&nt_at_flags::removedir)==nt_at_flags::removedir) + { + mode.CreateOptions |= 0x00004000; //FILE_OPEN_FOR_BACKUP_INTENT + mode.CreateOptions |= 0x00000001; //FILE_DIRECTORY_FILE + } + else + { + mode.CreateOptions |= 0x00000040; //FILE_NON_DIRECTORY_FILE 0x00000040 + } + return mode; +} + +template +inline void nt_unlinkat_impl(void* dirhd,char16_t const* path_c_str,std::size_t path_size,nt_at_flags flags) +{ + auto status{nt_close(nt_call_callback(dirhd,path_c_str,path_size,nt_create_callback{calculate_nt_delete_flag(flags)}))}; + if(status) + throw_nt_error(status); +} + +template +inline void nt_mkdirat_impl(void* dirhd,char16_t const* path_c_str,std::size_t path_size,perms pm) +{ + constexpr fast_io::win32::nt::details::nt_open_mode create_dir_mode{fast_io::win32::nt::details::calculate_nt_open_mode({fast_io::open_mode::creat|fast_io::open_mode::directory})}; + auto m_dir_mode{create_dir_mode}; + if((pm&perms::owner_write)==perms::none) + m_dir_mode.FileAttributes|=0x00000001; //FILE_ATTRIBUTE_READONLY + auto status{nt_close(nt_call_callback(dirhd,path_c_str,path_size,nt_create_callback{m_dir_mode}))}; + if(status) + throw_nt_error(status); +} +inline constexpr nt_open_mode calculate_nt_link_flag(nt_at_flags flags) noexcept +{ + nt_open_mode mode{ + .DesiredAccess=0x00100000|0x0100, //SYNCHRONIZE | FILE_WRITE_ATTRIBUTES + .FileAttributes=0x80, //FILE_READ_ATTRIBUTES + .ShareAccess=0x00000007, //FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE + .CreateDisposition=0x00200000 | 0x00000020, /*OPEN_EXISTING => FILE_OPEN*/ + }; + if((flags&nt_at_flags::symlink_nofollow)!=nt_at_flags::symlink_nofollow) + { + mode.CreateOptions |= 0x00200000;//FILE_FLAG_OPEN_REPARSE_POINT => FILE_OPEN_REPARSE_POINT (0x00200000) + } + return mode; +} +#if 0 +template +inline void nt_linkat_no_newpath_size_impl(void* olddirhd,char16_t const* oldpath_c_str,std::size_t oldpath_size, + void* newdirhd,char16_t const* to_path_c_str,nt_at_flags flags) +{ + +} +#endif + +struct file_link_information +{ + std::uint_least32_t ReplaceIfExists; + void* RootDirectory; + std::uint_least32_t FileNameLength; +}; + +template +inline void nt_linkat_impl( + void* olddirhd,char16_t const* oldpath_c_str,std::size_t oldpath_size, + void* newdirhd,char16_t const* newpath_c_str,std::size_t newpath_size, + nt_at_flags flags) +{ + nt_open_mode const md{calculate_nt_link_flag(flags)}; + basic_nt_family_file<(zw?(nt_family::zw):(nt_family::nt)),char> file(nt_call_callback(olddirhd,oldpath_c_str,oldpath_size,nt_create_callback{md})); + nt_call_callback( + newdirhd,newpath_c_str,newpath_size, + [&](void* directory_hd,win32::nt::unicode_string const* ustr) + { + char16_t const* pth_cstr{ustr->Buffer}; + std::uint_least32_t pth_size2{ustr->Length}; + ::fast_io::details::local_operator_new_array_ptr buffer(sizeof(file_link_information)+pth_size2); + file_link_information info{.ReplaceIfExists=false, + .RootDirectory=directory_hd, + .FileNameLength=static_cast(pth_size2)}; + + ::fast_io::details::my_memcpy(buffer.ptr,__builtin_addressof(info),sizeof(file_link_information)); + ::fast_io::details::my_memcpy(buffer.ptr+sizeof(file_link_information),pth_cstr,pth_size2); + + io_status_block block; + using file_link_information_may_alias_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = file_link_information*; + std::uint_least32_t status{nt_set_information_file( + file.handle, + __builtin_addressof(block), + reinterpret_cast(buffer.ptr), + static_cast(sizeof(info)), + file_information_class::FileLinkInformation)}; + if(status) + throw_nt_error(status); + }); +} + +template +inline auto nt22_api_dispatcher(void* olddirhd,char16_t const* oldpath_c_str,std::size_t oldpath_size, + void* newdirhd,char16_t const* newpath_c_str,std::size_t newpath_size,Args... args) +{ +#if 0 + if constexpr(dsp==::fast_io::details::posix_api_22::renameat) + { + static_assert(sizeof...(Args)==0); + nt_renameat_impl(olddirfd,oldpath,newdirfd,newpath); + } + else +#endif + if constexpr(dsp==::fast_io::details::posix_api_22::linkat) + { + nt_linkat_impl(olddirhd,oldpath_c_str,oldpath_size,newdirhd,newpath_c_str,newpath_size,args...); + } +} + +template +inline auto nt1x_api_dispatcher(void* dir_handle,char16_t const* path_c_str,std::size_t path_size,Args... args) +{ +#if 0 + if constexpr(dsp==::fast_io::details::posix_api_1x::faccessat) + nt_faccessat_impl(dir_handle,path_c_str,path_size,args...); + else if constexpr(dsp==::fast_io::details::posix_api_1x::fchmodat) + nt_fchmodat_impl(dir_handle,path_c_str,path_size,args...); + else if constexpr(dsp==::fast_io::details::posix_api_1x::fstatat) + nt_fstatat_impl(dir_handle,path_c_str,path_size,args...); + else +#endif + if constexpr(dsp==::fast_io::details::posix_api_1x::mkdirat) + nt_mkdirat_impl(dir_handle,path_c_str,path_size,args...); + else if constexpr(dsp==::fast_io::details::posix_api_1x::unlinkat) + nt_unlinkat_impl(dir_handle,path_c_str,path_size,args...); +#if 0 + else if constexpr(dsp==::fast_io::details::posix_api_1x::unlinkat::utimensat) + nt_utimensat_impl(dir_handle,path_c_str,path_size,args...); +#endif +} + +template +inline auto nt_deal_with1x( + void* dir_handle, + path_type const& path, + Args... args) +{ + return nt_api_common(path,[&](char16_t const* path_c_str,std::size_t path_size) + { + return nt1x_api_dispatcher(dir_handle,path_c_str,path_size,args...); + }); +} + +template +inline auto nt_deal_with22(void* olddirhd,oldpath_type const& oldpath, + void* newdirhd,newpath_type const& newpath,nt_at_flags ) +{ + return nt_api_common(oldpath,[&](char16_t const* oldpath_c_str,std::size_t oldpath_size) + { + return nt_api_common(newpath,[&](char16_t const* newpath_c_str,std::size_t newpath_size) + { + return nt22_api_dispatcher(olddirhd, + oldpath_c_str,oldpath_size, + newdirhd, + newpath_c_str,newpath_size); + }); + }); +} + + +} + + +template +requires (family==nt_family::nt||family==nt_family::zw) +inline void nt_family_mkdirat(nt_at_entry ent,path_type const& path,perms pm=static_cast(436)) +{ + ::fast_io::win32::nt::details::nt_deal_with1x(ent.handle,path,pm); +} + +template<::fast_io::constructible_to_os_c_str path_type> +inline void nt_mkdirat(nt_at_entry ent,path_type const& path,perms pm=static_cast(436)) +{ + ::fast_io::win32::nt::details::nt_deal_with1x(ent.handle,path,pm); +} + +template<::fast_io::constructible_to_os_c_str path_type> +inline void zw_mkdirat(nt_at_entry ent,path_type const& path,perms pm=static_cast(436)) +{ + ::fast_io::win32::nt::details::nt_deal_with1x(ent.handle,path,pm); +} + +template +requires (family==nt_family::nt||family==nt_family::zw) +inline void nt_family_unlinkat(nt_at_entry ent,path_type const& path,nt_at_flags flags={}) +{ + ::fast_io::win32::nt::details::nt_deal_with1x(ent.handle,path,flags); +} + +template<::fast_io::constructible_to_os_c_str path_type> +inline void nt_unlinkat(nt_at_entry ent,path_type const& path,nt_at_flags flags={}) +{ + ::fast_io::win32::nt::details::nt_deal_with1x(ent.handle,path,flags); +} + +template<::fast_io::constructible_to_os_c_str path_type> +inline void zw_unlinkat(nt_at_entry ent,path_type const& path,nt_at_flags flags={}) +{ + ::fast_io::win32::nt::details::nt_deal_with1x(ent.handle,path,flags); +} + + +#if !defined(__CYGWIN__) && !defined(__WINE__) +using native_at_flags = nt_at_flags; + +template<::fast_io::constructible_to_os_c_str path_type> +inline void native_mkdirat(nt_at_entry ent,path_type const& path, perms pm=static_cast(436)) +{ + ::fast_io::win32::nt::details::nt_deal_with1x(ent.handle,path,pm); +} + +template<::fast_io::constructible_to_os_c_str path_type> +inline void native_unlinkat(nt_at_entry ent,path_type const& path,native_at_flags flags={}) +{ + ::fast_io::win32::nt::details::nt_deal_with1x(ent.handle,path,flags); +} + +template<::fast_io::constructible_to_os_c_str path_type> +inline void native_fchownat(nt_at_entry,path_type&&,std::uintptr_t,std::uintptr_t,[[maybe_unused]] nt_at_flags flags=nt_at_flags::symlink_nofollow) +{ +//windows does not use POSIX user group system. stub it and it is perfectly fine. But nt_fchownat,zw_fchownat will not be provided since they do not exist. +} +#if 0 +template<::fast_io::constructible_to_os_c_str old_path_type,::fast_io::constructible_to_os_c_str new_path_type> +inline void native_linkat(native_at_entry oldent,old_path_type&& oldpath,native_at_entry newent,new_path_type&& newpath,nt_at_flags flags=nt_at_flags::symlink_nofollow) +{ + auto oldvw{details::to_its_cstring_view(oldpath)}; + auto newvw{details::to_its_cstring_view(newpath)}; + ::fast_io::win32::nt::details::nt_deal_with22(oldent.handle,oldvw.c_str(),oldvw.size(), + newent.handle,newvw.c_str(),newvw.size(),flags); +} +#endif +#endif +} diff --git a/src/fast_io/include/fast_io_hosted/filesystem/posix.h b/src/fast_io/include/fast_io_hosted/filesystem/posix.h new file mode 100644 index 0000000..5b8b13a --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/filesystem/posix.h @@ -0,0 +1,513 @@ +#pragma once +#include + +namespace fast_io +{ + +namespace details +{ +inline int dirp_to_fd(DIR* dirp) noexcept +{ + if(dirp==nullptr) + return -1; +#if defined(__CYGWIN__) + return dirp->__d_fd; +#else + return dirfd(dirp); +#endif +} + +} + +class posix_directory_io_observer +{ +public: + using native_handle_type = DIR*; + native_handle_type dirp{}; + constexpr native_handle_type native_handle() const noexcept + { + return dirp; + } + explicit constexpr operator bool() const noexcept + { + return dirp; + } + template + operator basic_posix_io_observer() const noexcept + { + return {details::dirp_to_fd(dirp)}; + } + constexpr native_handle_type release() noexcept + { + native_handle_type temp{dirp}; + dirp=nullptr; + return temp; + } +}; + +namespace details +{ + +inline DIR* sys_dup_dir(DIR* dirp) +{ + if(dirp==nullptr) + throw_posix_error(EBADF); + auto fd{ +#if defined(__CYGWIN__) + dirp->__d_fd +#else + dirfd(dirp) +#endif + }; + if(fd==-1) + throw_posix_error(); + auto newfd{details::sys_dup(fd)}; + auto newdir{::fdopendir(newfd)}; + if(newdir==nullptr) + { + details::sys_close(newfd); + throw_posix_error(); + } + return newdir; +} + +} + +class posix_directory_file:public posix_directory_io_observer +{ +public: + using native_handle_type = DIR*; + constexpr posix_directory_file() noexcept=default; + + explicit constexpr posix_directory_file(posix_directory_io_observer) noexcept=delete; + constexpr posix_directory_file& operator=(posix_directory_io_observer) noexcept=delete; + template + requires std::same_as> + constexpr posix_directory_file(native_hd dirp1):posix_directory_io_observer{dirp1}{} + posix_directory_file(posix_file&& pioh):posix_directory_io_observer{noexcept_call(::fdopendir,pioh.fd)} + { + if(this->dirp==nullptr) + throw_posix_error(); + pioh.release(); + } + posix_directory_file& operator=(posix_directory_file const& other) + { + auto newdir{details::sys_dup_dir(other.dirp)}; + if(this->dirp)[[likely]] + noexcept_call(::closedir,this->dirp); + this->dirp=newdir; + return *this; + } + constexpr posix_directory_file(posix_directory_file&& __restrict other) noexcept: + posix_directory_io_observer{other.release()}{} + + posix_directory_file& operator=(posix_directory_file&& __restrict other) noexcept + { + if(this->dirp)[[likely]] + noexcept_call(::closedir,this->dirp); + this->dirp=other.release(); + return *this; + } + inline void reset(native_handle_type dirp1=nullptr) noexcept + { + if(this->dirp)[[likely]] + noexcept_call(::closedir,this->dirp); + this->dirp=dirp1; + } + void close() + { + if(*this)[[likely]] + { + int ret{noexcept_call(::closedir,this->dirp)}; + this->dirp=nullptr; + if(ret==-1) + throw_posix_error(); + } + } + ~posix_directory_file() + { + if(this->dirp)[[likely]] + noexcept_call(::closedir,this->dirp); + } +}; + +namespace freestanding +{ + +template<> +struct is_trivially_relocatable +{ + inline static constexpr bool value = true; +}; + +template<> +struct is_zero_default_constructible +{ + inline static constexpr bool value = true; +}; + +} + +struct posix_directory_entry +{ + using native_char_type = char; + using char_type = char8_t; + DIR* dirp{}; + struct dirent* entry{}; + std::size_t d_namlen{}; + template + explicit operator basic_posix_io_observer() const noexcept + { + return {details::dirp_to_fd(dirp)}; + } +}; + +inline posix_fs_dirent drt(posix_directory_entry ndet) noexcept +{ + return posix_fs_dirent{details::dirp_to_fd(ndet.dirp),ndet.entry->d_name}; +} + +inline posix_at_entry at(posix_directory_entry ndet) noexcept +{ + return posix_at_entry{details::dirp_to_fd(ndet.dirp)}; +} + +inline constexpr ::fast_io::manipulators::basic_os_c_str_with_known_size native_filename(posix_directory_entry pioe) noexcept +{ + return {pioe.entry->d_name,pioe.d_namlen}; +} + +inline ::fast_io::manipulators::basic_os_c_str_with_known_size u8filename(posix_directory_entry pioe) noexcept +{ + using char8_may_alias_const_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + =char8_t const*; + return {reinterpret_cast(pioe.entry->d_name),pioe.d_namlen}; +} + +inline constexpr std::uint_least64_t inode_ul64(posix_directory_entry pioe) noexcept +{ + return pioe.entry->d_ino; +} + +inline constexpr file_type type(posix_directory_entry pioe) noexcept +{ +#ifdef __CYGWIN__ + switch(pioe.entry->d_type) + { + case 6: + return file_type::block; + case 2: + return file_type::character; + case 4: + return file_type::directory; + case 1: + return file_type::fifo; + case 10: + return file_type::symlink; + case 8: + return file_type::regular; + case 12: + return file_type::socket; + case 0: + return file_type::unknown; + default: + return file_type::not_found; + }; +#else + switch(pioe.entry->d_type) + { + case DT_BLK: + return file_type::block; + case DT_CHR: + return file_type::character; + case DT_DIR: + return file_type::directory; + case DT_FIFO: + return file_type::fifo; + case DT_LNK: + return file_type::symlink; + case DT_REG: + return file_type::regular; +#if defined(DT_SOCK) + case DT_SOCK: + return file_type::socket; +#endif + case DT_UNKNOWN: + return file_type::unknown; + default: + return file_type::not_found; + }; +#endif +} + +struct posix_directory_iterator +{ + DIR* dirp{}; + struct dirent* entry{}; + std::size_t d_namlen{}; +}; + +struct posix_directory_generator +{ + posix_directory_file dir_fl; +}; + +inline posix_directory_entry operator*(posix_directory_iterator pdit) noexcept +{ + return {pdit.dirp,pdit.entry,pdit.d_namlen}; +} + +inline posix_directory_iterator& operator++(posix_directory_iterator& pdit) +{ +/* +To fix: avoid setting errno +*/ + errno=0; + auto entry{readdir(pdit.dirp)}; + auto en{errno}; + if(entry==nullptr&&en) + throw_posix_error(en); + pdit.entry=entry; + if(entry==nullptr) + pdit.d_namlen=0; + else + { +#if defined(_DIRENT_HAVE_D_NAMLEN) + pdit.d_namlen=entry->d_namlen; +#else + pdit.d_namlen=cstr_len(entry->d_name); +#endif + } + return pdit; +} + +inline posix_directory_iterator begin(posix_directory_generator const& pdg) +{ + auto dirp{pdg.dir_fl.dirp}; + ::rewinddir(dirp); + posix_directory_iterator pdit{dirp}; + ++pdit; + return pdit; +} + +inline ::std::default_sentinel_t end(posix_directory_generator const&) noexcept +{ + return {}; +} + +inline constexpr bool operator==(::std::default_sentinel_t, posix_directory_iterator const& b) noexcept +{ + return b.entry == nullptr; +} +inline constexpr bool operator==(posix_directory_iterator const& b, ::std::default_sentinel_t) noexcept +{ + return b.entry == nullptr; +} +inline constexpr bool operator!=(::std::default_sentinel_t, posix_directory_iterator const& b) noexcept +{ + return b.entry; +} +inline constexpr bool operator!=(posix_directory_iterator const& b, ::std::default_sentinel_t) noexcept +{ + return b.entry; +} + +inline posix_directory_generator current(posix_at_entry pate) +{ + return {.dir_fl=posix_directory_file(posix_file(details::sys_dup(pate.fd)))}; +} + +template +struct basic_posix_recursive_directory_iterator +{ + using stack_type = StackType; + DIR* dirp{}; + struct dirent* entry{}; + std::size_t d_namlen{}; + stack_type stack; + constexpr basic_posix_recursive_directory_iterator()=default; + explicit constexpr basic_posix_recursive_directory_iterator(DIR* dp):dirp(dp){} + basic_posix_recursive_directory_iterator(basic_posix_recursive_directory_iterator const&)=delete; + basic_posix_recursive_directory_iterator& operator=(basic_posix_recursive_directory_iterator const&)=delete; + basic_posix_recursive_directory_iterator(basic_posix_recursive_directory_iterator&&) noexcept=default; + basic_posix_recursive_directory_iterator& operator=(basic_posix_recursive_directory_iterator&&) noexcept=default; +}; + +template +struct basic_posix_recursive_directory_generator +{ + using stack_type = StackType; + posix_directory_file dir_fl; +}; + +using posix_recursive_directory_generator = basic_posix_recursive_directory_generator<::fast_io::containers::vector>; + +template +inline std::size_t depth(basic_posix_recursive_directory_iterator const& prdit) noexcept +{ + return prdit.stack.size(); +} + +template +inline basic_posix_recursive_directory_iterator& operator++(basic_posix_recursive_directory_iterator& prdit) +{ + for(;;) + { + errno=0; + if(prdit.stack.empty()) + { + auto entry{readdir(prdit.dirp)}; + if(entry==nullptr) + { + auto en{errno}; + if(en) + throw_posix_error(en); + prdit.entry=nullptr; + return prdit; + } + prdit.entry=entry; + } + else + { + auto entry=readdir(prdit.stack.back().dirp); + if(entry==nullptr) + { + auto en{errno}; + if(en) + throw_posix_error(en); + prdit.stack.pop_back(); + continue; + } + prdit.entry=entry; + } + if(prdit.entry->d_type== +#if defined(__CYGWIN__) + 4 +#else + DT_DIR +#endif + ) + { + auto name{prdit.entry->d_name}; + if((*name==u8'.'&&name[1]==0)||(*name==u8'.'&&name[1]==u8'.'&&name[2]==0)) + continue; + prdit.stack.emplace_back(::fast_io::posix_file(::fast_io::posix_fs_dirent{details::dirp_to_fd(prdit.stack.empty()?prdit.dirp:prdit.stack.back().dirp),name},::fast_io::open_mode::directory)); + } + if(prdit.entry)[[likely]] + { +#if defined(_DIRENT_HAVE_D_NAMLEN) + prdit.d_namlen=prdit.entry->d_namlen; +#else + prdit.d_namlen=cstr_len(prdit.entry->d_name); +#endif + } + else + { + prdit.d_namlen=0; + } + return prdit; + } +} + +template +inline void pop(basic_posix_recursive_directory_iterator& prdit) noexcept +{ + if(prdit.stack.empty()) + { + prdit.entry=nullptr; + prdit.d_namlen=0; + } + else + { + prdit.stack.pop_back(); + ++prdit; + } +} + +template +inline basic_posix_recursive_directory_iterator begin(basic_posix_recursive_directory_generator const& pdg) +{ + auto dirp{pdg.dir_fl.dirp}; + ::rewinddir(dirp); + basic_posix_recursive_directory_iterator pdit{dirp}; + ++pdit; + return pdit; +} + +template +inline ::std::default_sentinel_t end(basic_posix_recursive_directory_generator const&) noexcept +{ + return {}; +} + +template +inline posix_directory_entry operator*(basic_posix_recursive_directory_iterator const& prdit) noexcept +{ + return {prdit.stack.empty()?prdit.dirp:prdit.stack.back().dirp,prdit.entry,prdit.d_namlen}; +} + +template +inline bool operator==(::std::default_sentinel_t, basic_posix_recursive_directory_iterator const& b) noexcept +{ + return b.stack.empty()&&b.entry == nullptr; +} + +template +inline bool operator==(basic_posix_recursive_directory_iterator const& b, ::std::default_sentinel_t sntnl) noexcept +{ + return sntnl==b; +} + +template +inline bool operator!=(::std::default_sentinel_t sntnl, basic_posix_recursive_directory_iterator const& b) noexcept +{ + return !(sntnl==b); +} + +template +inline bool operator!=(basic_posix_recursive_directory_iterator const& b, ::std::default_sentinel_t sntnl) noexcept +{ + return sntnl!=b; +} + +inline posix_recursive_directory_generator recursive(posix_at_entry pate) +{ + return {.dir_fl=posix_directory_file(posix_file(details::sys_dup(pate.fd)))}; +} + +inline auto native_extension(posix_directory_entry ent) noexcept +{ + return ::fast_io::details::find_dot_and_sep(ent.entry->d_name,ent.d_namlen); +} + +inline auto native_stem(posix_directory_entry ent) noexcept +{ + return ::fast_io::details::find_dot_and_sep(ent.entry->d_name,ent.d_namlen); +} + +inline auto u8extension(posix_directory_entry ent) noexcept +{ + return ::fast_io::details::find_dot_and_sep(ent.entry->d_name,ent.d_namlen); +} + +inline auto u8stem(posix_directory_entry ent) noexcept +{ + return ::fast_io::details::find_dot_and_sep(ent.entry->d_name,ent.d_namlen); +} + +inline cross_code_cvt_t print_alias_define(io_alias_t,posix_directory_entry pth) noexcept +{ + using char8_const_may_alias_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif + = char8_t const*; + return {{reinterpret_cast(pth.entry->d_name),pth.d_namlen}}; +} + +using native_directory_entry = posix_directory_entry; + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_hosted/filesystem/posix_at.h b/src/fast_io/include/fast_io_hosted/filesystem/posix_at.h new file mode 100644 index 0000000..a6aa866 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/filesystem/posix_at.h @@ -0,0 +1,740 @@ +#pragma once + +namespace fast_io +{ + +namespace posix +{ +extern int libc_faccessat(int dirfd,char const* pathname,int mode, int flags) noexcept __asm__("faccessat"); +extern int libc_renameat(int olddirfd,char const* oldpath,int newdirfd, char const* newpath) noexcept __asm__("renameat"); +extern int libc_linkat(int olddirfd,char const* oldpath,int newdirfd, char const* newpath,int flags) noexcept __asm__("linkat"); +extern int libc_symlinkat(char const* oldpath, int newdirfd, char const* newpath) noexcept __asm__("symlinkat"); +extern int libc_fchmodat(int dirfd, char const* pathname, mode_t mode, int flags) noexcept __asm__("fchmodat"); +extern int libc_utimensat(int dirfd, char const* pathname,struct timespec const* times, int flags) noexcept __asm__("utimensat"); +extern int libc_fchownat(int dirfd, char const* pathname,uid_t owner, gid_t group, int flags) noexcept __asm__("fchownat"); +extern int libc_fstatat(int dirfd, char const* pathname, struct stat *buf,int flags) noexcept __asm__("fstatat"); +extern int libc_mkdirat(int dirfd, char const* pathname, mode_t mode) noexcept __asm__("mkdirat"); +extern int libc_mknodat(int dirfd, char const* pathname, mode_t mode, dev_t dev) noexcept __asm__("mknodat"); +extern int libc_unlinkat(int dirfd, char const*pathname, int flags) noexcept __asm__("unlinkat"); +extern int libc_readlinkat(int dirfd, char const* pathname,char *buf, std::size_t bufsiz) noexcept __asm__("readlinkat"); +} + +namespace details +{ + +inline void posix_renameat_impl(int olddirfd,char const* oldpath, + int newdirfd,char const* newpath) +{ + system_call_throw_error( +#if defined(__linux__) && defined(__NR_renameat) + system_call<__NR_renameat,int> +#else + ::fast_io::posix::libc_renameat +#endif + (olddirfd,oldpath,newdirfd,newpath)); +} + +inline void posix_linkat_impl(int olddirfd,char const* oldpath, + int newdirfd,char const* newpath,int flags) +{ + system_call_throw_error( +#if defined(__linux__) + system_call<__NR_linkat,int> +#else + ::fast_io::posix::libc_linkat +#endif + (olddirfd,oldpath,newdirfd,newpath,flags)); +} + +template +inline auto posix22_api_dispatcher(int olddirfd,char const* oldpath, + int newdirfd,char const* newpath,Args... args) +{ + if constexpr(dsp==posix_api_22::renameat) + { + static_assert(sizeof...(Args)==0); + posix_renameat_impl(olddirfd,oldpath,newdirfd,newpath); + } + else if constexpr(dsp==posix_api_22::linkat) + { + posix_linkat_impl(olddirfd,oldpath,newdirfd,newpath,args...); + } +} +template +inline auto posix12_api_dispatcher(char const* oldpath, + int newdirfd,char const* newpath) +{ + if constexpr(dsp==posix_api_12::symlinkat) + { + system_call_throw_error( +#if defined(__linux__) + system_call<__NR_symlinkat,int> +#else + ::fast_io::posix::libc_symlinkat +#endif + (oldpath,newdirfd,newpath)); + } +} + +inline void posix_faccessat_impl(int dirfd, char const* pathname, int mode, int flags) +{ + system_call_throw_error( +#if defined(__linux__) && defined(__NR_faccessat2) + system_call<__NR_faccessat2,int> +#elif defined(__linux__) && defined(__NR_faccessat) + system_call<__NR_faccessat,int> +#else + ::fast_io::posix::libc_faccessat +#endif + (dirfd,pathname,mode,flags)); +} + +#if defined(__wasi__) && !defined(__wasilibc_unmodified_upstream) +inline void posix_fchownat_impl(int, char const* , uintmax_t, uintmax_t, int) +{ + throw_posix_error(ENOTSUP); +} +#else +inline void posix_fchownat_impl(int dirfd, char const* pathname, uintmax_t owner, uintmax_t group, int flags) +{ + if constexpr(sizeof(uintmax_t)>sizeof(uid_t)) + { + constexpr std::uintmax_t mx{std::numeric_limits::max()}; + if(static_cast(owner)>mx) + throw_posix_error(EOVERFLOW); + } + if constexpr(sizeof(uintmax_t)>sizeof(gid_t)) + { + constexpr std::uintmax_t mx{std::numeric_limits::max()}; + if(static_cast(owner)>mx) + throw_posix_error(EOVERFLOW); + } + system_call_throw_error( +#if defined(__linux__) + system_call<__NR_fchownat,int> +#else + ::fast_io::posix::libc_fchownat +#endif + (dirfd,pathname,static_cast(owner),static_cast(group),flags)); +} +#endif + +#if defined(__wasi__) && !defined(__wasilibc_unmodified_upstream) +inline void posix_fchmodat_impl(int, char const* , mode_t, int) +{ + throw_posix_error(ENOTSUP); +} +#else +inline void posix_fchmodat_impl(int dirfd, char const* pathname, mode_t mode, int flags) +{ + system_call_throw_error( +#if defined(__linux__) + system_call<__NR_fchmodat,int> +#else + ::fast_io::posix::libc_fchmodat +#endif + (dirfd,pathname,mode,flags)); +} +#endif + +inline posix_file_status posix_fstatat_impl(int dirfd, char const* pathname, int flags) +{ +#if defined(__linux__) + +#if defined(__USE_LARGEFILE64) && (defined(__NR_newfstatat) || defined(__NR_fstatat64)) + struct stat64 buf; +#else + struct stat buf; +#endif +#if defined(__NR_newfstatat) || defined(__NR_fstatat64) || defined(__NR_fstatat) + system_call_throw_error( + system_call< +#if defined(__NR_newfstatat) + __NR_newfstatat +#elif defined(__NR_fstatat64) + __NR_fstatat64 +#else + __NR_fstatat +#endif + ,int>(dirfd,pathname,__builtin_addressof(buf),flags)); + +#else + if((::fast_io::posix::libc_fstatat(dirfd,pathname,__builtin_addressof(buf),flags)) < 0) + { + throw_posix_error(); + } +#endif + +#else + struct stat buf; + system_call_throw_error(::fast_io::posix::libc_fstatat(dirfd,pathname,__builtin_addressof(buf),flags)); +#endif + return struct_stat_to_posix_file_status(buf); +} + +inline void posix_mkdirat_impl(int dirfd, char const* pathname, mode_t mode) +{ + system_call_throw_error( +#if defined(__linux__) + system_call< + __NR_mkdirat + ,int> +#else + ::fast_io::posix::libc_mkdirat +#endif + (dirfd,pathname,mode)); +} +#if 0 +#if (defined(__wasi__) && !defined(__wasilibc_unmodified_upstream)) || defined(__DARWIN_C_LEVEL) +inline void posix_mknodat_impl(int, char const* , mode_t,std::uintmax_t) +{ + throw_posix_error(ENOTSUP); +} +#else + +inline void posix_mknodat_impl(int dirfd, char const* pathname, mode_t mode,std::uintmax_t dev) +{ + if constexpr(sizeof(std::uintmax_t)>sizeof(dev_t)) + { + constexpr std::uintmax_t mx{std::numeric_limits::max()}; + if(static_cast(dev)>mx) + throw_posix_error(EOVERFLOW); + } + system_call_throw_error( +#if defined(__linux__) + system_call< +#if __NR_mknodat + __NR_mknodat +#endif + ,int> +#else + ::fast_io::posix::libc_mknodat +#endif + (dirfd,pathname,mode,static_cast(dev))); +} + +#endif +#endif +inline void posix_unlinkat_impl(int dirfd,char const* path,int flags) +{ + system_call_throw_error( +#if defined(__linux__) + system_call<__NR_unlinkat,int> +#else + ::fast_io::posix::libc_unlinkat +#endif + (dirfd,path,flags)); +} + +namespace details +{ +inline constexpr struct timespec unix_timestamp_to_struct_timespec64(unix_timestamp stmp) noexcept +{ + constexpr std::uint_least64_t mul_factor{uint_least64_subseconds_per_second/1000000000u}; + return {static_cast(stmp.seconds),static_cast(static_cast((stmp.subseconds)/mul_factor))}; +} + +inline +#if defined(UTIME_NOW) && defined(UTIME_OMIT) +constexpr +#endif +struct timespec unix_timestamp_to_struct_timespec64(unix_timestamp_option opt [[maybe_unused]]) noexcept +{ +#if defined(UTIME_NOW) && defined(UTIME_OMIT) + switch(opt.flags) + { + case utime_flags::now: + return {.tv_sec=0,.tv_nsec=UTIME_NOW}; + case utime_flags::omit: + return {.tv_sec=0,.tv_nsec=UTIME_OMIT}; + default: + return unix_timestamp_to_struct_timespec64(opt.timestamp); + } +#else + throw_posix_error(EINVAL); +#endif +} + +} + +inline void posix_utimensat_impl(int dirfd,char const* path, +unix_timestamp_option creation_time, +unix_timestamp_option last_access_time, +unix_timestamp_option last_modification_time, +int flags) +{ + if(creation_time.flags!=utime_flags::omit) + throw_posix_error(EINVAL); + struct timespec ts[2]{ + details::unix_timestamp_to_struct_timespec64(last_access_time), + details::unix_timestamp_to_struct_timespec64(last_modification_time), + }; + struct timespec* tsptr{ts}; + system_call_throw_error( +#if defined(__linux__) +#if defined(__NR_utimensat64) + system_call<__NR_utimensat64,int> +#else + system_call<__NR_utimensat,int> +#endif + +#else + ::fast_io::posix::libc_utimensat +#endif + (dirfd,path,tsptr,flags)); +} + +template +inline auto posix1x_api_dispatcher(int dirfd,char const* path,Args... args) +{ + if constexpr(dsp==posix_api_1x::faccessat) + posix_faccessat_impl(dirfd,path,args...); + else if constexpr(dsp==posix_api_1x::fchownat) + posix_fchownat_impl(dirfd,path,args...); + else if constexpr(dsp==posix_api_1x::fchmodat) + posix_fchmodat_impl(dirfd,path,args...); + else if constexpr(dsp==posix_api_1x::fstatat) + posix_fstatat_impl(dirfd,path,args...); + else if constexpr(dsp==posix_api_1x::mkdirat) + posix_mkdirat_impl(dirfd,path,args...); +#if 0 + else if constexpr(dsp==posix_api_1x::mknodat) + posix_mknodat_impl(dirfd,path,args...); +#endif + else if constexpr(dsp==posix_api_1x::unlinkat) + posix_unlinkat_impl(dirfd,path,args...); + else if constexpr(dsp==posix_api_1x::utimensat) + posix_utimensat_impl(dirfd,path,args...); +} + +template +inline auto posix_deal_with22(int olddirfd,old_path_type const& oldpath, + int newdirfd,new_path_type const& newpath) +{ + return fast_io::posix_api_common(oldpath,[&](char const* oldpath_c_str) + { + return fast_io::posix_api_common(newpath,[&](char const* newpath_c_str) + { + return posix22_api_dispatcher(olddirfd,oldpath_c_str,newdirfd,newpath_c_str); + }); + }); +} + +template +inline auto posix_deal_with12( + old_path_type const& oldpath, + int newdirfd, + old_path_type const& newpath) +{ + return fast_io::posix_api_common(oldpath,[&](char const* oldpath_c_str) + { + return fast_io::posix_api_common(newpath,[&](char const* newpath_c_str) + { + return posix1x_api_dispatcher(oldpath_c_str,newdirfd,newpath_c_str); + }); + }); +} + + +template +inline auto posix_deal_with1x( + int dirfd, + path_type const& path, + Args... args) +{ + return fast_io::posix_api_common(path,[&](char const* path_c_str) + { + return posix1x_api_dispatcher(dirfd,path_c_str,args...); + }); +} + +} + +template<::fast_io::constructible_to_os_c_str old_path_type, + ::fast_io::constructible_to_os_c_str new_path_type> +inline void posix_renameat(native_at_entry oldent, + old_path_type const& oldpath, + native_at_entry newent, + new_path_type const& newpath) +{ + details::posix_deal_with22( + oldent.fd,oldpath, + newent.fd,newpath); +} + +template<::fast_io::constructible_to_os_c_str new_path_type> +inline void posix_renameat(posix_fs_dirent fs_dirent, + native_at_entry newent, + new_path_type const& newpath) +{ + details::posix_deal_with22( + fs_dirent.fd,::fast_io::manipulators::os_c_str(fs_dirent.filename), + newent.fd,newpath); +} + +template<::fast_io::constructible_to_os_c_str old_path_type, + ::fast_io::constructible_to_os_c_str new_path_type> +inline void posix_symlinkat(old_path_type const& oldpath, + native_at_entry newent, + new_path_type const& newpath) +{ + details::posix_deal_with12( + oldpath, + newent.fd,newpath); +} + + + +template<::fast_io::constructible_to_os_c_str old_path_type, + ::fast_io::constructible_to_os_c_str new_path_type> +inline void native_renameat(native_at_entry oldent, + old_path_type const& oldpath, + native_at_entry newent, + new_path_type const& newpath) +{ + details::posix_deal_with22( + oldent.fd,oldpath, + newent.fd,newpath); +} + +template<::fast_io::constructible_to_os_c_str new_path_type> +inline void native_renameat(posix_fs_dirent fs_dirent, + native_at_entry newent, + new_path_type const& newpath) +{ + details::posix_deal_with22( + fs_dirent.fd,::fast_io::manipulators::os_c_str(fs_dirent.filename), + newent.fd,newpath); +} + +template<::fast_io::constructible_to_os_c_str old_path_type, + ::fast_io::constructible_to_os_c_str new_path_type> +inline void native_symlinkat(old_path_type const& oldpath, + native_at_entry newent, + new_path_type const& newpath) +{ + details::posix_deal_with12( + oldpath, + newent.fd,newpath); +} + + +enum class posix_at_flags +{ +eaccess= +#ifdef AT_EACCESS +AT_EACCESS +#else +0 +#endif +, +symlink_nofollow= +#ifdef AT_SYMLINK_NOFOLLOW +AT_SYMLINK_NOFOLLOW +#else +0 +#endif +, +no_automount= +#ifdef AT_NO_AUTOMOUNT +AT_NO_AUTOMOUNT +#else +0 +#endif +, +removedir= +#ifdef AT_REMOVEDIR +AT_REMOVEDIR +#else +0 +#endif +, +empty_path= +#ifdef AT_EMPTY_PATH +AT_EMPTY_PATH +#else +0x1000 +#endif +}; + +using native_at_flags=posix_at_flags; + +constexpr posix_at_flags operator&(posix_at_flags x, posix_at_flags y) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(static_cast(x) & static_cast(y)); +} + +constexpr posix_at_flags operator|(posix_at_flags x, posix_at_flags y) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(static_cast(x) | static_cast(y)); +} + +constexpr posix_at_flags operator^(posix_at_flags x, posix_at_flags y) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(static_cast(x) ^ static_cast(y)); +} + +constexpr posix_at_flags operator~(posix_at_flags x) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(~static_cast(x)); +} + +inline constexpr posix_at_flags& operator&=(posix_at_flags& x, posix_at_flags y) noexcept{return x=x&y;} + +inline constexpr posix_at_flags& operator|=(posix_at_flags& x, posix_at_flags y) noexcept{return x=x|y;} + +inline constexpr posix_at_flags& operator^=(posix_at_flags& x, posix_at_flags y) noexcept{return x=x^y;} + +template<::fast_io::constructible_to_os_c_str path_type> +inline void posix_faccessat(native_at_entry ent,path_type const& path, + access_how mode,posix_at_flags flags=posix_at_flags::symlink_nofollow) +{ + details::posix_deal_with1x(ent.fd,path,static_cast(mode),static_cast(flags)); +} + +template<::fast_io::constructible_to_os_c_str path_type> +inline void native_faccessat(native_at_entry ent,path_type const& path, + access_how mode,posix_at_flags flags=posix_at_flags::symlink_nofollow) +{ + details::posix_deal_with1x(ent.fd,path,static_cast(mode),static_cast(flags)); +} + +template<::fast_io::constructible_to_os_c_str path_type> +inline void posix_fchmodat(native_at_entry ent,path_type const& path, + perms mode,posix_at_flags flags=posix_at_flags::symlink_nofollow) +{ + details::posix_deal_with1x(ent.fd,path,static_cast(mode),static_cast(flags)); +} + +template<::fast_io::constructible_to_os_c_str path_type> +inline void native_fchmodat(native_at_entry ent,path_type const& path, + perms mode,posix_at_flags flags=posix_at_flags::symlink_nofollow) +{ + details::posix_deal_with1x(ent.fd,path,static_cast(mode),static_cast(flags)); +} + +template<::fast_io::constructible_to_os_c_str path_type> +inline void posix_fchownat(native_at_entry ent,path_type const& path,std::uintmax_t owner,std::uintmax_t group,posix_at_flags flags=posix_at_flags::symlink_nofollow) +{ + details::posix_deal_with1x(ent.fd,path,owner,group,static_cast(flags)); +} + +template<::fast_io::constructible_to_os_c_str path_type> +inline void native_fchownat(native_at_entry ent,path_type const& path,std::uintmax_t owner,std::uintmax_t group,posix_at_flags flags=posix_at_flags::symlink_nofollow) +{ + details::posix_deal_with1x(ent.fd,path,owner,group,static_cast(flags)); +} + +template<::fast_io::constructible_to_os_c_str path_type> +inline posix_file_status posix_fstatat(native_at_entry ent,path_type const& path,posix_at_flags flags=posix_at_flags::symlink_nofollow) +{ + return details::posix_deal_with1x(ent.fd,path,static_cast(flags)); +} + +template<::fast_io::constructible_to_os_c_str path_type> +inline posix_file_status native_fstatat(native_at_entry ent,path_type const& path,posix_at_flags flags=posix_at_flags::symlink_nofollow) +{ + return details::posix_deal_with1x(ent.fd,path,static_cast(flags)); +} + +template<::fast_io::constructible_to_os_c_str path_type> +inline void posix_mkdirat(native_at_entry ent,path_type const& path,perms perm=static_cast(436)) +{ + return details::posix_deal_with1x(ent.fd,path,static_cast(perm)); +} + +template<::fast_io::constructible_to_os_c_str path_type> +inline void native_mkdirat(native_at_entry ent,path_type const& path,perms perm=static_cast(436)) +{ + return details::posix_deal_with1x(ent.fd,path,static_cast(perm)); +} +#if 0 +template<::fast_io::constructible_to_os_c_str path_type> +inline void posix_mknodat(native_at_entry ent,path_type const& path,perms perm,std::uintmax_t dev) +{ + return details::posix_deal_with1x(ent.fd,path,static_cast(perm),dev); +} + +template<::fast_io::constructible_to_os_c_str path_type> +inline void native_mknodat(native_at_entry ent,path_type const& path,perms perm,std::uintmax_t dev) +{ + return details::posix_deal_with1x(ent.fd,path,static_cast(perm),dev); +} +#endif +template<::fast_io::constructible_to_os_c_str path_type> +inline void posix_unlinkat(native_at_entry ent,path_type const& path,posix_at_flags flags={}) +{ + details::posix_deal_with1x(ent.fd,path,static_cast(flags)); +} + +template<::fast_io::constructible_to_os_c_str path_type> +inline void native_unlinkat(native_at_entry ent,path_type const& path,posix_at_flags flags={}) +{ + details::posix_deal_with1x(ent.fd,path,static_cast(flags)); +} + +template<::fast_io::constructible_to_os_c_str old_path_type,::fast_io::constructible_to_os_c_str new_path_type> +inline void posix_linkat(native_at_entry oldent,old_path_type const& oldpath,native_at_entry newent,new_path_type const& newpath,posix_at_flags flags=posix_at_flags::symlink_nofollow) +{ + details::posix_deal_with22(oldent.fd,oldpath, + newent.fd,newpath,static_cast(flags)); +} + +template<::fast_io::constructible_to_os_c_str old_path_type,::fast_io::constructible_to_os_c_str new_path_type> +inline void native_linkat(native_at_entry oldent,old_path_type const& oldpath,native_at_entry newent,new_path_type const& newpath,posix_at_flags flags=posix_at_flags::symlink_nofollow) +{ + details::posix_deal_with22(oldent.fd,oldpath, + newent.fd,newpath,static_cast(flags)); +} + +template<::fast_io::constructible_to_os_c_str path_type> +inline void posix_utimensat(native_at_entry ent,path_type const& path, + unix_timestamp_option creation_time, + unix_timestamp_option last_access_time, + unix_timestamp_option last_modification_time, + posix_at_flags flags=posix_at_flags::symlink_nofollow) +{ + details::posix_deal_with1x(ent.fd,path, + creation_time,last_access_time,last_modification_time,static_cast(flags)); +} + +template<::fast_io::constructible_to_os_c_str path_type> +inline void native_utimensat(native_at_entry ent,path_type const& path, + unix_timestamp_option creation_time, + unix_timestamp_option last_access_time, + unix_timestamp_option last_modification_time, + posix_at_flags flags=posix_at_flags::symlink_nofollow) +{ + details::posix_deal_with1x(ent.fd,path, + creation_time,last_access_time,last_modification_time,static_cast(flags)); +} +#if 0 +template +struct basic_posix_readlinkat_t +{ + using char_type = ch_type; + int dirfd{-1}; + char const* path{}; +}; + +template<::fast_io::constructible_to_os_c_str path_type,std::integral char_type> +inline constexpr auto posix_readlinkat( + posix_at_entry ent, + path_type const& path, + char_type* buf,std::size_t bufsz) noexcept +{ + return basic_posix_readlinkat_t{ent.fd,strvw}; +} + +template<::fast_io::constructible_to_os_c_str path_type> +inline constexpr auto native_readlinkat( + posix_at_entry ent, + path_type const& path) noexcept +{ + auto strvw{path}; + using value_type = typename std::remove_cvref_t::value_type; + if constexpr(sizeof(value_type)==1) + return basic_posix_readlinkat_t{ent.fd,strvw.c_str()}; + else + return basic_posix_readlinkat_t{ent.fd,strvw}; +} + + +namespace details +{ + +inline constexpr std::size_t read_linkbuffer_size() noexcept +{ +#if defined(PATH_MAX) + if constexpr(PATH_MAX<4096) + return 4096; + else + return PATH_MAX; +#else + return 4096; +#endif +} + +inline std::size_t posix_readlinkat_common_impl(int dirfd,char const* pathname,char* buffer) +{ + constexpr std::size_t buffer_size{read_linkbuffer_size()}; + std::ptrdiff_t bytes{ +#if defined(__linux__) + system_call< +#if __NR_readlinkat + __NR_readlinkat +#endif + ,int> +#else + ::fast_io::posix::libc_readlinkat +#endif + (dirfd,pathname,buffer,buffer_size) + }; + system_call_throw_error(bytes); + return static_cast(bytes); +} + +template +inline std::size_t read_linkat_impl_phase2(char* dst,basic_posix_readlinkat_t rlkat) +{ + if constexpr(sizeof(path_char_type)==1) + { + return posix_readlinkat_common_impl(rlkat.dirfd,reinterpret_cast(rlkat.path),dst); + } + else + { + posix_api_encoding_converter converter(rlkat.path.data(),rlkat.path.size()); + return posix_readlinkat_common_impl(rlkat.dirfd,converter.native_c_str(),dst); + } +} + +template< +std::integral to_char_type, +std::integral path_char_type> +inline to_char_type* read_linkat_impl_phase1(to_char_type* dst,basic_posix_readlinkat_t rlkat) +{ + if constexpr(sizeof(path_char_type)==1) + { + return dst+read_linkat_impl_phase2(reinterpret_cast(dst),rlkat); + } + else + { + constexpr std::size_t buffer_size{read_linkbuffer_size()}; + local_operator_new_array_ptr dynamic_buffer(buffer_size); + std::size_t bytes{read_linkat_impl_phase2(reinterpret_cast(dynamic_buffer.ptr),rlkat)}; + return codecvt::general_code_cvt_full(dynamic_buffer.ptr,dynamic_buffer.ptr+bytes,dst); + } +} + +} + + +template +inline constexpr std::size_t print_reserve_size(io_reserve_type_t>, + basic_posix_readlinkat_t) noexcept +{ + if constexpr(sizeof(char_type)==1) + return details::read_linkbuffer_size(); + else + { + constexpr std::size_t sz{details::read_linkbuffer_size()}; + constexpr std::size_t decorated_size{details::cal_decorated_reserve_size<1,sizeof(char_type)>(sz)}; + return decorated_size; + } +} + +template<::std::integral char_type,std::integral char_type> +inline constexpr char_type* print_reserve_define(io_reserve_type_t>, + char_type* iter, + basic_posix_readlinkat_t rlkat) +{ + return details::read_linkat_impl_phase1(iter,rlkat); +} +#endif + +} diff --git a/src/fast_io/include/fast_io_hosted/iomutex.h b/src/fast_io/include/fast_io_hosted/iomutex.h new file mode 100644 index 0000000..91a644a --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/iomutex.h @@ -0,0 +1,93 @@ +#pragma once + +namespace fast_io +{ + +template +requires requires(Mutex&& m) +{ + m.lock(); + m.unlock(); + m.try_lock(); +} +struct basic_general_iomutex +{ + using mutex_type = Mutex; + using unlocked_handle_type = T; + using char_type = typename unlocked_handle_type::char_type; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif + T handle; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif + mutex_type mutex; + + template + requires std::constructible_from + explicit constexpr basic_general_iomutex(Args&& ...args):handle(::std::forward(args)...) + { + } + inline constexpr void lock() noexcept(noexcept(mutex.lock())) + { + mutex.lock(); + } + inline constexpr bool try_lock() noexcept(noexcept(mutex.try_lock())) + { + return mutex.try_lock(); + } + inline constexpr void unlock() noexcept + { + mutex.unlock(); + } + inline constexpr unlocked_handle_type const& unlocked_handle() const noexcept + { + return handle; + } + inline constexpr unlocked_handle_type& unlocked_handle() noexcept + { + return handle; + } + template + inline constexpr void reopen(Args&& ...args) + { + io_lock_guard gd{mutex}; + handle.reopen(::std::forward(args)...); + } +}; + +template +inline constexpr decltype(auto) read(basic_general_iomutex& mtx,Iter begin,Iter end) +{ + io_lock_guard gd{mtx.mutex}; + return read(mtx.handle,begin,end); +} + +template +inline constexpr decltype(auto) write(basic_general_iomutex& mtx,Iter begin,Iter end) +{ + io_lock_guard gd{mtx.mutex}; + return write(mtx.handle,begin,end); +} + +template +inline constexpr void flush(basic_general_iomutex& mtx) +{ + io_lock_guard gd{mtx.mutex}; + flush(mtx.handle); +} + +template +using basic_iomutex = basic_general_iomutex; + +} + diff --git a/src/fast_io/include/fast_io_hosted/mmap.h b/src/fast_io/include/fast_io_hosted/mmap.h new file mode 100644 index 0000000..21b8b13 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/mmap.h @@ -0,0 +1,19 @@ +#pragma once + +namespace fast_io +{ +/* +enum class mapping +{ +indeterminate,private,shared,copy_on_write,clean +}; +*/ + +enum class file_map_attribute +{ +execute_read=0x20,execute_read_write=0x40,execute_write_copy=0x80, +read_only=0x02,read_write=0x04,write_copy=0x08 +}; + + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_hosted/platforms/com_error.h b/src/fast_io/include/fast_io_hosted/platforms/com_error.h new file mode 100644 index 0000000..fef675d --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/com_error.h @@ -0,0 +1,41 @@ +#pragma once + +#include + +namespace fast_io +{ +#if 0 +namespace details +{ + +inline void report_com_error(error_reporter& report, auto hresult) requires(std::same_as) +{ + _com_error ce(hresult); + print_freestanding(report,cstring_view{ce.ErrorMessage()}); +} + +inline void report_com_error(error_reporter& report, auto hresult) requires(std::same_as&&sizeof(wchar_t)==2) +{ + _com_error ce(hresult); + print_freestanding(report,fast_io::code_cvt(std::wstring_view{ce.ErrorMessage()})); +} +} +#endif +class com_error : public std::exception +{ +public: + HRESULT hresult{}; + explicit com_error(HRESULT hr):hresult(hr){} + constexpr auto code() const noexcept + { + return hresult; + } +#if 0 + void report(error_reporter& report) const override + { + details::report_com_error(report,hresult); + } +#endif +}; + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_hosted/platforms/errc_default_impl.h b/src/fast_io/include/fast_io_hosted/platforms/errc_default_impl.h new file mode 100644 index 0000000..05f7d35 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/errc_default_impl.h @@ -0,0 +1,13 @@ +#pragma once + +namespace fast_io +{ + +namespace freestanding +{ + +using ::std::errc; + +} + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_hosted/platforms/errc_impl.h b/src/fast_io/include/fast_io_hosted/platforms/errc_impl.h new file mode 100644 index 0000000..02e9c50 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/errc_impl.h @@ -0,0 +1,16 @@ +#pragma once + +namespace fast_io +{ + +namespace freestanding +{ + +enum class errc: + ::std::uint_least32_t +{ +}; + +} + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_hosted/platforms/errno_to_win32_code.h b/src/fast_io/include/fast_io_hosted/platforms/errno_to_win32_code.h new file mode 100644 index 0000000..eedac80 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/errno_to_win32_code.h @@ -0,0 +1,131 @@ +#pragma once +case 0: return 0; +#if defined(EACCES) +case EACCES: return 5; +#endif +#if defined(EAGAIN) +case EAGAIN: return 89; +#endif +#if defined(EBADF) +case EBADF: return 6; +#endif +#if defined(EBADRQC) +case EBADRQC: return 1; +#endif +#if defined(EBUSY) +case EBUSY: return 32; +#endif +#if defined(ECHILD) +case ECHILD: return 128; +#endif +#if defined(ECOMM) +case ECOMM: return 233; +#endif +#if defined(ECONNREFUSED) +case ECONNREFUSED: return 1225; +#endif +#if defined(EDEADLOCK) +case EDEADLOCK: return 1131; +#endif +#if defined(EEXIST) +case EEXIST: return 80; +#endif +#if defined(EFAULT) +case EFAULT: return 998; +#endif +#if defined(EFBIG) +case EFBIG: return 1450; +#endif +#if defined(EINTR) +case EINTR: return 104; +#endif +#if defined(EINVAL) +case EINVAL: return 13; +#endif +#if defined(EIO) +case EIO: return 23; +#endif +#if defined(ELIBBAD) +case ELIBBAD: return 14001; +#endif +#if defined(EMFILE) +case EMFILE: return 4; +#endif +#if defined(EMLINK) +case EMLINK: return 1142; +#endif +#if defined(EMSGSIZE) +case EMSGSIZE: return 234; +#endif +#if defined(ENAMETOOLONG) +case ENAMETOOLONG: return 206; +#endif +#if defined(ENFILE) +case ENFILE: return 113; +#endif +#if defined(ENMFILE) +case ENMFILE: return 18; +#endif +#if defined(ENODATA) +case ENODATA: return 38; +#endif +#if defined(ENODEV) +case ENODEV: return 15; +#endif +#if defined(ENOENT) +case ENOENT: return 2; +#endif +#if defined(ENOEXEC) +case ENOEXEC: return 191; +#endif +#if defined(ENOLCK) +case ENOLCK: return 36; +#endif +#if defined(ENOLINK) +case ENOLINK: return 2250; +#endif +#if defined(ENOMEDIUM) +case ENOMEDIUM: return 21; +#endif +#if defined(ENOMEM) +case ENOMEM: return 8; +#endif +#if defined(ENONET) +case ENONET: return 51; +#endif +#if defined(ENOSPC) +case ENOSPC: return 39; +#endif +#if defined(ENOSYS) +case ENOSYS: return 50; +#endif +#if defined(ENOTDIR) +case ENOTDIR: return 267; +#endif +#if defined(ENOTEMPTY) +case ENOTEMPTY: return 145; +#endif +#if defined(ENOTSUP) +case ENOTSUP: return 282; +#endif +#if defined(ENOTUNIQ) +case ENOTUNIQ: return 52; +#endif +#if defined(ENXIO) +case ENXIO: return 1006; +#endif +#if defined(EPERM) +case EPERM: return 82; +#endif +#if defined(EPIPE) +case EPIPE: return 109; +#endif +#if defined(EROFS) +case EROFS: return 19; +#endif +#if defined(ESRCH) +case ESRCH: return 127; +#endif +#if defined(EXDEV) +case EXDEV: return 17; +#endif diff --git a/src/fast_io/include/fast_io_hosted/platforms/linux/aarch64.h b/src/fast_io/include/fast_io_hosted/platforms/linux/aarch64.h new file mode 100644 index 0000000..9d09fa9 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/linux/aarch64.h @@ -0,0 +1,145 @@ +#pragma once + +namespace fast_io +{ + +template +requires (1(x0); +} + +template +requires (1(x0); +} + +template +inline void system_call_no_return(auto p1) noexcept +{ + register std::uint_least64_t x8 __asm__("x8") = syscall_number; + register std::uint_least64_t x0 __asm__("x0") = (std::uint_least64_t)p1; + __asm__ __volatile__ + ("svc 0" + : "=r" (x0) + : "r"(x8), "0"(x0) + : "memory", "cc" + ); +} + +template +requires (1(x0); +} + +template +requires (1(x0); +} + +template +requires (1(x0); +} + +template +requires (1(x0); +} + +template +requires (1(x0); +} + +template +inline void fast_exit(I ret) noexcept +{ + system_call_no_return<__NR_exit>(ret); +} + +} diff --git a/src/fast_io/include/fast_io_hosted/platforms/linux/amd64.h b/src/fast_io/include/fast_io_hosted/platforms/linux/amd64.h new file mode 100644 index 0000000..3dcc1ec --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/linux/amd64.h @@ -0,0 +1,143 @@ +#pragma once +//https://github.com/bminor/glibc/master/sysdeps/unix/sysv/linux/x86_64/sysdep.h + +namespace fast_io +{ + +template +requires (1 +requires (1 +[[noreturn]] +inline void system_call_no_return(auto p1) noexcept +{ + std::size_t ret; + __asm__ __volatile__ + ( + "syscall" + : "=a" (ret) + //EDI RSI RDX + : "0"(syscall_number), "D"(p1) + : "memory", "cc", "r11", "cx" + ); +} + +template +requires (1 +requires (1 +requires (1 +requires (1 +requires (1 +inline void fast_exit(I ret) noexcept +{ + system_call_no_return<__NR_exit>(ret); +} +} diff --git a/src/fast_io/include/fast_io_hosted/platforms/linux/generic.h b/src/fast_io/include/fast_io_hosted/platforms/linux/generic.h new file mode 100644 index 0000000..b78914e --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/linux/generic.h @@ -0,0 +1,29 @@ +#pragma once +#include +#include + +namespace fast_io +{ + +template +requires (std::is_trivially_copyable_v&&...) +inline return_value_type system_call(Args ...args) noexcept +{ + long ret{::syscall(syscall_number,args...)}; + if(ret==-1) + return static_cast(-errno); + return static_cast(ret); +} + +template +[[noreturn]] inline void system_call_no_return(auto p1) noexcept +{ + ::syscall(syscall_number,p1); +} + +template +[[noreturn]] inline void fast_exit(I ret) noexcept +{ + system_call_no_return<__NR_exit>(ret); +} +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_hosted/platforms/linux/loongarch64.h b/src/fast_io/include/fast_io_hosted/platforms/linux/loongarch64.h new file mode 100644 index 0000000..e94da33 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/linux/loongarch64.h @@ -0,0 +1,150 @@ +#pragma once +/* +Referenced from +glibc loongarch +loongarch syscall is very similar to riscv. but it is using syscall instruction like x86_64 +*/ + +namespace fast_io +{ + +template +requires (1(a0); +} + +template +requires (1(a0); +} + +template +inline void system_call_no_return(auto p1) noexcept +{ + register std::uint_least64_t a7 __asm__("$a7") = syscall_number; + register std::uint_least64_t a0 __asm__("$a0") = (std::uint_least64_t)p1; + __asm__ __volatile__ + ("syscall 0" + : "+r" (a0) + : "r"(a7) + : "memory" + ); +} + +template +requires (1(a0); +} + +template +requires (1(a0); +} + +template +requires (1(a0); +} + +template +requires (1(a0); +} + +template +requires (1(a0); +} + +template +inline void fast_exit(I ret) noexcept +{ + system_call_no_return<__NR_exit>(ret); +} + +} diff --git a/src/fast_io/include/fast_io_hosted/platforms/linux/riscv64.h b/src/fast_io/include/fast_io_hosted/platforms/linux/riscv64.h new file mode 100644 index 0000000..ee2db74 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/linux/riscv64.h @@ -0,0 +1,150 @@ +#pragma once +/* +https://github.com/riscvarchive/riscv-musl/blob/develop/arch/riscv64/syscall_arch.h + +Do we need to deal with big endian with extra code??? +*/ + +namespace fast_io +{ + +template +requires (1(a0); +} + +template +requires (1(a0); +} + +template +inline void system_call_no_return(auto p1) noexcept +{ + register std::uint_least64_t a7 __asm__("a7") = syscall_number; + register std::uint_least64_t a0 __asm__("a0") = (std::uint_least64_t)p1; + __asm__ __volatile__ + ("ecall" + : "+r" (a0) + : "r"(a7) + : "memory" + ); +} + +template +requires (1(a0); +} + +template +requires (1(a0); +} + +template +requires (1(a0); +} + +template +requires (1(a0); +} + +template +requires (1(a0); +} + +template +inline void fast_exit(I ret) noexcept +{ + system_call_no_return<__NR_exit>(ret); +} + +} diff --git a/src/fast_io/include/fast_io_hosted/platforms/linux/system_call.h b/src/fast_io/include/fast_io_hosted/platforms/linux/system_call.h new file mode 100644 index 0000000..a890796 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/linux/system_call.h @@ -0,0 +1,61 @@ +#pragma once + +#if defined(__linux__) +#include +#ifdef __x86_64__ +#include"amd64.h" +#elif defined(__arm64__) || defined(__aarch64__) +#include"aarch64.h" +#elif defined(__riscv) && __SIZEOF_SIZE_T__==8 +#include"riscv64.h" +#elif defined(__loongarch__) && __SIZEOF_SIZE_T__==8 +#include"loongarch64.h" +#else +#include"generic.h" +#endif +#endif + + +namespace fast_io +{ + +#if defined(__linux__) + +template +inline constexpr bool linux_system_call_fails(int_type v) noexcept +{ + using unsigned_t = std::make_unsigned_t; + return static_cast(static_cast(v)+static_cast(4096))(4096); +} + +#endif + +template +requires(sizeof(I)>=1) +inline void system_call_throw_error(I v) +{ +#if defined(__linux__) + using unsigned_t = std::make_unsigned_t; + if(static_cast(static_cast(v)+static_cast(4096))(4096)) + { + if constexpr(always_terminate) + fast_terminate(); + else + { + throw_posix_error(static_cast(-v)); + } + } +#else + if(v<0) + { + if constexpr(always_terminate) + fast_terminate(); + else + { + throw_posix_error(); + } + } +#endif +} + +} diff --git a/src/fast_io/include/fast_io_hosted/platforms/linux_zerocopy.h b/src/fast_io/include/fast_io_hosted/platforms/linux_zerocopy.h new file mode 100644 index 0000000..b7ed59b --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/linux_zerocopy.h @@ -0,0 +1,134 @@ +#pragma once +// To verify __NR_copy_file_range +namespace fast_io +{ + +template +struct basic_linux_zero_copy_entry +{ + int fd{-1}; +}; + +template +inline basic_linux_zero_copy_entry zero_copy_in_handle(basic_posix_io_observer h) +{ + return {h.fd}; +} +template +inline basic_linux_zero_copy_entry zero_copy_out_handle(basic_posix_io_observer h) +{ + return {h.fd}; +} + +template +inline basic_linux_zero_copy_entry zero_copy_in_handle(basic_posix_pipe& h) +{ + return {h.in().fd}; +} +template +inline basic_linux_zero_copy_entry zero_copy_out_handle(basic_posix_pipe& h) +{ + return {h.out().fd}; +} + +namespace details +{ + +inline std::uintmax_t linux_send_file_transmit_raw_impl(int out_fd,int in_fd) +{ + return raw_transmit_decay(posix_io_observer{out_fd},posix_io_observer{in_fd}); +} + +inline std::uintmax_t zero_copy_transmit_define_impl(int out_fd,int in_fd) +{ + using posix_ssize_t = std::make_signed_t; + constexpr std::size_t transmit_a_round{static_cast(std::numeric_limits::max())}; + std::uintmax_t total_bytes{}; + for(;;) + { + posix_ssize_t diff{ +#if defined(__NR_sendfile64) + system_call<__NR_sendfile64,posix_ssize_t> +#else + system_call<__NR_sendfile,posix_ssize_t> +#endif + (out_fd,in_fd,nullptr,transmit_a_round)}; + if(linux_system_call_fails(diff))[[unlikely]] + return total_bytes+linux_send_file_transmit_raw_impl(out_fd,in_fd); + else if(diff==0)[[unlikely]] + break; + total_bytes+=static_cast(diff); + } + return total_bytes; +} + +inline std::uint_least64_t zero_copy_transmit_define64_impl(int out_fd,int in_fd,std::uint_least64_t count) +{ + using posix_ssize_t = std::make_signed_t; + constexpr std::size_t transmit_a_round{static_cast(std::numeric_limits::max())}; + std::uint_least64_t total_bytes{}; + for(;;) + { + std::uint_least64_t to_transmit_this_round{transmit_a_round}; + if(count +#else + system_call<__NR_sendfile,posix_ssize_t> +#endif + (out_fd,in_fd,nullptr,to_transmit_this_round)}; + if(linux_system_call_fails(diff))[[unlikely]] + { + return total_bytes+::fast_io::raw_transmit64_decay(posix_io_observer{out_fd},posix_io_observer{in_fd},count); + } + else if(diff==0)[[unlikely]] + break; + std::uint_least64_t diff64{static_cast(diff)}; + total_bytes+=diff64; + count-=diff64; + if(count==0) + break; + } + return total_bytes; +} + +} + +template +inline std::uintmax_t zero_copy_transmit_define(io_alias_t,basic_linux_zero_copy_entry outs,basic_linux_zero_copy_entry ins) +{ + return details::zero_copy_transmit_define_impl(outs.fd,ins.fd)/sizeof(ch_type2); +} + +template +inline std::uint_least64_t zero_copy_transmit64_define(io_alias_t,basic_linux_zero_copy_entry outs,basic_linux_zero_copy_entry ins,std::uint_least64_t characters) +{ + constexpr std::size_t input_char_type_size{sizeof(ch_type2)}; + if constexpr(input_char_type_size!=1) + { + constexpr std::uint_least64_t mx{std::numeric_limits::max()/input_char_type_size}; + std::uint_least64_t chars{}; + for(std::size_t i{};i!=input_char_type_size;++i) + { + bool const overflow_copy{characters>mx}; + std::uint_least64_t copy_this_round{characters}; + if(overflow_copy)[[unlikely]] + { + copy_this_round=mx; + } + chars+=::fast_io::details::zero_copy_transmit_define64_impl(io_alias,outs.fd,ins.fd,characters,copy_this_round)/sizeof(input_char_type_size); + if(!overflow_copy)[[likely]] + break; + characters-=mx; + } + return chars; + } + else + { + return ::fast_io::details::zero_copy_transmit_define64_impl(outs.fd,ins.fd,characters); + } +} + +} diff --git a/src/fast_io/include/fast_io_hosted/platforms/msdos.h b/src/fast_io/include/fast_io_hosted/platforms/msdos.h new file mode 100644 index 0000000..a8c3623 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/msdos.h @@ -0,0 +1,60 @@ +#pragma once + +namespace fast_io +{ +/* +MSDOS should not contain any issues with multiple write calls +*/ + +namespace details +{ + +inline io_scatter_status_t posix_scatter_read_impl_with_normal_read(int fd,io_scatters_t scatters) +{ + std::size_t total_size{}; + for(std::size_t i{};i!=scatters.len;++i) + { + auto e{scatters.base[i]}; + auto ret{noexcept_call(::read,fd,const_cast(e.base),e.len)}; + if(ret==-1) + throw_posix_error(); + std::size_t tsize{static_cast(ret)}; + total_size+=tsize; + if(tsize!=e.len) + return {total_size,i,tsize}; + } + return {total_size,scatters.len,0}; +} + +inline io_scatter_status_t posix_scatter_write_impl_with_normal_write(int fd,io_scatters_t scatters) +{ + std::size_t total_size{}; + for(std::size_t i{};i!=scatters.len;++i) + { + auto e{scatters.base[i]}; + auto ret{noexcept_call(::write,fd,e.base,e.len)}; + if(ret==-1) + throw_posix_error(); + std::size_t tsize{static_cast(ret)}; + total_size+=tsize; + if(tsize!=e.len) + return {total_size,i,tsize}; + } + return {total_size,scatters.len,0}; +} + +} + +template +inline io_scatter_status_t scatter_read(basic_posix_io_observer piob,io_scatters_t scatters) +{ + return details::posix_scatter_read_impl_with_normal_read(piob.fd,scatters); +} + +template +inline io_scatter_status_t scatter_write(basic_posix_io_observer piob,io_scatters_t scatters) +{ + return details::posix_scatter_write_impl_with_normal_write(piob.fd,scatters); +} + +} diff --git a/src/fast_io/include/fast_io_hosted/platforms/native.h b/src/fast_io/include/fast_io_hosted/platforms/native.h new file mode 100644 index 0000000..bff3521 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/native.h @@ -0,0 +1,12 @@ +#pragma once +#include"native_base.h" +#if defined(_WIN32) || defined(__CYGWIN__) +#include"win32_mapping.h" +#if defined(__CYGWIN__) +#include"posix_mapping.h" +#endif +#include"omap.h" +#elif !defined(__NEWLIB__) && !defined(__MSDOS__) && (!defined(__wasm__) || (defined(__wasi__)&&defined(_WASI_EMULATED_MMAN))) && __has_include() +#include"posix_mapping.h" +#include"omap.h" +#endif diff --git a/src/fast_io/include/fast_io_hosted/platforms/native_base.h b/src/fast_io/include/fast_io_hosted/platforms/native_base.h new file mode 100644 index 0000000..8eb37ba --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/native_base.h @@ -0,0 +1,103 @@ +#pragma once + +#if defined(_WIN32) || defined(__CYGWIN__) +#include"win32/impl.h" +namespace fast_io +{ + +inline constexpr std::uint_least32_t win32_stdin_number(static_cast(-10)); +inline constexpr std::uint_least32_t win32_stdout_number(static_cast(-11)); +inline constexpr std::uint_least32_t win32_stderr_number(static_cast(-12)); + +} +#include"win32_code.h" +#include"nt/impl.h" +#include"win32_error.h" + +#include"nt.h" +//#include"win32_iocp_overlapped.h" +#include"win32.h" +#include"win32_network/win32.h" +#endif +#include"linux/system_call.h" +#include"posix.h" +#if (!defined(_WIN32) || defined(__WINE__)) && __has_include() && __has_include() && !defined(__wasi__) +#include"posix_netop.h" +#if __has_include() +#include "posix_dns.h" +#endif +#endif + +namespace fast_io +{ + +#if defined(_WIN32) && !defined(__WINE__) +inline constexpr auto native_stdin_number(win32_stdin_number); +inline constexpr auto native_stdout_number(win32_stdout_number); +inline constexpr auto native_stderr_number(win32_stderr_number); + +using native_at_entry = nt_at_entry; +using native_fs_dirent = nt_fs_dirent; + +template +using basic_native_io_observer = basic_win32_io_observer; +template +using basic_native_file = basic_win32_file; +template +using basic_native_pipe = basic_win32_pipe; +#else +inline constexpr auto native_stdin_number(posix_stdin_number); +inline constexpr auto native_stdout_number(posix_stdout_number); +inline constexpr auto native_stderr_number(posix_stderr_number); + +using native_at_entry = posix_at_entry; +using native_fs_dirent = posix_fs_dirent; + +template +using basic_native_io_observer = basic_posix_io_observer; +template +using basic_native_file = basic_posix_file; +template +using basic_native_pipe = basic_posix_pipe; + +#endif + +using native_io_observer = basic_native_io_observer; +using native_file = basic_native_file; +using native_pipe = basic_native_pipe; + +using wnative_io_observer = basic_native_io_observer; +using wnative_file = basic_native_file; +using wnative_pipe = basic_native_pipe; + +using u8native_io_observer = basic_native_io_observer; +using u8native_file = basic_native_file; +using u8native_pipe = basic_native_pipe; + +using u16native_io_observer = basic_native_io_observer; +using u16native_file = basic_native_file; +using u16native_pipe = basic_native_pipe; + +using u32native_io_observer = basic_native_io_observer; +using u32native_file = basic_native_file; +using u32native_pipe = basic_native_pipe; + + +#if defined(_WIN32) || (__has_include() && __has_include() && !defined(__wasi__)) +using native_socket_io_observer = basic_native_socket_io_observer; +using native_socket_file = basic_native_socket_file; + +using wnative_socket_io_observer = basic_native_socket_io_observer; +using wnative_socket_file = basic_native_socket_file; + +using u8native_socket_io_observer = basic_native_socket_io_observer; +using u8native_socket_file = basic_native_socket_file; + +using u16native_socket_io_observer = basic_native_socket_io_observer; +using u16native_socket_file = basic_native_socket_file; + +using u32native_socket_io_observer = basic_native_socket_io_observer; +using u32native_socket_file = basic_native_socket_file; +#endif + +} diff --git a/src/fast_io/include/fast_io_hosted/platforms/nt.h b/src/fast_io/include/fast_io_hosted/platforms/nt.h new file mode 100644 index 0000000..00f260b --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/nt.h @@ -0,0 +1,1267 @@ +#pragma once + +namespace fast_io +{ + +/* +Referenced from Windows Internal Version 7 +*/ +enum class nt_family +{ +alpc, //Alpc: Advanced Local Procedure Calls +cc, //Cc: Common Cache +cm, //Cm: Configuration manager +dbg, //Dbg: kernel debug support +dbgk, //Dbgk: Debugging Framework for user mode +em, //Em: Errata manager +etw, //Event: Event Tracing for Windows +ex, //Executive support routines +fs_rtl, //FsRtl: File System Runtime Library +hv, //Hv: Hive library +hvl, //Hvl: Hypervisor Library +io, //Io: I/O manager +kd, //Kd: Kernel debugger +ke, //Ke: Kernel +kse, //Kse: Kernel Shim Engine +lsa, //Lsa: Local Security Authority +mm, //Mm: Memory manager +nt, //Nt: NT system services (accessible from user mode through system calls) +ob, //Ob: Object manager +pf, //Pf: Prefetcher +po, //Po: Power manager +po_fx, //PoFx: Power framework +pp, //Pp: PnP manager +ppm, //Ppm: Processor power manager +ps, //Ps: Process support +rtl, //Rtl: Run-time library +se, //Se: Security Reference Monitor +sm, //Sm: Store Manager +tm, //Tm: Transaction +ttm, //Ttm: Terminal timeout manager +vf, //Vf: Driver verifier +vsl, //Vsl: Virtual secure mode library +wdi, //Wdi: Windows Diagnostic Infrastructure +wfp, //Wfp: Windows FingerPrint +whea, //Whea: Windows Hardware Error Architecture +wmi, //Wmi: Windows Management Instrumentation +zw //Zw: Mirror entry point for system services (beginning with Nt) that sets previous access mode to kernel, which eliminates parameter validation, because Nt system services validate parameters only if previous access mode is user +}; + +namespace win32::nt::details +{ + +struct nt_open_mode +{ +::std::uint_least32_t DesiredAccess{}; +::std::uint_least32_t FileAttributes{}; +::std::uint_least32_t ShareAccess{}; +::std::uint_least32_t CreateDisposition{}; +::std::uint_least32_t CreateOptions{}; +::std::uint_least32_t ObjAttributes{}; +}; + +/* +https://docs.microsoft.com/en-us/windows/win32/secauthz/access-mask-format +*/ + +inline constexpr nt_open_mode calculate_nt_open_mode(open_mode_perms ompm) noexcept +{ + open_mode value{ompm.om}; + perms pm{ompm.pm}; + nt_open_mode mode; + if((value&open_mode::no_shared_read)==open_mode::none) + mode.ShareAccess|=1;//FILE_SHARE_READ + if((value&open_mode::no_shared_write)==open_mode::none) + mode.ShareAccess|=2;//FILE_SHARE_DELETE + if((value&open_mode::shared_delete)!=open_mode::none) + mode.ShareAccess|=4;//FILE_SHARE_WRITE + bool generic_write{}; + if((value&open_mode::app)!=open_mode::none) + mode.DesiredAccess|=4; //FILE_APPEND_DATA + else if((value&open_mode::out)!=open_mode::none) + { + mode.DesiredAccess|=0x120116; //FILE_GENERIC_WRITE + generic_write=true; + } + if(((value&open_mode::in)!=open_mode::none)||((value&open_mode::app)!=open_mode::none)) + { + mode.DesiredAccess|=0x120089; //FILE_GENERIC_READ + if((value&open_mode::out)!=open_mode::none&&((value&open_mode::app)!=open_mode::none&&(value&open_mode::trunc)!=open_mode::none)) + { + mode.DesiredAccess|=0x120116; + generic_write=true; + } + } +/* + +https://doxygen.reactos.org/d6/d0e/ndk_2iotypes_8h.html +#define FILE_SUPERSEDE 0x00000000 +#define FILE_OPEN 0x00000001 +#define FILE_CREATE 0x00000002 +#define FILE_OPEN_IF 0x00000003 +#define FILE_OVERWRITE 0x00000004 +#define FILE_OVERWRITE_IF 0x00000005 + +https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/nf-ntifs-ntcreatefile +CreateDisposition value Action if file exists Action if file does not exist +FILE_SUPERSEDE Replace the file. Create the file. 0x00000000 +FILE_OPEN Open the file. Return an error. 0x00000001 +FILE_CREATE Return an error. Create the file. 0x00000002 +FILE_OPEN_IF Open the file. Create the file. 0x00000003 +FILE_OVERWRITE Open the file, and overwrite it. Return an error. 0x00000004 +FILE_OVERWRITE_IF Open the file, and overwrite it. Create the file. 0x00000005 + + +https://doxygen.reactos.org/dd/d83/dll_2win32_2kernel32_2client_2file_2create_8c_source.html +Line 88: + +win32 => nt +CREATE_NEW => FILE_CREATE (0x00000002) +CREATE_ALWAYS => FILE_OVERWRITE_IF (0x00000005) +OPEN_EXISITNG => FILE_OPEN (0x00000001) +OPEN_ALWAYS => FILE_OPEN_IF (0x00000003) +TRUNCATING_EXISITING=> FILE_OVERWRITE (0x00000004) + +File access +mode string Meaning Explanation Action if file +already exists Action if file +does not exist +"r" read Open a file for reading read from start failure to open +"w" write Create a file for writing destroy contents create new +"a" append Append to a file write to end create new +"r+" read extended Open a file for read/write read from start error +"w+" write extended Create a file for read/write destroy contents create new +"a+" append extended Open a file for read/write write to end create new +*/ + if ((value&open_mode::trunc)!=open_mode::none) + { + if((value&open_mode::excl)!=open_mode::none) + mode.CreateDisposition=0x00000002;// CREATE_NEW => FILE_CREATE (0x00000002) + else + mode.CreateDisposition=0x00000005;// CREATE_ALWAYS => FILE_OVERWRITE_IF (0x00000005) + } + else if((value&open_mode::in)==open_mode::none) + { + if((value&open_mode::app)!=open_mode::none) + mode.CreateDisposition=0x00000003;//OPEN_ALWAYS => FILE_OPEN_IF (0x00000003) + else if((value&open_mode::out)!=open_mode::none) + { + if((value&open_mode::excl)!=open_mode::none) + mode.CreateDisposition=0x00000002;// CREATE_NEW => FILE_CREATE (0x00000002) + else + mode.CreateDisposition=0x00000005;// CREATE_ALWAYS => FILE_OVERWRITE_IF (0x00000005) + } + } + else if((value&open_mode::app)!=open_mode::none) + mode.CreateDisposition=0x00000003;//OPEN_ALWAYS => FILE_OPEN_IF (0x00000003) + else + mode.CreateDisposition=0x00000001;//OPEN_EXISTING => FILE_OPEN (0x00000001) + + if((value&open_mode::creat)!=open_mode::none) + { + if((value&open_mode::excl)!=open_mode::none) + mode.CreateDisposition=0x00000002;//CREATE_NEW => FILE_CREATE (0x00000002) + else + mode.CreateDisposition=0x00000003;//OPEN_ALWAYS => FILE_OPEN_IF (0x00000003) + } + if((value&open_mode::direct)!=open_mode::none) + mode.CreateOptions |= 0x00000008;//FILE_NO_INTERMEDIATE_BUFFERING + if((value&open_mode::sync)!=open_mode::none) + mode.CreateOptions |= 0x00000002;//FILE_WRITE_THROUGH + if((value&open_mode::follow)!=open_mode::none) + mode.CreateOptions |= 0x00200000; //FILE_FLAG_OPEN_REPARSE_POINT => FILE_OPEN_REPARSE_POINT (0x00200000) + bool set_normal{true}; + if((value&open_mode::archive)!=open_mode::none) + { + mode.FileAttributes|=0x20; //FILE_ATTRIBUTE_ARCHIVE + set_normal={}; + } + if((value&open_mode::encrypted)!=open_mode::none) + { + mode.FileAttributes|=0x4000; //FILE_ATTRIBUTE_ENCRYPTED + set_normal={}; + } + if((value&open_mode::hidden)!=open_mode::none) + { + mode.FileAttributes|=0x2; //FILE_ATTRIBUTE_HIDDEN + set_normal={}; + } + if((value&open_mode::compressed)!=open_mode::none) + { + mode.FileAttributes|=0x800; //FILE_ATTRIBUTE_COMPRESSED + set_normal={}; + } + if((value&open_mode::system)!=open_mode::none) + { + mode.FileAttributes|=0x4; //FILE_ATTRIBUTE_SYSTEM + set_normal={}; + } + if((value&open_mode::offline)!=open_mode::none) + { + mode.FileAttributes|=0x1000; //FILE_ATTRIBUTE_OFFLINE + set_normal={}; + } + if(set_normal)[[likely]] + mode.FileAttributes|=0x80; //FILE_ATTRIBUTE_NORMAL + + if((value&open_mode::directory)==open_mode::none) + mode.CreateOptions|=0x00000040; //FILE_NON_DIRECTORY_FILE 0x00000040 + else + { + if(mode.CreateDisposition==0) + { + mode.DesiredAccess|=0x120089; //FILE_GENERIC_READ + mode.CreateDisposition=0x00000001; //OPEN_EXISTING + } + mode.CreateOptions |= 0x00004000; //FILE_OPEN_FOR_BACKUP_INTENT + mode.CreateOptions |= 0x00000001; //FILE_DIRECTORY_FILE + if(generic_write) + mode.CreateOptions |= 0x00000400; //FILE_OPEN_REMOTE_INSTANCE + if((value&open_mode::creat)!=open_mode::none) + mode.DesiredAccess |= UINT32_C(0x120116)|UINT32_C(0x120089); //GENERIC_READ | GENERIC_WRITE + } + if((value&open_mode::no_block)==open_mode::none) + mode.CreateOptions|=0x00000020; //FILE_SYNCHRONOUS_IO_NONALERT 0x00000020 + else + mode.CreateOptions|=0x00000010; //FILE_SYNCHRONOUS_IO_ALERT 0x00000010 + + if((value&open_mode::random_access)==open_mode::none) + { + if((value&open_mode::directory)==open_mode::none) + mode.CreateOptions|=0x00000004; //FILE_SEQUENTIAL_ONLY 0x00000004 + } + else + mode.CreateOptions|=0x00000800; + if((value&open_mode::no_recall)!=open_mode::none) + mode.CreateOptions|=0x00400000; //FILE_OPEN_NO_RECALL 0x00400000 + if((value&open_mode::case_insensitive)!=open_mode::none) + mode.ObjAttributes|=0x00000040; //OBJ_CASE_INSENSITIVE + if((value&open_mode::inherit)!=open_mode::none) + mode.ObjAttributes|=0x00000002; //OBJ_INHERIT + + if((value&open_mode::session_aware)!=open_mode::none) + mode.CreateOptions|=0x00040000; //FILE_SESSION_AWARE + if((value&open_mode::temporary)!=open_mode::none) + { + mode.CreateOptions|=0x00001000; //FILE_DELETE_ON_CLOSE + mode.FileAttributes|=0x100; //FILE_ATTRIBUTE_TEMPORARY?? + mode.DesiredAccess|=0x00010000; //DELETE + } + if((pm&perms::owner_write)==perms::none) + mode.FileAttributes|=0x00000001; //FILE_ATTRIBUTE_READONLY + return mode; +} + +template +inline void* nt_create_file_common(void* directory, win32::nt::unicode_string* relative_path, nt_open_mode const& mode) +{ + win32::security_attributes sec_attr{sizeof(win32::security_attributes),nullptr,true}; + win32::nt::object_attributes obj{.Length=sizeof(win32::nt::object_attributes), + .RootDirectory=directory, + .ObjectName=relative_path, + .Attributes=mode.ObjAttributes, + .SecurityDescriptor=mode.ObjAttributes&0x00000002?__builtin_addressof(sec_attr):nullptr, + .SecurityQualityOfService=nullptr + }; + void* handle; + win32::nt::io_status_block block; + auto const status{win32::nt::nt_create_file( + __builtin_addressof(handle),mode.DesiredAccess,__builtin_addressof(obj),__builtin_addressof(block),nullptr,mode.FileAttributes, + mode.ShareAccess,mode.CreateDisposition,mode.CreateOptions,nullptr,0u)}; + if(status) + throw_nt_error(status); + return handle; +} + +template +struct nt_create_callback +{ + nt_open_mode const& mode; +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif + void* operator()(void* directory_handle,win32::nt::unicode_string* relative_path) const + { + return nt_create_file_common(directory_handle,relative_path,mode); //get rid of this pointer + } +}; + +template +inline void* nt_family_create_file_impl(char16_t const* filename_cstr,open_mode_perms ompm) +{ + return ::fast_io::win32::nt::details::nt_call_invoke_without_directory_handle_impl( + filename_cstr, + nt_create_callback{::fast_io::win32::nt::details::calculate_nt_open_mode(ompm)}); +} + +template +struct nt_family_open_file_parameter +{ + open_mode_perms ompm{}; +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif + inline void* operator()(char16_t const* filename_cstr) + { + return nt_family_create_file_impl(filename_cstr,ompm); + } +}; + +template +requires (::fast_io::constructible_to_os_c_str) +inline void* nt_create_file_impl(T const& t,open_mode_perms ompm) +{ + return nt_api_common(t,nt_family_open_file_parameter{ompm}); +} + +template +inline void* nt_family_create_file_at_impl(void* directory_handle,char16_t const* filename_c_str,std::size_t filename_c_str_len,open_mode_perms md) +{ + if constexpr(kernel) + { + return ::fast_io::win32::nt::details::nt_call_kernel_callback(directory_handle,filename_c_str,filename_c_str_len, + nt_create_callback{::fast_io::win32::nt::details::calculate_nt_open_mode(md)}); + } + else + { + return ::fast_io::win32::nt::details::nt_call_callback(directory_handle,filename_c_str,filename_c_str_len, + nt_create_callback{::fast_io::win32::nt::details::calculate_nt_open_mode(md)}); + } +} + +template +inline void* nt_family_create_file_fs_dirent_impl(void* directory_handle,char16_t const* filename_c_str,std::size_t filename_c_str_len,open_mode_perms md) +{ + using char16_may_alias_const_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = char16_t const*; + return ::fast_io::win32::nt::details::nt_call_kernel_fs_dirent_callback(directory_handle, + reinterpret_cast(filename_c_str),filename_c_str_len, + nt_create_callback{::fast_io::win32::nt::details::calculate_nt_open_mode(md)}); +} + +template +inline void* nt_family_create_file_kernel_impl(char16_t const* filename_cstr,std::size_t filename_c_str_len,open_mode_perms ompm) +{ + return ::fast_io::win32::nt::details::nt_call_kernel_nodir_callback( + filename_cstr,filename_c_str_len, + nt_create_callback{::fast_io::win32::nt::details::calculate_nt_open_mode(ompm)}); +} + +template +struct nt_family_open_file_kernel_parameter +{ + open_mode_perms ompm{}; +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif + inline void* operator()(char16_t const* filename_cstr,std::size_t filename_c_str_len) + { + return nt_family_create_file_kernel_impl(filename_cstr,filename_c_str_len,ompm); + } +}; + +template +requires (::fast_io::constructible_to_os_c_str) +inline void* nt_create_file_kernel_impl(T const& t,open_mode_perms op) +{ + return nt_api_common(t,nt_family_open_file_kernel_parameter{op}); +} + +template +struct nt_family_open_file_at_parameter +{ + void* directory_handle{}; + open_mode_perms ompm{}; +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif + inline void* operator()(char16_t const* filename_cstr,std::size_t filename_c_str_len) + { + return nt_family_create_file_at_impl(directory_handle,filename_cstr,filename_c_str_len,ompm); + } +}; + +template +requires (::fast_io::constructible_to_os_c_str) +inline void* nt_create_file_at_impl(void* directory_handle,T const& t,open_mode_perms op) +{ + return nt_api_common(t,nt_family_open_file_at_parameter{directory_handle,op}); +} + +template +inline std::size_t nt_read_impl(void* __restrict handle,void* __restrict begin,std::size_t size) +{ + if constexpr(4(UINT_LEAST32_MAX)(UINT_LEAST32_MAX); + win32::nt::io_status_block block; //some poeple in zwclose7 forum said we do not need to initialize io_status_block + auto const status{win32::nt::nt_read_file(handle,nullptr,nullptr,nullptr, + __builtin_addressof(block), begin, static_cast(size), nullptr, nullptr)}; + if(status) + throw_nt_error(status); + return block.Information; +} + +template +inline std::size_t nt_write_impl(void* __restrict handle,void const* __restrict begin,std::size_t size) +{ + if constexpr(4(UINT_LEAST32_MAX)) + to_write_this_round=static_cast(size); + win32::nt::io_status_block block; //some poeple in zwclose7 forum said we do not need to initialize io_status_block + auto const status{win32::nt::nt_write_file(handle,nullptr,nullptr,nullptr, + __builtin_addressof(block), begin, to_write_this_round, nullptr, nullptr)}; + if(status) + throw_nt_error(status); + std::uint_least32_t number_of_bytes_written{static_cast(block.Information)}; + written+=number_of_bytes_written; + if(number_of_bytes_written(handle,nullptr,nullptr,nullptr, + __builtin_addressof(block), begin, static_cast(size), nullptr, nullptr)}; + if(status) + throw_nt_error(status); + return block.Information; + } +} + +template +inline io_scatter_status_t nt_scatter_read_impl(void* __restrict handle,io_scatter_t const* scatters,std::size_t n) +{ + std::size_t total_size{}; + for(std::size_t i{};i!=n;++i) + { + std::size_t pos_in_span{nt_read_impl(handle,const_cast(scatters[i].base),scatters[i].len)}; + total_size+=pos_in_span; + if(pos_in_span +inline io_scatter_status_t nt_scatter_write_impl(void* __restrict handle,io_scatter_t const* scatters,std::size_t n) +{ + std::size_t total_size{}; + for(std::size_t i{};i!=n;++i) + { + std::size_t written{nt_write_impl(handle,scatters[i].base,scatters[i].len)}; + total_size+=written; + if(scatters[i].len(value)}; +} + +#if !defined(__CYGWIN__) && !defined(__WINE__) && !defined(__BIONIC__) +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline nt_at_entry at_fdcwd() noexcept +{ + return nt_at_fdcwd(); +} +#endif + +template +struct nt_family_at_entry:nt_at_entry +{ + using nt_at_entry::native_handle_type; + explicit constexpr nt_family_at_entry() noexcept=default; + explicit constexpr nt_family_at_entry(void* mhandle) noexcept:nt_at_entry{mhandle}{} +}; + +struct nt_fs_dirent +{ + void* handle{}; + ::fast_io::manipulators::basic_os_c_str_with_known_size filename{}; +}; + +using zw_at_entry=nt_family_at_entry; + +template +class basic_win32_family_io_observer; + +template +requires (family==nt_family::nt||family==nt_family::zw) +class basic_nt_family_io_observer +{ +public: + using native_handle_type = void*; + using char_type = ch_type; + native_handle_type handle{}; + constexpr native_handle_type native_handle() const noexcept + { + return handle; + } + explicit constexpr operator bool() const noexcept + { + return handle!=nullptr; + } + template + explicit operator basic_win32_family_io_observer() const noexcept + { + return basic_win32_family_io_observer{reinterpret_cast(handle)}; + } + template + constexpr operator basic_nt_family_io_observer() const noexcept + { + return basic_nt_family_io_observer{handle}; + } + constexpr native_handle_type release() noexcept + { + auto temp{handle}; + handle=nullptr; + return temp; + } +}; + +#if __cpp_lib_three_way_comparison >= 201907L + +template +inline constexpr bool operator==(basic_nt_family_io_observer a,basic_nt_family_io_observer b) noexcept +{ + return a.handle==b.handle; +} + +template +inline constexpr auto operator<=>(basic_nt_family_io_observer a,basic_nt_family_io_observer b) noexcept +{ + return a.handle<=>b.handle; +} + +#endif + +template +inline constexpr auto at(basic_nt_family_io_observer niob) noexcept +{ + if constexpr(family==nt_family::nt) + return nt_at_entry{niob.handle}; + else + return nt_family_at_entry{niob.handle}; +} + +template +inline constexpr basic_nt_family_io_observer io_value_handle(basic_nt_family_io_observer other) noexcept +{ + return other; +} + +template +[[nodiscard]] inline Iter read(basic_nt_family_io_observer obs,Iter begin,Iter end) +{ + return begin+win32::nt::details::nt_read_impl(obs.handle,::std::to_address(begin),static_cast(end-begin)*sizeof(*begin))/sizeof(*begin); +} + +template +inline Iter write(basic_nt_family_io_observer obs,Iter cbegin,Iter cend) +{ + return cbegin+win32::nt::details::nt_write_impl(obs.handle,::std::to_address(cbegin),static_cast(cend-cbegin)*sizeof(*cbegin))/sizeof(*cbegin); +} + +template +inline io_scatter_status_t scatter_read(basic_nt_family_io_observer obs,io_scatters_t sp) +{ + return win32::nt::details::nt_scatter_read_impl(obs.handle,sp.base,sp.len); +} + +template +inline io_scatter_status_t scatter_write(basic_nt_family_io_observer obs,io_scatters_t sp) +{ + return win32::nt::details::nt_scatter_write_impl(obs.handle,sp.base,sp.len); +} + +namespace win32::nt::details +{ + +template +inline void nt_flush_impl(void* handle) +{ + win32::nt::io_status_block block; + std::uint_least32_t status{win32::nt::nt_flush_buffers_file(handle,__builtin_addressof(block))}; + if(status) + throw_nt_error(status); +} + +template +inline void nt_data_sync_impl(void* handle,data_sync_flags flags [[maybe_unused]]) +{ +#if _WIN32_WINNT >= 0x0602 || WINVER >= 0x0602 +/* +NtFlushBuffersFileEx and ZwFlushBuffersFileEx are only provided since windows 8 +*/ + win32::nt::io_status_block block; + std::uint_least32_t status{win32::nt::nt_flush_buffers_file_ex(handle,static_cast(flags),nullptr,0u,__builtin_addressof(block))}; + if(status) + throw_nt_error(status); +#else + nt_flush_impl(handle); +#endif +} + +} + +template +inline void flush(basic_nt_family_io_observer ntiob) +{ + win32::nt::details::nt_flush_impl(ntiob.handle); +} + +template +inline void data_sync(basic_nt_family_io_observer ntiob,data_sync_flags flags) +{ + win32::nt::details::nt_data_sync_impl(ntiob.handle,flags); +} + +namespace win32::nt::details +{ +struct nt_file_position_status +{ + ::std::uint_least32_t status; + ::std::int_least64_t file_position; +}; + +template +inline nt_file_position_status nt_get_file_position_impl(void* __restrict handle,::std::int_least64_t offset,seekdir s) +{ + std::uint_least64_t file_position{static_cast(offset)}; + win32::nt::io_status_block block; + switch(s) + { + case seekdir::cur: + { + std::uint_least64_t fps{}; + auto status{win32::nt::nt_query_information_file(handle, + __builtin_addressof(block), + __builtin_addressof(fps), + static_cast<::std::uint_least32_t>(sizeof(std::uint_least64_t)), + win32::nt::file_information_class::FilePositionInformation)}; + if(status) + return {status}; + file_position+=fps; + } + break; + case seekdir::end: + { + win32::nt::file_standard_information fsi; + auto status{win32::nt::nt_query_information_file(handle, + __builtin_addressof(block), + __builtin_addressof(fsi), + static_cast<::std::uint_least32_t>(sizeof(win32::nt::file_standard_information)), + win32::nt::file_information_class::FileStandardInformation)}; + if(status) + return {status}; + file_position+=fsi.end_of_file; + } + break; + default:; + } + if(static_cast<::std::uint_least64_t>(std::numeric_limits<::std::int_least64_t>::max())(file_position)}; +} + +template +inline std::uint_least64_t nt_seek64_impl(void* __restrict handle,std::int_least64_t offset,seekdir s) +{ + auto [status,file_position]=nt_get_file_position_impl(handle,offset,s); + if(status) + throw_nt_error(status); + win32::nt::io_status_block block; + status=win32::nt::nt_set_information_file(handle, + __builtin_addressof(block), + __builtin_addressof(file_position), + sizeof(std::uint_least64_t), + win32::nt::file_information_class::FilePositionInformation); + if(status) + throw_nt_error(status); + return file_position; +} + +template +inline std::uintmax_t nt_seek_impl(void* __restrict handle,std::intmax_t offset,seekdir s) +{ + return static_cast(nt_seek64_impl(handle,static_cast(offset),s)); +} + +template +inline void* nt_dup_impl(void* handle) +{ + void* current_process{reinterpret_cast(static_cast(-1))}; + void* new_handle{}; + auto status{win32::nt::nt_duplicate_object(current_process,handle,current_process,__builtin_addressof(new_handle),0,0x00000002L,2)}; + if(status) + throw_nt_error(status); + return new_handle; +} + +template +inline void* nt_dup2_impl(void* handle,void* newhandle) +{ + auto temp{nt_dup_impl(handle)}; + if(newhandle)[[likely]] + win32::nt::nt_close(newhandle); + return temp; +} + +template +inline void nt_truncate_impl(void* handle,std::uintmax_t newfilesizem) +{ + std::uint_least64_t newfilesize{static_cast(newfilesizem)}; + win32::nt::io_status_block block; + auto status{win32::nt::nt_set_information_file(handle, + __builtin_addressof(block), + __builtin_addressof(newfilesize), + sizeof(std::uint_least64_t), + win32::nt::file_information_class::FileEndOfFileInformation)}; + if(status) + throw_nt_error(status); +} + +template +inline ::std::uint_least32_t nt_family_file_lock_common_impl(void* __restrict handle,flock_request_l64& req,bool failedimmediately) +{ + auto [status,file_position]=nt_get_file_position_impl(handle,req.start,req.whence); + if(status) + { + return status; + } + win32::nt::io_status_block block; + std::int_least64_t len{req.len}; + if(len==0) + { + len=INT_LEAST64_MAX; + } + req.whence = seekdir::beg; + req.start = file_position; + req.len = len; + if(req.type==file_lock_mode::unlock) + { + status=win32::nt::nt_unlock_file(handle,__builtin_addressof(block), + __builtin_addressof(file_position),__builtin_addressof(len),0u); + } + else + { + status=win32::nt::nt_lock_file(handle,nullptr,nullptr,nullptr,__builtin_addressof(block), + __builtin_addressof(file_position),__builtin_addressof(len),0u,failedimmediately,req.type!=file_lock_mode::shared_lock); + } + return status; +} + +template +inline void nt_family_file_unlock_common_impl(void* __restrict handle,flock_request_l64& req) noexcept +{ + auto [status,file_position]=nt_get_file_position_impl(handle,req.start,req.whence); + ::std::int_least64_t len{req.len}; + if(status) + { + file_position=0; + len=0; + } + if(len==0) + { + len=INT_LEAST64_MAX; + } + req.whence = seekdir::beg; + req.start = file_position; + req.len = len; + win32::nt::io_status_block block; + win32::nt::nt_unlock_file(handle,__builtin_addressof(block), + __builtin_addressof(file_position),__builtin_addressof(len),0u); +} + + +template +inline void nt_family_file_lock_common_impl(void* __restrict handle,flock_request_l64& req) +{ + auto status{nt_family_file_lock_common_impl(handle,req,false)}; + if(status) + { + throw_nt_error(status); + } +} + +template +inline void nt_family_file_lock_impl(void* __restrict handle,basic_flock_request& __restrict t) +{ + if constexpr(sizeof(int_type)>=sizeof(::std::int_least64_t)) + { + constexpr int_type mn{std::numeric_limits<::std::int_least64_t>::min()}; + constexpr int_type mx{std::numeric_limits<::std::int_least64_t>::max()}; + if(t.start(handle,t); +} + +template +inline void nt_family_file_unlock_impl(void* __restrict handle,basic_flock_request& __restrict t) +{ + if constexpr(sizeof(int_type)>=sizeof(::std::int_least64_t)) + { + constexpr int_type mn{std::numeric_limits<::std::int_least64_t>::min()}; + constexpr int_type mx{std::numeric_limits<::std::int_least64_t>::max()}; + if(t.start(handle,t); +} + +template +inline bool nt_family_file_try_lock_impl(void* __restrict handle,basic_flock_request& __restrict t) +{ + if constexpr(sizeof(int_type)>=sizeof(::std::int_least64_t)) + { + constexpr int_type mn{std::numeric_limits<::std::int_least64_t>::min()}; + constexpr int_type mx{std::numeric_limits<::std::int_least64_t>::max()}; + if(t.start) + { + return nt_family_file_lock_common_impl(handle,t,true)==0; + } + else + { + static_assert(::std::same_as); + return false; +#if 0 + return nt_family_file_lock_common_impl(handle,flock_request_l64{t.type,t.whence,static_cast<::std::int_least64_t>(t.start),static_cast<::std::int_least64_t>(t.len)},true)==0; +#endif + } +} + +} + +template +inline std::uintmax_t seek(basic_nt_family_io_observer handle,std::intmax_t offset=0,seekdir s=seekdir::cur) +{ + return win32::nt::details::nt_seek_impl(handle.handle,offset,s); +} + +template +inline void truncate(basic_nt_family_io_observer handle,std::uintmax_t newfilesize) +{ + win32::nt::details::nt_truncate_impl(handle.handle,newfilesize); +} +#if 0 +template +inline posix_file_status status(basic_nt_family_io_observer handle) +{ + return win32::win32::details::nt_status_impl(handle.handle); +} +#endif + + +template +struct nt_family_file_lock +{ + void* handle{}; + template + requires (sizeof(int_type)>=sizeof(std::int_least64_t)) + inline void lock(basic_flock_request& __restrict t) + { + ::fast_io::win32::nt::details::nt_family_file_lock_impl(this->handle,t); + } + template + requires (sizeof(int_type)>=sizeof(std::int_least64_t)) + inline void unlock(basic_flock_request& __restrict t) noexcept + { + ::fast_io::win32::nt::details::nt_family_file_unlock_impl(this->handle,t); + } + template + requires (sizeof(int_type)>=sizeof(std::int_least64_t)) + inline bool try_lock(basic_flock_request& __restrict t) noexcept + { + return ::fast_io::win32::nt::details::nt_family_file_try_lock_impl(this->handle,t); + } +}; + +using nt_file_lock = nt_family_file_lock; +using zw_file_lock = nt_family_file_lock; + +template +inline constexpr nt_family_file_lock file_lock(basic_nt_family_io_observer niob) noexcept +{ + return {niob}; +} + +template +struct +#if __has_cpp_attribute(clang::trivially_relocatable) +[[clang::trivially_relocatable]] +#endif +nt_family_file_factory +{ + using native_handle_type=void*; + void* handle{}; + explicit constexpr nt_family_file_factory(void* hd) noexcept:handle(hd){}; + nt_family_file_factory(nt_family_file_factory const&)=delete; + nt_family_file_factory& operator=(nt_family_file_factory const&)=delete; + ~nt_family_file_factory() + { + if(handle)[[likely]] + win32::nt::nt_close(this->handle); + } +}; + +using nt_file_factory = nt_family_file_factory; +using zw_file_factory = nt_family_file_factory; + +template +class basic_nt_family_file:public basic_nt_family_io_observer +{ +public: + using typename basic_nt_family_io_observer::char_type; + using typename basic_nt_family_io_observer::native_handle_type; + using file_factory_type = nt_family_file_factory; + constexpr basic_nt_family_file() noexcept=default; + constexpr basic_nt_family_file(basic_nt_family_io_observer) noexcept=delete; + constexpr basic_nt_family_file& operator=(basic_nt_family_io_observer) noexcept=delete; + + template + requires std::same_as> + explicit constexpr basic_nt_family_file(native_hd hd) noexcept:basic_nt_family_io_observer{hd}{} + constexpr basic_nt_family_file(decltype(nullptr)) noexcept = delete; + explicit constexpr basic_nt_family_file(nt_family_file_factory&& hd) noexcept:basic_nt_family_io_observer{hd} + { + hd.handle=nullptr; + } + explicit basic_nt_family_file(io_dup_t,basic_nt_family_io_observer wiob): + basic_nt_family_io_observer{win32::nt::details::nt_dup_impl(wiob.handle)} + {} + explicit basic_nt_family_file(nt_fs_dirent fsdirent,open_mode om,perms pm=static_cast(436)): + basic_nt_family_io_observer{win32::nt::details::nt_family_create_file_fs_dirent_impl(fsdirent.handle,fsdirent.filename.c_str(),fsdirent.filename.size(),{om,pm})}{} + template<::fast_io::constructible_to_os_c_str T> + explicit basic_nt_family_file(T const& t,open_mode om,perms pm=static_cast(436)):basic_nt_family_io_observer{::fast_io::win32::nt::details::nt_create_file_impl(t,{om,pm})}{} + template<::fast_io::constructible_to_os_c_str T> + explicit basic_nt_family_file(nt_at_entry ent,T const& t,open_mode om,perms pm=static_cast(436)):basic_nt_family_io_observer{::fast_io::win32::nt::details::nt_create_file_at_impl(ent.handle,t,{om,pm})}{} + + template<::fast_io::constructible_to_os_c_str T> + explicit basic_nt_family_file(io_kernel_t,T const& t,open_mode om,perms pm=static_cast(436)):basic_nt_family_io_observer{::fast_io::win32::nt::details::nt_create_file_kernel_impl(t,{om,pm})}{} + template<::fast_io::constructible_to_os_c_str T> + explicit basic_nt_family_file(io_kernel_t,nt_at_entry ent,T const& t,open_mode om,perms pm=static_cast(436)):basic_nt_family_io_observer{::fast_io::win32::nt::details::nt_create_file_at_impl(ent.handle,t,{om,pm})}{} + + template<::fast_io::constructible_to_os_c_str T> + constexpr bool open(nt_family_file_factory&& hd) noexcept + { + bool ok{this->handle==nullptr}; + if(ok) + { + this->handle=hd.handle; + hd.handle=nullptr; + } + return ok; + } + bool open(io_dup_t,basic_nt_family_io_observer wiob) + { + bool ok{this->handle==nullptr}; + if(ok) + { + this->handle=win32::nt::details::nt_dup_impl(wiob.handle); + } + return ok; + } + bool open(nt_fs_dirent fsdirent,open_mode om,perms pm=static_cast(436)) + { + bool ok{this->handle==nullptr}; + if(ok) + { + this->handle=win32::nt::details::nt_family_create_file_fs_dirent_impl(fsdirent.handle,fsdirent.filename.c_str(),fsdirent.filename.size(),{om,pm}); + } + return ok; + } + template<::fast_io::constructible_to_os_c_str T> + bool open(T const& t,open_mode om,perms pm=static_cast(436)) + { + bool ok{this->handle==nullptr}; + if(ok) + { + this->handle=::fast_io::win32::nt::details::nt_create_file_impl(t,{om,pm}); + } + return ok; + } + template<::fast_io::constructible_to_os_c_str T> + bool open(nt_at_entry ent,T const& t,open_mode om,perms pm=static_cast(436)) + { + bool ok{this->handle==nullptr}; + if(ok) + { + this->handle=::fast_io::win32::nt::details::nt_create_file_at_impl(ent.handle,t,{om,pm}); + } + return ok; + } + template<::fast_io::constructible_to_os_c_str T> + bool open(io_kernel_t,T const& t,open_mode om,perms pm=static_cast(436)) + { + bool ok{this->handle==nullptr}; + if(ok) + { + this->handle=::fast_io::win32::nt::details::nt_create_file_kernel_impl(t,{om,pm}); + } + return ok; + } + template<::fast_io::constructible_to_os_c_str T> + bool open(io_kernel_t,nt_at_entry ent,T const& t,open_mode om,perms pm=static_cast(436)) + { + bool ok{this->handle==nullptr}; + if(ok) + { + this->handle=::fast_io::win32::nt::details::nt_create_file_at_impl(ent.handle,t,{om,pm}); + } + return ok; + } + void close() + { + if(this->handle)[[likely]] + { + auto status{win32::nt::nt_close(this->handle)}; + this->handle=nullptr;//POSIX standard says we should never call close(2) again even close syscall fails + if(status)[[unlikely]] + throw_nt_error(status); + } + } + void reset(native_handle_type newhandle=nullptr) noexcept + { + if(this->handle)[[likely]] + win32::nt::nt_close(this->handle); + this->handle=newhandle; + } + template<::fast_io::constructible_to_os_c_str T> + constexpr void reopen(nt_family_file_factory&& hd) noexcept + { + if(this->handle)[[likely]] + win32::nt::nt_close(this->handle); + this->handle=hd.handle; + hd.handle=nullptr; + } + void reopen(io_dup_t,basic_nt_family_io_observer wiob) + { + this->reset(win32::nt::details::nt_dup_impl(wiob.handle)); + } + void reopen(nt_fs_dirent fsdirent,open_mode om,perms pm=static_cast(436)) + { + this->reset(win32::nt::details::nt_family_create_file_fs_dirent_impl(fsdirent.handle,fsdirent.filename.c_str(),fsdirent.filename.size(),{om,pm})); + } + template<::fast_io::constructible_to_os_c_str T> + void reopen(T const& t,open_mode om,perms pm=static_cast(436)) + { + this->reset(::fast_io::win32::nt::details::nt_create_file_impl(t,{om,pm})); + } + template<::fast_io::constructible_to_os_c_str T> + void reopen(nt_at_entry ent,T const& t,open_mode om,perms pm=static_cast(436)) + { + this->reset(::fast_io::win32::nt::details::nt_create_file_at_impl(ent.handle,t,{om,pm})); + } + template<::fast_io::constructible_to_os_c_str T> + void reopen(io_kernel_t,T const& t,open_mode om,perms pm=static_cast(436)) + { + this->reset(::fast_io::win32::nt::details::nt_create_file_kernel_impl(t,{om,pm})); + } + template<::fast_io::constructible_to_os_c_str T> + void reopen(io_kernel_t,nt_at_entry ent,T const& t,open_mode om,perms pm=static_cast(436)) + { + this->reset(::fast_io::win32::nt::details::nt_create_file_at_impl(ent.handle,t,{om,pm})); + } + basic_nt_family_file(basic_nt_family_file const& other): + basic_nt_family_io_observer(win32::nt::details::nt_dup_impl(other.handle)) + {} + basic_nt_family_file& operator=(basic_nt_family_file const& other) + { + this->handle=win32::nt::details::nt_dup2_impl(other.handle,this->handle); + return *this; + } + constexpr basic_nt_family_file(basic_nt_family_file&& __restrict other) noexcept: + basic_nt_family_io_observer{other.handle} + { + other.handle=nullptr; + } + basic_nt_family_file& operator=(basic_nt_family_file&& __restrict other) noexcept + { + if(this->handle)[[likely]] + win32::nt::nt_close(this->handle); + this->handle = other.handle; + other.handle=nullptr; + return *this; + } + ~basic_nt_family_file() + { + if(this->handle)[[likely]] + win32::nt::nt_close(this->handle); + } +}; + +template +using basic_nt_io_observer=basic_nt_family_io_observer; + +template +using basic_nt_file=basic_nt_family_file; + +using nt_io_observer=basic_nt_io_observer; +using nt_file=basic_nt_file; + +using wnt_io_observer=basic_nt_io_observer; +using wnt_file=basic_nt_file; + +using u8nt_io_observer=basic_nt_io_observer; +using u8nt_file=basic_nt_file; + +using u16nt_io_observer=basic_nt_io_observer; +using u16nt_file=basic_nt_file; + +using u32nt_io_observer=basic_nt_io_observer; +using u32nt_file=basic_nt_file; + +template +inline basic_nt_io_observer nt_stdin() noexcept +{ + return {fast_io::win32::GetStdHandle(static_cast(-10))}; +} + +template +inline basic_nt_io_observer nt_stdout() noexcept +{ + return {fast_io::win32::GetStdHandle(static_cast(-11))}; +} + +template +inline basic_nt_io_observer nt_stderr() noexcept +{ + return {fast_io::win32::GetStdHandle(static_cast(-12))}; +} + + +template +using basic_zw_io_observer=basic_nt_family_io_observer; + +template +using basic_zw_file=basic_nt_family_file; + +using zw_io_observer=basic_zw_io_observer; +using zw_file=basic_zw_file; + +using wzw_io_observer=basic_zw_io_observer; +using wzw_file=basic_zw_file; + +using u8zw_io_observer=basic_zw_io_observer; +using u8zw_file=basic_zw_file; + +using u16zw_io_observer=basic_zw_io_observer; +using u16zw_file=basic_zw_file; + +using u32zw_io_observer=basic_zw_io_observer; +using u32zw_file=basic_zw_file; + +template +inline basic_zw_io_observer zw_stdin() noexcept +{ + return {fast_io::win32::GetStdHandle(static_cast(-10))}; +} + +template +inline basic_zw_io_observer zw_stdout() noexcept +{ + return {fast_io::win32::GetStdHandle(static_cast(-11))}; +} + +template +inline basic_zw_io_observer zw_stderr() noexcept +{ + return {fast_io::win32::GetStdHandle(static_cast(-12))}; +} + +#if 0 +template +inline basic_nt_io_observer native_stdin() noexcept +{ + return {fast_io::win32::GetStdHandle(-10)}; +} +template +inline basic_nt_io_observer native_stdout() noexcept +{ + return {fast_io::win32::GetStdHandle(-11)}; +} +template +inline basic_nt_io_observer native_stderr() noexcept +{ + return {fast_io::win32::GetStdHandle(-12)}; +} +#endif + +namespace freestanding +{ +template +struct is_trivially_relocatable> +{ + inline static constexpr bool value = true; +}; + +template +struct is_zero_default_constructible> +{ + inline static constexpr bool value = true; +}; +} + +} diff --git a/src/fast_io/include/fast_io_hosted/platforms/nt/impl.h b/src/fast_io/include/fast_io_hosted/platforms/nt/impl.h new file mode 100644 index 0000000..679ddbe --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/nt/impl.h @@ -0,0 +1,7 @@ +#pragma once + +#include"nt_definitions.h" +#include"nt_linker.h" +#include"rtl_unicode_string_unique_ptr.h" +#include"nt_code.h" +#include"nt_path.h" \ No newline at end of file diff --git a/src/fast_io/include/fast_io_hosted/platforms/nt/nt_code.h b/src/fast_io/include/fast_io_hosted/platforms/nt/nt_code.h new file mode 100644 index 0000000..6ddfb39 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/nt/nt_code.h @@ -0,0 +1,88 @@ +#pragma once + +namespace fast_io +{ + +struct nt_code +{ + std::uint_least32_t ntstatus{}; +}; + +inline constexpr std::uintptr_t domain_define(error_type_t) noexcept +{ + if constexpr(sizeof(std::uintptr_t)<=sizeof(std::uint_least16_t)) + return 63612u; + else if constexpr(sizeof(std::uintptr_t)<=sizeof(std::uint_least32_t)) + return 3776340491u; + else + return 17311375720795711021ULL; +} + +inline constexpr std::uintptr_t nt_domain_value{domain_define(error_type)}; + +[[noreturn]] inline void throw_nt_error([[maybe_unused]] std::uint_least32_t err) +{ +#ifdef __cpp_exceptions +#if defined(_MSC_VER) && (!defined(_HAS_EXCEPTIONS) || _HAS_EXCEPTIONS == 0) + fast_terminate(); +#else + throw ::fast_io::error{nt_domain_value,static_cast(err)}; +#endif +#else + fast_terminate(); +#endif +} + +namespace details +{ +inline constexpr ::fast_io::manipulators::scalar_flags nt_errorflags{.base=16,.full=true,.floating=::fast_io::manipulators::floating_format::fixed}; + +template +requires (enable) +inline constexpr char_type* print_reserve_nt_error_impl(char_type* iter,std::uint_least32_t ntstatus) noexcept +{ + if constexpr(std::same_as) + iter=copy_string_literal("[nt:0x",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(L"[nt:0x",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(u"[nt:0x",iter); + else if constexpr(std::same_as) + iter=copy_string_literal(U"[nt:0x",iter); + else + iter=copy_string_literal(u8"[nt:0x",iter); + using namespace ::fast_io::manipulators; + iter=print_reserve_define(io_reserve_type>,iter,{ntstatus}); + *iter=char_literal_v; + ++iter; + return print_reserve_define_win32_error_impl(iter,win32::nt::rtl_nt_status_to_dos_error(ntstatus)); +} + +} + +template +inline constexpr std::size_t print_reserve_size(io_reserve_type_t) noexcept +{ + using namespace ::fast_io::manipulators; + constexpr std::size_t full_size(print_reserve_size(io_reserve_type>)+print_reserve_size(io_reserve_type)); + if constexpr(std::same_as) + { + return full_size+::fast_io::details::string_literal_size("[nt:0x]"); + } + else if constexpr(std::same_as) + { + return full_size+::fast_io::details::string_literal_size(L"[nt:0x]"); + } + else + { + return full_size+::fast_io::details::string_literal_size(u8"[nt:0x]"); + } +} + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define(io_reserve_type_t, char_type* iter,nt_code e) noexcept +{ + return ::fast_io::details::print_reserve_nt_error_impl(iter,e.ntstatus); +} + +} diff --git a/src/fast_io/include/fast_io_hosted/platforms/nt/nt_definitions.h b/src/fast_io/include/fast_io_hosted/platforms/nt/nt_definitions.h new file mode 100644 index 0000000..bd69c8c --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/nt/nt_definitions.h @@ -0,0 +1,606 @@ +#pragma once + +namespace fast_io::win32::nt +{ + +struct ansi_string +{ +std::uint_least16_t Length; +std::uint_least16_t MaximumLength; +char* Buffer; +}; + +struct unicode_string +{ +std::uint_least16_t Length; +std::uint_least16_t MaximumLength; +char16_t* Buffer; +}; + +struct object_attributes +{ +std::uint_least32_t Length; +void* RootDirectory; +unicode_string *ObjectName; +std::uint_least32_t Attributes; +void* SecurityDescriptor; +void* SecurityQualityOfService; +}; + +struct io_status_block +{ +union +{ + std::uint_least32_t Status; + void* Pointer; +} DUMMYUNIONNAME; +std::uintptr_t Information; +}; + +using pio_apc_routine = void (*)(void*,io_status_block*,std::uint_least32_t) noexcept; + +struct rtlp_curdir_def +{ + std::int_least32_t ref_count; + void* handle; +}; + +struct rtl_relative_name_u +{ + unicode_string relative_name; + void* containing_directory; + rtlp_curdir_def cur_dir_ref; +}; + +/* +https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ne-wdm-_file_information_class +*/ + +enum class file_information_class +{ +FileDirectoryInformation = 1, +FileFullDirectoryInformation, // 2 +FileBothDirectoryInformation, // 3 +FileBasicInformation, // 4 +FileStandardInformation, // 5 +FileInternalInformation, // 6 +FileEaInformation, // 7 +FileAccessInformation, // 8 +FileNameInformation, // 9 +FileRenameInformation, // 10 +FileLinkInformation, // 11 +FileNamesInformation, // 12 +FileDispositionInformation, // 13 +FilePositionInformation, // 14 +FileFullEaInformation, // 15 +FileModeInformation, // 16 +FileAlignmentInformation, // 17 +FileAllInformation, // 18 +FileAllocationInformation, // 19 +FileEndOfFileInformation, // 20 +FileAlternateNameInformation, // 21 +FileStreamInformation, // 22 +FilePipeInformation, // 23 +FilePipeLocalInformation, // 24 +FilePipeRemoteInformation, // 25 +FileMailslotQueryInformation, // 26 +FileMailslotSetInformation, // 27 +FileCompressionInformation, // 28 +FileObjectIdInformation, // 29 +FileCompletionInformation, // 30 +FileMoveClusterInformation, // 31 +FileQuotaInformation, // 32 +FileReparsePointInformation, // 33 +FileNetworkOpenInformation, // 34 +FileAttributeTagInformation, // 35 +FileTrackingInformation, // 36 +FileIdBothDirectoryInformation, // 37 +FileIdFullDirectoryInformation, // 38 +FileValidDataLengthInformation, // 39 +FileShortNameInformation, // 40 +FileIoCompletionNotificationInformation, // 41 +FileIoStatusBlockRangeInformation, // 42 +FileIoPriorityHintInformation, // 43 +FileSfioReserveInformation, // 44 +FileSfioVolumeInformation, // 45 +FileHardLinkInformation, // 46 +FileProcessIdsUsingFileInformation, // 47 +FileNormalizedNameInformation, // 48 +FileNetworkPhysicalNameInformation, // 49 +FileIdGlobalTxDirectoryInformation, // 50 +FileIsRemoteDeviceInformation, // 51 +FileUnusedInformation, // 52 +FileNumaNodeInformation, // 53 +FileStandardLinkInformation, // 54 +FileRemoteProtocolInformation, // 55 + + // + // These are special versions of these operations (defined earlier) + // which can be used by kernel mode drivers only to bypass security + // access checks for Rename and HardLink operations. These operations + // are only recognized by the IOManager, a file system should never + // receive these. + // + +FileRenameInformationBypassAccessCheck, // 56 +FileLinkInformationBypassAccessCheck, // 57 + + // + // End of special information classes reserved for IOManager. + // + +FileVolumeNameInformation, // 58 +FileIdInformation, // 59 +FileIdExtdDirectoryInformation, // 60 +FileReplaceCompletionInformation, // 61 +FileHardLinkFullIdInformation, // 62 +FileIdExtdBothDirectoryInformation, // 63 +FileDispositionInformationEx, // 64 +FileRenameInformationEx, // 65 +FileRenameInformationExBypassAccessCheck, // 66 +FileDesiredStorageClassInformation, // 67 +FileStatInformation, // 68 +FileMemoryPartitionInformation, // 69 +FileStatLxInformation, // 70 +FileCaseSensitiveInformation, // 71 +FileLinkInformationEx, // 72 +FileLinkInformationExBypassAccessCheck, // 73 +FileStorageReserveIdInformation, // 74 +FileCaseSensitiveInformationForceAccessCheck, // 75 + +}; + + +struct file_full_dir_information +{ +std::uint_least32_t NextEntryOffset; +std::uint_least32_t FileIndex; +std::int_least64_t CreationTime; +std::int_least64_t LastAccessTime; +std::int_least64_t LastWriteTime; +std::int_least64_t ChangeTime; +std::int_least64_t EndOfFile; +std::int_least64_t AllocationSize; +std::uint_least32_t FileAttributes; +std::uint_least32_t FileNameLength; +std::uint_least32_t EaSize; +char16_t FileName[1]; +}; + +struct file_both_dir_information +{ +std::uint_least32_t NextEntryOffset; +std::uint_least32_t FileIndex; +std::int_least64_t CreationTime; +std::int_least64_t LastAccessTime; +std::int_least64_t LastWriteTime; +std::int_least64_t ChangeTime; +std::int_least64_t EndOfFile; +std::int_least64_t AllocationSize; +std::uint_least32_t FileAttributes; +std::uint_least32_t FileNameLength; +std::uint_least32_t EaSize; +char ShortNameLength; +char16_t ShortName[12]; +char16_t FileName[1]; +}; + + +union dir_information +{ +void* DirInfo; +file_full_dir_information* FullDirInfo; +file_both_dir_information* BothDirInfo; +}; + +struct file_standard_information +{ +std::uint_least64_t allocation_size; +std::uint_least64_t end_of_file; +std::uint_least32_t number_of_links; +int delete_pending; +int directory; +}; + +enum class process_information_class +{ +ProcessBasicInformation, // q: PROCESS_BASIC_INFORMATION, PROCESS_EXTENDED_BASIC_INFORMATION +ProcessQuotaLimits, // qs: QUOTA_LIMITS, QUOTA_LIMITS_EX +ProcessIoCounters, // q: IO_COUNTERS +ProcessVmCounters, // q: VM_COUNTERS, VM_COUNTERS_EX, VM_COUNTERS_EX2 +ProcessTimes, // q: KERNEL_USER_TIMES +ProcessBasePriority, // s: KPRIORITY +ProcessRaisePriority, // s: ULONG +ProcessDebugPort, // q: HANDLE +ProcessExceptionPort, // s: PROCESS_EXCEPTION_PORT +ProcessAccessToken, // s: PROCESS_ACCESS_TOKEN +ProcessLdtInformation, // qs: PROCESS_LDT_INFORMATION // 10 +ProcessLdtSize, // s: PROCESS_LDT_SIZE +ProcessDefaultHardErrorMode, // qs: ULONG +ProcessIoPortHandlers, // (kernel-mode only) // PROCESS_IO_PORT_HANDLER_INFORMATION +ProcessPooledUsageAndLimits, // q: POOLED_USAGE_AND_LIMITS +ProcessWorkingSetWatch, // q: PROCESS_WS_WATCH_INFORMATION[]; s: void +ProcessUserModeIOPL, // qs: ULONG (requires SeTcbPrivilege) +ProcessEnableAlignmentFaultFixup, // s: BOOLEAN +ProcessPriorityClass, // qs: PROCESS_PRIORITY_CLASS +ProcessWx86Information, // qs: ULONG (requires SeTcbPrivilege) (VdmAllowed) +ProcessHandleCount, // q: ULONG, PROCESS_HANDLE_INFORMATION // 20 +ProcessAffinityMask, // s: KAFFINITY +ProcessPriorityBoost, // qs: ULONG +ProcessDeviceMap, // qs: PROCESS_DEVICEMAP_INFORMATION, PROCESS_DEVICEMAP_INFORMATION_EX +ProcessSessionInformation, // q: PROCESS_SESSION_INFORMATION +ProcessForegroundInformation, // s: PROCESS_FOREGROUND_BACKGROUND +ProcessWow64Information, // q: ULONG_PTR +ProcessImageFileName, // q: UNICODE_STRING +ProcessLUIDDeviceMapsEnabled, // q: ULONG +ProcessBreakOnTermination, // qs: ULONG +ProcessDebugObjectHandle, // q: HANDLE // 30 +ProcessDebugFlags, // qs: ULONG +ProcessHandleTracing, // q: PROCESS_HANDLE_TRACING_QUERY; s: size 0 disables, otherwise enables +ProcessIoPriority, // qs: IO_PRIORITY_HINT +ProcessExecuteFlags, // qs: ULONG +ProcessResourceManagement, // ProcessTlsInformation // PROCESS_TLS_INFORMATION +ProcessCookie, // q: ULONG +ProcessImageInformation, // q: SECTION_IMAGE_INFORMATION +ProcessCycleTime, // q: PROCESS_CYCLE_TIME_INFORMATION // since VISTA +ProcessPagePriority, // q: PAGE_PRIORITY_INFORMATION +ProcessInstrumentationCallback, // qs: PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION // 40 +ProcessThreadStackAllocation, // s: PROCESS_STACK_ALLOCATION_INFORMATION, PROCESS_STACK_ALLOCATION_INFORMATION_EX +ProcessWorkingSetWatchEx, // q: PROCESS_WS_WATCH_INFORMATION_EX[] +ProcessImageFileNameWin32, // q: UNICODE_STRING +ProcessImageFileMapping, // q: HANDLE (input) +ProcessAffinityUpdateMode, // qs: PROCESS_AFFINITY_UPDATE_MODE +ProcessMemoryAllocationMode, // qs: PROCESS_MEMORY_ALLOCATION_MODE +ProcessGroupInformation, // q: USHORT[] +ProcessTokenVirtualizationEnabled, // s: ULONG +ProcessConsoleHostProcess, // q: ULONG_PTR // ProcessOwnerInformation +ProcessWindowInformation, // q: PROCESS_WINDOW_INFORMATION // 50 +ProcessHandleInformation, // q: PROCESS_HANDLE_SNAPSHOT_INFORMATION // since WIN8 +ProcessMitigationPolicy, // s: PROCESS_MITIGATION_POLICY_INFORMATION +ProcessDynamicFunctionTableInformation, +ProcessHandleCheckingMode, // qs: ULONG; s: 0 disables, otherwise enables +ProcessKeepAliveCount, // q: PROCESS_KEEPALIVE_COUNT_INFORMATION +ProcessRevokeFileHandles, // s: PROCESS_REVOKE_FILE_HANDLES_INFORMATION +ProcessWorkingSetControl, // s: PROCESS_WORKING_SET_CONTROL +ProcessHandleTable, // q: ULONG[] // since WINBLUE +ProcessCheckStackExtentsMode, +ProcessCommandLineInformation, // q: UNICODE_STRING // 60 +ProcessProtectionInformation, // q: PS_PROTECTION +ProcessMemoryExhaustion, // PROCESS_MEMORY_EXHAUSTION_INFO // since THRESHOLD +ProcessFaultInformation, // PROCESS_FAULT_INFORMATION +ProcessTelemetryIdInformation, // PROCESS_TELEMETRY_ID_INFORMATION +ProcessCommitReleaseInformation, // PROCESS_COMMIT_RELEASE_INFORMATION +ProcessDefaultCpuSetsInformation, +ProcessAllowedCpuSetsInformation, +ProcessSubsystemProcess, +ProcessJobMemoryInformation, // PROCESS_JOB_MEMORY_INFO +ProcessInPrivate, // since THRESHOLD2 // 70 +ProcessRaiseUMExceptionOnInvalidHandleClose, // qs: ULONG; s: 0 disables, otherwise enables +ProcessIumChallengeResponse, +ProcessChildProcessInformation, // PROCESS_CHILD_PROCESS_INFORMATION +ProcessHighGraphicsPriorityInformation, +ProcessSubsystemInformation, // q: SUBSYSTEM_INFORMATION_TYPE // since REDSTONE2 +ProcessEnergyValues, // PROCESS_ENERGY_VALUES, PROCESS_EXTENDED_ENERGY_VALUES +ProcessActivityThrottleState, // PROCESS_ACTIVITY_THROTTLE_STATE +ProcessActivityThrottlePolicy, // PROCESS_ACTIVITY_THROTTLE_POLICY +ProcessWin32kSyscallFilterInformation, +ProcessDisableSystemAllowedCpuSets, // 80 +ProcessWakeInformation, // PROCESS_WAKE_INFORMATION +ProcessEnergyTrackingState, // PROCESS_ENERGY_TRACKING_STATE +ProcessManageWritesToExecutableMemory, // MANAGE_WRITES_TO_EXECUTABLE_MEMORY // since REDSTONE3 +ProcessCaptureTrustletLiveDump, +ProcessTelemetryCoverage, +ProcessEnclaveInformation, +ProcessEnableReadWriteVmLogging, // PROCESS_READWRITEVM_LOGGING_INFORMATION +ProcessUptimeInformation, // PROCESS_UPTIME_INFORMATION +ProcessImageSection, // q: HANDLE +ProcessDebugAuthInformation, // since REDSTONE4 // 90 +ProcessSystemResourceManagement, // PROCESS_SYSTEM_RESOURCE_MANAGEMENT +ProcessSequenceNumber, // q: ULONGLONG +ProcessLoaderDetour, // since REDSTONE5 +ProcessSecurityDomainInformation, // PROCESS_SECURITY_DOMAIN_INFORMATION +ProcessCombineSecurityDomainsInformation, // PROCESS_COMBINE_SECURITY_DOMAINS_INFORMATION +ProcessEnableLogging, // PROCESS_LOGGING_INFORMATION +ProcessLeapSecondInformation, // PROCESS_LEAP_SECOND_INFORMATION +ProcessFiberShadowStackAllocation, // PROCESS_FIBER_SHADOW_STACK_ALLOCATION_INFORMATION // since 19H1 +ProcessFreeFiberShadowStackAllocation, // PROCESS_FREE_FIBER_SHADOW_STACK_ALLOCATION_INFORMATION +ProcessAltSystemCallInformation, // qs: BOOLEAN (kernel-mode only) // since 20H1 // 100 +ProcessDynamicEHContinuationTargets, // PROCESS_DYNAMIC_EH_CONTINUATION_TARGETS_INFORMATION +MaxProcessInfoClass +}; + +struct process_basic_information +{ + std::uint_least32_t ExitStatus; + void* PebBaseAddress; + std::uintptr_t AffinityMask; + std::uint_least32_t BasePriority; + void* UniqueProcessId; + void* InheritedFromUniqueProcessId; +}; + +struct curdir +{ + unicode_string DosPath; + void* Handle; +}; + +struct rtl_drive_letter_curdir +{ + std::uint_least16_t Flags; + std::uint_least16_t Length; + std::uint_least32_t TimeStamp; + unicode_string DosPath; +}; + +inline constexpr std::size_t rtl_max_drive_letters{32}; + +struct client_id +{ + void* hprocess; + void* hthread; +}; + +enum class section_information_class +{ +SectionBasicInformation, +SectionImageInformation, +SectionRelocationInformation, +MaxSectionInfoClass +}; + +struct rtl_critical_section +{ + void* debug_info; + std::int_least32_t lock_count; + std::int_least32_t recursion_count; + void* owning_thread; + void* lock_semaphore; + std::uintptr_t spin_count; +}; + +struct section_image_information +{ + void* TransferAddress; + std::uint_least32_t ZeroBits; + std::size_t MaximumStackSize; + std::size_t CommittedStackSize; + std::uint_least32_t SubSystemType; + union U + { + struct S + { + std::uint_least16_t SubSystemMinorVersion; + std::uint_least16_t SubSystemMajorVersion; + }s; + std::uint_least32_t SubSystemVersion; + }u; + std::uint_least32_t GpValue; + std::uint_least16_t ImageCharacteristics; + std::uint_least16_t DllCharacteristics; + std::uint_least16_t Machine; + int ImageContainsCode; + union U1 + { + char unsigned ImageFlags; + struct S + { + char unsigned ComPlusNativeReady : 1; + char unsigned ComPlusILOnly : 1; + char unsigned ImageDynamicallyRelocated : 1; + char unsigned ImageMappedFlat : 1; + char unsigned BaseBelow4gb : 1; + char unsigned Reserved : 3; + }s; + }u1; + std::uint_least32_t LoaderFlags; + std::uint_least32_t ImageFileSize; + std::uint_least32_t CheckSum; +}; + +struct rtl_user_process_parameters +{ + std::uint_least32_t MaximumLength; + std::uint_least32_t Length; + + std::uint_least32_t Flags; + std::uint_least32_t DebugFlags; + + void* ConsoleHandle; + std::uint_least32_t ConsoleFlags; + void* StandardInput; + void* StandardOutput; + void* StandardError; + + curdir CurrentDirectory; + unicode_string DllPath; + unicode_string ImagePathName; + unicode_string CommandLine; + char16_t *Environment; + + std::uint_least32_t StartingX; + std::uint_least32_t StartingY; + std::uint_least32_t CountX; + std::uint_least32_t CountY; + std::uint_least32_t CountCharsX; + std::uint_least32_t CountCharsY; + std::uint_least32_t FillAttribute; + + std::uint_least32_t WindowFlags; + std::uint_least32_t ShowWindowFlags; + unicode_string WindowTitle; + unicode_string DesktopInfo; + unicode_string ShellInfo; + unicode_string RuntimeData; + rtl_drive_letter_curdir CurrentDirectories[rtl_max_drive_letters]; + + std::uint_least32_t EnvironmentSize; + std::uint_least32_t EnvironmentVersion; + void* PackageDependencyData; + std::uint_least32_t ProcessGroupId; + std::uint_least32_t LoaderThreads; +}; +enum class ps_create_state +{ +PsCreateInitialState, +PsCreateFailOnFileOpen, +PsCreateFailOnSectionCreate, +PsCreateFailExeFormat, +PsCreateFailMachineMismatch, +PsCreateFailExeName, // Debugger specified +PsCreateSuccess, +PsCreateMaximumStates +}; + +struct ps_create_info +{ + ::std::size_t Size; + ps_create_state State; + union unnamedunion + { + // PsCreateInitialState + struct InitStateT + { + union + { + ::std::uint_least32_t InitFlags; + struct + { + ::std::uint_least8_t WriteOutputOnExit : 1; + ::std::uint_least8_t DetectManifest : 1; + ::std::uint_least8_t IFEOSkipDebugger : 1; + ::std::uint_least8_t IFEODoNotPropagateKeyState : 1; + ::std::uint_least8_t SpareBits1 : 4; + ::std::uint_least8_t SpareBits2 : 8; + ::std::uint_least16_t ProhibitedImageCharacteristics : 16; + } s1; + } u1; + ::std::uint_least32_t AdditionalFileAccess; + } InitState; + + // PsCreateFailOnSectionCreate + struct FailSectionT + { + void* FileHandle; + } FailSection; + + // PsCreateFailExeFormat + struct ExeFormatT + { + ::std::uint_least16_t DllCharacteristics; + } ExeFormat; + + // PsCreateFailExeName + struct ExeNameT + { + void* IFEOKey; + } ExeName; + + // PsCreateSuccess + struct SuccessStateT + { + union + { + ::std::uint_least32_t OutputFlags; + struct s2T + { + ::std::uint_least8_t ProtectedProcess : 1; + ::std::uint_least8_t AddressSpaceOverride : 1; + ::std::uint_least8_t DevOverrideEnabled : 1; // From Image File Execution Options + ::std::uint_least8_t ManifestDetected : 1; + ::std::uint_least8_t ProtectedProcessLight : 1; + ::std::uint_least8_t SpareBits1 : 3; + ::std::uint_least8_t SpareBits2 : 8; + ::std::uint_least16_t SpareBits3 : 16; + } s2; + } u2; + void* FileHandle; + void* SectionHandle; + ::std::uint_least64_t UserProcessParametersNative; + ::std::uint_least32_t UserProcessParametersWow64; + ::std::uint_least32_t CurrentParameterFlags; + ::std::uint_least64_t PebAddressNative; + ::std::uint_least32_t PebAddressWow64; + ::std::uint_least64_t ManifestAddress; + ::std::uint_least32_t ManifestSize; + } SuccessState; + }; +}; + +struct ps_attribute +{ + ::std::uintptr_t Attribute; // PROC_THREAD_ATTRIBUTE_XXX | PROC_THREAD_ATTRIBUTE_XXX modifiers, see ProcThreadAttributeValue macro and Windows Internals 6 (372) + ::std::size_t Size; // Size of Value or *ValuePtr + union + { + ::std::uintptr_t Value; // Reserve 8 bytes for data (such as a Handle or a data pointer) + void* ValuePtr; // data pointer + }; + ::std::size_t* ReturnLength; // Either 0 or specifies size of data returned to caller via "ValuePtr" +}; + +struct +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +ps_attribute_list +{ + ::std::size_t TotalLength; // sizeof(PS_ATTRIBUTE_LIST) + ps_attribute Attributes[2]; // Depends on how many attribute entries should be supplied to NtCreateUserProcess +}; + +template<::std::size_t n> +requires (n!=0) +struct ps_attribute_list_array +{ + ::std::size_t TotalLength{sizeof(ps_attribute_list_array)}; // sizeof(PS_ATTRIBUTE_LIST) + ps_attribute Attributes[n]{}; // Depends on how many attribute entries should be supplied to NtCreateUserProcess + ps_attribute_list const* list_ptr() const noexcept + { + return reinterpret_cast(this); + } + ps_attribute_list* list_ptr() noexcept + { + return reinterpret_cast(this); + } +}; + +struct rtl_user_process_information +{ +::std::uint_least32_t Length; +void* Process; +void* Thread; +client_id ClientId; +section_image_information ImageInformation; +}; + +struct acl +{ +char unsigned AclRevision; +char unsigned Sbz1; +::std::uint_least16_t AclSize; +::std::uint_least16_t AceCount; +::std::uint_least16_t Sbz2; +}; + +struct security_descriptor +{ +char unsigned Revision; +char unsigned Sbz1; +::std::uint_least16_t Control; +void* Owner; +void* Group; +acl* Sacl; +acl* Dacl; +}; + +enum class object_information_class +{ +ObjectBasicInformation = 0, +ObjectNameInformation = 1, +ObjectTypeInformation = 2, +ObjectAllTypesInformation = 3, +ObjectHandleInformation = 4 +}; + +} diff --git a/src/fast_io/include/fast_io_hosted/platforms/nt/nt_linker.h b/src/fast_io/include/fast_io_hosted/platforms/nt/nt_linker.h new file mode 100644 index 0000000..775fb4b --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/nt/nt_linker.h @@ -0,0 +1,1692 @@ +#pragma once + +namespace fast_io::win32::nt +{ + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +rtl_nt_status_to_dos_error(std::uint_least32_t status) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("RtlNtStatusToDosError@4") +#else +__asm__("_RtlNtStatusToDosError@4") +#endif +#else +__asm__("RtlNtStatusToDosError") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +NtClose(void*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("NtClose@4") +#else +__asm__("_NtClose@4") +#endif +#else +__asm__("NtClose") +#endif +#endif +; +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +ZwClose(void*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("ZwClose@4") +#else +__asm__("_ZwClose@4") +#endif +#else +__asm__("ZwClose") +#endif +#endif +; + +template +inline std::uint_least32_t nt_close(void* handle) noexcept +{ + if constexpr(zw) + return ZwClose(handle); + else + return NtClose(handle); +} + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +NtCreateFile(void**,std::uint_least32_t,object_attributes*,io_status_block*,std::int_least64_t*, + std::uint_least32_t,std::uint_least32_t,std::uint_least32_t,std::uint_least32_t,void*,std::uint_least32_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("NtCreateFile@44") +#else +__asm__("_NtCreateFile@44") +#endif +#else +__asm__("NtCreateFile") +#endif +#endif +; +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +ZwCreateFile(void**,std::uint_least32_t,object_attributes*,io_status_block*,std::int_least64_t*, + std::uint_least32_t,std::uint_least32_t,std::uint_least32_t,std::uint_least32_t,void*,std::uint_least32_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("ZwCreateFile@44") +#else +__asm__("_ZwCreateFile@44") +#endif +#else +__asm__("ZwCreateFile") +#endif +#endif +; + +template +requires (sizeof...(Args)==11) +inline std::uint_least32_t nt_create_file(Args... args) noexcept +{ + if constexpr(zw) + return ZwCreateFile(args...); + else + return NtCreateFile(args...); +} + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +NtCreateSection(void** __restrict,std::uint_least32_t,object_attributes* __restrict, + std::uint_least64_t*,std::uint_least32_t,std::uint_least32_t,void* __restrict) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("NtCreateSection@28") +#else +__asm__("_NtCreateSection@28") +#endif +#else +__asm__("NtCreateSection") +#endif +#endif +; +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +ZwCreateSection(void** __restrict,std::uint_least32_t,object_attributes* __restrict, + std::uint_least64_t*,std::uint_least32_t,std::uint_least32_t,void* __restrict) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("ZwCreateSection@28") +#else +__asm__("_ZwCreateSection@28") +#endif +#else +__asm__("ZwCreateSection") +#endif +#endif +; + +template +requires (sizeof...(Args)==7) +inline std::uint_least32_t nt_create_section(Args... args) noexcept +{ + if constexpr(zw) + return ZwCreateSection(args...); + else + return NtCreateSection(args...); +} + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +NtQueryInformationProcess(void* __restrict, + process_information_class,process_basic_information*, + std::uint_least32_t,std::uint_least32_t*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("NtQueryInformationProcess@20") +#else +__asm__("_NtQueryInformationProcess@20") +#endif +#else +__asm__("NtQueryInformationProcess") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +ZwQueryInformationProcess(void* __restrict, + process_information_class,process_basic_information*, + std::uint_least32_t,std::uint_least32_t*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("ZwQueryInformationProcess@20") +#else +__asm__("_ZwQueryInformationProcess@20") +#endif +#else +__asm__("ZwQueryInformationProcess") +#endif +#endif +; + +template +requires (sizeof...(Args)==5) +inline std::uint_least32_t nt_query_information_process(Args... args) noexcept +{ + if constexpr(zw) + return ZwQueryInformationProcess(args...); + else + return NtQueryInformationProcess(args...); +} + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +NtWriteFile(void*,void*,pio_apc_routine,void*,io_status_block*, + void const*,std::uint_least32_t,std::int_least64_t*,std::uint_least32_t*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("NtWriteFile@36") +#else +__asm__("_NtWriteFile@36") +#endif +#else +__asm__("NtWriteFile") +#endif +#endif +; +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +ZwWriteFile(void*,void*,pio_apc_routine,void*,io_status_block*, + void const*,std::uint_least32_t,std::int_least64_t*,std::uint_least32_t*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("ZwWriteFile@36") +#else +__asm__("_ZwWriteFile@36") +#endif +#else +__asm__("ZwWriteFile") +#endif +#endif +; + +template +requires (sizeof...(Args)==9) +inline std::uint_least32_t nt_write_file(Args... args) noexcept +{ + if constexpr(zw) + return ZwWriteFile(args...); + else + return NtWriteFile(args...); +} + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +NtReadFile(void*,void*,pio_apc_routine,void*,io_status_block*, + void const*,std::uint_least32_t,std::int_least64_t*,std::uint_least32_t*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("NtReadFile@36") +#else +__asm__("_NtReadFile@36") +#endif +#else +__asm__("NtReadFile") +#endif +#endif +; +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +ZwReadFile(void*,void*,pio_apc_routine,void*,io_status_block*, + void const*,std::uint_least32_t,std::int_least64_t*,std::uint_least32_t*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("ZwReadFile@36") +#else +__asm__("_ZwReadFile@36") +#endif +#else +__asm__("ZwReadFile") +#endif +#endif +; + +template +requires (sizeof...(Args)==9) +inline std::uint_least32_t nt_read_file(Args... args) noexcept +{ + if constexpr(zw) + return ZwReadFile(args...); + else + return NtReadFile(args...); +} + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +NtQueryObject(void*,object_information_class,void*,::std::uint_least32_t,::std::uint_least32_t*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("NtQueryObject@20") +#else +__asm__("_NtQueryObject@20") +#endif +#else +__asm__("NtQueryObject") +#endif +#endif +; + + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +NtQueryDirectoryFile(void*,void*,pio_apc_routine,void*,io_status_block*, + void*,std::uint_least32_t,file_information_class,int,unicode_string*,int) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("NtQueryDirectoryFile@44") +#else +__asm__("_NtQueryDirectoryFile@44") +#endif +#else +__asm__("NtQueryDirectoryFile") +#endif +#endif +; +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +ZwQueryDirectoryFile(void*,void*,pio_apc_routine,void*,io_status_block*, + void*,std::uint_least32_t,file_information_class,int,unicode_string*,int) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("ZwQueryDirectoryFile@44") +#else +__asm__("_ZwQueryDirectoryFile@44") +#endif +#else +__asm__("ZwQueryDirectoryFile") +#endif +#endif +; + +template +requires (sizeof...(Args)==11) +inline std::uint_least32_t nt_query_directory_file(Args... args) noexcept +{ + if constexpr(zw) + return ZwQueryDirectoryFile(args...); + else + return NtQueryDirectoryFile(args...); +} + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +NtQuerySection(void*,section_information_class,void*,std::size_t,std::size_t*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("NtQuerySection@20") +#else +__asm__("_NtQuerySection@20") +#endif +#else +__asm__("NtQuerySection") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +ZwQuerySection(void*,section_information_class,void*,std::size_t,std::size_t*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("ZwQuerySection@20") +#else +__asm__("_ZwQuerySection@20") +#endif +#else +__asm__("ZwQuerySection") +#endif +#endif +; + +template +requires (sizeof...(Args)==5) +inline std::uint_least32_t nt_query_section(Args... args) noexcept +{ + if constexpr(zw) + return ZwQuerySection(args...); + else + return NtQuerySection(args...); +} + + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +NtQueryInformationFile(void* __restrict,io_status_block* __restrict,void* __restrict,std::uint_least32_t,file_information_class) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("NtQueryInformationFile@20") +#else +__asm__("_NtQueryInformationFile@20") +#endif +#else +__asm__("NtQueryInformationFile") +#endif +#endif +; +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +ZwQueryInformationFile(void* __restrict,io_status_block* __restrict,void* __restrict,std::uint_least32_t,file_information_class) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("ZwQueryInformationFile@20") +#else +__asm__("_ZwQueryInformationFile@20") +#endif +#else +__asm__("ZwQueryInformationFile") +#endif +#endif +; + +template +requires (sizeof...(Args)==5) +inline std::uint_least32_t nt_query_information_file(Args... args) noexcept +{ + if constexpr(zw) + return ZwQueryInformationFile(args...); + else + return NtQueryInformationFile(args...); +} + + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +NtSetInformationFile(void* __restrict,io_status_block* __restrict,void* __restrict,std::uint_least32_t,file_information_class) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("NtSetInformationFile@28") +#else +__asm__("_NtSetInformationFile@28") +#endif +#else +__asm__("NtSetInformationFile") +#endif +#endif +; +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +ZwSetInformationFile(void* __restrict,io_status_block* __restrict,void* __restrict,std::uint_least32_t,file_information_class) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("ZwSetInformationFile@28") +#else +__asm__("_ZwSetInformationFile@28") +#endif +#else +__asm__("ZwSetInformationFile") +#endif +#endif +; + +template +requires (sizeof...(Args)==5) +inline std::uint_least32_t nt_set_information_file(Args... args) noexcept +{ + if constexpr(zw) + return ZwSetInformationFile(args...); + else + return NtSetInformationFile(args...); +} + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +NtDuplicateObject(void*,void*,void*,void**,std::uint_least32_t,std::uint_least32_t,std::uint_least32_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("NtDuplicateObject@28") +#else +__asm__("_NtDuplicateObject@28") +#endif +#else +__asm__("NtDuplicateObject") +#endif +#endif +; +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +ZwDuplicateObject(void*,void*,void*,void**,std::uint_least32_t,std::uint_least32_t,std::uint_least32_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("ZwDuplicateObject@28") +#else +__asm__("_ZwDuplicateObject@28") +#endif +#else +__asm__("ZwDuplicateObject") +#endif +#endif +; + +template +requires (sizeof...(Args)==7) +inline std::uint_least32_t nt_duplicate_object(Args... args) noexcept +{ + if constexpr(zw) + return ZwDuplicateObject(args...); + else + return NtDuplicateObject(args...); +} + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +NtWaitForSingleObject(void*,int,std::uint_least64_t*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("NtWaitForSingleObject@12") +#else +__asm__("_NtWaitForSingleObject@12") +#endif +#else +__asm__("NtWaitForSingleObject") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +ZwWaitForSingleObject(void*,int,std::uint_least64_t*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("ZwWaitForSingleObject@12") +#else +__asm__("_ZwWaitForSingleObject@12") +#endif +#else +__asm__("ZwWaitForSingleObject") +#endif +#endif +; + +template +requires (sizeof...(Args)==3) +inline std::uint_least32_t nt_wait_for_single_object(Args... args) noexcept +{ + if constexpr(zw) + return ZwWaitForSingleObject(args...); + else + return NtWaitForSingleObject(args...); +} + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +NtSetSystemTime(std::uint_least64_t*,std::uint_least64_t*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("NtSetSystemTime@8") +#else +__asm__("_NtSetSystemTime@8") +#endif +#else +__asm__("NtSetSystemTime") +#endif +#endif +; +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +ZwSetSystemTime(std::uint_least64_t*,std::uint_least64_t*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("ZwSetSystemTime@8") +#else +__asm__("_ZwSetSystemTime@8") +#endif +#else +__asm__("ZwSetSystemTime") +#endif +#endif +; + +template +requires (sizeof...(Args)==2) +inline std::uint_least32_t nt_set_system_time(Args... args) noexcept +{ + if constexpr(zw) + return ZwSetSystemTime(args...); + else + return NtSetSystemTime(args...); +} + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +NtCreateProcess(void**,std::uint_least32_t,object_attributes*,void*,std::uint_least32_t,void*,void*,void*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("NtCreateProcess@32") +#else +__asm__("_NtCreateProcess@32") +#endif +#else +__asm__("NtCreateProcess") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +ZwCreateProcess(void**,std::uint_least32_t,object_attributes*,void*,std::uint_least32_t,void*,void*,void*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("ZwCreateProcess@32") +#else +__asm__("_ZwCreateProcess@32") +#endif +#else +__asm__("ZwCreateProcess") +#endif +#endif +; + +template +requires (sizeof...(Args)==8) +inline std::uint_least32_t nt_create_process(Args... args) noexcept +{ + if constexpr(zw) + return NtCreateProcess(args...); + else + return ZwCreateProcess(args...); +} + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern char unsigned +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +rtl_dos_path_name_to_nt_path_name_u(char16_t const*,unicode_string*,char16_t const**,rtl_relative_name_u*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("RtlDosPathNameToNtPathName_U@16") +#else +__asm__("_RtlDosPathNameToNtPathName_U@16") +#endif +#else +__asm__("RtlDosPathNameToNtPathName_U") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +rtl_dos_path_name_to_nt_path_name_u_with_status(char16_t const*,unicode_string*,char16_t const**,rtl_relative_name_u*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("RtlDosPathNameToNtPathName_U_WithStatus@16") +#else +__asm__("_RtlDosPathNameToNtPathName_U_WithStatus@16") +#endif +#else +__asm__("RtlDosPathNameToNtPathName_U_WithStatus") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern void +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +rtl_free_unicode_string(unicode_string*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("RtlFreeUnicodeString@4") +#else +__asm__("_RtlFreeUnicodeString@4") +#endif +#else +__asm__("RtlFreeUnicodeString") +#endif +#endif +; + + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern void +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +RtlInitializeCriticalSection(void*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("RtlInitializeCriticalSection@4") +#else +__asm__("_RtlInitializeCriticalSection@4") +#endif +#else +__asm__("RtlInitializeCriticalSection") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern void +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +RtlEnterCriticalSection(void*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("RtlEnterCriticalSection@4") +#else +__asm__("_RtlEnterCriticalSection@4") +#endif +#else +__asm__("RtlEnterCriticalSection") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +RtlTryEnterCriticalSection(void*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("RtlTryEnterCriticalSection@4") +#else +__asm__("_RtlTryEnterCriticalSection@4") +#endif +#else +__asm__("RtlTryEnterCriticalSection") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern void +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +RtlLeaveCriticalSection(void*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("RtlLeaveCriticalSection@4") +#else +__asm__("_RtlLeaveCriticalSection@4") +#endif +#else +__asm__("RtlLeaveCriticalSection") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern void +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +RtlDeleteCriticalSection(void*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("RtlDeleteCriticalSection@4") +#else +__asm__("_RtlDeleteCriticalSection@4") +#endif +#else +__asm__("RtlDeleteCriticalSection") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +RtlCreateUserThread(void*,void*,int,std::uint_least32_t,std::size_t,std::size_t,void*,void*,void**,client_id*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("RtlCreateUserThread@40") +#else +__asm__("_RtlCreateUserThread@40") +#endif +#else +__asm__("RtlCreateUserThread") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +NtResumeThread(void*,std::uint_least32_t*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("NtResumeThread@8") +#else +__asm__("_NtResumeThread@8") +#endif +#else +__asm__("NtResumeThread") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +ZwResumeThread(void*,std::uint_least32_t*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("ZwResumeThread@8") +#else +__asm__("_ZwResumeThread@8") +#endif +#else +__asm__("ZwResumeThread") +#endif +#endif +; + +template +requires (sizeof...(Args)==2) +inline std::uint_least32_t nt_resume_thread(Args... args) noexcept +{ + if constexpr(zw) + return ZwResumeThread(args...); + else + return NtResumeThread(args...); +} + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +NtLockFile(void*,void*,pio_apc_routine,void*,io_status_block*,std::int_least64_t*,std::int_least64_t*,std::uint_least32_t,char unsigned,char unsigned) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("NtLockFile@40") +#else +__asm__("_NtLockFile@40") +#endif +#else +__asm__("NtLockFile") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +ZwLockFile(void*,void*,pio_apc_routine,void*,io_status_block*,std::int_least64_t*,std::int_least64_t*,std::uint_least32_t,char unsigned,char unsigned) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("ZwLockFile@40") +#else +__asm__("_ZwLockFile@40") +#endif +#else +__asm__("ZwLockFile") +#endif +#endif +; + +template +requires (sizeof...(Args)==10) +inline std::uint_least32_t nt_lock_file(Args... args) noexcept +{ + if constexpr(zw) + return ZwLockFile(args...); + else + return NtLockFile(args...); +} + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +NtUnlockFile(void*,io_status_block*,std::int_least64_t*,std::int_least64_t*,std::uint_least32_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("NtUnlockFile@20") +#else +__asm__("_NtUnlockFile@20") +#endif +#else +__asm__("NtUnlockFile") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +ZwUnlockFile(void*,io_status_block*,std::int_least64_t*,std::int_least64_t*,std::uint_least32_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("ZwUnlockFile@20") +#else +__asm__("_ZwUnlockFile@20") +#endif +#else +__asm__("ZwUnlockFile") +#endif +#endif +; + +template +requires (sizeof...(Args)==5) +inline std::uint_least32_t nt_unlock_file(Args... args) noexcept +{ + if constexpr(zw) + return ZwUnlockFile(args...); + else + return NtUnlockFile(args...); +} + +/* +Available starting with Windows Vista??? +https://hfiref0x.github.io/syscalls.html +Actually this shows that it is available since the start of NT +*/ + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +NtFlushBuffersFile(void*,io_status_block*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("NtFlushBuffersFile@8") +#else +__asm__("_NtFlushBuffersFile@8") +#endif +#else +__asm__("NtFlushBuffersFile") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +ZwFlushBuffersFile(void*,io_status_block*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("ZwFlushBuffersFile@8") +#else +__asm__("_ZwFlushBuffersFile@8") +#endif +#else +__asm__("ZwFlushBuffersFile") +#endif +#endif +; + +template +requires (sizeof...(Args)==2) +inline std::uint_least32_t nt_flush_buffers_file(Args... args) noexcept +{ + if constexpr(zw) + return ZwFlushBuffersFile(args...); + else + return NtFlushBuffersFile(args...); +} + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +NtFlushBuffersFileEx(void*,std::uint_least32_t,void*,std::uint_least32_t,io_status_block*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("NtFlushBuffersFileEx@20") +#else +__asm__("_NtFlushBuffersFileEx@20") +#endif +#else +__asm__("NtFlushBuffersFileEx") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +ZwFlushBuffersFileEx(void*,std::uint_least32_t,void*,std::uint_least32_t,io_status_block*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("ZwFlushBuffersFileEx@20") +#else +__asm__("_ZwFlushBuffersFileEx@20") +#endif +#else +__asm__("ZwFlushBuffersFileEx") +#endif +#endif +; + +template +requires (sizeof...(Args)==5) +inline std::uint_least32_t nt_flush_buffers_file_ex(Args... args) noexcept +{ + if constexpr(zw) + return ZwFlushBuffersFileEx(args...); + else + return NtFlushBuffersFileEx(args...); +} + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if __has_cpp_attribute(__gnu__::__cdecl__) +[[__gnu__::__cdecl__]] +#endif +extern std::uint_least32_t +#if !__has_cpp_attribute(__gnu__::__cdecl__) && defined(_MSC_VER) +__cdecl +#endif +DbgPrint(char const*,...) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("DbgPrint") +#else +__asm__("_DbgPrint") +#endif +#else +__asm__("DbgPrint") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if __has_cpp_attribute(__gnu__::__cdecl__) +[[__gnu__::__cdecl__]] +#endif +extern std::uint_least32_t +#if !__has_cpp_attribute(__gnu__::__cdecl__) && defined(_MSC_VER) +__cdecl +#endif +DbgPrintEx(std::uint_least32_t,std::uint_least32_t,char const*,...) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("DbgPrintEx") +#else +__asm__("_DbgPrintEx") +#endif +#else +__asm__("DbgPrintEx") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern ::std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +RtlCreateProcessParameters(rtl_user_process_parameters**,unicode_string*,unicode_string*,unicode_string*,unicode_string*,void*,unicode_string*,unicode_string*,unicode_string*,unicode_string*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("RtlCreateProcessParameters@40") +#else +__asm__("_RtlCreateProcessParameters@40") +#endif +#else +__asm__("RtlCreateProcessParameters") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern ::std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +RtlCreateProcessParametersEx(rtl_user_process_parameters**,unicode_string*,unicode_string*,unicode_string*,unicode_string*,void*,unicode_string*,unicode_string*,unicode_string*,unicode_string*,::std::uint_least32_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("RtlCreateProcessParametersEx@44") +#else +__asm__("_RtlCreateProcessParametersEx@44") +#endif +#else +__asm__("RtlCreateProcessParametersEx") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern ::std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +RtlDestroyProcessParameters(rtl_user_process_parameters*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("RtlDestroyProcessParameters@4") +#else +__asm__("_RtlDestroyProcessParameters@4") +#endif +#else +__asm__("RtlDestroyProcessParameters") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern ::std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +NtCreateUserProcess(void*,void*,::std::uint_least32_t,::std::uint_least32_t,object_attributes*,object_attributes*,::std::uint_least32_t,::std::uint_least32_t,rtl_user_process_parameters*,ps_create_info*,ps_attribute_list*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("NtCreateUserProcess@44") +#else +__asm__("_NtCreateUserProcess@44") +#endif +#else +__asm__("NtCreateUserProcess") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern ::std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +ZwCreateUserProcess(void*,void*,::std::uint_least32_t,::std::uint_least32_t,object_attributes*,object_attributes*,::std::uint_least32_t,::std::uint_least32_t,rtl_user_process_parameters*,ps_create_info*,ps_attribute_list*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("ZwCreateUserProcess@44") +#else +__asm__("_ZwCreateUserProcess@44") +#endif +#else +__asm__("ZwCreateUserProcess") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern ::std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +RtlCreateUserProcess(unicode_string*,::std::uint_least32_t,rtl_user_process_parameters*,security_descriptor*,security_descriptor*,void*,char unsigned,void*,void*,rtl_user_process_information*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("RtlCreateUserProcess@40") +#else +__asm__("_RtlCreateUserProcess@40") +#endif +#else +__asm__("RtlCreateUserProcess") +#endif +#endif +; + + +} diff --git a/src/fast_io/include/fast_io_hosted/platforms/nt/nt_path.h b/src/fast_io/include/fast_io_hosted/platforms/nt/nt_path.h new file mode 100644 index 0000000..34b9b1b --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/nt/nt_path.h @@ -0,0 +1,156 @@ +#pragma once + +namespace fast_io::win32::nt::details +{ + +inline std::uint_least16_t nt_filename_bytes(std::size_t sz) +{ + if constexpr(sizeof(sz)(static_cast(sz)<<1u); + constexpr std::size_t max_value{static_cast(std::numeric_limits::max()>>1u)}; + if(max_value(sz<<1); +} + +inline void nt_file_rtl_path(char16_t const* filename,win32::nt::unicode_string& nt_name,char16_t const*& part_name,win32::nt::rtl_relative_name_u& relative_name) +{ +/* +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. +*/ +#if !defined(_WIN32_WINNT) || _WIN32_WINNT >= 0x0502 + auto status{rtl_dos_path_name_to_nt_path_name_u_with_status(filename,__builtin_addressof(nt_name),__builtin_addressof(part_name),__builtin_addressof(relative_name))}; + if(status) + throw_nt_error(status); +#else + if(!win32::nt::rtl_dos_path_name_to_nt_path_name_u(filename,__builtin_addressof(nt_name),__builtin_addressof(part_name),__builtin_addressof(relative_name))) + throw_nt_error(0xC0000039); +#endif +} + +template +inline auto nt_call_invoke_with_directory_handle_impl(void* directory,char_type const* filename,std::size_t filename_len,func callback) +{ + using char16_may_alias_const_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = char16_t const*; + if constexpr(std::same_as) + { + using char16_may_alias_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = char16_t*; + std::uint_least16_t const bytes(nt_filename_bytes(filename_len)); + win32::nt::unicode_string relative_path{ + .Length=bytes, + .MaximumLength=bytes, + .Buffer=const_cast(filename)}; + return callback(directory,__builtin_addressof(relative_path)); + } + else if constexpr(sizeof(char_type)==sizeof(char16_t)) + return nt_call_invoke_with_directory_handle_impl(directory,reinterpret_cast(filename),filename_len,callback); + else + { + nt_api_encoding_converter converter(filename,filename_len); + return nt_call_invoke_with_directory_handle_impl(directory,reinterpret_cast(converter.c_str()),converter.size(),callback); + } +} + +template +requires (sizeof(char_type)==sizeof(char16_t)) +inline auto nt_call_invoke_without_directory_handle_impl(char_type const* filename_c_str,func callback) +{ + if constexpr(std::same_as) + { + char16_t const* part_name{}; + win32::nt::rtl_relative_name_u relative_name{}; + win32::nt::unicode_string nt_name{}; + nt_file_rtl_path(filename_c_str,nt_name,part_name,relative_name); + win32::nt::rtl_unicode_string_unique_ptr us_ptr{__builtin_addressof(nt_name)}; + return callback(nullptr,__builtin_addressof(nt_name)); + } + else + { + using char16_may_alias_const_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = char16_t const*; + return nt_call_invoke_without_directory_handle_impl(reinterpret_cast(filename_c_str),callback); + } +} + +template +inline auto nt_call_invoke_without_directory_handle(char_type const* filename,std::size_t filename_len,func callback) +{ + using char16_may_alias_const_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = char16_t const*; + if constexpr(sizeof(char_type)==sizeof(char16_t)) + return nt_call_invoke_without_directory_handle_impl(reinterpret_cast(filename),callback); + else + { + nt_api_encoding_converter converter(filename,filename_len); + return nt_call_invoke_without_directory_handle_impl(reinterpret_cast(converter.c_str()),callback); + } +} + +template +inline auto nt_call_callback(void* directory, char_type const* filename,std::size_t filename_len,func callback) +{ + if(directory==nullptr) + throw_nt_error(0xC0000008); //STATUS_INVALID_HANDLE + else if(directory==reinterpret_cast(std::intptr_t(-3))) + return nt_call_invoke_without_directory_handle(filename,filename_len,callback); + return nt_call_invoke_with_directory_handle_impl(directory,filename,filename_len,callback); +} + +template +inline auto nt_call_callback_without_directory_handle(char_type const* filename,std::size_t filename_len,func callback) +{ + return nt_call_invoke_without_directory_handle(filename,filename_len,callback); +} + +template +inline auto nt_call_kernel_common_impl(void* directory,char16_t const* filename,std::size_t filename_len,func callback) +{ + std::uint_least16_t const bytes(nt_filename_bytes(filename_len)); + win32::nt::unicode_string relative_path{ + .Length=bytes, + .MaximumLength=bytes, + .Buffer=const_cast(filename)}; + return callback(directory,__builtin_addressof(relative_path)); +} + +template +inline auto nt_call_kernel_nodir_callback(char16_t const* filename,std::size_t filename_len,func callback) +{ + return nt_call_kernel_common_impl(nullptr,filename,filename_len,callback); +} + +template +inline auto nt_call_kernel_callback(void* directory,char16_t const* filename,std::size_t filename_len,func callback) +{ + if(directory==nullptr) + throw_nt_error(0xC0000008); //STATUS_INVALID_HANDLE + else if(directory==reinterpret_cast(std::intptr_t(-3))) + directory=nullptr; + return nt_call_kernel_common_impl(directory,filename,filename_len,callback); +} + +template +inline auto nt_call_kernel_fs_dirent_callback(void* directory,char16_t const* filename,std::size_t filename_len,func callback) +{ + if(directory==nullptr) + throw_nt_error(0xC0000008); //STATUS_INVALID_HANDLE + return nt_call_kernel_common_impl(directory,filename,filename_len,callback); +} + +} + diff --git a/src/fast_io/include/fast_io_hosted/platforms/nt/rtl_unicode_string_unique_ptr.h b/src/fast_io/include/fast_io_hosted/platforms/nt/rtl_unicode_string_unique_ptr.h new file mode 100644 index 0000000..6bf353c --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/nt/rtl_unicode_string_unique_ptr.h @@ -0,0 +1,32 @@ +#pragma once + +namespace fast_io::win32::nt +{ + +struct rtl_unicode_string_unique_ptr +{ + unicode_string* heap_ptr{}; + constexpr rtl_unicode_string_unique_ptr()=default; + constexpr rtl_unicode_string_unique_ptr(unicode_string* ptr):heap_ptr(ptr){} + rtl_unicode_string_unique_ptr(rtl_unicode_string_unique_ptr const&)=delete; + rtl_unicode_string_unique_ptr& operator=(rtl_unicode_string_unique_ptr const&)=delete; + constexpr rtl_unicode_string_unique_ptr(rtl_unicode_string_unique_ptr&& __restrict other) noexcept:heap_ptr(other.heap_ptr) + { + other.heap_ptr=nullptr; + } + rtl_unicode_string_unique_ptr& operator=(rtl_unicode_string_unique_ptr&& __restrict other) noexcept + { + if(heap_ptr)[[likely]] + rtl_free_unicode_string(heap_ptr); + heap_ptr=other.heap_ptr; + other.heap_ptr=nullptr; + return *this; + } + ~rtl_unicode_string_unique_ptr() + { + if(heap_ptr)[[likely]] + rtl_free_unicode_string(heap_ptr); + } +}; + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_hosted/platforms/omap.h b/src/fast_io/include/fast_io_hosted/platforms/omap.h new file mode 100644 index 0000000..4589706 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/omap.h @@ -0,0 +1,129 @@ +#pragma once + +namespace fast_io +{ + +template +class basic_omemory_map +{ +public: + using char_type = ch_type; + char_type *begin_ptr{},*curr_ptr{},*end_ptr{}; + constexpr basic_omemory_map() = default; + constexpr basic_omemory_map(native_memory_map_file const& iob,std::size_t offset=0):begin_ptr(reinterpret_cast(iob.address_begin+offset)),curr_ptr(begin_ptr),end_ptr(begin_ptr+iob.size()/sizeof(char_type)){} + + constexpr std::size_t written_bytes() const noexcept + { + return static_cast(curr_ptr-begin_ptr)*sizeof(char_type); + } +}; + +namespace details +{ + +template +inline constexpr void omemory_map_write_impl(basic_omemory_map& bomp,char_type const* begin,char_type const* end) noexcept +{ + std::size_t const to_write(end-begin); + if(static_cast(bomp.end_ptr-bomp.curr_ptr) +constexpr void write(basic_omemory_map& bomp,Iter begin,Iter end) noexcept +{ + details::omemory_map_write_impl(bomp,::std::to_address(begin),::std::to_address(end)); +} + +template +constexpr char_type* obuffer_begin(basic_omemory_map& bomp) noexcept +{ + return bomp.begin_ptr; +} +template +constexpr char_type* obuffer_curr(basic_omemory_map& bomp) noexcept +{ + return bomp.curr_ptr; +} +template +constexpr char_type* obuffer_end(basic_omemory_map& bomp) noexcept +{ + return bomp.end_ptr; +} + +template +constexpr void obuffer_overflow(basic_omemory_map&,char_type) noexcept +{ + fast_terminate(); +} + +template +constexpr void obuffer_set_curr(basic_omemory_map& bomp,char_type* ptr) noexcept +{ + bomp.curr_ptr=ptr; +} + +template +constexpr void obuffer_obuffer_overflow_never(basic_omemory_map&) noexcept{} + +using omemory_map = basic_omemory_map; + +template +class basic_imemory_map +{ +public: + using char_type = ch_type; + char_type *begin_ptr{},*curr_ptr{},*end_ptr{}; + constexpr basic_imemory_map() = default; + constexpr basic_imemory_map(native_memory_map_file const& iob,std::size_t offset=0):begin_ptr(reinterpret_cast(iob.address_begin+offset)),curr_ptr(this->begin_ptr),end_ptr(this->begin_ptr+iob.size()/sizeof(char_type)){} +}; + +template +constexpr Iter read(basic_imemory_map& bomp,Iter begin,Iter end) noexcept +{ + std::size_t to_read(end-begin); + std::size_t const remain_space(bomp.end_ptr-bomp.curr_ptr); + if(remain_space +constexpr char_type* ibuffer_begin(basic_imemory_map& bomp) noexcept +{ + return bomp.begin_ptr; +} +template +constexpr char_type* ibuffer_curr(basic_imemory_map& bomp) noexcept +{ + return bomp.curr_ptr; +} +template +constexpr char_type* ibuffer_end(basic_imemory_map& bomp) noexcept +{ + return bomp.end_ptr; +} + +template +constexpr bool ibuffer_underflow(basic_imemory_map&) noexcept +{ + return false; +} + +template +constexpr void ibuffer_set_curr(basic_imemory_map& bomp,char_type* ptr) noexcept +{ + bomp.curr_ptr=ptr; +} + +template +constexpr void ibuffer_underflow_never(basic_imemory_map&) noexcept{} + +using imemory_map = basic_imemory_map; + +} diff --git a/src/fast_io/include/fast_io_hosted/platforms/posix.h b/src/fast_io/include/fast_io_hosted/platforms/posix.h new file mode 100644 index 0000000..369232c --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/posix.h @@ -0,0 +1,1894 @@ +#pragma once + +#if ((defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__))&&!defined(__CYGWIN__)) || defined(__MSDOS__) +#if __has_include() +#include +#elif __has_include() +#include +#endif +#endif + +#if __has_include() +#include +#endif + +#if __has_include() +#include +#endif + +#if (!defined(_WIN32)||defined(__WINE__)||defined(__BIONIC__)) || defined(__CYGWIN__) + +#if __has_include() +#include +#endif + +#if __has_include() +#include +#endif + +#if __has_include() +#include +#endif + +#if __has_include() +#include +#endif + +#if __has_include() +#include +#endif + +#if defined(__wasi__) +#include +#endif + +#endif +#include"systemcall_details.h" + +#if ((!defined(_WIN32)||defined(__WINE__)) || defined(__CYGWIN__)) && __has_include() && __has_include() && !defined(__wasi__) +#include +#include "posix_netmode.h" +#endif + +#if defined(F_RDLCK) && defined(F_WRLCK) && defined(F_UNLCK) && !defined(__wasi__) +#include"posix_file_lock.h" +#endif + +namespace fast_io +{ + +namespace details +{ +#if (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) && !defined(__CYGWIN__) + +inline constexpr int calculate_posix_open_mode_for_win32_handle_impl(open_mode value,int mode) noexcept +{ + constexpr auto supported_values{open_mode::out|open_mode::app|open_mode::in}; + using utype = typename std::underlying_type::type; + switch(static_cast(supported_values)&static_cast(value)) + { +//Action if file already exists; Action if file does not exist; c-style mode; Explanation +//Read from start; Failure to open; "r"; Open a file for reading + case static_cast(open_mode::in): + return mode | O_RDONLY; +//Destroy contents; Create new; "w"; Create a file for writing + case static_cast(open_mode::out): +//Read from start; Error; "r+"; Open a file for read/write + case static_cast(open_mode::out)|static_cast(open_mode::in): + return mode; +//Append to file; Create new; "a"; Append to a file + case static_cast(open_mode::app): + case static_cast(open_mode::out)|static_cast(open_mode::app): + return mode | O_APPEND; +//Write to end; Create new; "a+"; Open a file for read/write + case static_cast(open_mode::out)|static_cast(open_mode::in)|static_cast(open_mode::app): + case static_cast(open_mode::in)|static_cast(open_mode::app): + return mode | O_APPEND; +//Destroy contents; Error; "wx"; Create a file for writing + default: + return mode; + } +} + +enum class posix_open_mode_text_behavior +{ +always_binary=0,text,wide_text,u8_text,u16_text +}; + +template +inline constexpr int calculate_posix_open_mode_for_win32_handle(open_mode value) noexcept +{ + int mode{}; + if constexpr(behavior==posix_open_mode_text_behavior::always_binary) + mode = _O_BINARY; + else + { + if((value&open_mode::text)==open_mode::none) + mode = _O_BINARY; + else + { + if constexpr(behavior==posix_open_mode_text_behavior::wide_text) + { +#if defined(_O_WTEXT) + mode |= _O_WTEXT; +#else + mode |= _O_BINARY; +#endif + } + else if constexpr(behavior==posix_open_mode_text_behavior::u8_text) + { +#if defined(_O_U8TEXT) + mode |= _O_U8TEXT; +#else + mode |= _O_BINARY; +#endif + } + else if constexpr(behavior==posix_open_mode_text_behavior::u16_text) + { +#if defined(_O_U16TEXT) + mode |= _O_U16TEXT; +#else + mode |= _O_BINARY; +#endif + } + else + { +#if defined(_O_TEXT) + mode |= _O_TEXT; +#else + mode |= _O_BINARY; +#endif + } + } + } + return calculate_posix_open_mode_for_win32_handle_impl(value,mode); +} +#endif + + +inline constexpr int calculate_posix_open_mode(open_mode value) noexcept +{ + int mode + { +#ifdef O_NOFOLLOW + O_NOFOLLOW +#endif + }; + if((value&open_mode::follow)!=open_mode::none) + mode = {}; + if((value&open_mode::inherit)==open_mode::none) +#ifdef O_CLOEXEC + mode |= O_CLOEXEC; +#elif _O_NOINHERIT + mode |= _O_NOINHERIT; +#endif +#ifdef O_BINARY + if((value&open_mode::text)==open_mode::none) + mode |= O_BINARY; +#endif + if((value&open_mode::creat)!=open_mode::none) + mode |= O_CREAT; + if((value&open_mode::excl)!=open_mode::none) + mode |= O_EXCL; + if((value&open_mode::trunc)!=open_mode::none) + mode |= O_TRUNC; +#ifdef O_DIRECT + if((value&open_mode::direct)!=open_mode::none) + mode |= O_DIRECT; +#endif +#ifdef O_SYNC + if((value&open_mode::sync)!=open_mode::none) + mode |= O_SYNC; +#endif +#ifdef O_TTY_INIT + if((value&open_mode::tty_init)!=open_mode::none) + mode |= O_TTY_INIT; +#endif +#ifdef O_NOCTTY + if((value&open_mode::no_ctty)!=open_mode::none) + mode |= O_NOCTTY; +#endif +#ifdef O_PATH + if((value&open_mode::path)!=open_mode::none) + mode |= O_PATH; +#endif +#ifdef O_NOATIME + if((value&open_mode::no_atime)!=open_mode::none) + mode |= O_NOATIME; +#endif + if((value&open_mode::no_block)!=open_mode::none) +#ifdef O_NONBLOCK + mode |= O_NONBLOCK; +#else + return {}; +#endif + + if((value&open_mode::temporary)!=open_mode::none) + { +#if defined(O_TMPFILE) + mode |= O_TMPFILE; +#elif defined(_O_TEMPORARY) + mode |= _O_TEMPORARY; +#else + return {}; +#endif + } +#ifdef _O_SEQUENTIAL + if((value&open_mode::random_access)!=open_mode::none) + mode |= _O_SEQUENTIAL; + else + mode |= _O_RANDOM; +#endif +#ifdef O_LARGEFILE + mode |= O_LARGEFILE; +#endif + + if((value&open_mode::directory)!=open_mode::none) +#ifdef O_DIRECTORY + mode |= O_DIRECTORY; +#else + return {}; +#endif + + using utype = typename std::underlying_type::type; + constexpr auto supported_values{static_cast(open_mode::out)|static_cast(open_mode::app)|static_cast(open_mode::in)}; + switch(static_cast(value)&static_cast(supported_values)) + { +/* +https://en.cppreference.com/w/cpp/io/basic_filebuf/open + +mode openmode & ~ate Action if file already exists Action if file does not exist +"r" in Read from start Failure to open +"w" out, out|trunc Destroy contents Create new +"a" app, out|app Append to file Create new +"r+" out|in Read from start Error +"w+" out|in|trunc Destroy contents Create new +"a+" out|in|app, in|app Write to end Create new +"rb" binary|in Read from start Failure to open +"wb" binary|out, binary|out|trunc Destroy contents Create new +"ab" binary|app, binary|out|app Write to end Create new +"r+b" binary|out|in Read from start Error +"w+b" binary|out|in|trunc Destroy contents Create new +"a+b" binary|out|in|app, binary|in|app Write to end Create new + +*/ +//Action if file already exists; Action if file does not exist; c-style mode; Explanation +//Read from start; Failure to open; "r"; Open a file for reading + case static_cast(open_mode::in): + return mode | O_RDONLY; +//Destroy contents; Create new; "w"; Create a file for writing + case static_cast(open_mode::out): + return mode | O_WRONLY | O_CREAT | O_TRUNC; +//Append to file; Create new; "a"; Append to a file + case static_cast(open_mode::app): + case static_cast(open_mode::out)|static_cast(open_mode::app): + return mode | O_WRONLY | O_CREAT | O_APPEND; +//Read from start; Error; "r+"; Open a file for read/write + case static_cast(open_mode::out)|static_cast(open_mode::in): + return mode | O_RDWR; +//Write to end; Create new; "a+"; Open a file for read/write + case static_cast(open_mode::out)|static_cast(open_mode::in)|static_cast(open_mode::app): + case static_cast(open_mode::in)|static_cast(open_mode::app): + return mode | O_RDWR | O_CREAT | O_APPEND; +//Destroy contents; Error; "wx"; Create a file for writing + default: + return mode; + } +} + +} + +struct posix_fs_dirent +{ + int fd{-1}; + char const* filename{}; + explicit constexpr posix_fs_dirent() = default; + explicit constexpr posix_fs_dirent(int fdd,char const* fnm):fd(fdd),filename(fnm){} +}; + +struct posix_io_redirection +{ + int *pipe_fds{}; + int fd{-1}; + bool dev_null{}; +}; + +struct posix_io_redirection_std:posix_io_redirection +{ + constexpr posix_io_redirection_std() noexcept=default; + template + requires requires(T&& t) + { + {redirect(::std::forward(t))}->std::same_as; + } + constexpr posix_io_redirection_std(T&& t) noexcept:posix_io_redirection(redirect(::std::forward(t))){} +}; + +struct posix_process_io +{ + posix_io_redirection_std in; + posix_io_redirection_std out; + posix_io_redirection_std err; +}; + +struct posix_dev_null_t{}; + +inline constexpr posix_dev_null_t posix_dev_null() noexcept +{ + return {}; +} + +inline constexpr posix_io_redirection redirect(posix_dev_null_t) noexcept +{ + return {.dev_null=true}; +} + +#if (defined(_WIN32)&&!defined(__WINE__)) || defined(__CYGWIN__) +namespace details +{ + +/* +Warning! cygwin's _get_osfhandle has the same name as msvcrt or ucrt's name, but they are completely different functions. Also, it returns long, not std::intptr_t +*/ +#if defined(__CYGWIN__) +#if (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +extern long cygwin_get_osfhandle(int fd) noexcept +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if defined(__GNUC__) +__asm__("_get_osfhandle") +#else +__asm__("__get_osfhandle") +#endif +#else +__asm__("_get_osfhandle") +#endif +; +#endif + +inline void* my_get_osfile_handle(int fd) noexcept +{ + if(fd==-1) + return nullptr; +#if defined(__BIONIC__) + return nullptr; +#elif defined(__CYGWIN__) + long ret{cygwin_get_osfhandle(fd)}; + if(ret==-1) + return nullptr; + return reinterpret_cast(static_cast(static_cast(ret))); +#else + std::intptr_t ret{noexcept_call(_get_osfhandle,fd)}; + if(ret==-1) + return nullptr; + return reinterpret_cast(ret); +#endif +} + +} +#endif + +template +class basic_posix_io_observer +{ +public: + using char_type = ch_type; + using native_handle_type = int; + native_handle_type fd=-1; + constexpr native_handle_type native_handle() const noexcept + { + return fd; + } + explicit constexpr operator bool() const noexcept + { + return fd!=-1; + } +#if (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) || defined(__CYGWIN__) + template + explicit operator basic_win32_family_io_observer() const noexcept + { + return {details::my_get_osfile_handle(fd)}; + } + template + explicit operator basic_nt_family_io_observer() const noexcept + { + return {details::my_get_osfile_handle(fd)}; + } +#endif + constexpr native_handle_type release() noexcept + { + auto temp{fd}; + fd=-1; + return temp; + } +}; + +#if __cpp_lib_three_way_comparison >= 201907L + +template +inline constexpr bool operator==(basic_posix_io_observer a,basic_posix_io_observer b) noexcept +{ + return a.fd==b.fd; +} + +template +inline constexpr auto operator<=>(basic_posix_io_observer a,basic_posix_io_observer b) noexcept +{ + return a.fd<=>b.fd; +} + +#endif + +template +inline constexpr posix_at_entry at(basic_posix_io_observer piob) noexcept +{ + return posix_at_entry{piob.fd}; +} + +template +inline constexpr basic_posix_io_observer io_value_handle(basic_posix_io_observer other) noexcept +{ + return other; +} + +#if !(defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) && defined(AT_FDCWD) + +inline constexpr posix_at_entry posix_at_fdcwd() noexcept +{ + return posix_at_entry(AT_FDCWD); +} + +inline constexpr posix_at_entry at_fdcwd() noexcept +{ + return posix_at_entry(AT_FDCWD); +} + +#endif + +namespace details +{ + +inline std::size_t posix_read_impl(int fd,void* address,std::size_t bytes_to_read) +{ +#if (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) && !defined(__CYGWIN__) + if constexpr(4(INT_LEAST32_MAX)(INT_LEAST32_MAX); +#endif + auto read_bytes( +#if defined(__linux__) + system_call<__NR_read,std::ptrdiff_t>( +#elif (defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WINE__) && !defined(__BIONIC__)) || defined(__MSDOS__) + ::fast_io::noexcept_call(::_read, +#else + ::fast_io::noexcept_call(::read, +#endif + fd,address, +#if (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) && !defined(__CYGWIN__) + static_cast(bytes_to_read) +#else + bytes_to_read +#endif + )); + system_call_throw_error(read_bytes); + return static_cast(read_bytes); +} + +#if (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) && !defined(__CYGWIN__) + +inline io_scatter_status_t posix_scatter_read_impl(int fd,io_scatters_t sp) +{ + std::size_t total_size{}; + for(std::size_t i{};i!=sp.len;++i) + { + std::size_t pos_in{posix_read_impl(fd,const_cast(sp.base[i].base),sp.base[i].len)}; + total_size+=pos_in; + if(pos_in(bytes_to_write))}; + if(ret==-1) + throw_posix_error(); + return static_cast(ret); +} + +inline std::size_t posix_write_nolock_impl(int fd,void const* address,std::size_t to_write) +{ + if constexpr(4(INT_LEAST32_MAX)) + to_write_this_round=static_cast(to_write); + std::uint_least32_t number_of_bytes_written{posix_write_simple_impl(fd,address,to_write_this_round)}; + written+=number_of_bytes_written; + if(number_of_bytes_written(address), .buf_len = to_write}; + std::size_t bytes_written; + auto ern{noexcept_call(__wasi_fd_write,fd, __builtin_addressof(iov), 1u, __builtin_addressof(bytes_written))}; + if(ern) + throw_posix_error(ern); + return bytes_written; +#else + auto write_bytes( +#if defined(__linux__) + system_call<__NR_write,std::ptrdiff_t>( +#elif (defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WINE__) && !defined(__BIONIC__)) || defined(__MSDOS__) + ::fast_io::noexcept_call(::_write, +#else + ::fast_io::noexcept_call(::write, +#endif + fd,address,to_write)); + system_call_throw_error(write_bytes); + return static_cast(write_bytes); +#endif +} + +inline std::uintmax_t posix_seek_impl(int fd,std::intmax_t offset,seekdir s) +{ +#if defined(__MSDOS__) + if constexpr(sizeof(off_t)(std::numeric_limits::min())||offset>static_cast(std::numeric_limits::max())) + throw_posix_error(EINVAL); + } + auto ret{noexcept_call(::lseek,fd,static_cast(offset),static_cast(s))}; + if(ret==-1) + throw_posix_error(); + return static_cast(static_cast>(ret)); +#elif defined(__linux__) +#if defined(__NR_llseek) + if constexpr(sizeof(off_t)<=sizeof(std::int_least32_t)) + { + std::uint_least64_t result{}; + std::uint_least64_t offset64_val{static_cast(static_cast(offset))}; + auto ret{system_call<__NR_llseek,int>(fd,static_cast(offset>>32u),static_cast(offset), + __builtin_addressof(result),static_cast(s))}; + system_call_throw_error(ret); + return static_cast(static_cast(result)); + } + else +#endif + { + if constexpr(sizeof(off_t)<=sizeof(std::int_least32_t)) + { + if(offset(std::numeric_limits::min())||offset>static_cast(std::numeric_limits::max())) + throw_posix_error(EOVERFLOW); + } + auto ret{system_call<__NR_lseek,std::ptrdiff_t>(fd,offset,static_cast(s))}; + system_call_throw_error(ret); + return static_cast(static_cast(ret)); + } +#else + if constexpr(sizeof(off_t)<=sizeof(std::int_least32_t)) + { + if(offset(std::numeric_limits::min())||offset>static_cast(std::numeric_limits::max())) + throw_posix_error(EOVERFLOW); + } + auto ret( +#if (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) && !defined(__CYGWIN__) + ::_lseeki64 +#else + ::lseek +#endif + (fd,static_cast(offset),static_cast(s))); + system_call_throw_error(ret); + return static_cast(static_cast(ret)); +#endif +} + +inline bool posix_is_character_device(int fd) noexcept +{ +#if (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) + return noexcept_call(::_isatty,fd)!=0; +#else + return noexcept_call(::isatty,fd)!=0; +#endif +} +#ifdef __MSDOS__ +extern void dos_clrscr() noexcept __asm__("_clrscr"); +#endif +inline void posix_clear_screen_main([[maybe_unused]] int fd) +{ +#ifdef __MSDOS__ + dos_clrscr(); +#else + constexpr std::size_t sequence_len{2}; + constexpr char8_t const clear_screen_control[2] {u8'\033',u8'c'}; + posix_write_impl(fd,clear_screen_control,sequence_len); +#endif +} + +inline void posix_clear_screen_impl(int fd) +{ +#if (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) && !defined(__CYGWIN__) + ::fast_io::win32::details::win32_clear_screen_impl(my_get_osfile_handle(fd)); +#else + if(!posix_is_character_device(fd)) + return; + posix_clear_screen_main(fd); +#endif +} + +inline void posix_flush_impl(int fd) +{ +#if (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) && !defined(__CYGWIN__) + if(noexcept_call(_commit,fd)==-1) + throw_posix_error(); +#elif defined(__linux__) && defined(__NR_fdatasync) + system_call_throw_error(system_call<__NR_fdatasync,int>(fd)); +#elif defined(__linux__) && defined(__NR_fsync) + system_call_throw_error(system_call<__NR_fsync,int>(fd)); +#else + if(noexcept_call(fsync,fd)==-1) + throw_posix_error(); +#endif +} + +inline void posix_data_sync_flags_impl(int fd,data_sync_flags) +{ +//todo + posix_flush_impl(fd); +} + +} + +template +[[nodiscard]] inline Iter read(basic_posix_io_observer h,Iter begin,Iter end) +{ + return begin+details::posix_read_impl(h.fd,::std::to_address(begin),static_cast(end-begin)*sizeof(*begin))/sizeof(*begin); +} +template +inline Iter write(basic_posix_io_observer h,Iter cbegin,Iter cend) +{ + return cbegin+details::posix_write_impl(h.fd,::std::to_address(cbegin),static_cast(cend-cbegin)*sizeof(*cbegin))/sizeof(*cbegin); +} + +template +inline std::uintmax_t seek(basic_posix_io_observer h,std::intmax_t i=0,seekdir s=seekdir::cur) +{ + return details::posix_seek_impl(h.fd,i,s); +} + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#endif +inline void flush(basic_posix_io_observer piob) +{ + details::posix_flush_impl(piob.fd); +} + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#endif +inline void data_sync(basic_posix_io_observer piob,data_sync_flags flags) +{ + details::posix_data_sync_flags_impl(piob.fd,flags); +} +#if defined(_WIN32)&& !defined(__WINE__) && !defined(__CYGINW__) + +template +inline constexpr auto file_lock(basic_posix_io_observer piob) noexcept +{ + return file_lock(::fast_io::basic_win32_io_observer{::fast_io::details::my_get_osfile_handle(piob.fd)}); +} + +#elif defined(F_RDLCK) && defined(F_WRLCK) && defined(F_UNLCK) && !defined(__wasi__) + +template +inline constexpr posix_file_lock file_lock(basic_posix_io_observer piob) noexcept +{ + return {piob.fd}; +} + +#else + +template +inline constexpr nop_file_lock file_lock(basic_posix_io_observer) noexcept +{ + return {}; +} + +#endif + + + +#if (!defined(__NEWLIB__) || defined(__CYGWIN__)) && (!defined(_WIN32) || defined(__WINE__)) +namespace details +{ + +#if (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) && !defined(__CYGWIN__) +using mode_t = int; +#endif + +inline constexpr perms st_mode_to_perms(mode_t m) noexcept +{ + return static_cast(m); +} + +inline constexpr file_type st_mode_to_file_type(mode_t m) noexcept +{ +/* +https://linux.die.net/man/2/fstat64 +The following POSIX macros are defined to check the file type using the st_mode field: + +S_ISREG(m) +is it a regular file? + +S_ISDIR(m) + +directory? + +S_ISCHR(m) + +character device? + +S_ISBLK(m) + +block device? + +S_ISFIFO(m) + +FIFO (named pipe)? + +S_ISLNK(m) + +symbolic link? (Not in POSIX.1-1996.) + +S_ISSOCK(m) + +socket? (Not in POSIX.1-1996.) +*/ +#if (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) && !defined(__CYGWIN__) +/* +https://github.com/Alexpux/mingw-w64/blob/master/mingw-w64-headers/crt/sys/stat.h + +#define _S_IFDIR 0x4000 +#define _S_IFCHR 0x2000 +#define _S_IFIFO 0x1000 +#define _S_IFREG 0x8000 +#define _S_IFBLK 0x3000 +*/ + if((m&0xF000)==0x8000) + return file_type::regular; + else if((m&0xF000)==0x4000) + return file_type::directory; + else if((m&0xF000)==0x2000) + return file_type::character; + else if((m&0xF000)==0x3000) + return file_type::block; + else if((m&0xF000)==0x1000) + return file_type::fifo; + else + return file_type::unknown; + +#else + if(S_ISREG(m)) + return file_type::regular; + else if(S_ISDIR(m)) + return file_type::directory; + else if(S_ISCHR(m)) + return file_type::character; + else if(S_ISBLK(m)) + return file_type::block; + else if(S_ISFIFO(m)) + return file_type::fifo; +#ifdef S_ISLNK + else if(S_ISLNK(m)) + return file_type::symlink; +#endif +#ifdef S_ISSOCK + else if(S_ISSOCK(m)) + return file_type::socket; +#endif + else + return file_type::unknown; +#endif +} + +template +inline constexpr posix_file_status struct_stat_to_posix_file_status(stat_model& st) noexcept +{ + return {static_cast(st.st_dev), + static_cast(st.st_ino), + st_mode_to_perms(st.st_mode), + st_mode_to_file_type(st.st_mode), + static_cast(st.st_nlink), + static_cast(st.st_uid), + static_cast(st.st_gid), + static_cast(st.st_rdev), + static_cast(st.st_size), +#if ((defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) && !defined(__CYGWIN__))||defined(__MSDOS__) + 131072, + static_cast(st.st_size/512), + {st.st_atime,{}},{st.st_mtime,{}},{st.st_ctime,{}},{0,0}, +#elif !defined(__CYGWIN__) && (defined(__BSD_VISIBLE) || defined(__DARWIN_C_LEVEL)) && !defined(_PICOLIBC__) && !defined(__linux__) + static_cast(st.st_blksize), + static_cast(st.st_blocks), + timespec_to_unix_timestamp(st.st_atimespec), + timespec_to_unix_timestamp(st.st_mtimespec), + timespec_to_unix_timestamp(st.st_ctimespec), +#if defined(__DARWIN_C_LEVEL) + {0,0} +#else + timespec_to_unix_timestamp(st.st_birthtimespec) +#endif + , +#else + static_cast(st.st_blksize), + static_cast(st.st_blocks), + timespec_to_unix_timestamp(st.st_atim), + timespec_to_unix_timestamp(st.st_mtim), + timespec_to_unix_timestamp(st.st_ctim), +#if defined(__CYGWIN__) +timespec_to_unix_timestamp(st.st_birthtim) +#else +{0,0} +#endif +, +#endif +#if !defined(__CYGWIN__) && (defined(__BSD_VISIBLE) || defined(__DARWIN_C_LEVEL)) && !defined(_PICOLIBC__) && !defined(__linux__) + st.st_flags,st.st_gen +#else + 0,0 +#endif +}; +} + +inline posix_file_status fstat_impl(int fd) +{ +#if (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) && !defined(__CYGWIN__) + struct __stat64 st; +#elif defined(__linux__) && defined(__USE_LARGEFILE64) + struct stat64 st; +#else + struct stat st; +#endif + if( +#if (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) && !defined(__CYGWIN__) +#if (!defined(__MINGW32__) || __has_include(<_mingw_stat64.h>)) +_fstat64 +#else +_fstati64 +#endif +#elif defined(__linux__) && defined(__USE_LARGEFILE64) +fstat64 +#else +fstat +#endif +(fd,__builtin_addressof(st))<0) + throw_posix_error(); + return struct_stat_to_posix_file_status(st); +} + +} + +template +inline posix_file_status status(basic_posix_io_observer piob) +{ +#if (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) && !defined(__CYGWIN__) + return status(static_cast>(piob)); +#else + return details::fstat_impl(piob.fd); +#endif +} + +#endif + +#if (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) && !defined(__CYGWIN__) +template +inline auto redirect_handle(basic_posix_io_observer h) noexcept +{ +#if (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) + return my_get_osfile_handle(h.fd); +#else + return h.fd; +#endif +} +#else + + +template +inline constexpr posix_io_redirection redirect(basic_posix_io_observer h) noexcept +{ + return {.fd=h.fd}; +} + +#endif + +#if (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) && !defined(__CYGWIN__) +template +requires io_controllable,Args...> +inline decltype(auto) io_control(basic_posix_io_observer h,Args&& ...args) +{ + return io_control(static_cast>(h),::std::forward(args)...); +} +#else + +namespace posix +{ +extern int ioctl(int, long unsigned, ...) noexcept __asm__("ioctl"); +} + + +template +requires requires(basic_posix_io_observer h,Args&& ...args) +{ + ::fast_io::posix::ioctl(h.fd,::std::forward(args)...); +} +inline void io_control(basic_posix_io_observer h,Args&& ...args) +{ +#if defined(__linux__) && defined(__NR_ioctl) + system_call_throw_error(system_call<__NR_ioctl,int>(h.fd,::std::forward(args)...)); +#else + if(::fast_io::posix::ioctl(h.fd,::std::forward(args)...)==-1) + throw_posix_error(); +#endif +} +#endif + +namespace details +{ + +#if (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) && !defined(__CYGWIN__) + +template +inline int open_fd_from_handle_impl(void* handle,open_mode md) +{ + int fd{::fast_io::noexcept_call(_open_osfhandle,reinterpret_cast(handle), + details::calculate_posix_open_mode_for_win32_handle(md))}; + if(fd==-1) + throw_posix_error(); + return fd; +} + +template +inline int open_fd_from_handle(void* handle,open_mode md) +{ + if constexpr(is_ebcdic) + return open_fd_from_handle_impl(handle,md); + else if constexpr(std::same_as) + return open_fd_from_handle_impl(handle,md); + else if constexpr(std::same_as) + return open_fd_from_handle_impl(handle,md); + else if constexpr(std::same_as) + return open_fd_from_handle_impl(handle,md); + else if constexpr(std::same_as) + return open_fd_from_handle_impl(handle,md); + else + return open_fd_from_handle_impl(handle,md); +} + +#else +#if defined(__NEWLIB__)||defined(__MSDOS__) || defined(_PICOLIBC__) + +template +inline int my_posix_openat(int,char const*,int,mode_t) +{ + if constexpr(always_terminate) + fast_terminate(); + else + throw_posix_error(EINVAL); +} +#else +template +inline int my_posix_openat(int dirfd,char const* pathname,int flags,mode_t mode) +{ + int fd{ +#if defined(__linux__) + system_call<__NR_openat,int> +#else + ::openat +#endif + (dirfd,pathname,flags,mode)}; + system_call_throw_error(fd); + return fd; +} +#endif + +#if defined(__CYGWIN__) + +#if (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +extern int my_cygwin_attach_handle_to_fd(char const* name, int fd, void* handle, int bin, int access) noexcept +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if defined(__GNUC__) +__asm__("cygwin_attach_handle_to_fd") +#else +__asm__("_cygwin_attach_handle_to_fd") +#endif +#else +__asm__("cygwin_attach_handle_to_fd") +#endif +; + +inline constexpr unsigned calculate_win32_cygwin_open_mode(open_mode value) +{ + unsigned access{}; + if((value&open_mode::out)==open_mode::out) + access|=0x80000000; + if((value&open_mode::in)==open_mode::in) + access|=0x40000000; + return access; +} + +inline int cygwin_create_fd_with_win32_handle(void* handle,open_mode mode) +{ + int fd{my_cygwin_attach_handle_to_fd(nullptr,-1,handle,true,static_cast(calculate_win32_cygwin_open_mode(mode)))}; + if(fd==-1) + throw_posix_error(); + return fd; +} + +#endif + +#ifdef __MSDOS__ +extern unsigned int my_dos_creat(char const*,short unsigned,int*) noexcept __asm__("__dos_creat"); +extern unsigned int my_dos_creatnew(char const*,short unsigned,int*) noexcept __asm__("__dos_creatnew"); +extern unsigned int my_dos_open(char const*,short unsigned,int*) noexcept __asm__("__dos_open"); +#endif +template +inline int my_posix_open(char const* pathname,int flags, +#if __has_cpp_attribute(maybe_unused) +[[maybe_unused]] +#endif +mode_t mode) +{ +#ifdef __MSDOS__ +/* +Referenced from +https://dl.acm.org/doi/pdf/10.1145/70931.70935?casa_token=rWDy5JyhhkMAAAAA:BdkF0zbbWgurns3mU3yEJI2HnHXWhe6wyYGtKxjRewlEgLg6lk-cGGNLZTTdr3vUjtFg6Cnia2b4 +An Example of Multiple Inheritance in C++: A Model of the Iostream Library +*/ + int fd{-1}; + unsigned int ret{}; + if(((flags&O_CREAT)==O_CREAT)) + { + if((flags&O_EXCL)!=O_EXCL) + ret=my_dos_creat(pathname,0,__builtin_addressof(fd)); + else + ret=my_dos_creatnew(pathname,0,__builtin_addressof(fd)); + } + else + ret=my_dos_open(pathname,static_cast(static_cast(flags)),__builtin_addressof(fd)); + if(ret) + { + if constexpr(always_terminate) + fast_terminate(); + else + throw_posix_error(); + } + return fd; +#elif (defined(__NEWLIB__) && !defined(AT_FDCWD)) || defined(_PICOLIBC__) + int fd{::open(pathname,flags,mode)}; + system_call_throw_error(fd); + return fd; +#else + return my_posix_openat(AT_FDCWD,pathname,flags,mode); +#endif +} + + +inline int my_posix_openat_file_internal_impl(int dirfd,char const* filepath,open_mode om,perms pm) +{ + return my_posix_openat(dirfd,filepath,details::calculate_posix_open_mode(om),static_cast(pm)); +} + +struct my_posix_at_open_paramter +{ + int dirfd{-1}; + int om{}; + mode_t pm{}; + inline int operator()(char const* filename) const + { + return my_posix_openat(dirfd,filename,om,pm); + } +}; + +struct my_posix_open_paramter +{ + int om{}; + mode_t pm{}; + inline int operator()(char const* filename) const + { + return my_posix_open(filename,om,pm); + } +}; + +#if defined(__MSDOS__) || (defined(__NEWLIB__) && !defined(AT_FDCWD)) || defined(_PICOLIBC__) + +template<::fast_io::constructible_to_os_c_str T> +inline constexpr int posix_openat_file_impl(int,T const&,open_mode,perms) +{ + throw_posix_error(EINVAL); + return -1; +} + +#else +template<::fast_io::constructible_to_os_c_str T> +inline constexpr int posix_openat_file_impl(int dirfd,T const& t,open_mode om,perms pm) +{ + return ::fast_io::posix_api_common(t,my_posix_at_open_paramter{dirfd,::fast_io::details::calculate_posix_open_mode(om),static_cast(pm)}); +} +#endif + +template<::fast_io::constructible_to_os_c_str T> +inline constexpr int posix_open_file_impl(T const& t,open_mode om,perms pm) +{ +#if defined(__MSDOS__) || (defined(__NEWLIB__) && !defined(AT_FDCWD)) || defined(_PICOLIBC__) + return ::fast_io::posix_api_common(t,my_posix_open_paramter{::fast_io::details::calculate_posix_open_mode(om),static_cast(pm)}); +#else + return ::fast_io::posix_api_common(t,my_posix_at_open_paramter{AT_FDCWD,::fast_io::details::calculate_posix_open_mode(om),static_cast(pm)}); +#endif +} + +#endif + +inline int my_open_posix_fd_temp_file() +{ +#if (defined(_WIN32) && !defined(__WINE__)&&!defined(__BIONIC__)) && !defined(__CYGWIN__) + ::fast_io::basic_win32_file wf(::fast_io::io_temp); + int fd{::fast_io::noexcept_call(_open_osfhandle,reinterpret_cast(wf.handle),_O_BINARY)}; + if(fd==-1) + throw_posix_error(); + wf.release(); + return fd; +#elif defined(__CYGWIN__) +/* +This implementation is not correct since cygwin runtime changes the tmp environment and it causes issues. +*/ + ::fast_io::basic_win32_file wf(::fast_io::io_temp); + constexpr int flag{static_cast(0x80000000|0x40000000)}; + int fd{my_cygwin_attach_handle_to_fd(nullptr,-1,wf.handle,true,flag)}; + if(fd==-1) + throw_posix_error(); + wf.release(); + return fd; +#elif defined(O_TMPFILE)&&defined(__linux__) + int fd{system_call<__NR_openat,int>(AT_FDCWD,u8"/tmp",O_EXCL|O_RDWR|O_TMPFILE|O_APPEND|O_NOATIME,S_IRUSR | S_IWUSR)}; + system_call_throw_error(fd); + return fd; +#else + throw_posix_error(EINVAL); +#endif +} + +} + +struct +#if __has_cpp_attribute(clang::trivially_relocatable) +[[clang::trivially_relocatable]] +#endif +posix_file_factory +{ + using native_handle_type = int; + int fd{-1}; + explicit constexpr posix_file_factory(int v) noexcept:fd(v){}; + posix_file_factory(posix_file_factory const&)=delete; + posix_file_factory& operator=(posix_file_factory const&)=delete; + ~posix_file_factory() + { + if(fd!=-1)[[likely]] + details::sys_close(fd); + } +}; + +template +class basic_posix_file:public basic_posix_io_observer +{ +public: + using typename basic_posix_io_observer::char_type; + using typename basic_posix_io_observer::native_handle_type; + using file_factory_type = posix_file_factory; + using basic_posix_io_observer::native_handle; + constexpr basic_posix_file() noexcept = default; + template + requires std::same_as> + explicit constexpr basic_posix_file(native_hd fd1) noexcept: basic_posix_io_observer{fd1}{} + + basic_posix_file(io_dup_t,basic_posix_io_observer piob):basic_posix_io_observer{details::sys_dup(piob.fd)} + {} + explicit constexpr basic_posix_file(posix_file_factory&& factory) noexcept: basic_posix_io_observer{factory.fd} + { + factory.fd=-1; + } + constexpr basic_posix_file(decltype(nullptr)) noexcept = delete; +#if (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) && !defined(__CYGWIN__) +//windows specific. open posix file from win32/nt/zw file + template + basic_posix_file(basic_win32_family_file&& hd,open_mode m): + basic_posix_io_observer{details::open_fd_from_handle(hd.handle,m)} + { + hd.release(); + } + template + basic_posix_file(basic_nt_family_file&& hd,open_mode m): + basic_posix_io_observer{details::open_fd_from_handle(hd.handle,m)} + { + hd.release(); + } + basic_posix_file(nt_fs_dirent fsdirent,open_mode om,perms pm=static_cast(436)): + basic_posix_file(basic_win32_file(fsdirent,om,pm),om){} + template<::fast_io::constructible_to_os_c_str T> + basic_posix_file(T const& file,open_mode om,perms pm=static_cast(436)): + basic_posix_file(basic_win32_file(file,om,pm),om) + {} + template<::fast_io::constructible_to_os_c_str T> + basic_posix_file(nt_at_entry nate,T const& file,open_mode om,perms pm=static_cast(436)): + basic_posix_file(basic_win32_file(nate,file,om,pm),om) + {} + +#else + +#if defined(__CYGWIN__) + template + basic_posix_file(basic_win32_family_file&& hd,open_mode m): + basic_posix_io_observer{details::cygwin_create_fd_with_win32_handle(hd.handle,m)} + { + hd.release(); + } + template + basic_posix_file(basic_nt_family_file&& hd,open_mode m): + basic_posix_io_observer{details::cygwin_create_fd_with_win32_handle(hd.handle,m)} + { + hd.release(); + } +#endif + basic_posix_file(posix_fs_dirent fsdirent,open_mode om,perms pm=static_cast(436)): + basic_posix_file(details::my_posix_openat_file_internal_impl(fsdirent.fd,fsdirent.filename,om,pm)){} +#if !defined(__wasi__) && __has_include() && __has_include() + basic_posix_file(sock_family d,sock_type t,open_mode m,sock_protocol p):basic_posix_io_observer{::fast_io::details::open_socket_impl(d,t,m,p)}{} +#endif + + template<::fast_io::constructible_to_os_c_str T> + explicit basic_posix_file(T const& filename,open_mode om,perms pm=static_cast(436)): + basic_posix_io_observer{::fast_io::details::posix_open_file_impl(filename,om,pm)} + {} + + template<::fast_io::constructible_to_os_c_str T> + explicit basic_posix_file(posix_at_entry pate,T const& filename,open_mode om,perms pm=static_cast(436)): + basic_posix_io_observer{::fast_io::details::posix_openat_file_impl(pate.fd,filename,om,pm)} + {} + +#endif + basic_posix_file(io_temp_t):basic_posix_io_observer{::fast_io::details::my_open_posix_fd_temp_file()}{} + + constexpr basic_posix_file(basic_posix_io_observer) noexcept=delete; + constexpr basic_posix_file& operator=(basic_posix_io_observer) noexcept=delete; + + basic_posix_file(basic_posix_file const& dp):basic_posix_io_observer{details::sys_dup(dp.fd)} + { + } + basic_posix_file& operator=(basic_posix_file const& dp) + { + this->fd=details::sys_dup2(dp.fd,this->fd); + return *this; + } + constexpr basic_posix_file(basic_posix_file&& __restrict b) noexcept : basic_posix_io_observer{b.fd} + { + b.fd = -1; + } + basic_posix_file& operator=(basic_posix_file&& __restrict b) noexcept + { + if(this->fd!=-1)[[likely]] + details::sys_close(this->fd); + this->fd=b.fd; + b.fd = -1; + return *this; + } + inline constexpr void reset(native_handle_type newfd=-1) noexcept + { + if(this->fd!=-1)[[likely]] + details::sys_close(this->fd); + this->fd=newfd; + } + void close() + { + if(this->fd!=-1)[[likely]] + details::sys_close_throw_error(this->fd); + } + ~basic_posix_file() + { + if(this->fd!=-1)[[likely]] + details::sys_close(this->fd); + } +}; +#if (!defined(__NEWLIB__) || defined(__CYGWIN__))&&!defined(_PICOLIBC__) + +namespace details +{ + +#if defined(__CYGWIN__) +#if (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if __has_cpp_attribute(__gnu__::__cdecl__) +[[__gnu__::__cdecl__]] +#endif +extern int ftruncate(int, off_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("ftruncate") +#else +__asm__("_ftruncate") +#endif +#else +__asm__("ftruncate") +#endif +#endif +; +#endif + +inline void posix_truncate_impl(int fd,std::uintmax_t size) +{ +#if (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) && !defined(__CYGWIN__) +#if (!defined(__MINGW32__) || __has_include(<_mingw_stat64.h>)) + if(size>static_cast(std::numeric_limits::max())) + throw_posix_error(EINVAL); + auto err(noexcept_call(_chsize_s,fd,static_cast(size))); + if(err) + throw_posix_error(err); +#else + if(size>std::numeric_limits::max()) + throw_posix_error(EINVAL); + auto err(noexcept_call(_chsize,fd,static_cast(size))); + if(err) + throw_posix_error(err); +#endif + +#elif defined(__linux__) && defined(__NR_ftruncate64) + system_call_throw_error(system_call<__NR_ftruncate64,int>(fd,size)); +#elif defined(__linux__) && defined(__NR_ftruncate) + system_call_throw_error(system_call<__NR_ftruncate,int>(fd,size)); +#else + if(noexcept_call(ftruncate,fd,static_cast(size))<0) + throw_posix_error(); +#endif +} + +} + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#endif +inline void truncate(basic_posix_io_observer h,std::uintmax_t size) +{ + details::posix_truncate_impl(h.fd,size); +} +#endif + +template +class basic_posix_pipe +{ +public: + using char_type = ch_type; + basic_posix_file pipes[2]; + basic_posix_pipe() + { +#if defined(__wasi__) + throw_posix_error(ENOTSUP); +#else + int a2[2]{-1,-1}; +#if (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) && !defined(__CYGWIN__) + if(noexcept_call(_pipe,a2,131072u,_O_BINARY)==-1) +#else + if(noexcept_call(::pipe,a2)==-1) +#endif + throw_posix_error(); + pipes->fd=*a2; + pipes[1].fd=a2[1]; +#endif + } + constexpr auto& in() noexcept + { + return *pipes; + } + constexpr auto& out() noexcept + { + return pipes[1]; + } +}; + +template +inline Iter read(basic_posix_pipe& h,Iter begin,Iter end) +{ + return read(h.in(),begin,end); +} +template +inline Iter write(basic_posix_pipe& h,Iter begin,Iter end) +{ + return write(h.out(),begin,end); +} + +template +inline void flush(basic_posix_pipe& pp) +{ + details::posix_flush_impl(pp.out().fd); + details::posix_flush_impl(pp.in().fd); +} + +#if (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) && !defined(__CYGWIN__) +template +inline ::fast_io::freestanding::array redirect_handle(basic_posix_pipe& h) +{ + return {__builtin_addressof(h.in().fd), + __builtin_addressof(h.out().fd)}; +} +#else +template +inline constexpr posix_io_redirection redirect(basic_posix_pipe& h) noexcept +{ + return {.pipe_fds=__builtin_addressof(h.in().fd)}; +} +#endif + +template +inline bool is_character_device(basic_posix_io_observer piob) noexcept +{ + return details::posix_is_character_device(piob.fd); +} + +template +inline void clear_screen(basic_posix_io_observer piob) +{ + details::posix_clear_screen_impl(piob.fd); +} + + +using posix_io_observer=basic_posix_io_observer; +using posix_file=basic_posix_file; +using posix_pipe=basic_posix_pipe; + +using wposix_io_observer=basic_posix_io_observer; +using wposix_file=basic_posix_file; +using wposix_pipe=basic_posix_pipe; + +using u8posix_io_observer=basic_posix_io_observer; +using u8posix_file=basic_posix_file; +using u8posix_pipe=basic_posix_pipe; + +using u16posix_io_observer=basic_posix_io_observer; +using u16posix_file=basic_posix_file; +using u16posix_pipe=basic_posix_pipe; + +using u32posix_io_observer=basic_posix_io_observer; +using u32posix_file=basic_posix_file; +using u32posix_pipe=basic_posix_pipe; + +inline constexpr int posix_stdin_number{0}; +inline constexpr int posix_stdout_number{1}; +inline constexpr int posix_stderr_number{2}; + +template +inline constexpr basic_posix_io_observer posix_stdin() +{ + return {posix_stdin_number}; +} +template +inline constexpr basic_posix_io_observer posix_stdout() +{ + return basic_posix_io_observer{posix_stdout_number}; +} +template +inline constexpr basic_posix_io_observer posix_stderr() +{ + return basic_posix_io_observer{posix_stderr_number}; +} + + +#if !defined(_WIN32) || defined(__WINE__) +template +inline constexpr basic_posix_io_observer native_stdin() noexcept +{ + return {posix_stdin_number}; +} +template +inline constexpr basic_posix_io_observer native_stdout() noexcept +{ + return basic_posix_io_observer{posix_stdout_number}; +} +template +inline constexpr basic_posix_io_observer native_stderr() noexcept +{ + return basic_posix_io_observer{posix_stderr_number}; +} + +#if defined(__CYGWIN__) || (!(defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) && !defined(__MSDOS__) && !defined(_PICOLIBC__)) +namespace details +{ + +#if defined(__NEWLIB__) && !defined(__CYGWIN__) +extern std::ptrdiff_t newlib_writev(int fd, struct iovec const* iov, int iovcnt) __asm__("writev"); +extern std::ptrdiff_t newlib_readv(int fd, struct iovec const* iov, int iovcnt) __asm__("readv"); +#endif + +inline std::size_t posix_scatter_read_size_impl(int fd,io_scatters_t sp) +{ +#if defined(__linux__) + static_assert(sizeof(unsigned long)==sizeof(std::size_t)); + auto val{system_call<__NR_readv,std::ptrdiff_t>(static_cast(fd),sp.base,sp.len)}; + system_call_throw_error(val); + return static_cast(val); +#elif defined(__wasi__) + using iovec_may_alias_const_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = __wasi_iovec_t const*; + std::size_t val{}; + auto err{noexcept_call(__wasi_fd_read,fd, + reinterpret_cast(sp.base),sp.len, + __builtin_addressof(val))}; + if(err) + throw_posix_error(err); + return val; +#else + std::size_t sz{sp.len}; + if(static_cast(std::numeric_limits::max())(std::numeric_limits::max()); + using iovec_may_alias_const_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = iovec const*; + auto ptr{reinterpret_cast(sp.base)}; +#if defined(__NEWLIB__) && !defined(__CYGWIN__) + std::ptrdiff_t val{newlib_readv(fd,ptr,static_cast(sz))}; +#else + std::ptrdiff_t val{noexcept_call(::readv,fd,ptr,static_cast(sz))}; +#endif + if(val<0) + throw_posix_error(); + return static_cast(val); +#endif +} + +inline constexpr io_scatter_status_t scatter_size_to_status(std::size_t sz,io_scatters_t sp) noexcept +{ + std::size_t total{sz}; + for(std::size_t i{};i!=sp.len;++i) + { + if(totallen}; + auto i{sp.base+1}; + auto e{sp.base+sp.len}; + for(;i!=e;++i) + { + std::size_t val{}; + __wasi_ciovec_t iovec{.buf = reinterpret_cast(i->base), .buf_len = i->len}; + auto err{noexcept_call(__wasi_fd_write,fd,__builtin_addressof(iovec),1u,__builtin_addressof(val))}; + if(err) + throw_posix_error(err); + total+=val; + if(val!=i->len) + return {total,static_cast(val),val}; + } + return {total,sp.len,0}; +} + +struct wasmtime_bug_code +{ + std::size_t val; + bool failed; +}; + +inline std::size_t wasmtime_bug_code_write_normal(int fd,io_scatters_t sp) +{ + using iovec_may_alias_const_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = __wasi_ciovec_t const*; + std::size_t val{}; + auto err{noexcept_call(__wasi_fd_write,fd,reinterpret_cast(sp.base), + sp.len,__builtin_addressof(val))}; + if(err) + throw_posix_error(err); + return val; +} + +inline io_scatter_status_t posix_scatter_wasmtime_bug_write_size_impl(int fd,io_scatters_t sp) +{ + auto val{wasmtime_bug_code_write_normal(fd,sp)}; + if(1len)[[unlikely]] + return wasmtime_bug_posix_scatter_write_cold(fd,sp); + return scatter_size_to_status(val,sp); +} +#else + +inline std::size_t posix_scatter_write_size_impl(int fd,io_scatters_t sp) +{ +#if defined(__linux__) + static_assert(sizeof(unsigned long)==sizeof(std::size_t)); + auto val{system_call<__NR_writev,std::ptrdiff_t>(static_cast(fd),sp.base,sp.len)}; + system_call_throw_error(val); + return static_cast(val); +#else + std::size_t sz{sp.len}; + if(static_cast(std::numeric_limits::max())(std::numeric_limits::max()); + using iovec_may_alias_const_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = iovec const*; + auto ptr{reinterpret_cast(sp.base)}; +#if defined(__NEWLIB__) && !defined(__CYGWIN__) + std::ptrdiff_t val{newlib_writev(fd,ptr,static_cast(sz))}; +#else + std::ptrdiff_t val{noexcept_call(::writev,fd,ptr,static_cast(sz))}; +#endif + if(val<0) + throw_posix_error(); + return static_cast(val); +#endif +} +#endif + + +inline io_scatter_status_t posix_scatter_write_impl(int fd,io_scatters_t sp) +{ +#ifdef __wasi__ + return posix_scatter_wasmtime_bug_write_size_impl(fd,sp); +#else + return scatter_size_to_status(posix_scatter_write_size_impl(fd,sp),sp); +#endif +} + +[[nodiscard]] inline io_scatter_status_t posix_scatter_read_impl(int fd,io_scatters_t sp) +{ + return scatter_size_to_status(posix_scatter_read_size_impl(fd,sp),sp); +} + +} + +#endif +#endif + +#if defined(__CYGWIN__) || ((!defined(__NEWLIB__)|| defined(FAST_IO_USE_NEWLIB_CUSTOM_WRITEV)) && !(defined(__BIONIC__)&&defined(_WIN32)) && !defined(__MSDOS__) && !defined(_PICOLIBC__)) + +template +[[nodiscard]] inline io_scatter_status_t scatter_read(basic_posix_io_observer h,io_scatters_t sp) +{ + return details::posix_scatter_read_impl(h.fd,sp); +} + +template +inline io_scatter_status_t scatter_write(basic_posix_io_observer h,io_scatters_t sp) +{ + return details::posix_scatter_write_impl(h.fd,sp); +} + +template +inline io_scatter_status_t scatter_read(basic_posix_pipe& h,io_scatters_t sp) +{ + return details::posix_scatter_read_impl(h.in().fd,sp); +} + +template +inline io_scatter_status_t scatter_write(basic_posix_pipe& h,io_scatters_t sp) +{ + return details::posix_scatter_write_impl(h.out().fd,sp); +} + +#endif + +#if _XOPEN_SOURCE >= 500 || _POSIX_C_SOURCE >= 200809L + +namespace details +{ + +inline std::size_t posix_pread_impl(int fd,void* address,std::size_t bytes_to_read,std::intmax_t offset) +{ + if constexpr(sizeof(std::intmax_t)>sizeof(off_t)) + { + if(static_cast(std::numeric_limits::max()) +#else + ::pread +#endif + (fd,address,bytes_to_read,static_cast(offset))); + system_call_throw_error(read_bytes); + return static_cast(read_bytes); +} + +inline std::size_t posix_pwrite_impl(int fd,void const* address,std::size_t bytes_to_write,std::intmax_t offset) +{ + if constexpr(sizeof(std::intmax_t)>sizeof(off_t)) + { + if(static_cast(std::numeric_limits::max()) +#else + ::pwrite +#endif + (fd,address,bytes_to_write,static_cast(offset))); + system_call_throw_error(written_bytes); + return static_cast(written_bytes); +} +#if !defined(__NEWLIB__) && (__BSD_VISIBLE || _BSD_SOURCE || _DEFAULT_SOURCE) +inline std::size_t posix_scatter_pread_size_impl(int fd,io_scatters_t sp,std::intmax_t offset) +{ + if constexpr(sizeof(std::intmax_t)>sizeof(off_t)) + { + if(static_cast(std::numeric_limits::max())(static_cast(fd),sp.base,sp.len,static_cast(offset))}; + system_call_throw_error(val); + return static_cast(val); +#else + using iovec_may_alias_const_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = iovec const*; + std::size_t sz{sp.len}; + if(static_cast(std::numeric_limits::max())(std::numeric_limits::max()); + auto ptr{reinterpret_cast(sp.base)}; + std::ptrdiff_t val{noexcept_call(::preadv,fd,ptr,static_cast(sz),static_cast(offset))}; + if(val<0) + throw_posix_error(); + return static_cast(val); +#endif +} + +inline std::size_t posix_scatter_pwrite_size_impl(int fd,io_scatters_t sp,std::intmax_t offset) +{ + if constexpr(sizeof(std::intmax_t)>sizeof(off_t)) + { + if(static_cast(std::numeric_limits::max())(static_cast(fd),sp.base,sp.len,static_cast(offset))}; + system_call_throw_error(val); + return static_cast(val); +#else + using iovec_may_alias_const_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = iovec const*; + std::size_t sz{sp.len}; + if(static_cast(std::numeric_limits::max())(std::numeric_limits::max()); + auto ptr{reinterpret_cast(sp.base)}; + std::ptrdiff_t val{noexcept_call(::pwritev,fd,ptr,static_cast(sz),static_cast(offset))}; + if(val<0) + throw_posix_error(); + return static_cast(val); +#endif +} + +inline io_scatter_status_t posix_scatter_pwrite_impl(int fd,io_scatters_t sp,std::intmax_t offset) +{ + return scatter_size_to_status(posix_scatter_pwrite_size_impl(fd,sp,offset),sp); +} + +[[nodiscard]] inline io_scatter_status_t posix_scatter_pread_impl(int fd,io_scatters_t sp,std::intmax_t offset) +{ + return scatter_size_to_status(posix_scatter_pread_size_impl(fd,sp,offset),sp); +} +#endif +} + +template +inline constexpr Iter pread(basic_posix_io_observer piob,Iter begin,Iter end,std::intmax_t offset) +{ + return begin+details::posix_pread_impl(piob.fd,::std::to_address(begin),(end-begin)*sizeof(*begin),offset)/sizeof(*begin); +} + +template +inline constexpr Iter pwrite(basic_posix_io_observer piob,Iter begin,Iter end,std::intmax_t offset) +{ + return begin+details::posix_pwrite_impl(piob.fd,::std::to_address(begin),(end-begin)*sizeof(*begin),offset)/sizeof(*begin); +} +#if !defined(__NEWLIB__) && (__BSD_VISIBLE || _BSD_SOURCE || _DEFAULT_SOURCE) +template +[[nodiscard]] inline io_scatter_status_t scatter_pread(basic_posix_io_observer piob,io_scatters_t sp,std::intmax_t offset) +{ + return details::posix_scatter_pread_impl(piob.fd,sp,offset); +} + +template +inline io_scatter_status_t scatter_pwrite(basic_posix_io_observer piob,io_scatters_t sp,std::intmax_t offset) +{ + return details::posix_scatter_pwrite_impl(piob.fd,sp,offset); +} +#endif +#endif +#if 0 +namespace freestanding +{ + +template +struct is_trivially_relocatable> +{ + inline static constexpr bool value = true; +}; + +} +#endif +} + +#if defined(__MSDOS__) || (defined(__BIONIC__)&&defined(_WIN32)) || ((defined(__NEWLIB__)||defined(_PICOLIBC__))&&!defined(FAST_IO_USE_NEWLIB_CUSTOM_WRITEV)&&!defined(__CYGWIN__)) +#include"msdos.h" +#endif + +#if defined(__linux__) && (defined(__NR_sendfile) || defined(__NR_sendfile64)) +#include"linux_zerocopy.h" +#endif diff --git a/src/fast_io/include/fast_io_hosted/platforms/posix_dns.h b/src/fast_io/include/fast_io_hosted/platforms/posix_dns.h new file mode 100644 index 0000000..b7570cd --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/posix_dns.h @@ -0,0 +1,236 @@ +#pragma once + +namespace fast_io +{ + +struct +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +posix_addrinfo +{ +int ai_flags{}; +int ai_family{}; +int ai_socktype{}; +int ai_protocol{}; +posix_socklen_t ai_addrlen{}; +#if defined(__BIONIC__) || defined(__BSD_VISIBLE) || defined(__CYGWIN__) || defined(__DARWIN_C_LEVEL) || defined(_PICOLIBC__) +char *ai_canonname{}; +posix_sockaddr *ai_addr{}; +#else +posix_sockaddr *ai_addr{}; +char *ai_canonname{}; +#endif +posix_addrinfo *ai_next{}; +}; + +namespace details +{ +extern int libc_getaddrinfo(char const *node, char const* service, + posix_addrinfo const *hints, + posix_addrinfo **res) noexcept __asm__("getaddrinfo"); + +extern void libc_freeaddrinfo(posix_addrinfo *res) noexcept __asm__("freeaddrinfo"); +} + +class posix_dns_io_observer +{ +public: + using char_type = char; + using native_handle_type = posix_addrinfo*; + native_handle_type res{}; + inline constexpr native_handle_type native_handle() const noexcept + { + return res; + } + explicit constexpr operator bool() noexcept + { + return res; + } + inline native_handle_type release() noexcept + { + native_handle_type temp{res}; + res=nullptr; + return temp; + } +}; + +struct posix_dns_iterator +{ + using native_handle_type = posix_addrinfo*; + native_handle_type res{}; +}; + +inline constexpr bool operator==(posix_dns_iterator a, ::std::default_sentinel_t) noexcept +{ + return a.res == nullptr; +} + +inline constexpr bool operator!=(posix_dns_iterator a, ::std::default_sentinel_t) noexcept +{ + return a.res; +} + +inline constexpr posix_dns_io_observer operator*(posix_dns_iterator d) noexcept +{ + return {d.res}; +} + +inline constexpr posix_dns_iterator& operator++(posix_dns_iterator& d) noexcept +{ + d.res = d.res->ai_next; + return d; +} + +inline constexpr posix_dns_iterator operator++(posix_dns_iterator& d, int) noexcept +{ + posix_dns_iterator temp{d}; + ++d; + return temp; +} + +namespace details +{ + +inline constexpr ::fast_io::ip_address posix_to_ip_address_with_ai_addr_impl(int ai_family,posix_sockaddr const* ai_addr) noexcept +{ + ::fast_io::ip_address ret; + switch(ai_family) + { + case AF_INET: + { + ::fast_io::details::my_memcpy(__builtin_addressof(ret.address.v4.address),__builtin_addressof(reinterpret_cast(ai_addr)->sin_addr),sizeof(posix_in_addr)); + ret.isv4=true; + break; + } + case AF_INET6: + { + ::fast_io::details::my_memcpy(__builtin_addressof(ret.address.v6.address),__builtin_addressof(reinterpret_cast(ai_addr)->sin6_addr),sizeof(posix_in6_addr)); + break; + } + } + return ret; +} + +inline constexpr ::fast_io::ip posix_to_ip_with_ai_addr_impl(int ai_family,posix_sockaddr const* ai_addr,std::uint_least16_t port) noexcept +{ + return ::fast_io::ip{posix_to_ip_address_with_ai_addr_impl(ai_family,ai_addr),port}; +} + +inline posix_addrinfo* my_getaddrinfo_impl(char const* node,char const* service,posix_addrinfo const* hints) +{ + posix_addrinfo* res{}; + int ec{libc_getaddrinfo(node,service,hints,__builtin_addressof(res))}; + if(ec) + throw_posix_error(ec); + return res; +} + +inline auto posix_dns_open_internal_impl(char const* node) +{ + constexpr posix_addrinfo info{.ai_family=AF_UNSPEC}; + return my_getaddrinfo_impl(node,nullptr,__builtin_addressof(info)); +} + +struct posix_dns_open_parameter +{ + inline auto operator()(char const* node_name_c_str) + { + return ::fast_io::details::posix_dns_open_internal_impl(node_name_c_str); + } +}; + +template +requires ::fast_io::constructible_to_os_c_str +inline constexpr auto posix_dns_open_impl(T const& t) +{ + return ::fast_io::posix_api_common(t,posix_dns_open_parameter{}); +} + +} + +inline constexpr ::fast_io::ip to_ip(posix_dns_io_observer d,std::uint_least16_t port) noexcept +{ + return fast_io::details::posix_to_ip_with_ai_addr_impl(d.res->ai_family,d.res->ai_addr,port); +} + +inline constexpr ::fast_io::ip_address to_ip_address(posix_dns_io_observer d) noexcept +{ + return fast_io::details::posix_to_ip_address_with_ai_addr_impl(d.res->ai_family,d.res->ai_addr); +} + +class +#if __has_cpp_attribute(clang::trivially_relocatable) +[[clang::trivially_relocatable]] +#endif +posix_dns_file:public posix_dns_io_observer +{ +public: + using typename posix_dns_io_observer::char_type; + using typename posix_dns_io_observer::native_handle_type; + constexpr posix_dns_file() noexcept = default; + constexpr posix_dns_file(posix_dns_io_observer) noexcept=delete; + constexpr posix_dns_file& operator=(posix_dns_io_observer) noexcept=delete; + template + requires std::same_as> + explicit constexpr posix_dns_file(native_hd res1) noexcept: posix_dns_io_observer(res1){} + explicit constexpr posix_dns_file(decltype(nullptr)) noexcept = delete; + posix_dns_file(char_type const* node,char_type const* service,posix_addrinfo const* hints):posix_dns_io_observer{details::my_getaddrinfo_impl(node,service,hints)}{} + template + requires ::fast_io::constructible_to_os_c_str + explicit posix_dns_file(T const& t):posix_dns_io_observer{::fast_io::details::posix_dns_open_impl(t)}{} + posix_dns_file(posix_dns_file const&)=delete; + posix_dns_file& operator=(posix_dns_file const&)=delete; + constexpr posix_dns_file(posix_dns_file&& __restrict other) noexcept: posix_dns_io_observer{other.res} + { + other.res=nullptr; + } + posix_dns_file& operator=(posix_dns_file&& __restrict other) noexcept + { + if(this->res)[[likely]] + details::libc_freeaddrinfo(this->res); + this->res=other.res; + other.res=nullptr; + return *this; + } + void close() noexcept + { + if(this->res)[[likely]] + { + details::libc_freeaddrinfo(this->res); + this->res=nullptr; + } + } + ~posix_dns_file() + { + if(this->res)[[likely]] + details::libc_freeaddrinfo(this->res); + } +}; + +inline constexpr posix_dns_iterator begin(posix_dns_io_observer pdniob) noexcept +{ + return {pdniob.res}; +} + +inline constexpr posix_dns_iterator cbegin(posix_dns_io_observer pdniob) noexcept +{ + return {pdniob.res}; +} + +inline constexpr ::std::default_sentinel_t end(posix_dns_io_observer) noexcept +{ + return {}; +} + +inline constexpr ::std::default_sentinel_t cend(posix_dns_io_observer) noexcept +{ + return {}; +} + +using native_addrinfo = posix_addrinfo; +using native_dns_io_observer = posix_dns_io_observer; +using native_dns_file = posix_dns_file; +using native_dns_iterator = posix_dns_iterator; + +} diff --git a/src/fast_io/include/fast_io_hosted/platforms/posix_file_lock.h b/src/fast_io/include/fast_io_hosted/platforms/posix_file_lock.h new file mode 100644 index 0000000..2833320 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/posix_file_lock.h @@ -0,0 +1,150 @@ +#pragma once +namespace fast_io +{ + +namespace details +{ +inline int fcntl_file_lock(int fd,int cmd,struct flock const* lockp) +{ + return ::fcntl(fd,cmd,__builtin_addressof(lockp)); +} + +inline void posix_file_lock_lock_common_impl(int fd,struct flock const& lockp) +{ +#if defined(__linux__) && defined(__NR_fcntl) + system_call_throw_error(system_call<__NR_fcntl,int>(fd,F_SETLKW,__builtin_addressof(lockp))); +#else + int ret{noexcept_call(fcntl_file_lock,fd,F_SETLKW,__builtin_addressof(lockp))}; + if(ret<0) + { + throw_posix_error(); + } +#endif +} + +inline constexpr short flock_type_to_native(file_lock_mode t) noexcept +{ + switch(t) + { + case file_lock_mode::shared_lock: + { + return F_RDLCK; + } + case file_lock_mode::unlock: + { + return F_UNLCK; + } + default: + { + return F_WRLCK; + } + } +} + +template +inline void posix_file_lock_lock_impl(int fd,basic_flock_request const& __restrict t) +{ + using flock_off_type = decltype(flock::l_start); + if constexpr(sizeof(flock_off_type)::min()}; + constexpr int_type flock_off_max{std::numeric_limits::max()}; + if(t.start(t.start); + temp.l_whence=static_cast(t.whence); + temp.l_pid = -1; + temp.l_len = static_cast(t.len); + posix_file_lock_lock_common_impl(fd,temp); +} + +inline bool posix_file_lock_try_lock_common_impl(int fd,struct flock const& lockp) noexcept +{ +#if defined(__linux__) && defined(__NR_fcntl) + return !linux_system_call_fails(system_call<__NR_fcntl,int>(fd,F_SETLK,__builtin_addressof(lockp))); +#else + int ret{noexcept_call(fcntl_file_lock,fd,F_SETLK,__builtin_addressof(lockp))}; + return 0<=ret; +#endif +} + +template +inline bool posix_file_lock_try_lock_impl(int fd,basic_flock_request const& __restrict t) noexcept +{ + using flock_off_type = decltype(flock::l_start); + if constexpr(sizeof(flock_off_type)::min()}; + constexpr int_type flock_off_max{std::numeric_limits::max()}; + if(t.start(t.start); + temp.l_whence=static_cast(t.whence); + temp.l_pid = -1; + temp.l_len = static_cast(t.len); + return posix_file_lock_try_lock_common_impl(fd,temp); +} + + +template +inline void posix_file_lock_unlock_impl(int fd,basic_flock_request const& __restrict t) noexcept +{ + using flock_off_type = decltype(flock::l_start); + if constexpr(sizeof(flock_off_type)::min()}; + constexpr int_type flock_off_max{std::numeric_limits::max()}; + if(t.start(t.start); + temp.l_whence=static_cast(t.whence); + temp.l_pid = -1; + temp.l_len = static_cast(t.len); +#if defined(__linux__) && defined(__NR_fcntl) + system_call<__NR_fcntl,int>(fd,F_SETLKW,__builtin_addressof(temp)); +#else + noexcept_call(fcntl_file_lock,fd,F_SETLKW,__builtin_addressof(temp)); +#endif +} + +} + +struct posix_file_lock +{ + int fd{-1}; + template + inline void lock(basic_flock_request const& __restrict t) + { + ::fast_io::details::posix_file_lock_lock_impl(this->fd,t); + } + template + inline void unlock(basic_flock_request const& __restrict t) noexcept + { + ::fast_io::details::posix_file_lock_unlock_impl(this->fd,t); + } + template + inline void try_lock(basic_flock_request const& __restrict t) + { + ::fast_io::details::posix_file_lock_lock_impl(this->fd,t); + } +}; + +} diff --git a/src/fast_io/include/fast_io_hosted/platforms/posix_mapping.h b/src/fast_io/include/fast_io_hosted/platforms/posix_mapping.h new file mode 100644 index 0000000..975d493 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/posix_mapping.h @@ -0,0 +1,255 @@ +#pragma once +#include +#include + +namespace fast_io +{ + +namespace details +{ + +inline std::byte* sys_mmap(void *addr, size_t len, int prot, int flags, int fd, std::uintmax_t offset) +{ +#if defined(__linux__) && defined(__NR_mmap) && !defined(__NR_mmap2) + if constexpr(sizeof(std::uintmax_t)>sizeof(off_t)) + { + if(offset>static_cast(std::numeric_limits::max())) + throw_posix_error(EINVAL); + } + std::intptr_t ret{system_call<__NR_mmap,std::intptr_t>(addr,len,prot,flags,fd,offset)}; + system_call_throw_error(ret); + return reinterpret_cast(ret); +#elif defined(HAVE_MMAP64) + if constexpr(sizeof(std::uintmax_t)>sizeof(off64_t)) + { + if(offset>static_cast(std::numeric_limits::max())) + throw_posix_error(EINVAL); + } + auto ret{reinterpret_cast(mmap64(addr,len,prot,flags,fd,offset))}; + if(ret==MAP_FAILED) + throw_posix_error(); + return ret; +#else + if constexpr(sizeof(std::uintmax_t)>sizeof(off_t)) + { + if(offset>static_cast(std::numeric_limits::max())) + throw_posix_error(EINVAL); + } + auto ret{reinterpret_cast(mmap(addr,len,prot,flags,fd,static_cast(static_cast>(offset))))}; + if(ret==MAP_FAILED) + throw_posix_error(); + return ret; +#endif +} + +inline int sys_munmap(void *addr, size_t len) +{ + return +#if defined(__linux__) && defined(__NR_munmap) + system_call<__NR_munmap,int>(addr,len); +#else + munmap(addr,len); +#endif +} + +inline void sys_munmap_throw_error(void *addr, std::size_t len) +{ + system_call_throw_error(sys_munmap(addr,len)); +} +} + +enum class posix_file_map_attribute +{ +none=PROT_NONE,write=PROT_WRITE,execute=PROT_EXEC,read=PROT_READ +}; + +constexpr posix_file_map_attribute operator&(posix_file_map_attribute x, posix_file_map_attribute y) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(static_cast(x) & static_cast(y)); +} + +constexpr posix_file_map_attribute operator|(posix_file_map_attribute x, posix_file_map_attribute y) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(static_cast(x) | static_cast(y)); +} + +constexpr posix_file_map_attribute operator^(posix_file_map_attribute x, posix_file_map_attribute y) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(static_cast(x) ^ static_cast(y)); +} + +constexpr posix_file_map_attribute operator~(posix_file_map_attribute x) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(~static_cast(x)); +} + +inline posix_file_map_attribute& operator&=(posix_file_map_attribute& x, posix_file_map_attribute y) noexcept{return x=x&y;} + +inline posix_file_map_attribute& operator|=(posix_file_map_attribute& x, posix_file_map_attribute y) noexcept{return x=x|y;} + +inline posix_file_map_attribute& operator^=(posix_file_map_attribute& x, posix_file_map_attribute y) noexcept{return x=x^y;} + +inline constexpr posix_file_map_attribute to_posix_file_map_attribute(file_map_attribute x) +{ + switch(x) + { + case file_map_attribute::execute_read:return posix_file_map_attribute::execute|posix_file_map_attribute::read; + case file_map_attribute::execute_read_write:return posix_file_map_attribute::execute|posix_file_map_attribute::read; + case file_map_attribute::execute_write_copy:return posix_file_map_attribute::execute|posix_file_map_attribute::write; + case file_map_attribute::read_only:return posix_file_map_attribute::read; + case file_map_attribute::read_write:return posix_file_map_attribute::read|posix_file_map_attribute::write; + case file_map_attribute::write_copy:return posix_file_map_attribute::write; + default: + throw_posix_error(EINVAL); + }; +} + +class posix_memory_map_file +{ +public: + using value_type = std::byte; + using pointer = value_type*; + using const_pointer = value_type const*; + using const_iterator = const_pointer; + using iterator = pointer; + using reference = value_type&; + using const_reference = value_type const&; + using size_type = std::size_t; + using difference_type = std::ptrdiff_t; + using const_reverse_iterator = std::reverse_iterator; + using reverse_iterator = std::reverse_iterator; + pointer address_begin{},address_end{}; + constexpr posix_memory_map_file()=default; + constexpr posix_memory_map_file(std::byte* addbg,std::byte* added):address_begin{addbg},address_end{added} + {} + posix_memory_map_file(posix_at_entry bf,file_map_attribute attr,std::size_t bytes,std::uintmax_t start_address=0) + :address_begin{details::sys_mmap(nullptr,bytes,static_cast(to_posix_file_map_attribute(attr)),MAP_SHARED,bf.fd,start_address)}, + address_end{address_begin+bytes} + {} + posix_memory_map_file(posix_memory_map_file const&)=delete; + posix_memory_map_file& operator=(posix_memory_map_file const&)=delete; + posix_memory_map_file(posix_memory_map_file&& __restrict other) noexcept:address_begin{other.address_begin},address_end{other.address_end} + { + other.address_end=other.address_begin=reinterpret_cast(MAP_FAILED); + } + posix_memory_map_file& operator=(posix_memory_map_file&& __restrict other) noexcept + { + if(this->address_begin!=reinterpret_cast(MAP_FAILED))[[likely]] + details::sys_munmap(this->address_begin,static_cast(address_end-address_begin)); + this->address_begin=other.address_begin; + this->address_end=other.address_end; + other.address_begin=reinterpret_cast(MAP_FAILED); + other.address_end=reinterpret_cast(MAP_FAILED); + return *this; + } + constexpr pointer data() const noexcept + { + return address_begin; + } + constexpr bool empty() const noexcept + { + return address_begin==address_end; + } + constexpr std::size_t size() const noexcept + { + return static_cast(address_end-address_begin); + } + constexpr const_iterator cbegin() const noexcept + { + return address_begin; + } + constexpr const_iterator begin() const noexcept + { + return address_begin; + } + constexpr iterator begin() noexcept + { + return address_begin; + } + constexpr const_iterator cend() const noexcept + { + return address_end; + } + constexpr const_iterator end() const noexcept + { + return address_end; + } + constexpr iterator end() noexcept + { + return address_end; + } + constexpr std::size_t max_size() const noexcept + { + return SIZE_MAX; + } + constexpr const_reverse_iterator crbegin() const noexcept + { + return const_reverse_iterator{address_end}; + } + constexpr reverse_iterator rbegin() noexcept + { + return reverse_iterator{address_end}; + } + constexpr const_reverse_iterator rbegin() const noexcept + { + return const_reverse_iterator{address_end}; + } + constexpr const_reverse_iterator crend() const noexcept + { + return const_reverse_iterator{address_begin}; + } + constexpr reverse_iterator rend() noexcept + { + return reverse_iterator{address_begin}; + } + constexpr const_reverse_iterator rend() const noexcept + { + return const_reverse_iterator{address_begin}; + } + constexpr const_reference front() const noexcept + { + return *address_begin; + } + constexpr reference front() noexcept + { + return *address_begin; + } + constexpr const_reference back() const noexcept + { + return address_end[-1]; + } + constexpr reference back() noexcept + { + return address_end[-1]; + } + constexpr reference operator[](size_type pos) noexcept + { + return address_begin[pos]; + } + constexpr const_reference operator[](size_type pos) const noexcept + { + return address_begin[pos]; + } + void close() noexcept + { + if(this->address_begin!=MAP_FAILED)[[likely]] + { + auto ret{details::sys_munmap(this->address_begin,static_cast(address_end-address_begin))}; + this->address_end=this->address_begin=reinterpret_cast(MAP_FAILED); + system_call_throw_error(ret); + } + } + ~posix_memory_map_file() + { + if(this->address_begin!=MAP_FAILED)[[likely]] + details::sys_munmap(this->address_begin,static_cast(address_end-address_begin)); + } +}; + +using native_memory_map_file = posix_memory_map_file; + +} diff --git a/src/fast_io/include/fast_io_hosted/platforms/posix_netmode.h b/src/fast_io/include/fast_io_hosted/platforms/posix_netmode.h new file mode 100644 index 0000000..870e587 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/posix_netmode.h @@ -0,0 +1,744 @@ +#pragma once + + +namespace fast_io +{ + +using posix_socklen_t=::socklen_t; +using native_socklen_t=posix_socklen_t; + +inline constexpr int to_posix_sock_family(sock_family dom) noexcept +{ +switch(dom) +{ +#ifdef AF_ALG +case sock_family::alg: + return AF_ALG; +#endif +#ifdef AF_APPLETALK +case sock_family::appletalk: + return AF_APPLETALK; +#endif +#ifdef AF_ARP +case sock_family::arp: + return AF_ARP; +#endif +#ifdef AF_ASH +case sock_family::ash: + return AF_ASH; +#endif +#ifdef AF_ATM +case sock_family::atm: + return AF_ATM; +#endif +#ifdef AF_ATMPVC +case sock_family::atmpvc: + return AF_ATMPVC; +#endif +#ifdef AF_ATMSVC +case sock_family::atmsvc: + return AF_ATMSVC; +#endif +#ifdef AF_AX25 +case sock_family::ax25: + return AF_AX25; +#endif +#ifdef AF_BAN +case sock_family::ban: + return AF_BAN; +#endif +#ifdef AF_BLUETOOTH +case sock_family::bluetooth: + return AF_BLUETOOTH; +#endif +#ifdef AF_BRIDGE +case sock_family::bridge: + return AF_BRIDGE; +#endif +#ifdef AF_CAIF +case sock_family::caif: + return AF_CAIF; +#endif +#ifdef AF_CAN +case sock_family::can: + return AF_CAN; +#endif +#ifdef AF_CCITT +case sock_family::ccitt: + return AF_CCITT; +#endif +#ifdef AF_CHAOS +case sock_family::chaos: + return AF_CHAOS; +#endif +#ifdef AF_CLUSTER +case sock_family::cluster: + return AF_CLUSTER; +#endif +#ifdef AF_CNT +case sock_family::cnt: + return AF_CNT; +#endif +#ifdef AF_COIP +case sock_family::coip: + return AF_COIP; +#endif +#ifdef AF_DATAKIT +case sock_family::datakit: + return AF_DATAKIT; +#endif +#ifdef AF_DECnet +case sock_family::decnet: + return AF_DECnet; +#endif +#ifdef AF_DII +case sock_family::dii: + return AF_DII; +#endif +#ifdef AF_ECMA +case sock_family::ecma: + return AF_ECMA; +#endif +#ifdef AF_ECONET +case sock_family::econet: + return AF_ECONET; +#endif +#ifdef AF_FIREFOX +case sock_family::firefox: + return AF_FIREFOX; +#endif +#ifdef AF_HYLINK +case sock_family::hylink: + return AF_HYLINK; +#endif +#ifdef AF_HYPERV +case sock_family::hyperv: + return AF_HYPERV; +#endif +#ifdef AF_IB +case sock_family::ib: + return AF_IB; +#endif +#ifdef AF_IEEE12844 +case sock_family::ieee12844: + return AF_IEEE12844; +#endif +#ifdef AF_IEEE80211 +case sock_family::ieee80211: + return AF_IEEE80211; +#endif +#ifdef AF_IEEE802154 +case sock_family::ieee802154: + return AF_IEEE802154; +#endif +#ifdef AF_IMPLINK +case sock_family::implink: + return AF_IMPLINK; +#endif +#ifdef AF_INET +case sock_family::inet: + return AF_INET; +#endif +#ifdef AF_INET6 +case sock_family::inet6: + return AF_INET6; +#endif +#ifdef AF_INET6_SDP +case sock_family::inet6_sdp: + return AF_INET6_SDP; +#endif +#ifdef AF_INET_SDP +case sock_family::inet_sdp: + return AF_INET_SDP; +#endif +#ifdef AF_IPX +case sock_family::ipx: + return AF_IPX; +#endif +#ifdef AF_IRDA +case sock_family::irda: + return AF_IRDA; +#endif +#ifdef AF_ISDN +case sock_family::isdn: + return AF_ISDN; +#endif +#ifdef AF_ISO +case sock_family::iso: + return AF_ISO; +#endif +#ifdef AF_IUCV +case sock_family::iucv: + return AF_IUCV; +#endif +#ifdef AF_KCM +case sock_family::kcm: + return AF_KCM; +#endif +#ifdef AF_KEY +case sock_family::key: + return AF_KEY; +#endif +#ifdef AF_LAT +case sock_family::lat: + return AF_LAT; +#endif +#ifdef AF_LINK +case sock_family::link: + return AF_LINK; +#endif +#ifdef AF_LLC +case sock_family::llc: + return AF_LLC; +#endif +#ifdef AF_LOCAL +case sock_family::local: + return AF_LOCAL; +#endif +#ifdef AF_MPLS +case sock_family::mpls: + return AF_MPLS; +#endif +#ifdef AF_NATM +case sock_family::natm: + return AF_NATM; +#endif +#ifdef AF_NETBEUI +case sock_family::netbeui: + return AF_NETBEUI; +#endif +#ifdef AF_NETBIOS +case sock_family::netbios: + return AF_NETBIOS; +#endif +#ifdef AF_NETGRAPH +case sock_family::netgraph: + return AF_NETGRAPH; +#endif +#ifdef AF_NETROM +case sock_family::netrom: + return AF_NETROM; +#endif +#ifdef AF_NETDES +case sock_family::netdes: + return AF_NETDES; +#endif +#ifdef AF_NFC +case sock_family::nfc: + return AF_NFC; +#endif +#ifdef AF_PACKET +case sock_family::packet: + return AF_PACKET; +#endif +#ifdef AF_PHONET +case sock_family::phonet: + return AF_PHONET; +#endif +#ifdef AF_PPPOX +case sock_family::pppox: + return AF_PPPOX; +#endif +#ifdef AF_pseudo_HDRCMPLT +case sock_family::pseudo_hdrcmplt: + return AF_pseudo_HDRCMPLT; +#endif +#ifdef AF_pseudo_KEY +case sock_family::pseudo_key: + return AF_pseudo_KEY; +#endif +#ifdef AF_pseudo_PIP +case sock_family::pseudo_pip: + return AF_pseudo_PIP; +#endif +#ifdef AF_pseudo_RTIP +case sock_family::pseudo_rtip: + return AF_pseudo_RTIP; +#endif +#ifdef AF_pseudo_XTP +case sock_family::pseudo_xtp: + return AF_pseudo_XTP; +#endif +#ifdef AF_pseudo_PUP +case sock_family::pseudo_pup: + return AF_pseudo_PUP; +#endif +#ifdef AF_QIPCRTR +case sock_family::qipcrtr: + return AF_QIPCRTR; +#endif +#ifdef AF_RDS +case sock_family::rds: + return AF_RDS; +#endif +#ifdef AF_ROSE +case sock_family::rose: + return AF_ROSE; +#endif +#ifdef AF_ROUTE +case sock_family::route: + return AF_ROUTE; +#endif +#ifdef AF_RXRPC +case sock_family::rxrpc: + return AF_RXRPC; +#endif +#ifdef AF_SCLUSTER +case sock_family::scluster: + return AF_SCLUSTER; +#endif +#ifdef AF_SECURITY +case sock_family::security: + return AF_SECURITY; +#endif +#ifdef AF_SIP +case sock_family::sip: + return AF_SIP; +#endif +#ifdef AF_SLOW +case sock_family::slow: + return AF_SLOW; +#endif +#ifdef AF_SMC +case sock_family::smc: + return AF_SMC; +#endif +#ifdef AF_SNA +case sock_family::sna: + return AF_SNA; +#endif +#ifdef AF_TCNPROCESS +case sock_family::tcnprocess: + return AF_TCNPROCESS; +#endif +#ifdef AF_TCNMESSAGE +case sock_family::tcnmessage: + return AF_TCNMESSAGE; +#endif +#ifdef AF_TIPC +case sock_family::tipc: + return AF_TIPC; +#endif +#ifdef AF_VOICEVIEW +case sock_family::voiceview: + return AF_VOICEVIEW; +#endif +#ifdef AF_VSOCK +case sock_family::vsock: + return AF_VSOCK; +#endif +#ifdef AF_WANPIPE +case sock_family::wanpipe: + return AF_WANPIPE; +#endif +#ifdef AF_X25 +case sock_family::x25: + return AF_X25; +#endif +#ifdef AF_XDP +case sock_family::xdp: + return AF_XDP; +#endif +default: +#ifdef AF_UNSPEC + return AF_UNSPEC; +#else + return -1; +#endif +} +} + +inline constexpr int to_native_sock_family(sock_family dom) noexcept +{ + return to_posix_sock_family(dom); +} + +inline constexpr int to_posix_sock_protocol(sock_protocol dom) noexcept +{ +switch(dom) +{ +#ifdef IPPROTO_AH +case sock_protocol::ah: + return IPPROTO_AH; +#endif +#ifdef IPPROTO_BEETPH +case sock_protocol::beetph: + return IPPROTO_BEETPH; +#endif +#ifdef IPPROTO_CARP +case sock_protocol::carp: + return IPPROTO_CARP; +#endif +#ifdef IPPROTO_CBT +case sock_protocol::cbt: + return IPPROTO_CBT; +#endif +#ifdef IPPROTO_COMP +case sock_protocol::comp: + return IPPROTO_COMP; +#endif +#ifdef IPPROTO_DCCP +case sock_protocol::dccp: + return IPPROTO_DCCP; +#endif +#ifdef IPPROTO_DSTOPTS +case sock_protocol::dstopts: + return IPPROTO_DSTOPTS; +#endif +#ifdef IPPROTO_EGP +case sock_protocol::egp: + return IPPROTO_EGP; +#endif +#ifdef IPPROTO_EIGRP +case sock_protocol::eigrp: + return IPPROTO_EIGRP; +#endif +#ifdef IPPROTO_ENCAP +case sock_protocol::encap: + return IPPROTO_ENCAP; +#endif +#ifdef IPPROTO_ESP +case sock_protocol::esp: + return IPPROTO_ESP; +#endif +#ifdef IPPROTO_ETHERNET +case sock_protocol::ethernet: + return IPPROTO_ETHERNET; +#endif +#ifdef IPPROTO_FRAGMENT +case sock_protocol::fragment: + return IPPROTO_FRAGMENT; +#endif +#ifdef IPPROTO_GGP +case sock_protocol::ggp: + return IPPROTO_GGP; +#endif +#ifdef IPPROTO_GRE +case sock_protocol::gre: + return IPPROTO_GRE; +#endif +#ifdef IPPROTO_HOPOPTS +case sock_protocol::hopopts: + return IPPROTO_HOPOPTS; +#endif +#ifdef IPPROTO_ICLFXBM +case sock_protocol::iclfxbm: + return IPPROTO_ICLFXBM; +#endif +#ifdef IPPROTO_ICMP +case sock_protocol::icmp: + return IPPROTO_ICMP; +#endif +#ifdef IPPROTO_ICMPV6 +case sock_protocol::icmpv6: + return IPPROTO_ICMPV6; +#endif +#ifdef IPPROTO_IDP +case sock_protocol::idp: + return IPPROTO_IDP; +#endif +#ifdef IPPROTO_IGMP +case sock_protocol::igmp: + return IPPROTO_IGMP; +#endif +#ifdef IPPROTO_IGP +case sock_protocol::igp: + return IPPROTO_IGP; +#endif +#ifdef IPPROTO_IP +case sock_protocol::ip: + return IPPROTO_IP; +#endif +#ifdef IPPROTO_IPV4 +case sock_protocol::ipv4: + return IPPROTO_IPV4; +#endif +#ifdef IPPROTO_IPV6 +case sock_protocol::ipv6: + return IPPROTO_IPV6; +#endif +#ifdef IPPROTO_L2TP +case sock_protocol::l2tp: + return IPPROTO_L2TP; +#endif +#ifdef IPPROTO_MOBILE +case sock_protocol::mobile: + return IPPROTO_MOBILE; +#endif +#ifdef IPPROTO_MOBILITY +case sock_protocol::mobility: + return IPPROTO_MOBILITY; +#endif +#ifdef IPPROTO_MOBILITY_OLD +case sock_protocol::mobility_old: + return IPPROTO_MOBILITY_OLD; +#endif +#ifdef IPPROTO_MPLS +case sock_protocol::mpls: + return IPPROTO_MPLS; +#endif +#ifdef IPPROTO_MPTCP +case sock_protocol::mptcp: + return IPPROTO_MPTCP; +#endif +#ifdef IPPROTO_MTP +case sock_protocol::mtp: + return IPPROTO_MTP; +#endif +#ifdef IPPROTO_ND +case sock_protocol::nd: + return IPPROTO_ND; +#endif +#ifdef IPPROTO_NONE +case sock_protocol::none: + return IPPROTO_NONE; +#endif +#ifdef IPPROTO_OSPF +case sock_protocol::ospf: + return IPPROTO_OSPF; +#endif +#ifdef IPPROTO_PGM +case sock_protocol::pgm: + return IPPROTO_PGM; +#endif +#ifdef IPPROTO_PIGP +case sock_protocol::pigp: + return IPPROTO_PIGP; +#endif +#ifdef IPPROTO_PIM +case sock_protocol::pim: + return IPPROTO_PIM; +#endif +#ifdef IPPROTO_PUP +case sock_protocol::pup: + return IPPROTO_PUP; +#endif +#ifdef IPPROTO_RAW +case sock_protocol::raw: + return IPPROTO_RAW; +#endif +#ifdef IPPROTO_RDP +case sock_protocol::rdp: + return IPPROTO_RDP; +#endif +#ifdef IPPROTO_ROUTING +case sock_protocol::routing: + return IPPROTO_ROUTING; +#endif +#ifdef IPPROTO_RSVP +case sock_protocol::rsvp: + return IPPROTO_RSVP; +#endif +#ifdef IPPROTO_SCTP +case sock_protocol::sctp: + return IPPROTO_SCTP; +#endif +#ifdef IPPROTO_ST +case sock_protocol::st: + return IPPROTO_ST; +#endif +#ifdef IPPROTO_TCP +case sock_protocol::tcp: + return IPPROTO_TCP; +#endif +#ifdef IPPROTO_TP +case sock_protocol::tp: + return IPPROTO_TP; +#endif +#ifdef IPPROTO_UDP +case sock_protocol::udp: + return IPPROTO_UDP; +#endif +#ifdef IPPROTO_UDPLITE +case sock_protocol::udplite: + return IPPROTO_UDPLITE; +#endif +#ifdef IPPROTO_VRRP +case sock_protocol::vrrp: + return IPPROTO_VRRP; +#endif +default: + return -1; +} +} + +inline constexpr int to_native_sock_protocol(sock_protocol prot) noexcept +{ + return to_posix_sock_protocol(prot); +} + +inline constexpr int to_posix_sock_type(sock_type soc) noexcept +{ +switch(soc) +{ +#ifdef SOCK_STREAM +case sock_type::stream: + return SOCK_STREAM; +#endif +#ifdef SOCK_DGRAM +case sock_type::dgram: + return SOCK_DGRAM; +#endif +#ifdef SOCK_SEQPACKET +case sock_type::seqpacket: + return SOCK_SEQPACKET; +#endif +#ifdef SOCK_RAW +case sock_type::raw: + return SOCK_RAW; +#endif +#ifdef SOCK_RDM +case sock_type::rdm: + return SOCK_RDM; +#endif +#ifdef SOCK_PACKET +case sock_type::packet: + return SOCK_PACKET; +#endif +default: + return -1; +}; +} + +inline constexpr int to_native_sock_type(sock_type soc) noexcept +{ + return to_posix_sock_type(soc); +} + +inline constexpr int to_posix_sock_open_mode(open_mode om) noexcept +{ + int ret{ +#ifdef SOCK_CLOEXEC + SOCK_CLOEXEC +#endif + }; + if((om&open_mode::inherit)==open_mode::inherit) + ret=0; + if((om&open_mode::no_block)==open_mode::no_block) +#ifdef SOCK_NONBLOCK + ret|=SOCK_NONBLOCK; +#else + ret=-1; +#endif + return ret; +} + +inline constexpr int to_native_sock_open_mode(open_mode om) noexcept +{ + return to_posix_sock_open_mode(om); +} + + +namespace details +{ + +inline int sys_socket(int domain,int type, int protocol) +{ +#if defined(__linux__) && defined(__NR_socket) + int fd{system_call<__NR_socket,int>(domain,type,protocol)}; + system_call_throw_error(fd); + return fd; +#else + int fd{socket(domain,type,protocol)}; + if(fd==-1) + throw_posix_error(); + return fd; +#endif +} + +inline int open_socket_impl(sock_family d,sock_type t,open_mode m,sock_protocol p) +{ + return sys_socket(to_posix_sock_family(d),to_posix_sock_type(t)|to_posix_sock_open_mode(m),to_posix_sock_protocol(p)); +} + + +inline std::size_t posix_socket_write_impl(int fd, void const* data,std::size_t to_write) +{ +#if defined(__linux__) && defined(__NR_send) + std::ptrdiff_t written{system_call<__NR_send,std::ptrdiff_t>(fd,data,to_write)}; + system_call_throw_error(written); + return static_cast(written); +#else + std::ptrdiff_t written{send(fd,data,to_write,0)}; + if(written<0) + throw_posix_error(); + return static_cast(written); +#endif +} + +inline std::size_t posix_socket_read_impl(int fd, void* data,std::size_t to_write) +{ +#if defined(__linux__) && defined(__NR_recv) + std::ptrdiff_t written{system_call<__NR_recv,std::ptrdiff_t>(fd,data,to_write)}; + system_call_throw_error(written); + return static_cast(written); +#else + std::ptrdiff_t written{recv(fd,data,to_write,0)}; + if(written<0) + throw_posix_error(); + return static_cast(written); +#endif +} + +inline void posix_connect_posix_socket_impl(int fd,void const* addr,posix_socklen_t addrlen) +{ +#if defined(__linux__) && defined(__NR_connect) + system_call_throw_error(system_call<__NR_connect,int>(fd,addr,addrlen)); +#else + using sockaddr_alias_const_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = struct sockaddr const*; + if(::connect(fd,reinterpret_cast(addr),addrlen)==-1) + throw_posix_error(); +#endif +} + +inline void posix_bind_posix_socket_impl(int fd,void const* addr,posix_socklen_t addrlen) +{ +#if defined(__linux__) && defined(__NR_bind) + system_call_throw_error(system_call<__NR_bind,int>(fd,addr,addrlen)); +#else + using sockaddr_alias_const_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = struct sockaddr const*; + if(::bind(fd,reinterpret_cast(addr),addrlen)==-1) + throw_posix_error(); +#endif +} + +inline void posix_listen_posix_socket_impl(int fd,int backlog) +{ +#if defined(__linux__) && defined(__NR_listen) + system_call_throw_error(system_call<__NR_listen,int>(fd,backlog)); +#else + if(::listen(fd,backlog)==-1) + throw_posix_error(); +#endif +} + +inline int posix_accept_posix_socket_impl(int fd,void* addr,posix_socklen_t* addrlen) +{ +#if defined(__linux__) && defined(__NR_accept) + int socfd{system_call<__NR_accept,int>(fd,addr,addrlen)}; + system_call_throw_error(socfd); + return socfd; +#else + using sockaddr_alias_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = struct sockaddr*; + int socfd{::accept(fd,reinterpret_cast(addr),addrlen)}; + if(socfd==-1) + throw_posix_error(); + return socfd; +#endif +} + +} + +} diff --git a/src/fast_io/include/fast_io_hosted/platforms/posix_netop.h b/src/fast_io/include/fast_io_hosted/platforms/posix_netop.h new file mode 100644 index 0000000..7d5c26b --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/posix_netop.h @@ -0,0 +1,124 @@ +#pragma once + +namespace fast_io +{ + +template +inline void posix_connect(basic_posix_io_observer h,void const* addr,posix_socklen_t addrlen) +{ + details::posix_connect_posix_socket_impl(h.fd,addr,addrlen); +} + +template +inline void posix_bind(basic_posix_io_observer h,void const* addr,posix_socklen_t addrlen) +{ + details::posix_bind_posix_socket_impl(h.fd,addr,addrlen); +} + +template +inline void posix_listen(basic_posix_io_observer h,int backlog) +{ + details::posix_listen_posix_socket_impl(h.fd,backlog); +} + +namespace details +{ + +inline int posix_tcp_connect_v4_impl(ipv4 v4,open_mode m) +{ + posix_file soc(sock_family::inet,sock_type::stream,m,sock_protocol::tcp); + constexpr auto inet{to_posix_sock_family(sock_family::inet)}; + posix_sockaddr_in in{.sin_family=inet,.sin_port=big_endian(static_cast(v4.port)),.sin_addr=v4.address}; + posix_connect(soc,__builtin_addressof(in),sizeof(in)); + return soc.release(); +} + +inline int posix_tcp_connect_v6_impl(ipv6 v6,open_mode m) +{ + posix_file soc(sock_family::inet6,sock_type::stream,m,sock_protocol::tcp); + constexpr auto inet6{to_posix_sock_family(sock_family::inet6)}; + posix_sockaddr_in6 in6{.sin6_family=inet6,.sin6_port=big_endian(static_cast(v6.port)),.sin6_addr=v6.address}; + posix_connect(soc,__builtin_addressof(in6),sizeof(in6)); + return soc.release(); +} + +inline int posix_tcp_connect_ip_impl(ip v,open_mode m) +{ + posix_file soc(v.address.isv4?sock_family::inet:sock_family::inet6,sock_type::stream,m,sock_protocol::tcp); + if(v.address.isv4) + { + constexpr auto inet{to_posix_sock_family(sock_family::inet)}; + posix_sockaddr_in in{.sin_family=inet,.sin_port=big_endian(v.port),.sin_addr=v.address.address.v4}; + posix_connect(soc,__builtin_addressof(in),sizeof(in)); + } + else + { + constexpr auto inet6{to_posix_sock_family(sock_family::inet6)}; + posix_sockaddr_in6 in6{.sin6_family=inet6,.sin6_port=big_endian(v.port),.sin6_addr=v.address.address.v6}; + posix_connect(soc,__builtin_addressof(in6),sizeof(in6)); + } + return soc.release(); +} + +inline int posix_tcp_listen_impl(std::uint_least16_t port,open_mode m) +{ + posix_file soc(sock_family::inet,sock_type::stream,m,sock_protocol::tcp); + constexpr auto inet{to_posix_sock_family(sock_family::inet)}; + posix_sockaddr_in in{.sin_family=inet,.sin_port=big_endian(port),.sin_addr={}}; + posix_bind_posix_socket_impl(soc.fd,__builtin_addressof(in),sizeof(in)); + posix_listen_posix_socket_impl(soc.fd,128); + return soc.release(); +} + +} + +template +inline posix_file_factory posix_accept(basic_posix_io_observer h,void* addr, posix_socklen_t* addrlen) +{ + return posix_file_factory{details::posix_accept_posix_socket_impl(h.fd,addr,addrlen)}; +} + +template +inline posix_file_factory tcp_accept(basic_posix_io_observer h) +{ + return posix_file_factory{details::posix_accept_posix_socket_impl(h.fd,nullptr,nullptr)}; +} + +inline posix_file_factory posix_tcp_connect(ipv4 v4,open_mode m=open_mode{}) +{ + return posix_file_factory{details::posix_tcp_connect_v4_impl(v4,m)}; +} + +inline posix_file_factory posix_tcp_connect(ipv6 v6,open_mode m=open_mode{}) +{ + return posix_file_factory{details::posix_tcp_connect_v6_impl(v6,m)}; +} + +inline posix_file_factory posix_tcp_connect(ip v,open_mode m=open_mode{}) +{ + return posix_file_factory{details::posix_tcp_connect_ip_impl(v,m)}; +} + +inline posix_file_factory tcp_connect(ipv4 v4,open_mode m=open_mode{}) +{ + return posix_file_factory{details::posix_tcp_connect_v4_impl(v4,m)}; +} +inline posix_file_factory tcp_connect(ipv6 v6,open_mode m=open_mode{}) +{ + return posix_file_factory{details::posix_tcp_connect_v6_impl(v6,m)}; +} +inline posix_file_factory tcp_connect(ip v,open_mode m=open_mode{}) +{ + return posix_file_factory{details::posix_tcp_connect_ip_impl(v,m)}; +} +inline posix_file_factory tcp_listen(std::uint_least16_t port,open_mode m=open_mode{}) +{ + return posix_file_factory{details::posix_tcp_listen_impl(port,m)}; +} + +template +using basic_native_socket_io_observer = basic_posix_io_observer; +template +using basic_native_socket_file = basic_posix_file; +using net_service = posix_empty_network_service; +} diff --git a/src/fast_io/include/fast_io_hosted/platforms/systemcall_details.h b/src/fast_io/include/fast_io_hosted/platforms/systemcall_details.h new file mode 100644 index 0000000..c42684f --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/systemcall_details.h @@ -0,0 +1,81 @@ +#pragma once + +namespace fast_io::details +{ + +#ifdef __MSDOS__ +extern int dup(int) noexcept __asm__("dup"); +extern int dup2(int,int) noexcept __asm__("dup2"); +extern int _close(int) noexcept __asm__("_close"); +#elif defined(__wasi__) +extern int dup(int) noexcept __asm__("dup"); +extern int dup2(int,int) noexcept __asm__("dup2"); +#endif + +inline int sys_dup(int old_fd) +{ +#if defined(__linux__) && defined(__NR_dup) + int fd{system_call<__NR_dup,int>(old_fd)}; + system_call_throw_error(fd); + return fd; +#else + auto fd{ +#if defined(_WIN32) && !defined(__BIONIC__) + _dup +#else + dup +#endif + (old_fd)}; + if(fd==-1) + throw_posix_error(); + return fd; +#endif +} + +template +inline int sys_dup2(int old_fd,int new_fd) +{ +#if defined(__linux__) && defined(__NR_dup2) + int fd{system_call<__NR_dup2,int>(old_fd,new_fd)}; + system_call_throw_error(fd); + return fd; +#else + auto fd{ +#if defined(_WIN32) && !defined(__BIONIC__) + _dup2 +#else + dup2 +#endif + (old_fd,new_fd)}; + if(fd==-1) + { + if constexpr(always_terminate) + fast_terminate(); + else + throw_posix_error(); + } + return fd; +#endif +} + +inline int sys_close(int fd) noexcept +{ + return +#if defined(__linux__) && defined(__NR_close) + system_call<__NR_close,int> +#elif (defined(_WIN32) && !defined(__BIONIC__)) || defined(__MSDOS__) + _close +#else + close +#endif + (fd); +} + +inline void sys_close_throw_error(int& fd) +{ + auto ret{sys_close(fd)}; + fd=-1;//POSIX standard says we should never call close(2) again even close syscall fails + system_call_throw_error(ret); +} + +} diff --git a/src/fast_io/include/fast_io_hosted/platforms/win32.h b/src/fast_io/include/fast_io_hosted/platforms/win32.h new file mode 100644 index 0000000..342a73c --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/win32.h @@ -0,0 +1,1486 @@ +#pragma once + +namespace fast_io +{ + +namespace details +{ + +namespace win32 +{ +/* +Reference from crypto++'s osrng. +Based on information from cryptopp, microsoft patched KB238187 because this api has issues before Windows Server 2012 R2 +We use an implementation referenced form crypto++'s implementation. +To avoid name collision, we use itanium abi of name mangling for i686-w64-mingw32-g++ -D_WIN32_WINDOWS=0x0400 +_ZN7fast_io7details5win3230crypt_acquire_context_fallbackILNS_12win32_familyE0EEEjv +*/ +template<::fast_io::win32_family family> +inline std::uintptr_t crypt_acquire_context_fallback() +{ + std::uintptr_t hprov{}; + if constexpr(family==::fast_io::win32_family::ansi_9x) + { + if (!::fast_io::win32::CryptAcquireContextA(__builtin_addressof(hprov), nullptr, nullptr, 0x1, 0xf0000000)) + { + std::uint_least32_t firsterr{::fast_io::win32::GetLastError()}; + if (!::fast_io::win32::CryptAcquireContextA(__builtin_addressof(hprov), u8"_ZN7fast_io7details5win3230crypt_acquire_context_fallbackILNS_12win32_familyE0EEEjv", nullptr, 0x1, 0x8)) + { + if(!::fast_io::win32::CryptAcquireContextA(__builtin_addressof(hprov), u8"_ZN7fast_io7details5win3230crypt_acquire_context_fallbackILNS_12win32_familyE0EEEjv", nullptr, 0x1, 0x20|0x8)) + { + throw_win32_error(firsterr); + } + } + } + } + else + { + if (!::fast_io::win32::CryptAcquireContextW(__builtin_addressof(hprov), nullptr, nullptr,0x1, 0xf0000000)) + { + std::uint_least32_t firsterr{::fast_io::win32::GetLastError()}; + if (!::fast_io::win32::CryptAcquireContextW(__builtin_addressof(hprov), u"_ZN7fast_io7details5win3230crypt_acquire_context_fallbackILNS_12win32_familyE0EEEjv", nullptr, 0x1, 0x8)) + { + if(!::fast_io::win32::CryptAcquireContextW(__builtin_addressof(hprov), u"_ZN7fast_io7details5win3230crypt_acquire_context_fallbackILNS_12win32_familyE0EEEjv", nullptr, 0x1, 0x20|0x8)) + { + throw_win32_error(firsterr); + } + } + } + } + return hprov; +} + +template<::fast_io::win32_family family> +struct win32_family_hcryptprov_guard +{ + ::std::uintptr_t hprov{}; + win32_family_hcryptprov_guard():hprov{crypt_acquire_context_fallback()} + {} + win32_family_hcryptprov_guard(win32_family_hcryptprov_guard const&)=delete; + win32_family_hcryptprov_guard& operator=(win32_family_hcryptprov_guard const&)=delete; + ~win32_family_hcryptprov_guard() + { + ::fast_io::win32::CryptReleaseContext(hprov,0); + } +}; + +} + +template +inline void* create_win32_temp_file_impl() +{ + constexpr bool is_nt{family==win32_family::wide_nt}; + using char_type = std::conditional_t; + using replace_char_type = std::conditional_t; + using char_type_may_alias_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = char_type*; + using char_type_may_alias_const_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = char_type const*; + constexpr std::uint_least32_t maximum_temp_path_size{261}; + constexpr std::uint_least32_t uuid_size{36}; + constexpr std::uint_least32_t literal_tmp_size{5}; + constexpr std::uint_least32_t total_buffer_size{maximum_temp_path_size+uuid_size+literal_tmp_size}; + replace_char_type arr[total_buffer_size]; + std::uint_least32_t temp_path_size; + if constexpr(is_nt) + { + temp_path_size=::fast_io::win32::GetTempPathW(maximum_temp_path_size,reinterpret_cast(arr)); + } + else + { + temp_path_size=::fast_io::win32::GetTempPathA(maximum_temp_path_size,reinterpret_cast(arr)); + } + if(temp_path_size==0) + throw_win32_error(); + auto arrp{arr+temp_path_size}; + constexpr bool winver_support_rtl_gen_random{ +#if !defined(_WIN32_WINNT) || _WIN32_WINNT >= 0x0501 +//RtlGenRandom support starts since Windows XP +is_nt +#endif + }; + ::std::conditional_t> hcryptguard; + for(std::size_t retries{};retries!=100;++retries)//retry 100 times. Or reporting error + { + constexpr std::uint_least32_t uuid_buffer_sz{16}; + std::byte uuid_buffer[uuid_buffer_sz]; + if constexpr(winver_support_rtl_gen_random) + { + if(!::fast_io::win32::SystemFunction036(uuid_buffer,uuid_buffer_sz)) + { + throw_win32_error(); + } + } + else + { + if(!::fast_io::win32::CryptGenRandom(hcryptguard.hprov,uuid_buffer_sz,reinterpret_cast(uuid_buffer))) + { + throw_win32_error(); + } + } + auto p{::fast_io::details::pr_rsv_uuid(arrp,uuid_buffer)}; + if constexpr(is_nt) + { + copy_string_literal(u".tmp\0",p); + } + else + { + copy_string_literal(u8".tmp\0",p); + } + void* handle; + if constexpr(is_nt) + { + handle=::fast_io::win32::CreateFileW(reinterpret_cast(arr), + 0x40000000|0x80000000, //GENERIC_READ|GENERIC_WRITE + 0, //Prevents other processes from opening a file or device if they request delete, read, or write access. + nullptr, + 1, //CREATE_NEW + 0x100|0x04000000|0x01000000|0x08000000, //FILE_ATTRIBUTE_TEMPORARY|FILE_FLAG_DELETE_ON_CLOSE|FILE_FLAG_POSIX_SEMANTICS|FILE_FLAG_SEQUENTIAL_SCAN + nullptr); + } + else + { + handle=::fast_io::win32::CreateFileA(reinterpret_cast(arr), + 0x40000000|0x80000000, //GENERIC_READ|GENERIC_WRITE + 0, //Prevents other processes from opening a file or device if they request delete, read, or write access. + nullptr, + 1, //CREATE_NEW + 0x100|0x04000000|0x01000000|0x08000000, //FILE_ATTRIBUTE_TEMPORARY|FILE_FLAG_DELETE_ON_CLOSE|FILE_FLAG_POSIX_SEMANTICS|FILE_FLAG_SEQUENTIAL_SCAN + nullptr); + } + if(handle==(void*) (std::intptr_t)-1)[[unlikely]] + { + std::uint_least32_t code{::fast_io::win32::GetLastError()}; + if(code==80u) //ERROR_FILE_EXISTS + continue; + throw_win32_error(code); + } + return handle; + } + throw_win32_error(80u); //ERROR_FILE_EXISTS +} + +inline void* create_io_completion_port(void* filehandle,void* existing_completionport,std::uintptr_t completionkey,std::uint_least32_t numberofconcurrentthreads) +{ + void* ptr{fast_io::win32::CreateIoCompletionPort(filehandle,existing_completionport,completionkey,numberofconcurrentthreads)}; + if(ptr==nullptr)[[unlikely]] + throw_win32_error(); + return ptr; +} + +inline void* create_io_completion_port_impl() +{ + return create_io_completion_port(reinterpret_cast(static_cast(-1)),nullptr,0,0); +} + +struct win32_open_mode +{ +::std::uint_least32_t dwDesiredAccess{}; +::std::uint_least32_t dwShareMode{}; +bool inherit{}; +::std::uint_least32_t dwCreationDisposition{}; //depends on EXCL +::std::uint_least32_t dwFlagsAndAttributes{};//=128|0x10000000;//FILE_ATTRIBUTE_NORMAL|FILE_FLAG_RANDOM_ACCESS +}; + +template +inline void* win32_family_create_file_internal_impl(std::conditional_t const* lpFileName,win32_open_mode const& mode) +{ + if constexpr(family==win32_family::wide_nt) + { + ::fast_io::win32::security_attributes sec_attr{sizeof(::fast_io::win32::security_attributes),nullptr,true}; + auto handle(::fast_io::win32::CreateFileW(lpFileName, + mode.dwDesiredAccess, + mode.dwShareMode, + mode.inherit?__builtin_addressof(sec_attr):nullptr, + mode.dwCreationDisposition, + mode.dwFlagsAndAttributes, + nullptr)); + if(handle==((void*) (std::intptr_t)-1)) + throw_win32_error(); + return handle; + } + else + { + auto handle(::fast_io::win32::CreateFileA(lpFileName, + mode.dwDesiredAccess, + mode.dwShareMode, + nullptr,//9x kernel does not support security attributes + mode.dwCreationDisposition, + mode.dwFlagsAndAttributes, + nullptr)); + if(handle==((void*) (std::intptr_t)-1)) + throw_win32_error(); + return handle; + } +} + +inline constexpr win32_open_mode calculate_win32_open_mode(open_mode_perms ompm) +{ + open_mode value{ompm.om}; + perms pm{ompm.pm}; + win32_open_mode mode; + if((value&open_mode::no_shared_read)==open_mode::none) + mode.dwShareMode|=1;//FILE_SHARE_READ + if((value&open_mode::no_shared_write)==open_mode::none) + mode.dwShareMode|=2;//FILE_SHARE_DELETE + if((value&open_mode::shared_delete)!=open_mode::none) + mode.dwShareMode|=4;//FILE_SHARE_WRITE + if((value&open_mode::app)!=open_mode::none) + mode.dwDesiredAccess|=4;//FILE_APPEND_DATA + else if((value&open_mode::out)!=open_mode::none) + mode.dwDesiredAccess|=0x40000000;//GENERIC_WRITE + if(((value&open_mode::in)!=open_mode::none)||((value&open_mode::app)!=open_mode::none)) + { + mode.dwDesiredAccess|=0x80000000;//GENERIC_READ + if((value&open_mode::out)!=open_mode::none&&((value&open_mode::app)!=open_mode::none&&(value&open_mode::trunc)!=open_mode::none)) + mode.dwDesiredAccess|=0x40000000;//GENERIC_WRITE + } +/* +Referenced partially from ReactOS +https://github.com/changloong/msvcrt/blob/master/io/wopen.c + + + +https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew + +CREATE_ALWAYS +2 +Creates a new file, always. +If the specified file exists and is writable, the function overwrites the file, the function succeeds, and last-error code is set to ERROR_ALREADY_EXISTS (183). + +If the specified file does not exist and is a valid path, a new file is created, the function succeeds, and the last-error code is set to zero. + +For more information, see the Remarks section of this topic. + +CREATE_NEW +1 +Creates a new file, only if it does not already exist. +If the specified file exists, the function fails and the last-error code is set to ERROR_FILE_EXISTS (80). + +If the specified file does not exist and is a valid path to a writable location, a new file is created. + +OPEN_ALWAYS +4 +Opens a file, always. +If the specified file exists, the function succeeds and the last-error code is set to ERROR_ALREADY_EXISTS (183). + +If the specified file does not exist and is a valid path to a writable location, the function creates a file and the last-error code is set to zero. + +OPEN_EXISTING +3 +Opens a file or device, only if it exists. +If the specified file or device does not exist, the function fails and the last-error code is set to ERROR_FILE_NOT_FOUND (2). + +For more information about devices, see the Remarks section. + +TRUNCATE_EXISTING +5 +Opens a file and truncates it so that its size is zero bytes, only if it exists. +If the specified file does not exist, the function fails and the last-error code is set to ERROR_FILE_NOT_FOUND (2). + +The calling process must open the file with the GENERIC_WRITE bit set as part of the dwDesiredAccess parameter. + + + +File access +mode string Meaning Explanation Action if file +already exists Action if file +does not exist +"r" read Open a file for reading read from start failure to open +"w" write Create a file for writing destroy contents create new +"a" append Append to a file write to end create new +"r+" read extended Open a file for read/write read from start error +"w+" write extended Create a file for read/write destroy contents create new +"a+" append extended Open a file for read/write write to end create new +*/ + if ((value&open_mode::trunc)!=open_mode::none) + { + if((value&open_mode::excl)!=open_mode::none) + mode.dwCreationDisposition=1;// CREATE_NEW + else + mode.dwCreationDisposition=2;// CREATE_ALWAYS + } + else if((value&open_mode::in)==open_mode::none) + { + if((value&open_mode::app)!=open_mode::none) + mode.dwCreationDisposition=4;//OPEN_ALWAYS + else if((value&open_mode::out)!=open_mode::none) + { + if((value&open_mode::excl)!=open_mode::none) + mode.dwCreationDisposition=1;// CREATE_NEW + else + mode.dwCreationDisposition=2;// CREATE_ALWAYS + } + } + else if((value&open_mode::app)!=open_mode::none) + mode.dwCreationDisposition=4;//OPEN_ALWAYS + else + mode.dwCreationDisposition=3;//OPEN_EXISTING + if((value&open_mode::creat)!=open_mode::none) + { + if((value&open_mode::excl)!=open_mode::none) + mode.dwCreationDisposition=1;//CREATE_NEW + else + mode.dwCreationDisposition=4;//OPEN_ALWAYS + } + if((value&open_mode::direct)!=open_mode::none) + mode.dwFlagsAndAttributes|=0x20000000;//FILE_FLAG_NO_BUFFERING + if((value&open_mode::sync)!=open_mode::none) + mode.dwFlagsAndAttributes|=0x80000000;//FILE_FLAG_WRITE_THROUGH + if((value&open_mode::no_block)!=open_mode::none) + mode.dwFlagsAndAttributes|=0x40000000;//FILE_FLAG_OVERLAPPED + if((value&open_mode::follow)!=open_mode::none) + mode.dwFlagsAndAttributes|=0x00200000; //FILE_FLAG_OPEN_REPARSE_POINT +/* +Referenced from: +https://stackoverflow.com/questions/4495767/create-a-directory-and-get-the-handle-by-issuing-one-irp + +CreateFile actually can create a directory. Set the disposition to CREATE_NEW and the flags to FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS | FILE_ATTRIBUTE_DIRECTORY. Since this isn't documented, it probably isn't implemented in ReactOS and Wine. Note that if you're in a scripting environment such as Python, make sure to use the correct value of FILE_FLAG_POSIX_SEMANTICS from the headers (0x01000000). The value listed on MSDN has always been wrong. +– Eryk Sun Jan 25 '17 at 4:14 + +I tried this. Oh no. It cannot + +*/ + if((value&open_mode::directory)!=open_mode::none) + { + mode.dwFlagsAndAttributes|=0x02000000; //FILE_FLAG_BACKUP_SEMANTICS + mode.dwFlagsAndAttributes|=0x10; //FILE_ATTRIBUTE_DIRECTORY + if(mode.dwCreationDisposition==0) + { + mode.dwDesiredAccess|=UINT32_C(0x120116)|UINT32_C(0x120089); //GENERIC_WRITE|GENERIC_READ + mode.dwCreationDisposition=3; //OPEN_EXISTING + } + } + bool set_normal{true}; + if((value&open_mode::archive)!=open_mode::none) + { + mode.dwFlagsAndAttributes|=0x20; //FILE_ATTRIBUTE_ARCHIVE + set_normal={}; + } + if((value&open_mode::encrypted)!=open_mode::none) + { + mode.dwFlagsAndAttributes|=0x4000; //FILE_ATTRIBUTE_ENCRYPTED + set_normal={}; + } + if((value&open_mode::hidden)!=open_mode::none) + { + mode.dwFlagsAndAttributes|=0x2; //FILE_ATTRIBUTE_HIDDEN + set_normal={}; + } + if((value&open_mode::compressed)!=open_mode::none) + { + mode.dwFlagsAndAttributes|=0x800; //FILE_ATTRIBUTE_COMPRESSED + set_normal={}; + } + if((value&open_mode::system)!=open_mode::none) + { + mode.dwFlagsAndAttributes|=0x4; //FILE_ATTRIBUTE_SYSTEM + set_normal={}; + } + if((value&open_mode::offline)!=open_mode::none) + { + mode.dwFlagsAndAttributes|=0x1000; //FILE_ATTRIBUTE_OFFLINE + set_normal={}; + } + if(set_normal)[[likely]] + mode.dwFlagsAndAttributes|=0x80; //FILE_ATTRIBUTE_NORMAL + if((value&open_mode::random_access)==open_mode::none) + { + if((value&open_mode::directory)==open_mode::none) + mode.dwFlagsAndAttributes|=0x10000000; //FILE_FLAG_SEQUENTIAL_SCAN + } + else + mode.dwFlagsAndAttributes|=0x08000000; //FILE_FLAG_RANDOM_ACCESS + if((value&open_mode::no_recall)!=open_mode::none) + mode.dwFlagsAndAttributes|=0x00100000; //FILE_FLAG_OPEN_NO_RECALL + if((value&open_mode::case_insensitive)==open_mode::none) + mode.dwFlagsAndAttributes|=0x01000000; //FILE_FLAG_POSIX_SEMANTICS + if((value&open_mode::session_aware)!=open_mode::none) + mode.dwFlagsAndAttributes|=0x00800000; //FILE_FLAG_SESSION_AWARE + if((value&open_mode::temporary)!=open_mode::none) + { + mode.dwFlagsAndAttributes|=0x04000000; //FILE_FLAG_DELETE_ON_CLOSE + mode.dwFlagsAndAttributes|=0x100; //FILE_ATTRIBUTE_TEMPORARY + } + if((pm&perms::owner_write)==perms::none) + mode.dwFlagsAndAttributes|=1; //FILE_ATTRIBUTE_READONLY + return mode; +} + +template +inline void* win32_family_create_file_impl(std::conditional_t const* filename_c_str,open_mode_perms ompm) +{ + return win32_family_create_file_internal_impl(filename_c_str,calculate_win32_open_mode(ompm)); +} + +template +struct win32_family_open_file_parameter +{ + using family_char_type = std::conditional_t; + open_mode_perms ompm{}; + inline void* operator()(family_char_type const* filename) + { + return win32_family_create_file_impl(filename,ompm); + } +}; + +template +requires (::fast_io::constructible_to_os_c_str) +inline void* win32_create_file_impl(T const& t,open_mode_perms ompm) +{ + return ::fast_io::win32_family_api_common(t,win32_family_open_file_parameter{ompm}); +} + +template +requires (::fast_io::constructible_to_os_c_str) +inline void* win32_create_file_at_impl(void* directory_handle,T const& t,open_mode_perms ompm) +{ + return ::fast_io::win32::nt::details::nt_create_file_at_impl(directory_handle,t,ompm); +} + +template +inline void* win32_create_file_at_fs_dirent_impl(void* directory_handle,char_type const* filename_c_str,std::size_t filename_c_str_len,open_mode_perms ompm) +{ + return ::fast_io::win32::nt::details::nt_family_create_file_fs_dirent_impl(directory_handle,filename_c_str,filename_c_str_len,ompm); +} + +} + +struct win32_io_redirection +{ + void *win32_pipe_in_handle{}; + void *win32_pipe_out_handle{}; + void *win32_handle{}; + bool is_dev_null{}; +}; + +struct win32_io_redirection_std:win32_io_redirection +{ + constexpr win32_io_redirection_std() noexcept=default; + template + requires requires(T&& t) + { + {redirect(::std::forward(t))}->std::same_as; + } + constexpr win32_io_redirection_std(T&& t) noexcept:win32_io_redirection(redirect(::std::forward(t))){} +}; + +struct win32_process_io +{ + win32_io_redirection_std in; + win32_io_redirection_std out; + win32_io_redirection_std err; +}; + +template +class basic_win32_family_io_observer +{ +public: + using native_handle_type = void*; + using char_type = ch_type; + native_handle_type handle{}; + constexpr native_handle_type native_handle() const noexcept + { + return handle; + } + explicit constexpr operator bool() const noexcept + { + return handle!=nullptr; + } + template + explicit constexpr operator basic_nt_family_io_observer() const noexcept + { + return basic_nt_family_io_observer{handle}; + } + template + explicit constexpr operator basic_win32_family_io_observer() const noexcept + { + return basic_win32_family_io_observer{handle}; + } + constexpr native_handle_type release() noexcept + { + auto temp{handle}; + handle=nullptr; + return temp; + } +}; + +#if __cpp_lib_three_way_comparison >= 201907L + +template +inline constexpr bool operator==(basic_win32_family_io_observer a,basic_win32_family_io_observer b) noexcept +{ + return a.handle==b.handle; +} + +template +inline constexpr auto operator<=>(basic_win32_family_io_observer a,basic_win32_family_io_observer b) noexcept +{ + return a.handle<=>b.handle; +} + +#endif + +template +inline constexpr nt_at_entry at(basic_win32_family_io_observer wiob) noexcept +{ + return nt_at_entry{wiob.handle}; +} + +template +inline constexpr basic_win32_family_io_observer io_value_handle(basic_win32_family_io_observer other) noexcept +{ + return other; +} + +template +inline constexpr win32_io_redirection redirect(basic_win32_family_io_observer other) noexcept +{ + return {.win32_handle=other.handle}; +} + +namespace win32::details +{ + +inline void* win32_dup_impl(void* handle) +{ + void* current_process{reinterpret_cast(static_cast(-1))}; + void* new_handle{}; + if(!DuplicateHandle(current_process,handle,current_process,__builtin_addressof(new_handle), 0, true, 2/*DUPLICATE_SAME_ACCESS*/)) + throw_win32_error(); + return handle; +} + +inline void* win32_dup2_impl(void* handle,void* newhandle) +{ + auto temp{win32_dup_impl(handle)}; + if(newhandle)[[likely]] + CloseHandle(newhandle); + return temp; +} + +inline void win32_flush_impl(void* __restrict handle) +{ + if(!FlushFileBuffers(handle)) + throw_win32_error(); +} + +inline void win32_data_sync_impl(void* __restrict handle,data_sync_flags flags [[maybe_unused]]) +{ +#if defined(_WIN32_WINDOWS) + win32_flush_impl(handle); +#else + ::fast_io::win32::nt::details::nt_data_sync_impl(handle,flags); +#endif +} + +} + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#endif +inline void flush(basic_win32_family_io_observer wiob) +{ + ::fast_io::win32::details::win32_flush_impl(wiob.handle); +} + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#endif +inline void data_sync(basic_win32_family_io_observer wiob,data_sync_flags flags) +{ + ::fast_io::win32::details::win32_data_sync_impl(wiob.handle,flags); +} + +namespace win32::details +{ + +inline std::size_t read_impl(void* __restrict handle,void* __restrict begin,std::size_t to_read) +{ + std::uint_least32_t number_of_bytes_read{}; + if constexpr(4(UINT_LEAST32_MAX)(UINT_LEAST32_MAX); + if(!win32::ReadFile(handle,begin,static_cast(to_read),__builtin_addressof(number_of_bytes_read),nullptr)) + { + auto err(win32::GetLastError()); + if(err==109) + return 0; + throw_win32_error(err); + } + return number_of_bytes_read; +} + +inline std::size_t pread_impl(void* __restrict handle,void* __restrict begin,std::size_t to_read,std::uintmax_t u64off) +{ + std::uint_least32_t number_of_bytes_read{}; + if constexpr(4(UINT_LEAST32_MAX)(UINT_LEAST32_MAX); + win32::overlapped overlap{}; + overlap.dummy_union_name.dummy_struct_name={static_cast(u64off),static_cast(u64off>>32)}; + if(!win32::ReadFile(handle,begin,static_cast(to_read),__builtin_addressof(number_of_bytes_read),__builtin_addressof(overlap))) + { + auto err(win32::GetLastError()); + if(err==109) + return 0; + throw_win32_error(err); + } + return number_of_bytes_read; +} + +inline io_scatter_status_t scatter_read_impl(void* __restrict handle,io_scatter_t const* scatters,std::size_t n) +{ + std::size_t total_size{}; + for(std::size_t i{};i!=n;++i) + { + std::size_t pos_in_span{read_impl(handle,const_cast(scatters[i].base),scatters[i].len)}; + total_size+=pos_in_span; + if(pos_in_span(to_write),__builtin_addressof(number_of_bytes_written),nullptr)) + throw_win32_error(); + return number_of_bytes_written; +} + +inline io_scatter_status_t scatter_pread_impl(void* __restrict handle,io_scatters_t sp,std::uintmax_t offset) +{ + std::size_t total_size{}; + for(std::size_t i{};i!=sp.len;++i) + { + std::size_t pos_in_span{pread_impl(handle,const_cast(sp.base[i].base),sp.base[i].len,offset)}; + total_size+=pos_in_span; + offset+=pos_in_span; + if(pos_in_span(offset)); + if constexpr(sizeof(std::uintmax_t)>sizeof(std::uint_least64_t)) + { + if(static_cast(std::numeric_limits::max())(u64off),static_cast(u64off>>32)}; + if(!win32::WriteFile(handle,cbegin,static_cast(to_write),__builtin_addressof(number_of_bytes_written),__builtin_addressof(overlap))) + throw_win32_error(); + return number_of_bytes_written; +} + +inline std::size_t pwrite_impl(void* __restrict handle,void const* __restrict cbegin,std::size_t to_write,std::uintmax_t offset) +{ + if constexpr(4(UINT_LEAST32_MAX)) + to_write_this_round=static_cast(to_write); + std::uint_least32_t number_of_bytes_written{pwrite_simple_impl(handle,cbegin,to_write_this_round,offset)}; + written+=number_of_bytes_written; + offset+=number_of_bytes_written; + if(number_of_bytes_written(UINT_LEAST32_MAX)) + to_write_this_round=static_cast(to_write); + std::uint_least32_t number_of_bytes_written{write_simple_impl(handle,cbegin,to_write_this_round)}; + written+=number_of_bytes_written; + if(number_of_bytes_writtensizeof(std::int_least32_t)) + { + constexpr std::intmax_t l32mx{INT_LEAST32_MAX}; + constexpr std::intmax_t l32mn{INT_LEAST32_MIN}; + if(offset>l32mx||offset(offset),__builtin_addressof(distance_to_move_high),static_cast(s))==invalid) + { + throw_win32_error(); + } + return static_cast(static_cast(distance_to_move_high)); +#else + if constexpr(sizeof(std::intmax_t)>sizeof(std::int_least64_t)) + { + constexpr std::intmax_t l64mx{INT_LEAST64_MAX}; + constexpr std::intmax_t l64mn{INT_LEAST64_MIN}; + if(offset>l64mx||offset(offset),__builtin_addressof(distance_to_move_high),static_cast(s))) + { + throw_win32_error(); + } + return static_cast(static_cast(distance_to_move_high)); +#endif +} + +inline io_scatter_status_t scatter_write_impl(void* __restrict handle,io_scatter_t const* scatters,std::size_t n) +{ + std::size_t total_size{}; + for(std::size_t i{};i!=n;++i) + { + std::size_t written{write_nolock_impl(handle,scatters[i].base,scatters[i].len)}; + total_size+=written; + if(scatters[i].len +inline std::uintmax_t seek(basic_win32_family_io_observer handle,std::intmax_t offset=0,seekdir s=seekdir::cur) +{ + return win32::details::seek_impl(handle.handle,offset,s); +} + +template +[[nodiscard]] inline Iter read(basic_win32_family_io_observer handle,Iter begin,Iter end) +{ + return begin+win32::details::read_impl(handle.handle,::std::to_address(begin),static_cast(end-begin)*sizeof(*begin))/sizeof(*begin); +} + +template +inline Iter write(basic_win32_family_io_observer handle,Iter cbegin,Iter cend) +{ + return cbegin+win32::details::write_impl(handle.handle,::std::to_address(cbegin),static_cast(cend-cbegin)*sizeof(*cbegin))/sizeof(*cbegin); +} + +template +inline io_scatter_status_t scatter_read(basic_win32_family_io_observer handle,io_scatters_t sp) +{ + return win32::details::scatter_read_impl(handle.handle,sp.base,sp.len); +} + +template +inline io_scatter_status_t scatter_write(basic_win32_family_io_observer handle,io_scatters_t sp) +{ + return win32::details::scatter_write_impl(handle.handle,sp.base,sp.len); +} + +template +inline constexpr ::std::conditional_t file_lock(basic_win32_family_io_observer wiob) noexcept +{ + if constexpr(family==win32_family::ansi_9x) + { + return {}; + } + else + { + return {wiob.handle}; + } +} + +#if 0 +namespace details +{ + +struct iocp_overlapped_base:public ::fast_io::win32::overlapped +{ +#if __cpp_constexpr >= 201907L + constexpr +#endif + virtual void invoke(std::size_t) = 0; +#if __cpp_constexpr >= 201907L + constexpr +#endif + virtual ~iocp_overlapped_base() noexcept=default; +}; + +template +struct iocp_overlapped_derived:iocp_overlapped_base +{ + Func func; + template + requires std::constructible_from + iocp_overlapped_derived(Args&& ...args):func(::std::forward(args)...){} +#if __cpp_constexpr >= 201907L + constexpr +#endif + void invoke(std::size_t value) override + { + func(value); + } +}; + +inline void iocp_async_write_define_impl(void* handle,void const* data,std::size_t to_write,std::ptrdiff_t offset,iocp_overlapped_base* callback) +{ + + if constexpr(4(UINT_LEAST32_MAX)(UINT_LEAST32_MAX); + if constexpr(4dummy_union_name.dummy_struct_name.Offset=static_cast(offset)&std::numeric_limits::max(); + callback->dummy_union_name.dummy_struct_name.OffsetHigh=static_cast(offset)>>static_cast(32); + } + else + { + callback->dummy_union_name.dummy_struct_name.Offset=static_cast(offset); + callback->dummy_union_name.dummy_struct_name.OffsetHigh=0; + } + if(!win32::WriteFile(handle,data,static_cast(to_write),nullptr,callback))[[likely]] + { + auto err(win32::GetLastError()); + if(err==997)[[likely]] + return; + delete callback; + throw_win32_error(err); + } +} + +template +inline void iocp_async_write_define(void* handle,void const* data,std::size_t bytes,std::ptrdiff_t offset,Func callback) +{ + iocp_async_write_define_impl(handle,data,bytes,offset,new iocp_overlapped_derived{callback}); +} + +inline void iocp_set_async_context(void* iocp_handle,void* filehandle) +{ + if(iocp_handle==nullptr||filehandle==nullptr) + throw_win32_error(0x000000A0); + create_io_completion_port(filehandle,iocp_handle,0,0); +} + +inline void iocp_async_wait_impl(void* handle) +{ + std::uint_least32_t transferred{}; + std::uintptr_t completionkey{}; + ::fast_io::win32::overlapped *over{}; + if(!::fast_io::win32::GetQueuedCompletionStatus(handle,__builtin_addressof(transferred),__builtin_addressof(completionkey), + over,std::numeric_limits::max())) + throw_win32_error(); + static_cast(over)->invoke(static_cast(transferred)); +} + +} + +template +inline void async_write_define(basic_win32_family_io_observer,nt_at_entry h,void const* data,std::size_t bytes,std::ptrdiff_t offset,Func callback) +{ + ::fast_io::details::iocp_async_write_define(h.handle,data,bytes,offset,std::move(callback)); +} + +template +inline void set_async_context(basic_win32_family_io_observer iocp,nt_at_entry h) +{ + ::fast_io::details::iocp_set_async_context(iocp.handle,h.handle); +} + +template +inline void io_async_wait(basic_win32_family_io_observer iocp) +{ + ::fast_io::details::iocp_async_wait_impl(iocp.handle); +} +#endif + +template +inline void cancel(basic_win32_family_io_observer h) +{ + if(!fast_io::win32::CancelIo(h.handle)) + throw_win32_error(); +} + +template +requires requires(basic_win32_family_io_observer h,Args&& ...args) +{ + fast_io::win32::DeviceIoControl(h.handle,::std::forward(args)...); +} +inline void io_control(basic_win32_family_io_observer h,Args&& ...args) +{ + if(!fast_io::win32::DeviceIoControl(h.handle,::std::forward(args)...)) + throw_win32_error(); +} + +struct +#if __has_cpp_attribute(clang::trivially_relocatable) +[[clang::trivially_relocatable]] +#endif +win32_file_factory +{ + using native_handle_type=void*; + void* handle{}; + explicit constexpr win32_file_factory(void* hd) noexcept:handle(hd){}; + win32_file_factory(win32_file_factory const&)=delete; + win32_file_factory& operator=(win32_file_factory const&)=delete; + ~win32_file_factory() + { + if(handle)[[likely]] + fast_io::win32::CloseHandle(handle); + } +}; + +template +class basic_win32_family_file:public basic_win32_family_io_observer +{ +public: + using typename basic_win32_family_io_observer::char_type; + using typename basic_win32_family_io_observer::native_handle_type; + using basic_win32_family_io_observer::native_handle; + using file_factory_type = win32_file_factory; + explicit constexpr basic_win32_family_file() noexcept=default; + + constexpr basic_win32_family_file(basic_win32_family_io_observer) noexcept=delete; + constexpr basic_win32_family_file& operator=(basic_win32_family_io_observer) noexcept=delete; + + basic_win32_family_file(basic_win32_family_file const& other):basic_win32_family_io_observer{win32::details::win32_dup_impl(other.handle)}{} + basic_win32_family_file& operator=(basic_win32_family_file const& other) + { + this->handle=win32::details::win32_dup2_impl(other.handle,this->handle); + return *this; + } + basic_win32_family_file(basic_win32_family_file&& __restrict b) noexcept: + basic_win32_family_io_observer{b.release()} + {} + basic_win32_family_file& operator=(basic_win32_family_file&& __restrict b) noexcept + { + if(this->handle)[[likely]] + ::fast_io::win32::CloseHandle(this->handle); + this->handle = b.handle; + b.handle=nullptr; + return *this; + } + void reset(native_handle_type newhandle=nullptr) noexcept + { + if(this->handle)[[likely]] + ::fast_io::win32::CloseHandle(this->handle); + this->handle=newhandle; + } + void close() + { + if(this->handle)[[likely]] + { + auto error{::fast_io::win32::CloseHandle(this->handle)}; + this->handle=nullptr;//POSIX standard says we should never call close(2) again even close syscall fails + if(!error)[[unlikely]] + throw_win32_error(); + } + } + + template + requires std::same_as> + explicit constexpr basic_win32_family_file(native_hd handle1) noexcept:basic_win32_family_io_observer{handle1}{} + + basic_win32_family_file(io_dup_t,basic_win32_family_io_observer wiob):basic_win32_family_io_observer{win32::details::win32_dup_impl(wiob.handle)} + {} + + explicit constexpr basic_win32_family_file(win32_file_factory&& fact) noexcept: basic_win32_family_io_observer{fact.handle} + { + fact.handle=nullptr; + } + explicit constexpr basic_win32_family_file(decltype(nullptr)) noexcept = delete; + explicit basic_win32_family_file(io_temp_t):basic_win32_family_io_observer{::fast_io::details::create_win32_temp_file_impl()}{} + explicit basic_win32_family_file(nt_fs_dirent fsdirent,open_mode om,perms pm=static_cast(436)): + basic_win32_family_io_observer{::fast_io::details::win32_create_file_at_fs_dirent_impl(fsdirent.handle,fsdirent.filename.c_str(),fsdirent.filename.size(),{om,pm})}{} + + template<::fast_io::constructible_to_os_c_str T> + explicit basic_win32_family_file(T const& filename,open_mode om,perms pm=static_cast(436)): + basic_win32_family_io_observer{::fast_io::details::win32_create_file_impl(filename,{om,pm})} + {} + + template<::fast_io::constructible_to_os_c_str T> + explicit basic_win32_family_file(nt_at_entry nate,T const& filename,open_mode om,perms pm=static_cast(436)): + basic_win32_family_io_observer{::fast_io::details::win32_create_file_at_impl(nate.handle,filename,{om,pm})} + {} + + explicit basic_win32_family_file(io_async_t) requires(std::same_as):basic_win32_family_io_observer{details::create_io_completion_port_impl()} + { + } + ~basic_win32_family_file() + { + if(this->handle)[[likely]] + ::fast_io::win32::CloseHandle(this->handle); + } +}; + +template +inline void truncate(basic_win32_family_io_observer handle,std::uintmax_t size) +{ + seek(handle,size,seekdir::beg); + if(!win32::SetEndOfFile(handle.handle)) + throw_win32_error(); +} + +template +inline constexpr Iter pwrite(basic_win32_family_io_observer wpioent,Iter begin,Iter end,std::intmax_t offset) +{ + return begin+win32::details::pwrite_impl(wpioent.handle,::std::to_address(begin),(end-begin)*sizeof(*begin),offset)/sizeof(*begin); +} + +template +inline io_scatter_status_t scatter_pwrite(basic_win32_family_io_observer wpioent,io_scatters_t sp,std::intmax_t offset) +{ + return win32::details::scatter_pwrite_impl(wpioent.handle,sp,offset); +} + +template +inline constexpr Iter pread(basic_win32_family_io_observer wpioent,Iter begin,Iter end,std::intmax_t offset) +{ + return begin+win32::details::pread_impl(wpioent.handle,::std::to_address(begin),(end-begin)*sizeof(*begin),offset)/sizeof(*begin); +} + +template +inline io_scatter_status_t scatter_pread(basic_win32_family_io_observer wpioent,io_scatters_t sp,std::intmax_t offset) +{ + return win32::details::scatter_pread_impl(wpioent.handle,sp,offset); +} + +namespace win32::details +{ + +inline file_type file_type_impl(void* handle) +{ +/* +https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfiletype +*/ + std::uint_least32_t ftvalue{GetFileType(handle)}; + switch(ftvalue) + { + case 0x0002: + return file_type::character; + case 0x0001: + return file_type::regular; + case 0x0003: + return file_type::fifo; + case 0x8000: + return file_type::remote; + case 0x0000: + { + auto errcd=GetLastError(); + if(errcd==0) + return file_type::unknown; + throw_win32_error(errcd); + [[fallthrough]]; + } + default: + return file_type::unknown; + }; +} + +inline posix_file_status win32_status_impl(void* __restrict handle) +{ + file_type ft{file_type_impl(handle)}; + if(ft==file_type::fifo||ft==file_type::character) + return posix_file_status{0,0,static_cast(436),ft,1,0,0, + static_cast(reinterpret_cast(handle)), + 0,131072,0,{},{},{},{},0,0}; + by_handle_file_information bhdi; + if(!GetFileInformationByHandle(handle,__builtin_addressof(bhdi))) + throw_win32_error(); + std::uintmax_t file_size{static_cast((static_cast(bhdi.nFileSizeHigh)<<32)|bhdi.nFileSizeLow)}; + std::underlying_type_t pm{0444}; + if((bhdi.dwFileAttributes&0x1)==0x0) + pm|=0222; + if((bhdi.dwFileAttributes&0x400)==0x400) + ft=file_type::symlink; + else if((bhdi.dwFileAttributes&0x10)==0x10) + ft=file_type::directory; + return posix_file_status{static_cast(bhdi.dwVolumeSerialNumber), + static_cast((static_cast(bhdi.nFileIndexHigh)<<32)|bhdi.nFileIndexLow), + static_cast(pm), + ft, + static_cast(bhdi.nNumberOfLinks), + 0,0,0, + file_size, + 131072,file_size>>9, + to_unix_timestamp(bhdi.ftLastAccessTime), + to_unix_timestamp(bhdi.ftLastWriteTime), + to_unix_timestamp(bhdi.ftLastWriteTime), + to_unix_timestamp(bhdi.ftCreationTime), + 0,0}; +} + + +/* +Thanks Fseuio for providing source code. +*/ +inline bool win32_is_character_device(void* handle) noexcept +{ + return (win32::GetFileType(handle) & 0xFFFF7FFF) ==2; +} + +struct win32_console_mode_guard +{ + void *out_hdl{}; + std::uint_least32_t mode{}; + win32_console_mode_guard(void* hd):out_hdl{hd} + { + if(!GetConsoleMode(out_hdl,__builtin_addressof(mode))) + throw_win32_error(); + if(!SetConsoleMode(out_hdl,mode|0x0004)) + throw_win32_error(); + } + win32_console_mode_guard(win32_console_mode_guard const&)=delete; + win32_console_mode_guard& operator=(win32_console_mode_guard const&)=delete; + ~win32_console_mode_guard() + { + SetConsoleMode(out_hdl,mode); + } +}; + +inline void win32_clear_screen_main(void* out_hdl) +{ +/* +Since many people are using console like msys2, we need to first write something to this console +*/ + constexpr char8_t const str[] = u8"\x1B[H\x1B[2J\x1B[3J"; + constexpr std::uint_least32_t written_chars{static_cast(::fast_io::details::string_literal_size(str))}; +//not bytes, but chars + win32_console_mode_guard guard{out_hdl}; + if(!win32::WriteFile(out_hdl, str, written_chars, nullptr, nullptr)) + throw_win32_error(); +} + + +inline void win32_clear_screen_impl(void* handle) +{ + if(!win32_is_character_device(handle)) + return; + win32_clear_screen_main(handle); +} + +} + +template +inline posix_file_status status(basic_win32_family_io_observer wiob) +{ + return win32::details::win32_status_impl(wiob.handle); +} + +template +class basic_win32_family_pipe +{ +public: + using char_type = ch_type; + basic_win32_family_file pipes[2]; + basic_win32_family_pipe() + { + win32::security_attributes sec_attr{sizeof(win32::security_attributes),nullptr,true}; + if(!win32::CreatePipe( + __builtin_addressof(pipes.front().handle), + __builtin_addressof(pipes.back().handle), + __builtin_addressof(sec_attr),0)) + throw_win32_error(); + } + constexpr auto& in() noexcept + { + return *pipes; + } + constexpr auto& out() noexcept + { + return pipes[1]; + } +}; + +template +inline Iter read(basic_win32_family_pipe& h,Iter begin,Iter end) +{ + return read(h.in(),begin,end); +} + +template +inline Iter write(basic_win32_family_pipe& h,Iter begin,Iter end) +{ + return write(h.out(),begin,end); +} + +template +inline io_scatter_status_t scatter_read(basic_win32_family_pipe& h,io_scatters_t sp) +{ + return scatter_read(h.in(),sp); +} + +template +inline io_scatter_status_t scatter_write(basic_win32_family_pipe& h,io_scatters_t sp) +{ + return scatter_write(h.out(),sp); +} + +template +inline ::fast_io::freestanding::array redirect(basic_win32_family_pipe& hd) +{ + return {hd.in().handle,hd.out().handle}; +} + +template +inline void clear_screen(basic_win32_family_io_observer wiob) +{ + win32::details::win32_clear_screen_impl(wiob.handle); +} + +template +inline bool is_character_device(basic_win32_family_io_observer wiob) noexcept +{ + return win32::details::win32_is_character_device(wiob.handle); +} + +template +inline void clear_screen(basic_nt_family_io_observer niob) +{ + win32::details::win32_clear_screen_impl(niob.handle); +} + +template +inline bool is_character_device(basic_nt_family_io_observer niob) noexcept +{ + return win32::details::win32_is_character_device(niob.handle); +} + +template +inline void flush(basic_win32_family_pipe& pipe) +{ + ::fast_io::win32::details::win32_flush_impl(pipe.out().handle); + ::fast_io::win32::details::win32_flush_impl(pipe.in().handle); +} + +template +using basic_win32_io_observer_9xa = basic_win32_family_io_observer; +template +using basic_win32_file_9xa = basic_win32_family_file; +template +using basic_win32_pipe_9xa = basic_win32_family_pipe; + +using win32_io_observer_9xa=basic_win32_io_observer_9xa; +using win32_file_9xa=basic_win32_file_9xa; +using win32_pipe_9xa=basic_win32_pipe_9xa; + +using wwin32_io_observer_9xa=basic_win32_io_observer_9xa; +using wwin32_file_9xa=basic_win32_file_9xa; +using wwin32_pipe_9xa=basic_win32_pipe_9xa; + +using u8win32_io_observer_9xa=basic_win32_io_observer_9xa; +using u8win32_file_9xa=basic_win32_file_9xa; +using u8win32_pipe_9xa=basic_win32_pipe_9xa; + +using u16win32_io_observer_9xa=basic_win32_io_observer_9xa; +using u16win32_file_9xa=basic_win32_file_9xa; +using u16win32_pipe_9xa=basic_win32_pipe_9xa; + +using u32win32_io_observer_9xa=basic_win32_io_observer_9xa; +using u32win32_file_9xa=basic_win32_file_9xa; +using u32win32_pipe_9xa=basic_win32_pipe_9xa; + + +template +using basic_win32_io_observer_ntw = basic_win32_family_io_observer; +template +using basic_win32_file_ntw = basic_win32_family_file; +template +using basic_win32_pipe_ntw = basic_win32_family_pipe; + +using win32_io_observer_ntw=basic_win32_io_observer_ntw; +using win32_file_ntw=basic_win32_file_ntw; +using win32_pipe_ntw=basic_win32_pipe_ntw; + +using wwin32_io_observer_ntw=basic_win32_io_observer_ntw; +using wwin32_file_ntw=basic_win32_file_ntw; +using wwin32_pipe_ntw=basic_win32_pipe_ntw; + +using u8win32_io_observer_ntw=basic_win32_io_observer_ntw; +using u8win32_file_ntw=basic_win32_file_ntw; +using u8win32_pipe_ntw=basic_win32_pipe_ntw; + +using u16win32_io_observer_ntw=basic_win32_io_observer_ntw; +using u16win32_file_ntw=basic_win32_file_ntw; +using u16win32_pipe_ntw=basic_win32_pipe_ntw; + +using u32win32_io_observer_ntw=basic_win32_io_observer_ntw; +using u32win32_file_ntw=basic_win32_file_ntw; +using u32win32_pipe_ntw=basic_win32_pipe_ntw; + + +template +using basic_win32_io_observer = basic_win32_family_io_observer; +template +using basic_win32_file = basic_win32_family_file; +template +using basic_win32_pipe = basic_win32_family_pipe; + +using win32_io_observer=basic_win32_io_observer; +using win32_file=basic_win32_file; +using win32_pipe=basic_win32_pipe; + +using wwin32_io_observer=basic_win32_io_observer; +using wwin32_file=basic_win32_file; +using wwin32_pipe=basic_win32_pipe; + +using u8win32_io_observer=basic_win32_io_observer; +using u8win32_file=basic_win32_file; +using u8win32_pipe=basic_win32_pipe; + +using u16win32_io_observer=basic_win32_io_observer; +using u16win32_file=basic_win32_file; +using u16win32_pipe=basic_win32_pipe; + +using u32win32_io_observer=basic_win32_io_observer; +using u32win32_file=basic_win32_file; +using u32win32_pipe=basic_win32_pipe; + +#if 0 +using io_async_observer=win32_io_observer; +using io_async_scheduler=win32_file; +#endif + +template +inline basic_win32_io_observer_9xa win32_stdin_9xa() noexcept +{ + return {fast_io::win32::GetStdHandle(win32_stdin_number)}; +} +template +inline basic_win32_io_observer_9xa win32_stdout_9xa() noexcept +{ + return {fast_io::win32::GetStdHandle(win32_stdout_number)}; +} +template +inline basic_win32_io_observer_9xa win32_stderr_9xa() noexcept +{ + return {fast_io::win32::GetStdHandle(win32_stderr_number)}; +} + +template +inline basic_win32_io_observer_ntw win32_stdin_ntw() noexcept +{ + return {fast_io::win32::GetStdHandle(win32_stdin_number)}; +} +template +inline basic_win32_io_observer_ntw win32_stdout_ntw() noexcept +{ + return {fast_io::win32::GetStdHandle(win32_stdout_number)}; +} +template +inline basic_win32_io_observer_ntw win32_stderr_ntw() noexcept +{ + return {fast_io::win32::GetStdHandle(win32_stderr_number)}; +} + +template +inline basic_win32_io_observer win32_stdin() noexcept +{ + return {fast_io::win32::GetStdHandle(win32_stdin_number)}; +} +template +inline basic_win32_io_observer win32_stdout() noexcept +{ + return {fast_io::win32::GetStdHandle(win32_stdout_number)}; +} +template +inline basic_win32_io_observer win32_stderr() noexcept +{ + return {fast_io::win32::GetStdHandle(win32_stderr_number)}; +} + +#if !defined(__CYGWIN__) && !defined(__WINE__) +template +inline basic_win32_io_observer native_stdin() noexcept +{ + return {fast_io::win32::GetStdHandle(win32_stdin_number)}; +} +template +inline basic_win32_io_observer native_stdout() noexcept +{ + return {fast_io::win32::GetStdHandle(win32_stdout_number)}; +} +template +inline basic_win32_io_observer native_stderr() noexcept +{ + return {fast_io::win32::GetStdHandle(win32_stderr_number)}; +} +#endif + +namespace freestanding +{ +template +struct is_trivially_relocatable> +{ + inline static constexpr bool value = true; +}; + +template +struct is_zero_default_constructible> +{ + inline static constexpr bool value = true; +}; + +} + +} diff --git a/src/fast_io/include/fast_io_hosted/platforms/win32/apis.h b/src/fast_io/include/fast_io_hosted/platforms/win32/apis.h new file mode 100644 index 0000000..b6c29b6 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/win32/apis.h @@ -0,0 +1,2772 @@ +#pragma once + +namespace fast_io::win32 +{ + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +GetLastError() noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("GetLastError@0") +#else +__asm__("_GetLastError@0") +#endif +#else +__asm__("GetLastError") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern void* +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +LoadLibraryA(char const*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("LoadLibraryA@4") +#else +__asm__("_LoadLibraryA@4") +#endif +#else +__asm__("LoadLibraryA") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern void * +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +LoadLibraryW(char16_t const*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("LoadLibraryW@4") +#else +__asm__("_LoadLibraryW@4") +#endif +#else +__asm__("LoadLibraryW") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern void* +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +LoadLibraryExA(char const*,void*,std::uint_least32_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("LoadLibraryExA@12") +#else +__asm__("_LoadLibraryExA@12") +#endif +#else +__asm__("LoadLibraryExA") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern void * +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +LoadLibraryExW(char16_t const*,void*,std::uint_least32_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("LoadLibraryExW@12") +#else +__asm__("_LoadLibraryExW@12") +#endif +#else +__asm__("LoadLibraryExW") +#endif +#endif +; + +// Used to retrieve a locale-specific message string for some error code +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +FormatMessageA(std::uint_least32_t, char const*, std::uint_least32_t,std::uint_least32_t, char*, std::uint_least32_t, void /*va_list*/ *) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("FormatMessageA@28") +#else +__asm__("_FormatMessageA@28") +#endif +#else +__asm__("FormatMessageA") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +FormatMessageW(std::uint_least32_t, char16_t const*, std::uint_least32_t,std::uint_least32_t, char16_t*, std::uint_least32_t, void /*va_list*/ *) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("FormatMessageW@28") +#else +__asm__("_FormatMessageW@28") +#endif +#else +__asm__("FormatMessageW") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern void* +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +CreateFileMappingA(void*,security_attributes*,std::uint_least32_t,std::uint_least32_t,std::uint_least32_t,char const*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("CreateFileMappingA@24") +#else +__asm__("_CreateFileMappingA@24") +#endif +#else +__asm__("CreateFileMappingA") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern void* +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +CreateFileMappingW(void*,security_attributes*,std::uint_least32_t,std::uint_least32_t,std::uint_least32_t,char16_t const*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("CreateFileMappingW@24") +#else +__asm__("_CreateFileMappingW@24") +#endif +#else +__asm__("CreateFileMappingW") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern void* +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +MapViewOfFile(void*,std::uint_least32_t,std::uint_least32_t,std::uint_least32_t,std::size_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("MapViewOfFile@20") +#else +__asm__("_MapViewOfFile@20") +#endif +#else +__asm__("MapViewOfFile") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +SetEndOfFile(void*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("SetEndOfFile@4") +#else +__asm__("_SetEndOfFile@4") +#endif +#else +__asm__("SetEndOfFile") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +UnmapViewOfFile(void const*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("UnmapViewOfFile@4") +#else +__asm__("_UnmapViewOfFile@4") +#endif +#else +__asm__("UnmapViewOfFile") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +WriteFile(void*,void const*,std::uint_least32_t,std::uint_least32_t*,overlapped*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("WriteFile@20") +#else +__asm__("_WriteFile@20") +#endif +#else +__asm__("WriteFile") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +ReadFile(void*,void const*,std::uint_least32_t,std::uint_least32_t*,overlapped*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("ReadFile@20") +#else +__asm__("_ReadFile@20") +#endif +#else +__asm__("ReadFile") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +SetFilePointer(void*,std::int_least32_t,std::int_least32_t*,std::uint_least32_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("SetFilePointer@16") +#else +__asm__("_SetFilePointer@16") +#endif +#else +__asm__("SetFilePointer") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +SetFilePointerEx(void*,std::int_least64_t,std::int_least64_t*,std::uint_least32_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("SetFilePointerEx@20") +#else +__asm__("_SetFilePointerEx@20") +#endif +#else +__asm__("SetFilePointerEx") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +DuplicateHandle(void*,void*,void*,void**,std::uint_least32_t,int,std::uint_least32_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("DuplicateHandle@28") +#else +__asm__("_DuplicateHandle@28") +#endif +#else +__asm__("DuplicateHandle") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern void* +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +GetStdHandle(std::uint_least32_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("GetStdHandle@4") +#else +__asm__("_GetStdHandle@4") +#endif +#else +__asm__("GetStdHandle") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +CreatePipe(void**,void**,security_attributes*,std::uint_least32_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("CreatePipe@16") +#else +__asm__("_CreatePipe@16") +#endif +#else +__asm__("CreatePipe") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +FreeLibrary(void*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("FreeLibrary@4") +#else +__asm__("_FreeLibrary@4") +#endif +#else +__asm__("FreeLibrary") +#endif +#endif +; + +using farproc = intptr_t( +#if defined(_MSC_VER) && (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +__stdcall +#elif (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +__attribute__((__stdcall__)) +#endif +*)() noexcept; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern farproc +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +GetProcAddress(void*,char const*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("GetProcAddress@8") +#else +__asm__("_GetProcAddress@8") +#endif +#else +__asm__("GetProcAddress") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern void* +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +GetModuleHandleA(char const*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("GetModuleHandleA@4") +#else +__asm__("_GetModuleHandleA@4") +#endif +#else +__asm__("GetModuleHandleA") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern void* +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +GetModuleHandleW(char16_t const*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("GetModuleHandleW@4") +#else +__asm__("_GetModuleHandleW@4") +#endif +#else +__asm__("GetModuleHandleW") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +WaitForSingleObject(void*,std::uint_least32_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("WaitForSingleObject@8") +#else +__asm__("_WaitForSingleObject@8") +#endif +#else +__asm__("WaitForSingleObject") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +CancelIo(void*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("CancelIo@4") +#else +__asm__("_CancelIo@4") +#endif +#else +__asm__("CancelIo") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +GetFileInformationByHandle(void* __restrict,by_handle_file_information* __restrict) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("GetFileInformationByHandle@8") +#else +__asm__("_GetFileInformationByHandle@8") +#endif +#else +__asm__("GetFileInformationByHandle") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +GetUserDefaultLocaleName(char16_t*,int) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("GetUserDefaultLocaleName@8") +#else +__asm__("_GetUserDefaultLocaleName@8") +#endif +#else +__asm__("GetUserDefaultLocaleName") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern ::std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +GetUserDefaultLCID(void) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("GetUserDefaultLCID@0") +#else +__asm__("_GetUserDefaultLCID@0") +#endif +#else +__asm__("GetUserDefaultLCID") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern void +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +GetSystemTimePreciseAsFileTime(filetime*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("GetSystemTimePreciseAsFileTime@4") +#else +__asm__("_GetSystemTimePreciseAsFileTime@4") +#endif +#else +__asm__("GetSystemTimePreciseAsFileTime") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern void +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +GetSystemTimeAsFileTime(filetime*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("GetSystemTimeAsFileTime@4") +#else +__asm__("_GetSystemTimeAsFileTime@4") +#endif +#else +__asm__("GetSystemTimeAsFileTime") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +QueryUnbiasedInterruptTime(std::uint_least64_t*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("QueryUnbiasedInterruptTime@4") +#else +__asm__("_QueryUnbiasedInterruptTime@4") +#endif +#else +__asm__("QueryUnbiasedInterruptTime") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +QueryPerformanceCounter(std::int_least64_t*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("QueryPerformanceCounter@4") +#else +__asm__("_QueryPerformanceCounter@4") +#endif +#else +__asm__("QueryPerformanceCounter") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +QueryPerformanceFrequency(std::int_least64_t*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("QueryPerformanceFrequency@4") +#else +__asm__("_QueryPerformanceFrequency@4") +#endif +#else +__asm__("QueryPerformanceFrequency") +#endif +#endif +; + + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +GetProcessTimes(void*,filetime*,filetime*,filetime*,filetime*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("GetProcessTimes@20") +#else +__asm__("_GetProcessTimes@20") +#endif +#else +__asm__("GetProcessTimes") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +GetThreadTimes(void*,filetime*,filetime*,filetime*,filetime*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("GetThreadTimes@20") +#else +__asm__("_GetThreadTimes@20") +#endif +#else +__asm__("GetThreadTimes") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +GetHandleInformation(void*,std::uint_least32_t*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("GetHandleInformation@8") +#else +__asm__("_GetHandleInformation@8") +#endif +#else +__asm__("GetHandleInformation") +#endif +#endif +; +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +SetHandleInformation(void*,std::uint_least32_t,std::uint_least32_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("SetHandleInformation@12") +#else +__asm__("_SetHandleInformation@12") +#endif +#else +__asm__("SetHandleInformation") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +GetTempPathA(std::uint_least32_t,char* buffer) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("GetTempPathA@8") +#else +__asm__("_GetTempPathA@8") +#endif +#else +__asm__("GetTempPathA") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +GetTempPathW(std::uint_least32_t,char16_t* buffer) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("GetTempPathW@8") +#else +__asm__("_GetTempPathW@8") +#endif +#else +__asm__("GetTempPathW") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern void* +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +CreateFileA(char const*,std::uint_least32_t,std::uint_least32_t,security_attributes*,std::uint_least32_t,std::uint_least32_t,void*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("CreateFileA@28") +#else +__asm__("_CreateFileA@28") +#endif +#else +__asm__("CreateFileA") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern void* +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +CreateFileW(char16_t const*,std::uint_least32_t,std::uint_least32_t,security_attributes*,std::uint_least32_t,std::uint_least32_t,void*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("CreateFileW@28") +#else +__asm__("_CreateFileW@28") +#endif +#else +__asm__("CreateFileW") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern void* +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +CreateIoCompletionPort(void*,void*,std::uintptr_t,std::uint_least32_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("CreateIoCompletionPort@16") +#else +__asm__("_CreateIoCompletionPort@16") +#endif +#else +__asm__("CreateIoCompletionPort") +#endif +#endif +; +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +SystemFunction036(void*,std::uint_least32_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("SystemFunction036@8") +#else +__asm__("_SystemFunction036@8") +#endif +#else +__asm__("SystemFunction036") +#endif +#endif +; +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +CloseHandle(void*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("CloseHandle@4") +#else +__asm__("_CloseHandle@4") +#endif +#else +__asm__("CloseHandle") +#endif +#endif +; +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +LockFileEx(void*,std::uint_least32_t,std::uint_least32_t,std::uint_least32_t,std::uint_least32_t,overlapped*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("LockFileEx@24") +#else +__asm__("_LockFileEx@24") +#endif +#else +__asm__("LockFileEx") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +UnlockFileEx(void*,std::uint_least32_t,std::uint_least32_t,std::uint_least32_t,overlapped*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("UnlockFileEx@20") +#else +__asm__("_UnlockFileEx@20") +#endif +#else +__asm__("UnlockFileEx") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +DeviceIoControl(void*,std::uint_least32_t,void*,std::uint_least32_t,void*,std::uint_least32_t,void*,overlapped*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("DeviceIoControl@32") +#else +__asm__("_DeviceIoControl@32") +#endif +#else +__asm__("DeviceIoControl") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +GetFileType(void*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("GetFileType@4") +#else +__asm__("_GetFileType@4") +#endif +#else +__asm__("GetFileType") +#endif +#endif +; + + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +GetACP() noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("GetACP@0") +#else +__asm__("_GetACP@0") +#endif +#else +__asm__("GetACP") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern ::std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +GetEnvironmentVariableA(char const*,char*,::std::uint_least32_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("GetEnvironmentVariableA@12") +#else +__asm__("_GetEnvironmentVariableA@12") +#endif +#else +__asm__("GetEnvironmentVariableA") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern ::std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +GetEnvironmentVariableW(char16_t const*,char16_t*,::std::uint_least32_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("GetEnvironmentVariableW@12") +#else +__asm__("_GetEnvironmentVariableW@12") +#endif +#else +__asm__("GetEnvironmentVariableW") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +MessageBoxA(void*,char const*,char const*,std::uint_least32_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("MessageBoxA@16") +#else +__asm__("_MessageBoxA@16") +#endif +#else +__asm__("MessageBoxA") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +MessageBoxW(void*,char16_t const*,char16_t const*,std::uint_least32_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("MessageBoxW@16") +#else +__asm__("_MessageBoxW@16") +#endif +#else +__asm__("MessageBoxW") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +GetConsoleMode(void *, std::uint_least32_t *) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("GetConsoleMode@8") +#else +__asm__("_GetConsoleMode@8") +#endif +#else +__asm__("GetConsoleMode") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +SetConsoleMode(void *, std::uint_least32_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("SetConsoleMode@8") +#else +__asm__("_SetConsoleMode@8") +#endif +#else +__asm__("SetConsoleMode") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +ReadConsoleA(void*,void*,std::uint_least32_t,std::uint_least32_t*,void*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("ReadConsoleA@20") +#else +__asm__("_ReadConsoleA@20") +#endif +#else +__asm__("ReadConsoleA") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +ReadConsoleW(void*,void*,std::uint_least32_t,std::uint_least32_t*,void*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("ReadConsoleW@20") +#else +__asm__("_ReadConsoleW@20") +#endif +#else +__asm__("ReadConsoleW") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +WriteConsoleA(void*,void const*,std::uint_least32_t,std::uint_least32_t*,void*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("WriteConsoleA@20") +#else +__asm__("_WriteConsoleA@20") +#endif +#else +__asm__("WriteConsoleA") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +WriteConsoleW(void*,void const*,std::uint_least32_t,std::uint_least32_t*,void*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("WriteConsoleW@20") +#else +__asm__("_WriteConsoleW@20") +#endif +#else +__asm__("WriteConsoleW") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +GetConsoleScreenBufferInfo(void *, console_screen_buffer_info *) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("GetConsoleScreenBufferInfo@8") +#else +__asm__("_GetConsoleScreenBufferInfo@8") +#endif +#else +__asm__("GetConsoleScreenBufferInfo") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +ScrollConsoleScreenBufferA(void *, small_rect const *, small_rect const *, coord, char_info const *) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("ScrollConsoleScreenBufferA@20") +#else +__asm__("_ScrollConsoleScreenBufferA@20") +#endif +#else +__asm__("ScrollConsoleScreenBufferA") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +ScrollConsoleScreenBufferW(void *, small_rect const *, small_rect const *, coord, char_info const *) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("ScrollConsoleScreenBufferW@20") +#else +__asm__("_ScrollConsoleScreenBufferW@20") +#endif +#else +__asm__("ScrollConsoleScreenBufferW") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +SetConsoleCursorPosition(void *, coord) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("SetConsoleCursorPosition@8") +#else +__asm__("_SetConsoleCursorPosition@8") +#endif +#else +__asm__("SetConsoleCursorPosition") +#endif +#endif +; + + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern void +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +InitializeCriticalSection(void*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("InitializeCriticalSection@4") +#else +__asm__("_InitializeCriticalSection@4") +#endif +#else +__asm__("InitializeCriticalSection") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern void +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +EnterCriticalSection(void*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("EnterCriticalSection@4") +#else +__asm__("_EnterCriticalSection@4") +#endif +#else +__asm__("EnterCriticalSection") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +TryEnterCriticalSection(void*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("TryEnterCriticalSection@4") +#else +__asm__("_TryEnterCriticalSection@4") +#endif +#else +__asm__("TryEnterCriticalSection") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern void +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +LeaveCriticalSection(void*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("LeaveCriticalSection@4") +#else +__asm__("_LeaveCriticalSection@4") +#endif +#else +__asm__("LeaveCriticalSection") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern void +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +DeleteCriticalSection(void*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("DeleteCriticalSection@4") +#else +__asm__("_DeleteCriticalSection@4") +#endif +#else +__asm__("DeleteCriticalSection") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +WSADuplicateSocketA(void*,std::uint_least32_t,wsaprotocol_infoa*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("WSADuplicateSocketA@12") +#else +__asm__("_WSADuplicateSocketA@12") +#endif +#else +__asm__("WSADuplicateSocketA") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern void +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +WSADuplicateSocketW(void*,std::uint_least32_t,wsaprotocol_infow*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("WSADuplicateSocketW@12") +#else +__asm__("_WSADuplicateSocketW@12") +#endif +#else +__asm__("WSADuplicateSocketW") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +WSACleanup() noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("WSACleanup@0") +#else +__asm__("_WSACleanup@0") +#endif +#else +__asm__("WSACleanup") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +WSAStartup(std::uint_least32_t,wsadata*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("WSAStartup@8") +#else +__asm__("_WSAStartup@8") +#endif +#else +__asm__("WSAStartup") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +WSAGetLastError() noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("WSAGetLastError@0") +#else +__asm__("_WSAGetLastError@0") +#endif +#else +__asm__("WSAGetLastError") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +closesocket(std::uintptr_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("closesocket@4") +#else +__asm__("_closesocket@4") +#endif +#else +__asm__("closesocket") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uintptr_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +WSASocketW(int,int,int,wsaprotocol_infow*,std::uint_least32_t,std::uint_least32_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("WSASocketW@24") +#else +__asm__("_WSASocketW@24") +#endif +#else +__asm__("WSASocketW") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uintptr_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +WSASocketA(int,int,int,wsaprotocol_infoa*,std::uint_least32_t,std::uint_least32_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("WSASocketA@24") +#else +__asm__("_WSASocketA@24") +#endif +#else +__asm__("WSASocketA") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +bind(std::uintptr_t,void const*,int) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("bind@12") +#else +__asm__("_bind@12") +#endif +#else +__asm__("bind") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +listen(std::uintptr_t,int) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("listen@8") +#else +__asm__("_listen@8") +#endif +#else +__asm__("listen") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uintptr_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +WSAAccept(std::uintptr_t,void const*,int*,lpconditionproc,std::uintptr_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("WSAAccept@20") +#else +__asm__("_WSAAccept@20") +#endif +#else +__asm__("WSAAccept") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +ioctlsocket(std::uintptr_t,long,std::uint_least32_t*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("ioctlsocket@12") +#else +__asm__("_ioctlsocket@12") +#endif +#else +__asm__("ioctlsocket") +#endif +#endif +; + + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +WSASend(std::uintptr_t,wsabuf*,std::uint_least32_t,std::uint_least32_t*,std::uint_least32_t,overlapped*,lpwsaoverlapped_completion_routine) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("WSASend@28") +#else +__asm__("_WSASend@28") +#endif +#else +__asm__("WSASend") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +WSASendMsg(std::uintptr_t,wsamsg*,std::uint_least32_t,std::uint_least32_t*,overlapped*,lpwsaoverlapped_completion_routine) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("WSASendMsg@24") +#else +__asm__("_WSASendMsg@24") +#endif +#else +__asm__("WSASendMsg") +#endif +#endif +; + + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +WSASendTo(std::uintptr_t,wsabuf*,std::uint_least32_t,std::uint_least32_t*,std::uint_least32_t,void const*,int,overlapped*,lpwsaoverlapped_completion_routine) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("WSASendTo@36") +#else +__asm__("_WSASendTo@36") +#endif +#else +__asm__("WSASendTo") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +recv(std::uintptr_t,char* buf,int len,int flags) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("recv@16") +#else +__asm__("_recv@16") +#endif +#else +__asm__("recv") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +WSARecv(std::uintptr_t,wsabuf*,std::uint_least32_t,std::uint_least32_t*,std::uint_least32_t*,overlapped*,lpwsaoverlapped_completion_routine) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("WSARecv@28") +#else +__asm__("_WSARecv@28") +#endif +#else +__asm__("WSARecv") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +WSARecvFrom(std::uintptr_t,wsabuf*,std::uint_least32_t,std::uint_least32_t*,std::uint_least32_t*,void const*,int*,overlapped*,lpwsaoverlapped_completion_routine) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("WSARecvFrom@36") +#else +__asm__("_WSARecvFrom@36") +#endif +#else +__asm__("WSARecvFrom") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +connect(std::uintptr_t,void const*,int) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("connect@12") +#else +__asm__("_connect@12") +#endif +#else +__asm__("connect") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +WSAConnect(std::uintptr_t,void const*,int,wsabuf*,wsabuf*,qualityofservice*,qualityofservice*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("WSAConnect@28") +#else +__asm__("_WSAConnect@28") +#endif +#else +__asm__("WSAConnect") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +shutdown(std::uintptr_t,void const*,int) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("shutdown@12") +#else +__asm__("_shutdown@12") +#endif +#else +__asm__("shutdown") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +GetCurrentProcessId() noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("GetCurrentProcessId@0") +#else +__asm__("_GetCurrentProcessId@0") +#endif +#else +__asm__("GetCurrentProcessId") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +FlushFileBuffers(void*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("FlushFileBuffers@4") +#else +__asm__("_FlushFileBuffers@4") +#endif +#else +__asm__("FlushFileBuffers") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +GetQueuedCompletionStatus(void*,std::uint_least32_t*,std::uintptr_t*,overlapped*,std::uint_least32_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("GetQueuedCompletionStatus@20") +#else +__asm__("_GetQueuedCompletionStatus@20") +#endif +#else +__asm__("GetQueuedCompletionStatus") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern void +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +freeaddrinfo(win32_addrinfo_9xa*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("freeaddrinfo@4") +#else +__asm__("_freeaddrinfo@4") +#endif +#else +__asm__("freeaddrinfo") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern void +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +FreeAddrInfoW(win32_addrinfo_ntw*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("FreeAddrInfoW@4") +#else +__asm__("_FreeAddrInfoW@4") +#endif +#else +__asm__("FreeAddrInfoW") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +getaddrinfo(char const*,char const*,win32_addrinfo_9xa const*,win32_addrinfo_9xa**) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("getaddrinfo@16") +#else +__asm__("_getaddrinfo@16") +#endif +#else +__asm__("getaddrinfo") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +GetAddrInfoW(char16_t const*,char16_t const*,win32_addrinfo_ntw const*,win32_addrinfo_ntw**) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("GetAddrInfoW@16") +#else +__asm__("_GetAddrInfoW@16") +#endif +#else +__asm__("GetAddrInfoW") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +CryptAcquireContextA(::std::uintptr_t*,char8_t const*,char8_t const*,::std::uint_least32_t,::std::uint_least32_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("CryptAcquireContextA@20") +#else +__asm__("_CryptAcquireContextA@20") +#endif +#else +__asm__("CryptAcquireContextA") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +CryptAcquireContextW(::std::uintptr_t*,char16_t const*,char16_t const*,::std::uint_least32_t,::std::uint_least32_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("CryptAcquireContextW@20") +#else +__asm__("_CryptAcquireContextW@20") +#endif +#else +__asm__("CryptAcquireContextW") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +CryptReleaseContext(::std::uintptr_t,::std::uint_least32_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("CryptReleaseContext@8") +#else +__asm__("_CryptReleaseContext@8") +#endif +#else +__asm__("CryptReleaseContext") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern int +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +CryptGenRandom(::std::uintptr_t,::std::uint_least32_t,char unsigned*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("CryptGenRandom@12") +#else +__asm__("_CryptGenRandom@12") +#endif +#else +__asm__("CryptGenRandom") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern ::std::int_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +RegOpenKeyA(::std::uintptr_t,char8_t const*,::std::uintptr_t*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("RegOpenKeyA@12") +#else +__asm__("_RegOpenKeyA@12") +#endif +#else +__asm__("RegOpenKeyA") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern ::std::int_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +RegOpenKeyW(::std::uintptr_t,char16_t const*,::std::uintptr_t*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("RegOpenKeyW@12") +#else +__asm__("_RegOpenKeyW@12") +#endif +#else +__asm__("RegOpenKeyW") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern ::std::int_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +RegQueryValueExA(::std::uintptr_t,char8_t const*,::std::uint_least32_t*,::std::uint_least32_t*,void*,::std::uint_least32_t*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("RegQueryValueExA@24") +#else +__asm__("_RegQueryValueExA@24") +#endif +#else +__asm__("RegQueryValueExA") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern ::std::int_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +RegQueryValueExW(::std::uintptr_t,char16_t const*,::std::uint_least32_t*,::std::uint_least32_t*,void*,::std::uint_least32_t*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("RegQueryValueExW@24") +#else +__asm__("_RegQueryValueExW@24") +#endif +#else +__asm__("RegQueryValueExW") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern ::std::int_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +RegCloseKey(::std::uintptr_t) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("RegCloseKey@4") +#else +__asm__("_RegCloseKey@4") +#endif +#else +__asm__("RegCloseKey") +#endif +#endif +; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern ::std::uint_least32_t +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +GetTimeZoneInformation(time_zone_information*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("GetTimeZoneInformation@4") +#else +__asm__("_GetTimeZoneInformation@4") +#endif +#else +__asm__("GetTimeZoneInformation") +#endif +#endif +; + +} diff --git a/src/fast_io/include/fast_io_hosted/platforms/win32/impl.h b/src/fast_io/include/fast_io_hosted/platforms/win32/impl.h new file mode 100644 index 0000000..e09a885 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/win32/impl.h @@ -0,0 +1,14 @@ +#pragma once + +#include"win32_definitions.h" +#include"apis.h" + +#if defined(_MSC_VER) && !defined(_WIN32_WINDOWS) && !defined(_KERNEL_MODE) +#pragma comment(lib,"bcrypt.lib") +#endif + +#if defined(_MSC_VER) && !defined(__clang__) +#include"msvc_linker.h" +#endif + +#include"utils.h" diff --git a/src/fast_io/include/fast_io_hosted/platforms/win32/msvc_linker.h b/src/fast_io/include/fast_io_hosted/platforms/win32/msvc_linker.h new file mode 100644 index 0000000..54d279d --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/win32/msvc_linker.h @@ -0,0 +1,9 @@ +#pragma once + +#if SIZE_MAX > UINT_LEAST32_MAX +#include"msvc_linker_64.h" +#elif defined(__x86__) || defined(_M_IX86) || defined(__i386__) +#include"msvc_linker_32_i686.h" +#else +#include"msvc_linker_32.h" +#endif diff --git a/src/fast_io/include/fast_io_hosted/platforms/win32/msvc_linker_32.h b/src/fast_io/include/fast_io_hosted/platforms/win32/msvc_linker_32.h new file mode 100644 index 0000000..5069531 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/win32/msvc_linker_32.h @@ -0,0 +1,164 @@ +#pragma once + +#pragma comment(linker,"/alternatename:__imp_?GetLastError@win32@fast_io@@YAIXZ=__imp_GetLastError") +#pragma comment(linker,"/alternatename:__imp_?LoadLibraryA@win32@fast_io@@YAPAXPBD@Z=__imp_LoadLibraryA") +#pragma comment(linker,"/alternatename:__imp_?LoadLibraryW@win32@fast_io@@YAPAXPB_S@Z=__imp_LoadLibraryW") +#pragma comment(linker,"/alternatename:__imp_?LoadLibraryExA@win32@fast_io@@YAPAXPBDPAXI@Z=__imp_LoadLibraryExA") +#pragma comment(linker,"/alternatename:__imp_?LoadLibraryExW@win32@fast_io@@YAPAXPB_SPAXI@Z=__imp_LoadLibraryExW") +#pragma comment(linker,"/alternatename:__imp_?FormatMessageA@win32@fast_io@@YAIIPBDIIPADIPAX@Z=__imp_FormatMessageA") +#pragma comment(linker,"/alternatename:__imp_?FormatMessageW@win32@fast_io@@YAIIPB_SIIPA_SIPAX@Z=__imp_FormatMessageW") +#pragma comment(linker,"/alternatename:__imp_?CreateFileMappingA@win32@fast_io@@YAPAXPAXPAUsecurity_attributes@12@IIIPBD@Z=__imp_CreateFileMappingA") +#pragma comment(linker,"/alternatename:__imp_?CreateFileMappingW@win32@fast_io@@YAPAXPAXPAUsecurity_attributes@12@IIIPB_S@Z=__imp_CreateFileMappingW") +#pragma comment(linker,"/alternatename:__imp_?MapViewOfFile@win32@fast_io@@YAPAXPAXIIII@Z=__imp_MapViewOfFile") +#pragma comment(linker,"/alternatename:__imp_?SetEndOfFile@win32@fast_io@@YAHPAX@Z=__imp_SetEndOfFile") +#pragma comment(linker,"/alternatename:__imp_?UnmapViewOfFile@win32@fast_io@@YAHPBX@Z=__imp_UnmapViewOfFile") +#pragma comment(linker,"/alternatename:__imp_?WriteFile@win32@fast_io@@YAHPAXPBXIPAIPAUoverlapped@12@@Z=__imp_WriteFile") +#pragma comment(linker,"/alternatename:__imp_?ReadFile@win32@fast_io@@YAHPAXPBXIPAIPAUoverlapped@12@@Z=__imp_ReadFile") +#pragma comment(linker,"/alternatename:__imp_?SetFilePointer@win32@fast_io@@YAIPAXHPAHI@Z=__imp_SetFilePointer") +#pragma comment(linker,"/alternatename:__imp_?SetFilePointerEx@win32@fast_io@@YAHPAX_JPA_JI@Z=__imp_SetFilePointerEx") +#pragma comment(linker,"/alternatename:__imp_?DuplicateHandle@win32@fast_io@@YAHPAX00PAPAXIHI@Z=__imp_DuplicateHandle") +#pragma comment(linker,"/alternatename:__imp_?GetStdHandle@win32@fast_io@@YAPAXI@Z=__imp_GetStdHandle") +#pragma comment(linker,"/alternatename:__imp_?CreatePipe@win32@fast_io@@YAHPAPAX0PAUsecurity_attributes@12@I@Z=__imp_CreatePipe") +#pragma comment(linker,"/alternatename:__imp_?FreeLibrary@win32@fast_io@@YAHPAX@Z=__imp_FreeLibrary") +#pragma comment(linker,"/alternatename:__imp_?GetProcAddress@win32@fast_io@@YAP6AHX_EPAXPBD@Z=__imp_GetProcAddress") +#pragma comment(linker,"/alternatename:__imp_?GetModuleHandleA@win32@fast_io@@YAPAXPBD@Z=__imp_GetModuleHandleA") +#pragma comment(linker,"/alternatename:__imp_?GetModuleHandleW@win32@fast_io@@YAPAXPB_S@Z=__imp_GetModuleHandleW") +#pragma comment(linker,"/alternatename:__imp_?WaitForSingleObject@win32@fast_io@@YAIPAXI@Z=__imp_WaitForSingleObject") +#pragma comment(linker,"/alternatename:__imp_?CancelIo@win32@fast_io@@YAIPAX@Z=__imp_CancelIo") +#pragma comment(linker,"/alternatename:__imp_?GetFileInformationByHandle@win32@fast_io@@YAHPIAXPIAUby_handle_file_information@12@@Z=__imp_GetFileInformationByHandle") +#pragma comment(linker,"/alternatename:__imp_?GetUserDefaultLocaleName@win32@fast_io@@YAHPA_SH@Z=__imp_GetUserDefaultLocaleName") +#pragma comment(linker,"/alternatename:__imp_?GetUserDefaultLCID@win32@fast_io@@YAIXZ=__imp_GetUserDefaultLCID") +#pragma comment(linker,"/alternatename:__imp_?GetSystemTimePreciseAsFileTime@win32@fast_io@@YAXPAUfiletime@12@@Z=__imp_GetSystemTimePreciseAsFileTime") +#pragma comment(linker,"/alternatename:__imp_?GetSystemTimeAsFileTime@win32@fast_io@@YAXPAUfiletime@12@@Z=__imp_GetSystemTimeAsFileTime") +#pragma comment(linker,"/alternatename:__imp_?QueryUnbiasedInterruptTime@win32@fast_io@@YAHPA_K@Z=__imp_QueryUnbiasedInterruptTime") +#pragma comment(linker,"/alternatename:__imp_?QueryPerformanceCounter@win32@fast_io@@YAHPA_J@Z=__imp_QueryPerformanceCounter") +#pragma comment(linker,"/alternatename:__imp_?QueryPerformanceFrequency@win32@fast_io@@YAHPA_J@Z=__imp_QueryPerformanceFrequency") +#pragma comment(linker,"/alternatename:__imp_?GetProcessTimes@win32@fast_io@@YAHPAXPAUfiletime@12@111@Z=__imp_GetProcessTimes") +#pragma comment(linker,"/alternatename:__imp_?GetThreadTimes@win32@fast_io@@YAHPAXPAUfiletime@12@111@Z=__imp_GetThreadTimes") +#pragma comment(linker,"/alternatename:__imp_?GetHandleInformation@win32@fast_io@@YAHPAXPAI@Z=__imp_GetHandleInformation") +#pragma comment(linker,"/alternatename:__imp_?SetHandleInformation@win32@fast_io@@YAHPAXII@Z=__imp_SetHandleInformation") +#pragma comment(linker,"/alternatename:__imp_?GetTempPathA@win32@fast_io@@YAIIPAD@Z=__imp_GetTempPathA") +#pragma comment(linker,"/alternatename:__imp_?GetTempPathW@win32@fast_io@@YAIIPA_S@Z=__imp_GetTempPathW") +#pragma comment(linker,"/alternatename:__imp_?CreateFileA@win32@fast_io@@YAPAXPBDIIPAUsecurity_attributes@12@IIPAX@Z=__imp_CreateFileA") +#pragma comment(linker,"/alternatename:__imp_?CreateFileW@win32@fast_io@@YAPAXPB_SIIPAUsecurity_attributes@12@IIPAX@Z=__imp_CreateFileW") +#pragma comment(linker,"/alternatename:__imp_?CreateIoCompletionPort@win32@fast_io@@YAPAXPAX0II@Z=__imp_CreateIoCompletionPort") +#pragma comment(linker,"/alternatename:__imp_?SystemFunction036@win32@fast_io@@YAHPAXI@Z=__imp_SystemFunction036") +#pragma comment(linker,"/alternatename:__imp_?CloseHandle@win32@fast_io@@YAHPAX@Z=__imp_CloseHandle") +#pragma comment(linker,"/alternatename:__imp_?LockFileEx@win32@fast_io@@YAHPAXIIIIPAUoverlapped@12@@Z=__imp_LockFileEx") +#pragma comment(linker,"/alternatename:__imp_?UnlockFileEx@win32@fast_io@@YAHPAXIIIPAUoverlapped@12@@Z=__imp_UnlockFileEx") +#pragma comment(linker,"/alternatename:__imp_?DeviceIoControl@win32@fast_io@@YAHPAXI0I0I0PAUoverlapped@12@@Z=__imp_DeviceIoControl") +#pragma comment(linker,"/alternatename:__imp_?GetFileType@win32@fast_io@@YAIPAX@Z=__imp_GetFileType") +#pragma comment(linker,"/alternatename:__imp_?GetACP@win32@fast_io@@YAIXZ=__imp_GetACP") +#pragma comment(linker,"/alternatename:__imp_?GetEnvironmentVariableA@win32@fast_io@@YAIPBDPADI@Z=__imp_GetEnvironmentVariableA") +#pragma comment(linker,"/alternatename:__imp_?GetEnvironmentVariableW@win32@fast_io@@YAIPB_SPA_SI@Z=__imp_GetEnvironmentVariableW") +#pragma comment(linker,"/alternatename:__imp_?MessageBoxA@win32@fast_io@@YAIPAXPBD1I@Z=__imp_MessageBoxA") +#pragma comment(linker,"/alternatename:__imp_?MessageBoxW@win32@fast_io@@YAIPAXPB_S1I@Z=__imp_MessageBoxW") +#pragma comment(linker,"/alternatename:__imp_?GetConsoleMode@win32@fast_io@@YAHPAXPAI@Z=__imp_GetConsoleMode") +#pragma comment(linker,"/alternatename:__imp_?SetConsoleMode@win32@fast_io@@YAHPAXI@Z=__imp_SetConsoleMode") +#pragma comment(linker,"/alternatename:__imp_?ReadConsoleA@win32@fast_io@@YAHPAX0IPAI0@Z=__imp_ReadConsoleA") +#pragma comment(linker,"/alternatename:__imp_?ReadConsoleW@win32@fast_io@@YAHPAX0IPAI0@Z=__imp_ReadConsoleW") +#pragma comment(linker,"/alternatename:__imp_?WriteConsoleA@win32@fast_io@@YAHPAXPBXIPAI0@Z=__imp_WriteConsoleA") +#pragma comment(linker,"/alternatename:__imp_?WriteConsoleW@win32@fast_io@@YAHPAXPBXIPAI0@Z=__imp_WriteConsoleW") +#pragma comment(linker,"/alternatename:__imp_?GetConsoleScreenBufferInfo@win32@fast_io@@YAHPAXPAUconsole_screen_buffer_info@12@@Z=__imp_GetConsoleScreenBufferInfo") +#pragma comment(linker,"/alternatename:__imp_?ScrollConsoleScreenBufferA@win32@fast_io@@YAHPAXPBUsmall_rect@12@1Ucoord@12@PBUchar_info@12@@Z=__imp_ScrollConsoleScreenBufferA") +#pragma comment(linker,"/alternatename:__imp_?ScrollConsoleScreenBufferW@win32@fast_io@@YAHPAXPBUsmall_rect@12@1Ucoord@12@PBUchar_info@12@@Z=__imp_ScrollConsoleScreenBufferW") +#pragma comment(linker,"/alternatename:__imp_?SetConsoleCursorPosition@win32@fast_io@@YAHPAXUcoord@12@@Z=__imp_SetConsoleCursorPosition") +#pragma comment(linker,"/alternatename:__imp_?InitializeCriticalSection@win32@fast_io@@YAXPAX@Z=__imp_InitializeCriticalSection") +#pragma comment(linker,"/alternatename:__imp_?EnterCriticalSection@win32@fast_io@@YAXPAX@Z=__imp_EnterCriticalSection") +#pragma comment(linker,"/alternatename:__imp_?TryEnterCriticalSection@win32@fast_io@@YAHPAX@Z=__imp_TryEnterCriticalSection") +#pragma comment(linker,"/alternatename:__imp_?LeaveCriticalSection@win32@fast_io@@YAXPAX@Z=__imp_LeaveCriticalSection") +#pragma comment(linker,"/alternatename:__imp_?DeleteCriticalSection@win32@fast_io@@YAXPAX@Z=__imp_DeleteCriticalSection") +#pragma comment(linker,"/alternatename:__imp_?WSADuplicateSocketA@win32@fast_io@@YAHPAXIPAUwsaprotocol_infoa@12@@Z=__imp_WSADuplicateSocketA") +#pragma comment(linker,"/alternatename:__imp_?WSADuplicateSocketW@win32@fast_io@@YAXPAXIPAUwsaprotocol_infow@12@@Z=__imp_WSADuplicateSocketW") +#pragma comment(linker,"/alternatename:__imp_?WSACleanup@win32@fast_io@@YAHXZ=__imp_WSACleanup") +#pragma comment(linker,"/alternatename:__imp_?WSAStartup@win32@fast_io@@YAHIPAUwsadata@12@@Z=__imp_WSAStartup") +#pragma comment(linker,"/alternatename:__imp_?WSAGetLastError@win32@fast_io@@YAHXZ=__imp_WSAGetLastError") +#pragma comment(linker,"/alternatename:__imp_?closesocket@win32@fast_io@@YAHI@Z=__imp_closesocket") +#pragma comment(linker,"/alternatename:__imp_?WSASocketW@win32@fast_io@@YAIHHHPAUwsaprotocol_infow@12@II@Z=__imp_WSASocketW") +#pragma comment(linker,"/alternatename:__imp_?WSASocketA@win32@fast_io@@YAIHHHPAUwsaprotocol_infoa@12@II@Z=__imp_WSASocketA") +#pragma comment(linker,"/alternatename:__imp_?bind@win32@fast_io@@YAHIPBXH@Z=__imp_bind") +#pragma comment(linker,"/alternatename:__imp_?listen@win32@fast_io@@YAHIH@Z=__imp_listen") +#pragma comment(linker,"/alternatename:__imp_?WSAAccept@win32@fast_io@@YAIIPBXPAHP6AXPAUwsabuf@12@2PAUqualityofservice@12@322PAII@_EI@Z=__imp_WSAAccept") +#pragma comment(linker,"/alternatename:__imp_?ioctlsocket@win32@fast_io@@YAHIJPAI@Z=__imp_ioctlsocket") +#pragma comment(linker,"/alternatename:__imp_?WSASend@win32@fast_io@@YAHIPAUwsabuf@12@IPAIIPAUoverlapped@12@P6AXII2I@_E@Z=__imp_WSASend") +#pragma comment(linker,"/alternatename:__imp_?WSASendMsg@win32@fast_io@@YAHIPAUwsamsg@12@IPAIPAUoverlapped@12@P6AXII2I@_E@Z=__imp_WSASendMsg") +#pragma comment(linker,"/alternatename:__imp_?WSASendTo@win32@fast_io@@YAHIPAUwsabuf@12@IPAIIPBXHPAUoverlapped@12@P6AXII3I@_E@Z=__imp_WSASendTo") +#pragma comment(linker,"/alternatename:__imp_?recv@win32@fast_io@@YAHIPADHH@Z=__imp_recv") +#pragma comment(linker,"/alternatename:__imp_?WSARecv@win32@fast_io@@YAHIPAUwsabuf@12@IPAI1PAUoverlapped@12@P6AXII2I@_E@Z=__imp_WSARecv") +#pragma comment(linker,"/alternatename:__imp_?WSARecvFrom@win32@fast_io@@YAHIPAUwsabuf@12@IPAI1PBXPAHPAUoverlapped@12@P6AXII4I@_E@Z=__imp_WSARecvFrom") +#pragma comment(linker,"/alternatename:__imp_?connect@win32@fast_io@@YAHIPBXH@Z=__imp_connect") +#pragma comment(linker,"/alternatename:__imp_?WSAConnect@win32@fast_io@@YAHIPBXHPAUwsabuf@12@1PAUqualityofservice@12@2@Z=__imp_WSAConnect") +#pragma comment(linker,"/alternatename:__imp_?shutdown@win32@fast_io@@YAHIPBXH@Z=__imp_shutdown") +#pragma comment(linker,"/alternatename:__imp_?GetCurrentProcessId@win32@fast_io@@YAIXZ=__imp_GetCurrentProcessId") +#pragma comment(linker,"/alternatename:__imp_?FlushFileBuffers@win32@fast_io@@YAHPAX@Z=__imp_FlushFileBuffers") +#pragma comment(linker,"/alternatename:__imp_?GetQueuedCompletionStatus@win32@fast_io@@YAHPAXPAI1PAUoverlapped@12@I@Z=__imp_GetQueuedCompletionStatus") +#pragma comment(linker,"/alternatename:__imp_?freeaddrinfo@win32@fast_io@@YAXPAU?$win32_family_addrinfo@$0A@@12@@Z=__imp_freeaddrinfo") +#pragma comment(linker,"/alternatename:__imp_?FreeAddrInfoW@win32@fast_io@@YAXPAU?$win32_family_addrinfo@$00@12@@Z=__imp_FreeAddrInfoW") +#pragma comment(linker,"/alternatename:__imp_?getaddrinfo@win32@fast_io@@YAHPBD0PBU?$win32_family_addrinfo@$0A@@12@PAPAU312@@Z=__imp_getaddrinfo") +#pragma comment(linker,"/alternatename:__imp_?GetAddrInfoW@win32@fast_io@@YAHPB_S0PBU?$win32_family_addrinfo@$00@12@PAPAU312@@Z=__imp_GetAddrInfoW") +#pragma comment(linker,"/alternatename:__imp_?CryptAcquireContextA@win32@fast_io@@YAHPAIPB_Q1II@Z=__imp_CryptAcquireContextA") +#pragma comment(linker,"/alternatename:__imp_?CryptAcquireContextW@win32@fast_io@@YAHPAIPB_S1II@Z=__imp_CryptAcquireContextW") +#pragma comment(linker,"/alternatename:__imp_?CryptReleaseContext@win32@fast_io@@YAHII@Z=__imp_CryptReleaseContext") +#pragma comment(linker,"/alternatename:__imp_?CryptGenRandom@win32@fast_io@@YAHIIPAE@Z=__imp_CryptGenRandom") +#pragma comment(linker,"/alternatename:__imp_?RegOpenKeyA@win32@fast_io@@YAHIPB_QPAI@Z=__imp_RegOpenKeyA") +#pragma comment(linker,"/alternatename:__imp_?RegOpenKeyW@win32@fast_io@@YAHIPB_SPAI@Z=__imp_RegOpenKeyW") +#pragma comment(linker,"/alternatename:__imp_?RegQueryValueExA@win32@fast_io@@YAHIPB_QPAI1PAX1@Z=__imp_RegQueryValueExA") +#pragma comment(linker,"/alternatename:__imp_?RegQueryValueExW@win32@fast_io@@YAHIPB_SPAI1PAX1@Z=__imp_RegQueryValueExW") +#pragma comment(linker,"/alternatename:__imp_?RegCloseKey@win32@fast_io@@YAHI@Z=__imp_RegCloseKey") +#pragma comment(linker,"/alternatename:__imp_?GetTimeZoneInformation@win32@fast_io@@YAIPAUtime_zone_information@12@@Z=__imp_GetTimeZoneInformation") +#pragma comment(linker,"/alternatename:__imp_?rtl_nt_status_to_dos_error@nt@win32@fast_io@@YAII@Z=__imp_RtlNtStatusToDosError") +#pragma comment(linker,"/alternatename:__imp_?NtClose@nt@win32@fast_io@@YAIPAX@Z=__imp_NtClose") +#pragma comment(linker,"/alternatename:__imp_?ZwClose@nt@win32@fast_io@@YAIPAX@Z=__imp_ZwClose") +#pragma comment(linker,"/alternatename:__imp_?NtCreateFile@nt@win32@fast_io@@YAIPAPAXIPAUobject_attributes@123@PAUio_status_block@123@PA_JIIIIPAXI@Z=__imp_NtCreateFile") +#pragma comment(linker,"/alternatename:__imp_?ZwCreateFile@nt@win32@fast_io@@YAIPAPAXIPAUobject_attributes@123@PAUio_status_block@123@PA_JIIIIPAXI@Z=__imp_ZwCreateFile") +#pragma comment(linker,"/alternatename:__imp_?NtCreateSection@nt@win32@fast_io@@YAIPIAPAXIPIAUobject_attributes@123@PA_KIIPIAX@Z=__imp_NtCreateSection") +#pragma comment(linker,"/alternatename:__imp_?ZwCreateSection@nt@win32@fast_io@@YAIPIAPAXIPIAUobject_attributes@123@PA_KIIPIAX@Z=__imp_ZwCreateSection") +#pragma comment(linker,"/alternatename:__imp_?NtQueryInformationProcess@nt@win32@fast_io@@YAIPIAXW4process_information_class@123@PAUprocess_basic_information@123@IPAI@Z=__imp_NtQueryInformationProcess") +#pragma comment(linker,"/alternatename:__imp_?ZwQueryInformationProcess@nt@win32@fast_io@@YAIPIAXW4process_information_class@123@PAUprocess_basic_information@123@IPAI@Z=__imp_ZwQueryInformationProcess") +#pragma comment(linker,"/alternatename:__imp_?NtWriteFile@nt@win32@fast_io@@YAIPAX0P6AX0PAUio_status_block@123@I@_E01PBXIPA_JPAI@Z=__imp_NtWriteFile") +#pragma comment(linker,"/alternatename:__imp_?ZwWriteFile@nt@win32@fast_io@@YAIPAX0P6AX0PAUio_status_block@123@I@_E01PBXIPA_JPAI@Z=__imp_ZwWriteFile") +#pragma comment(linker,"/alternatename:__imp_?NtReadFile@nt@win32@fast_io@@YAIPAX0P6AX0PAUio_status_block@123@I@_E01PBXIPA_JPAI@Z=__imp_NtReadFile") +#pragma comment(linker,"/alternatename:__imp_?ZwReadFile@nt@win32@fast_io@@YAIPAX0P6AX0PAUio_status_block@123@I@_E01PBXIPA_JPAI@Z=__imp_ZwReadFile") +#pragma comment(linker,"/alternatename:__imp_?NtQueryDirectoryFile@nt@win32@fast_io@@YAIPAX0P6AX0PAUio_status_block@123@I@_E010IW4file_information_class@123@HPAUunicode_string@123@H@Z=__imp_NtQueryDirectoryFile") +#pragma comment(linker,"/alternatename:__imp_?ZwQueryDirectoryFile@nt@win32@fast_io@@YAIPAX0P6AX0PAUio_status_block@123@I@_E010IW4file_information_class@123@HPAUunicode_string@123@H@Z=__imp_ZwQueryDirectoryFile") +#pragma comment(linker,"/alternatename:__imp_?NtQuerySection@nt@win32@fast_io@@YAIPAXW4section_information_class@123@0IPAI@Z=__imp_NtQuerySection") +#pragma comment(linker,"/alternatename:__imp_?ZwQuerySection@nt@win32@fast_io@@YAIPAXW4section_information_class@123@0IPAI@Z=__imp_ZwQuerySection") +#pragma comment(linker,"/alternatename:__imp_?NtQueryInformationFile@nt@win32@fast_io@@YAIPIAXPIAUio_status_block@123@0IW4file_information_class@123@@Z=__imp_NtQueryInformationFile") +#pragma comment(linker,"/alternatename:__imp_?ZwQueryInformationFile@nt@win32@fast_io@@YAIPIAXPIAUio_status_block@123@0IW4file_information_class@123@@Z=__imp_ZwQueryInformationFile") +#pragma comment(linker,"/alternatename:__imp_?NtSetInformationFile@nt@win32@fast_io@@YAIPIAXPIAUio_status_block@123@0IW4file_information_class@123@@Z=__imp_NtSetInformationFile") +#pragma comment(linker,"/alternatename:__imp_?ZwSetInformationFile@nt@win32@fast_io@@YAIPIAXPIAUio_status_block@123@0IW4file_information_class@123@@Z=__imp_ZwSetInformationFile") +#pragma comment(linker,"/alternatename:__imp_?NtDuplicateObject@nt@win32@fast_io@@YAIPAX00PAPAXIII@Z=__imp_NtDuplicateObject") +#pragma comment(linker,"/alternatename:__imp_?ZwDuplicateObject@nt@win32@fast_io@@YAIPAX00PAPAXIII@Z=__imp_ZwDuplicateObject") +#pragma comment(linker,"/alternatename:__imp_?NtWaitForSingleObject@nt@win32@fast_io@@YAIPAXHPA_K@Z=__imp_NtWaitForSingleObject") +#pragma comment(linker,"/alternatename:__imp_?ZwWaitForSingleObject@nt@win32@fast_io@@YAIPAXHPA_K@Z=__imp_ZwWaitForSingleObject") +#pragma comment(linker,"/alternatename:__imp_?NtSetSystemTime@nt@win32@fast_io@@YAIPA_K0@Z=__imp_NtSetSystemTime") +#pragma comment(linker,"/alternatename:__imp_?ZwSetSystemTime@nt@win32@fast_io@@YAIPA_K0@Z=__imp_ZwSetSystemTime") +#pragma comment(linker,"/alternatename:__imp_?NtCreateProcess@nt@win32@fast_io@@YAIPAPAXIPAUobject_attributes@123@PAXI222@Z=__imp_NtCreateProcess") +#pragma comment(linker,"/alternatename:__imp_?ZwCreateProcess@nt@win32@fast_io@@YAIPAPAXIPAUobject_attributes@123@PAXI222@Z=__imp_ZwCreateProcess") +#pragma comment(linker,"/alternatename:__imp_?rtl_dos_path_name_to_nt_path_name_u@nt@win32@fast_io@@YAEPB_SPAUunicode_string@123@PAPB_SPAUrtl_relative_name_u@123@@Z=__imp_RtlDosPathNameToNtPathName_U") +#pragma comment(linker,"/alternatename:__imp_?rtl_dos_path_name_to_nt_path_name_u_with_status@nt@win32@fast_io@@YAIPB_SPAUunicode_string@123@PAPB_SPAUrtl_relative_name_u@123@@Z=__imp_RtlDosPathNameToNtPathName_U_WithStatus") +#pragma comment(linker,"/alternatename:__imp_?rtl_free_unicode_string@nt@win32@fast_io@@YAXPAUunicode_string@123@@Z=__imp_RtlFreeUnicodeString") +#pragma comment(linker,"/alternatename:__imp_?RtlInitializeCriticalSection@nt@win32@fast_io@@YAXPAX@Z=__imp_RtlInitializeCriticalSection") +#pragma comment(linker,"/alternatename:__imp_?RtlEnterCriticalSection@nt@win32@fast_io@@YAXPAX@Z=__imp_RtlEnterCriticalSection") +#pragma comment(linker,"/alternatename:__imp_?RtlTryEnterCriticalSection@nt@win32@fast_io@@YAHPAX@Z=__imp_RtlTryEnterCriticalSection") +#pragma comment(linker,"/alternatename:__imp_?RtlLeaveCriticalSection@nt@win32@fast_io@@YAXPAX@Z=__imp_RtlLeaveCriticalSection") +#pragma comment(linker,"/alternatename:__imp_?RtlDeleteCriticalSection@nt@win32@fast_io@@YAXPAX@Z=__imp_RtlDeleteCriticalSection") +#pragma comment(linker,"/alternatename:__imp_?RtlCreateUserThread@nt@win32@fast_io@@YAIPAX0HIII00PAPAXPAUclient_id@123@@Z=__imp_RtlCreateUserThread") +#pragma comment(linker,"/alternatename:__imp_?NtResumeThread@nt@win32@fast_io@@YAIPAXPAI@Z=__imp_NtResumeThread") +#pragma comment(linker,"/alternatename:__imp_?ZwResumeThread@nt@win32@fast_io@@YAIPAXPAI@Z=__imp_ZwResumeThread") +#pragma comment(linker,"/alternatename:__imp_?NtLockFile@nt@win32@fast_io@@YAIPAX0P6AX0PAUio_status_block@123@I@_E01PA_J3IEE@Z=__imp_NtLockFile") +#pragma comment(linker,"/alternatename:__imp_?ZwLockFile@nt@win32@fast_io@@YAIPAX0P6AX0PAUio_status_block@123@I@_E01PA_J3IEE@Z=__imp_ZwLockFile") +#pragma comment(linker,"/alternatename:__imp_?NtUnlockFile@nt@win32@fast_io@@YAIPAXPAUio_status_block@123@PA_J2I@Z=__imp_NtUnlockFile") +#pragma comment(linker,"/alternatename:__imp_?ZwUnlockFile@nt@win32@fast_io@@YAIPAXPAUio_status_block@123@PA_J2I@Z=__imp_ZwUnlockFile") +#pragma comment(linker,"/alternatename:__imp_?NtFlushBuffersFile@nt@win32@fast_io@@YAIPAXPAUio_status_block@123@@Z=__imp_NtFlushBuffersFile") +#pragma comment(linker,"/alternatename:__imp_?ZwFlushBuffersFile@nt@win32@fast_io@@YAIPAXPAUio_status_block@123@@Z=__imp_ZwFlushBuffersFile") +#pragma comment(linker,"/alternatename:__imp_?NtFlushBuffersFileEx@nt@win32@fast_io@@YAIPAXI0IPAUio_status_block@123@@Z=__imp_NtFlushBuffersFileEx") +#pragma comment(linker,"/alternatename:__imp_?ZwFlushBuffersFileEx@nt@win32@fast_io@@YAIPAXI0IPAUio_status_block@123@@Z=__imp_ZwFlushBuffersFileEx") +#pragma comment(linker,"/alternatename:__imp_?DbgPrint@nt@win32@fast_io@@YAIPBDZZ=__imp_DbgPrint") +#pragma comment(linker,"/alternatename:__imp_?DbgPrintEx@nt@win32@fast_io@@YAIIIPBDZZ=__imp_DbgPrintEx") +#pragma comment(linker,"/alternatename:__imp_?RtlCreateProcessParameters@nt@win32@fast_io@@YAIPAPAUrtl_user_process_parameters@123@PAUunicode_string@123@111PAX1111@Z=__imp_RtlCreateProcessParameters") +#pragma comment(linker,"/alternatename:__imp_?RtlCreateProcessParametersEx@nt@win32@fast_io@@YAIPAPAUrtl_user_process_parameters@123@PAUunicode_string@123@111PAX1111I@Z=__imp_RtlCreateProcessParametersEx") +#pragma comment(linker,"/alternatename:__imp_?RtlDestroyProcessParameters@nt@win32@fast_io@@YAIPAUrtl_user_process_parameters@123@@Z=__imp_RtlDestroyProcessParameters") +#pragma comment(linker,"/alternatename:__imp_?NtCreateUserProcess@nt@win32@fast_io@@YAIPAX0IIPAUobject_attributes@123@1IIPAUrtl_user_process_parameters@123@PAUps_create_info@123@PAUps_attribute_list@123@@Z=__imp_NtCreateUserProcess") +#pragma comment(linker,"/alternatename:__imp_?ZwCreateUserProcess@nt@win32@fast_io@@YAIPAX0IIPAUobject_attributes@123@1IIPAUrtl_user_process_parameters@123@PAUps_create_info@123@PAUps_attribute_list@123@@Z=__imp_ZwCreateUserProcess") +#pragma comment(linker,"/alternatename:__imp_?RtlCreateUserProcess@nt@win32@fast_io@@YAIPAUunicode_string@123@IPAUrtl_user_process_parameters@123@PAUsecurity_descriptor@123@2PAXE33PAUrtl_user_process_information@123@@Z=__imp_RtlCreateUserProcess") diff --git a/src/fast_io/include/fast_io_hosted/platforms/win32/msvc_linker_32_i686.h b/src/fast_io/include/fast_io_hosted/platforms/win32/msvc_linker_32_i686.h new file mode 100644 index 0000000..aed9942 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/win32/msvc_linker_32_i686.h @@ -0,0 +1,164 @@ +#pragma once + +#pragma comment(linker,"/alternatename:__imp_?GetLastError@win32@fast_io@@YGIXZ=__imp__GetLastError@0") +#pragma comment(linker,"/alternatename:__imp_?LoadLibraryA@win32@fast_io@@YGPAXPBD@Z=__imp__LoadLibraryA@4") +#pragma comment(linker,"/alternatename:__imp_?LoadLibraryW@win32@fast_io@@YGPAXPB_S@Z=__imp__LoadLibraryW@4") +#pragma comment(linker,"/alternatename:__imp_?LoadLibraryExA@win32@fast_io@@YGPAXPBDPAXI@Z=__imp__LoadLibraryExA@12") +#pragma comment(linker,"/alternatename:__imp_?LoadLibraryExW@win32@fast_io@@YGPAXPB_SPAXI@Z=__imp__LoadLibraryExW@12") +#pragma comment(linker,"/alternatename:__imp_?FormatMessageA@win32@fast_io@@YGIIPBDIIPADIPAX@Z=__imp__FormatMessageA@28") +#pragma comment(linker,"/alternatename:__imp_?FormatMessageW@win32@fast_io@@YGIIPB_SIIPA_SIPAX@Z=__imp__FormatMessageW@28") +#pragma comment(linker,"/alternatename:__imp_?CreateFileMappingA@win32@fast_io@@YGPAXPAXPAUsecurity_attributes@12@IIIPBD@Z=__imp__CreateFileMappingA@24") +#pragma comment(linker,"/alternatename:__imp_?CreateFileMappingW@win32@fast_io@@YGPAXPAXPAUsecurity_attributes@12@IIIPB_S@Z=__imp__CreateFileMappingW@24") +#pragma comment(linker,"/alternatename:__imp_?MapViewOfFile@win32@fast_io@@YGPAXPAXIIII@Z=__imp__MapViewOfFile@20") +#pragma comment(linker,"/alternatename:__imp_?SetEndOfFile@win32@fast_io@@YGHPAX@Z=__imp__SetEndOfFile@4") +#pragma comment(linker,"/alternatename:__imp_?UnmapViewOfFile@win32@fast_io@@YGHPBX@Z=__imp__UnmapViewOfFile@4") +#pragma comment(linker,"/alternatename:__imp_?WriteFile@win32@fast_io@@YGHPAXPBXIPAIPAUoverlapped@12@@Z=__imp__WriteFile@20") +#pragma comment(linker,"/alternatename:__imp_?ReadFile@win32@fast_io@@YGHPAXPBXIPAIPAUoverlapped@12@@Z=__imp__ReadFile@20") +#pragma comment(linker,"/alternatename:__imp_?SetFilePointer@win32@fast_io@@YGIPAXHPAHI@Z=__imp__SetFilePointer@16") +#pragma comment(linker,"/alternatename:__imp_?SetFilePointerEx@win32@fast_io@@YGHPAX_JPA_JI@Z=__imp__SetFilePointerEx@20") +#pragma comment(linker,"/alternatename:__imp_?DuplicateHandle@win32@fast_io@@YGHPAX00PAPAXIHI@Z=__imp__DuplicateHandle@28") +#pragma comment(linker,"/alternatename:__imp_?GetStdHandle@win32@fast_io@@YGPAXI@Z=__imp__GetStdHandle@4") +#pragma comment(linker,"/alternatename:__imp_?CreatePipe@win32@fast_io@@YGHPAPAX0PAUsecurity_attributes@12@I@Z=__imp__CreatePipe@16") +#pragma comment(linker,"/alternatename:__imp_?FreeLibrary@win32@fast_io@@YGHPAX@Z=__imp__FreeLibrary@4") +#pragma comment(linker,"/alternatename:__imp_?GetProcAddress@win32@fast_io@@YGP6GHX_EPAXPBD@Z=__imp__GetProcAddress@8") +#pragma comment(linker,"/alternatename:__imp_?GetModuleHandleA@win32@fast_io@@YGPAXPBD@Z=__imp__GetModuleHandleA@4") +#pragma comment(linker,"/alternatename:__imp_?GetModuleHandleW@win32@fast_io@@YGPAXPB_S@Z=__imp__GetModuleHandleW@4") +#pragma comment(linker,"/alternatename:__imp_?WaitForSingleObject@win32@fast_io@@YGIPAXI@Z=__imp__WaitForSingleObject@8") +#pragma comment(linker,"/alternatename:__imp_?CancelIo@win32@fast_io@@YGIPAX@Z=__imp__CancelIo@4") +#pragma comment(linker,"/alternatename:__imp_?GetFileInformationByHandle@win32@fast_io@@YGHPIAXPIAUby_handle_file_information@12@@Z=__imp__GetFileInformationByHandle@8") +#pragma comment(linker,"/alternatename:__imp_?GetUserDefaultLocaleName@win32@fast_io@@YGHPA_SH@Z=__imp__GetUserDefaultLocaleName@8") +#pragma comment(linker,"/alternatename:__imp_?GetUserDefaultLCID@win32@fast_io@@YGIXZ=__imp__GetUserDefaultLCID@0") +#pragma comment(linker,"/alternatename:__imp_?GetSystemTimePreciseAsFileTime@win32@fast_io@@YGXPAUfiletime@12@@Z=__imp__GetSystemTimePreciseAsFileTime@4") +#pragma comment(linker,"/alternatename:__imp_?GetSystemTimeAsFileTime@win32@fast_io@@YGXPAUfiletime@12@@Z=__imp__GetSystemTimeAsFileTime@4") +#pragma comment(linker,"/alternatename:__imp_?QueryUnbiasedInterruptTime@win32@fast_io@@YGHPA_K@Z=__imp__QueryUnbiasedInterruptTime@4") +#pragma comment(linker,"/alternatename:__imp_?QueryPerformanceCounter@win32@fast_io@@YGHPA_J@Z=__imp__QueryPerformanceCounter@4") +#pragma comment(linker,"/alternatename:__imp_?QueryPerformanceFrequency@win32@fast_io@@YGHPA_J@Z=__imp__QueryPerformanceFrequency@4") +#pragma comment(linker,"/alternatename:__imp_?GetProcessTimes@win32@fast_io@@YGHPAXPAUfiletime@12@111@Z=__imp__GetProcessTimes@20") +#pragma comment(linker,"/alternatename:__imp_?GetThreadTimes@win32@fast_io@@YGHPAXPAUfiletime@12@111@Z=__imp__GetThreadTimes@20") +#pragma comment(linker,"/alternatename:__imp_?GetHandleInformation@win32@fast_io@@YGHPAXPAI@Z=__imp__GetHandleInformation@8") +#pragma comment(linker,"/alternatename:__imp_?SetHandleInformation@win32@fast_io@@YGHPAXII@Z=__imp__SetHandleInformation@12") +#pragma comment(linker,"/alternatename:__imp_?GetTempPathA@win32@fast_io@@YGIIPAD@Z=__imp__GetTempPathA@8") +#pragma comment(linker,"/alternatename:__imp_?GetTempPathW@win32@fast_io@@YGIIPA_S@Z=__imp__GetTempPathW@8") +#pragma comment(linker,"/alternatename:__imp_?CreateFileA@win32@fast_io@@YGPAXPBDIIPAUsecurity_attributes@12@IIPAX@Z=__imp__CreateFileA@28") +#pragma comment(linker,"/alternatename:__imp_?CreateFileW@win32@fast_io@@YGPAXPB_SIIPAUsecurity_attributes@12@IIPAX@Z=__imp__CreateFileW@28") +#pragma comment(linker,"/alternatename:__imp_?CreateIoCompletionPort@win32@fast_io@@YGPAXPAX0II@Z=__imp__CreateIoCompletionPort@16") +#pragma comment(linker,"/alternatename:__imp_?SystemFunction036@win32@fast_io@@YGHPAXI@Z=__imp__SystemFunction036@8") +#pragma comment(linker,"/alternatename:__imp_?CloseHandle@win32@fast_io@@YGHPAX@Z=__imp__CloseHandle@4") +#pragma comment(linker,"/alternatename:__imp_?LockFileEx@win32@fast_io@@YGHPAXIIIIPAUoverlapped@12@@Z=__imp__LockFileEx@24") +#pragma comment(linker,"/alternatename:__imp_?UnlockFileEx@win32@fast_io@@YGHPAXIIIPAUoverlapped@12@@Z=__imp__UnlockFileEx@20") +#pragma comment(linker,"/alternatename:__imp_?DeviceIoControl@win32@fast_io@@YGHPAXI0I0I0PAUoverlapped@12@@Z=__imp__DeviceIoControl@32") +#pragma comment(linker,"/alternatename:__imp_?GetFileType@win32@fast_io@@YGIPAX@Z=__imp__GetFileType@4") +#pragma comment(linker,"/alternatename:__imp_?GetACP@win32@fast_io@@YGIXZ=__imp__GetACP@0") +#pragma comment(linker,"/alternatename:__imp_?GetEnvironmentVariableA@win32@fast_io@@YGIPBDPADI@Z=__imp__GetEnvironmentVariableA@12") +#pragma comment(linker,"/alternatename:__imp_?GetEnvironmentVariableW@win32@fast_io@@YGIPB_SPA_SI@Z=__imp__GetEnvironmentVariableW@12") +#pragma comment(linker,"/alternatename:__imp_?MessageBoxA@win32@fast_io@@YGIPAXPBD1I@Z=__imp__MessageBoxA@16") +#pragma comment(linker,"/alternatename:__imp_?MessageBoxW@win32@fast_io@@YGIPAXPB_S1I@Z=__imp__MessageBoxW@16") +#pragma comment(linker,"/alternatename:__imp_?GetConsoleMode@win32@fast_io@@YGHPAXPAI@Z=__imp__GetConsoleMode@8") +#pragma comment(linker,"/alternatename:__imp_?SetConsoleMode@win32@fast_io@@YGHPAXI@Z=__imp__SetConsoleMode@8") +#pragma comment(linker,"/alternatename:__imp_?ReadConsoleA@win32@fast_io@@YGHPAX0IPAI0@Z=__imp__ReadConsoleA@20") +#pragma comment(linker,"/alternatename:__imp_?ReadConsoleW@win32@fast_io@@YGHPAX0IPAI0@Z=__imp__ReadConsoleW@20") +#pragma comment(linker,"/alternatename:__imp_?WriteConsoleA@win32@fast_io@@YGHPAXPBXIPAI0@Z=__imp__WriteConsoleA@20") +#pragma comment(linker,"/alternatename:__imp_?WriteConsoleW@win32@fast_io@@YGHPAXPBXIPAI0@Z=__imp__WriteConsoleW@20") +#pragma comment(linker,"/alternatename:__imp_?GetConsoleScreenBufferInfo@win32@fast_io@@YGHPAXPAUconsole_screen_buffer_info@12@@Z=__imp__GetConsoleScreenBufferInfo@8") +#pragma comment(linker,"/alternatename:__imp_?ScrollConsoleScreenBufferA@win32@fast_io@@YGHPAXPBUsmall_rect@12@1Ucoord@12@PBUchar_info@12@@Z=__imp__ScrollConsoleScreenBufferA@20") +#pragma comment(linker,"/alternatename:__imp_?ScrollConsoleScreenBufferW@win32@fast_io@@YGHPAXPBUsmall_rect@12@1Ucoord@12@PBUchar_info@12@@Z=__imp__ScrollConsoleScreenBufferW@20") +#pragma comment(linker,"/alternatename:__imp_?SetConsoleCursorPosition@win32@fast_io@@YGHPAXUcoord@12@@Z=__imp__SetConsoleCursorPosition@8") +#pragma comment(linker,"/alternatename:__imp_?InitializeCriticalSection@win32@fast_io@@YGXPAX@Z=__imp__InitializeCriticalSection@4") +#pragma comment(linker,"/alternatename:__imp_?EnterCriticalSection@win32@fast_io@@YGXPAX@Z=__imp__EnterCriticalSection@4") +#pragma comment(linker,"/alternatename:__imp_?TryEnterCriticalSection@win32@fast_io@@YGHPAX@Z=__imp__TryEnterCriticalSection@4") +#pragma comment(linker,"/alternatename:__imp_?LeaveCriticalSection@win32@fast_io@@YGXPAX@Z=__imp__LeaveCriticalSection@4") +#pragma comment(linker,"/alternatename:__imp_?DeleteCriticalSection@win32@fast_io@@YGXPAX@Z=__imp__DeleteCriticalSection@4") +#pragma comment(linker,"/alternatename:__imp_?WSADuplicateSocketA@win32@fast_io@@YGHPAXIPAUwsaprotocol_infoa@12@@Z=__imp__WSADuplicateSocketA@12") +#pragma comment(linker,"/alternatename:__imp_?WSADuplicateSocketW@win32@fast_io@@YGXPAXIPAUwsaprotocol_infow@12@@Z=__imp__WSADuplicateSocketW@12") +#pragma comment(linker,"/alternatename:__imp_?WSACleanup@win32@fast_io@@YGHXZ=__imp__WSACleanup@0") +#pragma comment(linker,"/alternatename:__imp_?WSAStartup@win32@fast_io@@YGHIPAUwsadata@12@@Z=__imp__WSAStartup@8") +#pragma comment(linker,"/alternatename:__imp_?WSAGetLastError@win32@fast_io@@YGHXZ=__imp__WSAGetLastError@0") +#pragma comment(linker,"/alternatename:__imp_?closesocket@win32@fast_io@@YGHI@Z=__imp__closesocket@4") +#pragma comment(linker,"/alternatename:__imp_?WSASocketW@win32@fast_io@@YGIHHHPAUwsaprotocol_infow@12@II@Z=__imp__WSASocketW@24") +#pragma comment(linker,"/alternatename:__imp_?WSASocketA@win32@fast_io@@YGIHHHPAUwsaprotocol_infoa@12@II@Z=__imp__WSASocketA@24") +#pragma comment(linker,"/alternatename:__imp_?bind@win32@fast_io@@YGHIPBXH@Z=__imp__bind@12") +#pragma comment(linker,"/alternatename:__imp_?listen@win32@fast_io@@YGHIH@Z=__imp__listen@8") +#pragma comment(linker,"/alternatename:__imp_?WSAAccept@win32@fast_io@@YGIIPBXPAHP6GXPAUwsabuf@12@2PAUqualityofservice@12@322PAII@_EI@Z=__imp__WSAAccept@20") +#pragma comment(linker,"/alternatename:__imp_?ioctlsocket@win32@fast_io@@YGHIJPAI@Z=__imp__ioctlsocket@12") +#pragma comment(linker,"/alternatename:__imp_?WSASend@win32@fast_io@@YGHIPAUwsabuf@12@IPAIIPAUoverlapped@12@P6GXII2I@_E@Z=__imp__WSASend@28") +#pragma comment(linker,"/alternatename:__imp_?WSASendMsg@win32@fast_io@@YGHIPAUwsamsg@12@IPAIPAUoverlapped@12@P6GXII2I@_E@Z=__imp__WSASendMsg@24") +#pragma comment(linker,"/alternatename:__imp_?WSASendTo@win32@fast_io@@YGHIPAUwsabuf@12@IPAIIPBXHPAUoverlapped@12@P6GXII3I@_E@Z=__imp__WSASendTo@36") +#pragma comment(linker,"/alternatename:__imp_?recv@win32@fast_io@@YGHIPADHH@Z=__imp__recv@16") +#pragma comment(linker,"/alternatename:__imp_?WSARecv@win32@fast_io@@YGHIPAUwsabuf@12@IPAI1PAUoverlapped@12@P6GXII2I@_E@Z=__imp__WSARecv@28") +#pragma comment(linker,"/alternatename:__imp_?WSARecvFrom@win32@fast_io@@YGHIPAUwsabuf@12@IPAI1PBXPAHPAUoverlapped@12@P6GXII4I@_E@Z=__imp__WSARecvFrom@36") +#pragma comment(linker,"/alternatename:__imp_?connect@win32@fast_io@@YGHIPBXH@Z=__imp__connect@12") +#pragma comment(linker,"/alternatename:__imp_?WSAConnect@win32@fast_io@@YGHIPBXHPAUwsabuf@12@1PAUqualityofservice@12@2@Z=__imp__WSAConnect@28") +#pragma comment(linker,"/alternatename:__imp_?shutdown@win32@fast_io@@YGHIPBXH@Z=__imp__shutdown@8") +#pragma comment(linker,"/alternatename:__imp_?GetCurrentProcessId@win32@fast_io@@YGIXZ=__imp__GetCurrentProcessId@0") +#pragma comment(linker,"/alternatename:__imp_?FlushFileBuffers@win32@fast_io@@YGHPAX@Z=__imp__FlushFileBuffers@4") +#pragma comment(linker,"/alternatename:__imp_?GetQueuedCompletionStatus@win32@fast_io@@YGHPAXPAI1PAUoverlapped@12@I@Z=__imp__GetQueuedCompletionStatus@20") +#pragma comment(linker,"/alternatename:__imp_?freeaddrinfo@win32@fast_io@@YGXPAU?$win32_family_addrinfo@$0A@@12@@Z=__imp__freeaddrinfo@4") +#pragma comment(linker,"/alternatename:__imp_?FreeAddrInfoW@win32@fast_io@@YGXPAU?$win32_family_addrinfo@$00@12@@Z=__imp__FreeAddrInfoW@4") +#pragma comment(linker,"/alternatename:__imp_?getaddrinfo@win32@fast_io@@YGHPBD0PBU?$win32_family_addrinfo@$0A@@12@PAPAU312@@Z=__imp__getaddrinfo@16") +#pragma comment(linker,"/alternatename:__imp_?GetAddrInfoW@win32@fast_io@@YGHPB_S0PBU?$win32_family_addrinfo@$00@12@PAPAU312@@Z=__imp__GetAddrInfoW@16") +#pragma comment(linker,"/alternatename:__imp_?CryptAcquireContextA@win32@fast_io@@YGHPAIPB_Q1II@Z=__imp__CryptAcquireContextA@20") +#pragma comment(linker,"/alternatename:__imp_?CryptAcquireContextW@win32@fast_io@@YGHPAIPB_S1II@Z=__imp__CryptAcquireContextW@20") +#pragma comment(linker,"/alternatename:__imp_?CryptReleaseContext@win32@fast_io@@YGHII@Z=__imp__CryptReleaseContext@8") +#pragma comment(linker,"/alternatename:__imp_?CryptGenRandom@win32@fast_io@@YGHIIPAE@Z=__imp__CryptGenRandom@12") +#pragma comment(linker,"/alternatename:__imp_?RegOpenKeyA@win32@fast_io@@YGHIPB_QPAI@Z=__imp__RegOpenKeyA@12") +#pragma comment(linker,"/alternatename:__imp_?RegOpenKeyW@win32@fast_io@@YGHIPB_SPAI@Z=__imp__RegOpenKeyW@12") +#pragma comment(linker,"/alternatename:__imp_?RegQueryValueExA@win32@fast_io@@YGHIPB_QPAI1PAX1@Z=__imp__RegQueryValueExA@24") +#pragma comment(linker,"/alternatename:__imp_?RegQueryValueExW@win32@fast_io@@YGHIPB_SPAI1PAX1@Z=__imp__RegQueryValueExW@24") +#pragma comment(linker,"/alternatename:__imp_?RegCloseKey@win32@fast_io@@YGHI@Z=__imp__RegCloseKey@4") +#pragma comment(linker,"/alternatename:__imp_?GetTimeZoneInformation@win32@fast_io@@YGIPAUtime_zone_information@12@@Z=__imp__GetTimeZoneInformation@4") +#pragma comment(linker,"/alternatename:__imp_?rtl_nt_status_to_dos_error@nt@win32@fast_io@@YGII@Z=__imp__RtlNtStatusToDosError@4") +#pragma comment(linker,"/alternatename:__imp_?NtClose@nt@win32@fast_io@@YGIPAX@Z=__imp__NtClose@4") +#pragma comment(linker,"/alternatename:__imp_?ZwClose@nt@win32@fast_io@@YGIPAX@Z=__imp__ZwClose@4") +#pragma comment(linker,"/alternatename:__imp_?NtCreateFile@nt@win32@fast_io@@YGIPAPAXIPAUobject_attributes@123@PAUio_status_block@123@PA_JIIIIPAXI@Z=__imp__NtCreateFile@44") +#pragma comment(linker,"/alternatename:__imp_?ZwCreateFile@nt@win32@fast_io@@YGIPAPAXIPAUobject_attributes@123@PAUio_status_block@123@PA_JIIIIPAXI@Z=__imp__ZwCreateFile@44") +#pragma comment(linker,"/alternatename:__imp_?NtCreateSection@nt@win32@fast_io@@YGIPIAPAXIPIAUobject_attributes@123@PA_KIIPIAX@Z=__imp__NtCreateSection@28") +#pragma comment(linker,"/alternatename:__imp_?ZwCreateSection@nt@win32@fast_io@@YGIPIAPAXIPIAUobject_attributes@123@PA_KIIPIAX@Z=__imp__ZwCreateSection@28") +#pragma comment(linker,"/alternatename:__imp_?NtQueryInformationProcess@nt@win32@fast_io@@YGIPIAXW4process_information_class@123@PAUprocess_basic_information@123@IPAI@Z=__imp__NtQueryInformationProcess@20") +#pragma comment(linker,"/alternatename:__imp_?ZwQueryInformationProcess@nt@win32@fast_io@@YGIPIAXW4process_information_class@123@PAUprocess_basic_information@123@IPAI@Z=__imp__ZwQueryInformationProcess@20") +#pragma comment(linker,"/alternatename:__imp_?NtWriteFile@nt@win32@fast_io@@YGIPAX0P6AX0PAUio_status_block@123@I@_E01PBXIPA_JPAI@Z=__imp__NtWriteFile@36") +#pragma comment(linker,"/alternatename:__imp_?ZwWriteFile@nt@win32@fast_io@@YGIPAX0P6AX0PAUio_status_block@123@I@_E01PBXIPA_JPAI@Z=__imp__ZwWriteFile@36") +#pragma comment(linker,"/alternatename:__imp_?NtReadFile@nt@win32@fast_io@@YGIPAX0P6AX0PAUio_status_block@123@I@_E01PBXIPA_JPAI@Z=__imp__NtReadFile@36") +#pragma comment(linker,"/alternatename:__imp_?ZwReadFile@nt@win32@fast_io@@YGIPAX0P6AX0PAUio_status_block@123@I@_E01PBXIPA_JPAI@Z=__imp__ZwReadFile@36") +#pragma comment(linker,"/alternatename:__imp_?NtQueryDirectoryFile@nt@win32@fast_io@@YGIPAX0P6AX0PAUio_status_block@123@I@_E010IW4file_information_class@123@HPAUunicode_string@123@H@Z=__imp__NtQueryDirectoryFile@44") +#pragma comment(linker,"/alternatename:__imp_?ZwQueryDirectoryFile@nt@win32@fast_io@@YGIPAX0P6AX0PAUio_status_block@123@I@_E010IW4file_information_class@123@HPAUunicode_string@123@H@Z=__imp__ZwQueryDirectoryFile@44") +#pragma comment(linker,"/alternatename:__imp_?NtQuerySection@nt@win32@fast_io@@YGIPAXW4section_information_class@123@0IPAI@Z=__imp__NtQuerySection@20") +#pragma comment(linker,"/alternatename:__imp_?ZwQuerySection@nt@win32@fast_io@@YGIPAXW4section_information_class@123@0IPAI@Z=__imp__ZwQuerySection@20") +#pragma comment(linker,"/alternatename:__imp_?NtQueryInformationFile@nt@win32@fast_io@@YGIPIAXPIAUio_status_block@123@0IW4file_information_class@123@@Z=__imp__NtQueryInformationFile@20") +#pragma comment(linker,"/alternatename:__imp_?ZwQueryInformationFile@nt@win32@fast_io@@YGIPIAXPIAUio_status_block@123@0IW4file_information_class@123@@Z=__imp__ZwQueryInformationFile@20") +#pragma comment(linker,"/alternatename:__imp_?NtSetInformationFile@nt@win32@fast_io@@YGIPIAXPIAUio_status_block@123@0IW4file_information_class@123@@Z=__imp__NtSetInformationFile@20") +#pragma comment(linker,"/alternatename:__imp_?ZwSetInformationFile@nt@win32@fast_io@@YGIPIAXPIAUio_status_block@123@0IW4file_information_class@123@@Z=__imp__ZwSetInformationFile@20") +#pragma comment(linker,"/alternatename:__imp_?NtDuplicateObject@nt@win32@fast_io@@YGIPAX00PAPAXIII@Z=__imp__NtDuplicateObject@28") +#pragma comment(linker,"/alternatename:__imp_?ZwDuplicateObject@nt@win32@fast_io@@YGIPAX00PAPAXIII@Z=__imp__ZwDuplicateObject@28") +#pragma comment(linker,"/alternatename:__imp_?NtWaitForSingleObject@nt@win32@fast_io@@YGIPAXHPA_K@Z=__imp__NtWaitForSingleObject@12") +#pragma comment(linker,"/alternatename:__imp_?ZwWaitForSingleObject@nt@win32@fast_io@@YGIPAXHPA_K@Z=__imp__ZwWaitForSingleObject@12") +#pragma comment(linker,"/alternatename:__imp_?NtSetSystemTime@nt@win32@fast_io@@YGIPA_K0@Z=__imp__NtSetSystemTime@8") +#pragma comment(linker,"/alternatename:__imp_?ZwSetSystemTime@nt@win32@fast_io@@YGIPA_K0@Z=__imp__ZwSetSystemTime@8") +#pragma comment(linker,"/alternatename:__imp_?NtCreateProcess@nt@win32@fast_io@@YGIPAPAXIPAUobject_attributes@123@PAXI222@Z=__imp__NtCreateProcess@32") +#pragma comment(linker,"/alternatename:__imp_?ZwCreateProcess@nt@win32@fast_io@@YGIPAPAXIPAUobject_attributes@123@PAXI222@Z=__imp__ZwCreateProcess@32") +#pragma comment(linker,"/alternatename:__imp_?rtl_dos_path_name_to_nt_path_name_u@nt@win32@fast_io@@YGEPB_SPAUunicode_string@123@PAPB_SPAUrtl_relative_name_u@123@@Z=__imp__RtlDosPathNameToNtPathName_U@16") +#pragma comment(linker,"/alternatename:__imp_?rtl_dos_path_name_to_nt_path_name_u_with_status@nt@win32@fast_io@@YGIPB_SPAUunicode_string@123@PAPB_SPAUrtl_relative_name_u@123@@Z=__imp__RtlDosPathNameToNtPathName_U_WithStatus@16") +#pragma comment(linker,"/alternatename:__imp_?rtl_free_unicode_string@nt@win32@fast_io@@YGXPAUunicode_string@123@@Z=__imp__RtlFreeUnicodeString@4") +#pragma comment(linker,"/alternatename:__imp_?RtlInitializeCriticalSection@nt@win32@fast_io@@YGXPAX@Z=__imp__RtlInitializeCriticalSection@4") +#pragma comment(linker,"/alternatename:__imp_?RtlEnterCriticalSection@nt@win32@fast_io@@YGXPAX@Z=__imp__RtlEnterCriticalSection@4") +#pragma comment(linker,"/alternatename:__imp_?RtlTryEnterCriticalSection@nt@win32@fast_io@@YGHPAX@Z=__imp__RtlTryEnterCriticalSection@4") +#pragma comment(linker,"/alternatename:__imp_?RtlLeaveCriticalSection@nt@win32@fast_io@@YGXPAX@Z=__imp__RtlLeaveCriticalSection@4") +#pragma comment(linker,"/alternatename:__imp_?RtlDeleteCriticalSection@nt@win32@fast_io@@YGXPAX@Z=__imp__RtlDeleteCriticalSection@4") +#pragma comment(linker,"/alternatename:__imp_?RtlCreateUserThread@nt@win32@fast_io@@YGIPAX0HIII00PAPAXPAUclient_id@123@@Z=__imp__RtlCreateUserThread@40") +#pragma comment(linker,"/alternatename:__imp_?NtResumeThread@nt@win32@fast_io@@YGIPAXPAI@Z=__imp__NtResumeThread@8") +#pragma comment(linker,"/alternatename:__imp_?ZwResumeThread@nt@win32@fast_io@@YGIPAXPAI@Z=__imp__ZwResumeThread@8") +#pragma comment(linker,"/alternatename:__imp_?NtLockFile@nt@win32@fast_io@@YGIPAX0P6AX0PAUio_status_block@123@I@_E01PA_J3IEE@Z=__imp__NtLockFile@40") +#pragma comment(linker,"/alternatename:__imp_?ZwLockFile@nt@win32@fast_io@@YGIPAX0P6AX0PAUio_status_block@123@I@_E01PA_J3IEE@Z=__imp__ZwLockFile@40") +#pragma comment(linker,"/alternatename:__imp_?NtUnlockFile@nt@win32@fast_io@@YGIPAXPAUio_status_block@123@PA_J2I@Z=__imp__NtUnlockFile@20") +#pragma comment(linker,"/alternatename:__imp_?ZwUnlockFile@nt@win32@fast_io@@YGIPAXPAUio_status_block@123@PA_J2I@Z=__imp__ZwUnlockFile@20") +#pragma comment(linker,"/alternatename:__imp_?NtFlushBuffersFile@nt@win32@fast_io@@YGIPAXPAUio_status_block@123@@Z=__imp__NtFlushBuffersFile@8") +#pragma comment(linker,"/alternatename:__imp_?ZwFlushBuffersFile@nt@win32@fast_io@@YGIPAXPAUio_status_block@123@@Z=__imp__ZwFlushBuffersFile@8") +#pragma comment(linker,"/alternatename:__imp_?NtFlushBuffersFileEx@nt@win32@fast_io@@YGIPAXI0IPAUio_status_block@123@@Z=__imp__NtFlushBuffersFileEx@20") +#pragma comment(linker,"/alternatename:__imp_?ZwFlushBuffersFileEx@nt@win32@fast_io@@YGIPAXI0IPAUio_status_block@123@@Z=__imp__ZwFlushBuffersFileEx@20") +#pragma comment(linker,"/alternatename:__imp_?DbgPrint@nt@win32@fast_io@@YAIPBDZZ=__imp__DbgPrint") +#pragma comment(linker,"/alternatename:__imp_?DbgPrintEx@nt@win32@fast_io@@YAIIIPBDZZ=__imp__DbgPrintEx") +#pragma comment(linker,"/alternatename:__imp_?RtlCreateProcessParameters@nt@win32@fast_io@@YGIPAPAUrtl_user_process_parameters@123@PAUunicode_string@123@111PAX1111@Z=__imp__RtlCreateProcessParameters@40") +#pragma comment(linker,"/alternatename:__imp_?RtlCreateProcessParametersEx@nt@win32@fast_io@@YGIPAPAUrtl_user_process_parameters@123@PAUunicode_string@123@111PAX1111I@Z=__imp__RtlCreateProcessParametersEx@44") +#pragma comment(linker,"/alternatename:__imp_?RtlDestroyProcessParameters@nt@win32@fast_io@@YGIPAUrtl_user_process_parameters@123@@Z=__imp__RtlDestroyProcessParameters@4") +#pragma comment(linker,"/alternatename:__imp_?NtCreateUserProcess@nt@win32@fast_io@@YGIPAX0IIPAUobject_attributes@123@1IIPAUrtl_user_process_parameters@123@PAUps_create_info@123@PAUps_attribute_list@123@@Z=__imp__NtCreateUserProcess@44") +#pragma comment(linker,"/alternatename:__imp_?ZwCreateUserProcess@nt@win32@fast_io@@YGIPAX0IIPAUobject_attributes@123@1IIPAUrtl_user_process_parameters@123@PAUps_create_info@123@PAUps_attribute_list@123@@Z=__imp__ZwCreateUserProcess@44") +#pragma comment(linker,"/alternatename:__imp_?RtlCreateUserProcess@nt@win32@fast_io@@YGIPAUunicode_string@123@IPAUrtl_user_process_parameters@123@PAUsecurity_descriptor@123@2PAXE33PAUrtl_user_process_information@123@@Z=__imp__RtlCreateUserProcess@40") diff --git a/src/fast_io/include/fast_io_hosted/platforms/win32/msvc_linker_64.h b/src/fast_io/include/fast_io_hosted/platforms/win32/msvc_linker_64.h new file mode 100644 index 0000000..bb4a12c --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/win32/msvc_linker_64.h @@ -0,0 +1,164 @@ +#pragma once + +#pragma comment(linker,"/alternatename:__imp_?GetLastError@win32@fast_io@@YAIXZ=__imp_GetLastError") +#pragma comment(linker,"/alternatename:__imp_?LoadLibraryA@win32@fast_io@@YAPEAXPEBD@Z=__imp_LoadLibraryA") +#pragma comment(linker,"/alternatename:__imp_?LoadLibraryW@win32@fast_io@@YAPEAXPEB_S@Z=__imp_LoadLibraryW") +#pragma comment(linker,"/alternatename:__imp_?LoadLibraryExA@win32@fast_io@@YAPEAXPEBDPEAXI@Z=__imp_LoadLibraryExA") +#pragma comment(linker,"/alternatename:__imp_?LoadLibraryExW@win32@fast_io@@YAPEAXPEB_SPEAXI@Z=__imp_LoadLibraryExW") +#pragma comment(linker,"/alternatename:__imp_?FormatMessageA@win32@fast_io@@YAIIPEBDIIPEADIPEAX@Z=__imp_FormatMessageA") +#pragma comment(linker,"/alternatename:__imp_?FormatMessageW@win32@fast_io@@YAIIPEB_SIIPEA_SIPEAX@Z=__imp_FormatMessageW") +#pragma comment(linker,"/alternatename:__imp_?CreateFileMappingA@win32@fast_io@@YAPEAXPEAXPEAUsecurity_attributes@12@IIIPEBD@Z=__imp_CreateFileMappingA") +#pragma comment(linker,"/alternatename:__imp_?CreateFileMappingW@win32@fast_io@@YAPEAXPEAXPEAUsecurity_attributes@12@IIIPEB_S@Z=__imp_CreateFileMappingW") +#pragma comment(linker,"/alternatename:__imp_?MapViewOfFile@win32@fast_io@@YAPEAXPEAXIII_K@Z=__imp_MapViewOfFile") +#pragma comment(linker,"/alternatename:__imp_?SetEndOfFile@win32@fast_io@@YAHPEAX@Z=__imp_SetEndOfFile") +#pragma comment(linker,"/alternatename:__imp_?UnmapViewOfFile@win32@fast_io@@YAHPEBX@Z=__imp_UnmapViewOfFile") +#pragma comment(linker,"/alternatename:__imp_?WriteFile@win32@fast_io@@YAHPEAXPEBXIPEAIPEAUoverlapped@12@@Z=__imp_WriteFile") +#pragma comment(linker,"/alternatename:__imp_?ReadFile@win32@fast_io@@YAHPEAXPEBXIPEAIPEAUoverlapped@12@@Z=__imp_ReadFile") +#pragma comment(linker,"/alternatename:__imp_?SetFilePointer@win32@fast_io@@YAIPEAXHPEAHI@Z=__imp_SetFilePointer") +#pragma comment(linker,"/alternatename:__imp_?SetFilePointerEx@win32@fast_io@@YAHPEAX_JPEA_JI@Z=__imp_SetFilePointerEx") +#pragma comment(linker,"/alternatename:__imp_?DuplicateHandle@win32@fast_io@@YAHPEAX00PEAPEAXIHI@Z=__imp_DuplicateHandle") +#pragma comment(linker,"/alternatename:__imp_?GetStdHandle@win32@fast_io@@YAPEAXI@Z=__imp_GetStdHandle") +#pragma comment(linker,"/alternatename:__imp_?CreatePipe@win32@fast_io@@YAHPEAPEAX0PEAUsecurity_attributes@12@I@Z=__imp_CreatePipe") +#pragma comment(linker,"/alternatename:__imp_?FreeLibrary@win32@fast_io@@YAHPEAX@Z=__imp_FreeLibrary") +#pragma comment(linker,"/alternatename:__imp_?GetProcAddress@win32@fast_io@@YAP6A_JX_EPEAXPEBD@Z=__imp_GetProcAddress") +#pragma comment(linker,"/alternatename:__imp_?GetModuleHandleA@win32@fast_io@@YAPEAXPEBD@Z=__imp_GetModuleHandleA") +#pragma comment(linker,"/alternatename:__imp_?GetModuleHandleW@win32@fast_io@@YAPEAXPEB_S@Z=__imp_GetModuleHandleW") +#pragma comment(linker,"/alternatename:__imp_?WaitForSingleObject@win32@fast_io@@YAIPEAXI@Z=__imp_WaitForSingleObject") +#pragma comment(linker,"/alternatename:__imp_?CancelIo@win32@fast_io@@YAIPEAX@Z=__imp_CancelIo") +#pragma comment(linker,"/alternatename:__imp_?GetFileInformationByHandle@win32@fast_io@@YAHPEIAXPEIAUby_handle_file_information@12@@Z=__imp_GetFileInformationByHandle") +#pragma comment(linker,"/alternatename:__imp_?GetUserDefaultLocaleName@win32@fast_io@@YAHPEA_SH@Z=__imp_GetUserDefaultLocaleName") +#pragma comment(linker,"/alternatename:__imp_?GetUserDefaultLCID@win32@fast_io@@YAIXZ=__imp_GetUserDefaultLCID") +#pragma comment(linker,"/alternatename:__imp_?GetSystemTimePreciseAsFileTime@win32@fast_io@@YAXPEAUfiletime@12@@Z=__imp_GetSystemTimePreciseAsFileTime") +#pragma comment(linker,"/alternatename:__imp_?GetSystemTimeAsFileTime@win32@fast_io@@YAXPEAUfiletime@12@@Z=__imp_GetSystemTimeAsFileTime") +#pragma comment(linker,"/alternatename:__imp_?QueryUnbiasedInterruptTime@win32@fast_io@@YAHPEA_K@Z=__imp_QueryUnbiasedInterruptTime") +#pragma comment(linker,"/alternatename:__imp_?QueryPerformanceCounter@win32@fast_io@@YAHPEA_J@Z=__imp_QueryPerformanceCounter") +#pragma comment(linker,"/alternatename:__imp_?QueryPerformanceFrequency@win32@fast_io@@YAHPEA_J@Z=__imp_QueryPerformanceFrequency") +#pragma comment(linker,"/alternatename:__imp_?GetProcessTimes@win32@fast_io@@YAHPEAXPEAUfiletime@12@111@Z=__imp_GetProcessTimes") +#pragma comment(linker,"/alternatename:__imp_?GetThreadTimes@win32@fast_io@@YAHPEAXPEAUfiletime@12@111@Z=__imp_GetThreadTimes") +#pragma comment(linker,"/alternatename:__imp_?GetHandleInformation@win32@fast_io@@YAHPEAXPEAI@Z=__imp_GetHandleInformation") +#pragma comment(linker,"/alternatename:__imp_?SetHandleInformation@win32@fast_io@@YAHPEAXII@Z=__imp_SetHandleInformation") +#pragma comment(linker,"/alternatename:__imp_?GetTempPathA@win32@fast_io@@YAIIPEAD@Z=__imp_GetTempPathA") +#pragma comment(linker,"/alternatename:__imp_?GetTempPathW@win32@fast_io@@YAIIPEA_S@Z=__imp_GetTempPathW") +#pragma comment(linker,"/alternatename:__imp_?CreateFileA@win32@fast_io@@YAPEAXPEBDIIPEAUsecurity_attributes@12@IIPEAX@Z=__imp_CreateFileA") +#pragma comment(linker,"/alternatename:__imp_?CreateFileW@win32@fast_io@@YAPEAXPEB_SIIPEAUsecurity_attributes@12@IIPEAX@Z=__imp_CreateFileW") +#pragma comment(linker,"/alternatename:__imp_?CreateIoCompletionPort@win32@fast_io@@YAPEAXPEAX0_KI@Z=__imp_CreateIoCompletionPort") +#pragma comment(linker,"/alternatename:__imp_?SystemFunction036@win32@fast_io@@YAHPEAXI@Z=__imp_SystemFunction036") +#pragma comment(linker,"/alternatename:__imp_?CloseHandle@win32@fast_io@@YAHPEAX@Z=__imp_CloseHandle") +#pragma comment(linker,"/alternatename:__imp_?LockFileEx@win32@fast_io@@YAHPEAXIIIIPEAUoverlapped@12@@Z=__imp_LockFileEx") +#pragma comment(linker,"/alternatename:__imp_?UnlockFileEx@win32@fast_io@@YAHPEAXIIIPEAUoverlapped@12@@Z=__imp_UnlockFileEx") +#pragma comment(linker,"/alternatename:__imp_?DeviceIoControl@win32@fast_io@@YAHPEAXI0I0I0PEAUoverlapped@12@@Z=__imp_DeviceIoControl") +#pragma comment(linker,"/alternatename:__imp_?GetFileType@win32@fast_io@@YAIPEAX@Z=__imp_GetFileType") +#pragma comment(linker,"/alternatename:__imp_?GetACP@win32@fast_io@@YAIXZ=__imp_GetACP") +#pragma comment(linker,"/alternatename:__imp_?GetEnvironmentVariableA@win32@fast_io@@YAIPEBDPEADI@Z=__imp_GetEnvironmentVariableA") +#pragma comment(linker,"/alternatename:__imp_?GetEnvironmentVariableW@win32@fast_io@@YAIPEB_SPEA_SI@Z=__imp_GetEnvironmentVariableW") +#pragma comment(linker,"/alternatename:__imp_?MessageBoxA@win32@fast_io@@YAIPEAXPEBD1I@Z=__imp_MessageBoxA") +#pragma comment(linker,"/alternatename:__imp_?MessageBoxW@win32@fast_io@@YAIPEAXPEB_S1I@Z=__imp_MessageBoxW") +#pragma comment(linker,"/alternatename:__imp_?GetConsoleMode@win32@fast_io@@YAHPEAXPEAI@Z=__imp_GetConsoleMode") +#pragma comment(linker,"/alternatename:__imp_?SetConsoleMode@win32@fast_io@@YAHPEAXI@Z=__imp_SetConsoleMode") +#pragma comment(linker,"/alternatename:__imp_?ReadConsoleA@win32@fast_io@@YAHPEAX0IPEAI0@Z=__imp_ReadConsoleA") +#pragma comment(linker,"/alternatename:__imp_?ReadConsoleW@win32@fast_io@@YAHPEAX0IPEAI0@Z=__imp_ReadConsoleW") +#pragma comment(linker,"/alternatename:__imp_?WriteConsoleA@win32@fast_io@@YAHPEAXPEBXIPEAI0@Z=__imp_WriteConsoleA") +#pragma comment(linker,"/alternatename:__imp_?WriteConsoleW@win32@fast_io@@YAHPEAXPEBXIPEAI0@Z=__imp_WriteConsoleW") +#pragma comment(linker,"/alternatename:__imp_?GetConsoleScreenBufferInfo@win32@fast_io@@YAHPEAXPEAUconsole_screen_buffer_info@12@@Z=__imp_GetConsoleScreenBufferInfo") +#pragma comment(linker,"/alternatename:__imp_?ScrollConsoleScreenBufferA@win32@fast_io@@YAHPEAXPEBUsmall_rect@12@1Ucoord@12@PEBUchar_info@12@@Z=__imp_ScrollConsoleScreenBufferA") +#pragma comment(linker,"/alternatename:__imp_?ScrollConsoleScreenBufferW@win32@fast_io@@YAHPEAXPEBUsmall_rect@12@1Ucoord@12@PEBUchar_info@12@@Z=__imp_ScrollConsoleScreenBufferW") +#pragma comment(linker,"/alternatename:__imp_?SetConsoleCursorPosition@win32@fast_io@@YAHPEAXUcoord@12@@Z=__imp_SetConsoleCursorPosition") +#pragma comment(linker,"/alternatename:__imp_?InitializeCriticalSection@win32@fast_io@@YAXPEAX@Z=__imp_InitializeCriticalSection") +#pragma comment(linker,"/alternatename:__imp_?EnterCriticalSection@win32@fast_io@@YAXPEAX@Z=__imp_EnterCriticalSection") +#pragma comment(linker,"/alternatename:__imp_?TryEnterCriticalSection@win32@fast_io@@YAHPEAX@Z=__imp_TryEnterCriticalSection") +#pragma comment(linker,"/alternatename:__imp_?LeaveCriticalSection@win32@fast_io@@YAXPEAX@Z=__imp_LeaveCriticalSection") +#pragma comment(linker,"/alternatename:__imp_?DeleteCriticalSection@win32@fast_io@@YAXPEAX@Z=__imp_DeleteCriticalSection") +#pragma comment(linker,"/alternatename:__imp_?WSADuplicateSocketA@win32@fast_io@@YAHPEAXIPEAUwsaprotocol_infoa@12@@Z=__imp_WSADuplicateSocketA") +#pragma comment(linker,"/alternatename:__imp_?WSADuplicateSocketW@win32@fast_io@@YAXPEAXIPEAUwsaprotocol_infow@12@@Z=__imp_WSADuplicateSocketW") +#pragma comment(linker,"/alternatename:__imp_?WSACleanup@win32@fast_io@@YAHXZ=__imp_WSACleanup") +#pragma comment(linker,"/alternatename:__imp_?WSAStartup@win32@fast_io@@YAHIPEAUwsadata@12@@Z=__imp_WSAStartup") +#pragma comment(linker,"/alternatename:__imp_?WSAGetLastError@win32@fast_io@@YAHXZ=__imp_WSAGetLastError") +#pragma comment(linker,"/alternatename:__imp_?closesocket@win32@fast_io@@YAH_K@Z=__imp_closesocket") +#pragma comment(linker,"/alternatename:__imp_?WSASocketW@win32@fast_io@@YA_KHHHPEAUwsaprotocol_infow@12@II@Z=__imp_WSASocketW") +#pragma comment(linker,"/alternatename:__imp_?WSASocketA@win32@fast_io@@YA_KHHHPEAUwsaprotocol_infoa@12@II@Z=__imp_WSASocketA") +#pragma comment(linker,"/alternatename:__imp_?bind@win32@fast_io@@YAH_KPEBXH@Z=__imp_bind") +#pragma comment(linker,"/alternatename:__imp_?listen@win32@fast_io@@YAH_KH@Z=__imp_listen") +#pragma comment(linker,"/alternatename:__imp_?WSAAccept@win32@fast_io@@YA_K_KPEBXPEAHP6AXPEAUwsabuf@12@3PEAUqualityofservice@12@433PEAI0@_E0@Z=__imp_WSAAccept") +#pragma comment(linker,"/alternatename:__imp_?ioctlsocket@win32@fast_io@@YAH_KJPEAI@Z=__imp_ioctlsocket") +#pragma comment(linker,"/alternatename:__imp_?WSASend@win32@fast_io@@YAH_KPEAUwsabuf@12@IPEAIIPEAUoverlapped@12@P6AXII3I@_E@Z=__imp_WSASend") +#pragma comment(linker,"/alternatename:__imp_?WSASendMsg@win32@fast_io@@YAH_KPEAUwsamsg@12@IPEAIPEAUoverlapped@12@P6AXII3I@_E@Z=__imp_WSASendMsg") +#pragma comment(linker,"/alternatename:__imp_?WSASendTo@win32@fast_io@@YAH_KPEAUwsabuf@12@IPEAIIPEBXHPEAUoverlapped@12@P6AXII4I@_E@Z=__imp_WSASendTo") +#pragma comment(linker,"/alternatename:__imp_?recv@win32@fast_io@@YAH_KPEADHH@Z=__imp_recv") +#pragma comment(linker,"/alternatename:__imp_?WSARecv@win32@fast_io@@YAH_KPEAUwsabuf@12@IPEAI2PEAUoverlapped@12@P6AXII3I@_E@Z=__imp_WSARecv") +#pragma comment(linker,"/alternatename:__imp_?WSARecvFrom@win32@fast_io@@YAH_KPEAUwsabuf@12@IPEAI2PEBXPEAHPEAUoverlapped@12@P6AXII5I@_E@Z=__imp_WSARecvFrom") +#pragma comment(linker,"/alternatename:__imp_?connect@win32@fast_io@@YAH_KPEBXH@Z=__imp_connect") +#pragma comment(linker,"/alternatename:__imp_?WSAConnect@win32@fast_io@@YAH_KPEBXHPEAUwsabuf@12@2PEAUqualityofservice@12@3@Z=__imp_WSAConnect") +#pragma comment(linker,"/alternatename:__imp_?shutdown@win32@fast_io@@YAH_KPEBXH@Z=__imp_shutdown") +#pragma comment(linker,"/alternatename:__imp_?GetCurrentProcessId@win32@fast_io@@YAIXZ=__imp_GetCurrentProcessId") +#pragma comment(linker,"/alternatename:__imp_?FlushFileBuffers@win32@fast_io@@YAHPEAX@Z=__imp_FlushFileBuffers") +#pragma comment(linker,"/alternatename:__imp_?GetQueuedCompletionStatus@win32@fast_io@@YAHPEAXPEAIPEA_KPEAUoverlapped@12@I@Z=__imp_GetQueuedCompletionStatus") +#pragma comment(linker,"/alternatename:__imp_?freeaddrinfo@win32@fast_io@@YAXPEAU?$win32_family_addrinfo@$0A@@12@@Z=__imp_freeaddrinfo") +#pragma comment(linker,"/alternatename:__imp_?FreeAddrInfoW@win32@fast_io@@YAXPEAU?$win32_family_addrinfo@$00@12@@Z=__imp_FreeAddrInfoW") +#pragma comment(linker,"/alternatename:__imp_?getaddrinfo@win32@fast_io@@YAHPEBD0PEBU?$win32_family_addrinfo@$0A@@12@PEAPEAU312@@Z=__imp_getaddrinfo") +#pragma comment(linker,"/alternatename:__imp_?GetAddrInfoW@win32@fast_io@@YAHPEB_S0PEBU?$win32_family_addrinfo@$00@12@PEAPEAU312@@Z=__imp_GetAddrInfoW") +#pragma comment(linker,"/alternatename:__imp_?CryptAcquireContextA@win32@fast_io@@YAHPEA_KPEB_Q1II@Z=__imp_CryptAcquireContextA") +#pragma comment(linker,"/alternatename:__imp_?CryptAcquireContextW@win32@fast_io@@YAHPEA_KPEB_S1II@Z=__imp_CryptAcquireContextW") +#pragma comment(linker,"/alternatename:__imp_?CryptReleaseContext@win32@fast_io@@YAH_KI@Z=__imp_CryptReleaseContext") +#pragma comment(linker,"/alternatename:__imp_?CryptGenRandom@win32@fast_io@@YAH_KIPEAE@Z=__imp_CryptGenRandom") +#pragma comment(linker,"/alternatename:__imp_?RegOpenKeyA@win32@fast_io@@YAH_KPEB_QPEA_K@Z=__imp_RegOpenKeyA") +#pragma comment(linker,"/alternatename:__imp_?RegOpenKeyW@win32@fast_io@@YAH_KPEB_SPEA_K@Z=__imp_RegOpenKeyW") +#pragma comment(linker,"/alternatename:__imp_?RegQueryValueExA@win32@fast_io@@YAH_KPEB_QPEAI2PEAX2@Z=__imp_RegQueryValueExA") +#pragma comment(linker,"/alternatename:__imp_?RegQueryValueExW@win32@fast_io@@YAH_KPEB_SPEAI2PEAX2@Z=__imp_RegQueryValueExW") +#pragma comment(linker,"/alternatename:__imp_?RegCloseKey@win32@fast_io@@YAH_K@Z=__imp_RegCloseKey") +#pragma comment(linker,"/alternatename:__imp_?GetTimeZoneInformation@win32@fast_io@@YAIPEAUtime_zone_information@12@@Z=__imp_GetTimeZoneInformation") +#pragma comment(linker,"/alternatename:__imp_?rtl_nt_status_to_dos_error@nt@win32@fast_io@@YAII@Z=__imp_RtlNtStatusToDosError") +#pragma comment(linker,"/alternatename:__imp_?NtClose@nt@win32@fast_io@@YAIPEAX@Z=__imp_NtClose") +#pragma comment(linker,"/alternatename:__imp_?ZwClose@nt@win32@fast_io@@YAIPEAX@Z=__imp_ZwClose") +#pragma comment(linker,"/alternatename:__imp_?NtCreateFile@nt@win32@fast_io@@YAIPEAPEAXIPEAUobject_attributes@123@PEAUio_status_block@123@PEA_JIIIIPEAXI@Z=__imp_NtCreateFile") +#pragma comment(linker,"/alternatename:__imp_?ZwCreateFile@nt@win32@fast_io@@YAIPEAPEAXIPEAUobject_attributes@123@PEAUio_status_block@123@PEA_JIIIIPEAXI@Z=__imp_ZwCreateFile") +#pragma comment(linker,"/alternatename:__imp_?NtCreateSection@nt@win32@fast_io@@YAIPEIAPEAXIPEIAUobject_attributes@123@PEA_KIIPEIAX@Z=__imp_NtCreateSection") +#pragma comment(linker,"/alternatename:__imp_?ZwCreateSection@nt@win32@fast_io@@YAIPEIAPEAXIPEIAUobject_attributes@123@PEA_KIIPEIAX@Z=__imp_ZwCreateSection") +#pragma comment(linker,"/alternatename:__imp_?NtQueryInformationProcess@nt@win32@fast_io@@YAIPEIAXW4process_information_class@123@PEAUprocess_basic_information@123@IPEAI@Z=__imp_NtQueryInformationProcess") +#pragma comment(linker,"/alternatename:__imp_?ZwQueryInformationProcess@nt@win32@fast_io@@YAIPEIAXW4process_information_class@123@PEAUprocess_basic_information@123@IPEAI@Z=__imp_ZwQueryInformationProcess") +#pragma comment(linker,"/alternatename:__imp_?NtWriteFile@nt@win32@fast_io@@YAIPEAX0P6AX0PEAUio_status_block@123@I@_E01PEBXIPEA_JPEAI@Z=__imp_NtWriteFile") +#pragma comment(linker,"/alternatename:__imp_?ZwWriteFile@nt@win32@fast_io@@YAIPEAX0P6AX0PEAUio_status_block@123@I@_E01PEBXIPEA_JPEAI@Z=__imp_ZwWriteFile") +#pragma comment(linker,"/alternatename:__imp_?NtReadFile@nt@win32@fast_io@@YAIPEAX0P6AX0PEAUio_status_block@123@I@_E01PEBXIPEA_JPEAI@Z=__imp_NtReadFile") +#pragma comment(linker,"/alternatename:__imp_?ZwReadFile@nt@win32@fast_io@@YAIPEAX0P6AX0PEAUio_status_block@123@I@_E01PEBXIPEA_JPEAI@Z=__imp_ZwReadFile") +#pragma comment(linker,"/alternatename:__imp_?NtQueryDirectoryFile@nt@win32@fast_io@@YAIPEAX0P6AX0PEAUio_status_block@123@I@_E010IW4file_information_class@123@HPEAUunicode_string@123@H@Z=__imp_NtQueryDirectoryFile") +#pragma comment(linker,"/alternatename:__imp_?ZwQueryDirectoryFile@nt@win32@fast_io@@YAIPEAX0P6AX0PEAUio_status_block@123@I@_E010IW4file_information_class@123@HPEAUunicode_string@123@H@Z=__imp_ZwQueryDirectoryFile") +#pragma comment(linker,"/alternatename:__imp_?NtQuerySection@nt@win32@fast_io@@YAIPEAXW4section_information_class@123@0_KPEA_K@Z=__imp_NtQuerySection") +#pragma comment(linker,"/alternatename:__imp_?ZwQuerySection@nt@win32@fast_io@@YAIPEAXW4section_information_class@123@0_KPEA_K@Z=__imp_ZwQuerySection") +#pragma comment(linker,"/alternatename:__imp_?NtQueryInformationFile@nt@win32@fast_io@@YAIPEIAXPEIAUio_status_block@123@0IW4file_information_class@123@@Z=__imp_NtQueryInformationFile") +#pragma comment(linker,"/alternatename:__imp_?ZwQueryInformationFile@nt@win32@fast_io@@YAIPEIAXPEIAUio_status_block@123@0IW4file_information_class@123@@Z=__imp_ZwQueryInformationFile") +#pragma comment(linker,"/alternatename:__imp_?NtSetInformationFile@nt@win32@fast_io@@YAIPEIAXPEIAUio_status_block@123@0IW4file_information_class@123@@Z=__imp_NtSetInformationFile") +#pragma comment(linker,"/alternatename:__imp_?ZwSetInformationFile@nt@win32@fast_io@@YAIPEIAXPEIAUio_status_block@123@0IW4file_information_class@123@@Z=__imp_ZwSetInformationFile") +#pragma comment(linker,"/alternatename:__imp_?NtDuplicateObject@nt@win32@fast_io@@YAIPEAX00PEAPEAXIII@Z=__imp_NtDuplicateObject") +#pragma comment(linker,"/alternatename:__imp_?ZwDuplicateObject@nt@win32@fast_io@@YAIPEAX00PEAPEAXIII@Z=__imp_ZwDuplicateObject") +#pragma comment(linker,"/alternatename:__imp_?NtWaitForSingleObject@nt@win32@fast_io@@YAIPEAXHPEA_K@Z=__imp_NtWaitForSingleObject") +#pragma comment(linker,"/alternatename:__imp_?ZwWaitForSingleObject@nt@win32@fast_io@@YAIPEAXHPEA_K@Z=__imp_ZwWaitForSingleObject") +#pragma comment(linker,"/alternatename:__imp_?NtSetSystemTime@nt@win32@fast_io@@YAIPEA_K0@Z=__imp_NtSetSystemTime") +#pragma comment(linker,"/alternatename:__imp_?ZwSetSystemTime@nt@win32@fast_io@@YAIPEA_K0@Z=__imp_ZwSetSystemTime") +#pragma comment(linker,"/alternatename:__imp_?NtCreateProcess@nt@win32@fast_io@@YAIPEAPEAXIPEAUobject_attributes@123@PEAXI222@Z=__imp_NtCreateProcess") +#pragma comment(linker,"/alternatename:__imp_?ZwCreateProcess@nt@win32@fast_io@@YAIPEAPEAXIPEAUobject_attributes@123@PEAXI222@Z=__imp_ZwCreateProcess") +#pragma comment(linker,"/alternatename:__imp_?rtl_dos_path_name_to_nt_path_name_u@nt@win32@fast_io@@YAEPEB_SPEAUunicode_string@123@PEAPEB_SPEAUrtl_relative_name_u@123@@Z=__imp_RtlDosPathNameToNtPathName_U") +#pragma comment(linker,"/alternatename:__imp_?rtl_dos_path_name_to_nt_path_name_u_with_status@nt@win32@fast_io@@YAIPEB_SPEAUunicode_string@123@PEAPEB_SPEAUrtl_relative_name_u@123@@Z=__imp_RtlDosPathNameToNtPathName_U_WithStatus") +#pragma comment(linker,"/alternatename:__imp_?rtl_free_unicode_string@nt@win32@fast_io@@YAXPEAUunicode_string@123@@Z=__imp_RtlFreeUnicodeString") +#pragma comment(linker,"/alternatename:__imp_?RtlInitializeCriticalSection@nt@win32@fast_io@@YAXPEAX@Z=__imp_RtlInitializeCriticalSection") +#pragma comment(linker,"/alternatename:__imp_?RtlEnterCriticalSection@nt@win32@fast_io@@YAXPEAX@Z=__imp_RtlEnterCriticalSection") +#pragma comment(linker,"/alternatename:__imp_?RtlTryEnterCriticalSection@nt@win32@fast_io@@YAHPEAX@Z=__imp_RtlTryEnterCriticalSection") +#pragma comment(linker,"/alternatename:__imp_?RtlLeaveCriticalSection@nt@win32@fast_io@@YAXPEAX@Z=__imp_RtlLeaveCriticalSection") +#pragma comment(linker,"/alternatename:__imp_?RtlDeleteCriticalSection@nt@win32@fast_io@@YAXPEAX@Z=__imp_RtlDeleteCriticalSection") +#pragma comment(linker,"/alternatename:__imp_?RtlCreateUserThread@nt@win32@fast_io@@YAIPEAX0HI_K100PEAPEAXPEAUclient_id@123@@Z=__imp_RtlCreateUserThread") +#pragma comment(linker,"/alternatename:__imp_?NtResumeThread@nt@win32@fast_io@@YAIPEAXPEAI@Z=__imp_NtResumeThread") +#pragma comment(linker,"/alternatename:__imp_?ZwResumeThread@nt@win32@fast_io@@YAIPEAXPEAI@Z=__imp_ZwResumeThread") +#pragma comment(linker,"/alternatename:__imp_?NtLockFile@nt@win32@fast_io@@YAIPEAX0P6AX0PEAUio_status_block@123@I@_E01PEA_J3IEE@Z=__imp_NtLockFile") +#pragma comment(linker,"/alternatename:__imp_?ZwLockFile@nt@win32@fast_io@@YAIPEAX0P6AX0PEAUio_status_block@123@I@_E01PEA_J3IEE@Z=__imp_ZwLockFile") +#pragma comment(linker,"/alternatename:__imp_?NtUnlockFile@nt@win32@fast_io@@YAIPEAXPEAUio_status_block@123@PEA_J2I@Z=__imp_NtUnlockFile") +#pragma comment(linker,"/alternatename:__imp_?ZwUnlockFile@nt@win32@fast_io@@YAIPEAXPEAUio_status_block@123@PEA_J2I@Z=__imp_ZwUnlockFile") +#pragma comment(linker,"/alternatename:__imp_?NtFlushBuffersFile@nt@win32@fast_io@@YAIPEAXPEAUio_status_block@123@@Z=__imp_NtFlushBuffersFile") +#pragma comment(linker,"/alternatename:__imp_?ZwFlushBuffersFile@nt@win32@fast_io@@YAIPEAXPEAUio_status_block@123@@Z=__imp_ZwFlushBuffersFile") +#pragma comment(linker,"/alternatename:__imp_?NtFlushBuffersFileEx@nt@win32@fast_io@@YAIPEAXI0IPEAUio_status_block@123@@Z=__imp_NtFlushBuffersFileEx") +#pragma comment(linker,"/alternatename:__imp_?ZwFlushBuffersFileEx@nt@win32@fast_io@@YAIPEAXI0IPEAUio_status_block@123@@Z=__imp_ZwFlushBuffersFileEx") +#pragma comment(linker,"/alternatename:__imp_?DbgPrint@nt@win32@fast_io@@YAIPEBDZZ=__imp_DbgPrint") +#pragma comment(linker,"/alternatename:__imp_?DbgPrintEx@nt@win32@fast_io@@YAIIIPEBDZZ=__imp_DbgPrintEx") +#pragma comment(linker,"/alternatename:__imp_?RtlCreateProcessParameters@nt@win32@fast_io@@YAIPEAPEAUrtl_user_process_parameters@123@PEAUunicode_string@123@111PEAX1111@Z=__imp_RtlCreateProcessParameters") +#pragma comment(linker,"/alternatename:__imp_?RtlCreateProcessParametersEx@nt@win32@fast_io@@YAIPEAPEAUrtl_user_process_parameters@123@PEAUunicode_string@123@111PEAX1111I@Z=__imp_RtlCreateProcessParametersEx") +#pragma comment(linker,"/alternatename:__imp_?RtlDestroyProcessParameters@nt@win32@fast_io@@YAIPEAUrtl_user_process_parameters@123@@Z=__imp_RtlDestroyProcessParameters") +#pragma comment(linker,"/alternatename:__imp_?NtCreateUserProcess@nt@win32@fast_io@@YAIPEAX0IIPEAUobject_attributes@123@1IIPEAUrtl_user_process_parameters@123@PEAUps_create_info@123@PEAUps_attribute_list@123@@Z=__imp_NtCreateUserProcess") +#pragma comment(linker,"/alternatename:__imp_?ZwCreateUserProcess@nt@win32@fast_io@@YAIPEAX0IIPEAUobject_attributes@123@1IIPEAUrtl_user_process_parameters@123@PEAUps_create_info@123@PEAUps_attribute_list@123@@Z=__imp_ZwCreateUserProcess") +#pragma comment(linker,"/alternatename:__imp_?RtlCreateUserProcess@nt@win32@fast_io@@YAIPEAUunicode_string@123@IPEAUrtl_user_process_parameters@123@PEAUsecurity_descriptor@123@2PEAXE33PEAUrtl_user_process_information@123@@Z=__imp_RtlCreateUserProcess") diff --git a/src/fast_io/include/fast_io_hosted/platforms/win32/utils.h b/src/fast_io/include/fast_io_hosted/platforms/win32/utils.h new file mode 100644 index 0000000..db067bf --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/win32/utils.h @@ -0,0 +1,43 @@ +#pragma once + +namespace fast_io::win32 +{ + +constexpr unix_timestamp to_unix_timestamp(filetime ft) noexcept +{ + std::uint_least64_t date_time{(static_cast(ft.dwHighDateTime)<<32)|ft.dwLowDateTime}; + +/* +116444736000000000 +18446744073709551616 + 999999999 +1000000000 +*/ + + constexpr std::uint_least64_t gap{11644473600000ULL * 10000ULL}; + constexpr std::uint_least64_t mul_factor{uint_least64_subseconds_per_second/10000000u}; + std::uint_least64_t unix_time{date_time-gap}; + if(date_time(unix_time/10000000ULL),static_cast(unix_time%10000000ULL)*mul_factor}; +} + +inline constexpr win32_timestamp to_win32_timestamp_ftu64(std::uint_least64_t ftu64) noexcept +{ + std::uint_least64_t seconds{ftu64/10000000ULL}; + std::uint_least64_t subseconds{ftu64%10000000ULL}; + constexpr std::uint_least64_t mul_factor{uint_least64_subseconds_per_second/10000000u}; + return {static_cast(seconds),static_cast(subseconds*mul_factor)}; +} + +inline constexpr std::uint_least64_t filetime_to_uint_least64_t(filetime ft) noexcept +{ + return (static_cast(ft.dwHighDateTime)<<32)|ft.dwLowDateTime; +} + +inline constexpr win32_timestamp to_win32_timestamp(filetime ft) noexcept +{ + return to_win32_timestamp_ftu64((static_cast(ft.dwHighDateTime)<<32)|ft.dwLowDateTime); +} + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_hosted/platforms/win32/win32_definitions.h b/src/fast_io/include/fast_io_hosted/platforms/win32/win32_definitions.h new file mode 100644 index 0000000..9faa1dd --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/win32/win32_definitions.h @@ -0,0 +1,326 @@ +#pragma once + +namespace fast_io::win32 +{ + +struct overlapped +{ +std::conditional_t<(sizeof(std::uintptr_t)>4),std::uint_least64_t,std::uint_least32_t> Internal,InternalHigh; +union dummy_union_name_t +{ +struct dummy_struct_name_t +{ +std::uint_least32_t Offset; +std::uint_least32_t OffsetHigh; +} dummy_struct_name; +void* Pointer; +} +dummy_union_name; +void* hEvent; +}; +struct security_attributes +{ +std::uint_least32_t nLength; +void* lpSecurityDescriptor; +int bInheritHandle; +}; +struct startupinfo +{ +std::uint_least32_t cb; +char16_t* lpReserved; +char16_t* lpDesktop; +char16_t* lpTitle; +std::uint_least32_t dwX; +std::uint_least32_t dwY; +std::uint_least32_t dwXSize; +std::uint_least32_t dwYSize; +std::uint_least32_t dwXCountChars; +std::uint_least32_t dwYCountChars; +std::uint_least32_t dwFillAttribute; +std::uint_least32_t dwFlags; +std::uint_least16_t wShowWindow; +std::uint_least16_t cbReserved2; +int* lpReserved2; +void* hStdInput; +void* hStdOutput; +void* hStdError; +}; +struct process_information +{ +void* hProcess; +void* hThread; +std::uint_least32_t dwProcessId; +std::uint_least32_t dwThreadId; +}; +/* +https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getfileinformationbyhandleex +*/ +struct file_standard_info +{ +std::int_least64_t AllocationSize; +std::int_least64_t EndOfFile; +std::uint_least32_t NumberOfLinks; +int DeletePending; +int Directory; +}; + +struct file_attribute_tag_info +{ +std::uint_least32_t FileAttributes; +std::uint_least32_t ReparseTag; +}; +enum class file_info_by_handle_class +{ +FileBasicInfo, +FileStandardInfo, +FileNameInfo, +FileRenameInfo, +FileDispositionInfo, +FileAllocationInfo, +FileEndOfFileInfo, +FileStreamInfo, +FileCompressionInfo, +FileAttributeTagInfo, +FileIdBothDirectoryInfo, +FileIdBothDirectoryRestartInfo, +FileIoPriorityHintInfo, +FileRemoteProtocolInfo, +FileFullDirectoryInfo, +FileFullDirectoryRestartInfo, +FileStorageInfo, +FileAlignmentInfo, +FileIdInfo, +FileIdExtdDirectoryInfo, +FileIdExtdDirectoryRestartInfo, +FileDispositionInfoEx, +FileRenameInfoEx, +FileCaseSensitiveInfo, +FileNormalizedNameInfo, +MaximumFileInfoByHandleClass +}; + +struct filetime +{ +std::uint_least32_t dwLowDateTime,dwHighDateTime; +}; + +struct by_handle_file_information +{ +std::uint_least32_t dwFileAttributes; +filetime ftCreationTime; +filetime ftLastAccessTime; +filetime ftLastWriteTime; +std::uint_least32_t dwVolumeSerialNumber; +std::uint_least32_t nFileSizeHigh; +std::uint_least32_t nFileSizeLow; +std::uint_least32_t nNumberOfLinks; +std::uint_least32_t nFileIndexHigh; +std::uint_least32_t nFileIndexLow; +}; + +struct coord +{ + std::int_least16_t X, Y; +}; + +struct small_rect +{ + std::int_least16_t Left, Top, Right, Bottom; +}; + +struct char_info +{ + char16_t character; + std::uint_least16_t Attrib; +}; + +struct console_screen_buffer_info +{ + coord Size, CursorPosition; + std::uint_least16_t Attrib; + small_rect Window; + coord MaxWindowSize; +}; + +struct guid +{ +unsigned long Data1; +unsigned short Data2; +unsigned short Data3; +unsigned char Data4[8]; +}; + +inline constexpr std::size_t wsaprotocol_len{255}; + +struct wsaprotocolchain +{ + int ChainLen; + std::uint_least32_t ChainEntries[7]; +}; + +struct wsaprotocol_infow +{ +std::uint_least32_t dwServiceFlags1; +std::uint_least32_t dwServiceFlags2; +std::uint_least32_t dwServiceFlags3; +std::uint_least32_t dwServiceFlags4; +std::uint_least32_t dwProviderFlags; +guid ProviderId; +std::uint_least32_t dwCatalogEntryId; +wsaprotocolchain ProtocolChain; +int iVersion; +int iAddressFamily; +int iMaxSockAddr; +int iMinSockAddr; +int iSocketType; +int iProtocol; +int iProtocolMaxOffset; +int iNetworkByteOrder; +int iSecurityScheme; +std::uint_least32_t dwMessageSize; +std::uint_least32_t dwProviderReserved; +char16_t szProtocol[wsaprotocol_len + 1]; +}; + +struct wsaprotocol_infoa +{ +std::uint_least32_t dwServiceFlags1; +std::uint_least32_t dwServiceFlags2; +std::uint_least32_t dwServiceFlags3; +std::uint_least32_t dwServiceFlags4; +std::uint_least32_t dwProviderFlags; +guid ProviderId; +std::uint_least32_t dwCatalogEntryId; +wsaprotocolchain ProtocolChain; +int iVersion; +int iAddressFamily; +int iMaxSockAddr; +int iMinSockAddr; +int iSocketType; +int iProtocol; +int iProtocolMaxOffset; +int iNetworkByteOrder; +int iSecurityScheme; +std::uint_least32_t dwMessageSize; +std::uint_least32_t dwProviderReserved; +char szProtocol[wsaprotocol_len + 1]; +}; + +inline constexpr std::size_t wsadescription_len{256}; +inline constexpr std::size_t wsasys_status_len{128}; + +struct wsadata { + std::uint_least16_t wVersion; + std::uint_least16_t wHighVersion; +#ifdef _WIN64 + unsigned short iMaxSockets; + unsigned short iMaxUdpDg; + char *lpVendorInfo; + char szDescription[wsadescription_len+1]; + char szSystemStatus[wsasys_status_len+1]; +#else + char szDescription[wsadescription_len+1]; + char szSystemStatus[wsasys_status_len+1]; + unsigned short iMaxSockets; + unsigned short iMaxUdpDg; + char *lpVendorInfo; +#endif +}; + +struct wsabuf +{ +std::uint_least32_t len; +char* buf; +}; + +struct wsamsg +{ +void* name; +int namelen; +wsabuf* lpBuffers; +std::uint_least32_t dwBufferCount; +wsabuf Control; +std::uint_least32_t dwflags; +}; + +using lpwsaoverlapped_completion_routine = void ( +#if defined(_MSC_VER) && (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +__stdcall +#elif (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +__attribute__((__stdcall__)) +#endif +*)(std::uint_least32_t dwError,std::uint_least32_t cbTransferred,overlapped* lpOverlapped,std::uint_least32_t dwFlags) noexcept; + +struct flowspec +{ +std::uint_least32_t TokenRate; +std::uint_least32_t TokenBucketSize; +std::uint_least32_t PeakBandwidth; +std::uint_least32_t Latency; +std::uint_least32_t DelayVariation; +std::uint_least32_t ServiceType; +std::uint_least32_t MaxSduSize; +std::uint_least32_t MinimumPolicedSize; +}; + +struct qualityofservice +{ +flowspec SendingFlowspec; +flowspec ReceivingFlowspec; +wsabuf ProviderSpecific; +}; + + +using lpconditionproc = void ( +#if defined(_MSC_VER) && (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +__stdcall +#elif (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +__attribute__((__stdcall__)) +#endif +*)(wsabuf*,wsabuf*,qualityofservice*,qualityofservice*,wsabuf*,wsabuf*,std::uint_least32_t*,std::uintptr_t) noexcept; + +template +requires (fam==win32_family::ansi_9x||fam==win32_family::wide_nt) +struct +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +win32_family_addrinfo +{ +int ai_flags{}; +int ai_family{}; +int ai_socktype{}; +int ai_protocol{}; +std::size_t ai_addrlen{}; +std::conditional_t *ai_canonname{}; +posix_sockaddr *ai_addr{}; +win32_family_addrinfo *ai_next{}; +}; + +using win32_addrinfo_9xa = win32_family_addrinfo; +using win32_addrinfo_ntw = win32_family_addrinfo; + +struct systemtime +{ +::std::uint_least16_t wYear; +::std::uint_least16_t wMonth; +::std::uint_least16_t wDayOfWeek; +::std::uint_least16_t wDay; +::std::uint_least16_t wHour; +::std::uint_least16_t wMinute; +::std::uint_least16_t wSecond; +::std::uint_least16_t wMilliseconds; +}; + +struct time_zone_information +{ +::std::int_least32_t Bias; +char16_t StandardName[32]; +systemtime StandardDate; +::std::int_least32_t StandardBias; +char16_t DaylightName[32]; +systemtime DaylightDate; +::std::int_least32_t DaylightBias; +}; + +} diff --git a/src/fast_io/include/fast_io_hosted/platforms/win32_code.h b/src/fast_io/include/fast_io_hosted/platforms/win32_code.h new file mode 100644 index 0000000..9afc5b9 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/win32_code.h @@ -0,0 +1,161 @@ +#pragma once + +namespace fast_io +{ + +struct win32_code +{ + std::uint_least32_t ec{}; +}; + +inline constexpr std::uintptr_t domain_define(error_type_t) noexcept +{ + if constexpr(sizeof(std::uintptr_t)<=sizeof(std::uint_least16_t)) + return 8987u; + else if constexpr(sizeof(std::uintptr_t)<=sizeof(std::uint_least32_t)) + return 588553401u; + else + return 12911969238956088748ULL; +} + +inline constexpr std::uintptr_t win32_domain_value{domain_define(error_type)}; + +namespace details +{ + +inline std::size_t print_reserve_define_win32_error_9xa_impl(char* ptr, std::uint_least32_t ec) noexcept +{ + constexpr std::size_t char8_buffer_size{65536}; + return win32::FormatMessageA( + 0x00000200 | 0x00001000, + nullptr, + ec, + (1 << 10), + ptr, + char8_buffer_size, + nullptr); +} + +inline std::size_t print_reserve_define_win32_error_ntw_impl(char16_t* ptr, std::uint_least32_t ec) noexcept +{ + constexpr std::size_t char16_buffer_size{32768}; + return win32::FormatMessageW( + 0x00000200 | 0x00001000, + nullptr, + ec, + (1 << 10), + ptr, + char16_buffer_size, + nullptr); +} + +template +inline constexpr char_type* print_reserve_define_win32_error_ptr_impl(char_type* ptr, std::uint_least32_t ec) noexcept +{ + if constexpr(family==win32_family::wide_nt) + { + if constexpr(std::same_as) + return ptr+print_reserve_define_win32_error_ntw_impl(ptr,ec); + else if constexpr(sizeof(char_type)==2) + { + using char_type_may_alias_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = char16_t*; + return ptr+print_reserve_define_win32_error_ntw_impl(reinterpret_cast(ptr),ec); + } + else + { + ::fast_io::freestanding::array buffer; + using char_type_may_alias_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = char16_t*; + std::size_t sz{print_reserve_define_win32_error_ntw_impl(reinterpret_cast(buffer.data()),ec)}; + return ::fast_io::details::codecvt::general_code_cvt_full(buffer.data(),buffer.data()+sz,ptr); + } + } + else + { + if constexpr(std::same_as) + return ptr+print_reserve_define_win32_error_9xa_impl(ptr,ec); + else if constexpr(sizeof(char_type)==1) + { + return ptr+print_reserve_define_win32_error_9xa_impl(reinterpret_cast(ptr),ec); + } + else + { + ::fast_io::freestanding::array buffer; + std::size_t sz{print_reserve_define_win32_error_9xa_impl(reinterpret_cast(buffer.data()),ec)}; + return ::fast_io::details::codecvt::general_code_cvt_full(buffer.data(),buffer.data()+sz,ptr); + } + } +} + +template +inline constexpr char_type* print_reserve_define_win32_error_impl(char_type* iter,std::uint_least32_t ec) noexcept +{ + return print_reserve_define_win32_error_ptr_impl(iter,ec); +} + +} + +template +inline constexpr std::size_t print_reserve_size(io_reserve_type_t) noexcept +{ + if constexpr(win32_family::native==win32_family::wide_nt) + { + if constexpr(sizeof(char_type)==2) + return 32768; + else + { + constexpr std::size_t sz{::fast_io::details::cal_decorated_reserve_size<2,sizeof(char_type)>(32768)}; + return sz; + } + } + else + { + if constexpr(sizeof(char_type)==1) + return 65536; + else + { + constexpr std::size_t sz{::fast_io::details::cal_decorated_reserve_size<1,sizeof(char_type)>(65536)}; + return sz; + } + } +} + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define(io_reserve_type_t, char_type* iter,win32_code e) noexcept +{ + return details::print_reserve_define_win32_error_impl(iter,e.ec); +} + +[[noreturn]] inline void throw_win32_error() +{ +#ifdef __cpp_exceptions +#if defined(_MSC_VER) && (!defined(_HAS_EXCEPTIONS) || _HAS_EXCEPTIONS == 0) + fast_terminate(); +#else + throw ::fast_io::error{win32_domain_value,static_cast(win32::GetLastError())}; +#endif +#else + fast_terminate(); +#endif +} +[[noreturn]] inline void throw_win32_error([[maybe_unused]] std::uint_least32_t err) +{ +#ifdef __cpp_exceptions +#if defined(_MSC_VER) && (!defined(_HAS_EXCEPTIONS) || _HAS_EXCEPTIONS == 0) + fast_terminate(); +#else + throw ::fast_io::error{win32_domain_value,static_cast(err)}; +#endif +#else + fast_terminate(); +#endif +} + +} diff --git a/src/fast_io/include/fast_io_hosted/platforms/win32_code_to_errno.h b/src/fast_io/include/fast_io_hosted/platforms/win32_code_to_errno.h new file mode 100644 index 0000000..8028dab --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/win32_code_to_errno.h @@ -0,0 +1,131 @@ +#pragma once +case 0: return 0; +#if defined(EACCES) +case 5:return EACCES; +#endif +#if defined(EAGAIN) +case 89:case 164:case 996:case 997:case 1451:case 1452:case 1453:case 1454:case 1455:case 2401:case 2402:case 2404:return EAGAIN; +#endif +#if defined(EBADF) +case 6:return EBADF; +#endif +#if defined(EBADRQC) +case 1:return EBADRQC; +#endif +#if defined(EBUSY) +case 32:case 33:case 129:case 162:case 170:case 231:case 535:case 1053:case 1460:return EBUSY; +#endif +#if defined(ECHILD) +case 128:return ECHILD; +#endif +#if defined(ECOMM) +case 233:case 536:return ECOMM; +#endif +#if defined(ECONNREFUSED) +case 1225:return ECONNREFUSED; +#endif +#if defined(EDEADLOCK) +case 1131:return EDEADLOCK; +#endif +#if defined(EEXIST) +case 80:case 183:case 1392:return EEXIST; +#endif +#if defined(EFAULT) +case 998:case 1067:return EFAULT; +#endif +#if defined(EFBIG) +case 1450:return EFBIG; +#endif +#if defined(EINTR) +case 104:case 1223:return EINTR; +#endif +#if defined(EINVAL) +case 13:case 25:case 27:case 87:case 131:case 208:case 209:case 210:case 230:case 254:case 255:case 424:case 487:case 1008:case 1332:case 2202:return EINVAL; +#endif +#if defined(EIO) +case 23:case 59:case 110:case 156:case 205:case 1101:case 1102:case 1103:case 1104:case 1106:case 1111:case 1117:case 1129:case 1165:case 1166:case 1393:case 1816:case 8341:return EIO; +#endif +#if defined(ELIBBAD) +case 14001:return ELIBBAD; +#endif +#if defined(EMFILE) +case 4:return EMFILE; +#endif +#if defined(EMLINK) +case 1142:return EMLINK; +#endif +#if defined(EMSGSIZE) +case 234:return EMSGSIZE; +#endif +#if defined(ENAMETOOLONG) +case 206:return ENAMETOOLONG; +#endif +#if defined(ENFILE) +case 113:return ENFILE; +#endif +#if defined(ENMFILE) +case 18:case 259:return ENMFILE; +#endif +#if defined(ENODATA) +case 38:return ENODATA; +#endif +#if defined(ENODEV) +case 15:case 20:case 1200:return ENODEV; +#endif +#if defined(ENOENT) +case 2:case 3:case 53:case 55:case 64:case 67:case 123:case 126:case 161:return ENOENT; +#endif +#if defined(ENOEXEC) +case 191:case 192:case 193:case 197:case 216:return ENOEXEC; +#endif +#if defined(ENOLCK) +case 36:return ENOLCK; +#endif +#if defined(ENOLINK) +case 2250:return ENOLINK; +#endif +#if defined(ENOMEDIUM) +case 21:case 1112:return ENOMEDIUM; +#endif +#if defined(ENOMEM) +case 8:case 14:return ENOMEM; +#endif +#if defined(ENONET) +case 51:return ENONET; +#endif +#if defined(ENOSPC) +case 39:case 112:case 275:case 277:case 1100:return ENOSPC; +#endif +#if defined(ENOSYS) +case 50:case 58:case 120:return ENOSYS; +#endif +#if defined(ENOTDIR) +case 267:return ENOTDIR; +#endif +#if defined(ENOTEMPTY) +case 145:return ENOTEMPTY; +#endif +#if defined(ENOTSUP) +case 282:return ENOTSUP; +#endif +#if defined(ENOTUNIQ) +case 52:return ENOTUNIQ; +#endif +#if defined(ENXIO) +case 1006:return ENXIO; +#endif +#if defined(EPERM) +case 82:case 288:case 1314:return EPERM; +#endif +#if defined(EPIPE) +case 109:case 232:return EPIPE; +#endif +#if defined(EROFS) +case 19:return EROFS; +#endif +#if defined(ESRCH) +case 127:return ESRCH; +#endif +#if defined(EXDEV) +case 17:return EXDEV; +#endif diff --git a/src/fast_io/include/fast_io_hosted/platforms/win32_error.h b/src/fast_io/include/fast_io_hosted/platforms/win32_error.h new file mode 100644 index 0000000..53fc245 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/win32_error.h @@ -0,0 +1,217 @@ +#pragma once + +namespace fast_io +{ + +namespace details +{ + +inline constexpr int eother_value{ +#if defined(EOTHER) +EOTHER +#else +131 +#endif +}; + +inline constexpr int win32_code_to_errno(std::uint_least32_t code) noexcept +{ + switch(code) + { +#include"win32_code_to_errno.h" +default: +return eother_value; + }; +} + +inline constexpr std::uint_least32_t errno_to_win32_code(int code) noexcept +{ + switch(code) + { +#include"errno_to_win32_code.h" +default: +return 0x00000057; + }; +} + +inline constexpr bool win32_code_equals_errno(std::uint_least32_t code,int ec) noexcept +{ + auto e{win32_code_to_errno(code)}; + if(e==eother_value) + { + return false; + } + return e==ec; +} + +inline bool nt_code_equivalent_impl(std::uintptr_t domain,std::uintptr_t code,std::uint_least32_t e) noexcept +{ + if(nt_domain_value==domain) + { + return code==e; + } + else if(win32_domain_value==domain||posix_domain_value==domain) + { + auto lasterr{::fast_io::win32::nt::rtl_nt_status_to_dos_error(e)}; + if(win32_domain_value==domain) + { + return lasterr==code; + } + else + { + return win32_code_equals_errno(lasterr,static_cast(static_cast(code))); + } + } + else + { + return false; + } +} + +inline bool win32_code_equivalent_impl(std::uintptr_t domain,std::uintptr_t code,std::uint_least32_t e) noexcept +{ + if(win32_domain_value==domain) + { + return code==e; + } + + else if(nt_domain_value==domain) + { +#ifdef _WIN32_WINDOWS + return false; +#else + return ::fast_io::win32::nt::rtl_nt_status_to_dos_error(static_cast(code))==e; +#endif + } + else if(posix_domain_value==domain) + { + return win32_code_equals_errno(e,static_cast(static_cast(code))); + } + else + { + return false; + } +} + +inline bool posix_code_equivalent_impl(std::uintptr_t domain,std::uintptr_t code,int e) noexcept +{ + if(posix_domain_value==domain) + { + using common_type = std::common_type_t; + return static_cast(static_cast(e))==code; + } + else if(win32_domain_value==domain||nt_domain_value==domain) + { + std::uint_least32_t win32cd{}; + if(nt_domain_value==domain) + { +#ifdef _WIN32_WINDOWS + win32cd=0x00000057; +#else + win32cd=::fast_io::win32::nt::rtl_nt_status_to_dos_error(static_cast(code)); +#endif + } + else + { + win32cd=static_cast(code); + } + return win32_code_equals_errno(win32cd,static_cast(static_cast(e))); + } + else + { + return false; + } +} + +inline constexpr std::uint_least32_t to_win32_code_impl(std::uintptr_t domain,std::uintptr_t code) noexcept +{ + if(win32_domain_value==domain) + { + return static_cast(code); + } + else if(nt_domain_value==domain) + { +#ifdef _WIN32_WINDOWS + return 0x00000057; +#else + return ::fast_io::win32::nt::rtl_nt_status_to_dos_error(static_cast(code)); +#endif + } + else if(posix_domain_value==domain) + { + return errno_to_win32_code(static_cast(static_cast(code))); + } + else + { + return 0x00000057; + } +} + +inline constexpr int to_posix_code_impl(std::uintptr_t domain,std::uintptr_t code) noexcept +{ + if(posix_domain_value==domain) + { + return win32_code_to_errno(static_cast(code)); + } + else if(win32_domain_value==domain||nt_domain_value==domain) + { + std::uint_least32_t win32cd{}; + if(nt_domain_value==domain) + { +#ifdef _WIN32_WINDOWS + return 0x00000057; +#else + win32cd=::fast_io::win32::nt::rtl_nt_status_to_dos_error(static_cast(code)); +#endif + } + else + { + win32cd=static_cast(code); + } + return win32_code_to_errno(win32cd); + } + else + { + return eother_value; + } +} + +} + +inline bool equivalent_define(error_type_t,error e,win32_code we) noexcept +{ + return ::fast_io::details::win32_code_equivalent_impl(e.domain,e.code,we.ec); +} + +inline bool equivalent_define(error_type_t,error e,nt_code we) noexcept +{ + return ::fast_io::details::nt_code_equivalent_impl(e.domain,e.code,we.ntstatus); +} + +inline bool equivalent_define(error_type_t<::fast_io::freestanding::errc>,error e,::fast_io::freestanding::errc we) noexcept +{ + return ::fast_io::details::posix_code_equivalent_impl(e.domain,e.code,static_cast(we)); +} + +inline ::fast_io::freestanding::errc to_code_define(error_type_t<::fast_io::freestanding::errc>,error e) noexcept +{ + return ::fast_io::freestanding::errc{::fast_io::details::to_posix_code_impl(e.domain,e.code)}; +} + +inline win32_code to_code_define(error_type_t,error e) noexcept +{ + return win32_code{::fast_io::details::to_win32_code_impl(e.domain,e.code)}; +} + +using native_code = win32_code; + +inline native_code print_alias_define(::fast_io::io_alias_t,::fast_io::error e) noexcept +{ +#if defined(_MSC_VER) && !defined(__clang__) + return to_code_define(error_type_t{},e); +#else + return to_code_define(error_type,e); +#endif +} + +} diff --git a/src/fast_io/include/fast_io_hosted/platforms/win32_iocp_overlapped.h b/src/fast_io/include/fast_io_hosted/platforms/win32_iocp_overlapped.h new file mode 100644 index 0000000..12eb23a --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/win32_iocp_overlapped.h @@ -0,0 +1,21 @@ +#pragma once + +namespace fast_io +{ + +class iocp_overlapped_base:public fast_io::win32::overlapped +{ +public: + constexpr iocp_overlapped_base():fast_io::win32::overlapped{} + {} +#if __cpp_constexpr >= 201907L + constexpr +#endif + virtual void invoke(std::size_t) noexcept = 0; +#if __cpp_constexpr >= 201907L + constexpr +#endif + virtual ~iocp_overlapped_base()=default; +}; + +} diff --git a/src/fast_io/include/fast_io_hosted/platforms/win32_mapping.h b/src/fast_io/include/fast_io_hosted/platforms/win32_mapping.h new file mode 100644 index 0000000..8c9f150 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/win32_mapping.h @@ -0,0 +1,235 @@ +#pragma once + +namespace fast_io +{ + +enum class win32_file_map_attribute +{ +copy=0x00000001,write=0x00000002,read=0x00000004,all_access=0x000f001f,execute=0x00000020 +}; + +constexpr win32_file_map_attribute operator&(win32_file_map_attribute x, win32_file_map_attribute y) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(static_cast(x) & static_cast(y)); +} + +constexpr win32_file_map_attribute operator|(win32_file_map_attribute x, win32_file_map_attribute y) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(static_cast(x) | static_cast(y)); +} + +constexpr win32_file_map_attribute operator^(win32_file_map_attribute x, win32_file_map_attribute y) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(static_cast(x) ^ static_cast(y)); +} + +constexpr win32_file_map_attribute operator~(win32_file_map_attribute x) noexcept +{ +using utype = typename std::underlying_type::type; +return static_cast(~static_cast(x)); +} + +inline constexpr win32_file_map_attribute& operator&=(win32_file_map_attribute& x, win32_file_map_attribute y) noexcept{return x=x&y;} + +inline constexpr win32_file_map_attribute& operator|=(win32_file_map_attribute& x, win32_file_map_attribute y) noexcept{return x=x|y;} + +inline constexpr win32_file_map_attribute& operator^=(win32_file_map_attribute& x, win32_file_map_attribute y) noexcept{return x=x^y;} + +inline constexpr win32_file_map_attribute to_win32_file_map_attribute(file_map_attribute x) +{ + switch(x) + { + case file_map_attribute::execute_read:return win32_file_map_attribute::execute|win32_file_map_attribute::read; + case file_map_attribute::execute_read_write:return win32_file_map_attribute::execute|win32_file_map_attribute::read; + case file_map_attribute::execute_write_copy:return win32_file_map_attribute::execute|win32_file_map_attribute::write|win32_file_map_attribute::copy; + case file_map_attribute::read_only:return win32_file_map_attribute::read; + case file_map_attribute::read_write:return win32_file_map_attribute::read|win32_file_map_attribute::write; + case file_map_attribute::write_copy:return win32_file_map_attribute::write|win32_file_map_attribute::copy; + default: + throw_win32_error(0x000000A0); + }; +} + +namespace win32::details +{ + +template +inline void* create_file_mapping_impl(void* handle,file_map_attribute attr) +{ + if constexpr(family==win32_family::wide_nt) + { + void* addr{win32::CreateFileMappingW(handle,nullptr,static_cast(attr),0,0,nullptr)}; + if(addr==nullptr) + throw_win32_error(); + return addr; + } + else + { + void* addr{win32::CreateFileMappingA(handle,nullptr,static_cast(attr),0,0,nullptr)}; + if(addr==nullptr) + throw_win32_error(); + return addr; + } +} + +} + +template +class win32_family_memory_map_file +{ +public: + using value_type = std::byte; + using pointer = value_type*; + using const_pointer = value_type const*; + using const_iterator = const_pointer; + using iterator = pointer; + using reference = value_type&; + using const_reference = value_type const&; + using size_type = std::size_t; + using difference_type = std::ptrdiff_t; + using const_reverse_iterator = std::reverse_iterator; + using reverse_iterator = std::reverse_iterator; + pointer address_begin{},address_end{}; + constexpr win32_family_memory_map_file()=default; + constexpr win32_family_memory_map_file(std::byte* addressbegin,std::byte* addressend):address_begin{addressbegin},address_end{addressend}{} + win32_family_memory_map_file(nt_at_entry bf,file_map_attribute attr,std::size_t bytes,std::uintmax_t start_address=0) + { + basic_win32_family_file mapping_file{win32::details::create_file_mapping_impl(bf.handle,attr)}; + void *base_ptr{win32::MapViewOfFile(mapping_file.handle,static_cast(to_win32_file_map_attribute(attr)),start_address>>32,static_cast(start_address),bytes)}; + if(base_ptr==nullptr) + throw_win32_error(); + this->address_begin=reinterpret_cast(base_ptr); + this->address_end=this->address_begin+bytes; + } + constexpr pointer data() const noexcept + { + return address_begin; + } + constexpr bool empty() const noexcept + { + return address_begin==address_end; + } + constexpr std::size_t size() const noexcept + { + return static_cast(address_end-address_begin); + } + constexpr const_iterator cbegin() const noexcept + { + return address_begin; + } + constexpr const_iterator begin() const noexcept + { + return address_begin; + } + constexpr iterator begin() noexcept + { + return address_begin; + } + constexpr const_iterator cend() const noexcept + { + return address_end; + } + constexpr const_iterator end() const noexcept + { + return address_end; + } + constexpr iterator end() noexcept + { + return address_end; + } + constexpr std::size_t max_size() const noexcept + { + return SIZE_MAX; + } + constexpr const_reverse_iterator crbegin() const noexcept + { + return const_reverse_iterator{address_end}; + } + constexpr reverse_iterator rbegin() noexcept + { + return reverse_iterator{address_end}; + } + constexpr const_reverse_iterator rbegin() const noexcept + { + return const_reverse_iterator{address_end}; + } + constexpr const_reverse_iterator crend() const noexcept + { + return const_reverse_iterator{address_begin}; + } + constexpr reverse_iterator rend() noexcept + { + return reverse_iterator{address_begin}; + } + constexpr const_reverse_iterator rend() const noexcept + { + return const_reverse_iterator{address_begin}; + } + constexpr const_reference front() const noexcept + { + return *address_begin; + } + constexpr reference front() noexcept + { + return *address_begin; + } + constexpr const_reference back() const noexcept + { + return address_end[-1]; + } + constexpr reference back() noexcept + { + return address_end[-1]; + } + inline constexpr reference operator[](size_type size) noexcept + { + return address_begin[size]; + } + inline constexpr const_reference operator[](size_type size) const noexcept + { + return address_begin[size]; + } + win32_family_memory_map_file(win32_family_memory_map_file const&)=delete; + win32_family_memory_map_file& operator=(win32_family_memory_map_file const&)=delete; + constexpr win32_family_memory_map_file(win32_family_memory_map_file&& __restrict other) noexcept:address_begin{other.address_begin},address_end{other.address_end} + { + other.address_end=other.address_begin=nullptr; + } + win32_family_memory_map_file& operator=(win32_family_memory_map_file&& __restrict other) noexcept + { + if(this->address_begin)[[likely]] + win32::UnmapViewOfFile(this->address_begin); + this->address_begin=other.address_begin; + this->address_end=other.address_end; + other.address_end=other.address_begin=nullptr; + return *this; + } + void close() + { + if(this->address_begin)[[likely]] + { + auto ret{win32::UnmapViewOfFile(this->address_begin)}; + this->address_end=this->address_begin=nullptr; + if(!ret) + throw_win32_error(); + } + } + ~win32_family_memory_map_file() + { + if(this->address_begin)[[likely]] + win32::UnmapViewOfFile(this->address_begin); + } +}; + +using win32_memory_map_file_9xa = win32_family_memory_map_file; +using win32_memory_map_file_ntw = win32_family_memory_map_file; +using win32_memory_map_file = win32_family_memory_map_file; + +#ifndef __CYGWIN__ +using native_memory_map_file = win32_memory_map_file; +#endif + +} diff --git a/src/fast_io/include/fast_io_hosted/platforms/win32_network/service.h b/src/fast_io/include/fast_io_hosted/platforms/win32_network/service.h new file mode 100644 index 0000000..c07490a --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/win32_network/service.h @@ -0,0 +1,28 @@ +#pragma once + +namespace fast_io +{ + +struct win32_wsa_service +{ + using native_handle_type = win32::wsadata; + win32::wsadata wsa_data; + explicit win32_wsa_service(std::uint_least16_t version) + { + if(win32::WSAStartup(version,__builtin_addressof(wsa_data))) + throw_win32_error(static_cast(win32::WSAGetLastError())); + } + win32_wsa_service():win32_wsa_service(514) + {} + win32_wsa_service(win32_wsa_service const&)=delete; + win32_wsa_service& operator=(win32_wsa_service const&)=delete; + ~win32_wsa_service() + { + win32::WSACleanup(); + } +}; + +#if !defined(__CYGWIN__) && !defined(__WINE__) +using net_service = win32_wsa_service; +#endif +} diff --git a/src/fast_io/include/fast_io_hosted/platforms/win32_network/socket_file.h b/src/fast_io/include/fast_io_hosted/platforms/win32_network/socket_file.h new file mode 100644 index 0000000..c31bfbf --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/win32_network/socket_file.h @@ -0,0 +1,783 @@ +#pragma once + +namespace fast_io +{ + +using win32_socklen_t = int; + +template +class basic_win32_family_socket_io_observer +{ +public: + using char_type = ch_type; + using native_handle_type = std::uintptr_t; + native_handle_type hsocket{}; + constexpr native_handle_type release() noexcept + { + native_handle_type temp{hsocket}; + hsocket={}; + return temp; + } + constexpr native_handle_type native_handle() const noexcept + { + return hsocket; + } +}; + +template +inline constexpr basic_win32_family_socket_io_observer io_value_handle(basic_win32_family_socket_io_observer value) noexcept +{ + return value; +} + +namespace win32::details +{ +inline std::uint_least32_t win32_socket_write_simple_impl(std::uintptr_t socket, void const* data,std::uint_least32_t len) +{ + wsabuf buffer{len,const_cast(reinterpret_cast(data))}; + std::uint_least32_t sent{}; + if(::fast_io::win32::WSASend(socket,__builtin_addressof(buffer),1,__builtin_addressof(sent),0,nullptr,nullptr)) + throw_win32_error(static_cast(::fast_io::win32::WSAGetLastError())); + return sent; +} + +inline std::size_t win32_socket_write_impl(std::uintptr_t socket, void const* data,std::size_t to_write) +{ + if constexpr(sizeof(std::uint_least32_t)(UINT_LEAST32_MAX)) + to_write_this_round=static_cast(to_write); + std::uint_least32_t number_of_bytes_written{win32_socket_write_simple_impl(socket,data,to_write_this_round)}; + written+=number_of_bytes_written; + if(number_of_bytes_written(to_write)); + } +} +inline std::size_t win32_socket_read_impl(std::uintptr_t socket, void* data,std::size_t to_read) +{ + if constexpr(sizeof(int)(static_cast(std::numeric_limits::max()))}; + if(intmax(data),static_cast(static_cast(to_read)),0)}; + if(recved==-1) + throw_win32_error(static_cast(::fast_io::win32::WSAGetLastError())); + return static_cast(static_cast(recved)); +} + +inline io_scatter_status_t win32_socket_scatter_read_impl(std::uintptr_t socket,io_scatter_t* scatter,std::size_t len) +{ + if(len==0) + return {0,0,0}; + io_scatter_t sc0{*scatter}; + return {win32_socket_read_impl(socket,const_cast(sc0.base),sc0.len),1,0}; +} + +inline io_scatter_status_t win32_socket_scatter_write_impl(std::uintptr_t socket,io_scatter_t* scatter,std::size_t len) +{ + std::size_t written{}; + for(std::size_t i{};i!=len;++i) + { + io_scatter_t sc{scatter[i]}; + std::size_t written_this_round{win32_socket_write_impl(socket,sc.base,sc.len)}; + written+=written_this_round; + if(written_this_round!=sc.len)[[unlikely]] + return {written,i,written_this_round}; + } + return {written,len,0}; +} + +inline void posix_connect_win32_socket_impl(std::uintptr_t hsocket,void const* addr,int addrlen) +{ + if(::fast_io::win32::WSAConnect(hsocket,addr,addrlen,nullptr,nullptr,nullptr,nullptr)) + throw_win32_error(static_cast(WSAGetLastError())); +} + +inline void posix_bind_win32_socket_impl(std::uintptr_t hsocket,void const* addr,int addrlen) +{ + if(::fast_io::win32::bind(hsocket,addr,addrlen)==-1) + throw_win32_error(static_cast(WSAGetLastError())); +} + +inline void posix_listen_win32_socket_impl(std::uintptr_t hsocket,int backlog) +{ + if(::fast_io::win32::listen(hsocket,backlog)==-1) + throw_win32_error(static_cast(WSAGetLastError())); +} + +inline std::uintptr_t posix_accept_win32_socket_impl(std::uintptr_t hsocket,void* addr,int* addrlen) +{ + std::uintptr_t accepted_socket{::fast_io::win32::WSAAccept(hsocket,addr,addrlen,nullptr,0)}; + if(accepted_socket==static_cast(-1)) + throw_win32_error(static_cast(WSAGetLastError())); + return accepted_socket; +} + +} + +template +[[nodiscard]] +inline constexpr Iter read(basic_win32_family_socket_io_observer sockiob,Iter first,Iter last) +{ + return win32::details::win32_socket_read_impl(sockiob.hsocket,::std::to_address(first),sizeof(*first)*static_cast(::std::to_address(last)-::std::to_address(first)))/sizeof(*first)+first; +} + +template +inline constexpr Iter write(basic_win32_family_socket_io_observer sockiob,Iter first,Iter last) +{ + return win32::details::win32_socket_write_impl(sockiob.hsocket,::std::to_address(first),sizeof(*first)*static_cast(::std::to_address(last)-::std::to_address(first)))/sizeof(*first)+first; +} + +template +[[nodiscard]] +inline constexpr io_scatter_status_t scatter_read(basic_win32_family_socket_io_observer sockiob,io_scatters_t scatters) +{ + return win32::details::win32_socket_scatter_read_impl(sockiob.hsocket,const_cast(scatters.base),scatters.len); +} + +template +inline constexpr io_scatter_status_t scatter_write(basic_win32_family_socket_io_observer sockiob,io_scatters_t scatters) +{ + return win32::details::win32_socket_scatter_write_impl(sockiob.hsocket, const_cast(scatters.base),scatters.len); +} + +template +inline void posix_connect(basic_win32_family_socket_io_observer sockiob,void const* remote_address,win32_socklen_t address_struct_size) +{ + win32::details::posix_connect_win32_socket_impl(sockiob.hsocket,remote_address,address_struct_size); +} + +template +inline void posix_bind(basic_win32_family_socket_io_observer h,void const* addr,win32_socklen_t addrlen) +{ + win32::details::posix_bind_win32_socket_impl(h.hsocket,addr,addrlen); +} + +template +inline void posix_listen(basic_win32_family_socket_io_observer h,int backlog) +{ + win32::details::posix_listen_win32_socket_impl(h.hsocket,backlog); +} + +namespace win32::details +{ + +inline std::uintptr_t win32_duphsocket(std::uintptr_t s) +{ + return reinterpret_cast(win32_dup_impl(reinterpret_cast(s))); +} +inline std::uintptr_t win32_dup2hsocket(std::uintptr_t handle,std::uintptr_t newhandle) +{ + auto temp{win32_duphsocket(handle)}; + if(newhandle)[[likely]] + closesocket(newhandle); + return temp; +} + +} + +inline constexpr int to_win32_sock_family(sock_family dom) noexcept +{ + switch(dom) + { + case sock_family::local: + return 1; + case sock_family::inet: + return 2; + case sock_family::implink: + return 3; + case sock_family::pup: + return 4; + case sock_family::chaos: + return 5; + case sock_family::ipx: + return 6; + case sock_family::iso: + return 7; + case sock_family::ecma: + return 8; + case sock_family::datakit: + return 9; + case sock_family::ccitt: + return 10; + case sock_family::sna: + return 11; + case sock_family::decnet: + return 12; + case sock_family::dli: + return 13; + case sock_family::lat: + return 14; + case sock_family::hylink: + return 15; + case sock_family::appletalk: + return 16; + case sock_family::netbios: + return 17; + case sock_family::voiceview: + return 18; + case sock_family::firefox: + return 19; + case sock_family::ban: + return 21; + case sock_family::atm: + return 22; + case sock_family::inet6: + return 23; + case sock_family::cluster: + return 24; + case sock_family::ieee12844: + return 25; + case sock_family::irda: + return 26; + case sock_family::netdes: + return 28; + case sock_family::tcnprocess: + return 29; + case sock_family::tcnmessage: + return 30; + case sock_family::iclfxbm: + return 31; + case sock_family::bluetooth: + return 32; + case sock_family::can: + return 65537; + default: + return 0; + } +} + + +inline constexpr int to_win32_sock_protocol(sock_protocol prot) noexcept +{ + switch(prot) + { + case sock_protocol::ip: + return 0; + case sock_protocol::hopopts: + return 0; + case sock_protocol::icmp: + return 1; + case sock_protocol::igmp: + return 2; + case sock_protocol::ggp: + return 3; + case sock_protocol::ipv4: + return 4; + case sock_protocol::st: + return 5; + case sock_protocol::tcp: + return 6; + case sock_protocol::cbt: + return 7; + case sock_protocol::egp: + return 8; + case sock_protocol::igp: + return 9; + case sock_protocol::pup: + return 12; + case sock_protocol::udp: + return 17; + case sock_protocol::idp: + return 22; + case sock_protocol::rdp: + return 27; + case sock_protocol::ipv6: + return 41; + case sock_protocol::routing: + return 43; + case sock_protocol::fragment: + return 44; + case sock_protocol::icmpv6: + return 58; + case sock_protocol::none: + return 59; + case sock_protocol::dstopts: + return 60; + case sock_protocol::nd: + return 77; + case sock_protocol::iclfxbm: + return 78; + case sock_protocol::pim: + return 103; + case sock_protocol::pgm: + return 113; + case sock_protocol::l2tp: + return 115; + case sock_protocol::sctp: + return 132; + case sock_protocol::raw: + return 255; + default: + return -1; + } +} + +inline constexpr int to_win32_sock_type(sock_type dom) noexcept +{ + switch(dom) + { + case sock_type::stream: + return 1; + case sock_type::dgram: + return 2; + case sock_type::seqpacket: + return 5; + case sock_type::raw: + return 3; + case sock_type::rdm: + return 4; + default: + return -1; + }; +} + +inline constexpr std::uint_least32_t to_win32_sock_open_mode(open_mode m) noexcept +{ + std::uint_least32_t flags{}; + if((m&open_mode::no_block)==open_mode::no_block) + flags|=0x01; +#if defined(_WIN32_WINDOWS) || _WIN32_WINNT >= 0x0602 +//this flag only supports after windows 7 sp1. So we start supporting this flag from windows 8 + if((m&open_mode::inherit)!=open_mode::inherit) + flags|=0x80; +#endif + return flags; +} + +inline constexpr std::uint_least32_t to_win32_sock_open_mode_9xa(open_mode m) noexcept +{ + std::uint_least32_t flags{}; + if((m&open_mode::no_block)==open_mode::no_block) + flags|=0x01; + return flags; +} + + +#if !defined(__CYGWIN__) && !defined(__WINE__) + +inline constexpr int to_native_sock_family(sock_family dom) noexcept +{ + return to_win32_sock_family(dom); +} + +inline constexpr int to_native_sock_type(sock_type dom) noexcept +{ + return to_win32_sock_type(dom); +} + +inline constexpr int to_native_sock_protocol(sock_protocol prot) noexcept +{ + return to_win32_sock_protocol(prot); +} + +inline constexpr std::uint_least32_t to_native_sock_open_mode(open_mode m) noexcept +{ + return to_win32_sock_open_mode(m); +} + +#endif + +namespace win32::details +{ + +template +inline std::uintptr_t open_win32_socket_raw_impl(int af,int tp,int prt,std::uint_least32_t dwflags) +{ + if constexpr(family==win32_family::wide_nt) + { + std::uintptr_t ret{::fast_io::win32::WSASocketW(af,tp,prt,nullptr,0,dwflags)}; + if(ret==UINTPTR_MAX) + throw_win32_error(static_cast(WSAGetLastError())); + return ret; + } + else + { + std::uintptr_t ret{::fast_io::win32::WSASocketA(af,tp,prt,nullptr,0,dwflags)}; + if(ret==UINTPTR_MAX) + throw_win32_error(static_cast(WSAGetLastError())); + return ret; + } +} + +template +inline std::uintptr_t open_win32_socket_raw_om_custom_only_impl(int af,int tp,int prt,open_mode om) +{ + if constexpr(family==::fast_io::win32_family::wide_nt) + { + return open_win32_socket_raw_impl(af,tp,prt,to_win32_sock_open_mode(om)); + } + else + { + return open_win32_socket_raw_impl(af,tp,prt,to_win32_sock_open_mode_9xa(om)); + } +} + +template +inline std::uintptr_t open_win32_socket_impl(sock_family d,sock_type t,open_mode m,sock_protocol p) +{ + return open_win32_socket_raw_om_custom_only_impl(to_win32_sock_family(d),to_win32_sock_type(t),to_win32_sock_protocol(p),m); +} + +} + +struct +#if __has_cpp_attribute(clang::trivially_relocatable) +[[clang::trivially_relocatable]] +#endif +win32_socket_factory +{ + using native_handle_type = std::uintptr_t; + std::uintptr_t hsocket{}; + explicit constexpr win32_socket_factory(std::uintptr_t v) noexcept:hsocket(v){} + win32_socket_factory(win32_socket_factory const&)=delete; + win32_socket_factory& operator=(win32_socket_factory const&)=delete; + ~win32_socket_factory() + { + if(hsocket)[[likely]] + win32::closesocket(hsocket); + } +}; + + +template +inline win32_socket_factory posix_accept(basic_win32_family_socket_io_observer h,void* addr,win32_socklen_t* addrlen) +{ + return win32_socket_factory{win32::details::posix_accept_win32_socket_impl(h.hsocket,addr,addrlen)}; +} + +template +inline win32_socket_factory tcp_accept(basic_win32_family_socket_io_observer h) +{ + return win32_socket_factory{win32::details::posix_accept_win32_socket_impl(h.hsocket,nullptr,nullptr)}; +} + +template +class +#if __has_cpp_attribute(clang::trivially_relocatable) +[[clang::trivially_relocatable]] +#endif +basic_win32_family_socket_file : public basic_win32_family_socket_io_observer +{ +public: + using typename basic_win32_family_socket_io_observer::char_type; + using typename basic_win32_family_socket_io_observer::native_handle_type; + constexpr basic_win32_family_socket_file() noexcept=default; + + constexpr basic_win32_family_socket_file(basic_win32_family_socket_io_observer) noexcept=delete; + constexpr basic_win32_family_socket_file& operator=(basic_win32_family_socket_io_observer) noexcept=delete; + + template + requires std::same_as> + explicit constexpr basic_win32_family_socket_file(native_hd hsocket1) noexcept: basic_win32_family_socket_io_observer{hsocket1} + {} + explicit constexpr basic_win32_family_socket_file(decltype(nullptr)) noexcept=delete; + basic_win32_family_socket_file(io_dup_t,basic_win32_family_socket_io_observer wsiob):basic_win32_family_socket_io_observer{win32::details::win32_duphsocket(wsiob.hsocket)} + {} + basic_win32_family_socket_file(sock_family d,sock_type t,open_mode m,sock_protocol p) + :basic_win32_family_socket_file{win32::details::open_win32_socket_impl(d,t,m,p)} + {} + + basic_win32_family_socket_file(basic_win32_family_socket_file const& dp):basic_win32_family_socket_io_observer{win32::details::win32_duphsocket(dp.hsocket)} + { + } + basic_win32_family_socket_file& operator=(basic_win32_family_socket_file const& dp) + { + this->hsocket=win32::details::win32_dup2hsocket(dp.hsocket,this->hsocket); + return *this; + } + constexpr basic_win32_family_socket_file(basic_win32_family_socket_file&& __restrict b) noexcept : basic_win32_family_socket_io_observer{b.hsocket} + { + b.hsocket = 0; + } + basic_win32_family_socket_file& operator=(basic_win32_family_socket_file&& __restrict b) noexcept + { + if(this->hsocket)[[likely]] + ::fast_io::win32::closesocket(this->hsocket); + this->hsocket=b.hsocket; + b.hsocket = 0; + return *this; + } + constexpr void reset(native_handle_type newhsocket=0) noexcept + { + if(this->hsocket)[[likely]] + ::fast_io::win32::closesocket(this->hsocket); + this->hsocket=newhsocket; + } + void close() + { + if(this->hsocket)[[likely]] + { + auto ret{::fast_io::win32::closesocket(this->hsocket)}; + this->hsocket=0;//POSIX standard says we should never call close(2) again even close syscall fails + if(ret) + throw_win32_error(static_cast(::fast_io::win32::WSAGetLastError())); + } + } + + explicit constexpr basic_win32_family_socket_file(win32_socket_factory&& other) noexcept : basic_win32_family_socket_io_observer{other.hsocket} + { + other.hsocket=0; + } + ~basic_win32_family_socket_file() + { + if(this->hsocket)[[likely]] + ::fast_io::win32::closesocket(this->hsocket); + } +}; + + +namespace details +{ + +template +inline std::uintptr_t win32_family_tcp_connect_v4_impl(ipv4 v4,open_mode m) +{ + basic_win32_family_socket_file soc(sock_family::inet,sock_type::stream,m,sock_protocol::tcp); + constexpr auto inet{to_win32_sock_family(sock_family::inet)}; + posix_sockaddr_in in{.sin_family=inet,.sin_port=big_endian(static_cast(v4.port)),.sin_addr=v4.address}; + posix_connect(soc,__builtin_addressof(in),sizeof(in)); + return soc.release(); +} + + +template +inline std::uintptr_t win32_family_tcp_connect_v6_impl(ipv6 v6,open_mode m) +{ + basic_win32_family_socket_file soc(sock_family::inet6,sock_type::stream,m,sock_protocol::tcp); + constexpr auto inet6{to_win32_sock_family(sock_family::inet6)}; + posix_sockaddr_in6 in6{.sin6_family=inet6,.sin6_port=big_endian(static_cast(v6.port)),.sin6_addr=v6.address}; + posix_connect(soc,__builtin_addressof(in6),sizeof(in6)); + return soc.release(); +} + +template +inline std::uintptr_t win32_family_tcp_connect_ip_impl(ip v,open_mode m) +{ + basic_win32_family_socket_file soc(v.address.isv4?sock_family::inet:sock_family::inet6,sock_type::stream,m,sock_protocol::tcp); + if(v.address.isv4) + { + constexpr auto inet{to_win32_sock_family(sock_family::inet)}; + posix_sockaddr_in in{.sin_family=inet,.sin_port=big_endian(v.port),.sin_addr=v.address.address.v4}; + posix_connect(soc,__builtin_addressof(in),sizeof(in)); + } + else + { + constexpr auto inet6{to_win32_sock_family(sock_family::inet6)}; + posix_sockaddr_in6 in6{.sin6_family=inet6,.sin6_port=big_endian(v.port),.sin6_addr=v.address.address.v6}; + posix_connect(soc,__builtin_addressof(in6),sizeof(in6)); + } + return soc.release(); +} + +inline void win32_tcp_listen_common_impl(std::uintptr_t hsocket,std::uint_least16_t port) +{ + constexpr auto inet{to_win32_sock_family(sock_family::inet)}; + posix_sockaddr_in in{.sin_family=inet,.sin_port=big_endian(port),.sin_addr={}}; + ::fast_io::win32::details::posix_bind_win32_socket_impl(hsocket,__builtin_addressof(in),sizeof(in)); + ::fast_io::win32::details::posix_listen_win32_socket_impl(hsocket,128); +} + +template +inline std::uintptr_t win32_tcp_listen_impl(std::uint_least16_t port,open_mode m) +{ + basic_win32_family_socket_file soc(sock_family::inet,sock_type::stream,m,sock_protocol::tcp); + win32_tcp_listen_common_impl(soc.hsocket,port); + return soc.release(); +} + +} + +template +inline win32_socket_factory win32_family_tcp_connect(ipv4 v4,open_mode m=open_mode{}) +{ + return win32_socket_factory{details::win32_family_tcp_connect_v4_impl(v4,m)}; +} + +inline win32_socket_factory win32_tcp_connect_9xa(ipv4 v4,open_mode m=open_mode{}) +{ + return win32_socket_factory{details::win32_family_tcp_connect_v4_impl(v4,m)}; +} + +inline win32_socket_factory win32_tcp_connect_ntw(ipv4 v4,open_mode m=open_mode{}) +{ + return win32_socket_factory{details::win32_family_tcp_connect_v4_impl(v4,m)}; +} + +inline win32_socket_factory win32_tcp_connect(ipv4 v4,open_mode m=open_mode{}) +{ + return win32_socket_factory{details::win32_family_tcp_connect_v4_impl(v4,m)}; +} + + +template +inline win32_socket_factory win32_family_tcp_connect(ipv6 v6,open_mode m=open_mode{}) +{ + return win32_socket_factory{details::win32_family_tcp_connect_v6_impl(v6,m)}; +} + +inline win32_socket_factory win32_tcp_connect_9xa(ipv6 v6,open_mode m=open_mode{}) +{ + return win32_socket_factory{details::win32_family_tcp_connect_v6_impl(v6,m)}; +} + +inline win32_socket_factory win32_tcp_connect_ntw(ipv6 v6,open_mode m=open_mode{}) +{ + return win32_socket_factory{details::win32_family_tcp_connect_v6_impl(v6,m)}; +} + +inline win32_socket_factory win32_tcp_connect(ipv6 v6,open_mode m=open_mode{}) +{ + return win32_socket_factory{details::win32_family_tcp_connect_v6_impl(v6,m)}; +} + +inline win32_socket_factory win32_tcp_connect_9xa(ip v,open_mode m=open_mode{}) +{ + return win32_socket_factory{details::win32_family_tcp_connect_ip_impl(v,m)}; +} + +inline win32_socket_factory win32_tcp_connect_ntw(ip v,open_mode m=open_mode{}) +{ + return win32_socket_factory{details::win32_family_tcp_connect_ip_impl(v,m)}; +} + +inline win32_socket_factory win32_tcp_connect(ip v,open_mode m=open_mode{}) +{ + return win32_socket_factory{details::win32_family_tcp_connect_ip_impl(v,m)}; +} + + +template +inline win32_socket_factory win32_family_tcp_listen(std::uint_least16_t port,open_mode m=open_mode{}) +{ + return win32_socket_factory{details::win32_tcp_listen_impl(port,m)}; +} + +inline win32_socket_factory win32_tcp_listen_ntw(std::uint_least16_t port,open_mode m=open_mode{}) +{ + return win32_socket_factory{details::win32_tcp_listen_impl(port,m)}; +} + +inline win32_socket_factory win32_tcp_listen_9xa(std::uint_least16_t port,open_mode m=open_mode{}) +{ + return win32_socket_factory{details::win32_tcp_listen_impl(port,m)}; +} + +inline win32_socket_factory win32_tcp_listen(std::uint_least16_t port,open_mode m=open_mode{}) +{ + return win32_socket_factory{details::win32_tcp_listen_impl(port,m)}; +} + +template +using basic_win32_socket_io_observer_9xa = basic_win32_family_socket_io_observer; + +using win32_socket_io_observer_9xa=basic_win32_socket_io_observer_9xa; +using wwin32_socket_io_observer_9xa=basic_win32_socket_io_observer_9xa; +using u8win32_socket_io_observer_9xa=basic_win32_socket_io_observer_9xa; +using u16win32_socket_io_observer_9xa=basic_win32_socket_io_observer_9xa; +using u32win32_socket_io_observer_9xa=basic_win32_socket_io_observer_9xa; + +template +using basic_win32_socket_io_observer_ntw = basic_win32_family_socket_io_observer; + +using win32_socket_io_observer_ntw=basic_win32_socket_io_observer_ntw; +using wwin32_socket_io_observer_ntw=basic_win32_socket_io_observer_ntw; +using u8win32_socket_io_observer_ntw=basic_win32_socket_io_observer_ntw; +using u16win32_socket_io_observer_ntw=basic_win32_socket_io_observer_ntw; +using u32win32_socket_io_observer_ntw=basic_win32_socket_io_observer_ntw; + +template +using basic_win32_socket_io_observer = basic_win32_family_socket_io_observer; + +using win32_socket_io_observer=basic_win32_socket_io_observer; +using wwin32_socket_io_observer=basic_win32_socket_io_observer; +using u8win32_socket_io_observer=basic_win32_socket_io_observer; +using u16win32_socket_io_observer=basic_win32_socket_io_observer; +using u32win32_socket_io_observer=basic_win32_socket_io_observer; + +template +using basic_win32_socket_file_9xa = basic_win32_family_socket_file; + +using win32_socket_file_9xa=basic_win32_socket_file_9xa; +using wwin32_socket_file_9xa=basic_win32_socket_file_9xa; +using u8win32_socket_file_9xa=basic_win32_socket_file_9xa; +using u16win32_socket_file_9xa=basic_win32_socket_file_9xa; +using u32win32_socket_file_9xa=basic_win32_socket_file_9xa; + +template +using basic_win32_socket_file_ntw = basic_win32_family_socket_file; + +using win32_socket_file_ntw=basic_win32_socket_file_ntw; +using wwin32_socket_file_ntw=basic_win32_socket_file_ntw; +using u8win32_socket_file_ntw=basic_win32_socket_file_ntw; +using u16win32_socket_file_ntw=basic_win32_socket_file_ntw; +using u32win32_socket_file_ntw=basic_win32_socket_file_ntw; + +template +using basic_win32_socket_file = basic_win32_family_socket_file; + +using win32_socket_file=basic_win32_socket_file; +using wwin32_socket_file=basic_win32_socket_file; +using u8win32_socket_file=basic_win32_socket_file; +using u16win32_socket_file=basic_win32_socket_file; +using u32win32_socket_file=basic_win32_socket_file; + +#if !defined(__CYGWIN__) && !defined(__WINE__) + +template +using basic_native_socket_io_observer = basic_win32_socket_io_observer; +template +using basic_native_socket_file = basic_win32_socket_file; +using native_socklen_t = win32_socklen_t; + +inline win32_socket_factory tcp_connect(ipv4 v4,open_mode m=open_mode{}) +{ + return win32_socket_factory{details::win32_family_tcp_connect_v4_impl(v4,m)}; +} +inline win32_socket_factory tcp_connect(ipv6 v6,open_mode m=open_mode{}) +{ + return win32_socket_factory{details::win32_family_tcp_connect_v6_impl(v6,m)}; +} +inline win32_socket_factory tcp_connect(ip v,open_mode m=open_mode{}) +{ + return win32_socket_factory{details::win32_family_tcp_connect_ip_impl(v,m)}; +} + +inline win32_socket_factory tcp_listen(std::uint_least16_t port,open_mode m=open_mode{}) +{ + return win32_socket_factory{details::win32_tcp_listen_impl(port,m)}; +} + +#endif + +namespace freestanding +{ + +template +struct is_trivially_relocatable> +{ + inline static constexpr bool value = true; +}; + +template +struct is_zero_default_constructible> +{ + inline static constexpr bool value = true; +}; + +} + +} diff --git a/src/fast_io/include/fast_io_hosted/platforms/win32_network/win32.h b/src/fast_io/include/fast_io_hosted/platforms/win32_network/win32.h new file mode 100644 index 0000000..3640bc1 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/win32_network/win32.h @@ -0,0 +1,13 @@ +#pragma once + +#if defined(_MSC_VER) && !defined(_KERNEL_MODE) +#pragma comment(lib,"ws2_32.lib") +#endif + +#include"service.h" +#include"socket_file.h" +#include"win32_dns.h" + +#if !defined(_MSC_VER) && !defined(__WINE__) && !defined(__CYGWIN__) +#include"win32_9x_dns.h" +#endif diff --git a/src/fast_io/include/fast_io_hosted/platforms/win32_network/win32_9x_dns.h b/src/fast_io/include/fast_io_hosted/platforms/win32_network/win32_9x_dns.h new file mode 100644 index 0000000..b0bbc27 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/win32_network/win32_9x_dns.h @@ -0,0 +1,220 @@ +#pragma once + +namespace fast_io +{ +namespace win32 +{ + +struct hostent +{ +char *h_name; +char **h_aliases; +short h_addrtype; +short h_length; +char **h_addr_list; +}; + +#if defined(_MSC_VER) && !defined(__clang__) +__declspec(dllimport) +#elif (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if (__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) +[[__gnu__::__stdcall__]] +#endif +extern hostent* +#if (!__has_cpp_attribute(__gnu__::__stdcall__)&&!defined(__WINE__)) && defined(_MSC_VER) +__stdcall +#endif +gethostbyname(char const*) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("gethostbyname@4") +#else +__asm__("_gethostbyname@4") +#endif +#else +__asm__("gethostbyname") +#endif +#endif +; +} + +namespace details +{ + +inline constexpr ::fast_io::ip_address hostent_to_ip_address_impl(::fast_io::win32::hostent* ent,std::size_t pos) noexcept +{ + ::fast_io::ip_address ipaddr; + if(ent->h_addrtype==2) + { + if(ent->h_length==sizeof(posix_in_addr))[[likely]] + { + my_memcpy(__builtin_addressof(ipaddr.address.v4.address),ent->h_addr_list[pos],sizeof(posix_in_addr)); + ipaddr.isv4=true; + } + } + else if(ent->h_addrtype==23) + { + if(ent->h_length==sizeof(posix_in6_addr))[[likely]] + { + my_memcpy(__builtin_addressof(ipaddr.address.v6.address),ent->h_addr_list[pos],sizeof(posix_in6_addr)); + } + } + return ipaddr; +} + +inline constexpr ::fast_io::ip hostent_to_ip_impl(::fast_io::win32::hostent* ent,std::size_t pos,std::uint_least16_t port) noexcept +{ + return ::fast_io::ip{hostent_to_ip_address_impl(ent,pos),port}; +} + +} + +class win32_9x_dns_io_observer +{ +public: + using native_handle_type = ::fast_io::win32::hostent*; + native_handle_type res{}; + inline constexpr native_handle_type native_handle() const noexcept + { + return res; + } + explicit constexpr operator bool() noexcept + { + return res; + } + inline native_handle_type release() noexcept + { + native_handle_type temp{res}; + res=nullptr; + return temp; + } +}; + +inline constexpr ::fast_io::ip to_ip(win32_9x_dns_io_observer d,std::uint_least16_t port) noexcept +{ + return ::fast_io::details::hostent_to_ip_impl(d.res,0u,port); +} + +inline constexpr ::fast_io::ip_address to_ip_address(win32_9x_dns_io_observer d) noexcept +{ + return ::fast_io::details::hostent_to_ip_address_impl(d.res,0u); +} + +struct win32_9x_dns_iterator +{ + using native_handle_type = ::fast_io::win32::hostent*; + native_handle_type res{}; + std::size_t pos{}; +}; + +inline constexpr win32_9x_dns_iterator operator*(win32_9x_dns_iterator d) noexcept +{ + return {d.res}; +} + +inline constexpr win32_9x_dns_iterator& operator++(win32_9x_dns_iterator& d) noexcept +{ + ++d.pos; + return d; +} + +inline constexpr win32_9x_dns_iterator operator++(win32_9x_dns_iterator d, int) noexcept +{ + auto temp{d}; + ++d; + return temp; +} + +inline constexpr win32_9x_dns_iterator begin(win32_9x_dns_io_observer w9xniob) noexcept +{ + return {w9xniob.res,0u}; +} + +inline constexpr win32_9x_dns_iterator cbegin(win32_9x_dns_io_observer w9xniob) noexcept +{ + return {w9xniob.res,0u}; +} + +inline constexpr ::std::default_sentinel_t end(win32_9x_dns_io_observer) noexcept +{ + return {}; +} + +inline constexpr ::std::default_sentinel_t cend(win32_9x_dns_io_observer) noexcept +{ + return {}; +} + +inline constexpr bool operator==(win32_9x_dns_iterator a, ::std::default_sentinel_t) noexcept +{ + return a.res==nullptr||(a.res->h_addr_list[a.pos]==nullptr); +} +inline constexpr bool operator!=(win32_9x_dns_iterator a, ::std::default_sentinel_t b) noexcept +{ + return !(a==b); +} + +inline constexpr ::fast_io::ip to_ip(win32_9x_dns_iterator d,std::uint_least16_t port) +{ + return ::fast_io::details::hostent_to_ip_impl(d.res,d.pos,port); +} + +namespace details +{ +inline ::fast_io::win32::hostent* win32_9x_gethostbyname_impl(char const* name) +{ + ::fast_io::win32::hostent* ret{::fast_io::win32::gethostbyname(name)}; + if(ret==nullptr) + throw_win32_error(static_cast(::fast_io::win32::WSAGetLastError())); + return ret; +} + +struct win32_9x_dns_open_parameter +{ + inline auto operator()(char const* node_name_c_str) + { + return ::fast_io::details::win32_9x_gethostbyname_impl(node_name_c_str); + } +}; + +template +requires ::fast_io::constructible_to_os_c_str +inline constexpr auto win32_9x_dns_open_impl(T const& t) +{ + return ::fast_io::posix_api_common(t,win32_9x_dns_open_parameter{}); +} + +} + +class win32_9x_dns_file:public win32_9x_dns_io_observer +{ +public: + using native_handle_type = typename win32_9x_dns_io_observer::native_handle_type; + constexpr win32_9x_dns_file() noexcept = default; + template + requires std::same_as> + explicit constexpr win32_9x_dns_file(native_hd res1) noexcept: win32_9x_dns_io_observer{res1}{} + explicit constexpr win32_9x_dns_file(decltype(nullptr)) noexcept = delete; + + constexpr win32_9x_dns_file(win32_9x_dns_io_observer) noexcept=delete; + constexpr win32_9x_dns_file& operator=(win32_9x_dns_io_observer) noexcept=delete; + + template + requires ::fast_io::constructible_to_os_c_str + explicit win32_9x_dns_file(T const& t):win32_9x_dns_io_observer{::fast_io::details::win32_9x_dns_open_impl(t)}{} + void close() noexcept + { + this->res=nullptr; + } +}; + +#if (defined(_WIN32_WINDOWS) || _WIN32_WINNT <= 0x0500) +using native_dns_io_observer = win32_9x_dns_io_observer; +using native_dns_file = win32_9x_dns_file; +using native_dns_iterator = win32_9x_dns_iterator; +#endif + +} diff --git a/src/fast_io/include/fast_io_hosted/platforms/win32_network/win32_dns.h b/src/fast_io/include/fast_io_hosted/platforms/win32_network/win32_dns.h new file mode 100644 index 0000000..974c3b0 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/win32_network/win32_dns.h @@ -0,0 +1,272 @@ +#pragma once + +namespace fast_io +{ + +template +requires (fam==win32_family::ansi_9x||fam==win32_family::wide_nt) +class win32_family_dns_io_observer +{ +public: + using char_type = std::conditional_t; + using native_handle_type = ::fast_io::win32::win32_family_addrinfo*; + native_handle_type res{}; + inline constexpr native_handle_type native_handle() const noexcept + { + return res; + } + explicit constexpr operator bool() noexcept + { + return res; + } + inline native_handle_type release() noexcept + { + native_handle_type temp{res}; + res=nullptr; + return temp; + } +}; + +template +requires (fam==win32_family::ansi_9x||fam==win32_family::wide_nt) +struct win32_family_dns_iterator +{ + using native_handle_type = ::fast_io::win32::win32_family_addrinfo*; + native_handle_type res{}; +}; + +template +inline constexpr bool operator==(win32_family_dns_iterator a, ::std::default_sentinel_t) noexcept +{ + return a.res == nullptr; +} + +template +inline constexpr bool operator!=(win32_family_dns_iterator a, ::std::default_sentinel_t) noexcept +{ + return a.res; +} + +template +inline constexpr win32_family_dns_io_observer operator*(win32_family_dns_iterator d) noexcept +{ + return {d.res}; +} + +template +inline constexpr win32_family_dns_iterator& operator++(win32_family_dns_iterator& d) noexcept +{ + d.res = d.res->ai_next; + return d; +} + +template +inline constexpr win32_family_dns_iterator operator++(win32_family_dns_iterator& d, int) noexcept +{ + auto temp{d}; + ++d; + return temp; +} + +namespace details +{ +inline constexpr ::fast_io::ip_address win32_to_ip_address_with_ai_addr_impl(int ai_family,posix_sockaddr const* ai_addr) noexcept +{ + ::fast_io::ip_address ret; + switch(ai_family) + { + case 2: + { + ::fast_io::details::my_memcpy(__builtin_addressof(ret.address.v4),__builtin_addressof(reinterpret_cast(ai_addr)->sin_addr),sizeof(posix_in_addr)); + ret.isv4=true; + break; + } + case 23: + { + ::fast_io::details::my_memcpy(__builtin_addressof(ret.address.v6),__builtin_addressof(reinterpret_cast(ai_addr)->sin6_addr),sizeof(posix_in6_addr)); + break; + } + } + return ret; +} + +inline constexpr ::fast_io::ip win32_to_ip_with_ai_addr_impl(int ai_family,posix_sockaddr const* ai_addr,std::uint_least16_t port) noexcept +{ + return ::fast_io::ip{win32_to_ip_address_with_ai_addr_impl(ai_family,ai_addr),port}; +} + +} + +template +inline constexpr ::fast_io::ip to_ip(win32_family_dns_io_observer d,std::uint_least16_t port) noexcept +{ + return ::fast_io::details::win32_to_ip_with_ai_addr_impl(d.res->ai_family,d.res->ai_addr,port); +} + +template +inline constexpr ::fast_io::ip_address to_ip_address(win32_family_dns_io_observer d) noexcept +{ + return ::fast_io::details::win32_to_ip_address_with_ai_addr_impl(d.res->ai_family,d.res->ai_addr); +} + +namespace details +{ + +template +inline ::fast_io::win32::win32_family_addrinfo* win32_getaddrinfo_impl(std::conditional_t const* node,std::conditional_t const* service,::fast_io::win32::win32_family_addrinfo const* hints) +{ + ::fast_io::win32::win32_family_addrinfo* res{}; + if constexpr(win32_family::ansi_9x==fam) + { + int ret{::fast_io::win32::getaddrinfo(node,service,hints,__builtin_addressof(res))}; + if(ret) + throw_win32_error(static_cast(ret)); + } + else + { + int ret{::fast_io::win32::GetAddrInfoW(node,service,hints,__builtin_addressof(res))}; + if(ret) + throw_win32_error(static_cast(ret)); + } + return res; +} + +template<::fast_io::win32_family fam> +inline void win32_family_freeaddrinfo_impl(::fast_io::win32::win32_family_addrinfo* paddrinfo) +{ + if constexpr(fam==::fast_io::win32_family::ansi_9x) + { + ::fast_io::win32::freeaddrinfo(paddrinfo); + } + else + { + ::fast_io::win32::FreeAddrInfoW(paddrinfo); + } +} + + +template +inline constexpr auto win32_family_dns_open_internal_impl(std::conditional_t const* node) +{ + constexpr ::fast_io::win32::win32_family_addrinfo info{.ai_family=0}; + return win32_getaddrinfo_impl(node,nullptr,__builtin_addressof(info)); +} + +template +struct win32_family_dns_open_parameter +{ + inline auto operator()(std::conditional_t const* node_name_c_str) + { + return ::fast_io::details::win32_family_dns_open_internal_impl(node_name_c_str); + } +}; + +template +requires ::fast_io::constructible_to_os_c_str +inline constexpr auto win32_family_dns_open_impl(T const& t) +{ + return ::fast_io::win32_family_api_common(t,win32_family_dns_open_parameter{}); +} + +} + +template +class win32_family_dns_file:public win32_family_dns_io_observer +{ +public: + using typename win32_family_dns_io_observer::char_type; + using typename win32_family_dns_io_observer::native_handle_type; + constexpr win32_family_dns_file() noexcept = default; + constexpr win32_family_dns_file(win32_family_dns_io_observer) noexcept=delete; + constexpr win32_family_dns_file& operator=(win32_family_dns_io_observer) noexcept=delete; + + template + requires std::same_as> + explicit constexpr win32_family_dns_file(native_hd res1) noexcept: win32_family_dns_io_observer{res1}{} + explicit constexpr win32_family_dns_file(decltype(nullptr)) noexcept = delete; + win32_family_dns_file(char_type const* node,char_type const* service,::fast_io::win32::win32_family_addrinfo const* hints):win32_family_dns_io_observer{::fast_io::details::win32_getaddrinfo_impl(node,service,hints)}{} + template + requires ::fast_io::constructible_to_os_c_str + explicit win32_family_dns_file(T const& t):win32_family_dns_io_observer{::fast_io::details::win32_family_dns_open_impl(t)}{} + win32_family_dns_file(win32_family_dns_file const&)=delete; + win32_family_dns_file& operator=(win32_family_dns_file const&)=delete; + constexpr win32_family_dns_file(win32_family_dns_file&& __restrict other) noexcept: win32_family_dns_io_observer{other.res} + { + other.res=nullptr; + } + win32_family_dns_file& operator=(win32_family_dns_file&& __restrict other) noexcept + { + if(this->res)[[likely]] + ::fast_io::details::win32_family_freeaddrinfo_impl(this->res); + this->res=other.res; + other.res=nullptr; + return *this; + } + void close() noexcept + { + if(this->res)[[likely]] + { + ::fast_io::details::win32_family_freeaddrinfo_impl(this->res); + this->res=nullptr; + } + } + ~win32_family_dns_file() + { + if(this->res)[[likely]] + ::fast_io::details::win32_family_freeaddrinfo_impl(this->res); + } +}; + +template +inline constexpr win32_family_dns_iterator begin(win32_family_dns_io_observer pdniob) noexcept +{ + return {pdniob.res}; +} + +template +inline constexpr win32_family_dns_iterator cbegin(win32_family_dns_io_observer pdniob) noexcept +{ + return {pdniob.res}; +} + +template +inline constexpr ::std::default_sentinel_t end(win32_family_dns_io_observer) noexcept +{ + return {}; +} + +template +inline constexpr ::std::default_sentinel_t cend(win32_family_dns_io_observer) noexcept +{ + return {}; +} + +using ::fast_io::win32::win32_family_addrinfo; +using ::fast_io::win32::win32_addrinfo_9xa; +using ::fast_io::win32::win32_addrinfo_ntw; +using win32_addrinfo = ::fast_io::win32::win32_family_addrinfo<::fast_io::win32_family::native>; + +using win32_dns_io_observer_9xa = win32_family_dns_io_observer; +using win32_dns_io_observer_ntw = win32_family_dns_io_observer; +using win32_dns_io_observer = win32_family_dns_io_observer; + +using win32_dns_file_9xa = win32_family_dns_file; +using win32_dns_file_ntw = win32_family_dns_file; +using win32_dns_file = win32_family_dns_file; + +using win32_dns_iterator_9xa = win32_family_dns_iterator; +using win32_dns_iterator_ntw = win32_family_dns_iterator; +using win32_dns_iterator = win32_family_dns_iterator; + +#if !defined(__WINE__) && !defined(__CYGWIN__) +using native_addrinfo = win32_addrinfo; + +#if (defined(_MSC_VER) || (!defined(_WIN32_WINDOWS) && _WIN32_WINNT>=0x0501)) +using native_dns_io_observer = win32_dns_io_observer; +using native_dns_file = win32_dns_file; +using native_dns_iterator = win32_dns_iterator; +#endif + +#endif + +} diff --git a/src/fast_io/include/fast_io_hosted/platforms/win32_scheduling.h b/src/fast_io/include/fast_io_hosted/platforms/win32_scheduling.h new file mode 100644 index 0000000..e18465b --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/win32_scheduling.h @@ -0,0 +1,43 @@ +#pragma once + +namespace fast_io +{ + +inline void io_async_wait(win32_io_observer iocp) +{ + std::uint_least32_t transferred{}; + std::uintptr_t completionkey{}; + win32::overlapped *over{}; + if(!GetQueuedCompletionStatus(iocp.native_handle(),__builtin_addressof(transferred),__builtin_addressof(completionkey), + __builtin_addressof(over),std::numeric_limits::max())) + throw_win32_error(); + static_cast(over)->invoke(static_cast(transferred)); +} + +namespace details +{ +inline bool iocp_io_async_wait_timeout_detail(win32_io_observer iocp,std::uint_least32_t millseconds) +{ + std::uint_least32_t transferred{}; + std::uintptr_t completionkey{}; + win32::overlapped *over{}; + if(!GetQueuedCompletionStatus(iocp.native_handle(),__builtin_addressof(transferred),__builtin_addressof(completionkey), + __builtin_addressof(over),millseconds)) + { + auto errc{win32::GetLastError()}; + if(errc==258) + return false; + throw_win32_error(errc); + } + static_cast(over)->invoke(static_cast(transferred)); + return true; +} +} + +template +inline bool io_async_wait_timeout(win32_io_observer iocp,std::chrono::duration duration) +{ + return details::iocp_io_async_wait_timeout_detail(iocp,std::chrono::duration_cast(duration).count()); +} + +} diff --git a/src/fast_io/include/fast_io_hosted/platforms/wine/linux_syscall_table/i686.h b/src/fast_io/include/fast_io_hosted/platforms/wine/linux_syscall_table/i686.h new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/wine/linux_syscall_table/i686.h @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/fast_io/include/fast_io_hosted/platforms/wine/linux_syscall_table/impl.h b/src/fast_io/include/fast_io_hosted/platforms/wine/linux_syscall_table/impl.h new file mode 100644 index 0000000..7acb800 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/wine/linux_syscall_table/impl.h @@ -0,0 +1,14 @@ +#pragma once + +namespace fast_io::wine +{ + +using linux_syscall_table = +#if defined(__x86_64__) +linux_syscall_table_x86_64 +#else +linux_syscall_table_i686 +#endif +; + +} diff --git a/src/fast_io/include/fast_io_hosted/platforms/wine/linux_syscall_table/x86_64.h b/src/fast_io/include/fast_io_hosted/platforms/wine/linux_syscall_table/x86_64.h new file mode 100644 index 0000000..bfcbd4a --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/wine/linux_syscall_table/x86_64.h @@ -0,0 +1,6 @@ +#pragma once + +namespace fast_io::wine::linux_syscall_table_x86_64 +{ + +} diff --git a/src/fast_io/include/fast_io_hosted/platforms/wine/wine.h b/src/fast_io/include/fast_io_hosted/platforms/wine/wine.h new file mode 100644 index 0000000..7c7c627 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/platforms/wine/wine.h @@ -0,0 +1,80 @@ +#pragma once + +namespace fast_io +{ + +enum class wine_family:std::uint_least32_t +{ +unspecified_host=0, +linux_host=1, +cygwin_host=2, +native= +#if defined(_WIN32_WINE_LINUX) +linux_host +#else +unspecified_host +#endif +}; + +template +class basic_wine_family_io_observer +{ +public: + using char_type = ch_type; + using native_handle_type = int; + native_handle_type host_fd{-1}; + constexpr native_handle_type native_handle() const noexcept + { + return host_fd; + } + explicit constexpr operator bool() const noexcept + { + return host_fd!=-1; + } + constexpr native_handle_type release() noexcept + { + auto temp{host_fd}; + host_fd=-1; + return temp; + } +}; + +template +struct +#if __has_cpp_attribute(clang::trivially_relocatable) +[[clang::trivially_relocatable]] +#endif +wine_family_file_factory +{ + using native_handle_type = int; + int host_fd{-1}; + explicit constexpr wine_family_file_factory(int v) noexcept:host_fd(v){}; + wine_family_file_factory(wine_family_file_factory const&)=delete; + wine_family_file_factory& operator=(wine_family_file_factory const&)=delete; + ~wine_family_file_factory() + { + if(host_fd!=-1)[[likely]] + ::fast_io::details::wine::wine_close(host_fd); + } +}; + +using wine_file_factory = wine_family_file_factory; + +template +class basic_wine_family_file:public basic_wine_family_io_observer +{ +public: + using typename basic_wine_family_io_observer::char_type; + using typename basic_wine_family_io_observer::native_handle_type; + using file_factory_type = wine_family_file_factory; + constexpr basic_wine_family_file() noexcept = default; + template + requires std::same_as> + explicit constexpr basic_wine_family_file(native_hd host_fd1) noexcept: basic_wine_family_io_observer{host_fd1}{} + constexpr basic_wine_family_file(decltype(nullptr)) noexcept = delete; + constexpr basic_wine_family_file(basic_wine_family_file) noexcept=delete; + constexpr basic_wine_family_file& operator=(basic_wine_family_file) noexcept=delete; + +}; + +} diff --git a/src/fast_io/include/fast_io_hosted/posix_error.h b/src/fast_io/include/fast_io_hosted/posix_error.h new file mode 100644 index 0000000..011305e --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/posix_error.h @@ -0,0 +1,102 @@ +#pragma once + +namespace fast_io +{ + + +inline constexpr std::uintptr_t domain_define(error_type_t<::fast_io::freestanding::errc>) noexcept +{ + if constexpr(sizeof(std::uintptr_t)<=sizeof(std::uint_least16_t)) + return 52386u; + else if constexpr(sizeof(std::uintptr_t)<=sizeof(std::uint_least32_t)) + return 1105291838u; + else + return 11138730069487200664ULL; +} + +inline constexpr std::uintptr_t posix_domain_value{domain_define(error_type<::fast_io::freestanding::errc>)}; + +[[noreturn]] inline void throw_posix_error() +{ +#ifdef __cpp_exceptions +#if defined(_MSC_VER) && (!defined(_HAS_EXCEPTIONS) || _HAS_EXCEPTIONS == 0) + fast_terminate(); +#else + throw ::fast_io::error{posix_domain_value,static_cast(static_cast(errno))}; +#endif +#else + fast_terminate(); +#endif +} +[[noreturn]] inline void throw_posix_error([[maybe_unused]] int err) +{ +#ifdef __cpp_exceptions +#if defined(_MSC_VER) && (!defined(_HAS_EXCEPTIONS) || _HAS_EXCEPTIONS == 0) + fast_terminate(); +#else + throw ::fast_io::error{posix_domain_value,static_cast(static_cast(err))}; +#endif +#else + fast_terminate(); +#endif +} + +template +inline constexpr basic_io_scatter_t status_io_print_forward(io_alias_type_t,::fast_io::freestanding::errc perr) noexcept +{ + return get_posix_errno_scatter(static_cast(perr)); +} + +#if !((defined(_WIN32)&&!defined(__WINE__)) || defined(__CYGWIN__)) + +namespace details +{ +inline constexpr bool posix_code_equivalent_impl(std::uintptr_t domain,std::uintptr_t code,int e) noexcept +{ + if(posix_domain_value!=domain) + return false; + else + { + using common_type = std::common_type_t; + return code==static_cast(static_cast(e)); + } +} + +inline constexpr int to_posix_code_impl(std::uintptr_t domain,std::uintptr_t code) noexcept +{ + if(posix_domain_value!=domain) + { +#if defined(EOTHER) + return EOTHER; +#else + return EINVAL; +#endif + } + else + { + return static_cast(static_cast(code)); + } +} + +} + +inline constexpr bool equivalent_define(error_type_t<::fast_io::freestanding::errc>,::fast_io::error e,::fast_io::freestanding::errc p) +{ + return ::fast_io::details::posix_code_equivalent_impl(e.domain,e.code,static_cast(p)); +} + +inline constexpr ::fast_io::freestanding::errc to_code_define(error_type_t<::fast_io::freestanding::errc>,error e) noexcept +{ + return ::fast_io::freestanding::errc{::fast_io::details::to_posix_code_impl(e.domain,e.code)}; +} + +using native_code = ::fast_io::freestanding::errc; + +inline constexpr ::fast_io::freestanding::errc print_alias_define(::fast_io::io_alias_t,::fast_io::error e) noexcept +{ + return to_code_define(error_type<::fast_io::freestanding::errc>,e); +} + +#endif + +} diff --git a/src/fast_io/include/fast_io_hosted/posix_error_scatter/avr.h b/src/fast_io/include/fast_io_hosted/posix_error_scatter/avr.h new file mode 100644 index 0000000..9194810 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/posix_error_scatter/avr.h @@ -0,0 +1,190 @@ + if constexpr(std::same_as) + { +switch(errn) +{ +case 0: + return tsc("Success"); +#if defined(EDOM) +case EDOM: + return tsc("Mathematics argument out of domain of function"); +#endif +#if defined(ERANGE) +case ERANGE: + return tsc("Result too large"); +#endif +#if defined(EOVERFLOW) +case EOVERFLOW: + return tsc("Value too large for defined data type"); +#endif +#if defined(ENOTSUP) +case ENOTSUP: + return tsc("Not supported"); +#endif +#if defined(ENOSYS) +case ENOSYS: + return tsc("Function not implemented"); +#endif +#if defined(EINTR) +case EINTR: + return tsc("Interrupted system call"); +#endif +#if defined(ENOERR) +case ENOERR: + return tsc("Error"); +#endif +default: + return tsc("Unknown"); +} + } + else if constexpr(std::same_as) + { +switch(errn) +{ +case 0: + return tsc(L"Success"); +#if defined(EDOM) +case EDOM: + return tsc(L"Mathematics argument out of domain of function"); +#endif +#if defined(ERANGE) +case ERANGE: + return tsc(L"Result too large"); +#endif +#if defined(EOVERFLOW) +case EOVERFLOW: + return tsc(L"Value too large for defined data type"); +#endif +#if defined(ENOTSUP) +case ENOTSUP: + return tsc(L"Not supported"); +#endif +#if defined(ENOSYS) +case ENOSYS: + return tsc(L"Function not implemented"); +#endif +#if defined(EINTR) +case EINTR: + return tsc(L"Interrupted system call"); +#endif +#if defined(ENOERR) +case ENOERR: + return tsc(L"Error"); +#endif +default: + return tsc(L"Unknown"); +} + } + else if constexpr(std::same_as) + { +switch(errn) +{ +case 0: + return tsc(u"Success"); +#if defined(EDOM) +case EDOM: + return tsc(u"Mathematics argument out of domain of function"); +#endif +#if defined(ERANGE) +case ERANGE: + return tsc(u"Result too large"); +#endif +#if defined(EOVERFLOW) +case EOVERFLOW: + return tsc(u"Value too large for defined data type"); +#endif +#if defined(ENOTSUP) +case ENOTSUP: + return tsc(u"Not supported"); +#endif +#if defined(ENOSYS) +case ENOSYS: + return tsc(u"Function not implemented"); +#endif +#if defined(EINTR) +case EINTR: + return tsc(u"Interrupted system call"); +#endif +#if defined(ENOERR) +case ENOERR: + return tsc(u"Error"); +#endif +default: + return tsc(u"Unknown"); +} + } + else if constexpr(std::same_as) + { +switch(errn) +{ +case 0: + return tsc(U"Success"); +#if defined(EDOM) +case EDOM: + return tsc(U"Mathematics argument out of domain of function"); +#endif +#if defined(ERANGE) +case ERANGE: + return tsc(U"Result too large"); +#endif +#if defined(EOVERFLOW) +case EOVERFLOW: + return tsc(U"Value too large for defined data type"); +#endif +#if defined(ENOTSUP) +case ENOTSUP: + return tsc(U"Not supported"); +#endif +#if defined(ENOSYS) +case ENOSYS: + return tsc(U"Function not implemented"); +#endif +#if defined(EINTR) +case EINTR: + return tsc(U"Interrupted system call"); +#endif +#if defined(ENOERR) +case ENOERR: + return tsc(U"Error"); +#endif +default: + return tsc(U"Unknown"); +} + } + else + { +switch(errn) +{ +case 0: + return tsc(u8"Success"); +#if defined(EDOM) +case EDOM: + return tsc(u8"Mathematics argument out of domain of function"); +#endif +#if defined(ERANGE) +case ERANGE: + return tsc(u8"Result too large"); +#endif +#if defined(EOVERFLOW) +case EOVERFLOW: + return tsc(u8"Value too large for defined data type"); +#endif +#if defined(ENOTSUP) +case ENOTSUP: + return tsc(u8"Not supported"); +#endif +#if defined(ENOSYS) +case ENOSYS: + return tsc(u8"Function not implemented"); +#endif +#if defined(EINTR) +case EINTR: + return tsc(u8"Interrupted system call"); +#endif +#if defined(ENOERR) +case ENOERR: + return tsc(u8"Error"); +#endif +default: + return tsc(u8"Unknown"); +} + } \ No newline at end of file diff --git a/src/fast_io/include/fast_io_hosted/posix_error_scatter/generic.h b/src/fast_io/include/fast_io_hosted/posix_error_scatter/generic.h new file mode 100644 index 0000000..dc01606 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/posix_error_scatter/generic.h @@ -0,0 +1,1975 @@ + if constexpr(std::same_as) + { +switch(errn) +{ +case 0: + return tsc("Success"); +#if defined (EPERM) && (!defined (EACCES) || (EPERM != EACCES)) +case EPERM: + return tsc("Not owner"); +#endif +#ifdef ENOENT +case ENOENT: + return tsc("No such file or directory"); +#endif +#ifdef ESRCH +case ESRCH: + return tsc("No such process"); +#endif +#ifdef EINTR +case EINTR: + return tsc("Interrupted system call"); +#endif +#ifdef EIO +case EIO: + return tsc("I/O error"); +#endif +/* go32 defines ENXIO as ENODEV */ +#if defined (ENXIO) && (!defined (ENODEV) || (ENXIO != ENODEV)) +case ENXIO: + return tsc("No such device or address"); +#endif +#ifdef E2BIG +case E2BIG: + return tsc("Arg list too long"); +#endif +#ifdef ENOEXEC +case ENOEXEC: + return tsc("Exec format error"); +#endif +#ifdef EALREADY +case EALREADY: + return tsc("Socket already connected"); +#endif +#ifdef EBADF +case EBADF: + return tsc("Bad file number"); +#endif +#ifdef ECHILD +case ECHILD: + return tsc("No children"); +#endif +#ifdef EDESTADDRREQ +case EDESTADDRREQ: + return tsc("Destination address required"); +#endif +#ifdef EAGAIN +case EAGAIN: + return tsc("No more processes"); +#endif +#ifdef ENOMEM +case ENOMEM: + return tsc("Not enough space"); +#endif +#ifdef EACCES +case EACCES: + return tsc("Permission denied"); +#endif +#ifdef EFAULT +case EFAULT: + return tsc("Bad address"); +#endif +#ifdef ENOTBLK +case ENOTBLK: + return tsc("Block device required"); +#endif +#ifdef EBUSY +case EBUSY: + return tsc("Device or resource busy"); +#endif +#ifdef EEXIST +case EEXIST: + return tsc("File exists"); +#endif +#ifdef EXDEV +case EXDEV: + return tsc("Cross-device link"); +#endif +#ifdef ENODEV +case ENODEV: + return tsc("No such device"); +#endif +#ifdef ENOTDIR +case ENOTDIR: + return tsc("Not a directory"); +#endif +#ifdef EHOSTDOWN +case EHOSTDOWN: + return tsc("Host is down"); +#endif +#ifdef EINPROGRESS +case EINPROGRESS: + return tsc("Connection already in progress"); +#endif +#ifdef EISDIR +case EISDIR: + return tsc("Is a directory"); +#endif +#ifdef EINVAL +case EINVAL: + return tsc("Invalid argument"); +#endif +#ifdef ENETDOWN +case ENETDOWN: + return tsc("Network interface is not configured"); +#endif +#ifdef ENETRESET +case ENETRESET: + return tsc("Connection aborted by network"); +#endif +#ifdef ENFILE +case ENFILE: + return tsc("Too many open files in system"); +#endif +#ifdef EMFILE +case EMFILE: + return tsc("File descriptor value too large"); +#endif +#ifdef ENOTTY +case ENOTTY: + return tsc("Not a character device"); +#endif +#ifdef ETXTBSY +case ETXTBSY: + return tsc("Text file busy"); +#endif +#ifdef EFBIG +case EFBIG: + return tsc("File too large"); +#endif +#ifdef EHOSTUNREACH +case EHOSTUNREACH: + return tsc("Host is unreachable"); +#endif +#ifdef ENOSPC +case ENOSPC: + return tsc("No space left on device"); +#endif +#ifdef ENOTSUP +case ENOTSUP: + return tsc("Not supported"); +#endif +#ifdef ESPIPE +case ESPIPE: + return tsc("Illegal seek"); +#endif +#ifdef EROFS +case EROFS: + return tsc("Read-only file system"); +#endif +#ifdef EMLINK +case EMLINK: + return tsc("Too many links"); +#endif +#ifdef EPIPE +case EPIPE: + return tsc("Broken pipe"); +#endif +#ifdef EDOM +case EDOM: + return tsc("Mathematics argument out of domain of function"); +#endif +#ifdef ERANGE +case ERANGE: + return tsc("Result too large"); +#endif +#ifdef ENOMSG +case ENOMSG: + return tsc("No message of desired type"); +#endif +#ifdef EIDRM +case EIDRM: + return tsc("Identifier removed"); +#endif +#ifdef EILSEQ +case EILSEQ: + return tsc("Illegal byte sequence"); +#endif +#ifdef EDEADLK +case EDEADLK: + return tsc("Deadlock"); +#endif +#ifdef ENETUNREACH +case ENETUNREACH: + return tsc("Network is unreachable"); +#endif +#ifdef ENOLCK +case ENOLCK: + return tsc("No lock"); +#endif +#ifdef ENOSTR +case ENOSTR: + return tsc("Not a stream"); +#endif +#ifdef ETIME +case ETIME: + return tsc("Stream ioctl timeout"); +#endif +#ifdef ENOSR +case ENOSR: + return tsc("No stream resources"); +#endif +#ifdef ENONET +case ENONET: + return tsc("Machine is not on the network"); +#endif +#ifdef ENOPKG +case ENOPKG: + return tsc("No package"); +#endif +#ifdef EREMOTE +case EREMOTE: + return tsc("Resource is remote"); +#endif +#ifdef ENOLINK +case ENOLINK: + return tsc("Virtual circuit is gone"); +#endif +#ifdef EADV +case EADV: + return tsc("Advertise error"); +#endif +#ifdef ESRMNT +case ESRMNT: + return tsc("Srmount error"); +#endif +#ifdef ECOMM +case ECOMM: + return tsc("Communication error"); +#endif +#ifdef EPROTO +case EPROTO: + return tsc("Protocol error"); +#endif +#ifdef EPROTONOSUPPORT +case EPROTONOSUPPORT: + return tsc("Unknown protocol"); +#endif +#ifdef EMULTIHOP +case EMULTIHOP: + return tsc("Multihop attempted"); +#endif +#ifdef EBADMSG +case EBADMSG: + return tsc("Bad message"); +#endif +#ifdef ELIBACC +case ELIBACC: + return tsc("Cannot access a needed shared library"); +#endif +#ifdef ELIBBAD +case ELIBBAD: + return tsc("Accessing a corrupted shared library"); +#endif +#ifdef ELIBSCN +case ELIBSCN: + return tsc(".lib section in a.out corrupted"); +#endif +#ifdef ELIBMAX +case ELIBMAX: + return tsc("Attempting to link in more shared libraries than system limit"); +#endif +#ifdef ELIBEXEC +case ELIBEXEC: + return tsc("Cannot exec a shared library directly"); +#endif +#ifdef ENOSYS +case ENOSYS: + return tsc("Function not implemented"); +#endif +#ifdef ENMFILE +case ENMFILE: + return tsc("No more files"); +#endif +#ifdef ENOTEMPTY +case ENOTEMPTY: + return tsc("Directory not empty"); +#endif +#ifdef ENAMETOOLONG +case ENAMETOOLONG: + return tsc("File or path name too long"); +#endif +#ifdef ELOOP +case ELOOP: + return tsc("Too many symbolic links"); +#endif +#ifdef ENOBUFS +case ENOBUFS: + return tsc("No buffer space available"); +#endif +#ifdef ENODATA +case ENODATA: + return tsc("No data"); +#endif +#ifdef EAFNOSUPPORT +case EAFNOSUPPORT: + return tsc("Address family not supported by protocol family"); +#endif +#ifdef EPROTOTYPE +case EPROTOTYPE: + return tsc("Protocol wrong type for socket"); +#endif +#ifdef ENOTSOCK +case ENOTSOCK: + return tsc("Socket operation on non-socket"); +#endif +#ifdef ENOPROTOOPT +case ENOPROTOOPT: + return tsc("Protocol not available"); +#endif +#ifdef ESHUTDOWN +case ESHUTDOWN: + return tsc("Can't send after socket shutdown"); +#endif +#ifdef ECONNREFUSED +case ECONNREFUSED: + return tsc("Connection refused"); +#endif +#ifdef ECONNRESET +case ECONNRESET: + return tsc("Connection reset by peer"); +#endif +#ifdef EADDRINUSE +case EADDRINUSE: + return tsc("Address already in use"); +#endif +#ifdef EADDRNOTAVAIL +case EADDRNOTAVAIL: + return tsc("Address not available"); +#endif +#ifdef ECONNABORTED +case ECONNABORTED: + return tsc("Software caused connection abort"); +#endif +#if (defined(EWOULDBLOCK) && (!defined (EAGAIN) || (EWOULDBLOCK != EAGAIN))) +case EWOULDBLOCK: + return tsc("Operation would block"); +#endif +#ifdef ENOTCONN +case ENOTCONN: + return tsc("Socket is not connected"); +#endif +#ifdef ESOCKTNOSUPPORT +case ESOCKTNOSUPPORT: + return tsc("Socket type not supported"); +#endif +#ifdef EISCONN +case EISCONN: + return tsc("Socket is already connected"); +#endif +#ifdef ECANCELED +case ECANCELED: + return tsc("Operation canceled"); +#endif +#ifdef ENOTRECOVERABLE +case ENOTRECOVERABLE: + return tsc("State not recoverable"); +#endif +#ifdef EOWNERDEAD +case EOWNERDEAD: + return tsc("Previous owner died"); +#endif +#ifdef ESTRPIPE +case ESTRPIPE: + return tsc("Streams pipe error"); +#endif +#if defined(EOPNOTSUPP) && (!defined(ENOTSUP) || (ENOTSUP != EOPNOTSUPP)) +case EOPNOTSUPP: + return tsc("Operation not supported on socket"); +#endif +#ifdef EOVERFLOW +case EOVERFLOW: + return tsc("Value too large for defined data type"); +#endif +#ifdef EMSGSIZE +case EMSGSIZE: + return tsc("Message too long"); +#endif +#ifdef ETIMEDOUT +case ETIMEDOUT: + return tsc("Connection timed out"); +#endif +default: + return tsc("Unknown"); +} + } + else if constexpr(std::same_as) + { +switch(errn) +{ +case 0: + return tsc(L"Success"); +#if defined (EPERM) && (!defined (EACCES) || (EPERM != EACCES)) +case EPERM: + return tsc(L"Not owner"); +#endif +#ifdef ENOENT +case ENOENT: + return tsc(L"No such file or directory"); +#endif +#ifdef ESRCH +case ESRCH: + return tsc(L"No such process"); +#endif +#ifdef EINTR +case EINTR: + return tsc(L"Interrupted system call"); +#endif +#ifdef EIO +case EIO: + return tsc(L"I/O error"); +#endif +/* go32 defines ENXIO as ENODEV */ +#if defined (ENXIO) && (!defined (ENODEV) || (ENXIO != ENODEV)) +case ENXIO: + return tsc(L"No such device or address"); +#endif +#ifdef E2BIG +case E2BIG: + return tsc(L"Arg list too long"); +#endif +#ifdef ENOEXEC +case ENOEXEC: + return tsc(L"Exec format error"); +#endif +#ifdef EALREADY +case EALREADY: + return tsc(L"Socket already connected"); +#endif +#ifdef EBADF +case EBADF: + return tsc(L"Bad file number"); +#endif +#ifdef ECHILD +case ECHILD: + return tsc(L"No children"); +#endif +#ifdef EDESTADDRREQ +case EDESTADDRREQ: + return tsc(L"Destination address required"); +#endif +#ifdef EAGAIN +case EAGAIN: + return tsc(L"No more processes"); +#endif +#ifdef ENOMEM +case ENOMEM: + return tsc(L"Not enough space"); +#endif +#ifdef EACCES +case EACCES: + return tsc(L"Permission denied"); +#endif +#ifdef EFAULT +case EFAULT: + return tsc(L"Bad address"); +#endif +#ifdef ENOTBLK +case ENOTBLK: + return tsc(L"Block device required"); +#endif +#ifdef EBUSY +case EBUSY: + return tsc(L"Device or resource busy"); +#endif +#ifdef EEXIST +case EEXIST: + return tsc(L"File exists"); +#endif +#ifdef EXDEV +case EXDEV: + return tsc(L"Cross-device link"); +#endif +#ifdef ENODEV +case ENODEV: + return tsc(L"No such device"); +#endif +#ifdef ENOTDIR +case ENOTDIR: + return tsc(L"Not a directory"); +#endif +#ifdef EHOSTDOWN +case EHOSTDOWN: + return tsc(L"Host is down"); +#endif +#ifdef EINPROGRESS +case EINPROGRESS: + return tsc(L"Connection already in progress"); +#endif +#ifdef EISDIR +case EISDIR: + return tsc(L"Is a directory"); +#endif +#ifdef EINVAL +case EINVAL: + return tsc(L"Invalid argument"); +#endif +#ifdef ENETDOWN +case ENETDOWN: + return tsc(L"Network interface is not configured"); +#endif +#ifdef ENETRESET +case ENETRESET: + return tsc(L"Connection aborted by network"); +#endif +#ifdef ENFILE +case ENFILE: + return tsc(L"Too many open files in system"); +#endif +#ifdef EMFILE +case EMFILE: + return tsc(L"File descriptor value too large"); +#endif +#ifdef ENOTTY +case ENOTTY: + return tsc(L"Not a character device"); +#endif +#ifdef ETXTBSY +case ETXTBSY: + return tsc(L"Text file busy"); +#endif +#ifdef EFBIG +case EFBIG: + return tsc(L"File too large"); +#endif +#ifdef EHOSTUNREACH +case EHOSTUNREACH: + return tsc(L"Host is unreachable"); +#endif +#ifdef ENOSPC +case ENOSPC: + return tsc(L"No space left on device"); +#endif +#ifdef ENOTSUP +case ENOTSUP: + return tsc(L"Not supported"); +#endif +#ifdef ESPIPE +case ESPIPE: + return tsc(L"Illegal seek"); +#endif +#ifdef EROFS +case EROFS: + return tsc(L"Read-only file system"); +#endif +#ifdef EMLINK +case EMLINK: + return tsc(L"Too many links"); +#endif +#ifdef EPIPE +case EPIPE: + return tsc(L"Broken pipe"); +#endif +#ifdef EDOM +case EDOM: + return tsc(L"Mathematics argument out of domain of function"); +#endif +#ifdef ERANGE +case ERANGE: + return tsc(L"Result too large"); +#endif +#ifdef ENOMSG +case ENOMSG: + return tsc(L"No message of desired type"); +#endif +#ifdef EIDRM +case EIDRM: + return tsc(L"Identifier removed"); +#endif +#ifdef EILSEQ +case EILSEQ: + return tsc(L"Illegal byte sequence"); +#endif +#ifdef EDEADLK +case EDEADLK: + return tsc(L"Deadlock"); +#endif +#ifdef ENETUNREACH +case ENETUNREACH: + return tsc(L"Network is unreachable"); +#endif +#ifdef ENOLCK +case ENOLCK: + return tsc(L"No lock"); +#endif +#ifdef ENOSTR +case ENOSTR: + return tsc(L"Not a stream"); +#endif +#ifdef ETIME +case ETIME: + return tsc(L"Stream ioctl timeout"); +#endif +#ifdef ENOSR +case ENOSR: + return tsc(L"No stream resources"); +#endif +#ifdef ENONET +case ENONET: + return tsc(L"Machine is not on the network"); +#endif +#ifdef ENOPKG +case ENOPKG: + return tsc(L"No package"); +#endif +#ifdef EREMOTE +case EREMOTE: + return tsc(L"Resource is remote"); +#endif +#ifdef ENOLINK +case ENOLINK: + return tsc(L"Virtual circuit is gone"); +#endif +#ifdef EADV +case EADV: + return tsc(L"Advertise error"); +#endif +#ifdef ESRMNT +case ESRMNT: + return tsc(L"Srmount error"); +#endif +#ifdef ECOMM +case ECOMM: + return tsc(L"Communication error"); +#endif +#ifdef EPROTO +case EPROTO: + return tsc(L"Protocol error"); +#endif +#ifdef EPROTONOSUPPORT +case EPROTONOSUPPORT: + return tsc(L"Unknown protocol"); +#endif +#ifdef EMULTIHOP +case EMULTIHOP: + return tsc(L"Multihop attempted"); +#endif +#ifdef EBADMSG +case EBADMSG: + return tsc(L"Bad message"); +#endif +#ifdef ELIBACC +case ELIBACC: + return tsc(L"Cannot access a needed shared library"); +#endif +#ifdef ELIBBAD +case ELIBBAD: + return tsc(L"Accessing a corrupted shared library"); +#endif +#ifdef ELIBSCN +case ELIBSCN: + return tsc(L".lib section in a.out corrupted"); +#endif +#ifdef ELIBMAX +case ELIBMAX: + return tsc(L"Attempting to link in more shared libraries than system limit"); +#endif +#ifdef ELIBEXEC +case ELIBEXEC: + return tsc(L"Cannot exec a shared library directly"); +#endif +#ifdef ENOSYS +case ENOSYS: + return tsc(L"Function not implemented"); +#endif +#ifdef ENMFILE +case ENMFILE: + return tsc(L"No more files"); +#endif +#ifdef ENOTEMPTY +case ENOTEMPTY: + return tsc(L"Directory not empty"); +#endif +#ifdef ENAMETOOLONG +case ENAMETOOLONG: + return tsc(L"File or path name too long"); +#endif +#ifdef ELOOP +case ELOOP: + return tsc(L"Too many symbolic links"); +#endif +#ifdef ENOBUFS +case ENOBUFS: + return tsc(L"No buffer space available"); +#endif +#ifdef ENODATA +case ENODATA: + return tsc(L"No data"); +#endif +#ifdef EAFNOSUPPORT +case EAFNOSUPPORT: + return tsc(L"Address family not supported by protocol family"); +#endif +#ifdef EPROTOTYPE +case EPROTOTYPE: + return tsc(L"Protocol wrong type for socket"); +#endif +#ifdef ENOTSOCK +case ENOTSOCK: + return tsc(L"Socket operation on non-socket"); +#endif +#ifdef ENOPROTOOPT +case ENOPROTOOPT: + return tsc(L"Protocol not available"); +#endif +#ifdef ESHUTDOWN +case ESHUTDOWN: + return tsc(L"Can't send after socket shutdown"); +#endif +#ifdef ECONNREFUSED +case ECONNREFUSED: + return tsc(L"Connection refused"); +#endif +#ifdef ECONNRESET +case ECONNRESET: + return tsc(L"Connection reset by peer"); +#endif +#ifdef EADDRINUSE +case EADDRINUSE: + return tsc(L"Address already in use"); +#endif +#ifdef EADDRNOTAVAIL +case EADDRNOTAVAIL: + return tsc(L"Address not available"); +#endif +#ifdef ECONNABORTED +case ECONNABORTED: + return tsc(L"Software caused connection abort"); +#endif +#if (defined(EWOULDBLOCK) && (!defined (EAGAIN) || (EWOULDBLOCK != EAGAIN))) +case EWOULDBLOCK: + return tsc(L"Operation would block"); +#endif +#ifdef ENOTCONN +case ENOTCONN: + return tsc(L"Socket is not connected"); +#endif +#ifdef ESOCKTNOSUPPORT +case ESOCKTNOSUPPORT: + return tsc(L"Socket type not supported"); +#endif +#ifdef EISCONN +case EISCONN: + return tsc(L"Socket is already connected"); +#endif +#ifdef ECANCELED +case ECANCELED: + return tsc(L"Operation canceled"); +#endif +#ifdef ENOTRECOVERABLE +case ENOTRECOVERABLE: + return tsc(L"State not recoverable"); +#endif +#ifdef EOWNERDEAD +case EOWNERDEAD: + return tsc(L"Previous owner died"); +#endif +#ifdef ESTRPIPE +case ESTRPIPE: + return tsc(L"Streams pipe error"); +#endif +#if defined(EOPNOTSUPP) && (!defined(ENOTSUP) || (ENOTSUP != EOPNOTSUPP)) +case EOPNOTSUPP: + return tsc(L"Operation not supported on socket"); +#endif +#ifdef EOVERFLOW +case EOVERFLOW: + return tsc(L"Value too large for defined data type"); +#endif +#ifdef EMSGSIZE +case EMSGSIZE: + return tsc(L"Message too long"); +#endif +#ifdef ETIMEDOUT +case ETIMEDOUT: + return tsc(L"Connection timed out"); +#endif +default: + return tsc(L"Unknown"); +} + } + else if constexpr(std::same_as) + { +switch(errn) +{ +case 0: + return tsc(u"Success"); +#if defined (EPERM) && (!defined (EACCES) || (EPERM != EACCES)) +case EPERM: + return tsc(u"Not owner"); +#endif +#ifdef ENOENT +case ENOENT: + return tsc(u"No such file or directory"); +#endif +#ifdef ESRCH +case ESRCH: + return tsc(u"No such process"); +#endif +#ifdef EINTR +case EINTR: + return tsc(u"Interrupted system call"); +#endif +#ifdef EIO +case EIO: + return tsc(u"I/O error"); +#endif +/* go32 defines ENXIO as ENODEV */ +#if defined (ENXIO) && (!defined (ENODEV) || (ENXIO != ENODEV)) +case ENXIO: + return tsc(u"No such device or address"); +#endif +#ifdef E2BIG +case E2BIG: + return tsc(u"Arg list too long"); +#endif +#ifdef ENOEXEC +case ENOEXEC: + return tsc(u"Exec format error"); +#endif +#ifdef EALREADY +case EALREADY: + return tsc(u"Socket already connected"); +#endif +#ifdef EBADF +case EBADF: + return tsc(u"Bad file number"); +#endif +#ifdef ECHILD +case ECHILD: + return tsc(u"No children"); +#endif +#ifdef EDESTADDRREQ +case EDESTADDRREQ: + return tsc(u"Destination address required"); +#endif +#ifdef EAGAIN +case EAGAIN: + return tsc(u"No more processes"); +#endif +#ifdef ENOMEM +case ENOMEM: + return tsc(u"Not enough space"); +#endif +#ifdef EACCES +case EACCES: + return tsc(u"Permission denied"); +#endif +#ifdef EFAULT +case EFAULT: + return tsc(u"Bad address"); +#endif +#ifdef ENOTBLK +case ENOTBLK: + return tsc(u"Block device required"); +#endif +#ifdef EBUSY +case EBUSY: + return tsc(u"Device or resource busy"); +#endif +#ifdef EEXIST +case EEXIST: + return tsc(u"File exists"); +#endif +#ifdef EXDEV +case EXDEV: + return tsc(u"Cross-device link"); +#endif +#ifdef ENODEV +case ENODEV: + return tsc(u"No such device"); +#endif +#ifdef ENOTDIR +case ENOTDIR: + return tsc(u"Not a directory"); +#endif +#ifdef EHOSTDOWN +case EHOSTDOWN: + return tsc(u"Host is down"); +#endif +#ifdef EINPROGRESS +case EINPROGRESS: + return tsc(u"Connection already in progress"); +#endif +#ifdef EISDIR +case EISDIR: + return tsc(u"Is a directory"); +#endif +#ifdef EINVAL +case EINVAL: + return tsc(u"Invalid argument"); +#endif +#ifdef ENETDOWN +case ENETDOWN: + return tsc(u"Network interface is not configured"); +#endif +#ifdef ENETRESET +case ENETRESET: + return tsc(u"Connection aborted by network"); +#endif +#ifdef ENFILE +case ENFILE: + return tsc(u"Too many open files in system"); +#endif +#ifdef EMFILE +case EMFILE: + return tsc(u"File descriptor value too large"); +#endif +#ifdef ENOTTY +case ENOTTY: + return tsc(u"Not a character device"); +#endif +#ifdef ETXTBSY +case ETXTBSY: + return tsc(u"Text file busy"); +#endif +#ifdef EFBIG +case EFBIG: + return tsc(u"File too large"); +#endif +#ifdef EHOSTUNREACH +case EHOSTUNREACH: + return tsc(u"Host is unreachable"); +#endif +#ifdef ENOSPC +case ENOSPC: + return tsc(u"No space left on device"); +#endif +#ifdef ENOTSUP +case ENOTSUP: + return tsc(u"Not supported"); +#endif +#ifdef ESPIPE +case ESPIPE: + return tsc(u"Illegal seek"); +#endif +#ifdef EROFS +case EROFS: + return tsc(u"Read-only file system"); +#endif +#ifdef EMLINK +case EMLINK: + return tsc(u"Too many links"); +#endif +#ifdef EPIPE +case EPIPE: + return tsc(u"Broken pipe"); +#endif +#ifdef EDOM +case EDOM: + return tsc(u"Mathematics argument out of domain of function"); +#endif +#ifdef ERANGE +case ERANGE: + return tsc(u"Result too large"); +#endif +#ifdef ENOMSG +case ENOMSG: + return tsc(u"No message of desired type"); +#endif +#ifdef EIDRM +case EIDRM: + return tsc(u"Identifier removed"); +#endif +#ifdef EILSEQ +case EILSEQ: + return tsc(u"Illegal byte sequence"); +#endif +#ifdef EDEADLK +case EDEADLK: + return tsc(u"Deadlock"); +#endif +#ifdef ENETUNREACH +case ENETUNREACH: + return tsc(u"Network is unreachable"); +#endif +#ifdef ENOLCK +case ENOLCK: + return tsc(u"No lock"); +#endif +#ifdef ENOSTR +case ENOSTR: + return tsc(u"Not a stream"); +#endif +#ifdef ETIME +case ETIME: + return tsc(u"Stream ioctl timeout"); +#endif +#ifdef ENOSR +case ENOSR: + return tsc(u"No stream resources"); +#endif +#ifdef ENONET +case ENONET: + return tsc(u"Machine is not on the network"); +#endif +#ifdef ENOPKG +case ENOPKG: + return tsc(u"No package"); +#endif +#ifdef EREMOTE +case EREMOTE: + return tsc(u"Resource is remote"); +#endif +#ifdef ENOLINK +case ENOLINK: + return tsc(u"Virtual circuit is gone"); +#endif +#ifdef EADV +case EADV: + return tsc(u"Advertise error"); +#endif +#ifdef ESRMNT +case ESRMNT: + return tsc(u"Srmount error"); +#endif +#ifdef ECOMM +case ECOMM: + return tsc(u"Communication error"); +#endif +#ifdef EPROTO +case EPROTO: + return tsc(u"Protocol error"); +#endif +#ifdef EPROTONOSUPPORT +case EPROTONOSUPPORT: + return tsc(u"Unknown protocol"); +#endif +#ifdef EMULTIHOP +case EMULTIHOP: + return tsc(u"Multihop attempted"); +#endif +#ifdef EBADMSG +case EBADMSG: + return tsc(u"Bad message"); +#endif +#ifdef ELIBACC +case ELIBACC: + return tsc(u"Cannot access a needed shared library"); +#endif +#ifdef ELIBBAD +case ELIBBAD: + return tsc(u"Accessing a corrupted shared library"); +#endif +#ifdef ELIBSCN +case ELIBSCN: + return tsc(u".lib section in a.out corrupted"); +#endif +#ifdef ELIBMAX +case ELIBMAX: + return tsc(u"Attempting to link in more shared libraries than system limit"); +#endif +#ifdef ELIBEXEC +case ELIBEXEC: + return tsc(u"Cannot exec a shared library directly"); +#endif +#ifdef ENOSYS +case ENOSYS: + return tsc(u"Function not implemented"); +#endif +#ifdef ENMFILE +case ENMFILE: + return tsc(u"No more files"); +#endif +#ifdef ENOTEMPTY +case ENOTEMPTY: + return tsc(u"Directory not empty"); +#endif +#ifdef ENAMETOOLONG +case ENAMETOOLONG: + return tsc(u"File or path name too long"); +#endif +#ifdef ELOOP +case ELOOP: + return tsc(u"Too many symbolic links"); +#endif +#ifdef ENOBUFS +case ENOBUFS: + return tsc(u"No buffer space available"); +#endif +#ifdef ENODATA +case ENODATA: + return tsc(u"No data"); +#endif +#ifdef EAFNOSUPPORT +case EAFNOSUPPORT: + return tsc(u"Address family not supported by protocol family"); +#endif +#ifdef EPROTOTYPE +case EPROTOTYPE: + return tsc(u"Protocol wrong type for socket"); +#endif +#ifdef ENOTSOCK +case ENOTSOCK: + return tsc(u"Socket operation on non-socket"); +#endif +#ifdef ENOPROTOOPT +case ENOPROTOOPT: + return tsc(u"Protocol not available"); +#endif +#ifdef ESHUTDOWN +case ESHUTDOWN: + return tsc(u"Can't send after socket shutdown"); +#endif +#ifdef ECONNREFUSED +case ECONNREFUSED: + return tsc(u"Connection refused"); +#endif +#ifdef ECONNRESET +case ECONNRESET: + return tsc(u"Connection reset by peer"); +#endif +#ifdef EADDRINUSE +case EADDRINUSE: + return tsc(u"Address already in use"); +#endif +#ifdef EADDRNOTAVAIL +case EADDRNOTAVAIL: + return tsc(u"Address not available"); +#endif +#ifdef ECONNABORTED +case ECONNABORTED: + return tsc(u"Software caused connection abort"); +#endif +#if (defined(EWOULDBLOCK) && (!defined (EAGAIN) || (EWOULDBLOCK != EAGAIN))) +case EWOULDBLOCK: + return tsc(u"Operation would block"); +#endif +#ifdef ENOTCONN +case ENOTCONN: + return tsc(u"Socket is not connected"); +#endif +#ifdef ESOCKTNOSUPPORT +case ESOCKTNOSUPPORT: + return tsc(u"Socket type not supported"); +#endif +#ifdef EISCONN +case EISCONN: + return tsc(u"Socket is already connected"); +#endif +#ifdef ECANCELED +case ECANCELED: + return tsc(u"Operation canceled"); +#endif +#ifdef ENOTRECOVERABLE +case ENOTRECOVERABLE: + return tsc(u"State not recoverable"); +#endif +#ifdef EOWNERDEAD +case EOWNERDEAD: + return tsc(u"Previous owner died"); +#endif +#ifdef ESTRPIPE +case ESTRPIPE: + return tsc(u"Streams pipe error"); +#endif +#if defined(EOPNOTSUPP) && (!defined(ENOTSUP) || (ENOTSUP != EOPNOTSUPP)) +case EOPNOTSUPP: + return tsc(u"Operation not supported on socket"); +#endif +#ifdef EOVERFLOW +case EOVERFLOW: + return tsc(u"Value too large for defined data type"); +#endif +#ifdef EMSGSIZE +case EMSGSIZE: + return tsc(u"Message too long"); +#endif +#ifdef ETIMEDOUT +case ETIMEDOUT: + return tsc(u"Connection timed out"); +#endif +default: + return tsc(u"Unknown"); +} + } + else if constexpr(std::same_as) + { +switch(errn) +{ +case 0: + return tsc(U"Success"); +#if defined (EPERM) && (!defined (EACCES) || (EPERM != EACCES)) +case EPERM: + return tsc(U"Not owner"); +#endif +#ifdef ENOENT +case ENOENT: + return tsc(U"No such file or directory"); +#endif +#ifdef ESRCH +case ESRCH: + return tsc(U"No such process"); +#endif +#ifdef EINTR +case EINTR: + return tsc(U"Interrupted system call"); +#endif +#ifdef EIO +case EIO: + return tsc(U"I/O error"); +#endif +/* go32 defines ENXIO as ENODEV */ +#if defined (ENXIO) && (!defined (ENODEV) || (ENXIO != ENODEV)) +case ENXIO: + return tsc(U"No such device or address"); +#endif +#ifdef E2BIG +case E2BIG: + return tsc(U"Arg list too long"); +#endif +#ifdef ENOEXEC +case ENOEXEC: + return tsc(U"Exec format error"); +#endif +#ifdef EALREADY +case EALREADY: + return tsc(U"Socket already connected"); +#endif +#ifdef EBADF +case EBADF: + return tsc(U"Bad file number"); +#endif +#ifdef ECHILD +case ECHILD: + return tsc(U"No children"); +#endif +#ifdef EDESTADDRREQ +case EDESTADDRREQ: + return tsc(U"Destination address required"); +#endif +#ifdef EAGAIN +case EAGAIN: + return tsc(U"No more processes"); +#endif +#ifdef ENOMEM +case ENOMEM: + return tsc(U"Not enough space"); +#endif +#ifdef EACCES +case EACCES: + return tsc(U"Permission denied"); +#endif +#ifdef EFAULT +case EFAULT: + return tsc(U"Bad address"); +#endif +#ifdef ENOTBLK +case ENOTBLK: + return tsc(U"Block device required"); +#endif +#ifdef EBUSY +case EBUSY: + return tsc(U"Device or resource busy"); +#endif +#ifdef EEXIST +case EEXIST: + return tsc(U"File exists"); +#endif +#ifdef EXDEV +case EXDEV: + return tsc(U"Cross-device link"); +#endif +#ifdef ENODEV +case ENODEV: + return tsc(U"No such device"); +#endif +#ifdef ENOTDIR +case ENOTDIR: + return tsc(U"Not a directory"); +#endif +#ifdef EHOSTDOWN +case EHOSTDOWN: + return tsc(U"Host is down"); +#endif +#ifdef EINPROGRESS +case EINPROGRESS: + return tsc(U"Connection already in progress"); +#endif +#ifdef EISDIR +case EISDIR: + return tsc(U"Is a directory"); +#endif +#ifdef EINVAL +case EINVAL: + return tsc(U"Invalid argument"); +#endif +#ifdef ENETDOWN +case ENETDOWN: + return tsc(U"Network interface is not configured"); +#endif +#ifdef ENETRESET +case ENETRESET: + return tsc(U"Connection aborted by network"); +#endif +#ifdef ENFILE +case ENFILE: + return tsc(U"Too many open files in system"); +#endif +#ifdef EMFILE +case EMFILE: + return tsc(U"File descriptor value too large"); +#endif +#ifdef ENOTTY +case ENOTTY: + return tsc(U"Not a character device"); +#endif +#ifdef ETXTBSY +case ETXTBSY: + return tsc(U"Text file busy"); +#endif +#ifdef EFBIG +case EFBIG: + return tsc(U"File too large"); +#endif +#ifdef EHOSTUNREACH +case EHOSTUNREACH: + return tsc(U"Host is unreachable"); +#endif +#ifdef ENOSPC +case ENOSPC: + return tsc(U"No space left on device"); +#endif +#ifdef ENOTSUP +case ENOTSUP: + return tsc(U"Not supported"); +#endif +#ifdef ESPIPE +case ESPIPE: + return tsc(U"Illegal seek"); +#endif +#ifdef EROFS +case EROFS: + return tsc(U"Read-only file system"); +#endif +#ifdef EMLINK +case EMLINK: + return tsc(U"Too many links"); +#endif +#ifdef EPIPE +case EPIPE: + return tsc(U"Broken pipe"); +#endif +#ifdef EDOM +case EDOM: + return tsc(U"Mathematics argument out of domain of function"); +#endif +#ifdef ERANGE +case ERANGE: + return tsc(U"Result too large"); +#endif +#ifdef ENOMSG +case ENOMSG: + return tsc(U"No message of desired type"); +#endif +#ifdef EIDRM +case EIDRM: + return tsc(U"Identifier removed"); +#endif +#ifdef EILSEQ +case EILSEQ: + return tsc(U"Illegal byte sequence"); +#endif +#ifdef EDEADLK +case EDEADLK: + return tsc(U"Deadlock"); +#endif +#ifdef ENETUNREACH +case ENETUNREACH: + return tsc(U"Network is unreachable"); +#endif +#ifdef ENOLCK +case ENOLCK: + return tsc(U"No lock"); +#endif +#ifdef ENOSTR +case ENOSTR: + return tsc(U"Not a stream"); +#endif +#ifdef ETIME +case ETIME: + return tsc(U"Stream ioctl timeout"); +#endif +#ifdef ENOSR +case ENOSR: + return tsc(U"No stream resources"); +#endif +#ifdef ENONET +case ENONET: + return tsc(U"Machine is not on the network"); +#endif +#ifdef ENOPKG +case ENOPKG: + return tsc(U"No package"); +#endif +#ifdef EREMOTE +case EREMOTE: + return tsc(U"Resource is remote"); +#endif +#ifdef ENOLINK +case ENOLINK: + return tsc(U"Virtual circuit is gone"); +#endif +#ifdef EADV +case EADV: + return tsc(U"Advertise error"); +#endif +#ifdef ESRMNT +case ESRMNT: + return tsc(U"Srmount error"); +#endif +#ifdef ECOMM +case ECOMM: + return tsc(U"Communication error"); +#endif +#ifdef EPROTO +case EPROTO: + return tsc(U"Protocol error"); +#endif +#ifdef EPROTONOSUPPORT +case EPROTONOSUPPORT: + return tsc(U"Unknown protocol"); +#endif +#ifdef EMULTIHOP +case EMULTIHOP: + return tsc(U"Multihop attempted"); +#endif +#ifdef EBADMSG +case EBADMSG: + return tsc(U"Bad message"); +#endif +#ifdef ELIBACC +case ELIBACC: + return tsc(U"Cannot access a needed shared library"); +#endif +#ifdef ELIBBAD +case ELIBBAD: + return tsc(U"Accessing a corrupted shared library"); +#endif +#ifdef ELIBSCN +case ELIBSCN: + return tsc(U".lib section in a.out corrupted"); +#endif +#ifdef ELIBMAX +case ELIBMAX: + return tsc(U"Attempting to link in more shared libraries than system limit"); +#endif +#ifdef ELIBEXEC +case ELIBEXEC: + return tsc(U"Cannot exec a shared library directly"); +#endif +#ifdef ENOSYS +case ENOSYS: + return tsc(U"Function not implemented"); +#endif +#ifdef ENMFILE +case ENMFILE: + return tsc(U"No more files"); +#endif +#ifdef ENOTEMPTY +case ENOTEMPTY: + return tsc(U"Directory not empty"); +#endif +#ifdef ENAMETOOLONG +case ENAMETOOLONG: + return tsc(U"File or path name too long"); +#endif +#ifdef ELOOP +case ELOOP: + return tsc(U"Too many symbolic links"); +#endif +#ifdef ENOBUFS +case ENOBUFS: + return tsc(U"No buffer space available"); +#endif +#ifdef ENODATA +case ENODATA: + return tsc(U"No data"); +#endif +#ifdef EAFNOSUPPORT +case EAFNOSUPPORT: + return tsc(U"Address family not supported by protocol family"); +#endif +#ifdef EPROTOTYPE +case EPROTOTYPE: + return tsc(U"Protocol wrong type for socket"); +#endif +#ifdef ENOTSOCK +case ENOTSOCK: + return tsc(U"Socket operation on non-socket"); +#endif +#ifdef ENOPROTOOPT +case ENOPROTOOPT: + return tsc(U"Protocol not available"); +#endif +#ifdef ESHUTDOWN +case ESHUTDOWN: + return tsc(U"Can't send after socket shutdown"); +#endif +#ifdef ECONNREFUSED +case ECONNREFUSED: + return tsc(U"Connection refused"); +#endif +#ifdef ECONNRESET +case ECONNRESET: + return tsc(U"Connection reset by peer"); +#endif +#ifdef EADDRINUSE +case EADDRINUSE: + return tsc(U"Address already in use"); +#endif +#ifdef EADDRNOTAVAIL +case EADDRNOTAVAIL: + return tsc(U"Address not available"); +#endif +#ifdef ECONNABORTED +case ECONNABORTED: + return tsc(U"Software caused connection abort"); +#endif +#if (defined(EWOULDBLOCK) && (!defined (EAGAIN) || (EWOULDBLOCK != EAGAIN))) +case EWOULDBLOCK: + return tsc(U"Operation would block"); +#endif +#ifdef ENOTCONN +case ENOTCONN: + return tsc(U"Socket is not connected"); +#endif +#ifdef ESOCKTNOSUPPORT +case ESOCKTNOSUPPORT: + return tsc(U"Socket type not supported"); +#endif +#ifdef EISCONN +case EISCONN: + return tsc(U"Socket is already connected"); +#endif +#ifdef ECANCELED +case ECANCELED: + return tsc(U"Operation canceled"); +#endif +#ifdef ENOTRECOVERABLE +case ENOTRECOVERABLE: + return tsc(U"State not recoverable"); +#endif +#ifdef EOWNERDEAD +case EOWNERDEAD: + return tsc(U"Previous owner died"); +#endif +#ifdef ESTRPIPE +case ESTRPIPE: + return tsc(U"Streams pipe error"); +#endif +#if defined(EOPNOTSUPP) && (!defined(ENOTSUP) || (ENOTSUP != EOPNOTSUPP)) +case EOPNOTSUPP: + return tsc(U"Operation not supported on socket"); +#endif +#ifdef EOVERFLOW +case EOVERFLOW: + return tsc(U"Value too large for defined data type"); +#endif +#ifdef EMSGSIZE +case EMSGSIZE: + return tsc(U"Message too long"); +#endif +#ifdef ETIMEDOUT +case ETIMEDOUT: + return tsc(U"Connection timed out"); +#endif +default: + return tsc(U"Unknown"); +} + } + else + { +switch(errn) +{ +case 0: + return tsc(u8"Success"); +#if defined (EPERM) && (!defined (EACCES) || (EPERM != EACCES)) +case EPERM: + return tsc(u8"Not owner"); +#endif +#ifdef ENOENT +case ENOENT: + return tsc(u8"No such file or directory"); +#endif +#ifdef ESRCH +case ESRCH: + return tsc(u8"No such process"); +#endif +#ifdef EINTR +case EINTR: + return tsc(u8"Interrupted system call"); +#endif +#ifdef EIO +case EIO: + return tsc(u8"I/O error"); +#endif +/* go32 defines ENXIO as ENODEV */ +#if defined (ENXIO) && (!defined (ENODEV) || (ENXIO != ENODEV)) +case ENXIO: + return tsc(u8"No such device or address"); +#endif +#ifdef E2BIG +case E2BIG: + return tsc(u8"Arg list too long"); +#endif +#ifdef ENOEXEC +case ENOEXEC: + return tsc(u8"Exec format error"); +#endif +#ifdef EALREADY +case EALREADY: + return tsc(u8"Socket already connected"); +#endif +#ifdef EBADF +case EBADF: + return tsc(u8"Bad file number"); +#endif +#ifdef ECHILD +case ECHILD: + return tsc(u8"No children"); +#endif +#ifdef EDESTADDRREQ +case EDESTADDRREQ: + return tsc(u8"Destination address required"); +#endif +#ifdef EAGAIN +case EAGAIN: + return tsc(u8"No more processes"); +#endif +#ifdef ENOMEM +case ENOMEM: + return tsc(u8"Not enough space"); +#endif +#ifdef EACCES +case EACCES: + return tsc(u8"Permission denied"); +#endif +#ifdef EFAULT +case EFAULT: + return tsc(u8"Bad address"); +#endif +#ifdef ENOTBLK +case ENOTBLK: + return tsc(u8"Block device required"); +#endif +#ifdef EBUSY +case EBUSY: + return tsc(u8"Device or resource busy"); +#endif +#ifdef EEXIST +case EEXIST: + return tsc(u8"File exists"); +#endif +#ifdef EXDEV +case EXDEV: + return tsc(u8"Cross-device link"); +#endif +#ifdef ENODEV +case ENODEV: + return tsc(u8"No such device"); +#endif +#ifdef ENOTDIR +case ENOTDIR: + return tsc(u8"Not a directory"); +#endif +#ifdef EHOSTDOWN +case EHOSTDOWN: + return tsc(u8"Host is down"); +#endif +#ifdef EINPROGRESS +case EINPROGRESS: + return tsc(u8"Connection already in progress"); +#endif +#ifdef EISDIR +case EISDIR: + return tsc(u8"Is a directory"); +#endif +#ifdef EINVAL +case EINVAL: + return tsc(u8"Invalid argument"); +#endif +#ifdef ENETDOWN +case ENETDOWN: + return tsc(u8"Network interface is not configured"); +#endif +#ifdef ENETRESET +case ENETRESET: + return tsc(u8"Connection aborted by network"); +#endif +#ifdef ENFILE +case ENFILE: + return tsc(u8"Too many open files in system"); +#endif +#ifdef EMFILE +case EMFILE: + return tsc(u8"File descriptor value too large"); +#endif +#ifdef ENOTTY +case ENOTTY: + return tsc(u8"Not a character device"); +#endif +#ifdef ETXTBSY +case ETXTBSY: + return tsc(u8"Text file busy"); +#endif +#ifdef EFBIG +case EFBIG: + return tsc(u8"File too large"); +#endif +#ifdef EHOSTUNREACH +case EHOSTUNREACH: + return tsc(u8"Host is unreachable"); +#endif +#ifdef ENOSPC +case ENOSPC: + return tsc(u8"No space left on device"); +#endif +#ifdef ENOTSUP +case ENOTSUP: + return tsc(u8"Not supported"); +#endif +#ifdef ESPIPE +case ESPIPE: + return tsc(u8"Illegal seek"); +#endif +#ifdef EROFS +case EROFS: + return tsc(u8"Read-only file system"); +#endif +#ifdef EMLINK +case EMLINK: + return tsc(u8"Too many links"); +#endif +#ifdef EPIPE +case EPIPE: + return tsc(u8"Broken pipe"); +#endif +#ifdef EDOM +case EDOM: + return tsc(u8"Mathematics argument out of domain of function"); +#endif +#ifdef ERANGE +case ERANGE: + return tsc(u8"Result too large"); +#endif +#ifdef ENOMSG +case ENOMSG: + return tsc(u8"No message of desired type"); +#endif +#ifdef EIDRM +case EIDRM: + return tsc(u8"Identifier removed"); +#endif +#ifdef EILSEQ +case EILSEQ: + return tsc(u8"Illegal byte sequence"); +#endif +#ifdef EDEADLK +case EDEADLK: + return tsc(u8"Deadlock"); +#endif +#ifdef ENETUNREACH +case ENETUNREACH: + return tsc(u8"Network is unreachable"); +#endif +#ifdef ENOLCK +case ENOLCK: + return tsc(u8"No lock"); +#endif +#ifdef ENOSTR +case ENOSTR: + return tsc(u8"Not a stream"); +#endif +#ifdef ETIME +case ETIME: + return tsc(u8"Stream ioctl timeout"); +#endif +#ifdef ENOSR +case ENOSR: + return tsc(u8"No stream resources"); +#endif +#ifdef ENONET +case ENONET: + return tsc(u8"Machine is not on the network"); +#endif +#ifdef ENOPKG +case ENOPKG: + return tsc(u8"No package"); +#endif +#ifdef EREMOTE +case EREMOTE: + return tsc(u8"Resource is remote"); +#endif +#ifdef ENOLINK +case ENOLINK: + return tsc(u8"Virtual circuit is gone"); +#endif +#ifdef EADV +case EADV: + return tsc(u8"Advertise error"); +#endif +#ifdef ESRMNT +case ESRMNT: + return tsc(u8"Srmount error"); +#endif +#ifdef ECOMM +case ECOMM: + return tsc(u8"Communication error"); +#endif +#ifdef EPROTO +case EPROTO: + return tsc(u8"Protocol error"); +#endif +#ifdef EPROTONOSUPPORT +case EPROTONOSUPPORT: + return tsc(u8"Unknown protocol"); +#endif +#ifdef EMULTIHOP +case EMULTIHOP: + return tsc(u8"Multihop attempted"); +#endif +#ifdef EBADMSG +case EBADMSG: + return tsc(u8"Bad message"); +#endif +#ifdef ELIBACC +case ELIBACC: + return tsc(u8"Cannot access a needed shared library"); +#endif +#ifdef ELIBBAD +case ELIBBAD: + return tsc(u8"Accessing a corrupted shared library"); +#endif +#ifdef ELIBSCN +case ELIBSCN: + return tsc(u8".lib section in a.out corrupted"); +#endif +#ifdef ELIBMAX +case ELIBMAX: + return tsc(u8"Attempting to link in more shared libraries than system limit"); +#endif +#ifdef ELIBEXEC +case ELIBEXEC: + return tsc(u8"Cannot exec a shared library directly"); +#endif +#ifdef ENOSYS +case ENOSYS: + return tsc(u8"Function not implemented"); +#endif +#ifdef ENMFILE +case ENMFILE: + return tsc(u8"No more files"); +#endif +#ifdef ENOTEMPTY +case ENOTEMPTY: + return tsc(u8"Directory not empty"); +#endif +#ifdef ENAMETOOLONG +case ENAMETOOLONG: + return tsc(u8"File or path name too long"); +#endif +#ifdef ELOOP +case ELOOP: + return tsc(u8"Too many symbolic links"); +#endif +#ifdef ENOBUFS +case ENOBUFS: + return tsc(u8"No buffer space available"); +#endif +#ifdef ENODATA +case ENODATA: + return tsc(u8"No data"); +#endif +#ifdef EAFNOSUPPORT +case EAFNOSUPPORT: + return tsc(u8"Address family not supported by protocol family"); +#endif +#ifdef EPROTOTYPE +case EPROTOTYPE: + return tsc(u8"Protocol wrong type for socket"); +#endif +#ifdef ENOTSOCK +case ENOTSOCK: + return tsc(u8"Socket operation on non-socket"); +#endif +#ifdef ENOPROTOOPT +case ENOPROTOOPT: + return tsc(u8"Protocol not available"); +#endif +#ifdef ESHUTDOWN +case ESHUTDOWN: + return tsc(u8"Can't send after socket shutdown"); +#endif +#ifdef ECONNREFUSED +case ECONNREFUSED: + return tsc(u8"Connection refused"); +#endif +#ifdef ECONNRESET +case ECONNRESET: + return tsc(u8"Connection reset by peer"); +#endif +#ifdef EADDRINUSE +case EADDRINUSE: + return tsc(u8"Address already in use"); +#endif +#ifdef EADDRNOTAVAIL +case EADDRNOTAVAIL: + return tsc(u8"Address not available"); +#endif +#ifdef ECONNABORTED +case ECONNABORTED: + return tsc(u8"Software caused connection abort"); +#endif +#if (defined(EWOULDBLOCK) && (!defined (EAGAIN) || (EWOULDBLOCK != EAGAIN))) +case EWOULDBLOCK: + return tsc(u8"Operation would block"); +#endif +#ifdef ENOTCONN +case ENOTCONN: + return tsc(u8"Socket is not connected"); +#endif +#ifdef ESOCKTNOSUPPORT +case ESOCKTNOSUPPORT: + return tsc(u8"Socket type not supported"); +#endif +#ifdef EISCONN +case EISCONN: + return tsc(u8"Socket is already connected"); +#endif +#ifdef ECANCELED +case ECANCELED: + return tsc(u8"Operation canceled"); +#endif +#ifdef ENOTRECOVERABLE +case ENOTRECOVERABLE: + return tsc(u8"State not recoverable"); +#endif +#ifdef EOWNERDEAD +case EOWNERDEAD: + return tsc(u8"Previous owner died"); +#endif +#ifdef ESTRPIPE +case ESTRPIPE: + return tsc(u8"Streams pipe error"); +#endif +#if defined(EOPNOTSUPP) && (!defined(ENOTSUP) || (ENOTSUP != EOPNOTSUPP)) +case EOPNOTSUPP: + return tsc(u8"Operation not supported on socket"); +#endif +#ifdef EOVERFLOW +case EOVERFLOW: + return tsc(u8"Value too large for defined data type"); +#endif +#ifdef EMSGSIZE +case EMSGSIZE: + return tsc(u8"Message too long"); +#endif +#ifdef ETIMEDOUT +case ETIMEDOUT: + return tsc(u8"Connection timed out"); +#endif +default: + return tsc(u8"Unknown"); +} + } \ No newline at end of file diff --git a/src/fast_io/include/fast_io_hosted/posix_error_scatter/impl.h b/src/fast_io/include/fast_io_hosted/posix_error_scatter/impl.h new file mode 100644 index 0000000..4f355cd --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/posix_error_scatter/impl.h @@ -0,0 +1,43 @@ +#pragma once + +namespace fast_io +{ +/* +Unfortunately, strerror is not thread-safe and strerror_r is not guaranteed to be available on all platforms. +BTW. I wouldn't say I like the idea this can be affected by locale. Locale is trash. +The libc implementation will also make it fail to work under the EBCDIC execution charset. +Even libstdc++ is doing the wrong thing here. I believe this is a severe CVE vulnerability. +https://github.com/gcc-mirror/gcc/blob/16e2427f50c208dfe07d07f18009969502c25dc8/libstdc%2B%2B-v3/src/c%2B%2B11/system_error.cc#L51 +We use the same strerror strings in GNU newlib since newlib is the standard in OS kernel, and the linker will remove the same string literals. + +*/ + +namespace details::tsc_namespace +{ +template +inline constexpr basic_io_scatter_t tsc(char_type const (&a)[N]) noexcept +{ + return {a,N-1}; +} +} + +template +inline constexpr basic_io_scatter_t get_posix_errno_scatter([[maybe_unused]] int errn) noexcept +{ +/* +Referenced from GNU newlib +https://github.com/bminor/newlib/blob/ea275093c179fea636470173509615eb6bddad0f/newlib/libc/string/strerror.c +*/ + using namespace details::tsc_namespace; +#if __has_include() +#if defined(__AVR__) +#include"avr.h" +#else +#include"generic.h" +#endif +#else +#include"unknown.h" +#endif +} + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_hosted/posix_error_scatter/unknown.h b/src/fast_io/include/fast_io_hosted/posix_error_scatter/unknown.h new file mode 100644 index 0000000..cc344d5 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/posix_error_scatter/unknown.h @@ -0,0 +1,20 @@ + if constexpr(std::same_as) + { + return tsc("Unknown"); + } + else if constexpr(std::same_as) + { + return tsc(L"Unknown"); + } + else if constexpr(std::same_as) + { + return tsc(u"Unknown"); + } + else if constexpr(std::same_as) + { + return tsc(U"Unknown"); + } + else + { + return tsc(u8"Unknown"); + } \ No newline at end of file diff --git a/src/fast_io/include/fast_io_hosted/posix_status.h b/src/fast_io/include/fast_io_hosted/posix_status.h new file mode 100644 index 0000000..be64b51 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/posix_status.h @@ -0,0 +1,264 @@ +#pragma once + +namespace fast_io +{ + +/* +Referenced from man on Linux +*/ + +struct posix_file_status +{ + std::uintmax_t dev; // ID of device containing file + std::uintmax_t ino; // Inode number + perms perm; + file_type type; + std::uintmax_t nlink; // Number of hard links + std::uintmax_t uid; // User ID of owner + std::uintmax_t gid; // Group ID of owner + std::uintmax_t rdev; // Device ID (if special file) + std::uintmax_t size; // Total size, in bytes + std::uintmax_t blksize; // Block size for filesystem I/O + std::uintmax_t blocks; // Number of 512B blocks allocated + + /* Since Linux 2.6, the kernel supports nanosecond + precision for the following timestamp fields. + For the details before Linux 2.6, see NOTES. */ + unix_timestamp atim; // Time of last access + unix_timestamp mtim; // Time of last modification + unix_timestamp ctim; // Time of last status change + unix_timestamp btim; // Time of file creation + std::uintmax_t flags; // user defined flags for file + std::uintmax_t gen; // file generation number +}; + +template +inline constexpr std::size_t print_reserve_size(io_reserve_type_t) +{ + constexpr std::size_t res{ + print_reserve_size(io_reserve_type)*11+ + sizeof(u8"dev:")+sizeof(u8"\nino:")+sizeof(u8"\nperm:")+sizeof(u8"\ntype:")+ + sizeof(u8"\nnlink:")+sizeof(u8"\nuid:")+sizeof(u8"\ngid:")+sizeof(u8"\nrdev:")+ + sizeof(u8"\nsize:")+sizeof(u8"\nblksize:")+sizeof(u8"\nblocks:")+sizeof(u8"\natim:")+ + sizeof(u8"\nmtim:")+sizeof(u8"\nctim:")+sizeof(u8"\nbtim:")+sizeof(u8"\nflags:")+sizeof(u8"\ngen:")-16+ + print_reserve_size(io_reserve_type)+ + print_reserve_size(io_reserve_type)+ + print_reserve_size(io_reserve_type)*4}; + return res; +} + +namespace details +{ +template +inline constexpr char_type* print_file_status_impl(char_type* iter,fast_io::posix_file_status const& status) +{ + if constexpr(std::same_as) + { + iter=details::copy_string_literal("dev:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.dev); + iter=details::copy_string_literal("\nino:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.ino); + iter=details::copy_string_literal("\nperm:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.perm); + iter=details::copy_string_literal("\ntype:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.type); + iter=details::copy_string_literal("\nnlink:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.nlink); + iter=details::copy_string_literal("\nuid:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.uid); + iter=details::copy_string_literal("\ngid:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.gid); + iter=details::copy_string_literal("\nrdev:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.rdev); + iter=details::copy_string_literal("\nsize:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.size); + iter=details::copy_string_literal("\nblksize:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.blksize); + iter=details::copy_string_literal("\nblocks:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.blocks); + + + iter=details::copy_string_literal("\natim:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.atim); + iter=details::copy_string_literal("\nmtim:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.mtim); + iter=details::copy_string_literal("\nctim:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.ctim); + iter=details::copy_string_literal("\nbtim:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.btim); + + iter=details::copy_string_literal("\nflags:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.flags); + iter=details::copy_string_literal("\ngen:",iter); + return print_reserve_define(io_reserve_type,iter,status.gen); + } + else if constexpr(std::same_as) + { + iter=details::copy_string_literal(L"dev:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.dev); + iter=details::copy_string_literal(L"\nino:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.ino); + iter=details::copy_string_literal(L"\nperm:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.perm); + iter=details::copy_string_literal(L"\ntype:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.type); + iter=details::copy_string_literal(L"\nnlink:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.nlink); + iter=details::copy_string_literal(L"\nuid:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.uid); + iter=details::copy_string_literal(L"\ngid:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.gid); + iter=details::copy_string_literal(L"\nrdev:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.rdev); + iter=details::copy_string_literal(L"\nsize:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.size); + iter=details::copy_string_literal(L"\nblksize:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.blksize); + iter=details::copy_string_literal(L"\nblocks:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.blocks); + + + iter=details::copy_string_literal(L"\natim:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.atim); + iter=details::copy_string_literal(L"\nmtim:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.mtim); + iter=details::copy_string_literal(L"\nctim:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.ctim); + iter=details::copy_string_literal(L"\nbtim:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.btim); + + iter=details::copy_string_literal(L"\nflags:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.flags); + iter=details::copy_string_literal(L"\ngen:",iter); + return print_reserve_define(io_reserve_type,iter,status.gen); + } + else if constexpr(std::same_as) + { + iter=details::copy_string_literal(u"dev:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.dev); + iter=details::copy_string_literal(u"\nino:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.ino); + iter=details::copy_string_literal(u"\nperm:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.perm); + iter=details::copy_string_literal(u"\ntype:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.type); + iter=details::copy_string_literal(u"\nnlink:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.nlink); + iter=details::copy_string_literal(u"\nuid:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.uid); + iter=details::copy_string_literal(u"\ngid:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.gid); + iter=details::copy_string_literal(u"\nrdev:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.rdev); + iter=details::copy_string_literal(u"\nsize:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.size); + iter=details::copy_string_literal(u"\nblksize:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.blksize); + iter=details::copy_string_literal(u"\nblocks:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.blocks); + + + iter=details::copy_string_literal(u"\natim:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.atim); + iter=details::copy_string_literal(u"\nmtim:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.mtim); + iter=details::copy_string_literal(u"\nctim:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.ctim); + iter=details::copy_string_literal(u"\nbtim:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.btim); + + iter=details::copy_string_literal(u"\nflags:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.flags); + iter=details::copy_string_literal(u"\ngen:",iter); + return print_reserve_define(io_reserve_type,iter,status.gen); + } + else if constexpr(std::same_as) + { + iter=details::copy_string_literal(U"dev:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.dev); + iter=details::copy_string_literal(U"\nino:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.ino); + iter=details::copy_string_literal(U"\nperm:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.perm); + iter=details::copy_string_literal(U"\ntype:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.type); + iter=details::copy_string_literal(U"\nnlink:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.nlink); + iter=details::copy_string_literal(U"\nuid:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.uid); + iter=details::copy_string_literal(U"\ngid:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.gid); + iter=details::copy_string_literal(U"\nrdev:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.rdev); + iter=details::copy_string_literal(U"\nsize:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.size); + iter=details::copy_string_literal(U"\nblksize:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.blksize); + iter=details::copy_string_literal(U"\nblocks:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.blocks); + + + iter=details::copy_string_literal(U"\natim:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.atim); + iter=details::copy_string_literal(U"\nmtim:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.mtim); + iter=details::copy_string_literal(U"\nctim:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.ctim); + iter=details::copy_string_literal(U"\nbtim:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.btim); + + iter=details::copy_string_literal(U"\nflags:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.flags); + iter=details::copy_string_literal(U"\ngen:",iter); + return print_reserve_define(io_reserve_type,iter,status.gen); + } + else + { + iter=details::copy_string_literal(u8"dev:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.dev); + iter=details::copy_string_literal(u8"\nino:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.ino); + iter=details::copy_string_literal(u8"\nperm:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.perm); + iter=details::copy_string_literal(u8"\ntype:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.type); + iter=details::copy_string_literal(u8"\nnlink:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.nlink); + iter=details::copy_string_literal(u8"\nuid:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.uid); + iter=details::copy_string_literal(u8"\ngid:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.gid); + iter=details::copy_string_literal(u8"\nrdev:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.rdev); + iter=details::copy_string_literal(u8"\nsize:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.size); + iter=details::copy_string_literal(u8"\nblksize:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.blksize); + iter=details::copy_string_literal(u8"\nblocks:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.blocks); + + + iter=details::copy_string_literal(u8"\natim:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.atim); + iter=details::copy_string_literal(u8"\nmtim:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.mtim); + iter=details::copy_string_literal(u8"\nctim:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.ctim); + iter=details::copy_string_literal(u8"\nbtim:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.btim); + + iter=details::copy_string_literal(u8"\nflags:",iter); + iter=print_reserve_define(io_reserve_type,iter,status.flags); + iter=details::copy_string_literal(u8"\ngen:",iter); + return print_reserve_define(io_reserve_type,iter,status.gen); + } +} +} + +template +inline constexpr char_type* print_reserve_define(io_reserve_type_t, char_type* iter,fast_io::posix_file_status const& status) +{ + return details::print_file_status_impl(iter,status); +} + +} diff --git a/src/fast_io/include/fast_io_hosted/process_revamp/native.h b/src/fast_io/include/fast_io_hosted/process_revamp/native.h new file mode 100644 index 0000000..8810359 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/process_revamp/native.h @@ -0,0 +1,12 @@ +#pragma once + +#if !defined(__MSDOS__) && !defined(__NEWLIB__) && !defined(__wasi__) && !defined(_PICOLIBC__) + +#if defined(_WIN32) +#include"nt.h" +#elif __has_include() +#include +#include"posix.h" +#endif +#endif + diff --git a/src/fast_io/include/fast_io_hosted/process_revamp/nt.h b/src/fast_io/include/fast_io_hosted/process_revamp/nt.h new file mode 100644 index 0000000..82f6d3e --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/process_revamp/nt.h @@ -0,0 +1,353 @@ +#pragma once + +namespace fast_io +{ + +struct nt_user_process_information +{ + void* hprocess{}; + void* hthread{}; +}; + +namespace win32::nt::details +{ +template +inline void close_nt_user_process_information_not_null(nt_user_process_information* hnt_user_process_info) noexcept +{ + if(hnt_user_process_info->hthread)[[likely]] + { + win32::nt::nt_close(hnt_user_process_info->hthread); + hnt_user_process_info->hthread=nullptr; + } + if(hnt_user_process_info->hprocess)[[likely]] + { + win32::nt::nt_close(hnt_user_process_info->hprocess); + hnt_user_process_info->hprocess=nullptr; + } + delete hnt_user_process_info; +} +template +inline void close_nt_user_process_information(nt_user_process_information* hnt_user_process_info) noexcept +{ + if(hnt_user_process_info)[[likely]] + return details::close_nt_user_process_information_not_null(hnt_user_process_info); +} +template +inline std::uint_least32_t nt_wait_user_process_or_thread(void* hprocess_thread) noexcept +{ + return win32::nt::nt_wait_for_single_object(hprocess_thread,false,nullptr); +} + +template +inline void nt_wait_and_close_user_process_or_thread(void*& handle) noexcept(!throw_eh) +{ + if(handle==nullptr) + return; + auto status{nt_wait_user_process_or_thread(handle)}; + auto status2{win32::nt::nt_close(handle)}; + handle=nullptr; + if constexpr(throw_eh) + { + if(status) + throw_nt_error(status); + if(status2) + throw_nt_error(status2); + } +} + +template +inline void close_nt_user_process_information_and_wait(nt_user_process_information* hnt_user_process_info) noexcept(!throw_eh) +{ + if(hnt_user_process_info)[[likely]] + { + nt_wait_and_close_user_process_or_thread(hnt_user_process_info->hthread); + nt_wait_and_close_user_process_or_thread(hnt_user_process_info->hprocess); + delete hnt_user_process_info; + } +} + +template +inline void nt_duplicate_object_std(void* parent_process,void*& standard_io_handle,void* process_handle) +{ + if(standard_io_handle==nullptr) + return; + check_nt_status(nt_duplicate_object(parent_process,standard_io_handle,process_handle,__builtin_addressof(standard_io_handle),0,0,0x00000002|0x00000004)); +} + +inline void check_nt_status(std::uint_least32_t status) +{ + if(status) + throw_nt_error(status); +} + +template +inline void* nt_duplicate_process_std_handle_impl(void* __restrict hprocess,win32_io_redirection const& redi) +{ + void* const current_process{}; + void* ptr{}; + if(redi.win32_handle)[[likely]] + { + check_nt_status(nt_duplicate_object(hprocess,current_process,redi.win32_handle,__builtin_addressof(ptr),0,0, + /*DUPLICATE_SAME_ACCESS|DUPLICATE_SAME_ATTRIBUTES*/0x00000004|0x00000002)); + } + return ptr; +} + +template +inline void nt_duplicate_process_std_handles_impl(void* __restrict hprocess,win32_process_io const& processio,rtl_user_process_parameters& para) +{ + para.StandardInput=nt_duplicate_process_std_handle_impl(hprocess,processio.in); + para.StandardOutput=nt_duplicate_process_std_handle_impl(hprocess,processio.out); + para.StandardError=nt_duplicate_process_std_handle_impl(hprocess,processio.err); +} + +/* +Referenced from ReactOS +https://doxygen.reactos.org/d3/d4d/sdk_2lib_2rtl_2process_8c.html +*/ + +struct +#if __has_cpp_attribute(clang::trivially_relocatable) +[[clang::trivially_relocatable]] +#endif +nt_user_process_information_scoped_ptr +{ + nt_user_process_information* ptr{}; + constexpr nt_user_process_information_scoped_ptr()=default; + explicit constexpr nt_user_process_information_scoped_ptr(nt_user_process_information* p):ptr(p){} + nt_user_process_information_scoped_ptr(nt_user_process_information_scoped_ptr const&)=delete; + nt_user_process_information_scoped_ptr& operator=(nt_user_process_information_scoped_ptr const&)=delete; + inline constexpr nt_user_process_information& operator*() noexcept + { + return *ptr; + } + inline constexpr nt_user_process_information const& operator*() const noexcept + { + return *ptr; + } + inline constexpr nt_user_process_information* release() noexcept + { + auto temp{ptr}; + ptr=nullptr; + return temp; + } + constexpr ~nt_user_process_information_scoped_ptr() + { + delete ptr; + } +}; + +template +inline nt_user_process_information* nt_process_create_impl(void* __restrict fhandle,win32_process_io const& processio) +{ + constexpr bool zw{family==nt_family::zw}; + nt_user_process_information_scoped_ptr uptr(new nt_user_process_information); + void* hsection{}; + check_nt_status(nt_create_section(__builtin_addressof(hsection),0xf001f /*SECTION_ALL_ACCESS*/, + nullptr,nullptr,0x02 /*PAGE_READONLY*/,0x1000000 /*SEC_IMAGE*/,fhandle)); + basic_nt_family_file section(hsection); + void* const current_process{reinterpret_cast(static_cast(-1))}; + void* hprocess{}; + check_nt_status(nt_create_process(__builtin_addressof(hprocess),0x000F0000U|0x00100000U|0xFFF + /*PROCESS_ALL_ACCESS==(STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFF)*/, + nullptr,current_process,true,hsection,nullptr,nullptr)); +// println_freestanding(fast_io::win32_stdout(),std::source_location::current()); + basic_nt_family_file process(hprocess); + process_basic_information pb_info{}; + check_nt_status(nt_query_information_process(hprocess,process_information_class::ProcessBasicInformation, + __builtin_addressof(pb_info),sizeof(pb_info),nullptr)); + +// println_freestanding(fast_io::win32_stdout(),std::source_location::current()); + section_image_information sec_info{}; + check_nt_status(nt_query_section(hsection,section_information_class::SectionImageInformation, + __builtin_addressof(sec_info),sizeof(sec_info),nullptr)); + + rtl_user_process_parameters rtl_up{}; + nt_duplicate_process_std_handles_impl(hprocess,processio,rtl_up); +// check_nt_status(RtlpInitEnvironment(hprocess,pb_info.PebBaseAddress,__builtin_addressof(rtl_up))); +// println_freestanding(fast_io::win32_stdout(),std::source_location::current()); + void* hthread{}; + client_id cid{}; +// println_freestanding(fast_io::win32_stdout(),std::source_location::current()); + check_nt_status(RtlCreateUserThread(hprocess,nullptr,true,sec_info.ZeroBits,sec_info.MaximumStackSize, + sec_info.CommittedStackSize,sec_info.TransferAddress,pb_info.PebBaseAddress,__builtin_addressof(hthread),__builtin_addressof(cid))); + basic_nt_family_file thread(hthread); +// println_freestanding(fast_io::win32_stdout(),std::source_location::current()," ",cid.hprocess," ",cid.hthread); + std::uint_least32_t lprevcount{}; + check_nt_status(nt_resume_thread(hthread,__builtin_addressof(lprevcount))); +// println_freestanding(fast_io::win32_stdout(),std::source_location::current()," ",lprevcount); + *uptr={process.release(),thread.release()}; + return uptr.release(); +} + +template +inline nt_user_process_information* nt_create_process_overloads(nt_at_entry entry,path_type const& filename,win32_process_io const& processio) +{ + basic_nt_family_file nf(entry,filename,open_mode::in|open_mode::excl); + return nt_process_create_impl(nf.handle,processio); +} + +template +inline nt_user_process_information* nt_create_process_overloads(path_type const& filename,win32_process_io const& processio) +{ + basic_nt_family_file nf(filename,open_mode::in|open_mode::excl); + return nt_process_create_impl(nf.handle,processio); +} + +template +inline nt_user_process_information* nt_create_process_overloads(::fast_io::nt_fs_dirent ent,win32_process_io const& processio) +{ + basic_nt_family_file nf(ent,open_mode::in|open_mode::excl); + return nt_process_create_impl(nf.handle,processio); +} + +} + +template +requires (family==nt_family::nt||family==nt_family::zw) +class nt_family_process_observer +{ +public: + using native_handle_type = nt_user_process_information*; + native_handle_type hnt_user_process_info{}; + constexpr auto& native_handle() noexcept + { + return hnt_user_process_info; + } + constexpr auto& native_handle() const noexcept + { + return hnt_user_process_info; + } + explicit constexpr operator bool() const noexcept + { + return hnt_user_process_info; + } + inline constexpr native_handle_type release() noexcept + { + auto temp{hnt_user_process_info}; + hnt_user_process_info={}; + return temp; + } +}; + +template +inline void detach(nt_family_process_observer& ppob) noexcept +{ + win32::nt::details::close_nt_user_process_information(ppob.hnt_user_process_info); + ppob.hnt_user_process_info=nullptr; +} +#if 0 +struct nt_wait_status +{ + std::uint_least32_t exit_code{}; +}; + +inline nt_wait_status query_process_basic_info(nt_process_observer ppob) +{ + +} + +inline nt_wait_status wait(nt_process_observer ppob) +{ + if(handle==nullptr) + throw_nt_status(0xC0000008); + win32::nt::details_wait_and_close_user_process_or_thread(ppob.hnt_user_process_info->hthread); + auto& hprocess=ppob.hnt_user_process_info->hprocess; + auto status{nt_wait_user_process_or_thread(hprocess)}; + + auto status2{win32::nt::nt_close(hprocess)}; + + hprocess=nullptr; + if constexpr(throw_eh) + { + if(status) + throw_nt_error(status); + if(status2) + throw_nt_error(status2); + } +} +#endif + + +#if 0 +struct nt_process_args +{ + char const* const* args{}; + bool is_dynamic_allocated{}; + inline constexpr nt_process_args(char const* const* envir) noexcept:args(envir){} + template<::std::random_access_iterator Iter> + requires (std::convertible_to<::std::iter_value_t,char const*>||requires(::std::iter_value_t v) + { + {v.c_str()}->std::convertible_to; + }) + inline constexpr nt_process_args(Iter begin,Iter end): + args(details::dup_enviro_entry(begin,end)),is_dynamic_allocated(true) + {} + template + requires (std::convertible_to,char const*>||requires(std::ranges::range_value_t v) + { + {v.c_str()}->std::convertible_to; + }) + inline constexpr nt_process_args(range&& rg):nt_process_args(std::ranges::cbegin(rg),std::ranges::cend(rg)) + {} + inline constexpr nt_process_args(std::initializer_list ilist): + nt_process_args(ilist.begin(),ilist.end()){} + nt_process_args(nt_process_args const&)=delete; + nt_process_args& operator=(nt_process_args const&)=delete; +#if __cpp_constexpr_dynamic_alloc >= 201907L + inline constexpr +#endif + ~nt_process_args() + { + if(is_dynamic_allocated) + delete[] args; + } +}; +#endif + +template +class nt_family_process:public nt_family_process_observer +{ +public: + using native_handle_type = nt_user_process_information*; + constexpr nt_family_process() noexcept = default; + template + requires std::same_as> + explicit constexpr nt_family_process(native_hd hd) noexcept:nt_family_process_observer{hd}{} + + template<::fast_io::constructible_to_os_c_str path_type> + explicit nt_family_process(nt_at_entry nate,path_type const& filename,win32_process_io const& processio): + nt_family_process_observer{win32::nt::details::nt_create_process_overloads(nate,filename,processio)} + {} + + template<::fast_io::constructible_to_os_c_str path_type> + explicit nt_family_process(path_type const& filename,win32_process_io const& processio): + nt_family_process_observer{win32::nt::details::nt_create_process_overloads(filename,processio)} + {} + + explicit nt_family_process(::fast_io::nt_fs_dirent ent,win32_process_io const& processio): + nt_family_process_observer{win32::nt::details::nt_create_process_overloads(ent,processio)} + {} + + nt_family_process(nt_family_process const& b)=delete; + nt_family_process& operator=(nt_family_process const& b)=delete; + constexpr nt_family_process(nt_family_process&& __restrict b) noexcept:nt_family_process_observer{b.release()}{} + nt_family_process& operator=(nt_family_process&& __restrict b) noexcept + { + win32::nt::details::close_nt_user_process_information_and_wait(this->hnt_user_process_info); + this->hnt_user_process_info = b.release(); + return *this; + } + ~nt_family_process() + { + win32::nt::details::close_nt_user_process_information_and_wait(this->hnt_user_process_info); + } +}; + +using nt_process_observer = nt_family_process_observer; +using nt_process = nt_family_process; + +using zw_process_observer = nt_family_process_observer; +using zw_process = nt_family_process; + +} diff --git a/src/fast_io/include/fast_io_hosted/process_revamp/posix.h b/src/fast_io/include/fast_io_hosted/process_revamp/posix.h new file mode 100644 index 0000000..5a1c5b5 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/process_revamp/posix.h @@ -0,0 +1,450 @@ +#pragma once +#if __has_include() +#include +#endif + +namespace fast_io +{ + +namespace posix +{ +extern int libc_fexecve(int fd, char *const* argv, char *const* envp) noexcept __asm__("fexecve"); +} + +struct posix_wait_status +{ + int wait_loc{}; +}; +#if 0 +inline constexpr posix_wait_reason reason(posix_wait_status pws) noexcept +{ +#ifdef WIFEXITED + if(WIFEXITED(pws.wait_loc)) + return posix_wait_reason::if_exited; +#endif +#ifdef WIFSIGNALED + if(WIFSIGNALED(pws.wait_loc)) + return posix_wait_reason::if_signaled; +#endif +#ifdef WIFCORED + if(WIFCORED(pws.wait_loc)) + return posix_wait_reason::if_core_dump; +#endif +#ifdef WIFSTOPPED + if(WIFSTOPPED(pws.wait_loc)) + return posix_wait_reason::if_stopped; +#endif + return posix_wait_reason::none; +} + +inline constexpr int native_code(posix_wait_status pws) noexcept +{ + return pws.wait_loc; +} + +inline constexpr std::uintmax_t code(posix_wait_status pws) noexcept +{ + return static_cast(pws.wait_loc); + +template +inline constexpr std::size_t print_reserve_size(io_reserve_type_t) noexcept +{ + return sizeof(u8"reason:")+print_reserve_size(io_reserve_type) + +sizeof(u8" native_code:")+print_reserve_size(io_reserve_type); +} + +template +inline constexpr Iter print_reserve_define(io_reserve_type_t,Iter iter,posix_wait_status pws) noexcept +{ + if constexpr(std::same_as) + iter=details::copy_string_literal("reason:",iter); + else if constexpr(std::same_as) + iter=details::copy_string_literal(L"reason:",iter); + else if constexpr(std::same_as) + iter=details::copy_string_literal(u"reason:",iter); + else if constexpr(std::same_as) + iter=details::copy_string_literal(U"reason:",iter); + else + iter=details::copy_string_literal(u8"reason:",iter); + iter=print_reserve_define(io_reserve_type,iter,reason(pws)); + if constexpr(std::same_as) + iter=details::copy_string_literal(" native_code:",iter); + else if constexpr(std::same_as) + iter=details::copy_string_literal(L" native_code:",iter); + else if constexpr(std::same_as) + iter=details::copy_string_literal(u" native_code:",iter); + else if constexpr(std::same_as) + iter=details::copy_string_literal(U" native_code:",iter); + else + iter=details::copy_string_literal(u8" native_code:",iter); + return print_reserve_define(io_reserve_type,iter,pws.wait_loc); +} +#endif + +namespace details +{ +inline pid_t posix_fork() +{ + +#if defined(__linux__) && defined(__NR_fork) + pid_t pid{system_call<__NR_fork,pid_t>()}; + system_call_throw_error(pid); +#else + pid_t pid{noexcept_call(::fork)}; + if(pid==-1) + throw_posix_error(); +#endif + return pid; +} + +inline posix_wait_status posix_waitpid(pid_t pid) +{ + posix_wait_status status; +#if defined(__linux__) && defined(__NR_wait4) + system_call_throw_error(system_call<__NR_wait4,int>(pid,__builtin_addressof(status.wait_loc),0,nullptr)); +#else + if(noexcept_call(waitpid,pid,__builtin_addressof(status.wait_loc),0)==-1) + throw_posix_error(); +#endif + return status; +} + +inline void posix_waitpid_noexcept(pid_t pid) noexcept +{ +#if defined(__linux__) && defined(__NR_wait4) + system_call<__NR_wait4,int>(pid,nullptr,0,nullptr); +#else + noexcept_call(waitpid,pid,nullptr,0); +#endif +} + +[[noreturn]] inline void posix_execveat(int dirfd,char const* path,char const* const* argv,char const* const* envp) noexcept +{ +#if defined(__linux__) && defined(__NR_execveat) + system_call<__NR_execveat,int>(dirfd,path,argv,envp,AT_SYMLINK_NOFOLLOW); + fast_terminate(); +#else + int fd{::openat(dirfd,path,O_RDONLY|O_EXCL,0644)}; + if(fd==-1) + fast_terminate(); + ::fast_io::posix::libc_fexecve(fd,const_cast(argv),const_cast(envp)); + fast_terminate(); +#endif +} + +inline int child_process_deal_with_process_io(posix_io_redirection const& red,int fd) noexcept +{ + bool is_stdin{fd==0}; + if(red.pipe_fds) + { + auto v{red.pipe_fds[!is_stdin]}; + if(v!=-1) + fd=v; + int& closefd{red.pipe_fds[is_stdin]}; + if(closefd!=-1) + { + sys_close(closefd); + closefd=-1; + } + } + else if(red.fd!=-1) + fd=red.fd; + else if(red.dev_null) + fd=-1; + return fd; +} + + +inline void child_process_execveat(int dirfd,char const* cstr,char const* const* args_ptr,char const* const* envp_ptr,posix_process_io const& pio) noexcept +{ + int in_fd{child_process_deal_with_process_io(pio.in,0)}; + int out_fd{child_process_deal_with_process_io(pio.out,1)}; + int err_fd{child_process_deal_with_process_io(pio.err,2)}; + if((in_fd==-1)|(out_fd==-1)|(err_fd==-1)) + { + posix_file pf{my_posix_open("/dev/null",O_RDWR,0644)}; + if(in_fd==-1) + sys_dup2(pf.fd,0); + if(out_fd==-1) + sys_dup2(pf.fd,1); + if(err_fd==-1) + sys_dup2(pf.fd,2); + } + if((in_fd!=-1)&(in_fd!=0)) + sys_dup2(in_fd,0); + if((out_fd!=-1)&(out_fd!=1)) + sys_dup2(out_fd,1); + if((err_fd!=-1)&(err_fd!=2)) + sys_dup2(err_fd,2); + posix_execveat(dirfd,cstr,args_ptr,envp_ptr); +}; + + +template +inline void parent_process_deal_with_process_io(posix_io_redirection const& red) noexcept +{ + if(red.pipe_fds) + { + int& fd{red.pipe_fds[!is_stdin]}; + if(fd!=-1) + { + sys_close(fd); + fd=-1; + } + } +} + + +inline pid_t posix_fork_execveat_common_impl(int dirfd,char const* cstr,char const* const* args,char const* const* envp,posix_process_io const& pio) +{ + pid_t pid{posix_fork()}; + if(pid) + { + parent_process_deal_with_process_io(pio.in); + parent_process_deal_with_process_io(pio.out); + parent_process_deal_with_process_io(pio.err); + return pid; + } + child_process_execveat(dirfd,cstr,args,envp,pio); + fast_terminate(); +} + +template +inline pid_t posix_fork_execveat_impl(int dirfd,path_type const& csv,char const* const* args,char const* const* envp,posix_process_io const& pio) +{ + return ::fast_io::posix_api_common(csv,[&](char const* cstr){ + return posix_fork_execveat_common_impl(dirfd,cstr,args,envp,pio); + }); +} + +template +inline pid_t posix_fork_execve_impl(path_type const& csv,char const* const* args,char const* const* envp,posix_process_io const& pio) +{ +#if defined(AT_FDCWD) + return posix_fork_execveat_impl(AT_FDCWD,csv,args,envp,pio); +#else + throw_posix_error(EINVAL); + return -1; +#endif +} + +} + +class posix_process_observer +{ +public: + using native_handle_type = pid_t; + pid_t pid{-1}; + constexpr auto& native_handle() noexcept + { + return pid; + } + constexpr auto& native_handle() const noexcept + { + return pid; + } + explicit inline constexpr operator bool() const noexcept + { + return pid!=-1; + } + inline constexpr pid_t release() noexcept + { + auto temp{pid}; + pid=-1; + return temp; + } +}; + +inline constexpr void detach(posix_process_observer& ppob) noexcept +{ + ppob.pid=-1; +} + +inline posix_wait_status wait(posix_process_observer& ppob) +{ + posix_wait_status status{details::posix_waitpid(ppob.pid)}; + ppob.pid=-1; + return status; +} + +inline constexpr bool operator==(posix_process_observer a,posix_process_observer b) noexcept +{ + return a.pid==b.pid; +} + +inline constexpr auto operator<=>(posix_process_observer a,posix_process_observer b) noexcept +{ + return a.pid<=>b.pid; +} + +namespace details +{ + +template +struct temp_array_scoped_ptr +{ + T* ptr{}; + constexpr temp_array_scoped_ptr() noexcept = default; + explicit constexpr temp_array_scoped_ptr(std::size_t n):ptr(new T[n]){} + temp_array_scoped_ptr(temp_array_scoped_ptr const&)=delete; + temp_array_scoped_ptr& operator=(temp_array_scoped_ptr const&)=delete; +#if __cpp_constexpr_dynamic_alloc >= 201907L + constexpr +#endif + ~temp_array_scoped_ptr() + { + delete[] ptr; + } + inline constexpr T* release() noexcept + { + auto temp{ptr}; + ptr=nullptr; + return temp; + } + inline constexpr T const* get() const noexcept + { + return ptr; + } + inline constexpr T* get() noexcept + { + return ptr; + } + constexpr T& operator[](std::size_t pos) noexcept + { + return ptr[pos]; + } + constexpr T const& operator[](std::size_t pos) const noexcept + { + return ptr[pos]; + } +}; + +template<::std::forward_iterator Iter> +inline +#if __cpp_constexpr_dynamic_alloc >= 201907L +// constexpr +#endif +char const* const* dup_enviro_impl_with_size(Iter begin,Iter end,std::size_t size) +{ + temp_array_scoped_ptr uptr(size+1); + if constexpr(requires(::std::iter_value_t v) + { + {v.c_str()}->std::convertible_to; + }) + { + for(char const** it{uptr.get()};begin!=end;++begin) + { + *it=begin->c_str(); + ++it; + } + } + else + non_overlapped_copy_n(begin,size,uptr.get()); + uptr[size]=nullptr; + return uptr.release(); +} + +template<::std::forward_iterator Iter> +inline +#if __cpp_constexpr_dynamic_alloc >= 201907L + constexpr +#endif +char const* const* dup_enviro_impl(Iter begin,Iter end) +{ + return dup_enviro_impl_with_size(begin,end,static_cast(::std::distance(begin,end))); +} + +template<::std::forward_iterator Iter> +inline +#if __cpp_constexpr_dynamic_alloc >= 201907L + constexpr +#endif +char const* const* dup_enviro_entry(Iter begin,Iter end) +{ + if constexpr(::std::contiguous_iterator) + return dup_enviro_impl(::std::to_address(begin),::std::to_address(end)); + else + return dup_enviro_impl(begin,end); +} + +} + +struct posix_process_args +{ + char const* const* args{}; + bool is_dynamic_allocated{}; + constexpr posix_process_args(char const* const* envir) noexcept:args(envir){} + template<::std::forward_iterator Iter> + requires (std::convertible_to<::std::iter_value_t,char const*>||requires(::std::iter_value_t v) + { + {v.c_str()}->std::convertible_to; + }) + constexpr posix_process_args(Iter begin,Iter end): + args(details::dup_enviro_entry(begin,end)),is_dynamic_allocated(true) + {} +#if __has_include() + template + requires (std::convertible_to,char const*>||requires(std::ranges::range_value_t v) + { + {v.c_str()}->std::convertible_to; + }) + constexpr posix_process_args(range&& rg):posix_process_args(std::ranges::cbegin(rg),std::ranges::cend(rg)) + {} +#if __has_include() + constexpr posix_process_args(std::initializer_list ilist): + posix_process_args(ilist.begin(),ilist.end()){} +#endif +#endif + posix_process_args(posix_process_args const&)=delete; + posix_process_args& operator=(posix_process_args const&)=delete; +#if __cpp_constexpr_dynamic_alloc >= 201907L + constexpr +#endif + ~posix_process_args() + { + if(is_dynamic_allocated) + delete[] args; + } +}; + + +class posix_process:public posix_process_observer +{ +public: + using native_handle_type = pid_t; + explicit constexpr posix_process() noexcept =default; + template + requires std::same_as> + explicit constexpr posix_process(native_hd pid1) noexcept: + posix_process_observer{pid1}{} + template<::fast_io::constructible_to_os_c_str path_type> + posix_process(posix_at_entry pate,path_type const& filename,posix_process_args const& args,posix_process_args const& envp,posix_process_io const& pio): + posix_process_observer{details::posix_fork_execveat_impl(pate.fd,filename,args.args,envp.args,pio)}{} + + template<::fast_io::constructible_to_os_c_str path_type> + posix_process(path_type const& filename,posix_process_args const& args,posix_process_args const& envp,posix_process_io const& pio): + posix_process_observer{::fast_io::details::posix_fork_execve_impl(filename,args.args,envp.args,pio)}{} + + posix_process(::fast_io::posix_fs_dirent ent,posix_process_args const& args,posix_process_args const& envp,posix_process_io const& pio): + posix_process_observer{::fast_io::details::posix_fork_execveat_common_impl(ent.fd,ent.filename,args.args,envp.args,pio)}{} + + posix_process(posix_process const&)=delete; + posix_process& operator=(posix_process const&)=delete; + constexpr posix_process(posix_process&& __restrict other) noexcept:posix_process_observer{other.pid} + { + other.pid=-1; + } + posix_process& operator=(posix_process&& __restrict other) noexcept + { + details::posix_waitpid_noexcept(this->pid); + this->pid=other.pid; + other.pid=-1; + return *this; + } + ~posix_process() + { + details::posix_waitpid_noexcept(this->pid); + } +}; + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_hosted/process_revamp/win32.h b/src/fast_io/include/fast_io_hosted/process_revamp/win32.h new file mode 100644 index 0000000..9cb594c --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/process_revamp/win32.h @@ -0,0 +1,36 @@ +#pragma once + +namespace fast_io +{ + +class win32_process_observer +{ +public: + using native_handle_type = pid_t; + pid_t pid{-1}; + constexpr auto& native_handle() noexcept + { + return pid; + } + constexpr auto& native_handle() const noexcept + { + return pid; + } + explicit inline constexpr operator bool() const noexcept + { + return pid!=-1; + } + constexpr pid_t release() noexcept + { + auto temp{pid}; + pid=-1; + return temp; + } +}; + +struct win32_process +{ + +}; + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_hosted/threads/mutex/gcc_gthread_mutex.h b/src/fast_io/include/fast_io_hosted/threads/mutex/gcc_gthread_mutex.h new file mode 100644 index 0000000..d478e4d --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/threads/mutex/gcc_gthread_mutex.h @@ -0,0 +1,27 @@ +#pragma once + +namespace fast_io +{ + +struct gcc_gthread_mutex +{ + using native_handle_type = __gthread_mutex_t; + native_handle_type mutex{}; + constexpr explicit gcc_gthread_mutex() noexcept=default; + gcc_gthread_mutex(gcc_gthread_mutex const&)=delete; + gcc_gthread_mutex& operator=(gcc_gthread_mutex const&)=delete; + void lock() noexcept + { + __gthread_mutex_lock(__builtin_addressof(mutex)); + } + bool try_lock() noexcept + { + return !__gthread_mutex_trylock(__builtin_addressof(mutex)); + } + void unlock() noexcept + { + __gthread_mutex_unlock(__builtin_addressof(mutex)); + } +}; + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_hosted/threads/mutex/impl.h b/src/fast_io/include/fast_io_hosted/threads/mutex/impl.h new file mode 100644 index 0000000..4c762f4 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/threads/mutex/impl.h @@ -0,0 +1,31 @@ +#pragma once + +#include"single.h" +#ifdef __USING_MCFGTHREAD__ +#include +#include "mcf_gthread_mutex.h" +#endif +#if defined(_WIN32) || defined(__CYGWIN__) +#include"rtl_critical_section.h" +#include"win32_critical_section.h" +#endif +#if !defined(__SINGLE_THREAD__) && (!defined(__NEWLIB__) || defined(__CYGWIN__)) && !defined(_WIN32) && !defined(__MSDOS__) && !defined(__wasi__) && __has_include() +#include"posix_pthread_mutex.h" +#endif + +namespace fast_io +{ + +using native_mutex = +#ifdef __USING_MCFGTHREAD__ +mcf_gthread_mutex +#elif (defined(_WIN32)&&!defined(__WINE__)) || defined(__CYGWIN__) +win32_critical_section +#elif defined(__SINGLE_THREAD__) || defined(__MSDOS__) || (defined(__NEWLIB__) && !defined(__CYGWIN__)) || defined(__wasi__) || !__has_include() +single_thread_noop_mutex +#else +posix_pthread_mutex +#endif +; + +} diff --git a/src/fast_io/include/fast_io_hosted/threads/mutex/mcf_gthread_mutex.h b/src/fast_io/include/fast_io_hosted/threads/mutex/mcf_gthread_mutex.h new file mode 100644 index 0000000..c8d8ed8 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/threads/mutex/mcf_gthread_mutex.h @@ -0,0 +1,31 @@ +#pragma once + +namespace fast_io +{ + +struct mcf_gthread_mutex +{ + using native_handle_type = __MCF_mutex; + native_handle_type mutex{}; + explicit mcf_gthread_mutex() noexcept + { + _MCF_mutex_init(__builtin_addressof(mutex)); + } + mcf_gthread_mutex(mcf_gthread_mutex const&)=delete; + mcf_gthread_mutex& operator=(mcf_gthread_mutex const&)=delete; + void lock() noexcept + { + _MCF_mutex_lock(__builtin_addressof(mutex),nullptr); + } + bool try_lock() noexcept + { + ::std::int_least64_t timeout{}; + return !_MCF_mutex_lock(__builtin_addressof(mutex),__builtin_addressof(timeout)); + } + void unlock() noexcept + { + _MCF_mutex_unlock(__builtin_addressof(mutex)); + } +}; + +} diff --git a/src/fast_io/include/fast_io_hosted/threads/mutex/posix_pthread_mutex.h b/src/fast_io/include/fast_io_hosted/threads/mutex/posix_pthread_mutex.h new file mode 100644 index 0000000..fbef6bb --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/threads/mutex/posix_pthread_mutex.h @@ -0,0 +1,36 @@ +#pragma once + +#include + +namespace fast_io +{ + +struct posix_pthread_mutex +{ + using native_handle_type = pthread_mutex_t; + native_handle_type mutex; + explicit posix_pthread_mutex() noexcept:mutex(PTHREAD_MUTEX_INITIALIZER) + {} + posix_pthread_mutex(posix_pthread_mutex const&)=delete; + posix_pthread_mutex& operator=(posix_pthread_mutex const&)=delete; + void lock() + { + if(noexcept_call(pthread_mutex_lock,__builtin_addressof(mutex)))[[unlikely]] + throw_posix_error(); + } + bool try_lock() noexcept + { + return !noexcept_call(pthread_mutex_trylock,__builtin_addressof(mutex)); + } + void unlock() noexcept + { + noexcept_call(pthread_mutex_unlock,__builtin_addressof(mutex)); + } + + ~posix_pthread_mutex() + { + noexcept_call(pthread_mutex_destroy,__builtin_addressof(mutex)); + } +}; + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_hosted/threads/mutex/rtl_critical_section.h b/src/fast_io/include/fast_io_hosted/threads/mutex/rtl_critical_section.h new file mode 100644 index 0000000..e131f84 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/threads/mutex/rtl_critical_section.h @@ -0,0 +1,34 @@ +#pragma once + +namespace fast_io +{ + +struct rtl_critical_section +{ + using native_handle_type = ::fast_io::win32::nt::rtl_critical_section; + native_handle_type critical_section; + explicit rtl_critical_section() noexcept + { + ::fast_io::win32::nt::RtlInitializeCriticalSection(__builtin_addressof(critical_section)); + } + rtl_critical_section(rtl_critical_section const&)=delete; + rtl_critical_section& operator=(rtl_critical_section const&)=delete; + void lock() noexcept + { + ::fast_io::win32::nt::RtlEnterCriticalSection(__builtin_addressof(critical_section)); + } + bool try_lock() noexcept + { + return ::fast_io::win32::nt::RtlTryEnterCriticalSection(__builtin_addressof(critical_section))!=0; + } + void unlock() noexcept + { + ::fast_io::win32::nt::RtlLeaveCriticalSection(__builtin_addressof(critical_section)); + } + ~rtl_critical_section() + { + ::fast_io::win32::nt::RtlDeleteCriticalSection(__builtin_addressof(critical_section)); + } +}; + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_hosted/threads/mutex/single.h b/src/fast_io/include/fast_io_hosted/threads/mutex/single.h new file mode 100644 index 0000000..8089f12 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/threads/mutex/single.h @@ -0,0 +1,13 @@ +#pragma once + +namespace fast_io +{ + +struct single_thread_noop_mutex +{ + constexpr void lock() noexcept {} + constexpr void unlock() noexcept {} + constexpr void try_lock() noexcept {} +}; + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_hosted/threads/mutex/win32_critical_section.h b/src/fast_io/include/fast_io_hosted/threads/mutex/win32_critical_section.h new file mode 100644 index 0000000..621f9b2 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/threads/mutex/win32_critical_section.h @@ -0,0 +1,34 @@ +#pragma once + +namespace fast_io +{ + +struct win32_critical_section +{ + using native_handle_type = ::fast_io::win32::nt::rtl_critical_section; + native_handle_type critical_section; + explicit win32_critical_section() noexcept + { + ::fast_io::win32::InitializeCriticalSection(__builtin_addressof(critical_section)); + } + win32_critical_section(win32_critical_section const&)=delete; + win32_critical_section& operator=(win32_critical_section const&)=delete; + void lock() noexcept + { + ::fast_io::win32::EnterCriticalSection(__builtin_addressof(critical_section)); + } + bool try_lock() noexcept + { + return ::fast_io::win32::TryEnterCriticalSection(__builtin_addressof(critical_section))!=0; + } + void unlock() noexcept + { + ::fast_io::win32::LeaveCriticalSection(__builtin_addressof(critical_section)); + } + ~win32_critical_section() + { + ::fast_io::win32::DeleteCriticalSection(__builtin_addressof(critical_section)); + } +}; + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_hosted/timeutil/environ_timezone.h b/src/fast_io/include/fast_io_hosted/timeutil/environ_timezone.h new file mode 100644 index 0000000..ddb5494 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/timeutil/environ_timezone.h @@ -0,0 +1,54 @@ +#pragma once + +#include + +namespace fast_io +{ + +struct environ_timezone_name +{ + using char8_const_may_alias_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = char8_t const*; + char8_const_may_alias_ptr name{u8"Etc/GMT"}; +}; + +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) + __builtin_getenv +#else + ::std::getenv +#endif +#else + ::std::getenv +#endif + (reinterpret_cast(u8"TZ")))}; + if(ptr==nullptr) + return {}; + return {ptr}; +} +} + +struct environ_local_timezone +{ + inline environ_timezone_name operator()() noexcept + { + return ::fast_io::details::environ_localtimezone_impl(); + } +}; + +inline constexpr cross_code_cvt_t print_alias_define(::fast_io::io_alias_t,environ_timezone_name enm) noexcept +{ + return ::fast_io::cross_code_cvt_t{{enm.name,::fast_io::details::dummy_cstr_len(enm.name)}}; +} + +using native_local_timezone = environ_local_timezone; + +} diff --git a/src/fast_io/include/fast_io_hosted/timeutil/impl.h b/src/fast_io/include/fast_io_hosted/timeutil/impl.h new file mode 100644 index 0000000..cacc2ff --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/timeutil/impl.h @@ -0,0 +1,16 @@ +#pragma once +#include"time.h" + +#if (defined(_WIN32) && !defined(__WINE__)) || defined(__CYGWIN__) +#include"win32_timezone.h" +#endif +#if !defined(_WIN32) || defined(__WINE__) +#if defined(__MSDOS__) || (defined(__NEWLIB__) && !defined(__CYGWIN__)) || defined(__wasi__) +#include"environ_timezone.h" +#else +#ifdef __CYGWIN__ +#include"environ_timezone.h" +#endif +#include"posix_timezone.h" +#endif +#endif diff --git a/src/fast_io/include/fast_io_hosted/timeutil/posix_timezone.h b/src/fast_io/include/fast_io_hosted/timeutil/posix_timezone.h new file mode 100644 index 0000000..2ff4ac1 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/timeutil/posix_timezone.h @@ -0,0 +1,105 @@ +#pragma once + +namespace fast_io +{ + +struct posix_timezone_name +{ + char8_t *ptr{}; + std::size_t n{}; + constexpr posix_timezone_name() noexcept=default; + constexpr posix_timezone_name(posix_timezone_name const&)=delete; + posix_timezone_name& operator=(posix_timezone_name const&)=delete; + constexpr posix_timezone_name(posix_timezone_name&& other) noexcept:ptr(other.ptr),n(other.n) + { + other.ptr=nullptr; + other.n=0; + } + posix_timezone_name& operator=(posix_timezone_name&& other) noexcept + { + ::fast_io::typed_generic_allocator_adapter<::fast_io::generic_allocator_adapter<::fast_io::c_malloc_allocator>,char8_t>::deallocate(this->ptr); + this->ptr=other.ptr; + this->n=other.n; + other.ptr=nullptr; + other.n=0; + return *this; + } + constexpr + ~posix_timezone_name() + { + ::fast_io::typed_generic_allocator_adapter<::fast_io::generic_allocator_adapter<::fast_io::c_malloc_allocator>,char8_t>::deallocate(ptr); + } +}; + +namespace posix +{ +extern int libc_lstat(char8_t const* pathname,struct stat* buf) noexcept __asm__("lstat"); +extern std::ptrdiff_t libc_readlink(char8_t const* pathname,char8_t* buf, std::size_t bufsiz) noexcept __asm__("readlink"); +} + +namespace details +{ + +inline constexpr char8_t localtimezoneinfo[]{u8"/usr/share/zoneinfo/"}; +inline constexpr std::size_t localtimezoneinfo_string_len{std::ranges::size(localtimezoneinfo)-1}; + +inline posix_timezone_name posix_localtimezone_impl() noexcept +{ + struct stat st; + int ret{::fast_io::posix::libc_lstat(u8"/etc/localtime",__builtin_addressof(st))}; + if(ret==-1) + { + return {}; + } + using unsignedtype = ::std::make_unsigned_t; + if constexpr(sizeof(decltype(st.st_size))>sizeof(std::size_t)) + { + constexpr std::size_t mx{::std::numeric_limits::max()}; + if(mx(st.st_size)) + { + return {}; + } + } + std::size_t real_size{static_cast(st.st_size)}; + char8_t* bufptr{::fast_io::typed_generic_allocator_adapter<::fast_io::generic_allocator_adapter<::fast_io::c_malloc_allocator>,char8_t>::allocate(real_size)}; + posix_timezone_name nm; + nm.ptr=bufptr; + nm.n=static_cast(static_cast(st.st_size)); + std::ptrdiff_t symret{::fast_io::posix::libc_readlink(u8"/etc/localtime",bufptr,real_size)}; + if(ret==-1||static_cast(symret)!=real_size||real_size<=localtimezoneinfo_string_len) + { + return {}; + } + if(__builtin_memcmp(localtimezoneinfo,bufptr,localtimezoneinfo_string_len)!=0) + { + return {}; + } + return nm; +} + +} + +struct posix_local_timezone +{ + inline posix_timezone_name operator()() noexcept + { + return ::fast_io::details::posix_localtimezone_impl(); + } +}; + +inline constexpr cross_code_cvt_t print_alias_define(::fast_io::io_alias_t,posix_timezone_name const& enm) noexcept +{ + if(enm.ptr==nullptr) + { + return ::fast_io::cross_code_cvt_t{{u8"Etc/GMT",7u}}; + } + else + { + return ::fast_io::cross_code_cvt_t{{enm.ptr+::fast_io::details::localtimezoneinfo_string_len,enm.n-::fast_io::details::localtimezoneinfo_string_len}}; + } +} + +#ifndef __CYGWIN__ +using native_local_timezone = posix_local_timezone; +#endif +} diff --git a/src/fast_io/include/fast_io_hosted/timeutil/time.h b/src/fast_io/include/fast_io_hosted/timeutil/time.h new file mode 100644 index 0000000..f564323 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/timeutil/time.h @@ -0,0 +1,920 @@ +#pragma once + +namespace fast_io +{ +#if !defined(_WIN32) && !defined(__AVR__) && !defined(__MSDOS__) +namespace posix +{ +extern int libc_clock_getres(clockid_t clk_id, struct timespec *tp) noexcept __asm__("clock_getres"); +extern int libc_clock_settime(clockid_t clk_id, struct timespec const* tp) noexcept __asm__("clock_settime"); +extern int libc_clock_gettime(clockid_t clk_id, struct timespec* tp) noexcept __asm__("clock_gettime"); +} +#endif + +namespace details +{ +#if !defined(__AVR__) +#if __has_cpp_attribute(__gnu__::__pure__) +[[__gnu__::__pure__]] +#endif +inline constexpr auto posix_clock_id_to_native_value(posix_clock_id pcid) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + switch(pcid) + { + case posix_clock_id::realtime: + case posix_clock_id::tai: + return posix_clock_id::tai; + break; + case posix_clock_id::monotonic: + return posix_clock_id::monotonic; + break; + default: + throw_win32_error(0x00000057); + }; +#else + switch(pcid) + { +#ifdef CLOCK_REALTIME + case posix_clock_id::realtime: + return CLOCK_REALTIME; + break; +#endif +#ifdef CLOCK_REALTIME_ALARM + case posix_clock_id::realtime_alarm: + return CLOCK_REALTIME_ALARM; + break; +#elif defined(CLOCK_REALTIME) + case posix_clock_id::realtime_alarm: + return CLOCK_REALTIME; + break; +#endif +#ifdef CLOCK_REALTIME_COARSE + case posix_clock_id::realtime_coarse: + return CLOCK_REALTIME_COARSE; + break; +#elif defined(CLOCK_REALTIME) + case posix_clock_id::realtime_coarse: + return CLOCK_REALTIME; + break; +#endif +#ifdef CLOCK_TAI + case posix_clock_id::tai: + return CLOCK_TAI; + break; +#elif defined(CLOCK_REALTIME) + case posix_clock_id::tai: + return CLOCK_REALTIME; + break; +#endif +#ifdef CLOCK_MONOTONIC + case posix_clock_id::monotonic: + return CLOCK_MONOTONIC; + break; +#endif +#ifdef CLOCK_MONOTONIC_COARSE + case posix_clock_id::monotonic_coarse: + return CLOCK_MONOTONIC_COARSE; + break; +#endif +#ifdef CLOCK_MONOTONIC_RAW + case posix_clock_id::monotonic_raw: + return CLOCK_MONOTONIC_RAW; + break; +#elif defined(CLOCK_MONOTONIC) + case posix_clock_id::monotonic_raw: + return CLOCK_MONOTONIC; + break; +#endif +#ifdef CLOCK_MONOTONIC_RAW_APPROX + case posix_clock_id::monotonic_raw_approx: + return CLOCK_MONOTONIC_RAW_APPROX; + break; +#endif +#ifdef CLOCK_BOOTTIME + case posix_clock_id::boottime: + return CLOCK_BOOTTIME; + break; +#else +#ifdef CLOCK_MONOTONIC + case posix_clock_id::boottime: + return CLOCK_MONOTONIC; + break; +#endif +#endif +#ifdef CLOCK_BOOTTIME_ALARM + case posix_clock_id::boottime_alarm: + return CLOCK_BOOTTIME_ALARM; + break; +#endif +#ifdef CLOCK_UPTIME_RAW + case posix_clock_id::uptime_raw: + return CLOCK_UPTIME_RAW; + break; +#endif +#ifdef CLOCK_UPTIME_RAW_APPROX + case posix_clock_id::uptime_raw_approx: + return CLOCK_UPTIME_RAW_APPROX; + break; +#endif +#ifdef CLOCK_PROCESS_CPUTIME_ID + case posix_clock_id::process_cputime_id: + return CLOCK_PROCESS_CPUTIME_ID; + break; +#endif +#ifdef CLOCK_THREAD_CPUTIME_ID + case posix_clock_id::thread_cputime_id: + return CLOCK_THREAD_CPUTIME_ID; + break; +#endif + default: + throw_posix_error(EINVAL); + }; +#endif +} + +#endif +#ifdef _WIN32 +#if __has_cpp_attribute(__gnu__::__pure__) +[[__gnu__::__pure__]] +#endif +inline std::int_least64_t win32_query_performance_frequency() +{ + std::int_least64_t val{}; + if(!::fast_io::win32::QueryPerformanceFrequency(__builtin_addressof(val))) + throw_win32_error(); + if(val<=0) + throw_win32_error(0x00000057); + return val; +} + +#if __has_cpp_attribute(__gnu__::__pure__) +[[__gnu__::__pure__]] +#endif +inline unix_timestamp win32_query_performance_frequency_to_unix_timestamp() +{ + return {0,uint_least64_subseconds_per_second/static_cast(win32_query_performance_frequency())}; +} +#endif +} + +inline +#if (defined(_WIN32) && !defined(__CYGWIN__)) || defined(__MSDOS__) +constexpr +#endif +unix_timestamp posix_clock_getres([[maybe_unused]] posix_clock_id pclk_id) +{ +#if (defined(_WIN32) && !defined(__CYGWIN__)) + switch(pclk_id) + { + case posix_clock_id::realtime: + case posix_clock_id::realtime_alarm: + case posix_clock_id::realtime_coarse: + case posix_clock_id::tai: + case posix_clock_id::process_cputime_id: + case posix_clock_id::thread_cputime_id: + { + constexpr std::uint_least64_t mul_factor{uint_least64_subseconds_per_second/10000000u}; + constexpr unix_timestamp constexpr_stamp{0,mul_factor}; + return constexpr_stamp; + } + case posix_clock_id::monotonic: + case posix_clock_id::monotonic_coarse: + case posix_clock_id::monotonic_raw: + case posix_clock_id::boottime: + return ::fast_io::details::win32_query_performance_frequency_to_unix_timestamp(); + break; + default: + throw_win32_error(0x00000057); + } +#elif defined(__MSDOS__) + switch(pclk_id) + { + case posix_clock_id::realtime: + case posix_clock_id::realtime_alarm: + case posix_clock_id::realtime_coarse: + case posix_clock_id::tai: + case posix_clock_id::monotonic: + case posix_clock_id::monotonic_coarse: + case posix_clock_id::monotonic_raw: + case posix_clock_id::boottime: + { + constexpr std::uint_least64_t mul_factor{uint_least64_subseconds_per_second/100u}; + return {0,mul_factor}; + } + case posix_clock_id::process_cputime_id: + case posix_clock_id::thread_cputime_id: + { + constexpr std::uint_least64_t mul_factor{uint_least64_subseconds_per_second/UCLOCKS_PER_SEC}; + return {0,mul_factor}; + } + default: + throw_posix_error(EINVAL); + }; +#elif defined(__AVR__) + return {1,0}; +#elif !defined(__NEWLIB__) || defined(_POSIX_TIMERS) + auto clk{details::posix_clock_id_to_native_value(pclk_id)}; + struct timespec res; +//vdso + if(::fast_io::posix::libc_clock_getres(clk,__builtin_addressof(res))<0) + throw_posix_error(); + constexpr std::uint_least64_t mul_factor{uint_least64_subseconds_per_second/1000000000u}; + return {static_cast(res.tv_sec),static_cast(res.tv_nsec)*mul_factor}; +#else + throw_posix_error(EINVAL); +#endif +} +#if (defined(_WIN32) && !defined(__CYGWIN__)) +namespace win32::details +{ + +inline unix_timestamp win32_posix_clock_gettime_tai_impl() noexcept +{ + ::fast_io::win32::filetime ftm; +#if (defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0602) && !defined(_WIN32_WINDOWS) + ::fast_io::win32::GetSystemTimePreciseAsFileTime(__builtin_addressof(ftm)); +#else + ::fast_io::win32::GetSystemTimeAsFileTime(__builtin_addressof(ftm)); +#endif + return static_cast(to_win32_timestamp(ftm)); +} + +inline unix_timestamp win32_posix_clock_gettime_boottime_impl() +{ + std::uint_least64_t ftm{}; + if(!::fast_io::win32::QueryUnbiasedInterruptTime(__builtin_addressof(ftm))) + throw_win32_error(); + constexpr std::uint_least64_t mul_factor{uint_least64_subseconds_per_second/10000000u}; + std::uint_least64_t seconds{ftm/10000000ULL}; + std::uint_least64_t subseconds{ftm%10000000ULL}; + return {static_cast(seconds),static_cast(subseconds*mul_factor)}; +} + +template +inline unix_timestamp win32_posix_clock_gettime_process_or_thread_time_impl() +{ + ::fast_io::win32::filetime creation_time,exit_time,kernel_time,user_time; + if constexpr(is_thread) + { + auto hthread{bit_cast(std::intptr_t(-2))}; + if(!::fast_io::win32::GetThreadTimes(hthread,__builtin_addressof(creation_time), + __builtin_addressof(exit_time), + __builtin_addressof(kernel_time), + __builtin_addressof(user_time))) + throw_win32_error(); + } + else + { + auto hprocess{bit_cast(std::intptr_t(-1))}; + if(!::fast_io::win32::GetProcessTimes(hprocess,__builtin_addressof(creation_time), + __builtin_addressof(exit_time), + __builtin_addressof(kernel_time), + __builtin_addressof(user_time))) + throw_win32_error(); + } + std::uint_least64_t ftm{::fast_io::win32::filetime_to_uint_least64_t(kernel_time)+ + ::fast_io::win32::filetime_to_uint_least64_t(user_time)}; + std::uint_least64_t seconds{ftm/10000000ULL}; + std::uint_least64_t subseconds{ftm%10000000ULL}; + constexpr std::uint_least64_t mul_factor{uint_least64_subseconds_per_second/10000000u}; + return {static_cast(seconds),static_cast(subseconds*mul_factor)}; +} + +inline unix_timestamp win32_posix_clock_gettime_boottime_xp_impl() +{ + std::uint_least64_t freq{static_cast(::fast_io::details::win32_query_performance_frequency())}; + std::int_least64_t counter{}; + if(!::fast_io::win32::QueryPerformanceCounter(__builtin_addressof(counter))) + throw_win32_error(); + if(counter<0) + throw_win32_error(0x00000057); + std::uint_least64_t ucounter{static_cast(counter)}; + std::uint_least64_t val{uint_least64_subseconds_per_second/freq}; + std::uint_least64_t dv{ucounter/freq}; + std::uint_least64_t md{ucounter%freq}; + return unix_timestamp{static_cast(dv),static_cast(md*static_cast(val))}; +} + +} +#endif + +#ifdef __MSDOS__ +namespace details +{ + +struct my_dos_date_t +{ + std::uint_least8_t day; + std::uint_least8_t month; + std::uint_least16_t year; + std::uint_least8_t dayofweek; +}; + +struct my_dos_time_t +{ + std::uint_least8_t hour; /* 0-23 */ + std::uint_least8_t minute; /* 0-59 */ + std::uint_least8_t second; /* 0-59 */ + std::uint_least8_t hsecond; /* 0-99 */ +}; + +extern void my_dos_getdate(my_dos_date_t*) noexcept __asm__("__dos_getdate"); +extern void my_dos_gettime(my_dos_time_t*) noexcept __asm__("__dos_gettime"); + +extern unsigned int my_dos_settime(my_dos_time_t*) noexcept __asm__("__dos_settime"); +extern unsigned int my_dos_setdate(my_dos_date_t*) noexcept __asm__("__dos_setdate"); + +inline iso8601_timestamp get_dos_iso8601_timestamp() +{ + my_dos_date_t dos_date; + my_dos_time_t dos_time; + my_dos_date_t dos_date_temp; + for(std::size_t i{};i!=100;++i) + { + my_dos_getdate(&dos_date); + my_dos_gettime(&dos_time); + my_dos_getdate(&dos_date_temp); + if(dos_date.day==dos_date_temp.day&& + dos_date.month==dos_date_temp.month&& + dos_date.year==dos_date_temp.year&& + dos_date.dayofweek==dos_date_temp.dayofweek) + { + constexpr std::uint_least64_t factor{uint_least64_subseconds_per_second/100u}; + return {static_cast(dos_date.year),dos_date.month,dos_date.day, + dos_time.hour,dos_time.minute,dos_time.second, + static_cast(dos_time.hsecond)*factor,0}; + } + } + throw_posix_error(EINVAL); +} + +inline unix_timestamp get_dos_unix_timestamp() +{ + return to_timestamp(get_dos_iso8601_timestamp()); +} + +inline void set_dos_unix_timestamp(unix_timestamp tsp) +{ + iso8601_timestamp iso8601{utc(tsp)}; + if(iso8601.year>static_cast(UINT_LEAST16_MAX)||iso8601.year<0) + throw_posix_error(EINVAL); + std::uint_least16_t year{static_cast(iso8601.year)}; + my_dos_date_t dos_date{static_cast(iso8601.day),static_cast(iso8601.month),year,0}; + constexpr std::uint_least64_t precision{uint_least64_subseconds_per_second/100ULL}; + my_dos_time_t dos_time{static_cast(iso8601.hours), + static_cast(iso8601.minutes), + static_cast(iso8601.seconds), + static_cast(iso8601.subseconds/precision)}; + if(!my_dos_setdate(__builtin_addressof(dos_date))) + throw_posix_error(); + if(!my_dos_settime(__builtin_addressof(dos_time))) + throw_posix_error(); + my_dos_date_t dos_date_temp; + for(std::size_t i{};i!=100;++i) + { + my_dos_getdate(__builtin_addressof(dos_date_temp)); + if(dos_date.day==dos_date_temp.day&& + dos_date.month==dos_date_temp.month&& + dos_date.year==dos_date_temp.year&& + dos_date.dayofweek==dos_date_temp.dayofweek) + return; + if(!my_dos_setdate(__builtin_addressof(dos_date))) + throw_posix_error(); + if(!my_dos_settime(__builtin_addressof(dos_time))) + throw_posix_error(); + } + throw_posix_error(EINVAL); +} + +} +#endif + +inline unix_timestamp posix_clock_gettime([[maybe_unused]] posix_clock_id pclk_id) +{ +#if (defined(_WIN32) && !defined(__CYGWIN__)) + switch(pclk_id) + { + case posix_clock_id::realtime: + case posix_clock_id::realtime_alarm: + case posix_clock_id::realtime_coarse: + case posix_clock_id::tai: + return win32::details::win32_posix_clock_gettime_tai_impl(); + case posix_clock_id::monotonic: + case posix_clock_id::monotonic_coarse: + case posix_clock_id::monotonic_raw: + case posix_clock_id::boottime: +// return win32::details::win32_posix_clock_gettime_boottime_impl(); + return win32::details::win32_posix_clock_gettime_boottime_xp_impl(); + case posix_clock_id::process_cputime_id: + return win32::details::win32_posix_clock_gettime_process_or_thread_time_impl(); + case posix_clock_id::thread_cputime_id: + return win32::details::win32_posix_clock_gettime_process_or_thread_time_impl(); + default: + throw_win32_error(0x00000057); + } +#elif defined(__MSDOS__) + switch(pclk_id) + { + case posix_clock_id::realtime: + case posix_clock_id::realtime_alarm: + case posix_clock_id::realtime_coarse: + case posix_clock_id::tai: + case posix_clock_id::monotonic: + case posix_clock_id::monotonic_coarse: + case posix_clock_id::monotonic_raw: + case posix_clock_id::boottime: + { + return details::get_dos_unix_timestamp(); + } + case posix_clock_id::process_cputime_id: + case posix_clock_id::thread_cputime_id: + { + std::make_unsigned_t u(noexcept_call(::uclock)); + std::uint_least64_t seconds(u/UCLOCKS_PER_SEC); + std::uint_least64_t subseconds(u%UCLOCKS_PER_SEC); + constexpr std::uint_least64_t mul_factor{uint_least64_subseconds_per_second/UCLOCKS_PER_SEC}; + return {static_cast(seconds),static_cast(subseconds)*mul_factor}; + } + default: + throw_posix_error(EINVAL); + } +#elif defined(__AVR__) + time_t t{}; + constexpr std::int_least64_t y2k_offset{static_cast(UNIX_OFFSET)}; + return {static_cast(static_cast(static_cast>(noexcept_call(::time,__builtin_addressof(t)))))+y2k_offset,0}; +#elif defined(_POSIX_TIMERS) + struct timespec res; + auto clk{details::posix_clock_id_to_native_value(pclk_id)}; +//vdso + if(::fast_io::posix::libc_clock_gettime(clk,__builtin_addressof(res))<0) + throw_posix_error(); + constexpr std::uint_least64_t mul_factor{uint_least64_subseconds_per_second/1000000000u}; + return {static_cast(res.tv_sec),static_cast(res.tv_nsec)*mul_factor}; +#else + throw_posix_error(EINVAL); +#endif +} + +#if defined(_WIN32) || defined(__CYGWIN__) +template +requires (family==nt_family::nt||family==nt_family::zw) +inline basic_timestamp nt_family_clock_settime(posix_clock_id pclk_id,basic_timestamp timestamp) +{ + if constexpr(std::same_as>) + { + switch(pclk_id) + { + case posix_clock_id::realtime: + case posix_clock_id::realtime_alarm: + case posix_clock_id::realtime_coarse: + case posix_clock_id::tai: + { + constexpr std::uint_least64_t mul_factor{uint_least64_subseconds_per_second/10000000u}; + std::uint_least64_t tms(static_cast(timestamp.seconds)*10000000ULL+timestamp.subseconds/mul_factor); + std::uint_least64_t old_tms{}; + auto ntstatus{win32::nt::nt_set_system_time(__builtin_addressof(tms),__builtin_addressof(old_tms))}; + if(ntstatus) + throw_nt_error(ntstatus); + return to_win32_timestamp_ftu64(old_tms); + } + default: + throw_nt_error(0xC00000EF); + }; + } + else + { + return static_cast>(nt_family_clock_settime(pclk_id,static_cast(timestamp))); + } +} +template +inline basic_timestamp nt_clock_settime(posix_clock_id pclk_id,basic_timestamp timestamp) +{ + return nt_family_clock_settime(pclk_id,timestamp); +} + +template +inline basic_timestamp zw_clock_settime(posix_clock_id pclk_id,basic_timestamp timestamp) +{ + return nt_family_clock_settime(pclk_id,timestamp); +} + +#endif + +namespace details +{ +#if !defined(_WIN32) || defined(__CYGWIN__) +template +inline struct tm unix_timestamp_to_tm_impl(std::int_least64_t seconds) +{ +#if defined(_TIME64_T) + time64_t val{static_cast(seconds)}; + struct tm t; + if constexpr(local_tm) + { + if(::fast_io::noexcept_call(localtime64_r,__builtin_addressof(val),__builtin_addressof(t))==0) + throw_posix_error(); + } + else + { + if(::fast_io::noexcept_call(gmtime64_r,__builtin_addressof(val),__builtin_addressof(t))==0) + throw_posix_error(); + } + return t; +#else + time_t val{static_cast(seconds)}; + struct tm t; +#if defined(__AVR__) + if constexpr(local_tm) + noexcept_call(localtime_r,__builtin_addressof(val),__builtin_addressof(t)); + else + noexcept_call(gmtime_r,__builtin_addressof(val),__builtin_addressof(t)); +#else + if constexpr(local_tm) + { + if(localtime_r(__builtin_addressof(val),__builtin_addressof(t))==0) + throw_posix_error(); + } + else + { + if(gmtime_r(__builtin_addressof(val),__builtin_addressof(t))==0) + throw_posix_error(); + } +#endif + return t; + +#endif +} +#endif + + +inline iso8601_timestamp to_iso8601_local_impl(std::int_least64_t seconds,std::uint_least64_t subseconds,[[maybe_unused]] bool dstadj) +{ +#if defined(__MSDOS__) || (defined(__NEWLIB__)&&!defined(__CYGWIN__)) || defined(__AVR__) || defined(_PICOLIBC__) || defined(__serenity__) + return unix_timestamp_to_iso8601_tsp_impl_internal(seconds,subseconds,0); +#elif (defined(_WIN32) && !defined(__WINE__) && !defined(__CYGWIN__)) || defined(__linux__) +#if (defined(__MINGW32__) && !__has_include(<_mingw_stat64.h>)) + return unix_timestamp_to_iso8601_tsp_impl_internal(seconds,subseconds,0); +#else + long tm_gmtoff{}; + #if (defined(_MSC_VER) || defined(_UCRT)) && !defined(__BIONIC__) + { + auto errn{noexcept_call(_get_timezone,__builtin_addressof(tm_gmtoff))}; + if(errn) + throw_posix_error(static_cast(errn)); + } + #elif defined(_WIN32) && !defined(__BIONIC__) && !defined(__WINE__) && !defined(__CYGWIN__) + tm_gmtoff=_timezone; + #else + tm_gmtoff=timezone; + #endif + long bias{}; + if(dstadj) + { + #if (defined(_MSC_VER) || defined(_UCRT)) && !defined(__BIONIC__) + { + auto errn{noexcept_call(_get_dstbias,__builtin_addressof(bias))}; + if(errn) + throw_posix_error(static_cast(errn)); + } + #elif defined(_WIN32) && !defined(__BIONIC__) && !defined(__WINE__) && !defined(__CYGWIN__)&& (defined(_M_IX86) || defined(_M_X64) ||defined(__i386__) || defined(__x86_64__)) + bias=_dstbias; + #else + bias=daylight?-3600L:0; + #endif + } + std::uint_least32_t const ul32_tm_gmtoff{static_cast(static_cast(tm_gmtoff))}; + std::uint_least32_t const ul32_bias{static_cast(static_cast(bias))}; + std::uint_least32_t const dst_timezone{ul32_tm_gmtoff+ul32_bias}; + constexpr std::uint_least32_t ul32_zero{}; + return unix_timestamp_to_iso8601_tsp_impl_internal(sub_overflow(seconds,static_cast(static_cast(dst_timezone))), + subseconds,static_cast(ul32_zero-dst_timezone)); +#endif +#else + auto res{unix_timestamp_to_tm_impl(seconds)}; + long tm_gmtoff{}; +#if defined(_WIN32) + #if defined(_MSC_VER) || defined(_UCRT) + { + auto errn{::fast_io::noexcept_call(_get_timezone,__builtin_addressof(tm_gmtoff))}; + if(errn) + throw_posix_error(static_cast(errn)); + } + #else + tm_gmtoff=_timezone; + #endif + long unsigned ulong_tm_gmtoff{static_cast(tm_gmtoff)}; + long seconds{}; +#if (defined(_MSC_VER) || defined(_UCRT))&& (defined(_M_IX86) || defined(_M_X64) ||defined(__i386__) || defined(__x86_64__)) + { + auto errn{::fast_io::noexcept_call(_get_dstbias,__builtin_addressof(seconds))}; + if(errn) + throw_posix_error(static_cast(errn)); + } +#else + seconds=_dstbias; +#endif + auto const ulong_seconds{static_cast(static_cast(seconds))}; + ulong_tm_gmtoff+=ulong_seconds; + ulong_tm_gmtoff=0ul-ulong_tm_gmtoff; + tm_gmtoff=static_cast(ulong_tm_gmtoff); +#elif defined(__TM_GMTOFF) + tm_gmtoff=res.__TM_GMTOFF; +#elif defined(__NEWLIB__) || defined(__AVR__) || defined(_PICOLIBC__) || defined(__serenity__) + tm_gmtoff=0; +#else + tm_gmtoff=res.tm_gmtoff; +#endif + std::uint_least8_t month{static_cast(res.tm_mon)}; + auto year{res.tm_year+1900}; + if(month==0) + { + --year; + month=12; + } + else + { + ++month; + } + return {year, + month, + static_cast(res.tm_mday), + static_cast(res.tm_hour), + static_cast(res.tm_min), + static_cast(res.tm_sec),subseconds,static_cast(tm_gmtoff)}; +#endif +} + +#if defined(__NEWLIB__) || defined(_PICOLIBC__) +#if (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__))&&defined(__CYGWIN__) +[[__gnu__::__dllimport__]] +#endif +extern void m_tzset() noexcept __asm__("tzset"); +#endif +} + +inline void posix_tzset() noexcept +{ +#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WINE__) && !defined(__BIONIC__) + noexcept_call(_tzset); +#elif defined(__NEWLIB__) || defined(_PICOLIBC__) + details::m_tzset(); +#elif !defined(__AVR__)&&(!defined(__wasi__) || defined(__wasilibc_unmodified_upstream)) + noexcept_call(tzset); +#endif +} + +#if defined(_WIN32) && !defined(__BIONIC__) && !defined(__CYGWIN__) && (defined(_UCRT) || defined(_MSC_VER)) +struct win32_timezone_t +{ + std::size_t tz_name_len{}; + bool is_dst{}; +}; + +inline bool posix_daylight() noexcept +{ + int hours; + if(::fast_io::noexcept_call(_get_daylight,__builtin_addressof(hours))) + return false; + return hours!=0; +} + +inline win32_timezone_t timezone_name(bool is_dst=posix_daylight()) +{ + win32_timezone_t tzt{.is_dst=is_dst}; + constexpr std::size_t zero{}; + auto errn{::fast_io::noexcept_call(_get_tzname,__builtin_addressof(tzt.tz_name_len),nullptr,zero,is_dst)}; + if(errn) + throw_posix_error(static_cast(errn)); + return tzt; +} + +inline constexpr std::size_t print_reserve_size(io_reserve_type_t,win32_timezone_t tzt) noexcept +{ + return tzt.tz_name_len; +} + +namespace details +{ + +inline std::size_t print_reserve_define_impl(char* first,win32_timezone_t tzt) +{ + auto errn{::fast_io::noexcept_call(_get_tzname,__builtin_addressof(tzt.tz_name_len),first,tzt.tz_name_len,tzt.is_dst)}; + if(errn) + throw_posix_error(static_cast(errn)); + if(tzt.tz_name_len) + return tzt.tz_name_len-1; + else + return 0; +} + +} + +inline char* print_reserve_define(io_reserve_type_t, char* first,win32_timezone_t tzt) +{ + return details::print_reserve_define_impl(::std::to_address(first),tzt)+first; +} + +#else + +#if defined(__NEWLIB__) || defined(_PICOLIBC__) +extern char *m_tzname[2] __asm__("_tzname"); +extern int m_daylight __asm__("_daylight"); +#endif + +inline bool posix_daylight() +{ +#if defined(__MSDOS__) || (defined(__wasi__) &&!defined(__wasilibc_unmodified_upstream)) || defined(__AVR__) + return 0; +#elif defined(_WIN32) && !defined(__WINE__) && !defined(__CYGWIN__) && !defined(__BIONIC__) + return _daylight; +#elif defined(__NEWLIB__) && !defined(__CYGWIN__) + return m_daylight; +#else + std::time_t t{}; + struct tm stm{}; + if(noexcept_call(localtime_r,__builtin_addressof(t),__builtin_addressof(stm))==0) + throw_posix_error(); + return stm.tm_isdst; +#endif +} + +inline basic_io_scatter_t timezone_name([[maybe_unused]] bool dst=posix_daylight()) noexcept +{ +#if defined(__MSDOS__) || (defined(__wasi__) &&!defined(__wasilibc_unmodified_upstream)) || defined(__AVR__) + return {reinterpret_cast(u8"UTC"),3}; +#else +#if defined(__NEWLIB__) || defined(_PICOLIBC__) + auto nm{m_tzname[dst]}; +#else + auto nm{tzname[dst]}; +#endif + return {nm,::fast_io::cstr_len(nm)}; +#endif +} + +#endif + + +template +inline iso8601_timestamp local(basic_timestamp timestamp,[[maybe_unused]] bool dstadj=posix_daylight()) +{ +#ifdef __MSDOS__ + return utc(timestamp); +#if 0 + return details::to_iso8601_local_impl(static_cast(timestamp)); +#endif +#else + if constexpr(off_to_epoch==0) + { + return details::to_iso8601_local_impl(timestamp.seconds,timestamp.subseconds,dstadj); + } + else + { + unix_timestamp stmp(static_cast(timestamp)); + return details::to_iso8601_local_impl(stmp.seconds,stmp.subseconds,dstadj); + } +#endif +} + +inline void posix_clock_settime([[maybe_unused]] posix_clock_id pclk_id,[[maybe_unused]] unix_timestamp timestamp) +{ +#if defined(_WIN32) && !defined(__NEWLIB__) + nt_clock_settime(pclk_id,timestamp); +#elif defined(__MSDOS__) + switch(pclk_id) + { + case posix_clock_id::realtime: + case posix_clock_id::realtime_alarm: + case posix_clock_id::realtime_coarse: + case posix_clock_id::tai: + { +#if 0 + if constexpr(sizeof(std::time_t)(std::numeric_limits::max())(timestamp.seconds), + static_cast(timestamp.subseconds/mul_factor)}; + if(::fast_io::noexcept_call(::settimeofday,__builtin_addressof(tv), nullptr)<0) + throw_posix_error(); +#else + details::set_dos_unix_timestamp(timestamp); +#endif + } + default: + throw_posix_error(EINVAL); + } +#elif defined(__AVR__) + constexpr std::int_least64_t mn_unix_offset{UNIX_OFFSET}; + auto tsp_seconds{timestamp.seconds}; + if(tsp_seconds=sizeof(std::int_least64_t)) + { + time_t t{static_cast(tsp_seconds)}; + if(__builtin_add_overflow(t,UNIX_OFFSET,__builtin_addressof(t))) + throw_posix_error(EINVAL); + noexcept_call(::set_system_time,t); + } + else + { + constexpr std::int_least64_t mx_unix_offset{static_cast(std::numeric_limits::max())-UNIX_OFFSET}; + if(tsp_seconds>mx_unix_offset) + throw_posix_error(EINVAL); + time_t t{static_cast(tsp_seconds)}; + noexcept_call(::set_system_time,t); + } +#elif (!defined(__NEWLIB__) || defined(_POSIX_TIMERS)) && (!defined(__wasi__) || defined(__wasilibc_unmodified_upstream)) + constexpr std::uint_least64_t mul_factor{uint_least64_subseconds_per_second/1000000000u}; + struct timespec res{static_cast(timestamp.seconds), + static_cast(timestamp.subseconds/mul_factor)}; + auto clk{details::posix_clock_id_to_native_value(pclk_id)}; +#ifdef __linux__ + system_call_throw_error(system_call<__NR_clock_settime,int>(clk,__builtin_addressof(res))); +#else + if(::fast_io::posix::libc_clock_settime(clk,__builtin_addressof(res))<0) + throw_posix_error(); +#endif +#else + throw_posix_error(EINVAL); +#endif +} + + +#if 0 +#ifdef _WIN32 + + +namespace details +{ + +} + +inline void posix_clock_sleep_abstime_complete(posix_clock_id pclk_id,unix_timestamp timestamp) +{ + switch(pclk_id) + { + case posix_clock_id::realtime: + case posix_clock_id::realtime_alarm: + case posix_clock_id::realtime_coarse: + case posix_clock_id::tai: + return win32::details::win32_posix_clock_gettime_tai_impl(); + case posix_clock_id::monotonic: + case posix_clock_id::monotonic_coarse: + case posix_clock_id::monotonic_raw: + case posix_clock_id::boottime: +// return win32::details::win32_posix_clock_gettime_boottime_impl(); + return win32::details::win32_posix_clock_gettime_boottime_xp_impl(); + case posix_clock_id::process_cputime_id: + return win32::details::win32_posix_clock_gettime_process_or_thread_time_impl(); + case posix_clock_id::thread_cputime_id: + return win32::details::win32_posix_clock_gettime_process_or_thread_time_impl(); + default: + throw_win32_error(0x00000057); + } +} + +inline [[nodiscard]] bool posix_clock_sleep_abstime(posix_clock_id pclk_id,unix_timestamp timestamp) +{ + posix_clock_sleep_abstime_complete(pclk_id,timestamp); + return false; +} + +#else + +inline [[nodiscard]] bool posix_clock_sleep_abstime(posix_clock_id pclk_id,unix_timestamp timestamp) +{ + constexpr std::uint_least64_t mul_factor{uint_least64_subseconds_per_second/1000000000u}; + struct timespec timestamp_spec{static_cast(timestamp.seconds),static_cast(timestamp.subseconds/mul_factor)}; + auto ret{::fast_io::noexcept_call(::clock_nanosleep,pclk_id,TIMER_ABSTIME,__builtin_addressof(timestamp_spec),ptr,nullptr)}; + if(ret<0) + { + auto ern{errno}; + if(ern!=EINTR) + throw_posix_error(ern); + return true; + } + return false; +} + +inline void posix_clock_sleep_abstime_complete(posix_clock_id pclk_id,unix_timestamp timestamp) +{ + constexpr std::uint_least64_t mul_factor{uint_least64_subseconds_per_second/1000000000u}; + struct timespec timestamp_spec{static_cast(timestamp.seconds),static_cast(timestamp.subseconds/mul_factor)} + for(;;) + { + auto ret{::fast_io::noexcept_call(::clock_nanosleep,pclk_id,TIMER_ABSTIME,__builtin_addressof(timestamp_spec),nullptr)}; + if(ret==0)[[likely]] + return; + auto ern{errno}; + if(ern!=EINTR) + throw_posix_error(ern); + } +} + +#endif +#endif +} diff --git a/src/fast_io/include/fast_io_hosted/timeutil/win32_regtz_to_ianatz.h b/src/fast_io/include/fast_io_hosted/timeutil/win32_regtz_to_ianatz.h new file mode 100644 index 0000000..2ad04b9 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/timeutil/win32_regtz_to_ianatz.h @@ -0,0 +1,988 @@ +#pragma once + +inline constexpr basic_io_scatter_t win32_registry_timezone_9xa[] +{ +{u8"AUS Central Standard Time",25}, +{u8"AUS Eastern Standard Time",25}, +{u8"Afghanistan Standard Time",25}, +{u8"Alaskan Standard Time",21}, +{u8"Aleutian Standard Time",22}, +{u8"Altai Standard Time",19}, +{u8"Arab Standard Time",18}, +{u8"Arabian Standard Time",21}, +{u8"Arabic Standard Time",20}, +{u8"Argentina Standard Time",23}, +{u8"Astrakhan Standard Time",23}, +{u8"Atlantic Standard Time",22}, +{u8"Aus Central W. Standard Time",28}, +{u8"Azerbaijan Standard Time",24}, +{u8"Azores Standard Time",20}, +{u8"Bahia Standard Time",19}, +{u8"Bangladesh Standard Time",24}, +{u8"Belarus Standard Time",21}, +{u8"Bougainville Standard Time",26}, +{u8"Canada Central Standard Time",28}, +{u8"Cape Verde Standard Time",24}, +{u8"Caucasus Standard Time",22}, +{u8"Cen. Australia Standard Time",28}, +{u8"Central America Standard Time",29}, +{u8"Central Asia Standard Time",26}, +{u8"Central Brazilian Standard Time",31}, +{u8"Central Europe Standard Time",28}, +{u8"Central European Standard Time",30}, +{u8"Central Pacific Standard Time",29}, +{u8"Central Standard Time",21}, +{u8"Central Standard Time (Mexico)",30}, +{u8"Chatham Islands Standard Time",29}, +{u8"China Standard Time",19}, +{u8"Cuba Standard Time",18}, +{u8"Dateline Standard Time",22}, +{u8"E. Africa Standard Time",23}, +{u8"E. Australia Standard Time",26}, +{u8"E. Europe Standard Time",23}, +{u8"E. South America Standard Time",30}, +{u8"Easter Island Standard Time",27}, +{u8"Eastern Standard Time",21}, +{u8"Eastern Standard Time (Mexico)",30}, +{u8"Egypt Standard Time",19}, +{u8"Ekaterinburg Standard Time",26}, +{u8"FLE Standard Time",17}, +{u8"Fiji Standard Time",18}, +{u8"GMT Standard Time",17}, +{u8"GTB Standard Time",17}, +{u8"Georgian Standard Time",22}, +{u8"Greenland Standard Time",23}, +{u8"Greenwich Standard Time",23}, +{u8"Haiti Standard Time",19}, +{u8"Hawaiian Standard Time",22}, +{u8"India Standard Time",19}, +{u8"Iran Standard Time",18}, +{u8"Israel Standard Time",20}, +{u8"Jordan Standard Time",20}, +{u8"Kaliningrad Standard Time",25}, +{u8"Korea Standard Time",19}, +{u8"Libya Standard Time",19}, +{u8"Line Islands Standard Time",26}, +{u8"Lord Howe Standard Time",23}, +{u8"Magadan Standard Time",21}, +{u8"Magallanes Standard Time",24}, +{u8"Marquesas Standard Time",23}, +{u8"Mauritius Standard Time",23}, +{u8"Middle East Standard Time",25}, +{u8"Montevideo Standard Time",24}, +{u8"Morocco Standard Time",21}, +{u8"Mountain Standard Time",22}, +{u8"Mountain Standard Time (Mexico)",31}, +{u8"Myanmar Standard Time",21}, +{u8"N. Central Asia Standard Time",29}, +{u8"Namibia Standard Time",21}, +{u8"Nepal Standard Time",19}, +{u8"New Zealand Standard Time",25}, +{u8"Newfoundland Standard Time",26}, +{u8"Norfolk Standard Time",21}, +{u8"North Asia East Standard Time",29}, +{u8"North Asia Standard Time",24}, +{u8"North Korea Standard Time",25}, +{u8"Omsk Standard Time",18}, +{u8"Pacific SA Standard Time",24}, +{u8"Pacific Standard Time",21}, +{u8"Pacific Standard Time (Mexico)",30}, +{u8"Pakistan Standard Time",22}, +{u8"Paraguay Standard Time",22}, +{u8"Qyzylorda Standard Time",23}, +{u8"Romance Standard Time",21}, +{u8"Russia Time Zone 10",19}, +{u8"Russia Time Zone 11",19}, +{u8"Russia Time Zone 3",18}, +{u8"Russian Standard Time",21}, +{u8"SA Eastern Standard Time",24}, +{u8"SA Pacific Standard Time",24}, +{u8"SA Western Standard Time",24}, +{u8"SE Asia Standard Time",21}, +{u8"Saint Pierre Standard Time",26}, +{u8"Sakhalin Standard Time",22}, +{u8"Samoa Standard Time",19}, +{u8"Sao Tome Standard Time",22}, +{u8"Saratov Standard Time",21}, +{u8"Singapore Standard Time",23}, +{u8"South Africa Standard Time",26}, +{u8"Sri Lanka Standard Time",23}, +{u8"Sudan Standard Time",19}, +{u8"Syria Standard Time",19}, +{u8"Taipei Standard Time",20}, +{u8"Tasmania Standard Time",22}, +{u8"Tocantins Standard Time",23}, +{u8"Tokyo Standard Time",19}, +{u8"Tomsk Standard Time",19}, +{u8"Tonga Standard Time",19}, +{u8"Transbaikal Standard Time",25}, +{u8"Turkey Standard Time",20}, +{u8"Turks And Caicos Standard Time",30}, +{u8"US Eastern Standard Time",24}, +{u8"US Mountain Standard Time",25}, +{u8"UTC",3}, +{u8"UTC+12",6}, +{u8"UTC+13",6}, +{u8"UTC-02",6}, +{u8"UTC-08",6}, +{u8"UTC-09",6}, +{u8"UTC-11",6}, +{u8"Ulaanbaatar Standard Time",25}, +{u8"Venezuela Standard Time",23}, +{u8"Vladivostok Standard Time",25}, +{u8"Volgograd Standard Time",23}, +{u8"W. Australia Standard Time",26}, +{u8"W. Central Africa Standard Time",31}, +{u8"W. Europe Standard Time",23}, +{u8"W. Mongolia Standard Time",25}, +{u8"West Asia Standard Time",23}, +{u8"West Bank Standard Time",23}, +{u8"West Pacific Standard Time",26}, +{u8"Yakutsk Standard Time",21} +}; + +inline constexpr basic_io_scatter_t win32_registry_timezone_ntw[] +{ +{u"AUS Central Standard Time",25}, +{u"AUS Eastern Standard Time",25}, +{u"Afghanistan Standard Time",25}, +{u"Alaskan Standard Time",21}, +{u"Aleutian Standard Time",22}, +{u"Altai Standard Time",19}, +{u"Arab Standard Time",18}, +{u"Arabian Standard Time",21}, +{u"Arabic Standard Time",20}, +{u"Argentina Standard Time",23}, +{u"Astrakhan Standard Time",23}, +{u"Atlantic Standard Time",22}, +{u"Aus Central W. Standard Time",28}, +{u"Azerbaijan Standard Time",24}, +{u"Azores Standard Time",20}, +{u"Bahia Standard Time",19}, +{u"Bangladesh Standard Time",24}, +{u"Belarus Standard Time",21}, +{u"Bougainville Standard Time",26}, +{u"Canada Central Standard Time",28}, +{u"Cape Verde Standard Time",24}, +{u"Caucasus Standard Time",22}, +{u"Cen. Australia Standard Time",28}, +{u"Central America Standard Time",29}, +{u"Central Asia Standard Time",26}, +{u"Central Brazilian Standard Time",31}, +{u"Central Europe Standard Time",28}, +{u"Central European Standard Time",30}, +{u"Central Pacific Standard Time",29}, +{u"Central Standard Time",21}, +{u"Central Standard Time (Mexico)",30}, +{u"Chatham Islands Standard Time",29}, +{u"China Standard Time",19}, +{u"Cuba Standard Time",18}, +{u"Dateline Standard Time",22}, +{u"E. Africa Standard Time",23}, +{u"E. Australia Standard Time",26}, +{u"E. Europe Standard Time",23}, +{u"E. South America Standard Time",30}, +{u"Easter Island Standard Time",27}, +{u"Eastern Standard Time",21}, +{u"Eastern Standard Time (Mexico)",30}, +{u"Egypt Standard Time",19}, +{u"Ekaterinburg Standard Time",26}, +{u"FLE Standard Time",17}, +{u"Fiji Standard Time",18}, +{u"GMT Standard Time",17}, +{u"GTB Standard Time",17}, +{u"Georgian Standard Time",22}, +{u"Greenland Standard Time",23}, +{u"Greenwich Standard Time",23}, +{u"Haiti Standard Time",19}, +{u"Hawaiian Standard Time",22}, +{u"India Standard Time",19}, +{u"Iran Standard Time",18}, +{u"Israel Standard Time",20}, +{u"Jordan Standard Time",20}, +{u"Kaliningrad Standard Time",25}, +{u"Korea Standard Time",19}, +{u"Libya Standard Time",19}, +{u"Line Islands Standard Time",26}, +{u"Lord Howe Standard Time",23}, +{u"Magadan Standard Time",21}, +{u"Magallanes Standard Time",24}, +{u"Marquesas Standard Time",23}, +{u"Mauritius Standard Time",23}, +{u"Middle East Standard Time",25}, +{u"Montevideo Standard Time",24}, +{u"Morocco Standard Time",21}, +{u"Mountain Standard Time",22}, +{u"Mountain Standard Time (Mexico)",31}, +{u"Myanmar Standard Time",21}, +{u"N. Central Asia Standard Time",29}, +{u"Namibia Standard Time",21}, +{u"Nepal Standard Time",19}, +{u"New Zealand Standard Time",25}, +{u"Newfoundland Standard Time",26}, +{u"Norfolk Standard Time",21}, +{u"North Asia East Standard Time",29}, +{u"North Asia Standard Time",24}, +{u"North Korea Standard Time",25}, +{u"Omsk Standard Time",18}, +{u"Pacific SA Standard Time",24}, +{u"Pacific Standard Time",21}, +{u"Pacific Standard Time (Mexico)",30}, +{u"Pakistan Standard Time",22}, +{u"Paraguay Standard Time",22}, +{u"Qyzylorda Standard Time",23}, +{u"Romance Standard Time",21}, +{u"Russia Time Zone 10",19}, +{u"Russia Time Zone 11",19}, +{u"Russia Time Zone 3",18}, +{u"Russian Standard Time",21}, +{u"SA Eastern Standard Time",24}, +{u"SA Pacific Standard Time",24}, +{u"SA Western Standard Time",24}, +{u"SE Asia Standard Time",21}, +{u"Saint Pierre Standard Time",26}, +{u"Sakhalin Standard Time",22}, +{u"Samoa Standard Time",19}, +{u"Sao Tome Standard Time",22}, +{u"Saratov Standard Time",21}, +{u"Singapore Standard Time",23}, +{u"South Africa Standard Time",26}, +{u"Sri Lanka Standard Time",23}, +{u"Sudan Standard Time",19}, +{u"Syria Standard Time",19}, +{u"Taipei Standard Time",20}, +{u"Tasmania Standard Time",22}, +{u"Tocantins Standard Time",23}, +{u"Tokyo Standard Time",19}, +{u"Tomsk Standard Time",19}, +{u"Tonga Standard Time",19}, +{u"Transbaikal Standard Time",25}, +{u"Turkey Standard Time",20}, +{u"Turks And Caicos Standard Time",30}, +{u"US Eastern Standard Time",24}, +{u"US Mountain Standard Time",25}, +{u"UTC",3}, +{u"UTC+12",6}, +{u"UTC+13",6}, +{u"UTC-02",6}, +{u"UTC-08",6}, +{u"UTC-09",6}, +{u"UTC-11",6}, +{u"Ulaanbaatar Standard Time",25}, +{u"Venezuela Standard Time",23}, +{u"Vladivostok Standard Time",25}, +{u"Volgograd Standard Time",23}, +{u"W. Australia Standard Time",26}, +{u"W. Central Africa Standard Time",31}, +{u"W. Europe Standard Time",23}, +{u"W. Mongolia Standard Time",25}, +{u"West Asia Standard Time",23}, +{u"West Bank Standard Time",23}, +{u"West Pacific Standard Time",26}, +{u"Yakutsk Standard Time",21} +}; + +inline constexpr basic_io_scatter_t iana_db_timezone[] +{ +{"Australia/Darwin",16}, +{"Australia/Sydney",16}, +{"Asia/Kabul",10}, +{"America/Anchorage",17}, +{"America/Adak",12}, +{"Asia/Barnaul",12}, +{"Asia/Riyadh",11}, +{"Asia/Dubai",10}, +{"Asia/Baghdad",12}, +{"America/Buenos_Aires",20}, +{"Europe/Astrakhan",16}, +{"America/Halifax",15}, +{"Australia/Eucla",15}, +{"Asia/Baku",9}, +{"Atlantic/Azores",15}, +{"America/Bahia",13}, +{"Asia/Dhaka",10}, +{"Europe/Minsk",12}, +{"Pacific/Bougainville",20}, +{"America/Regina",14}, +{"Atlantic/Cape_Verde",19}, +{"Asia/Yerevan",12}, +{"Australia/Adelaide",18}, +{"America/Guatemala",17}, +{"Asia/Almaty",11}, +{"America/Cuiaba",14}, +{"Europe/Budapest",15}, +{"Europe/Warsaw",13}, +{"Pacific/Guadalcanal",19}, +{"America/Chicago",15}, +{"America/Mexico_City",19}, +{"Pacific/Chatham",15}, +{"Asia/Shanghai",13}, +{"America/Havana",14}, +{"Etc/GMT+12",10}, +{"Africa/Nairobi",14}, +{"Australia/Brisbane",18}, +{"Europe/Chisinau",15}, +{"America/Sao_Paulo",17}, +{"Pacific/Easter",14}, +{"America/New_York",16}, +{"America/Cancun",14}, +{"Africa/Cairo",12}, +{"Asia/Yekaterinburg",18}, +{"Europe/Kiev",11}, +{"Pacific/Fiji",12}, +{"Europe/London",13}, +{"Europe/Bucharest",16}, +{"Asia/Tbilisi",12}, +{"America/Godthab",15}, +{"Atlantic/Reykjavik",18}, +{"America/Port-au-Prince",22}, +{"Pacific/Honolulu",16}, +{"Asia/Calcutta",13}, +{"Asia/Tehran",11}, +{"Asia/Jerusalem",14}, +{"Asia/Amman",10}, +{"Europe/Kaliningrad",18}, +{"Asia/Seoul",10}, +{"Africa/Tripoli",14}, +{"Pacific/Kiritimati",18}, +{"Australia/Lord_Howe",19}, +{"Asia/Magadan",12}, +{"America/Punta_Arenas",20}, +{"Pacific/Marquesas",17}, +{"Indian/Mauritius",16}, +{"Asia/Beirut",11}, +{"America/Montevideo",18}, +{"Africa/Casablanca",17}, +{"America/Denver",14}, +{"America/Chihuahua",17}, +{"Asia/Rangoon",12}, +{"Asia/Novosibirsk",16}, +{"Africa/Windhoek",15}, +{"Asia/Katmandu",13}, +{"Pacific/Auckland",16}, +{"America/St_Johns",16}, +{"Pacific/Norfolk",15}, +{"Asia/Irkutsk",12}, +{"Asia/Krasnoyarsk",16}, +{"Asia/Pyongyang",14}, +{"Asia/Omsk",9}, +{"America/Santiago",16}, +{"America/Los_Angeles",19}, +{"America/Tijuana",15}, +{"Asia/Karachi",12}, +{"America/Asuncion",16}, +{"Asia/Qyzylorda",14}, +{"Europe/Paris",12}, +{"Asia/Srednekolymsk",18}, +{"Asia/Kamchatka",14}, +{"Europe/Samara",13}, +{"Europe/Moscow",13}, +{"America/Cayenne",15}, +{"America/Bogota",14}, +{"America/La_Paz",14}, +{"Asia/Bangkok",12}, +{"America/Miquelon",16}, +{"Asia/Sakhalin",13}, +{"Pacific/Apia",12}, +{"Africa/Sao_Tome",15}, +{"Europe/Saratov",14}, +{"Asia/Singapore",14}, +{"Africa/Johannesburg",19}, +{"Asia/Colombo",12}, +{"Africa/Khartoum",15}, +{"Asia/Damascus",13}, +{"Asia/Taipei",11}, +{"Australia/Hobart",16}, +{"America/Araguaina",17}, +{"Asia/Tokyo",10}, +{"Asia/Tomsk",10}, +{"Pacific/Tongatapu",17}, +{"Asia/Chita",10}, +{"Europe/Istanbul",15}, +{"America/Grand_Turk",18}, +{"America/Indianapolis",20}, +{"America/Phoenix",15}, +{"Etc/GMT",7}, +{"Etc/GMT-12",10}, +{"Etc/GMT-13",10}, +{"Etc/GMT+2",9}, +{"Etc/GMT+8",9}, +{"Etc/GMT+9",9}, +{"Etc/GMT+11",10}, +{"Asia/Ulaanbaatar",16}, +{"America/Caracas",15}, +{"Asia/Vladivostok",16}, +{"Europe/Volgograd",16}, +{"Australia/Perth",15}, +{"Africa/Lagos",12}, +{"Europe/Berlin",13}, +{"Asia/Hovd",9}, +{"Asia/Tashkent",13}, +{"Asia/Hebron",11}, +{"Pacific/Port_Moresby",20}, +{"Asia/Yakutsk",12} +}; + +inline constexpr basic_io_scatter_t wiana_db_timezone[] +{ +{L"Australia/Darwin",16}, +{L"Australia/Sydney",16}, +{L"Asia/Kabul",10}, +{L"America/Anchorage",17}, +{L"America/Adak",12}, +{L"Asia/Barnaul",12}, +{L"Asia/Riyadh",11}, +{L"Asia/Dubai",10}, +{L"Asia/Baghdad",12}, +{L"America/Buenos_Aires",20}, +{L"Europe/Astrakhan",16}, +{L"America/Halifax",15}, +{L"Australia/Eucla",15}, +{L"Asia/Baku",9}, +{L"Atlantic/Azores",15}, +{L"America/Bahia",13}, +{L"Asia/Dhaka",10}, +{L"Europe/Minsk",12}, +{L"Pacific/Bougainville",20}, +{L"America/Regina",14}, +{L"Atlantic/Cape_Verde",19}, +{L"Asia/Yerevan",12}, +{L"Australia/Adelaide",18}, +{L"America/Guatemala",17}, +{L"Asia/Almaty",11}, +{L"America/Cuiaba",14}, +{L"Europe/Budapest",15}, +{L"Europe/Warsaw",13}, +{L"Pacific/Guadalcanal",19}, +{L"America/Chicago",15}, +{L"America/Mexico_City",19}, +{L"Pacific/Chatham",15}, +{L"Asia/Shanghai",13}, +{L"America/Havana",14}, +{L"Etc/GMT+12",10}, +{L"Africa/Nairobi",14}, +{L"Australia/Brisbane",18}, +{L"Europe/Chisinau",15}, +{L"America/Sao_Paulo",17}, +{L"Pacific/Easter",14}, +{L"America/New_York",16}, +{L"America/Cancun",14}, +{L"Africa/Cairo",12}, +{L"Asia/Yekaterinburg",18}, +{L"Europe/Kiev",11}, +{L"Pacific/Fiji",12}, +{L"Europe/London",13}, +{L"Europe/Bucharest",16}, +{L"Asia/Tbilisi",12}, +{L"America/Godthab",15}, +{L"Atlantic/Reykjavik",18}, +{L"America/Port-au-Prince",22}, +{L"Pacific/Honolulu",16}, +{L"Asia/Calcutta",13}, +{L"Asia/Tehran",11}, +{L"Asia/Jerusalem",14}, +{L"Asia/Amman",10}, +{L"Europe/Kaliningrad",18}, +{L"Asia/Seoul",10}, +{L"Africa/Tripoli",14}, +{L"Pacific/Kiritimati",18}, +{L"Australia/Lord_Howe",19}, +{L"Asia/Magadan",12}, +{L"America/Punta_Arenas",20}, +{L"Pacific/Marquesas",17}, +{L"Indian/Mauritius",16}, +{L"Asia/Beirut",11}, +{L"America/Montevideo",18}, +{L"Africa/Casablanca",17}, +{L"America/Denver",14}, +{L"America/Chihuahua",17}, +{L"Asia/Rangoon",12}, +{L"Asia/Novosibirsk",16}, +{L"Africa/Windhoek",15}, +{L"Asia/Katmandu",13}, +{L"Pacific/Auckland",16}, +{L"America/St_Johns",16}, +{L"Pacific/Norfolk",15}, +{L"Asia/Irkutsk",12}, +{L"Asia/Krasnoyarsk",16}, +{L"Asia/Pyongyang",14}, +{L"Asia/Omsk",9}, +{L"America/Santiago",16}, +{L"America/Los_Angeles",19}, +{L"America/Tijuana",15}, +{L"Asia/Karachi",12}, +{L"America/Asuncion",16}, +{L"Asia/Qyzylorda",14}, +{L"Europe/Paris",12}, +{L"Asia/Srednekolymsk",18}, +{L"Asia/Kamchatka",14}, +{L"Europe/Samara",13}, +{L"Europe/Moscow",13}, +{L"America/Cayenne",15}, +{L"America/Bogota",14}, +{L"America/La_Paz",14}, +{L"Asia/Bangkok",12}, +{L"America/Miquelon",16}, +{L"Asia/Sakhalin",13}, +{L"Pacific/Apia",12}, +{L"Africa/Sao_Tome",15}, +{L"Europe/Saratov",14}, +{L"Asia/Singapore",14}, +{L"Africa/Johannesburg",19}, +{L"Asia/Colombo",12}, +{L"Africa/Khartoum",15}, +{L"Asia/Damascus",13}, +{L"Asia/Taipei",11}, +{L"Australia/Hobart",16}, +{L"America/Araguaina",17}, +{L"Asia/Tokyo",10}, +{L"Asia/Tomsk",10}, +{L"Pacific/Tongatapu",17}, +{L"Asia/Chita",10}, +{L"Europe/Istanbul",15}, +{L"America/Grand_Turk",18}, +{L"America/Indianapolis",20}, +{L"America/Phoenix",15}, +{L"Etc/GMT",7}, +{L"Etc/GMT-12",10}, +{L"Etc/GMT-13",10}, +{L"Etc/GMT+2",9}, +{L"Etc/GMT+8",9}, +{L"Etc/GMT+9",9}, +{L"Etc/GMT+11",10}, +{L"Asia/Ulaanbaatar",16}, +{L"America/Caracas",15}, +{L"Asia/Vladivostok",16}, +{L"Europe/Volgograd",16}, +{L"Australia/Perth",15}, +{L"Africa/Lagos",12}, +{L"Europe/Berlin",13}, +{L"Asia/Hovd",9}, +{L"Asia/Tashkent",13}, +{L"Asia/Hebron",11}, +{L"Pacific/Port_Moresby",20}, +{L"Asia/Yakutsk",12} +}; + +inline constexpr basic_io_scatter_t u8iana_db_timezone[] +{ +{u8"Australia/Darwin",16}, +{u8"Australia/Sydney",16}, +{u8"Asia/Kabul",10}, +{u8"America/Anchorage",17}, +{u8"America/Adak",12}, +{u8"Asia/Barnaul",12}, +{u8"Asia/Riyadh",11}, +{u8"Asia/Dubai",10}, +{u8"Asia/Baghdad",12}, +{u8"America/Buenos_Aires",20}, +{u8"Europe/Astrakhan",16}, +{u8"America/Halifax",15}, +{u8"Australia/Eucla",15}, +{u8"Asia/Baku",9}, +{u8"Atlantic/Azores",15}, +{u8"America/Bahia",13}, +{u8"Asia/Dhaka",10}, +{u8"Europe/Minsk",12}, +{u8"Pacific/Bougainville",20}, +{u8"America/Regina",14}, +{u8"Atlantic/Cape_Verde",19}, +{u8"Asia/Yerevan",12}, +{u8"Australia/Adelaide",18}, +{u8"America/Guatemala",17}, +{u8"Asia/Almaty",11}, +{u8"America/Cuiaba",14}, +{u8"Europe/Budapest",15}, +{u8"Europe/Warsaw",13}, +{u8"Pacific/Guadalcanal",19}, +{u8"America/Chicago",15}, +{u8"America/Mexico_City",19}, +{u8"Pacific/Chatham",15}, +{u8"Asia/Shanghai",13}, +{u8"America/Havana",14}, +{u8"Etc/GMT+12",10}, +{u8"Africa/Nairobi",14}, +{u8"Australia/Brisbane",18}, +{u8"Europe/Chisinau",15}, +{u8"America/Sao_Paulo",17}, +{u8"Pacific/Easter",14}, +{u8"America/New_York",16}, +{u8"America/Cancun",14}, +{u8"Africa/Cairo",12}, +{u8"Asia/Yekaterinburg",18}, +{u8"Europe/Kiev",11}, +{u8"Pacific/Fiji",12}, +{u8"Europe/London",13}, +{u8"Europe/Bucharest",16}, +{u8"Asia/Tbilisi",12}, +{u8"America/Godthab",15}, +{u8"Atlantic/Reykjavik",18}, +{u8"America/Port-au-Prince",22}, +{u8"Pacific/Honolulu",16}, +{u8"Asia/Calcutta",13}, +{u8"Asia/Tehran",11}, +{u8"Asia/Jerusalem",14}, +{u8"Asia/Amman",10}, +{u8"Europe/Kaliningrad",18}, +{u8"Asia/Seoul",10}, +{u8"Africa/Tripoli",14}, +{u8"Pacific/Kiritimati",18}, +{u8"Australia/Lord_Howe",19}, +{u8"Asia/Magadan",12}, +{u8"America/Punta_Arenas",20}, +{u8"Pacific/Marquesas",17}, +{u8"Indian/Mauritius",16}, +{u8"Asia/Beirut",11}, +{u8"America/Montevideo",18}, +{u8"Africa/Casablanca",17}, +{u8"America/Denver",14}, +{u8"America/Chihuahua",17}, +{u8"Asia/Rangoon",12}, +{u8"Asia/Novosibirsk",16}, +{u8"Africa/Windhoek",15}, +{u8"Asia/Katmandu",13}, +{u8"Pacific/Auckland",16}, +{u8"America/St_Johns",16}, +{u8"Pacific/Norfolk",15}, +{u8"Asia/Irkutsk",12}, +{u8"Asia/Krasnoyarsk",16}, +{u8"Asia/Pyongyang",14}, +{u8"Asia/Omsk",9}, +{u8"America/Santiago",16}, +{u8"America/Los_Angeles",19}, +{u8"America/Tijuana",15}, +{u8"Asia/Karachi",12}, +{u8"America/Asuncion",16}, +{u8"Asia/Qyzylorda",14}, +{u8"Europe/Paris",12}, +{u8"Asia/Srednekolymsk",18}, +{u8"Asia/Kamchatka",14}, +{u8"Europe/Samara",13}, +{u8"Europe/Moscow",13}, +{u8"America/Cayenne",15}, +{u8"America/Bogota",14}, +{u8"America/La_Paz",14}, +{u8"Asia/Bangkok",12}, +{u8"America/Miquelon",16}, +{u8"Asia/Sakhalin",13}, +{u8"Pacific/Apia",12}, +{u8"Africa/Sao_Tome",15}, +{u8"Europe/Saratov",14}, +{u8"Asia/Singapore",14}, +{u8"Africa/Johannesburg",19}, +{u8"Asia/Colombo",12}, +{u8"Africa/Khartoum",15}, +{u8"Asia/Damascus",13}, +{u8"Asia/Taipei",11}, +{u8"Australia/Hobart",16}, +{u8"America/Araguaina",17}, +{u8"Asia/Tokyo",10}, +{u8"Asia/Tomsk",10}, +{u8"Pacific/Tongatapu",17}, +{u8"Asia/Chita",10}, +{u8"Europe/Istanbul",15}, +{u8"America/Grand_Turk",18}, +{u8"America/Indianapolis",20}, +{u8"America/Phoenix",15}, +{u8"Etc/GMT",7}, +{u8"Etc/GMT-12",10}, +{u8"Etc/GMT-13",10}, +{u8"Etc/GMT+2",9}, +{u8"Etc/GMT+8",9}, +{u8"Etc/GMT+9",9}, +{u8"Etc/GMT+11",10}, +{u8"Asia/Ulaanbaatar",16}, +{u8"America/Caracas",15}, +{u8"Asia/Vladivostok",16}, +{u8"Europe/Volgograd",16}, +{u8"Australia/Perth",15}, +{u8"Africa/Lagos",12}, +{u8"Europe/Berlin",13}, +{u8"Asia/Hovd",9}, +{u8"Asia/Tashkent",13}, +{u8"Asia/Hebron",11}, +{u8"Pacific/Port_Moresby",20}, +{u8"Asia/Yakutsk",12} +}; + +inline constexpr basic_io_scatter_t u16iana_db_timezone[] +{ +{u"Australia/Darwin",16}, +{u"Australia/Sydney",16}, +{u"Asia/Kabul",10}, +{u"America/Anchorage",17}, +{u"America/Adak",12}, +{u"Asia/Barnaul",12}, +{u"Asia/Riyadh",11}, +{u"Asia/Dubai",10}, +{u"Asia/Baghdad",12}, +{u"America/Buenos_Aires",20}, +{u"Europe/Astrakhan",16}, +{u"America/Halifax",15}, +{u"Australia/Eucla",15}, +{u"Asia/Baku",9}, +{u"Atlantic/Azores",15}, +{u"America/Bahia",13}, +{u"Asia/Dhaka",10}, +{u"Europe/Minsk",12}, +{u"Pacific/Bougainville",20}, +{u"America/Regina",14}, +{u"Atlantic/Cape_Verde",19}, +{u"Asia/Yerevan",12}, +{u"Australia/Adelaide",18}, +{u"America/Guatemala",17}, +{u"Asia/Almaty",11}, +{u"America/Cuiaba",14}, +{u"Europe/Budapest",15}, +{u"Europe/Warsaw",13}, +{u"Pacific/Guadalcanal",19}, +{u"America/Chicago",15}, +{u"America/Mexico_City",19}, +{u"Pacific/Chatham",15}, +{u"Asia/Shanghai",13}, +{u"America/Havana",14}, +{u"Etc/GMT+12",10}, +{u"Africa/Nairobi",14}, +{u"Australia/Brisbane",18}, +{u"Europe/Chisinau",15}, +{u"America/Sao_Paulo",17}, +{u"Pacific/Easter",14}, +{u"America/New_York",16}, +{u"America/Cancun",14}, +{u"Africa/Cairo",12}, +{u"Asia/Yekaterinburg",18}, +{u"Europe/Kiev",11}, +{u"Pacific/Fiji",12}, +{u"Europe/London",13}, +{u"Europe/Bucharest",16}, +{u"Asia/Tbilisi",12}, +{u"America/Godthab",15}, +{u"Atlantic/Reykjavik",18}, +{u"America/Port-au-Prince",22}, +{u"Pacific/Honolulu",16}, +{u"Asia/Calcutta",13}, +{u"Asia/Tehran",11}, +{u"Asia/Jerusalem",14}, +{u"Asia/Amman",10}, +{u"Europe/Kaliningrad",18}, +{u"Asia/Seoul",10}, +{u"Africa/Tripoli",14}, +{u"Pacific/Kiritimati",18}, +{u"Australia/Lord_Howe",19}, +{u"Asia/Magadan",12}, +{u"America/Punta_Arenas",20}, +{u"Pacific/Marquesas",17}, +{u"Indian/Mauritius",16}, +{u"Asia/Beirut",11}, +{u"America/Montevideo",18}, +{u"Africa/Casablanca",17}, +{u"America/Denver",14}, +{u"America/Chihuahua",17}, +{u"Asia/Rangoon",12}, +{u"Asia/Novosibirsk",16}, +{u"Africa/Windhoek",15}, +{u"Asia/Katmandu",13}, +{u"Pacific/Auckland",16}, +{u"America/St_Johns",16}, +{u"Pacific/Norfolk",15}, +{u"Asia/Irkutsk",12}, +{u"Asia/Krasnoyarsk",16}, +{u"Asia/Pyongyang",14}, +{u"Asia/Omsk",9}, +{u"America/Santiago",16}, +{u"America/Los_Angeles",19}, +{u"America/Tijuana",15}, +{u"Asia/Karachi",12}, +{u"America/Asuncion",16}, +{u"Asia/Qyzylorda",14}, +{u"Europe/Paris",12}, +{u"Asia/Srednekolymsk",18}, +{u"Asia/Kamchatka",14}, +{u"Europe/Samara",13}, +{u"Europe/Moscow",13}, +{u"America/Cayenne",15}, +{u"America/Bogota",14}, +{u"America/La_Paz",14}, +{u"Asia/Bangkok",12}, +{u"America/Miquelon",16}, +{u"Asia/Sakhalin",13}, +{u"Pacific/Apia",12}, +{u"Africa/Sao_Tome",15}, +{u"Europe/Saratov",14}, +{u"Asia/Singapore",14}, +{u"Africa/Johannesburg",19}, +{u"Asia/Colombo",12}, +{u"Africa/Khartoum",15}, +{u"Asia/Damascus",13}, +{u"Asia/Taipei",11}, +{u"Australia/Hobart",16}, +{u"America/Araguaina",17}, +{u"Asia/Tokyo",10}, +{u"Asia/Tomsk",10}, +{u"Pacific/Tongatapu",17}, +{u"Asia/Chita",10}, +{u"Europe/Istanbul",15}, +{u"America/Grand_Turk",18}, +{u"America/Indianapolis",20}, +{u"America/Phoenix",15}, +{u"Etc/GMT",7}, +{u"Etc/GMT-12",10}, +{u"Etc/GMT-13",10}, +{u"Etc/GMT+2",9}, +{u"Etc/GMT+8",9}, +{u"Etc/GMT+9",9}, +{u"Etc/GMT+11",10}, +{u"Asia/Ulaanbaatar",16}, +{u"America/Caracas",15}, +{u"Asia/Vladivostok",16}, +{u"Europe/Volgograd",16}, +{u"Australia/Perth",15}, +{u"Africa/Lagos",12}, +{u"Europe/Berlin",13}, +{u"Asia/Hovd",9}, +{u"Asia/Tashkent",13}, +{u"Asia/Hebron",11}, +{u"Pacific/Port_Moresby",20}, +{u"Asia/Yakutsk",12} +}; + +inline constexpr basic_io_scatter_t u32iana_db_timezone[] +{ +{U"Australia/Darwin",16}, +{U"Australia/Sydney",16}, +{U"Asia/Kabul",10}, +{U"America/Anchorage",17}, +{U"America/Adak",12}, +{U"Asia/Barnaul",12}, +{U"Asia/Riyadh",11}, +{U"Asia/Dubai",10}, +{U"Asia/Baghdad",12}, +{U"America/Buenos_Aires",20}, +{U"Europe/Astrakhan",16}, +{U"America/Halifax",15}, +{U"Australia/Eucla",15}, +{U"Asia/Baku",9}, +{U"Atlantic/Azores",15}, +{U"America/Bahia",13}, +{U"Asia/Dhaka",10}, +{U"Europe/Minsk",12}, +{U"Pacific/Bougainville",20}, +{U"America/Regina",14}, +{U"Atlantic/Cape_Verde",19}, +{U"Asia/Yerevan",12}, +{U"Australia/Adelaide",18}, +{U"America/Guatemala",17}, +{U"Asia/Almaty",11}, +{U"America/Cuiaba",14}, +{U"Europe/Budapest",15}, +{U"Europe/Warsaw",13}, +{U"Pacific/Guadalcanal",19}, +{U"America/Chicago",15}, +{U"America/Mexico_City",19}, +{U"Pacific/Chatham",15}, +{U"Asia/Shanghai",13}, +{U"America/Havana",14}, +{U"Etc/GMT+12",10}, +{U"Africa/Nairobi",14}, +{U"Australia/Brisbane",18}, +{U"Europe/Chisinau",15}, +{U"America/Sao_Paulo",17}, +{U"Pacific/Easter",14}, +{U"America/New_York",16}, +{U"America/Cancun",14}, +{U"Africa/Cairo",12}, +{U"Asia/Yekaterinburg",18}, +{U"Europe/Kiev",11}, +{U"Pacific/Fiji",12}, +{U"Europe/London",13}, +{U"Europe/Bucharest",16}, +{U"Asia/Tbilisi",12}, +{U"America/Godthab",15}, +{U"Atlantic/Reykjavik",18}, +{U"America/Port-au-Prince",22}, +{U"Pacific/Honolulu",16}, +{U"Asia/Calcutta",13}, +{U"Asia/Tehran",11}, +{U"Asia/Jerusalem",14}, +{U"Asia/Amman",10}, +{U"Europe/Kaliningrad",18}, +{U"Asia/Seoul",10}, +{U"Africa/Tripoli",14}, +{U"Pacific/Kiritimati",18}, +{U"Australia/Lord_Howe",19}, +{U"Asia/Magadan",12}, +{U"America/Punta_Arenas",20}, +{U"Pacific/Marquesas",17}, +{U"Indian/Mauritius",16}, +{U"Asia/Beirut",11}, +{U"America/Montevideo",18}, +{U"Africa/Casablanca",17}, +{U"America/Denver",14}, +{U"America/Chihuahua",17}, +{U"Asia/Rangoon",12}, +{U"Asia/Novosibirsk",16}, +{U"Africa/Windhoek",15}, +{U"Asia/Katmandu",13}, +{U"Pacific/Auckland",16}, +{U"America/St_Johns",16}, +{U"Pacific/Norfolk",15}, +{U"Asia/Irkutsk",12}, +{U"Asia/Krasnoyarsk",16}, +{U"Asia/Pyongyang",14}, +{U"Asia/Omsk",9}, +{U"America/Santiago",16}, +{U"America/Los_Angeles",19}, +{U"America/Tijuana",15}, +{U"Asia/Karachi",12}, +{U"America/Asuncion",16}, +{U"Asia/Qyzylorda",14}, +{U"Europe/Paris",12}, +{U"Asia/Srednekolymsk",18}, +{U"Asia/Kamchatka",14}, +{U"Europe/Samara",13}, +{U"Europe/Moscow",13}, +{U"America/Cayenne",15}, +{U"America/Bogota",14}, +{U"America/La_Paz",14}, +{U"Asia/Bangkok",12}, +{U"America/Miquelon",16}, +{U"Asia/Sakhalin",13}, +{U"Pacific/Apia",12}, +{U"Africa/Sao_Tome",15}, +{U"Europe/Saratov",14}, +{U"Asia/Singapore",14}, +{U"Africa/Johannesburg",19}, +{U"Asia/Colombo",12}, +{U"Africa/Khartoum",15}, +{U"Asia/Damascus",13}, +{U"Asia/Taipei",11}, +{U"Australia/Hobart",16}, +{U"America/Araguaina",17}, +{U"Asia/Tokyo",10}, +{U"Asia/Tomsk",10}, +{U"Pacific/Tongatapu",17}, +{U"Asia/Chita",10}, +{U"Europe/Istanbul",15}, +{U"America/Grand_Turk",18}, +{U"America/Indianapolis",20}, +{U"America/Phoenix",15}, +{U"Etc/GMT",7}, +{U"Etc/GMT-12",10}, +{U"Etc/GMT-13",10}, +{U"Etc/GMT+2",9}, +{U"Etc/GMT+8",9}, +{U"Etc/GMT+9",9}, +{U"Etc/GMT+11",10}, +{U"Asia/Ulaanbaatar",16}, +{U"America/Caracas",15}, +{U"Asia/Vladivostok",16}, +{U"Europe/Volgograd",16}, +{U"Australia/Perth",15}, +{U"Africa/Lagos",12}, +{U"Europe/Berlin",13}, +{U"Asia/Hovd",9}, +{U"Asia/Tashkent",13}, +{U"Asia/Hebron",11}, +{U"Pacific/Port_Moresby",20}, +{U"Asia/Yakutsk",12} +}; diff --git a/src/fast_io/include/fast_io_hosted/timeutil/win32_timezone.h b/src/fast_io/include/fast_io_hosted/timeutil/win32_timezone.h new file mode 100644 index 0000000..5db674b --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/timeutil/win32_timezone.h @@ -0,0 +1,187 @@ +#pragma once + +namespace fast_io +{ + +struct win32_timezone_name +{ + std::size_t position{183}; +}; + +enum win32_timezone_family +{ +registry, +gettimezoneinformation, +#ifdef __BIONIC__ +//Intel pintool does not support registry api +native = gettimezoneinformation +#else +native = registry +#endif +}; + +namespace win32::details +{ +#include"win32_regtz_to_ianatz.h" + +struct win32_registry_guard +{ + ::std::uintptr_t k; + explicit constexpr win32_registry_guard(::std::uintptr_t k1) noexcept:k(k1){} + win32_registry_guard(win32_registry_guard const&)=delete; + win32_registry_guard& operator=(win32_registry_guard const&)=delete; + ~win32_registry_guard() + { + ::fast_io::win32::RegCloseKey(k); + } +}; + +template +requires (::std::same_as||::std::same_as) +inline constexpr win32_timezone_name find_win32_regtz_position_impl(T const* str,std::size_t len) noexcept +{ + ::fast_io::basic_io_scatter_t scatter{str,len}; + ::fast_io::basic_io_scatter_t const* first; + ::fast_io::basic_io_scatter_t const* last; + if constexpr(::std::same_as) + { + first = win32_registry_timezone_ntw; + last = win32_registry_timezone_ntw+::std::ranges::size(win32_registry_timezone_ntw); + } + else + { + first = win32_registry_timezone_9xa; + last = win32_registry_timezone_9xa+::std::ranges::size(win32_registry_timezone_9xa); + } + auto it{::fast_io::freestanding::lower_bound(first,last, + scatter, + [](::fast_io::basic_io_scatter_t const& a,::fast_io::basic_io_scatter_t const& b) + { + return ::fast_io::freestanding::lexicographical_compare(a.base,a.base+a.len,b.base,b.base+b.len); + })}; + if(it==last) + { + return {}; + } + if(!::fast_io::freestanding::equal(it->base,it->base+it->len,str,str+len)) + { + return {}; + } + return {static_cast(it-first)}; +} + +template +inline win32_timezone_name win32_localtimezone_impl() noexcept +{ + using api_char_type = std::conditional_t; + if constexpr(tzfamily == win32_timezone_family::gettimezoneinformation) + { + static_assert(tzfamily != win32_timezone_family::gettimezoneinformation + || family!=win32_family::ansi_9x); + ::fast_io::win32::time_zone_information tzi{}; + ::std::uint_least32_t retval{::fast_io::win32::GetTimeZoneInformation(__builtin_addressof(tzi))}; + if(retval==UINT_LEAST32_MAX) + { + throw_win32_error(); + } + std::size_t const standardnamesize{::fast_io::cstr_nlen(tzi.StandardName,sizeof(tzi.StandardName))}; + return ::fast_io::win32::details::find_win32_regtz_position_impl(tzi.StandardName,standardnamesize); + } + else + { + ::std::uintptr_t k; + ::std::int_least32_t win32retcode; + if constexpr(family==win32_family::ansi_9x) + { + win32retcode=::fast_io::win32::RegOpenKeyA(0x80000002 /*HKEY_LOCAL_MACHINE*/,u8"SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation",__builtin_addressof(k)); + } + else + { + win32retcode=::fast_io::win32::RegOpenKeyW(0x80000002 /*HKEY_LOCAL_MACHINE*/,u"SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation",__builtin_addressof(k)); + } + if(win32retcode) + { + return {}; + } + constexpr + ::std::size_t n{128}; + api_char_type buffer[n]; + constexpr std::uint_least32_t bfbytes{n*sizeof(api_char_type)}; + ::std::uint_least32_t cbdata{bfbytes}; + { + ::fast_io::win32::details::win32_registry_guard guard(k); + if constexpr(family==win32_family::ansi_9x) + { + win32retcode=::fast_io::win32::RegQueryValueExA(k,u8"TimeZoneKeyName",nullptr,nullptr,buffer,__builtin_addressof(cbdata)); + } + else + { + win32retcode=::fast_io::win32::RegQueryValueExW(k,u"TimeZoneKeyName",nullptr,nullptr,buffer,__builtin_addressof(cbdata)); + } + if(win32retcode) + { + cbdata=bfbytes; + if constexpr(family==win32_family::ansi_9x) + { + win32retcode=::fast_io::win32::RegQueryValueExA(k,u8"StandardName",nullptr,nullptr,buffer,__builtin_addressof(cbdata)); + } + else + { + win32retcode=::fast_io::win32::RegQueryValueExW(k,u"StandardName",nullptr,nullptr,buffer,__builtin_addressof(cbdata)); + } + if(win32retcode) + { + return {}; + } + } + } + if constexpr(sizeof(api_char_type)!=1u) + { + cbdata/=sizeof(api_char_type); + } + if(!cbdata) + { + return {}; + } + std::size_t const stringlen{static_cast(cbdata-1u)}; + return ::fast_io::win32::details::find_win32_regtz_position_impl(buffer,stringlen); + } +} + +} + +template +struct basic_win32_family_local_timezone +{ + inline win32_timezone_name operator()() noexcept + { + return ::fast_io::win32::details::win32_localtimezone_impl(); + } +}; + +template +using basic_win32_local_timezone = basic_win32_family_local_timezone; +using win32_local_timezone_9xa = basic_win32_local_timezone<::fast_io::win32_family::ansi_9x>; +using win32_local_timezone_ntw = basic_win32_local_timezone<::fast_io::win32_family::wide_nt>; +using win32_local_timezone = basic_win32_local_timezone<::fast_io::win32_family::native>; + +#ifndef __CYGWIN__ +using native_local_timezone = win32_local_timezone; +#endif + +template +inline constexpr basic_io_scatter_t status_io_print_forward(io_alias_type_t,win32_timezone_name tzn) noexcept +{ + if constexpr(::std::same_as) + return ::fast_io::win32::details::iana_db_timezone[tzn.position]; + else if constexpr(::std::same_as) + return ::fast_io::win32::details::wiana_db_timezone[tzn.position]; + else if constexpr(::std::same_as) + return ::fast_io::win32::details::u16iana_db_timezone[tzn.position]; + else if constexpr(::std::same_as) + return ::fast_io::win32::details::u32iana_db_timezone[tzn.position]; + else + return ::fast_io::win32::details::u8iana_db_timezone[tzn.position]; +} + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_hosted/white_hole/linux_getrandom.h b/src/fast_io/include/fast_io_hosted/white_hole/linux_getrandom.h new file mode 100644 index 0000000..052b113 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/white_hole/linux_getrandom.h @@ -0,0 +1,51 @@ +#pragma once +#if !(defined(__linux__) && defined(__NR_getrandom)) && __has_include() +#include +#endif + +namespace fast_io +{ + +template +class basic_linux_getrandom +{ +public: + using char_type = ch_type; + unsigned flags{}; + constexpr void close() noexcept{} +}; + +template +inline constexpr basic_linux_getrandom io_value_handle(basic_linux_getrandom brg) noexcept +{ + return brg; +} + +namespace details +{ +inline std::size_t linux_getrandom_read(void* ptr,std::size_t sz,unsigned flags) +{ +#if defined(__linux__) && defined(__NR_getrandom) + auto ret{system_call<__NR_getrandom,std::ptrdiff_t>(ptr,sz,flags)}; + system_call_throw_error(ret); +#else + auto ret{noexcept_call(getrandom,ptr,sz,flags)}; + if(ret<0) + throw_posix_error(); +#endif + return static_cast(ret); +} +} + +template +inline Iter read(basic_linux_getrandom g,Iter bg,Iter ed) +{ + return bg+::fast_io::details::linux_getrandom_read(::std::to_address(bg),static_cast(ed-bg)*sizeof(*bg),g.flags)/sizeof(*bg); +} + +using linux_getrandom = basic_linux_getrandom; + +template +inline constexpr void require_secure_clear(basic_linux_getrandom){} + +} diff --git a/src/fast_io/include/fast_io_hosted/white_hole/posix_dev_urandom.h b/src/fast_io/include/fast_io_hosted/white_hole/posix_dev_urandom.h new file mode 100644 index 0000000..c5445cf --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/white_hole/posix_dev_urandom.h @@ -0,0 +1,53 @@ +#pragma once + +namespace fast_io +{ + +template +class posix_dev_urandom +{ +public: + using native_handle_type = T; + using char_type = typename native_handle_type::char_type; + native_handle_type device; + template + requires ((sizeof...(Args)!=0)&&std::constructible_from) + constexpr posix_dev_urandom(Args&& ...args):device(::std::forward(args)...){} + constexpr posix_dev_urandom():device(u8"/dev/urandom",fast_io::open_mode::in){} + constexpr auto& native_handle() noexcept + { + return device; + } + constexpr auto& native_handle() const noexcept + { + return device; + } + constexpr void close() requires(closable_stream) + { + device.close(); + } +}; + +template +inline constexpr Iter read(posix_dev_urandom& t,Iter begin,Iter end) +{ + return read(t.device,begin,end); +} + +template +inline constexpr auto scatter_read(posix_dev_urandom& t,io_scatters_t scatters) +{ + return scatter_read(t.device,scatters); +} + +template +inline constexpr void require_secure_clear(posix_dev_urandom&){} + +template +requires ::fast_io::details::has_entroy_method_impl +inline constexpr auto random_entropy(posix_dev_urandom const& pu) noexcept +{ + return random_entropy(pu.device); +} + +} diff --git a/src/fast_io/include/fast_io_hosted/white_hole/rtl_gen_random.h b/src/fast_io/include/fast_io_hosted/white_hole/rtl_gen_random.h new file mode 100644 index 0000000..ad291ae --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/white_hole/rtl_gen_random.h @@ -0,0 +1,79 @@ +#pragma once + +namespace fast_io +{ + +#if defined(_MSC_VER) && !defined(_KERNEL_MODE) +#pragma comment(lib,"advapi32.lib") +#endif + +template +class basic_rtl_gen_random +{ +public: + using char_type = ch_type; + constexpr void close() noexcept{} +}; + +namespace win32 +{ + +namespace details +{ +inline void rtl_gen_random_read_u32(void* ptr,std::size_t sz) +{ + if(!SystemFunction036(ptr,static_cast(sz))) + throw_win32_error(); +} + +inline std::size_t rtl_gen_random_read(void* ptr,std::size_t sz) +{ + std::byte *base_ptr{reinterpret_cast(ptr)}; + std::byte *iter{base_ptr}; + while(sz) + { + constexpr std::size_t uintleast32mx{static_cast(UINT_LEAST32_MAX)}; + std::size_t mn{sz}; + if(uintleast32mx(mn))) + { + if(base_ptr==iter) + throw_win32_error(); + break; + } + sz-=mn; + iter+=mn; + } + return static_cast(iter-base_ptr); +} +} +} + +template +inline Iter read(basic_rtl_gen_random,Iter bg,Iter ed) +{ + if constexpr(sizeof(std::uint_least32_t)(ed-bg)*sizeof(*bg))}; + return bg+(ret/sizeof(*bg)); + } + else + { + win32::details::rtl_gen_random_read_u32(::std::to_address(bg),static_cast(ed-bg)*sizeof(*bg)); + return ed; + } +} + +template +inline constexpr basic_rtl_gen_random io_value_handle(basic_rtl_gen_random brg) noexcept +{ + return brg; +} + +using rtl_gen_random = basic_rtl_gen_random; + +template +inline constexpr void require_secure_clear(basic_rtl_gen_random) noexcept{} + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_hosted/white_hole/wasi_random_get.h b/src/fast_io/include/fast_io_hosted/white_hole/wasi_random_get.h new file mode 100644 index 0000000..c060cf8 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/white_hole/wasi_random_get.h @@ -0,0 +1,84 @@ +#pragma once + +namespace fast_io +{ +namespace details +{ + +inline void wasi_random_get_full_impl(void* ptr,std::size_t sz) +{ + using u8ptr_may_alias +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = std::uint_least8_t*; + auto ret{::fast_io::noexcept_call(__wasi_random_get,reinterpret_cast(ptr),static_cast<__wasi_size_t>(sz))}; + if(ret) + throw_posix_error(ret); +} + +inline std::size_t wasi_random_get_impl(void* ptr,std::size_t sz) +{ + using u8ptr_may_alias +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = std::uint_least8_t*; + static_assert(std::unsigned_integral<__wasi_size_t>); + u8ptr_may_alias base_ptr{reinterpret_cast(ptr)}; + u8ptr_may_alias iter{base_ptr}; + while(sz) + { + constexpr std::size_t sz_max{static_cast(SIZE_MAX)}; + __wasi_size_t mn{sz}; + if(sz_max(iter-base_ptr); +} +} + +template +class basic_wasi_random_get +{ +public: + using char_type = ch_type; + constexpr void close() noexcept{} +}; + +template +inline Iter read(basic_wasi_random_get,Iter bg,Iter ed) +{ + if constexpr(sizeof(__wasi_size_t)(ed-bg)*sizeof(*bg))}; + return bg+(sz/sizeof(*bg)); + } + else + { + ::fast_io::details::wasi_random_get_full_impl(::std::to_address(bg),static_cast(ed-bg)*sizeof(*bg)); + return ed; + } +} + +template +inline constexpr basic_wasi_random_get io_value_handle(basic_wasi_random_get brg) noexcept +{ + return brg; +} + +using wasi_random_get = basic_wasi_random_get; + +template +inline constexpr void require_secure_clear(basic_wasi_random_get){} + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_hosted/white_hole/white_hole.h b/src/fast_io/include/fast_io_hosted/white_hole/white_hole.h new file mode 100644 index 0000000..6fc80a3 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/white_hole/white_hole.h @@ -0,0 +1,126 @@ +#pragma once +#if (defined(_WIN32)&&!defined(__WINE__)) || defined(__CYGWIN__) +#include"rtl_gen_random.h" +#include"win32_crypt_gen_random.h" +#endif +#if defined(__wasi__) +#include"wasi_random_get.h" +#endif + +namespace fast_io::details +{ +template +concept has_entroy_method_impl = requires(T&& handle) +{ + {random_entropy(handle)}->std::convertible_to; +}; +} +#if ((defined(__linux__) && defined(__NR_getrandom)) || (!defined(__linux__)&&__has_include())) && !defined(__wasi__) && !defined(__DARWIN_C_LEVEL) +#include"linux_getrandom.h" +#endif +#include"posix_dev_urandom.h" + +namespace fast_io +{ +#if (defined(_WIN32)&&!defined(__WINE__)&& (defined(RNDGETENTCNT))) || defined(__linux__) +namespace details +{ +#if defined(RNDGETENTCNT) || defined(__linux__) +inline int my_random_entropy(int fd) noexcept +{ + int ent{}; +#if defined(__linux__) && defined(__NR_ioctl) + if(system_call<__NR_ioctl,std::ptrdiff_t>(fd,static_cast(u8'R')<<8u,__builtin_addressof(ent))!=0) + return 0.0; +#else + if(::fast_io::posix::ioctl(fd,RNDGETENTCNT,__builtin_addressof(ent))!=0) + return 0.0; +#endif + return ent; +} +#endif +} + +template +inline int random_entropy(basic_posix_io_observer piob) noexcept +{ + return ::fast_io::details::my_random_entropy(piob.fd); +} +#endif + +template +using basic_native_white_hole = +#if defined(_WIN32)&&!defined(__WINE__) +#if defined(_WIN32_WINDOWS) || (defined(_WIN32_WINNT)&&_WIN32_WINNT <= 0x0500) +basic_win32_crypt_gen_random_file; +#else +basic_rtl_gen_random; +#endif +#elif defined(__wasi__) +basic_wasi_random_get; +#elif (defined(__linux__) && defined(__NR_getrandom)) || (!defined(__linux__)&&__has_include()) && !defined(__DARWIN_C_LEVEL) +basic_linux_getrandom; +#else +posix_dev_urandom>; +#endif + +template +using basic_ibuf_white_hole = basic_io_buffer,buffer_mode::in|buffer_mode::secure_clear,basic_decorators,4096u>; + +using native_white_hole = basic_native_white_hole; +using ibuf_white_hole = basic_ibuf_white_hole; + +using wnative_white_hole = basic_native_white_hole; +using wibuf_white_hole = basic_ibuf_white_hole; + +using u8native_white_hole = basic_native_white_hole; +using u8ibuf_white_hole = basic_ibuf_white_hole; + +using u16native_white_hole = basic_native_white_hole; +using u16ibuf_white_hole = basic_ibuf_white_hole; + +using u32native_white_hole = basic_native_white_hole; +using u32ibuf_white_hole = basic_ibuf_white_hole; + +template +requires std::same_as,char> +struct basic_white_hole_engine +{ + using handle_type = handletype; + using result_type = std::size_t; + handle_type handle; + static inline constexpr result_type min() noexcept + { + return 0; + } + static inline constexpr result_type max() noexcept + { + return SIZE_MAX; + } + inline constexpr double entropy() const noexcept + { + if constexpr(::fast_io::details::has_entroy_method_impl) + { + auto v{random_entropy(handle)}; + constexpr std::size_t mx_value{static_cast(::std::numeric_limits<::std::size_t>::digits)}; + if(v>mx_value) + v=mx_value; + return static_cast(v); + } + else + { + return 0.0; + } + } + inline constexpr result_type operator()() + { + result_type type; + ::fast_io::read_all(handle,__builtin_addressof(type),__builtin_addressof(type)+1); + return type; + } +}; + +using native_white_hole_engine = basic_white_hole_engine; +using ibuf_white_hole_engine = basic_white_hole_engine; + +} diff --git a/src/fast_io/include/fast_io_hosted/white_hole/win32_crypt_gen_random.h b/src/fast_io/include/fast_io_hosted/white_hole/win32_crypt_gen_random.h new file mode 100644 index 0000000..261b7c3 --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/white_hole/win32_crypt_gen_random.h @@ -0,0 +1,135 @@ +#pragma once + +namespace fast_io +{ + +template +class basic_win32_crypt_gen_random_io_observer +{ +public: + using native_handle_type = std::uintptr_t; + using char_type = ch_type; + native_handle_type hprov{}; + inline constexpr native_handle_type native_handle() const noexcept + { + return hprov; + } + inline constexpr native_handle_type release() noexcept + { + auto tmp{hprov}; + hprov=0; + return tmp; + } +}; + +template +inline constexpr basic_win32_crypt_gen_random_io_observer io_value_handle(basic_win32_crypt_gen_random_io_observer giob) noexcept +{ + return giob; +} + +template +inline constexpr void require_secure_clear(basic_win32_crypt_gen_random_io_observer) noexcept{} + +namespace win32::details +{ + +inline void win32_crypt_gen_random_read_u32(std::uintptr_t hprov,void* ptr,std::size_t sz) +{ + if(!::fast_io::win32::CryptGenRandom(hprov,static_cast(sz),reinterpret_cast(ptr))) + { + throw_win32_error(); + } +} + +inline std::size_t win32_crypt_gen_random_read(std::uintptr_t hprov,void* ptr,std::size_t sz) +{ + std::byte *base_ptr{reinterpret_cast(ptr)}; + std::byte *iter{base_ptr}; + while(sz) + { + constexpr std::size_t ul32_max{static_cast(UINT_LEAST32_MAX)}; + std::size_t mn{sz}; + if(ul32_max(mn),reinterpret_cast(iter))) + { + if(base_ptr==iter) + throw_win32_error(); + break; + } + sz-=mn; + iter+=mn; + } + return static_cast(iter-base_ptr); +} + +} + +template +inline Iter read(basic_win32_crypt_gen_random_io_observer hp,Iter bg,Iter ed) +{ + if constexpr(sizeof(std::uint_least32_t)(ed-bg)*sizeof(*bg))}; + return bg+(ret/sizeof(*bg)); + } + else + { + win32::details::win32_crypt_gen_random_read_u32(hp.hprov,::std::to_address(bg),static_cast(ed-bg)*sizeof(*bg)); + return ed; + } +} + +template +class basic_win32_family_crypt_gen_random_file:public basic_win32_crypt_gen_random_io_observer +{ +public: + using native_handle_type = std::uintptr_t; + using char_type = ch_type; + basic_win32_family_crypt_gen_random_file():basic_win32_crypt_gen_random_io_observer{::fast_io::details::win32::crypt_acquire_context_fallback()}{} + constexpr basic_win32_family_crypt_gen_random_file(::std::nullptr_t):basic_win32_crypt_gen_random_io_observer{} + {} + basic_win32_family_crypt_gen_random_file(basic_win32_family_crypt_gen_random_file const&)=delete; + basic_win32_family_crypt_gen_random_file& operator=(basic_win32_family_crypt_gen_random_file const&)=delete; + constexpr basic_win32_family_crypt_gen_random_file(basic_win32_family_crypt_gen_random_file&& __restrict other) noexcept: + basic_win32_crypt_gen_random_io_observer{other.hprov} + { + other.hprov=0; + } + basic_win32_family_crypt_gen_random_file& operator=(basic_win32_family_crypt_gen_random_file&& __restrict other) noexcept + { + if(this->hprov)[[likely]] + { + ::fast_io::win32::CryptReleaseContext(this->hprov,0); + } + this->hprov=other.hprov; + other.hprov=0; + return *this; + } + + ~basic_win32_family_crypt_gen_random_file() + { + if(!this->hprov)[[likely]] + { + ::fast_io::win32::CryptReleaseContext(this->hprov,0); + } + } + void close() + { + if(this->hprov)[[likely]] + { + if(!::fast_io::win32::CryptReleaseContext(this->hprov,0)) + throw_win32_error(); + } + } +}; + +template +using basic_win32_crypt_gen_random_file_9xa = basic_win32_family_crypt_gen_random_file; +template +using basic_win32_crypt_gen_random_file_ntw = basic_win32_family_crypt_gen_random_file; +template +using basic_win32_crypt_gen_random_file = basic_win32_family_crypt_gen_random_file; + +} diff --git a/src/fast_io/include/fast_io_hosted/wrapper.h b/src/fast_io/include/fast_io_hosted/wrapper.h new file mode 100644 index 0000000..2525bdf --- /dev/null +++ b/src/fast_io/include/fast_io_hosted/wrapper.h @@ -0,0 +1,37 @@ +#pragma once + +namespace fast_io +{ + +template +struct basic_file_wrapper:public T +{ + using typename T::char_type; + using typename T::native_handle_type; + using typename T::file_factory_type; + constexpr basic_file_wrapper() noexcept=default; + template + requires std::same_as> + explicit constexpr basic_file_wrapper(native_hd hd) noexcept:T(hd){} + explicit constexpr basic_file_wrapper(file_factory_type&& factory) noexcept:T(static_cast(factory)){} + constexpr basic_file_wrapper(native_fs_dirent fsdirent,open_mode m=interface_mode,perms p=static_cast(436)): + T(fsdirent,m|interface_mode,p){} + + template<::fast_io::constructible_to_os_c_str pathtype> + explicit constexpr basic_file_wrapper(pathtype const& filename,open_mode om=interface_mode,perms pm=static_cast(436)):T(filename,om|interface_mode,pm){} + template<::fast_io::constructible_to_os_c_str pathtype> + explicit constexpr basic_file_wrapper(native_at_entry nate,pathtype const& filename,open_mode om=interface_mode,perms pm=static_cast(436)):T(nate,filename,om|interface_mode,pm){} + + explicit constexpr basic_file_wrapper(io_temp_t):T(io_temp){} +}; + +template +using input_file_wrapper = basic_file_wrapper; +template +using output_file_wrapper = basic_file_wrapper; + +template +using directory_file_wrapper = basic_file_wrapper; + + +} diff --git a/src/fast_io/include/fast_io_hosted_crypto.h b/src/fast_io/include/fast_io_hosted_crypto.h new file mode 100644 index 0000000..e0d8a1a --- /dev/null +++ b/src/fast_io/include/fast_io_hosted_crypto.h @@ -0,0 +1,33 @@ +#pragma once + +#if !defined(__cplusplus) +#error "You are not using a C++ compiler" +#endif + +#if !defined(__cpp_concepts) +#error "fast_io requires at least C++20 standard compiler." +#else + +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning(push) +#pragma warning( disable : 4061 ) +#pragma warning( disable : 4514 ) +#pragma warning( disable : 4623 ) +#pragma warning( disable : 4626 ) +#pragma warning( disable : 4668 ) +#pragma warning( disable : 4710 ) +#pragma warning( disable : 4820 ) +#pragma warning( disable : 5027 ) +#pragma warning( disable : 5045 ) +#endif + +#if ((__STDC_HOSTED__==1 && (!defined(_GLIBCXX_HOSTED) || _GLIBCXX_HOSTED==1) && !defined(_LIBCPP_FREESTANDING)) || defined(FAST_IO_ENABLE_HOSTED_FEATURES)) +#include"fast_io_hosted.h" +#include"fast_io_crypto/platforms/impl.h" +#endif + +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning(pop) +#endif + +#endif diff --git a/src/fast_io/include/fast_io_i18n.h b/src/fast_io/include/fast_io_i18n.h new file mode 100644 index 0000000..13f07a2 --- /dev/null +++ b/src/fast_io/include/fast_io_i18n.h @@ -0,0 +1,43 @@ +#pragma once +#if !defined(__cplusplus) +#error "You are not using a C++ compiler" +#endif + +#if !defined(__cpp_concepts) +#error "fast_io requires at least C++20 standard compiler." +#else +#include"fast_io_hosted.h" + +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning(push) +#pragma warning( disable : 4514 ) +#pragma warning( disable : 4623 ) +#pragma warning( disable : 4668 ) +#pragma warning( disable : 4710 ) +#pragma warning( disable : 4711 ) +#pragma warning( disable : 4820 ) +#pragma warning( disable : 5045 ) +#endif +#include"fast_io_i18n/lc.h" +#include"fast_io_i18n/lc_print.h" +#if ((__STDC_HOSTED__==1 && (!defined(_GLIBCXX_HOSTED) || _GLIBCXX_HOSTED==1) && !defined(_LIBCPP_FREESTANDING)) || defined(FAST_IO_ENABLE_HOSTED_FEATURES)) +#include"fast_io_i18n/locale/impl.h" +#endif +#include"fast_io_i18n/imbuer.h" +#include"fast_io_i18n/lc_print_status.h" +#include"fast_io_i18n/lc_numbers/impl.h" + +#if ((__STDC_HOSTED__==1 && (!defined(_GLIBCXX_HOSTED) || _GLIBCXX_HOSTED==1) && !defined(_LIBCPP_FREESTANDING)) || defined(FAST_IO_ENABLE_HOSTED_FEATURES)) +#if defined(_GLIBCXX_STRING) || defined(_LIBCPP_STRING) || defined(_STRING_) +#include"fast_io_unit/string.h" +#include"fast_io_unit/string_impl/lc_concat.h" +#endif +#endif +#endif + +#ifndef FAST_IO_DISABLE_FLOATING_POINT +#include"fast_io_unit/floating/lc_impl.h" +#endif +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning(pop) +#endif diff --git a/src/fast_io/include/fast_io_i18n/imbuer.h b/src/fast_io/include/fast_io_i18n/imbuer.h new file mode 100644 index 0000000..4c2a6e3 --- /dev/null +++ b/src/fast_io/include/fast_io_i18n/imbuer.h @@ -0,0 +1,43 @@ +#pragma once + +namespace fast_io +{ + +template +requires (value_based_stream&&requires(stm sm) +{ + {io_value_handle(sm)}->std::same_as; +}&&std::is_trivially_copyable_v) +struct lc_imbuer +{ + using handle_type = stm; + using char_type = typename handle_type::char_type; + using lc_all_type = basic_lc_all; + lc_all_type const* all{}; +#ifndef __INTELLISENSE__ +#if __has_cpp_attribute(msvc::no_unique_address) +[[msvc::no_unique_address]] +#elif __has_cpp_attribute(no_unique_address) >= 201803 +[[no_unique_address]] +#endif +#endif + handle_type handle{}; +}; + +template +inline constexpr lc_imbuer io_value_handle(lc_imbuer sm) noexcept +{ + return sm; +} + +template +requires (std::is_lvalue_reference_v||std::is_trivially_copyable_v) +inline constexpr auto imbue(basic_lc_all::char_type> const* all,stm&& out) noexcept +{ + if constexpr(value_based_stream) + return lc_imbuer{all,io_value_handle(out)}; + else + return lc_imbuer{all,io_ref(out)}; +} + +} diff --git a/src/fast_io/include/fast_io_i18n/iso14651.h b/src/fast_io/include/fast_io_i18n/iso14651.h new file mode 100644 index 0000000..a5687a1 --- /dev/null +++ b/src/fast_io/include/fast_io_i18n/iso14651.h @@ -0,0 +1,24 @@ +#pragma once + +/* +TO DO +*/ + +namespace fast_io::char_category +{ + +using charmax_t = char32_t; + +inline constexpr bool is_iso14651_space(charmax_t ch) noexcept +{ + switch(ch) + { +case 0x9:case 0xA:case 0xB:case 0xC:case 0xD:case 0x20: +case 0x1680:case 0x2000:case 0x2001:case 0x2002:case 0x2003: +case 0x2004:case 0x2005:case 0x2006:case 0x2008:case 0x2009: +case 0x200A:case 0x2028:case 0x2029:case 0x205F:case 0x3000: + return true; + default:return false; + }; +} +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_i18n/lc.h b/src/fast_io/include/fast_io_i18n/lc.h new file mode 100644 index 0000000..39c4db0 --- /dev/null +++ b/src/fast_io/include/fast_io_i18n/lc.h @@ -0,0 +1,290 @@ +#pragma once + +namespace fast_io +{ + +template +struct basic_lc_identification +{ + basic_io_scatter_t name{}; + basic_io_scatter_t encoding{}; + basic_io_scatter_t title{}; + basic_io_scatter_t source{}; + basic_io_scatter_t address{}; + basic_io_scatter_t contact{}; + basic_io_scatter_t email{}; + basic_io_scatter_t tel{}; + basic_io_scatter_t fax{}; + basic_io_scatter_t language{}; + basic_io_scatter_t territory{}; + basic_io_scatter_t audience{}; + basic_io_scatter_t application{}; + basic_io_scatter_t abbreviation{}; + basic_io_scatter_t revision{}; + basic_io_scatter_t date{}; +}; + +using lc_identification=basic_lc_identification; +using wlc_identification=basic_lc_identification; +using u8lc_identification=basic_lc_identification; +using u16lc_identification=basic_lc_identification; +using u32lc_identification=basic_lc_identification; + +template +struct basic_lc_monetary +{ + basic_io_scatter_t int_curr_symbol{}; + basic_io_scatter_t currency_symbol{}; + basic_io_scatter_t mon_decimal_point{}; + basic_io_scatter_t mon_thousands_sep{}; + basic_io_scatter_t mon_grouping{}; + basic_io_scatter_t positive_sign{}; + basic_io_scatter_t negative_sign{}; + std::size_t int_frac_digits{}; + std::size_t frac_digits{}; + std::size_t p_cs_precedes{}; + std::size_t p_sep_by_space{}; + std::size_t n_cs_precedes{}; + std::size_t n_sep_by_space{}; + std::size_t int_p_cs_precedes{}; + std::size_t int_p_sep_by_space{}; + std::size_t int_n_cs_precedes{}; + std::size_t int_n_sep_by_space{}; + std::size_t p_sign_posn{}; + std::size_t n_sign_posn{}; + std::size_t int_p_sign_posn{}; + std::size_t int_n_sign_posn{}; +}; + +using lc_monetary=basic_lc_monetary; +using wlc_monetary=basic_lc_monetary; +using u8lc_monetary=basic_lc_monetary; +using u16lc_monetary=basic_lc_monetary; +using u32lc_monetary=basic_lc_monetary; + +template +struct basic_lc_numeric +{ + basic_io_scatter_t decimal_point{}; + basic_io_scatter_t thousands_sep{}; + basic_io_scatter_t grouping{}; +}; + +using lc_numeric=basic_lc_numeric; +using wlc_numeric=basic_lc_numeric; +using u8lc_numeric=basic_lc_numeric; +using u16lc_numeric=basic_lc_numeric; +using u32lc_numeric=basic_lc_numeric; + +template +struct basic_lc_time_era +{ + bool direction{};//+ is true, - is false + std::int_least64_t offset{}; + std::int_least64_t start_date_year{}; + std::uint_least8_t start_date_month{}; + std::uint_least8_t start_date_day{}; + std::int_least8_t end_date_special{};//-1 is -*, 0 means end_date exist, 1 is +* + std::int_least64_t end_date_year{}; + std::uint_least8_t end_date_month{}; + std::uint_least8_t end_date_day{}; + basic_io_scatter_t era_name; + basic_io_scatter_t era_format; + basic_io_scatter_t era; +}; + +template +struct basic_lc_time +{ + basic_io_scatter_t abday[7]{}; + basic_io_scatter_t day[7]{}; + basic_io_scatter_t abmon[12]{}; + basic_io_scatter_t ab_alt_mon[12]{}; + basic_io_scatter_t mon[12]{}; + basic_io_scatter_t d_t_fmt{}; + basic_io_scatter_t d_fmt{}; + basic_io_scatter_t t_fmt{}; + basic_io_scatter_t t_fmt_ampm{}; + basic_io_scatter_t date_fmt{}; + basic_io_scatter_t am_pm[2]{}; + basic_io_scatter_t> era{}; + basic_io_scatter_t era_d_fmt{}; + basic_io_scatter_t era_d_t_fmt{}; + basic_io_scatter_t era_t_fmt{}; + basic_io_scatter_t> alt_digits{}; + struct + { + std::size_t ndays{7}; + std::int_least64_t first_day{19971201}; + std::size_t first_week{4}; + }week{}; + std::size_t first_weekday{}; + std::size_t first_workday{}; + std::size_t cal_direction{}; + basic_io_scatter_t> timezone{}; +}; + +using lc_time=basic_lc_time; +using wlc_time=basic_lc_time; +using u8lc_time=basic_lc_time; +using u16lc_time=basic_lc_time; +using u32lc_time=basic_lc_time; + +template +struct basic_lc_messages +{ + basic_io_scatter_t yesexpr{}; + basic_io_scatter_t noexpr{}; + basic_io_scatter_t yesstr{}; + basic_io_scatter_t nostr{}; +}; + +using lc_messages=basic_lc_messages; +using wlc_messages=basic_lc_messages; +using u8lc_messages=basic_lc_messages; +using u16lc_messages=basic_lc_messages; +using u32lc_messages=basic_lc_messages; + +template +struct basic_lc_paper +{ + std::uint_least64_t width{}; + std::uint_least64_t height{}; +}; + +using lc_paper=basic_lc_paper; +using wlc_paper=basic_lc_paper; +using u8lc_paper=basic_lc_paper; +using u16lc_paper=basic_lc_paper; +using u32lc_paper=basic_lc_paper; + +template +struct basic_lc_telephone +{ + basic_io_scatter_t tel_int_fmt{}; + basic_io_scatter_t tel_dom_fmt{}; + basic_io_scatter_t int_select{}; + basic_io_scatter_t int_prefix{}; +}; + +using lc_telephone=basic_lc_telephone; +using wlc_telephone=basic_lc_telephone; +using u8lc_telephone=basic_lc_telephone; +using u16lc_telephone=basic_lc_telephone; +using u32lc_telephone=basic_lc_telephone; + +template +struct basic_lc_name +{ + basic_io_scatter_t name_fmt{}; + basic_io_scatter_t name_gen{}; + basic_io_scatter_t name_miss{}; + basic_io_scatter_t name_mr{}; + basic_io_scatter_t name_mrs{}; + basic_io_scatter_t name_ms{}; +}; + +using lc_name=basic_lc_name; +using wlc_name=basic_lc_name; +using u8lc_name=basic_lc_name; +using u16lc_name=basic_lc_name; +using u32lc_name=basic_lc_name; + +template +struct basic_lc_address +{ + basic_io_scatter_t postal_fmt{}; + basic_io_scatter_t country_name{}; + basic_io_scatter_t country_post{}; + basic_io_scatter_t country_ab2{}; + basic_io_scatter_t country_ab3{}; + std::uint_least64_t country_num{}; + basic_io_scatter_t country_car{}; + basic_io_scatter_t country_isbn{}; + basic_io_scatter_t lang_name{}; + basic_io_scatter_t lang_ab{}; + basic_io_scatter_t lang_term{}; + basic_io_scatter_t lang_lib{}; +}; + +using lc_address=basic_lc_address; +using wlc_address=basic_lc_address; +using u8lc_address=basic_lc_address; +using u16lc_address=basic_lc_address; +using u32lc_address=basic_lc_address; + +template +struct basic_lc_measurement +{ + std::uint_least64_t measurement{}; +}; + +using lc_measurement=basic_lc_measurement; +using wlc_measurement=basic_lc_measurement; +using u8lc_measurement=basic_lc_measurement; +using u16lc_measurement=basic_lc_measurement; +using u32lc_measurement=basic_lc_measurement; + +template +struct basic_lc_keyboard +{ + basic_io_scatter_t> keyboards{}; +}; + +using lc_keyboard=basic_lc_keyboard; +using wlc_keyboard=basic_lc_keyboard; +using u8lc_keyboard=basic_lc_keyboard; +using u16lc_keyboard=basic_lc_keyboard; +using u32lc_keyboard=basic_lc_keyboard; + +template +struct basic_lc_all +{ + basic_lc_identification identification{}; + basic_lc_monetary monetary{}; + basic_lc_numeric numeric{}; + basic_lc_time time{}; + basic_lc_messages messages{}; + basic_lc_paper paper{}; + basic_lc_telephone telephone{}; + basic_lc_name name{}; + basic_lc_address address{}; + basic_lc_measurement measurement{}; + basic_lc_keyboard keyboard{}; +}; + +using lc_all=basic_lc_all; +using wlc_all=basic_lc_all; +using u8lc_all=basic_lc_all; +using u16lc_all=basic_lc_all; +using u32lc_all=basic_lc_all; + +struct lc_locale +{ + lc_all const* all{}; + wlc_all const* wall{}; + u8lc_all const* u8all{}; + u16lc_all const* u16all{}; + u32lc_all const* u32all{}; +}; + +template +requires (std::same_as||std::same_as|| + std::same_as||std::same_as||std::same_as) +inline constexpr basic_lc_all const* get_all(lc_locale const& loc) noexcept +{ + if constexpr(std::same_as) + return loc.all; + else if constexpr(std::same_as) + return loc.wall; + else if constexpr(std::same_as) + return loc.u8all; + else if constexpr(std::same_as) + return loc.u16all; + else if constexpr(std::same_as) + return loc.u32all; + else + return {}; +} + +} diff --git a/src/fast_io/include/fast_io_i18n/lc_numbers/boolalpha.h b/src/fast_io/include/fast_io_i18n/lc_numbers/boolalpha.h new file mode 100644 index 0000000..4122f4c --- /dev/null +++ b/src/fast_io/include/fast_io_i18n/lc_numbers/boolalpha.h @@ -0,0 +1,16 @@ +#pragma once + +namespace fast_io +{ + +template +requires (flags.alphabet) +inline constexpr basic_io_scatter_t print_scatter_define(basic_lc_all const* __restrict all,manipulators::scalar_manip_t val) noexcept +{ + if(val.reference) + return all->messages.yesstr; + else + return all->messages.nostr; +} + +} diff --git a/src/fast_io/include/fast_io_i18n/lc_numbers/chrono.h b/src/fast_io/include/fast_io_i18n/lc_numbers/chrono.h new file mode 100644 index 0000000..0f4b40d --- /dev/null +++ b/src/fast_io/include/fast_io_i18n/lc_numbers/chrono.h @@ -0,0 +1,308 @@ +#pragma once + +namespace fast_io +{ + +template +inline constexpr std::size_t print_reserve_size(basic_lc_all const* __restrict all,std::chrono::weekday wkd) noexcept +{ + unsigned value(wkd.c_encoding()); + if(7)}; + return unsigned_size; + } + else + { + if(value==7) + value=0; + return all->time.day[value].len; + } +} + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define(basic_lc_all const* __restrict all,char_type* it,std::chrono::weekday wkd) noexcept +{ + unsigned value{wkd.c_encoding()}; + if(7u,it,value); + } + else + { + if(value==7u) + value={}; + return details::non_overlapped_copy_n(all->time.day[value].base,all->time.day[value].len,it); + } +} + +template +inline constexpr std::size_t print_reserve_size(basic_lc_all const* __restrict all,std::chrono::month m) noexcept +{ + unsigned value(m); + --value; + if(value<12u) + return all->time.mon[value].len; + else + { + constexpr std::size_t unsigned_size{print_reserve_size(io_reserve_type)}; + return unsigned_size; + } +} + +template<::std::random_access_iterator Iter,std::integral char_type> +inline constexpr Iter print_reserve_define(basic_lc_all const* __restrict all,Iter iter,std::chrono::month m) noexcept +{ + unsigned value(m); + unsigned value1(value); + --value; + if(value<12u) + return details::non_overlapped_copy_n(all->time.mon[value].base,all->time.mon[value].len,iter); + else + return print_reserve_define(io_reserve_type,iter,value1); +} + +/* +Referenced from IBM +LC_TIME Category for the Locale Definition Source File Format +https://www.ibm.com/support/knowledgecenter/ssw_aix_71/filesreference/LC_TIME.html +*/ + +namespace manipulators +{ + +template +struct abbr_t +{ + using manip_tag = manip_tag_t; + T reference; +}; + +template +struct alt_t +{ + using manip_tag = manip_tag_t; + T reference; +}; + +template +struct alt_num_t +{ + using manip_tag = manip_tag_t; + T reference; +}; + +template +struct am_pm_t +{ + using manip_tag = manip_tag_t; + T reference; +}; + +inline constexpr am_pm_t am_pm(bool is_pm) noexcept +{ + return {is_pm}; +} + +inline constexpr abbr_t abbr(std::chrono::weekday wkd) noexcept +{ + return {wkd}; +} + +inline constexpr abbr_t abbr(std::chrono::month wkd) noexcept +{ + return {wkd}; +} + +inline constexpr abbr_t> abbr_alt(std::chrono::month wkd) noexcept +{ + return {{wkd}}; +} + +template +requires (std::same_as|| +std::same_as|| +std::same_as) +inline constexpr alt_num_t alt_num(T m) noexcept +{ + return {m}; +} + + +template +inline constexpr basic_io_scatter_t print_scatter_define(basic_lc_all const* __restrict all,am_pm_t ampm) noexcept +{ + return all->time.am_pm[ampm.reference]; +} + +template +inline constexpr std::size_t print_reserve_size(basic_lc_all const* __restrict all,abbr_t wkd) noexcept +{ + unsigned value(wkd.reference.c_encoding()); + if(7)}; + return unsigned_size; + } + else + { + if(value==7) + value=0; + return all->time.abday[value].len; + } +} + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define(basic_lc_all const* __restrict all,char_type* it,abbr_t wkd) noexcept +{ + unsigned value(wkd.reference.c_encoding()); + if(7u,it,value); + } + else + { + if(value==7u) + value={}; + return details::non_overlapped_copy_n(all->time.abday[value].base,all->time.abday[value].len,it); + } +} + +template +inline constexpr std::size_t print_reserve_size(basic_lc_all const* __restrict all,abbr_t m) noexcept +{ + unsigned value(m.reference); + --value; + if(value<12u) + return all->time.abmon[value].len; + else + { + constexpr std::size_t unsigned_size{print_reserve_size(io_reserve_type)}; + return unsigned_size; + } +} + +template<::std::random_access_iterator Iter,std::integral char_type> +inline constexpr Iter print_reserve_define(basic_lc_all const* __restrict all,Iter iter,abbr_t m) noexcept +{ + unsigned value(m.reference); + unsigned value1(value); + --value; + if(value<12u) + return details::non_overlapped_copy_n(all->time.abmon[value].base,all->time.abmon[value].len,iter); + else + return print_reserve_define(io_reserve_type,iter,value1); +} + +template +inline constexpr std::size_t print_reserve_size(basic_lc_all const* __restrict all,abbr_t> m) noexcept +{ + unsigned value(m.reference.reference); + --value; + if(value<12u) + { + if(all->time.ab_alt_mon[value].len==0) + return all->time.abmon[value].len; + else + return all->time.ab_alt_mon[value].len; + } + else + { + constexpr std::size_t unsigned_size{print_reserve_size(io_reserve_type)}; + return unsigned_size; + } +} + +template<::std::random_access_iterator Iter,std::integral char_type> +inline constexpr Iter print_reserve_define(basic_lc_all const* __restrict all,Iter iter,abbr_t> m) noexcept +{ + unsigned value(m.reference.reference); + unsigned value1(value); + --value; + if(value<12u) + { + if(all->time.ab_alt_mon[value].len==0) + return details::non_overlapped_copy_n(all->time.abmon[value].base,all->time.abmon[value].len,iter); + else + return details::non_overlapped_copy_n(all->time.ab_alt_mon[value].base,all->time.ab_alt_mon[value].len,iter); + } + else + return print_reserve_define(io_reserve_type,iter,value1); +} + +template +requires (std::same_as|| +std::same_as|| +std::same_as) +inline constexpr std::size_t print_reserve_size(basic_lc_all const* __restrict all, + alt_num_t m) noexcept +{ + using namespace std::chrono; + if constexpr(std::same_as||std::same_as) + { + unsigned value(m.reference); + if(valuetime.alt_digits.len) + return all->time.alt_digits.base[value].len; + else + { + constexpr std::size_t unsigned_size{print_reserve_size(io_reserve_type)}; + return unsigned_size; + } + } + else + { + unsigned value(m.reference.iso_encoding()); + if(valuetime.alt_digits.len) + return all->time.alt_digits.base[value].len; + else + { + constexpr std::size_t unsigned_size{print_reserve_size(io_reserve_type)}; + return unsigned_size; + } + } +} + +template +requires (std::same_as|| +std::same_as|| +std::same_as) +inline constexpr Iter print_reserve_define(basic_lc_all const* __restrict all,Iter iter, + alt_num_t m) noexcept +{ + using namespace std::chrono; + if constexpr(std::same_as||std::same_as) + { + unsigned value(m.reference); + if(valuetime.alt_digits.len) + return details::non_overlapped_copy_n(all->time.alt_digits.base[value].base, + all->time.alt_digits.base[value].len,iter); + else + return print_reserve_define(io_reserve_type,iter,m.reference); + } + else + { + unsigned value(m.reference.iso_encoding()); + if(valuetime.alt_digits.len) + return details::non_overlapped_copy_n(all->time.alt_digits.base[value].base, + all->time.alt_digits.base[value].len,iter); + else + return print_reserve_define(io_reserve_type,iter,m.reference); + } +} + +#if 0 +template +inline constexpr std::size_t print_reserve_size(basic_lc_all const* __restrict all,std::chrono::year_month_day m) noexcept +{ + constexpr std::size_t unitsize{::fast_io::freestanding::max(print_reserve_size(io_reserve_type),print_reserve_size(io_reserve_type))}; + return unitsize*all->time.d_fmt.len; +} + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define(basic_lc_all const* __restrict all,char_type* iter,std::chrono::year_month_day m) noexcept +{ + +} +#endif +} +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_i18n/lc_numbers/cond.h b/src/fast_io/include/fast_io_i18n/lc_numbers/cond.h new file mode 100644 index 0000000..57ca6ef --- /dev/null +++ b/src/fast_io/include/fast_io_i18n/lc_numbers/cond.h @@ -0,0 +1,159 @@ +#pragma once + +namespace fast_io +{ + +namespace details +{ +template +concept cond_ok_lc_scatter_printable_impl= + lc_scatter_printable&& + (lc_scatter_printable||scatter_printable); + +template +concept cond_ok_lc_dynamic_reserve_printable_impl= + (lc_dynamic_reserve_printable||lc_scatter_printable)&& + (lc_dynamic_reserve_printable||lc_scatter_printable||reserve_printable||dynamic_reserve_printable||scatter_printable); + +template +concept cond_ok_lc_printable_impl=cond_ok_printable_impl&&lc_printable; + +template +concept cond_ok_lc_dynamic_rsv_printable_impl=cond_ok_dynamic_rsv_printable_impl|| + lc_dynamic_reserve_printable||lc_scatter_printable; +} + +template +requires (::fast_io::details::cond_ok_lc_scatter_printable_impl|| + ::fast_io::details::cond_ok_lc_scatter_printable_impl) +inline constexpr basic_io_scatter_t print_scatter_define(basic_lc_all const* __restrict all,::fast_io::manipulators::condition c) +{ + if(c.pred) + { + if constexpr(lc_scatter_printable) + { + return {print_scatter_define(all,c.t1)}; + } + else + { + return {print_scatter_define(io_reserve_type,c.t1)}; + } + } + else + { + if constexpr(lc_scatter_printable) + { + return {print_scatter_define(all,c.t2)}; + } + else + { + return {print_scatter_define(io_reserve_type,c.t2)}; + } + } +} + +namespace details +{ + +template +inline constexpr ::std::size_t cond_lc_print_reserve_size_impl(basic_lc_all const* __restrict all,T1 c) +{ + if constexpr(lc_scatter_printable) + { + return print_scatter_define(all,c).len; + } + else if constexpr(lc_dynamic_reserve_printable) + { + return print_reserve_size(all,c); + } + else if constexpr(scatter_printable) + { + return print_scatter_define(io_reserve_type,c).len; + } + else if constexpr(reserve_printable) + { + constexpr std::size_t sz{print_reserve_size(io_reserve_type)}; + return sz; + } + else + { + return print_reserve_size(io_reserve_type,c); + } +} + +template +inline constexpr char_type* cond_lc_print_reserve_define_impl(basic_lc_all const* __restrict all,char_type* iter,T1 c) +{ + if constexpr(lc_scatter_printable) + { + return copy_scatter(print_scatter_define(all,c),iter); + } + else if constexpr(lc_dynamic_reserve_printable) + { + return print_reserve_define(all,iter,c); + } + else if constexpr(scatter_printable) + { + return copy_scatter(print_scatter_define(io_reserve_type,c),iter); + } + else if constexpr(reserve_printable) + { + constexpr std::size_t sz{print_reserve_size(io_reserve_type)}; + return sz; + } + else + { + return print_reserve_size(io_reserve_type,c); + } +} + +} + +template +requires (::fast_io::details::cond_ok_lc_dynamic_reserve_printable_impl|| + ::fast_io::details::cond_ok_lc_dynamic_reserve_printable_impl) +inline constexpr ::std::size_t print_reserve_size(basic_lc_all const* __restrict all,::fast_io::manipulators::condition c) +{ + if(c.pred) + { + return ::fast_io::details::cond_lc_print_reserve_size_impl(all,c.t1); + } + else + { + return ::fast_io::details::cond_lc_print_reserve_size_impl(all,c.t2); + } +} + +template<::std::integral char_type,typename T1,typename T2> +requires (::fast_io::details::cond_ok_lc_dynamic_reserve_printable_impl|| + ::fast_io::details::cond_ok_lc_dynamic_reserve_printable_impl) +inline constexpr char_type* print_reserve_define(basic_lc_all const* __restrict all,char_type* iter,::fast_io::manipulators::condition c) +{ + if(c.pred) + { + return ::fast_io::details::cond_lc_print_reserve_define_impl(all,iter,c.t1); + } + else + { + return ::fast_io::details::cond_lc_print_reserve_define_impl(all,iter,c.t2); + } +} + +template<::std::integral char_type,typename T1,typename T2,::fast_io::buffer_output_stream bop> +requires ((::fast_io::details::cond_ok_lc_printable_impl + ||::fast_io::details::cond_ok_lc_printable_impl) + &&(!(::fast_io::details::cond_ok_lc_dynamic_rsv_printable_impl)|| + ::fast_io::details::cond_ok_lc_dynamic_rsv_printable_impl)) +inline constexpr void print_define(basic_lc_all const* __restrict all,bop b,::fast_io::manipulators::condition c) +{ + if(c.pred) + { + print_freestanding(imbue(all,b),c.t1); + } + else + { + print_freestanding(imbue(all,b),c.t2); + } +} + +} diff --git a/src/fast_io/include/fast_io_i18n/lc_numbers/impl.h b/src/fast_io/include/fast_io_i18n/lc_numbers/impl.h new file mode 100644 index 0000000..4373362 --- /dev/null +++ b/src/fast_io/include/fast_io_i18n/lc_numbers/impl.h @@ -0,0 +1,16 @@ +#pragma once + +#include"width.h" + +#include"boolalpha.h" +#include"integers.h" + +#if __cpp_lib_chrono >= 201907L || (__GNUC__ >= 11 || defined(__clang__)) +#if defined(_GLIBCXX_CHRONO) || defined(_LIBCPP_CHRONO) || defined(_CHRONO_) +#include"chrono.h" +#endif +#endif + + +#include"lc_time.h" +#include"cond.h" diff --git a/src/fast_io/include/fast_io_i18n/lc_numbers/integers.h b/src/fast_io/include/fast_io_i18n/lc_numbers/integers.h new file mode 100644 index 0000000..17e0d8e --- /dev/null +++ b/src/fast_io/include/fast_io_i18n/lc_numbers/integers.h @@ -0,0 +1,416 @@ +#pragma once + +namespace fast_io +{ + +namespace details +{ +template +inline constexpr std::size_t lc_print_reserve_size_int_cal(basic_lc_all const* __restrict all) noexcept +{ + constexpr std::size_t static_size{print_integer_reserved_size_cache>}; + constexpr std::size_t static_sizem1{static_size-1}; + return static_size+static_sizem1*all->numeric.thousands_sep.len; +} + +template +inline constexpr char_type to_char_single_digit(T t) noexcept +{ + if constexpr(base<=10) + { + return ::fast_io::char_literal_add(t); + } + else + { + constexpr T ten{static_cast(10u)}; + if(t(t); + else + { + if constexpr(is_ebcdic) + { + if constexpr(base<=19) + { + if constexpr(uppercase) + return static_cast((0xC1-10)+t); + else + return static_cast((0x81-10)+t); + } + else if constexpr(base<=28) + { + if(t<19u) + { + if constexpr(uppercase) + return static_cast((0xC1-10u)+t); + else + return static_cast((0x81-10u)+t); + } + else + { + if constexpr(uppercase) + return static_cast((0xD1-19u)+t); + else + return static_cast((0x91-19u)+t); + } + } + else + { + if(t<19u) + { + if constexpr(uppercase) + return static_cast((0xC1-10u)+t); + else + return static_cast((0x81-10u)+t); + } + else if(t<28u) + { + if constexpr(uppercase) + return static_cast((0xD1-19u)+t); + else + return static_cast((0x91-19u)+t); + } + else + { + if constexpr(uppercase) + return static_cast((0xE2-28u)+t); + else + return static_cast((0xA2-28u)+t); + } + } + } + else + { + return ::fast_io::char_literal_add(t-ten); + } + } + } +} + +template +constexpr char_type* lc_grouping_single_sep_ch_impl(basic_io_scatter_t const& grouping, char_type* iter,T t, char_type replacement_ch) noexcept +{ + std::size_t const* grouping_base{grouping.base}; + std::size_t const grouping_len{grouping.len}; + std::size_t i{}; + constexpr T c0{static_cast(base)}; + constexpr std::size_t full_len{cal_max_int_size()}; + std::size_t full_i{}; + for(;i!=grouping_len;++i) + { + auto e{grouping_base[i]}; + if(e==0) + break; + for(std::size_t j{};j!=e;++j) + { + *--iter=to_char_single_digit(static_cast(t%c0)); + t/=c0; + if constexpr(full) + { + if((++full_i)==full_len) + return iter; + } + else + { + if(t==0) + return iter; + } + } + *--iter=replacement_ch; + } + if(i!=grouping_len) + { + for(;;) + { + *--iter=to_char_single_digit(static_cast(t%c0)); + t/=c0; + if constexpr(full) + { + if((++full_i)==full_len) + return iter; + } + else + { + if(t==0) + return iter; + } + } + } + else + { + for(std::size_t e{grouping_base[i-1]};;*--iter=replacement_ch) + { + for(std::size_t j{};j!=e;++j) + { + *--iter=to_char_single_digit(static_cast(t%c0)); + t/=c0; + if constexpr(full) + { + if((++full_i)==full_len) + return iter; + } + else + { + if(t==0) + return iter; + } + } + } + } +} + + +template +constexpr char_type* grouping_mul_sep_print_sep_impl(char_type const* thousands_sep_base,std::size_t thousands_sep_len, + char_type const* first,char_type const* last, + char_type* outit) noexcept +{ + for(;first!=last;++first) + { + if(*first==char_literal_v) + { + outit=non_overlapped_copy_n(thousands_sep_base,thousands_sep_len,outit); + } + else + { + *outit=*first; + ++outit; + } + } + return outit; +} + +template +constexpr char_type* grouping_mul_sep_impl(basic_lc_all const* __restrict all, char_type* iter,T t) noexcept +{ + constexpr std::size_t array_len{cal_max_int_size()*2u-1u}; + char_type array[array_len]; + auto const ed{array+array_len}; + auto thousands_sep{all->numeric.thousands_sep}; + char_type replacement_ch{char_literal_v}; + bool single_character{thousands_sep.len==1}; + if(single_character) + { + replacement_ch=*thousands_sep.base; + } + auto first{lc_grouping_single_sep_ch_impl(all->numeric.grouping,ed,t,replacement_ch)}; + if(single_character) + { + return non_overlapped_copy(first,ed,iter); + } + else + { + return grouping_mul_sep_print_sep_impl(thousands_sep.base,thousands_sep.len,first,ed,iter); + } +} + +template +requires (sizeof(T)>1) +constexpr void lc_print_unsigned_with_3_seperator_len(char_type seperator_ch, char_type* iter,T value,std::size_t size) noexcept +{ + constexpr auto table(digits_table); + constexpr std::uint_least32_t cpow1{static_cast(base)}; + constexpr std::uint_least32_t cpow2{static_cast(cpow1*cpow1)}; + constexpr std::uint_least32_t cpow3{static_cast(cpow2*cpow1)}; + for(;3u(value%cpow3)}; + value/=cpow3; + T low2digits{static_cast(low3digits%cpow2)}; + T highdigit{static_cast(low3digits/cpow2)}; + non_overlapped_copy_n(table+(low2digits<<1),2u,iter-=2u); + *--iter=to_char_single_digit(highdigit); + size-=3u; + } + if(size==3) + { + T low2digits{static_cast(value%cpow2)}; + T highdigit{static_cast(value/cpow2)}; + non_overlapped_copy_n(table+(low2digits<<1),2u,iter-=2u); + *--iter=to_char_single_digit(highdigit); + } + else if(size==2) + non_overlapped_copy_n(table+(value<<1),2u,iter-=2u); + else + { + *--iter=to_char_single_digit(value); + } +} + +template +inline constexpr char_type* print_lc_grouping_3_path_impl(char_type seperator, char_type* iter,int_type t) noexcept +{ + if constexpr(full) + { + constexpr std::size_t size{cal_max_int_size()}; + constexpr std::size_t offset_size{size+(size-1)/3}; + if constexpr(sizeof(int_type)<=sizeof(unsigned)) + lc_print_unsigned_with_3_seperator_len(seperator,iter+=offset_size,static_cast(t),size); + else + lc_print_unsigned_with_3_seperator_len(seperator,iter+=offset_size,t,size); + } + else + { + std::size_t const size{chars_len(t)}; + std::size_t const offset_size{size+(size-1u)/3u}; + if constexpr(sizeof(int_type)<=sizeof(unsigned)) + lc_print_unsigned_with_3_seperator_len(seperator,iter+=offset_size,static_cast(t),size); + else + lc_print_unsigned_with_3_seperator_len(seperator,iter+=offset_size,t,size); + } + return iter; +} + +template +inline constexpr char_type* lc_print_reserve_integral_withfull_main_impl(basic_lc_all const* __restrict all, char_type* first,intg t) +{ + if((all->numeric.grouping.len==0)|(all->numeric.thousands_sep.len==0)) + return print_reserve_integral_withfull_main_impl(first,t); + else if((all->numeric.grouping.len==1&&*all->numeric.grouping.base==3)&(all->numeric.thousands_sep.len==1)) + return print_lc_grouping_3_path_impl(*(all->numeric.thousands_sep.base),first,t); + else + return grouping_mul_sep_impl(all,first,t); +} + +template +inline constexpr char_type* lc_print_reserve_integral_define(basic_lc_all const* __restrict all, char_type* first,int_type t) noexcept +{ + if constexpr(base<=10&&uppercase) + { + return print_reserve_integral_define(first,t);//prevent duplications + } + else + { + static_assert((2<=base)&&(base<=36)); + using unsigned_type = ::fast_io::details::my_make_unsigned_t; + unsigned_type u{static_cast(t)}; + if constexpr(showpos) + { + if constexpr(::fast_io::details::my_unsigned_integral) + { + *first=char_literal_v; + } + else + { + if(t<0) + { + *first=char_literal_v; + constexpr unsigned_type zero{}; + u=zero-u; + } + else + { + *first=char_literal_v; + } + } + ++first; + } + else + { + if constexpr(::fast_io::details::my_signed_integral) + { + if(t<0) + { + *first=char_literal_v; + ++first; + constexpr unsigned_type zero{}; + u=zero-u; + } + } + } + if constexpr(showbase&&(base!=10)) + first=print_reserve_show_base_impl(first); + return lc_print_reserve_integral_withfull_main_impl(all,first,u); + } +} + + +template +inline constexpr std::size_t print_reserve_size_grouping_timestamp_impl(basic_lc_all const* __restrict all) +{ + constexpr std::size_t static_size{print_reserve_size(io_reserve_type)}; + constexpr std::size_t static_sizem1{static_size-1}; + return static_size+static_sizem1*all->numeric.thousands_sep.len+all->numeric.decimal_point.len+std::numeric_limits::digits10; +} + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define_grouping_timestamp_impl(basic_lc_all const* __restrict all, char_type* iter,unix_timestamp timestamp) +{ + iter=lc_print_reserve_integral_define<10>(all,iter,timestamp.seconds); + if(timestamp.subseconds) + { + if(all->numeric.decimal_point.len==1) + { + *iter=all->numeric.decimal_point.base[0]; + ++iter; + } + else + iter=non_overlapped_copy_n(all->numeric.decimal_point.base,all->numeric.decimal_point.len,iter); + iter=output_iso8601_subseconds_main(iter,timestamp.subseconds); + } + return iter; +} + +} +template +requires ((details::my_integral||std::same_as,std::byte>)&&!flags.alphabet&&!std::same_as,bool>) +inline constexpr std::size_t print_reserve_size(basic_lc_all const* __restrict all,manipulators::scalar_manip_t) noexcept +{ + if constexpr(std::same_as,std::byte>) + return ::fast_io::details::lc_print_reserve_size_int_cal(all); + else + return ::fast_io::details::lc_print_reserve_size_int_cal>(all); +} + +template<::std::integral char_type,::fast_io::manipulators::scalar_flags flags,typename T> +requires ((details::my_integral||std::same_as,std::byte>)&&!flags.alphabet&&!std::same_as,bool>) +inline constexpr char_type* print_reserve_define(basic_lc_all const* __restrict all, char_type* iter,manipulators::scalar_manip_t t) noexcept +{ + if constexpr(std::same_as,std::byte>) + return details::lc_print_reserve_integral_define(iter,static_cast(t.reference)); + else + return details::lc_print_reserve_integral_define(all,iter,t.reference); +} + +template +inline constexpr std::size_t print_reserve_size(basic_lc_all const* __restrict all,basic_timestamp) noexcept +{ + return details::print_reserve_size_grouping_timestamp_impl(all); +} + +template<::std::integral char_type,std::int_least64_t off_to_epoch> +inline constexpr char_type* print_reserve_define(basic_lc_all const* __restrict all, char_type* iter,basic_timestamp ts) noexcept +{ + if constexpr(off_to_epoch==0) + return details::print_reserve_define_grouping_timestamp_impl(all,iter,ts); + else + return details::print_reserve_define_grouping_timestamp_impl(all,iter,{ts.seconds,ts.subseconds}); +} + +template +requires ((details::my_integral||std::same_as,std::byte>)&&!flags.alphabet&&!std::same_as,bool>&&(flags.showpos||!details::my_unsigned_integral)) +inline constexpr std::size_t print_define_internal_shift(basic_lc_all const* __restrict,manipulators::scalar_manip_t t) noexcept +{ + if constexpr(flags.showpos) + { + return 1; + } + else + { + return t.reference<0; + } +} + +template +inline constexpr std::size_t print_define_internal_shift(basic_lc_all const* __restrict,basic_timestamp t) noexcept +{ + return t.seconds<0; +} + + +} diff --git a/src/fast_io/include/fast_io_i18n/lc_numbers/lc_time.h b/src/fast_io/include/fast_io_i18n/lc_numbers/lc_time.h new file mode 100644 index 0000000..a11ae2e --- /dev/null +++ b/src/fast_io/include/fast_io_i18n/lc_numbers/lc_time.h @@ -0,0 +1,1243 @@ +#pragma once +/* +Unfinished. Do not use it. +*/ +namespace fast_io +{ + +namespace details +{ +/* +https://www.ibm.com/docs/en/aix/7.1?topic=ff-lc-time-category-locale-definition-source-file-format +*/ + +template +inline constexpr bool is_leap_year(year_type year) noexcept +{ + if constexpr (my_signed_integral) + return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0); + else + return year % 4u == 0 && (year % 100u != 0 || year % 400u == 0); +} + +inline constexpr std::uint_least16_t month_accum[]{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; + +inline constexpr std::uint_least16_t day_of_the_year(iso8601_timestamp const& tsp) noexcept +{ + std::uint_least8_t month_minus1{ tsp.month }; + --month_minus1; + if (month_minus1 > 11u) [[unlikely]] return 0; + std::uint_least16_t value{ static_cast(month_accum[month_minus1] + static_cast(tsp.day))}; + if (month_minus1 > 1u && is_leap_year(tsp.year)) + ++value; + return value; +} + +inline constexpr std::int_least64_t day_diff( + std::int_least64_t year_after, + std::uint_least8_t month_after, + std::uint_least8_t day_after, + std::int_least64_t year_before, + std::uint_least8_t month_before, + std::uint_least8_t day_before +) noexcept +{ + auto month_after_minus1{ month_after }; + auto month_before_minus1{ month_before }; + --month_after_minus1; + --month_before_minus1; + if (month_after_minus1 > 11u || month_before_minus1 > 11u) [[unlikely]] + return 0; + std::int_least64_t value{ year_after / 4 - year_before / 4 + - year_after / 100 + year_before / 100 + + year_after / 400 - year_before / 400 + + 365 * (year_after - year_before) + + month_accum[month_after_minus1] - month_accum[month_before_minus1] + + day_after - day_before }; + if (month_after_minus1 < 2u && is_leap_year(year_after)) + --value; + if (month_before_minus1 < 2u && is_leap_year(year_before)) + ++value; + return value; +} + +inline constexpr std::int_least64_t day_diff(iso8601_timestamp const& tsp_after, iso8601_timestamp const& tsp_before) noexcept +{ + return ::fast_io::details::day_diff(tsp_after.year, tsp_after.month, tsp_after.day, tsp_before.year, tsp_before.month, tsp_before.day); +} + +template +inline constexpr std::size_t lc_format_alt_digits_len(basic_io_scatter_t> const& alt_digits,T value) noexcept +{ + std::size_t size_value{static_cast(value)}; + std::size_t alt_digits_len{alt_digits.len}; + if (size_value) }; + return int_type_reserve_size; + } +} + +template +inline constexpr char_type* lc_format_alt_digits_print(basic_io_scatter_t> const& alt_digits,T value, char_type* iter) noexcept +{ + std::size_t size_value{static_cast(value)}; + std::size_t alt_digits_len{alt_digits.len}; + if (size_value(iter,value); +} + +/* +compress them to force them to be passed by value on ms abi +*/ +struct lc_month_day_pass_aux +{ + std::uint_least8_t month; + std::uint_least8_t day; +}; + +inline constexpr bool test_era_started(std::int_least64_t y0,std::uint_least8_t m0,std::uint_least8_t d0, + std::int_least64_t y1,std::uint_least8_t m1,std::uint_least8_t d1) noexcept +{ + if(y0 +inline constexpr basic_lc_time_era const* lc_time_find_era_impl( + basic_lc_time_era const* first,basic_lc_time_era const* last, + std::int_least64_t year,lc_month_day_pass_aux month_day) noexcept +{ + std::uint_least8_t month{month_day.month}; + std::uint_least8_t day{month_day.day}; + for(;first!=last;++first) + { + basic_lc_time_era const& e{*first}; + bool has_era_start{}; + bool direction{e.direction}; + if(direction) + { + has_era_start=test_era_started( + e.start_date_year,e.start_date_month,e.start_date_day, + year,month,day); + } + else + { + has_era_start=test_era_started(year,month,day, + e.start_date_year,e.start_date_month,e.start_date_day); + } + if(has_era_start) + { + std::int_least8_t end_special{e.end_date_special}; + if(0 +inline constexpr lc_time_ox_common_res lc_time_ox_common_impl(iso8601_timestamp const& tsp,char_type ch) noexcept +{ + switch(ch) + { + case char_literal_v: + case char_literal_v: + { + return {tsp.day}; + } + case char_literal_v: + { + return {tsp.hours}; + } + case char_literal_v: + { + std::uint_least8_t hours{tsp.hours}; + constexpr std::uint_least8_t twlv{static_cast(12u)}; + if (hours == 0u) + { + hours=twlv; + } + else if(twlv: + { + return {tsp.month}; + } + case char_literal_v: + { + return {tsp.minutes}; + } + case char_literal_v: + { + return {tsp.seconds}; + } + case char_literal_v: + { + return {weekday(tsp)}; + } + case char_literal_v: + { + return {static_cast(static_cast(weekday(tsp.year, 1, 1)+day_of_the_year(tsp)-1u)/7u)}; + } + case char_literal_v: + case char_literal_v: + { + return {c_weekday(tsp)}; + } + case char_literal_v: + { + std::uint_least64_t year{static_cast(tsp.year)}; + if(tsp.year<0) + { + year=0u-year; + } + return {static_cast(year%100u)}; + } + default: + { + return {0,true}; + } + } + return {0,true}; +} + +template <::std::integral char_type> +inline constexpr char_type* non_overlapped_copy_to_lowercase(char_type const* __restrict first, char_type const* last, char_type* __restrict dest) noexcept +{ + for(;first!=last;++first) + { + *dest=::fast_io::char_category::to_c_lower(*first); + ++dest; + } + return dest; +} + +template +inline constexpr char_type* copy_scatter_to_lowercase(basic_io_scatter_t const& scatter, char_type* iter) noexcept +{ + return non_overlapped_copy_to_lowercase(scatter.base,scatter.base+scatter.len,iter); +} + +template +inline constexpr std::size_t lc_print_reserve_size_time_format_common_impl(basic_lc_time const& t, iso8601_timestamp const& tsp, basic_io_scatter_t const& format_str) noexcept +{ + constexpr std::size_t uint_least8_reserve_size{ print_reserve_size(io_reserve_type) }; + constexpr std::size_t uint_least16_reserve_size{ print_reserve_size(io_reserve_type) }; + constexpr std::size_t int_least64_reserve_size{ print_reserve_size(io_reserve_type) }; + std::size_t value{}; + for (char_type const* i{format_str.base},*end_it{i+format_str.len};i!=end_it;++i) + { + auto p{::fast_io::freestanding::find(i,end_it,char_literal_v)}; + value+=static_cast(p-i); + if(p==end_it) + return value; + if((++p)==end_it) + return value+1; + bool omit{*p==char_literal_v}; + if(omit) + { + ++value; + if((++p)==end_it) + return value+1; + } + switch(*p) + { + case char_literal_v: + case char_literal_v: + case char_literal_v: + { + ++value; + break; + } + case char_literal_v: + case char_literal_v: + { + basic_io_scatter_t const* base_ptr; + if(*p==char_literal_v) + base_ptr=t.abday; + else + base_ptr=t.day; + value += base_ptr[c_weekday(tsp)].len; + break; + } + case char_literal_v: + case char_literal_v: + case char_literal_v: + { + std::uint_least8_t month_minus1{ tsp.month }; + --month_minus1; + if (month_minus1 > 11u) [[unlikely]] + value += uint_least8_reserve_size; + else + { + auto mon_or_abmon{*p==char_literal_v?t.mon:t.abmon}; + value += mon_or_abmon[month_minus1].len; + } + break; + } + case char_literal_v: + { + value += lc_print_reserve_size_time_format_common_impl(t,tsp,t.d_t_fmt); + break; + } + case char_literal_v: + case char_literal_v: + case char_literal_v: + case char_literal_v: + case char_literal_v: + case char_literal_v: + { + value += int_least64_reserve_size; + break; + } + case char_literal_v: + case char_literal_v: + case char_literal_v: + case char_literal_v: + case char_literal_v: + case char_literal_v: + case char_literal_v: + case char_literal_v: + case char_literal_v: + { + value+=uint_least8_reserve_size; + break; + } + case char_literal_v: + case char_literal_v: + case char_literal_v: + case char_literal_v: + { + value += uint_least16_reserve_size; + break; + } + case char_literal_v: + case char_literal_v: + { + constexpr std::size_t int_least64_reserve_size_plus6{ static_cast(2) + uint_least8_reserve_size*2 + int_least64_reserve_size }; + value += int_least64_reserve_size_plus6; + break; + } + case char_literal_v: + { + if((++p)==end_it)[[unlikely]] + { + value+=static_cast(end_it-i); + return value; + } + switch(*p) + { + case char_literal_v: + case char_literal_v: + case char_literal_v: + { + basic_io_scatter_t const* scatter_ptr{}; + switch(*p) + { + case char_literal_v: + { + scatter_ptr=__builtin_addressof(t.era_d_t_fmt); + break; + } + case char_literal_v: + { + scatter_ptr=__builtin_addressof(t.era_d_fmt); + break; + } + default: + { + scatter_ptr=__builtin_addressof(t.era_t_fmt); + break; + } + } + value += lc_print_reserve_size_time_format_common_impl(t,tsp,*scatter_ptr); + break; + } + case char_literal_v: + case char_literal_v: + case char_literal_v: + { + auto era_scatter_start{t.era.base}; + auto era_scatter_end{era_scatter_start+t.era.len}; + auto era_result{lc_time_find_era_impl(era_scatter_start,era_scatter_end,tsp.year,{tsp.month,tsp.day})}; + if(era_result!=era_scatter_end) + { + switch(*p) + { + case char_literal_v: + { + value += era_result->era_name.len; + break; + } + case char_literal_v: + { + value += int_least64_reserve_size; + break; + } + default: + { + value += lc_print_reserve_size_time_format_common_impl(t,tsp,era_result->era_format); + break; + } + } + } + break; + } + default: + return value+static_cast(end_it-p+2); + } + break; + } + case char_literal_v: + { + if((++p)==end_it)[[unlikely]] + return value+2; + char_type const ch{*p}; + switch(ch) + { + case char_literal_v: + case char_literal_v: + { + auto month_minus1{ static_cast(tsp.month - 1u) }; + if (month_minus1 > 11u) [[unlikely]] + month_minus1 = 0u; + value += t.ab_alt_mon[month_minus1].len; + break; + } + case char_literal_v: + { + std::int_least64_t yr{tsp.year/100}; + value += lc_format_alt_digits_len(t.alt_digits,yr); + break; + } + case char_literal_v: //Glibc's changelog said do not use %Op but the upstream still use this + case char_literal_v: + { + std::uint_least8_t const hours{tsp.hours}; + if(hours<12u) + value += t.am_pm[0].len; + else if(hours<24u) + value += t.am_pm[1].len; + //if hours >=24, ignore am pm + break; + } + default: + { + auto ret{lc_time_ox_common_impl(tsp,ch)}; + if(ret.failed)[[unlikely]] + { + return value+static_cast(end_it-p+2); + } + else + { + value += lc_format_alt_digits_len(t.alt_digits,ret.alt_value); + break; + } + } + } + break; + } + case char_literal_v: + { + value += 20u;//20 Represents the alternate era name.??? to fix + break; + } + case char_literal_v: + case char_literal_v: + { + std::uint_least8_t const hours{tsp.hours}; + if(hours<12u) + value += t.am_pm[0].len; + else if(hours<24u) + value += t.am_pm[1].len; + //if hours >=24, ignore am pm + break; + } + case char_literal_v: + { + value += lc_print_reserve_size_time_format_common_impl(t, tsp, t.t_fmt_ampm); + break; + } + case char_literal_v: + { + constexpr std::size_t uint_least8_reserve_sizedouble{uint_least8_reserve_size*2+1}; + value += uint_least8_reserve_sizedouble; + break; + } + case char_literal_v: + { + ++value; + break; + } + case char_literal_v: + { + constexpr std::size_t uint_least8_reserve_size_result{ 2 + 3 * uint_least8_reserve_size }; + value += uint_least8_reserve_size_result; + break; + } + case char_literal_v: + { + value += lc_print_reserve_size_time_format_common_impl(t, tsp, t.d_fmt); + break; + } + case char_literal_v: + { + value += lc_print_reserve_size_time_format_common_impl(t, tsp, t.t_fmt); + break; + } + case char_literal_v: + case char_literal_v: + { + value += print_reserve_size_timezone_impl_v; + break; + } + default: + // the format string is invalid + // or it contains other string. %c %r %x %X %Ec %Ex %EX + return value+static_cast(end_it-p+1); + } + i=p; + } + return value; +} + +template<::std::integral char_type> +inline constexpr char_type* lc_copy_01_impl(char_type* iter) noexcept +{ + if constexpr (std::same_as) + return copy_string_literal("01", iter); + else if constexpr (std::same_as) + return copy_string_literal(L"01", iter); + else if constexpr (std::same_as) + return copy_string_literal(u"01", iter); + else if constexpr (std::same_as) + return copy_string_literal(U"01", iter); + else + return copy_string_literal(u8"01", iter); +} + +template<::std::integral char_type> +inline constexpr char_type* lc_copy_12_impl(char_type* iter) noexcept +{ + if constexpr(std::same_as) + return copy_string_literal("12",iter); + else if constexpr(std::same_as) + return copy_string_literal(L"12",iter); + else if constexpr(std::same_as) + return copy_string_literal(u"12",iter); + else if constexpr(std::same_as) + return copy_string_literal(U"12",iter); + else + return copy_string_literal(u8"12",iter); +} + +template<::std::integral char_type> +inline constexpr char_type* lc_copy_52_impl(char_type* iter) noexcept +{ + if constexpr (std::same_as) + return copy_string_literal("52", iter); + else if constexpr (std::same_as) + return copy_string_literal(L"52", iter); + else if constexpr (std::same_as) + return copy_string_literal(u"52", iter); + else if constexpr (std::same_as) + return copy_string_literal(U"52", iter); + else + return copy_string_literal(u8"52", iter); +} + +template<::std::integral char_type> +inline constexpr char_type* lc_copy_53_impl(char_type* iter) noexcept +{ + if constexpr (std::same_as) + return copy_string_literal("53", iter); + else if constexpr (std::same_as) + return copy_string_literal(L"53", iter); + else if constexpr (std::same_as) + return copy_string_literal(u"53", iter); + else if constexpr (std::same_as) + return copy_string_literal(U"53", iter); + else + return copy_string_literal(u8"53", iter); +} + +template +inline constexpr char_type* lc_print_month_fmt_common(basic_io_scatter_t const* month_array, char_type* iter,std::uint_least8_t month) +{ + constexpr std::uint_least8_t twelve{12}; + std::uint_least8_t month_minus1{month}; + --month_minus1; + if(month_minus1 < twelve) [[likely]] + return copy_scatter(month_array[month_minus1], iter); + else + return print_reserve_integral_define<10>(iter, month); +} + +template +inline constexpr char_type* lc_print_reserve_define_time_fmt_common_impl(basic_lc_time const& t, char_type* iter,iso8601_timestamp const& tsp,basic_io_scatter_t const& format_str) +{ + for (char_type const* i{format_str.base},*end_it{i+format_str.len};i!=end_it;++i) + { + char_type const* p{::fast_io::freestanding::find(i,end_it,char_literal_v)}; + iter=non_overlapped_copy(i,p,iter); + if(p==end_it) + return iter; + if((++p)==end_it) + { + *iter=*(--p); + ++iter; + return iter; + } + bool omit{*p==char_literal_v}; + if(omit) + { + if((++p)==end_it) + { + *iter=char_literal_v; + ++iter; + return iter; + } + } + char_type const first_format_ch{*p}; + switch(first_format_ch) + { + case char_literal_v: [[unlikely]] + { + *iter = char_literal_v; + ++iter; + break; + } + case char_literal_v: + case char_literal_v: + { + basic_io_scatter_t const* base_ptr; + if(*p==char_literal_v) + base_ptr=t.abday; + else + base_ptr=t.day; + + iter=copy_scatter(base_ptr[c_weekday(tsp)],iter); + break; + } + case char_literal_v: + { + iter=lc_print_month_fmt_common(t.mon,iter,tsp.month); + break; + } + case char_literal_v: + case char_literal_v: + { + auto mon_or_abmon{first_format_ch==char_literal_v?t.mon:t.abmon}; + iter=lc_print_month_fmt_common(mon_or_abmon,iter,tsp.month); + break; + } + case char_literal_v: + { + iter=lc_print_reserve_define_time_fmt_common_impl(t, iter, tsp, t.d_t_fmt); + break; + } + case char_literal_v: + { + iter = print_reserve_integral_define<10>(iter, tsp.year / 100); + break; + } + case char_literal_v: + { + if(omit) + iter = print_reserve_integral_define<10>(iter, tsp.day); + else + iter = chrono_two_digits_impl(iter, tsp.day); + break; + } + case char_literal_v: + { + iter = chrono_two_digits_impl(iter, tsp.month); + *iter = char_literal_v; + ++iter; + iter = chrono_two_digits_impl(iter, tsp.day); + *iter = char_literal_v; + ++iter; + iter = chrono_year_impl(iter, tsp.year); + break; + } + case char_literal_v: + { + iter = chrono_two_digits_impl(iter, tsp.day); + break; + } + case char_literal_v: + { + if((++p)==end_it)[[unlikely]] + { + if(omit) + return non_overlapped_copy_n(end_it-3,3,iter); + else + return non_overlapped_copy_n(end_it-2,2,iter); + } + switch(*p) + { + case char_literal_v: + { + iter = lc_print_reserve_define_time_fmt_common_impl(t, iter, tsp, t.era_d_t_fmt); + break; + } + case char_literal_v: + case char_literal_v: + case char_literal_v: + { + auto era_scatter_start{t.era.base}; + auto era_scatter_end{era_scatter_start+t.era.len}; + auto era_result{lc_time_find_era_impl(era_scatter_start,era_scatter_end,tsp.year,{tsp.month,tsp.day})}; + if(era_result!=era_scatter_end)[[likely]] + { + switch(*p) + { + case char_literal_v: + { + iter = lc_print_reserve_define_time_fmt_common_impl(t,iter,tsp,era_result->era_format); + break; + } + case char_literal_v: + { + iter = copy_scatter(era_result->era_name,iter); + break; + } + default: + { + std::int_least64_t real_era_year_offset{era_result->start_date_year-era_result->offset}; + std::int_least64_t era_year; + if(::fast_io::details::intrinsics::sub_underflow(tsp.year,real_era_year_offset,era_year))[[unlikely]] + { + if(omit) + iter=non_overlapped_copy_n(p-4,4,iter); + else + iter=non_overlapped_copy_n(p-3,3,iter); + } + else + iter=print_reserve_integral_define<10>(iter,era_year); + } + } + } + break; + } + case char_literal_v: + { + iter = lc_print_reserve_define_time_fmt_common_impl(t, iter, tsp, t.era_d_fmt); + break; + } + case char_literal_v: + { + iter = lc_print_reserve_define_time_fmt_common_impl(t, iter, tsp, t.era_t_fmt); + break; + } + default: + { + if(omit) + --p; + return non_overlapped_copy(p-2,end_it,iter); + } + } + break; + } + case char_literal_v: + { + iter = chrono_year_impl(iter, tsp.year); + *iter = char_literal_v; + ++iter; + iter = chrono_two_digits_impl(iter, tsp.month); + *iter = char_literal_v; + ++iter; + iter = chrono_two_digits_impl(iter, tsp.day); + break; + } + case char_literal_v: + case char_literal_v: + { + auto year{ tsp.year }; + auto month{ tsp.month }; + auto day{ tsp.day }; + std::uint_least8_t weekday_of_1st_day_this_year{ weekday(tsp.year, 1, 1) }; + auto weekday_of_last_day_this_year{ weekday_of_1st_day_this_year }; + if (is_leap_year(year)) + ++weekday_of_last_day_this_year; + if (month == 1u && weekday_of_1st_day_this_year > 4u && weekday_of_1st_day_this_year + day < 9u) + iter = chrono_year_impl(iter, year - 1); + else if (month == 12u && weekday_of_last_day_this_year < 4u && weekday_of_last_day_this_year + day > 31u) + iter = chrono_year_impl(iter, year + 1); + else + iter = chrono_year_impl(iter, year); + break; + } + case char_literal_v: + { + iter = chrono_two_digits_impl(iter, tsp.hours); + break; + } + case char_literal_v: + case char_literal_v: + { + std::uint_least8_t hours = tsp.hours; + if (hours == 0u) + iter = lc_copy_12_impl(iter); + else if (hours <= 12u)[[likely]] + iter = chrono_two_digits_impl(iter, hours); + else if (hours <= 24u)[[likely]] + iter = chrono_two_digits_impl(iter, static_cast(hours-12u)); + break; + } + case char_literal_v: + { + iter = print_reserve_integral_define<10>(iter, day_of_the_year(tsp)); + break; + } + case char_literal_v: + { + auto hours{tsp.hours}; + if(!omit) + { + constexpr std::uint_least8_t ten{10u}; + if(hours; + ++iter; + } + } + iter = print_reserve_integral_define<10>(iter, hours); + break; + } + case char_literal_v: + { + if(omit) + iter = print_reserve_integral_define<10>(iter, tsp.month); + else + iter = chrono_two_digits_impl(iter, tsp.month); + break; + } + case char_literal_v: + { + iter = chrono_two_digits_impl(iter, tsp.minutes); + break; + } + case char_literal_v: + { + *iter = char_literal_v; + ++iter; + break; + } + case char_literal_v: + { + if((++p)==end_it)[[unlikely]] + { + if(omit) + return non_overlapped_copy_n(end_it-3,3,iter); + else + return non_overlapped_copy_n(end_it-2,2,iter); + } + char_type const ch{*p}; + switch(ch) + { + case char_literal_v: + case char_literal_v: + { + auto month_minus1{ static_cast(tsp.month - 1u) }; + if (month_minus1 > 11u) [[unlikely]] + month_minus1 = 0u; + auto month_scatter{ t.ab_alt_mon[month_minus1] }; + iter = non_overlapped_copy_n(month_scatter.base, month_scatter.len, iter); + break; + } + case char_literal_v: + { + iter = lc_format_alt_digits_print(t.alt_digits,tsp.year/100,iter); + break; + } + case char_literal_v: + { + auto hours{tsp.hours}; + if (hours < 24u)[[likely]] + iter = copy_scatter_to_lowercase(t.am_pm[12u<=hours], iter); + break; + } + case char_literal_v: + { + auto hours{tsp.hours}; + if (hours < 24u)[[likely]] + iter = copy_scatter(t.am_pm[12u<=hours], iter); + break; + } + default: + { + auto ret{lc_time_ox_common_impl(tsp,ch)}; + if(ret.failed)[[unlikely]] + { + if(omit) + --p; + return non_overlapped_copy(p-2,end_it,iter); + } + else + { + iter = lc_format_alt_digits_print(t.alt_digits,ret.alt_value,iter); + break; + } + } + } + break; + } + case char_literal_v: + { + auto hours{tsp.hours}; + if (hours < 24u)[[likely]] + iter = copy_scatter_to_lowercase(t.am_pm[12u<=hours], iter); + break; + } + case char_literal_v: + { + auto hours{tsp.hours}; + if (hours < 24u)[[likely]] + iter = copy_scatter(t.am_pm[12u<=hours], iter); + break; + } + case char_literal_v: + { + iter = lc_print_reserve_define_time_fmt_common_impl(t, iter, tsp, t.t_fmt_ampm); + break; + } + case char_literal_v: + { + iter = chrono_two_digits_impl(iter, tsp.hours); + *iter = char_literal_v; + ++iter; + iter = chrono_two_digits_impl(iter, tsp.minutes); + break; + } + case char_literal_v: + { + iter = chrono_two_digits_impl(iter, tsp.seconds); + break; + } + case char_literal_v: + { + *iter = char_literal_v; + ++iter; + break; + } + case char_literal_v: + { + iter = chrono_two_digits_impl(iter, tsp.hours); + *iter = char_literal_v; + ++iter; + iter = chrono_two_digits_impl(iter, tsp.minutes); + *iter = char_literal_v; + ++iter; + iter = chrono_two_digits_impl(iter, tsp.seconds); + break; + } + case char_literal_v: + { + iter = chrono_one_digit_impl(iter, weekday(tsp)); + break; + } + case char_literal_v: + { + iter = print_reserve_integral_define<10>(iter, + static_cast(weekday(tsp.year, 1, 1) + day_of_the_year(tsp) - 1u) / 7u); + break; + } + case char_literal_v: + { + std::int_least64_t const year{ tsp.year }; + std::uint_least8_t const month{ tsp.month }; + std::uint_least8_t const day{ tsp.day }; + std::size_t const ndays{ t.week.ndays }; + std::size_t const first_week{ t.week.first_week }; + auto const benchmark_year{ static_cast(t.week.first_day / 10000) }; + auto const benchmark_month{ static_cast(t.week.first_day % 10000 / 100) }; + auto const benchmark_day{ static_cast(t.week.first_day % 100) }; + union { + std::int_least64_t s; + std::uint_least64_t u; + } weekday_of_1st_day_this_year{ day_diff(year, 1, 1, benchmark_year, benchmark_month, benchmark_day) % my_make_signed_t(ndays) }; + if (weekday_of_1st_day_this_year.s < 0) + weekday_of_1st_day_this_year.u += ndays + 1u; + else + ++weekday_of_1st_day_this_year.u; + std::uint_least64_t weekday_of_last_day_this_year; + if (is_leap_year(year)) + weekday_of_last_day_this_year = (weekday_of_1st_day_this_year.u + 364u) % ndays + 1u; + else + weekday_of_last_day_this_year = (weekday_of_1st_day_this_year.u + 363u) % ndays + 1u; + if (month == 1u && weekday_of_1st_day_this_year.u > ndays - first_week + 1u && weekday_of_1st_day_this_year.u + day < ndays + 2) + { + // calculate the week number of 12/31 of the last year + std::uint_least64_t weekday_of_12_31{ static_cast(weekday_of_1st_day_this_year.u + day_of_the_year(tsp) - 2u) % ndays }; + auto day_of_12_31{ static_cast(is_leap_year(year - 1) ? 366u : 365u) }; + auto weekday_of_1st_day_last_year{ static_cast((weekday_of_1st_day_this_year.s - day_of_12_31 - 1) % my_make_signed_t(ndays) + static_cast(ndays) + 1) }; + std::uint_least64_t weeknum{ static_cast(day_of_12_31 + weekday_of_1st_day_last_year - weekday_of_12_31 - 1u) / ndays }; + if (weekday_of_1st_day_last_year < ndays - first_week + 2u) + ++weeknum; + iter = chrono_two_digits_impl(iter, weeknum); + } + else if (month == 12u && weekday_of_last_day_this_year <= ndays - first_week && weekday_of_last_day_this_year + day >= 32) + iter = lc_copy_01_impl(iter); + else [[likely]] + { + std::uint_least64_t weekday_of_today{ static_cast(weekday_of_1st_day_this_year.u + day_of_the_year(tsp) - 2u) % ndays + 1u }; + std::uint_least64_t weeknum{ static_cast(day_of_the_year(tsp) + weekday_of_1st_day_this_year.u - weekday_of_today - 1u) / ndays }; + if (weekday_of_1st_day_this_year.u < ndays - first_week + 2u) + ++weeknum; + iter = chrono_two_digits_impl(iter, weeknum); + } + break; + } + case char_literal_v: + { + auto year{ tsp.year }; + auto month{ tsp.month }; + auto day{ tsp.day }; + std::uint_least8_t weekday_of_1st_day_this_year{ weekday(tsp.year, 1, 1) }; + auto weekday_of_last_day_this_year{ weekday_of_1st_day_this_year }; + if (is_leap_year(year)) + ++weekday_of_last_day_this_year; + if (month == 1u && weekday_of_1st_day_this_year > 4u && weekday_of_1st_day_this_year + day < 9u) + { + // calculate the week number of the last year + auto year_minus1{ year - 1 }; + if ((is_leap_year(year_minus1) && weekday_of_1st_day_this_year > 5u) || + (is_leap_year(year_minus1) && weekday_of_1st_day_this_year > 6u)) + iter = lc_copy_52_impl(iter); + else + iter = lc_copy_53_impl(iter); + } + else if (month == 12u && weekday_of_last_day_this_year < 4u && weekday_of_last_day_this_year + day > 31u) + iter = lc_copy_01_impl(iter); + else + { + // the number of today out of 1/1 this year + auto weeknum{ static_cast(static_cast(day_of_the_year(tsp) - weekday(tsp) + weekday_of_1st_day_this_year - 1u) / 7u) }; + // the week number of 1/1 may be 0 or 1 + if (weekday_of_1st_day_this_year < 5u) + ++weeknum; + iter = chrono_two_digits_impl(iter, weeknum); + } + break; + } + case char_literal_v: + { + *iter = static_cast(c_weekday(tsp)+char_literal_v); + ++iter; + break; + } + case char_literal_v: + { + iter = chrono_two_digits_impl(iter, + static_cast(day_of_the_year(tsp) - weekday(tsp) + weekday(tsp.year, 1, 1) - 1u) / 7u); + break; + } + case char_literal_v: + { + iter = lc_print_reserve_define_time_fmt_common_impl(t, iter, tsp, t.d_fmt); + break; + } + case char_literal_v: + { + iter = lc_print_reserve_define_time_fmt_common_impl(t, iter, tsp, t.t_fmt); + break; + } + case char_literal_v: + case char_literal_v: + { + iter = chrono_year_impl(iter, tsp.year); + break; + } + case char_literal_v: + case char_literal_v: + { + iter = print_reserve_timezone_impl(iter,tsp.timezone); + break; + } + default: + { + if(omit) + --p; + return non_overlapped_copy(p-1,end_it,iter); + } + } + i=p; + } + return iter; +} + +template<::fast_io::manipulators::lc_time_flag flag> +inline constexpr ::fast_io::manipulators::scalar_flags base_lc_time_flags_cache{.time_flag=flag}; + +} + +namespace manipulators +{ +/* +do not use them. they are experimental +*/ +inline constexpr scalar_manip_t<::fast_io::details::base_lc_time_flags_cache,iso8601_timestamp const&> d_t_fmt(iso8601_timestamp const& tsp) noexcept +{ + return {tsp}; +} + +inline constexpr scalar_manip_t<::fast_io::details::base_lc_time_flags_cache,iso8601_timestamp const&> d_fmt(iso8601_timestamp const& tsp) noexcept +{ + return {tsp}; +} + +inline constexpr scalar_manip_t<::fast_io::details::base_lc_time_flags_cache,iso8601_timestamp const&> t_fmt(iso8601_timestamp const& tsp) noexcept +{ + return {tsp}; +} + +inline constexpr scalar_manip_t<::fast_io::details::base_lc_time_flags_cache,iso8601_timestamp const&> t_fmt_ampm(iso8601_timestamp const& tsp) noexcept +{ + return {tsp}; +} + +inline constexpr scalar_manip_t<::fast_io::details::base_lc_time_flags_cache,iso8601_timestamp const&> date_fmt(iso8601_timestamp const& tsp) noexcept +{ + return {tsp}; +} + +inline constexpr scalar_manip_t<::fast_io::details::base_lc_time_flags_cache,iso8601_timestamp const&> era_d_t_fmt(iso8601_timestamp const& tsp) noexcept +{ + return {tsp}; +} + +inline constexpr scalar_manip_t<::fast_io::details::base_lc_time_flags_cache,iso8601_timestamp const&> era_d_fmt(iso8601_timestamp const& tsp) noexcept +{ + return {tsp}; +} + +inline constexpr scalar_manip_t<::fast_io::details::base_lc_time_flags_cache,iso8601_timestamp const&> era_t_fmt(iso8601_timestamp const& tsp) noexcept +{ + return {tsp}; +} + +} + +template<::fast_io::manipulators::scalar_flags flags,std::integral char_type> +requires (static_cast(static_cast(flags.time_flag)-static_cast(1u))< + static_cast(8u)) +inline constexpr std::size_t print_reserve_size(basic_lc_all const* all, + ::fast_io::manipulators::scalar_manip_t tsp) noexcept +{ + constexpr manipulators::lc_time_flag current_lc_time_flag{flags.time_flag}; + if constexpr(current_lc_time_flag==manipulators::lc_time_flag::d_t_fmt) + return details::lc_print_reserve_size_time_format_common_impl(all->time, tsp.reference, all->time.d_t_fmt); + else if constexpr(current_lc_time_flag==manipulators::lc_time_flag::d_fmt) + return details::lc_print_reserve_size_time_format_common_impl(all->time, tsp.reference, all->time.d_fmt); + else if constexpr(current_lc_time_flag==manipulators::lc_time_flag::t_fmt) + return details::lc_print_reserve_size_time_format_common_impl(all->time, tsp.reference, all->time.t_fmt); + else if constexpr(current_lc_time_flag==manipulators::lc_time_flag::t_fmt_ampm) + return details::lc_print_reserve_size_time_format_common_impl(all->time, tsp.reference, all->time.t_fmt_ampm); + else if constexpr(current_lc_time_flag==manipulators::lc_time_flag::date_fmt) + return details::lc_print_reserve_size_time_format_common_impl(all->time, tsp.reference, all->time.date_fmt); + else if constexpr(current_lc_time_flag==manipulators::lc_time_flag::era_d_t_fmt) + { + auto* e{__builtin_addressof(all->time.era_d_t_fmt)}; + if(e->len==0) + e=__builtin_addressof(all->time.d_t_fmt); + return details::lc_print_reserve_size_time_format_common_impl(all->time, tsp.reference, *e); + } + else if constexpr(current_lc_time_flag==manipulators::lc_time_flag::era_d_fmt) + { + auto* e{__builtin_addressof(all->time.era_d_fmt)}; + if(e->len==0) + e=__builtin_addressof(all->time.d_fmt); + return details::lc_print_reserve_size_time_format_common_impl(all->time, tsp.reference, *e); + } + else if constexpr(current_lc_time_flag==manipulators::lc_time_flag::era_t_fmt) + { + auto* e{__builtin_addressof(all->time.era_t_fmt)}; + if(e->len==0) + e=__builtin_addressof(all->time.t_fmt); + return details::lc_print_reserve_size_time_format_common_impl(all->time, tsp.reference, *e); + } +} + +template<::fast_io::manipulators::scalar_flags flags, ::std::integral char_type> +requires (static_cast(static_cast(flags.time_flag)-static_cast(1u))< + static_cast(8u)) +inline constexpr char_type* print_reserve_define(basic_lc_all const* all, char_type* iter, + ::fast_io::manipulators::scalar_manip_t tsp) noexcept +{ + constexpr manipulators::lc_time_flag current_lc_time_flag{flags.time_flag}; + if constexpr(current_lc_time_flag==manipulators::lc_time_flag::d_t_fmt) + return details::lc_print_reserve_define_time_fmt_common_impl(all->time,iter,tsp.reference,all->time.d_t_fmt); + else if constexpr(current_lc_time_flag==manipulators::lc_time_flag::d_fmt) + return details::lc_print_reserve_define_time_fmt_common_impl(all->time,iter,tsp.reference,all->time.d_fmt); + else if constexpr(current_lc_time_flag==manipulators::lc_time_flag::t_fmt) + return details::lc_print_reserve_define_time_fmt_common_impl(all->time,iter,tsp.reference,all->time.t_fmt); + else if constexpr(current_lc_time_flag==manipulators::lc_time_flag::t_fmt_ampm) + return details::lc_print_reserve_define_time_fmt_common_impl(all->time,iter,tsp.reference,all->time.t_fmt_ampm); + else if constexpr(current_lc_time_flag==manipulators::lc_time_flag::date_fmt) + return details::lc_print_reserve_define_time_fmt_common_impl(all->time,iter,tsp.reference,all->time.date_fmt); + else if constexpr(current_lc_time_flag==manipulators::lc_time_flag::era_d_t_fmt) + { + auto* e{__builtin_addressof(all->time.era_d_t_fmt)}; + if(e->len==0) + e=__builtin_addressof(all->time.d_t_fmt); + return details::lc_print_reserve_define_time_fmt_common_impl(all->time,iter,tsp.reference,*e); + } + else if constexpr(current_lc_time_flag==manipulators::lc_time_flag::era_d_fmt) + { + auto* e{__builtin_addressof(all->time.era_d_fmt)}; + if(e->len==0) + e=__builtin_addressof(all->time.d_fmt); + return details::lc_print_reserve_define_time_fmt_common_impl(all->time,iter,tsp.reference,*e); + } + else if constexpr(current_lc_time_flag==manipulators::lc_time_flag::era_t_fmt) + { + auto* e{__builtin_addressof(all->time.era_t_fmt)}; + if(e->len==0) + e=__builtin_addressof(all->time.t_fmt); + return details::lc_print_reserve_define_time_fmt_common_impl(all->time,iter,tsp.reference,*e); + } +} + +} diff --git a/src/fast_io/include/fast_io_i18n/lc_numbers/width.h b/src/fast_io/include/fast_io_i18n/lc_numbers/width.h new file mode 100644 index 0000000..563ee08 --- /dev/null +++ b/src/fast_io/include/fast_io_i18n/lc_numbers/width.h @@ -0,0 +1,125 @@ +#pragma once + +namespace fast_io +{ + +namespace details +{ + +template +inline constexpr std::size_t lc_print_reserve_size_width_impl(basic_lc_all const* all,T w,std::size_t width) noexcept +{ + using value_type = std::remove_cvref_t; + if constexpr(lc_dynamic_reserve_printable) + { + std::size_t const sz{print_reserve_size(all,w)}; + if(width) + { + basic_io_scatter_t const scatter{print_scatter_define(all,w)}; + if(width +requires (std::is_trivially_copyable_v) +inline constexpr char_type* lc_print_reserve_define_width_ch_impl(basic_lc_all const* __restrict all,char_type* iter,T t,std::size_t wdt,char_type fillch) noexcept +{ + using value_type = std::remove_cvref_t; + if constexpr(placement==::fast_io::manipulators::scalar_placement::internal) + { + static_assert(lc_printable_internal_shift); + if constexpr(lc_printable_internal_shift) + { + if constexpr(lc_scatter_printable) + { + auto sc{print_scatter_define(all,t)}; + auto it{copy_scatter(sc,iter)}; + return handle_common_internal_ch(iter,it,wdt,fillch,print_define_internal_shift(all,t)); + } + else + { + char_type* it{print_reserve_define(all,iter,t)}; + return handle_common_internal_ch(iter,it,wdt,fillch,print_define_internal_shift(all,t)); + } + } + else + { + return print_reserve_define_width_ch_impl<::fast_io::manipulators::scalar_placement::right>(iter,t,wdt,fillch); + } + } + else + { + if constexpr(lc_scatter_printable) + { + auto sc{print_scatter_define(all,t)}; + auto it{copy_scatter(sc,iter)}; + return handle_common_ch(iter,it,wdt,fillch); + } + else + { + char_type* it{print_reserve_define(all,iter,t)}; + return handle_common_ch(iter,it,wdt,fillch); + } + } +} + +template<::fast_io::manipulators::scalar_placement wm,::std::integral char_type,typename T> +inline constexpr char_type* lc_print_reserve_define_width_impl(basic_lc_all const* __restrict all, char_type* iter,T t,std::size_t width) noexcept +{ + return lc_print_reserve_define_width_ch_impl(all,iter,t,width,char_literal_v); +} + +} + +template +requires ((lc_dynamic_reserve_printable>|| + lc_scatter_printable>)) +inline constexpr std::size_t print_reserve_size(basic_lc_all const* __restrict all,manipulators::width_t w) noexcept +{ + if constexpr(std::is_reference_v) + return details::lc_print_reserve_size_width_impl(all,parameter{w.reference},w.width); + else + return details::lc_print_reserve_size_width_impl(all,w.reference,w.width); +} + +template<::std::integral char_type,manipulators::scalar_placement wm,typename T> +requires ((lc_dynamic_reserve_printable>|| + lc_scatter_printable>)) +inline constexpr char_type* print_reserve_define(basic_lc_all const* __restrict all, char_type* iter,manipulators::width_t w) noexcept +{ + if constexpr(std::is_reference_v) + return details::lc_print_reserve_define_width_impl(all,iter,parameter{w.reference},w.width); + else + return details::lc_print_reserve_define_width_impl(all,iter,w.reference,w.width); +} + + +template +requires ((lc_dynamic_reserve_printable>|| + lc_scatter_printable>)) +inline constexpr std::size_t print_reserve_size(basic_lc_all const* __restrict all,manipulators::width_ch_t w) noexcept +{ + if constexpr(std::is_reference_v) + return details::lc_print_reserve_size_width_impl(all,parameter{w.reference},w.width); + else + return details::lc_print_reserve_size_width_impl(all,w.reference,w.width); +} + +template<::std::integral char_type,manipulators::scalar_placement wm,typename T> +requires ((lc_dynamic_reserve_printable>|| + lc_scatter_printable>)) +inline constexpr char_type* print_reserve_define(basic_lc_all const* __restrict all, char_type* iter,manipulators::width_ch_t w) noexcept +{ + if constexpr(std::is_reference_v) + return details::lc_print_reserve_define_width_ch_impl(all,iter,parameter{w.reference},w.width,w.ch); + else + return details::lc_print_reserve_define_width_ch_impl(all,iter,w.reference,w.width,w.ch); +} + +} diff --git a/src/fast_io/include/fast_io_i18n/lc_print.h b/src/fast_io/include/fast_io_i18n/lc_print.h new file mode 100644 index 0000000..c45caad --- /dev/null +++ b/src/fast_io/include/fast_io_i18n/lc_print.h @@ -0,0 +1,1000 @@ +#pragma once + +namespace fast_io +{ + +namespace details +{ + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +constexpr void print_define_impl_lc_identification(output bos,basic_lc_identification const& identification) +{ + if constexpr(std::same_as) + print_freestanding(bos,"LC_IDENTIFICATION\n" + "name\t\"",identification.name,"\"\n" + "encoding\t\"",identification.encoding,"\"\n" + "title\t\"",identification.title,"\"\n" + "source\t\"",identification.source,"\"\n" + "address\t\"",identification.address,"\"\n" + "contact\t\"",identification.contact,"\"\n" + "email\t\"",identification.email,"\"\n" + "tel\t\"",identification.tel,"\"\n" + "fax\t\"",identification.fax,"\"\n" + "language\t\"",identification.language,"\"\n" + "territory\t\"",identification.territory,"\"\n" + "audience\t\"",identification.audience,"\"\n" + "application\t\"",identification.application,"\"\n" + "abbreviation\t\"",identification.abbreviation,"\"\n" + "revision\t\"",identification.revision,"\"\n" + "date\t\"",identification.date,"\"\n" + "END LC_IDENTIFICATION"); + else if constexpr(std::same_as) + print_freestanding(bos,L"LC_IDENTIFICATION\n" + L"name\t\"",identification.name,L"\"\n" + L"encoding\t\"",identification.encoding,L"\"\n" + L"title\t\"",identification.title,L"\"\n" + L"source\t\"",identification.source,L"\"\n" + L"address\t\"",identification.address,L"\"\n" + L"contact\t\"",identification.contact,L"\"\n" + L"email\t\"",identification.email,L"\"\n" + L"tel\t\"",identification.tel,L"\"\n" + L"fax\t\"",identification.fax,L"\"\n" + L"language\t\"",identification.language,L"\"\n" + L"territory\t\"",identification.territory,L"\"\n" + L"audience\t\"",identification.audience,L"\"\n" + L"application\t\"",identification.application,L"\"\n" + L"abbreviation\t\"",identification.abbreviation,L"\"\n" + L"revision\t\"",identification.revision,L"\"\n" + L"date\t\"",identification.date,L"\"\n" + L"END LC_IDENTIFICATION"); + else if constexpr(std::same_as) + print_freestanding(bos,u"LC_IDENTIFICATION\n" + u"name\t\"",identification.name,u"\"\n" + u"encoding\t\"",identification.encoding,u"\"\n" + u"title\t\"",identification.title,u"\"\n" + u"source\t\"",identification.source,u"\"\n" + u"address\t\"",identification.address,u"\"\n" + u"contact\t\"",identification.contact,u"\"\n" + u"email\t\"",identification.email,u"\"\n" + u"tel\t\"",identification.tel,u"\"\n" + u"fax\t\"",identification.fax,u"\"\n" + u"language\t\"",identification.language,u"\"\n" + u"territory\t\"",identification.territory,u"\"\n" + u"audience\t\"",identification.audience,u"\"\n" + u"application\t\"",identification.application,u"\"\n" + u"abbreviation\t\"",identification.abbreviation,u"\"\n" + u"revision\t\"",identification.revision,u"\"\n" + u"date\t\"",identification.date,u"\"\n" + u"END LC_IDENTIFICATION"); + else if constexpr(std::same_as) + print_freestanding(bos,U"LC_IDENTIFICATION\n" + U"name\t\"",identification.name,U"\"\n" + U"encoding\t\"",identification.encoding,U"\"\n" + U"title\t\"",identification.title,U"\"\n" + U"source\t\"",identification.source,U"\"\n" + U"address\t\"",identification.address,U"\"\n" + U"contact\t\"",identification.contact,U"\"\n" + U"email\t\"",identification.email,U"\"\n" + U"tel\t\"",identification.tel,U"\"\n" + U"fax\t\"",identification.fax,U"\"\n" + U"language\t\"",identification.language,U"\"\n" + U"territory\t\"",identification.territory,U"\"\n" + U"audience\t\"",identification.audience,U"\"\n" + U"application\t\"",identification.application,U"\"\n" + U"abbreviation\t\"",identification.abbreviation,U"\"\n" + U"revision\t\"",identification.revision,U"\"\n" + U"date\t\"",identification.date,U"\"\n" + U"END LC_IDENTIFICATION"); + else if constexpr(std::same_as) + print_freestanding(bos,u8"LC_IDENTIFICATION\n" + u8"name\t\"",identification.name,u8"\"\n" + u8"encoding\t\"",identification.encoding,u8"\"\n" + u8"title\t\"",identification.title,u8"\"\n" + u8"source\t\"",identification.source,u8"\"\n" + u8"address\t\"",identification.address,u8"\"\n" + u8"contact\t\"",identification.contact,u8"\"\n" + u8"email\t\"",identification.email,u8"\"\n" + u8"tel\t\"",identification.tel,u8"\"\n" + u8"fax\t\"",identification.fax,u8"\"\n" + u8"language\t\"",identification.language,u8"\"\n" + u8"territory\t\"",identification.territory,u8"\"\n" + u8"audience\t\"",identification.audience,u8"\"\n" + u8"application\t\"",identification.application,u8"\"\n" + u8"abbreviation\t\"",identification.abbreviation,u8"\"\n" + u8"revision\t\"",identification.revision,u8"\"\n" + u8"date\t\"",identification.date,u8"\"\n" + u8"END LC_IDENTIFICATION"); +} + + +} + +namespace details +{ +template +constexpr void print_grouping(output bos,basic_io_scatter_t grouping) +{ + using char_type = typename output::char_type; + if(grouping.len==0) + { + if constexpr(std::same_as) + print_freestanding(bos,"-1"); + else if constexpr(std::same_as) + print_freestanding(bos,L"-1"); + else if constexpr(std::same_as) + print_freestanding(bos,u"-1"); + else if constexpr(std::same_as) + print_freestanding(bos,U"-1"); + else if constexpr(std::same_as) + print_freestanding(bos,u8"-1"); + return; + } + for(std::size_t i{};i!=grouping.len;++i) + { + if(i) + put(bos,char_literal_v); + if(grouping.base[i]==std::numeric_limits::max()) + { + if constexpr(std::same_as) + print_freestanding(bos,"-1"); + else if constexpr(std::same_as) + print_freestanding(bos,L"-1"); + else if constexpr(std::same_as) + print_freestanding(bos,u"-1"); + else if constexpr(std::same_as) + print_freestanding(bos,U"-1"); + else if constexpr(std::same_as) + print_freestanding(bos,u8"-1"); + } + else + print_freestanding(bos,grouping.base[i]); + } +} + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +constexpr void print_define_impl_lc_monetary(output bos,basic_lc_monetary const& monetary) +{ + if constexpr(std::same_as) + { + print_freestanding(bos,"LC_MONETARY\n" + "int_curr_symbol\t\"",monetary.int_curr_symbol,"\"\n" + "currency_symbol\t\"",monetary.currency_symbol,"\"\n" + "mon_decimal_point\t\"",monetary.mon_decimal_point,"\"\n" + "mon_thousands_sep\t\"",monetary.mon_thousands_sep,"\"\n" + "mon_grouping\t"); + ::fast_io::details::print_grouping(bos,monetary.mon_grouping); + print_freestanding(bos,"\n" + "positive_sign\t\"",monetary.positive_sign,"\"\n" + "negative_sign\t\"",monetary.negative_sign,"\"\n" + "int_frac_digits\t",monetary.int_frac_digits,"\n" + "frac_digits\t",monetary.frac_digits,"\n" + "p_cs_precedes\t",monetary.p_cs_precedes,"\n" + "p_sep_by_space\t",monetary.p_sep_by_space,"\n" + "n_cs_precedes\t",monetary.n_cs_precedes,"\n" + "n_sep_by_space\t",monetary.n_sep_by_space,"\n" + "int_p_cs_precedes\t",monetary.int_p_cs_precedes,"\n" + "int_p_sep_by_space\t",monetary.int_p_sep_by_space,"\n" + "int_n_cs_precedes\t",monetary.int_n_cs_precedes,"\n" + "int_n_sep_by_space\t",monetary.int_n_sep_by_space,"\n" + "p_sign_posn\t",monetary.p_sign_posn,"\n" + "n_sign_posn\t",monetary.n_sign_posn,"\n" + "int_p_sign_posn\t",monetary.int_p_sign_posn,"\n" + "int_n_sign_posn\t",monetary.int_n_sign_posn,"\n" + "END LC_MONETARY"); + } + else if constexpr(std::same_as) + { + print_freestanding(bos,L"LC_MONETARY\n" + L"int_curr_symbol\t\"",monetary.int_curr_symbol,L"\"\n" + L"currency_symbol\t\"",monetary.currency_symbol,L"\"\n" + L"mon_decimal_point\t\"",monetary.mon_decimal_point,L"\"\n" + L"mon_thousands_sep\t\"",monetary.mon_thousands_sep,L"\"\n" + L"mon_grouping\t"); + ::fast_io::details::print_grouping(bos,monetary.mon_grouping); + print_freestanding(bos,L"\n" + L"positive_sign\t\"",monetary.positive_sign,L"\"\n" + L"negative_sign\t\"",monetary.negative_sign,L"\"\n" + L"int_frac_digits\t",monetary.int_frac_digits,L"\n" + L"frac_digits\t",monetary.frac_digits,L"\n" + L"p_cs_precedes\t",monetary.p_cs_precedes,L"\n" + L"p_sep_by_space\t",monetary.p_sep_by_space,L"\n" + L"n_cs_precedes\t",monetary.n_cs_precedes,L"\n" + L"n_sep_by_space\t",monetary.n_sep_by_space,L"\n" + L"int_p_cs_precedes\t",monetary.int_p_cs_precedes,L"\n" + L"int_p_sep_by_space\t",monetary.int_p_sep_by_space,L"\n" + L"int_n_cs_precedes\t",monetary.int_n_cs_precedes,L"\n" + L"int_n_sep_by_space\t",monetary.int_n_sep_by_space,L"\n" + L"p_sign_posn\t",monetary.p_sign_posn,L"\n" + L"n_sign_posn\t",monetary.n_sign_posn,L"\n" + L"int_p_sign_posn\t",monetary.int_p_sign_posn,L"\n" + L"int_n_sign_posn\t",monetary.int_n_sign_posn,L"\n" + L"END LC_MONETARY"); + } + else if constexpr(std::same_as) + { + print_freestanding(bos,u"LC_MONETARY\n" + u"int_curr_symbol\t\"",monetary.int_curr_symbol,u"\"\n" + u"currency_symbol\t\"",monetary.currency_symbol,u"\"\n" + u"mon_decimal_point\t\"",monetary.mon_decimal_point,u"\"\n" + u"mon_thousands_sep\t\"",monetary.mon_thousands_sep,u"\"\n" + u"mon_grouping\t"); + ::fast_io::details::print_grouping(bos,monetary.mon_grouping); + print_freestanding(bos,u"\n" + u"positive_sign\t\"",monetary.positive_sign,u"\"\n" + u"negative_sign\t\"",monetary.negative_sign,u"\"\n" + u"int_frac_digits\t",monetary.int_frac_digits,u"\n" + u"frac_digits\t",monetary.frac_digits,u"\n" + u"p_cs_precedes\t",monetary.p_cs_precedes,u"\n" + u"p_sep_by_space\t",monetary.p_sep_by_space,u"\n" + u"n_cs_precedes\t",monetary.n_cs_precedes,u"\n" + u"n_sep_by_space\t",monetary.n_sep_by_space,u"\n" + u"int_p_cs_precedes\t",monetary.int_p_cs_precedes,u"\n" + u"int_p_sep_by_space\t",monetary.int_p_sep_by_space,u"\n" + u"int_n_cs_precedes\t",monetary.int_n_cs_precedes,u"\n" + u"int_n_sep_by_space\t",monetary.int_n_sep_by_space,u"\n" + u"p_sign_posn\t",monetary.p_sign_posn,u"\n" + u"n_sign_posn\t",monetary.n_sign_posn,u"\n" + u"int_p_sign_posn\t",monetary.int_p_sign_posn,u"\n" + u"int_n_sign_posn\t",monetary.int_n_sign_posn,u"\n" + u"END LC_MONETARY"); + } + else if constexpr(std::same_as) + { + print_freestanding(bos,U"LC_MONETARY\n" + U"int_curr_symbol\t\"",monetary.int_curr_symbol,U"\"\n" + U"currency_symbol\t\"",monetary.currency_symbol,U"\"\n" + U"mon_decimal_point\t\"",monetary.mon_decimal_point,U"\"\n" + U"mon_thousands_sep\t\"",monetary.mon_thousands_sep,U"\"\n" + U"mon_grouping\t"); + ::fast_io::details::print_grouping(bos,monetary.mon_grouping); + print_freestanding(bos,U"\n" + U"positive_sign\t\"",monetary.positive_sign,U"\"\n" + U"negative_sign\t\"",monetary.negative_sign,U"\"\n" + U"int_frac_digits\t",monetary.int_frac_digits,U"\n" + U"frac_digits\t",monetary.frac_digits,U"\n" + U"p_cs_precedes\t",monetary.p_cs_precedes,U"\n" + U"p_sep_by_space\t",monetary.p_sep_by_space,U"\n" + U"n_cs_precedes\t",monetary.n_cs_precedes,U"\n" + U"n_sep_by_space\t",monetary.n_sep_by_space,U"\n" + U"int_p_cs_precedes\t",monetary.int_p_cs_precedes,U"\n" + U"int_p_sep_by_space\t",monetary.int_p_sep_by_space,U"\n" + U"int_n_cs_precedes\t",monetary.int_n_cs_precedes,U"\n" + U"int_n_sep_by_space\t",monetary.int_n_sep_by_space,U"\n" + U"p_sign_posn\t",monetary.p_sign_posn,U"\n" + U"n_sign_posn\t",monetary.n_sign_posn,U"\n" + U"int_p_sign_posn\t",monetary.int_p_sign_posn,U"\n" + U"int_n_sign_posn\t",monetary.int_n_sign_posn,U"\n" + U"END LC_MONETARY"); + } + else if constexpr(std::same_as) + { + print_freestanding(bos,u8"LC_MONETARY\n" + u8"int_curr_symbol\t\"",monetary.int_curr_symbol,u8"\"\n" + u8"currency_symbol\t\"",monetary.currency_symbol,u8"\"\n" + u8"mon_decimal_point\t\"",monetary.mon_decimal_point,u8"\"\n" + u8"mon_thousands_sep\t\"",monetary.mon_thousands_sep,u8"\"\n" + u8"mon_grouping\t"); + ::fast_io::details::print_grouping(bos,monetary.mon_grouping); + print_freestanding(bos,u8"\n" + u8"positive_sign\t\"",monetary.positive_sign,u8"\"\n" + u8"negative_sign\t\"",monetary.negative_sign,u8"\"\n" + u8"int_frac_digits\t",monetary.int_frac_digits,u8"\n" + u8"frac_digits\t",monetary.frac_digits,u8"\n" + u8"p_cs_precedes\t",monetary.p_cs_precedes,u8"\n" + u8"p_sep_by_space\t",monetary.p_sep_by_space,u8"\n" + u8"n_cs_precedes\t",monetary.n_cs_precedes,u8"\n" + u8"n_sep_by_space\t",monetary.n_sep_by_space,u8"\n" + u8"int_p_cs_precedes\t",monetary.int_p_cs_precedes,u8"\n" + u8"int_p_sep_by_space\t",monetary.int_p_sep_by_space,u8"\n" + u8"int_n_cs_precedes\t",monetary.int_n_cs_precedes,u8"\n" + u8"int_n_sep_by_space\t",monetary.int_n_sep_by_space,u8"\n" + u8"p_sign_posn\t",monetary.p_sign_posn,u8"\n" + u8"n_sign_posn\t",monetary.n_sign_posn,u8"\n" + u8"int_p_sign_posn\t",monetary.int_p_sign_posn,u8"\n" + u8"int_n_sign_posn\t",monetary.int_n_sign_posn,u8"\n" + u8"END LC_MONETARY"); + } +} +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +constexpr void print_define_impl_lc_numeric(output bos,basic_lc_numeric const& numeric) +{ + if constexpr(std::same_as) + { + print_freestanding(bos,"LC_NUMERIC\n" + "decimal_point\t\"",numeric.decimal_point,"\"\n" + "thousands_sep\t\"",numeric.thousands_sep,"\"\n" + "grouping\t"); + ::fast_io::details::print_grouping(bos,numeric.grouping); + print_freestanding(bos,"\n" + "END LC_NUMERIC"); + } + else if constexpr(std::same_as) + { + print_freestanding(bos,L"LC_NUMERIC\n" + L"decimal_point\t\"",numeric.decimal_point,L"\"\n" + L"thousands_sep\t\"",numeric.thousands_sep,L"\"\n" + L"grouping\t"); + ::fast_io::details::print_grouping(bos,numeric.grouping); + print_freestanding(bos,L"\n" + L"END LC_NUMERIC"); + } + else if constexpr(std::same_as) + { + print_freestanding(bos,u"LC_NUMERIC\n" + u"decimal_point\t\"",numeric.decimal_point,u"\"\n" + u"thousands_sep\t\"",numeric.thousands_sep,u"\"\n" + u"grouping\t"); + ::fast_io::details::print_grouping(bos,numeric.grouping); + print_freestanding(bos,u"\n" + u"END LC_NUMERIC"); + } + else if constexpr(std::same_as) + { + print_freestanding(bos,U"LC_NUMERIC\n" + U"decimal_point\t\"",numeric.decimal_point,U"\"\n" + U"thousands_sep\t\"",numeric.thousands_sep,U"\"\n" + U"grouping\t"); + ::fast_io::details::print_grouping(bos,numeric.grouping); + print_freestanding(bos,U"\n" + U"END LC_NUMERIC"); + } + else if constexpr(std::same_as) + { + print_freestanding(bos,u8"LC_NUMERIC\n" + u8"decimal_point\t\"",numeric.decimal_point,u8"\"\n" + u8"thousands_sep\t\"",numeric.thousands_sep,u8"\"\n" + u8"grouping\t"); + ::fast_io::details::print_grouping(bos,numeric.grouping); + print_freestanding(bos,u8"\n" + u8"END LC_NUMERIC"); + } +} +} + +namespace details +{ +template +constexpr void print_loc_days_real_impl(output bos,typename output::char_type const* category_name,std::size_t category_name_len,basic_io_scatter_t const* day_strings,std::size_t day_strings_len) +{ + using char_type = typename output::char_type; + if(day_strings_len==0||day_strings_len==0) + return; + print_freestanding(bos,basic_io_scatter_t{category_name,category_name_len}); + put(bos,char_literal_v); + for(std::size_t i{};i!=day_strings_len;++i) + { + if(i) + put(bos,char_literal_v); + put(bos,char_literal_v); + print_freestanding(bos,day_strings[i]); + put(bos,char_literal_v); + } + put(bos,char_literal_v); +} + +template +constexpr void print_loc_days_impl(output bos,typename output::char_type const (&category_name)[n],basic_io_scatter_t> day_strings) +{ + print_loc_days_real_impl(bos,category_name,n-1,day_strings.base,day_strings.len); +} + +template +constexpr void print_loc_era_impl(output bos,basic_lc_time_era const* eras_ptr,std::size_t n) +{ + using char_type = typename output::char_type; + if(n==0) + return; + if constexpr(std::same_as) + { + print(bos,"era\t"); + } + else if constexpr(std::same_as) + { + print(bos,L"era\t"); + } + else if constexpr(std::same_as) + { + print(bos,u"era\t"); + } + else if constexpr(std::same_as) + { + print(bos,U"era\t"); + } + else + { + print(bos,u8"era\t"); + } + for(std::size_t i{};i!=n;++i) + { + if(i) + put(bos,char_literal_v); + put(bos,char_literal_v); + print_freestanding(bos,eras_ptr[i].era); + put(bos,char_literal_v); + } + put(bos,char_literal_v); +} + +template +constexpr void print_loc_days_impl_const(output bos,ch_type1 const (&category_name)[n1],basic_io_scatter_t const (&day_strings)[n2]) +{ + print_loc_days_real_impl(bos,category_name,n1-1,day_strings,n2); +} + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +constexpr void print_define_impl_lc_time(output bos,basic_lc_time const& time) +{ + if constexpr(std::same_as) + { + print_freestanding(bos,"LC_TIME\n"); + ::fast_io::details::print_loc_days_impl_const(bos,"abday",time.abday); + ::fast_io::details::print_loc_days_impl_const(bos,"day",time.day); + ::fast_io::details::print_loc_days_impl_const(bos,"abmon",time.abmon); + ::fast_io::details::print_loc_days_impl_const(bos,"ab_alt_mon",time.ab_alt_mon); + ::fast_io::details::print_loc_days_impl_const(bos,"mon",time.mon); + print_freestanding(bos, + "d_t_fmt\t\"",time.d_t_fmt,"\"\n", + "d_fmt\t\"",time.d_fmt,"\"\n", + "t_fmt\t\"",time.t_fmt,"\"\n", + "t_fmt_ampm\t\"",time.t_fmt_ampm,"\"\n", + "date_fmt\t\"",time.date_fmt,"\"\n", + "am_pm\t\"",time.am_pm[0],"\";\"",time.am_pm[1],"\"\n"); + ::fast_io::details::print_loc_era_impl(bos,time.era.base,time.era.len); + print_freestanding(bos,"era_d_fmt\t\"",time.era_d_fmt,"\"\n", + "era_d_t_fmt\t\"",time.era_d_t_fmt,"\"\n", + "era_t_fmt\t\"",time.era_t_fmt,"\"\n"); + ::fast_io::details::print_loc_days_impl(bos,"alt_digits",time.alt_digits); + println_freestanding(bos,"week\t",time.week.ndays,";",time.week.first_day,";",time.week.first_week,"\n", + "first_weekday\t",time.first_weekday,"\n" + "first_workday\t",time.first_workday,"\n" + "cal_direction\t",time.cal_direction); + ::fast_io::details::print_loc_days_impl(bos,"timezone",time.timezone); + print_freestanding(bos,"END LC_TIME"); + } + else if constexpr(std::same_as) + { + print_freestanding(bos,L"LC_TIME\n"); + ::fast_io::details::print_loc_days_impl_const(bos,L"abday",time.abday); + ::fast_io::details::print_loc_days_impl_const(bos,L"day",time.day); + ::fast_io::details::print_loc_days_impl_const(bos,L"abmon",time.abmon); + ::fast_io::details::print_loc_days_impl_const(bos,L"ab_alt_mon",time.ab_alt_mon); + ::fast_io::details::print_loc_days_impl_const(bos,L"mon",time.mon); + print_freestanding(bos, + L"d_t_fmt\t\"",time.d_t_fmt,L"\"\n", + L"d_fmt\t\"",time.d_fmt,L"\"\n", + L"t_fmt\t\"",time.t_fmt,L"\"\n", + L"t_fmt_ampm\t\"",time.t_fmt_ampm,L"\"\n", + L"date_fmt\t\"",time.date_fmt,L"\"\n", + L"am_pm\t\"",time.am_pm[0],L"\";\"",time.am_pm[1],L"\"\n"); + ::fast_io::details::print_loc_era_impl(bos,time.era.base,time.era.len); + print_freestanding(bos,L"era_d_fmt\t\"",time.era_d_fmt,L"\"\n", + L"era_d_t_fmt\t\"",time.era_d_t_fmt,L"\"\n", + L"era_t_fmt\t\"",time.era_t_fmt,L"\"\n"); + ::fast_io::details::print_loc_days_impl(bos,L"alt_digits",time.alt_digits); + println_freestanding(bos,L"week\t",time.week.ndays,L";",time.week.first_day,L";",time.week.first_week,L"\n", + L"first_weekday\t",time.first_weekday,L"\n" + L"first_workday\t",time.first_workday,L"\n" + L"cal_direction\t",time.cal_direction); + ::fast_io::details::print_loc_days_impl(bos,L"timezone",time.timezone); + print_freestanding(bos,L"END LC_TIME"); + } + else if constexpr(std::same_as) + { + print_freestanding(bos,u"LC_TIME\n"); + ::fast_io::details::print_loc_days_impl_const(bos,u"abday",time.abday); + ::fast_io::details::print_loc_days_impl_const(bos,u"day",time.day); + ::fast_io::details::print_loc_days_impl_const(bos,u"abmon",time.abmon); + ::fast_io::details::print_loc_days_impl_const(bos,u"ab_alt_mon",time.ab_alt_mon); + ::fast_io::details::print_loc_days_impl_const(bos,u"mon",time.mon); + print_freestanding(bos, + u"d_t_fmt\t\"",time.d_t_fmt,u"\"\n", + u"d_fmt\t\"",time.d_fmt,u"\"\n", + u"t_fmt\t\"",time.t_fmt,u"\"\n", + u"t_fmt_ampm\t\"",time.t_fmt_ampm,u"\"\n", + u"date_fmt\t\"",time.date_fmt,u"\"\n", + u"am_pm\t\"",time.am_pm[0],u"\";\"",time.am_pm[1],u"\"\n"); + ::fast_io::details::print_loc_era_impl(bos,time.era.base,time.era.len); + print_freestanding(bos,u"era_d_fmt\t\"",time.era_d_fmt,u"\"\n", + u"era_d_t_fmt\t\"",time.era_d_t_fmt,u"\"\n", + u"era_t_fmt\t\"",time.era_t_fmt,u"\"\n"); + ::fast_io::details::print_loc_days_impl(bos,u"alt_digits",time.alt_digits); + println_freestanding(bos,u"week\t",time.week.ndays,u";",time.week.first_day,u";",time.week.first_week,u"\n", + u"first_weekday\t",time.first_weekday,u"\n" + u"first_workday\t",time.first_workday,u"\n" + u"cal_direction\t",time.cal_direction); + ::fast_io::details::print_loc_days_impl(bos,u"timezone",time.timezone); + print_freestanding(bos,u"END LC_TIME"); + } + else if constexpr(std::same_as) + { + print_freestanding(bos,U"LC_TIME\n"); + ::fast_io::details::print_loc_days_impl_const(bos,U"abday",time.abday); + ::fast_io::details::print_loc_days_impl_const(bos,U"day",time.day); + ::fast_io::details::print_loc_days_impl_const(bos,U"abmon",time.abmon); + ::fast_io::details::print_loc_days_impl_const(bos,U"ab_alt_mon",time.ab_alt_mon); + ::fast_io::details::print_loc_days_impl_const(bos,U"mon",time.mon); + print_freestanding(bos, + U"d_t_fmt\t\"",time.d_t_fmt,U"\"\n", + U"d_fmt\t\"",time.d_fmt,U"\"\n", + U"t_fmt\t\"",time.t_fmt,U"\"\n", + U"t_fmt_ampm\t\"",time.t_fmt_ampm,U"\"\n", + U"date_fmt\t\"",time.date_fmt,U"\"\n", + U"am_pm\t\"",time.am_pm[0],U"\";\"",time.am_pm[1],U"\"\n"); + ::fast_io::details::print_loc_era_impl(bos,time.era.base,time.era.len); + print_freestanding(bos,U"era_d_fmt\t\"",time.era_d_fmt,U"\"\n", + U"era_d_t_fmt\t\"",time.era_d_t_fmt,U"\"\n", + U"era_t_fmt\t\"",time.era_t_fmt,U"\"\n"); + ::fast_io::details::print_loc_days_impl(bos,U"alt_digits",time.alt_digits); + println_freestanding(bos,U"week\t",time.week.ndays,U";",time.week.first_day,U";",time.week.first_week,U"\n", + U"first_weekday\t",time.first_weekday,U"\n" + U"first_workday\t",time.first_workday,U"\n" + U"cal_direction\t",time.cal_direction); + ::fast_io::details::print_loc_days_impl(bos,U"timezone",time.timezone); + print_freestanding(bos,U"END LC_TIME"); + } + else if constexpr(std::same_as) + { + print_freestanding(bos,u8"LC_TIME\n"); + ::fast_io::details::print_loc_days_impl_const(bos,u8"abday",time.abday); + ::fast_io::details::print_loc_days_impl_const(bos,u8"day",time.day); + ::fast_io::details::print_loc_days_impl_const(bos,u8"abmon",time.abmon); + ::fast_io::details::print_loc_days_impl_const(bos,u8"ab_alt_mon",time.ab_alt_mon); + ::fast_io::details::print_loc_days_impl_const(bos,u8"mon",time.mon); + print_freestanding(bos, + u8"d_t_fmt\t\"",time.d_t_fmt,u8"\"\n", + u8"d_fmt\t\"",time.d_fmt,u8"\"\n", + u8"t_fmt\t\"",time.t_fmt,u8"\"\n", + u8"t_fmt_ampm\t\"",time.t_fmt_ampm,u8"\"\n", + u8"date_fmt\t\"",time.date_fmt,u8"\"\n", + u8"am_pm\t\"",time.am_pm[0],u8"\";\"",time.am_pm[1],u8"\"\n"); + ::fast_io::details::print_loc_era_impl(bos,time.era.base,time.era.len); + print_freestanding(bos,u8"era_d_fmt\t\"",time.era_d_fmt,u8"\"\n", + u8"era_d_t_fmt\t\"",time.era_d_t_fmt,u8"\"\n", + u8"era_t_fmt\t\"",time.era_t_fmt,u8"\"\n"); + ::fast_io::details::print_loc_days_impl(bos,u8"alt_digits",time.alt_digits); + println_freestanding(bos,u8"week\t",time.week.ndays,u8";",time.week.first_day,u8";",time.week.first_week,u8"\n", + u8"first_weekday\t",time.first_weekday,u8"\n" + u8"first_workday\t",time.first_workday,u8"\n" + u8"cal_direction\t",time.cal_direction); + ::fast_io::details::print_loc_days_impl(bos,u8"timezone",time.timezone); + print_freestanding(bos,u8"END LC_TIME"); + } +} + +template +constexpr void print_loc_keyboards_impl(output bos,basic_io_scatter_t const* keyboards_strings,std::size_t keyboards_strings_len) +{ + for(std::size_t i{};i!=keyboards_strings_len;++i) + { + if(i) + put(bos,char_literal_v); + put(bos,char_literal_v); + print(bos,keyboards_strings[i]); + put(bos,char_literal_v); + } +} + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +constexpr void print_define_impl_lc_messages(output bos,basic_lc_messages const& messages) +{ + if constexpr(std::same_as) + { + print_freestanding(bos,"LC_MESSAGES\n" + "yesexpr\t\"",messages.yesexpr,"\"\n" + "noexpr\t\"",messages.noexpr,"\"\n" + "yesstr\t\"",messages.yesstr,"\"\n" + "nostr\t\"",messages.nostr,"\"\n" + "END LC_MESSAGES"); + } + else if constexpr(std::same_as) + { + print_freestanding(bos,L"LC_MESSAGES\n" + L"yesexpr\t\"",messages.yesexpr,L"\"\n" + L"noexpr\t\"",messages.noexpr,L"\"\n" + L"yesstr\t\"",messages.yesstr,L"\"\n" + L"nostr\t\"",messages.nostr,L"\"\n" + L"END LC_MESSAGES"); + } + else if constexpr(std::same_as) + { + print_freestanding(bos,u"LC_MESSAGES\n" + u"yesexpr\t\"",messages.yesexpr,u"\"\n" + u"noexpr\t\"",messages.noexpr,u"\"\n" + u"yesstr\t\"",messages.yesstr,u"\"\n" + u"nostr\t\"",messages.nostr,u"\"\n" + u"END LC_MESSAGES"); + } + else if constexpr(std::same_as) + { + print_freestanding(bos,U"LC_MESSAGES\n" + U"yesexpr\t\"",messages.yesexpr,U"\"\n" + U"noexpr\t\"",messages.noexpr,U"\"\n" + U"yesstr\t\"",messages.yesstr,U"\"\n" + U"nostr\t\"",messages.nostr,U"\"\n" + U"END LC_MESSAGES"); + } + else if constexpr(std::same_as) + { + print_freestanding(bos,u8"LC_MESSAGES\n" + u8"yesexpr\t\"",messages.yesexpr,u8"\"\n" + u8"noexpr\t\"",messages.noexpr,u8"\"\n" + u8"yesstr\t\"",messages.yesstr,u8"\"\n" + u8"nostr\t\"",messages.nostr,u8"\"\n" + u8"END LC_MESSAGES"); + } +} +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +constexpr void print_define_impl_lc_paper(output bos,basic_lc_paper const& paper) +{ + if constexpr(std::same_as) + { + print_freestanding(bos,"LC_PAPER\n" + "width\t",paper.width,"\n" + "height\t",paper.height,"\n" + "END LC_PAPER"); + } + else if constexpr(std::same_as) + { + print_freestanding(bos,L"LC_PAPER\n" + L"width\t",paper.width,L"\n" + L"height\t",paper.height,L"\n" + L"END LC_PAPER"); + } + else if constexpr(std::same_as) + { + print_freestanding(bos,u"LC_PAPER\n" + u"width\t",paper.width,u"\n" + u"height\t",paper.height,u"\n" + u"END LC_PAPER"); + } + else if constexpr(std::same_as) + { + print_freestanding(bos,U"LC_PAPER\n" + U"width\t",paper.width,U"\n" + U"height\t",paper.height,U"\n" + U"END LC_PAPER"); + } + else if constexpr(std::same_as) + { + print_freestanding(bos,u8"LC_PAPER\n" + u8"width\t",paper.width,u8"\n" + u8"height\t",paper.height,u8"\n" + u8"END LC_PAPER"); + } +} + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +constexpr void print_define_impl_lc_telephone(output bos,basic_lc_telephone const& telephone) +{ + if constexpr(std::same_as) + { + print_freestanding(bos,"LC_TELEPHONE\n" + "tel_int_fmt\t\"",telephone.tel_int_fmt,"\"\n" + "tel_dom_fmt\t\"",telephone.tel_dom_fmt,"\"\n" + "int_select\t\"",telephone.int_select,"\"\n" + "int_prefix\t\"",telephone.int_prefix,"\"\n" + "END LC_TELEPHONE"); + } + else if constexpr(std::same_as) + { + print_freestanding(bos,L"LC_TELEPHONE\n" + L"tel_int_fmt\t\"",telephone.tel_int_fmt,L"\"\n" + L"tel_dom_fmt\t\"",telephone.tel_dom_fmt,L"\"\n" + L"int_select\t\"",telephone.int_select,L"\"\n" + L"int_prefix\t\"",telephone.int_prefix,L"\"\n" + L"END LC_TELEPHONE"); + } + else if constexpr(std::same_as) + { + print_freestanding(bos,u"LC_TELEPHONE\n" + u"tel_int_fmt\t\"",telephone.tel_int_fmt,u"\"\n" + u"tel_dom_fmt\t\"",telephone.tel_dom_fmt,u"\"\n" + u"int_select\t\"",telephone.int_select,u"\"\n" + u"int_prefix\t\"",telephone.int_prefix,u"\"\n" + u"END LC_TELEPHONE"); + } + else if constexpr(std::same_as) + { + print_freestanding(bos,U"LC_TELEPHONE\n" + U"tel_int_fmt\t\"",telephone.tel_int_fmt,U"\"\n" + U"tel_dom_fmt\t\"",telephone.tel_dom_fmt,U"\"\n" + U"int_select\t\"",telephone.int_select,U"\"\n" + U"int_prefix\t\"",telephone.int_prefix,U"\"\n" + U"END LC_TELEPHONE"); + } + else if constexpr(std::same_as) + { + print_freestanding(bos,u8"LC_TELEPHONE\n" + u8"tel_int_fmt\t\"",telephone.tel_int_fmt,u8"\"\n" + u8"tel_dom_fmt\t\"",telephone.tel_dom_fmt,u8"\"\n" + u8"int_select\t\"",telephone.int_select,u8"\"\n" + u8"int_prefix\t\"",telephone.int_prefix,u8"\"\n" + u8"END LC_TELEPHONE"); + } +} +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +constexpr void print_define_impl_lc_name(output bos,basic_lc_name const& name) +{ + if constexpr(std::same_as) + { + print_freestanding(bos,"LC_NAME\n" + "name_fmt\t\"",name.name_fmt,"\"\n" + "name_gen\t\"",name.name_gen,"\"\n" + "name_miss\t\"",name.name_miss,"\"\n" + "name_mr\t\"",name.name_mr,"\"\n" + "name_mrs\t\"",name.name_mrs,"\"\n" + "name_ms\t\"",name.name_ms,"\"\n" + "END LC_NAME"); + } + else if constexpr(std::same_as) + { + print_freestanding(bos,L"LC_NAME\n" + L"name_fmt\t\"",name.name_fmt,L"\"\n" + L"name_gen\t\"",name.name_gen,L"\"\n" + L"name_miss\t\"",name.name_miss,L"\"\n" + L"name_mr\t\"",name.name_mr,L"\"\n" + L"name_mrs\t\"",name.name_mrs,L"\"\n" + L"name_ms\t\"",name.name_ms,L"\"\n" + L"END LC_NAME"); + } + else if constexpr(std::same_as) + { + print_freestanding(bos,u"LC_NAME\n" + u"name_fmt\t\"",name.name_fmt,u"\"\n" + u"name_gen\t\"",name.name_gen,u"\"\n" + u"name_miss\t\"",name.name_miss,u"\"\n" + u"name_mr\t\"",name.name_mr,u"\"\n" + u"name_mrs\t\"",name.name_mrs,u"\"\n" + u"name_ms\t\"",name.name_ms,u"\"\n" + u"END LC_NAME"); + } + else if constexpr(std::same_as) + { + print_freestanding(bos,U"LC_NAME\n" + U"name_fmt\t\"",name.name_fmt,U"\"\n" + U"name_gen\t\"",name.name_gen,U"\"\n" + U"name_miss\t\"",name.name_miss,U"\"\n" + U"name_mr\t\"",name.name_mr,U"\"\n" + U"name_mrs\t\"",name.name_mrs,U"\"\n" + U"name_ms\t\"",name.name_ms,U"\"\n" + U"END LC_NAME"); + } + else if constexpr(std::same_as) + { + print_freestanding(bos,u8"LC_NAME\n" + u8"name_fmt\t\"",name.name_fmt,u8"\"\n" + u8"name_gen\t\"",name.name_gen,u8"\"\n" + u8"name_miss\t\"",name.name_miss,u8"\"\n" + u8"name_mr\t\"",name.name_mr,u8"\"\n" + u8"name_mrs\t\"",name.name_mrs,u8"\"\n" + u8"name_ms\t\"",name.name_ms,u8"\"\n" + u8"END LC_NAME"); + } +} +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +constexpr void print_define_impl_lc_measurement(output bos,basic_lc_measurement measurement) +{ + if constexpr(std::same_as) + { + print_freestanding(bos,"LC_MEASUREMENT\n" + "measurement\t",measurement.measurement,"\n" + "END LC_MEASUREMENT"); + } + else if constexpr(std::same_as) + { + print_freestanding(bos,L"LC_MEASUREMENT\n" + L"measurement\t",measurement.measurement,L"\n" + L"END LC_MEASUREMENT"); + } + else if constexpr(std::same_as) + { + print_freestanding(bos,u"LC_MEASUREMENT\n" + u"measurement\t",measurement.measurement,u"\n" + u"END LC_MEASUREMENT"); + } + else if constexpr(std::same_as) + { + print_freestanding(bos,U"LC_MEASUREMENT\n" + U"measurement\t",measurement.measurement,U"\n" + U"END LC_MEASUREMENT"); + } + else if constexpr(std::same_as) + { + print_freestanding(bos,u8"LC_MEASUREMENT\n" + u8"measurement\t",measurement.measurement,u8"\n" + u8"END LC_MEASUREMENT"); + } +} +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +constexpr void print_define_impl_lc_keyboard(output bos,basic_lc_keyboard const& keyboard) +{ + if constexpr(std::same_as) + { + print_freestanding(bos,"LC_KEYBOARD\nkeyboards\t"); + ::fast_io::details::print_loc_keyboards_impl(bos,keyboard.keyboards.base,keyboard.keyboards.len); + print_freestanding(bos,"\nEND LC_KEYBOARD"); + } + else if constexpr(std::same_as) + { + print_freestanding(bos,L"LC_KEYBOARD\nkeyboards\t"); + ::fast_io::details::print_loc_keyboards_impl(bos,keyboard.keyboards.base,keyboard.keyboards.len); + print_freestanding(bos,L"\nEND LC_KEYBOARD"); + } + else if constexpr(std::same_as) + { + print_freestanding(bos,u"LC_KEYBOARD\nkeyboards\t"); + ::fast_io::details::print_loc_keyboards_impl(bos,keyboard.keyboards.base,keyboard.keyboards.len); + print_freestanding(bos,u"\nEND LC_KEYBOARD"); + } + else if constexpr(std::same_as) + { + print_freestanding(bos,U"LC_KEYBOARD\nkeyboards\t"); + ::fast_io::details::print_loc_keyboards_impl(bos,keyboard.keyboards.base,keyboard.keyboards.len); + print_freestanding(bos,U"\nEND LC_KEYBOARD"); + } + else if constexpr(std::same_as) + { + print_freestanding(bos,u8"LC_KEYBOARD\nkeyboards\t"); + ::fast_io::details::print_loc_keyboards_impl(bos,keyboard.keyboards.base,keyboard.keyboards.len); + print_freestanding(bos,u8"\nEND LC_KEYBOARD"); + } +} + +template +inline constexpr char_type const* lc_all_create_nn() noexcept +{ + if constexpr(std::same_as) + return "\n\n"; + else if constexpr(std::same_as) + return L"\n\n"; + else if constexpr(std::same_as) + return u"\n\n"; + else if constexpr(std::same_as) + return U"\n\n"; + else + return u8"\n\n"; +} + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +constexpr void print_define_impl_lc_all(output bos,basic_lc_all const& all) +{ + constexpr char_type const* first{lc_all_create_nn()}; + constexpr char_type const* last{first+2}; + print_define_impl_lc_identification(bos,all.identification); + write(bos,first,last); + print_define_impl_lc_monetary(bos,all.monetary); + write(bos,first,last); + print_define_impl_lc_time(bos,all.time); + write(bos,first,last); + print_define_impl_lc_messages(bos,all.messages); + write(bos,first,last); + print_define_impl_lc_paper(bos,all.paper); + write(bos,first,last); + print_define_impl_lc_telephone(bos,all.telephone); + write(bos,first,last); + print_define_impl_lc_name(bos,all.name); + write(bos,first,last); + print_define_impl_lc_measurement(bos,all.measurement); + write(bos,first,last); + print_define_impl_lc_keyboard(bos,all.keyboard); +} + +} + +template +requires (std::same_as&&::std::is_trivially_copyable_v) +constexpr void print_define(io_reserve_type_t>,output bos,basic_lc_identification const& identification) +{ + ::fast_io::details::print_define_impl_lc_identification(bos,identification); +} + +template +requires (std::same_as&&::std::is_trivially_copyable_v) +constexpr void print_define(io_reserve_type_t>,output bos,basic_lc_monetary const& monetary) +{ + ::fast_io::details::print_define_impl_lc_monetary(bos,monetary); +} + +template +requires (std::same_as&&::std::is_trivially_copyable_v) +constexpr void print_define(io_reserve_type_t>,output bos,basic_lc_numeric const& numeric) +{ + ::fast_io::details::print_define_impl_lc_numeric(bos,numeric); +} + +template +requires (std::same_as&&::std::is_trivially_copyable_v) +constexpr void print_define(io_reserve_type_t>,output bos,basic_lc_time const& time) +{ + ::fast_io::details::print_define_impl_lc_time(bos,time); +} + +template +requires (std::same_as&&::std::is_trivially_copyable_v) +constexpr void print_define(io_reserve_type_t>,output bos,basic_lc_messages const& messages) +{ + ::fast_io::details::print_define_impl_lc_messages(bos,messages); +} + +template +requires (std::same_as&&::std::is_trivially_copyable_v) +constexpr void print_define(io_reserve_type_t>,output bos,basic_lc_paper const& paper) +{ + ::fast_io::details::print_define_impl_lc_paper(bos,paper); +} + +template +requires (std::same_as&&::std::is_trivially_copyable_v) +constexpr void print_define(io_reserve_type_t>,output bos,basic_lc_telephone const& telephone) +{ + ::fast_io::details::print_define_impl_lc_telephone(bos,telephone); +} + +template +requires (std::same_as&&::std::is_trivially_copyable_v) +constexpr void print_define(io_reserve_type_t>,output bos,basic_lc_name const& name) +{ + ::fast_io::details::print_define_impl_lc_name(bos,name); +} + +template +requires (std::same_as&&::std::is_trivially_copyable_v) +constexpr void print_define(io_reserve_type_t>,output bos,basic_lc_measurement measurement) +{ + ::fast_io::details::print_define_impl_lc_measurement(bos,measurement); +} + +template +requires (std::same_as&&::std::is_trivially_copyable_v) +constexpr void print_define(io_reserve_type_t>,output bos,basic_lc_keyboard keyboard) +{ + ::fast_io::details::print_define_impl_lc_keyboard(bos,keyboard); +} + +template +requires (std::same_as&&::std::is_trivially_copyable_v) +constexpr void print_define(io_reserve_type_t>,output bos,basic_lc_all const& all) +{ + ::fast_io::details::print_define_impl_lc_all(bos,all); +} + +template +constexpr ::fast_io::parameter const&> status_io_print_forward(io_alias_type_t,lc_locale const& ln) noexcept +{ + return {*get_all(ln)}; +} + +} diff --git a/src/fast_io/include/fast_io_i18n/lc_print_status.h b/src/fast_io/include/fast_io_i18n/lc_print_status.h new file mode 100644 index 0000000..91f4398 --- /dev/null +++ b/src/fast_io/include/fast_io_i18n/lc_print_status.h @@ -0,0 +1,442 @@ +#pragma once + +namespace fast_io +{ + +template +concept lc_dynamic_reserve_printable = std::integral&& + requires(T t,basic_lc_all const* all,char_type* ptr,std::size_t size) +{ + {print_reserve_size(all,t)}->std::convertible_to; + {print_reserve_define(all,ptr,t)}->std::convertible_to; +}; + +template +requires lc_dynamic_reserve_printable> +inline constexpr auto print_reserve_size(basic_lc_all const* __restrict all,parameter para) +{ + return print_reserve_size(all,para.reference); +} + +template +requires lc_dynamic_reserve_printable> +inline constexpr auto print_reserve_define(basic_lc_all const* __restrict all,char_type* begin,parameter para) +{ + return print_reserve_define(all,begin,para.reference); +} + +template +concept lc_scatter_printable=requires(basic_lc_all const* all,T t) +{ + {print_scatter_define(all,t)}->std::same_as>; +}; + +template +concept lc_printable = requires(basic_lc_all const* all,::fast_io::details::dummy_buffer_output_stream out,T t) +{ + print_define(all,out,t); +}; + +template +concept lc_printable_internal_shift=requires(basic_lc_all const* all,T t) +{ + {print_define_internal_shift(all,t)}->std::same_as; +}; + +template +requires lc_printable_internal_shift> +inline constexpr auto print_define_internal_shift(basic_lc_all const* __restrict all,parameter para) +{ + return print_define_internal_shift(all,para.reference); +} + +namespace details::decay +{ + +template +inline constexpr std::size_t calculate_lc_scatter_dynamic_reserve_size( + basic_lc_all const* __restrict all,T t,Args... args) +{ + if constexpr(lc_dynamic_reserve_printable) + { + std::size_t res{print_reserve_size(all,t)}; + if constexpr(sizeof...(Args)==0) + return res; + else + return ::fast_io::details::intrinsics::add_or_overflow_die(res,calculate_lc_scatter_dynamic_reserve_size(all,args...)); + } + else if constexpr(!reserve_printable&& + dynamic_reserve_printable) + { + std::size_t res{print_reserve_size(io_reserve_type,t)}; + if constexpr(sizeof...(Args)==0) + return res; + else + return ::fast_io::details::intrinsics::add_or_overflow_die(res,calculate_lc_scatter_dynamic_reserve_size(all,args...)); + } + else + { + if constexpr(sizeof...(Args)==0) + return 0; + else + return calculate_lc_scatter_dynamic_reserve_size(all,args...); + } +} + +template +inline constexpr void lc_scatter_print_with_dynamic_reserve_recursive( + basic_lc_all const* __restrict all, + io_scatter_t* __restrict arr, + char_type* __restrict ptr, + char_type* __restrict dynamic_buffer_ptr,T t, Args ...args) +{ + if constexpr(lc_scatter_printable) + { + auto sc{print_scatter_define(all,t)}; + *arr={sc.base,sc.len*sizeof(char_type)}; + } + else if constexpr(lc_dynamic_reserve_printable) + { + auto end_ptr = print_reserve_define(all,dynamic_buffer_ptr,t); + *arr={dynamic_buffer_ptr,(end_ptr-dynamic_buffer_ptr)*sizeof(*dynamic_buffer_ptr)}; + if constexpr(sizeof...(Args)!=0) + dynamic_buffer_ptr = end_ptr; + } + else if constexpr(scatter_printable) + { + auto sc{print_scatter_define(io_reserve_type,t)}; + *arr={sc.base,sc.len*sizeof(char_type)}; + } + else if constexpr(reserve_printable) + { + auto end_ptr = print_reserve_define(io_reserve_type,ptr,t); + *arr={ptr,(end_ptr-ptr)*sizeof(*ptr)}; + if constexpr(sizeof...(Args)!=0) + ptr=end_ptr; + } + else + { + auto end_ptr = print_reserve_define(io_reserve_type,dynamic_buffer_ptr,t); + *arr={dynamic_buffer_ptr,static_cast(end_ptr-dynamic_buffer_ptr)*sizeof(*dynamic_buffer_ptr)}; + if constexpr(sizeof...(Args)!=0) + dynamic_buffer_ptr = end_ptr; + } + if constexpr(sizeof...(Args)!=0) + { + if constexpr(((!lc_dynamic_reserve_printable&&!lc_scatter_printable)&&...)) + scatter_print_with_dynamic_reserve_recursive(arr+1,ptr,dynamic_buffer_ptr,args...); + else + lc_scatter_print_with_dynamic_reserve_recursive(all,arr+1,ptr,dynamic_buffer_ptr,args...); + } +} + + +template +inline constexpr void lc_scatter_print_with_dynamic_only_reserve_recursive( + basic_lc_all const* __restrict all, + io_scatter_t* __restrict arr, + char_type* __restrict dynamic_buffer_ptr,T t, Args ...args) +{ + static_assert(!reserve_printable); + if constexpr(lc_scatter_printable) + { + auto sc{print_scatter_define(all,t)}; + *arr={sc.base,sc.len*sizeof(char_type)}; + } + else if constexpr(lc_dynamic_reserve_printable) + { + auto end_ptr = print_reserve_define(all,dynamic_buffer_ptr,t); + *arr={dynamic_buffer_ptr,(end_ptr-dynamic_buffer_ptr)*sizeof(*dynamic_buffer_ptr)}; + if constexpr(sizeof...(Args)!=0) + dynamic_buffer_ptr = end_ptr; + } + else if constexpr(scatter_printable) + { + auto sc{print_scatter_define(io_reserve_type,t)}; + *arr={sc.base,sc.len*sizeof(char_type)}; + } + else + { + auto end_ptr = print_reserve_define(io_reserve_type,dynamic_buffer_ptr,t); + *arr={dynamic_buffer_ptr,static_cast(end_ptr-dynamic_buffer_ptr)*sizeof(*dynamic_buffer_ptr)}; + if constexpr(sizeof...(Args)!=0) + dynamic_buffer_ptr = end_ptr; + } + if constexpr(sizeof...(Args)!=0) + { + if constexpr(((!lc_dynamic_reserve_printable&&!lc_scatter_printable)&&...)) + scatter_print_with_dynamic_only_reserve_recursive(arr+1,dynamic_buffer_ptr,args...); + else + lc_scatter_print_with_dynamic_only_reserve_recursive(all,arr+1,dynamic_buffer_ptr,args...); + } +} + + +template +inline constexpr void lc_print_control_reserve_bad_path(basic_lc_all const* __restrict lc,output out,T t,std::size_t size) +{ + using char_type = typename output::char_type; + if constexpr(line) + { + if(SIZE_MAX==size) + fast_terminate(); + ++size; + } + local_operator_new_array_ptr ptr(size); + auto it{print_reserve_define(lc,ptr.ptr,t)}; + if constexpr(line) + { + *it=char_literal_v; + ++it; + } + write(out,ptr.ptr,it); +} + +template +requires (std::is_trivially_copyable_v&&std::is_trivially_copyable_v) +inline constexpr void lc_print_control(basic_lc_all const* __restrict lc,output out,T t) +{ + using char_type = typename output::char_type; + using value_type = std::remove_cvref_t; + if constexpr(lc_scatter_printable) + print_control(out,print_scatter_define(lc,t)); + else if constexpr(lc_dynamic_reserve_printable) + { + std::size_t sz{print_reserve_size(lc,t)}; + if constexpr(buffer_output_stream) + { + auto bcurr{obuffer_curr(out)}; + auto bend{obuffer_end(out)}; + std::ptrdiff_t diff(bend-bcurr); + if constexpr(line) + { + --diff; + } + if(static_cast(sz); + ++it; + } + obuffer_set_curr(out,it); + } + else + lc_print_control_reserve_bad_path(lc,out,t,sz); + } + else + lc_print_control_reserve_bad_path(lc,out,t,sz); + } + else if constexpr(lc_printable) + { + print_define(lc,out,t); + if constexpr(line) + { + put(out,char_literal_v); + } + } + else + print_control(out,t); +} + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr void lc_print_controls_line(basic_lc_all const* __restrict lc,output out,T t,Args... args) +{ + if constexpr(sizeof...(Args)==0) + { + lc_print_control(lc,out,t); + } + else + { + using char_type = typename output::char_type; + lc_print_control(lc,out,t); + if constexpr(((lc_scatter_printable|| + lc_dynamic_reserve_printable|| + lc_printable)||...)) + { + if constexpr(line) + { + lc_print_controls_line(lc,out,args...); + } + else + { + (lc_print_control(lc,out,args),...); + } + } + else + print_controls_line(out,args...); + } +} + +template +inline constexpr void lc_scatter_print_recursive(basic_lc_all const* __restrict lc,io_scatter_t* arr,T t, Args ...args) +{ + if constexpr(lc_scatter_printable) + { + auto sc{print_scatter_define(lc,t)}; + *arr={sc.base,sc.len*sizeof(char_type)}; + } + else + { + auto sc{print_scatter_define(io_reserve_type,t)}; + *arr={sc.base,sc.len*sizeof(char_type)}; + } + if constexpr(sizeof...(Args)!=0) + { + if constexpr(((!lc_scatter_printable)&&...)) + scatter_print_recursive(arr+1,args...); + else + lc_scatter_print_recursive(lc,arr+1,args...); + } +} + +template +inline constexpr void lc_print_fallback(basic_lc_all const* __restrict lc,output out,Args... args) +{ + using char_type = typename output::char_type; + if constexpr((((!lc_dynamic_reserve_printable&& + !lc_printable&&!lc_scatter_printable))&&...)) + { + print_freestanding_decay_no_status(out,args...); + } + else if constexpr((scatter_output_stream||scatter_constant_output_stream)&& + ((reserve_printable + ||dynamic_reserve_printable + ||lc_dynamic_reserve_printable + ||scatter_printable + ||lc_scatter_printable + )&&...)) + { + constexpr std::size_t args_num{sizeof...(Args)}; + constexpr std::size_t scatters_num{args_num+static_cast(ln)}; + io_scatter_t scatters[scatters_num]; + if constexpr(((scatter_printable||lc_scatter_printable)&&...)) + { + lc_scatter_print_recursive(lc,scatters,args...); + if constexpr(ln) + { + scatters[args_num]={__builtin_addressof(char_literal_v),sizeof(char_type)}; + } + if constexpr(scatter_constant_output_stream) + { + scatter_constant_write(out,scatters); + } + else + { + scatter_write(out,{scatters,scatters_num}); + } + } + else + { + constexpr std::size_t arrayn{calculate_scatter_reserve_size()}; + if constexpr(arrayn!=0) + { + char_type reserve_array[arrayn]; + local_operator_new_array_ptr new_ptr(calculate_lc_scatter_dynamic_reserve_size(lc,args...)); + lc_scatter_print_with_dynamic_reserve_recursive(lc,scatters,reserve_array,new_ptr.ptr,args...); + if constexpr(ln) + { + scatters[args_num]={__builtin_addressof(char_literal_v),sizeof(char_type)}; + } + if constexpr(scatter_constant_output_stream) + { + scatter_constant_write(out,scatters); + } + else + { + scatter_write(out,{scatters,scatters_num}); + } + } + else + { + local_operator_new_array_ptr new_ptr(calculate_lc_scatter_dynamic_reserve_size(lc,args...)); + lc_scatter_print_with_dynamic_only_reserve_recursive(lc,scatters,new_ptr.ptr,args...); + if constexpr(ln) + { + scatters[args_num]={__builtin_addressof(char_literal_v),sizeof(char_type)}; + } + if constexpr(scatter_constant_output_stream) + { + scatter_constant_write(out,scatters); + } + else + { + scatter_write(out,{scatters,scatters_num}); + } + } + } + } + else + { + temporary_buffer buffer; + buffer.out=out; + auto ref{io_ref(buffer)}; + lc_print_controls_line(lc,ref,args...); + flush(buffer); + } +} + +template +inline constexpr void lc_print_status_define_further_decay(basic_lc_all const* __restrict lc,output out,Args... args) +{ + using char_type = typename output::char_type; + if constexpr(sizeof...(Args)==0&&!ln) + return; + else if constexpr(mutex_stream) + { + io_lock_guard lg{out}; + decltype(auto) dout{out.unlocked_handle()}; + lc_print_status_define_further_decay(lc,io_ref(dout),args...); + } + else if constexpr(buffer_output_stream) + { + if constexpr(sizeof...(Args)==0&&ln) + { + put(out,char_literal_v); + } + else + { + lc_print_controls_line(lc,out,args...); + } + } + else if constexpr(sizeof...(Args)==1&&(!ln||output_stream_with_writeln) + &&((printable|| + scatter_printable||lc_scatter_printable|| + lc_dynamic_reserve_printable|| + reserve_printable||dynamic_reserve_printable + )&&...) + ) + { + lc_print_controls_line(lc,out,args...); + } + else if constexpr(sizeof...(Args)==1&&ln&&((lc_dynamic_reserve_printable)&&...)) + { + (lc_print_control(lc,out,args),...); + } + else + lc_print_fallback(lc,out,args...); +} + +} + +template +concept lc_print_status_define_okay_character_type = std::integral&&( + ((printable||reserve_printable||dynamic_reserve_printable||scatter_printable|| + lc_printable||lc_dynamic_reserve_printable|| + lc_scatter_printable)&&...)); + +template +requires lc_print_status_define_okay_character_type +inline constexpr void print_status_define(lc_imbuer imb,Args... args) +{ + ::fast_io::details::decay::lc_print_status_define_further_decay(imb.all,imb.handle,args...); +} + +} diff --git a/src/fast_io/include/fast_io_i18n/locale/impl.h b/src/fast_io/include/fast_io_i18n/locale/impl.h new file mode 100644 index 0000000..2d96e3c --- /dev/null +++ b/src/fast_io/include/fast_io_i18n/locale/impl.h @@ -0,0 +1,8 @@ +#pragma once + +#if (defined(_WIN32) && !defined(__WINE__)) || defined(__CYGWIN__) +#include"win32.h" +#endif +#if (!defined(_WIN32) || defined(__WINE__)) && (!defined(__wasi__) || !defined(__NEWLIB__) || defined(__CYGWIN__)) +#include"posix.h" +#endif diff --git a/src/fast_io/include/fast_io_i18n/locale/posix.h b/src/fast_io/include/fast_io_i18n/locale/posix.h new file mode 100644 index 0000000..2cb5e00 --- /dev/null +++ b/src/fast_io/include/fast_io_i18n/locale/posix.h @@ -0,0 +1,225 @@ +#pragma once + +namespace fast_io +{ + +namespace details +{ +#if defined(_GNU_SOURCE) && !defined(__ANDROID__) +extern char const* libc_secure_getenv(char const*) noexcept __asm__("secure_getenv"); +#else +extern char const* libc_getenv(char const*) noexcept __asm__("getenv"); +#endif + +inline char const* my_u8getenv(char8_t const* env) noexcept +{ + return +#if defined(_GNU_SOURCE) && !defined(__ANDROID__) + libc_secure_getenv(reinterpret_cast(env)); +#else + libc_getenv(reinterpret_cast(env)); +#endif +} + +inline void* posix_load_l10n_common_impl(char8_t const* cstr,std::size_t n,lc_locale& loc) +{ + constexpr std::size_t size_restriction{256u}; + constexpr std::size_t encoding_size_restriction{128u}; + using native_char_type = char8_t; + using native_char_type_may_alias_const_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = native_char_type const*; + constexpr std::size_t msys2_encoding_size_restriction{size_restriction>>2}; + if(n>=size_restriction) //locale should not contain so many characters + { + throw_posix_error(EINVAL); + } + else if(n==0) + { + constexpr std::size_t sz{3}; + constexpr char8_t const* candidates[sz]{u8"L10N",u8"LANG"}; + char const* lc_all_env{reinterpret_cast(u8"C")}; + for(auto i{candidates},iend{candidates+sz};i!=iend;++i) + { + char const* ret{my_u8getenv(*i)}; + if(ret!=nullptr&&*ret!=0) + { + lc_all_env=ret; + break; + } + } + cstr=reinterpret_cast(lc_all_env); + n= +#if defined(__has_builtin) +#if __has_builtin(__builtin_strlen) + __builtin_strlen(lc_all_env); +#else + ::std::strlen(lc_all_env); +#endif +#else + ::std::strlen(lc_all_env); +#endif + if(n>=msys2_encoding_size_restriction) + { + throw_posix_error(EINVAL); + } + } + auto const cstr_end{cstr+n}; + auto found_dot{cstr_end}; + for(auto i{cstr};i!=cstr_end;++i) + { + switch(*i) + { + case 0: + case char_literal_v: + case char_literal_v: + { + throw_posix_error(EINVAL); + } + case char_literal_v: + { + if(found_dot!=cstr_end) + { + throw_posix_error(EINVAL); + } + found_dot = i; + break; + } + } + } + constexpr bool extension_is_dll{ +#ifdef __CYGWIN__ +true +#endif + }; + constexpr std::size_t extension_size{extension_is_dll?sizeof(u8".dll"):sizeof(u8".so")}; + //fast_io_i18n.locale.{localename}.{dll/so} + constexpr std::size_t total_size{::fast_io::details::intrinsics::add_or_overflow_die_chain(sizeof(u8"fast_io_i18n.locale."),size_restriction,encoding_size_restriction,extension_size)}; + native_char_type buffer[total_size]; + native_char_type* it{buffer}; + it=::fast_io::details::copy_string_literal(u8"fast_io_i18n.locale.",it); + it=::fast_io::details::non_overlapped_copy_n(cstr,n,it); + if(found_dot==cstr_end) + { + it=::fast_io::details::copy_string_literal(u8".UTF-8",it); + } + if constexpr(extension_is_dll) + { + it=::fast_io::details::copy_string_literal(u8".dll",it); + } + else + { + it=::fast_io::details::copy_string_literal(u8".so",it); + } + *it=0; + auto p{buffer}; + posix_dll_file dllfile(::fast_io::mnp::os_c_str(p),::fast_io::dll_mode::posix_rtld_global | ::fast_io::dll_mode::posix_rtld_now | ::fast_io::dll_mode::posix_rtld_nodelete); + auto func{reinterpret_cast< +void ( +#if defined(__CYGWIN__) +#if !__has_cpp_attribute(__gnu__::__fastcall__)&&defined(_MSC_VER) +__fastcall +#elif __has_cpp_attribute(__gnu__::__fastcall__) +__attribute__((__fastcall__)) +#endif +#endif + *)(lc_locale*) noexcept>(dll_load_symbol(dllfile, +#if defined(__CYGWIN__) && (SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__))) + u8"@export_v0@4" +#else + u8"export_v0" +#endif + ))}; + func(__builtin_addressof(loc)); + return dllfile.release(); +} + +template<::fast_io::constructible_to_os_c_str path_type> +inline void* posix_load_l10n_impl(path_type const& p,lc_locale& loc) +{ + return ::fast_io::posix_api_common(p,[&loc](auto const* cstr_ptr,std::size_t n) + { + using native_char_type = char8_t; + using native_char_type_may_alias_const_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = native_char_type const*; + return posix_load_l10n_common_impl(reinterpret_cast(cstr_ptr),n,loc); + }); +} + +} + +class posix_l10n +{ +public: + using native_handle_type = void*; + lc_locale loc{}; + native_handle_type rtld_handle{}; + constexpr posix_l10n() noexcept=default; + + template<::fast_io::constructible_to_os_c_str path_type> + explicit posix_l10n(path_type const& p) + { + this->rtld_handle=::fast_io::details::posix_load_l10n_impl(p,loc); + } + + explicit constexpr operator bool() const noexcept + { + return rtld_handle!=nullptr; + } + void close() noexcept + { + if(rtld_handle)[[likely]] + { + noexcept_call(dlclose,this->rtld_handle); + rtld_handle=nullptr; + } + } + inline constexpr native_handle_type release() noexcept + { + auto temp{this->rtld_handle}; + this->rtld_handle=nullptr; + return temp; + } + inline constexpr native_handle_type native_handle() const noexcept + { + return this->rtld_handle; + } + posix_l10n& operator=(posix_l10n const&)=delete; + posix_l10n(posix_l10n const&)=delete; + posix_l10n& operator=(posix_l10n&& __restrict other) noexcept + { + close(); + loc=other.loc; + rtld_handle=other.rtld_handle; + other.rtld_handle=nullptr; + other.loc={}; + return *this; + } + ~posix_l10n() + { + close(); + } +}; + +template +inline constexpr ::fast_io::parameter const&> status_io_print_forward(io_alias_type_t,posix_l10n const& loc) noexcept +{ + return status_io_print_forward(io_alias_type,loc.loc); +} + +template +requires (std::is_lvalue_reference_v||std::is_trivially_copyable_v) +inline constexpr auto imbue(posix_l10n& loc,stm&& out) noexcept +{ + using char_type = typename std::remove_cvref_t::char_type; + return imbue(get_all(loc.loc),::std::forward(out)); +} + +using native_l10n = posix_l10n; + +} diff --git a/src/fast_io/include/fast_io_i18n/locale/win32.h b/src/fast_io/include/fast_io_i18n/locale/win32.h new file mode 100644 index 0000000..133da11 --- /dev/null +++ b/src/fast_io/include/fast_io_i18n/locale/win32.h @@ -0,0 +1,405 @@ +#pragma once + +namespace fast_io +{ + +namespace details +{ + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline constexpr char_type* win32_get_locale_name_from_lcid(::std::uint_least32_t lcid,char_type* p) noexcept +{ +#include"win32_lcid_table.h" +} + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline constexpr char_type* win32_get_locale_encoding_from_code_page(::std::uint_least32_t acp,char_type* p) noexcept +{ + if constexpr(::std::same_as) + { + switch(acp) + { + case 936:case 54936: + { + return copy_string_literal(u".GB18030",p); + } +#if 0 + case 1250: + { + return copy_string_literal(u".Windows-1250",p); + } + case 1251: + { + return copy_string_literal(u".Windows-1251",p); + } + case 1252: + { + return copy_string_literal(u".Windows-1252",p); + } + case 1253: + { + return copy_string_literal(u".Windows-1253",p); + } + case 1254: + { + return copy_string_literal(u".Windows-1254",p); + } + case 1255: + { + return copy_string_literal(u".Windows-1255",p); + } + case 1256: + { + return copy_string_literal(u".Windows-1256",p); + } + case 1257: + { + return copy_string_literal(u".Windows-1257",p); + } + case 1258: + { + return copy_string_literal(u".Windows-1258",p); + } +#endif + default: + { + return copy_string_literal(u".UTF-8",p); + } + } + } + else + { + switch(acp) + { + case 936:case 54936: + { + return copy_string_literal(u8".GB18030",p); + } +#if 0 + case 1250: + { + return copy_string_literal(u8".Windows-1250",p); + } + case 1251: + { + return copy_string_literal(u8".Windows-1251",p); + } + case 1252: + { + return copy_string_literal(u8".Windows-1252",p); + } + case 1253: + { + return copy_string_literal(u8".Windows-1253",p); + } + case 1254: + { + return copy_string_literal(u8".Windows-1254",p); + } + case 1255: + { + return copy_string_literal(u8".Windows-1255",p); + } + case 1256: + { + return copy_string_literal(u8".Windows-1256",p); + } + case 1257: + { + return copy_string_literal(u8".Windows-1257",p); + } + case 1258: + { + return copy_string_literal(u8".Windows-1258",p); + } +#endif + default: + { + return copy_string_literal(u8".UTF-8",p); + } + } + } +} + +template<::fast_io::win32_family family> +inline void* win32_family_load_l10n_common_impl(::std::conditional_t const* cstr,std::size_t n,lc_locale& loc) +{ + constexpr std::size_t size_restriction{256u}; + constexpr std::size_t encoding_size_restriction{128u}; + using native_char_type = std::conditional_t; + constexpr std::size_t msys2_encoding_size_restriction{size_restriction>>2}; + native_char_type msys2_encoding[msys2_encoding_size_restriction]; + if(n>=size_restriction) //locale should not contain so many characters + { + throw_win32_error(0x0000203C); + } + else if(n==0) + { + constexpr std::uint_least32_t encoding_size_restriction_ul32{msys2_encoding_size_restriction}; + if constexpr(family==::fast_io::win32_family::ansi_9x) + { + constexpr std::size_t sz{3}; + constexpr char8_t const* candidates[sz]{u8"L10N",u8"LANG"}; + for(auto i{candidates},ed{i+sz};i!=ed;++i) + { + ::std::uint_least32_t env_size{::fast_io::win32::GetEnvironmentVariableA(reinterpret_cast(*i),reinterpret_cast(msys2_encoding),msys2_encoding_size_restriction)}; + if(env_size<2u) + { + continue; + } + else if(env_size>=encoding_size_restriction_ul32) + { + throw_win32_error(0x00000057); + } + cstr=msys2_encoding; + n=static_cast(env_size); + break; + } + } + else + { + constexpr std::size_t sz{3}; + constexpr char16_t const* candidates[sz]{u"L10N",u"LANG"}; + for(auto i{candidates},ed{i+sz};i!=ed;++i) + { + ::std::uint_least32_t env_size{::fast_io::win32::GetEnvironmentVariableW(*i,msys2_encoding,msys2_encoding_size_restriction)}; + if(env_size<2u) + { + continue; + } + else if(env_size>=encoding_size_restriction_ul32) + { + throw_win32_error(0x00000057); + } + cstr=msys2_encoding; + n=static_cast(env_size); + break; + } + } + } + auto const cstr_end{cstr+n}; + auto found_dot{cstr_end}; + for(auto i{cstr};i!=cstr_end;++i) + { + switch(*i) + { + case 0: + case char_literal_v: + case char_literal_v: + { + throw_win32_error(0x0000203C); + } + case char_literal_v: + { + if(found_dot!=cstr_end) + { + throw_win32_error(0x0000203C); + } + found_dot = i; + break; + } + } + } + //fast_io_i18n.locale.{localename}.{dll/so} + constexpr std::size_t total_size{::fast_io::details::intrinsics::add_or_overflow_die_chain(sizeof(u8"fast_io_i18n.locale."),size_restriction,encoding_size_restriction,sizeof(u8".dll"))}; + native_char_type buffer[total_size]; + native_char_type* it{buffer}; + if constexpr(family==::fast_io::win32_family::wide_nt) + { + it=::fast_io::details::copy_string_literal(u"fast_io_i18n.locale.",it); + } + else + { + it=::fast_io::details::copy_string_literal(u8"fast_io_i18n.locale.",it); + } + if(n==0) + { + constexpr bool use_get_user_default_locale_name +{ +#if !defined(_WIN32_WINDOWS) && (!defined(_WIN32_WINNT) || _WIN32_WINNT >= 0x0600) +family==::fast_io::win32_family::wide_nt +#endif +}; + if constexpr(use_get_user_default_locale_name) + { + constexpr int locale_name_max_len{85}; + static_assert(locale_name_max_len(it),locale_name_max_len)}; + if(ret) + { + --ret; + for(auto p{it},pe{it+ret};p!=pe;++p) + { + switch(*p) + { + case char_literal_v: + case char_literal_v: + case char_literal_v: + { + throw_win32_error(0x0000203C); + } + case char_literal_v: + { + *p=char_literal_v; + break; + } + }; + } + it+=ret; + } + else + { + *it=char_literal_v; + ++it; + } + } + else + { + it=win32_get_locale_name_from_lcid(::fast_io::win32::GetUserDefaultLCID(),it); + } + } + else + { + it=::fast_io::details::non_overlapped_copy_n(cstr,n,it); + } + if(found_dot == cstr_end) + { + it=win32_get_locale_encoding_from_code_page(::fast_io::win32::GetACP(),it); + } + if constexpr(family==::fast_io::win32_family::wide_nt) + { + it=::fast_io::details::copy_string_literal(u".dll",it); + } + else + { + it=::fast_io::details::copy_string_literal(u8".dll",it); + } + *it=0; + auto p{buffer}; + win32_family_dll_file dllfile(::fast_io::mnp::os_c_str(p),::fast_io::dll_mode::none); + auto func{reinterpret_cast< +void ( +#if defined(__CYGWIN__) +#if !__has_cpp_attribute(__gnu__::__fastcall__)&&defined(_MSC_VER) +__fastcall +#elif __has_cpp_attribute(__gnu__::__fastcall__) +__attribute__((__fastcall__)) +#endif +#endif + *)(lc_locale*) noexcept>(dll_load_symbol(dllfile, +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) + u8"@export_v0@4" +#else + u8"export_v0" +#endif + ))}; + func(__builtin_addressof(loc)); + return dllfile.release(); +} + +template<::fast_io::win32_family family,::fast_io::constructible_to_os_c_str path_type> +inline void* win32_family_load_l10n_impl(path_type const& p,lc_locale& loc) +{ + return ::fast_io::win32_family_api_common(p,[&loc](auto const* cstr_ptr,std::size_t n) + { + using native_char_type = std::conditional_t; + using native_char_type_may_alias_const_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = native_char_type const*; + return win32_family_load_l10n_common_impl(reinterpret_cast(cstr_ptr),n,loc); + }); +} + +} + +template<::fast_io::win32_family family> +class win32_family_l10n +{ +public: + using native_handle_type = void*; + lc_locale loc{}; + native_handle_type hmodule{}; + constexpr win32_family_l10n() noexcept=default; + + template<::fast_io::constructible_to_os_c_str path_type> + explicit win32_family_l10n(path_type const& p) + { + this->hmodule=::fast_io::details::win32_family_load_l10n_impl(p,loc); + } + + explicit constexpr operator bool() const noexcept + { + return hmodule!=nullptr; + } + void close() noexcept + { + if(hmodule)[[likely]] + { + fast_io::win32::FreeLibrary(hmodule); + hmodule=nullptr; + } + } + inline constexpr native_handle_type release() noexcept + { + auto temp{this->hmodule}; + this->hmodule=nullptr; + return temp; + } + inline constexpr native_handle_type native_handle() const noexcept + { + return this->hmodule; + } + + win32_family_l10n& operator=(win32_family_l10n const&)=delete; + win32_family_l10n(win32_family_l10n const&)=delete; + win32_family_l10n& operator=(win32_family_l10n&& __restrict other) noexcept + { + close(); + loc=other.loc; + hmodule=other.hmodule; + other.hmodule=nullptr; + other.loc={}; + return *this; + } + ~win32_family_l10n() + { + close(); + } +}; + +template +inline constexpr ::fast_io::parameter const&> status_io_print_forward(io_alias_type_t,win32_family_l10n const& loc) noexcept +{ + return status_io_print_forward(io_alias_type,loc.loc); +} + +template<::fast_io::win32_family family,stream stm> +requires (std::is_lvalue_reference_v||std::is_trivially_copyable_v) +inline constexpr auto imbue(win32_family_l10n& loc,stm&& out) noexcept +{ + using char_type = typename std::remove_cvref_t::char_type; + return imbue(get_all(loc.loc),::std::forward(out)); +} + +using win32_l10n_9xa = win32_family_l10n<::fast_io::win32_family::ansi_9x>; +using win32_l10n_ntw = win32_family_l10n<::fast_io::win32_family::wide_nt>; +using win32_l10n = win32_family_l10n<::fast_io::win32_family::native>; + +#if !defined(__CYGWIN__) && !defined(__WINE__) +using native_l10n = win32_l10n; +#endif + +} diff --git a/src/fast_io/include/fast_io_i18n/locale/win32_lcid_table.h b/src/fast_io/include/fast_io_i18n/locale/win32_lcid_table.h new file mode 100644 index 0000000..b0bec32 --- /dev/null +++ b/src/fast_io/include/fast_io_i18n/locale/win32_lcid_table.h @@ -0,0 +1,412 @@ +if constexpr(::std::same_as) +{ +switch(lcid) +{ +case 0x002C:return copy_string_literal(u"az_AZ",p); +case 0x003D:return copy_string_literal(u"yi_US",p); +case 0x0051:return copy_string_literal(u"bo_IN",p); +case 0x0059:return copy_string_literal(u"sd_IN",p); +case 0x0062:return copy_string_literal(u"fy_DE",p); +case 0x0079:return copy_string_literal(u"pap_AW",p); +case 0x0092:return copy_string_literal(u"ku_TR",p); +case 0x0401:return copy_string_literal(u"ar_SA",p); +case 0x0402:return copy_string_literal(u"bg_BG",p); +case 0x0403:return copy_string_literal(u"ca_ES",p); +case 0x0404:return copy_string_literal(u"zh_TW",p); +case 0x0405:return copy_string_literal(u"cs_CZ",p); +case 0x0406:return copy_string_literal(u"da_DK",p); +case 0x0407:return copy_string_literal(u"de_DE",p); +case 0x0408:return copy_string_literal(u"el_GR",p); +case 0x0409:return copy_string_literal(u"en_US",p); +case 0x040B:return copy_string_literal(u"fi_FI",p); +case 0x040C:return copy_string_literal(u"fr_FR",p); +case 0x040D:return copy_string_literal(u"he_IL",p); +case 0x040E:return copy_string_literal(u"hu_HU",p); +case 0x040F:return copy_string_literal(u"is_IS",p); +case 0x0410:return copy_string_literal(u"it_IT",p); +case 0x0411:return copy_string_literal(u"ja_JP",p); +case 0x0412:return copy_string_literal(u"ko_KR",p); +case 0x0413:return copy_string_literal(u"nl_NL",p); +case 0x0414:return copy_string_literal(u"nb_NO",p); +case 0x0415:return copy_string_literal(u"pl_PL",p); +case 0x0416:return copy_string_literal(u"pt_BR",p); +case 0x0418:return copy_string_literal(u"ro_RO",p); +case 0x0419:return copy_string_literal(u"ru_RU",p); +case 0x041A:return copy_string_literal(u"hr_HR",p); +case 0x041B:return copy_string_literal(u"sk_SK",p); +case 0x041C:return copy_string_literal(u"sq_AL",p); +case 0x041D:return copy_string_literal(u"sv_SE",p); +case 0x041E:return copy_string_literal(u"th_TH",p); +case 0x041F:return copy_string_literal(u"tr_TR",p); +case 0x0420:return copy_string_literal(u"ur_PK",p); +case 0x0421:return copy_string_literal(u"id_ID",p); +case 0x0422:return copy_string_literal(u"uk_UA",p); +case 0x0423:return copy_string_literal(u"be_BY",p); +case 0x0424:return copy_string_literal(u"sl_SI",p); +case 0x0425:return copy_string_literal(u"et_EE",p); +case 0x0426:return copy_string_literal(u"lv_LV",p); +case 0x0427:return copy_string_literal(u"lt_LT",p); +case 0x0428:return copy_string_literal(u"tg_TJ",p); +case 0x0429:return copy_string_literal(u"fa_IR",p); +case 0x042A:return copy_string_literal(u"vi_VN",p); +case 0x042B:return copy_string_literal(u"hy_AM",p); +case 0x042D:return copy_string_literal(u"eu_ES",p); +case 0x042E:return copy_string_literal(u"hsb_DE",p); +case 0x042F:return copy_string_literal(u"mk_MK",p); +case 0x0430:return copy_string_literal(u"st_ZA",p); +case 0x0431:return copy_string_literal(u"ts_ZA",p); +case 0x0432:return copy_string_literal(u"tn_ZA",p); +case 0x0433:return copy_string_literal(u"ve_ZA",p); +case 0x0434:return copy_string_literal(u"xh_ZA",p); +case 0x0435:return copy_string_literal(u"zu_ZA",p); +case 0x0436:return copy_string_literal(u"af_ZA",p); +case 0x0437:return copy_string_literal(u"ka_GE",p); +case 0x0438:return copy_string_literal(u"fo_FO",p); +case 0x0439:return copy_string_literal(u"hi_IN",p); +case 0x043A:return copy_string_literal(u"mt_MT",p); +case 0x043B:return copy_string_literal(u"se_NO",p); +case 0x043E:return copy_string_literal(u"ms_MY",p); +case 0x043F:return copy_string_literal(u"kk_KZ",p); +case 0x0440:return copy_string_literal(u"ky_KG",p); +case 0x0441:return copy_string_literal(u"sw_KE",p); +case 0x0442:return copy_string_literal(u"tk_TM",p); +case 0x0443:return copy_string_literal(u"uz_UZ",p); +case 0x0444:return copy_string_literal(u"tt_RU",p); +case 0x0445:return copy_string_literal(u"bn_IN",p); +case 0x0446:return copy_string_literal(u"pa_IN",p); +case 0x0447:return copy_string_literal(u"gu_IN",p); +case 0x0448:return copy_string_literal(u"or_IN",p); +case 0x0449:return copy_string_literal(u"ta_IN",p); +case 0x044A:return copy_string_literal(u"te_IN",p); +case 0x044B:return copy_string_literal(u"kn_IN",p); +case 0x044C:return copy_string_literal(u"ml_IN",p); +case 0x044D:return copy_string_literal(u"as_IN",p); +case 0x044E:return copy_string_literal(u"mr_IN",p); +case 0x044F:return copy_string_literal(u"sa_IN",p); +case 0x0450:return copy_string_literal(u"mn_MN",p); +case 0x0451:return copy_string_literal(u"bo_CN",p); +case 0x0452:return copy_string_literal(u"cy_GB",p); +case 0x0453:return copy_string_literal(u"km_KH",p); +case 0x0454:return copy_string_literal(u"lo_LA",p); +case 0x0455:return copy_string_literal(u"my_MM",p); +case 0x0456:return copy_string_literal(u"gl_ES",p); +case 0x0457:return copy_string_literal(u"kok_IN",p); +case 0x0458:return copy_string_literal(u"mni_IN",p); +case 0x0459:return copy_string_literal(u"sd_IN@devanagari",p); +case 0x045B:return copy_string_literal(u"si_LK",p); +case 0x045C:return copy_string_literal(u"chr_US",p); +case 0x045D:return copy_string_literal(u"iu_CA",p); +case 0x045E:return copy_string_literal(u"am_ET",p); +case 0x0461:return copy_string_literal(u"ne_NP",p); +case 0x0462:return copy_string_literal(u"fy_NL",p); +case 0x0463:return copy_string_literal(u"ps_AF",p); +case 0x0464:return copy_string_literal(u"fil_PH",p); +case 0x0465:return copy_string_literal(u"dv_MV",p); +case 0x0468:return copy_string_literal(u"ha_NG",p); +case 0x046A:return copy_string_literal(u"yo_NG",p); +case 0x046C:return copy_string_literal(u"nso_ZA",p); +case 0x046E:return copy_string_literal(u"lb_LU",p); +case 0x046F:return copy_string_literal(u"kl_GL",p); +case 0x0470:return copy_string_literal(u"ig_NG",p); +case 0x0472:return copy_string_literal(u"om_ET",p); +case 0x0473:return copy_string_literal(u"ti_ET",p); +case 0x0477:return copy_string_literal(u"so_SO",p); +case 0x047E:return copy_string_literal(u"br_FR",p); +case 0x0480:return copy_string_literal(u"ug_CN",p); +case 0x0481:return copy_string_literal(u"mi_NZ",p); +case 0x0482:return copy_string_literal(u"oc_FR",p); +case 0x0485:return copy_string_literal(u"sah_RU",p); +case 0x0487:return copy_string_literal(u"rw_RW",p); +case 0x0488:return copy_string_literal(u"wo_SN",p); +case 0x048E:return copy_string_literal(u"yue_HK",p); +case 0x0491:return copy_string_literal(u"gd_GB",p); +case 0x0801:return copy_string_literal(u"ar_IQ",p); +case 0x0803:return copy_string_literal(u"ca_ES@valencia",p); +case 0x0804:return copy_string_literal(u"zh_CN",p); +case 0x0807:return copy_string_literal(u"de_CH",p); +case 0x0809:return copy_string_literal(u"en_GB",p); +case 0x080A:return copy_string_literal(u"es_MX",p); +case 0x080C:return copy_string_literal(u"fr_BE",p); +case 0x0810:return copy_string_literal(u"it_CH",p); +case 0x0813:return copy_string_literal(u"nl_BE",p); +case 0x0814:return copy_string_literal(u"nn_NO",p); +case 0x0816:return copy_string_literal(u"pt_PT",p); +case 0x081D:return copy_string_literal(u"sv_FI",p); +case 0x0820:return copy_string_literal(u"ur_IN",p); +case 0x082E:return copy_string_literal(u"dsb_DE",p); +case 0x083C:return copy_string_literal(u"ga_IE",p); +case 0x0843:return copy_string_literal(u"uz_UZ@cyrillic",p); +case 0x0845:return copy_string_literal(u"bn_BD",p); +case 0x0846:return copy_string_literal(u"pa_PK",p); +case 0x0849:return copy_string_literal(u"ta_LK",p); +case 0x0860:return copy_string_literal(u"ks_IN@devanagari",p); +case 0x0867:return copy_string_literal(u"ff_SN",p); +case 0x0873:return copy_string_literal(u"ti_ER",p); +case 0x0C01:return copy_string_literal(u"ar_EG",p); +case 0x0C04:return copy_string_literal(u"zh_HK",p); +case 0x0C07:return copy_string_literal(u"de_AT",p); +case 0x0C09:return copy_string_literal(u"en_AU",p); +case 0x0C0A:return copy_string_literal(u"es_ES",p); +case 0x0C0C:return copy_string_literal(u"fr_CA",p); +case 0x0C51:return copy_string_literal(u"dz_BT",p); +case 0x0C6b:return copy_string_literal(u"quz_PE",p); +case 0x1000:return copy_string_literal(u"aa_DJ",p); +case 0x1001:return copy_string_literal(u"ar_LY",p); +case 0x1004:return copy_string_literal(u"zh_SG",p); +case 0x1007:return copy_string_literal(u"de_LU",p); +case 0x1009:return copy_string_literal(u"en_CA",p); +case 0x100A:return copy_string_literal(u"es_GT",p); +case 0x100C:return copy_string_literal(u"fr_CH",p); +case 0x1401:return copy_string_literal(u"ar_DZ",p); +case 0x1407:return copy_string_literal(u"de_LI",p); +case 0x1409:return copy_string_literal(u"en_NZ",p); +case 0x140A:return copy_string_literal(u"es_CR",p); +case 0x140C:return copy_string_literal(u"fr_LU",p); +case 0x1801:return copy_string_literal(u"ar_MA",p); +case 0x1809:return copy_string_literal(u"en_IE",p); +case 0x180A:return copy_string_literal(u"es_PA",p); +case 0x1C01:return copy_string_literal(u"ar_TN",p); +case 0x1C09:return copy_string_literal(u"en_ZA",p); +case 0x1C0A:return copy_string_literal(u"es_DO",p); +case 0x2001:return copy_string_literal(u"ar_OM",p); +case 0x200A:return copy_string_literal(u"es_VE",p); +case 0x201A:return copy_string_literal(u"bs_BA",p); +case 0x2401:return copy_string_literal(u"ar_YE",p); +case 0x240A:return copy_string_literal(u"es_CO",p); +case 0x241A:return copy_string_literal(u"sr_RS@latin",p); +case 0x2801:return copy_string_literal(u"ar_SY",p); +case 0x280A:return copy_string_literal(u"es_PE",p); +case 0x281A:return copy_string_literal(u"sr_RS",p); +case 0x2C01:return copy_string_literal(u"ar_JO",p); +case 0x2C0A:return copy_string_literal(u"es_AR",p); +case 0x3001:return copy_string_literal(u"ar_LB",p); +case 0x3009:return copy_string_literal(u"en_ZW",p); +case 0x300A:return copy_string_literal(u"es_EC",p); +case 0x301A:return copy_string_literal(u"sr_ME",p); +case 0x3401:return copy_string_literal(u"ar_KW",p); +case 0x3409:return copy_string_literal(u"en_PH",p); +case 0x340A:return copy_string_literal(u"es_CL",p); +case 0x3801:return copy_string_literal(u"ar_AE",p); +case 0x380A:return copy_string_literal(u"es_UY",p); +case 0x3C01:return copy_string_literal(u"ar_BH",p); +case 0x3C09:return copy_string_literal(u"en_HK",p); +case 0x3C0A:return copy_string_literal(u"es_PY",p); +case 0x4001:return copy_string_literal(u"ar_QA",p); +case 0x4009:return copy_string_literal(u"en_IN",p); +case 0x400A:return copy_string_literal(u"es_BO",p); +case 0x440A:return copy_string_literal(u"es_SV",p); +case 0x4809:return copy_string_literal(u"en_SG",p); +case 0x480A:return copy_string_literal(u"es_HN",p); +case 0x4C0A:return copy_string_literal(u"es_NI",p); +case 0x500A:return copy_string_literal(u"es_PR",p); +case 0x540A:return copy_string_literal(u"es_US",p); +case 0x5C0A:return copy_string_literal(u"es_CU",p); +default:*p=u'C';return p+1; +} +} +else +{ +switch(lcid) +{ +case 0x002C:return copy_string_literal(u8"az_AZ",p); +case 0x003D:return copy_string_literal(u8"yi_US",p); +case 0x0051:return copy_string_literal(u8"bo_IN",p); +case 0x0059:return copy_string_literal(u8"sd_IN",p); +case 0x0062:return copy_string_literal(u8"fy_DE",p); +case 0x0079:return copy_string_literal(u8"pap_AW",p); +case 0x0092:return copy_string_literal(u8"ku_TR",p); +case 0x0401:return copy_string_literal(u8"ar_SA",p); +case 0x0402:return copy_string_literal(u8"bg_BG",p); +case 0x0403:return copy_string_literal(u8"ca_ES",p); +case 0x0404:return copy_string_literal(u8"zh_TW",p); +case 0x0405:return copy_string_literal(u8"cs_CZ",p); +case 0x0406:return copy_string_literal(u8"da_DK",p); +case 0x0407:return copy_string_literal(u8"de_DE",p); +case 0x0408:return copy_string_literal(u8"el_GR",p); +case 0x0409:return copy_string_literal(u8"en_US",p); +case 0x040B:return copy_string_literal(u8"fi_FI",p); +case 0x040C:return copy_string_literal(u8"fr_FR",p); +case 0x040D:return copy_string_literal(u8"he_IL",p); +case 0x040E:return copy_string_literal(u8"hu_HU",p); +case 0x040F:return copy_string_literal(u8"is_IS",p); +case 0x0410:return copy_string_literal(u8"it_IT",p); +case 0x0411:return copy_string_literal(u8"ja_JP",p); +case 0x0412:return copy_string_literal(u8"ko_KR",p); +case 0x0413:return copy_string_literal(u8"nl_NL",p); +case 0x0414:return copy_string_literal(u8"nb_NO",p); +case 0x0415:return copy_string_literal(u8"pl_PL",p); +case 0x0416:return copy_string_literal(u8"pt_BR",p); +case 0x0418:return copy_string_literal(u8"ro_RO",p); +case 0x0419:return copy_string_literal(u8"ru_RU",p); +case 0x041A:return copy_string_literal(u8"hr_HR",p); +case 0x041B:return copy_string_literal(u8"sk_SK",p); +case 0x041C:return copy_string_literal(u8"sq_AL",p); +case 0x041D:return copy_string_literal(u8"sv_SE",p); +case 0x041E:return copy_string_literal(u8"th_TH",p); +case 0x041F:return copy_string_literal(u8"tr_TR",p); +case 0x0420:return copy_string_literal(u8"ur_PK",p); +case 0x0421:return copy_string_literal(u8"id_ID",p); +case 0x0422:return copy_string_literal(u8"uk_UA",p); +case 0x0423:return copy_string_literal(u8"be_BY",p); +case 0x0424:return copy_string_literal(u8"sl_SI",p); +case 0x0425:return copy_string_literal(u8"et_EE",p); +case 0x0426:return copy_string_literal(u8"lv_LV",p); +case 0x0427:return copy_string_literal(u8"lt_LT",p); +case 0x0428:return copy_string_literal(u8"tg_TJ",p); +case 0x0429:return copy_string_literal(u8"fa_IR",p); +case 0x042A:return copy_string_literal(u8"vi_VN",p); +case 0x042B:return copy_string_literal(u8"hy_AM",p); +case 0x042D:return copy_string_literal(u8"eu_ES",p); +case 0x042E:return copy_string_literal(u8"hsb_DE",p); +case 0x042F:return copy_string_literal(u8"mk_MK",p); +case 0x0430:return copy_string_literal(u8"st_ZA",p); +case 0x0431:return copy_string_literal(u8"ts_ZA",p); +case 0x0432:return copy_string_literal(u8"tn_ZA",p); +case 0x0433:return copy_string_literal(u8"ve_ZA",p); +case 0x0434:return copy_string_literal(u8"xh_ZA",p); +case 0x0435:return copy_string_literal(u8"zu_ZA",p); +case 0x0436:return copy_string_literal(u8"af_ZA",p); +case 0x0437:return copy_string_literal(u8"ka_GE",p); +case 0x0438:return copy_string_literal(u8"fo_FO",p); +case 0x0439:return copy_string_literal(u8"hi_IN",p); +case 0x043A:return copy_string_literal(u8"mt_MT",p); +case 0x043B:return copy_string_literal(u8"se_NO",p); +case 0x043E:return copy_string_literal(u8"ms_MY",p); +case 0x043F:return copy_string_literal(u8"kk_KZ",p); +case 0x0440:return copy_string_literal(u8"ky_KG",p); +case 0x0441:return copy_string_literal(u8"sw_KE",p); +case 0x0442:return copy_string_literal(u8"tk_TM",p); +case 0x0443:return copy_string_literal(u8"uz_UZ",p); +case 0x0444:return copy_string_literal(u8"tt_RU",p); +case 0x0445:return copy_string_literal(u8"bn_IN",p); +case 0x0446:return copy_string_literal(u8"pa_IN",p); +case 0x0447:return copy_string_literal(u8"gu_IN",p); +case 0x0448:return copy_string_literal(u8"or_IN",p); +case 0x0449:return copy_string_literal(u8"ta_IN",p); +case 0x044A:return copy_string_literal(u8"te_IN",p); +case 0x044B:return copy_string_literal(u8"kn_IN",p); +case 0x044C:return copy_string_literal(u8"ml_IN",p); +case 0x044D:return copy_string_literal(u8"as_IN",p); +case 0x044E:return copy_string_literal(u8"mr_IN",p); +case 0x044F:return copy_string_literal(u8"sa_IN",p); +case 0x0450:return copy_string_literal(u8"mn_MN",p); +case 0x0451:return copy_string_literal(u8"bo_CN",p); +case 0x0452:return copy_string_literal(u8"cy_GB",p); +case 0x0453:return copy_string_literal(u8"km_KH",p); +case 0x0454:return copy_string_literal(u8"lo_LA",p); +case 0x0455:return copy_string_literal(u8"my_MM",p); +case 0x0456:return copy_string_literal(u8"gl_ES",p); +case 0x0457:return copy_string_literal(u8"kok_IN",p); +case 0x0458:return copy_string_literal(u8"mni_IN",p); +case 0x0459:return copy_string_literal(u8"sd_IN@devanagari",p); +case 0x045B:return copy_string_literal(u8"si_LK",p); +case 0x045C:return copy_string_literal(u8"chr_US",p); +case 0x045D:return copy_string_literal(u8"iu_CA",p); +case 0x045E:return copy_string_literal(u8"am_ET",p); +case 0x0461:return copy_string_literal(u8"ne_NP",p); +case 0x0462:return copy_string_literal(u8"fy_NL",p); +case 0x0463:return copy_string_literal(u8"ps_AF",p); +case 0x0464:return copy_string_literal(u8"fil_PH",p); +case 0x0465:return copy_string_literal(u8"dv_MV",p); +case 0x0468:return copy_string_literal(u8"ha_NG",p); +case 0x046A:return copy_string_literal(u8"yo_NG",p); +case 0x046C:return copy_string_literal(u8"nso_ZA",p); +case 0x046E:return copy_string_literal(u8"lb_LU",p); +case 0x046F:return copy_string_literal(u8"kl_GL",p); +case 0x0470:return copy_string_literal(u8"ig_NG",p); +case 0x0472:return copy_string_literal(u8"om_ET",p); +case 0x0473:return copy_string_literal(u8"ti_ET",p); +case 0x0477:return copy_string_literal(u8"so_SO",p); +case 0x047E:return copy_string_literal(u8"br_FR",p); +case 0x0480:return copy_string_literal(u8"ug_CN",p); +case 0x0481:return copy_string_literal(u8"mi_NZ",p); +case 0x0482:return copy_string_literal(u8"oc_FR",p); +case 0x0485:return copy_string_literal(u8"sah_RU",p); +case 0x0487:return copy_string_literal(u8"rw_RW",p); +case 0x0488:return copy_string_literal(u8"wo_SN",p); +case 0x048E:return copy_string_literal(u8"yue_HK",p); +case 0x0491:return copy_string_literal(u8"gd_GB",p); +case 0x0801:return copy_string_literal(u8"ar_IQ",p); +case 0x0803:return copy_string_literal(u8"ca_ES@valencia",p); +case 0x0804:return copy_string_literal(u8"zh_CN",p); +case 0x0807:return copy_string_literal(u8"de_CH",p); +case 0x0809:return copy_string_literal(u8"en_GB",p); +case 0x080A:return copy_string_literal(u8"es_MX",p); +case 0x080C:return copy_string_literal(u8"fr_BE",p); +case 0x0810:return copy_string_literal(u8"it_CH",p); +case 0x0813:return copy_string_literal(u8"nl_BE",p); +case 0x0814:return copy_string_literal(u8"nn_NO",p); +case 0x0816:return copy_string_literal(u8"pt_PT",p); +case 0x081D:return copy_string_literal(u8"sv_FI",p); +case 0x0820:return copy_string_literal(u8"ur_IN",p); +case 0x082E:return copy_string_literal(u8"dsb_DE",p); +case 0x083C:return copy_string_literal(u8"ga_IE",p); +case 0x0843:return copy_string_literal(u8"uz_UZ@cyrillic",p); +case 0x0845:return copy_string_literal(u8"bn_BD",p); +case 0x0846:return copy_string_literal(u8"pa_PK",p); +case 0x0849:return copy_string_literal(u8"ta_LK",p); +case 0x0860:return copy_string_literal(u8"ks_IN@devanagari",p); +case 0x0867:return copy_string_literal(u8"ff_SN",p); +case 0x0873:return copy_string_literal(u8"ti_ER",p); +case 0x0C01:return copy_string_literal(u8"ar_EG",p); +case 0x0C04:return copy_string_literal(u8"zh_HK",p); +case 0x0C07:return copy_string_literal(u8"de_AT",p); +case 0x0C09:return copy_string_literal(u8"en_AU",p); +case 0x0C0A:return copy_string_literal(u8"es_ES",p); +case 0x0C0C:return copy_string_literal(u8"fr_CA",p); +case 0x0C51:return copy_string_literal(u8"dz_BT",p); +case 0x0C6b:return copy_string_literal(u8"quz_PE",p); +case 0x1000:return copy_string_literal(u8"aa_DJ",p); +case 0x1001:return copy_string_literal(u8"ar_LY",p); +case 0x1004:return copy_string_literal(u8"zh_SG",p); +case 0x1007:return copy_string_literal(u8"de_LU",p); +case 0x1009:return copy_string_literal(u8"en_CA",p); +case 0x100A:return copy_string_literal(u8"es_GT",p); +case 0x100C:return copy_string_literal(u8"fr_CH",p); +case 0x1401:return copy_string_literal(u8"ar_DZ",p); +case 0x1407:return copy_string_literal(u8"de_LI",p); +case 0x1409:return copy_string_literal(u8"en_NZ",p); +case 0x140A:return copy_string_literal(u8"es_CR",p); +case 0x140C:return copy_string_literal(u8"fr_LU",p); +case 0x1801:return copy_string_literal(u8"ar_MA",p); +case 0x1809:return copy_string_literal(u8"en_IE",p); +case 0x180A:return copy_string_literal(u8"es_PA",p); +case 0x1C01:return copy_string_literal(u8"ar_TN",p); +case 0x1C09:return copy_string_literal(u8"en_ZA",p); +case 0x1C0A:return copy_string_literal(u8"es_DO",p); +case 0x2001:return copy_string_literal(u8"ar_OM",p); +case 0x200A:return copy_string_literal(u8"es_VE",p); +case 0x201A:return copy_string_literal(u8"bs_BA",p); +case 0x2401:return copy_string_literal(u8"ar_YE",p); +case 0x240A:return copy_string_literal(u8"es_CO",p); +case 0x241A:return copy_string_literal(u8"sr_RS@latin",p); +case 0x2801:return copy_string_literal(u8"ar_SY",p); +case 0x280A:return copy_string_literal(u8"es_PE",p); +case 0x281A:return copy_string_literal(u8"sr_RS",p); +case 0x2C01:return copy_string_literal(u8"ar_JO",p); +case 0x2C0A:return copy_string_literal(u8"es_AR",p); +case 0x3001:return copy_string_literal(u8"ar_LB",p); +case 0x3009:return copy_string_literal(u8"en_ZW",p); +case 0x300A:return copy_string_literal(u8"es_EC",p); +case 0x301A:return copy_string_literal(u8"sr_ME",p); +case 0x3401:return copy_string_literal(u8"ar_KW",p); +case 0x3409:return copy_string_literal(u8"en_PH",p); +case 0x340A:return copy_string_literal(u8"es_CL",p); +case 0x3801:return copy_string_literal(u8"ar_AE",p); +case 0x380A:return copy_string_literal(u8"es_UY",p); +case 0x3C01:return copy_string_literal(u8"ar_BH",p); +case 0x3C09:return copy_string_literal(u8"en_HK",p); +case 0x3C0A:return copy_string_literal(u8"es_PY",p); +case 0x4001:return copy_string_literal(u8"ar_QA",p); +case 0x4009:return copy_string_literal(u8"en_IN",p); +case 0x400A:return copy_string_literal(u8"es_BO",p); +case 0x440A:return copy_string_literal(u8"es_SV",p); +case 0x4809:return copy_string_literal(u8"en_SG",p); +case 0x480A:return copy_string_literal(u8"es_HN",p); +case 0x4C0A:return copy_string_literal(u8"es_NI",p); +case 0x500A:return copy_string_literal(u8"es_PR",p); +case 0x540A:return copy_string_literal(u8"es_US",p); +case 0x5C0A:return copy_string_literal(u8"es_CU",p); +default:*p=u8'C';return p+1; +} +} diff --git a/src/fast_io/include/fast_io_i18n/timezone.h b/src/fast_io/include/fast_io_i18n/timezone.h new file mode 100644 index 0000000..079a383 --- /dev/null +++ b/src/fast_io/include/fast_io_i18n/timezone.h @@ -0,0 +1,2 @@ +#pragma once + diff --git a/src/fast_io/include/fast_io_legacy.h b/src/fast_io/include/fast_io_legacy.h new file mode 100644 index 0000000..ed8be1a --- /dev/null +++ b/src/fast_io/include/fast_io_legacy.h @@ -0,0 +1,37 @@ +#pragma once +#if !defined(__cplusplus) +#error "You are not using a C++ compiler" +#endif + +#if !defined(__cpp_concepts) +#error "fast_io requires at least C++20 standard compiler." +#else +//fast_io_legacy.h deals with legacy C++ // interface +#if ((__STDC_HOSTED__==1 && (!defined(_GLIBCXX_HOSTED) || _GLIBCXX_HOSTED==1) && !defined(_LIBCPP_FREESTANDING)) || defined(FAST_IO_ENABLE_HOSTED_FEATURES)) + +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning(push) +#pragma warning( disable : 4514 ) +#pragma warning( disable : 4668 ) +#pragma warning( disable : 4710 ) +#pragma warning( disable : 4711 ) +#pragma warning( disable : 4820 ) +#endif + +#include +#include +#include + +#include"fast_io.h" + +#include"fast_io_legacy_impl/filebuf/streambuf_io_observer.h" +#include"fast_io_legacy_impl/filebuf/filebuf_file.h" + +#include"fast_io_legacy_impl/filebuf/op_out.h" +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning(pop) +#endif + +#endif + +#endif diff --git a/src/fast_io/include/fast_io_legacy_impl/c/avrlibc.h b/src/fast_io/include/fast_io_legacy_impl/c/avrlibc.h new file mode 100644 index 0000000..a5b95cb --- /dev/null +++ b/src/fast_io/include/fast_io_legacy_impl/c/avrlibc.h @@ -0,0 +1,78 @@ +#pragma once + +namespace fast_io +{ +namespace details +{ +inline void avr_libc_write_common_impl(FILE* fp, char const* first, char const* last) +{ + for(;first!=last;++first) + if(noexcept_call(fp->put,*first,fp))[[unlikely]] + throw_posix_error(EINVAL); +} + +inline void avr_libc_scatter_write_impl_with_normal_write(FILE* fp,io_scatter_t const* scatters,std::size_t n) +{ + auto put_func{fp->put}; + if(put_func==nullptr) + throw_posix_error(EINVAL); + for(std::size_t i{};i!=n;++i) + { + char const* bs{reinterpret_cast(scatters[i].base)}; + avr_libc_write_common_impl(fp,bs,bs+scatters[i].len); + } +} +inline void avr_libc_write_internal_impl(FILE* fp, char const* first, char const* last) +{ + auto put_func{fp->put}; + if(put_func==nullptr) + throw_posix_error(EINVAL); + avr_libc_write_common_impl(fp,first,last); +} + +inline char* avr_libc_read_internal_impl(FILE* fp,char* first,char* last) +{ + auto get_func{fp->get}; + if(get_func==nullptr) + throw_posix_error(EINVAL); + for (;first!=last;++first) + { + int ret{noexcept_call(getc,fp)}; + if(ret==EOF) + return first; + *first=static_cast(static_cast(ret)); + } + return last; +} + +} + +template +inline constexpr void write(basic_c_family_io_observer ciob,Iter first,Iter last) +{ + ::fast_io::details::avr_libc_write_internal_impl(ciob.fp,reinterpret_cast(::std::to_address(first)), + reinterpret_cast(::std::to_address(last))); +} + +template +inline constexpr void scatter_write(basic_c_family_io_observer ciob,io_scatters_t scatters) +{ + ::fast_io::details::avr_libc_scatter_write_impl_with_normal_write(ciob.fp,scatters.base,scatters.len); +} + +template +inline constexpr Iter read(basic_c_family_io_observer ciob,Iter first,Iter last) +{ + auto first_addr{reinterpret_cast(::std::to_address(first))}; + return (::fast_io::details::avr_libc_read_internal_impl(ciob.fp, + first_addr,reinterpret_cast(::std::to_address(last)))-first_addr)+first; +} + +template +requires (sizeof(char_type)==sizeof(char)) +inline void try_unget(basic_c_family_io_observer ciob,char_type ch) noexcept +{ + noexcept_call(::ungetc,static_cast(ch),ciob.fp); +} + +} diff --git a/src/fast_io/include/fast_io_legacy_impl/c/custom.h b/src/fast_io/include/fast_io_legacy_impl/c/custom.h new file mode 100644 index 0000000..a1bd0ec --- /dev/null +++ b/src/fast_io/include/fast_io_legacy_impl/c/custom.h @@ -0,0 +1,107 @@ +#pragma once + +namespace fast_io +{ + +template +requires requires(FILE* fp) +{ + {::std::posix::__libc_stdio_fp_ibuffer_begin(fp)}->char_type*; +} +inline char_type* ibuffer_begin(basic_c_io_observer_unlocked ciob) noexcept +{ + return ::std::posix::__libc_stdio_fp_ibuffer_begin(ciob.fp); +} + +template +requires requires(FILE* fp) +{ + {::std::posix::__libc_stdio_fp_ibuffer_curr(fp)}->char_type*; +} +inline char_type* ibuffer_curr(basic_c_io_observer_unlocked ciob) noexcept +{ + return ::std::posix::__libc_stdio_fp_ibuffer_curr(ciob.fp); +} + +template +requires requires(FILE* fp) +{ + {::std::posix::__libc_stdio_fp_ibuffer_end(fp)}->char_type*; +} +inline char_type* ibuffer_end(basic_c_io_observer_unlocked ciob) noexcept +{ + return ::std::posix::__libc_stdio_fp_ibuffer_end(ciob.fp); +} + +template +requires requires(FILE* fp,char_type* ptr) +{ + {::std::posix::__libc_stdio_fp_ibuffer_set_curr(fp,ptr)}; +} +inline void ibuffer_set_curr(basic_c_io_observer_unlocked ciob,char_type* ptr) noexcept +{ + ::std::posix::__libc_stdio_fp_ibuffer_set_curr(ciob.fp,ptr); +} + +template +inline bool ibuffer_underflow(basic_c_io_observer_unlocked ciob) +requires requires(FILE* fp) +{ + {::std::posix::__libc_stdio_fp_ibuffer_underflow(fp)}->bool; +} +{ + return ::std::posix::__libc_stdio_fp_ibuffer_underflow(ciob.fp); +} + + +template +requires requires(FILE* fp) +{ + {::std::posix::__libc_stdio_fp_obuffer_begin(fp)}->char_type*; +} +inline char_type* obuffer_begin(basic_c_io_observer_unlocked ciob) noexcept +{ + return ::std::posix::__libc_stdio_fp_obuffer_begin(ciob.fp); +} + +template +requires requires(FILE* fp) +{ + {::std::posix::__libc_stdio_fp_obuffer_curr(fp)}->char_type*; +} +inline char_type* obuffer_curr(basic_c_io_observer_unlocked ciob) noexcept +{ + return ::std::posix::__libc_stdio_fp_obuffer_curr(ciob.fp); +} + +template +requires requires(FILE* fp) +{ + {::std::posix::__libc_stdio_fp_obuffer_end(fp)}->char_type*; +} +inline char_type* obuffer_end(basic_c_io_observer_unlocked ciob) noexcept +{ + return ::std::posix::__libc_stdio_fp_obuffer_end(ciob.fp); +} + +template +requires requires(FILE* fp,char_type* ptr) +{ + {::std::posix::__libc_stdio_fp_obuffer_set_curr(fp,ptr)}->char_type*; +} +inline void obuffer_set_curr(basic_c_io_observer_unlocked ciob,char_type* ptr) noexcept +{ + ::std::posix::__libc_stdio_fp_obuffer_set_curr(ciob.fp,ptr); +} + +template +requires requires(FILE* fp,char_type ch) +{ + ::std::posix::__libc_stdio_fp_obuffer_overflow(fp,ch); +} +inline void obuffer_overflow(basic_c_io_observer_unlocked ciob,char_type ch) +{ + ::std::posix::__libc_stdio_fp_obuffer_overflow(ciob.fp,ch); +} + +} diff --git a/src/fast_io/include/fast_io_legacy_impl/c/done.h b/src/fast_io/include/fast_io_legacy_impl/c/done.h new file mode 100644 index 0000000..3385365 --- /dev/null +++ b/src/fast_io/include/fast_io_legacy_impl/c/done.h @@ -0,0 +1,345 @@ +#pragma once + +namespace fast_io +{ + +namespace details +{ + +#if defined(__CYGWIN__) +#if (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if __has_cpp_attribute(__gnu__::__cdecl__) +[[__gnu__::__cdecl__]] +#endif +extern std::size_t +#if !__has_cpp_attribute(__gnu__::__cdecl__) && defined(_MSC_VER) +__cdecl +#endif +my_cygwin_fwrite_unlocked(void const* __restrict buffer,std::size_t size,std::size_t count,FILE* __restrict) noexcept __asm__("fwrite_unlocked"); + +#if (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if __has_cpp_attribute(__gnu__::__cdecl__) +[[__gnu__::__cdecl__]] +#endif +extern std::size_t +#if !__has_cpp_attribute(__gnu__::__cdecl__) && defined(_MSC_VER) +__cdecl +#endif +my_cygwin_fread_unlocked(void* __restrict buffer,std::size_t size,std::size_t count,FILE* __restrict) noexcept __asm__("fread_unlocked"); +#endif + +inline std::size_t c_fwrite_unlocked_impl(void const* __restrict begin,std::size_t type_size,std::size_t count,FILE* __restrict fp) +{ + if(count==0) + return 0; +#if defined(__NEWLIB__)&&!defined(__CYGWIN__) + struct _reent rent{}; + std::size_t written_count{ +#if defined(__IMPL_UNLOCKED__) + noexcept_call(_fwrite_unlocked_r,__builtin_addressof(rent),begin,type_size,count,fp) +#else + noexcept_call(_fwrite_r,__builtin_addressof(rent),begin,type_size,count,fp) +#endif + }; + if(!written_count)[[unlikely]] + throw_posix_error(rent._errno); +#else + std::size_t written_count{ +#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) + __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) + __builtin_fwrite(begin,type_size,count,fp) +#else + fwrite(begin,type_size,count,fp) +#endif +#else + fwrite(begin,type_size,count,fp) +#endif + }; + if(!written_count)[[unlikely]] + throw_posix_error(); +#endif + return written_count; +} + +inline std::size_t c_fread_unlocked_impl(void* __restrict begin,std::size_t type_size,std::size_t count,FILE* __restrict fp) +{ + if(fp==stdin) + { + ::fast_io::noexcept_call(::fflush,stdout); + } +#if defined(__NEWLIB__)&&!defined(__CYGWIN__) + struct _reent rent{}; + std::size_t read_count{ +#if defined(__IMPL_UNLOCKED__) + noexcept_call(_fread_unlocked_r,__builtin_addressof(rent),begin,type_size,count,fp) +#else + noexcept_call(_fread_r,__builtin_addressof(rent),begin,type_size,count,fp) +#endif + }; + if(read_count==0)[[unlikely]] + { + if(rent._errno) + throw_posix_error(rent._errno); + } +#else + std::size_t read_count{ +#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) + __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) + __builtin_fread(begin,type_size,count,fp) +#else + fread(begin,type_size,count,fp) +#endif +#else + fread(begin,type_size,count,fp) +#endif + }; + if(read_count==0)[[unlikely]] + { + if( +#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) + __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) + __builtin_ferror(fp) +#else + ferror(fp) +#endif +#else + ferror(fp) +#endif + ) + throw_posix_error(); + } +#endif + return read_count; +} + +inline std::size_t c_fwrite_impl(void const* __restrict begin,std::size_t type_size,std::size_t count,FILE* __restrict fp) +{ + if(count==0) + return 0; +#if defined(__NEWLIB__)&&!defined(__CYGWIN__) + struct _reent rent{}; + std::size_t written_count{noexcept_call(_fwrite_r,__builtin_addressof(rent),begin,type_size,count,fp)}; + if(!written_count)[[unlikely]] + throw_posix_error(rent._errno); +#else + + std::size_t written_count{ +#if !defined(fwrite)&&defined(__has_builtin) +#if __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 + }; + if(!written_count)[[unlikely]] + throw_posix_error(); +#endif + return written_count; +} + +inline std::size_t c_read_impl(void* __restrict begin,std::size_t type_size,std::size_t count,FILE* __restrict fp) +{ + if(fp==stdin) + { + ::fast_io::noexcept_call(::fflush,stdout); + } +#if defined(__NEWLIB__) + struct _reent rent{}; + std::size_t read_count{noexcept_call(_fread_r,__builtin_addressof(rent),begin,type_size,count,fp)}; + if(read_count==0)[[unlikely]] + { + if(rent._errno) + throw_posix_error(rent._errno); + } +#else + std::size_t read_count{ +#if !defined(fread)&&defined(__has_builtin) +#if __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 + }; + if(read_count==0)[[unlikely]] + { + if( +#if !defined(ferror)&&defined(__has_builtin) +#if __has_builtin(__builtin_ferror) + __builtin_ferror(fp) +#else + ferror(fp) +#endif +#else + ferror(fp) +#endif + ) + throw_posix_error(); + } +#endif + return read_count; +} + +template +inline std::size_t c_io_write_impl(basic_c_family_io_observer cfhd,char_type const* begin,char_type const* end) +{ + std::ptrdiff_t const count(end-begin); + if constexpr(family==c_family::unlocked) + { + if constexpr(buffer_output_stream_impl>) + { + auto curr{obuffer_curr(cfhd)}; + auto ed{obuffer_end(cfhd)}; + if(count(count),curr); + obuffer_set_curr(cfhd,curr+count); + return static_cast(count); + } + } + return c_fwrite_unlocked_impl(begin,sizeof(char_type),static_cast(count),cfhd.fp); + } + else if constexpr(buffer_output_stream_impl>) + { + io_lock_guard guard{cfhd}; + return c_io_write_impl(basic_c_io_observer_unlocked{cfhd.fp},begin,end); + } + else + return c_fwrite_impl(begin,sizeof(char_type),static_cast(count),cfhd.fp); +} + +template +inline std::size_t c_io_read_impl(basic_c_family_io_observer cfhd,char_type* begin,char_type* end) +{ + std::ptrdiff_t const count(end-begin); + if constexpr(buffer_input_stream_impl>) + { + auto curr{ibuffer_curr(cfhd)}; + auto ed{ibuffer_end(cfhd)}; + if(count(count),begin); + ibuffer_set_curr(cfhd,curr+count); + return static_cast(count); + } + return c_fread_unlocked_impl(begin,sizeof(char_type),static_cast(count),cfhd.fp); + } + else if constexpr(buffer_input_stream_impl>) + { + io_lock_guard guard{cfhd}; + return c_io_read_impl(basic_c_io_observer_unlocked{cfhd.fp},begin,end); + } + else + return c_read_impl(begin,sizeof(char_type),static_cast(count),cfhd.fp); +} +#if 0 +template +inline io_scatter_status_t c_io_scatter_write_impl(basic_c_family_io_observer cfhd,basic_io_scatter_t const* scatters,std::size_t n) +{ + if constexpr(family==c_family::standard) + { + if(n==0) + return {0,0,0}; + if constexpr(buffer_output_stream_impl>) + { + lock_guard guard{cfhd}; + return c_io_scatter_write_impl(basic_c_io_observer_unlocked{cfhd.fp},begin,end); + + } + else + { + if(n==1) + return c_fwrite_impl(scatters[0].base,,scatters[0].len); + lock_guard guard{cfhd}; + return c_io_scatter_write_impl(basic_c_io_observer_unlocked{cfhd.fp},begin,end); + } + } + else + { + std::size_t total_written{}; + for(std::size_t i{};i!=n;++i) + { + io_scatter_t scat{scatters[i]}; + std::size_t sz{c_io_write_impl(cfhd,scat.base,scat.len)}; + total_written+=sz; + if(sz!=scat.len) + return {total_written,i,sz}; + } + return {total_written,n,0}; + } +} + +template +inline io_scatter_status_t c_io_scatter_read_impl(basic_c_family_io_observer cfhd,io_scatter_t const* scatters,std::size_t n) +{ + +} +#endif +} + +template +requires (std::same_as>||std::same_as) +inline Iter write(basic_c_family_io_observer cfhd,Iter cbegin,Iter cend) +{ + if constexpr(std::same_as<::std::iter_value_t,T>) + return cbegin+details::c_io_write_impl(cfhd,::std::to_address(cbegin),::std::to_address(cend)); + else + return cbegin+details::c_io_write_impl(cfhd,reinterpret_cast(::std::to_address(cbegin)),reinterpret_cast(::std::to_address(cend)))/sizeof(*cbegin); +} + +template +requires (std::same_as>||std::same_as) +[[nodiscard]] inline Iter read(basic_c_family_io_observer cfhd,Iter begin,Iter end) +{ + if constexpr(std::same_as<::std::iter_value_t,T>) + return begin+details::c_io_read_impl(cfhd,::std::to_address(begin),::std::to_address(end)); + else + return begin+details::c_io_read_impl(cfhd,reinterpret_cast(::std::to_address(begin)),reinterpret_cast(::std::to_address(end)))/sizeof(*begin); +} + +} diff --git a/src/fast_io/include/fast_io_legacy_impl/c/general.h b/src/fast_io/include/fast_io_legacy_impl/c/general.h new file mode 100644 index 0000000..b8842d1 --- /dev/null +++ b/src/fast_io/include/fast_io_legacy_impl/c/general.h @@ -0,0 +1,119 @@ +#pragma once +#if __has_include() +#include +#elif __has_include() +#include +#endif +/* + +Provide a general emulation of FILE*'s internal implementation with fgetc_unlocked and ungetc_unlocked. + +It is probably slow. However, it is a general case when we have not supported hacks of libcs on your platform. + +BTW, musl libc and BSD libc does not provide general buffering for wide characters. This should cover that gap. +*/ + +namespace fast_io +{ + +namespace details +{ +template +inline auto fgetc_unlocked_impl(FILE* fp) noexcept +{ + if constexpr(std::same_as||std::same_as) + { +#if (defined(_WIN32)&&!defined(__WINE__)) + return _fgetc_nolock(fp); +#elif (defined(__NEWLIB__) && __GNU_VISIBLE) || (!defined(__NEWLIB__)&&(_POSIX_C_SOURCE >= 199309L || _XOPEN_SOURCE || _POSIX_SOURCE || _BSD_SOURCE || _SVID_SOURCE)) + return fgetc_unlocked(fp); +#else + return fgetc(fp); +#endif + } + else + { +#if defined(_MSC_VER) || defined(_UCRT) || __MSVCRT_VERSION__ >= 0x800 + return _fgetwc_nolock(fp); +#elif (defined(__NEWLIB__) && __GNU_VISIBLE) || (!defined(__NEWLIB__)&&(_POSIX_C_SOURCE >= 199309L || _XOPEN_SOURCE || _POSIX_SOURCE || _BSD_SOURCE || _SVID_SOURCE)) + return fgetwc_unlocked(fp); +#elif defined(__serenity__) + return EOF; +#else + return fgetwc(fp); +#endif + } +} + +template +requires (std::same_as||std::same_as||std::same_as) +inline constexpr bool equals_to_eof_macro(int_type inv) noexcept +{ + if constexpr(std::same_as||std::same_as) + return inv==EOF; + else + return inv==WEOF; +} + +template +inline auto ungetc_unlocked_impl(char_type ch,FILE* fp) noexcept +{ + if constexpr(std::same_as||std::same_as) + { +#if defined(_MSC_VER) + return _ungetc_nolock(ch,fp); +#elif (defined(__NEWLIB__) && __GNU_VISIBLE) || (!defined(__NEWLIB__)&&(_POSIX_C_SOURCE >= 199309L || _XOPEN_SOURCE || _POSIX_SOURCE || _BSD_SOURCE || _SVID_SOURCE)) + return ungetc_unlocked(ch,fp); +#else + return ungetc(ch,fp); +#endif + } + else + { +#if defined(_MSC_VER) + return _ungetwc_nolock(ch,fp); +#elif (defined(__NEWLIB__) && __GNU_VISIBLE) || (!defined(__NEWLIB__)&&(_POSIX_C_SOURCE >= 199309L || _XOPEN_SOURCE || _POSIX_SOURCE || _BSD_SOURCE || _SVID_SOURCE)) + return ungetwc_unlocked(ch,fp); +#else + return ungetwc(ch,fp); +#endif + } +} +inline void ferror_throw_ex_impl(FILE* fp) +{ + if( +#if (defined(__NEWLIB__) && __GNU_VISIBLE) || (!defined(__NEWLIB__)&&(_POSIX_C_SOURCE >= 199309L || _XOPEN_SOURCE || _POSIX_SOURCE || _BSD_SOURCE || _SVID_SOURCE)) + ferror_unlocked(fp) +#else + ferror(fp) +#endif + ) + throw_posix_error(); +} +} + +template +requires (std::same_as +#if !defined(__serenity__) +||std::same_as +#endif +||std::same_as) +inline std::pair try_get(basic_c_io_observer_unlocked ciob) +{ + auto ret{details::fgetc_unlocked_impl(ciob.fp)}; + if(details::equals_to_eof_macro(ret)) + { + details::ferror_throw_ex_impl(ciob.fp); + return {0,false}; + } + return {static_cast(ret),true}; +} + +template +requires (std::same_as||std::same_as||std::same_as) +inline void try_unget(basic_c_io_observer_unlocked ciob,char_type ch) noexcept +{ + details::ungetc_unlocked_impl(ch,ciob.fp); +} + +} diff --git a/src/fast_io/include/fast_io_legacy_impl/c/glibc.h b/src/fast_io/include/fast_io_legacy_impl/c/glibc.h new file mode 100644 index 0000000..d567fd7 --- /dev/null +++ b/src/fast_io/include/fast_io_legacy_impl/c/glibc.h @@ -0,0 +1,274 @@ +#pragma once + +namespace fast_io +{ + +inline constexpr char* ibuffer_begin(c_io_observer_unlocked cio) noexcept +{ + return cio.fp->_IO_read_base; +} + +inline constexpr char* ibuffer_curr(c_io_observer_unlocked cio) noexcept +{ + return cio.fp->_IO_read_ptr; +} + +inline constexpr char* ibuffer_end(c_io_observer_unlocked cio) noexcept +{ + return cio.fp->_IO_read_end; +} + +inline constexpr void ibuffer_set_curr(c_io_observer_unlocked cio,char* ptr) noexcept +{ + cio.fp->_IO_read_ptr=ptr; +} + +extern int glibc_underflow (FILE*) noexcept __asm__("__underflow"); +inline bool ibuffer_underflow(c_io_observer_unlocked cio) noexcept +{ + cio.fp->_IO_read_ptr=cio.fp->_IO_read_end; + return glibc_underflow(cio.fp)!=EOF; +} + +inline constexpr char* obuffer_begin(c_io_observer_unlocked cio) noexcept +{ + return cio.fp->_IO_write_base; +} + +inline constexpr char* obuffer_curr(c_io_observer_unlocked cio) noexcept +{ + return cio.fp->_IO_write_ptr; +} + +inline constexpr char* obuffer_end(c_io_observer_unlocked cio) noexcept +{ + return cio.fp->_IO_write_end; +} + +inline constexpr void obuffer_set_curr(c_io_observer_unlocked cio,char* ptr) noexcept +{ + cio.fp->_IO_write_ptr=ptr; +} + +extern int glibc_overflow (FILE *,int) noexcept __asm__("__overflow"); + +inline void obuffer_overflow(c_io_observer_unlocked cio,char ch) +{ + if(glibc_overflow(cio.fp,static_cast(static_cast(ch)))==EOF)[[unlikely]] + throw_posix_error(); +} + + +[[__gnu__::__may_alias__]] inline char8_t* ibuffer_begin(u8c_io_observer_unlocked cio) noexcept +{ + return bit_cast(cio.fp->_IO_read_base); +} + +[[__gnu__::__may_alias__]] inline char8_t* ibuffer_curr(u8c_io_observer_unlocked cio) noexcept +{ + return bit_cast(cio.fp->_IO_read_ptr); +} + +[[__gnu__::__may_alias__]] inline char8_t* ibuffer_end(u8c_io_observer_unlocked cio) noexcept +{ + return bit_cast(cio.fp->_IO_read_end); +} + +inline void ibuffer_set_curr(u8c_io_observer_unlocked cio,char8_t* ptr) noexcept +{ + cio.fp->_IO_read_ptr=bit_cast(ptr); +} + +inline bool ibuffer_underflow(u8c_io_observer_unlocked cio) noexcept +{ + cio.fp->_IO_read_ptr=cio.fp->_IO_read_end; + return glibc_underflow(cio.fp)!=EOF; +} + +[[__gnu__::__may_alias__]] inline char8_t* obuffer_begin(u8c_io_observer_unlocked cio) noexcept +{ + return bit_cast(cio.fp->_IO_write_base); +} + +[[__gnu__::__may_alias__]] inline char8_t* obuffer_curr(u8c_io_observer_unlocked cio) noexcept +{ + return bit_cast(cio.fp->_IO_write_ptr); +} + +[[__gnu__::__may_alias__]] inline char8_t* obuffer_end(u8c_io_observer_unlocked cio) noexcept +{ + return bit_cast(cio.fp->_IO_write_end); +} + +inline void obuffer_set_curr(u8c_io_observer_unlocked cio,[[__gnu__::__may_alias__]] char8_t* ptr) noexcept +{ + cio.fp->_IO_write_ptr=bit_cast(ptr); +} + +inline void obuffer_overflow(u8c_io_observer_unlocked cio,char8_t ch) +{ + if(glibc_overflow(cio.fp,static_cast(ch))==EOF)[[unlikely]] + throw_posix_error(); +} + +namespace details::fp_wide_hack +{ +/* +https://github.com/lattera/glibc/blob/master/libio/bits/types/struct_FILE.h +*/ +inline std::byte* hack_wide_data(FILE* fp) noexcept +{ + constexpr std::size_t off{sizeof(__off64_t)+2*sizeof(std::uintptr_t)}; + std::byte* value; + ::fast_io::details::my_memcpy(__builtin_addressof(value),reinterpret_cast(__builtin_addressof(fp->_lock))+off,sizeof(std::byte*)); + return value; +} + +template +requires (sizeof(char_type)==sizeof(char32_t)) +inline char_type* hack_wp(FILE* fp) noexcept +{ + constexpr std::size_t off{position*sizeof(uintptr_t)}; + char_type* value; + ::fast_io::details::my_memcpy(__builtin_addressof(value),hack_wide_data(fp)+off,sizeof(wchar_t*)); + return value; +} +template +requires (sizeof(char_type)==sizeof(char32_t)) +inline void hack_wpset(FILE* fp,char_type* ptr) noexcept +{ + constexpr std::size_t off{position*sizeof(uintptr_t)}; + ::fast_io::details::my_memcpy(hack_wide_data(fp)+off,__builtin_addressof(ptr),sizeof(wchar_t*)); +} +} +#if WCHAR_MAX == UINT_LEAST32_MAX +//wchar_t supports + +inline wchar_t* ibuffer_begin(wc_io_observer_unlocked cio) noexcept +{ + return details::fp_wide_hack::hack_wp<2,wchar_t>(cio.fp); +} + +inline wchar_t* ibuffer_curr(wc_io_observer_unlocked cio) noexcept +{ + return details::fp_wide_hack::hack_wp<0,wchar_t>(cio.fp); +} + +inline wchar_t* ibuffer_end(wc_io_observer_unlocked cio) noexcept +{ + return details::fp_wide_hack::hack_wp<1,wchar_t>(cio.fp); +} + +inline void ibuffer_set_curr(wc_io_observer_unlocked cio,wchar_t* ptr) noexcept +{ + details::fp_wide_hack::hack_wpset<0,wchar_t>(cio.fp,ptr); +} +#endif + +namespace details +{ +extern std::uint_least32_t glibc_wunderflow (FILE *) noexcept __asm__("__wunderflow"); +} +#if WCHAR_MAX == UINT_LEAST32_MAX +inline bool ibuffer_underflow(wc_io_observer_unlocked cio) noexcept +{ + ibuffer_set_curr(cio,ibuffer_end(cio)); + return details::glibc_wunderflow(cio.fp)!=static_cast(0xffffffffu); +} +inline wchar_t* obuffer_begin(wc_io_observer_unlocked cio) noexcept +{ + return details::fp_wide_hack::hack_wp<3,wchar_t>(cio.fp); +} + +inline wchar_t* obuffer_curr(wc_io_observer_unlocked cio) noexcept +{ + return details::fp_wide_hack::hack_wp<4,wchar_t>(cio.fp); +} + +inline wchar_t* obuffer_end(wc_io_observer_unlocked cio) noexcept +{ + return details::fp_wide_hack::hack_wp<5,wchar_t>(cio.fp); +} + +inline void obuffer_set_curr(wc_io_observer_unlocked cio,wchar_t* ptr) noexcept +{ + ibuffer_set_curr(cio,ibuffer_end(cio)); + details::fp_wide_hack::hack_wpset<4,wchar_t>(cio.fp,ptr); +} +#endif +namespace details +{ +extern std::uint_least32_t glibc_woverflow (FILE *,std::uint_least32_t) noexcept __asm__("__woverflow"); +} + +inline void obuffer_overflow(wc_io_observer_unlocked cio,wchar_t ch) +{ + if(details::glibc_woverflow(cio.fp,static_cast(ch))==static_cast(0xffffffffu))[[unlikely]] + throw_posix_error(); +} + + +[[__gnu__::__may_alias__]] inline char32_t* ibuffer_begin(u32c_io_observer_unlocked cio) noexcept +{ + return details::fp_wide_hack::hack_wp<2,char32_t>(cio.fp); +} + +[[__gnu__::__may_alias__]] inline char32_t* ibuffer_curr(u32c_io_observer_unlocked cio) noexcept +{ + return details::fp_wide_hack::hack_wp<0,char32_t>(cio.fp); +} + +[[__gnu__::__may_alias__]] inline char32_t* ibuffer_end(u32c_io_observer_unlocked cio) noexcept +{ + return details::fp_wide_hack::hack_wp<1,char32_t>(cio.fp); +} + +inline void ibuffer_set_curr(u32c_io_observer_unlocked cio,[[__gnu__::__may_alias__]] char32_t* ptr) noexcept +{ + details::fp_wide_hack::hack_wpset<0,char32_t>(cio.fp,ptr); +} + +inline bool ibuffer_underflow(u32c_io_observer_unlocked cio) noexcept +{ + ibuffer_set_curr(cio,ibuffer_end(cio)); + return details::glibc_wunderflow(cio.fp)!=static_cast(0xffffffffu); +} + +[[__gnu__::__may_alias__]] inline char32_t* obuffer_begin(u32c_io_observer_unlocked cio) noexcept +{ + return details::fp_wide_hack::hack_wp<3,char32_t>(cio.fp); +} + +[[__gnu__::__may_alias__]] inline char32_t* obuffer_curr(u32c_io_observer_unlocked cio) noexcept +{ + return details::fp_wide_hack::hack_wp<4,char32_t>(cio.fp); +} + +[[__gnu__::__may_alias__]] inline char32_t* obuffer_end(u32c_io_observer_unlocked cio) noexcept +{ + return details::fp_wide_hack::hack_wp<5,char32_t>(cio.fp); +} + +inline void obuffer_set_curr(u32c_io_observer_unlocked cio,[[__gnu__::__may_alias__]] char32_t* ptr) noexcept +{ + details::fp_wide_hack::hack_wpset<4,char32_t>(cio.fp,ptr); +} + +inline void obuffer_overflow(u32c_io_observer_unlocked cio,char32_t ch) +{ + if(details::glibc_woverflow(cio.fp,static_cast(ch))==static_cast(0xffffffffu))[[unlikely]] + throw_posix_error(); +} + +namespace details +{ +extern int glibc_flbf(FILE* fp) noexcept __asm__("__flbf"); +} + +template +inline bool obuffer_is_line_buffering(basic_c_io_observer_unlocked ciou) noexcept +{ + return details::glibc_flbf(ciou.fp); +} + +} diff --git a/src/fast_io/include/fast_io_legacy_impl/c/impl.h b/src/fast_io/include/fast_io_legacy_impl/c/impl.h new file mode 100644 index 0000000..4f882c0 --- /dev/null +++ b/src/fast_io/include/fast_io_legacy_impl/c/impl.h @@ -0,0 +1,1110 @@ +#pragma once +#if __has_include() +#include +#elif __has_include() +#include +#endif + +#if defined(__MINGW32__) && !defined(_UCRT) && !defined(__BIONIC__) +#include"msvcrt_lock.h" +#endif + +namespace fast_io +{ + +inline constexpr open_mode native_c_supported(open_mode m) noexcept +{ +#if (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) && !defined(__CYGWIN__) +using utype = typename std::underlying_type::type; +constexpr auto c_supported_values{static_cast(open_mode::text)| + static_cast(open_mode::out)| + static_cast(open_mode::app)| + static_cast(open_mode::in)| + static_cast(open_mode::trunc)}; +return static_cast(static_cast(m)&c_supported_values); +#else +return c_supported(m); +#endif +} +inline constexpr +#if (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) && !defined(__CYGWIN__) && !defined(_WIN32_WINDOWS) +wchar_t const* +#else +char const* +#endif +to_native_c_mode(open_mode m) noexcept +{ +#if (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) && !defined(__CYGWIN__) +/* +https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/fdopen-wfdopen?view=vs-2019 +From microsoft's document. _fdopen only supports + +"r" Opens for reading. If the file does not exist or cannot be found, the fopen call fails. +"w" Opens an empty file for writing. If the given file exists, its contents are destroyed. +"a" Opens for writing at the end of the file (appending). Creates the file if it does not exist. +"r+" Opens for both reading and writing. The file must exist. +"w+" Opens an empty file for both reading and writing. If the file exists, its contents are destroyed. +"a+" Opens for reading and appending. Creates the file if it does not exist. + +"x" will throw EINVAL which does not satisfy POSIX, C11 and C++17 standard. +*/ + using utype = typename std::underlying_type::type; +#ifdef _WIN32_WINDOWS + switch(static_cast(native_c_supported(m))) + { +//Action if file already exists; Action if file does not exist; c-style mode; Explanation +//Read from start; Failure to open; "r"; Open a file for reading + case static_cast(open_mode::in)|static_cast(open_mode::text): + return "\x72"; +//Destroy contents; Create new; "w"; Create a file for writing + case static_cast(open_mode::out)|static_cast(open_mode::text): + case static_cast(open_mode::out)|static_cast(open_mode::trunc)|static_cast(open_mode::text): + return "\x77"; +//Append to file; Create new; "a"; Append to a file + case static_cast(open_mode::app)|static_cast(open_mode::text): + case static_cast(open_mode::out)|static_cast(open_mode::app)|static_cast(open_mode::text): + return "\x61"; +//Read from start; Error; "r+"; Open a file for read/write + case static_cast(open_mode::out)|static_cast(open_mode::in)|static_cast(open_mode::text): + return "\x72\x2b"; +//Destroy contents; Create new; "w+"; Create a file for read/write + case static_cast(open_mode::out)|static_cast(open_mode::in)|static_cast(open_mode::trunc)|static_cast(open_mode::text): + return "\x77\x2b"; +//Write to end; Create new; "a+"; Open a file for read/write + case static_cast(open_mode::out)|static_cast(open_mode::in)|static_cast(open_mode::app)|static_cast(open_mode::text): + case static_cast(open_mode::in)|static_cast(open_mode::app)|static_cast(open_mode::text): + return "\x77\x2b"; + +//binary support + +//Action if file already exists; Action if file does not exist; c-style mode; Explanation +//Read from start; Failure to open; "rb"; Open a file for reading + case static_cast(open_mode::in): + return "\x72\x62"; +//Destroy contents; Create new; "wb"; Create a file for writing + case static_cast(open_mode::out): + case static_cast(open_mode::out)|static_cast(open_mode::trunc): + return "\x77\x62"; +//Append to file; Create new; "ab"; Append to a file + case static_cast(open_mode::app): + case static_cast(open_mode::out)|static_cast(open_mode::app): + return "\x61\x62"; +//Read from start; Error; "r+b"; Open a file for read/write + case static_cast(open_mode::out)|static_cast(open_mode::in): + return "\x72\x2b\x62"; +//Destroy contents; Create new; "w+b"; Create a file for read/write + case static_cast(open_mode::out)|static_cast(open_mode::in)|static_cast(open_mode::trunc): + return "\x77\x2b\x62"; +//Write to end; Create new; "a+b"; Open a file for read/write + case static_cast(open_mode::out)|static_cast(open_mode::in)|static_cast(open_mode::app): + case static_cast(open_mode::in)|static_cast(open_mode::app): + return "\x61\x2b\x62"; + case 0: + if((m&open_mode::directory)!=open_mode::none) + return "\x72"; + [[fallthrough]]; + default: + return ""; + } +#else + switch(static_cast(native_c_supported(m))) + { +//Action if file already exists; Action if file does not exist; c-style mode; Explanation +//Read from start; Failure to open; "r"; Open a file for reading + case static_cast(open_mode::in)|static_cast(open_mode::text): + return L"\x72"; +//Destroy contents; Create new; "w"; Create a file for writing + case static_cast(open_mode::out)|static_cast(open_mode::text): + case static_cast(open_mode::out)|static_cast(open_mode::trunc)|static_cast(open_mode::text): + return L"\x77"; +//Append to file; Create new; "a"; Append to a file + case static_cast(open_mode::app)|static_cast(open_mode::text): + case static_cast(open_mode::out)|static_cast(open_mode::app)|static_cast(open_mode::text): + return L"\x61"; +//Read from start; Error; "r+"; Open a file for read/write + case static_cast(open_mode::out)|static_cast(open_mode::in)|static_cast(open_mode::text): + return L"\x72\x2b"; +//Destroy contents; Create new; "w+"; Create a file for read/write + case static_cast(open_mode::out)|static_cast(open_mode::in)|static_cast(open_mode::trunc)|static_cast(open_mode::text): + return L"\x77\x2b"; +//Write to end; Create new; "a+"; Open a file for read/write + case static_cast(open_mode::out)|static_cast(open_mode::in)|static_cast(open_mode::app)|static_cast(open_mode::text): + case static_cast(open_mode::in)|static_cast(open_mode::app)|static_cast(open_mode::text): + return L"\x77\x2b"; + +//binary support + +//Action if file already exists; Action if file does not exist; c-style mode; Explanation +//Read from start; Failure to open; "rb"; Open a file for reading + case static_cast(open_mode::in): + return L"\x72\x62"; +//Destroy contents; Create new; "wb"; Create a file for writing + case static_cast(open_mode::out): + case static_cast(open_mode::out)|static_cast(open_mode::trunc): + return L"\x77\x62"; +//Append to file; Create new; "ab"; Append to a file + case static_cast(open_mode::app): + case static_cast(open_mode::out)|static_cast(open_mode::app): + return L"\x61\x62"; +//Read from start; Error; "r+b"; Open a file for read/write + case static_cast(open_mode::out)|static_cast(open_mode::in): + return L"\x72\x2b\x62"; +//Destroy contents; Create new; "w+b"; Create a file for read/write + case static_cast(open_mode::out)|static_cast(open_mode::in)|static_cast(open_mode::trunc): + return L"\x77\x2b\x62"; +//Write to end; Create new; "a+b"; Open a file for read/write + case static_cast(open_mode::out)|static_cast(open_mode::in)|static_cast(open_mode::app): + case static_cast(open_mode::in)|static_cast(open_mode::app): + return L"\x61\x2b\x62"; + case 0: + if((m&open_mode::directory)!=open_mode::none) + return L"\x72"; + [[fallthrough]]; + default: + return L""; + } +#endif +#else + return to_c_mode(m); +#endif +} + +namespace details +{ + +#if defined(__MSDOS__) +extern int fileno(FILE*) noexcept __asm__("_fileno"); +extern FILE* fdopen(int,char const*) noexcept __asm__("_fdopen"); +#elif defined(__CYGWIN__) +[[__gnu__::__dllimport__]] extern int fileno(FILE*) noexcept +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if defined(__GNUC__) +__asm__("fileno") +#else +__asm__("_fileno") +#endif +#else +__asm__("fileno") +#endif +; +[[__gnu__::__dllimport__]] extern FILE* fdopen(int,char const*) noexcept +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if defined(__GNUC__) +__asm__("fdopen") +#else +__asm__("_fdopen") +#endif +#else +__asm__("fdopen") +#endif +; + +#endif + + +#if defined(__CYGWIN__) + +[[__gnu__::__dllimport__]] extern void my_cygwin_pthread_mutex_lock(void*) noexcept +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if defined(__GNUC__) +__asm__("pthread_mutex_lock") +#else +__asm__("_pthread_mutex_lock") +#endif +#else +__asm__("pthread_mutex_lock") +#endif +; + +[[__gnu__::__dllimport__]] extern void my_cygwin_pthread_mutex_unlock(void*) noexcept +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if defined(__GNUC__) +__asm__("pthread_mutex_unlock") +#else +__asm__("_pthread_mutex_unlock") +#endif +#else +__asm__("pthread_mutex_unlock") +#endif +; + +inline void my_cygwin_flockfile(FILE* fp) noexcept +{ + if(!((fp->_flags)&__SSTR)) + my_cygwin_pthread_mutex_lock(fp->_lock); +} + +inline void my_cygwin_funlockfile(FILE* fp) noexcept +{ + if(!((fp->_flags)&__SSTR)) + my_cygwin_pthread_mutex_unlock(fp->_lock); +} + +#endif + +#if (defined(_MSC_VER)||defined(_UCRT)) && !defined(__WINE__) && !defined(__CYGWIN__) +inline void ucrt_lock_file(FILE* fp) noexcept; +inline void ucrt_unlock_file(FILE* fp) noexcept; +#endif + +} + + +enum class c_family:std::uint_fast8_t +{ +standard, +unlocked, +emulated, +emulated_unlocked, +native= +#if defined(__AVR__) || defined(_PICOLIBC__) +emulated_unlocked +#elif defined(__MSDOS__) +unlocked +#else +standard +#endif +, +native_unlocked = +#if defined(__AVR__) || defined(_PICOLIBC__) +emulated_unlocked +#else +unlocked +#endif +}; + +enum class c_io_device_environment:std::uint_fast8_t +{ +file, +custom, +native = +#if defined(__AVR__) +custom +#else +file +#endif +}; + +struct c_io_device_open_t +{ +explicit constexpr c_io_device_open_t() noexcept = default; +}; +inline constexpr c_io_device_open_t c_io_device_open{}; + +namespace details +{ + +template +inline int my_fileno_impl(FILE* fp) noexcept +{ + if(fp==nullptr) + return -1; + if constexpr(family==c_family::standard) + { + return +#if (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) && !defined(__CYGWIN__) + noexcept_call(_fileno,fp) +#elif defined(__NEWLIB__) + fp->_file +#else + noexcept_call(fileno,fp) +#endif + ; + + } + else + { + return +#if (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) && !defined(__CYGWIN__) + noexcept_call(_fileno,fp) +#elif defined(__NEWLIB__) || defined(__DARWIN_C_LEVEL) + fp->_file +#elif (defined(__MISC_VISIBLE) || defined(__USE_MISC))&&!defined(_PICOLIBC__) + noexcept_call(fileno_unlocked,fp) +#else + noexcept_call(fileno,fp) +#endif + ; + } +} + +inline int fp_to_fd(FILE* fp) noexcept +{ + return my_fileno_impl(fp); +} + +inline int fp_unlocked_to_fd(FILE* fp) noexcept +{ + return my_fileno_impl(fp); +} + +#if (defined(_WIN32)&&!defined(__WINE__)) || defined(__CYGWIN__) +template +inline void* my_fp_to_win32_handle_impl(FILE* fp) noexcept +{ + return my_get_osfile_handle(my_fileno_impl(fp)); +} +#endif + +template +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) + return __builtin_fclose(fp); +#else + return fclose(fp); +#endif +#else + return fclose(fp); +#endif + } + else + { +#if defined(_MSC_VER) || defined(_UCRT) + return noexcept_call(_fclose_nolock,fp); +#else +#ifdef __has_builtin +#if __has_builtin(__builtin_fclose) + return __builtin_fclose(fp); +#else + return fclose(fp); +#endif +#else + return fclose(fp); +#endif +#endif + } +} + +#if !defined(__NEWLIB__) || defined(__CYGWIN__) + +#if defined(__GLIBC__) +extern size_t glibc_fbufsize(FILE *stream) noexcept __asm__("__fbufsize"); +#endif + +inline FILE* my_fdopen(int fd,char const* mode) noexcept +{ + auto fp{ +#if (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) && !defined(__CYGWIN__) + noexcept_call(_fdopen,fd,mode) +#elif defined(__MSDOS__) || defined(__CYGWIN__) + fdopen(fd,mode) +#else + noexcept_call(fdopen,fd,mode) +#endif + }; +/* +WSL since microsoft sets the fstat block size incorrectly, leading to massive IO slow down for glibc. +i woud like to add bandaids to fix it. Not working. setvbuf is a noop + +For fstream for GNU libstdc++. We should no longer construct FILE* by ourself if user is not using c_file to construct filebuf_file. +*/ + return fp; +} + +#endif + +inline FILE* my_c_file_open_impl(int fd,open_mode mode) +{ +#if (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) && !defined(__CYGWIN__) && !defined(_WIN32_WINDOWS) + +/* +Reference implementation from ReactOS shows that _fdopen will call MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,str,len,wstr,len); which is not thread-safe +and we might get screwed by locale on NT kernel. Avoid it and call _wfdopen instead. +https://doxygen.reactos.org/d2/d1b/sdk_2lib_2crt_2stdio_2file_8c_source.html +*/ + + wchar_t const* cmode{to_native_c_mode(mode)}; +#if defined(__MINGW32__) && !__has_include(<_mingw_stat64.h>) + auto fp{noexcept_call(_wfdopen,fd,const_cast(cmode))}; +#else + auto fp{noexcept_call(_wfdopen,fd,cmode)}; +#endif + if(fp==nullptr) + throw_posix_error(); +#else + char const* cmode{to_native_c_mode(mode)}; +#if defined(__NEWLIB__) && !defined(__CYGWIN__) + struct _reent ent{}; + auto fp{noexcept_call(_fdopen_r,__builtin_addressof(ent),fd,cmode)}; + if(fp==nullptr) + throw_posix_error(ent._errno); +#else + auto fp{my_fdopen(fd,cmode)}; + if(fp==nullptr) + throw_posix_error(); +#endif +#endif + return fp; +} +#if defined(__NEWLIB__) +inline void my_c_io_newlib_flush_impl(FILE* fp) +{ + struct _reent ent{}; + if(noexcept_call(_fflush_r,__builtin_addressof(ent),fp)) + throw_posix_error(ent._errno); +} +#endif + +template +inline void my_c_io_flush_impl(FILE* fp) +{ +#if defined(__NEWLIB__) && !defined(__CYGWIN__) + my_c_io_newlib_flush_impl(fp); +#else + if constexpr(family==c_family::standard) + { +#if defined(__has_builtin) +#if __has_builtin(__builtin_fflush) + if(__builtin_fflush(fp)) +#else + if(fflush(fp)) +#endif +#else + if(fflush(fp)) +#endif + throw_posix_error(); + } + else + { +#if (defined(_MSC_VER) || defined(_UCRT)) && !defined(__BIONIC__) + if(noexcept_call(_fflush_nolock,fp)) + throw_posix_error(); +#elif defined(__MISC_VISIBLE) && !defined(__NEWLIB__)&&!defined(_PICOLIBC__) + if(noexcept_call(fflush_unlocked,fp)) + throw_posix_error(); +#else + return my_c_io_flush_impl(fp); +#endif + } +#endif +} + +inline void c_flush_unlocked_impl(FILE* fp) +{ + my_c_io_flush_impl(fp); +} + +#if defined(__AVR__) + +[[noreturn]] inline void avr_libc_nosup_impl() +{ + throw_posix_error(EINVAL); +} + +template +inline std::uintmax_t my_c_io_seek_impl(FILE*,std::intmax_t,seekdir) +{ + avr_libc_nosup_impl(); +} + +#else +template +inline std::uintmax_t my_c_io_seek_impl(FILE* fp,std::intmax_t offset,seekdir s) +{ + +/* +We avoid standard C functions since they cannot deal with large file on 32 bits platforms + +Reference: + +https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/fseek-nolock-fseeki64-nolock?view=vs-2019 + +https://www.gnu.org/software/libc/manual/html_node/File-Positioning.html + +*/ + if constexpr(family==c_family::unlocked||family==c_family::emulated_unlocked) + { +#if (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) && !defined(__CYGWIN__) +#if defined(_MSC_VER) || defined(_UCRT) || __MSVCRT_VERSION__ >= 0x800 + if(noexcept_call(_fseeki64_nolock,fp,offset,static_cast(s))) + throw_posix_error(); + auto val{noexcept_call(_ftelli64_nolock,fp)}; + if(val<0) + throw_posix_error(); + return val; +#else + if(noexcept_call(fseeko64,fp,offset,static_cast(s))) + throw_posix_error(); + auto val{noexcept_call(ftello64,fp)}; + if(val<0) + throw_posix_error(); + return static_cast(val); +#endif +#else + return my_c_io_seek_impl(fp,offset,s); +#endif + } + else + { + +#if defined(__NEWLIB__) && !defined(__CYGWIN__) + struct _reent ent{}; + if(noexcept_call(_fseeko_r,__builtin_addressof(ent),fp,static_cast<_off_t>(offset),static_cast(s))) + throw_posix_error(ent._errno); + ent={}; + auto val{noexcept_call(_ftell_r,__builtin_addressof(ent),fp)}; + if(val<0) + throw_posix_error(ent._errno); + return val; +#elif defined(__MSDOS__) || defined(__CYGWIN__) || defined(_PICOLIBC__) || (defined(__MINGW32__)&&!__has_include(<_mingw_stat64.h>)) + if constexpr(sizeof(long)(std::numeric_limits::min())||offset>static_cast(std::numeric_limits::max())) + throw_posix_error(EINVAL); + } + if(noexcept_call(::fseek,fp,static_cast(offset),static_cast(s))) + throw_posix_error(); + auto val{noexcept_call(::ftell,fp)}; + if(val<0) + throw_posix_error(); + return static_cast(static_cast(val)); +#else + if( +#if (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) && !defined(__CYGWIN__) + _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) + __builtin_fseeko(fp,offset,static_cast(s)) +#else + fseeko(fp,offset,static_cast(s)) +#endif +#else + fseeko(fp,offset,static_cast(s)) +#endif + ) + throw_posix_error(); + auto val{ +#if (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) && !defined(__CYGWIN__) + noexcept_call(_ftelli64,fp) +#elif defined(__USE_LARGEFILE64) + noexcept_call(ftello64,fp) +#elif defined(__has_builtin) +#if __has_builtin(__builtin_ftello) + __builtin_ftello(fp) +#else + ftello(fp) +#endif +#else + ftello(fp) +#endif + }; + if(val<0) + throw_posix_error(); + return static_cast(val); +#endif + } +} +#endif + +inline FILE* my_c_open_tmp_file() +{ +#if defined(__AVR__) || defined(_PICOLIBC__) + throw_posix_error(EINVAL); +#else + ::fast_io::posix_file pf(io_temp); + auto fp{::fast_io::details::my_c_file_open_impl(pf.fd,::fast_io::open_mode::in|::fast_io::open_mode::out)}; + pf.release(); + return fp; +#endif +} + +} + +template +requires (family==c_family::native||family==c_family::native_unlocked) +class basic_c_family_io_observer +{ +public: + using char_type = ch_type; + using native_handle_type = FILE*; + native_handle_type fp{}; + constexpr native_handle_type native_handle() const noexcept + { + return fp; + } + explicit constexpr operator bool() const noexcept + { + return fp; + } + constexpr native_handle_type release() noexcept + { + auto temp{fp}; + fp=nullptr; + return temp; + } +#if !defined(__AVR__) + explicit operator basic_posix_io_observer() const noexcept + { + return basic_posix_io_observer{details::my_fileno_impl(fp)}; + } +#if (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) || defined(__CYGWIN__) + template + explicit operator basic_win32_family_io_observer() const noexcept + { + return {details::my_fp_to_win32_handle_impl(fp)}; + } + template + explicit operator basic_nt_family_io_observer() const noexcept + { + return {details::my_fp_to_win32_handle_impl(fp)}; + } +#endif +#endif + inline void lock() const noexcept requires(family==c_family::standard||family==c_family::emulated) + { +#if (defined(_MSC_VER)||defined(_UCRT)) && !defined(__CYGWIN__) && !defined(__WINE__) && !defined(__BIONIC__) + if constexpr(false) + { + ::fast_io::details::ucrt_lock_file(fp); + } + else + { + noexcept_call(_lock_file,fp); + } +#elif (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) && !defined(__CYGWIN__) && !defined(__WINE__) + win32::my_msvcrt_lock_file(fp); +#elif !defined(__SINGLE_THREAD__) +#if defined(__NEWLIB__) +#if defined(__CYGWIN__) + details::my_cygwin_flockfile(fp); +#elif !defined(__SINGLE_THREAD__) +// _flockfile(fp); //TO FIX undefined reference to `__cygwin_lock_lock' why? +#endif +#elif defined(__MSDOS__) || (defined(__wasi__) &&!defined(__wasilibc_unmodified_upstream) && !defined(_REENTRANT)) || defined(__AVR__) || defined(_PICOLIBC__) +#else + noexcept_call(flockfile,fp); +#endif +#endif + } + inline void unlock() const noexcept requires(family==c_family::standard||family==c_family::emulated) + { +#if (defined(_MSC_VER)||defined(_UCRT)) && !defined(__CYGWIN__) && !defined(__WINE__) && !defined(__BIONIC__) + if constexpr(false) + { + ::fast_io::details::ucrt_unlock_file(fp); + } + else + { + noexcept_call(_unlock_file,fp); + } +#elif (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) && !defined(__CYGWIN__) + win32::my_msvcrt_unlock_file(fp); +#elif !defined(__SINGLE_THREAD__) +#if defined(__NEWLIB__) +#if defined(__CYGWIN__) + details::my_cygwin_funlockfile(fp); +#elif !defined(__SINGLE_THREAD__) +// _funlockfile(fp); //TO FIX +#endif +#elif defined(__MSDOS__) || (defined(__wasi__) &&!defined(__wasilibc_unmodified_upstream) && !defined(_REENTRANT)) || defined(__AVR__) || defined(_PICOLIBC__) +#else + noexcept_call(funlockfile,fp); +#endif +#endif + } + inline constexpr basic_c_family_io_observer unlocked_handle() const noexcept requires(family==c_family::standard) + { + return {fp}; + } + inline constexpr basic_c_family_io_observer unlocked_handle() const noexcept requires(family==c_family::emulated) + { + return {fp}; + } +}; + +template +inline constexpr basic_c_family_io_observer io_value_handle(basic_c_family_io_observer other) noexcept +{ + return other; +} +#if defined(__AVR__) +template +inline constexpr posix_file_status status(basic_c_family_io_observer ciob) +{ + details::avr_libc_nosup_impl(); +} + +template +inline void io_control(basic_c_family_io_observer h,Args&& ...args) +{ + details::avr_libc_nosup_impl(); +} + +#else + +template +inline constexpr posix_at_entry at(basic_c_family_io_observer other) noexcept +{ + return posix_at_entry{details::my_fileno_impl(other.fp)}; +} + +template +requires requires(basic_posix_io_observer piob) +{ + status(piob); +} +inline constexpr posix_file_status status(basic_c_family_io_observer ciob) +{ + return status(static_cast>(ciob)); +} + +template +requires io_controllable,Args...> +inline decltype(auto) io_control(basic_c_family_io_observer h,Args&& ...args) +{ + return io_control(static_cast>(h),::std::forward(args)...); +} +#endif + +template +inline void flush(basic_c_family_io_observer cfhd) +{ + details::my_c_io_flush_impl(cfhd.fp); +} + +template +inline std::uintmax_t seek(basic_c_family_io_observer cfhd,std::intmax_t offset=0,seekdir s=seekdir::cur) +{ + return details::my_c_io_seek_impl(cfhd.fp,offset,s); +} + +#if __cpp_lib_three_way_comparison >= 201907L + +template +inline constexpr bool operator==(basic_c_family_io_observer a,basic_c_family_io_observer b) noexcept +{ + return a.fp==b.fp; +} + +template +inline constexpr auto operator<=>(basic_c_family_io_observer a,basic_c_family_io_observer b) noexcept +{ + return a.fp<=>b.fp; +} +#endif + + +namespace details +{ +#if defined(__AVR__) +template +inline constexpr bool my_c_is_character_device_impl(FILE*) noexcept +{ + return false; +} +template +inline void my_c_clear_screen_impl(FILE*) +{ + avr_libc_nosup_impl(); +} + +#else +template +inline bool my_c_is_character_device_impl(FILE* fp) noexcept +{ + return posix_is_character_device(my_fileno_impl(fp)); +} + +template +inline void my_c_clear_screen_impl(FILE* fp) +{ + if constexpr(family==c_family::native) + { + if constexpr(c_family::native==c_family::native_unlocked) + { + my_c_clear_screen_impl(fp); + } + else + { + basic_c_family_io_observer ciob{fp}; + io_lock_guard guard{ciob}; + my_c_clear_screen_impl(fp); + } + } + else + { +#if (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) && !defined(__CYGWIN__) + void* handle{my_fp_to_win32_handle_impl(fp)}; + if(!::fast_io::win32::details::win32_is_character_device(handle)) + return; + my_c_io_flush_impl(fp); + ::fast_io::win32::details::win32_clear_screen_main(handle); +#else + int fd{my_fileno_impl(fp)}; + if(!posix_is_character_device(fd)) + return; + my_c_io_flush_impl(fp); + posix_clear_screen_main(fd); +#endif + } +} +#endif +} + +template +inline bool is_character_device(basic_c_family_io_observer ciob) noexcept +{ + return details::my_c_is_character_device_impl(ciob.fp); +} + +template +inline void clear_screen(basic_c_family_io_observer ciob) +{ + details::my_c_clear_screen_impl(ciob.fp); +} +#if !defined(__AVR__) +template +requires requires(basic_c_family_io_observer h) +{ + redirect_handle(static_cast>(h)); +} +inline decltype(auto) redirect_handle(basic_c_family_io_observer h) +{ + return redirect_handle(static_cast>(h)); +} + +template +requires zero_copy_input_stream> +inline decltype(auto) zero_copy_in_handle(basic_c_family_io_observer h) +{ + return zero_copy_in_handle(static_cast>(h)); +} + +template +requires zero_copy_output_stream> +inline decltype(auto) zero_copy_out_handle(basic_c_family_io_observer h) +{ + return zero_copy_out_handle(static_cast>(h)); +} +#endif + +template +struct +#if __has_cpp_attribute(clang::trivially_relocatable) +[[clang::trivially_relocatable]] +#endif +c_family_file_factory +{ + using native_handle_type = FILE*; + FILE* fp{}; + explicit constexpr c_family_file_factory(FILE* fpp) noexcept:fp(fpp){}; + c_family_file_factory(c_family_file_factory const&)=delete; + c_family_file_factory& operator=(c_family_file_factory const&)=delete; + ~c_family_file_factory() + { + if(fp)[[likely]] + { +#if defined(__NEWLIB__) && !defined(__CYGWIN__) + struct _reent ent{}; + noexcept_call(_fclose_r,__builtin_addressof(ent),this->fp); +#else + details::my_fclose_impl(this->fp); +#endif + } + } +}; + +template +class basic_c_family_file:public basic_c_family_io_observer +{ +public: + using char_type = ch_type; + using native_handle_type = FILE*; + constexpr basic_c_family_file() noexcept=default; + template + requires std::same_as> + explicit constexpr basic_c_family_file(native_hd ffp) noexcept:basic_c_family_io_observer{ffp}{} + template + explicit constexpr basic_c_family_file(c_family_file_factory&& other) noexcept:basic_c_family_io_observer{other.fp} + { + other.fp=nullptr; + } + constexpr basic_c_family_file(basic_c_family_io_observer) noexcept=delete; + constexpr basic_c_family_file& operator=(basic_c_family_io_observer) noexcept=delete; + + basic_c_family_file(basic_c_family_file const&)=delete; + basic_c_family_file& operator=(basic_c_family_file const&)=delete; + constexpr basic_c_family_file(decltype(nullptr)) noexcept = delete; + constexpr basic_c_family_file(basic_c_family_file&& other) noexcept:basic_c_family_io_observer{other.fp} + { + other.fp=nullptr; + } + basic_c_family_file& operator=(basic_c_family_file&& other) noexcept + { + if(__builtin_addressof(other)!=this) + return *this; + if(this->fp)[[likely]] + { +#if defined(__NEWLIB__) && !defined(__CYGWIN__) + struct _reent ent{}; + noexcept_call(_fclose_r,__builtin_addressof(ent),this->fp); +#else + details::my_fclose_impl(this->fp); +#endif + } + this->fp=other.fp; + other.fp=nullptr; + return *this; + } + void close() + { + if(this->fp==nullptr)[[unlikely]] + return; +#if defined(__NEWLIB__) && !defined(__CYGWIN__) + struct _reent ent{}; + int ret{noexcept_call(_fclose_r,__builtin_addressof(ent),this->fp)}; + this->fp=nullptr; + if(ret==EOF) + throw_posix_error(ent._errno); +#else + int ret{details::my_fclose_impl(this->fp)}; + this->fp=nullptr; + if(ret==EOF) + throw_posix_error(errno); +#endif + } + ~basic_c_family_file() + { + if(this->fp)[[likely]] + { +#if defined(__NEWLIB__) && !defined(__CYGWIN__) + struct _reent ent{}; + noexcept_call(_fclose_r,__builtin_addressof(ent),this->fp); +#else + details::my_fclose_impl(this->fp); +#endif + } + } +#if !defined(__AVR__) + basic_c_family_file(basic_posix_file&& phd,open_mode om): + basic_c_family_io_observer{::fast_io::details::my_c_file_open_impl(phd.fd,om)} + { + phd.fd=-1; + } +#if (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) || defined(__CYGWIN__) +//windows specific. open posix file from win32 io handle + template + basic_c_family_file(basic_win32_family_file&& win32_handle,open_mode om): + basic_c_family_file(basic_posix_file(::std::move(win32_handle),om),om) + { + } + template + basic_c_family_file(basic_nt_family_file&& nt_handle,open_mode om): + basic_c_family_file(basic_posix_file(::std::move(nt_handle),om),om) + { + } +#endif + basic_c_family_file(native_fs_dirent ent,open_mode om,perms pm=static_cast(436)): + basic_c_family_file(basic_posix_file(ent,om,pm),om) + {} + template<::fast_io::constructible_to_os_c_str T> + basic_c_family_file(T const& file,open_mode om,perms pm=static_cast(436)): + basic_c_family_file(basic_posix_file(file,om,pm),om) + {} + template<::fast_io::constructible_to_os_c_str T> + basic_c_family_file(native_at_entry nate,T const& file,open_mode om,perms pm=static_cast(436)): + basic_c_family_file(basic_posix_file(nate,file,om,pm),om) + {} +#endif + basic_c_family_file(io_temp_t):basic_c_family_io_observer{::fast_io::details::my_c_open_tmp_file()} + {} +}; + +template +using basic_c_io_observer_unlocked = basic_c_family_io_observer; +template +using basic_c_io_observer = basic_c_family_io_observer; + +template +using basic_c_file_unlocked = basic_c_family_file; +template +using basic_c_file = basic_c_family_file; + +using c_io_observer_unlocked=basic_c_io_observer_unlocked; +using c_io_observer=basic_c_io_observer; +using c_file = basic_c_file; +using c_file_unlocked = basic_c_file_unlocked; +using wc_io_observer_unlocked=basic_c_io_observer_unlocked; +using wc_io_observer=basic_c_io_observer; +using wc_file = basic_c_file; +using wc_file_unlocked = basic_c_file_unlocked; +using u8c_io_observer_unlocked=basic_c_io_observer_unlocked; +using u8c_io_observer=basic_c_io_observer; +using u8c_file = basic_c_file; +using u8c_file_unlocked = basic_c_file_unlocked; +using u16c_io_observer_unlocked=basic_c_io_observer_unlocked; +using u16c_io_observer=basic_c_io_observer; +using u16c_file = basic_c_file; +using u16c_file_unlocked = basic_c_file_unlocked; +using u32c_io_observer_unlocked = basic_c_io_observer_unlocked; +using u32c_io_observer=basic_c_io_observer; +using u32c_file = basic_c_file; +using u32c_file_unlocked = basic_c_file_unlocked; + +using c_file_factory = c_family_file_factory; +using c_file_factory_unlocked = c_family_file_factory; + +namespace freestanding +{ + +template +struct is_trivially_relocatable> +{ + inline static constexpr bool value = true; +}; + +template +struct is_zero_default_constructible> +{ + inline static constexpr bool value = true; +}; + +} + +} + +#if (defined(_WIN32)&&!defined(__WINE__)&&!defined(__BIONIC__)) && !defined(__CYGWIN__) +#include"wincrt.h" +#elif defined(__AVR__) || defined(_PICOLIBC__) +#include"avrlibc.h" +#include"macros_general.h" +#else +#if defined(__LLVM_LIBC_TYPES_FILE_H__) +#include"llvm.h" +#elif defined(__UCLIBC__) +#if defined(__STDIO_BUFFERS) +#include"uclibc.h" +#elif defined(FAST_IO_LIBC_CUSTOM_BUFFER_PTRS) +#include"custom.h" +#endif +#elif defined(__MLIBC_O_CLOEXEC) +#include"mlibc.h" +#elif defined(__GLIBC__) +#include"glibc.h" +#elif defined(__wasi__) +#include"musl.h" +#elif defined(__NEED___isoc_va_list) || defined(__musl__) +#include"musl.h" +#elif defined(__serenity__) +#include"serenity.h" +#elif defined(__BSD_VISIBLE) ||defined(__DARWIN_C_LEVEL) \ + || (defined(__NEWLIB__) &&!defined(__CUSTOM_FILE_IO__)) \ + || defined(__BIONIC__) || defined(__MSDOS__) +#include"unix.h" +#elif defined(FAST_IO_LIBC_CUSTOM_BUFFER_PTRS) +#include"custom.h" +#endif + +#if !defined(__MSDOS__) +#include"general.h" +#endif +#include"done.h" +#include"macros_general.h" +#endif + diff --git a/src/fast_io/include/fast_io_legacy_impl/c/llvm.h b/src/fast_io/include/fast_io_legacy_impl/c/llvm.h new file mode 100644 index 0000000..c77ba53 --- /dev/null +++ b/src/fast_io/include/fast_io_legacy_impl/c/llvm.h @@ -0,0 +1,250 @@ +#pragma once +/* +This implementation is an untested guessing implementation since i do not know how to build LLVM libc. + +If you see this does not work, please file an issue on github to cppfastio; +Referenced from +https://github.com/llvm/llvm-project/blob/main/libc/src/__support/CPP/atomic.h +https://github.com/llvm/llvm-project/blob/main/libc/src/__support/threads/linux/futex_word.h +https://github.com/llvm/llvm-project/blob/main/libc/src/__support/File/file.h + +*/ + +namespace fast_io +{ + +namespace details::llvmlibc_hack +{ + +template +struct llvmlibc_atomic +{ +using value_type = T; +static inline constexpr int llvmlibc_atomic_alignment = sizeof(T) > alignof(T) ? sizeof(T) + : alignof(T); + +// We keep the internal value public so that it can be addressable. +// This is useful in places like the Linux futex operations where +// we need pointers to the memory of the atomic values. Load and store +// operations should be performed using the atomic methods however. +alignas(llvmlibc_atomic_alignment) value_type val; +}; + +using FutexWordType = unsigned int; + +struct Mutex { +unsigned char timed; +unsigned char recursive; +unsigned char robust; + +void *owner; +unsigned long long lock_count; + +llvmlibc_atomic futex_word; +}; + +struct +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +File +{ + +using LockFunc = void(File *) noexcept; +using UnlockFunc = void(File *) noexcept; + +using WriteFunc = size_t(File *, void const *, size_t) noexcept; +using ReadFunc = size_t(File *, void *, size_t) noexcept; +using SeekFunc = int(File *, long, int) noexcept; //why seek offset long??? +using CloseFunc = int(File *) noexcept; +using FlushFunc = int(File *) noexcept; + +using ModeFlags = ::std::uint_least32_t; +enum class FileOp : ::std::uint_least8_t { NONE, READ, WRITE, SEEK }; +WriteFunc *platform_write; +ReadFunc *platform_read; +SeekFunc *platform_seek; +CloseFunc *platform_close; +FlushFunc *platform_flush; + +Mutex mutex; + +void *buf; // Pointer to the stream buffer for buffered streams +size_t bufsize; // Size of the buffer pointed to by |buf|. + +// Buffering mode to used to buffer. +int bufmode; + +// If own_buf is true, the |buf| is owned by the stream and will be +// free-ed when close method is called on the stream. +bool own_buf; + +// The mode in which the file was opened. +ModeFlags mode; + +// Current read or write pointer. +size_t pos; + +// Represents the previous operation that was performed. +FileOp prev_op; + +// When the buffer is used as a read buffer, read_limit is the upper limit +// of the index to which the buffer can be read until. +size_t read_limit; + +bool eof; +bool err; + +}; + +inline void* llvm_libc_buffer_begin(FILE* fpp) noexcept +{ + auto fp{reinterpret_cast(fpp)}; + return reinterpret_cast(fp->buf); +} + +inline void* llvm_libc_buffer_curr(FILE* fpp) noexcept +{ + auto fp{reinterpret_cast(fpp)}; + return reinterpret_cast(fp->buf)+fp->pos; +} + +inline void* llvm_libc_ibuffer_end(FILE* fpp) noexcept +{ + auto fp{reinterpret_cast(fpp)}; + return reinterpret_cast(fp->buf)+fp->read_limit; +} + +inline void* llvm_libc_obuffer_end(FILE* fpp) noexcept +{ + auto fp{reinterpret_cast(fpp)}; + return reinterpret_cast(fp->buf)+fp->bufsize; +} + +inline void llvm_libc_set_buffer_curr(FILE* fpp,void* currptr) noexcept +{ + auto fp{reinterpret_cast(fpp)}; + fp->pos=static_cast(reinterpret_cast(currptr)-reinterpret_cast(fp->buf)); +} + +inline bool llvm_libc_underflow(FILE* fpp) noexcept +{ + auto fp{reinterpret_cast(fpp)}; + auto pr{fp->platform_read}; + if(pr==nullptr) + { + return false; + } + fp->read_limit=fp->platform_read(fp,fp->buf,fp->bufsize); + fp->pos=0; + return fp->read_limit; +} + +inline void llvm_libc_overflow(FILE* fpp,char ch) noexcept +{ + auto fp{reinterpret_cast(fpp)}; + auto pr{fp->platform_write}; + if(pr==nullptr) + { + return; + } + fp->platform_write(fp,fp->buf,fp->pos); + fp->pos=0; + if(fp->bufsize) + { + *reinterpret_cast(fp->buf)=ch; + ++fp->pos; + } +} + +} + +template +requires (sizeof(char_type)==1) +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char_type* ibuffer_begin(basic_c_io_observer_unlocked ciob) noexcept +{ + return reinterpret_cast(::fast_io::details::llvmlibc_hack::llvm_libc_buffer_begin(ciob.fp)); +} + +template +requires (sizeof(char_type)==1) +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char_type* obuffer_begin(basic_c_io_observer_unlocked ciob) noexcept +{ + return reinterpret_cast(::fast_io::details::llvmlibc_hack::llvm_libc_buffer_begin(ciob.fp)); +} + +template +requires (sizeof(char_type)==1) +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char_type* ibuffer_curr(basic_c_io_observer_unlocked ciob) noexcept +{ + return reinterpret_cast(::fast_io::details::llvmlibc_hack::llvm_libc_buffer_curr(ciob.fp)); +} + +template +requires (sizeof(char_type)==1) +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char_type* obuffer_curr(basic_c_io_observer_unlocked ciob) noexcept +{ + return reinterpret_cast(::fast_io::details::llvmlibc_hack::llvm_libc_buffer_curr(ciob.fp)); +} + +template +requires (sizeof(char_type)==1) +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char_type* ibuffer_end(basic_c_io_observer_unlocked ciob) noexcept +{ + return reinterpret_cast(::fast_io::details::llvmlibc_hack::llvm_libc_ibuffer_end(ciob.fp)); +} + +template +requires (sizeof(char_type)==1) +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char_type* obuffer_end(basic_c_io_observer_unlocked ciob) noexcept +{ + return reinterpret_cast(::fast_io::details::llvmlibc_hack::llvm_libc_obuffer_end(ciob.fp)); +} + +template +requires (sizeof(char_type)==1) +inline void ibuffer_set_curr(basic_c_io_observer_unlocked ciob,char_type* ptr) noexcept +{ + ::fast_io::details::llvmlibc_hack::llvm_libc_set_buffer_curr(ciob.fp,ptr); +} + +template +requires (sizeof(char_type)==1) +inline void obuffer_set_curr(basic_c_io_observer_unlocked ciob,char_type* ptr) noexcept +{ + ::fast_io::details::llvmlibc_hack::llvm_libc_set_buffer_curr(ciob.fp,ptr); +} + +template +requires (sizeof(char_type)==1) +inline bool ibuffer_underflow(basic_c_io_observer_unlocked ciob) noexcept +{ + return ::fast_io::details::llvmlibc_hack::llvm_libc_underflow(ciob.fp); +} + +template +requires (sizeof(char_type)==1) +inline void obuffer_overflow(basic_c_io_observer_unlocked ciob,char_type ch) noexcept +{ + ::fast_io::details::llvmlibc_hack::llvm_libc_overflow(ciob.fp,static_cast(ch)); +} + +} diff --git a/src/fast_io/include/fast_io_legacy_impl/c/macros_general.h b/src/fast_io/include/fast_io_legacy_impl/c/macros_general.h new file mode 100644 index 0000000..fd43c63 --- /dev/null +++ b/src/fast_io/include/fast_io_legacy_impl/c/macros_general.h @@ -0,0 +1,50 @@ +#pragma once + +namespace fast_io +{ + +inline c_io_observer c_stdin() noexcept +{ + return {stdin}; +} + +inline c_io_observer c_stdout() noexcept +{ + return {stdout}; +} + +inline c_io_observer c_stderr() noexcept +{ + return {stderr}; +} +inline wc_io_observer wc_stdin() noexcept +{ + return {stdin}; +} + +inline wc_io_observer wc_stdout() noexcept +{ + return {stdout}; +} + +inline wc_io_observer wc_stderr() noexcept +{ + return {stderr}; +} + +inline u8c_io_observer u8c_stdin() noexcept +{ + return {stdin}; +} + +inline u8c_io_observer u8c_stdout() noexcept +{ + return {stdout}; +} + +inline u8c_io_observer u8c_stderr() noexcept +{ + return {stderr}; +} + +} diff --git a/src/fast_io/include/fast_io_legacy_impl/c/mlibc.h b/src/fast_io/include/fast_io_legacy_impl/c/mlibc.h new file mode 100644 index 0000000..1982568 --- /dev/null +++ b/src/fast_io/include/fast_io_legacy_impl/c/mlibc.h @@ -0,0 +1,204 @@ +#pragma once + +/* +Referenced from: +https://github.com/managarm/mlibc/blob/master/options/ansi/include/stdio.h +*/ + +namespace fast_io +{ +namespace details::mlibc_hack +{ + +inline constexpr char* hack_ibuffer_begin_impl(FILE* fp) noexcept +{ + return fp->__buffer_ptr; +} + +inline constexpr char* hack_ibuffer_curr_impl(FILE* fp) noexcept +{ + return fp->__buffer_ptr+fp->__offset; +} + +inline constexpr char* hack_ibuffer_end_impl(FILE* fp) noexcept +{ + return fp->__buffer_ptr+fp->__valid_limit; +} + +inline constexpr void hack_ibuffer_set_curr_impl(FILE* fp,char* ptr) noexcept +{ + std::size_t new_size{static_cast(ptr-fp->__buffer_ptr)}; + fp->__offset=fp->__io_offset=new_size; +} + +inline constexpr char* hack_obuffer_begin_impl(FILE* fp) noexcept +{ + return fp->__buffer_ptr; +} + +inline constexpr char* hack_obuffer_curr_impl(FILE* fp) noexcept +{ + return fp->__buffer_ptr+fp->__offset; +} + +inline constexpr char* hack_obuffer_end_impl(FILE* fp) noexcept +{ + if(fp->__buffer_ptr)[[likely]] + return fp->__buffer_ptr+fp->__io_offset; + else + return nullptr; +} + +inline constexpr void hack_obuffer_set_curr_impl(FILE* fp,char* ptr) noexcept +{ + std::size_t new_size{static_cast(ptr-fp->__buffer_ptr)}; + if(fp->__dirty_begin==fp->__io_offset) + { + fp->__dirty_begin=new_size; + fp->__offset=new_size; + } + fp->__io_offset=new_size; + fp->__valid_limit=new_size; + fp->__dirty_end=new_size; +} + +inline void hack_overflow_impl(FILE* fp,char unsigned ch) +{ + if(noexcept_call(putc_unlocked,ch,fp)==EOF) + throw_posix_error(); +} + +inline bool hack_underflow_impl(FILE* fp) +{ + int ch{noexcept_call(getc_unlocked,fp)}; + if(ch==EOF) + { + if(noexcept_call(ferror_unlocked,fp)) + throw_posix_error(); + return false; + } + fp->__offset=fp->__io_offset=0; + return true; +} + +} + +inline constexpr char* obuffer_begin(c_io_observer_unlocked ciob) noexcept +{ + return details::mlibc_hack::hack_obuffer_begin_impl(ciob.fp); +} + +inline constexpr char* obuffer_curr(c_io_observer_unlocked ciob) noexcept +{ + return details::mlibc_hack::hack_obuffer_curr_impl(ciob.fp); +} + +inline constexpr char* obuffer_end(c_io_observer_unlocked ciob) noexcept +{ + return details::mlibc_hack::hack_obuffer_end_impl(ciob.fp); +} + +inline constexpr void obuffer_set_curr(c_io_observer_unlocked ciob,char* ptr) noexcept +{ + details::mlibc_hack::hack_obuffer_set_curr_impl(ciob.fp,ptr); +} + +inline void obuffer_overflow(c_io_observer_unlocked ciob,char ch) +{ + details::mlibc_hack::hack_overflow_impl(ciob.fp,static_cast(ch)); +} + +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char8_t* obuffer_begin(u8c_io_observer_unlocked ciob) noexcept +{ + return reinterpret_cast(details::mlibc_hack::hack_obuffer_begin_impl(ciob.fp)); +} + +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char8_t* obuffer_curr(u8c_io_observer_unlocked ciob) noexcept +{ + return reinterpret_cast(details::mlibc_hack::hack_obuffer_curr_impl(ciob.fp)); +} + +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char8_t* obuffer_end(u8c_io_observer_unlocked ciob) noexcept +{ + return reinterpret_cast(details::mlibc_hack::hack_obuffer_end_impl(ciob.fp)); +} + +inline void obuffer_set_curr(u8c_io_observer_unlocked ciob,char8_t* ptr) noexcept +{ + details::mlibc_hack::hack_obuffer_set_curr_impl(ciob.fp,reinterpret_cast(ptr)); +} + +inline void obuffer_overflow(u8c_io_observer_unlocked ciob,char8_t ch) +{ + details::mlibc_hack::hack_overflow_impl(ciob.fp,static_cast(ch)); +} + + + +inline constexpr char* ibuffer_begin(c_io_observer_unlocked ciob) noexcept +{ + return details::mlibc_hack::hack_ibuffer_begin_impl(ciob.fp); +} + +inline constexpr char* ibuffer_curr(c_io_observer_unlocked ciob) noexcept +{ + return details::mlibc_hack::hack_ibuffer_curr_impl(ciob.fp); +} + +inline constexpr char* ibuffer_end(c_io_observer_unlocked ciob) noexcept +{ + return details::mlibc_hack::hack_ibuffer_end_impl(ciob.fp); +} + +inline constexpr void ibuffer_set_curr(c_io_observer_unlocked ciob,char* ptr) noexcept +{ + details::mlibc_hack::hack_ibuffer_set_curr_impl(ciob.fp,ptr); +} + +inline bool ibuffer_underflow(c_io_observer_unlocked ciob) +{ + return details::mlibc_hack::hack_underflow_impl(ciob.fp); +} + +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char8_t* ibuffer_begin(u8c_io_observer_unlocked ciob) noexcept +{ + return reinterpret_cast(details::mlibc_hack::hack_ibuffer_begin_impl(ciob.fp)); +} +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char8_t* ibuffer_curr(u8c_io_observer_unlocked ciob) noexcept +{ + return reinterpret_cast(details::mlibc_hack::hack_ibuffer_curr_impl(ciob.fp)); +} +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char8_t* ibuffer_end(u8c_io_observer_unlocked ciob) noexcept +{ + return reinterpret_cast(details::mlibc_hack::hack_ibuffer_end_impl(ciob.fp)); +} + +inline bool ibuffer_underflow(u8c_io_observer_unlocked ciob) +{ + return details::mlibc_hack::hack_underflow_impl(ciob.fp); +} + +inline void ibuffer_set_curr(u8c_io_observer_unlocked ciob,char8_t* ptr) noexcept +{ + details::mlibc_hack::hack_ibuffer_set_curr_impl(ciob.fp,reinterpret_cast(ptr)); +} + +} diff --git a/src/fast_io/include/fast_io_legacy_impl/c/msvcrt_lock.h b/src/fast_io/include/fast_io_legacy_impl/c/msvcrt_lock.h new file mode 100644 index 0000000..f74dce9 --- /dev/null +++ b/src/fast_io/include/fast_io_legacy_impl/c/msvcrt_lock.h @@ -0,0 +1,131 @@ +#pragma once + +namespace fast_io::win32 +{ + +/* +Referenced from ReactOS +https://doxygen.reactos.org/d2/d1b/sdk_2lib_2crt_2stdio_2file_8c_source.html +Referenced from MinGW-w64 CRT +https://github.com/Alexpux/mingw-w64/blob/d0d7f784833bbb0b2d279310ddc6afb52fe47a46/mingw-w64-crt/stdio/mingw_lock.c#L36 +*/ +#if (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if __has_cpp_attribute(__gnu__::__cdecl__) +[[__gnu__::__cdecl__]] +#endif +extern void +#if !__has_cpp_attribute(__gnu__::__cdecl__) && defined(_MSC_VER) +__cdecl +#endif +_lock(int) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("_lock") +#else +__asm__("__lock") +#endif +#else +__asm__("_lock") +#endif +#endif +; + +#if (__has_cpp_attribute(__gnu__::__dllimport__)&&!defined(__WINE__)) +[[__gnu__::__dllimport__]] +#endif +#if __has_cpp_attribute(__gnu__::__cdecl__) +[[__gnu__::__cdecl__]] +#endif +extern void +#if !__has_cpp_attribute(__gnu__::__cdecl__) && defined(_MSC_VER) +__cdecl +#endif +_unlock(int) noexcept +#if defined(__clang__) || defined(__GNUC__) +#if SIZE_MAX<=UINT_LEAST32_MAX &&(defined(__x86__) || defined(_M_IX86) || defined(__i386__)) +#if !defined(__clang__) +__asm__("_unlock") +#else +__asm__("__unlock") +#endif +#else +__asm__("_unlock") +#endif +#endif +; + + +#if __has_cpp_attribute(__gnu__::__const__) +[[__gnu__::__const__]] +#endif +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline FILE* wincrt_iob_func() noexcept +{ +#if defined(__iob_func) + return __iob_func(); +#else +#if (!defined(__MINGW32__) || __has_include(<_mingw_stat64.h>)) + return noexcept_call(__iob_func); +#else + return _iob; +#endif +#endif +} + +inline constexpr std::size_t msvcrt_iob_entries +{ +#if defined(_IOB_ENTRIES) +_IOB_ENTRIES +#else +20 +#endif +}; + +inline void my_msvcrt_lock_file(FILE* fp) noexcept +{ + auto iob{wincrt_iob_func()}; + std::size_t entry{static_cast(fp-iob)}; + if(entry(16+entry)); + fp->_flag |= 0x8000; //_IOLOCKED We set _IOLOCKED to indicate we locked the stream + } + else + EnterCriticalSection(fp+1); +} + +inline void my_msvcrt_unlock_file(FILE* fp) noexcept +{ + auto iob{wincrt_iob_func()}; + std::size_t entry{static_cast(fp-iob)}; + if(entry_flag &= ~0x8000; + _unlock(static_cast(16+entry)); + } + else + LeaveCriticalSection(fp+1); +} + +/* +Referenced from ReactOS +https://doxygen.reactos.org/d2/d1b/sdk_2lib_2crt_2stdio_2file_8c_source.html +Line 3075 +MSVCRT +https://github.com/changloong/msvcrt/blob/master/stdio/fwrite.c +*/ + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_legacy_impl/c/musl.h b/src/fast_io/include/fast_io_legacy_impl/c/musl.h new file mode 100644 index 0000000..aa08dcb --- /dev/null +++ b/src/fast_io/include/fast_io_legacy_impl/c/musl.h @@ -0,0 +1,280 @@ +#pragma once + + +namespace fast_io +{ + +namespace details::fp_hack +{ + + +#ifdef __wasi__ + +struct fp_model { + unsigned flags; + unsigned char *rpos, *rend; + int (*close)(FILE *); + unsigned char *wend, *wpos; +#ifdef __wasilibc_unmodified_upstream // WASI doesn't need backwards-compatibility fields. + unsigned char *mustbezero_1; +#endif + unsigned char *wbase; + size_t (*read)(FILE *, unsigned char *, size_t); + size_t (*write)(FILE *, const unsigned char *, size_t); + off_t (*seek)(FILE *, off_t, int); + unsigned char *buf; + size_t buf_size; + FILE *prev, *next; + int fd; +#ifdef __wasilibc_unmodified_upstream // WASI has no popen + int pipe_pid; +#endif +#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT) + long lockcount; +#endif + int mode; +#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT) + volatile int lock; +#endif + int lbf; + void *cookie; + off_t off; + char *getln_buf; +#ifdef __wasilibc_unmodified_upstream // WASI doesn't need backwards-compatibility fields. + void *mustbezero_2; +#endif + unsigned char *shend; + off_t shlim, shcnt; +#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT) + FILE *prev_locked, *next_locked; +#endif + void *locale; +}; + +#else +//https://github.com/EOSIO/musl/blob/master/src/internal/stdio_impl.h +struct fp_model +{ + unsigned flags; + unsigned char *rpos, *rend; + int (*close)(FILE *); + unsigned char *wend, *wpos; + unsigned char *mustbezero_1; + unsigned char *wbase; + size_t (*read)(FILE *, unsigned char *, size_t); + size_t (*write)(FILE *, const unsigned char *, size_t); + off_t (*seek)(FILE *, off_t, int); + unsigned char *buf; + size_t buf_size; + FILE *prev, *next; + int fd; + int pipe_pid; + long lockcount; + short dummy3; + signed char mode; + signed char lbf; + volatile int lock; + volatile int waiters; + void *cookie; + off_t off; + char *getln_buf; + void *mustbezero_2; + unsigned char *shend; + off_t shlim, shcnt; + FILE *prev_locked, *next_locked; + void *locale; +}; +#endif + +template +requires (position<6) +constexpr std::size_t get_offset() noexcept +{ + if constexpr(position==0) + return __builtin_offsetof(fp_model,buf); + else if constexpr(position==1) + return __builtin_offsetof(fp_model,rpos); + else if constexpr(position==2) + return __builtin_offsetof(fp_model,rend); + else if constexpr(position==3) + return __builtin_offsetof(fp_model,wbase); + else if constexpr(position==4) + return __builtin_offsetof(fp_model,wpos); + else if constexpr(position==5) + return __builtin_offsetof(fp_model,wend); +} + +template +inline char_type* hack_fp_ptr(FILE* fp) noexcept +{ + constexpr std::size_t offset{get_offset()}; + char_type* value; + __builtin_memcpy(__builtin_addressof(value),reinterpret_cast(fp)+offset,sizeof(char_type*)); + return value; +} + +template +inline void hack_fp_set_ptr(FILE* fp,char_type* ptr) noexcept +{ + constexpr std::size_t offset(get_offset()); + __builtin_memcpy(reinterpret_cast(fp)+offset,__builtin_addressof(ptr),sizeof(char_type*)); +} + +} + +inline char* ibuffer_begin(c_io_observer_unlocked cio) noexcept +{ + return details::fp_hack::hack_fp_ptr(cio.fp); +} + +inline char* ibuffer_curr(c_io_observer_unlocked cio) noexcept +{ + return details::fp_hack::hack_fp_ptr(cio.fp); +} + +inline char* ibuffer_end(c_io_observer_unlocked cio) noexcept +{ + return details::fp_hack::hack_fp_ptr(cio.fp); +} + +inline void ibuffer_set_curr(c_io_observer_unlocked cio,char* ptr) noexcept +{ + details::fp_hack::hack_fp_set_ptr<1>(cio.fp,ptr); +} + +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char8_t* ibuffer_begin(u8c_io_observer_unlocked cio) noexcept +{ + return details::fp_hack::hack_fp_ptr(cio.fp); +} + +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char8_t* ibuffer_curr(u8c_io_observer_unlocked cio) noexcept +{ + return details::fp_hack::hack_fp_ptr(cio.fp); +} + +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char8_t* ibuffer_end(u8c_io_observer_unlocked cio) noexcept +{ + return details::fp_hack::hack_fp_ptr(cio.fp); +} + +inline void ibuffer_set_curr(u8c_io_observer_unlocked cio, +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +char8_t* ptr) noexcept +{ + details::fp_hack::hack_fp_set_ptr<1>(cio.fp,ptr); +} + + + + +namespace details::fp_hack +{ +extern int libc_uflow (FILE *) noexcept __asm__("__uflow"); + +inline bool musl_fp_underflow_impl(FILE* fp) +{ + if(fp==stdin) + { + ::fast_io::noexcept_call(fflush,stdout); + } + bool eof{libc_uflow(fp)!=EOF}; + if(!eof&&ferror_unlocked(fp)) + throw_posix_error(); + hack_fp_set_ptr<1>(fp,hack_fp_ptr(fp)); + return eof; +} + +} + +inline bool ibuffer_underflow(c_io_observer_unlocked cio) +{ + return details::fp_hack::musl_fp_underflow_impl(cio.fp); +} + +inline bool ibuffer_underflow(u8c_io_observer_unlocked cio) +{ + return details::fp_hack::musl_fp_underflow_impl(cio.fp); +} + +inline char* obuffer_begin(c_io_observer_unlocked cio) noexcept +{ + return details::fp_hack::hack_fp_ptr(cio.fp); +} + +inline char* obuffer_curr(c_io_observer_unlocked cio) noexcept +{ + return details::fp_hack::hack_fp_ptr(cio.fp); +} + +inline char* obuffer_end(c_io_observer_unlocked cio) noexcept +{ + return details::fp_hack::hack_fp_ptr(cio.fp); +} + +inline void obuffer_set_curr(c_io_observer_unlocked cio,char* ptr) noexcept +{ + details::fp_hack::hack_fp_set_ptr<4>(cio.fp,ptr); +} + +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char8_t* obuffer_begin(u8c_io_observer_unlocked cio) noexcept +{ + return details::fp_hack::hack_fp_ptr(cio.fp); +} + +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char8_t* obuffer_curr(u8c_io_observer_unlocked cio) noexcept +{ + return details::fp_hack::hack_fp_ptr(cio.fp); +} + +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char8_t* obuffer_end(u8c_io_observer_unlocked cio) noexcept +{ + return details::fp_hack::hack_fp_ptr(cio.fp); +} + +inline void obuffer_set_curr(u8c_io_observer_unlocked cio, +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +char8_t* ptr) noexcept +{ + details::fp_hack::hack_fp_set_ptr<4>(cio.fp,ptr); +} + +namespace details +{ +extern int libc_overflow(_IO_FILE *, int) noexcept __asm__("__overflow"); +} + +inline void obuffer_overflow(c_io_observer_unlocked cio,char ch) +{ + if(details::libc_overflow(cio.fp,static_cast(static_cast(ch)))==EOF)[[unlikely]] + throw_posix_error(); +} + +inline void obuffer_overflow(u8c_io_observer_unlocked cio,char8_t ch) +{ + if(details::libc_overflow(cio.fp,static_cast(static_cast(ch)))==EOF)[[unlikely]] + throw_posix_error(); +} + +} diff --git a/src/fast_io/include/fast_io_legacy_impl/c/serenity.h b/src/fast_io/include/fast_io_legacy_impl/c/serenity.h new file mode 100644 index 0000000..afdd415 --- /dev/null +++ b/src/fast_io/include/fast_io_legacy_impl/c/serenity.h @@ -0,0 +1,262 @@ +#pragma once + +namespace fast_io +{ + +namespace details +{ +/* +Referenced from https://github.com/SerenityOS/serenity/blob/master/Userland/Libraries/LibC/stdio.cpp + +*/ +struct +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +serenity_file_buffer_model +{ + std::uint_least8_t* m_data{}; + std::size_t m_capacity{BUFSIZ}; + std::size_t m_begin{}; + std::size_t m_end{}; + int m_mode{-1}; + std::uint_least8_t m_unget_buffer{}; + bool m_ungotten:1 {}; + bool m_data_is_malloced:1 {}; + bool m_empty: 1{true}; +}; + +struct +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +serenity_file_model +{ + int m_fd{-1}; + int m_mode{}; + std::uint_least8_t m_flags{}; + int m_error{}; + bool m_eof{}; + pid_t m_popen_child{-1}; + serenity_file_buffer_model m_buffer; + __pthread_mutex_t m_mutex; +}; + +inline char* serenity_obuffer_begin(serenity_file_model* +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +fp) noexcept +{ + return reinterpret_cast(fp->m_buffer.m_data); +} + +inline char* serenity_obuffer_curr(serenity_file_model* +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +fp) noexcept +{ + return reinterpret_cast(fp->m_buffer.m_data)+fp->m_buffer.m_begin; +} + +inline char* serenity_obuffer_end(serenity_file_model* +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +fp) noexcept +{ + return reinterpret_cast(fp->m_buffer.m_data)+fp->m_buffer.m_end; +} + +inline void serenity_obuffer_set_curr(serenity_file_model* +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +fp,char * ptr) noexcept +{ + fp->m_buffer.m_begin=static_cast(ptr-reinterpret_cast(fp->m_buffer.m_data)); +} + +inline void serenity_obuffer_overflow(serenity_file_model* +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +fp,char ch) +{ + using file_ptr_may_alias +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif + = FILE*; + int ret{noexcept_call(::fputc,ch,reinterpret_cast(fp))}; + if(ret==EOF) + throw_posix_error(); +} + + +inline char* serenity_ibuffer_begin(serenity_file_model* +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +fp) noexcept +{ + return reinterpret_cast(fp->m_buffer.m_data); +} + +inline char* serenity_ibuffer_curr(serenity_file_model* +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +fp) noexcept +{ + return reinterpret_cast(fp->m_buffer.m_data)+fp->m_buffer.m_begin; +} + +inline char* serenity_ibuffer_end(serenity_file_model* +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +fp) noexcept +{ + return reinterpret_cast(fp->m_buffer.m_data)+fp->m_buffer.m_end; +} + +inline void serenity_ibuffer_set_curr(serenity_file_model* +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +fp,char* ptr) noexcept +{ + fp->m_buffer.m_begin=static_cast(ptr-reinterpret_cast(fp->m_buffer.m_data)); +} + +inline bool serenity_ibuffer_underflow(serenity_file_model* +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +fp) +{ + fp->m_buffer.m_begin=fp->m_buffer.m_end; + using file_ptr_may_alias +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif + = FILE*; + int c{noexcept_call(fgetc,reinterpret_cast(fp))}; + if(c==EOF) + { + if(fp->m_error) + throw_posix_error(); + return false; + } + fp->m_buffer.m_begin=0; + return true; +} + +} + +template +requires (sizeof(char_type)==1) +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char_type* ibuffer_begin(basic_c_io_observer_unlocked bciob) noexcept +{ + return ::fast_io::details::serenity_ibuffer_begin(reinterpret_cast<::fast_io::details::serenity_file_model*>(bciob.fp)); +} + +template +requires (sizeof(char_type)==1) +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char_type* ibuffer_curr(basic_c_io_observer_unlocked bciob) noexcept +{ + return ::fast_io::details::serenity_ibuffer_curr(reinterpret_cast<::fast_io::details::serenity_file_model*>(bciob.fp)); +} + +template +requires (sizeof(char_type)==1) +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char_type* ibuffer_end(basic_c_io_observer_unlocked bciob) noexcept +{ + return ::fast_io::details::serenity_ibuffer_end(reinterpret_cast<::fast_io::details::serenity_file_model*>(bciob.fp)); +} + +template +requires (sizeof(char_type)==1) +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline void ibuffer_set_curr(basic_c_io_observer_unlocked bciob,char_type* +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +ptr +) noexcept +{ + ::fast_io::details::serenity_ibuffer_set_curr(reinterpret_cast<::fast_io::details::serenity_file_model*>(bciob.fp),reinterpret_cast(ptr)); +} + +template +inline bool ibuffer_underflow(basic_c_io_observer_unlocked bciob) noexcept +{ + return ::fast_io::details::serenity_ibuffer_underflow(reinterpret_cast<::fast_io::details::serenity_file_model*>(bciob.fp)); +} + +template +requires (sizeof(char_type)==1) +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char_type* obuffer_begin(basic_c_io_observer_unlocked bciob) noexcept +{ + return ::fast_io::details::serenity_obuffer_begin(reinterpret_cast<::fast_io::details::serenity_file_model*>(bciob.fp)); +} + +template +requires (sizeof(char_type)==1) +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char_type* obuffer_curr(basic_c_io_observer_unlocked bciob) noexcept +{ + return ::fast_io::details::serenity_obuffer_curr(reinterpret_cast<::fast_io::details::serenity_file_model*>(bciob.fp)); +} + +template +requires (sizeof(char_type)==1) +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char_type* obuffer_end(basic_c_io_observer_unlocked bciob) noexcept +{ + return ::fast_io::details::serenity_obuffer_end(reinterpret_cast<::fast_io::details::serenity_file_model*>(bciob.fp)); +} + +template +requires (sizeof(char_type)==1) +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline void obuffer_set_curr(basic_c_io_observer_unlocked bciob,char_type* +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +ptr +) noexcept +{ + ::fast_io::details::serenity_obuffer_set_curr(reinterpret_cast<::fast_io::details::serenity_file_model*>(bciob.fp),reinterpret_cast(ptr)); +} + +template +requires (sizeof(char_type)==1) +inline void obuffer_overflow(basic_c_io_observer_unlocked bciob,char_type ch) noexcept +{ + return ::fast_io::details::serenity_obuffer_overflow(reinterpret_cast<::fast_io::details::serenity_file_model*>(bciob.fp),ch); +} + +} diff --git a/src/fast_io/include/fast_io_legacy_impl/c/uclibc.h b/src/fast_io/include/fast_io_legacy_impl/c/uclibc.h new file mode 100644 index 0000000..039725e --- /dev/null +++ b/src/fast_io/include/fast_io_legacy_impl/c/uclibc.h @@ -0,0 +1,226 @@ +#pragma once + +/* Referenced from + +https://github.com/wbx-github/uclibc-ng/blob/master/libc/sysdeps/linux/common/bits/uClibc_stdio.h + +*/ + +#if 0 +#if defined __UCLIBC_HAS_THREADS__ && !defined __UCLIBC_IO_MUTEX +/* keep this in sync with uClibc_mutex.h */ +# ifdef __USE_STDIO_FUTEXES__ +# include +# define __UCLIBC_IO_MUTEX(M) _IO_lock_t M +# else +# include +# define __UCLIBC_IO_MUTEX(M) pthread_mutex_t M +# endif /* __UCLIBC_HAS_THREADS_NATIVE__ */ +#endif + +struct __STDIO_FILE_STRUCT { + unsigned short __modeflags; + /* There could be a hole here, but modeflags is used most.*/ +#ifdef __UCLIBC_HAS_WCHAR__ + unsigned char __ungot_width[2]; /* 0: current (building) char; 1: scanf */ + /* Move the following futher down to avoid problems with getc/putc + * macros breaking shared apps when wchar config support is changed. */ + /* wchar_t ungot[2]; */ +#else /* __UCLIBC_HAS_WCHAR__ */ + unsigned char __ungot[2]; +#endif /* __UCLIBC_HAS_WCHAR__ */ + int __filedes; +#ifdef __STDIO_BUFFERS + unsigned char *__bufstart; /* pointer to buffer */ + unsigned char *__bufend; /* pointer to 1 past end of buffer */ + unsigned char *__bufpos; + unsigned char *__bufread; /* pointer to 1 past last buffered read char */ + +#ifdef __STDIO_GETC_MACRO + unsigned char *__bufgetc_u; /* 1 past last readable by getc_unlocked */ +#endif /* __STDIO_GETC_MACRO */ +#ifdef __STDIO_PUTC_MACRO + unsigned char *__bufputc_u; /* 1 past last writeable by putc_unlocked */ +#endif /* __STDIO_PUTC_MACRO */ + +#endif /* __STDIO_BUFFERS */ + +#ifdef __STDIO_HAS_OPENLIST + struct __STDIO_FILE_STRUCT *__nextopen; +#endif +#ifdef __UCLIBC_HAS_WCHAR__ + wchar_t __ungot[2]; +#endif +#ifdef __STDIO_MBSTATE + __mbstate_t __state; +#endif +#ifdef __UCLIBC_HAS_XLOCALE__ + void *__unused; /* Placeholder for codeset binding. */ +#endif +#ifdef __UCLIBC_HAS_THREADS__ + int __user_locking; + __UCLIBC_IO_MUTEX(__lock); +#endif +/* Everything after this is unimplemented... and may be trashed. */ +#if __STDIO_BUILTIN_BUF_SIZE > 0 + unsigned char __builtinbuf[__STDIO_BUILTIN_BUF_SIZE]; +#endif /* __STDIO_BUILTIN_BUF_SIZE > 0 */ +}; +#endif + +namespace fast_io +{ + +namespace details +{ +extern int uclibc_fgetc_unlocked(FILE*) noexcept __asm__("__fgetc_unlocked"); + +extern int uclibc_fputc_unlocked(int,FILE*) noexcept __asm__("__fputc_unlocked"); + + +inline bool uclibc_underflow_impl(FILE* fp) +{ + bool eof{uclibc_fgetc_unlocked(fp)==EOF}; + if(eof&&((fp->__modeflags&__FLAG_ERROR)==__FLAG_ERROR)) + throw_posix_error(); + fp->__bufpos=fp->__bufstart; + return !eof; +} + +inline void uclibc_overflow_impl(FILE* fp,char unsigned ch) +{ + if(uclibc_fputc_unlocked(static_cast(ch),fp)==EOF) + throw_posix_error(); +} + +inline void uclibc_set_curr_ptr_impl(FILE* fp,char unsigned* ptr) noexcept +{ + fp->__modeflags|=__FLAG_WRITING; + fp->__bufpos=reinterpret_cast(ptr); +} + +} + +inline char* ibuffer_begin(c_io_observer_unlocked ciob) noexcept +{ + return reinterpret_cast(ciob.fp->__bufstart); +} + +inline char* ibuffer_curr(c_io_observer_unlocked ciob) noexcept +{ + return reinterpret_cast(ciob.fp->__bufpos); +} + +inline char* ibuffer_end(c_io_observer_unlocked ciob) noexcept +{ + return reinterpret_cast(ciob.fp->__bufread); +} + +inline void ibuffer_set_curr(c_io_observer_unlocked ciob,char* ptr) noexcept +{ + ciob.fp->__bufpos=reinterpret_cast(ptr); +} + +inline bool ibuffer_underflow(c_io_observer_unlocked ciob) +{ + return details::uclibc_underflow_impl(ciob.fp); +} + + +inline char* obuffer_begin(c_io_observer_unlocked ciob) noexcept +{ + return reinterpret_cast(ciob.fp->__bufstart); +} + +inline char* obuffer_curr(c_io_observer_unlocked ciob) noexcept +{ + return reinterpret_cast(ciob.fp->__bufpos); +} + +inline char* obuffer_end(c_io_observer_unlocked ciob) noexcept +{ + return reinterpret_cast(ciob.fp->__bufend); +} + +inline void obuffer_set_curr(c_io_observer_unlocked ciob,char* ptr) noexcept +{ + details::uclibc_set_curr_ptr_impl(ciob.fp,reinterpret_cast(ptr)); +} + +inline void obuffer_overflow(c_io_observer_unlocked ciob,char ch) +{ + details::uclibc_overflow_impl(ciob.fp,static_cast(ch)); +} + +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char8_t* ibuffer_begin(u8c_io_observer_unlocked ciob) noexcept +{ + return reinterpret_cast(ciob.fp->__bufstart); +} + +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char8_t* ibuffer_curr(u8c_io_observer_unlocked ciob) noexcept +{ + return reinterpret_cast(ciob.fp->__bufpos); +} + +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char8_t* ibuffer_end(u8c_io_observer_unlocked ciob) noexcept +{ + return reinterpret_cast(ciob.fp->__bufread); +} + +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline void ibuffer_set_curr(u8c_io_observer_unlocked ciob,char8_t* ptr) noexcept +{ + ciob.fp->__bufpos=reinterpret_cast(ptr); +} + +inline bool ibuffer_underflow(u8c_io_observer_unlocked ciob) +{ + return details::uclibc_underflow_impl(ciob.fp); +} + +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char8_t* obuffer_begin(u8c_io_observer_unlocked ciob) noexcept +{ + return reinterpret_cast(ciob.fp->__bufstart); +} + +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char8_t* obuffer_curr(u8c_io_observer_unlocked ciob) noexcept +{ + return reinterpret_cast(ciob.fp->__bufpos); +} + +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char8_t* obuffer_end(u8c_io_observer_unlocked ciob) noexcept +{ + return reinterpret_cast(ciob.fp->__bufend); +} + +inline void obuffer_set_curr(u8c_io_observer_unlocked ciob,char8_t* ptr) noexcept +{ + details::uclibc_set_curr_ptr_impl(ciob.fp,reinterpret_cast(ptr)); +} + +inline void obuffer_overflow(u8c_io_observer_unlocked ciob,char8_t ch) +{ + details::uclibc_overflow_impl(ciob.fp,static_cast(ch)); +} + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_legacy_impl/c/unix.h b/src/fast_io/include/fast_io_legacy_impl/c/unix.h new file mode 100644 index 0000000..434712c --- /dev/null +++ b/src/fast_io/include/fast_io_legacy_impl/c/unix.h @@ -0,0 +1,332 @@ +#pragma once +/* +newlib and many other libcs (including MSVCRT and UCRT windows)'s FILE is very similar to BSD. Maybe they all come from BSD? + +Anyway. All FILE implementations are trash tbh. +*/ + + +namespace fast_io +{ + +namespace details +{ + +#if defined(__BIONIC__) +struct +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +sbuf { + unsigned char *_base; + int _size; +}; + +struct +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +sFILE { + unsigned char *_p; /* current position in (some) buffer */ + int _r; /* read space left for getc() */ + int _w; /* write space left for putc() */ + short _flag; /* flags, below; this FILE is free if 0 */ + short _file; /* fileno, if Unix descriptor, else -1 */ + struct sbuf _bf; /* the buffer (at least 1 byte, if !NULL) */ + int _lbfsize; /* 0 or -_bf._size, for inline putc */ + + /* operations */ + void *_cookie; /* cookie passed to io functions */ + int (*_close)(void *); + int (*_read)(void *, char *, int); + fpos_t (*_seek)(void *, fpos_t, int); + int (*_write)(void *, const char *, int); + + /* extension data, to avoid further ABI breakage */ + struct sbuf _ext; + /* data for long sequences of ungetc() */ + unsigned char *_up; /* saved _p when _p is doing ungetc data */ + int _ur; /* saved _r when _r is counting ungetc data */ + + /* tricks to meet minimum requirements even when malloc() fails */ + unsigned char _ubuf[3]; /* guarantee an ungetc() buffer */ + unsigned char _nbuf[1]; /* guarantee a getc() buffer */ + + /* separate buffer for fgetln() when line crosses buffer boundary */ + struct sbuf _lb; /* buffer for fgetln() */ + + /* Unix stdio files get aligned to block boundaries on fseek() */ + int _blksize; /* stat.st_blksize (may be != _bf._size) */ + fpos_t _offset; /* current lseek offset */ +}; + +#endif + +template +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline T* bsd_get_buffer_ptr_impl(FILE* __restrict fpp) noexcept +{ + static_assert(num<4); +#if defined(__MSDOS__) + FILE* fp{fpp}; + if constexpr(num==0) + return reinterpret_cast(fp->_base); + else if constexpr(num==1) + return reinterpret_cast(fp->_ptr); + else + return reinterpret_cast(fp->_ptr+fp->_cnt); +#else +#if defined(__BIONIC__) + sFILE* fp{reinterpret_cast(fpp)}; +#else + FILE* fp{fpp}; +#endif + if constexpr(num==0) + return reinterpret_cast(fp->_bf._base); + else if constexpr(num==1) + return reinterpret_cast(fp->_p); + else if constexpr(num==2) + return reinterpret_cast(fp->_p+fp->_w); + else + return reinterpret_cast(fp->_p+fp->_r); +#endif +} + + +template +inline void bsd_set_buffer_curr_ptr_impl(FILE* __restrict fpp, +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +T* ptr) noexcept +{ +#if defined(__MSDOS__) + FILE* fp{fpp}; + if constexpr(w) //set dirty for output + fp->_flag|=0x010000; + fp->_cnt-=static_cast(reinterpret_cast(ptr)-fp->_ptr); + fp->_ptr=reinterpret_cast(ptr); +#else +#if defined(__BIONIC__) + sFILE* fp{reinterpret_cast(fpp)}; +#else + FILE* fp{fpp}; +#endif + if constexpr(w) + { + fp->_w-=static_cast(reinterpret_cast(ptr)-fp->_p); + fp->_p=reinterpret_cast(ptr); + } + else + { + fp->_r-=static_cast(reinterpret_cast(ptr)-fp->_p); + fp->_p=reinterpret_cast(ptr); + } +#endif +} + +#if defined(__BSD_VISIBLE) ||defined(__DARWIN_C_LEVEL) +extern int bsd_srget(FILE *) noexcept __asm__("__srget"); +#elif defined(__MSDOS__) +extern int _filbuf(FILE *) noexcept __asm__("__filbuf"); +extern int _flsbuf(int, FILE*) noexcept __asm__("__flsbuf"); +#endif + +inline bool bsd_underflow_impl(FILE* __restrict fp) +{ +#if defined(__NEWLIB__) +//untested +#if defined(__CYGWIN__) + bool eof{fgetc(fp)==EOF}; + if(eof&&((fp->_flags & __SERR)!=0))[[unlikely]] + throw_posix_error(); + ++fp->_r; + --fp->_p; + return !eof; +#else + struct _reent rent{}; + bool eof{__sgetc_r(__builtin_addressof(rent),fp)!=EOF}; + if(!eof&&((fp->_flags & __SERR)!=0))[[unlikely]] + throw_posix_error(); + ++fp->_r; + --fp->_p; + return eof; +#endif +#elif defined(__BIONIC__) + bool eof{getc_unlocked(fp)!=EOF}; + if(!eof&&ferror_unlocked(fp))[[unlikely]] + throw_posix_error(); + sFILE* fpp{reinterpret_cast(fp)}; + ++fpp->_r; + --fpp->_p; + return eof; +#else + bool eof{ +#if defined(__DARWIN_C_LEVEL) +#if __DARWIN_C_LEVEL >= 199506L + ::fast_io::noexcept_call(::__srget,fp) +#else + ::fast_io::noexcept_call(::fgetc,fp) +#endif +#else +bsd_srget(fp) +#endif +!=EOF}; + if(!eof&&ferror_unlocked(fp))[[unlikely]] + throw_posix_error(); + ++fp->_r; + --fp->_p; + return eof; +#endif +} + +inline void bsd_overflow(FILE* __restrict fp,char unsigned ch) +{ +#if defined(__MSDOS__) + fp->_flag|=0x010000; + if(_flsbuf(static_cast(static_cast(ch)),fp)==EOF)[[unlikely]] + throw_posix_error(); +#elif defined(__NEWLIB__) + struct _reent rent; + if(__sputc_r(&rent,static_cast(static_cast(ch)),fp)==EOF)[[unlikely]] + throw_posix_error(rent._errno); +#elif defined(__BIONIC__) + if(putc_unlocked(static_cast(static_cast(ch)),fp)==EOF)[[unlikely]] + throw_posix_error(); +#else + if(__sputc(static_cast(static_cast(ch)),fp)==EOF)[[unlikely]] + throw_posix_error(); +#endif +} + +} + +inline char* obuffer_begin(c_io_observer_unlocked cio) noexcept +{ + return details::bsd_get_buffer_ptr_impl(cio.fp); +} + +inline char* obuffer_curr(c_io_observer_unlocked cio) noexcept +{ + return details::bsd_get_buffer_ptr_impl(cio.fp); +} + +inline char* obuffer_end(c_io_observer_unlocked cio) noexcept +{ + return details::bsd_get_buffer_ptr_impl(cio.fp); +} + +inline void obuffer_set_curr(c_io_observer_unlocked cio,char* ptr) noexcept +{ + details::bsd_set_buffer_curr_ptr_impl(cio.fp,ptr); +} + +inline void obuffer_overflow(c_io_observer_unlocked cio,char ch) +{ + details::bsd_overflow(cio.fp,static_cast(ch)); +} + +inline char* ibuffer_begin(c_io_observer_unlocked cio) noexcept +{ + return details::bsd_get_buffer_ptr_impl(cio.fp); +} + +inline char* ibuffer_curr(c_io_observer_unlocked cio) noexcept +{ + return details::bsd_get_buffer_ptr_impl(cio.fp); +} + +inline char* ibuffer_end(c_io_observer_unlocked cio) noexcept +{ + return details::bsd_get_buffer_ptr_impl(cio.fp); +} + +inline void ibuffer_set_curr(c_io_observer_unlocked cio,char* __restrict ptr) noexcept +{ + details::bsd_set_buffer_curr_ptr_impl(cio.fp,ptr); +} + +inline bool ibuffer_underflow(c_io_observer_unlocked cio) +{ + return details::bsd_underflow_impl(cio.fp); +} + +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char8_t* obuffer_begin(u8c_io_observer_unlocked cio) noexcept +{ + return details::bsd_get_buffer_ptr_impl(cio.fp); +} + +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char8_t* obuffer_curr(u8c_io_observer_unlocked cio) noexcept +{ + return details::bsd_get_buffer_ptr_impl(cio.fp); +} + +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char8_t* obuffer_end(u8c_io_observer_unlocked cio) noexcept +{ + return details::bsd_get_buffer_ptr_impl(cio.fp); +} + +inline void obuffer_set_curr(u8c_io_observer_unlocked cio, +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +char8_t* __restrict ptr) noexcept +{ + details::bsd_set_buffer_curr_ptr_impl(cio.fp,ptr); +} + +inline void obuffer_overflow(u8c_io_observer_unlocked cio,char8_t ch) +{ + details::bsd_overflow(cio.fp,static_cast(ch)); +} + +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char8_t* ibuffer_begin(u8c_io_observer_unlocked cio) noexcept +{ + return details::bsd_get_buffer_ptr_impl(cio.fp); +} + +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char8_t* ibuffer_curr(u8c_io_observer_unlocked cio) noexcept +{ + return details::bsd_get_buffer_ptr_impl(cio.fp); +} + +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char8_t* ibuffer_end(u8c_io_observer_unlocked cio) noexcept +{ + return details::bsd_get_buffer_ptr_impl(cio.fp); +} + +inline void ibuffer_set_curr(u8c_io_observer_unlocked cio, +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +char8_t* ptr) noexcept +{ + details::bsd_set_buffer_curr_ptr_impl(cio.fp,ptr); +} + +inline bool ibuffer_underflow(u8c_io_observer_unlocked cio) +{ + return details::bsd_underflow_impl(cio.fp); +} + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_legacy_impl/c/wincrt.h b/src/fast_io/include/fast_io_legacy_impl/c/wincrt.h new file mode 100644 index 0000000..dc35396 --- /dev/null +++ b/src/fast_io/include/fast_io_legacy_impl/c/wincrt.h @@ -0,0 +1,630 @@ +#pragma once + +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning(push) +#pragma warning( disable : 4710 ) +#pragma warning( disable : 4820 ) +#endif + +namespace fast_io +{ + +namespace win32 +{ +#if __has_cpp_attribute(__gnu__::__const__) +[[__gnu__::__const__]] +#endif +inline FILE* wincrt_acrt_iob_func(unsigned index) noexcept +{ +#if defined(_MSC_VER) || defined(_UCRT) + return noexcept_call(__acrt_iob_func,index); +#else + return ::fast_io::win32::wincrt_iob_func()+index; +#endif +} +} + +namespace details +{ +/* +the entire stdio on windows is too broken. I want to add tie semantics to stdin and stdout to avoid troubles. +*/ + +#if defined(_MSC_VER) || defined(_UCRT) + + +struct +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +ucrt_iobuf +{ + char* _ptr; + char* _base; + int _cnt; + long _flag; + long _file; + int _charbuf; + int _bufsiz; + char* _tmpfname; +}; + +#endif + +inline constexpr std::size_t wincrt_internal_buffer_size{4096}; + +template +inline constexpr void wincrt_fp_set_flag_dirty_impl(fileptr* __restrict fp) noexcept +{ + fp->_flag|=0x0002; +} + +template +inline constexpr void wincrt_fp_set_flag_mybuf_impl(fileptr* __restrict fp) noexcept +{ +#if defined(_MSC_VER) || defined(_UCRT) + fp->_flag|=0x0040; +#else + fp->_flag|=0x0008; +#endif +} + +template +inline constexpr bool wincrt_fp_is_dirty_impl(fileptr* __restrict fp) noexcept +{ + constexpr unsigned mask{0x0002}; + return (static_cast(fp->_flag)&mask)==mask; +} + +inline void* my_malloc_crt(std::size_t buffer_size) noexcept +{ + auto ptr{ +#if defined(_DEBUG) && defined(_MSC_VER) + +/* +https://docs.microsoft.com/en-us/visualstudio/debugger/crt-debug-heap-details +_NORMAL_BLOCK A call to malloc or calloc creates a Normal block. If you intend to use Normal blocks only, and have no need for Client blocks, you may want to define _CRTDBG_MAP_ALLOC, which causes all heap allocation calls to be mapped to their debug equivalents in Debug builds. This will allow file name and line number information about each allocation call to be stored in the corresponding block header. + +_CRT_BLOCK The memory blocks allocated internally by many run-time library functions are marked as CRT blocks so they can be handled separately. As a result, leak detection and other operations need not be affected by them. An allocation must never allocate, reallocate, or free any block of CRT type. + +_CLIENT_BLOCK An application can keep special track of a given group of allocations for debugging purposes by allocating them as this type of memory block, using explicit calls to the debug heap functions. MFC, for example, allocates all CObjects as Client blocks; other applications might keep different memory objects in Client blocks. Subtypes of Client blocks can also be specified for greater tracking granularity. To specify subtypes of Client blocks, shift the number left by 16 bits and OR it with _CLIENT_BLOCK. For example: + +*/ + + ::fast_io::noexcept_call(_malloc_dbg,buffer_size, +#if defined(_CRT_BLOCK) + _CRT_BLOCK +#else + 2 /*_CRT_BLOCK*/ +#endif +,__FILE__,__LINE__) +// Provide Debugging information to this file so if people find out issues with hacking they can report to fast_io project +#else +/* +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) + __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. + if(ptr==nullptr)[[unlikely]] + fast_terminate(); + return ptr; +} + +inline void wincrt_fp_allocate_buffer_impl(FILE* __restrict fpp) noexcept +{ +#if defined(_MSC_VER) || defined(_UCRT) + ucrt_iobuf* fp{reinterpret_cast(fpp)}; +#else + FILE* fp{fpp}; +#endif + if(fp->_bufsiz<4) + { + fp->_bufsiz=wincrt_internal_buffer_size; + } + fp->_bufsiz>>=2; + fp->_bufsiz<<=2; + std::size_t allocated_buffer_size{static_cast(static_cast(fp->_bufsiz))}; + auto new_buffer{my_malloc_crt(allocated_buffer_size)}; + fp->_ptr=fp->_base=reinterpret_cast(new_buffer); + fp->_cnt=0; + wincrt_fp_set_flag_mybuf_impl(fp); +} + +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline void wincrt_fp_write_cold_malloc_case_impl(FILE* __restrict fpp,char const* __restrict first,std::size_t diff) +{ +#if defined(_MSC_VER) || defined(_UCRT) + ucrt_iobuf* fp{reinterpret_cast(fpp)}; +#else + FILE* fp{fpp}; +#endif + if(diff==0) + return; + std::size_t allocated_buffer_size{wincrt_internal_buffer_size}; + if(fp->_bufsiz>=4) + { + allocated_buffer_size=static_cast(static_cast(fp->_bufsiz)); + allocated_buffer_size>>=2; + allocated_buffer_size<<=2; + } + if(diff>=allocated_buffer_size) + { + posix_write_nolock_impl(static_cast(fp->_file),first,diff); + return; + } + auto newbuffer{my_malloc_crt(allocated_buffer_size)}; + my_memcpy(newbuffer,first,diff); + fp->_ptr=(fp->_base=reinterpret_cast(newbuffer))+diff; + wincrt_fp_set_flag_mybuf_impl(fp); + fp->_bufsiz=static_cast(allocated_buffer_size); + fp->_cnt=fp->_bufsiz-static_cast(diff); + wincrt_fp_set_flag_dirty_impl(fp); +} + +inline void wincrt_fp_write_cold_normal_case_impl(FILE* __restrict fpp,char const* __restrict first,std::size_t diff) +{ +#if defined(_MSC_VER) || defined(_UCRT) + ucrt_iobuf* fp{reinterpret_cast(fpp)}; +#else + FILE* fp{fpp}; +#endif + std::size_t remain{static_cast(static_cast(fp->_cnt))}; + non_overlapped_copy_n(first,remain,fp->_ptr); + diff-=remain; + first+=remain; + fp->_ptr+=remain; + fp->_cnt=0; + wincrt_fp_set_flag_dirty_impl(fp); + posix_write_simple_impl(static_cast(fp->_file),fp->_base,static_cast(fp->_ptr-fp->_base)); + std::size_t const bufsiz{static_cast(static_cast(fp->_bufsiz))}; + if(diff>=bufsiz) + posix_write_nolock_impl(static_cast(fp->_file),first,diff); + else + { + fp->_ptr=non_overlapped_copy_n(first,diff,fp->_base); + fp->_cnt=static_cast(bufsiz-diff); + } +} + +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline void wincrt_fp_write_cold_impl(FILE* __restrict fp,char const* __restrict first,std::size_t diff) +{ +#if defined(_MSC_VER) || defined(_UCRT) + ucrt_iobuf* fpp{reinterpret_cast(fp)}; +#else + FILE* fpp{fp}; +#endif + if(fpp->_base==nullptr) + wincrt_fp_write_cold_malloc_case_impl(fp,first,diff); + else + wincrt_fp_write_cold_normal_case_impl(fp,first,diff); +} + +template +inline void wincrt_fp_write_impl(FILE* __restrict fpp,char_type const* first,char_type const* last) +{ + if constexpr(family==c_family::standard) + { + c_io_observer ciob{fpp}; + io_lock_guard guard{ciob}; + wincrt_fp_write_impl(fpp,first,last); + } + else + { +#if defined(_MSC_VER) || defined(_UCRT) + ucrt_iobuf* fp{reinterpret_cast(fpp)}; +#else + FILE* fp{fpp}; +#endif + std::size_t diff{static_cast(last-first)*sizeof(char_type)}; + std::size_t remain{static_cast(static_cast(fp->_cnt))}; + if(diff_ptr,first,diff); + auto intdiff{static_cast(static_cast(diff))}; + fp->_cnt-=intdiff; + fp->_ptr+=intdiff; + } + return; + } + wincrt_fp_write_cold_impl(fpp,reinterpret_cast(first),diff); + } +} + + +template +requires (sizeof(char_type)<=4) +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline void wincrt_fp_overflow_impl(FILE* __restrict fpp,char_type ch) +{ +#if defined(_MSC_VER) || defined(_UCRT) + ucrt_iobuf* fp{reinterpret_cast(fpp)}; +#else + FILE* fp{fpp}; +#endif + if(fp->_base==nullptr) + wincrt_fp_allocate_buffer_impl(fpp); + else + posix_write_simple_impl(static_cast(fp->_file),fp->_base,static_cast(static_cast(fp->_bufsiz))); + fp->_ptr=fp->_base; + my_memcpy(fp->_ptr,__builtin_addressof(ch),sizeof(ch)); + fp->_ptr+=sizeof(ch); + fp->_cnt=static_cast(static_cast(fp->_bufsiz-static_cast(sizeof(ch)))); + wincrt_fp_set_flag_dirty_impl(fp); +} + +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline void wincrt_fp_flush_stdout_impl() +{ +#if defined(_MSC_VER) || defined(_UCRT) + ucrt_iobuf* fp{reinterpret_cast(::fast_io::win32::wincrt_acrt_iob_func(1))}; +#else + FILE* fp{::fast_io::win32::wincrt_acrt_iob_func(1)}; +#endif + std::size_t diff{static_cast(fp->_ptr-fp->_base)}; +// if(diff==0||!wincrt_fp_is_dirty_impl(fp)) + if(diff==0) + return; + posix_write_simple_impl(static_cast(fp->_file),fp->_base,diff); + fp->_ptr=fp->_base; +} + +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline std::size_t wincrt_fp_read_cold_impl(FILE* __restrict fpp,char* first,std::size_t diff) +{ + if(fpp==::fast_io::win32::wincrt_acrt_iob_func(0)) + wincrt_fp_flush_stdout_impl(); +#if defined(_MSC_VER) || defined(_UCRT) + ucrt_iobuf* fp{reinterpret_cast(fpp)}; +#else + FILE* fp{fpp}; +#endif + std::size_t cnt{static_cast(static_cast(fp->_cnt))}; + non_overlapped_copy_n(fp->_ptr,cnt,first); + auto first_temp{first}; + first+=cnt; + diff-=cnt; + std::size_t allocated_buffer_size{static_cast(static_cast(fp->_bufsiz))}; + if(allocated_buffer_size<4) + allocated_buffer_size=wincrt_internal_buffer_size; + + if(diff>=allocated_buffer_size) + return posix_read_impl(static_cast(fp->_file),first,diff); + else + { + if(fp->_base==nullptr) + { + auto new_buffer{my_malloc_crt(allocated_buffer_size)}; + fp->_ptr=fp->_base=reinterpret_cast(new_buffer); + fp->_cnt=0; + fp->_bufsiz=static_cast(static_cast(allocated_buffer_size)); + wincrt_fp_set_flag_mybuf_impl(fp); + } + std::size_t readed{posix_read_impl(static_cast(fp->_file),fp->_base,static_cast(static_cast(fp->_bufsiz)))}; + fp->_cnt=static_cast(static_cast(readed)); + fp->_ptr=fp->_base; + if(readed_base,diff,first); + fp->_ptr+=diff; + fp->_cnt-=static_cast(static_cast(diff)); + return static_cast(first+diff-first_temp); + } +} + +template +inline char_type* wincrt_fp_read_impl(FILE* __restrict fpp,char_type* first,char_type* last) +{ + if constexpr(family==c_family::standard) + { + c_io_observer ciob{fpp}; + io_lock_guard guard{ciob}; + return wincrt_fp_read_impl(fpp,first,last); + } + else + { +#if defined(_MSC_VER) || defined(_UCRT) + ucrt_iobuf* fp{reinterpret_cast(fpp)}; +#else + FILE* fp{fpp}; +#endif + std::size_t diff{static_cast(last-first)*sizeof(char_type)}; + std::size_t remain{static_cast(static_cast(fp->_cnt))}; + if(diff_ptr,diff); + auto intdiff{static_cast(static_cast(diff))}; + fp->_cnt-=intdiff; + fp->_ptr+=intdiff; + } + return last; + } + return first+wincrt_fp_read_cold_impl(fpp,reinterpret_cast(first),diff)/sizeof(char_type); + } +} + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline bool wincrt_fp_underflow_impl(FILE* __restrict fpp) +{ + if(fpp==::fast_io::win32::wincrt_acrt_iob_func(0)) + wincrt_fp_flush_stdout_impl(); +#if defined(_MSC_VER) || defined(_UCRT) + ucrt_iobuf* fp{reinterpret_cast(fpp)}; +#else + FILE* fp{fpp}; +#endif + if(fp->_base==nullptr) + wincrt_fp_allocate_buffer_impl(fpp); + std::size_t size{posix_read_impl(static_cast(fp->_file),fp->_base,static_cast(static_cast(fp->_bufsiz)))}; + fp->_ptr=fp->_base; + fp->_cnt=static_cast(static_cast(size)); + if constexpr(sizeof(char_type)==1) + return static_cast(size); + else + return sizeof(char_type)<=size; +} + +template +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline T* wincrt_get_buffer_ptr_impl(FILE* __restrict fpp) noexcept +{ + static_assert(num<4); +#if defined(_UCRT) || defined(_MSC_VER) + ucrt_iobuf* fp{reinterpret_cast(fpp)}; +#else + FILE* fp{fpp}; +#endif + if constexpr(num==0) + return reinterpret_cast(fp->_base); + else if constexpr(num==1) + return reinterpret_cast(fp->_ptr); + else + return reinterpret_cast(fp->_ptr+fp->_cnt); +} + + +template +inline void wincrt_set_buffer_curr_ptr_impl(FILE* __restrict fpp, +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +T* ptr) noexcept +{ +#if defined(_MSC_VER) || defined(_UCRT) + ucrt_iobuf* fp{reinterpret_cast(fpp)}; +#else + FILE* fp{fpp}; +#endif + fp->_cnt-=static_cast(static_cast(static_cast(reinterpret_cast(ptr)-fp->_ptr)/sizeof(T))); + fp->_ptr=reinterpret_cast(ptr); +} +#if defined(_MSC_VER) || defined(_UCRT) +/* +WINE has not correctly implemented this yet. I am submitting patches. +*/ +inline void ucrt_lock_file(FILE* __restrict fp) noexcept +{ + char* fp2{reinterpret_cast(fp)}; + ::fast_io::win32::EnterCriticalSection(fp2+sizeof(ucrt_iobuf)); +} +inline void ucrt_unlock_file(FILE* __restrict fp) noexcept +{ + char* fp2{reinterpret_cast(fp)}; + ::fast_io::win32::LeaveCriticalSection(fp2+sizeof(ucrt_iobuf)); +} +#endif +} + +template +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char_type* ibuffer_begin(basic_c_io_observer_unlocked ciob) noexcept +{ + return details::wincrt_get_buffer_ptr_impl(ciob.fp); +} + +template +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char_type* ibuffer_curr(basic_c_io_observer_unlocked ciob) noexcept +{ + return details::wincrt_get_buffer_ptr_impl(ciob.fp); +} + +template +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char_type* ibuffer_end(basic_c_io_observer_unlocked ciob) noexcept +{ + return details::wincrt_get_buffer_ptr_impl(ciob.fp); +} + +template +inline void ibuffer_set_curr(basic_c_io_observer_unlocked ciob,char_type* ptr) noexcept +{ + details::wincrt_set_buffer_curr_ptr_impl(ciob.fp,ptr); +} + +template +inline bool ibuffer_underflow(basic_c_io_observer_unlocked ciob) +{ + return details::wincrt_fp_underflow_impl(ciob.fp); +} + + +template +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char_type* obuffer_begin(basic_c_io_observer_unlocked ciob) noexcept +{ + return details::wincrt_get_buffer_ptr_impl(ciob.fp); +} + +template +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char_type* obuffer_curr(basic_c_io_observer_unlocked ciob) noexcept +{ + return details::wincrt_get_buffer_ptr_impl(ciob.fp); +} + +template +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +inline char_type* obuffer_end(basic_c_io_observer_unlocked ciob) noexcept +{ + return details::wincrt_get_buffer_ptr_impl(ciob.fp); +} + +template +inline void obuffer_set_curr(basic_c_io_observer_unlocked ciob,char_type* ptr) noexcept +{ + details::wincrt_set_buffer_curr_ptr_impl(ciob.fp,ptr); +} + +template +inline void obuffer_overflow(basic_c_io_observer_unlocked ciob,char_type ch) +{ + details::wincrt_fp_overflow_impl(ciob.fp,ch); +} + +template +requires (std::same_as||std::same_as<::std::iter_value_t,char_type>) +inline Iter read(basic_c_family_io_observer ciob,Iter bg,Iter ed) +{ + if constexpr(!std::same_as<::std::iter_value_t,char_type>||!std::is_pointer_v) + return read(ciob,reinterpret_cast(::std::to_address(bg)), + reinterpret_cast(::std::to_address(ed)))- + reinterpret_cast(::std::to_address(bg))+bg; + else + return details::wincrt_fp_read_impl(ciob.fp,bg,ed); +} + + +template +requires (std::same_as||std::same_as<::std::iter_value_t,char_type>) +inline void write(basic_c_family_io_observer ciob,Iter bg,Iter ed) +{ + if constexpr(!std::same_as<::std::iter_value_t,char_type>||!std::is_pointer_v) + write(ciob,reinterpret_cast(::std::to_address(bg)), + reinterpret_cast(::std::to_address(ed))); + else + details::wincrt_fp_write_impl(ciob.fp,bg,ed); +} + +inline c_io_observer c_stdin() noexcept +{ + return {::fast_io::win32::wincrt_acrt_iob_func(0)}; +} + +inline c_io_observer c_stdout() noexcept +{ + return {::fast_io::win32::wincrt_acrt_iob_func(1)}; +} + +inline c_io_observer c_stderr() noexcept +{ + return {::fast_io::win32::wincrt_acrt_iob_func(2)}; +} + +inline wc_io_observer wc_stdin() noexcept +{ + return {::fast_io::win32::wincrt_acrt_iob_func(0)}; +} + +inline wc_io_observer wc_stdout() noexcept +{ + return {::fast_io::win32::wincrt_acrt_iob_func(1)}; +} + +inline wc_io_observer wc_stderr() noexcept +{ + return {::fast_io::win32::wincrt_acrt_iob_func(2)}; +} + +inline u8c_io_observer u8c_stdin() noexcept +{ + return {::fast_io::win32::wincrt_acrt_iob_func(0)}; +} + +inline u8c_io_observer u8c_stdout() noexcept +{ + return {::fast_io::win32::wincrt_acrt_iob_func(1)}; +} + +inline u8c_io_observer u8c_stderr() noexcept +{ + return {::fast_io::win32::wincrt_acrt_iob_func(2)}; +} + +inline u16c_io_observer u16c_stdin() noexcept +{ + return {::fast_io::win32::wincrt_acrt_iob_func(0)}; +} + +inline u16c_io_observer u16c_stdout() noexcept +{ + return {::fast_io::win32::wincrt_acrt_iob_func(1)}; +} + +inline u16c_io_observer u16c_stderr() noexcept +{ + return {::fast_io::win32::wincrt_acrt_iob_func(2)}; +} + +inline u32c_io_observer u32c_stdin() noexcept +{ + return {::fast_io::win32::wincrt_acrt_iob_func(0)}; +} + +inline u32c_io_observer u32c_stdout() noexcept +{ + return {::fast_io::win32::wincrt_acrt_iob_func(1)}; +} + +inline u32c_io_observer u32c_stderr() noexcept +{ + return {::fast_io::win32::wincrt_acrt_iob_func(2)}; +} + +} + +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning(pop) +#endif diff --git a/src/fast_io/include/fast_io_legacy_impl/filebuf/bp_hack/common.h b/src/fast_io/include/fast_io_legacy_impl/filebuf/bp_hack/common.h new file mode 100644 index 0000000..55a3525 --- /dev/null +++ b/src/fast_io/include/fast_io_legacy_impl/filebuf/bp_hack/common.h @@ -0,0 +1,49 @@ +#pragma once + +namespace fast_io +{ + +namespace details::streambuf_hack +{ +template +class basic_streambuf_hack_model : private ::std::basic_streambuf +{ +public: + using ::std::basic_streambuf::underflow; + using ::std::basic_streambuf::overflow; +}; +} + +template +inline bool ibuffer_underflow(::fast_io::basic_general_streambuf_io_observer biob) +{ + using char_type = typename ::fast_io::basic_general_streambuf_io_observer::char_type; + using traits_type = typename ::fast_io::basic_general_streambuf_io_observer::traits_type; + using model = ::fast_io::details::streambuf_hack::basic_streambuf_hack_model; + constexpr auto underflow_method_ptr{&model::underflow}; + ibuffer_set_curr(biob,ibuffer_end(biob)); + return (biob.fb->*underflow_method_ptr)()!=EOF; +} + +template +inline void obuffer_overflow(::fast_io::basic_general_streambuf_io_observer biob,typename T::char_type ch) +{ + using char_type = typename ::fast_io::basic_general_streambuf_io_observer::char_type; + using traits_type = typename ::fast_io::basic_general_streambuf_io_observer::traits_type; + using model = ::fast_io::details::streambuf_hack::basic_streambuf_hack_model; + constexpr auto overflow_method_ptr{&model::overflow}; + obuffer_set_curr(biob,obuffer_end(biob)); + if(((biob.fb->*overflow_method_ptr)(traits_type::to_int_type(ch)))==EOF) + { + throw_posix_error( +#if defined(EIO) + EIO +#else + EINVAL +#endif + ); + } +} + +} + diff --git a/src/fast_io/include/fast_io_legacy_impl/filebuf/bp_hack/emulated.h b/src/fast_io/include/fast_io_legacy_impl/filebuf/bp_hack/emulated.h new file mode 100644 index 0000000..bc648ca --- /dev/null +++ b/src/fast_io/include/fast_io_legacy_impl/filebuf/bp_hack/emulated.h @@ -0,0 +1,132 @@ +#pragma once + +namespace fast_io +{ + +namespace details::streambuf_hack +{ +template +class emulated_basic_streambuf_hack_model : private ::std::basic_streambuf +{ +public: + using ::std::basic_streambuf::eback; + using ::std::basic_streambuf::gptr; + using ::std::basic_streambuf::egptr; + using ::std::basic_streambuf::pbase; + using ::std::basic_streambuf::pptr; + using ::std::basic_streambuf::epptr; + using ::std::basic_streambuf::gbump; + using ::std::basic_streambuf::pbump; +}; +} + +template +inline typename T::char_type* ibuffer_begin(::fast_io::basic_general_streambuf_io_observer biob) noexcept +{ + using char_type = typename ::fast_io::basic_general_streambuf_io_observer::char_type; + using traits_type = typename ::fast_io::basic_general_streambuf_io_observer::traits_type; + using model = ::fast_io::details::streambuf_hack::emulated_basic_streambuf_hack_model; + constexpr auto methodptr{&model::eback}; + return (biob.fb->*methodptr)(); +} + +template +inline typename T::char_type* ibuffer_curr(::fast_io::basic_general_streambuf_io_observer biob) noexcept +{ + using char_type = typename ::fast_io::basic_general_streambuf_io_observer::char_type; + using traits_type = typename ::fast_io::basic_general_streambuf_io_observer::traits_type; + using model = ::fast_io::details::streambuf_hack::emulated_basic_streambuf_hack_model; + constexpr auto methodptr{&model::gptr}; + return (biob.fb->*methodptr)(); +} + +template +inline typename T::char_type* ibuffer_end(::fast_io::basic_general_streambuf_io_observer biob) noexcept +{ + using char_type = typename ::fast_io::basic_general_streambuf_io_observer::char_type; + using traits_type = typename ::fast_io::basic_general_streambuf_io_observer::traits_type; + using model = ::fast_io::details::streambuf_hack::emulated_basic_streambuf_hack_model; + constexpr auto methodptr{&model::egptr}; + return (biob.fb->*methodptr)(); +} + +template +inline void ibuffer_set_curr(::fast_io::basic_general_streambuf_io_observer biob,typename T::char_type* ptr) noexcept +{ +/* +Work around bugs in issue 255 +https://cplusplus.github.io/LWG/issue255 +*/ + using char_type = typename ::fast_io::basic_general_streambuf_io_observer::char_type; + using traits_type = typename ::fast_io::basic_general_streambuf_io_observer::traits_type; + using model = ::fast_io::details::streambuf_hack::emulated_basic_streambuf_hack_model; + constexpr auto curr_methodptr{&model::gptr}; + auto diff{ptr-(biob.fb->*curr_methodptr)()}; + if constexpr(sizeof(int)(::std::numeric_limits::min())},mx{static_cast<::std::ptrdiff_t>(::std::numeric_limits::max())}; + if(diff*methodptr)(static_cast(diff)); +} + +template +inline typename T::char_type* obuffer_begin(::fast_io::basic_general_streambuf_io_observer biob) noexcept +{ + using char_type = typename ::fast_io::basic_general_streambuf_io_observer::char_type; + using traits_type = typename ::fast_io::basic_general_streambuf_io_observer::traits_type; + using model = ::fast_io::details::streambuf_hack::emulated_basic_streambuf_hack_model; + constexpr auto methodptr{&model::pbase}; + return (biob.fb->*methodptr)(); +} + +template +inline typename T::char_type* obuffer_curr(::fast_io::basic_general_streambuf_io_observer biob) noexcept +{ + using char_type = typename ::fast_io::basic_general_streambuf_io_observer::char_type; + using traits_type = typename ::fast_io::basic_general_streambuf_io_observer::traits_type; + using model = ::fast_io::details::streambuf_hack::emulated_basic_streambuf_hack_model; + constexpr auto methodptr{&model::pptr}; + return (biob.fb->*methodptr)(); +} + +template +inline typename T::char_type* obuffer_end(::fast_io::basic_general_streambuf_io_observer biob) noexcept +{ + using char_type = typename ::fast_io::basic_general_streambuf_io_observer::char_type; + using traits_type = typename ::fast_io::basic_general_streambuf_io_observer::traits_type; + using model = ::fast_io::details::streambuf_hack::emulated_basic_streambuf_hack_model; + constexpr auto methodptr{&model::epptr}; + return (biob.fb->*methodptr)(); +} + +template +inline void obuffer_set_curr(::fast_io::basic_general_streambuf_io_observer biob,typename T::char_type* ptr) noexcept +{ +/* +Work around bugs in issue 255 +https://cplusplus.github.io/LWG/issue255 +*/ + using char_type = typename ::fast_io::basic_general_streambuf_io_observer::char_type; + using traits_type = typename ::fast_io::basic_general_streambuf_io_observer::traits_type; + using model = ::fast_io::details::streambuf_hack::emulated_basic_streambuf_hack_model; + constexpr auto curr_methodptr{&model::pptr}; + auto diff{ptr-(biob.fb->*curr_methodptr)()}; + if constexpr(sizeof(int)(::std::numeric_limits::min())},mx{static_cast<::std::ptrdiff_t>(::std::numeric_limits::max())}; + if(diff*methodptr)(static_cast(diff)); +} + +} + diff --git a/src/fast_io/include/fast_io_legacy_impl/filebuf/bp_hack/impl.h b/src/fast_io/include/fast_io_legacy_impl/filebuf/bp_hack/impl.h new file mode 100644 index 0000000..cae5abe --- /dev/null +++ b/src/fast_io/include/fast_io_legacy_impl/filebuf/bp_hack/impl.h @@ -0,0 +1,13 @@ +#pragma once +#if defined(_LIBCPP_VERSION) +#include"libc++.h" +#elif defined(__GLIBCXX__) +#include"libstdc++.h" +#elif defined(_MSVC_STL_UPDATE) +#include"msvc_stl.h" +#else +#include"emulated.h" +#endif + +#include"common.h" + diff --git a/src/fast_io/include/fast_io_legacy_impl/filebuf/bp_hack/libc++.h b/src/fast_io/include/fast_io_legacy_impl/filebuf/bp_hack/libc++.h new file mode 100644 index 0000000..a7be2c5 --- /dev/null +++ b/src/fast_io/include/fast_io_legacy_impl/filebuf/bp_hack/libc++.h @@ -0,0 +1,119 @@ +#pragma once + +namespace fast_io +{ + +namespace details::streambuf_hack +{ +#if 0 +/* +libc++ +https://github.com/llvm-mirror/libcxx/blob/master/include/streambuf +*/ + +locale __loc_; +char_type* __binp_; +char_type* __ninp_; +char_type* __einp_; +char_type* __bout_; +char_type* __nout_; +char_type* __eout_; + +#endif +template +class libcxx_basic_streambuf_hack_model +{ +public: + void* vptr; + ::std::locale __loc_; + char_type* __binp_; + char_type* __ninp_; + char_type* __einp_; + char_type* __bout_; + char_type* __nout_; + char_type* __eout_; +}; + +} + +template +inline typename T::char_type* ibuffer_begin(::fast_io::basic_general_streambuf_io_observer biob) noexcept +{ + using char_type = typename ::fast_io::basic_general_streambuf_io_observer::char_type; + using traits_type = typename ::fast_io::basic_general_streambuf_io_observer::traits_type; + using model = ::fast_io::details::streambuf_hack::libcxx_basic_streambuf_hack_model; + constexpr std::size_t offset{__builtin_offsetof(model,__binp_)}; + return *reinterpret_cast(reinterpret_cast(biob.fb)+offset); +} + +template +inline typename T::char_type* ibuffer_curr(::fast_io::basic_general_streambuf_io_observer biob) noexcept +{ + using char_type = typename ::fast_io::basic_general_streambuf_io_observer::char_type; + using traits_type = typename ::fast_io::basic_general_streambuf_io_observer::traits_type; + using model = ::fast_io::details::streambuf_hack::libcxx_basic_streambuf_hack_model; + constexpr std::size_t offset{__builtin_offsetof(model,__ninp_)}; + return *reinterpret_cast(reinterpret_cast(biob.fb)+offset); +} + +template +inline typename T::char_type* ibuffer_end(::fast_io::basic_general_streambuf_io_observer biob) noexcept +{ + using char_type = typename ::fast_io::basic_general_streambuf_io_observer::char_type; + using traits_type = typename ::fast_io::basic_general_streambuf_io_observer::traits_type; + using model = ::fast_io::details::streambuf_hack::libcxx_basic_streambuf_hack_model; + constexpr std::size_t offset{__builtin_offsetof(model,__einp_)}; + return *reinterpret_cast(reinterpret_cast(biob.fb)+offset); +} + +template +inline void ibuffer_set_curr(::fast_io::basic_general_streambuf_io_observer biob,typename T::char_type* ptr) noexcept +{ + using char_type = typename ::fast_io::basic_general_streambuf_io_observer::char_type; + using traits_type = typename ::fast_io::basic_general_streambuf_io_observer::traits_type; + using model = ::fast_io::details::streambuf_hack::libcxx_basic_streambuf_hack_model; + constexpr std::size_t offset{__builtin_offsetof(model,__ninp_)}; + *reinterpret_cast(reinterpret_cast(biob.fb)+offset)=ptr; +} + +template +inline typename T::char_type* obuffer_begin(::fast_io::basic_general_streambuf_io_observer biob) noexcept +{ + using char_type = typename ::fast_io::basic_general_streambuf_io_observer::char_type; + using traits_type = typename ::fast_io::basic_general_streambuf_io_observer::traits_type; + using model = ::fast_io::details::streambuf_hack::libcxx_basic_streambuf_hack_model; + constexpr std::size_t offset{__builtin_offsetof(model,__bout_)}; + return *reinterpret_cast(reinterpret_cast(biob.fb)+offset); +} + +template +inline typename T::char_type* obuffer_curr(::fast_io::basic_general_streambuf_io_observer biob) noexcept +{ + using char_type = typename ::fast_io::basic_general_streambuf_io_observer::char_type; + using traits_type = typename ::fast_io::basic_general_streambuf_io_observer::traits_type; + using model = ::fast_io::details::streambuf_hack::libcxx_basic_streambuf_hack_model; + constexpr std::size_t offset{__builtin_offsetof(model,__nout_)}; + return *reinterpret_cast(reinterpret_cast(biob.fb)+offset); +} + +template +inline typename T::char_type* obuffer_end(::fast_io::basic_general_streambuf_io_observer biob) noexcept +{ + using char_type = typename ::fast_io::basic_general_streambuf_io_observer::char_type; + using traits_type = typename ::fast_io::basic_general_streambuf_io_observer::traits_type; + using model = ::fast_io::details::streambuf_hack::libcxx_basic_streambuf_hack_model; + constexpr std::size_t offset{__builtin_offsetof(model,__eout_)}; + return *reinterpret_cast(reinterpret_cast(biob.fb)+offset); +} + +template +inline void obuffer_set_curr(::fast_io::basic_general_streambuf_io_observer biob,typename T::char_type* ptr) noexcept +{ + using char_type = typename ::fast_io::basic_general_streambuf_io_observer::char_type; + using traits_type = typename ::fast_io::basic_general_streambuf_io_observer::traits_type; + using model = ::fast_io::details::streambuf_hack::libcxx_basic_streambuf_hack_model; + constexpr std::size_t offset{__builtin_offsetof(model,__nout_)}; + *reinterpret_cast(reinterpret_cast(biob.fb)+offset)=ptr; +} + +} diff --git a/src/fast_io/include/fast_io_legacy_impl/filebuf/bp_hack/libstdc++.h b/src/fast_io/include/fast_io_legacy_impl/filebuf/bp_hack/libstdc++.h new file mode 100644 index 0000000..3ff2014 --- /dev/null +++ b/src/fast_io/include/fast_io_legacy_impl/filebuf/bp_hack/libstdc++.h @@ -0,0 +1,131 @@ +#pragma once + +namespace fast_io +{ +namespace details::streambuf_hack +{ +#if 0 + +/* +https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/std/streambuf +*/ + +/* +* This is based on _IO_FILE, just reordered to be more consistent, +* and is intended to be the most minimal abstraction for an +* internal buffer. +* - get == input == read +* - put == output == write +*/ +char_type* _M_in_beg; ///< Start of get area. +char_type* _M_in_cur; ///< Current read area. +char_type* _M_in_end; ///< End of get area. +char_type* _M_out_beg; ///< Start of put area. +char_type* _M_out_cur; ///< Current put area. +char_type* _M_out_end; ///< End of put area. + +/// Current locale setting. +locale _M_buf_locale; + +#endif + +template +class libstdcxx_basic_streambuf_hack_model +{ +public: +void* vptr; +char_type* _M_in_beg; ///< Start of get area. +char_type* _M_in_cur; ///< Current read area. +char_type* _M_in_end; ///< End of get area. +char_type* _M_out_beg; ///< Start of put area. +char_type* _M_out_cur; ///< Current put area. +char_type* _M_out_end; ///< End of put area. + +/// Current locale setting. +::std::locale _M_buf_locale; +}; + +} + +template +inline typename T::char_type* ibuffer_begin(::fast_io::basic_general_streambuf_io_observer biob) noexcept +{ + using char_type = typename ::fast_io::basic_general_streambuf_io_observer::char_type; + using traits_type = typename ::fast_io::basic_general_streambuf_io_observer::traits_type; + using model = ::fast_io::details::streambuf_hack::libstdcxx_basic_streambuf_hack_model; + constexpr std::size_t offset{__builtin_offsetof(model,_M_in_beg)}; + return *reinterpret_cast(reinterpret_cast(biob.fb)+offset); +} + +template +inline typename T::char_type* ibuffer_curr(::fast_io::basic_general_streambuf_io_observer biob) noexcept +{ + using char_type = typename ::fast_io::basic_general_streambuf_io_observer::char_type; + using traits_type = typename ::fast_io::basic_general_streambuf_io_observer::traits_type; + using model = ::fast_io::details::streambuf_hack::libstdcxx_basic_streambuf_hack_model; + constexpr std::size_t offset{__builtin_offsetof(model,_M_in_cur)}; + return *reinterpret_cast(reinterpret_cast(biob.fb)+offset); +} + +template +inline typename T::char_type* ibuffer_end(::fast_io::basic_general_streambuf_io_observer biob) noexcept +{ + using char_type = typename ::fast_io::basic_general_streambuf_io_observer::char_type; + using traits_type = typename ::fast_io::basic_general_streambuf_io_observer::traits_type; + using model = ::fast_io::details::streambuf_hack::libstdcxx_basic_streambuf_hack_model; + constexpr std::size_t offset{__builtin_offsetof(model,_M_in_end)}; + return *reinterpret_cast(reinterpret_cast(biob.fb)+offset); +} + +template +inline void ibuffer_set_curr(::fast_io::basic_general_streambuf_io_observer biob,typename T::char_type* ptr) noexcept +{ + using char_type = typename ::fast_io::basic_general_streambuf_io_observer::char_type; + using traits_type = typename ::fast_io::basic_general_streambuf_io_observer::traits_type; + using model = ::fast_io::details::streambuf_hack::libstdcxx_basic_streambuf_hack_model; + constexpr std::size_t offset{__builtin_offsetof(model,_M_in_cur)}; + *reinterpret_cast(reinterpret_cast(biob.fb)+offset)=ptr; +} + +template +inline typename T::char_type* obuffer_begin(::fast_io::basic_general_streambuf_io_observer biob) noexcept +{ + using char_type = typename ::fast_io::basic_general_streambuf_io_observer::char_type; + using traits_type = typename ::fast_io::basic_general_streambuf_io_observer::traits_type; + using model = ::fast_io::details::streambuf_hack::libstdcxx_basic_streambuf_hack_model; + constexpr std::size_t offset{__builtin_offsetof(model,_M_out_beg)}; + return *reinterpret_cast(reinterpret_cast(biob.fb)+offset); +} + +template +inline typename T::char_type* obuffer_curr(::fast_io::basic_general_streambuf_io_observer biob) noexcept +{ + using char_type = typename ::fast_io::basic_general_streambuf_io_observer::char_type; + using traits_type = typename ::fast_io::basic_general_streambuf_io_observer::traits_type; + using model = ::fast_io::details::streambuf_hack::libstdcxx_basic_streambuf_hack_model; + constexpr std::size_t offset{__builtin_offsetof(model,_M_out_cur)}; + return *reinterpret_cast(reinterpret_cast(biob.fb)+offset); +} + +template +inline typename T::char_type* obuffer_end(::fast_io::basic_general_streambuf_io_observer biob) noexcept +{ + using char_type = typename ::fast_io::basic_general_streambuf_io_observer::char_type; + using traits_type = typename ::fast_io::basic_general_streambuf_io_observer::traits_type; + using model = ::fast_io::details::streambuf_hack::libstdcxx_basic_streambuf_hack_model; + constexpr std::size_t offset{__builtin_offsetof(model,_M_out_end)}; + return *reinterpret_cast(reinterpret_cast(biob.fb)+offset); +} + +template +inline void obuffer_set_curr(::fast_io::basic_general_streambuf_io_observer biob,typename T::char_type* ptr) noexcept +{ + using char_type = typename ::fast_io::basic_general_streambuf_io_observer::char_type; + using traits_type = typename ::fast_io::basic_general_streambuf_io_observer::traits_type; + using model = ::fast_io::details::streambuf_hack::libstdcxx_basic_streambuf_hack_model; + constexpr std::size_t offset{__builtin_offsetof(model,_M_out_cur)}; + *reinterpret_cast(reinterpret_cast(biob.fb)+offset)=ptr; +} + +} + diff --git a/src/fast_io/include/fast_io_legacy_impl/filebuf/bp_hack/msvc_stl.h b/src/fast_io/include/fast_io_legacy_impl/filebuf/bp_hack/msvc_stl.h new file mode 100644 index 0000000..1cc0db4 --- /dev/null +++ b/src/fast_io/include/fast_io_legacy_impl/filebuf/bp_hack/msvc_stl.h @@ -0,0 +1,146 @@ +#pragma once + +namespace fast_io +{ +namespace details::streambuf_hack +{ +#if 0 +/* +https://github.com/microsoft/STL/blob/master/stl/inc/streambuf +*/ +private: + _Elem* _Gfirst; // beginning of read buffer + _Elem* _Pfirst; // beginning of write buffer + _Elem** _IGfirst; // pointer to beginning of read buffer + _Elem** _IPfirst; // pointer to beginning of write buffer + _Elem* _Gnext; // current position in read buffer + _Elem* _Pnext; // current position in write buffer + _Elem** _IGnext; // pointer to current position in read buffer + _Elem** _IPnext; // pointer to current position in write buffer + + int _Gcount; // length of read buffer + int _Pcount; // length of write buffer + int* _IGcount; // pointer to length of read buffer + int* _IPcount; // pointer to length of write buffer + +protected: + locale* _Plocale; // pointer to imbued locale object +#endif + +template +class msvc_stl_basic_streambuf_hack_model +{ +public: + void* vptr; + _Elem* _Gfirst; // beginning of read buffer + _Elem* _Pfirst; // beginning of write buffer + _Elem** _IGfirst; // pointer to beginning of read buffer + _Elem** _IPfirst; // pointer to beginning of write buffer + _Elem* _Gnext; // current position in read buffer + _Elem* _Pnext; // current position in write buffer + _Elem** _IGnext; // pointer to current position in read buffer + _Elem** _IPnext; // pointer to current position in write buffer + + int _Gcount; // length of read buffer + int _Pcount; // length of write buffer + int* _IGcount; // pointer to length of read buffer + int* _IPcount; // pointer to length of write buffer + + ::std::locale* _Plocale; // pointer to imbued locale object +}; + +} + +template +inline typename T::char_type* ibuffer_begin(::fast_io::basic_general_streambuf_io_observer biob) noexcept +{ + using char_type = typename ::fast_io::basic_general_streambuf_io_observer::char_type; + using traits_type = typename ::fast_io::basic_general_streambuf_io_observer::traits_type; + using model = ::fast_io::details::streambuf_hack::msvc_stl_basic_streambuf_hack_model; + constexpr std::size_t offset{__builtin_offsetof(model,_IGfirst)}; + return **reinterpret_cast(reinterpret_cast(biob.fb)+offset); +} + +template +inline typename T::char_type* ibuffer_curr(::fast_io::basic_general_streambuf_io_observer biob) noexcept +{ + using char_type = typename ::fast_io::basic_general_streambuf_io_observer::char_type; + using traits_type = typename ::fast_io::basic_general_streambuf_io_observer::traits_type; + using model = ::fast_io::details::streambuf_hack::msvc_stl_basic_streambuf_hack_model; + constexpr std::size_t offset{__builtin_offsetof(model,_IGnext)}; + return **reinterpret_cast(reinterpret_cast(biob.fb)+offset); +} + +template +inline typename T::char_type* ibuffer_end(::fast_io::basic_general_streambuf_io_observer biob) noexcept +{ + using char_type = typename ::fast_io::basic_general_streambuf_io_observer::char_type; + using traits_type = typename ::fast_io::basic_general_streambuf_io_observer::traits_type; + using model = ::fast_io::details::streambuf_hack::msvc_stl_basic_streambuf_hack_model; + constexpr std::size_t offset{__builtin_offsetof(model,_IGnext)}; + constexpr std::size_t count_offset{__builtin_offsetof(model,_IGcount)}; + return **reinterpret_cast(reinterpret_cast(biob.fb)+offset)+ + **reinterpret_cast(reinterpret_cast(biob.fb)+count_offset); +} + +template +inline void ibuffer_set_curr(::fast_io::basic_general_streambuf_io_observer biob,typename T::char_type* ptr) noexcept +{ + using char_type = typename ::fast_io::basic_general_streambuf_io_observer::char_type; + using traits_type = typename ::fast_io::basic_general_streambuf_io_observer::traits_type; + using model = ::fast_io::details::streambuf_hack::msvc_stl_basic_streambuf_hack_model; + constexpr std::size_t offset{__builtin_offsetof(model,_IGnext)}; + constexpr std::size_t count_offset{__builtin_offsetof(model,_IGcount)}; + char_type** addr_of_currptr{*reinterpret_cast(reinterpret_cast(biob.fb)+offset)}; + char_type* currptr{*addr_of_currptr}; + *addr_of_currptr=ptr; + **reinterpret_cast(reinterpret_cast(biob.fb)+count_offset)-=static_cast(ptr-currptr); +} + +template +inline typename T::char_type* obuffer_begin(::fast_io::basic_general_streambuf_io_observer biob) noexcept +{ + using char_type = typename ::fast_io::basic_general_streambuf_io_observer::char_type; + using traits_type = typename ::fast_io::basic_general_streambuf_io_observer::traits_type; + using model = ::fast_io::details::streambuf_hack::msvc_stl_basic_streambuf_hack_model; + constexpr std::size_t offset{__builtin_offsetof(model,_IPfirst)}; + return **reinterpret_cast(reinterpret_cast(biob.fb)+offset); +} + +template +inline typename T::char_type* obuffer_curr(::fast_io::basic_general_streambuf_io_observer biob) noexcept +{ + using char_type = typename ::fast_io::basic_general_streambuf_io_observer::char_type; + using traits_type = typename ::fast_io::basic_general_streambuf_io_observer::traits_type; + using model = ::fast_io::details::streambuf_hack::msvc_stl_basic_streambuf_hack_model; + constexpr std::size_t offset{__builtin_offsetof(model,_IPnext)}; + return **reinterpret_cast(reinterpret_cast(biob.fb)+offset); +} + +template +inline typename T::char_type* obuffer_end(::fast_io::basic_general_streambuf_io_observer biob) noexcept +{ + using char_type = typename ::fast_io::basic_general_streambuf_io_observer::char_type; + using traits_type = typename ::fast_io::basic_general_streambuf_io_observer::traits_type; + using model = ::fast_io::details::streambuf_hack::msvc_stl_basic_streambuf_hack_model; + constexpr std::size_t offset{__builtin_offsetof(model,_IPnext)}; + constexpr std::size_t count_offset{__builtin_offsetof(model,_IPcount)}; + return **reinterpret_cast(reinterpret_cast(biob.fb)+offset)+ + **reinterpret_cast(reinterpret_cast(biob.fb)+count_offset); +} + +template +inline void obuffer_set_curr(::fast_io::basic_general_streambuf_io_observer biob,typename T::char_type* ptr) noexcept +{ + using char_type = typename ::fast_io::basic_general_streambuf_io_observer::char_type; + using traits_type = typename ::fast_io::basic_general_streambuf_io_observer::traits_type; + using model = ::fast_io::details::streambuf_hack::msvc_stl_basic_streambuf_hack_model; + constexpr std::size_t offset{__builtin_offsetof(model,_IPnext)}; + constexpr std::size_t count_offset{__builtin_offsetof(model,_IPcount)}; + char_type** addr_of_currptr{*reinterpret_cast(reinterpret_cast(biob.fb)+offset)}; + char_type* currptr{*addr_of_currptr}; + *addr_of_currptr=ptr; + **reinterpret_cast(reinterpret_cast(biob.fb)+count_offset)-=static_cast(ptr-currptr); +} + +} diff --git a/src/fast_io/include/fast_io_legacy_impl/filebuf/filebuf_file.h b/src/fast_io/include/fast_io_legacy_impl/filebuf/filebuf_file.h new file mode 100644 index 0000000..07ff80a --- /dev/null +++ b/src/fast_io/include/fast_io_legacy_impl/filebuf/filebuf_file.h @@ -0,0 +1,179 @@ +#pragma once + +namespace fast_io +{ + +namespace details +{ + +inline constexpr std::ios::openmode calculate_fstream_file_open_mode(open_mode om) noexcept +{ + std::ios::openmode ios_om{}; + if((om&open_mode::app)!=open_mode::none) + ios_om=ios_om|std::ios::app; + if((om&open_mode::text)==open_mode::none) + ios_om=ios_om|std::ios::binary; + if((om&open_mode::in)!=open_mode::none) + ios_om=ios_om|std::ios::in; + if((om&open_mode::out)!=open_mode::none) + ios_om=ios_om|std::ios::out; + if((om&open_mode::trunc)!=open_mode::none) + ios_om=ios_om|std::ios::trunc; +#if defined(__cpp_lib_ios_noreplace) + if((om&open_mode::noreplace)!=open_mode::noreplace) + ios_om=ios_om|std::ios::noreplace; +#endif + if(((om&open_mode::directory)!=open_mode::none)&&ios_om==std::ios::openmode{}) + ios_om=ios_om|std::ios::in; + return ios_om; +} + +inline constexpr std::ios::openmode calculate_fstream_open_value(open_mode om) noexcept +{ + return calculate_fstream_file_open_mode(om); +} + +} + + +template> +class basic_filebuf_file:public basic_filebuf_io_observer +{ +public: + using char_type = CharT; + using traits_type = Traits; + using native_handle_type = std::basic_filebuf*; + constexpr basic_filebuf_file() noexcept=default; + template + requires std::same_as> + constexpr basic_filebuf_file(native_hd fb) noexcept:basic_filebuf_io_observer{fb}{} + constexpr basic_filebuf_file(basic_filebuf_io_observer) noexcept=delete; + constexpr basic_filebuf_file& operator=(basic_filebuf_io_observer) noexcept=delete; + + basic_filebuf_file(decltype(nullptr)) = delete; +#if defined(_LIBCPP_VERSION) + template + basic_filebuf_file(basic_c_family_file&& chd,open_mode mode): + basic_filebuf_io_observer{new std::basic_filebuf} + { + details::streambuf_hack::fp_hack_open(this->fb,chd.fp,details::calculate_fstream_open_value(mode)); + chd.fp=nullptr; + } +#elif defined(__GLIBCXX__) + template + requires std::same_as<::std::__c_file*,typename basic_c_family_file::native_handle_type> + basic_filebuf_file(basic_c_family_file&& chd,open_mode mode): + basic_filebuf_io_observer{::fast_io::details::streambuf_hack::open_libstdcxx_basic_filebuf(chd.fp,mode)} + { + chd.fp=nullptr; + } +#elif defined(_MSVC_STL_UPDATE) + template + basic_filebuf_file(basic_c_family_file&& chd,open_mode):basic_filebuf_io_observer{new std::basic_filebuf(chd.fp)} + { + if(!this->fb->is_open()) + { + delete this->fb; + throw_posix_error(); + } + chd.fp=nullptr; + details::streambuf_hack::msvc_hack_set_close(this->fb); + } +#endif + basic_filebuf_file(io_temp_t):basic_filebuf_file(::fast_io::basic_c_file_unlocked(::fast_io::io_temp),::fast_io::open_mode::in|::fast_io::open_mode::out) + { + } +#if defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) || defined(_MSVC_STL_UPDATE) +#if !defined(__AVR__) && !defined(_GLIBCXX_USE_STDIO_PURE) + basic_filebuf_file(basic_posix_file&& piohd,open_mode mode): + basic_filebuf_file(basic_c_file_unlocked(::std::move(piohd),mode),mode){} +#if (defined(_WIN32)&&!defined(__WINE__)) || defined(__CYGWIN__) +//windows specific. open posix file from win32 io handle + template + basic_filebuf_file(basic_win32_family_file&& win32_handle,open_mode mode): + basic_filebuf_file(basic_posix_file(::std::move(win32_handle),mode),mode) + { + } + template + basic_filebuf_file(basic_nt_family_file&& nt_handle,open_mode mode): + basic_filebuf_file(basic_posix_file(::std::move(nt_handle),mode),mode) + { + } +#endif + + basic_filebuf_file(native_fs_dirent fsdirent,open_mode om,perms pm=static_cast(436)): + basic_filebuf_file(basic_posix_file(fsdirent,om,pm),om) + {} + template<::fast_io::constructible_to_os_c_str T> + basic_filebuf_file(T const& file,open_mode om,perms pm=static_cast(436)): + basic_filebuf_file(basic_posix_file(file,om,pm),om) + {} + template<::fast_io::constructible_to_os_c_str T> + basic_filebuf_file(native_at_entry nate,T const& file,open_mode om,perms pm=static_cast(436)): + basic_filebuf_file(basic_posix_file(nate,file,om,pm),om) + {} +#endif +#endif + basic_filebuf_file& operator=(basic_filebuf_file const&)=delete; + basic_filebuf_file(basic_filebuf_file const&)=delete; + basic_filebuf_file(basic_filebuf_file&& __restrict other) noexcept:basic_filebuf_io_observer{other.release()}{} + + basic_filebuf_file& operator=(basic_filebuf_file&& __restrict bf) noexcept + { + delete this->fb; + this->fb=bf.release(); + return *this; + } + void close() + { + if(this->fb)[[likely]] + { + struct delete_guard + { + native_handle_type& fbr; + delete_guard(native_handle_type& fb):fbr(fb){} + delete_guard(delete_guard const&)=delete; + delete_guard& operator=(delete_guard const&)=delete; + ~delete_guard() + { + delete fbr; + fbr=nullptr; + } + }; + delete_guard guard{this->fb}; + if(this->fb->close()==nullptr)[[unlikely]] + throw_posix_error(); + } + } + void reset(native_handle_type fb=nullptr) noexcept + { + delete this->fb; + this->fb=fb; + } + ~basic_filebuf_file() + { + delete this->fb; + } +}; + +using filebuf_file=basic_filebuf_file; +using wfilebuf_file=basic_filebuf_file; + +namespace freestanding +{ + +template +struct is_trivially_relocatable> +{ + inline static constexpr bool value = true; +}; + +template +struct is_zero_default_constructible> +{ + inline static constexpr bool value = true; +}; + +} + +} diff --git a/src/fast_io/include/fast_io_legacy_impl/filebuf/fp_hack/impl.h b/src/fast_io/include/fast_io_legacy_impl/filebuf/fp_hack/impl.h new file mode 100644 index 0000000..2ced3ad --- /dev/null +++ b/src/fast_io/include/fast_io_legacy_impl/filebuf/fp_hack/impl.h @@ -0,0 +1,8 @@ +#pragma once +#if defined(_LIBCPP_VERSION) +#include"libc++.h" +#elif defined(__GLIBCXX__) +#include"libstdc++.h" +#elif defined(_MSVC_STL_UPDATE) +#include"msvc_stl.h" +#endif \ No newline at end of file diff --git a/src/fast_io/include/fast_io_legacy_impl/filebuf/fp_hack/libc++.h b/src/fast_io/include/fast_io_legacy_impl/filebuf/fp_hack/libc++.h new file mode 100644 index 0000000..6b752ba --- /dev/null +++ b/src/fast_io/include/fast_io_legacy_impl/filebuf/fp_hack/libc++.h @@ -0,0 +1,167 @@ +#pragma once + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC system_header +#endif + +/* +https://github.com/llvm/llvm-project/blob/main/libcxx/src/std_stream.h +*/ + +#include"libc++symbol.h" + +namespace fast_io::details::streambuf_hack +{ + +/* +https://github.com/llvm-mirror/libcxx/blob/master/include/__std_stream +private: + FILE* __file_; + const codecvt* __cv_; + state_type* __st_; + int __encoding_; + int_type __last_consumed_; + bool __last_consumed_is_next_; + bool __always_noconv_; +*/ + +template +inline FILE* stdinbuf_stdoutbuf_fp_hack(T* stdbuf) noexcept +{ + FILE* fp{}; + // we can only do this or ubsanitizer will complain. Do not do down_cast + ::fast_io::details::my_memcpy(__builtin_addressof(fp),reinterpret_cast(stdbuf)+ + sizeof(std::basic_streambuf),sizeof(fp)); + return fp; +} + +/* +https://github.com/llvm-mirror/libcxx/blob/master/include/fstream +private: + char* __extbuf_; + const char* __extbufnext_; + const char* __extbufend_; + char __extbuf_min_[8]; + size_t __ebs_; + char_type* __intbuf_; + size_t __ibs_; + FILE* __file_; + const codecvt* __cv_; + state_type __st_; + state_type __st_last_; + ios_base::openmode __om_; + ios_base::openmode __cm_; + bool __owns_eb_; + bool __owns_ib_; + bool __always_noconv_; +*/ + +template +class libcxx_basic_filebuf_model + : public std::basic_streambuf<_CharT, _Traits> +{ +public: + typedef _CharT char_type; + typedef _Traits traits_type; + typedef typename traits_type::int_type int_type; + typedef typename traits_type::pos_type pos_type; + typedef typename traits_type::off_type off_type; + typedef typename traits_type::state_type state_type; + char* __extbuf_; + const char* __extbufnext_; + const char* __extbufend_; + char __extbuf_min_[8]; + std::size_t __ebs_; + char_type* __intbuf_; + std::size_t __ibs_; + FILE* __file_; + const std::codecvt* __cv_; + state_type __st_; + state_type __st_last_; + std::ios_base::openmode __om_; + std::ios_base::openmode __cm_; + bool __owns_eb_; + bool __owns_ib_; + bool __always_noconv_; +}; + + +template +inline constexpr std::size_t libcxx_fp_location{__builtin_offsetof(libcxx_basic_filebuf_model,__file_)}; + +template +inline constexpr std::size_t libcxx_om_location{__builtin_offsetof(libcxx_basic_filebuf_model,__om_)}; + +template +inline FILE* fp_hack_impl(std::basic_filebuf* fbuf) noexcept +{ + FILE* fp{}; + // we can only do this or ubsanitizer will complain. Do not do down_cast + ::fast_io::details::my_memcpy(__builtin_addressof(fp),reinterpret_cast(fbuf)+libcxx_fp_location,sizeof(fp)); + return fp; +} + +template +inline FILE* fp_hack(std::basic_filebuf* fbuf) noexcept +{ + if(fbuf==nullptr) + return nullptr; + return fp_hack_impl(fbuf); +} + + +template +requires (std::same_as>) +inline FILE* fp_hack([[maybe_unused]] T* stdbuf) noexcept +{ +#ifdef __cpp_rtti + using char_type = typename T::char_type; + using traits_type = typename T::traits_type; +#ifdef __cpp_exceptions + try + { +#endif + if(stdbuf)[[likely]] + { + if constexpr( + ::std::same_as||::std::same_as|| + ::std::same_as||::std::same_as|| + ::std::same_as + ) + { + char const* my_type{typeid(*stdbuf).name()}; + ::std::size_t mytypelen{::std::strlen(my_type)}; + if((mytypelen==::fast_io::details::libcxx_stdinoutbufname.size()&& + ::std::memcmp(my_type, + ::fast_io::details::libcxx_stdinoutbufname.data(), + mytypelen)==0)|| + (mytypelen==::fast_io::details::libcxx_stdinoutbufname.size()&& + ::std::memcmp(my_type, + ::fast_io::details::libcxx_stdinoutbufname.data(), + mytypelen)==0)) + { + return stdinbuf_stdoutbuf_fp_hack(stdbuf); + } + } + auto fbf{dynamic_cast*>(stdbuf)}; + if(fbf) + { + return fp_hack_impl(fbf); + } + } +#ifdef __cpp_exceptions + } + catch(...){} +#endif +#endif + return nullptr; +} + +template +inline void fp_hack_open(std::basic_filebuf* fb,FILE* fp,std::ios::openmode mode) noexcept +{ + ::fast_io::details::my_memcpy(reinterpret_cast(fb)+libcxx_om_location,__builtin_addressof(mode),sizeof(mode)); + ::fast_io::details::my_memcpy(reinterpret_cast(fb)+libcxx_fp_location,__builtin_addressof(fp),sizeof(fp)); +} + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_legacy_impl/filebuf/fp_hack/libc++symbol.h b/src/fast_io/include/fast_io_legacy_impl/filebuf/fp_hack/libc++symbol.h new file mode 100644 index 0000000..d27c163 --- /dev/null +++ b/src/fast_io/include/fast_io_legacy_impl/filebuf/fp_hack/libc++symbol.h @@ -0,0 +1,214 @@ +#pragma once + +namespace fast_io::details +{ + +template +inline constexpr char8_t* compute_libcxx_copy_string_literal(char8_t const(&s)[n],char8_t* result) noexcept +{ + constexpr + ::std::size_t mn1{static_cast<::std::size_t>(n-1u)}; + for(::std::size_t i{};i!=mn1;++i) + { + result[i]=s[i]; + } + return result+mn1; +} + +constexpr std::size_t compute_libcxx_symbol_name_chars_len(::std::size_t value) noexcept +{ + std::size_t sz{1}; + for(;10u<=value;value/=10u) + ++sz; + return sz; +} + +#define FAST_IO_LIBCPP_ABI_NAMESPACE_STR_SSTRIFY(s) u8 ## #s +#define FAST_IO_LIBCPP_ABI_NAMESPACE_STR_STRIFY(s) FAST_IO_LIBCPP_ABI_NAMESPACE_STR_SSTRIFY(s) +#define FAST_IO_LIBCPP_ABI_NAMESPACE_STR FAST_IO_LIBCPP_ABI_NAMESPACE_STR_STRIFY(_LIBCPP_ABI_NAMESPACE) + + +inline constexpr + ::std::size_t libcxx_symbol_len{sizeof(FAST_IO_LIBCPP_ABI_NAMESPACE_STR)-1u}; + +inline constexpr + ::std::size_t libcxx_symbol_name_chars_len{compute_libcxx_symbol_name_chars_len(libcxx_symbol_len)}; + +inline constexpr char8_t* compute_libcxx_itanium_prefix(char8_t* iter) noexcept +{ + auto ed{iter+libcxx_symbol_name_chars_len}; + auto rit{ed}; + for(::std::size_t v{libcxx_symbol_len};iter!=rit;--rit) + { + ::std::size_t dv{static_cast<::std::size_t>(v/10u)}; + char8_t md{static_cast(v%10u)}; + rit[-1]=static_cast(md+u8'0'); + v=dv; + } + return ed; +} + +template +struct libcxx_msvcabi_symbol_name_holder +{ + char8_t const* ptr{}; + inline constexpr auto data() const noexcept + { + return ptr; + } + inline static constexpr ::std::size_t size() noexcept + { + return n; + } +}; + +template +inline constexpr libcxx_msvcabi_symbol_name_holder compute_libcxx_msvcabi_symbol(char8_t const(&s)[n]) noexcept +{ + return {s}; +} + +template +requires (::std::same_as|| + ::std::same_as|| + ::std::same_as|| + ::std::same_as|| + ::std::same_as) +inline constexpr auto compute_libcxx_stdinoutbufname() noexcept +{ + constexpr bool ismsvcabi{ +#ifdef _LIBCPP_ABI_MICROSOFT + true +#endif + }; + if constexpr(ismsvcabi) + { + if constexpr(isoutbuf) + { + if constexpr(::std::same_as) + { + return ::fast_io::details::compute_libcxx_msvcabi_symbol( + u8"class std::" FAST_IO_LIBCPP_ABI_NAMESPACE_STR u8"::__stdoutbuf"); + } + else if constexpr(::std::same_as) + { + return ::fast_io::details::compute_libcxx_msvcabi_symbol( + u8"class std::" FAST_IO_LIBCPP_ABI_NAMESPACE_STR u8"::__stdoutbuf"); + } + else if constexpr(::std::same_as) + { + return ::fast_io::details::compute_libcxx_msvcabi_symbol( + u8"class std::" FAST_IO_LIBCPP_ABI_NAMESPACE_STR u8"::__stdoutbuf"); + } + else if constexpr(::std::same_as) + { + return ::fast_io::details::compute_libcxx_msvcabi_symbol( + u8"class std::" FAST_IO_LIBCPP_ABI_NAMESPACE_STR u8"::__stdoutbuf"); + } + else + { + return ::fast_io::details::compute_libcxx_msvcabi_symbol( + u8"class std::" FAST_IO_LIBCPP_ABI_NAMESPACE_STR u8"::__stdoutbuf"); + } + } + else + { + if constexpr(::std::same_as) + { + return ::fast_io::details::compute_libcxx_msvcabi_symbol( + u8"class std::" FAST_IO_LIBCPP_ABI_NAMESPACE_STR u8"::__stdinbuf"); + } + else if constexpr(::std::same_as) + { + return ::fast_io::details::compute_libcxx_msvcabi_symbol( + u8"class std::" FAST_IO_LIBCPP_ABI_NAMESPACE_STR u8"::__stdinbuf"); + } + else if constexpr(::std::same_as) + { + return ::fast_io::details::compute_libcxx_msvcabi_symbol( + u8"class std::" FAST_IO_LIBCPP_ABI_NAMESPACE_STR u8"::__stdinbuf"); + } + else if constexpr(::std::same_as) + { + return ::fast_io::details::compute_libcxx_msvcabi_symbol( + u8"class std::" FAST_IO_LIBCPP_ABI_NAMESPACE_STR u8"::__stdinbuf"); + } + else + { + return ::fast_io::details::compute_libcxx_msvcabi_symbol( + u8"class std::" FAST_IO_LIBCPP_ABI_NAMESPACE_STR u8"::__stdinbuf"); + } + } + } + else + { +/* +Itanium ABI +*/ + constexpr + ::std::size_t stdinoutsz{(isoutbuf?sizeof(u8"11__stdoutbufI"): + sizeof(u8"10__stdinbufI"))-1}; + constexpr + ::std::size_t chartypesize{ + (::std::same_as||::std::same_as)?1:2 + }; + constexpr + ::std::size_t buffersize{ + sizeof(u8"NStEE")+stdinoutsz+chartypesize+ + ::fast_io::details::libcxx_symbol_len+ + ::fast_io::details::libcxx_symbol_name_chars_len-1}; + ::fast_io::freestanding::array buffer; + auto it{buffer.data()}; + it=::fast_io::details::compute_libcxx_copy_string_literal(u8"NSt",it); + it=::fast_io::details::compute_libcxx_itanium_prefix(it); + it=::fast_io::details::compute_libcxx_copy_string_literal( FAST_IO_LIBCPP_ABI_NAMESPACE_STR ,it); + if constexpr(isoutbuf) + { + it=::fast_io::details::compute_libcxx_copy_string_literal(u8"11__stdoutbufI",it); + } + else + { + it=::fast_io::details::compute_libcxx_copy_string_literal(u8"10__stdinbufI",it); + } + if constexpr(::std::same_as) + { + *it=u8'c'; + ++it; + } + else if constexpr(::std::same_as) + { + *it=u8'w'; + ++it; + } + else + { + *it=u8'D'; + ++it; + if constexpr(::std::same_as) + { + *it=u8'u'; + } + else if constexpr(::std::same_as) + { + *it=u8's'; + } + else + { + *it=u8'i'; + } + ++it; + } + ::fast_io::details::compute_libcxx_copy_string_literal(u8"EE",it); + return buffer; + } +} + +template +inline constexpr auto libcxx_stdinoutbufname{::fast_io::details::compute_libcxx_stdinoutbufname()}; + + +#undef FAST_IO_LIBCPP_ABI_NAMESPACE_STR_SSTRIFY +#undef FAST_IO_LIBCPP_ABI_NAMESPACE_STR_STRIFY +#undef FAST_IO_LIBCPP_ABI_NAMESPACE_STR + +} diff --git a/src/fast_io/include/fast_io_legacy_impl/filebuf/fp_hack/libstdc++.h b/src/fast_io/include/fast_io_legacy_impl/filebuf/fp_hack/libstdc++.h new file mode 100644 index 0000000..58c27ec --- /dev/null +++ b/src/fast_io/include/fast_io_legacy_impl/filebuf/fp_hack/libstdc++.h @@ -0,0 +1,144 @@ +#pragma once +//https://www.ginac.de/~kreckel/fileno/ +#ifdef __cpp_rtti +#include +#endif +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC system_header +#endif + +namespace fast_io::details +{ + +inline constexpr std::ios::openmode calculate_fstream_file_open_mode(open_mode) noexcept; + +namespace streambuf_hack +{ + +template +class hack_libstdcxx_basic_filebuf : private ::std::basic_filebuf +{ +public: + using ::std::basic_filebuf::_M_lock; + using ::std::basic_filebuf::_M_file; + using ::std::basic_filebuf::_M_mode; + using ::std::basic_filebuf::_M_buf_size; + using ::std::basic_filebuf::_M_set_buffer; + using ::std::basic_filebuf::_M_reading; + using ::std::basic_filebuf::_M_writing; + using ::std::basic_filebuf::_M_allocate_internal_buffer; +}; + +template +inline FILE* fp_hack_impl(std::basic_filebuf* fbuf) noexcept +{ + using hack_filebuf_type = hack_libstdcxx_basic_filebuf; + auto pfbf{reinterpret_cast(fbuf)}; + return reinterpret_cast(pfbf+__builtin_offsetof(hack_filebuf_type,_M_file))->file(); +} + +template +inline FILE* fp_hack(std::basic_filebuf* fbuf) noexcept +{ + if(fbuf==nullptr) + return nullptr; + return fp_hack_impl(fbuf); +} + +template +requires (std::same_as>) +inline FILE* fp_hack([[maybe_unused]] T* cio) noexcept +{ +#ifdef __cpp_rtti + using char_type = typename T::char_type; + using traits_type = typename T::traits_type; + if(cio)[[likely]] + { + auto fbuf{dynamic_cast*>(cio)}; + if(fbuf) + return fp_hack_impl(fbuf); + auto sync_fbuf=dynamic_cast<__gnu_cxx::stdio_sync_filebuf*>(cio); + if(sync_fbuf) + return sync_fbuf->file(); + } +#endif + return nullptr; +} + +template +struct libstdcxx_filebuf_guard +{ + using filebuf_type = ::std::basic_filebuf; + filebuf_type* new_filebuf{new std::basic_filebuf}; + + explicit libstdcxx_filebuf_guard() = default; + libstdcxx_filebuf_guard(libstdcxx_filebuf_guard const&)=delete; + libstdcxx_filebuf_guard& operator=(libstdcxx_filebuf_guard const&)=delete; + + ~libstdcxx_filebuf_guard() + { + if(new_filebuf) + delete new_filebuf; + } + inline constexpr filebuf_type* release() noexcept + { + auto temp{new_filebuf}; + new_filebuf=nullptr; + return temp; + } +}; + +template +inline void open_libstdcxx_basic_filebuf_ios_base_open_mode_common(std::basic_filebuf* ptr_fbf, std::ios_base::openmode mode) +{ + using hack_filebuf_type = hack_libstdcxx_basic_filebuf; + constexpr auto libstdcxx_filebuf_M_set_buffer{&hack_filebuf_type::_M_set_buffer}; + constexpr auto libstdcxx_filebuf_M_allocate_internal_buffer_ptr{&hack_filebuf_type::_M_allocate_internal_buffer}; + auto& fbf_ref{*ptr_fbf}; + auto pfbf{reinterpret_cast(ptr_fbf)}; + auto& libstdcxx_filebuf_m_mode{*reinterpret_cast(pfbf+__builtin_offsetof(hack_filebuf_type,_M_mode))}; + auto& libstdcxx_filebuf_m_buf_size{*reinterpret_cast(pfbf+__builtin_offsetof(hack_filebuf_type,_M_buf_size))}; + + auto& libstdcxx_filebuf_m_reading{*reinterpret_cast(pfbf+__builtin_offsetof(hack_filebuf_type,_M_reading))}; + auto& libstdcxx_filebuf_m_writing{*reinterpret_cast(pfbf+__builtin_offsetof(hack_filebuf_type,_M_writing))}; + + libstdcxx_filebuf_m_mode=mode; + constexpr std::size_t buffer_size{fast_io::details::cal_buffer_size()}; + libstdcxx_filebuf_m_buf_size=buffer_size; + (fbf_ref.*libstdcxx_filebuf_M_allocate_internal_buffer_ptr)(); + libstdcxx_filebuf_m_reading=false; + libstdcxx_filebuf_m_writing=false; + (fbf_ref.*libstdcxx_filebuf_M_set_buffer)(-1); +} + +template +#if __has_cpp_attribute(nodiscard) +[[nodiscard]] +#endif +inline std::basic_filebuf* open_libstdcxx_basic_filebuf_ios_base_open_mode(::std::__c_file* fp, std::ios_base::openmode mode) +{ + if(fp==nullptr) + throw_posix_error(EINVAL); + using hack_filebuf_type = hack_libstdcxx_basic_filebuf; + libstdcxx_filebuf_guard fbf_guard; + auto const ptr_fbf{fbf_guard.new_filebuf}; + auto pfbf{reinterpret_cast(ptr_fbf)}; + auto& libstdcxx_filebuf_m_file{*reinterpret_cast(pfbf+__builtin_offsetof(hack_filebuf_type,_M_file))}; + libstdcxx_filebuf_m_file.sys_open(fp,mode); + auto& libstdcxx_filebuf_c_file_m_cfile_created{*reinterpret_cast(pfbf+__builtin_offsetof(hack_filebuf_type,_M_file)+sizeof(::std::__c_file*))}; + libstdcxx_filebuf_c_file_m_cfile_created=true; + open_libstdcxx_basic_filebuf_ios_base_open_mode_common(ptr_fbf,mode); + return fbf_guard.release(); +} + +template +#if __has_cpp_attribute(nodiscard) +[[nodiscard]] +#endif +inline std::basic_filebuf* open_libstdcxx_basic_filebuf(::std::__c_file* fp, ::fast_io::open_mode mode) +{ + return open_libstdcxx_basic_filebuf_ios_base_open_mode(fp,::fast_io::details::calculate_fstream_file_open_mode(mode)); +} + +} +} diff --git a/src/fast_io/include/fast_io_legacy_impl/filebuf/fp_hack/msvc_stl.h b/src/fast_io/include/fast_io_legacy_impl/filebuf/fp_hack/msvc_stl.h new file mode 100644 index 0000000..f05f115 --- /dev/null +++ b/src/fast_io/include/fast_io_legacy_impl/filebuf/fp_hack/msvc_stl.h @@ -0,0 +1,84 @@ +#pragma once + +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC system_header +#endif + +namespace fast_io::details::streambuf_hack +{ + +/* +https://github.com/microsoft/STL/blob/master/stl/inc/fstream#L775 + + const _Cvt* _Pcvt; // pointer to codecvt facet (may be null) + _Elem _Mychar; // putback character, when _Ungetc fails + bool _Wrotesome; // true if homing sequence may be needed + typename _Traits::state_type _State; // current conversion state + bool _Closef; // true if C stream must be closed + FILE* _Myfile; // pointer to C stream +*/ + +template +class basic_filebuf_model : public std::basic_streambuf<_Elem, _Traits> +{ +public: + using _Mysb = std::basic_streambuf<_Elem, _Traits>; + using _Cvt = std::codecvt<_Elem, char, typename _Traits::state_type>; + using int_type = typename _Traits::int_type; + using pos_type = typename _Traits::pos_type; + using off_type = typename _Traits::off_type; + const _Cvt* _Pcvt; // pointer to codecvt facet (may be null) + _Elem _Mychar; // putback character, when _Ungetc fails + bool _Wrotesome; // true if homing sequence may be needed + typename _Traits::state_type _State; // current conversion state + bool _Closef; // true if C stream must be closed + FILE* _Myfile; // pointer to C stream + + _Elem* _Set_eback; // saves eback() during one-element putback + _Elem* _Set_egptr; // saves egptr() +}; + +template +inline FILE* fp_hack_impl(std::basic_filebuf* fbuf) noexcept +{ + using filebuf_model_type = basic_filebuf_model; + FILE* fp{}; + static_assert(sizeof(filebuf_model_type)==sizeof(std::basic_filebuf),"unmatched std::basic_filebuf model"); + // we can only do this or ubsanitizer will complain. Do not do down_cast + ::fast_io::details::my_memcpy(__builtin_addressof(fp),reinterpret_cast(fbuf)+offsetof(filebuf_model_type,_Myfile),sizeof(fp)); + return fp; +} + +template +inline FILE* fp_hack(std::basic_filebuf* fbuf) noexcept +{ + if(fbuf==nullptr) + return nullptr; + return fp_hack_impl(fbuf); +} + +template +requires (std::same_as>) +inline FILE* fp_hack([[maybe_unused]] T* cio) noexcept +{ +#ifdef __cpp_rtti + if(cio)[[likely]] + { + using filebuf_type = std::basic_filebuf; + auto fptr{dynamic_cast(cio)}; + if(fptr) + return fp_hack_impl(fptr); + } +#endif + return nullptr; +} + +template +inline void msvc_hack_set_close(std::basic_filebuf* fbuf) noexcept//not null +{ + using filebuf_model_type = basic_filebuf_model; + static_assert(sizeof(filebuf_model_type)==sizeof(std::basic_filebuf),"unmatched std::basic_filebuf model"); + ::fast_io::details::my_memset(reinterpret_cast(fbuf)+offsetof(filebuf_model_type,_Closef),true,sizeof(bool)); +} + +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_legacy_impl/filebuf/op_out.h b/src/fast_io/include/fast_io_legacy_impl/filebuf/op_out.h new file mode 100644 index 0000000..571e4a0 --- /dev/null +++ b/src/fast_io/include/fast_io_legacy_impl/filebuf/op_out.h @@ -0,0 +1,58 @@ +#pragma once + +/* +This provides a compatibility layer for printing custom types with existing ostream apis. +*/ + +namespace fast_io::details +{ +template +concept printable_to_cxx_ostringstream=std::integral&&requires(std::basic_ostringstream& oss,T const& t) +{ + oss< +requires (sizeof...(Args)!=0) +inline std::string operator_output(Args const& ...args) +{ + constexpr bool type_error{(::fast_io::details::printable_to_cxx_ostringstream&&...)}; + if constexpr(type_error) + { + std::ostringstream oss; + (oss<<...< +requires (sizeof...(Args)!=0) +inline std::basic_string woperator_output(Args const& ...args) +{ + constexpr bool type_error{(::fast_io::details::printable_to_cxx_ostringstream&&...)}; + if constexpr(type_error) + { + std::basic_ostringstream oss; + (oss<<...<(); + } + return {}; +} + +} diff --git a/src/fast_io/include/fast_io_legacy_impl/filebuf/streambuf_io_observer.h b/src/fast_io/include/fast_io_legacy_impl/filebuf/streambuf_io_observer.h new file mode 100644 index 0000000..d220f3f --- /dev/null +++ b/src/fast_io/include/fast_io_legacy_impl/filebuf/streambuf_io_observer.h @@ -0,0 +1,298 @@ +#pragma once + +#include"fp_hack/impl.h" + +namespace fast_io +{ + +template +#if !defined(_MSC_VER) || defined(__clang__) +requires std::derived_from> +#endif +class basic_general_streambuf_io_observer +{ +public: + using streambuf_type = T; + using char_type = typename streambuf_type::char_type; + using traits_type = typename streambuf_type::traits_type; + using native_handle_type = streambuf_type*; + native_handle_type fb{}; + inline constexpr native_handle_type native_handle() const noexcept + { + return fb; + } + inline constexpr native_handle_type release() noexcept + { + native_handle_type temp{fb}; + fb=nullptr; + return temp; + } + explicit constexpr operator bool() const noexcept + { + return fb; + } +#if defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) || defined(_MSVC_STL_UPDATE) + template + explicit operator basic_c_family_io_observer() const noexcept + { + return basic_c_io_observer{details::streambuf_hack::fp_hack(fb)}; + } +#if !defined(__AVR__) + explicit operator basic_posix_io_observer() const noexcept + { + return static_cast>(static_cast>(*this)); + } +#if (defined(_WIN32)&&!defined(__WINE__)) || defined(__CYGWIN__) + explicit operator basic_win32_io_observer() const noexcept + { + return static_cast> + (static_cast>(*this)); + } + template + explicit operator basic_nt_family_io_observer() const noexcept + { + return static_cast> + (static_cast>(*this)); + } +#endif +#endif +#endif +}; + +template +inline void flush(basic_general_streambuf_io_observer h) +{ + if(h.fb->pubsync()==-1) + throw_posix_error(EIO); +} + +#if __cpp_lib_three_way_comparison >= 201907L + +template +inline constexpr bool operator==(basic_general_streambuf_io_observer a,basic_general_streambuf_io_observer b) noexcept +{ + return a.fb==b.fb; +} + +template +inline constexpr auto operator<=>(basic_general_streambuf_io_observer a,basic_general_streambuf_io_observer b) noexcept +{ + return a.fb<=>b.fb; +} + +#endif + +template +inline constexpr basic_general_streambuf_io_observer io_value_handle(basic_general_streambuf_io_observer other) noexcept +{ + return other; +} + +template> +using basic_streambuf_io_observer = basic_general_streambuf_io_observer>; + +template> +using basic_filebuf_io_observer = basic_general_streambuf_io_observer>; + +using streambuf_io_observer = basic_streambuf_io_observer; +using filebuf_io_observer = basic_filebuf_io_observer; + +using wstreambuf_io_observer = basic_streambuf_io_observer; +using wfilebuf_io_observer = basic_filebuf_io_observer; +#if defined(_LIBCPP_VERSION) || defined(__GLIBCXX__) || defined(_MSVC_STL_UPDATE) +template +requires zero_copy_input_stream> +inline constexpr decltype(auto) zero_copy_in_handle(basic_filebuf_io_observer h) +{ + return zero_copy_in_handle(static_cast>(h)); +} +template +requires zero_copy_output_stream> +inline constexpr decltype(auto) zero_copy_out_handle(basic_filebuf_io_observer h) +{ + return zero_copy_out_handle(static_cast>(h)); +} + +template +inline auto seek(basic_filebuf_io_observer h,std::intmax_t offset=0,seekdir s=seekdir::cur) +{ + h.fb->pubsync(); + return seek(static_cast>(h),offset,s); +} + +template +requires io_controllable,Args...> +inline decltype(auto) io_control(basic_filebuf_io_observer h,Args&& ...args) +{ + return io_control(static_cast>(h),::std::forward(args)...); +} + +template +requires requires(basic_c_io_observer piob) +{ + status(piob); +} +inline constexpr auto status(basic_streambuf_io_observer ciob) +{ + return status(static_cast>(ciob)); +} + +template +requires requires(basic_c_io_observer piob) +{ + status(piob); +} +inline constexpr auto status(basic_filebuf_io_observer ciob) +{ + return status(static_cast>(ciob)); +} + +template +inline constexpr posix_at_entry at(basic_filebuf_io_observer other) noexcept +{ + return posix_at_entry{details::fp_to_fd(details::streambuf_hack::fp_hack(other.fb))}; +} + +template +requires (std::same_as>|| +std::derived_from>) +inline bool is_character_device(basic_general_streambuf_io_observer other) +{ + using char_type = typename T::char_type; + basic_c_io_observer bciob{static_cast>(other)}; + if constexpr(std::same_as>) + { + if(bciob.fp==nullptr) +#ifdef EBADF + throw_posix_error(EBADF); +#else + throw_posix_error(EINVAL); +#endif + } + return is_character_device(bciob); + +} + +template +requires (std::same_as>|| +std::derived_from>) +inline void clear_screen(basic_general_streambuf_io_observer other) +{ + using char_type = typename T::char_type; + basic_c_io_observer bciob{static_cast>(other)}; + if constexpr(std::same_as>) + { + if(bciob.fp==nullptr) +#ifdef EBADF + throw_posix_error(EBADF); +#else + throw_posix_error(EINVAL); +#endif + } +#if defined(__AVR__) + ::fast_io::details::avr_libc_nosup_impl(); +#else + io_lock_guard guard{bciob}; + FILE* fp{bciob.fp}; + int fd{details::fp_unlocked_to_fd(fp)}; +#if defined(_WIN32)&&!defined(__WINE__) + void* handle{details::my_get_osfile_handle(fd)}; + if(!win32::details::win32_is_character_device(handle)) + return; + other.fb->pubsync(); + details::c_flush_unlocked_impl(fp); + win32::details::win32_clear_screen_main(handle); +#else + if(!details::posix_is_character_device(fd)) + return; + other.fb->pubsync(); + details::c_flush_unlocked_impl(fp); + details::posix_clear_screen_main(fd); +#endif +#endif +} +#endif +} + +#include"bp_hack/impl.h" + +namespace fast_io +{ + +namespace details +{ + +template +inline std::size_t streambuf_write_report_eh_impl(std::basic_streambuf* fb, + char_type const* src, std::size_t count) +{ + return static_cast(fb->sputn(src,static_cast(count))); +} + +template +inline std::size_t streambuf_read_report_eh_impl(std::basic_streambuf* fb,char_type* dest, std::size_t count) +{ + return static_cast(fb->sgetn(dest,static_cast(count))); +} + + +template +inline std::size_t streambuf_write_impl(basic_streambuf_io_observer t,char_type const* src, std::size_t count) +{ + auto curr{obuffer_curr(t)}; + auto ed{obuffer_end(t)}; + if(count(ed-curr))[[likely]] + { + traits_type::copy(curr,src,count); + obuffer_set_curr(t,curr+count); + return count; + } + return streambuf_write_report_eh_impl(t.fb,src,count); +} + +template +inline std::size_t streambuf_read_impl(basic_streambuf_io_observer t,char_type* dest, std::size_t count) +{ + auto curr{ibuffer_curr(t)}; + auto ed{ibuffer_end(t)}; + if(count(ed-curr))[[likely]] + { + traits_type::copy(dest,curr,count); + ibuffer_set_curr(t,curr+count); + return count; + } + return streambuf_read_report_eh_impl(t.fb,dest,count); +} + + +} + +template +requires (std::same_as>||std::same_as) +[[nodiscard]] inline Iter read(basic_general_streambuf_io_observer t,Iter begin,Iter end) +{ + using char_type = typename T::char_type; + using traits_type = typename T::traits_type; + if constexpr(std::same_as>) + return begin+details::streambuf_read_impl(basic_streambuf_io_observer{t.fb}, + ::std::to_address(begin),static_cast(end-begin)); + else + return begin+details::streambuf_read_impl(basic_streambuf_io_observer{t.fb}, + reinterpret_cast(::std::to_address(begin)),static_cast(end-begin)*sizeof(*begin))/(*begin); +} + +template +requires (std::same_as>||std::same_as) +inline Iter write(basic_general_streambuf_io_observer t,Iter begin,Iter end) +{ + using char_type = typename T::char_type; + using traits_type = typename T::traits_type; + if constexpr(std::same_as>) + return begin+details::streambuf_write_impl(basic_streambuf_io_observer{t.fb}, + ::std::to_address(begin),static_cast(end-begin)); + else + return begin+details::streambuf_write_impl(basic_streambuf_io_observer{t.fb}, + reinterpret_cast(::std::to_address(begin)),static_cast(end-begin)*sizeof(*begin))/(*begin); +} +//static_assert(value_based_stream); +} diff --git a/src/fast_io/include/fast_io_unit/async.h b/src/fast_io/include/fast_io_unit/async.h new file mode 100644 index 0000000..ad1d265 --- /dev/null +++ b/src/fast_io/include/fast_io_unit/async.h @@ -0,0 +1,54 @@ +#pragma once + +#include + +namespace fast_io +{ +struct task +{ +struct promise_type +{ +constexpr auto get_return_object() noexcept { return task{}; } +constexpr auto initial_suspend() noexcept { return std::suspend_never{}; } +constexpr auto final_suspend() noexcept { return std::suspend_never{}; } +void unhandled_exception() noexcept { __builtin_trap(); } +constexpr void return_void() noexcept {} +}; +}; + +#if defined(_WIN32)&&!defined(__WINE__) || defined(__CYGWIN__) +template +inline constexpr auto async_write(basic_win32_family_io_observer wiob,nt_at_entry ent,void const* buffer,std::size_t buffersize,std::ptrdiff_t diff) +{ + struct awaiter + { + void* handle; + void const* buffer; + std::size_t buffer_size; + std::ptrdiff_t diff; + std::size_t wrtn{}; + constexpr bool await_ready() const noexcept { return false; } + constexpr void await_suspend(std::coroutine_handle<> co_handle) noexcept + { + try + { + ::fast_io::details::iocp_async_write_define(handle,buffer,buffer_size,diff,[this,co_handle](std::size_t written) + { + this->wrtn=written; + co_handle(); + }); + } + catch(fast_io::win32_error e) + { + perrln(handle," ",e); + } + } + constexpr std::size_t await_resume() const noexcept + { + return wrtn; + } + }; + return awaiter{ent.handle,buffer,buffersize,diff}; +} +#endif +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_unit/bitset.h b/src/fast_io/include/fast_io_unit/bitset.h new file mode 100644 index 0000000..33e8b4b --- /dev/null +++ b/src/fast_io/include/fast_io_unit/bitset.h @@ -0,0 +1,83 @@ +#pragma once + +namespace fast_io +{ + +struct bitset_print_reserve_proxy +{ + using manip_tag = manip_tag_t; + + using native_storage_type = +#if defined(_LIBCPP_VERSION) + ::std::size_t +#else + unsigned long +#endif +; + using native_storage_const_pointer +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = native_storage_type const*; + using reference_type = native_storage_const_pointer; + native_storage_const_pointer reference{}; + ::std::size_t bits{}; +}; + +template<::std::integral char_type> +inline constexpr + ::std::size_t print_reserve_size(io_reserve_type_t,bitset_print_reserve_proxy p) noexcept +{ + return p.bits; +} + +namespace details +{ + +template<::std::integral char_type> +inline constexpr char_type* pr_vs_iter_impl(char_type* first,::std::size_t bits, + ::std::unsigned_integral auto p) noexcept +{ + auto last{first+bits}; + for(auto i{last};i!=first;) + { + *(--i)=::fast_io::char_literal_add(p&0x1u); + p>>=1; + } + return last; +} + +template<::std::integral char_type> +inline constexpr char_type* prv_rsv_bitset_impl(char_type* iter,typename bitset_print_reserve_proxy::native_storage_const_pointer ptr,::std::size_t bits) noexcept +{ + using nr_type = typename bitset_print_reserve_proxy::native_storage_type; + constexpr + ::std::size_t bits_per_rep{::std::numeric_limits::digits}; + ::std::size_t const counts{bits/bits_per_rep}; + ::std::size_t const remain_bits{bits%bits_per_rep}; + auto ptr_end{ptr+counts}; + if(remain_bits) + { + iter=pr_vs_iter_impl(iter,remain_bits,*ptr_end); + } + for(;ptr!=ptr_end;iter=pr_vs_iter_impl(iter,bits_per_rep,*(--ptr_end))); + return iter; +} + +} + +template<::std::integral char_type> +inline constexpr char_type* print_reserve_define(io_reserve_type_t,char_type* iter,bitset_print_reserve_proxy p) noexcept +{ + return ::fast_io::details::prv_rsv_bitset_impl(iter,p.reference,p.bits); +} + +template< + ::std::size_t n> +inline bitset_print_reserve_proxy print_alias_define(io_alias_t, + ::std::bitset const& bts) noexcept +{ + return ::fast_io::bitset_print_reserve_proxy{reinterpret_cast<::fast_io::bitset_print_reserve_proxy::native_storage_const_pointer>(__builtin_addressof(bts)),n}; +} + +} diff --git a/src/fast_io/include/fast_io_unit/chrono.h b/src/fast_io/include/fast_io_unit/chrono.h new file mode 100644 index 0000000..622afd3 --- /dev/null +++ b/src/fast_io/include/fast_io_unit/chrono.h @@ -0,0 +1,464 @@ +#pragma once + +namespace fast_io +{ + +template +requires (reserve_printable&&(std::same_as||std::same_as||std::same_as|| + std::same_as>||std::same_as>|| + std::same_as>||std::same_as>|| + std::same_as>||std::same_as>|| + std::same_as>)) +constexpr std::size_t print_reserve_size(io_reserve_type_t>) noexcept +{ + constexpr std::size_t sz{print_reserve_size(io_reserve_type)}; + if constexpr(std::same_as||std::same_as + ||std::same_as||std::same_as>|| + std::same_as>||std::same_as>) + return sz+2; + else if constexpr(std::same_as>) + return sz+3; + else + return sz+1; +} + +template +requires (reserve_printable&&(std::same_as||std::same_as||std::same_as|| + std::same_as>||std::same_as>|| + std::same_as>||std::same_as>|| + std::same_as>||std::same_as>|| + std::same_as>)) +constexpr Iter print_reserve_define(io_reserve_type_t>,Iter it,std::chrono::duration duration) noexcept +{ + it=print_reserve_define(io_reserve_type,it,duration.count()); + if constexpr(std::same_as) + { + if constexpr(std::same_as) + return details::copy_string_literal("ns",it); + else if constexpr(std::same_as) + return details::copy_string_literal(L"ns",it); + else if constexpr(std::same_as) + return details::copy_string_literal(u"ns",it); + else if constexpr(std::same_as) + return details::copy_string_literal(U"ns",it); + else + return details::copy_string_literal(u8"ns",it); + } + else if constexpr(std::same_as) + { + if constexpr(std::same_as) + return details::copy_string_literal("us",it); + else if constexpr(std::same_as) + return details::copy_string_literal(L"us",it); + else if constexpr(std::same_as) + return details::copy_string_literal(u"us",it); + else if constexpr(std::same_as) + return details::copy_string_literal(U"us",it); + else + return details::copy_string_literal(u8"us",it); + } + else if constexpr(std::same_as) + { + if constexpr(std::same_as) + return details::copy_string_literal("ms",it); + else if constexpr(std::same_as) + return details::copy_string_literal(L"ms",it); + else if constexpr(std::same_as) + return details::copy_string_literal(u"ms",it); + else if constexpr(std::same_as) + return details::copy_string_literal(U"ms",it); + else + return details::copy_string_literal(u8"ms",it); + } + else if constexpr(std::same_as>) + { + if constexpr(std::same_as) + *it='s'; + else if constexpr(std::same_as) + *it=L's'; + else + *it=u8's'; + ++it; + return it; + } + else if constexpr(std::same_as>) + { + if constexpr(std::same_as) + return details::copy_string_literal("min",it); + else if constexpr(std::same_as) + return details::copy_string_literal(L"min",it); + else if constexpr(std::same_as) + return details::copy_string_literal(u"min",it); + else if constexpr(std::same_as) + return details::copy_string_literal(U"min",it); + else + return details::copy_string_literal(u8"min",it); + } + else if constexpr(std::same_as>) + { + if constexpr(std::same_as) + *it='h'; + else if constexpr(std::same_as) + *it=L'h'; + else + *it=u8'h'; + ++it; + return it; + } + else if constexpr(std::same_as>) + { + if constexpr(std::same_as) + *it='d'; + else if constexpr(std::same_as) + *it=L'd'; + else + *it=u8'd'; + ++it; + return it; + } + else if constexpr(std::same_as>) + { + if constexpr(std::same_as) + return details::copy_string_literal("wk",it); + else if constexpr(std::same_as) + return details::copy_string_literal(L"wk",it); + else if constexpr(std::same_as) + return details::copy_string_literal(u"wk",it); + else if constexpr(std::same_as) + return details::copy_string_literal(U"wk",it); + else + return details::copy_string_literal(u8"wk",it); + } + else if constexpr(std::same_as>) + { + if constexpr(std::same_as) + return details::copy_string_literal("mo",it); + else if constexpr(std::same_as) + return details::copy_string_literal(L"mo",it); + else if constexpr(std::same_as) + return details::copy_string_literal(u"mo",it); + else if constexpr(std::same_as) + return details::copy_string_literal(U"mo",it); + else + return details::copy_string_literal(u8"mo",it); + } + else if constexpr(std::same_as>) + { + if constexpr(std::same_as) + return details::copy_string_literal("yr",it); + else if constexpr(std::same_as) + return details::copy_string_literal(L"yr",it); + else if constexpr(std::same_as) + return details::copy_string_literal(u"yr",it); + else if constexpr(std::same_as) + return details::copy_string_literal(U"yr",it); + else + return details::copy_string_literal(u8"yr",it); + } +} + + + +#if __cpp_lib_chrono >= 201907L || (defined(__GNUC__) && __GNUC__ >= 11) + +template +inline constexpr std::size_t print_reserve_size(io_reserve_type_t) noexcept +{ + return print_reserve_size(io_reserve_type); +} + +template +inline constexpr Iter print_reserve_define(io_reserve_type_t,Iter it,std::chrono::year year) noexcept +{ + return details::chrono_year_impl(it,static_cast(year)); +} + +template +inline constexpr std::size_t print_reserve_size(io_reserve_type_t) noexcept +{ + return print_reserve_size(io_reserve_type); +} + +template +inline constexpr Iter print_reserve_define(io_reserve_type_t,Iter it,std::chrono::month m) noexcept +{ + return details::chrono_two_digits_impl(it,static_cast(m)); +} + +template +inline constexpr std::size_t print_reserve_size(io_reserve_type_t) noexcept +{ + return print_reserve_size(io_reserve_type); +} + +template +inline constexpr Iter print_reserve_define(io_reserve_type_t,Iter it,std::chrono::day m) noexcept +{ + return details::chrono_two_digits_impl(it,static_cast(m)); +} + +template +inline constexpr std::size_t print_reserve_size(io_reserve_type_t) noexcept +{ + return print_reserve_size(io_reserve_type); +} + +template +inline constexpr Iter print_reserve_define(io_reserve_type_t,Iter it,std::chrono::weekday wkd) noexcept +{ + return details::chrono_one_digit_impl(it,static_cast(wkd.iso_encoding())); +} + + +namespace details +{ + +template +inline constexpr Iter print_reserve_define_ymd_impl(Iter it,T ymd) noexcept +{ + if constexpr(requires() + { + ymd.year(); + }) + { + it=chrono_year_impl(it,static_cast(ymd.year())); + if constexpr(std::same_as) + *it='-'; + else if constexpr(std::same_as) + *it=L'-'; + else + *it=u8'-'; + ++it; + } + else + { + if constexpr(std::same_as) + it=copy_string_literal("--",it); + else if constexpr(std::same_as) + it=copy_string_literal(L"--",it); + else if constexpr(std::same_as) + it=copy_string_literal(u"--",it); + else if constexpr(std::same_as) + it=copy_string_literal(U"--",it); + else + it=copy_string_literal(u8"--",it); + } + it=chrono_two_digits_impl(it,static_cast(ymd.month())); + if constexpr(requires() + { + ymd.day(); + }) + { + if constexpr(std::same_as) + *it='-'; + else if constexpr(std::same_as) + *it=L'-'; + else + *it=u8'-'; + ++it; + return chrono_two_digits_impl(it,static_cast(ymd.day())); + } + else + return it; +} + +} + + +template +inline constexpr std::size_t print_reserve_size(io_reserve_type_t) noexcept +{ + return print_reserve_size(io_reserve_type)+print_reserve_size(io_reserve_type)+3; +} + +template +inline constexpr Iter print_reserve_define(io_reserve_type_t,Iter it,std::chrono::month_day md) noexcept +{ + return details::print_reserve_define_ymd_impl(it,md); +} + +template +inline constexpr std::size_t print_reserve_size(io_reserve_type_t) noexcept +{ + return print_reserve_size(io_reserve_type)+print_reserve_size(io_reserve_type)+1; +} + +template +inline constexpr Iter print_reserve_define(io_reserve_type_t,Iter it,std::chrono::year_month ym) noexcept +{ + return details::print_reserve_define_ymd_impl(it,ym); +} + +template +inline constexpr std::size_t print_reserve_size(io_reserve_type_t) noexcept +{ + return print_reserve_size(io_reserve_type)+print_reserve_size(io_reserve_type)+1; +} + +template +inline constexpr Iter print_reserve_define(io_reserve_type_t,Iter it,std::chrono::year_month_day ymd) noexcept +{ + return details::print_reserve_define_ymd_impl(it,ymd); +} + +template +requires (details::denom_is_natural_pow10(den)) +inline constexpr std::size_t print_reserve_size(io_reserve_type_t>>>) noexcept +{ + if constexpr(den==1) + { + return print_reserve_size(io_reserve_type)+ + print_reserve_size(io_reserve_type)+ + print_reserve_size(io_reserve_type)+3; + } + else + { + return print_reserve_size(io_reserve_type)+ + print_reserve_size(io_reserve_type)+ + print_reserve_size(io_reserve_type)+ + print_reserve_size(io_reserve_type)+4; + } +} + +namespace details +{ + +template +inline constexpr Iter print_hh_mm_ss_reserve_define_impl(Iter it, + std::chrono::hh_mm_ss>> hms) noexcept +{ + if(hms.is_negative()) + { + if constexpr(std::same_as) + *it='-'; + else if constexpr(std::same_as) + *it=L'-'; + else + *it=u8'-'; + ++it; + } + it=chrono_two_digits_impl(it,hms.hours().count()); + if constexpr(std::same_as) + *it=':'; + else if constexpr(std::same_as) + *it=L':'; + else + *it=u8':'; + ++it; + it=chrono_two_digits_impl(it,hms.minutes().count()); + if constexpr(std::same_as) + *it=':'; + else if constexpr(std::same_as) + *it=L':'; + else + *it=u8':'; + ++it; + it=chrono_two_digits_impl(it,hms.seconds().count()); + if constexpr(den==1) + return it; + else + return subseconds_part_print_sz_impl(den),char_type>(it, + static_cast>>(hms.subseconds().count())); +} +} + +template +requires (details::denom_is_natural_pow10(den)) +inline constexpr Iter print_reserve_define( + io_reserve_type_t>>>, + Iter it,std::chrono::hh_mm_ss>> hms) noexcept +{ + return details::print_hh_mm_ss_reserve_define_impl(it,hms); +} + +namespace details +{ + +template +inline constexpr Iter print_system_clock_reserve_impl(Iter it,std::chrono::time_point tp) noexcept +{ + std::chrono::sys_days sdy{std::chrono::time_point_cast(tp)}; + std::chrono::year_month_day ymd(sdy); + it=chrono_year_impl(it,static_cast(ymd.year())); + if constexpr(std::same_as) + *it='-'; + else if constexpr(std::same_as) + *it=L'-'; + else + *it=u8'-'; + ++it; + it=chrono_two_digits_impl(it,static_cast(ymd.month())); + if constexpr(std::same_as) + *it='-'; + else if constexpr(std::same_as) + *it=L'-'; + else + *it=u8'-'; + ++it; + it=chrono_two_digits_impl(it,static_cast(ymd.day())); + if constexpr(std::same_as) + *it='T'; + else if constexpr(std::same_as) + *it=L'T'; + else + *it=u8'T'; + ++it; + std::chrono::hh_mm_ss hms(tp.time_since_epoch()-std::chrono::duration_cast(sdy.time_since_epoch())); + it=chrono_two_digits_impl(it,hms.hours().count()); + if constexpr(std::same_as) + *it=':'; + else if constexpr(std::same_as) + *it=L':'; + else + *it=u8':'; + ++it; + it=chrono_two_digits_impl(it,hms.minutes().count()); + if constexpr(std::same_as) + *it=':'; + else if constexpr(std::same_as) + *it=L':'; + else + *it=u8':'; + ++it; + it=chrono_two_digits_impl(it,hms.seconds().count()); + if constexpr(Duration::period::num==1&&Duration::period::den!=1) + it=subseconds_part_print_sz_impl(Duration::period::den),char_type>( + it,static_cast>>(hms.subseconds().count())); + if constexpr(std::same_as) + *it='Z'; + else if constexpr(std::same_as) + *it=L'Z'; + else + *it=u8'Z'; + ++it; + return it; +} + +} + +template +requires(std::same_as) +inline constexpr std::size_t print_reserve_size(io_reserve_type_t>) noexcept +{ +/* +ISO8601 Time stamp +2020-11-08T07:23:27Z +*/ + return print_reserve_size(io_reserve_type)+sizeof(u8"-11-08T07:23:27Z")+1+print_reserve_size(io_reserve_type); +} +template +requires(std::same_as) +inline constexpr Iter print_reserve_define(io_reserve_type_t> + ,Iter it,std::chrono::time_point tp) noexcept +{ + return details::print_system_clock_reserve_impl(it,tp); +} + +#endif + +} diff --git a/src/fast_io/include/fast_io_unit/complex.h b/src/fast_io/include/fast_io_unit/complex.h new file mode 100644 index 0000000..17efdba --- /dev/null +++ b/src/fast_io/include/fast_io_unit/complex.h @@ -0,0 +1,395 @@ +#pragma once + +namespace fast_io +{ + +namespace manipulators +{ +template +requires (::fast_io::details::my_floating_point) +inline constexpr auto hexfloat(std::complex t) noexcept +{ + if constexpr(std::same_as,long double> +#if defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__) + ||std::same_as,__float128> +#endif + ) + { +#if (defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__)) && defined(__SIZEOF_INT128__) + if constexpr(sizeof(scalar_type)>sizeof(double)) + return scalar_manip_t<::fast_io::details::hexafloat_mani_flags_cache,std::complex<__float128>>{{static_cast<__float128>(::std::real(t)),static_cast<__float128>(::std::imag(t))}}; + else +#endif + return scalar_manip_t<::fast_io::details::hexafloat_mani_flags_cache,std::complex>{{static_cast(::std::real(t)),static_cast(::std::imag(t))}}; + } + else + return scalar_manip_t<::fast_io::details::hexafloat_mani_flags_cache,std::complex>>{{static_cast>(::std::real(t)),static_cast>(::std::imag(t))}}; +} + +template +requires (::fast_io::details::my_floating_point) +inline constexpr auto hexfloat(std::complex t,std::size_t n) noexcept +{ + if constexpr(std::same_as,long double> +#if defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__) + ||std::same_as,__float128> +#endif + ) + { +#if (defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__)) && defined(__SIZEOF_INT128__) + if constexpr(sizeof(scalar_type)>sizeof(double)) + return scalar_manip_precision_t<::fast_io::details::hexafloat_mani_flags_cache,std::complex<__float128>>{{static_cast<__float128>(::std::real(t)),static_cast<__float128>(::std::imag(t))},n}; + else +#endif + return scalar_manip_precision_t<::fast_io::details::hexafloat_mani_flags_cache,std::complex>{{static_cast(::std::real(t)),static_cast(::std::imag(t))},n}; + } + else + return scalar_manip_precision_t<::fast_io::details::hexafloat_mani_flags_cache,std::complex>>{{static_cast>(::std::real(t)),static_cast>(::std::imag(t))},n}; +} + +template +requires (::fast_io::details::my_floating_point) +inline constexpr auto comma_hexfloat(std::complex t) noexcept +{ + if constexpr(std::same_as,long double> +#if defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__) + ||std::same_as,__float128> +#endif + ) + { +#if (defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__)) && defined(__SIZEOF_INT128__) + if constexpr(sizeof(scalar_type)>sizeof(double)) + return scalar_manip_t<::fast_io::details::hexafloat_mani_flags_cache,std::complex<__float128>>{{static_cast<__float128>(::std::real(t)),static_cast<__float128>(::std::imag(t))}}; + else +#endif + return scalar_manip_t<::fast_io::details::hexafloat_mani_flags_cache,std::complex>{{static_cast(::std::real(t)),static_cast(::std::imag(t))}}; + } + else + return scalar_manip_t<::fast_io::details::hexafloat_mani_flags_cache,std::complex>>{{static_cast>(::std::real(t)),static_cast>(::std::imag(t))}}; +} + + +template +requires (::fast_io::details::my_floating_point) +inline constexpr auto comma_hexfloat(std::complex t,std::size_t n) noexcept +{ + if constexpr(std::same_as,long double> +#if defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__) + ||std::same_as,__float128> +#endif + ) + { +#if (defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__)) && defined(__SIZEOF_INT128__) + if constexpr(sizeof(scalar_type)>sizeof(double)) + return scalar_manip_precision_t<::fast_io::details::hexafloat_mani_flags_cache,std::complex<__float128>>{{static_cast<__float128>(::std::real(t)),static_cast<__float128>(::std::imag(t))},n}; + else +#endif + return scalar_manip_precision_t<::fast_io::details::hexafloat_mani_flags_cache,std::complex>{{static_cast(::std::real(t)),static_cast(::std::imag(t))},n}; + } + else + return scalar_manip_precision_t<::fast_io::details::hexafloat_mani_flags_cache,std::complex>>{{static_cast>(::std::real(t)),static_cast>(::std::imag(t))},n}; +} + +template +requires (::fast_io::details::my_floating_point) +inline constexpr auto general(std::complex t) noexcept +{ + if constexpr(std::same_as,long double> +#if defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__) + ||std::same_as,__float128> +#endif + ) + { +#if (defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__)) && defined(__SIZEOF_INT128__) + if constexpr(sizeof(scalar_type)>sizeof(double)) + return scalar_manip_t<::fast_io::details::dcmfloat_mani_flags_cache,std::complex<__float128>>{{static_cast<__float128>(::std::real(t)),static_cast<__float128>(::std::imag(t))}}; + else +#endif + return scalar_manip_t<::fast_io::details::dcmfloat_mani_flags_cache,std::complex>{{static_cast(::std::real(t)),static_cast(::std::imag(t))}}; + } + else + return scalar_manip_t<::fast_io::details::dcmfloat_mani_flags_cache,std::complex>>{{static_cast>(::std::real(t)),static_cast>(::std::imag(t))}}; +} + +template +requires (::fast_io::details::my_floating_point) +inline constexpr auto comma_general(std::complex t) noexcept +{ + if constexpr(std::same_as,long double> +#if defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__) + ||std::same_as,__float128> +#endif + ) + { +#if (defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__)) && defined(__SIZEOF_INT128__) + if constexpr(sizeof(scalar_type)>sizeof(double)) + return scalar_manip_t<::fast_io::details::dcmfloat_mani_flags_cache,std::complex<__float128>>{{static_cast<__float128>(::std::real(t)),static_cast<__float128>(::std::imag(t))}}; + else +#endif + return scalar_manip_t<::fast_io::details::dcmfloat_mani_flags_cache,std::complex>{{static_cast(::std::real(t)),static_cast(::std::imag(t))}}; + } + else + return scalar_manip_t<::fast_io::details::dcmfloat_mani_flags_cache,std::complex>>{{static_cast>(::std::real(t)),static_cast>(::std::imag(t))}}; +} + +template +requires (::fast_io::details::my_floating_point) +inline constexpr auto general(std::complex t,std::size_t n) noexcept +{ + if constexpr(std::same_as,long double> +#if defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__) + ||std::same_as,__float128> +#endif + ) + { +#if (defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__)) && defined(__SIZEOF_INT128__) + if constexpr(sizeof(scalar_type)>sizeof(double)) + return scalar_manip_precision_t<::fast_io::details::dcmfloat_mani_flags_cache,std::complex<__float128>>{{static_cast<__float128>(::std::real(t)),static_cast<__float128>(::std::imag(t))},n}; + else +#endif + return scalar_manip_precision_t<::fast_io::details::dcmfloat_mani_flags_cache,std::complex>{{static_cast(::std::real(t)),static_cast(::std::imag(t))},n}; + } + else + return scalar_manip_precision_t<::fast_io::details::dcmfloat_mani_flags_cache,std::complex>>{{static_cast>(::std::real(t)),static_cast>(::std::imag(t))},n}; +} + +template +requires (::fast_io::details::my_floating_point) +inline constexpr auto comma_general(std::complex t,std::size_t n) noexcept +{ + if constexpr(std::same_as,long double> +#if defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__) + ||std::same_as,__float128> +#endif + ) + { +#if (defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__)) && defined(__SIZEOF_INT128__) + if constexpr(sizeof(scalar_type)>sizeof(double)) + return scalar_manip_precision_t<::fast_io::details::dcmfloat_mani_flags_cache,std::complex<__float128>>{{static_cast<__float128>(::std::real(t)),static_cast<__float128>(::std::imag(t))},n}; + else +#endif + return scalar_manip_precision_t<::fast_io::details::dcmfloat_mani_flags_cache,std::complex>{{static_cast(::std::real(t)),static_cast(::std::imag(t))},n}; + } + else + return scalar_manip_precision_t<::fast_io::details::dcmfloat_mani_flags_cache,std::complex>>{{static_cast>(::std::real(t)),static_cast>(::std::imag(t))},n}; +} + +template +requires (::fast_io::details::my_floating_point) +inline constexpr auto fixed(std::complex t) noexcept +{ + if constexpr(std::same_as,long double> +#if defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__) + ||std::same_as,__float128> +#endif + ) + { +#if (defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__)) && defined(__SIZEOF_INT128__) + if constexpr(sizeof(scalar_type)>sizeof(double)) + return scalar_manip_t<::fast_io::details::dcmfloat_mani_flags_cache,std::complex<__float128>>{{static_cast<__float128>(::std::real(t)),static_cast<__float128>(::std::imag(t))}}; + else +#endif + return scalar_manip_t<::fast_io::details::dcmfloat_mani_flags_cache,std::complex>{{static_cast(::std::real(t)),static_cast(::std::imag(t))}}; + } + else + return scalar_manip_t<::fast_io::details::dcmfloat_mani_flags_cache,std::complex>>{{static_cast>(::std::real(t)),static_cast>(::std::imag(t))}}; +} + +template +requires (::fast_io::details::my_floating_point) +inline constexpr auto comma_fixed(std::complex t) noexcept +{ + if constexpr(std::same_as,long double> +#if defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__) + ||std::same_as,__float128> +#endif + ) + { +#if (defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__)) && defined(__SIZEOF_INT128__) + if constexpr(sizeof(scalar_type)>sizeof(double)) + return scalar_manip_t<::fast_io::details::dcmfloat_mani_flags_cache,std::complex<__float128>>{{static_cast<__float128>(::std::real(t)),static_cast<__float128>(::std::imag(t))}}; + else +#endif + return scalar_manip_t<::fast_io::details::dcmfloat_mani_flags_cache,std::complex>{{static_cast(::std::real(t)),static_cast(::std::imag(t))}}; + } + else + return scalar_manip_t<::fast_io::details::dcmfloat_mani_flags_cache,std::complex>>{{static_cast>(::std::real(t)),static_cast>(::std::imag(t))}}; +} + + +template +requires (::fast_io::details::my_floating_point) +inline constexpr auto fixed(std::complex t,std::size_t n) noexcept +{ + if constexpr(std::same_as,long double> +#if defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__) + ||std::same_as,__float128> +#endif + ) + { +#if (defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__)) && defined(__SIZEOF_INT128__) + if constexpr(sizeof(scalar_type)>sizeof(double)) + return scalar_manip_precision_t<::fast_io::details::dcmfloat_mani_flags_cache,std::complex<__float128>>{{static_cast<__float128>(::std::real(t)),static_cast<__float128>(::std::imag(t))},n}; + else +#endif + return scalar_manip_precision_t<::fast_io::details::dcmfloat_mani_flags_cache,std::complex>{{static_cast(::std::real(t)),static_cast(::std::imag(t))},n}; + } + else + return scalar_manip_precision_t<::fast_io::details::dcmfloat_mani_flags_cache,std::complex>>{{static_cast>(::std::real(t)),static_cast>(::std::imag(t))},n}; +} + +template +requires (::fast_io::details::my_floating_point) +inline constexpr auto comma_fixed(std::complex t,std::size_t n) noexcept +{ + if constexpr(std::same_as,long double> +#if defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__) + ||std::same_as,__float128> +#endif + ) + { +#if (defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__)) && defined(__SIZEOF_INT128__) + if constexpr(sizeof(scalar_type)>sizeof(double)) + return scalar_manip_precision_t<::fast_io::details::dcmfloat_mani_flags_cache,std::complex<__float128>>{{static_cast<__float128>(::std::real(t)),static_cast<__float128>(::std::imag(t))},n}; + else +#endif + return scalar_manip_precision_t<::fast_io::details::dcmfloat_mani_flags_cache,std::complex>{{static_cast(::std::real(t)),static_cast(::std::imag(t))},n}; + } + else + return scalar_manip_precision_t<::fast_io::details::dcmfloat_mani_flags_cache,std::complex>>{{static_cast>(::std::real(t)),static_cast>(::std::imag(t))},n}; +} + +template +requires (::fast_io::details::my_floating_point) +inline constexpr auto scientific(std::complex t) noexcept +{ + if constexpr(std::same_as,long double> +#if defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__) + ||std::same_as,__float128> +#endif + ) + { +#if (defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__)) && defined(__SIZEOF_INT128__) + if constexpr(sizeof(scalar_type)>sizeof(double)) + return scalar_manip_t<::fast_io::details::dcmfloat_mani_flags_cache,std::complex<__float128>>{{static_cast<__float128>(::std::real(t)),static_cast<__float128>(::std::imag(t))}}; + else +#endif + return scalar_manip_t<::fast_io::details::dcmfloat_mani_flags_cache,std::complex>{{static_cast(::std::real(t)),static_cast(::std::imag(t))}}; + } + else + return scalar_manip_t<::fast_io::details::dcmfloat_mani_flags_cache,std::complex>>{{static_cast>(::std::real(t)),static_cast>(::std::imag(t))}}; +} + +template +requires (::fast_io::details::my_floating_point) +inline constexpr auto comma_scientific(std::complex t) noexcept +{ + if constexpr(std::same_as,long double> +#if defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__) + ||std::same_as,__float128> +#endif + ) + { +#if (defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__)) && defined(__SIZEOF_INT128__) + if constexpr(sizeof(scalar_type)>sizeof(double)) + return scalar_manip_t<::fast_io::details::dcmfloat_mani_flags_cache,std::complex<__float128>>{{static_cast<__float128>(::std::real(t)),static_cast<__float128>(::std::imag(t))}}; + else +#endif + return scalar_manip_t<::fast_io::details::dcmfloat_mani_flags_cache,std::complex>{{static_cast(::std::real(t)),static_cast(::std::imag(t))}}; + } + else + return scalar_manip_t<::fast_io::details::dcmfloat_mani_flags_cache,std::complex>>{{static_cast>(::std::real(t)),static_cast>(::std::imag(t))}}; +} + +template +requires (::fast_io::details::my_floating_point) +inline constexpr auto scientific(std::complex t,std::size_t n) noexcept +{ + if constexpr(std::same_as,long double> +#if defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__) + ||std::same_as,__float128> +#endif + ) + { +#if (defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__)) && defined(__SIZEOF_INT128__) + if constexpr(sizeof(scalar_type)>sizeof(double)) + return scalar_manip_precision_t<::fast_io::details::dcmfloat_mani_flags_cache,std::complex<__float128>>{{static_cast<__float128>(::std::real(t)),static_cast<__float128>(::std::imag(t))},n}; + else +#endif + return scalar_manip_precision_t<::fast_io::details::dcmfloat_mani_flags_cache,std::complex>{{static_cast(::std::real(t)),static_cast(::std::imag(t))},n}; + } + else + return scalar_manip_precision_t<::fast_io::details::dcmfloat_mani_flags_cache,std::complex>>{{static_cast>(::std::real(t)),static_cast>(::std::imag(t))},n}; +} + +template +requires (::fast_io::details::my_floating_point) +inline constexpr auto comma_scientific(std::complex t,std::size_t n) noexcept +{ + if constexpr(std::same_as,long double> +#if defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__) + ||std::same_as,__float128> +#endif + ) + { +#if (defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__)) && defined(__SIZEOF_INT128__) + if constexpr(sizeof(scalar_type)>sizeof(double)) + return scalar_manip_precision_t<::fast_io::details::dcmfloat_mani_flags_cache,::std::complex<__float128>>{static_cast<__float128>(t),n}; + else +#endif + return scalar_manip_precision_t<::fast_io::details::dcmfloat_mani_flags_cache,::std::complex>{static_cast(t),n}; + } + else + return scalar_manip_precision_t<::fast_io::details::dcmfloat_mani_flags_cache,std::complex>>{{static_cast>(::std::real(t)),static_cast>(::std::imag(t))},n}; +} + +} + + + +template +requires (::fast_io::details::my_floating_point) +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr auto print_alias_define(io_alias_t,::std::complex t) noexcept +{ + return ::fast_io::mnp::general(t); +} + +namespace details +{ +template<::fast_io::manipulators::scalar_flags flags,typename T,::std::integral char_type> +inline constexpr char_type* print_reserve_complex_impl(char_type* iter,T real,T imag) noexcept +{ + *iter=char_literal_v; + ++iter; + iter=print_reserve_define(io_reserve_type>,iter,::fast_io::manipulators::scalar_manip_t{real}); + *iter=char_literal_v<(flags.comma?u8'.':u8','),char_type>; + ++iter; + iter=print_reserve_define(io_reserve_type>,iter,::fast_io::manipulators::scalar_manip_t{imag}); + *iter=char_literal_v; + ++iter; + return iter; +} +} + +template +requires (flags.base==10) +inline constexpr std::size_t print_reserve_size(io_reserve_type_t>>) noexcept +{ + constexpr std::size_t v{print_reserve_size(io_reserve_type>)}; + constexpr std::size_t res{(v*2u)+3}; + return res; +} + +template<::std::integral char_type,manipulators::scalar_flags flags,details::my_floating_point flt> +requires (flags.base==10) +inline constexpr char_type* print_reserve_define(io_reserve_type_t>>,char_type* iter,manipulators::scalar_manip_t> f) noexcept +{ + return ::fast_io::details::print_reserve_complex_impl(iter,::std::real(f.reference),::std::imag(f.reference)); +} + +} diff --git a/src/fast_io/include/fast_io_unit/filesystem.h b/src/fast_io/include/fast_io_unit/filesystem.h new file mode 100644 index 0000000..5d395db --- /dev/null +++ b/src/fast_io/include/fast_io_unit/filesystem.h @@ -0,0 +1,12 @@ +#pragma once + +namespace fast_io +{ + +inline cross_code_cvt_t print_alias_define(io_alias_t,std::filesystem::path const& pth) noexcept +{ + auto const& native{pth.native()}; + return {{native.c_str(),native.size()}}; +} + +} diff --git a/src/fast_io/include/fast_io_unit/floating.h b/src/fast_io/include/fast_io_unit/floating.h new file mode 100644 index 0000000..079a383 --- /dev/null +++ b/src/fast_io/include/fast_io_unit/floating.h @@ -0,0 +1,2 @@ +#pragma once + diff --git a/src/fast_io/include/fast_io_unit/floating/hexfloat.h b/src/fast_io/include/fast_io_unit/floating/hexfloat.h new file mode 100644 index 0000000..16b8dd3 --- /dev/null +++ b/src/fast_io/include/fast_io_unit/floating/hexfloat.h @@ -0,0 +1,100 @@ +#pragma once +/* +Algorithm: fast_io +Author: cqwrteur +Reference: no reference +Credit: Jk jeon +*/ +namespace fast_io +{ + +namespace details +{ + +template +inline constexpr Iter with_sign_prt_rsv_exponent_hex_impl(Iter iter,std::int_least32_t e2) +{ + using char_type = ::std::iter_value_t; + std::uint_least32_t ue2{static_cast(e2)}; + if(e2<0) + { + ue2=0u-ue2; + *iter=char_literal_v; + } + else + *iter=char_literal_v; + ++iter; + return prt_rsv_exponent_impl(iter,ue2); +} + +template< +bool showbase, +bool showbase_uppercase, +bool showpos, +bool uppercase, +bool uppercase_e, +bool comma, +typename flt,::std::integral char_type> +inline constexpr char_type* print_rsvhexfloat_define_impl(char_type* iter,flt f) noexcept +{ + using trait = iec559_traits; + using mantissa_type = typename trait::mantissa_type; + constexpr std::size_t mbits{trait::mbits}; + constexpr std::size_t ebits{trait::ebits}; + constexpr std::uint_least32_t bias{(static_cast(1<>1)-1}; + constexpr mantissa_type exponent_mask{(static_cast(1)<(exponent_mask)}; + constexpr std::int_least32_t minus_bias{-static_cast(bias)}; + constexpr std::uint_least32_t makeup_bits{((mbits / 4 + 1) * 4 - mbits) % 4};//Thanks jk-jeon for the formula + iter=print_rsv_fp_sign_impl(iter,sign); + if(exponent==exponent_mask_u32) + return prsv_fp_nan_impl(iter,mantissa); + if constexpr(showbase) + iter=print_reserve_show_base_impl<16,showbase_uppercase>(iter); + if(!mantissa&&!exponent) + return prsv_fp_hex0p0(iter); + std::int_least32_t e2{static_cast(exponent)+minus_bias}; + if(mantissa) + { + std::uint_least32_t trailing_zeros_digits{static_cast(my_countr_zero_unchecked(mantissa))+makeup_bits}; + constexpr std::uint_least32_t trailing_zeros_mdigits_d4{static_cast((mbits+makeup_bits)>>2)}; + std::uint_least32_t trailing_zeros_digits_d4{trailing_zeros_digits>>2}; + std::uint_least32_t trailing_zeros_digits_d4m4{trailing_zeros_digits_d4<<2}; + + mantissa<<=makeup_bits; + mantissa>>=trailing_zeros_digits_d4m4; + std::uint_least32_t mantissa_len{trailing_zeros_mdigits_d4-trailing_zeros_digits_d4}; + if(exponent==0) + { + ++e2; + iter=prsv_fp_hex0d(iter); + } + else + iter=prsv_fp_hex1d(iter); + print_reserve_integral_main_impl<16,uppercase>(iter+=mantissa_len,mantissa,mantissa_len); + } + else + { + *iter=char_literal_v; + ++iter; + } + *iter=char_literal_v; + ++iter; + return with_sign_prt_rsv_exponent_hex_impl(iter,e2); +} + + +template< +bool showbase, +typename mantissa_type> +inline constexpr std::size_t print_rsvhexfloat_size_cache +{ +print_integer_reserved_size_cache<16,showbase,true,mantissa_type>+ +6+ +print_integer_reserved_size_cache<10,true,true,std::int_least32_t> +}; + +} + +} diff --git a/src/fast_io/include/fast_io_unit/floating/impl.h b/src/fast_io/include/fast_io_unit/floating/impl.h new file mode 100644 index 0000000..ca0b71f --- /dev/null +++ b/src/fast_io/include/fast_io_unit/floating/impl.h @@ -0,0 +1,104 @@ +#pragma once + +#include"punning.h" +#include"hexfloat.h" +#include"roundtrip.h" + +namespace fast_io +{ + +template +requires (flags.base==10) +inline constexpr std::size_t print_reserve_size(io_reserve_type_t>) noexcept +{ + static_assert(manipulators::floating_format::general==flags.floating|| + manipulators::floating_format::scientific==flags.floating|| + manipulators::floating_format::fixed==flags.floating|| + manipulators::floating_format::decimal==flags.floating|| + manipulators::floating_format::hexfloat==flags.floating); + using trait = ::fast_io::details::iec559_traits; + if constexpr(flags.floating==manipulators::floating_format::hexfloat) + { + if constexpr(std::same_as,long double> +#if defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__) + ||std::same_as,__float128> +#endif + ) + { +#if (defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__)) && defined(__SIZEOF_INT128__) + if constexpr(sizeof(flt)>sizeof(double)) + return details::print_rsvhexfloat_size_cache; + else +#endif + return details::print_rsvhexfloat_size_cache::mantissa_type>; + } + else + return details::print_rsvhexfloat_size_cache; + } + else + { + if constexpr(std::same_as,long double>&&sizeof(flt)==sizeof(double)) //this is the case on xxx-windows-msvc + { + return details::print_rsv_cache; + } + static_assert((std::same_as,double>||std::same_as,float> +#ifdef __STDCPP_FLOAT32_T__ + ||std::same_as,_Float32> +#endif +#ifdef __STDCPP_FLOAT64_T__ + ||std::same_as,_Float64> +#endif + ),"currently only support iec559 float32 and float64, sorry"); + return details::print_rsv_cache,flags.floating>; + } +} + +template<::std::integral char_type,manipulators::scalar_flags flags,details::my_floating_point flt> +requires (flags.base==10) +inline constexpr char_type* print_reserve_define(io_reserve_type_t>, char_type* iter,manipulators::scalar_manip_t f) noexcept +{ + static_assert(manipulators::floating_format::general==flags.floating|| + manipulators::floating_format::scientific==flags.floating|| + manipulators::floating_format::fixed==flags.floating|| + manipulators::floating_format::decimal==flags.floating|| + manipulators::floating_format::hexfloat==flags.floating); + if constexpr(flags.floating==manipulators::floating_format::hexfloat) + { + if constexpr(std::same_as,long double> +#if defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__) + ||std::same_as,__float128> +#endif + ) + { +#if (defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__)) && defined(__SIZEOF_INT128__) + if constexpr(sizeof(flt)>sizeof(double)) + return details::print_rsvhexfloat_define_impl(iter,static_cast<__float128>(f.reference)); + else +#endif + return details::print_rsvhexfloat_define_impl(iter,static_cast(f.reference)); + } + else + return details::print_rsvhexfloat_define_impl(iter,f.reference); + } + else + { + if constexpr(std::same_as,long double>&&sizeof(flt)==sizeof(double)) //this is the case on xxx-windows-msvc + { + return details::print_rsvflt_define_impl(iter,static_cast(f.reference)); + } + else + { + //this is the case for every other platform, including xxx-windows-gnu + static_assert((std::same_as,double>||std::same_as,float> +#ifdef __STDCPP_FLOAT32_T__ + ||std::same_as,_Float32> +#endif +#ifdef __STDCPP_FLOAT64_T__ + ||std::same_as,_Float64> +#endif + ),"currently only support iec559 float32 and float64, sorry"); + return details::print_rsvflt_define_impl(iter,f.reference); + } + } +} +} diff --git a/src/fast_io/include/fast_io_unit/floating/lc_hexfloat.h b/src/fast_io/include/fast_io_unit/floating/lc_hexfloat.h new file mode 100644 index 0000000..68eb894 --- /dev/null +++ b/src/fast_io/include/fast_io_unit/floating/lc_hexfloat.h @@ -0,0 +1,78 @@ +#pragma once +/* +Algorithm: fast_io +Author: cqwrteur +Reference: no reference +Credit: Jk jeon +*/ +namespace fast_io::details +{ + +template< +bool showbase, +bool showbase_uppercase, +bool showpos, +bool uppercase, +bool uppercase_e, +typename flt,::std::integral char_type> +inline constexpr char_type* lc_print_rsvhexfloat_define_impl(char_type* iter,flt f,char_type const* decimal_point_base,std::size_t decimal_point_len) noexcept +{ + using trait = iec559_traits; + using mantissa_type = typename trait::mantissa_type; + constexpr std::size_t mbits{trait::mbits}; + constexpr std::size_t ebits{trait::ebits}; + constexpr std::uint_least32_t bias{(static_cast(1<>1)-1}; + constexpr mantissa_type exponent_mask{(static_cast(1)<(exponent_mask)}; + constexpr std::int_least32_t minus_bias{-static_cast(bias)}; + constexpr std::uint_least32_t makeup_bits{((mbits / 4 + 1) * 4 - mbits) % 4};//Thanks jk-jeon for the formula + iter=print_rsv_fp_sign_impl(iter,sign); + if(exponent==exponent_mask_u32) + return prsv_fp_nan_impl(iter,mantissa); + if constexpr(showbase) + iter=print_reserve_show_base_impl<16,showbase_uppercase>(iter); + if(!mantissa&&!exponent) + return prsv_fp_hex0p0(iter); + std::int_least32_t e2{static_cast(exponent)+minus_bias}; + if(mantissa) + { + std::uint_least32_t trailing_zeros_digits{static_cast(my_countr_zero_unchecked(mantissa))+makeup_bits}; + constexpr std::uint_least32_t trailing_zeros_mdigits_d4{static_cast((mbits+makeup_bits)>>2)}; + std::uint_least32_t trailing_zeros_digits_d4{trailing_zeros_digits>>2}; + std::uint_least32_t trailing_zeros_digits_d4m4{trailing_zeros_digits_d4<<2}; + mantissa<<=makeup_bits; + mantissa>>=trailing_zeros_digits_d4m4; + std::uint_least32_t mantissa_len{trailing_zeros_mdigits_d4-trailing_zeros_digits_d4}; + if(exponent==0) + { + ++e2; + *iter=char_literal_v; + } + else + { + *iter=char_literal_v; + } + ++iter; + if(decimal_point_len==1)[[likely]] + { + *iter=*decimal_point_base; + ++iter; + } + else + { + iter=non_overlapped_copy_n(decimal_point_base,decimal_point_len,iter); + } + print_reserve_integral_main_impl<16,uppercase>(iter+=mantissa_len,mantissa,mantissa_len); + } + else + { + *iter=char_literal_v; + ++iter; + } + *iter=char_literal_v; + ++iter; + return with_sign_prt_rsv_exponent_hex_impl(iter,e2); +} + +} diff --git a/src/fast_io/include/fast_io_unit/floating/lc_impl.h b/src/fast_io/include/fast_io_unit/floating/lc_impl.h new file mode 100644 index 0000000..f3e1526 --- /dev/null +++ b/src/fast_io/include/fast_io_unit/floating/lc_impl.h @@ -0,0 +1,133 @@ +#pragma once + +#include"lc_hexfloat.h" +#include"lc_roundtrip.h" + +namespace fast_io +{ + +namespace details +{ + +template +inline constexpr std::size_t lc_print_rsv_iec559_size(basic_lc_all const* all) +{ + using trait = iec559_traits; + if constexpr(mf==::fast_io::manipulators::floating_format::fixed) + { +//(+/-)(significants+sep) + constexpr std::size_t sum{2}; + constexpr std::size_t digits{trait::e10max+trait::m10digits}; + static_assert(digits!=0); + constexpr std::size_t digitsm1{digits-1}; + return sum+digitsm1+all->numeric.decimal_point.len+digitsm1*all->numeric.thousands_sep.len; + } + else if constexpr(mf==::fast_io::manipulators::floating_format::scientific) + { + constexpr std::size_t sum{print_rsv_cache}; + return sum+all->numeric.decimal_point.len; + } + else + { + constexpr std::size_t sum{3+trait::e10digits}; + constexpr std::size_t digitsplus3{trait::m10digits+3}; + return sum+digitsplus3+all->numeric.decimal_point.len+digitsplus3*all->numeric.thousands_sep.len; + } +} + +template +inline constexpr std::size_t lc_print_reserve_float_size_impl(basic_lc_all const* all) noexcept +{ + static_assert(manipulators::floating_format::general==flags.floating|| + manipulators::floating_format::scientific==flags.floating|| + manipulators::floating_format::fixed==flags.floating|| + manipulators::floating_format::decimal==flags.floating|| + manipulators::floating_format::hexfloat==flags.floating); + if constexpr(flags.floating==manipulators::floating_format::hexfloat) + { + constexpr std::size_t non_lc_reserve_size{print_reserve_size(io_reserve_type>)}; + static_assert(non_lc_reserve_size!=0); + constexpr std::size_t non_lc_reserve_size_m1{non_lc_reserve_size-1u}; + return all->numeric.decimal_point.len+non_lc_reserve_size_m1; + } + else + { + if constexpr(std::same_as,long double>&&sizeof(flt)==sizeof(double)) //this is the case on xxx-windows-msvc + { + return lc_print_rsv_iec559_size(all); + } + static_assert((std::same_as,double>||std::same_as,float> +#ifdef __STDCPP_FLOAT32_T__ + ||std::same_as,_Float32> +#endif +#ifdef __STDCPP_FLOAT64_T__ + ||std::same_as,_Float64> +#endif + ),"currently only support iec559 float32 and float64, sorry"); + return lc_print_rsv_iec559_size,flags.floating>(all); + } +} + +} + +template +requires (flags.base==10) +inline constexpr std::size_t print_reserve_size(basic_lc_all const* all,manipulators::scalar_manip_t) noexcept +{ + return ::fast_io::details::lc_print_reserve_float_size_impl(all); +} + +template<::std::integral char_type,manipulators::scalar_flags flags,details::my_floating_point flt> +requires (flags.base==10) +inline constexpr char_type* print_reserve_define(basic_lc_all const* all, char_type* iter,manipulators::scalar_manip_t f) noexcept +{ + static_assert(manipulators::floating_format::general==flags.floating|| + manipulators::floating_format::scientific==flags.floating|| + manipulators::floating_format::fixed==flags.floating|| + manipulators::floating_format::decimal==flags.floating|| + manipulators::floating_format::hexfloat==flags.floating); + + if constexpr(flags.floating==manipulators::floating_format::hexfloat) + { + auto decimal_point{all->numeric.decimal_point}; + if constexpr(std::same_as,long double> +#if defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__) + ||std::same_as,__float128> +#endif + ) + { +#if (defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__)) && defined(__SIZEOF_INT128__) + if constexpr(sizeof(flt)>sizeof(double)) + return ::fast_io::details::lc_print_rsvhexfloat_define_impl(iter,static_cast<__float128>(f.reference),decimal_point.base,decimal_point.len); + else +#endif + return ::fast_io::details::lc_print_rsvhexfloat_define_impl(iter,static_cast(f.reference),decimal_point.base,decimal_point.len); + } + else + return ::fast_io::details::lc_print_rsvhexfloat_define_impl(iter,f.reference,decimal_point.base,decimal_point.len); + } + else + { + if constexpr(std::same_as,long double>&&sizeof(flt)==sizeof(double)) //this is the case on xxx-windows-msvc + { + return ::fast_io::details::lc_print_rsvflt_define_impl(all,iter,static_cast(f.reference)); + } + else + { + //this is the case for every other platform, including xxx-windows-gnu + static_assert((std::same_as,double>||std::same_as,float> +#ifdef __STDCPP_FLOAT32_T__ + ||std::same_as,_Float32> +#endif +#ifdef __STDCPP_FLOAT64_T__ + ||std::same_as,_Float64> +#endif + ),"currently only support iec559 float32 and float64, sorry"); + return ::fast_io::details::lc_print_rsvflt_define_impl(all,iter,f.reference); + } + return iter; + } +} + + +} diff --git a/src/fast_io/include/fast_io_unit/floating/lc_roundtrip.h b/src/fast_io/include/fast_io_unit/floating/lc_roundtrip.h new file mode 100644 index 0000000..1a66807 --- /dev/null +++ b/src/fast_io/include/fast_io_unit/floating/lc_roundtrip.h @@ -0,0 +1,392 @@ +#pragma once + +namespace fast_io::details +{ +//let the compiler pick the best calling convention. +template<::std::integral char_type,my_unsigned_integral U> +inline constexpr char_type* lc_print_rsv_fp_dgs_common_decay_impl(char_type const* decimal_point_base,std::size_t decimal_point_len,char_type* iter,U m10,std::uint_least32_t m10len) noexcept +{ + auto res{iter+m10len+decimal_point_len}; + print_reserve_integral_main_impl<10,false,true>(res,m10,m10len); + *iter=iter[decimal_point_len]; + ++iter; + if(decimal_point_len==1)[[likely]] + *iter=*decimal_point_base; + else + iter=non_overlapped_copy_n(decimal_point_base,decimal_point_len,iter); + return res; +} + +template<::std::integral char_type,my_unsigned_integral U> +inline constexpr char_type* lc_print_rsv_fp_dgs_common_impl(basic_io_scatter_t const& decimal_point_ref,char_type* iter,U m10,std::uint_least32_t m10len) noexcept +{ + basic_io_scatter_t decimal_point{decimal_point_ref}; + return lc_print_rsv_fp_dgs_common_decay_impl(decimal_point.base,decimal_point.len,iter,m10,m10len); +} + +template<::std::integral char_type,my_unsigned_integral U> +inline constexpr char_type* lc_print_rsv_fp_decimal_common_impl(basic_io_scatter_t const& decimal_point_ref,char_type* iter,U m10,std::uint_least32_t m10len) noexcept +{ + if(m10len==1)[[unlikely]] + { + *iter=::fast_io::char_literal_add(m10); + ++iter; + return iter; + } + else + return lc_print_rsv_fp_dgs_common_impl(decimal_point_ref,iter,m10,m10len); +} +struct lc_fixed_carrier +{ + std::int_least32_t olength; + std::int_least32_t real_exp; +}; + +template +inline constexpr char_type* lc_no_grouping_fixed_case1_integer_and_point(char_type* iter,typename iec559_traits::mantissa_type m10,lc_fixed_carrier carrier,basic_io_scatter_t const& decimal_point) noexcept +{ + std::int_least32_t olength{carrier.olength}; + std::int_least32_t real_exp{carrier.real_exp}; + auto eposition(real_exp+1); + if(olength==eposition) + print_reserve_integral_main_impl<10,false,true>(iter+=olength,m10,static_cast(olength)); + else + { + auto tmp{iter}; + auto decimal_point_base{decimal_point.base}; + std::size_t const decimal_point_len{decimal_point.len}; + print_reserve_integral_main_impl<10,false,true>(iter+=olength+decimal_point_len,m10,static_cast(olength)); + my_copy_n(tmp+decimal_point_len,static_cast(eposition),tmp); + if(decimal_point_len==1u)[[likely]] + tmp[eposition]=*decimal_point_base; + else + { + non_overlapped_copy_n(decimal_point_base,decimal_point_len,tmp+eposition); + } + } + return iter; +} + +template +inline constexpr char_type* lc_grouping_fixed_case2_all_point(char_type* iter,typename iec559_traits::mantissa_type m10,lc_fixed_carrier carrier,basic_io_scatter_t const& decimal_point) noexcept +{ + *iter=char_literal_v; + ++iter; + auto decimal_point_base{decimal_point.base}; + std::size_t const decimal_point_len{decimal_point.len}; + if(decimal_point_len==1u) + { + *iter=*decimal_point_base; + ++iter; + } + else + { + iter=non_overlapped_copy_n(decimal_point_base,decimal_point_len,iter); + } + std::int_least32_t olength{carrier.olength}; + std::int_least32_t real_exp{carrier.real_exp}; + iter=fill_zeros_impl(iter,static_cast(-real_exp-1)); + print_reserve_integral_main_impl<10,false,true>(iter+=olength,m10,static_cast(olength)); + return iter; +} + +template<::std::integral char_type> +constexpr char_type* lc_grouping_single_sep_ch_impl(std::size_t const* grouping_base,std::size_t grouping_len,char_type* first,char_type* last,char_type* out_reverse,char_type replacement_ch) noexcept +{ + auto iter{last}; + std::size_t i{}; + for(;i!=grouping_len;++i) + { + auto e{grouping_base[i]}; + if(e==0) + break; + for(std::size_t j{};j!=e;++j) + { + *--out_reverse=*--iter; + if(iter==first) + return out_reverse; + } + *--out_reverse=replacement_ch; + } + if(i!=grouping_len) + { + for(;;) + { + *--out_reverse=*--iter; + if(iter==first) + return out_reverse; + } + } + else + { + for(std::size_t e{grouping_base[i-1]};;*--out_reverse=replacement_ch) + { + for(std::size_t j{};j!=e;++j) + { + *--out_reverse=*--iter; + if(iter==first) + return out_reverse; + } + } + } + return out_reverse; +} + +template<::std::random_access_iterator srcIter,::std::random_access_iterator destIter> +inline constexpr destIter grouping_handle_buffer_internal(srcIter first,srcIter last,destIter dest,std::size_t const* grouping_base,std::size_t grouping_len, +::std::iter_value_t const* thousands_sep_base,std::size_t thousands_sep_len,::std::iter_value_t* buffer_end) noexcept +{ + using char_type = ::std::iter_value_t; + char_type seperator_ch{char_literal_v}; + bool sep_single_character{thousands_sep_len==1}; + if(sep_single_character) + { + seperator_ch=*thousands_sep_base; + } + auto buffer_start{lc_grouping_single_sep_ch_impl(grouping_base,grouping_len,first,last,buffer_end,seperator_ch)}; + if(sep_single_character) + return non_overlapped_copy(buffer_start,buffer_end,dest); + else + return grouping_mul_sep_print_sep_impl(thousands_sep_base,thousands_sep_len,buffer_start,buffer_end,dest); +} + +template +requires (digits<(SIZE_MAX>>1u)) +inline constexpr destIter grouping_handle_buffer(srcIter first,srcIter last,destIter dest,std::size_t const* grouping_base,std::size_t grouping_len, +::std::iter_value_t const* thousands_sep_base,std::size_t thousands_sep_len) noexcept +{ + using char_type = ::std::iter_value_t; + constexpr std::size_t allocated_buffer_size{digits<<1u}; + char_type buffer[allocated_buffer_size]; + return grouping_handle_buffer_internal(first,last,dest,grouping_base,grouping_len,thousands_sep_base,thousands_sep_len,buffer+allocated_buffer_size); +} + +template +inline constexpr Iter lc_grouping_fixed_case1_integer_and_point(Iter iter,typename iec559_traits::mantissa_type m10,lc_fixed_carrier carrier,basic_io_scatter_t<::std::iter_value_t> const& decimal_point, +std::size_t const* grouping_base,std::size_t grouping_len,::std::iter_value_t const* thousands_sep_base,std::size_t thousands_sep_len) noexcept +{ + using trait = iec559_traits; + constexpr std::size_t m10total_digits{trait::m10digits+trait::e10digits+2}; + using char_type = ::std::iter_value_t; + std::int_least32_t olength{carrier.olength}; + std::int_least32_t real_exp{carrier.real_exp}; + auto eposition(real_exp+1); + if(olength==eposition) + { + char_type buffer1[m10total_digits]; + auto buffer1_end{buffer1+olength}; + print_reserve_integral_main_impl<10,false,true>(buffer1_end,m10,static_cast(olength)); + return grouping_handle_buffer(buffer1,buffer1_end,iter,grouping_base,grouping_len,thousands_sep_base,thousands_sep_len); + } + else + { + char_type buffer1[m10total_digits]; + auto buffer1_end{buffer1+olength}; + print_reserve_integral_main_impl<10,false,true>(buffer1_end,m10,static_cast(olength)); + iter=grouping_handle_buffer(buffer1,buffer1+eposition,iter,grouping_base,grouping_len,thousands_sep_base,thousands_sep_len); + auto decimal_point_base{decimal_point.base}; + auto decimal_point_len{decimal_point.len}; + if(decimal_point_len==1u) + { + *iter=*decimal_point_base; + ++iter; + } + else + { + iter=non_overlapped_copy_n(decimal_point_base,decimal_point_len,iter); + } + iter=non_overlapped_copy(buffer1+eposition,buffer1_end,iter); + } + return iter; +} + +template +inline constexpr char_type* lc_print_rsv_fp_fixed_decision_impl(basic_lc_all const* all,char_type* iter,typename iec559_traits::mantissa_type m10,std::int_least32_t e10) noexcept +{ + auto const& numeric_ref{all->numeric}; + auto thousands_sep{numeric_ref.thousands_sep}; + auto thousands_sep_base{thousands_sep.base}; + auto thousands_sep_len{thousands_sep.len}; + auto grouping{numeric_ref.grouping}; + auto grouping_base{grouping.base}; + auto grouping_len{grouping.len}; + std::int_least32_t olength(static_cast(chars_len<10,true>(m10))); + std::int_least32_t const real_exp(static_cast(e10 + olength - 1)); + bool no_grouping_grouping_case{((grouping_len==0u)||(thousands_sep_len==0u))}; //no grouping. for case like "C" or "POSIX" + if(olength<=real_exp) + { + if(no_grouping_grouping_case) + { + return fixed_case0_full_integer(iter,m10,olength,real_exp); + } + else + { + using trait = iec559_traits; + constexpr std::size_t m10total_digits{trait::m10digits+trait::e10max+2}; + char_type buffer1[m10total_digits]; + auto buffer1_end{fixed_case0_full_integer(buffer1,m10,olength,real_exp)}; + return grouping_handle_buffer(buffer1,buffer1_end,iter,grouping_base,grouping_len,thousands_sep_base,thousands_sep_len); + } + } + else if(0<=real_exp&&real_exp(iter,m10,{olength,real_exp},numeric_ref.decimal_point); + } + else + { + return lc_grouping_fixed_case1_integer_and_point(iter,m10,{olength,real_exp},numeric_ref.decimal_point,grouping_base,grouping_len,thousands_sep_base,thousands_sep_len); + } + } + else + { + return lc_grouping_fixed_case2_all_point(iter,m10,{olength,real_exp},numeric_ref.decimal_point); + } +} + +template< +typename flt, +bool uppercase_e, +::fast_io::manipulators::floating_format mt, +::std::integral char_type> +inline constexpr char_type* lc_print_rsv_fp_decision_impl(basic_lc_all const* all,char_type* iter,typename iec559_traits::mantissa_type m10,std::int_least32_t e10) noexcept +{ + if constexpr(mt==::fast_io::manipulators::floating_format::general) + { + if(-5(all,iter,m10,e10); + } + return lc_print_rsv_fp_decision_impl(all,iter,m10,e10); + } + else if constexpr(mt==::fast_io::manipulators::floating_format::scientific) + { + if(m10<10u)[[unlikely]] + { + *iter=::fast_io::char_literal_add(m10); + ++iter; + } + else + { + std::uint_least32_t olength{static_cast(chars_len<10,true>(m10))}; + std::uint_least32_t sz{static_cast(olength-1u)}; + e10+=static_cast(sz); + iter=lc_print_rsv_fp_dgs_common_impl(all->numeric.decimal_point,iter,m10,olength); + } + return print_rsv_fp_e_impl(iter,e10); + } + else //decimal + { + std::int_least32_t olength{static_cast(chars_len<10,true>(m10))}; + std::int_least32_t const real_exp{static_cast(e10 + olength - 1)}; + std::uint_least32_t fixed_length{},this_case{}; + if(olength<=real_exp) + { + fixed_length=static_cast(real_exp+1); + this_case=1; + } + else if(0<=real_exp&&real_exp(olength+2); + if(olength==real_exp+1) + --fixed_length; + this_case=2; + } + else + fixed_length=static_cast(static_cast(-real_exp)+static_cast(olength)+1u); + std::uint_least32_t scientific_length{static_cast(olength==1?olength+3:olength+5)}; + auto const& numeric_ref{all->numeric}; + if(scientific_length(olength)); + return print_rsv_fp_e_impl(iter,real_exp); + } + //fixed decision + auto thousands_sep{numeric_ref.thousands_sep}; + auto thousands_sep_base{thousands_sep.base}; + auto thousands_sep_len{thousands_sep.len}; + auto grouping{numeric_ref.grouping}; + auto grouping_base{grouping.base}; + auto grouping_len{grouping.len}; + bool no_grouping_grouping_case{((grouping_len==0u)||(thousands_sep_len==0u))}; //no grouping. for case like "C" or "POSIX" + using trait = iec559_traits; + constexpr std::size_t m10total_digits{trait::m10digits+trait::e10digits+2}; + switch(this_case) + { + case 1: + { + if(no_grouping_grouping_case) + { + return fixed_case0_full_integer(iter,m10,olength,real_exp); + } + else + { + char_type buffer1[m10total_digits]; + auto buffer1_end{fixed_case0_full_integer(buffer1,m10,olength,real_exp)}; + return grouping_handle_buffer(buffer1,buffer1_end,iter,grouping_base,grouping_len,thousands_sep_base,thousands_sep_len); + } + } + case 2: + { + if(no_grouping_grouping_case) + { + return lc_no_grouping_fixed_case1_integer_and_point(iter,m10,{olength,real_exp},numeric_ref.decimal_point); + } + else + { + return lc_grouping_fixed_case1_integer_and_point(iter,m10,{olength,real_exp},numeric_ref.decimal_point,grouping_base,grouping_len,thousands_sep_base,thousands_sep_len); + } + } + default: + { + return lc_grouping_fixed_case2_all_point(iter,m10,{olength,real_exp},numeric_ref.decimal_point); + } + } + } +} + +template< +bool showpos, +bool uppercase, +bool uppercase_e, +::fast_io::manipulators::floating_format mt, +typename flt,::std::integral char_type> +inline constexpr char_type* lc_print_rsvflt_define_impl(basic_lc_all const* all,char_type* iter,flt f) noexcept +{ + if constexpr(::fast_io::manipulators::floating_format::fixed==mt&&uppercase_e) + { + return lc_print_rsvflt_define_impl(all,iter,f); + } + else + { + using trait = iec559_traits; + using mantissa_type = typename trait::mantissa_type; + constexpr std::size_t ebits{trait::ebits}; + constexpr mantissa_type exponent_mask{(static_cast(1)<(exponent_mask)}; + auto [mantissa,exponent,sign] = get_punned_result(f); + iter=print_rsv_fp_sign_impl(iter,sign); + if(exponent==exponent_mask_u32) + return prsv_fp_nan_impl(iter,mantissa); + if(!mantissa&&!exponent) + { + if constexpr(mt!=::fast_io::manipulators::floating_format::scientific) + { + *iter=char_literal_v; + ++iter; + return iter; + } + else + return prsv_fp_dece0(iter); + } + auto [m10,e10] = dragonbox_impl(mantissa,static_cast(exponent)); + if constexpr(mt==::fast_io::manipulators::floating_format::fixed) + return lc_print_rsv_fp_fixed_decision_impl(all,iter,m10,e10); + else + return lc_print_rsv_fp_decision_impl(all,iter,m10,e10); + } +} + +} diff --git a/src/fast_io/include/fast_io_unit/floating/precision.h b/src/fast_io/include/fast_io_unit/floating/precision.h new file mode 100644 index 0000000..5d4c913 --- /dev/null +++ b/src/fast_io/include/fast_io_unit/floating/precision.h @@ -0,0 +1,367 @@ +#pragma once + +namespace fast_io +{ +namespace details::precisionfloat +{ + +template +requires (sizeof(T)==sizeof(std::uint_least16_t)||sizeof(T)==sizeof(std::uint_least32_t)||sizeof(T)==sizeof(std::uint_least64_t)) +inline constexpr T factor_mulassign{sizeof(std::uint_least16_t)==sizeof(T)?100u:(sizeof(std::uint_least32_t)==sizeof(T)?10000u:1000000000ULL)}; + +template +requires (sizeof(T)==sizeof(std::uint_least16_t)||sizeof(T)==sizeof(std::uint_least32_t)||sizeof(T)==sizeof(std::uint_least64_t)) +inline constexpr std::uint_least32_t factor_mulassigndigits{sizeof(std::uint_least16_t)==sizeof(T)?2:(sizeof(std::uint_least32_t)==sizeof(T)?4:9)}; + +template +inline constexpr std::size_t mulassign(T* data, + T* __restrict temp, + std::size_t na, + T const* bdatai, + std::size_t nb) noexcept +{ + std::size_t nab{na+nb}; + for(std::size_t i{};i!=nab;++i) + { + temp[i]=0; + } + for(std::size_t i{};i!=na;++i) + { + auto ini{data[i]}; + auto tempi{temp+i}; + for(std::size_t j{};j!=nb;++j) + { + tempi[j]+=ini*bdatai[j]; + } + } + T carry{}; + for(std::size_t i{};i!=nab;++i) + { + T outi{temp[i]+carry}; + carry=0; + if(factor_mulassign<=outi) + { + T t{outi/factor_mulassign}; + T mi{outi%factor_mulassign}; + carry=t; + outi=mi; + } + data[i]=outi; + } + if(carry) + { + data[nab]=carry; + ++nab; + } + for(;nab&&!data[nab-1];--nab); + return nab; +} + +template +inline constexpr std::size_t sqrassign(T* __restrict data, + T* __restrict temp,std::size_t n) noexcept +{ + return mulassign(data,temp,n,data,n); +} + +template +inline constexpr std::size_t mulv(T* data,std::size_t n,std::uint_least32_t constant) noexcept +{ + T carry{}; + for(std::size_t i{};i!=n;++i) + { + T temp{data[i]*constant+carry}; + carry=0; + if(factor_mulassign<=temp) + { + T t{temp/factor_mulassign}; + T mi{temp%factor_mulassign}; + carry=t; + temp=mi; + } + data[i]=temp; + } + if(carry) + { + data[n]=carry; + ++n; + } + return n; +} + +template +inline constexpr std::size_t pow_full(T* __restrict res, + T* __restrict temp, + T* __restrict base,std::uint_least32_t exponent) noexcept +{ + *res=1; + std::size_t nbase{1}; + std::size_t nres{1}; + for(;exponent;) + { + if(exponent&1) + { + if(nres==1&&*res==1) + { + for(std::size_t i{};i!=nbase;++i) + { + res[i]=base[i]; + } + nres=nbase; + } + else + { + nres=mulassign(res,temp,nres,base,nbase); + } + } + exponent>>=1; + nbase=sqrassign(base,temp,nbase); + } + return nres; +} + +template +inline constexpr std::size_t precisionincrement(T* res,std::size_t n) noexcept +{ + for(std::size_t i{};i!=n;++i) + { + if((++res[i])!=factor_mulassign) + { + return n; + } + } + return n+1; +} +template +inline constexpr std::uint_least32_t chars_len_precision_tree(std::uint_least32_t u) noexcept +{ + if constexpr(left==right) + { + return chars_len_precision_tree(u); + } + else if constexpr(left+1==right) + { + if(u<(::fast_io::details::compile_pow10)) + { + return left; + } + else + { + return right; + } + } + else if constexpr(left+2==right) + { + if(u<(::fast_io::details::compile_pow10)) + { + return left; + } + else + { + return chars_len_precision_tree(u); + } + } + else if constexpr(left==0) + { + if(u<100u) + { + return chars_len_precision_tree<0,1>(u); + } + else + { + return chars_len_precision_tree<2,right>(u); + } + } + else + { + constexpr std::size_t middle{(left+right)/2}; + if(u<(::fast_io::details::compile_pow10)) + { + return chars_len_precision_tree(u); + } + else + { + return chars_len_precision_tree(u); + } + } +} + +inline constexpr std::size_t chars_len_precision(std::size_t u) noexcept +{ + return chars_len_precision_tree<0,factor_mulassigndigits-1>(static_cast(u))+1; +} + +template +inline constexpr std::size_t total_length(T const* data,std::size_t resn1) noexcept +{ + if(resn1==0) + { + return 0; + } + std::size_t ndigits{(resn1-1)*factor_mulassigndigits}; + ndigits+=chars_len_precision(data[resn1-1]); + return ndigits; +} + +template +inline constexpr + ::std::uint_least32_t requiredbuffersizevamx{ + ((iec559_traits::e10max+iec559_traits::m10digits)+100)/factor_mulassigndigits+1}; + +template +inline constexpr std::size_t precision_m2_e2_common(std::size_t* res,typename iec559_traits::mantissa_type m2,std::int_least32_t e2) noexcept +{ + using trait = iec559_traits; + using mantissa_type = typename iec559_traits::mantissa_type; + + + constexpr + ::std::uint_least32_t m10digits{iec559_traits::m10digits}; + constexpr + ::std::uint_least32_t digitsperunsigned{m10digits/factor_mulassigndigits}; + constexpr + ::std::uint_least32_t digitsmod{m10digits%factor_mulassigndigits}; + constexpr + ::std::uint_least32_t requiredbuffersize{digitsperunsigned+(digitsmod!=0)}; + ::std::size_t tempbuffer[requiredbuffersizevamx], + base[requiredbuffersizevamx]; + ::std::size_t resn1{1}; + std::uint_least32_t e2abs{}; + if(e2<0) + { + *base=5; + e2abs=static_cast(-e2); + } + else + { + *base=2; + e2abs=e2; + } + resn1=pow_full(res,tempbuffer,base,e2abs); + ::std::size_t basei{}; + if constexpr(requiredbuffersize==1) + { + *base=static_cast(m2); + basei=1; + } + else + { + for(;m2;++basei) + { + ::std::size_t temp{m2%factor_mulassign}; + m2/=factor_mulassign; + base[basei]=temp; + } + } + return mulassign(res,tempbuffer,resn1,base,basei); +} +#if 0 +template +inline constexpr std::uint_fast8_t precisionindex(std::size_t* res,std::size_t resn,T val,std::size_t pos) noexcept +{ + return 0; +} +#endif +template +inline constexpr char_type* precision_m2_e2(typename iec559_traits::mantissa_type m2,std::int_least32_t e2,char_type* iter,std::size_t precision) noexcept +{ + using trait = iec559_traits; + using mantissa_type = typename iec559_traits::mantissa_type; + constexpr std::size_t mbits{trait::mbits}; + constexpr std::size_t ebits{trait::ebits}; + constexpr std::uint_least32_t bias{(static_cast(1<>1)-1}; + constexpr std::int_least32_t exponent_bias{bias+mbits}; + constexpr mantissa_type mflags{static_cast(static_cast(1)<(exponent_bias)}; + e2=e2bias; + } + else + { + e2-=exponent_bias; + m2|=mflags; + if(e2==0) + { + return iter; + } + } + ::std::size_t res[requiredbuffersizevamx]; + ::std::size_t n{precision_m2_e2_common(res,m2,e2)}; + + ::std::size_t const length{total_length(res,n)}; + ::std::int_least32_t const lengthl32{static_cast(static_cast(length))}; + ::std::int_least32_t const lengthpluse2{lengthl32+e2}; + if constexpr(mt==::fast_io::manipulators::floating_format::scientific) + { + if(lengthpluse2<0) + { + + } + else + { + + } + } + else if constexpr(mt==::fast_io::manipulators::floating_format::generic) + { + + } + else if constexpr(mt==::fast_io::manipulators::floating_format::fixed) + { + + } + return iter; +} + +template +inline constexpr char_type* precision_flt(char_type* iter,flttype f,std::size_t precision) noexcept +{ + auto [mantissa,exponent,sign] = get_punned_result(f); + iter=print_rsv_fp_sign_impl(iter,sign); + using trait = iec559_traits; + using mantissa_type = typename trait::mantissa_type; + constexpr std::size_t ebits{trait::ebits}; + constexpr mantissa_type exponent_mask{(static_cast(1)<(exponent_mask)}; + if(exponent==exponent_mask_u32) + return prsv_fp_nan_impl(iter,mantissa!=0u); + if(!mantissa&&!exponent) + { + if constexpr(mt!=::fast_io::manipulators::floating_format::scientific) + { + *iter=char_literal_v; + ++iter; + return iter; + } + else + return prsv_fp_dece0(iter); + } + return precision_m2_e2(mantissa,exponent,iter,precision); +} + +#if 0 +template +inline constexpr char_type* precision_m2_e2(typename iec559_traits::mantissa_type m2,std::int_least32_t e2,char_type* iter) noexcept +{ + constexpr + ::std::uint_least32_t vamx{(iec559_traits::e10max+iec559_traits::m10digits)+100}; + constexpr + ::std::uint_least32_t requiredbuffersizevamx{vamx/factor_mulassigndigits+1}; + ::std::size_t res[requiredbuffersizevamx]; +} +#endif +} +} \ No newline at end of file diff --git a/src/fast_io/include/fast_io_unit/floating/punning.h b/src/fast_io/include/fast_io_unit/floating/punning.h new file mode 100644 index 0000000..61c217c --- /dev/null +++ b/src/fast_io/include/fast_io_unit/floating/punning.h @@ -0,0 +1,633 @@ +#pragma once + +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning(push) +#pragma warning( disable : 4820 ) +#endif + +namespace fast_io::details +{ + +template +struct iec559_traits; + + +#if defined(__SIZEOF_FLOAT16__) || defined(__FLOAT16__) +template<> +struct iec559_traits<__float16> +{ + using mantissa_type = std::uint_least16_t; + inline static constexpr std::size_t mbits{10}; + inline static constexpr std::size_t ebits{5}; + inline static constexpr std::uint_least32_t m10digits{4}; + inline static constexpr std::uint_least32_t m2hexdigits{3}; + inline static constexpr std::uint_least32_t e10digits{2}; + inline static constexpr std::uint_least32_t e2hexdigits{2}; + inline static constexpr std::uint_least32_t e10max{7}; +}; +#endif + +template<> +struct iec559_traits +{ + using mantissa_type = std::uint_least32_t; + inline static constexpr std::size_t mbits{23}; + inline static constexpr std::size_t ebits{8}; + inline static constexpr std::uint_least32_t m10digits{9}; + inline static constexpr std::uint_least32_t m2hexdigits{6}; + inline static constexpr std::uint_least32_t e10digits{2}; + inline static constexpr std::uint_least32_t e2hexdigits{3}; + inline static constexpr std::uint_least32_t e10max{38}; +}; + +template<> +struct iec559_traits +{ + using mantissa_type = std::uint_least64_t; + inline static constexpr std::size_t mbits{52}; + inline static constexpr std::size_t ebits{11}; + inline static constexpr std::uint_least32_t m10digits{17}; + inline static constexpr std::uint_least32_t m2hexdigits{13}; + inline static constexpr std::uint_least32_t e10digits{3}; + inline static constexpr std::uint_least32_t e2hexdigits{4}; + inline static constexpr std::uint_least32_t e10max{308}; +}; + +#if defined(__SIZEOF_INT128__) + +#if defined(__SIZEOF_FLOAT128__) || defined(__FLOAT128__) +template<> +struct iec559_traits<__float128> +{ + using mantissa_type = __uint128_t; + inline static constexpr std::size_t mbits{112}; + inline static constexpr std::size_t ebits{15}; + inline static constexpr std::uint_least32_t m10digits{37}; + inline static constexpr std::uint_least32_t m2hexdigits{28}; + inline static constexpr std::uint_least32_t e10digits{4}; + inline static constexpr std::uint_least32_t e2hexdigits{5}; + inline static constexpr std::uint_least32_t e10max{4966}; +}; +#endif + +#endif + +#ifdef __STDCPP_FLOAT16_T__ +template<> +struct iec559_traits<_Float16> +{ + using mantissa_type = std::uint_least16_t; + inline static constexpr std::size_t mbits{10}; + inline static constexpr std::size_t ebits{5}; + inline static constexpr std::uint_least32_t m10digits{4}; + inline static constexpr std::uint_least32_t m2hexdigits{3}; + inline static constexpr std::uint_least32_t e10digits{2}; + inline static constexpr std::uint_least32_t e2hexdigits{2}; + inline static constexpr std::uint_least32_t e10max{7}; +}; +#endif + +#ifdef __STDCPP_FLOAT32_T__ +template<> +struct iec559_traits<_Float32> +{ + using mantissa_type = std::uint_least32_t; + inline static constexpr std::size_t mbits{23}; + inline static constexpr std::size_t ebits{8}; + inline static constexpr std::uint_least32_t m10digits{9}; + inline static constexpr std::uint_least32_t m2hexdigits{6}; + inline static constexpr std::uint_least32_t e10digits{2}; + inline static constexpr std::uint_least32_t e2hexdigits{3}; + inline static constexpr std::uint_least32_t e10max{38}; +}; +#endif + +#ifdef __STDCPP_FLOAT64_T__ +template<> +struct iec559_traits<_Float64> +{ + using mantissa_type = std::uint_least64_t; + inline static constexpr std::size_t mbits{52}; + inline static constexpr std::size_t ebits{11}; + inline static constexpr std::uint_least32_t m10digits{17}; + inline static constexpr std::uint_least32_t m2hexdigits{13}; + inline static constexpr std::uint_least32_t e10digits{3}; + inline static constexpr std::uint_least32_t e2hexdigits{4}; + inline static constexpr std::uint_least32_t e10max{308}; +}; +#endif + +#if defined(__STDCPP_FLOAT128_T__) && defined(__SIZEOF_INT128__) +template<> +struct iec559_traits<_Float128> +{ + using mantissa_type = __uint128_t; + inline static constexpr std::size_t mbits{112}; + inline static constexpr std::size_t ebits{15}; + inline static constexpr std::uint_least32_t m10digits{37}; + inline static constexpr std::uint_least32_t m2hexdigits{28}; + inline static constexpr std::uint_least32_t e10digits{4}; + inline static constexpr std::uint_least32_t e2hexdigits{5}; + inline static constexpr std::uint_least32_t e10max{4966}; +}; +#endif + +#ifdef __STDCPP_BFLOAT16_T__ + +/* +To do: change the value +*/ +template<> +struct iec559_traits +{ + using mantissa_type = std::uint_least16_t; + inline static constexpr std::size_t mbits{7}; + inline static constexpr std::size_t ebits{8}; + inline static constexpr std::uint_least32_t m10digits{4}; + inline static constexpr std::uint_least32_t m2hexdigits{3}; + inline static constexpr std::uint_least32_t e10digits{2}; + inline static constexpr std::uint_least32_t e2hexdigits{2}; + inline static constexpr std::uint_least32_t e10max{7}; +}; +#endif + +template +#if defined(_MSC_VER) && !defined(__clang__) +#if __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +#endif +inline constexpr int my_countr_zero_unchecked(T x) noexcept //contract: t cannot be zero +{ +//referenced from libstdc++ +#if defined(__GNUC__) || defined(__clang__) + constexpr auto Nd = std::numeric_limits::digits*sizeof(T); + constexpr auto Nd_ull = std::numeric_limits::digits; + constexpr auto Nd_ul = std::numeric_limits::digits; + constexpr auto Nd_u = std::numeric_limits::digits; + if constexpr (Nd <= Nd_u) + return __builtin_ctz(x); + else if constexpr (Nd <= Nd_ul) + return __builtin_ctzl(x); + else if constexpr (Nd <= Nd_ull) + return __builtin_ctzll(x); + else + { + static_assert(Nd <= (2 * Nd_ull), + "Maximum supported integer size is 128-bit"); + constexpr auto max_ull = std::numeric_limits::max(); + unsigned long long low = x & max_ull; + if (low != 0) + return __builtin_ctzll(low); + unsigned long long high = x >> Nd_ull; + return __builtin_ctzll(high) + Nd_ull; + } +#else + return std::countr_zero(x); +#endif +} + +template +struct iec559_rep +{ + using mantissa_type = typename iec559_traits::mantissa_type; + mantissa_type m; + std::int_least32_t e; +}; + +template +inline constexpr char_type* prsv_fp_nan_impl(char_type* iter,bool isnan) noexcept +{ + if(isnan) + { + if constexpr(uppercase) + { + if constexpr(std::same_as) + return copy_string_literal("NAN",iter); + else if constexpr(std::same_as) + return copy_string_literal(L"NAN",iter); + else if constexpr(std::same_as) + return copy_string_literal(u"NAN",iter); + else if constexpr(std::same_as) + return copy_string_literal(U"NAN",iter); + else + return copy_string_literal(u8"NAN",iter); + } + else + { + if constexpr(std::same_as) + return copy_string_literal("nan",iter); + else if constexpr(std::same_as) + return copy_string_literal(L"nan",iter); + else if constexpr(std::same_as) + return copy_string_literal(u"nan",iter); + else if constexpr(std::same_as) + return copy_string_literal(U"nan",iter); + else + return copy_string_literal(u8"nan",iter); + } + } + else + { + if constexpr(uppercase) + { + if constexpr(std::same_as) + return copy_string_literal("INF",iter); + else if constexpr(std::same_as) + return copy_string_literal(L"INF",iter); + else if constexpr(std::same_as) + return copy_string_literal(u"INF",iter); + else if constexpr(std::same_as) + return copy_string_literal(U"INF",iter); + else + return copy_string_literal(u8"INF",iter); + } + else + { + if constexpr(std::same_as) + return copy_string_literal("inf",iter); + else if constexpr(std::same_as) + return copy_string_literal(L"inf",iter); + else if constexpr(std::same_as) + return copy_string_literal(u"inf",iter); + else if constexpr(std::same_as) + return copy_string_literal(U"inf",iter); + else + return copy_string_literal(u8"inf",iter); + } + } +} + +template +inline constexpr char_type* prsv_fp_hex_0(char_type* iter) noexcept +{ + if constexpr(uppercase) + { + if constexpr(std::same_as) + return copy_string_literal("0P+0",iter); + else if constexpr(std::same_as) + return copy_string_literal(L"0P+0",iter); + else if constexpr(std::same_as) + return copy_string_literal(u"0P+0",iter); + else if constexpr(std::same_as) + return copy_string_literal(U"0P+0",iter); + else + return copy_string_literal(u8"0P+0",iter); + } + else + { + if constexpr(std::same_as) + return copy_string_literal("0p+0",iter); + else if constexpr(std::same_as) + return copy_string_literal(L"0p+0",iter); + else if constexpr(std::same_as) + return copy_string_literal(u"0p+0",iter); + else if constexpr(std::same_as) + return copy_string_literal(U"0p+0",iter); + else + return copy_string_literal(u8"0p+0",iter); + } +} + +template +inline constexpr char_type* prsv_fp_hex1d(char_type* iter) noexcept +{ + if constexpr(comma) + { + if constexpr(std::same_as) + return copy_string_literal("1,",iter); + else if constexpr(std::same_as) + return copy_string_literal(L"1,",iter); + else if constexpr(std::same_as) + return copy_string_literal(u"1,",iter); + else if constexpr(std::same_as) + return copy_string_literal(U"1,",iter); + else + return copy_string_literal(u8"1,",iter); + } + else + { + if constexpr(std::same_as) + return copy_string_literal("1.",iter); + else if constexpr(std::same_as) + return copy_string_literal(L"1.",iter); + else if constexpr(std::same_as) + return copy_string_literal(u"1.",iter); + else if constexpr(std::same_as) + return copy_string_literal(U"1.",iter); + else + return copy_string_literal(u8"1.",iter); + } +} + +template +inline constexpr char_type* prsv_fp_hex0d(char_type* iter) noexcept +{ + if constexpr(comma) + { + if constexpr(std::same_as) + return copy_string_literal("0,",iter); + else if constexpr(std::same_as) + return copy_string_literal(L"0,",iter); + else if constexpr(std::same_as) + return copy_string_literal(u"0,",iter); + else if constexpr(std::same_as) + return copy_string_literal(U"0,",iter); + else + return copy_string_literal(u8"0,",iter); + } + else + { + if constexpr(std::same_as) + return copy_string_literal("0.",iter); + else if constexpr(std::same_as) + return copy_string_literal(L"0.",iter); + else if constexpr(std::same_as) + return copy_string_literal(u"0.",iter); + else if constexpr(std::same_as) + return copy_string_literal(U"0.",iter); + else + return copy_string_literal(u8"0.",iter); + } +} + +template +inline constexpr char_type* prsv_fp_hex0p0(char_type* iter) noexcept +{ + if constexpr(uppercase) + { + if constexpr(std::same_as) + return copy_string_literal("0P+0",iter); + else if constexpr(std::same_as) + return copy_string_literal(L"0P+0",iter); + else if constexpr(std::same_as) + return copy_string_literal(u"0P+0",iter); + else if constexpr(std::same_as) + return copy_string_literal(U"0P+0",iter); + else + return copy_string_literal(u8"0P+0",iter); + } + else + { + if constexpr(std::same_as) + return copy_string_literal("0p+0",iter); + else if constexpr(std::same_as) + return copy_string_literal(L"0p+0",iter); + else if constexpr(std::same_as) + return copy_string_literal(u"0p+0",iter); + else if constexpr(std::same_as) + return copy_string_literal(U"0p+0",iter); + else + return copy_string_literal(u8"0p+0",iter); + } +} + +template +inline constexpr char_type* prsv_fp_dece0(char_type* iter) noexcept +{ + if constexpr(uppercase) + { + if constexpr(std::same_as) + return copy_string_literal("0E+0",iter); + else if constexpr(std::same_as) + return copy_string_literal(L"0E+0",iter); + else if constexpr(std::same_as) + return copy_string_literal(u"0E+0",iter); + else if constexpr(std::same_as) + return copy_string_literal(U"0E+0",iter); + else + return copy_string_literal(u8"0E+0",iter); + } + else + { + if constexpr(std::same_as) + return copy_string_literal("0e+0",iter); + else if constexpr(std::same_as) + return copy_string_literal(L"0e+0",iter); + else if constexpr(std::same_as) + return copy_string_literal(u"0e+0",iter); + else if constexpr(std::same_as) + return copy_string_literal(U"0e+0",iter); + else + return copy_string_literal(u8"0e+0",iter); + } +} + +template +struct punning_result +{ + typename iec559_traits::mantissa_type mantissa; + std::uint_least32_t exponent; + bool sign; +}; + +struct +#if __has_cpp_attribute(__gnu__::__packed__) +[[__gnu__::__packed__]] +#endif +float80_result +{ + std::uint_least64_t mantissa; + std::uint_least16_t exponent; +}; + +template +#if __has_cpp_attribute(__gnu__::__always_inline__) +[[__gnu__::__always_inline__]] +#elif __has_cpp_attribute(msvc::forceinline) +[[msvc::forceinline]] +#endif +inline constexpr punning_result get_punned_result(flt f) noexcept +{ + using trait = iec559_traits; + using mantissa_type = typename trait::mantissa_type; + constexpr std::size_t mbits{trait::mbits}; + constexpr std::size_t ebits{trait::ebits}; + constexpr std::size_t total_bits{mbits+ebits}; + constexpr mantissa_type mantissa_mask{(static_cast(1)<(1)<(f) +#endif +#elif defined(_MSC_VER) && __cpp_lib_bit_cast >= 201806L + __builtin_bit_cast(mantissa_type,f) +#else + bit_cast(f) +#endif + ; + return {unwrap&mantissa_mask,static_cast((unwrap>>mbits)&exponent_mask),static_cast((unwrap>>total_bits)&1u)}; +} + +template +inline constexpr char_type* print_rsv_fp_sign_impl(char_type* iter,bool sign) noexcept +{ + if constexpr(showpos) + { + *iter=sign?char_literal_v:char_literal_v; + ++iter; + } + else + { + if(sign) + { + *iter=char_literal_v; + ++iter; + } + } + return iter; +} + +template<::std::integral char_type,my_unsigned_integral U> +#if __has_cpp_attribute(__gnu__::__hot__) +[[__gnu__::__hot__]] +#endif +inline constexpr char_type* prt_rsv_hundred_flt_impl(char_type* iter,U u) noexcept +{ + return non_overlapped_copy_n(::fast_io::details::digits_table+(u<<1),2,iter); +} + +template +inline constexpr char_type* prt_rsv_exponent_impl(char_type* iter,U u) noexcept +{ + if constexpr(mxdigits==0) + return iter; + else if constexpr(mxdigits==1) + { + *iter=::fast_io::char_literal_add(u); + ++iter; + return iter; + } + else + { + constexpr U ten{10u}; + constexpr U hundred{100u}; + constexpr U thousand{1000u}; + if constexpr(mxdigits==2) + { + if constexpr(indent) + { + return prt_rsv_hundred_flt_impl(iter,u); + } + else + { + if(u>=ten) + return prt_rsv_hundred_flt_impl(iter,u); + else + { + *iter=::fast_io::char_literal_add(u); + ++iter; + return iter; + } + } + } + else if constexpr(mxdigits==3) + { + if constexpr(indent) + { + if(u>=hundred) + { + U div100{u/hundred}; + U mod100{u%hundred}; + *iter=::fast_io::char_literal_add(div100); + ++iter; + u=mod100; + } + return prt_rsv_hundred_flt_impl(iter,u); + } + else + { + if(u>=hundred) + { + U div100{u/hundred}; + U mod100{u%hundred}; + *iter=::fast_io::char_literal_add(div100); + ++iter; + return prt_rsv_hundred_flt_impl(iter,mod100); + } + else if(u(u); + ++iter; + return iter; + } + return prt_rsv_hundred_flt_impl(iter,u); + } + } + else if constexpr(mxdigits==4) + { + if constexpr(indent) + { + if(u=thousand) + sz=4; + print_reserve_integral_main_impl<10,false>(iter+=sz,u,sz); + } + else + { + std::size_t sz(1); + if(u>=thousand) + sz=4; + else if(u>=hundred) + sz=3; + else if(u>=ten) + sz=2; + print_reserve_integral_main_impl<10,false>(iter+=sz,u,sz); + } + return iter; + } + else if constexpr(mxdigits==5) + { + constexpr U tenthousand{10000u}; + if constexpr(indent) + { + if(u=tenthousand) + sz=5; + else if(u>=thousand) + sz=4; + print_reserve_integral_main_impl<10,false>(iter+=sz,u,sz); + } + else + { + std::size_t sz(1); + if(u>=tenthousand) + sz=5; + else if(u>=thousand) + sz=4; + else if(u>=hundred) + sz=3; + else if(u>=ten) + sz=2; + print_reserve_integral_main_impl<10,false>(iter+=sz,u,sz); + } + return iter; + } + else + { + if constexpr(indent) + { + if(u(u)}; + auto temp{iter+sz}; + print_reserve_integral_main_impl<10,false>(temp,u,sz); + return temp; + } + } +} + +} + +#if defined(_MSC_VER) && !defined(__clang__) +#pragma warning(pop) +#endif diff --git a/src/fast_io/include/fast_io_unit/floating/roundtrip.h b/src/fast_io/include/fast_io_unit/floating/roundtrip.h new file mode 100644 index 0000000..d546183 --- /dev/null +++ b/src/fast_io/include/fast_io_unit/floating/roundtrip.h @@ -0,0 +1,1375 @@ +#pragma once +/* +Algorithm: Dragonbox +Author: Jk Jeon +Reference: Abolz +*/ +namespace fast_io::details +{ + +struct uint32x2 +{ +std::uint_least32_t hi; +std::uint_least32_t lo; +}; + +struct uint64x2 +{ +std::uint_least64_t hi; +std::uint_least64_t lo; +}; + +inline constexpr std::uint_least64_t pow10_float32_tb[] +{ +0x81ceb32c4b43fcf5, 0xa2425ff75e14fc32, 0xcad2f7f5359a3b3f, 0xfd87b5f28300ca0e, +0x9e74d1b791e07e49, 0xc612062576589ddb, 0xf79687aed3eec552, 0x9abe14cd44753b53, +0xc16d9a0095928a28, 0xf1c90080baf72cb2, 0x971da05074da7bef, 0xbce5086492111aeb, +0xec1e4a7db69561a6, 0x9392ee8e921d5d08, 0xb877aa3236a4b44a, 0xe69594bec44de15c, +0x901d7cf73ab0acda, 0xb424dc35095cd810, 0xe12e13424bb40e14, 0x8cbccc096f5088cc, +0xafebff0bcb24aaff, 0xdbe6fecebdedd5bf, 0x89705f4136b4a598, 0xabcc77118461cefd, +0xd6bf94d5e57a42bd, 0x8637bd05af6c69b6, 0xa7c5ac471b478424, 0xd1b71758e219652c, +0x83126e978d4fdf3c, 0xa3d70a3d70a3d70b, 0xcccccccccccccccd, 0x8000000000000000, +0xa000000000000000, 0xc800000000000000, 0xfa00000000000000, 0x9c40000000000000, +0xc350000000000000, 0xf424000000000000, 0x9896800000000000, 0xbebc200000000000, +0xee6b280000000000, 0x9502f90000000000, 0xba43b74000000000, 0xe8d4a51000000000, +0x9184e72a00000000, 0xb5e620f480000000, 0xe35fa931a0000000, 0x8e1bc9bf04000000, +0xb1a2bc2ec5000000, 0xde0b6b3a76400000, 0x8ac7230489e80000, 0xad78ebc5ac620000, +0xd8d726b7177a8000, 0x878678326eac9000, 0xa968163f0a57b400, 0xd3c21bcecceda100, +0x84595161401484a0, 0xa56fa5b99019a5c8, 0xcecb8f27f4200f3a, 0x813f3978f8940984, +0xa18f07d736b90be5, 0xc9f2c9cd04674ede, 0xfc6f7c4045812296, 0x9dc5ada82b70b59d, +0xc5371912364ce305, 0xf684df56c3e01bc6, 0x9a130b963a6c115c, 0xc097ce7bc90715b3, +0xf0bdc21abb48db20, 0x96769950b50d88f4, 0xbc143fa4e250eb31, 0xeb194f8e1ae525fd, +0x92efd1b8d0cf37be, 0xb7abc627050305ad, 0xe596b7b0c643c719, 0x8f7e32ce7bea5c6f, +0xb35dbf821ae4f38b, 0xe0352f62a19e306e +}; + +inline constexpr uint32x2 float_mod5_tb[] +{ +{0x00000001u,0xFFFFFFFFu}, +{0xCCCCCCCDu,0x33333333u}, +{0xC28F5C29u,0x0A3D70A3u}, +{0x26E978D5u,0x020C49BAu}, +{0x3AFB7E91u,0x0068DB8Bu}, +{0x0BCBE61Du,0x0014F8B5u}, +{0x68C26139u,0x000431BDu}, +{0xAE8D46A5u,0x0000D6BFu}, +{0x22E90E21u,0x00002AF3u}, +{0x3A2E9C6Du,0x00000897u}, +{0x3ED61F49u,0x000001B7u} +}; + +inline constexpr auto compute_pow10_float32{pow10_float32_tb+31}; + +inline constexpr uint64x2 pow10_float64_tb[] +{ +{0xFF77B1FCBEBCDC4F, 0x25E8E89C13BB0F7B}, +{0x9FAACF3DF73609B1, 0x77B191618C54E9AD}, +{0xC795830D75038C1D, 0xD59DF5B9EF6A2418}, +{0xF97AE3D0D2446F25, 0x4B0573286B44AD1E}, +{0x9BECCE62836AC577, 0x4EE367F9430AEC33}, +{0xC2E801FB244576D5, 0x229C41F793CDA740}, +{0xF3A20279ED56D48A, 0x6B43527578C11110}, +{0x9845418C345644D6, 0x830A13896B78AAAA}, +{0xBE5691EF416BD60C, 0x23CC986BC656D554}, +{0xEDEC366B11C6CB8F, 0x2CBFBE86B7EC8AA9}, +{0x94B3A202EB1C3F39, 0x7BF7D71432F3D6AA}, +{0xB9E08A83A5E34F07, 0xDAF5CCD93FB0CC54}, +{0xE858AD248F5C22C9, 0xD1B3400F8F9CFF69}, +{0x91376C36D99995BE, 0x23100809B9C21FA2}, +{0xB58547448FFFFB2D, 0xABD40A0C2832A78B}, +{0xE2E69915B3FFF9F9, 0x16C90C8F323F516D}, +{0x8DD01FAD907FFC3B, 0xAE3DA7D97F6792E4}, +{0xB1442798F49FFB4A, 0x99CD11CFDF41779D}, +{0xDD95317F31C7FA1D, 0x40405643D711D584}, +{0x8A7D3EEF7F1CFC52, 0x482835EA666B2573}, +{0xAD1C8EAB5EE43B66, 0xDA3243650005EED0}, +{0xD863B256369D4A40, 0x90BED43E40076A83}, +{0x873E4F75E2224E68, 0x5A7744A6E804A292}, +{0xA90DE3535AAAE202, 0x711515D0A205CB37}, +{0xD3515C2831559A83, 0x0D5A5B44CA873E04}, +{0x8412D9991ED58091, 0xE858790AFE9486C3}, +{0xA5178FFF668AE0B6, 0x626E974DBE39A873}, +{0xCE5D73FF402D98E3, 0xFB0A3D212DC81290}, +{0x80FA687F881C7F8E, 0x7CE66634BC9D0B9A}, +{0xA139029F6A239F72, 0x1C1FFFC1EBC44E81}, +{0xC987434744AC874E, 0xA327FFB266B56221}, +{0xFBE9141915D7A922, 0x4BF1FF9F0062BAA9}, +{0x9D71AC8FADA6C9B5, 0x6F773FC3603DB4AA}, +{0xC4CE17B399107C22, 0xCB550FB4384D21D4}, +{0xF6019DA07F549B2B, 0x7E2A53A146606A49}, +{0x99C102844F94E0FB, 0x2EDA7444CBFC426E}, +{0xC0314325637A1939, 0xFA911155FEFB5309}, +{0xF03D93EEBC589F88, 0x793555AB7EBA27CB}, +{0x96267C7535B763B5, 0x4BC1558B2F3458DF}, +{0xBBB01B9283253CA2, 0x9EB1AAEDFB016F17}, +{0xEA9C227723EE8BCB, 0x465E15A979C1CADD}, +{0x92A1958A7675175F, 0x0BFACD89EC191ECA}, +{0xB749FAED14125D36, 0xCEF980EC671F667C}, +{0xE51C79A85916F484, 0x82B7E12780E7401B}, +{0x8F31CC0937AE58D2, 0xD1B2ECB8B0908811}, +{0xB2FE3F0B8599EF07, 0x861FA7E6DCB4AA16}, +{0xDFBDCECE67006AC9, 0x67A791E093E1D49B}, +{0x8BD6A141006042BD, 0xE0C8BB2C5C6D24E1}, +{0xAECC49914078536D, 0x58FAE9F773886E19}, +{0xDA7F5BF590966848, 0xAF39A475506A899F}, +{0x888F99797A5E012D, 0x6D8406C952429604}, +{0xAAB37FD7D8F58178, 0xC8E5087BA6D33B84}, +{0xD5605FCDCF32E1D6, 0xFB1E4A9A90880A65}, +{0x855C3BE0A17FCD26, 0x5CF2EEA09A550680}, +{0xA6B34AD8C9DFC06F, 0xF42FAA48C0EA481F}, +{0xD0601D8EFC57B08B, 0xF13B94DAF124DA27}, +{0x823C12795DB6CE57, 0x76C53D08D6B70859}, +{0xA2CB1717B52481ED, 0x54768C4B0C64CA6F}, +{0xCB7DDCDDA26DA268, 0xA9942F5DCF7DFD0A}, +{0xFE5D54150B090B02, 0xD3F93B35435D7C4D}, +{0x9EFA548D26E5A6E1, 0xC47BC5014A1A6DB0}, +{0xC6B8E9B0709F109A, 0x359AB6419CA1091C}, +{0xF867241C8CC6D4C0, 0xC30163D203C94B63}, +{0x9B407691D7FC44F8, 0x79E0DE63425DCF1E}, +{0xC21094364DFB5636, 0x985915FC12F542E5}, +{0xF294B943E17A2BC4, 0x3E6F5B7B17B2939E}, +{0x979CF3CA6CEC5B5A, 0xA705992CEECF9C43}, +{0xBD8430BD08277231, 0x50C6FF782A838354}, +{0xECE53CEC4A314EBD, 0xA4F8BF5635246429}, +{0x940F4613AE5ED136, 0x871B7795E136BE9A}, +{0xB913179899F68584, 0x28E2557B59846E40}, +{0xE757DD7EC07426E5, 0x331AEADA2FE589D0}, +{0x9096EA6F3848984F, 0x3FF0D2C85DEF7622}, +{0xB4BCA50B065ABE63, 0x0FED077A756B53AA}, +{0xE1EBCE4DC7F16DFB, 0xD3E8495912C62895}, +{0x8D3360F09CF6E4BD, 0x64712DD7ABBBD95D}, +{0xB080392CC4349DEC, 0xBD8D794D96AACFB4}, +{0xDCA04777F541C567, 0xECF0D7A0FC5583A1}, +{0x89E42CAAF9491B60, 0xF41686C49DB57245}, +{0xAC5D37D5B79B6239, 0x311C2875C522CED6}, +{0xD77485CB25823AC7, 0x7D633293366B828C}, +{0x86A8D39EF77164BC, 0xAE5DFF9C02033198}, +{0xA8530886B54DBDEB, 0xD9F57F830283FDFD}, +{0xD267CAA862A12D66, 0xD072DF63C324FD7C}, +{0x8380DEA93DA4BC60, 0x4247CB9E59F71E6E}, +{0xA46116538D0DEB78, 0x52D9BE85F074E609}, +{0xCD795BE870516656, 0x67902E276C921F8C}, +{0x806BD9714632DFF6, 0x00BA1CD8A3DB53B7}, +{0xA086CFCD97BF97F3, 0x80E8A40ECCD228A5}, +{0xC8A883C0FDAF7DF0, 0x6122CD128006B2CE}, +{0xFAD2A4B13D1B5D6C, 0x796B805720085F82}, +{0x9CC3A6EEC6311A63, 0xCBE3303674053BB1}, +{0xC3F490AA77BD60FC, 0xBEDBFC4411068A9D}, +{0xF4F1B4D515ACB93B, 0xEE92FB5515482D45}, +{0x991711052D8BF3C5, 0x751BDD152D4D1C4B}, +{0xBF5CD54678EEF0B6, 0xD262D45A78A0635E}, +{0xEF340A98172AACE4, 0x86FB897116C87C35}, +{0x9580869F0E7AAC0E, 0xD45D35E6AE3D4DA1}, +{0xBAE0A846D2195712, 0x8974836059CCA10A}, +{0xE998D258869FACD7, 0x2BD1A438703FC94C}, +{0x91FF83775423CC06, 0x7B6306A34627DDD0}, +{0xB67F6455292CBF08, 0x1A3BC84C17B1D543}, +{0xE41F3D6A7377EECA, 0x20CABA5F1D9E4A94}, +{0x8E938662882AF53E, 0x547EB47B7282EE9D}, +{0xB23867FB2A35B28D, 0xE99E619A4F23AA44}, +{0xDEC681F9F4C31F31, 0x6405FA00E2EC94D5}, +{0x8B3C113C38F9F37E, 0xDE83BC408DD3DD05}, +{0xAE0B158B4738705E, 0x9624AB50B148D446}, +{0xD98DDAEE19068C76, 0x3BADD624DD9B0958}, +{0x87F8A8D4CFA417C9, 0xE54CA5D70A80E5D7}, +{0xA9F6D30A038D1DBC, 0x5E9FCF4CCD211F4D}, +{0xD47487CC8470652B, 0x7647C32000696720}, +{0x84C8D4DFD2C63F3B, 0x29ECD9F40041E074}, +{0xA5FB0A17C777CF09, 0xF468107100525891}, +{0xCF79CC9DB955C2CC, 0x7182148D4066EEB5}, +{0x81AC1FE293D599BF, 0xC6F14CD848405531}, +{0xA21727DB38CB002F, 0xB8ADA00E5A506A7D}, +{0xCA9CF1D206FDC03B, 0xA6D90811F0E4851D}, +{0xFD442E4688BD304A, 0x908F4A166D1DA664}, +{0x9E4A9CEC15763E2E, 0x9A598E4E043287FF}, +{0xC5DD44271AD3CDBA, 0x40EFF1E1853F29FE}, +{0xF7549530E188C128, 0xD12BEE59E68EF47D}, +{0x9A94DD3E8CF578B9, 0x82BB74F8301958CF}, +{0xC13A148E3032D6E7, 0xE36A52363C1FAF02}, +{0xF18899B1BC3F8CA1, 0xDC44E6C3CB279AC2}, +{0x96F5600F15A7B7E5, 0x29AB103A5EF8C0BA}, +{0xBCB2B812DB11A5DE, 0x7415D448F6B6F0E8}, +{0xEBDF661791D60F56, 0x111B495B3464AD22}, +{0x936B9FCEBB25C995, 0xCAB10DD900BEEC35}, +{0xB84687C269EF3BFB, 0x3D5D514F40EEA743}, +{0xE65829B3046B0AFA, 0x0CB4A5A3112A5113}, +{0x8FF71A0FE2C2E6DC, 0x47F0E785EABA72AC}, +{0xB3F4E093DB73A093, 0x59ED216765690F57}, +{0xE0F218B8D25088B8, 0x306869C13EC3532D}, +{0x8C974F7383725573, 0x1E414218C73A13FC}, +{0xAFBD2350644EEACF, 0xE5D1929EF90898FB}, +{0xDBAC6C247D62A583, 0xDF45F746B74ABF3A}, +{0x894BC396CE5DA772, 0x6B8BBA8C328EB784}, +{0xAB9EB47C81F5114F, 0x066EA92F3F326565}, +{0xD686619BA27255A2, 0xC80A537B0EFEFEBE}, +{0x8613FD0145877585, 0xBD06742CE95F5F37}, +{0xA798FC4196E952E7, 0x2C48113823B73705}, +{0xD17F3B51FCA3A7A0, 0xF75A15862CA504C6}, +{0x82EF85133DE648C4, 0x9A984D73DBE722FC}, +{0xA3AB66580D5FDAF5, 0xC13E60D0D2E0EBBB}, +{0xCC963FEE10B7D1B3, 0x318DF905079926A9}, +{0xFFBBCFE994E5C61F, 0xFDF17746497F7053}, +{0x9FD561F1FD0F9BD3, 0xFEB6EA8BEDEFA634}, +{0xC7CABA6E7C5382C8, 0xFE64A52EE96B8FC1}, +{0xF9BD690A1B68637B, 0x3DFDCE7AA3C673B1}, +{0x9C1661A651213E2D, 0x06BEA10CA65C084F}, +{0xC31BFA0FE5698DB8, 0x486E494FCFF30A63}, +{0xF3E2F893DEC3F126, 0x5A89DBA3C3EFCCFB}, +{0x986DDB5C6B3A76B7, 0xF89629465A75E01D}, +{0xBE89523386091465, 0xF6BBB397F1135824}, +{0xEE2BA6C0678B597F, 0x746AA07DED582E2D}, +{0x94DB483840B717EF, 0xA8C2A44EB4571CDD}, +{0xBA121A4650E4DDEB, 0x92F34D62616CE414}, +{0xE896A0D7E51E1566, 0x77B020BAF9C81D18}, +{0x915E2486EF32CD60, 0x0ACE1474DC1D122F}, +{0xB5B5ADA8AAFF80B8, 0x0D819992132456BB}, +{0xE3231912D5BF60E6, 0x10E1FFF697ED6C6A}, +{0x8DF5EFABC5979C8F, 0xCA8D3FFA1EF463C2}, +{0xB1736B96B6FD83B3, 0xBD308FF8A6B17CB3}, +{0xDDD0467C64BCE4A0, 0xAC7CB3F6D05DDBDF}, +{0x8AA22C0DBEF60EE4, 0x6BCDF07A423AA96C}, +{0xAD4AB7112EB3929D, 0x86C16C98D2C953C7}, +{0xD89D64D57A607744, 0xE871C7BF077BA8B8}, +{0x87625F056C7C4A8B, 0x11471CD764AD4973}, +{0xA93AF6C6C79B5D2D, 0xD598E40D3DD89BD0}, +{0xD389B47879823479, 0x4AFF1D108D4EC2C4}, +{0x843610CB4BF160CB, 0xCEDF722A585139BB}, +{0xA54394FE1EEDB8FE, 0xC2974EB4EE658829}, +{0xCE947A3DA6A9273E, 0x733D226229FEEA33}, +{0x811CCC668829B887, 0x0806357D5A3F5260}, +{0xA163FF802A3426A8, 0xCA07C2DCB0CF26F8}, +{0xC9BCFF6034C13052, 0xFC89B393DD02F0B6}, +{0xFC2C3F3841F17C67, 0xBBAC2078D443ACE3}, +{0x9D9BA7832936EDC0, 0xD54B944B84AA4C0E}, +{0xC5029163F384A931, 0x0A9E795E65D4DF12}, +{0xF64335BCF065D37D, 0x4D4617B5FF4A16D6}, +{0x99EA0196163FA42E, 0x504BCED1BF8E4E46}, +{0xC06481FB9BCF8D39, 0xE45EC2862F71E1D7}, +{0xF07DA27A82C37088, 0x5D767327BB4E5A4D}, +{0x964E858C91BA2655, 0x3A6A07F8D510F870}, +{0xBBE226EFB628AFEA, 0x890489F70A55368C}, +{0xEADAB0ABA3B2DBE5, 0x2B45AC74CCEA842F}, +{0x92C8AE6B464FC96F, 0x3B0B8BC90012929E}, +{0xB77ADA0617E3BBCB, 0x09CE6EBB40173745}, +{0xE55990879DDCAABD, 0xCC420A6A101D0516}, +{0x8F57FA54C2A9EAB6, 0x9FA946824A12232E}, +{0xB32DF8E9F3546564, 0x47939822DC96ABFA}, +{0xDFF9772470297EBD, 0x59787E2B93BC56F8}, +{0x8BFBEA76C619EF36, 0x57EB4EDB3C55B65B}, +{0xAEFAE51477A06B03, 0xEDE622920B6B23F2}, +{0xDAB99E59958885C4, 0xE95FAB368E45ECEE}, +{0x88B402F7FD75539B, 0x11DBCB0218EBB415}, +{0xAAE103B5FCD2A881, 0xD652BDC29F26A11A}, +{0xD59944A37C0752A2, 0x4BE76D3346F04960}, +{0x857FCAE62D8493A5, 0x6F70A4400C562DDC}, +{0xA6DFBD9FB8E5B88E, 0xCB4CCD500F6BB953}, +{0xD097AD07A71F26B2, 0x7E2000A41346A7A8}, +{0x825ECC24C873782F, 0x8ED400668C0C28C9}, +{0xA2F67F2DFA90563B, 0x728900802F0F32FB}, +{0xCBB41EF979346BCA, 0x4F2B40A03AD2FFBA}, +{0xFEA126B7D78186BC, 0xE2F610C84987BFA9}, +{0x9F24B832E6B0F436, 0x0DD9CA7D2DF4D7CA}, +{0xC6EDE63FA05D3143, 0x91503D1C79720DBC}, +{0xF8A95FCF88747D94, 0x75A44C6397CE912B}, +{0x9B69DBE1B548CE7C, 0xC986AFBE3EE11ABB}, +{0xC24452DA229B021B, 0xFBE85BADCE996169}, +{0xF2D56790AB41C2A2, 0xFAE27299423FB9C4}, +{0x97C560BA6B0919A5, 0xDCCD879FC967D41B}, +{0xBDB6B8E905CB600F, 0x5400E987BBC1C921}, +{0xED246723473E3813, 0x290123E9AAB23B69}, +{0x9436C0760C86E30B, 0xF9A0B6720AAF6522}, +{0xB94470938FA89BCE, 0xF808E40E8D5B3E6A}, +{0xE7958CB87392C2C2, 0xB60B1D1230B20E05}, +{0x90BD77F3483BB9B9, 0xB1C6F22B5E6F48C3}, +{0xB4ECD5F01A4AA828, 0x1E38AEB6360B1AF4}, +{0xE2280B6C20DD5232, 0x25C6DA63C38DE1B1}, +{0x8D590723948A535F, 0x579C487E5A38AD0F}, +{0xB0AF48EC79ACE837, 0x2D835A9DF0C6D852}, +{0xDCDB1B2798182244, 0xF8E431456CF88E66}, +{0x8A08F0F8BF0F156B, 0x1B8E9ECB641B5900}, +{0xAC8B2D36EED2DAC5, 0xE272467E3D222F40}, +{0xD7ADF884AA879177, 0x5B0ED81DCC6ABB10}, +{0x86CCBB52EA94BAEA, 0x98E947129FC2B4EA}, +{0xA87FEA27A539E9A5, 0x3F2398D747B36225}, +{0xD29FE4B18E88640E, 0x8EEC7F0D19A03AAE}, +{0x83A3EEEEF9153E89, 0x1953CF68300424AD}, +{0xA48CEAAAB75A8E2B, 0x5FA8C3423C052DD8}, +{0xCDB02555653131B6, 0x3792F412CB06794E}, +{0x808E17555F3EBF11, 0xE2BBD88BBEE40BD1}, +{0xA0B19D2AB70E6ED6, 0x5B6ACEAEAE9D0EC5}, +{0xC8DE047564D20A8B, 0xF245825A5A445276}, +{0xFB158592BE068D2E, 0xEED6E2F0F0D56713}, +{0x9CED737BB6C4183D, 0x55464DD69685606C}, +{0xC428D05AA4751E4C, 0xAA97E14C3C26B887}, +{0xF53304714D9265DF, 0xD53DD99F4B3066A9}, +{0x993FE2C6D07B7FAB, 0xE546A8038EFE402A}, +{0xBF8FDB78849A5F96, 0xDE98520472BDD034}, +{0xEF73D256A5C0F77C, 0x963E66858F6D4441}, +{0x95A8637627989AAD, 0xDDE7001379A44AA9}, +{0xBB127C53B17EC159, 0x5560C018580D5D53}, +{0xE9D71B689DDE71AF, 0xAAB8F01E6E10B4A7}, +{0x9226712162AB070D, 0xCAB3961304CA70E9}, +{0xB6B00D69BB55C8D1, 0x3D607B97C5FD0D23}, +{0xE45C10C42A2B3B05, 0x8CB89A7DB77C506B}, +{0x8EB98A7A9A5B04E3, 0x77F3608E92ADB243}, +{0xB267ED1940F1C61C, 0x55F038B237591ED4}, +{0xDF01E85F912E37A3, 0x6B6C46DEC52F6689}, +{0x8B61313BBABCE2C6, 0x2323AC4B3B3DA016}, +{0xAE397D8AA96C1B77, 0xABEC975E0A0D081B}, +{0xD9C7DCED53C72255, 0x96E7BD358C904A22}, +{0x881CEA14545C7575, 0x7E50D64177DA2E55}, +{0xAA242499697392D2, 0xDDE50BD1D5D0B9EA}, +{0xD4AD2DBFC3D07787, 0x955E4EC64B44E865}, +{0x84EC3C97DA624AB4, 0xBD5AF13BEF0B113F}, +{0xA6274BBDD0FADD61, 0xECB1AD8AEACDD58F}, +{0xCFB11EAD453994BA, 0x67DE18EDA5814AF3}, +{0x81CEB32C4B43FCF4, 0x80EACF948770CED8}, +{0xA2425FF75E14FC31, 0xA1258379A94D028E}, +{0xCAD2F7F5359A3B3E, 0x096EE45813A04331}, +{0xFD87B5F28300CA0D, 0x8BCA9D6E188853FD}, +{0x9E74D1B791E07E48, 0x775EA264CF55347E}, +{0xC612062576589DDA, 0x95364AFE032A819E}, +{0xF79687AED3EEC551, 0x3A83DDBD83F52205}, +{0x9ABE14CD44753B52, 0xC4926A9672793543}, +{0xC16D9A0095928A27, 0x75B7053C0F178294}, +{0xF1C90080BAF72CB1, 0x5324C68B12DD6339}, +{0x971DA05074DA7BEE, 0xD3F6FC16EBCA5E04}, +{0xBCE5086492111AEA, 0x88F4BB1CA6BCF585}, +{0xEC1E4A7DB69561A5, 0x2B31E9E3D06C32E6}, +{0x9392EE8E921D5D07, 0x3AFF322E62439FD0}, +{0xB877AA3236A4B449, 0x09BEFEB9FAD487C3}, +{0xE69594BEC44DE15B, 0x4C2EBE687989A9B4}, +{0x901D7CF73AB0ACD9, 0x0F9D37014BF60A11}, +{0xB424DC35095CD80F, 0x538484C19EF38C95}, +{0xE12E13424BB40E13, 0x2865A5F206B06FBA}, +{0x8CBCCC096F5088CB, 0xF93F87B7442E45D4}, +{0xAFEBFF0BCB24AAFE, 0xF78F69A51539D749}, +{0xDBE6FECEBDEDD5BE, 0xB573440E5A884D1C}, +{0x89705F4136B4A597, 0x31680A88F8953031}, +{0xABCC77118461CEFC, 0xFDC20D2B36BA7C3E}, +{0xD6BF94D5E57A42BC, 0x3D32907604691B4D}, +{0x8637BD05AF6C69B5, 0xA63F9A49C2C1B110}, +{0xA7C5AC471B478423, 0x0FCF80DC33721D54}, +{0xD1B71758E219652B, 0xD3C36113404EA4A9}, +{0x83126E978D4FDF3B, 0x645A1CAC083126EA}, +{0xA3D70A3D70A3D70A, 0x3D70A3D70A3D70A4}, +{0xCCCCCCCCCCCCCCCC, 0xCCCCCCCCCCCCCCCD}, +{0x8000000000000000, 0x0000000000000000}, +{0xA000000000000000, 0x0000000000000000}, +{0xC800000000000000, 0x0000000000000000}, +{0xFA00000000000000, 0x0000000000000000}, +{0x9C40000000000000, 0x0000000000000000}, +{0xC350000000000000, 0x0000000000000000}, +{0xF424000000000000, 0x0000000000000000}, +{0x9896800000000000, 0x0000000000000000}, +{0xBEBC200000000000, 0x0000000000000000}, +{0xEE6B280000000000, 0x0000000000000000}, +{0x9502F90000000000, 0x0000000000000000}, +{0xBA43B74000000000, 0x0000000000000000}, +{0xE8D4A51000000000, 0x0000000000000000}, +{0x9184E72A00000000, 0x0000000000000000}, +{0xB5E620F480000000, 0x0000000000000000}, +{0xE35FA931A0000000, 0x0000000000000000}, +{0x8E1BC9BF04000000, 0x0000000000000000}, +{0xB1A2BC2EC5000000, 0x0000000000000000}, +{0xDE0B6B3A76400000, 0x0000000000000000}, +{0x8AC7230489E80000, 0x0000000000000000}, +{0xAD78EBC5AC620000, 0x0000000000000000}, +{0xD8D726B7177A8000, 0x0000000000000000}, +{0x878678326EAC9000, 0x0000000000000000}, +{0xA968163F0A57B400, 0x0000000000000000}, +{0xD3C21BCECCEDA100, 0x0000000000000000}, +{0x84595161401484A0, 0x0000000000000000}, +{0xA56FA5B99019A5C8, 0x0000000000000000}, +{0xCECB8F27F4200F3A, 0x0000000000000000}, +{0x813F3978F8940984, 0x4000000000000000}, +{0xA18F07D736B90BE5, 0x5000000000000000}, +{0xC9F2C9CD04674EDE, 0xA400000000000000}, +{0xFC6F7C4045812296, 0x4D00000000000000}, +{0x9DC5ADA82B70B59D, 0xF020000000000000}, +{0xC5371912364CE305, 0x6C28000000000000}, +{0xF684DF56C3E01BC6, 0xC732000000000000}, +{0x9A130B963A6C115C, 0x3C7F400000000000}, +{0xC097CE7BC90715B3, 0x4B9F100000000000}, +{0xF0BDC21ABB48DB20, 0x1E86D40000000000}, +{0x96769950B50D88F4, 0x1314448000000000}, +{0xBC143FA4E250EB31, 0x17D955A000000000}, +{0xEB194F8E1AE525FD, 0x5DCFAB0800000000}, +{0x92EFD1B8D0CF37BE, 0x5AA1CAE500000000}, +{0xB7ABC627050305AD, 0xF14A3D9E40000000}, +{0xE596B7B0C643C719, 0x6D9CCD05D0000000}, +{0x8F7E32CE7BEA5C6F, 0xE4820023A2000000}, +{0xB35DBF821AE4F38B, 0xDDA2802C8A800000}, +{0xE0352F62A19E306E, 0xD50B2037AD200000}, +{0x8C213D9DA502DE45, 0x4526F422CC340000}, +{0xAF298D050E4395D6, 0x9670B12B7F410000}, +{0xDAF3F04651D47B4C, 0x3C0CDD765F114000}, +{0x88D8762BF324CD0F, 0xA5880A69FB6AC800}, +{0xAB0E93B6EFEE0053, 0x8EEA0D047A457A00}, +{0xD5D238A4ABE98068, 0x72A4904598D6D880}, +{0x85A36366EB71F041, 0x47A6DA2B7F864750}, +{0xA70C3C40A64E6C51, 0x999090B65F67D924}, +{0xD0CF4B50CFE20765, 0xFFF4B4E3F741CF6D}, +{0x82818F1281ED449F, 0xBFF8F10E7A8921A4}, +{0xA321F2D7226895C7, 0xAFF72D52192B6A0D}, +{0xCBEA6F8CEB02BB39, 0x9BF4F8A69F764490}, +{0xFEE50B7025C36A08, 0x02F236D04753D5B4}, +{0x9F4F2726179A2245, 0x01D762422C946590}, +{0xC722F0EF9D80AAD6, 0x424D3AD2B7B97EF5}, +{0xF8EBAD2B84E0D58B, 0xD2E0898765A7DEB2}, +{0x9B934C3B330C8577, 0x63CC55F49F88EB2F}, +{0xC2781F49FFCFA6D5, 0x3CBF6B71C76B25FB}, +{0xF316271C7FC3908A, 0x8BEF464E3945EF7A}, +{0x97EDD871CFDA3A56, 0x97758BF0E3CBB5AC}, +{0xBDE94E8E43D0C8EC, 0x3D52EEED1CBEA317}, +{0xED63A231D4C4FB27, 0x4CA7AAA863EE4BDD}, +{0x945E455F24FB1CF8, 0x8FE8CAA93E74EF6A}, +{0xB975D6B6EE39E436, 0xB3E2FD538E122B44}, +{0xE7D34C64A9C85D44, 0x60DBBCA87196B616}, +{0x90E40FBEEA1D3A4A, 0xBC8955E946FE31CD}, +{0xB51D13AEA4A488DD, 0x6BABAB6398BDBE41}, +{0xE264589A4DCDAB14, 0xC696963C7EED2DD1}, +{0x8D7EB76070A08AEC, 0xFC1E1DE5CF543CA2}, +{0xB0DE65388CC8ADA8, 0x3B25A55F43294BCB}, +{0xDD15FE86AFFAD912, 0x49EF0EB713F39EBE}, +{0x8A2DBF142DFCC7AB, 0x6E3569326C784337}, +{0xACB92ED9397BF996, 0x49C2C37F07965404}, +{0xD7E77A8F87DAF7FB, 0xDC33745EC97BE906}, +{0x86F0AC99B4E8DAFD, 0x69A028BB3DED71A3}, +{0xA8ACD7C0222311BC, 0xC40832EA0D68CE0C}, +{0xD2D80DB02AABD62B, 0xF50A3FA490C30190}, +{0x83C7088E1AAB65DB, 0x792667C6DA79E0FA}, +{0xA4B8CAB1A1563F52, 0x577001B891185938}, +{0xCDE6FD5E09ABCF26, 0xED4C0226B55E6F86}, +{0x80B05E5AC60B6178, 0x544F8158315B05B4}, +{0xA0DC75F1778E39D6, 0x696361AE3DB1C721}, +{0xC913936DD571C84C, 0x03BC3A19CD1E38E9}, +{0xFB5878494ACE3A5F, 0x04AB48A04065C723}, +{0x9D174B2DCEC0E47B, 0x62EB0D64283F9C76}, +{0xC45D1DF942711D9A, 0x3BA5D0BD324F8394}, +{0xF5746577930D6500, 0xCA8F44EC7EE36479}, +{0x9968BF6ABBE85F20, 0x7E998B13CF4E1ECB}, +{0xBFC2EF456AE276E8, 0x9E3FEDD8C321A67E}, +{0xEFB3AB16C59B14A2, 0xC5CFE94EF3EA101E}, +{0x95D04AEE3B80ECE5, 0xBBA1F1D158724A12}, +{0xBB445DA9CA61281F, 0x2A8A6E45AE8EDC97}, +{0xEA1575143CF97226, 0xF52D09D71A3293BD}, +{0x924D692CA61BE758, 0x593C2626705F9C56}, +{0xB6E0C377CFA2E12E, 0x6F8B2FB00C77836C}, +{0xE498F455C38B997A, 0x0B6DFB9C0F956447}, +{0x8EDF98B59A373FEC, 0x4724BD4189BD5EAC}, +{0xB2977EE300C50FE7, 0x58EDEC91EC2CB657}, +{0xDF3D5E9BC0F653E1, 0x2F2967B66737E3ED}, +{0x8B865B215899F46C, 0xBD79E0D20082EE74}, +{0xAE67F1E9AEC07187, 0xECD8590680A3AA11}, +{0xDA01EE641A708DE9, 0xE80E6F4820CC9495}, +{0x884134FE908658B2, 0x3109058D147FDCDD}, +{0xAA51823E34A7EEDE, 0xBD4B46F0599FD415}, +{0xD4E5E2CDC1D1EA96, 0x6C9E18AC7007C91A}, +{0x850FADC09923329E, 0x03E2CF6BC604DDB0}, +{0xA6539930BF6BFF45, 0x84DB8346B786151C}, +{0xCFE87F7CEF46FF16, 0xE612641865679A63}, +{0x81F14FAE158C5F6E, 0x4FCB7E8F3F60C07E}, +{0xA26DA3999AEF7749, 0xE3BE5E330F38F09D}, +{0xCB090C8001AB551C, 0x5CADF5BFD3072CC5}, +{0xFDCB4FA002162A63, 0x73D9732FC7C8F7F6}, +{0x9E9F11C4014DDA7E, 0x2867E7FDDCDD9AFA}, +{0xC646D63501A1511D, 0xB281E1FD541501B8}, +{0xF7D88BC24209A565, 0x1F225A7CA91A4226}, +{0x9AE757596946075F, 0x3375788DE9B06958}, +{0xC1A12D2FC3978937, 0x0052D6B1641C83AE}, +{0xF209787BB47D6B84, 0xC0678C5DBD23A49A}, +{0x9745EB4D50CE6332, 0xF840B7BA963646E0}, +{0xBD176620A501FBFF, 0xB650E5A93BC3D898}, +{0xEC5D3FA8CE427AFF, 0xA3E51F138AB4CEBE}, +{0x93BA47C980E98CDF, 0xC66F336C36B10137}, +{0xB8A8D9BBE123F017, 0xB80B0047445D4184}, +{0xE6D3102AD96CEC1D, 0xA60DC059157491E5}, +{0x9043EA1AC7E41392, 0x87C89837AD68DB2F}, +{0xB454E4A179DD1877, 0x29BABE4598C311FB}, +{0xE16A1DC9D8545E94, 0xF4296DD6FEF3D67A}, +{0x8CE2529E2734BB1D, 0x1899E4A65F58660C}, +{0xB01AE745B101E9E4, 0x5EC05DCFF72E7F8F}, +{0xDC21A1171D42645D, 0x76707543F4FA1F73}, +{0x899504AE72497EBA, 0x6A06494A791C53A8}, +{0xABFA45DA0EDBDE69, 0x0487DB9D17636892}, +{0xD6F8D7509292D603, 0x45A9D2845D3C42B6}, +{0x865B86925B9BC5C2, 0x0B8A2392BA45A9B2}, +{0xA7F26836F282B732, 0x8E6CAC7768D7141E}, +{0xD1EF0244AF2364FF, 0x3207D795430CD926}, +{0x8335616AED761F1F, 0x7F44E6BD49E807B8}, +{0xA402B9C5A8D3A6E7, 0x5F16206C9C6209A6}, +{0xCD036837130890A1, 0x36DBA887C37A8C0F}, +{0x802221226BE55A64, 0xC2494954DA2C9789}, +{0xA02AA96B06DEB0FD, 0xF2DB9BAA10B7BD6C}, +{0xC83553C5C8965D3D, 0x6F92829494E5ACC7}, +{0xFA42A8B73ABBF48C, 0xCB772339BA1F17F9}, +{0x9C69A97284B578D7, 0xFF2A760414536EFB}, +{0xC38413CF25E2D70D, 0xFEF5138519684ABA}, +{0xF46518C2EF5B8CD1, 0x7EB258665FC25D69}, +{0x98BF2F79D5993802, 0xEF2F773FFBD97A61}, +{0xBEEEFB584AFF8603, 0xAAFB550FFACFD8FA}, +{0xEEAABA2E5DBF6784, 0x95BA2A53F983CF38}, +{0x952AB45CFA97A0B2, 0xDD945A747BF26183}, +{0xBA756174393D88DF, 0x94F971119AEEF9E4}, +{0xE912B9D1478CEB17, 0x7A37CD5601AAB85D}, +{0x91ABB422CCB812EE, 0xAC62E055C10AB33A}, +{0xB616A12B7FE617AA, 0x577B986B314D6009}, +{0xE39C49765FDF9D94, 0xED5A7E85FDA0B80B}, +{0x8E41ADE9FBEBC27D, 0x14588F13BE847307}, +{0xB1D219647AE6B31C, 0x596EB2D8AE258FC8}, +{0xDE469FBD99A05FE3, 0x6FCA5F8ED9AEF3BB}, +{0x8AEC23D680043BEE, 0x25DE7BB9480D5854}, +{0xADA72CCC20054AE9, 0xAF561AA79A10AE6A}, +{0xD910F7FF28069DA4, 0x1B2BA1518094DA04}, +{0x87AA9AFF79042286, 0x90FB44D2F05D0842}, +{0xA99541BF57452B28, 0x353A1607AC744A53}, +{0xD3FA922F2D1675F2, 0x42889B8997915CE8}, +{0x847C9B5D7C2E09B7, 0x69956135FEBADA11}, +{0xA59BC234DB398C25, 0x43FAB9837E699095}, +{0xCF02B2C21207EF2E, 0x94F967E45E03F4BB}, +{0x8161AFB94B44F57D, 0x1D1BE0EEBAC278F5}, +{0xA1BA1BA79E1632DC, 0x6462D92A69731732}, +{0xCA28A291859BBF93, 0x7D7B8F7503CFDCFE}, +{0xFCB2CB35E702AF78, 0x5CDA735244C3D43E}, +{0x9DEFBF01B061ADAB, 0x3A0888136AFA64A7}, +{0xC56BAEC21C7A1916, 0x088AAA1845B8FDD0}, +{0xF6C69A72A3989F5B, 0x8AAD549E57273D45}, +{0x9A3C2087A63F6399, 0x36AC54E2F678864B}, +{0xC0CB28A98FCF3C7F, 0x84576A1BB416A7DD}, +{0xF0FDF2D3F3C30B9F, 0x656D44A2A11C51D5}, +{0x969EB7C47859E743, 0x9F644AE5A4B1B325}, +{0xBC4665B596706114, 0x873D5D9F0DDE1FEE}, +{0xEB57FF22FC0C7959, 0xA90CB506D155A7EA}, +{0x9316FF75DD87CBD8, 0x09A7F12442D588F2}, +{0xB7DCBF5354E9BECE, 0x0C11ED6D538AEB2F}, +{0xE5D3EF282A242E81, 0x8F1668C8A86DA5FA}, +{0x8FA475791A569D10, 0xF96E017D694487BC}, +{0xB38D92D760EC4455, 0x37C981DCC395A9AC}, +{0xE070F78D3927556A, 0x85BBE253F47B1417}, +{0x8C469AB843B89562, 0x93956D7478CCEC8E}, +{0xAF58416654A6BABB, 0x387AC8D1970027B2}, +{0xDB2E51BFE9D0696A, 0x06997B05FCC0319E}, +{0x88FCF317F22241E2, 0x441FECE3BDF81F03}, +{0xAB3C2FDDEEAAD25A, 0xD527E81CAD7626C3}, +{0xD60B3BD56A5586F1, 0x8A71E223D8D3B074}, +{0x85C7056562757456, 0xF6872D5667844E49}, +{0xA738C6BEBB12D16C, 0xB428F8AC016561DB}, +{0xD106F86E69D785C7, 0xE13336D701BEBA52}, +{0x82A45B450226B39C, 0xECC0024661173473}, +{0xA34D721642B06084, 0x27F002D7F95D0190}, +{0xCC20CE9BD35C78A5, 0x31EC038DF7B441F4}, +{0xFF290242C83396CE, 0x7E67047175A15271}, +{0x9F79A169BD203E41, 0x0F0062C6E984D386}, +{0xC75809C42C684DD1, 0x52C07B78A3E60868}, +{0xF92E0C3537826145, 0xA7709A56CCDF8A82}, +{0x9BBCC7A142B17CCB, 0x88A66076400BB691}, +{0xC2ABF989935DDBFE, 0x6ACFF893D00EA435}, +{0xF356F7EBF83552FE, 0x0583F6B8C4124D43}, +{0x98165AF37B2153DE, 0xC3727A337A8B704A}, +{0xBE1BF1B059E9A8D6, 0x744F18C0592E4C5C}, +{0xEDA2EE1C7064130C, 0x1162DEF06F79DF73}, +{0x9485D4D1C63E8BE7, 0x8ADDCB5645AC2BA8}, +{0xB9A74A0637CE2EE1, 0x6D953E2BD7173692}, +{0xE8111C87C5C1BA99, 0xC8FA8DB6CCDD0437}, +{0x910AB1D4DB9914A0, 0x1D9C9892400A22A2}, +{0xB54D5E4A127F59C8, 0x2503BEB6D00CAB4B}, +{0xE2A0B5DC971F303A, 0x2E44AE64840FD61D}, +{0x8DA471A9DE737E24, 0x5CEAECFED289E5D2}, +{0xB10D8E1456105DAD, 0x7425A83E872C5F47}, +{0xDD50F1996B947518, 0xD12F124E28F77719}, +{0x8A5296FFE33CC92F, 0x82BD6B70D99AAA6F}, +{0xACE73CBFDC0BFB7B, 0x636CC64D1001550B}, +{0xD8210BEFD30EFA5A, 0x3C47F7E05401AA4E}, +{0x8714A775E3E95C78, 0x65ACFAEC34810A71}, +{0xA8D9D1535CE3B396, 0x7F1839A741A14D0D}, +{0xD31045A8341CA07C, 0x1EDE48111209A050}, +{0x83EA2B892091E44D, 0x934AED0AAB460432}, +{0xA4E4B66B68B65D60, 0xF81DA84D5617853F}, +{0xCE1DE40642E3F4B9, 0x36251260AB9D668E}, +{0x80D2AE83E9CE78F3, 0xC1D72B7C6B426019}, +{0xA1075A24E4421730, 0xB24CF65B8612F81F}, +{0xC94930AE1D529CFC, 0xDEE033F26797B627}, +{0xFB9B7CD9A4A7443C, 0x169840EF017DA3B1}, +{0x9D412E0806E88AA5, 0x8E1F289560EE864E}, +{0xC491798A08A2AD4E, 0xF1A6F2BAB92A27E2}, +{0xF5B5D7EC8ACB58A2, 0xAE10AF696774B1DB}, +{0x9991A6F3D6BF1765, 0xACCA6DA1E0A8EF29}, +{0xBFF610B0CC6EDD3F, 0x17FD090A58D32AF3}, +{0xEFF394DCFF8A948E, 0xDDFC4B4CEF07F5B0}, +{0x95F83D0A1FB69CD9, 0x4ABDAF101564F98E}, +{0xBB764C4CA7A4440F, 0x9D6D1AD41ABE37F1}, +{0xEA53DF5FD18D5513, 0x84C86189216DC5ED}, +{0x92746B9BE2F8552C, 0x32FD3CF5B4E49BB4}, +{0xB7118682DBB66A77, 0x3FBC8C33221DC2A1}, +{0xE4D5E82392A40515, 0x0FABAF3FEAA5334A}, +{0x8F05B1163BA6832D, 0x29CB4D87F2A7400E}, +{0xB2C71D5BCA9023F8, 0x743E20E9EF511012}, +{0xDF78E4B2BD342CF6, 0x914DA9246B255416}, +{0x8BAB8EEFB6409C1A, 0x1AD089B6C2F7548E}, +{0xAE9672ABA3D0C320, 0xA184AC2473B529B1}, +{0xDA3C0F568CC4F3E8, 0xC9E5D72D90A2741E}, +{0x8865899617FB1871, 0x7E2FA67C7A658892}, +{0xAA7EEBFB9DF9DE8D, 0xDDBB901B98FEEAB7}, +{0xD51EA6FA85785631, 0x552A74227F3EA565}, +{0x8533285C936B35DE, 0xD53A88958F87275F}, +{0xA67FF273B8460356, 0x8A892ABAF368F137}, +{0xD01FEF10A657842C, 0x2D2B7569B0432D85}, +{0x8213F56A67F6B29B, 0x9C3B29620E29FC73}, +{0xA298F2C501F45F42, 0x8349F3BA91B47B8F}, +{0xCB3F2F7642717713, 0x241C70A936219A73}, +{0xFE0EFB53D30DD4D7, 0xED238CD383AA0110}, +{0x9EC95D1463E8A506, 0xF4363804324A40AA}, +{0xC67BB4597CE2CE48, 0xB143C6053EDCD0D5}, +{0xF81AA16FDC1B81DA, 0xDD94B7868E94050A}, +{0x9B10A4E5E9913128, 0xCA7CF2B4191C8326}, +{0xC1D4CE1F63F57D72, 0xFD1C2F611F63A3F0}, +{0xF24A01A73CF2DCCF, 0xBC633B39673C8CEC}, +{0x976E41088617CA01, 0xD5BE0503E085D813}, +{0xBD49D14AA79DBC82, 0x4B2D8644D8A74E18}, +{0xEC9C459D51852BA2, 0xDDF8E7D60ED1219E}, +{0x93E1AB8252F33B45, 0xCABB90E5C942B503}, +{0xB8DA1662E7B00A17, 0x3D6A751F3B936243}, +{0xE7109BFBA19C0C9D, 0x0CC512670A783AD4}, +{0x906A617D450187E2, 0x27FB2B80668B24C5}, +{0xB484F9DC9641E9DA, 0xB1F9F660802DEDF6}, +{0xE1A63853BBD26451, 0x5E7873F8A0396973}, +{0x8D07E33455637EB2, 0xDB0B487B6423E1E8}, +{0xB049DC016ABC5E5F, 0x91CE1A9A3D2CDA62}, +{0xDC5C5301C56B75F7, 0x7641A140CC7810FB}, +{0x89B9B3E11B6329BA, 0xA9E904C87FCB0A9D}, +{0xAC2820D9623BF429, 0x546345FA9FBDCD44}, +{0xD732290FBACAF133, 0xA97C177947AD4095}, +{0x867F59A9D4BED6C0, 0x49ED8EABCCCC485D}, +{0xA81F301449EE8C70, 0x5C68F256BFFF5A74}, +{0xD226FC195C6A2F8C, 0x73832EEC6FFF3111}, +{0x83585D8FD9C25DB7, 0xC831FD53C5FF7EAB}, +{0xA42E74F3D032F525, 0xBA3E7CA8B77F5E55}, +{0xCD3A1230C43FB26F, 0x28CE1BD2E55F35EB}, +{0x80444B5E7AA7CF85, 0x7980D163CF5B81B3}, +{0xA0555E361951C366, 0xD7E105BCC332621F}, +{0xC86AB5C39FA63440, 0x8DD9472BF3FEFAA7}, +{0xFA856334878FC150, 0xB14F98F6F0FEB951}, +{0x9C935E00D4B9D8D2, 0x6ED1BF9A569F33D3}, +{0xC3B8358109E84F07, 0x0A862F80EC4700C8}, +{0xF4A642E14C6262C8, 0xCD27BB612758C0FA}, +{0x98E7E9CCCFBD7DBD, 0x8038D51CB897789C}, +{0xBF21E44003ACDD2C, 0xE0470A63E6BD56C3}, +{0xEEEA5D5004981478, 0x1858CCFCE06CAC74}, +{0x95527A5202DF0CCB, 0x0F37801E0C43EBC8}, +{0xBAA718E68396CFFD, 0xD30560258F54E6BA}, +{0xE950DF20247C83FD, 0x47C6B82EF32A2069}, +{0x91D28B7416CDD27E, 0x4CDC331D57FA5441}, +{0xB6472E511C81471D, 0xE0133FE4ADF8E952}, +{0xE3D8F9E563A198E5, 0x58180FDDD97723A6}, +{0x8E679C2F5E44FF8F, 0x570F09EAA7EA7648}, +{0xB201833B35D63F73, 0x2CD2CC6551E513DA}, +{0xDE81E40A034BCF4F, 0xF8077F7EA65E58D1}, +{0x8B112E86420F6191, 0xFB04AFAF27FAF782}, +{0xADD57A27D29339F6, 0x79C5DB9AF1F9B563}, +{0xD94AD8B1C7380874, 0x18375281AE7822BC}, +{0x87CEC76F1C830548, 0x8F2293910D0B15B5}, +{0xA9C2794AE3A3C69A, 0xB2EB3875504DDB22}, +{0xD433179D9C8CB841, 0x5FA60692A46151EB}, +{0x849FEEC281D7F328, 0xDBC7C41BA6BCD333}, +{0xA5C7EA73224DEFF3, 0x12B9B522906C0800}, +{0xCF39E50FEAE16BEF, 0xD768226B34870A00}, +{0x81842F29F2CCE375, 0xE6A1158300D46640}, +{0xA1E53AF46F801C53, 0x60495AE3C1097FD0}, +{0xCA5E89B18B602368, 0x385BB19CB14BDFC4}, +{0xFCF62C1DEE382C42, 0x46729E03DD9ED7B5}, +{0x9E19DB92B4E31BA9, 0x6C07A2C26A8346D1}, +{0xC5A05277621BE293, 0xC7098B7305241885}, +{0xF70867153AA2DB38, 0xB8CBEE4FC66D1EA7} +}; + +inline constexpr uint64x2 float64_mod5_tb[] +{ +{0x0000000000000001u, 0xFFFFFFFFFFFFFFFFu}, // 5^0 +{0xCCCCCCCCCCCCCCCDu, 0x3333333333333333u}, // 5^1 +{0x8F5C28F5C28F5C29u, 0x0A3D70A3D70A3D70u}, // 5^2 +{0x1CAC083126E978D5u, 0x020C49BA5E353F7Cu}, // 5^3 +{0xD288CE703AFB7E91u, 0x0068DB8BAC710CB2u}, // 5^4 +{0x5D4E8FB00BCBE61Du, 0x0014F8B588E368F0u}, // 5^5 +{0x790FB65668C26139u, 0x000431BDE82D7B63u}, // 5^6 +{0xE5032477AE8D46A5u, 0x0000D6BF94D5E57Au}, // 5^7 +{0xC767074B22E90E21u, 0x00002AF31DC46118u}, // 5^8 +{0x8E47CE423A2E9C6Du, 0x0000089705F4136Bu}, // 5^9 +{0x4FA7F60D3ED61F49u, 0x000001B7CDFD9D7Bu}, // 5^10 +{0x0FEE64690C913975u, 0x00000057F5FF85E5u}, // 5^11 +{0x3662E0E1CF503EB1u, 0x000000119799812Du}, // 5^12 +{0xA47A2CF9F6433FBDu, 0x0000000384B84D09u}, // 5^13 +{0x54186F653140A659u, 0x00000000B424DC35u}, // 5^14 +{0x7738164770402145u, 0x0000000024075F3Du}, // 5^15 +{0xE4A4D1417CD9A041u, 0x000000000734ACA5u}, // 5^16 +{0xC75429D9E5C5200Du, 0x000000000170EF54u}, // 5^17 +{0xC1773B91FAC10669u, 0x000000000049C977u}, // 5^18 +{0x26B172506559CE15u, 0x00000000000EC1E4u}, // 5^19 +{0xD489E3A9ADDEC2D1u, 0x000000000002F394u}, // 5^20 +{0x90E860BB892C8D5Du, 0x000000000000971Du}, // 5^21 +{0x502E79BF1B6F4F79u, 0x0000000000001E39u}, // 5^22 +{0xDCD618596BE30FE5u, 0x000000000000060Bu} // 5^23 +}; + +inline constexpr auto compute_pow10_float64{pow10_float64_tb+292}; + +template +struct m10_result +{ + mantissa_type m10; + std::int_least32_t e10; +}; + +inline constexpr std::int_least32_t mul_ln2_div_ln10_floor(std::int_least32_t e) noexcept +{ + return (e*1262611)>>22; +} + +inline constexpr std::int_least32_t mul_ln10_div_ln2_floor(std::int_least32_t e) noexcept +{ + return (e*1741647)>>19; +} + +inline constexpr std::uint_least64_t mulshift_float64(std::uint_least64_t x,std::uint_least64_t ylow,std::uint_least64_t yhigh) noexcept +{ + std::uint_least64_t p0high{intrinsics::umul_least64_high(x,ylow)}; + std::uint_least64_t p1high; + std::uint_least64_t p1low{intrinsics::umul(x,yhigh,p1high)}; + constexpr std::uint_least64_t zero{}; + intrinsics::add_carry(intrinsics::add_carry(false,p1low,p0high,p1low),p1high,zero,p1high); + return p1high; +} + +inline constexpr std::uint_least32_t mulshift_float32(std::uint_least32_t x,std::uint_least64_t y) noexcept +{ + return static_cast(intrinsics::umul_least64_high(x,y)); +} + +inline constexpr bool mul_parity_float64(std::uint_least64_t two_f,std::uint_least64_t pow10_low,std::uint_least64_t pow10_high,std::int_least32_t beta_minus_1) noexcept +{ + std::uint_least64_t const p01{two_f * pow10_high}; + std::uint_least64_t const p10{intrinsics::umul_least64_high(two_f,pow10_low)}; + std::uint_least64_t const mid{p01 + p10}; + constexpr std::uint_least64_t one{1}; + return (mid & (one << (64 - beta_minus_1))); +} + +inline constexpr bool mul_parity_float32(std::uint_least64_t two_f,std::uint_least64_t pow10,std::int_least32_t beta_minus_1) noexcept +{ + std::uint_least64_t const p01{two_f * pow10}; + constexpr std::uint_least64_t one{1}; + return (p01 & (one << (64 - beta_minus_1))); +} + +template +inline constexpr bool multiple_of_pow2_unchecked(value_type value,std::uint_least32_t e2) noexcept +{ + constexpr value_type one{1}; + return !(value & ((one << e2) - 1)); +} + +template +inline constexpr bool multiple_of_pow2(value_type value,std::int_least32_t e2) noexcept +{ + constexpr std::int_least32_t e2max_bits{static_cast(sizeof(value_type)*8)}; + return e2 < e2max_bits && multiple_of_pow2_unchecked(value,static_cast(e2)); +} + +inline constexpr bool multiple_of_pow5(std::uint_least64_t value,std::uint_least32_t e5) noexcept +{ + auto m5{float64_mod5_tb[e5]}; + return value*m5.hi <= m5.lo; +} + +inline constexpr bool is_integral_end_point(std::uint_least64_t two_f,std::int_least32_t e2,std::int_least32_t minus_k) noexcept +{ + if(e2<-2) + return false; + if(e2<=9) + return true; + if(e2<=86) + return multiple_of_pow5(two_f, static_cast(minus_k)); + return false; +} + +inline constexpr bool is_integral_mid_point(std::uint_least64_t two_f,std::int_least32_t e2,std::int_least32_t minus_k) noexcept +{ + if(e2<-4) + return multiple_of_pow2(two_f,minus_k-e2+1); + if(e2<=9) + return true; + if(e2<=86) + return multiple_of_pow5(two_f,static_cast(minus_k)); + return false; +} + +inline constexpr bool multiple_of_pow5_float32(std::uint_least32_t value,std::uint_least32_t e5) noexcept +{ + auto m5{float_mod5_tb[e5]}; + return value*m5.hi <= m5.lo; +} + +inline constexpr bool is_integral_end_point_float32(std::uint_least32_t two_f,std::int_least32_t e2,std::int_least32_t minus_k) noexcept +{ + if(e2<-1) + return false; + if(e2<=6) + return true; + if(e2<=39) + return multiple_of_pow5_float32(two_f, static_cast(minus_k)); + return false; +} + +inline constexpr bool is_integral_mid_point_float32(std::uint_least32_t two_f,std::int_least32_t e2,std::int_least32_t minus_k) noexcept +{ + if(e2<-2) + return multiple_of_pow2(two_f,minus_k-e2+1); + if(e2<=6) + return true; + if(e2<=39) + return multiple_of_pow5_float32(two_f,static_cast(minus_k)); + return false; +} + +template +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline constexpr m10_result::mantissa_type> schubfach_asymmetric_interval(std::int_least32_t e2) noexcept +{ + using trait = iec559_traits; + + constexpr std::int_least32_t mbits{trait::mbits}; + std::int_least32_t const minus_k{(e2 * 1262611 - 524031)>>22}; + std::int_least32_t const plus_k{-minus_k}; + std::int_least32_t const beta_minus_1{e2 + mul_ln10_div_ln2_floor(plus_k)}; + std::uint_least32_t const rshift{static_cast(64-mbits-beta_minus_1)}; + if constexpr(sizeof(flt)==sizeof(::std::uint_least64_t)) + { + uint64x2 const pw{compute_pow10_float64[plus_k]}; + std::uint_least64_t const pw_lo{pw.lo},pw_hi{pw.hi}; + std::uint_least64_t const lower_endpoint{(pw_hi-(pw_hi>>(mbits+1)))>>rshift}; + std::uint_least64_t q{(pw_lo+(pw_hi>>mbits))>>rshift}; + bool const lower_endpoint_is_not_integer((2!=e2)&(3!=e2)); + std::uint_least64_t const xi{lower_endpoint+lower_endpoint_is_not_integer}; + q/=10; + if(q*10>=xi) + return {q,minus_k+1}; + q=((pw_hi>>(rshift-1))+1)>>1; + if(e2==-77) + q-=(q&1); + else + q+=(q>(mbits+1)))>>rshift}; + std::uint_least64_t q{(pw>>mbits)>>rshift}; + bool const lower_endpoint_is_not_integer((2!=e2)&(3!=e2)); + std::uint_least64_t const xi{lower_endpoint+lower_endpoint_is_not_integer}; + q/=10; + if(q*10>=xi) + return {static_cast(q),minus_k+1}; + q=((pw>>(rshift-1))+1)>>1; + if(e2==-35) + q-=(q&1); + else + q+=(q(q),minus_k}; + } +} + +template +#if __has_cpp_attribute(__gnu__::__pure__) +[[__gnu__::__pure__]] +#endif +#if __has_cpp_attribute(__gnu__::__hot__) +[[__gnu__::__hot__]] +#endif +inline constexpr m10_result::mantissa_type> dragonbox_main(typename iec559_traits::mantissa_type m2,std::int_least32_t e2) noexcept +{ + using trait = iec559_traits; + using mantissa_type = typename trait::mantissa_type; + + constexpr std::size_t mbits{trait::mbits}; + constexpr std::size_t ebits{trait::ebits}; + constexpr std::uint_least32_t bias{(static_cast(1<>1)-1}; + constexpr std::int_least32_t exponent_bias{bias+mbits}; + constexpr mantissa_type mflags{static_cast(static_cast(1)<(exponent_bias)}; + e2=e2bias; + } + else + { + auto e2_temp{e2}; + e2-=exponent_bias; + m2|=mflags; + std::uint_least32_t pos_e2{static_cast(-e2)}; + if(pos_e2>pos_e2, 0}; + if(m2==0&&e2_temp>1)[[unlikely]] + return schubfach_asymmetric_interval(e2); + } + bool const is_even{(m2&1u)==0u}; + std::int_least32_t const minus_k{mul_ln2_div_ln10_floor(e2)-kappa}; + std::int_least32_t const plus_k{-minus_k}; + std::int_least32_t const beta_minus_1{e2+mul_ln10_div_ln2_floor(plus_k)}; + if constexpr(sizeof(flt)==sizeof(::std::uint_least64_t)) + { + uint64x2 const pow10{compute_pow10_float64[plus_k]}; + std::uint_least64_t const pow10_lo{pow10.lo}; + std::uint_least64_t const pow10_hi{pow10.hi}; + std::uint_least32_t const delta{static_cast(pow10_hi>>(63-beta_minus_1))}; + std::uint_least64_t const two_fc{m2<<1},two_fl{two_fc-1},two_fr{two_fc+1}; + std::uint_least64_t const zi{mulshift_float64(two_fr<(zi%big_divisor); + if(r(r-delta/2+small_divisor_div2)}; + constexpr std::uint_least32_t distq_divisor_divisor{100}; + std::uint_least32_t const dist_q{dist / distq_divisor_divisor}; + std::uint_least32_t const dist_q_mul100{dist_q * distq_divisor_divisor}; + q+=dist_q; + if(dist==dist_q_mul100) + { + bool const approx_y_parity{(dist & 1u)!=0u}; + if((mul_parity_float64(two_fc,pow10_lo,pow10_hi,beta_minus_1)!=approx_y_parity)||((q&1)&&is_integral_mid_point(two_fc, e2, minus_k))) + --q; + } + return {q,minus_k+kappa}; + } + else if constexpr(sizeof(flt)==sizeof(::std::uint_least32_t)) + { + std::uint_least64_t const pow10{compute_pow10_float32[plus_k]}; + std::uint_least32_t const two_fc{m2<<1},two_fl{two_fc-1},two_fr{two_fc+1}; + std::uint_least32_t const zi{mulshift_float32(two_fr<(pow10>>(63-beta_minus_1))}; + if(r(r-delta/2+small_divisor_div2)}; + std::uint_least32_t const dist_q{dist / small_divisor}; + std::uint_least32_t const dist_q_mul100{dist_q * small_divisor}; + q+=dist_q; + if(dist==dist_q_mul100) + { + bool const approx_y_parity{(dist & 1u)!=0u}; + if((mul_parity_float32(two_fc,pow10,beta_minus_1)!=approx_y_parity)||((q&1)&&is_integral_mid_point_float32(two_fc, e2, minus_k))) + --q; + } + return {q,minus_k+kappa}; + } +} + +template +#if __has_cpp_attribute(__gnu__::__pure__) +[[__gnu__::__pure__]] +#endif +#if __has_cpp_attribute(__gnu__::__hot__) +[[__gnu__::__hot__]] +#endif +inline constexpr m10_result::mantissa_type> dragonbox_impl(typename iec559_traits::mantissa_type m2,std::int_least32_t e2) noexcept +{ + using mantissa_type = typename iec559_traits::mantissa_type; + auto [m10,e10]=dragonbox_main(m2,e2); +//m10 should not ==0 + if constexpr(sizeof(std::size_t)>=sizeof(std::uint_least64_t)|| + sizeof(mantissa_type)=1000000000u) + { + auto tmp_div100(m10/100u); + auto tmp_mod100(m10%100u); + if(tmp_mod100) + { + auto tmp_div10{m10/10u}; + auto tmp_mod10{m10%10u}; + if(!tmp_mod10) + { + m10=tmp_div10; + ++e10; + } + return {m10,e10}; + } + m10=tmp_div100; + e10+=2; + } + std::uint_least32_t m10ul32{static_cast(m10)}; + for(;;) + { + auto tmp_div100{m10ul32/100u}; + auto tmp_mod100{m10ul32%100u}; + if(tmp_mod100) + break; + m10ul32=tmp_div100; + e10+=2; + } + return {static_cast(m10ul32),e10}; + } +} + +template +inline constexpr char_type* print_rsv_fp_decimal_scientific_common_impl(char_type* iter,U m10,std::uint_least32_t m10len) noexcept +{ + auto itp1{iter+1}; + ::fast_io::details::jeaiii::jeaiii_main_len(itp1,m10,m10len); + *iter=*itp1; + *itp1=char_literal_v; + return itp1+m10len; +} + +template +inline constexpr char_type* print_rsv_fp_decimal_common_impl(char_type* iter,U m10,std::uint_least32_t m10len) noexcept +{ + if(m10len==1)[[unlikely]] + { + *iter=::fast_io::char_literal_add(m10); + ++iter; + return iter; + } + else + return print_rsv_fp_decimal_scientific_common_impl(iter,m10,m10len); +} + +template +inline constexpr char_type* print_rsv_fp_e_impl(char_type* iter,std::int_least32_t e10) noexcept +{ + *iter=char_literal_v; + ++iter; + std::uint_least32_t ue10{static_cast(e10)}; + if(e10<0) + { + ue10=0u-ue10; + *iter=char_literal_v; + } + else + *iter=char_literal_v; + ++iter; + return prt_rsv_exponent_impl::e10digits,true>(iter,ue10); +} + +template<::std::integral char_type> +inline constexpr char_type* fill_zeros_impl(char_type* iter,std::size_t n) noexcept +{ + for(std::size_t i{};i!=n;++i) + { + *iter=char_literal_v; + ++iter; + } + return iter; +} + +template +inline constexpr char_type* fill_zero_point_impl(char_type* iter) noexcept +{ + if constexpr(comma) + { + if constexpr(std::same_as) + return copy_string_literal("0,",iter); + else if constexpr(std::same_as) + return copy_string_literal(L"0,",iter); + else if constexpr(std::same_as) + return copy_string_literal(u"0,",iter); + else if constexpr(std::same_as) + return copy_string_literal(U"0,",iter); + else + return copy_string_literal(u8"0,",iter); + } + else + { + if constexpr(std::same_as) + return copy_string_literal("0.",iter); + else if constexpr(std::same_as) + return copy_string_literal(L"0.",iter); + else if constexpr(std::same_as) + return copy_string_literal(u"0.",iter); + else if constexpr(std::same_as) + return copy_string_literal(U"0.",iter); + else + return copy_string_literal(u8"0.",iter); + } +} + +template +inline constexpr char_type* fixed_case0_full_integer(char_type* iter,typename iec559_traits::mantissa_type m10,std::int_least32_t olength,std::int_least32_t real_exp) noexcept +{ + ::fast_io::details::jeaiii::jeaiii_main_len(iter,m10,static_cast(olength)); + iter+=olength; + return fill_zeros_impl(iter,static_cast(real_exp+1-olength)); +} + +template +inline constexpr char_type* fixed_case1_integer_and_point(char_type* iter,typename iec559_traits::mantissa_type m10,std::int_least32_t olength,std::int_least32_t real_exp) noexcept +{ + auto eposition(real_exp+1); + if(olength==eposition) + { + ::fast_io::details::jeaiii::jeaiii_main_len(iter,m10,static_cast(olength)); + iter+=olength; + } + else + { + auto tmp{iter}; + ::fast_io::details::jeaiii::jeaiii_main_len(iter+1,m10,static_cast(olength)); + iter+=olength+1; + my_copy_n(tmp+1,static_cast(eposition),tmp); + tmp[eposition]=char_literal_v<(comma?u8',':u8'.'),char_type>; + } + return iter; +} + +template +inline constexpr char_type* fixed_case2_all_point(char_type* iter,typename iec559_traits::mantissa_type m10,std::int_least32_t olength,std::int_least32_t real_exp) noexcept +{ + iter=fill_zero_point_impl(iter); + iter=fill_zeros_impl(iter,static_cast(-real_exp-1)); + ::fast_io::details::jeaiii::jeaiii_main_len(iter,m10,static_cast(olength)); + iter+=olength; + return iter; +} + +template +inline constexpr char_type* print_rsv_fp_fixed_decision_impl(char_type* iter,typename iec559_traits::mantissa_type m10,std::int_least32_t e10) noexcept +{ + std::int_least32_t olength(static_cast(chars_len<10,true>(m10))); + std::int_least32_t const real_exp(static_cast(e10 + olength - 1)); + if(olength<=real_exp) + { + return fixed_case0_full_integer(iter,m10,olength,real_exp); + } + else if(0<=real_exp&&real_exp(iter,m10,olength,real_exp); + } + else + { + return fixed_case2_all_point(iter,m10,olength,real_exp); + } +} + +template< +typename flt, +bool comma, +bool uppercase_e, +::fast_io::manipulators::floating_format mt, +::std::integral char_type> +inline constexpr char_type* print_rsv_fp_decision_impl(char_type* iter,typename iec559_traits::mantissa_type m10,std::int_least32_t e10) noexcept +{ + if constexpr(mt==::fast_io::manipulators::floating_format::general) + { + if(-5(iter,m10,e10); + } + return print_rsv_fp_decision_impl(iter,m10,e10); + } + else if constexpr(mt==::fast_io::manipulators::floating_format::scientific) + { + if(m10<10u)[[unlikely]] + { + *iter=::fast_io::char_literal_add(m10); + ++iter; + } + else + { + auto iterp1{iter}; + ++iterp1; + auto new_iter{::fast_io::details::jeaiii::jeaiii_main(iterp1,m10)}; + e10+=static_cast(static_cast(new_iter-iterp1)-1u); + *iter=*iterp1; + *iterp1=char_literal_v; + iter=new_iter; + } + return print_rsv_fp_e_impl(iter,e10); + } + else //decimal + { + std::int_least32_t olength{static_cast(chars_len<10,true>(m10))}; + std::int_least32_t const real_exp{static_cast(e10 + olength - 1)}; + std::uint_least32_t fixed_length{},this_case{}; + if(olength<=real_exp) + { + fixed_length=static_cast(real_exp+1); + this_case=1; + } + else if(0<=real_exp&&real_exp(olength+2); + if(olength==real_exp+1) + --fixed_length; + this_case=2; + } + else + fixed_length=static_cast(static_cast(-real_exp)+static_cast(olength)+1u); + std::uint_least32_t scientific_length{static_cast(olength==1?olength+3:olength+5)}; + if(scientific_length(iter,m10,static_cast(olength)); + return print_rsv_fp_e_impl(iter,real_exp); + } + //fixed decision + switch(this_case) + { + case 1: + return fixed_case0_full_integer(iter,m10,olength,real_exp); + case 2: + { + return fixed_case1_integer_and_point(iter,m10,olength,real_exp); + } + default: + { + return fixed_case2_all_point(iter,m10,olength,real_exp); + } + } + } +} + +template< +bool showpos, +bool uppercase, +bool uppercase_e, +bool comma, +::fast_io::manipulators::floating_format mt, +typename flt,::std::integral char_type> +inline constexpr char_type* print_rsvflt_define_impl(char_type* iter,flt f) noexcept +{ + if constexpr(::fast_io::manipulators::floating_format::fixed==mt&&uppercase_e) + { + return print_rsvflt_define_impl(iter,f); + } + else + { + using trait = iec559_traits; + using mantissa_type = typename trait::mantissa_type; + constexpr std::size_t ebits{trait::ebits}; + constexpr mantissa_type exponent_mask{(static_cast(1)<(exponent_mask)}; + auto [mantissa,exponent,sign] = get_punned_result(f); + iter=print_rsv_fp_sign_impl(iter,sign); + if(exponent==exponent_mask_u32) + return prsv_fp_nan_impl(iter,mantissa!=0u); + if(!mantissa&&!exponent) + { + if constexpr(mt!=::fast_io::manipulators::floating_format::scientific) + { + *iter=char_literal_v; + ++iter; + return iter; + } + else + return prsv_fp_dece0(iter); + } + auto [m10,e10] = dragonbox_impl(mantissa,static_cast(exponent)); + if constexpr(mt==::fast_io::manipulators::floating_format::fixed) + return print_rsv_fp_fixed_decision_impl(iter,m10,e10); + else + return print_rsv_fp_decision_impl(iter,m10,e10); + } +} + +template +inline constexpr std::size_t print_rsvflt_size_impl() noexcept +{ + using trait = iec559_traits; + if constexpr(mf==::fast_io::manipulators::floating_format::fixed) + { + //general's max length is equal to scientific's max length +//(+/-)(significants+sep) + std::size_t sum{1};//sign(+/-) + sum+=2;//0./, + sum+=trait::e10max; + sum+=trait::m10digits; + return sum; + } + else + { + //decimal and general's max lengths are equal to scientific's max length +//(+/-)(significants+sep)(E/e)(+/-)e + std::size_t sum{1};//sign(+/-) + sum+=trait::m10digits; + ++sum;//./, + sum+=2;//(E/e)(+/-) + sum+=trait::e10digits; + return sum; + } +} + +template +inline constexpr std::size_t print_rsv_cache{print_rsvflt_size_impl()}; + +} diff --git a/src/fast_io/include/fast_io_unit/gb18030.h b/src/fast_io/include/fast_io_unit/gb18030.h new file mode 100644 index 0000000..d735b9b --- /dev/null +++ b/src/fast_io/include/fast_io_unit/gb18030.h @@ -0,0 +1,266 @@ +#pragma once + +namespace fast_io +{ + +/* +Referenced from +GB18030与Unicode编码转换算法.程小刚,郭韧 +https://max.book118.com/html/2019/0128/6114222054002004.shtm +*/ + +namespace details::codecvt::gb18030 +{ + +inline constexpr char32_t linear_18030(char32_t a,char32_t b,char32_t c,char32_t d) noexcept +{ + return ((a*static_cast(10)+b)*static_cast(126)+c)*static_cast(10)+d; +} + +inline constexpr char32_t linear_18030_base{linear_18030(0x81,0x30,0x81,0x30)}; + +inline constexpr char32_t linear(char32_t x) noexcept +{ + return linear_18030((x>>24)&0xff,(x>>16)&0xff,(x>>8)&0xff,x&0xff); +} + +inline constexpr char32_t gb18030_ranges[13][4]{ +{0x0452,0x2010,linear(0x8130D330),linear(0x8136A531)}, +{0x2643,0x2E81,linear(0x8137A839),linear(0x8138FD38)}, +{0x361B,0x3918,linear(0x8230A633),linear(0x8230F237)}, +{0x3CE1,0x4056,linear(0x8231D438),linear(0x8232AF32)}, +{0x4160,0x4337,linear(0x8232C937),linear(0x8232F837)}, +{0x44D7,0x464C,linear(0x8233A339),linear(0x8233C931)}, +{0x478E,0x4947,linear(0x8233E838),linear(0x82349638)}, +{0x49B8,0x4C77,linear(0x8234A131),linear(0x8234E733)}, +{0x9FA6,0xD800,linear(0x82358F33),linear(0x8336C738)}, +{0xE865,0xF92C,linear(0x8336D030),linear(0x84308534)}, +{0xFA2A,0xFE30,linear(0x84309C38),linear(0x84318537)}, +{0xFFE6,0x10000,linear(0x8431A234),linear(0x8431A439)}, +{0x10000,0x110000,linear(0x90308130),linear(0xE3329A35)}}; + +template +requires (sizeof(T)==1) +inline constexpr std::size_t get_gb18030_invalid_code_units(T* p_dst) noexcept +{ + *p_dst=static_cast(0x84); + p_dst[1]=static_cast(0x31); + p_dst[2]=static_cast(0xA4); + p_dst[3]=static_cast(0x37); + return 4; +} + +inline constexpr char32_t lookup_uni_to_gb18030_tb[32781]{ +#include"gb18030_impl/gb18030_tb.h" +}; +inline constexpr char32_t lookup_gb18030_to_uni4_tb[5974]{ +#include"gb18030_impl/gb18030_uni4_tb.h" +}; + +inline constexpr char32_t lookup_gb18030_to_uni2_tb[23940]{ +#include"gb18030_impl/gb18030_uni2_tb.h" +}; + +template +requires (sizeof(T)==1) +inline constexpr std::size_t lookup_uni_to_gb18030(char32_t cdpt, T* p_dst) noexcept +{ + char32_t v{lookup_uni_to_gb18030_tb[cdpt]}; + char16_t v2{static_cast(v)}; + if(static_cast(v2)==v) + { + if constexpr((!std::is_volatile_v)&&(std::endian::native==std::endian::little||std::endian::native==std::endian::big)) + { +#if __cpp_lib_is_constant_evaluated>=201811L + if(!std::is_constant_evaluated()) + { + if constexpr(std::endian::native==std::endian::big) + v2=byte_swap(v2); + ::fast_io::details::my_memcpy(p_dst,&v2,2); + } + else +#endif + { + p_dst[0]=static_cast(v2&0xFF); + p_dst[1]=static_cast(v2>>8); + } + } + else + { + p_dst[0]=static_cast(v2&0xFF); + p_dst[1]=static_cast(v2>>8); + } + return 2; + } + if constexpr((!std::is_volatile_v)&&(std::endian::native==std::endian::little||std::endian::native==std::endian::big)) + { +#if __cpp_lib_is_constant_evaluated>=201811L + if(!std::is_constant_evaluated()) + { + if constexpr(std::endian::native==std::endian::big) + v=byte_swap(v); + ::fast_io::details::my_memcpy(p_dst,&v,4); + } + else +#endif + { + p_dst[0]=static_cast(v&0xFF); + p_dst[1]=static_cast((v>>8)&0xFF); + p_dst[2]=static_cast((v>>16)&0xFF); + p_dst[3]=static_cast(v>>24); + } + } + else + { + p_dst[0]=static_cast(v&0xFF); + p_dst[1]=static_cast((v>>8)&0xFF); + p_dst[2]=static_cast((v>>16)&0xFF); + p_dst[3]=static_cast(v>>24); + } + return 4; +} + +template +requires (sizeof(T)==1) +inline constexpr std::size_t get_gb18030_code_units_unhappy(char32_t u32, T* p_dst) noexcept +{ + if(u32<0x110000)[[likely]] + { + if(u32<0x0452) + return lookup_uni_to_gb18030(u32-128,p_dst); + char32_t sum{128}; + for(std::size_t i{};i!=13;++i) + { + auto const& e{gb18030_ranges[i]}; + auto const e0{e[0]}; + auto const e1{e[1]}; + char32_t diff{static_cast(e1-e0)}; + sum+=diff; + if(static_cast(u32-e0)(0x30+gb%10); gb/=10; + p_dst[2]=static_cast(0x81+gb%126); gb/=126; + p_dst[1]=static_cast(0x30+gb%10); gb/=10; + *p_dst=static_cast(0x81+gb); + return 4; + } + else if(static_cast(u32-e1)(gb18030_ranges[i+1][0]-e1)) + return lookup_uni_to_gb18030(u32-sum,p_dst); + } + } + return get_gb18030_invalid_code_units(p_dst); +} + +template +requires (sizeof(T)==1) +inline constexpr std::size_t get_gb18030_code_units(char32_t cdpt, T* p_dst) noexcept +{ + if(cdpt<0x80)[[likely]] + { + *p_dst=static_cast(static_cast>(cdpt)); + return 1; + } + return get_gb18030_code_units_unhappy(cdpt,p_dst); +} + +inline constexpr char32_t lookup_gb18030_to_uni4_func(char32_t index) noexcept +{ + if(index>=5974)[[unlikely]] + return 0xFFFD; + return lookup_gb18030_to_uni4_tb[index]; +} + +inline constexpr char32_t utf32cp_by_gb18030_index(char32_t index) noexcept +{ + char32_t sum{linear_18030_base+820}; + for(std::size_t i{};i!=13;++i) + { + auto const& e{gb18030_ranges[i]}; + auto const e0{e[0]}; + auto const e1{e[1]}; + sum+=static_cast(e1-e0); + auto const e2{e[2]}; + auto const e3{e[3]}; + char32_t diff{static_cast(e3-e2)}; + if(static_cast(index-e2)<=diff) + return index-e[2]+e[0]; + else if(e3 +requires (sizeof(T)==1) +inline constexpr gb18030_advance_unchecked_result gb18030_advance_unchecked(T const* src) noexcept +{ + char8_t const src0{static_cast(*src)}; + if(src0<0x80) + return {src0,1}; + if(src0==0x80) + return {0x20AC,1}; + if(src0==0xFF) + return {0xFFFD,1}; + char8_t const src1{static_cast(src[1])}; + if(src1==0x7F) + return {0xFFFD,2}; + else if((static_cast(src1-static_cast(0x40))(0xFF-0x40))) + { + char32_t c{src1}; + if(src1>0x7F) + --c; + return {lookup_gb18030_to_uni2_tb[static_cast((static_cast(src0)-0x81)*190u+(c-0x40))],2}; + } + else if((src1<0x30)|(src1==0xFF)) + return {0xFFFD,2}; + char8_t const src2{static_cast(src[2])}; + if(static_cast(0xFF-0x81)<=static_cast(src2-static_cast(0x81))) + return {0xFFFD,3}; + char8_t const src3{static_cast(src[3])}; + if(static_cast(0x40-0x30)<=static_cast(src3-static_cast(0x30))) + return {0xFFFD,4}; + return {utf32cp_by_gb18030_index(linear_18030(src0,src1,src2,src3)),4}; +} + +template +requires (sizeof(T)==1) +inline constexpr gb18030_advance_unchecked_result gb18030_advance(T const* src,std::size_t sz) noexcept +{ + char8_t const src0{static_cast(*src)}; + if(src0<0x80) + return {src0,1}; + if(src0==0x80) + return {0x20AC,1}; + if(src0==0xFF) + return {0xFFFD,1}; + if(sz<2) + return {0,static_cast(-1)}; + char8_t const src1{static_cast(src[1])}; + if(src1==0x7F) + return {0xFFFD,2}; + else if((static_cast(src1-static_cast(0x40))(0xFF-0x40))) + { + char32_t c{src1}; + if(0x7F((static_cast(src0)-0x81)*190u+(c-0x40))],2}; + } + else if((src1<0x30)|(src1==0xFF)) + return {0xFFFD,2}; + if(sz<4) + return {0,static_cast(-1)}; + char8_t const src2{static_cast(src[2])}; + if(static_cast(0xFF-0x81)<=static_cast(src2-static_cast(0x81))) + return {0xFFFD,3}; + char8_t const src3{static_cast(src[3])}; + if(static_cast(0x40-0x30)<=static_cast(src3-static_cast(0x30))) + return {0xFFFD,4}; + return {utf32cp_by_gb18030_index(linear_18030(src0,src1,src2,src3)),4}; +} + +} + +} diff --git a/src/fast_io/include/fast_io_unit/gb18030_impl/gb18030_tb.h b/src/fast_io/include/fast_io_unit/gb18030_impl/gb18030_tb.h new file mode 100644 index 0000000..f857e8b --- /dev/null +++ b/src/fast_io/include/fast_io_unit/gb18030_impl/gb18030_tb.h @@ -0,0 +1 @@ +0x30813081,0x31813081,0x32813081,0x33813081,0x34813081,0x35813081,0x36813081,0x37813081,0x38813081,0x39813081,0x30823081,0x31823081,0x32823081,0x33823081,0x34823081,0x35823081,0x36823081,0x37823081,0x38823081,0x39823081,0x30833081,0x31833081,0x32833081,0x33833081,0x34833081,0x35833081,0x36833081,0x37833081,0x38833081,0x39833081,0x30843081,0x31843081,0x32843081,0x33843081,0x34843081,0x35843081,0xE8A1,0x36843081,0x37843081,0xECA1,0xA7A1,0x38843081,0x39843081,0x30853081,0x31853081,0x32853081,0x33853081,0x34853081,0xE3A1,0xC0A1,0x35853081,0x36853081,0x37853081,0x38853081,0x39853081,0xA4A1,0x30863081,0x31863081,0x32863081,0x33863081,0x34863081,0x35863081,0x36863081,0x37863081,0x38863081,0x39863081,0x30873081,0x31873081,0x32873081,0x33873081,0x34873081,0x35873081,0x36873081,0x37873081,0x38873081,0x39873081,0x30883081,0x31883081,0x32883081,0x33883081,0x34883081,0x35883081,0x36883081,0x37883081,0x38883081,0x39883081,0x30893081,0xC1A1,0x31893081,0x32893081,0x33893081,0x34893081,0x35893081,0x36893081,0x37893081,0x38893081,0xA4A8,0xA2A8,0x39893081,0x308A3081,0x318A3081,0x328A3081,0x338A3081,0x348A3081,0xA8A8,0xA6A8,0xBAA8,0x358A3081,0xACA8,0xAAA8,0x368A3081,0x378A3081,0x388A3081,0x398A3081,0xB0A8,0xAEA8,0x308B3081,0x318B3081,0x328B3081,0xC2A1,0x338B3081,0xB4A8,0xB2A8,0x348B3081,0xB9A8,0x358B3081,0x368B3081,0x378B3081,0x388B3081,0xA1A8,0x398B3081,0x308C3081,0x318C3081,0x328C3081,0x338C3081,0x348C3081,0x358C3081,0x368C3081,0x378C3081,0x388C3081,0x398C3081,0x308D3081,0x318D3081,0x328D3081,0x338D3081,0x348D3081,0x358D3081,0xA5A8,0x368D3081,0x378D3081,0x388D3081,0x398D3081,0x308E3081,0x318E3081,0x328E3081,0xA7A8,0x338E3081,0x348E3081,0x358E3081,0x368E3081,0x378E3081,0x388E3081,0x398E3081,0x308F3081,0x318F3081,0x328F3081,0x338F3081,0x348F3081,0x358F3081,0x368F3081,0x378F3081,0xA9A8,0x388F3081,0x398F3081,0x30903081,0x31903081,0x32903081,0x33903081,0x34903081,0x35903081,0x36903081,0x37903081,0x38903081,0x39903081,0x30913081,0x31913081,0x32913081,0x33913081,0x34913081,0x35913081,0x36913081,0x37913081,0x38913081,0x39913081,0x30923081,0x31923081,0xBDA8,0x32923081,0x33923081,0x34923081,0xBEA8,0x35923081,0x36923081,0x37923081,0x38923081,0xADA8,0x39923081,0x30933081,0x31933081,0x32933081,0x33933081,0x34933081,0x35933081,0x36933081,0x37933081,0x38933081,0x39933081,0x30943081,0x31943081,0x32943081,0x33943081,0x34943081,0x35943081,0x36943081,0x37943081,0x38943081,0x39943081,0x30953081,0x31953081,0x32953081,0x33953081,0x34953081,0x35953081,0x36953081,0x37953081,0xB1A8,0x38953081,0x39953081,0x30963081,0x31963081,0x32963081,0x33963081,0x34963081,0x35963081,0x36963081,0x37963081,0x38963081,0x39963081,0x30973081,0x31973081,0x32973081,0x33973081,0x34973081,0x35973081,0x36973081,0x37973081,0x38973081,0x39973081,0x30983081,0x31983081,0x32983081,0x33983081,0x34983081,0x35983081,0x36983081,0x37983081,0x38983081,0x39983081,0x30993081,0x31993081,0x32993081,0x33993081,0x34993081,0x35993081,0x36993081,0x37993081,0x38993081,0x39993081,0x309A3081,0x319A3081,0x329A3081,0x339A3081,0x349A3081,0x359A3081,0x369A3081,0x379A3081,0x389A3081,0x399A3081,0x309B3081,0x319B3081,0x329B3081,0x339B3081,0x349B3081,0x359B3081,0x369B3081,0x379B3081,0x389B3081,0x399B3081,0x309C3081,0x319C3081,0x329C3081,0x339C3081,0x349C3081,0x359C3081,0x369C3081,0x379C3081,0x389C3081,0x399C3081,0x309D3081,0x319D3081,0x329D3081,0x339D3081,0x349D3081,0x359D3081,0x369D3081,0x379D3081,0x389D3081,0x399D3081,0x309E3081,0x319E3081,0x329E3081,0x339E3081,0x349E3081,0x359E3081,0x369E3081,0x379E3081,0x389E3081,0x399E3081,0x309F3081,0x319F3081,0x329F3081,0x339F3081,0x349F3081,0x359F3081,0xA3A8,0x369F3081,0xABA8,0x379F3081,0xAFA8,0x389F3081,0xB3A8,0x399F3081,0xB5A8,0x30A03081,0xB6A8,0x31A03081,0xB7A8,0x32A03081,0xB8A8,0x33A03081,0x34A03081,0x35A03081,0x36A03081,0x37A03081,0x38A03081,0x39A03081,0x30A13081,0x31A13081,0x32A13081,0x33A13081,0x34A13081,0x35A13081,0x36A13081,0x37A13081,0x38A13081,0x39A13081,0x30A23081,0x31A23081,0x32A23081,0x33A23081,0x34A23081,0x35A23081,0x36A23081,0x37A23081,0x38A23081,0x39A23081,0x30A33081,0xBFA8,0x31A33081,0x32A33081,0x33A33081,0x34A33081,0x35A33081,0x36A33081,0x37A33081,0x38A33081,0x39A33081,0x30A43081,0x31A43081,0x32A43081,0x33A43081,0x34A43081,0x35A43081,0x36A43081,0x37A43081,0x38A43081,0x39A43081,0x30A53081,0x31A53081,0x32A53081,0x33A53081,0x34A53081,0x35A53081,0x36A53081,0x37A53081,0x38A53081,0x39A53081,0x30A63081,0x31A63081,0x32A63081,0x33A63081,0x34A63081,0x35A63081,0x36A63081,0x37A63081,0x38A63081,0x39A63081,0x30A73081,0x31A73081,0x32A73081,0x33A73081,0x34A73081,0x35A73081,0x36A73081,0x37A73081,0x38A73081,0x39A73081,0x30A83081,0x31A83081,0x32A83081,0x33A83081,0x34A83081,0x35A83081,0x36A83081,0x37A83081,0x38A83081,0x39A83081,0x30A93081,0x31A93081,0x32A93081,0x33A93081,0x34A93081,0x35A93081,0x36A93081,0x37A93081,0x38A93081,0x39A93081,0x30AA3081,0x31AA3081,0x32AA3081,0x33AA3081,0x34AA3081,0x35AA3081,0x36AA3081,0x37AA3081,0x38AA3081,0x39AA3081,0x30AB3081,0x31AB3081,0x32AB3081,0x33AB3081,0x34AB3081,0x35AB3081,0x36AB3081,0x37AB3081,0xBBA8,0x38AB3081,0x39AB3081,0x30AC3081,0x31AC3081,0x32AC3081,0x33AC3081,0x34AC3081,0x35AC3081,0x36AC3081,0x37AC3081,0x38AC3081,0x39AC3081,0x30AD3081,0x31AD3081,0x32AD3081,0xC0A8,0x33AD3081,0x34AD3081,0x35AD3081,0x36AD3081,0x37AD3081,0x38AD3081,0x39AD3081,0x30AE3081,0x31AE3081,0x32AE3081,0x33AE3081,0x34AE3081,0x35AE3081,0x36AE3081,0x37AE3081,0x38AE3081,0x39AE3081,0x30AF3081,0x31AF3081,0x32AF3081,0x33AF3081,0x34AF3081,0x35AF3081,0x36AF3081,0x37AF3081,0x38AF3081,0x39AF3081,0x30B03081,0x31B03081,0x32B03081,0x33B03081,0x34B03081,0x35B03081,0x36B03081,0x37B03081,0x38B03081,0x39B03081,0x30B13081,0x31B13081,0x32B13081,0x33B13081,0x34B13081,0x35B13081,0x36B13081,0x37B13081,0x38B13081,0x39B13081,0x30B23081,0x31B23081,0x32B23081,0x33B23081,0x34B23081,0x35B23081,0x36B23081,0x37B23081,0x38B23081,0x39B23081,0x30B33081,0x31B33081,0x32B33081,0x33B33081,0x34B33081,0x35B33081,0x36B33081,0x37B33081,0x38B33081,0x39B33081,0x30B43081,0x31B43081,0x32B43081,0x33B43081,0x34B43081,0x35B43081,0x36B43081,0x37B43081,0x38B43081,0x39B43081,0x30B53081,0x31B53081,0x32B53081,0x33B53081,0x34B53081,0x35B53081,0x36B53081,0x37B53081,0x38B53081,0x39B53081,0x30B63081,0x31B63081,0x32B63081,0x33B63081,0x34B63081,0x35B63081,0x36B63081,0x37B63081,0x38B63081,0x39B63081,0x30B73081,0x31B73081,0x32B73081,0x33B73081,0xA6A1,0x34B73081,0xA5A1,0x40A8,0x41A8,0x35B73081,0x36B73081,0x37B73081,0x38B73081,0x39B73081,0x30B83081,0x31B83081,0x32B83081,0x33B83081,0x34B83081,0x35B83081,0x36B83081,0x37B83081,0x42A8,0x38B83081,0x39B83081,0x30B93081,0x31B93081,0x32B93081,0x33B93081,0x34B93081,0x35B93081,0x36B93081,0x37B93081,0x38B93081,0x39B93081,0x30BA3081,0x31BA3081,0x32BA3081,0x33BA3081,0x34BA3081,0x35BA3081,0x36BA3081,0x37BA3081,0x38BA3081,0x39BA3081,0x30BB3081,0x31BB3081,0x32BB3081,0x33BB3081,0x34BB3081,0x35BB3081,0x36BB3081,0x37BB3081,0x38BB3081,0x39BB3081,0x30BC3081,0x31BC3081,0x32BC3081,0x33BC3081,0x34BC3081,0x35BC3081,0x36BC3081,0x37BC3081,0x38BC3081,0x39BC3081,0x30BD3081,0x31BD3081,0x32BD3081,0x33BD3081,0x34BD3081,0x35BD3081,0x36BD3081,0x37BD3081,0x38BD3081,0x39BD3081,0x30BE3081,0x31BE3081,0x32BE3081,0x33BE3081,0x34BE3081,0x35BE3081,0x36BE3081,0x37BE3081,0x38BE3081,0x39BE3081,0x30BF3081,0x31BF3081,0x32BF3081,0x33BF3081,0x34BF3081,0x35BF3081,0x36BF3081,0x37BF3081,0x38BF3081,0x39BF3081,0x30C03081,0x31C03081,0x32C03081,0x33C03081,0x34C03081,0x35C03081,0x36C03081,0x37C03081,0x38C03081,0x39C03081,0x30C13081,0x31C13081,0x32C13081,0x33C13081,0x34C13081,0x35C13081,0x36C13081,0x37C13081,0x38C13081,0x39C13081,0x30C23081,0x31C23081,0x32C23081,0x33C23081,0x34C23081,0x35C23081,0x36C23081,0x37C23081,0x38C23081,0x39C23081,0x30C33081,0x31C33081,0x32C33081,0x33C33081,0x34C33081,0x35C33081,0x36C33081,0x37C33081,0x38C33081,0x39C33081,0x30C43081,0x31C43081,0x32C43081,0x33C43081,0x34C43081,0x35C43081,0x36C43081,0x37C43081,0x38C43081,0x39C43081,0x30C53081,0x31C53081,0x32C53081,0x33C53081,0x34C53081,0x35C53081,0x36C53081,0x37C53081,0x38C53081,0x39C53081,0x30C63081,0x31C63081,0x32C63081,0x33C63081,0x34C63081,0x35C63081,0x36C63081,0x37C63081,0x38C63081,0x39C63081,0x30C73081,0x31C73081,0x32C73081,0x33C73081,0x34C73081,0x35C73081,0x36C73081,0x37C73081,0x38C73081,0x39C73081,0x30C83081,0x31C83081,0x32C83081,0x33C83081,0x34C83081,0x35C83081,0x36C83081,0x37C83081,0x38C83081,0x39C83081,0x30C93081,0x31C93081,0x32C93081,0x33C93081,0x34C93081,0x35C93081,0x36C93081,0x37C93081,0x38C93081,0x39C93081,0x30CA3081,0x31CA3081,0x32CA3081,0x33CA3081,0x34CA3081,0x35CA3081,0x36CA3081,0x37CA3081,0x38CA3081,0x39CA3081,0x30CB3081,0xA1A6,0xA2A6,0xA3A6,0xA4A6,0xA5A6,0xA6A6,0xA7A6,0xA8A6,0xA9A6,0xAAA6,0xABA6,0xACA6,0xADA6,0xAEA6,0xAFA6,0xB0A6,0xB1A6,0x31CB3081,0xB2A6,0xB3A6,0xB4A6,0xB5A6,0xB6A6,0xB7A6,0xB8A6,0x32CB3081,0x33CB3081,0x34CB3081,0x35CB3081,0x36CB3081,0x37CB3081,0x38CB3081,0xC1A6,0xC2A6,0xC3A6,0xC4A6,0xC5A6,0xC6A6,0xC7A6,0xC8A6,0xC9A6,0xCAA6,0xCBA6,0xCCA6,0xCDA6,0xCEA6,0xCFA6,0xD0A6,0xD1A6,0x39CB3081,0xD2A6,0xD3A6,0xD4A6,0xD5A6,0xD6A6,0xD7A6,0xD8A6,0x30CC3081,0x31CC3081,0x32CC3081,0x33CC3081,0x34CC3081,0x35CC3081,0x36CC3081,0x37CC3081,0x38CC3081,0x39CC3081,0x30CD3081,0x31CD3081,0x32CD3081,0x33CD3081,0x34CD3081,0x35CD3081,0x36CD3081,0x37CD3081,0x38CD3081,0x39CD3081,0x30CE3081,0x31CE3081,0x32CE3081,0x33CE3081,0x34CE3081,0x35CE3081,0x36CE3081,0x37CE3081,0x38CE3081,0x39CE3081,0x30CF3081,0x31CF3081,0x32CF3081,0x33CF3081,0x34CF3081,0x35CF3081,0x36CF3081,0x37CF3081,0x38CF3081,0x39CF3081,0x30D03081,0x31D03081,0x32D03081,0x33D03081,0x34D03081,0x35D03081,0x36D03081,0x37D03081,0x38D03081,0x39D03081,0x30D13081,0x31D13081,0x32D13081,0x33D13081,0x34D13081,0xA7A7,0x35D13081,0x36D13081,0x37D13081,0x38D13081,0x39D13081,0x30D23081,0x31D23081,0x32D23081,0x33D23081,0x34D23081,0x35D23081,0x36D23081,0x37D23081,0x38D23081,0xA1A7,0xA2A7,0xA3A7,0xA4A7,0xA5A7,0xA6A7,0xA8A7,0xA9A7,0xAAA7,0xABA7,0xACA7,0xADA7,0xAEA7,0xAFA7,0xB0A7,0xB1A7,0xB2A7,0xB3A7,0xB4A7,0xB5A7,0xB6A7,0xB7A7,0xB8A7,0xB9A7,0xBAA7,0xBBA7,0xBCA7,0xBDA7,0xBEA7,0xBFA7,0xC0A7,0xC1A7,0xD1A7,0xD2A7,0xD3A7,0xD4A7,0xD5A7,0xD6A7,0xD8A7,0xD9A7,0xDAA7,0xDBA7,0xDCA7,0xDDA7,0xDEA7,0xDFA7,0xE0A7,0xE1A7,0xE2A7,0xE3A7,0xE4A7,0xE5A7,0xE6A7,0xE7A7,0xE8A7,0xE9A7,0xEAA7,0xEBA7,0xECA7,0xEDA7,0xEEA7,0xEFA7,0xF0A7,0xF1A7,0x39D23081,0xD7A7,0x5CA9,0x32A53681,0x33A53681,0x43A8,0xAAA1,0x44A8,0xACA1,0x34A53681,0xAEA1,0xAFA1,0x35A53681,0x36A53681,0xB0A1,0xB1A1,0x37A53681,0x38A53681,0x39A53681,0x30A63681,0x31A63681,0x32A63681,0x33A63681,0x45A8,0xADA1,0x34A63681,0x35A63681,0x36A63681,0x37A63681,0x38A63681,0x39A63681,0x30A73681,0x31A73681,0x32A73681,0xEBA1,0x33A73681,0xE4A1,0xE5A1,0x34A73681,0x46A8,0x35A73681,0x36A73681,0x37A73681,0x38A73681,0x39A73681,0xF9A1,0x30A83681,0x31A83681,0x32A83681,0x33A83681,0x34A83681,0x35A83681,0x36A83681,0x37A83681,0x38A83681,0x39A83681,0x30A93681,0x31A93681,0x32A93681,0x33A93681,0x34A93681,0x35A93681,0x36A93681,0x37A93681,0x38A93681,0x39A93681,0x30AA3681,0x31AA3681,0x32AA3681,0x33AA3681,0x34AA3681,0x35AA3681,0x36AA3681,0x37AA3681,0x38AA3681,0x39AA3681,0x30AB3681,0x31AB3681,0x32AB3681,0x33AB3681,0x34AB3681,0x35AB3681,0x36AB3681,0x37AB3681,0x38AB3681,0x39AB3681,0x30AC3681,0x31AC3681,0x32AC3681,0x33AC3681,0x34AC3681,0x35AC3681,0x36AC3681,0x37AC3681,0x38AC3681,0x39AC3681,0x30AD3681,0x31AD3681,0x32AD3681,0x33AD3681,0x34AD3681,0x35AD3681,0x36AD3681,0x37AD3681,0x38AD3681,0x39AD3681,0x30AE3681,0x31AE3681,0x32AE3681,0x33AE3681,0x34AE3681,0x35AE3681,0x36AE3681,0x37AE3681,0x38AE3681,0x39AE3681,0x30AF3681,0x31AF3681,0x32AF3681,0x33AF3681,0x34AF3681,0x35AF3681,0x36AF3681,0x37AF3681,0x38AF3681,0x39AF3681,0x30B03681,0x31B03681,0x32B03681,0x33B03681,0x34B03681,0x35B03681,0x36B03681,0x37B03681,0x38B03681,0x39B03681,0x30B13681,0x31B13681,0x32B13681,0x33B13681,0x34B13681,0x35B13681,0x36B13681,0x37B13681,0x38B13681,0x39B13681,0x30B23681,0x31B23681,0x32B23681,0x33B23681,0x34B23681,0x35B23681,0x36B23681,0x37B23681,0x38B23681,0x39B23681,0x30B33681,0x31B33681,0xE3A2,0x32B33681,0x33B33681,0x34B33681,0x35B33681,0x36B33681,0x37B33681,0x38B33681,0x39B33681,0x30B43681,0x31B43681,0x32B43681,0x33B43681,0x34B43681,0x35B43681,0x36B43681,0x37B43681,0x38B43681,0x39B43681,0x30B53681,0x31B53681,0x32B53681,0x33B53681,0x34B53681,0x35B53681,0x36B53681,0x37B53681,0x38B53681,0x39B53681,0x30B63681,0x31B63681,0x32B63681,0x33B63681,0x34B63681,0x35B63681,0x36B63681,0x37B63681,0x38B63681,0x39B63681,0x30B73681,0x31B73681,0x32B73681,0x33B73681,0x34B73681,0x35B73681,0x36B73681,0x37B73681,0x38B73681,0x39B73681,0x30B83681,0x31B83681,0x32B83681,0x33B83681,0x34B83681,0x35B83681,0x36B83681,0x37B83681,0x38B83681,0x39B83681,0x30B93681,0x31B93681,0x32B93681,0x33B93681,0x34B93681,0x35B93681,0x36B93681,0x37B93681,0x38B93681,0x39B93681,0x30BA3681,0x31BA3681,0x32BA3681,0x33BA3681,0x34BA3681,0x35BA3681,0x36BA3681,0x37BA3681,0x38BA3681,0x39BA3681,0x30BB3681,0x31BB3681,0x32BB3681,0x33BB3681,0x34BB3681,0x35BB3681,0x36BB3681,0x37BB3681,0xE6A1,0x38BB3681,0x47A8,0x39BB3681,0x30BC3681,0x31BC3681,0x48A8,0x32BC3681,0x33BC3681,0x34BC3681,0x35BC3681,0x36BC3681,0x37BC3681,0x38BC3681,0x39BC3681,0x30BD3681,0x31BD3681,0x32BD3681,0x33BD3681,0xEDA1,0x34BD3681,0x35BD3681,0x36BD3681,0x37BD3681,0x38BD3681,0x39BD3681,0x30BE3681,0x31BE3681,0x32BE3681,0x33BE3681,0x59A9,0x34BE3681,0x35BE3681,0x36BE3681,0x37BE3681,0x38BE3681,0x39BE3681,0x30BF3681,0x31BF3681,0x32BF3681,0x33BF3681,0x34BF3681,0x35BF3681,0x36BF3681,0x37BF3681,0x38BF3681,0x39BF3681,0x30C03681,0x31C03681,0x32C03681,0x33C03681,0x34C03681,0x35C03681,0x36C03681,0x37C03681,0x38C03681,0x39C03681,0x30C13681,0x31C13681,0x32C13681,0x33C13681,0x34C13681,0x35C13681,0x36C13681,0x37C13681,0x38C13681,0x39C13681,0x30C23681,0x31C23681,0x32C23681,0x33C23681,0x34C23681,0x35C23681,0x36C23681,0x37C23681,0x38C23681,0x39C23681,0x30C33681,0x31C33681,0x32C33681,0x33C33681,0x34C33681,0x35C33681,0x36C33681,0x37C33681,0x38C33681,0x39C33681,0x30C43681,0x31C43681,0x32C43681,0x33C43681,0x34C43681,0x35C43681,0xF1A2,0xF2A2,0xF3A2,0xF4A2,0xF5A2,0xF6A2,0xF7A2,0xF8A2,0xF9A2,0xFAA2,0xFBA2,0xFCA2,0x36C43681,0x37C43681,0x38C43681,0x39C43681,0xA1A2,0xA2A2,0xA3A2,0xA4A2,0xA5A2,0xA6A2,0xA7A2,0xA8A2,0xA9A2,0xAAA2,0x30C53681,0x31C53681,0x32C53681,0x33C53681,0x34C53681,0x35C53681,0x36C53681,0x37C53681,0x38C53681,0x39C53681,0x30C63681,0x31C63681,0x32C63681,0x33C63681,0x34C63681,0x35C63681,0x36C63681,0x37C63681,0x38C63681,0x39C63681,0x30C73681,0x31C73681,0xFBA1,0xFCA1,0xFAA1,0xFDA1,0x32C73681,0x33C73681,0x49A8,0x4AA8,0x4BA8,0x4CA8,0x34C73681,0x35C73681,0x36C73681,0x37C73681,0x38C73681,0x39C73681,0x30C83681,0x31C83681,0x32C83681,0x33C83681,0x34C83681,0x35C83681,0x36C83681,0x37C83681,0x38C83681,0x39C83681,0x30C93681,0x31C93681,0x32C93681,0x33C93681,0x34C93681,0x35C93681,0x36C93681,0x37C93681,0x38C93681,0x39C93681,0x30CA3681,0x31CA3681,0x32CA3681,0x33CA3681,0x34CA3681,0x35CA3681,0x36CA3681,0x37CA3681,0x38CA3681,0x39CA3681,0x30CB3681,0x31CB3681,0x32CB3681,0x33CB3681,0x34CB3681,0x35CB3681,0x36CB3681,0x37CB3681,0x38CB3681,0x39CB3681,0x30CC3681,0x31CC3681,0x32CC3681,0x33CC3681,0x34CC3681,0x35CC3681,0x36CC3681,0x37CC3681,0x38CC3681,0x39CC3681,0x30CD3681,0x31CD3681,0x32CD3681,0x33CD3681,0x34CD3681,0x35CD3681,0x36CD3681,0x37CD3681,0x38CD3681,0x39CD3681,0x30CE3681,0x31CE3681,0x32CE3681,0x33CE3681,0x34CE3681,0x35CE3681,0x36CE3681,0x37CE3681,0x38CE3681,0x39CE3681,0x30CF3681,0x31CF3681,0x32CF3681,0x33CF3681,0x34CF3681,0x35CF3681,0x36CF3681,0x37CF3681,0x38CF3681,0x39CF3681,0x30D03681,0x31D03681,0x32D03681,0x33D03681,0x34D03681,0x35D03681,0x36D03681,0x37D03681,0x38D03681,0x39D03681,0x30D13681,0x31D13681,0x32D13681,0x33D13681,0x34D13681,0x35D13681,0x36D13681,0x37D13681,0x38D13681,0x39D13681,0x30D23681,0x31D23681,0x32D23681,0x33D23681,0xCAA1,0x34D23681,0x35D23681,0x36D23681,0x37D23681,0x38D23681,0x39D23681,0xC7A1,0x30D33681,0xC6A1,0x31D33681,0x32D33681,0x33D33681,0x4DA8,0x34D33681,0x35D33681,0x36D33681,0x37D33681,0xCCA1,0x38D33681,0x39D33681,0xD8A1,0xDEA1,0x4EA8,0xCFA1,0x30D43681,0x31D43681,0x4FA8,0x32D43681,0xCEA1,0x33D43681,0xC4A1,0xC5A1,0xC9A1,0xC8A1,0xD2A1,0x34D43681,0x35D43681,0xD3A1,0x36D43681,0x37D43681,0x38D43681,0x39D43681,0x30D53681,0xE0A1,0xDFA1,0xC3A1,0xCBA1,0x31D53681,0x32D53681,0x33D53681,0x34D53681,0x35D53681,0xD7A1,0x36D53681,0x37D53681,0x38D53681,0x39D53681,0x30D63681,0x31D63681,0x32D63681,0x33D63681,0x34D63681,0x35D63681,0xD6A1,0x36D63681,0x37D63681,0x38D63681,0xD5A1,0x39D63681,0x30D73681,0x31D73681,0x32D73681,0x33D73681,0x50A8,0x34D73681,0x35D73681,0x36D73681,0x37D73681,0x38D73681,0x39D73681,0x30D83681,0x31D83681,0x32D83681,0x33D83681,0x34D83681,0x35D83681,0x36D83681,0xD9A1,0xD4A1,0x37D83681,0x38D83681,0xDCA1,0xDDA1,0x51A8,0x52A8,0x39D83681,0x30D93681,0x31D93681,0x32D93681,0x33D93681,0x34D93681,0xDAA1,0xDBA1,0x35D93681,0x36D93681,0x37D93681,0x38D93681,0x39D93681,0x30DA3681,0x31DA3681,0x32DA3681,0x33DA3681,0x34DA3681,0x35DA3681,0x36DA3681,0x37DA3681,0x38DA3681,0x39DA3681,0x30DB3681,0x31DB3681,0x32DB3681,0x33DB3681,0x34DB3681,0x35DB3681,0x36DB3681,0x37DB3681,0x38DB3681,0x39DB3681,0x30DC3681,0x31DC3681,0x32DC3681,0x33DC3681,0x34DC3681,0x35DC3681,0x36DC3681,0x37DC3681,0x38DC3681,0x39DC3681,0x30DD3681,0x31DD3681,0x92A8,0x32DD3681,0x33DD3681,0x34DD3681,0xD1A1,0x35DD3681,0x36DD3681,0x37DD3681,0x38DD3681,0x39DD3681,0x30DE3681,0x31DE3681,0x32DE3681,0x33DE3681,0x34DE3681,0x35DE3681,0xCDA1,0x36DE3681,0x37DE3681,0x38DE3681,0x39DE3681,0x30DF3681,0x31DF3681,0x32DF3681,0x33DF3681,0x34DF3681,0x35DF3681,0x36DF3681,0x37DF3681,0x38DF3681,0x39DF3681,0x30E03681,0x31E03681,0x32E03681,0x33E03681,0x34E03681,0x35E03681,0x36E03681,0x37E03681,0x38E03681,0x39E03681,0x30E13681,0x53A8,0x31E13681,0x32E13681,0x33E13681,0x34E13681,0x35E13681,0x36E13681,0x37E13681,0x38E13681,0x39E13681,0x30E23681,0x31E23681,0x32E23681,0x33E23681,0x34E23681,0x35E23681,0x36E23681,0x37E23681,0x38E23681,0x39E23681,0x30E33681,0x31E33681,0x32E33681,0x33E33681,0x34E33681,0x35E33681,0x36E33681,0x37E33681,0x38E33681,0x39E33681,0x30E43681,0x31E43681,0x32E43681,0x33E43681,0x34E43681,0x35E43681,0x36E43681,0x37E43681,0x38E43681,0x39E43681,0x30E53681,0x31E53681,0x32E53681,0x33E53681,0x34E53681,0x35E53681,0x36E53681,0x37E53681,0x38E53681,0x39E53681,0x30E63681,0x31E63681,0x32E63681,0x33E63681,0x34E63681,0x35E63681,0x36E63681,0x37E63681,0x38E63681,0x39E63681,0x30E73681,0x31E73681,0x32E73681,0x33E73681,0x34E73681,0x35E73681,0x36E73681,0x37E73681,0x38E73681,0x39E73681,0x30E83681,0x31E83681,0x32E83681,0x33E83681,0x34E83681,0x35E83681,0x36E83681,0x37E83681,0x38E83681,0x39E83681,0x30E93681,0x31E93681,0x32E93681,0xD0A1,0x33E93681,0x34E93681,0x35E93681,0x36E93681,0x37E93681,0x38E93681,0x39E93681,0x30EA3681,0x31EA3681,0x32EA3681,0x33EA3681,0x34EA3681,0x35EA3681,0x36EA3681,0x37EA3681,0x38EA3681,0x39EA3681,0x30EB3681,0x31EB3681,0x32EB3681,0x33EB3681,0x34EB3681,0x35EB3681,0x36EB3681,0x37EB3681,0x38EB3681,0x39EB3681,0x30EC3681,0x31EC3681,0x32EC3681,0x33EC3681,0x34EC3681,0x35EC3681,0x36EC3681,0x37EC3681,0x38EC3681,0x39EC3681,0x30ED3681,0x31ED3681,0x32ED3681,0x33ED3681,0x34ED3681,0x35ED3681,0x36ED3681,0x37ED3681,0x38ED3681,0x39ED3681,0x30EE3681,0x31EE3681,0x32EE3681,0x33EE3681,0x34EE3681,0x35EE3681,0x36EE3681,0x37EE3681,0x38EE3681,0x39EE3681,0x30EF3681,0x31EF3681,0x32EF3681,0x33EF3681,0x34EF3681,0x35EF3681,0x36EF3681,0x37EF3681,0x38EF3681,0x39EF3681,0x30F03681,0x31F03681,0x32F03681,0x33F03681,0x34F03681,0x35F03681,0x36F03681,0x37F03681,0x38F03681,0x39F03681,0x30F13681,0x31F13681,0x32F13681,0x33F13681,0x34F13681,0x35F13681,0x36F13681,0x37F13681,0x38F13681,0x39F13681,0x30F23681,0x31F23681,0x32F23681,0x33F23681,0x34F23681,0x35F23681,0x36F23681,0x37F23681,0x38F23681,0x39F23681,0x30F33681,0x31F33681,0x32F33681,0x33F33681,0x34F33681,0x35F33681,0x36F33681,0x37F33681,0x38F33681,0x39F33681,0x30F43681,0x31F43681,0x32F43681,0x33F43681,0x34F43681,0x35F43681,0x36F43681,0x37F43681,0x38F43681,0x39F43681,0x30F53681,0x31F53681,0x32F53681,0x33F53681,0x34F53681,0x35F53681,0x36F53681,0x37F53681,0x38F53681,0x39F53681,0x30F63681,0x31F63681,0x32F63681,0x33F63681,0x34F63681,0x35F63681,0x36F63681,0x37F63681,0x38F63681,0x39F63681,0x30F73681,0x31F73681,0x32F73681,0x33F73681,0x34F73681,0x35F73681,0x36F73681,0x37F73681,0x38F73681,0x39F73681,0x30F83681,0x31F83681,0x32F83681,0x33F83681,0x34F83681,0x35F83681,0x36F83681,0x37F83681,0x38F83681,0x39F83681,0x30F93681,0x31F93681,0x32F93681,0x33F93681,0x34F93681,0x35F93681,0x36F93681,0x37F93681,0x38F93681,0x39F93681,0x30FA3681,0x31FA3681,0x32FA3681,0x33FA3681,0x34FA3681,0x35FA3681,0x36FA3681,0x37FA3681,0x38FA3681,0x39FA3681,0x30FB3681,0x31FB3681,0x32FB3681,0x33FB3681,0x34FB3681,0x35FB3681,0x36FB3681,0x37FB3681,0x38FB3681,0x39FB3681,0x30FC3681,0x31FC3681,0x32FC3681,0x33FC3681,0x34FC3681,0x35FC3681,0x36FC3681,0x37FC3681,0x38FC3681,0x39FC3681,0x30FD3681,0x31FD3681,0x32FD3681,0x33FD3681,0x34FD3681,0x35FD3681,0x36FD3681,0x37FD3681,0x38FD3681,0x39FD3681,0x30FE3681,0x31FE3681,0x32FE3681,0x33FE3681,0x34FE3681,0x35FE3681,0x36FE3681,0x37FE3681,0x38FE3681,0x39FE3681,0x30813781,0x31813781,0x32813781,0x33813781,0x34813781,0x35813781,0x36813781,0x37813781,0x38813781,0x39813781,0x30823781,0x31823781,0x32823781,0x33823781,0x34823781,0x35823781,0x36823781,0x37823781,0x38823781,0x39823781,0x30833781,0x31833781,0x32833781,0x33833781,0x34833781,0x35833781,0x36833781,0x37833781,0x38833781,0x39833781,0x30843781,0x31843781,0x32843781,0x33843781,0x34843781,0x35843781,0x36843781,0x37843781,0x38843781,0x39843781,0x30853781,0x31853781,0x32853781,0x33853781,0x34853781,0x35853781,0x36853781,0x37853781,0x38853781,0x39853781,0x30863781,0x31863781,0x32863781,0x33863781,0x34863781,0x35863781,0x36863781,0x37863781,0x38863781,0x39863781,0x30873781,0x31873781,0x32873781,0x33873781,0x34873781,0x35873781,0x36873781,0x37873781,0x38873781,0x39873781,0x30883781,0x31883781,0x32883781,0x33883781,0x34883781,0x35883781,0x36883781,0x37883781,0x38883781,0x39883781,0x30893781,0x31893781,0x32893781,0x33893781,0x34893781,0x35893781,0x36893781,0x37893781,0x38893781,0x39893781,0x308A3781,0x318A3781,0x328A3781,0x338A3781,0x348A3781,0x358A3781,0x368A3781,0x378A3781,0x388A3781,0x398A3781,0x308B3781,0x318B3781,0x328B3781,0x338B3781,0x348B3781,0x358B3781,0x368B3781,0x378B3781,0x388B3781,0x398B3781,0x308C3781,0x318C3781,0x328C3781,0x338C3781,0x348C3781,0x358C3781,0xD9A2,0xDAA2,0xDBA2,0xDCA2,0xDDA2,0xDEA2,0xDFA2,0xE0A2,0xE1A2,0xE2A2,0x368C3781,0x378C3781,0x388C3781,0x398C3781,0x308D3781,0x318D3781,0x328D3781,0x338D3781,0x348D3781,0x358D3781,0xC5A2,0xC6A2,0xC7A2,0xC8A2,0xC9A2,0xCAA2,0xCBA2,0xCCA2,0xCDA2,0xCEA2,0xCFA2,0xD0A2,0xD1A2,0xD2A2,0xD3A2,0xD4A2,0xD5A2,0xD6A2,0xD7A2,0xD8A2,0xB1A2,0xB2A2,0xB3A2,0xB4A2,0xB5A2,0xB6A2,0xB7A2,0xB8A2,0xB9A2,0xBAA2,0xBBA2,0xBCA2,0xBDA2,0xBEA2,0xBFA2,0xC0A2,0xC1A2,0xC2A2,0xC3A2,0xC4A2,0x368D3781,0x378D3781,0x388D3781,0x398D3781,0x308E3781,0x318E3781,0x328E3781,0x338E3781,0x348E3781,0x358E3781,0x368E3781,0x378E3781,0x388E3781,0x398E3781,0x308F3781,0x318F3781,0x328F3781,0x338F3781,0x348F3781,0x358F3781,0x368F3781,0x378F3781,0x388F3781,0x398F3781,0x30903781,0x31903781,0x32903781,0x33903781,0x34903781,0x35903781,0x36903781,0x37903781,0x38903781,0x39903781,0x30913781,0x31913781,0x32913781,0x33913781,0x34913781,0x35913781,0x36913781,0x37913781,0x38913781,0x39913781,0x30923781,0x31923781,0x32923781,0x33923781,0x34923781,0x35923781,0x36923781,0x37923781,0x38923781,0x39923781,0x30933781,0x31933781,0x32933781,0x33933781,0x34933781,0x35933781,0x36933781,0x37933781,0x38933781,0x39933781,0x30943781,0x31943781,0x32943781,0x33943781,0x34943781,0x35943781,0x36943781,0x37943781,0x38943781,0x39943781,0x30953781,0x31953781,0x32953781,0x33953781,0x34953781,0x35953781,0x36953781,0x37953781,0x38953781,0x39953781,0x30963781,0x31963781,0x32963781,0x33963781,0x34963781,0x35963781,0x36963781,0x37963781,0x38963781,0x39963781,0x30973781,0x31973781,0x32973781,0x33973781,0x34973781,0x35973781,0xA4A9,0xA5A9,0xA6A9,0xA7A9,0xA8A9,0xA9A9,0xAAA9,0xABA9,0xACA9,0xADA9,0xAEA9,0xAFA9,0xB0A9,0xB1A9,0xB2A9,0xB3A9,0xB4A9,0xB5A9,0xB6A9,0xB7A9,0xB8A9,0xB9A9,0xBAA9,0xBBA9,0xBCA9,0xBDA9,0xBEA9,0xBFA9,0xC0A9,0xC1A9,0xC2A9,0xC3A9,0xC4A9,0xC5A9,0xC6A9,0xC7A9,0xC8A9,0xC9A9,0xCAA9,0xCBA9,0xCCA9,0xCDA9,0xCEA9,0xCFA9,0xD0A9,0xD1A9,0xD2A9,0xD3A9,0xD4A9,0xD5A9,0xD6A9,0xD7A9,0xD8A9,0xD9A9,0xDAA9,0xDBA9,0xDCA9,0xDDA9,0xDEA9,0xDFA9,0xE0A9,0xE1A9,0xE2A9,0xE3A9,0xE4A9,0xE5A9,0xE6A9,0xE7A9,0xE8A9,0xE9A9,0xEAA9,0xEBA9,0xECA9,0xEDA9,0xEEA9,0xEFA9,0x36973781,0x37973781,0x38973781,0x39973781,0x54A8,0x55A8,0x56A8,0x57A8,0x58A8,0x59A8,0x5AA8,0x5BA8,0x5CA8,0x5DA8,0x5EA8,0x5FA8,0x60A8,0x61A8,0x62A8,0x63A8,0x64A8,0x65A8,0x66A8,0x67A8,0x68A8,0x69A8,0x6AA8,0x6BA8,0x6CA8,0x6DA8,0x6EA8,0x6FA8,0x70A8,0x71A8,0x72A8,0x73A8,0x74A8,0x75A8,0x76A8,0x77A8,0x30983781,0x31983781,0x32983781,0x33983781,0x34983781,0x35983781,0x36983781,0x37983781,0x38983781,0x39983781,0x30993781,0x31993781,0x32993781,0x78A8,0x79A8,0x7AA8,0x7BA8,0x7CA8,0x7DA8,0x7EA8,0x80A8,0x81A8,0x82A8,0x83A8,0x84A8,0x85A8,0x86A8,0x87A8,0x33993781,0x34993781,0x35993781,0x88A8,0x89A8,0x8AA8,0x36993781,0x37993781,0x38993781,0x39993781,0x309A3781,0x319A3781,0x329A3781,0x339A3781,0x349A3781,0x359A3781,0xF6A1,0xF5A1,0x369A3781,0x379A3781,0x389A3781,0x399A3781,0x309B3781,0x319B3781,0x329B3781,0x339B3781,0x349B3781,0x359B3781,0x369B3781,0x379B3781,0x389B3781,0x399B3781,0x309C3781,0x319C3781,0xF8A1,0xF7A1,0x329C3781,0x339C3781,0x349C3781,0x359C3781,0x369C3781,0x379C3781,0x389C3781,0x399C3781,0x8BA8,0x8CA8,0x309D3781,0x319D3781,0x329D3781,0x339D3781,0x349D3781,0x359D3781,0x369D3781,0x379D3781,0xF4A1,0xF3A1,0x389D3781,0x399D3781,0x309E3781,0xF0A1,0x319E3781,0x329E3781,0xF2A1,0xF1A1,0x339E3781,0x349E3781,0x359E3781,0x369E3781,0x379E3781,0x389E3781,0x399E3781,0x309F3781,0x319F3781,0x329F3781,0x339F3781,0x349F3781,0x359F3781,0x369F3781,0x379F3781,0x389F3781,0x399F3781,0x30A03781,0x8DA8,0x8EA8,0x8FA8,0x90A8,0x31A03781,0x32A03781,0x33A03781,0x34A03781,0x35A03781,0x36A03781,0x37A03781,0x38A03781,0x39A03781,0x30A13781,0x31A13781,0x32A13781,0x33A13781,0x34A13781,0x35A13781,0x36A13781,0x37A13781,0x38A13781,0x39A13781,0x30A23781,0x31A23781,0x32A23781,0x33A23781,0x34A23781,0x35A23781,0x36A23781,0x37A23781,0x38A23781,0x39A23781,0x30A33781,0x31A33781,0xEFA1,0xEEA1,0x32A33781,0x33A33781,0x91A8,0x34A33781,0x35A33781,0x36A33781,0x37A33781,0x38A33781,0x39A33781,0x30A43781,0x31A43781,0x32A43781,0x33A43781,0x34A43781,0x35A43781,0x36A43781,0x37A43781,0x38A43781,0x39A43781,0x30A53781,0x31A53781,0x32A53781,0x33A53781,0x34A53781,0x35A53781,0x36A53781,0x37A53781,0x38A53781,0x39A53781,0x30A63781,0x31A63781,0x32A63781,0x33A63781,0x34A63781,0x35A63781,0x36A63781,0x37A63781,0x38A63781,0x39A63781,0x30A73781,0x31A73781,0x32A73781,0x33A73781,0x34A73781,0x35A73781,0x36A73781,0x37A73781,0x38A73781,0x39A73781,0x30A83781,0x31A83781,0x32A83781,0x33A83781,0x34A83781,0x35A83781,0x36A83781,0x37A83781,0xE2A1,0x38A83781,0xE1A1,0x50FE,0x39FD3881,0x30FE3881,0x54FE,0x31FE3881,0x32FE3881,0x33FE3881,0x57FE,0x34FE3881,0x35FE3881,0x58FE,0x5DFE,0x36FE3881,0x37FE3881,0x38FE3881,0x39FE3881,0x30813981,0x31813981,0x32813981,0x33813981,0x34813981,0x35813981,0x5EFE,0x36813981,0x37813981,0x38813981,0x39813981,0x30823981,0x31823981,0x32823981,0x33823981,0x34823981,0x35823981,0x36823981,0x37823981,0x38823981,0x39823981,0x30833981,0x6BFE,0x31833981,0x32833981,0x6EFE,0x33833981,0x34833981,0x35833981,0x71FE,0x36833981,0x37833981,0x38833981,0x39833981,0x73FE,0x30843981,0x31843981,0x74FE,0x75FE,0x32843981,0x33843981,0x34843981,0x79FE,0x35843981,0x36843981,0x37843981,0x38843981,0x39843981,0x30853981,0x31853981,0x32853981,0x33853981,0x34853981,0x35853981,0x36853981,0x37853981,0x38853981,0x84FE,0x39853981,0x30863981,0x31863981,0x32863981,0x33863981,0x34863981,0x35863981,0x36863981,0x37863981,0x38863981,0x39863981,0x30873981,0x31873981,0x32873981,0x33873981,0x34873981,0x35873981,0x36873981,0x37873981,0x38873981,0x39873981,0x30883981,0x31883981,0x32883981,0x33883981,0x34883981,0x35883981,0x36883981,0x37883981,0x38883981,0x39883981,0x30893981,0x31893981,0x32893981,0x33893981,0x34893981,0x35893981,0x36893981,0x37893981,0x38893981,0x39893981,0x308A3981,0x318A3981,0x328A3981,0x338A3981,0x348A3981,0x358A3981,0x368A3981,0x378A3981,0x388A3981,0x398A3981,0x308B3981,0x318B3981,0x328B3981,0x338B3981,0x348B3981,0x358B3981,0x368B3981,0x378B3981,0x388B3981,0x398B3981,0x308C3981,0x318C3981,0x328C3981,0x338C3981,0x348C3981,0x358C3981,0x368C3981,0x378C3981,0x388C3981,0x398C3981,0x308D3981,0x318D3981,0x328D3981,0x338D3981,0x348D3981,0x358D3981,0x368D3981,0x378D3981,0x388D3981,0x398D3981,0x308E3981,0x318E3981,0x328E3981,0x338E3981,0x348E3981,0x358E3981,0x368E3981,0x378E3981,0x388E3981,0x398E3981,0x308F3981,0x318F3981,0x328F3981,0x338F3981,0x348F3981,0x358F3981,0x368F3981,0x378F3981,0x388F3981,0x398F3981,0x30903981,0x31903981,0x32903981,0x33903981,0x34903981,0x35903981,0x36903981,0x37903981,0x38903981,0x39903981,0x30913981,0x31913981,0x32913981,0x33913981,0x34913981,0x35913981,0x36913981,0x37913981,0x38913981,0x39913981,0x30923981,0x31923981,0x32923981,0x33923981,0x34923981,0x35923981,0x36923981,0x37923981,0x38923981,0x39923981,0x30933981,0x31933981,0x32933981,0x33933981,0x34933981,0x35933981,0x36933981,0x37933981,0x38933981,0x39933981,0x30943981,0x31943981,0x32943981,0x33943981,0x34943981,0x35943981,0x36943981,0x37943981,0x38943981,0x39943981,0x30953981,0x31953981,0x32953981,0x33953981,0x34953981,0x35953981,0x36953981,0x37953981,0x38953981,0x39953981,0x30963981,0x31963981,0x32963981,0x33963981,0x34963981,0x35963981,0x36963981,0x37963981,0x38963981,0x39963981,0x30973981,0x31973981,0x32973981,0x33973981,0x34973981,0x35973981,0x36973981,0x37973981,0x38973981,0x39973981,0x30983981,0x31983981,0x32983981,0x33983981,0x34983981,0x35983981,0x36983981,0x37983981,0x38983981,0x39983981,0x30993981,0x31993981,0x32993981,0x33993981,0x34993981,0x35993981,0x36993981,0x37993981,0x38993981,0x39993981,0x309A3981,0x319A3981,0x329A3981,0x339A3981,0x349A3981,0x359A3981,0x369A3981,0x379A3981,0x389A3981,0x399A3981,0x309B3981,0x319B3981,0x329B3981,0x339B3981,0x349B3981,0x359B3981,0x369B3981,0x379B3981,0x389B3981,0x399B3981,0x309C3981,0x319C3981,0x329C3981,0x339C3981,0x349C3981,0x359C3981,0x369C3981,0x379C3981,0x389C3981,0x399C3981,0x309D3981,0x319D3981,0x329D3981,0x339D3981,0x349D3981,0x359D3981,0x369D3981,0x379D3981,0x389D3981,0x399D3981,0x309E3981,0x319E3981,0x329E3981,0x339E3981,0x349E3981,0x359E3981,0x369E3981,0x379E3981,0x389E3981,0x399E3981,0x309F3981,0x319F3981,0x329F3981,0x339F3981,0x349F3981,0x359F3981,0x369F3981,0x379F3981,0x389F3981,0x399F3981,0x30A03981,0x31A03981,0x32A03981,0x33A03981,0x34A03981,0x35A03981,0x36A03981,0x37A03981,0x38A03981,0x39A03981,0x30A13981,0x31A13981,0x32A13981,0x33A13981,0x34A13981,0x35A13981,0x36A13981,0x37A13981,0x38A13981,0x39A13981,0x30A23981,0x31A23981,0x32A23981,0x33A23981,0x34A23981,0x35A23981,0x36A23981,0x37A23981,0x38A23981,0x39A23981,0x30A33981,0x31A33981,0x8AA9,0x8BA9,0x8CA9,0x8DA9,0x8EA9,0x8FA9,0x90A9,0x91A9,0x92A9,0x93A9,0x94A9,0x95A9,0x32A33981,0x33A33981,0x34A33981,0x35A33981,0xA1A1,0xA2A1,0xA3A1,0xA8A1,0x36A33981,0xA9A1,0x65A9,0x96A9,0xB4A1,0xB5A1,0xB6A1,0xB7A1,0xB8A1,0xB9A1,0xBAA1,0xBBA1,0xBEA1,0xBFA1,0x93A8,0xFEA1,0xB2A1,0xB3A1,0xBCA1,0xBDA1,0x37A33981,0x38A33981,0x39A33981,0x30A43981,0x31A43981,0x94A8,0x95A8,0x32A43981,0x33A43981,0x40A9,0x41A9,0x42A9,0x43A9,0x44A9,0x45A9,0x46A9,0x47A9,0x48A9,0x34A43981,0x35A43981,0x36A43981,0x37A43981,0x38A43981,0x39A43981,0x30A53981,0x31A53981,0x32A53981,0x33A53981,0x34A53981,0x35A53981,0x36A53981,0x37A53981,0x38A53981,0x39A53981,0x30A63981,0x31A63981,0x32A63981,0x33A63981,0x89A9,0x34A63981,0x35A63981,0xA1A4,0xA2A4,0xA3A4,0xA4A4,0xA5A4,0xA6A4,0xA7A4,0xA8A4,0xA9A4,0xAAA4,0xABA4,0xACA4,0xADA4,0xAEA4,0xAFA4,0xB0A4,0xB1A4,0xB2A4,0xB3A4,0xB4A4,0xB5A4,0xB6A4,0xB7A4,0xB8A4,0xB9A4,0xBAA4,0xBBA4,0xBCA4,0xBDA4,0xBEA4,0xBFA4,0xC0A4,0xC1A4,0xC2A4,0xC3A4,0xC4A4,0xC5A4,0xC6A4,0xC7A4,0xC8A4,0xC9A4,0xCAA4,0xCBA4,0xCCA4,0xCDA4,0xCEA4,0xCFA4,0xD0A4,0xD1A4,0xD2A4,0xD3A4,0xD4A4,0xD5A4,0xD6A4,0xD7A4,0xD8A4,0xD9A4,0xDAA4,0xDBA4,0xDCA4,0xDDA4,0xDEA4,0xDFA4,0xE0A4,0xE1A4,0xE2A4,0xE3A4,0xE4A4,0xE5A4,0xE6A4,0xE7A4,0xE8A4,0xE9A4,0xEAA4,0xEBA4,0xECA4,0xEDA4,0xEEA4,0xEFA4,0xF0A4,0xF1A4,0xF2A4,0xF3A4,0x36A63981,0x37A63981,0x38A63981,0x39A63981,0x30A73981,0x31A73981,0x32A73981,0x61A9,0x62A9,0x66A9,0x67A9,0x33A73981,0x34A73981,0xA1A5,0xA2A5,0xA3A5,0xA4A5,0xA5A5,0xA6A5,0xA7A5,0xA8A5,0xA9A5,0xAAA5,0xABA5,0xACA5,0xADA5,0xAEA5,0xAFA5,0xB0A5,0xB1A5,0xB2A5,0xB3A5,0xB4A5,0xB5A5,0xB6A5,0xB7A5,0xB8A5,0xB9A5,0xBAA5,0xBBA5,0xBCA5,0xBDA5,0xBEA5,0xBFA5,0xC0A5,0xC1A5,0xC2A5,0xC3A5,0xC4A5,0xC5A5,0xC6A5,0xC7A5,0xC8A5,0xC9A5,0xCAA5,0xCBA5,0xCCA5,0xCDA5,0xCEA5,0xCFA5,0xD0A5,0xD1A5,0xD2A5,0xD3A5,0xD4A5,0xD5A5,0xD6A5,0xD7A5,0xD8A5,0xD9A5,0xDAA5,0xDBA5,0xDCA5,0xDDA5,0xDEA5,0xDFA5,0xE0A5,0xE1A5,0xE2A5,0xE3A5,0xE4A5,0xE5A5,0xE6A5,0xE7A5,0xE8A5,0xE9A5,0xEAA5,0xEBA5,0xECA5,0xEDA5,0xEEA5,0xEFA5,0xF0A5,0xF1A5,0xF2A5,0xF3A5,0xF4A5,0xF5A5,0xF6A5,0x35A73981,0x36A73981,0x37A73981,0x38A73981,0x39A73981,0x60A9,0x63A9,0x64A9,0x30A83981,0x31A83981,0x32A83981,0x33A83981,0x34A83981,0x35A83981,0xC5A8,0xC6A8,0xC7A8,0xC8A8,0xC9A8,0xCAA8,0xCBA8,0xCCA8,0xCDA8,0xCEA8,0xCFA8,0xD0A8,0xD1A8,0xD2A8,0xD3A8,0xD4A8,0xD5A8,0xD6A8,0xD7A8,0xD8A8,0xD9A8,0xDAA8,0xDBA8,0xDCA8,0xDDA8,0xDEA8,0xDFA8,0xE0A8,0xE1A8,0xE2A8,0xE3A8,0xE4A8,0xE5A8,0xE6A8,0xE7A8,0xE8A8,0xE9A8,0x36A83981,0x37A83981,0x38A83981,0x39A83981,0x30A93981,0x31A93981,0x32A93981,0x33A93981,0x34A93981,0x35A93981,0x36A93981,0x37A93981,0x38A93981,0x39A93981,0x30AA3981,0x31AA3981,0x32AA3981,0x33AA3981,0x34AA3981,0x35AA3981,0x36AA3981,0x37AA3981,0x38AA3981,0x39AA3981,0x30AB3981,0x31AB3981,0x32AB3981,0x33AB3981,0x34AB3981,0x35AB3981,0x36AB3981,0x37AB3981,0x38AB3981,0x39AB3981,0x30AC3981,0x31AC3981,0x32AC3981,0x33AC3981,0x34AC3981,0x35AC3981,0x36AC3981,0x37AC3981,0x38AC3981,0x39AC3981,0x30AD3981,0x31AD3981,0x32AD3981,0x33AD3981,0x34AD3981,0x35AD3981,0x36AD3981,0x37AD3981,0x38AD3981,0x39AD3981,0x30AE3981,0x31AE3981,0x32AE3981,0x33AE3981,0x34AE3981,0x35AE3981,0x36AE3981,0x37AE3981,0x38AE3981,0x39AE3981,0x30AF3981,0x31AF3981,0x32AF3981,0x33AF3981,0x34AF3981,0x35AF3981,0x36AF3981,0x37AF3981,0x38AF3981,0x39AF3981,0x30B03981,0x31B03981,0x32B03981,0x33B03981,0x34B03981,0x35B03981,0x36B03981,0x37B03981,0x38B03981,0x39B03981,0x30B13981,0x31B13981,0x32B13981,0x33B13981,0x34B13981,0x35B13981,0x36B13981,0x37B13981,0x38B13981,0x39B13981,0x30B23981,0x31B23981,0x32B23981,0x33B23981,0x34B23981,0x35B23981,0x36B23981,0x37B23981,0x38B23981,0x39B23981,0x30B33981,0x31B33981,0x32B33981,0x33B33981,0x34B33981,0x35B33981,0x36B33981,0x37B33981,0x38B33981,0x39B33981,0x30B43981,0x31B43981,0x32B43981,0x33B43981,0x34B43981,0x35B43981,0x36B43981,0x37B43981,0x38B43981,0x39B43981,0x30B53981,0x31B53981,0x32B53981,0x33B53981,0x34B53981,0x35B53981,0x36B53981,0x37B53981,0x38B53981,0x39B53981,0x30B63981,0x31B63981,0x32B63981,0x33B63981,0x34B63981,0x35B63981,0x36B63981,0x37B63981,0x38B63981,0x39B63981,0x30B73981,0x31B73981,0x32B73981,0x33B73981,0x34B73981,0x35B73981,0x36B73981,0x37B73981,0x38B73981,0x39B73981,0x30B83981,0x31B83981,0x32B83981,0x33B83981,0x34B83981,0x35B83981,0x36B83981,0x37B83981,0x38B83981,0x39B83981,0x30B93981,0x31B93981,0x32B93981,0x33B93981,0x34B93981,0x35B93981,0x36B93981,0x37B93981,0x38B93981,0x39B93981,0x30BA3981,0x31BA3981,0x32BA3981,0x33BA3981,0x34BA3981,0x35BA3981,0x36BA3981,0x37BA3981,0x38BA3981,0x39BA3981,0x30BB3981,0x31BB3981,0x32BB3981,0x33BB3981,0x34BB3981,0x35BB3981,0x36BB3981,0x37BB3981,0x38BB3981,0x39BB3981,0x30BC3981,0x31BC3981,0x32BC3981,0x33BC3981,0x34BC3981,0x35BC3981,0x36BC3981,0x37BC3981,0x38BC3981,0x39BC3981,0x30BD3981,0x31BD3981,0x32BD3981,0x33BD3981,0x34BD3981,0x35BD3981,0x36BD3981,0x37BD3981,0x38BD3981,0x39BD3981,0x30BE3981,0x31BE3981,0x32BE3981,0x33BE3981,0x34BE3981,0x35BE3981,0x36BE3981,0x37BE3981,0x38BE3981,0x39BE3981,0x30BF3981,0x31BF3981,0x32BF3981,0x33BF3981,0x34BF3981,0x35BF3981,0x36BF3981,0x37BF3981,0x38BF3981,0x39BF3981,0x30C03981,0x31C03981,0x32C03981,0x33C03981,0x34C03981,0x35C03981,0x36C03981,0x37C03981,0x38C03981,0x39C03981,0x30C13981,0x31C13981,0xE5A2,0xE6A2,0xE7A2,0xE8A2,0xE9A2,0xEAA2,0xEBA2,0xECA2,0xEDA2,0xEEA2,0x32C13981,0x33C13981,0x34C13981,0x35C13981,0x36C13981,0x37C13981,0x38C13981,0x5AA9,0x39C13981,0x30C23981,0x31C23981,0x32C23981,0x33C23981,0x34C23981,0x35C23981,0x36C23981,0x37C23981,0x38C23981,0x39C23981,0x30C33981,0x31C33981,0x32C33981,0x33C33981,0x34C33981,0x35C33981,0x36C33981,0x37C33981,0x38C33981,0x39C33981,0x30C43981,0x31C43981,0x32C43981,0x33C43981,0x34C43981,0x35C43981,0x36C43981,0x37C43981,0x38C43981,0x39C43981,0x30C53981,0x31C53981,0x32C53981,0x33C53981,0x34C53981,0x35C53981,0x36C53981,0x37C53981,0x38C53981,0x39C53981,0x30C63981,0x31C63981,0x32C63981,0x33C63981,0x34C63981,0x35C63981,0x36C63981,0x37C63981,0x38C63981,0x39C63981,0x30C73981,0x31C73981,0x32C73981,0x33C73981,0x34C73981,0x35C73981,0x36C73981,0x37C73981,0x38C73981,0x39C73981,0x30C83981,0x31C83981,0x32C83981,0x33C83981,0x34C83981,0x35C83981,0x36C83981,0x37C83981,0x38C83981,0x39C83981,0x30C93981,0x31C93981,0x32C93981,0x33C93981,0x34C93981,0x35C93981,0x36C93981,0x37C93981,0x38C93981,0x39C93981,0x30CA3981,0x31CA3981,0x32CA3981,0x33CA3981,0x34CA3981,0x35CA3981,0x36CA3981,0x37CA3981,0x38CA3981,0x39CA3981,0x30CB3981,0x31CB3981,0x32CB3981,0x33CB3981,0x34CB3981,0x35CB3981,0x36CB3981,0x37CB3981,0x38CB3981,0x39CB3981,0x30CC3981,0x31CC3981,0x32CC3981,0x33CC3981,0x34CC3981,0x35CC3981,0x36CC3981,0x37CC3981,0x38CC3981,0x39CC3981,0x30CD3981,0x31CD3981,0x49A9,0x32CD3981,0x33CD3981,0x34CD3981,0x35CD3981,0x36CD3981,0x37CD3981,0x38CD3981,0x39CD3981,0x30CE3981,0x31CE3981,0x32CE3981,0x33CE3981,0x34CE3981,0x35CE3981,0x36CE3981,0x37CE3981,0x38CE3981,0x39CE3981,0x30CF3981,0x31CF3981,0x32CF3981,0x33CF3981,0x34CF3981,0x35CF3981,0x36CF3981,0x37CF3981,0x38CF3981,0x39CF3981,0x30D03981,0x31D03981,0x32D03981,0x33D03981,0x34D03981,0x35D03981,0x36D03981,0x37D03981,0x38D03981,0x39D03981,0x30D13981,0x31D13981,0x32D13981,0x33D13981,0x34D13981,0x35D13981,0x36D13981,0x37D13981,0x38D13981,0x39D13981,0x30D23981,0x31D23981,0x32D23981,0x33D23981,0x34D23981,0x35D23981,0x36D23981,0x37D23981,0x38D23981,0x39D23981,0x30D33981,0x31D33981,0x32D33981,0x33D33981,0x34D33981,0x35D33981,0x36D33981,0x37D33981,0x38D33981,0x39D33981,0x30D43981,0x31D43981,0x32D43981,0x33D43981,0x34D43981,0x35D43981,0x36D43981,0x37D43981,0x38D43981,0x39D43981,0x30D53981,0x31D53981,0x32D53981,0x33D53981,0x34D53981,0x35D53981,0x36D53981,0x37D53981,0x38D53981,0x39D53981,0x30D63981,0x31D63981,0x32D63981,0x33D63981,0x34D63981,0x35D63981,0x36D63981,0x37D63981,0x38D63981,0x39D63981,0x30D73981,0x31D73981,0x32D73981,0x33D73981,0x34D73981,0x35D73981,0x36D73981,0x37D73981,0x38D73981,0x39D73981,0x30D83981,0x31D83981,0x32D83981,0x33D83981,0x34D83981,0x35D83981,0x36D83981,0x37D83981,0x38D83981,0x39D83981,0x30D93981,0x31D93981,0x32D93981,0x33D93981,0x34D93981,0x35D93981,0x36D93981,0x37D93981,0x38D93981,0x39D93981,0x30DA3981,0x31DA3981,0x32DA3981,0x33DA3981,0x34DA3981,0x35DA3981,0x36DA3981,0x37DA3981,0x38DA3981,0x39DA3981,0x30DB3981,0x31DB3981,0x32DB3981,0x33DB3981,0x34DB3981,0x35DB3981,0x36DB3981,0x37DB3981,0x38DB3981,0x39DB3981,0x30DC3981,0x31DC3981,0x32DC3981,0x33DC3981,0x34DC3981,0x35DC3981,0x36DC3981,0x37DC3981,0x38DC3981,0x39DC3981,0x30DD3981,0x31DD3981,0x32DD3981,0x33DD3981,0x34DD3981,0x35DD3981,0x36DD3981,0x37DD3981,0x38DD3981,0x39DD3981,0x30DE3981,0x31DE3981,0x32DE3981,0x33DE3981,0x34DE3981,0x35DE3981,0x36DE3981,0x37DE3981,0x38DE3981,0x39DE3981,0x30DF3981,0x31DF3981,0x32DF3981,0x33DF3981,0x34DF3981,0x35DF3981,0x36DF3981,0x37DF3981,0x38DF3981,0x39DF3981,0x30E03981,0x31E03981,0x32E03981,0x33E03981,0x34E03981,0x35E03981,0x36E03981,0x37E03981,0x38E03981,0x39E03981,0x30E13981,0x31E13981,0x32E13981,0x33E13981,0x34E13981,0x35E13981,0x36E13981,0x37E13981,0x38E13981,0x39E13981,0x30E23981,0x31E23981,0x32E23981,0x33E23981,0x34E23981,0x35E23981,0x36E23981,0x37E23981,0x38E23981,0x39E23981,0x30E33981,0x31E33981,0x32E33981,0x33E33981,0x34E33981,0x35E33981,0x36E33981,0x37E33981,0x38E33981,0x39E33981,0x30E43981,0x31E43981,0x32E43981,0x33E43981,0x34E43981,0x35E43981,0x4AA9,0x4BA9,0x36E43981,0x37E43981,0x38E43981,0x39E43981,0x30E53981,0x31E53981,0x32E53981,0x33E53981,0x34E53981,0x35E53981,0x36E53981,0x37E53981,0x4CA9,0x4DA9,0x4EA9,0x38E53981,0x39E53981,0x4FA9,0x30E63981,0x31E63981,0x32E63981,0x33E63981,0x34E63981,0x35E63981,0x36E63981,0x37E63981,0x38E63981,0x39E63981,0x30E73981,0x31E73981,0x32E73981,0x33E73981,0x34E73981,0x35E73981,0x36E73981,0x37E73981,0x38E73981,0x39E73981,0x30E83981,0x31E83981,0x32E83981,0x33E83981,0x34E83981,0x35E83981,0x36E83981,0x37E83981,0x38E83981,0x39E83981,0x30E93981,0x31E93981,0x32E93981,0x33E93981,0x50A9,0x34E93981,0x35E93981,0x36E93981,0x37E93981,0x38E93981,0x39E93981,0x30EA3981,0x31EA3981,0x32EA3981,0x51A9,0x33EA3981,0x34EA3981,0x52A9,0x53A9,0x35EA3981,0x36EA3981,0x54A9,0x37EA3981,0x38EA3981,0x39EA3981,0x30EB3981,0x31EB3981,0x32EB3981,0x33EB3981,0x34EB3981,0x35EB3981,0x36EB3981,0x37EB3981,0x38EB3981,0x39EB3981,0x30EC3981,0x31EC3981,0x32EC3981,0x33EC3981,0x34EC3981,0x35EC3981,0x36EC3981,0x37EC3981,0x38EC3981,0x39EC3981,0x30ED3981,0x31ED3981,0x32ED3981,0x33ED3981,0x34ED3981,0x35ED3981,0x36ED3981,0x37ED3981,0x38ED3981,0x39ED3981,0x30EE3981,0x31EE3981,0x32EE3981,0x33EE3981,0x34EE3981,0x35EE3981,0x36EE3981,0x37EE3981,0x38EE3981,0x39EE3981,0x30EF3981,0x31EF3981,0x32EF3981,0x33EF3981,0x34EF3981,0x35EF3981,0x36EF3981,0x37EF3981,0x38EF3981,0x39EF3981,0x30F03981,0x31F03981,0x32F03981,0x33F03981,0x34F03981,0x35F03981,0x36F03981,0x37F03981,0x38F03981,0x39F03981,0x30F13981,0x31F13981,0x32F13981,0x33F13981,0x34F13981,0x35F13981,0x36F13981,0x37F13981,0x38F13981,0x39F13981,0x30F23981,0x31F23981,0x32F23981,0x33F23981,0x34F23981,0x35F23981,0x36F23981,0x37F23981,0x38F23981,0x39F23981,0x30F33981,0x31F33981,0x32F33981,0x33F33981,0x34F33981,0x35F33981,0x36F33981,0x37F33981,0x38F33981,0x39F33981,0x30F43981,0x31F43981,0x32F43981,0x33F43981,0x34F43981,0x35F43981,0x36F43981,0x37F43981,0x38F43981,0x39F43981,0x30F53981,0x31F53981,0x32F53981,0x33F53981,0x34F53981,0x35F53981,0x36F53981,0x37F53981,0x38F53981,0x39F53981,0x56FE,0x30F63981,0x31F63981,0x32F63981,0x33F63981,0x34F63981,0x35F63981,0x36F63981,0x37F63981,0x38F63981,0x39F63981,0x30F73981,0x31F73981,0x32F73981,0x33F73981,0x34F73981,0x35F73981,0x36F73981,0x37F73981,0x38F73981,0x39F73981,0x30F83981,0x31F83981,0x32F83981,0x33F83981,0x34F83981,0x35F83981,0x36F83981,0x37F83981,0x38F83981,0x39F83981,0x30F93981,0x31F93981,0x32F93981,0x33F93981,0x34F93981,0x35F93981,0x36F93981,0x37F93981,0x38F93981,0x39F93981,0x30FA3981,0x31FA3981,0x32FA3981,0x55FE,0x33FA3981,0x34FA3981,0x35FA3981,0x36FA3981,0x37FA3981,0x38FA3981,0x39FA3981,0x30FB3981,0x31FB3981,0x32FB3981,0x33FB3981,0x34FB3981,0x35FB3981,0x36FB3981,0x37FB3981,0x38FB3981,0x39FB3981,0x30FC3981,0x31FC3981,0x32FC3981,0x33FC3981,0x34FC3981,0x35FC3981,0x36FC3981,0x37FC3981,0x38FC3981,0x39FC3981,0x30FD3981,0x31FD3981,0x32FD3981,0x33FD3981,0x34FD3981,0x35FD3981,0x36FD3981,0x37FD3981,0x38FD3981,0x39FD3981,0x30FE3981,0x31FE3981,0x32FE3981,0x33FE3981,0x34FE3981,0x35FE3981,0x36FE3981,0x37FE3981,0x38FE3981,0x39FE3981,0x30813082,0x31813082,0x32813082,0x33813082,0x34813082,0x35813082,0x36813082,0x37813082,0x38813082,0x39813082,0x30823082,0x31823082,0x32823082,0x33823082,0x34823082,0x35823082,0x36823082,0x37823082,0x38823082,0x39823082,0x30833082,0x31833082,0x32833082,0x33833082,0x34833082,0x35833082,0x36833082,0x37833082,0x38833082,0x39833082,0x30843082,0x31843082,0x32843082,0x33843082,0x34843082,0x35843082,0x36843082,0x37843082,0x38843082,0x39843082,0x30853082,0x31853082,0x32853082,0x33853082,0x34853082,0x35853082,0x36853082,0x37853082,0x38853082,0x39853082,0x30863082,0x31863082,0x32863082,0x33863082,0x34863082,0x35863082,0x36863082,0x37863082,0x38863082,0x39863082,0x30873082,0x31873082,0x32873082,0x33873082,0x34873082,0x35873082,0x36873082,0x37873082,0x38873082,0x39873082,0x30883082,0x31883082,0x32883082,0x33883082,0x34883082,0x35883082,0x36883082,0x37883082,0x38883082,0x39883082,0x30893082,0x31893082,0x32893082,0x33893082,0x34893082,0x35893082,0x36893082,0x37893082,0x38893082,0x39893082,0x308A3082,0x318A3082,0x328A3082,0x338A3082,0x348A3082,0x358A3082,0x368A3082,0x378A3082,0x388A3082,0x398A3082,0x308B3082,0x318B3082,0x328B3082,0x338B3082,0x348B3082,0x358B3082,0x368B3082,0x378B3082,0x388B3082,0x398B3082,0x308C3082,0x318C3082,0x328C3082,0x338C3082,0x348C3082,0x358C3082,0x368C3082,0x378C3082,0x388C3082,0x398C3082,0x308D3082,0x318D3082,0x328D3082,0x338D3082,0x348D3082,0x358D3082,0x368D3082,0x378D3082,0x388D3082,0x398D3082,0x308E3082,0x318E3082,0x328E3082,0x338E3082,0x348E3082,0x358E3082,0x368E3082,0x378E3082,0x388E3082,0x398E3082,0x308F3082,0x318F3082,0x328F3082,0x338F3082,0x348F3082,0x358F3082,0x368F3082,0x378F3082,0x388F3082,0x398F3082,0x30903082,0x31903082,0x32903082,0x33903082,0x34903082,0x35903082,0x36903082,0x37903082,0x38903082,0x39903082,0x30913082,0x31913082,0x32913082,0x33913082,0x34913082,0x35913082,0x36913082,0x37913082,0x38913082,0x39913082,0x30923082,0x31923082,0x32923082,0x33923082,0x34923082,0x35923082,0x36923082,0x37923082,0x38923082,0x39923082,0x30933082,0x31933082,0x32933082,0x33933082,0x34933082,0x35933082,0x36933082,0x37933082,0x38933082,0x39933082,0x30943082,0x31943082,0x32943082,0x33943082,0x34943082,0x35943082,0x36943082,0x37943082,0x38943082,0x39943082,0x30953082,0x31953082,0x32953082,0x33953082,0x34953082,0x35953082,0x36953082,0x37953082,0x38953082,0x39953082,0x30963082,0x31963082,0x32963082,0x33963082,0x34963082,0x35963082,0x36963082,0x37963082,0x38963082,0x39963082,0x30973082,0x31973082,0x32973082,0x33973082,0x34973082,0x35973082,0x36973082,0x37973082,0x38973082,0x39973082,0x30983082,0x31983082,0x32983082,0x33983082,0x34983082,0x35983082,0x36983082,0x37983082,0x38983082,0x39983082,0x30993082,0x31993082,0x32993082,0x33993082,0x34993082,0x35993082,0x36993082,0x37993082,0x38993082,0x39993082,0x309A3082,0x5AFE,0x319A3082,0x329A3082,0x339A3082,0x349A3082,0x359A3082,0x369A3082,0x379A3082,0x389A3082,0x399A3082,0x309B3082,0x319B3082,0x329B3082,0x339B3082,0x349B3082,0x359B3082,0x369B3082,0x379B3082,0x389B3082,0x399B3082,0x309C3082,0x319C3082,0x329C3082,0x339C3082,0x349C3082,0x359C3082,0x369C3082,0x379C3082,0x389C3082,0x399C3082,0x309D3082,0x319D3082,0x329D3082,0x339D3082,0x349D3082,0x359D3082,0x369D3082,0x379D3082,0x389D3082,0x399D3082,0x309E3082,0x319E3082,0x329E3082,0x339E3082,0x349E3082,0x359E3082,0x369E3082,0x379E3082,0x389E3082,0x399E3082,0x309F3082,0x319F3082,0x329F3082,0x339F3082,0x349F3082,0x359F3082,0x369F3082,0x379F3082,0x389F3082,0x399F3082,0x30A03082,0x31A03082,0x32A03082,0x33A03082,0x34A03082,0x35A03082,0x36A03082,0x37A03082,0x38A03082,0x39A03082,0x30A13082,0x31A13082,0x32A13082,0x33A13082,0x34A13082,0x35A13082,0x36A13082,0x37A13082,0x38A13082,0x39A13082,0x30A23082,0x31A23082,0x32A23082,0x33A23082,0x34A23082,0x35A23082,0x36A23082,0x37A23082,0x38A23082,0x39A23082,0x30A33082,0x31A33082,0x32A33082,0x33A33082,0x34A33082,0x35A33082,0x36A33082,0x37A33082,0x38A33082,0x39A33082,0x30A43082,0x31A43082,0x32A43082,0x33A43082,0x34A43082,0x35A43082,0x36A43082,0x37A43082,0x38A43082,0x39A43082,0x30A53082,0x31A53082,0x5CFE,0x32A53082,0x33A53082,0x34A53082,0x35A53082,0x36A53082,0x37A53082,0x38A53082,0x39A53082,0x30A63082,0x31A63082,0x32A63082,0x5BFE,0x60FE,0x38F23082,0x39F23082,0x30F33082,0x31F33082,0x32F33082,0x33F33082,0x34F33082,0x35F33082,0x36F33082,0x37F33082,0x38F33082,0x39F33082,0x30F43082,0x31F43082,0x32F43082,0x33F43082,0x34F43082,0x35F43082,0x36F43082,0x37F43082,0x38F43082,0x39F43082,0x30F53082,0x31F53082,0x32F53082,0x33F53082,0x34F53082,0x35F53082,0x36F53082,0x37F53082,0x38F53082,0x39F53082,0x30F63082,0x31F63082,0x32F63082,0x33F63082,0x34F63082,0x35F63082,0x36F63082,0x37F63082,0x38F63082,0x39F63082,0x30F73082,0x31F73082,0x32F73082,0x33F73082,0x34F73082,0x35F73082,0x36F73082,0x37F73082,0x38F73082,0x39F73082,0x30F83082,0x31F83082,0x32F83082,0x33F83082,0x34F83082,0x35F83082,0x36F83082,0x37F83082,0x38F83082,0x39F83082,0x30F93082,0x31F93082,0x32F93082,0x33F93082,0x34F93082,0x35F93082,0x36F93082,0x37F93082,0x38F93082,0x39F93082,0x30FA3082,0x31FA3082,0x32FA3082,0x33FA3082,0x34FA3082,0x35FA3082,0x36FA3082,0x37FA3082,0x38FA3082,0x39FA3082,0x30FB3082,0x31FB3082,0x32FB3082,0x5FFE,0x33FB3082,0x34FB3082,0x35FB3082,0x36FB3082,0x37FB3082,0x38FB3082,0x39FB3082,0x30FC3082,0x31FC3082,0x32FC3082,0x33FC3082,0x34FC3082,0x35FC3082,0x36FC3082,0x37FC3082,0x38FC3082,0x39FC3082,0x30FD3082,0x31FD3082,0x32FD3082,0x33FD3082,0x34FD3082,0x35FD3082,0x36FD3082,0x37FD3082,0x38FD3082,0x39FD3082,0x30FE3082,0x31FE3082,0x32FE3082,0x33FE3082,0x34FE3082,0x35FE3082,0x36FE3082,0x37FE3082,0x38FE3082,0x39FE3082,0x30813182,0x31813182,0x32813182,0x33813182,0x34813182,0x35813182,0x36813182,0x37813182,0x38813182,0x39813182,0x30823182,0x31823182,0x32823182,0x33823182,0x34823182,0x35823182,0x36823182,0x37823182,0x38823182,0x39823182,0x30833182,0x31833182,0x32833182,0x33833182,0x34833182,0x35833182,0x36833182,0x37833182,0x38833182,0x39833182,0x30843182,0x31843182,0x32843182,0x33843182,0x34843182,0x35843182,0x36843182,0x37843182,0x38843182,0x39843182,0x30853182,0x31853182,0x32853182,0x33853182,0x34853182,0x35853182,0x36853182,0x37853182,0x38853182,0x39853182,0x30863182,0x31863182,0x32863182,0x33863182,0x34863182,0x35863182,0x36863182,0x37863182,0x38863182,0x62FE,0x65FE,0x39863182,0x30873182,0x31873182,0x32873182,0x33873182,0x34873182,0x35873182,0x36873182,0x37873182,0x38873182,0x39873182,0x30883182,0x31883182,0x32883182,0x63FE,0x33883182,0x34883182,0x35883182,0x36883182,0x37883182,0x38883182,0x39883182,0x30893182,0x31893182,0x32893182,0x33893182,0x34893182,0x35893182,0x36893182,0x37893182,0x38893182,0x39893182,0x308A3182,0x318A3182,0x328A3182,0x338A3182,0x348A3182,0x358A3182,0x368A3182,0x378A3182,0x388A3182,0x398A3182,0x308B3182,0x318B3182,0x328B3182,0x338B3182,0x348B3182,0x358B3182,0x368B3182,0x378B3182,0x388B3182,0x398B3182,0x308C3182,0x318C3182,0x328C3182,0x338C3182,0x348C3182,0x358C3182,0x368C3182,0x378C3182,0x388C3182,0x398C3182,0x308D3182,0x318D3182,0x328D3182,0x338D3182,0x348D3182,0x358D3182,0x368D3182,0x378D3182,0x388D3182,0x398D3182,0x308E3182,0x318E3182,0x328E3182,0x338E3182,0x348E3182,0x358E3182,0x368E3182,0x378E3182,0x388E3182,0x398E3182,0x308F3182,0x318F3182,0x328F3182,0x338F3182,0x348F3182,0x358F3182,0x368F3182,0x378F3182,0x388F3182,0x398F3182,0x30903182,0x31903182,0x32903182,0x33903182,0x34903182,0x35903182,0x36903182,0x37903182,0x38903182,0x39903182,0x30913182,0x31913182,0x32913182,0x33913182,0x34913182,0x35913182,0x36913182,0x37913182,0x38913182,0x39913182,0x30923182,0x31923182,0x32923182,0x33923182,0x34923182,0x35923182,0x36923182,0x37923182,0x38923182,0x39923182,0x30933182,0x31933182,0x32933182,0x33933182,0x34933182,0x35933182,0x36933182,0x37933182,0x38933182,0x39933182,0x30943182,0x31943182,0x32943182,0x33943182,0x34943182,0x35943182,0x36943182,0x37943182,0x38943182,0x39943182,0x30953182,0x31953182,0x32953182,0x33953182,0x34953182,0x35953182,0x36953182,0x37953182,0x38953182,0x39953182,0x30963182,0x31963182,0x32963182,0x33963182,0x34963182,0x35963182,0x36963182,0x37963182,0x38963182,0x39963182,0x64FE,0x30973182,0x31973182,0x32973182,0x33973182,0x34973182,0x35973182,0x36973182,0x37973182,0x38973182,0x39973182,0x30983182,0x31983182,0x32983182,0x33983182,0x34983182,0x35983182,0x36983182,0x37983182,0x38983182,0x39983182,0x30993182,0x31993182,0x32993182,0x33993182,0x34993182,0x35993182,0x36993182,0x37993182,0x38993182,0x39993182,0x309A3182,0x319A3182,0x329A3182,0x339A3182,0x349A3182,0x359A3182,0x369A3182,0x379A3182,0x389A3182,0x399A3182,0x309B3182,0x319B3182,0x329B3182,0x339B3182,0x349B3182,0x359B3182,0x369B3182,0x379B3182,0x389B3182,0x399B3182,0x309C3182,0x319C3182,0x329C3182,0x339C3182,0x349C3182,0x359C3182,0x369C3182,0x379C3182,0x389C3182,0x399C3182,0x309D3182,0x319D3182,0x329D3182,0x339D3182,0x349D3182,0x359D3182,0x369D3182,0x379D3182,0x389D3182,0x399D3182,0x309E3182,0x319E3182,0x329E3182,0x339E3182,0x349E3182,0x359E3182,0x369E3182,0x379E3182,0x389E3182,0x399E3182,0x309F3182,0x319F3182,0x329F3182,0x339F3182,0x349F3182,0x359F3182,0x369F3182,0x379F3182,0x389F3182,0x399F3182,0x30A03182,0x31A03182,0x32A03182,0x33A03182,0x34A03182,0x35A03182,0x36A03182,0x37A03182,0x38A03182,0x39A03182,0x30A13182,0x31A13182,0x32A13182,0x33A13182,0x34A13182,0x35A13182,0x36A13182,0x37A13182,0x38A13182,0x39A13182,0x30A23182,0x31A23182,0x32A23182,0x33A23182,0x34A23182,0x35A23182,0x36A23182,0x37A23182,0x38A23182,0x39A23182,0x30A33182,0x31A33182,0x32A33182,0x33A33182,0x34A33182,0x35A33182,0x36A33182,0x37A33182,0x38A33182,0x39A33182,0x30A43182,0x31A43182,0x32A43182,0x33A43182,0x34A43182,0x35A43182,0x36A43182,0x37A43182,0x38A43182,0x39A43182,0x30A53182,0x31A53182,0x32A53182,0x33A53182,0x34A53182,0x35A53182,0x36A53182,0x37A53182,0x38A53182,0x39A53182,0x30A63182,0x31A63182,0x32A63182,0x33A63182,0x34A63182,0x35A63182,0x36A63182,0x37A63182,0x38A63182,0x39A63182,0x30A73182,0x31A73182,0x32A73182,0x33A73182,0x34A73182,0x35A73182,0x36A73182,0x37A73182,0x38A73182,0x39A73182,0x30A83182,0x31A83182,0x32A83182,0x33A83182,0x34A83182,0x35A83182,0x36A83182,0x37A83182,0x38A83182,0x39A83182,0x30A93182,0x31A93182,0x32A93182,0x33A93182,0x34A93182,0x35A93182,0x36A93182,0x37A93182,0x38A93182,0x39A93182,0x30AA3182,0x31AA3182,0x32AA3182,0x33AA3182,0x34AA3182,0x35AA3182,0x36AA3182,0x37AA3182,0x38AA3182,0x39AA3182,0x30AB3182,0x31AB3182,0x32AB3182,0x33AB3182,0x34AB3182,0x35AB3182,0x36AB3182,0x37AB3182,0x38AB3182,0x39AB3182,0x30AC3182,0x31AC3182,0x32AC3182,0x33AC3182,0x34AC3182,0x35AC3182,0x36AC3182,0x37AC3182,0x68FE,0x38AC3182,0x39AC3182,0x30AD3182,0x31AD3182,0x32AD3182,0x33AD3182,0x34AD3182,0x35AD3182,0x36AD3182,0x37AD3182,0x38AD3182,0x39AD3182,0x30AE3182,0x31AE3182,0x32AE3182,0x33AE3182,0x34AE3182,0x35AE3182,0x36AE3182,0x37AE3182,0x38AE3182,0x39AE3182,0x30AF3182,0x31AF3182,0x32AF3182,0x33AF3182,0x34AF3182,0x35AF3182,0x36AF3182,0x37AF3182,0x38AF3182,0x39AF3182,0x30B03182,0x31B03182,0x32B03182,0x33B03182,0x34B03182,0x35B03182,0x36B03182,0x37B03182,0x38B03182,0x39B03182,0x30B13182,0x31B13182,0x32B13182,0x33B13182,0x34B13182,0x35B13182,0x36B13182,0x37B13182,0x38B13182,0x39B13182,0x30B23182,0x31B23182,0x32B23182,0x33B23182,0x34B23182,0x35B23182,0x36B23182,0x37B23182,0x38B23182,0x39B23182,0x30B33182,0x31B33182,0x32B33182,0x33B33182,0x34B33182,0x35B33182,0x36B33182,0x37B33182,0x38B33182,0x39B33182,0x30B43182,0x31B43182,0x32B43182,0x33B43182,0x34B43182,0x35B43182,0x36B43182,0x37B43182,0x38B43182,0x39B43182,0x30B53182,0x31B53182,0x32B53182,0x33B53182,0x34B53182,0x35B53182,0x36B53182,0x37B53182,0x38B53182,0x39B53182,0x30B63182,0x31B63182,0x32B63182,0x33B63182,0x34B63182,0x35B63182,0x36B63182,0x37B63182,0x38B63182,0x39B63182,0x30B73182,0x31B73182,0x32B73182,0x33B73182,0x34B73182,0x35B73182,0x36B73182,0x37B73182,0x38B73182,0x39B73182,0x30B83182,0x31B83182,0x32B83182,0x33B83182,0x34B83182,0x35B83182,0x36B83182,0x37B83182,0x38B83182,0x39B83182,0x30B93182,0x31B93182,0x32B93182,0x33B93182,0x34B93182,0x35B93182,0x36B93182,0x37B93182,0x38B93182,0x39B93182,0x30BA3182,0x31BA3182,0x32BA3182,0x33BA3182,0x34BA3182,0x35BA3182,0x36BA3182,0x37BA3182,0x38BA3182,0x39BA3182,0x30BB3182,0x31BB3182,0x32BB3182,0x33BB3182,0x34BB3182,0x35BB3182,0x36BB3182,0x37BB3182,0x38BB3182,0x39BB3182,0x30BC3182,0x31BC3182,0x32BC3182,0x33BC3182,0x34BC3182,0x35BC3182,0x36BC3182,0x37BC3182,0x38BC3182,0x39BC3182,0x30BD3182,0x31BD3182,0x32BD3182,0x33BD3182,0x34BD3182,0x35BD3182,0x36BD3182,0x37BD3182,0x38BD3182,0x39BD3182,0x30BE3182,0x31BE3182,0x32BE3182,0x33BE3182,0x34BE3182,0x35BE3182,0x36BE3182,0x37BE3182,0x38BE3182,0x39BE3182,0x30BF3182,0x31BF3182,0x32BF3182,0x33BF3182,0x34BF3182,0x35BF3182,0x36BF3182,0x37BF3182,0x38BF3182,0x39BF3182,0x30C03182,0x31C03182,0x32C03182,0x33C03182,0x34C03182,0x35C03182,0x36C03182,0x37C03182,0x38C03182,0x39C03182,0x30C13182,0x31C13182,0x32C13182,0x33C13182,0x34C13182,0x35C13182,0x36C13182,0x37C13182,0x38C13182,0x39C13182,0x30C23182,0x31C23182,0x32C23182,0x33C23182,0x34C23182,0x35C23182,0x36C23182,0x37C23182,0x38C23182,0x39C23182,0x30C33182,0x31C33182,0x32C33182,0x33C33182,0x34C33182,0x35C33182,0x36C33182,0x37C33182,0x38C33182,0x39C33182,0x30C43182,0x31C43182,0x32C43182,0x33C43182,0x34C43182,0x35C43182,0x36C43182,0x37C43182,0x38C43182,0x39C43182,0x30C53182,0x31C53182,0x32C53182,0x33C53182,0x34C53182,0x35C53182,0x36C53182,0x37C53182,0x38C53182,0x39C53182,0x30C63182,0x31C63182,0x32C63182,0x33C63182,0x34C63182,0x35C63182,0x36C63182,0x37C63182,0x38C63182,0x39C63182,0x30C73182,0x31C73182,0x32C73182,0x33C73182,0x34C73182,0x35C73182,0x36C73182,0x37C73182,0x38C73182,0x39C73182,0x30C83182,0x31C83182,0x32C83182,0x33C83182,0x34C83182,0x35C83182,0x36C83182,0x37C83182,0x38C83182,0x39C83182,0x30C93182,0x31C93182,0x32C93182,0x33C93182,0x34C93182,0x69FE,0x35C93182,0x36C93182,0x37C93182,0x38C93182,0x39C93182,0x30CA3182,0x31CA3182,0x32CA3182,0x33CA3182,0x34CA3182,0x35CA3182,0x36CA3182,0x37CA3182,0x38CA3182,0x39CA3182,0x30CB3182,0x31CB3182,0x32CB3182,0x33CB3182,0x34CB3182,0x35CB3182,0x36CB3182,0x37CB3182,0x38CB3182,0x39CB3182,0x30CC3182,0x31CC3182,0x32CC3182,0x33CC3182,0x34CC3182,0x35CC3182,0x36CC3182,0x37CC3182,0x38CC3182,0x39CC3182,0x30CD3182,0x31CD3182,0x32CD3182,0x33CD3182,0x34CD3182,0x35CD3182,0x36CD3182,0x37CD3182,0x38CD3182,0x39CD3182,0x30CE3182,0x31CE3182,0x32CE3182,0x33CE3182,0x34CE3182,0x35CE3182,0x36CE3182,0x37CE3182,0x38CE3182,0x39CE3182,0x30CF3182,0x31CF3182,0x32CF3182,0x33CF3182,0x34CF3182,0x35CF3182,0x36CF3182,0x37CF3182,0x38CF3182,0x39CF3182,0x30D03182,0x31D03182,0x32D03182,0x33D03182,0x34D03182,0x35D03182,0x36D03182,0x37D03182,0x38D03182,0x39D03182,0x30D13182,0x31D13182,0x32D13182,0x33D13182,0x34D13182,0x35D13182,0x36D13182,0x37D13182,0x38D13182,0x39D13182,0x30D23182,0x31D23182,0x32D23182,0x33D23182,0x34D23182,0x35D23182,0x36D23182,0x37D23182,0x38D23182,0x39D23182,0x30D33182,0x31D33182,0x32D33182,0x33D33182,0x34D33182,0x35D33182,0x36D33182,0x37D33182,0x38D33182,0x39D33182,0x30D43182,0x31D43182,0x32D43182,0x33D43182,0x34D43182,0x35D43182,0x36D43182,0x37D43182,0x6AFE,0x6FFE,0x33AF3282,0x34AF3282,0x35AF3282,0x36AF3282,0x37AF3282,0x38AF3282,0x39AF3282,0x30B03282,0x31B03282,0x32B03282,0x33B03282,0x34B03282,0x35B03282,0x36B03282,0x37B03282,0x38B03282,0x39B03282,0x30B13282,0x31B13282,0x32B13282,0x33B13282,0x34B13282,0x35B13282,0x36B13282,0x37B13282,0x38B13282,0x39B13282,0x30B23282,0x31B23282,0x32B23282,0x33B23282,0x34B23282,0x35B23282,0x36B23282,0x37B23282,0x38B23282,0x39B23282,0x30B33282,0x31B33282,0x32B33282,0x33B33282,0x34B33282,0x35B33282,0x36B33282,0x37B33282,0x38B33282,0x39B33282,0x30B43282,0x31B43282,0x32B43282,0x33B43282,0x34B43282,0x35B43282,0x36B43282,0x37B43282,0x38B43282,0x39B43282,0x30B53282,0x31B53282,0x32B53282,0x33B53282,0x34B53282,0x35B53282,0x36B53282,0x37B53282,0x38B53282,0x39B53282,0x30B63282,0x31B63282,0x32B63282,0x33B63282,0x34B63282,0x35B63282,0x36B63282,0x37B63282,0x38B63282,0x39B63282,0x30B73282,0x31B73282,0x32B73282,0x33B73282,0x34B73282,0x35B73282,0x36B73282,0x37B73282,0x38B73282,0x39B73282,0x30B83282,0x31B83282,0x32B83282,0x33B83282,0x34B83282,0x35B83282,0x36B83282,0x37B83282,0x38B83282,0x39B83282,0x30B93282,0x31B93282,0x32B93282,0x33B93282,0x34B93282,0x35B93282,0x36B93282,0x37B93282,0x38B93282,0x39B93282,0x30BA3282,0x31BA3282,0x32BA3282,0x33BA3282,0x34BA3282,0x35BA3282,0x36BA3282,0x37BA3282,0x38BA3282,0x39BA3282,0x30BB3282,0x31BB3282,0x32BB3282,0x33BB3282,0x34BB3282,0x35BB3282,0x36BB3282,0x37BB3282,0x38BB3282,0x39BB3282,0x30BC3282,0x31BC3282,0x32BC3282,0x33BC3282,0x34BC3282,0x35BC3282,0x36BC3282,0x37BC3282,0x38BC3282,0x39BC3282,0x30BD3282,0x31BD3282,0x32BD3282,0x33BD3282,0x34BD3282,0x35BD3282,0x36BD3282,0x37BD3282,0x38BD3282,0x39BD3282,0x30BE3282,0x31BE3282,0x32BE3282,0x33BE3282,0x34BE3282,0x35BE3282,0x36BE3282,0x37BE3282,0x38BE3282,0x39BE3282,0x30BF3282,0x31BF3282,0x32BF3282,0x33BF3282,0x34BF3282,0x35BF3282,0x36BF3282,0x37BF3282,0x38BF3282,0x39BF3282,0x30C03282,0x31C03282,0x32C03282,0x33C03282,0x34C03282,0x35C03282,0x36C03282,0x37C03282,0x38C03282,0x39C03282,0x30C13282,0x31C13282,0x32C13282,0x33C13282,0x34C13282,0x35C13282,0x36C13282,0x37C13282,0x38C13282,0x39C13282,0x30C23282,0x31C23282,0x32C23282,0x33C23282,0x34C23282,0x35C23282,0x36C23282,0x37C23282,0x38C23282,0x39C23282,0x30C33282,0x31C33282,0x32C33282,0x33C33282,0x34C33282,0x35C33282,0x36C33282,0x37C33282,0x38C33282,0x39C33282,0x30C43282,0x31C43282,0x32C43282,0x33C43282,0x34C43282,0x35C43282,0x36C43282,0x37C43282,0x38C43282,0x39C43282,0x30C53282,0x31C53282,0x32C53282,0x33C53282,0x34C53282,0x35C53282,0x36C53282,0x37C53282,0x38C53282,0x39C53282,0x30C63282,0x31C63282,0x32C63282,0x33C63282,0x34C63282,0x35C63282,0x36C63282,0x37C63282,0x38C63282,0x39C63282,0x30C73282,0x31C73282,0x32C73282,0x33C73282,0x34C73282,0x35C73282,0x36C73282,0x37C73282,0x38C73282,0x39C73282,0x30C83282,0x31C83282,0x32C83282,0x33C83282,0x34C83282,0x35C83282,0x36C83282,0x37C83282,0x38C83282,0x39C83282,0x30C93282,0x31C93282,0x32C93282,0x33C93282,0x34C93282,0x35C93282,0x36C93282,0x70FE,0x72FE,0x38F83282,0x39F83282,0x30F93282,0x31F93282,0x32F93282,0x33F93282,0x34F93282,0x35F93282,0x36F93282,0x37F93282,0x38F93282,0x39F93282,0x30FA3282,0x31FA3282,0x32FA3282,0x33FA3282,0x34FA3282,0x35FA3282,0x36FA3282,0x37FA3282,0x38FA3282,0x39FA3282,0x30FB3282,0x31FB3282,0x32FB3282,0x33FB3282,0x34FB3282,0x35FB3282,0x36FB3282,0x37FB3282,0x38FB3282,0x39FB3282,0x30FC3282,0x31FC3282,0x32FC3282,0x33FC3282,0x34FC3282,0x35FC3282,0x36FC3282,0x37FC3282,0x38FC3282,0x39FC3282,0x30FD3282,0x31FD3282,0x32FD3282,0x33FD3282,0x34FD3282,0x35FD3282,0x36FD3282,0x37FD3282,0x38FD3282,0x39FD3282,0x30FE3282,0x31FE3282,0x32FE3282,0x33FE3282,0x34FE3282,0x35FE3282,0x36FE3282,0x37FE3282,0x38FE3282,0x39FE3282,0x30813382,0x31813382,0x32813382,0x33813382,0x34813382,0x35813382,0x36813382,0x37813382,0x38813382,0x39813382,0x30823382,0x31823382,0x32823382,0x33823382,0x34823382,0x35823382,0x36823382,0x37823382,0x38823382,0x39823382,0x30833382,0x31833382,0x32833382,0x33833382,0x34833382,0x35833382,0x36833382,0x37833382,0x38833382,0x39833382,0x30843382,0x31843382,0x32843382,0x33843382,0x34843382,0x35843382,0x36843382,0x37843382,0x38843382,0x39843382,0x30853382,0x31853382,0x32853382,0x33853382,0x34853382,0x35853382,0x36853382,0x37853382,0x38853382,0x39853382,0x30863382,0x31863382,0x32863382,0x33863382,0x78FE,0x34863382,0x35863382,0x36863382,0x37863382,0x77FE,0x38863382,0x39863382,0x30873382,0x31873382,0x32873382,0x33873382,0x34873382,0x35873382,0x36873382,0x37873382,0x38873382,0x39873382,0x30883382,0x31883382,0x32883382,0x33883382,0x34883382,0x35883382,0x36883382,0x37883382,0x38883382,0x39883382,0x30893382,0x31893382,0x32893382,0x33893382,0x34893382,0x35893382,0x36893382,0x37893382,0x38893382,0x39893382,0x308A3382,0x318A3382,0x328A3382,0x338A3382,0x348A3382,0x358A3382,0x368A3382,0x378A3382,0x388A3382,0x398A3382,0x308B3382,0x7AFE,0x318B3382,0x328B3382,0x338B3382,0x348B3382,0x358B3382,0x368B3382,0x378B3382,0x388B3382,0x398B3382,0x308C3382,0x318C3382,0x328C3382,0x338C3382,0x348C3382,0x358C3382,0x368C3382,0x378C3382,0x388C3382,0x398C3382,0x308D3382,0x318D3382,0x328D3382,0x338D3382,0x348D3382,0x358D3382,0x368D3382,0x378D3382,0x388D3382,0x398D3382,0x308E3382,0x318E3382,0x328E3382,0x338E3382,0x348E3382,0x358E3382,0x368E3382,0x378E3382,0x388E3382,0x398E3382,0x308F3382,0x318F3382,0x328F3382,0x338F3382,0x348F3382,0x358F3382,0x368F3382,0x378F3382,0x388F3382,0x398F3382,0x30903382,0x31903382,0x32903382,0x33903382,0x34903382,0x35903382,0x36903382,0x37903382,0x38903382,0x39903382,0x30913382,0x31913382,0x32913382,0x33913382,0x34913382,0x35913382,0x36913382,0x37913382,0x38913382,0x39913382,0x30923382,0x31923382,0x32923382,0x33923382,0x34923382,0x35923382,0x36923382,0x37923382,0x38923382,0x39923382,0x30933382,0x31933382,0x32933382,0x33933382,0x34933382,0x35933382,0x36933382,0x37933382,0x38933382,0x39933382,0x30943382,0x31943382,0x32943382,0x33943382,0x34943382,0x35943382,0x36943382,0x37943382,0x38943382,0x39943382,0x30953382,0x31953382,0x32953382,0x33953382,0x34953382,0x35953382,0x36953382,0x37953382,0x38953382,0x39953382,0x30963382,0x31963382,0x32963382,0x33963382,0x34963382,0x35963382,0x36963382,0x37963382,0x38963382,0x39963382,0x30973382,0x31973382,0x32973382,0x33973382,0x34973382,0x35973382,0x36973382,0x37973382,0x38973382,0x39973382,0x30983382,0x31983382,0x32983382,0x33983382,0x34983382,0x35983382,0x36983382,0x37983382,0x38983382,0x39983382,0x30993382,0x31993382,0x32993382,0x33993382,0x34993382,0x35993382,0x36993382,0x37993382,0x38993382,0x39993382,0x309A3382,0x319A3382,0x329A3382,0x339A3382,0x349A3382,0x359A3382,0x369A3382,0x379A3382,0x389A3382,0x399A3382,0x309B3382,0x319B3382,0x329B3382,0x339B3382,0x349B3382,0x359B3382,0x369B3382,0x379B3382,0x389B3382,0x399B3382,0x309C3382,0x319C3382,0x329C3382,0x339C3382,0x349C3382,0x359C3382,0x369C3382,0x379C3382,0x389C3382,0x399C3382,0x309D3382,0x319D3382,0x329D3382,0x339D3382,0x349D3382,0x359D3382,0x369D3382,0x379D3382,0x389D3382,0x399D3382,0x309E3382,0x319E3382,0x329E3382,0x339E3382,0x349E3382,0x359E3382,0x369E3382,0x379E3382,0x389E3382,0x399E3382,0x309F3382,0x319F3382,0x329F3382,0x339F3382,0x349F3382,0x359F3382,0x369F3382,0x379F3382,0x389F3382,0x399F3382,0x30A03382,0x31A03382,0x32A03382,0x33A03382,0x34A03382,0x35A03382,0x36A03382,0x37A03382,0x38A03382,0x39A03382,0x30A13382,0x31A13382,0x32A13382,0x33A13382,0x34A13382,0x35A13382,0x36A13382,0x37A13382,0x38A13382,0x39A13382,0x30A23382,0x31A23382,0x32A23382,0x33A23382,0x34A23382,0x35A23382,0x36A23382,0x37A23382,0x38A23382,0x39A23382,0x30A33382,0x31A33382,0x32A33382,0x33A33382,0x34A33382,0x35A33382,0x36A33382,0x37A33382,0x38A33382,0x7BFE,0x7DFE,0x32C93382,0x33C93382,0x34C93382,0x35C93382,0x36C93382,0x37C93382,0x38C93382,0x39C93382,0x30CA3382,0x31CA3382,0x32CA3382,0x33CA3382,0x34CA3382,0x35CA3382,0x36CA3382,0x37CA3382,0x38CA3382,0x39CA3382,0x30CB3382,0x31CB3382,0x7CFE,0x32CB3382,0x33CB3382,0x34CB3382,0x35CB3382,0x36CB3382,0x37CB3382,0x38CB3382,0x39CB3382,0x30CC3382,0x31CC3382,0x32CC3382,0x33CC3382,0x34CC3382,0x35CC3382,0x36CC3382,0x37CC3382,0x38CC3382,0x39CC3382,0x30CD3382,0x31CD3382,0x32CD3382,0x33CD3382,0x34CD3382,0x35CD3382,0x36CD3382,0x37CD3382,0x38CD3382,0x39CD3382,0x30CE3382,0x31CE3382,0x32CE3382,0x33CE3382,0x34CE3382,0x35CE3382,0x36CE3382,0x37CE3382,0x38CE3382,0x39CE3382,0x30CF3382,0x31CF3382,0x32CF3382,0x33CF3382,0x34CF3382,0x35CF3382,0x36CF3382,0x37CF3382,0x38CF3382,0x39CF3382,0x30D03382,0x31D03382,0x32D03382,0x33D03382,0x34D03382,0x35D03382,0x36D03382,0x37D03382,0x38D03382,0x39D03382,0x30D13382,0x31D13382,0x32D13382,0x33D13382,0x34D13382,0x35D13382,0x36D13382,0x37D13382,0x38D13382,0x39D13382,0x30D23382,0x31D23382,0x32D23382,0x33D23382,0x34D23382,0x35D23382,0x36D23382,0x37D23382,0x38D23382,0x39D23382,0x30D33382,0x31D33382,0x32D33382,0x33D33382,0x34D33382,0x35D33382,0x36D33382,0x37D33382,0x38D33382,0x39D33382,0x30D43382,0x31D43382,0x32D43382,0x33D43382,0x34D43382,0x35D43382,0x36D43382,0x37D43382,0x38D43382,0x39D43382,0x30D53382,0x31D53382,0x32D53382,0x33D53382,0x34D53382,0x35D53382,0x36D53382,0x37D53382,0x38D53382,0x39D53382,0x30D63382,0x31D63382,0x32D63382,0x33D63382,0x34D63382,0x35D63382,0x36D63382,0x37D63382,0x38D63382,0x39D63382,0x30D73382,0x31D73382,0x32D73382,0x33D73382,0x34D73382,0x35D73382,0x36D73382,0x37D73382,0x38D73382,0x39D73382,0x30D83382,0x31D83382,0x32D83382,0x33D83382,0x34D83382,0x35D83382,0x36D83382,0x37D83382,0x38D83382,0x39D83382,0x30D93382,0x31D93382,0x32D93382,0x33D93382,0x34D93382,0x35D93382,0x36D93382,0x37D93382,0x38D93382,0x39D93382,0x30DA3382,0x31DA3382,0x32DA3382,0x33DA3382,0x34DA3382,0x35DA3382,0x36DA3382,0x37DA3382,0x38DA3382,0x39DA3382,0x30DB3382,0x31DB3382,0x32DB3382,0x33DB3382,0x34DB3382,0x35DB3382,0x36DB3382,0x37DB3382,0x38DB3382,0x39DB3382,0x30DC3382,0x31DC3382,0x32DC3382,0x33DC3382,0x34DC3382,0x35DC3382,0x36DC3382,0x37DC3382,0x38DC3382,0x39DC3382,0x30DD3382,0x31DD3382,0x32DD3382,0x33DD3382,0x34DD3382,0x35DD3382,0x36DD3382,0x37DD3382,0x38DD3382,0x39DD3382,0x30DE3382,0x31DE3382,0x32DE3382,0x33DE3382,0x34DE3382,0x80FE,0x35DE3382,0x36DE3382,0x37DE3382,0x38DE3382,0x39DE3382,0x81FE,0x30DF3382,0x31DF3382,0x32DF3382,0x33DF3382,0x34DF3382,0x35DF3382,0x36DF3382,0x37DF3382,0x38DF3382,0x39DF3382,0x30E03382,0x31E03382,0x32E03382,0x33E03382,0x34E03382,0x35E03382,0x36E03382,0x37E03382,0x38E03382,0x39E03382,0x30E13382,0x31E13382,0x32E13382,0x33E13382,0x34E13382,0x35E13382,0x36E13382,0x37E13382,0x38E13382,0x39E13382,0x30E23382,0x31E23382,0x32E23382,0x33E23382,0x34E23382,0x35E23382,0x36E23382,0x37E23382,0x38E23382,0x39E23382,0x30E33382,0x31E33382,0x32E33382,0x33E33382,0x34E33382,0x35E33382,0x36E33382,0x37E33382,0x38E33382,0x39E33382,0x30E43382,0x31E43382,0x32E43382,0x33E43382,0x34E43382,0x35E43382,0x36E43382,0x37E43382,0x38E43382,0x39E43382,0x30E53382,0x31E53382,0x32E53382,0x33E53382,0x34E53382,0x35E53382,0x36E53382,0x37E53382,0x38E53382,0x39E53382,0x30E63382,0x31E63382,0x32E63382,0x33E63382,0x34E63382,0x35E63382,0x36E63382,0x37E63382,0x38E63382,0x39E63382,0x30E73382,0x31E73382,0x82FE,0x32E73382,0x33E73382,0x34E73382,0x35E73382,0x36E73382,0x37E73382,0x38E73382,0x39E73382,0x30E83382,0x31E83382,0x32E83382,0x33E83382,0x34E83382,0x35E83382,0x36E83382,0x37E83382,0x83FE,0x85FE,0x39963482,0x30973482,0x31973482,0x32973482,0x33973482,0x34973482,0x35973482,0x36973482,0x37973482,0x38973482,0x39973482,0x30983482,0x31983482,0x32983482,0x33983482,0x34983482,0x35983482,0x36983482,0x37983482,0x38983482,0x39983482,0x30993482,0x31993482,0x32993482,0x33993482,0x34993482,0x35993482,0x36993482,0x37993482,0x38993482,0x39993482,0x309A3482,0x319A3482,0x329A3482,0x339A3482,0x349A3482,0x359A3482,0x369A3482,0x379A3482,0x389A3482,0x399A3482,0x309B3482,0x319B3482,0x329B3482,0x339B3482,0x349B3482,0x359B3482,0x369B3482,0x379B3482,0x389B3482,0x86FE,0x399B3482,0x309C3482,0x87FE,0x319C3482,0x329C3482,0x339C3482,0x349C3482,0x88FE,0x89FE,0x359C3482,0x8AFE,0x8BFE,0x369C3482,0x379C3482,0x389C3482,0x399C3482,0x309D3482,0x319D3482,0x329D3482,0x339D3482,0x349D3482,0x359D3482,0x369D3482,0x379D3482,0x389D3482,0x399D3482,0x309E3482,0x319E3482,0x329E3482,0x339E3482,0x349E3482,0x359E3482,0x8DFE,0x369E3482,0x379E3482,0x389E3482,0x8CFE,0x399E3482,0x309F3482,0x319F3482,0x329F3482,0x339F3482,0x349F3482,0x359F3482,0x369F3482,0x379F3482,0x389F3482,0x399F3482,0x30A03482,0x31A03482,0x32A03482,0x33A03482,0x34A03482,0x35A03482,0x36A03482,0x37A03482,0x38A03482,0x39A03482,0x30A13482,0x8FFE,0x8EFE,0x96FE,0x34E73482,0x35E73482,0x36E73482,0x37E73482,0x38E73482,0x39E73482,0x30E83482,0x31E83482,0x32E83482,0x33E83482,0x34E83482,0x35E83482,0x36E83482,0x37E83482,0x38E83482,0x39E83482,0x30E93482,0x31E93482,0x32E93482,0x33E93482,0x34E93482,0x35E93482,0x36E93482,0x37E93482,0x38E93482,0x39E93482,0x30EA3482,0x31EA3482,0x32EA3482,0x33EA3482,0x34EA3482,0x35EA3482,0x36EA3482,0x37EA3482,0x38EA3482,0x39EA3482,0x30EB3482,0x31EB3482,0x32EB3482,0x93FE,0x94FE,0x95FE,0x97FE,0x92FE,0x33EB3482,0x34EB3482,0x35EB3482,0x36EB3482,0x37EB3482,0x38EB3482,0x39EB3482,0x30EC3482,0x31EC3482,0x32EC3482,0x33EC3482,0x34EC3482,0x35EC3482,0x36EC3482,0x37EC3482,0x38EC3482,0x39EC3482,0x30ED3482,0x31ED3482,0x32ED3482,0x33ED3482,0x34ED3482,0x35ED3482,0x36ED3482,0x37ED3482,0x38ED3482,0x39ED3482,0x30EE3482,0x31EE3482,0x32EE3482,0x33EE3482,0x34EE3482,0x35EE3482,0x36EE3482,0x37EE3482,0x38EE3482,0x39EE3482,0x30EF3482,0x31EF3482,0x32EF3482,0x33EF3482,0x34EF3482,0x35EF3482,0x36EF3482,0x37EF3482,0x38EF3482,0x39EF3482,0x30F03482,0x31F03482,0x32F03482,0x33F03482,0x34F03482,0x35F03482,0x36F03482,0x37F03482,0x38F03482,0x39F03482,0x30F13482,0x31F13482,0x32F13482,0x33F13482,0x34F13482,0x35F13482,0x36F13482,0x37F13482,0x38F13482,0x39F13482,0x30F23482,0x31F23482,0x32F23482,0x33F23482,0x34F23482,0x35F23482,0x36F23482,0x37F23482,0x38F23482,0x39F23482,0x30F33482,0x31F33482,0x32F33482,0x33F33482,0x34F33482,0x35F33482,0x36F33482,0x37F33482,0x38F33482,0x39F33482,0x30F43482,0x31F43482,0x32F43482,0x33F43482,0x34F43482,0x35F43482,0x36F43482,0x37F43482,0x38F43482,0x39F43482,0x30F53482,0x31F53482,0x32F53482,0x33F53482,0x34F53482,0x35F53482,0x36F53482,0x37F53482,0x38F53482,0x39F53482,0x30F63482,0x31F63482,0x32F63482,0x33F63482,0x98FE,0x99FE,0x9AFE,0x9BFE,0x9CFE,0x9DFE,0x9EFE,0x34F63482,0x35F63482,0x36F63482,0x37F63482,0x38F63482,0x39F63482,0x30F73482,0x31F73482,0x32F73482,0x33F73482,0x34F73482,0x35F73482,0x36F73482,0x37F73482,0x38F73482,0x39F73482,0x30F83482,0x31F83482,0x32F83482,0x33F83482,0x34F83482,0x35F83482,0x36F83482,0x37F83482,0x38F83482,0x39F83482,0x30F93482,0x31F93482,0x32F93482,0x33F93482,0x34F93482,0x35F93482,0x36F93482,0x37F93482,0x38F93482,0x39F93482,0x30FA3482,0x31FA3482,0x32FA3482,0x33FA3482,0x34FA3482,0x35FA3482,0x36FA3482,0x37FA3482,0x38FA3482,0x39FA3482,0x30FB3482,0x31FB3482,0x32FB3482,0x33FB3482,0x34FB3482,0x35FB3482,0x36FB3482,0x37FB3482,0x38FB3482,0x39FB3482,0x30FC3482,0x31FC3482,0x32FC3482,0x33FC3482,0x34FC3482,0x35FC3482,0x36FC3482,0x37FC3482,0x38FC3482,0x39FC3482,0x30FD3482,0x31FD3482,0x32FD3482,0x33FD3482,0x34FD3482,0x35FD3482,0x36FD3482,0x37FD3482,0x38FD3482,0x39FD3482,0x30FE3482,0x31FE3482,0x32FE3482,0x33FE3482,0x34FE3482,0x35FE3482,0x36FE3482,0x37FE3482,0x38FE3482,0x39FE3482,0x30813582,0x31813582,0x32813582,0x33813582,0x34813582,0x35813582,0x36813582,0x37813582,0x38813582,0x39813582,0x30823582,0x31823582,0x32823582,0x33823582,0x34823582,0x35823582,0x36823582,0x37823582,0x38823582,0x39823582,0x30833582,0x31833582,0x32833582,0x33833582,0x34833582,0x35833582,0x36833582,0x37833582,0x38833582,0x39833582,0x30843582,0x31843582,0x32843582,0x33843582,0x34843582,0x35843582,0x36843582,0x37843582,0x38843582,0x39843582,0x30853582,0x31853582,0x32853582,0x33853582,0x34853582,0x35853582,0x36853582,0x37853582,0x38853582,0x39853582,0x30863582,0x31863582,0x32863582,0x33863582,0x34863582,0x35863582,0x36863582,0x37863582,0x38863582,0x39863582,0x30873582,0x31873582,0x9FFE,0x32873582,0x33873582,0x34873582,0x35873582,0x36873582,0x37873582,0x38873582,0x39873582,0x30883582,0x31883582,0x32883582,0x33883582,0x34883582,0x35883582,0x36883582,0x37883582,0x38883582,0x39883582,0x30893582,0x31893582,0x32893582,0x33893582,0x34893582,0x35893582,0x36893582,0x37893582,0x38893582,0x39893582,0x308A3582,0x318A3582,0x328A3582,0x338A3582,0x348A3582,0x358A3582,0x368A3582,0x378A3582,0x388A3582,0x398A3582,0x308B3582,0x318B3582,0x328B3582,0x338B3582,0x348B3582,0x358B3582,0x368B3582,0x378B3582,0x388B3582,0x398B3582,0x308C3582,0x318C3582,0x328C3582,0x338C3582,0x348C3582,0x358C3582,0x368C3582,0x378C3582,0x388C3582,0x398C3582,0x308D3582,0x318D3582,0x328D3582,0x338D3582,0x348D3582,0x358D3582,0x368D3582,0x378D3582,0x388D3582,0x398D3582,0x308E3582,0x318E3582,0x328E3582,0x338E3582,0x348E3582,0x358E3582,0x368E3582,0x378E3582,0x388E3582,0x398E3582,0x308F3582,0x318F3582,0x328F3582,0xBBD2,0xA1B6,0x4081,0xDFC6,0x4181,0x4281,0x4381,0xF2CD,0xC9D5,0xFDC8,0xCFC9,0xC2CF,0xA2D8,0xBBB2,0xEBD3,0x4481,0xA4D8,0xF3B3,0x4581,0xA8D7,0xD2C7,0xA7D8,0xC0CA,0x4681,0xF0C7,0xFBB1,0xB5D2,0xD4B4,0xABB6,0xBFCB,0xA9D8,0x4781,0x4881,0x4981,0xAAB6,0x4A81,0xBDC1,0xCFD1,0x4B81,0xA5C9,0xADD8,0x4C81,0xF6B8,0xBED1,0xDCE3,0xD0D6,0x4D81,0x4E81,0xE1B7,0x4F81,0xAEB4,0x5081,0xD9C1,0x5181,0xBCD8,0x5281,0xE8CD,0xA4B5,0xAACE,0xF7D6,0x5381,0xF6C0,0xD9BE,0xAFD8,0x5481,0x5581,0x5681,0xCBC4,0x5781,0xC3BE,0x5881,0xB1D8,0xB4C3,0xE5D2,0x5981,0xAED6,0xDACE,0xA7D5,0xF5BA,0xA6B7,0xD6C0,0x5A81,0xB9C6,0xD2C5,0xC7C7,0x5B81,0xD4B9,0x5C81,0xCBB3,0xD2D2,0x5D81,0x5E81,0xBFD8,0xC5BE,0xF2C6,0xB2D2,0xB0CF,0xE7CF,0x5F81,0x6081,0x6181,0x6281,0xE9CA,0x6381,0x6481,0xC0D8,0x6581,0x6681,0x6781,0x6881,0x6981,0x6A81,0xF2C2,0xD2C2,0x6B81,0xE9C8,0x6C81,0x6D81,0x6E81,0x6F81,0x7081,0x7181,0x7281,0x7381,0x7481,0x7581,0xACC7,0x7681,0x7781,0x7881,0x7981,0x7A81,0x7B81,0x7C81,0xCBC1,0x7D81,0xE8D3,0xF9D5,0x7E81,0xC2CA,0xFEB6,0xA1D8,0xDAD3,0xF7BF,0x8081,0xC6D4,0xA5BB,0xC1D8,0xE5CE,0xAEBE,0x8181,0x8281,0xA8D8,0x8381,0xC7D1,0xA9D0,0x8481,0x8581,0x8681,0xBDD8,0xEFD9,0xF6CD,0xBABF,0x8781,0xBBBD,0xA5BA,0xE0D2,0xFAB2,0xE0BA,0xB6C4,0x8881,0xEDCF,0xA9BE,0xA4CD,0xC1C1,0x8981,0x8A81,0x8B81,0xD7C7,0xF1D9,0x8C81,0xF4D9,0x8D81,0x8E81,0x8F81,0x9081,0xCBC8,0xE9D8,0x9181,0x9281,0x9381,0xDAD2,0xB2CA,0xCAC8,0xECD8,0xEAD8,0xC6D8,0xF6BD,0xCDC6,0xF0B3,0x9481,0xEBD8,0xF1BD,0xE9BD,0x9581,0xD4C8,0xD3B4,0x9681,0x9781,0xD8C2,0x9881,0xD6B2,0xD0D7,0xCBCA,0xFBCB,0xCCD5,0xB6B8,0xC9CF,0x9981,0x9A81,0x9B81,0xDAD9,0xF0D8,0xAAC7,0x9C81,0xEED8,0x9D81,0xFAB4,0xEEC1,0xD4D2,0x9E81,0x9F81,0xEDD8,0xA081,0xC7D2,0xEFD8,0xC7C3,0xA181,0xA281,0xA381,0xF6D1,0xA481,0xD9D6,0xF2D8,0xA581,0xF5D8,0xFEBC,0xDBBC,0xA681,0xA781,0xA881,0xCEC8,0xA981,0xDDB7,0xAA81,0xC2B7,0xAB81,0xF3C6,0xAC81,0xAD81,0xAE81,0xAF81,0xB081,0xB181,0xB281,0xF8D8,0xC1D2,0xB381,0xB481,0xE9CE,0xBFBC,0xFCB7,0xA5B7,0xDDD0,0xB581,0xB681,0xB781,0xB881,0xB981,0xDAD6,0xC5D3,0xEFBB,0xE1BB,0xF1D8,0xBA81,0xBB81,0xA1C9,0xB0CE,0xABB4,0xBC81,0xF3D8,0xBD81,0xCBC9,0xF6D8,0xD7C2,0xF7D8,0xBE81,0xBF81,0xB1CE,0xF9D8,0xC081,0xC181,0xC281,0xAEB2,0xC0B9,0xC381,0xA3D9,0xC481,0xE9B0,0xC581,0xE6C1,0xC681,0xECC9,0xC781,0xC5CB,0xC881,0xC6CB,0xA4D9,0xC981,0xCA81,0xCB81,0xCC81,0xCD81,0xE8B5,0xCE81,0xCF81,0xABB5,0xD081,0xD181,0xD281,0xD381,0xD481,0xD581,0xBBCE,0xCDB5,0xA1D7,0xF4D7,0xD3D3,0xD681,0xE5CC,0xD781,0xCEBA,0xD881,0xA2D9,0xDCD9,0xE0D3,0xFDD8,0xF0B7,0xF7D7,0xFED8,0xFAD8,0xA1D9,0xE3C4,0xD981,0xDA81,0xB6D3,0xF4D8,0xDDD9,0xDB81,0xFBD8,0xDC81,0xE5C5,0xDD81,0xDE81,0xD0C0,0xDF81,0xE081,0xF0D1,0xDBB0,0xE181,0xE281,0xD1BC,0xA6D9,0xE381,0xA5D9,0xE481,0xE581,0xE681,0xE781,0xACD9,0xAED9,0xE881,0xABD9,0xB9CA,0xE981,0xEA81,0xEB81,0xA9D9,0xB6D6,0xEC81,0xED81,0xEE81,0xDEB3,0xA8D9,0xEF81,0xFDC0,0xF081,0xCCCA,0xF181,0xAAD9,0xF281,0xA7D9,0xF381,0xF481,0xB0D9,0xF581,0xF681,0xB1B6,0xF781,0xF881,0xF981,0xA9B9,0xFA81,0xC0D2,0xFB81,0xFC81,0xC0CF,0xFD81,0xFE81,0xC2C2,0x4082,0xC4BD,0xECD5,0xE0B2,0xC8C7,0xEBBF,0xADD9,0x4182,0xAFD9,0x4282,0xEACE,0xEEBA,0x4382,0x4482,0x4582,0x4682,0x4782,0xD6C7,0x4882,0x4982,0x4A82,0x4B82,0x4C82,0x4D82,0x4E82,0x4F82,0x5082,0xE3B1,0x5182,0x5282,0x5382,0xD9B4,0xEDB6,0xB4D9,0x5482,0x5582,0x5682,0x5782,0xA1BF,0x5882,0x5982,0x5A82,0xDED9,0xCEC7,0xFEC0,0xB8D9,0x5B82,0x5C82,0x5D82,0x5E82,0x5F82,0xD7CB,0xFDB7,0x6082,0xB5D9,0x6182,0xB7D9,0xA3B1,0xE1D3,0xB9D9,0x6282,0xC5D0,0x6382,0xB6D9,0x6482,0x6582,0xB1D9,0x6682,0xB2D9,0xA9C1,0xB3D9,0x6782,0x6882,0xF3BC,0xDED0,0xA9B8,0x6982,0xE3BE,0x6A82,0xBDD9,0x6B82,0x6C82,0x6D82,0x6E82,0xBAD9,0x6F82,0xB3B0,0x7082,0x7182,0x7282,0xC2D9,0x7382,0x7482,0x7582,0x7682,0x7782,0x7882,0x7982,0x7A82,0x7B82,0x7C82,0x7D82,0x7E82,0x8082,0xC4D9,0xB6B1,0x8182,0xBFD9,0x8282,0x8382,0xB9B5,0x8482,0xF3BE,0x8582,0x8682,0x8782,0xC8CC,0xF2BA,0xD0D2,0x8882,0xC3D9,0x8982,0x8A82,0xE8BD,0x8B82,0xABB3,0x8C82,0x8D82,0x8E82,0xC5D9,0xEBBE,0x8F82,0xC6D9,0xBBD9,0xDFC4,0x9082,0xBED9,0xC1D9,0xC0D9,0x9182,0x9282,0x9382,0x9482,0x9582,0x9682,0x9782,0x9882,0x9982,0x9A82,0x9B82,0xAED5,0x9C82,0xB5D6,0x9D82,0xE3C7,0x9E82,0x9F82,0xA082,0xA182,0xC8D9,0xA282,0xA382,0xA482,0xD9BC,0xCAD9,0xA582,0xA682,0xA782,0xBCD9,0xA882,0xCBD9,0xABC6,0xA982,0xAA82,0xAB82,0xAC82,0xAD82,0xC9D9,0xAE82,0xAF82,0xB082,0xB182,0xF6D7,0xB282,0xA3CD,0xB382,0xB482,0xB582,0xB682,0xB782,0xB882,0xB982,0xBA82,0xA1BD,0xBB82,0xBC82,0xBD82,0xBE82,0xBF82,0xC082,0xCCD9,0xC182,0xC282,0xC382,0xC482,0xC582,0xC682,0xC782,0xC882,0xC982,0xBCC5,0xB5CD,0xCA82,0xCB82,0xCC82,0xCDD9,0xCD82,0xCE82,0xC7D9,0xA5B3,0xFEBF,0xCF82,0xD082,0xD182,0xD282,0xB5B8,0xD382,0xD482,0xFCC0,0xD582,0xD682,0xD782,0xD882,0xF8B0,0xD982,0xDA82,0xDB82,0xDC82,0xDD82,0xDE82,0xDF82,0xE082,0xE182,0xE282,0xE382,0xE482,0xE582,0xE682,0xE782,0xE882,0xE982,0xEA82,0xEB82,0xEC82,0xED82,0xF6B4,0xEE82,0xCED9,0xEF82,0xCFD9,0xA2B4,0xD0D9,0xF082,0xF182,0xDFB4,0xF282,0xF382,0xF482,0xF582,0xF682,0xC1B0,0xF782,0xF882,0xF982,0xFA82,0xFB82,0xFC82,0xFD82,0xD1D9,0xB5C9,0xFE82,0x4083,0x4183,0x4283,0x4383,0x4483,0x4583,0x4683,0x4783,0x4883,0x4983,0x4A83,0x4B83,0x4C83,0x4D83,0x4E83,0x4F83,0x5083,0x5183,0xF1CF,0x5283,0x5383,0x5483,0x5583,0x5683,0x5783,0xD2D9,0x5883,0x5983,0x5A83,0xC5C1,0x5B83,0x5C83,0x5D83,0x5E83,0x5F83,0x6083,0x6183,0x6283,0x6383,0x6483,0x6583,0xD6D9,0xAEC9,0x6683,0x6783,0x6883,0x6983,0xD5D9,0xD4D9,0xD7D9,0x6A83,0x6B83,0x6C83,0x6D83,0xDBCB,0x6E83,0xA9BD,0x6F83,0x7083,0x7183,0x7283,0x7383,0xA7C6,0x7483,0x7583,0x7683,0x7783,0x7883,0x7983,0x7A83,0x7B83,0x7C83,0x7D83,0xD3D9,0xD8D9,0x7E83,0x8083,0x8183,0xD9D9,0x8283,0x8383,0x8483,0x8583,0x8683,0x8783,0xE5C8,0x8883,0x8983,0x8A83,0x8B83,0x8C83,0x8D83,0x8E83,0x8F83,0x9083,0x9183,0x9283,0x9383,0x9483,0x9583,0xDCC0,0x9683,0x9783,0x9883,0x9983,0x9A83,0x9B83,0x9C83,0x9D83,0x9E83,0x9F83,0xA083,0xA183,0xA283,0xA383,0xA483,0xA583,0xA683,0xA783,0xA883,0xA983,0xAA83,0xAB83,0xAC83,0xAD83,0xAE83,0xAF83,0xB083,0xB183,0xB283,0xF9B6,0xA3D8,0xCAD4,0xB383,0xAAD4,0xD6D0,0xE4B3,0xD7D5,0xB483,0xC8CF,0xE2B9,0xB583,0xCBBF,0xB683,0xE2C3,0xB783,0xB883,0xB983,0xD2B6,0xBA83,0xBB83,0xC3CD,0xEED9,0xF0D9,0xBC83,0xBD83,0xBE83,0xB3B5,0xBF83,0xB5B6,0xC083,0xC183,0xC283,0xC383,0xC483,0xA4BE,0xC583,0xC683,0xEBC8,0xC783,0xC883,0xABC8,0xC983,0xCA83,0xCBB0,0xABB9,0xF9C1,0xE2D9,0xCB83,0xBCC0,0xB2B9,0xCC83,0xD8B9,0xCBD0,0xF8B1,0xE4C6,0xDFBE,0xE4B5,0xC8D7,0xCD83,0xF8D1,0xE6BC,0xDECA,0xCE83,0xCF83,0xBDBC,0xE6D9,0xE7D8,0xD083,0xD183,0xDAC4,0xD283,0xD383,0xD4B8,0xBDC8,0xD483,0xD583,0xE1B2,0xD9D4,0xD683,0xD783,0xD883,0xD983,0xB0C3,0xDA83,0xDB83,0xE1C3,0xA2DA,0xDFC8,0xDC83,0xB4D0,0xDD83,0xFCBE,0xA9C5,0xDE83,0xDF83,0xE083,0xDAB9,0xE183,0xA3DA,0xE283,0xA9D4,0xA4DA,0xE383,0xE483,0xE583,0xE683,0xE783,0xFBD9,0xACB6,0xE883,0xE983,0xEBB7,0xF9B1,0xFCD9,0xE5B3,0xF6BE,0xEA83,0xF6BF,0xB1D2,0xE4C0,0xEB83,0xEC83,0xED83,0xB3B6,0xFED9,0xFDD9,0xEE83,0xEF83,0xBBBE,0xF083,0xF183,0xF283,0xE0C6,0xF383,0xBCD7,0xA1DA,0xF483,0xB9C1,0xF583,0xF2B5,0xE8C1,0xF683,0xF783,0xF5BC,0xF883,0xD5B4,0xF983,0xFA83,0xFB83,0xFC83,0xFD83,0xFE83,0x4084,0x4184,0x4284,0xDDC1,0x4384,0xFDC4,0x4484,0x4584,0xB8BC,0xB2B7,0x4684,0x4784,0xEFB7,0x4884,0x4984,0x4A84,0x4B84,0x4C84,0x4D84,0xECD9,0x4E84,0xBEC6,0x4F84,0xADBF,0xCBBB,0x5084,0x5184,0xCAB5,0x5284,0xC9DB,0xD7D0,0x5384,0xB9CD,0xBCB0,0xF6B3,0xF7BB,0xCADB,0xAFBA,0x5484,0xE4D4,0xB6B5,0xF3B5,0xD6D8,0xD0C8,0x5584,0x5684,0xD6B7,0xD0C7,0xD7D8,0x5784,0xAFBF,0x5884,0x5984,0xBBDB,0xD8D8,0x5A84,0x5B84,0xCCD0,0xAEBB,0x5C84,0x5D84,0x5E84,0xBEEB,0xD0C1,0xF5C1,0xF2D4,0xD5B8,0xB4B4,0x5F84,0xF5B3,0x6084,0x6184,0xBEC9,0x6284,0x6384,0x6484,0xD0C5,0x6584,0x6684,0x6784,0xD9C5,0xFBC0,0x6884,0xF0B1,0x6984,0xD9D8,0xCEB9,0x6A84,0xBDB5,0x6B84,0x6C84,0xDAD8,0x6D84,0x6E84,0xC6D6,0xA2CB,0xAFC8,0xB2C9,0xCCB4,0xCCBF,0x6F84,0xF4B9,0x7084,0xDBD8,0xDCD8,0xE7B6,0xC1BC,0xEACC,0x7184,0x7284,0x7384,0x7484,0x7584,0x7684,0xF7CF,0x7784,0xDDD8,0xB0C7,0x7884,0x7984,0xD0B9,0xA3BD,0x7A84,0x7B84,0xDECC,0x7C84,0xCAC6,0x7D84,0x7E84,0x8084,0x8184,0x8284,0xE0D8,0x8384,0xDED8,0x8484,0x8584,0xDFD8,0x8684,0x8784,0x8884,0xFEB0,0x8984,0xE7BE,0x8A84,0xA3CA,0xF4BC,0x8B84,0x8C84,0x8D84,0x8E84,0xB1B8,0x8F84,0x9084,0xEEB8,0x9184,0x9284,0x9384,0x9484,0x9584,0x9684,0x9784,0x9884,0x9984,0x9A84,0xE2D8,0x9B84,0xCBBD,0x9C84,0xE4D8,0xE3D8,0x9D84,0x9E84,0x9F84,0xA084,0xA184,0xFCC5,0xA284,0xA384,0xA484,0xA584,0xA684,0xA784,0xA884,0xE5D8,0xA984,0xAA84,0xE6D8,0xAB84,0xAC84,0xAD84,0xAE84,0xAF84,0xB084,0xB184,0xA6C1,0xB284,0xB0C8,0xECB0,0xA6B9,0xD3BC,0xF1CE,0xBDDB,0xD3C1,0xB384,0xB484,0xB584,0xB684,0xAFB6,0xFAD6,0xACC5,0xD9BD,0xBEDB,0xBFDB,0xB784,0xB884,0xB984,0xF8C0,0xA2BE,0xCDC0,0xBA84,0xBB84,0xBC84,0xBD84,0xBE84,0xBF84,0xC084,0xC184,0xC284,0xC384,0xC0DB,0xC6CA,0xC484,0xC584,0xC684,0xAAB2,0xC784,0xC884,0xC984,0xC2D3,0xCA84,0xE3C3,0xCB84,0xABD1,0xCC84,0xCD84,0xCE84,0xCF84,0xC2DB,0xD084,0xD5C0,0xD184,0xD284,0xD384,0xC3DB,0xD484,0xB1BF,0xD584,0xD684,0xD784,0xD884,0xD984,0xDA84,0xBCC4,0xDB84,0xDC84,0xDD84,0xDE84,0xDAC7,0xDF84,0xE084,0xE184,0xE284,0xE384,0xE484,0xE584,0xE684,0xE784,0xE884,0xE984,0xC4DB,0xEA84,0xEB84,0xEC84,0xED84,0xEE84,0xEF84,0xF084,0xF184,0xE8D9,0xD7C9,0xF284,0xF384,0xF484,0xB4B9,0xF0CE,0xC8D4,0xF584,0xF684,0xF784,0xF884,0xFCB0,0xD2B4,0xF984,0xD9D0,0xFA84,0xFB84,0xFC84,0xFD84,0xE9D9,0xFE84,0xCBDE,0xEBD9,0x4085,0x4185,0x4285,0x4385,0xB0D8,0xAFBB,0xB1B1,0x4485,0xD7B3,0xCED8,0x4585,0x4685,0xD1D4,0x4785,0x4885,0xB3BD,0xEFBF,0x4985,0xBBCF,0x4A85,0x4B85,0xD0D8,0x4C85,0x4D85,0x4E85,0xCBB7,0x4F85,0x5085,0x5185,0xD1D8,0x5285,0x5385,0x5485,0x5585,0x5685,0x5785,0x5885,0x5985,0x5A85,0x5B85,0xA5C6,0xF8C7,0xBDD2,0x5C85,0x5D85,0xD2D8,0xE4C4,0x5E85,0xAECA,0x5F85,0xA7C7,0x6085,0xA6D8,0x6185,0xFDC9,0xE7CE,0xDCBB,0xEBB0,0x6285,0x6385,0x6485,0xAABB,0xADD0,0x6585,0xB0B1,0xE4D7,0xBFD7,0x6685,0xA5B5,0xF4C2,0xCFC4,0x6785,0x6885,0xA9B2,0x6985,0xB7B2,0x6A85,0xE5B1,0xB2DF,0xBCD5,0xA8BF,0xACC2,0xD5D8,0xB1C2,0x6B85,0xD4D8,0xD4CE,0x6C85,0xE0DA,0x6D85,0xC0CE,0x6E85,0x6F85,0xB4D8,0xAEC3,0xA1D3,0xA3CE,0x7085,0xB4BC,0xB4C8,0xD1C2,0x7185,0xEDBE,0xB6D0,0x7285,0xE1DA,0x7385,0x7485,0x7585,0x7685,0xE4C7,0x7785,0x7885,0xA7B3,0x7985,0xF2B6,0xFCCC,0xFAC0,0x7A85,0x7B85,0xF7C0,0x7C85,0xB9D1,0xE1D1,0xC7D8,0x7D85,0x7E85,0x8085,0x8185,0x8285,0x8385,0x8485,0xDEB2,0x8585,0x8685,0xE5C0,0x8785,0xF1BA,0x8885,0x8985,0xC8D8,0x8A85,0xADD4,0x8B85,0x8C85,0xE1CF,0xC9D8,0x8D85,0xCAD8,0xC3CF,0x8E85,0xF8B3,0xC7BE,0x8F85,0x9085,0x9185,0x9285,0xCBD8,0x9385,0x9485,0x9585,0x9685,0x9785,0x9885,0x9985,0xCCDB,0x9A85,0x9B85,0x9C85,0x9D85,0xA5C8,0x9E85,0x9F85,0xA085,0xD8CF,0xA185,0xFEC8,0xCEB2,0xA285,0xA385,0xA485,0xA585,0xA685,0xD6D3,0xE6B2,0xB0BC,0xD1D3,0xABCB,0xB4B7,0xA785,0xA885,0xA985,0xA2B7,0xAA85,0xAB85,0xE5CA,0xAC85,0xA1C8,0xDCCA,0xE4B1,0xF0D0,0xAD85,0xD1C5,0xAE85,0xAF85,0xB085,0xC5DB,0xFEB5,0xB185,0xB285,0xDABF,0xC5B9,0xE4BE,0xEDC1,0xB385,0xB6DF,0xB5DF,0xBBD6,0xD0BD,0xD9D5,0xC8B0,0xA3B6,0xC9BF,0xA8CC,0xB3DF,0xB7CA,0xD2D3,0xB485,0xCFD8,0xB6D2,0xC5BA,0xBECB,0xBECC,0xB585,0xB7DF,0xF0B5,0xB4DF,0xB685,0xB785,0xB885,0xF5D3,0xB985,0xD4B3,0xF7B8,0xBA85,0xBADF,0xBB85,0xCFBA,0xAABC,0xF5B5,0xBC85,0xACCD,0xFBC3,0xF3BA,0xF4C0,0xC2CD,0xF2CF,0xB8DF,0xC5CF,0xBD85,0xC0C2,0xB9DF,0xF0C2,0xBE85,0xBF85,0xC085,0xFDBE,0xC185,0xDFC1,0xCCCD,0xF7D2,0xCDB7,0xC1DF,0xC285,0xC4DF,0xC385,0xC485,0xF1B7,0xC9B0,0xD6B6,0xD4B7,0xC585,0xACBA,0xFDCC,0xD4BF,0xB1CB,0xF4C6,0xC685,0xA8D6,0xC5DF,0xC785,0xE2CE,0xB3B3,0xC885,0xC985,0xFCCE,0xB5B4,0xCA85,0xC7CE,0xF0BA,0xCB85,0xE1CE,0xCC85,0xBDD1,0xCD85,0xCE85,0xC0DF,0xCF85,0xD085,0xF4B4,0xD185,0xCAB3,0xD285,0xE6B8,0xBBDF,0xD385,0xD485,0xD585,0xD685,0xC5C4,0xD785,0xBCDF,0xBDDF,0xBEDF,0xBBC5,0xBFDF,0xC2DF,0xB1D4,0xC3DF,0xD885,0xBAC7,0xD8CE,0xD985,0xDA85,0xDB85,0xDC85,0xDD85,0xD8C4,0xDE85,0xCADF,0xDF85,0xCFDF,0xE085,0xDCD6,0xE185,0xE285,0xE385,0xE485,0xE585,0xE685,0xE785,0xE885,0xC9DF,0xDADF,0xB6CE,0xE985,0xC7BA,0xCEDF,0xC8DF,0xDEC5,0xEA85,0xEB85,0xEBC9,0xF4BA,0xFCC3,0xEC85,0xED85,0xD7BE,0xEE85,0xC6DF,0xEF85,0xCDDF,0xF085,0xD8C5,0xF185,0xF285,0xF385,0xF485,0xA6D5,0xCDBA,0xF585,0xCCBE,0xBDD3,0xC0B8,0xF685,0xE4D6,0xF785,0xC7DF,0xBEB9,0xA7BF,0xF885,0xF985,0xFCC1,0xCBDF,0xCCDF,0xFA85,0xD0DF,0xFB85,0xFC85,0xFD85,0xFE85,0x4086,0xDBDF,0xE5DF,0x4186,0xD7DF,0xD6DF,0xC9D7,0xE3DF,0xE4DF,0xEBE5,0xA7D2,0xD2DF,0x4286,0xA9BF,0x4386,0xDBD4,0x4486,0xC8BF,0xD4DF,0x4586,0x4686,0x4786,0xCCCF,0x4886,0x4986,0xDDDF,0x4A86,0xCAD1,0x4B86,0xDEDF,0xA7B0,0xB7C6,0xD3DF,0x4C86,0xE5BA,0x4D86,0xDFB6,0xDBCD,0xFEB9,0xD5D4,0x4E86,0x4F86,0xDFDF,0xECCF,0xA5B0,0xE7DF,0xD1DF,0xC6D1,0xD5DF,0xD8DF,0xD9DF,0xDCDF,0x5086,0xA9BB,0x5186,0xE0DF,0xE1DF,0x5286,0xE2DF,0xE6DF,0xE8DF,0xB4D3,0x5386,0x5486,0x5586,0x5686,0x5786,0xE7B8,0xB6C5,0xEADF,0xDAC9,0xA8C1,0xC4C4,0x5886,0x5986,0xDEBF,0xF8CF,0x5A86,0x5B86,0x5C86,0xDCD5,0xEEDF,0x5D86,0x5E86,0x5F86,0x6086,0x6186,0x6286,0xB8B2,0x6386,0xDFBA,0xECDF,0x6486,0xC1DB,0x6586,0xE4D1,0x6686,0x6786,0x6886,0x6986,0xF4CB,0xBDB4,0x6A86,0xA6B0,0x6B86,0x6C86,0x6D86,0x6E86,0x6F86,0xF1DF,0xC6CC,0xF2DF,0x7086,0x7186,0xEDDF,0x7286,0x7386,0x7486,0x7586,0x7686,0x7786,0xE9DF,0x7886,0x7986,0x7A86,0x7B86,0xEBDF,0x7C86,0xEFDF,0xF0DF,0xBDBB,0x7D86,0x7E86,0xF3DF,0x8086,0x8186,0xF4DF,0x8286,0xA3BB,0x8386,0xDBCA,0xA8CE,0xA7E0,0xAAB3,0x8486,0xA6E0,0x8586,0x8686,0x8786,0xA1E0,0x8886,0x8986,0x8A86,0x8B86,0xFEDF,0x8C86,0xD9CD,0xFCDF,0x8D86,0xFADF,0x8E86,0xD0BF,0xC4D7,0x8F86,0xCCC9,0x9086,0x9186,0xF8DF,0xA1B0,0x9286,0x9386,0x9486,0x9586,0x9686,0xFDDF,0x9786,0x9886,0x9986,0x9A86,0xFBDF,0xA2E0,0x9B86,0x9C86,0x9D86,0x9E86,0x9F86,0xA8E0,0xA086,0xA186,0xA286,0xA386,0xC8B7,0xA486,0xA586,0xA1C6,0xB6C9,0xB2C0,0xF5DF,0xA686,0xA786,0xBEC5,0xA886,0xC4D8,0xF9DF,0xF6C4,0xA986,0xAA86,0xAB86,0xAC86,0xAD86,0xAE86,0xA3E0,0xA4E0,0xA5E0,0xA5D0,0xAF86,0xB086,0xB4E0,0xE4CC,0xB186,0xB1E0,0xB286,0xA6BF,0xAFE0,0xB9CE,0xABE0,0xC6C9,0xB386,0xB486,0xAEC0,0xAEE0,0xEDBA,0xB0BA,0xA9E0,0xB586,0xB686,0xB786,0xF6DF,0xB886,0xB3E0,0xB986,0xBA86,0xB8E0,0xBB86,0xBC86,0xBD86,0xADB4,0xB9E0,0xBE86,0xBF86,0xB2CF,0xC8BA,0xC086,0xB0E0,0xC186,0xC286,0xC386,0xC486,0xC586,0xC686,0xC786,0xFAD0,0xC886,0xC986,0xCA86,0xCB86,0xCC86,0xCD86,0xCE86,0xCF86,0xD086,0xACE0,0xD186,0xFBD4,0xD286,0xF7DF,0xD386,0xE7C5,0xD486,0xADE0,0xD586,0xF7D3,0xD686,0xB6E0,0xB7E0,0xD786,0xD886,0xD986,0xDA86,0xDB86,0xC4E0,0xE1D0,0xDC86,0xDD86,0xDE86,0xBCE0,0xDF86,0xE086,0xC9E0,0xCAE0,0xE186,0xE286,0xE386,0xBEE0,0xAAE0,0xA4C9,0xC1E0,0xE486,0xB2E0,0xE586,0xE686,0xE786,0xE886,0xE986,0xC8CA,0xC3E0,0xEA86,0xB5E0,0xEB86,0xCBCE,0xEC86,0xC3CB,0xCDE0,0xC6E0,0xC2E0,0xED86,0xCBE0,0xEE86,0xBAE0,0xBFE0,0xC0E0,0xEF86,0xF086,0xC5E0,0xF186,0xF286,0xC7E0,0xC8E0,0xF386,0xCCE0,0xF486,0xBBE0,0xF586,0xF686,0xF786,0xF886,0xF986,0xD4CB,0xD5E0,0xFA86,0xD6E0,0xD2E0,0xFB86,0xFC86,0xFD86,0xFE86,0x4087,0x4187,0xD0E0,0xCEBC,0x4287,0x4387,0xD1E0,0x4487,0xC2B8,0xC5D8,0x4587,0x4687,0x4787,0x4887,0x4987,0x4A87,0x4B87,0x4C87,0xEAD0,0x4D87,0x4E87,0xEFC2,0x4F87,0x5087,0xCFE0,0xBDE0,0x5187,0x5287,0x5387,0xD4E0,0xD3E0,0x5487,0x5587,0xD7E0,0x5687,0x5787,0x5887,0x5987,0xDCE0,0xD8E0,0x5A87,0x5B87,0x5C87,0xF6D6,0xB0B3,0x5D87,0xECD7,0x5E87,0xBBCB,0x5F87,0x6087,0xDAE0,0x6187,0xFBCE,0x6287,0x6387,0x6487,0xD9BA,0x6587,0x6687,0x6787,0x6887,0x6987,0x6A87,0x6B87,0x6C87,0x6D87,0x6E87,0x6F87,0x7087,0xE1E0,0xDDE0,0xADD2,0x7187,0x7287,0x7387,0x7487,0x7587,0xE2E0,0x7687,0x7787,0xDBE0,0xD9E0,0xDFE0,0x7887,0x7987,0xE0E0,0x7A87,0x7B87,0x7C87,0x7D87,0x7E87,0xDEE0,0x8087,0xE4E0,0x8187,0x8287,0x8387,0xF7C6,0xACD8,0xEBD4,0xE6E0,0xC9CA,0x8487,0x8587,0x8687,0x8787,0xE5E0,0x8887,0x8987,0x8A87,0x8B87,0xC1B8,0x8C87,0x8D87,0x8E87,0x8F87,0xE7E0,0xE8E0,0x9087,0x9187,0x9287,0x9387,0x9487,0x9587,0x9687,0x9787,0xE9E0,0xE3E0,0x9887,0x9987,0x9A87,0x9B87,0x9C87,0x9D87,0x9E87,0xBFBA,0xE7CC,0x9F87,0xA087,0xA187,0xEAE0,0xA287,0xA387,0xA487,0xA587,0xA687,0xA787,0xA887,0xA987,0xAA87,0xAB87,0xAC87,0xAD87,0xAE87,0xAF87,0xB087,0xF9CF,0xB187,0xB287,0xB387,0xB487,0xB587,0xB687,0xB787,0xB887,0xB987,0xBA87,0xBB87,0xEBE0,0xBC87,0xBD87,0xBE87,0xBF87,0xC087,0xC187,0xC287,0xC2C8,0xC387,0xC487,0xC587,0xC687,0xC0BD,0xC787,0xC887,0xC987,0xCA87,0xCB87,0xCC87,0xCD87,0xCE87,0xCF87,0xD087,0xD187,0xD287,0xD387,0xD2C4,0xD487,0xD587,0xD687,0xD787,0xD887,0xD987,0xDA87,0xDB87,0xDC87,0xECE0,0xDD87,0xDE87,0xEDE0,0xDF87,0xE087,0xF4C7,0xC4CB,0xE187,0xEEE0,0xD8BB,0xB6D8,0xF2D2,0xEFE0,0xC5CD,0xE287,0xDAB6,0xE387,0xE487,0xE587,0xE687,0xE787,0xE887,0xF1E0,0xE987,0xB0D4,0xEA87,0xEB87,0xA7C0,0xD1B4,0xEC87,0xED87,0xA7CE,0xF0E0,0xEE87,0xEF87,0xF087,0xF2E0,0xCCB9,0xF187,0xF287,0xFAB9,0xBCCD,0xF3E0,0xF387,0xF487,0xF587,0xD4C6,0xF4E0,0xF687,0xB2D4,0xF787,0xA6C8,0xF6E0,0xF5E0,0xF887,0xF987,0xFA87,0xFB87,0xFC87,0xFD87,0xFE87,0x4088,0x4188,0x4288,0x4388,0x4488,0x4588,0x4688,0x4788,0x4888,0x4988,0xF7E0,0x4A88,0x4B88,0xC1CD,0x4C88,0x4D88,0x4E88,0xA5CA,0x4F88,0x5088,0x5188,0x5288,0xDAD4,0xD7DB,0xD9DB,0x5388,0xD8DB,0xE7B9,0xDCDB,0xDDDB,0xD8B5,0x5488,0x5588,0xDADB,0x5688,0x5788,0x5888,0x5988,0x5A88,0xDBDB,0xA1B3,0xDFDB,0x5B88,0x5C88,0xF8BB,0x5D88,0xB7D6,0x5E88,0xE0DB,0x5F88,0x6088,0x6188,0x6288,0xF9BE,0x6388,0x6488,0xBBB7,0x6588,0xD0DB,0xAECC,0xB2BF,0xB5BB,0xF8D7,0xD3BF,0x6688,0x6788,0x6888,0x6988,0x6A88,0xE9BF,0x6B88,0x6C88,0xE1BC,0xB3CC,0xDEDB,0xD3B0,0xEBCE,0xD8B7,0xB9D7,0xC2C6,0x6D88,0x6E88,0xA4C0,0x6F88,0xB9CC,0x7088,0xE7DB,0xE1DB,0xBAC6,0xE3DB,0x7188,0xE8DB,0x7288,0xF7C5,0x7388,0x7488,0x7588,0xEADB,0x7688,0x7788,0xE9DB,0xC0BF,0x7888,0x7988,0x7A88,0xE6DB,0xE5DB,0x7B88,0x7C88,0x7D88,0x7E88,0x8088,0xB9B4,0xACC0,0xA2C2,0xE2DB,0xE4DB,0x8188,0x8288,0x8388,0x8488,0xCDD0,0xEDDB,0x8588,0x8688,0x8788,0x8888,0x8988,0xDDC0,0xF2DB,0x8A88,0x8B88,0x8C88,0x8D88,0x8E88,0x8F88,0x9088,0xE2B6,0x9188,0x9288,0x9388,0x9488,0xF3DB,0xD2DB,0xB8B9,0xABD4,0xECDB,0x9588,0xD1BF,0xF0DB,0x9688,0xD1DB,0x9788,0xE6B5,0x9888,0xEBDB,0xE5BF,0x9988,0x9A88,0x9B88,0xEEDB,0x9C88,0xF1DB,0x9D88,0x9E88,0x9F88,0xF9DB,0xA088,0xA188,0xA288,0xA388,0xA488,0xA588,0xA688,0xA788,0xA888,0xA1B9,0xA3B0,0xA988,0xAA88,0xAB88,0xAC88,0xAD88,0xAE88,0xAF88,0xF1C2,0xB088,0xB188,0xC7B3,0xEFDB,0xB288,0xB388,0xF8DB,0xB488,0xD2C6,0xF4DB,0xB588,0xB688,0xF5DB,0xF7DB,0xF6DB,0xB788,0xB888,0xFEDB,0xB988,0xF2D3,0xBAB2,0xBA88,0xBB88,0xBC88,0xFDDB,0xBD88,0xBE88,0xBF88,0xC088,0xC188,0xC288,0xC388,0xC488,0xA4DC,0xC588,0xFBDB,0xC688,0xC788,0xC888,0xC988,0xFADB,0xCA88,0xCB88,0xCC88,0xFCDB,0xE0C5,0xF9BB,0xCD88,0xCE88,0xA3DC,0xCF88,0xD088,0xA5DC,0xD188,0xC3CC,0xD288,0xD388,0xD488,0xD1B6,0xC0DD,0xD588,0xD688,0xD788,0xA1DC,0xD888,0xA2DC,0xD988,0xDA88,0xDB88,0xB5C7,0xDC88,0xDD88,0xDE88,0xE9B6,0xDF88,0xE088,0xE188,0xA7DC,0xE288,0xE388,0xE488,0xE588,0xA6DC,0xE688,0xA9DC,0xA4B1,0xE788,0xE888,0xCCB5,0xE988,0xEA88,0xEB88,0xEC88,0xED88,0xB0BF,0xEE88,0xEF88,0xF088,0xF188,0xF288,0xDFD1,0xF388,0xF488,0xF588,0xF688,0xC2B6,0xF788,0xF888,0xF988,0xFA88,0xFB88,0xFC88,0xFD88,0xFE88,0x4089,0x4189,0x4289,0x4389,0x4489,0x4589,0xA8DC,0x4689,0x4789,0x4889,0x4989,0x4A89,0x4B89,0x4C89,0xFACB,0xF3EB,0x4D89,0x4E89,0x4F89,0xDCCB,0x5089,0x5189,0xFECB,0x5289,0x5389,0x5489,0xC1CC,0x5589,0x5689,0x5789,0x5889,0x5989,0xFBC8,0x5A89,0x5B89,0x5C89,0x5D89,0x5E89,0x5F89,0xAADC,0x6089,0x6189,0x6289,0x6389,0x6489,0xEECC,0xABDC,0x6589,0x6689,0x6789,0x6889,0x6989,0x6A89,0x6B89,0x6C89,0x6D89,0x6E89,0x6F89,0x7089,0x7189,0x7289,0x7389,0x7489,0x7589,0xD3DB,0x7689,0xAFDC,0xACDC,0x7789,0xB3BE,0x7889,0xFBCA,0x7989,0x7A89,0x7B89,0xADDC,0x7C89,0x7D89,0x7E89,0x8089,0x8189,0x8289,0x8389,0x8489,0xCAC9,0xB9C4,0x8589,0x8689,0x8789,0x8889,0x8989,0xBDC7,0xAEDC,0x8A89,0x8B89,0x8C89,0xF6D4,0xE6D0,0x8D89,0x8E89,0x8F89,0x9089,0x9189,0x9289,0x9389,0x9489,0xABC4,0xD5B6,0x9589,0x9689,0x9789,0x9889,0x9989,0x9A89,0x9B89,0x9C89,0x9D89,0x9E89,0x9F89,0xA089,0xA189,0xA289,0xA389,0xA489,0xA589,0xA689,0xD4DB,0xA789,0xA889,0xA989,0xAA89,0xDAB1,0xAB89,0xAC89,0xAD89,0xD5DB,0xAE89,0xAF89,0xB089,0xB189,0xB289,0xB389,0xB489,0xB589,0xB689,0xB789,0xB889,0xD6DB,0xB989,0xBA89,0xBB89,0xBEBA,0xBC89,0xBD89,0xBE89,0xBF89,0xC089,0xC189,0xC289,0xC389,0xC489,0xC589,0xC689,0xC789,0xC889,0xC989,0xC0C8,0xCA89,0xCB89,0xCC89,0xCD89,0xCE89,0xCF89,0xBFCA,0xC9C8,0xD089,0xB3D7,0xD189,0xF9C9,0xD289,0xD389,0xC7BF,0xD489,0xD589,0xF8BA,0xD689,0xD789,0xBCD2,0xD889,0xD989,0xDA89,0xDB89,0xDC89,0xDD89,0xDE89,0xDF89,0xBAE2,0xE089,0xA6B4,0xE189,0xE289,0xB8B1,0xE389,0xE489,0xE589,0xE689,0xE789,0xB4B8,0xE889,0xC4CF,0xE989,0xEA89,0xEB89,0xEC89,0xE7D9,0xA6CF,0xE2CD,0xED89,0xEE89,0xEDD9,0xE0B6,0xEF89,0xB9D2,0xF089,0xF189,0xBBB9,0xF289,0xF389,0xF489,0xF589,0xB9E2,0xB7E2,0xF689,0xF3B4,0xF789,0xECCC,0xABCC,0xF2B7,0xF889,0xB2D8,0xEBD1,0xBBBA,0xF989,0xA7CA,0xFA89,0xFB89,0xB7CD,0xFC89,0xFD89,0xC4D2,0xE4BF,0xD0BC,0xE1B6,0xFE89,0xC5DE,0x408A,0x418A,0x428A,0x438A,0xC6DE,0xBCDB,0x448A,0xD9D1,0x458A,0x468A,0xE6C6,0xCEC4,0xEEB7,0x478A,0xDCB7,0x488A,0x498A,0xFCBF,0xE0D7,0x4A8A,0xF5C6,0x4B8A,0x4C8A,0xBCB1,0xC8DE,0xB1BD,0xD7CC,0xCADE,0x4D8A,0xC9DE,0x4E8A,0x4F8A,0x508A,0x518A,0x528A,0xECB5,0x538A,0xDDC9,0x548A,0x558A,0xC2B0,0x568A,0x578A,0x588A,0x598A,0x5A8A,0x5B8A,0x5C8A,0x5D8A,0x5E8A,0x5F8A,0x608A,0x618A,0x628A,0xAEC5,0xABC5,0x638A,0xCCC4,0x648A,0xE9BC,0xFDCB,0x658A,0x668A,0x678A,0xC3BA,0x688A,0x698A,0x6A8A,0xF9E5,0xE7C8,0xFAE5,0xFDCD,0x6B8A,0xB1D7,0xBEB8,0xE8C2,0x6C8A,0xD1C8,0x6D8A,0x6E8A,0xFBE5,0x6F8A,0x708A,0x718A,0x728A,0xCAB6,0xCBBC,0x738A,0x748A,0xFDD1,0xA1E6,0x758A,0xEEC3,0x768A,0x778A,0x788A,0x798A,0xA4E6,0x7A8A,0x7B8A,0x7C8A,0x7D8A,0xFEE5,0xA5E6,0xD7CD,0x7E8A,0x808A,0xC1B7,0xFCE5,0xFDE5,0xA3E6,0x818A,0x828A,0xDDC4,0xA8E6,0x838A,0x848A,0xA7E6,0x858A,0x868A,0x878A,0x888A,0x898A,0x8A8A,0xC3C3,0x8B8A,0xDEC6,0x8C8A,0x8D8A,0xAAE6,0x8E8A,0x8F8A,0x908A,0x918A,0x928A,0x938A,0x948A,0xB7C4,0x958A,0x968A,0x978A,0xA2E6,0xBCCA,0x988A,0x998A,0x9A8A,0x9B8A,0xE3BD,0xC3B9,0xA6E6,0xD5D0,0xAFCE,0x9C8A,0x9D8A,0xA9E6,0xB0E6,0x9E8A,0xA6D2,0x9F8A,0xAABD,0xADE6,0xA08A,0xA18A,0xA28A,0xA38A,0xA48A,0xAFE6,0xA58A,0xD1C0,0xA68A,0xA78A,0xCCD2,0xA88A,0xA98A,0xAA8A,0xA7BC,0xAB8A,0xAC8A,0xAD8A,0xAE8A,0xAF8A,0xB08A,0xB18A,0xB28A,0xB38A,0xB48A,0xB58A,0xB68A,0xB1E6,0xB78A,0xF6D2,0xB88A,0xB98A,0xBA8A,0xCBD7,0xBB8A,0xFECD,0xBC8A,0xDECD,0xA6C2,0xABE6,0xACE6,0xBFBD,0xAEE6,0xB3E6,0xBD8A,0xBE8A,0xB2E6,0xBF8A,0xC08A,0xC18A,0xC28A,0xB6E6,0xC38A,0xB8E6,0xC48A,0xC58A,0xC68A,0xC78A,0xEFC4,0xC88A,0xC98A,0xCA8A,0xC8C4,0xCB8A,0xCC8A,0xEABE,0xEFC9,0xCD8A,0xCE8A,0xB7E6,0xCF8A,0xF0B6,0xD08A,0xD18A,0xD28A,0xE4C3,0xD38A,0xD48A,0xD58A,0xD68A,0xD78A,0xD88A,0xD98A,0xE9D3,0xB4E6,0xDA8A,0xB5E6,0xDB8A,0xA2C8,0xDC8A,0xDD8A,0xDE8A,0xDF8A,0xE08A,0xBDE6,0xE18A,0xE28A,0xE38A,0xB9E6,0xE48A,0xE58A,0xE68A,0xE78A,0xE88A,0xC5C6,0xE98A,0xEA8A,0xF1CD,0xBBE6,0xEB8A,0xEC8A,0xED8A,0xEE8A,0xEF8A,0xF08A,0xF18A,0xF28A,0xF38A,0xF48A,0xBCE6,0xF58A,0xF68A,0xF78A,0xF88A,0xE9BB,0xF98A,0xFA8A,0xFB8A,0xFC8A,0xFD8A,0xFE8A,0x408B,0xBEE6,0x418B,0x428B,0x438B,0x448B,0xBAE6,0x458B,0x468B,0xB7C0,0x478B,0x488B,0x498B,0x4A8B,0x4B8B,0x4C8B,0x4D8B,0x4E8B,0x4F8B,0xA4D3,0xBFE6,0xF4C9,0xC3E6,0x508B,0x518B,0xC4E6,0x528B,0x538B,0x548B,0x558B,0xF6D0,0x568B,0x578B,0x588B,0x598B,0x5A8B,0x5B8B,0x5C8B,0x5D8B,0x5E8B,0x5F8B,0x608B,0x618B,0x628B,0x638B,0x648B,0x658B,0x668B,0x678B,0xBDC3,0x688B,0x698B,0x6A8B,0x6B8B,0x6C8B,0x6D8B,0x6E8B,0xC4C3,0xC2E6,0x6F8B,0x708B,0x718B,0x728B,0x738B,0x748B,0x758B,0x768B,0x778B,0x788B,0x798B,0x7A8B,0x7B8B,0x7C8B,0xC1E6,0x7D8B,0x7E8B,0x808B,0x818B,0x828B,0x838B,0x848B,0xC7E6,0xB1CF,0x858B,0xF4EB,0x868B,0x878B,0xCAE6,0x888B,0x898B,0x8A8B,0x8B8B,0x8C8B,0xC5E6,0x8D8B,0x8E8B,0xDEBC,0xA9C9,0x8F8B,0x908B,0x918B,0x928B,0x938B,0x948B,0xB5BC,0x958B,0x968B,0xD3CF,0x978B,0x988B,0x998B,0x9A8B,0x9B8B,0xC8E6,0x9C8B,0xC9E6,0x9D8B,0xCEE6,0x9E8B,0xD0E6,0x9F8B,0xA08B,0xA18B,0xD1E6,0xA28B,0xA38B,0xA48B,0xCBE6,0xD5B5,0xA58B,0xCCE6,0xA68B,0xA78B,0xCFE6,0xA88B,0xA98B,0xDBC4,0xAA8B,0xC6E6,0xAB8B,0xAC8B,0xAD8B,0xAE8B,0xAF8B,0xCDE6,0xB08B,0xB18B,0xB28B,0xB38B,0xB48B,0xB58B,0xB68B,0xB78B,0xB88B,0xB98B,0xBA8B,0xBB8B,0xBC8B,0xBD8B,0xBE8B,0xBF8B,0xC08B,0xC18B,0xC28B,0xC38B,0xC48B,0xC58B,0xC68B,0xD2E6,0xC78B,0xC88B,0xC98B,0xCA8B,0xCB8B,0xCC8B,0xCD8B,0xCE8B,0xCF8B,0xD08B,0xD18B,0xD28B,0xD4E6,0xD3E6,0xD38B,0xD48B,0xD58B,0xD68B,0xD78B,0xD88B,0xD98B,0xDA8B,0xDB8B,0xDC8B,0xDD8B,0xDE8B,0xDF8B,0xE08B,0xE18B,0xE28B,0xE38B,0xE48B,0xE58B,0xE68B,0xE78B,0xE88B,0xE98B,0xEA8B,0xEB8B,0xEC8B,0xD5E6,0xED8B,0xF8D9,0xEE8B,0xEF8B,0xD6E6,0xF08B,0xF18B,0xF28B,0xF38B,0xF48B,0xF58B,0xF68B,0xF78B,0xD7E6,0xF88B,0xF98B,0xFA8B,0xFB8B,0xFC8B,0xFD8B,0xFE8B,0x408C,0x418C,0x428C,0x438C,0x448C,0x458C,0x468C,0x478C,0xD3D7,0xDDE6,0x488C,0xDEE6,0xD7BF,0xD0D4,0x498C,0xD6D7,0xE6B4,0xEFCB,0xDAE6,0xC3D8,0xCED7,0xA2D0,0x4A8C,0xCFC3,0x4B8C,0x4C8C,0xDFE6,0xBEBC,0xC2B9,0xDBE6,0xA7D1,0x4D8C,0x4E8C,0xA2BA,0xCFC2,0x4F8C,0xABD8,0x508C,0x518C,0x528C,0xEBCA,0xEEE5,0x538C,0xDCE6,0x548C,0xF5B7,0x558C,0x568C,0x578C,0x588C,0xE6C8,0x598C,0x5A8C,0xF5C4,0x5B8C,0x5C8C,0xB2E5,0xFEC4,0x5D8C,0xFCCB,0xB3E5,0xACD5,0x5E8C,0xEED3,0xD8CA,0xB2B0,0x5F8C,0xCECB,0xEACD,0x608C,0x618C,0xEABA,0x628C,0x638C,0x648C,0xB5E5,0x658C,0xB4E5,0x668C,0xDAD7,0xD9B9,0xE6D6,0xA8B6,0xF0CD,0xCBD2,0xA6B1,0xB5CA,0x678C,0xE8B3,0xF3C9,0xCDBF,0xFBD0,0xD2CA,0xB6E5,0xC2BB,0x688C,0x698C,0x6A8C,0xDCCF,0xACB9,0x6B8C,0x6C8C,0x6D8C,0x6E8C,0xD7D4,0x6F8C,0x708C,0xA6BA,0xE7D1,0xFCCF,0xD2BC,0x718C,0xB7E5,0xDDC8,0x728C,0x738C,0x748C,0xEDBF,0xF6B1,0xDECB,0x758C,0x768C,0xC5BC,0x778C,0xC4BC,0xFAD2,0xDCC3,0xDCBF,0x788C,0x798C,0x7A8C,0x7B8C,0xBBB8,0x7C8C,0x7D8C,0x7E8C,0xC2C3,0x808C,0xAEBA,0xA2D4,0x818C,0x828C,0x838C,0x848C,0x858C,0x868C,0x878C,0x888C,0x898C,0xDEC7,0xAFC4,0xECB2,0x8A8C,0xD1B9,0x8B8C,0x8C8C,0xBBE5,0xC8C1,0x8D8C,0x8E8C,0xAFD5,0x8F8C,0x908C,0x918C,0x928C,0x938C,0xBCE5,0x948C,0xBEE5,0x958C,0x968C,0x978C,0x988C,0x998C,0x9A8C,0x9B8C,0xE7B4,0xD4B6,0xC2CB,0xB0D1,0xBCB5,0x9C8C,0x9D8C,0xD9CA,0x9E8C,0xE2B7,0x9F8C,0xA08C,0xE4C9,0xA18C,0xABBD,0xA28C,0xA38C,0xBECE,0xF0D7,0xA48C,0xA58C,0xA68C,0xA78C,0xA1D0,0xA88C,0xD9C9,0xA98C,0xAA8C,0xFBB6,0xD8E6,0xE2BC,0xAB8C,0xBEB3,0xAC8C,0xD0C9,0xAD8C,0xD9E6,0xA2B3,0xAE8C,0xAF8C,0xB08C,0xB18C,0xCCDE,0xB28C,0xC8D3,0xCDDE,0xB38C,0xA2D2,0xB48C,0xB58C,0xB68C,0xB78C,0xCEDE,0xB88C,0xB98C,0xBA8C,0xBB8C,0xCDBE,0xBC8C,0xBD8C,0xCFDE,0xBE8C,0xBF8C,0xC08C,0xACCA,0xFCD2,0xDFB3,0xEAE5,0xE1C4,0xA1BE,0xB2CE,0xF2C4,0xD6BE,0xA8C6,0xE3B2,0xC18C,0xC28C,0xD3BE,0xC38C,0xC48C,0xFCC7,0xEBCC,0xECBD,0xDDCE,0xC58C,0xC68C,0xBACA,0xC1C6,0xECE5,0xBCD0,0xC78C,0xC88C,0xC98C,0xB9D5,0xCA8C,0xCB8C,0xCC8C,0xEDE5,0xCD8C,0xCE8C,0xCF8C,0xD08C,0xF4CA,0xD18C,0xC0CD,0xC5C2,0xD28C,0xEFE5,0xD38C,0xC4C2,0xF0E5,0xD48C,0xD58C,0xD68C,0xD78C,0xD88C,0xD98C,0xDA8C,0xF8E5,0xCDCD,0xDB8C,0xBDC9,0xDC8C,0xDD8C,0xDE8C,0xDF8C,0xE08C,0xE18C,0xE28C,0xD9D2,0xA8E1,0xE38C,0xE48C,0xE58C,0xE68C,0xECD3,0xE78C,0xEACB,0xF1C6,0xE88C,0xE98C,0xEA8C,0xEB8C,0xEC8C,0xACE1,0xED8C,0xEE8C,0xEF8C,0xA7E1,0xA9E1,0xF08C,0xF18C,0xAAE1,0xAFE1,0xF28C,0xF38C,0xEDB2,0xF48C,0xABE1,0xDAB8,0xADE1,0xAEE1,0xB0E1,0xBAB5,0xB1E1,0xF58C,0xF68C,0xF78C,0xF88C,0xF98C,0xB3E1,0xB8E1,0xFA8C,0xFB8C,0xFC8C,0xFD8C,0xFE8C,0xD2D1,0x408D,0xB6E1,0xB5E1,0xEBC1,0x418D,0x428D,0x438D,0xB7E1,0x448D,0xC0D4,0x458D,0xB2E1,0x468D,0xBAE1,0xB6B0,0x478D,0x488D,0x498D,0x4A8D,0xB4E1,0x4B8D,0xF9BF,0x4C8D,0xB9E1,0x4D8D,0x4E8D,0xBBE1,0x4F8D,0x508D,0x518D,0x528D,0x538D,0x548D,0xBEE1,0x558D,0x568D,0x578D,0x588D,0x598D,0x5A8D,0xBCE1,0x5B8D,0x5C8D,0x5D8D,0x5E8D,0x5F8D,0x608D,0xC5D6,0x618D,0x628D,0x638D,0x648D,0x658D,0x668D,0x678D,0xBFCF,0x688D,0x698D,0xBDE1,0xBFE1,0xCDC2,0x6A8D,0xEBB6,0x6B8D,0xF8D3,0x6C8D,0x6D8D,0xCDC7,0x6E8D,0x6F8D,0xE5B7,0x708D,0x718D,0x728D,0x738D,0x748D,0x758D,0x768D,0x778D,0x788D,0x798D,0xFEBE,0x7A8D,0x7B8D,0x7C8D,0x7D8D,0x7E8D,0x808D,0xC0E1,0xC1E1,0x818D,0x828D,0xC7E1,0xE7B3,0x838D,0x848D,0x858D,0x868D,0x878D,0x888D,0xE9C6,0x898D,0x8A8D,0x8B8D,0x8C8D,0x8D8D,0xDEB4,0x8E8D,0xC2D1,0x8F8D,0x908D,0x918D,0x928D,0xC8E1,0x938D,0x948D,0xC6E1,0x958D,0x968D,0x978D,0x988D,0x998D,0xC5E1,0x9A8D,0xC3E1,0xC2E1,0x9B8D,0xC0B1,0x9C8D,0x9D8D,0x9E8D,0xB8D5,0xC4E1,0x9F8D,0xA08D,0xA18D,0xA28D,0xA38D,0xCBE1,0xA48D,0xA58D,0xA68D,0xA78D,0xA88D,0xA98D,0xAA8D,0xAB8D,0xCCE1,0xCAE1,0xAC8D,0xAD8D,0xAE8D,0xAF8D,0xB08D,0xB18D,0xB28D,0xB38D,0xFAEF,0xB48D,0xB58D,0xD3E1,0xD2E1,0xB6C7,0xB68D,0xB78D,0xB88D,0xB98D,0xBA8D,0xBB8D,0xBC8D,0xBD8D,0xBE8D,0xBF8D,0xC08D,0xC9E1,0xC18D,0xC28D,0xCEE1,0xC38D,0xD0E1,0xC48D,0xC58D,0xC68D,0xC78D,0xC88D,0xC98D,0xCA8D,0xCB8D,0xCC8D,0xCD8D,0xCE8D,0xD4E1,0xCF8D,0xD1E1,0xCDE1,0xD08D,0xD18D,0xCFE1,0xD28D,0xD38D,0xD48D,0xD58D,0xD5E1,0xD68D,0xD78D,0xD88D,0xD98D,0xDA8D,0xDB8D,0xDC8D,0xDD8D,0xDE8D,0xDF8D,0xE08D,0xE18D,0xE28D,0xD6E1,0xE38D,0xE48D,0xE58D,0xE68D,0xE78D,0xE88D,0xE98D,0xEA8D,0xEB8D,0xEC8D,0xED8D,0xEE8D,0xEF8D,0xF08D,0xF18D,0xF28D,0xF38D,0xF48D,0xF58D,0xF68D,0xF78D,0xF88D,0xD7E1,0xF98D,0xFA8D,0xFB8D,0xD8E1,0xFC8D,0xFD8D,0xFE8D,0x408E,0x418E,0x428E,0x438E,0x448E,0x458E,0x468E,0x478E,0x488E,0x498E,0x4A8E,0x4B8E,0x4C8E,0x4D8E,0x4E8E,0x4F8E,0x508E,0x518E,0x528E,0x538E,0x548E,0x558E,0xDAE1,0x568E,0x578E,0x588E,0x598E,0x5A8E,0x5B8E,0x5C8E,0x5D8E,0x5E8E,0x5F8E,0x608E,0x618E,0x628E,0xDBE1,0x638E,0x648E,0x658E,0x668E,0x678E,0x688E,0x698E,0xA1CE,0x6A8E,0x6B8E,0x6C8E,0x6D8E,0x6E8E,0x6F8E,0x708E,0x718E,0x728E,0x738E,0x748E,0x758E,0x768E,0xDDE7,0x778E,0xA8B4,0xDDD6,0x788E,0x798E,0xB2D1,0xB2B3,0x7A8E,0x7B8E,0xA4B9,0xF3D7,0xC9C7,0xDEBE,0xAEB9,0x7C8E,0xD7CE,0x7D8E,0x7E8E,0xEEB2,0xCFDB,0x808E,0xBABC,0xD1D2,0xC8CB,0xCDB0,0x818E,0x828E,0xEFCF,0x838E,0x848E,0x858E,0x868E,0x878E,0xE3D9,0xEDBD,0x888E,0x898E,0xD2B1,0xD0CA,0xBCB2,0x8A8E,0xA7CB,0xABB7,0x8B8E,0xA6CA,0x8C8E,0x8D8E,0x8E8E,0xA3CF,0x8F8E,0x908E,0xF8E0,0xCAD5,0xFBE0,0x918E,0x928E,0xFAE0,0xC1C5,0xFBCC,0x938E,0xB1C1,0xF9E0,0xE3D6,0xAFB2,0xC4D6,0xDBB5,0x948E,0x958E,0x968E,0x978E,0x988E,0x998E,0x9A8E,0x9B8E,0xF8B4,0xA1D6,0x9C8E,0x9D8E,0x9E8E,0x9F8E,0xA08E,0xAFCF,0xEFB0,0xA18E,0xA28E,0xFCE0,0xA38E,0xA48E,0xA58E,0xA68E,0xA78E,0xA1E1,0xA3B3,0xA88E,0xA98E,0xFDE0,0xFEE0,0xB1C3,0xAA8E,0xAB8E,0xAC8E,0xAD8E,0xDDC3,0xAE8E,0xA2E1,0xF9B7,0xAF8E,0xB08E,0xB18E,0xB28E,0xB38E,0xB48E,0xCFBB,0xB58E,0xB68E,0xB78E,0xB88E,0xB98E,0xBA8E,0xBB8E,0xA3E1,0xBBC4,0xBC8E,0xBD8E,0xBE8E,0xBF8E,0xC08E,0xA4E1,0xC18E,0xC28E,0xA5E1,0xC38E,0xC48E,0xA6E1,0xB1B4,0xC58E,0xC68E,0xC78E,0xC88E,0xC98E,0xCA8E,0xCB8E,0xCC8E,0xCD8E,0xCE8E,0xCF8E,0xD08E,0xD18E,0xD28E,0xD38E,0xC9B8,0xBDC6,0xEAC4,0xD48E,0xA2B2,0xD58E,0xD2D0,0xD68E,0xDBE7,0xC3BB,0xD7D3,0xC4D3,0xD78E,0xE3B9,0xCFE2,0xD88E,0xD98E,0xDA8E,0xAFD7,0xDB8E,0xECC7,0xD3B1,0xDC8E,0xDD8E,0xB2B4,0xD1E2,0xDE8E,0xDF8E,0xE08E,0xF2D0,0xAEC2,0xD0E2,0xE18E,0xE2BF,0xA6D3,0xD7B5,0xD2E2,0xEAB5,0xE28E,0xEDC3,0xFDB8,0xE38E,0xAEB8,0xE48E,0xD3C5,0xCFB7,0xD4E2,0xE58E,0xE68E,0xE78E,0xE88E,0xD3E2,0xC8B6,0xF9D7,0xE98E,0xEA8E,0xEB8E,0xEC8E,0xED8E,0xA5CD,0xEE8E,0xEF8E,0xF08E,0xF18E,0xF28E,0xD8E2,0xF38E,0xD6E2,0xFCCA,0xB5BF,0xB9D3,0xD5E2,0xF48E,0xF58E,0xF68E,0xF78E,0xD7E2,0xF88E,0xF98E,0xFA8E,0xFB8E,0xFC8E,0xFD8E,0xFE8E,0x408F,0x418F,0x428F,0xAEC1,0xC8C0,0x438F,0x448F,0x458F,0x468F,0x478F,0x488F,0xDBE2,0xDAE2,0xAAC0,0x498F,0x4A8F,0xCEC1,0x4B8F,0x4C8F,0x4D8F,0x4E8F,0xDCE2,0x4F8F,0x508F,0x518F,0x528F,0x538F,0x548F,0x558F,0x568F,0x578F,0x588F,0x598F,0x5A8F,0xDDE2,0x5B8F,0xDEE2,0x5C8F,0x5D8F,0x5E8F,0x5F8F,0x608F,0x618F,0x628F,0x638F,0x648F,0xC8DB,0x658F,0xD3D1,0xA2CD,0x668F,0x678F,0xA8BD,0x688F,0x698F,0x6A8F,0xC3DE,0xA5D8,0xAABF,0xCDDB,0xECD2,0xFAC6,0xAAC5,0x6B8F,0x6C8F,0x6D8F,0xC4DE,0x6E8F,0xD7B1,0xAEDF,0x6F8F,0x708F,0x718F,0xBDCA,0x728F,0xB1DF,0x738F,0xADB9,0x748F,0xFDD2,0x758F,0xA5B8,0xEBBA,0x768F,0x778F,0xDAB3,0x788F,0x798F,0x7A8F,0xDCB5,0xC5D5,0x7B8F,0x7C8F,0x7D8F,0x7E8F,0xD6C3,0xD2CF,0xA1BB,0x808F,0xF3E5,0xF2E5,0x818F,0x828F,0xF4E5,0x838F,0xE4CD,0x848F,0xF5C8,0x858F,0x868F,0x878F,0x888F,0x898F,0x8A8F,0x8B8F,0xAFB5,0xBFC7,0x8C8F,0xF6E5,0x8D8F,0x8E8F,0x8F8F,0xB0EC,0x908F,0x918F,0x928F,0x938F,0x948F,0x958F,0x968F,0x978F,0x988F,0x998F,0x9A8F,0x9B8F,0x9C8F,0x9D8F,0x9E8F,0xE6E5,0x9F8F,0xE9B9,0xB1B5,0xA08F,0xBCC2,0xE8E5,0xE7E5,0xE9E5,0xA18F,0xA28F,0xA38F,0xA48F,0xCDD2,0xA58F,0xA68F,0xA78F,0xEAE1,0xCED0,0xA88F,0xAECD,0xA98F,0xE5D1,0xAA8F,0xAB8F,0xCAB2,0xEBB1,0xAC8F,0xF2B1,0xEDC5,0xAD8F,0xAE8F,0xC3D5,0xB0D3,0xAF8F,0xDCE1,0xB08F,0xB18F,0xB28F,0xDDE1,0xB38F,0xDBD2,0xB48F,0xB9B3,0xCBB1,0xB58F,0xB68F,0xB78F,0xF9CD,0xF7D5,0xDEE1,0xB88F,0xB6BE,0xFDB4,0xB98F,0xDFE1,0xDCBA,0xE0E1,0xB2BB,0xC9C2,0xE1E1,0xBA8F,0xBB8F,0xBC8F,0xECD0,0xBD8F,0xBDCD,0xBE8F,0xBF8F,0xE2E1,0xC08F,0xC3B5,0xC7C5,0xE3E1,0xC18F,0xC28F,0xE4E1,0xC38F,0xC48F,0xC58F,0xC68F,0xF9D3,0xC78F,0xC88F,0xC98F,0xCA8F,0xCB8F,0xCC8F,0xE5E1,0xCD8F,0xADD1,0xCE8F,0xCF8F,0xE6E1,0xA2CE,0xD08F,0xD18F,0xD28F,0xD38F,0xD48F,0xD58F,0xE7E1,0xD68F,0xC2B5,0xD78F,0xD88F,0xD98F,0xDA8F,0xE8E1,0xD5BB,0xDB8F,0xDC8F,0xDD8F,0xDE8F,0xDF8F,0xC4D0,0xE0E2,0xD8B1,0xE4D2,0xE08F,0xE18F,0xE1E2,0xE28F,0xE38F,0xC9BC,0xCCC8,0xE48F,0xE3E2,0xFEEC,0xFDEC,0xAFDF,0xE58F,0xE68F,0xE78F,0xE2E2,0xBED6,0xFCCD,0xA6C3,0xE88F,0xE98F,0xEA8F,0xC3E3,0xEB8F,0xEC8F,0xD2D6,0xE7E2,0xED8F,0xEE8F,0xE8E2,0xEF8F,0xF08F,0xC7D3,0xF18F,0xF28F,0xECE2,0xECBF,0xF38F,0xEDE2,0xE5E2,0xF48F,0xF58F,0xC0B3,0xF68F,0xF78F,0xF88F,0xEEC4,0xF98F,0xFA8F,0xEEE2,0xFB8F,0xFC8F,0xC3D0,0xFD8F,0xF6BA,0xE9E2,0xDEB7,0xB3BB,0xACCC,0xCBCB,0xE4E2,0xE6E2,0xEAE2,0xEBE2,0xFE8F,0x4090,0x4190,0xF7E2,0x4290,0x4390,0xF4E2,0xF5D4,0xF3E2,0x4490,0x4590,0xADC5,0x4690,0xFAD5,0xC2C5,0xC0B2,0x4790,0x4890,0xEFE2,0x4990,0xF2E2,0xAFC1,0xBCCB,0x4A90,0x4B90,0xA1B5,0xF9E2,0x4C90,0x4D90,0x4E90,0xB1BC,0xF1E2,0xD4D0,0xB9D4,0xF5E2,0xD6B9,0xF6E2,0x4F90,0x5090,0x5190,0xD3C7,0x5290,0x5390,0x5490,0x5590,0x5690,0xF0E2,0x5790,0x5890,0x5990,0x5A90,0x5B90,0xDCD7,0xA1ED,0x5C90,0x5D90,0xF8E2,0x5E90,0xA5ED,0xFEE2,0xD1CA,0x5F90,0x6090,0x6190,0x6290,0x6390,0x6490,0x6590,0xB5C1,0x6690,0xD0BB,0x6790,0x6890,0xD6BF,0x6990,0xE3BA,0x6A90,0x6B90,0xA1CB,0x6C90,0x6D90,0x6E90,0xA6ED,0xA3ED,0x6F90,0x7090,0xA2ED,0x7190,0x7290,0x7390,0x7490,0xD6BB,0xA7ED,0xF4D0,0x7590,0x7690,0xA4ED,0xDEBA,0xF7B6,0xA1E3,0xB2B6,0xF1CC,0xA7B9,0x7790,0xA2CF,0xA1C7,0x7890,0x7990,0xD2BF,0x7A90,0x7B90,0xF1B6,0x7C90,0xFAE2,0xFBE2,0xFDE2,0xFCE2,0xD5C4,0xA2E3,0x7D90,0xC1D3,0x7E90,0x8090,0x8190,0xA7E3,0xC4C7,0x8290,0x8390,0x8490,0x8590,0xA4CF,0x8690,0x8790,0xA9E3,0xB7BA,0x8890,0x8990,0x8A90,0x8B90,0xA8E3,0x8C90,0xDABB,0x8D90,0xA3E3,0x8E90,0x8F90,0x9090,0xA4E3,0xAAE3,0x9190,0xA6E3,0x9290,0xF2CE,0xC6D3,0x9390,0x9490,0xBCBB,0x9590,0x9690,0xC3D4,0x9790,0xFAC4,0x9890,0x9990,0xA8ED,0xFCD0,0xA5E3,0x9A90,0xF5C3,0x9B90,0xADE3,0xAFB1,0x9C90,0xB2E3,0x9D90,0x9E90,0x9F90,0xC2BC,0xA090,0xA190,0xACE3,0xBFB5,0xA290,0xA390,0xA490,0xA590,0xA690,0xA790,0xA890,0xA990,0xE9C7,0xB0E3,0xAA90,0xAB90,0xAC90,0xAABE,0xEFCD,0xAD90,0xAE90,0xAF90,0xB090,0xB190,0xF3BB,0xB290,0xB390,0xB490,0xE8CC,0xB590,0xB690,0xAFE3,0xB790,0xB1E3,0xB890,0xA7CF,0xAEE3,0xB990,0xA9CE,0xDDBB,0xBA90,0xBB90,0xBC90,0xBD90,0xBE90,0xEBB5,0xE5BE,0xD2B2,0xCDB3,0xBF90,0xB9B1,0xABE3,0xD1B2,0xACB5,0xDFB9,0xE8B6,0xC090,0xC190,0xEBCF,0xB7E3,0xC290,0xCCBB,0xC390,0xC490,0xC7C8,0xCAD0,0xC590,0xC690,0xC790,0xC890,0xC990,0xB8E3,0xEEB3,0xCA90,0xCB90,0xCC90,0xCD90,0xA9ED,0xCE90,0xFAD3,0xE4D3,0xCF90,0xD090,0xD190,0xAAED,0xB9E3,0xE2D2,0xD290,0xD390,0xD490,0xD590,0xD690,0xB5E3,0xD790,0xD890,0xD990,0xDA90,0xDED3,0xDB90,0xDC90,0xDD90,0xDE90,0xD0B8,0xB3E3,0xDF90,0xE090,0xB6E3,0xDFB7,0xE190,0xB4E3,0xA2C0,0xE290,0xE390,0xE490,0xBAE3,0xE590,0xE690,0xE790,0xE890,0xE990,0xEA90,0xEB90,0xEC90,0xED90,0xEE90,0xEF90,0xF090,0xF190,0xF290,0xF390,0xF490,0xF590,0xF690,0xF790,0xB8D4,0xF890,0xF990,0xFA90,0xFB90,0xFC90,0xFD90,0xFE90,0x4091,0xC8B4,0x4191,0xBBE3,0x4291,0xC5BB,0x4391,0xF7C9,0x4491,0x4591,0xE5C9,0x4691,0x4791,0x4891,0xBDC4,0x4991,0x4A91,0x4B91,0x4C91,0x4D91,0x4E91,0x4F91,0xABED,0x5091,0x5191,0x5291,0x5391,0xFDC2,0x5491,0x5591,0x5691,0x5791,0xDBBB,0xAEBF,0x5891,0x5991,0x5A91,0x5B91,0x5C91,0x5D91,0x5E91,0xBFCE,0x5F91,0x6091,0x6191,0x6291,0xBCE3,0x6391,0xB6BF,0x6491,0x6591,0x6691,0x6791,0x6891,0x6991,0x6A91,0x6B91,0x6C91,0x6D91,0x6E91,0x6F91,0x7091,0x7191,0x7291,0x7391,0x7491,0x7591,0x7691,0xEFB1,0x7791,0x7891,0xF7D4,0x7991,0x7A91,0x7B91,0x7C91,0x7D91,0xBEE3,0x7E91,0x8091,0x8191,0x8291,0x8391,0x8491,0x8591,0x8691,0xADED,0x8791,0x8891,0x8991,0x8A91,0x8B91,0x8C91,0x8D91,0x8E91,0x8F91,0xBFE3,0xA9BA,0xACED,0x9091,0x9191,0xBDE3,0x9291,0x9391,0x9491,0x9591,0x9691,0x9791,0x9891,0x9991,0x9A91,0x9B91,0xC0E3,0x9C91,0x9D91,0x9E91,0x9F91,0xA091,0xA191,0xB6BA,0xA291,0xA391,0xA491,0xAEB6,0xA591,0xA691,0xA791,0xA891,0xA991,0xB8D0,0xAA91,0xC3B0,0xAEED,0xAB91,0xAC91,0xAD91,0xAE91,0xAF91,0xAFED,0xC1C0,0xB091,0xC1E3,0xB191,0xB291,0xB391,0xB491,0xB591,0xB691,0xB791,0xB891,0xB991,0xBA91,0xBB91,0xBC91,0xBD91,0xBE91,0xBF91,0xC091,0xC191,0xB3C5,0xC291,0xC391,0xC491,0xC591,0xC691,0xC791,0xC891,0xC991,0xCA91,0xCB91,0xCC91,0xCD91,0xCE91,0xCF91,0xC2E3,0xD091,0xD191,0xD291,0xD391,0xD491,0xD591,0xD691,0xD791,0xD891,0xB2DC,0xD991,0xDA91,0xDB91,0xDC91,0xDD91,0xDE91,0xB0ED,0xDF91,0xEAB8,0xE091,0xECCE,0xA7EA,0xE7D0,0xF9CA,0xD6C8,0xB7CF,0xC9B3,0xD2CE,0xE4BD,0xE191,0xE291,0xDEE3,0xF2BB,0xA8EA,0xBDD5,0xE391,0xDDC6,0xA9EA,0xE491,0xE591,0xE691,0xAAEA,0xE791,0xACEA,0xABEA,0xE891,0xAEEA,0xADEA,0xE991,0xEA91,0xEB91,0xEC91,0xD8BD,0xED91,0xAFEA,0xEE91,0xBEC2,0xEF91,0xF091,0xF191,0xF291,0xC1B4,0xF7B4,0xF391,0xF491,0xA7BB,0xF591,0xF691,0xF791,0xF891,0xF991,0xE6EC,0xE5EC,0xBFB7,0xF9CB,0xE2B1,0xFA91,0xE7EC,0xFB91,0xFC91,0xFD91,0xC8C9,0xE8EC,0xE9EC,0xFE91,0xD6CA,0xD0DE,0xC5B2,0xFAD4,0x4092,0x4192,0xCBC6,0xC7B0,0xF2B4,0xD3C8,0x4292,0x4392,0x4492,0xD0CD,0x4592,0x4692,0xB8BF,0x4792,0x4892,0x4992,0x4A92,0x4B92,0x4C92,0x4D92,0xDBBF,0x4E92,0x4F92,0xA4C7,0xB4D6,0x5092,0xA9C0,0xD1DE,0xA8C9,0xEFD1,0xA4C5,0xE7B0,0xB6B3,0xC5C8,0x5192,0x5292,0xE2B0,0x5392,0x5492,0xF6B7,0x5592,0x5692,0xFAC5,0x5792,0x5892,0xF3B6,0x5992,0xD2D5,0xD0B3,0xBCBC,0x5A92,0x5B92,0x5C92,0xADB3,0x5D92,0x5E92,0x5F92,0x6092,0xF1BE,0xD1B0,0x6192,0x6292,0x6392,0x6492,0x6592,0x6692,0xD6D2,0xE3CA,0xA5D7,0x6792,0xB6CD,0xB6B6,0xB9BF,0xDBD5,0x6892,0xA7B8,0xD7C5,0x6992,0x6A92,0x6B92,0xD2DE,0xD9BF,0xD5C2,0xC0C7,0x6C92,0xA4BB,0xA8B1,0x6D92,0x6E92,0xEAC5,0x6F92,0x7092,0xFBC5,0xA7CC,0x7192,0x7292,0x7392,0x7492,0xA7B1,0x7592,0x7692,0x7792,0xD6B5,0x7892,0x7992,0x7A92,0xA8C4,0x7B92,0xD3DE,0xBAD1,0xE9B3,0x7C92,0xF2C3,0x7D92,0x7E92,0xF7B7,0x8092,0xF4D6,0xA3B5,0xF0B2,0xB4C4,0xE9C4,0xADC0,0xD4DE,0x8192,0xE8B0,0xC4C5,0xE0C1,0x8292,0xD5B9,0x8392,0xDCBE,0xD8CD,0xCEB0,0x8492,0xCFCD,0xD6DE,0xD0BE,0xBED7,0xD5DE,0xD0D5,0xDDB0,0x8592,0x8692,0xE2C4,0x8792,0x8892,0xA3C2,0xF0BC,0x8992,0xB5D3,0xB9C0,0xA1C5,0xA6B2,0xF1D4,0x8A92,0x8B92,0xA8C0,0xC3CA,0xD7DE,0xFCD5,0x8C92,0xB0B9,0x8D92,0xADC8,0xA9CB,0x8E92,0xD9DE,0xBDBF,0x8F92,0x9092,0x9192,0x9292,0xB4C6,0xA7D7,0xB0CA,0xC3C4,0x9392,0xD6B3,0xD2B9,0x9492,0x9592,0x9692,0x9792,0xB8D6,0xFCEA,0xB4B0,0x9892,0x9992,0x9A92,0x9B92,0xE6BF,0x9C92,0x9D92,0xF4CC,0x9E92,0x9F92,0xA092,0xA192,0xDACD,0xA292,0xA392,0xA492,0xBFD6,0xCEC2,0xA592,0xCECE,0xA2CC,0xAED0,0xD3C4,0xB2B5,0xD8DE,0xF5D5,0xB7BC,0xD3BB,0xA692,0xA792,0xA4B0,0xA892,0xB2C5,0xECB4,0xA992,0xAA92,0xAB92,0xF1D5,0xAC92,0xAD92,0xFDEA,0xAE92,0xAF92,0xB092,0xB192,0xB292,0xB392,0xDADE,0xA6CD,0xB492,0xB592,0xECCD,0xB692,0xB792,0xB892,0xB992,0xE6CE,0xDCDE,0xBA92,0xB1CD,0xA6C0,0xBB92,0xBC92,0xBDD7,0xBD92,0xDBDE,0xC6B0,0xB4BA,0xD3C9,0xF3C4,0xE8BE,0xBE92,0xBF92,0xC092,0xC192,0xB6B2,0xC292,0xC392,0xC492,0xC592,0xC692,0xC792,0xC892,0xC992,0xCCC0,0xF0CB,0xCA92,0xF1BC,0xBBBB,0xB7B5,0xCB92,0xCC92,0xCD92,0xF5C5,0xCE92,0xE6DE,0xCF92,0xD092,0xD192,0xE3DE,0xDDBE,0xD292,0xD392,0xDFDE,0xD492,0xD592,0xD692,0xD792,0xB7B4,0xDDBD,0xD892,0xD992,0xE0DE,0xEDC4,0xDA92,0xDB92,0xDC92,0xDD92,0xC6CF,0xDE92,0xE0B5,0xDF92,0xE092,0xE192,0xE292,0xDEB6,0xDACA,0xF4B5,0xE5DE,0xE392,0xC6D5,0xE492,0xE1DE,0xCDCC,0xFEC6,0xE592,0xC5C5,0xE692,0xE792,0xE892,0xB4D2,0xE992,0xF2BE,0xEA92,0xEB92,0xEC92,0xED92,0xEE92,0xEF92,0xF092,0xD3C2,0xF192,0xBDCC,0xB8B3,0xF292,0xD3BD,0xF392,0xD8BF,0xC6CD,0xDAD1,0xEBB4,0xF492,0xE4DE,0xDDDE,0xE7DE,0xF592,0xFEEA,0xF692,0xF792,0xB0C2,0xE2DE,0xF892,0xF992,0xC0D6,0xA7B5,0xFA92,0xF4B2,0xFB92,0xE8DE,0xFC92,0xF2DE,0xFD92,0xFE92,0x4093,0x4193,0x4293,0xEDDE,0x4393,0xF1DE,0x4493,0x4593,0xE0C8,0x4693,0x4793,0x4893,0xE1D7,0xEFDE,0xE8C3,0xE1CC,0x4993,0xE5B2,0x4A93,0x4B93,0x4C93,0xBED2,0x4D93,0x4E93,0x4F93,0x5093,0x5193,0x5293,0x5393,0xEEDE,0x5493,0xEBDE,0xD5CE,0x5593,0xA7B4,0x5693,0x5793,0x5893,0x5993,0x5A93,0xABBF,0xBEBE,0x5B93,0x5C93,0xD2BD,0x5D93,0x5E93,0x5F93,0x6093,0xE9DE,0x6193,0xAED4,0x6293,0xDEDE,0x6393,0xEADE,0x6493,0x6593,0x6693,0x6793,0xBFC0,0x6893,0xECDE,0xF3B2,0xE9B8,0xA7C2,0x6993,0x6A93,0xC1BD,0x6B93,0x6C93,0x6D93,0x6E93,0x6F93,0xF5DE,0xF8DE,0x7093,0x7193,0xABB2,0xA4B4,0x7293,0x7393,0xEAB4,0xA6C9,0x7493,0x7593,0x7693,0x7793,0x7893,0x7993,0xF6DE,0xD1CB,0x7A93,0xE3B8,0x7B93,0xF7DE,0xFADE,0x7C93,0x7D93,0x7E93,0x8093,0xF9DE,0x8193,0x8293,0x8393,0xC2CC,0x8493,0xE1B0,0xEEB4,0x8593,0x8693,0x8793,0x8893,0x8993,0x8A93,0xBAE5,0x8B93,0x8C93,0x8D93,0x8E93,0x8F93,0xAFD0,0x9093,0x9193,0xEBB2,0x9293,0xA1EB,0x9393,0xF4DE,0x9493,0x9593,0xE3C9,0xF3DE,0xDAB0,0xA1D2,0xF7B1,0x9693,0xAFCC,0x9793,0x9893,0x9993,0x9A93,0x9B93,0x9C93,0x9D93,0xF0DE,0x9E93,0xA4CB,0x9F93,0xA093,0xA193,0xAAD5,0xA293,0xA393,0xA493,0xA593,0xA693,0xFBDE,0xA793,0xA893,0xA993,0xAA93,0xAB93,0xAC93,0xAD93,0xAE93,0xDDB4,0xAF93,0xA6C4,0xB093,0xB193,0xB293,0xFDDE,0xB393,0xB493,0xB593,0xB693,0xB793,0xB893,0xB993,0xBA93,0xBB93,0xBC93,0xFEC3,0xA1C4,0xA1DF,0xBD93,0xBE93,0xBF93,0xC093,0xC193,0xC293,0xC393,0xCCC1,0xC493,0xFCDE,0xEFBE,0xC593,0xB2C6,0xC693,0xC793,0xC893,0xC993,0xCA93,0xCB93,0xCC93,0xCD93,0xCE93,0xC5B3,0xF6C8,0xCF93,0xD093,0xBACB,0xFEDE,0xD193,0xD293,0xA4DF,0xD393,0xD493,0xD593,0xD693,0xB2D7,0xD793,0xD893,0xD993,0xDA93,0xDB93,0xB7B3,0xDC93,0xDD93,0xDE93,0xDF93,0xC3C1,0xE093,0xE193,0xCBC7,0xA5B2,0xE9B4,0xE293,0xABD7,0xE393,0xE493,0xE593,0xE693,0xECC4,0xE793,0xA2DF,0xA3DF,0xE893,0xA5DF,0xE993,0xB3BA,0xEA93,0xEB93,0xEC93,0xA6DF,0xED93,0xDEC0,0xEE93,0xEF93,0xC3C9,0xF093,0xF193,0xF293,0xF393,0xF493,0xF593,0xF693,0xD9B2,0xE6C7,0xF793,0xA7DF,0xF893,0xDCC7,0xF993,0xFA93,0xFB93,0xFC93,0xA8DF,0xA2EB,0xFD93,0xFE93,0x4094,0x4194,0x4294,0xD3CB,0x4394,0x4494,0x4594,0xAADF,0x4694,0xA9DF,0x4794,0xC1B2,0x4894,0x4994,0x4A94,0x4B94,0x4C94,0x4D94,0x4E94,0x4F94,0x5094,0x5194,0x5294,0x5394,0x5494,0x5594,0x5694,0x5794,0x5894,0x5994,0x5A94,0x5B94,0x5C94,0x5D94,0x5E94,0x5F94,0x6094,0xCAC5,0x6194,0x6294,0x6394,0x6494,0x6594,0x6694,0x6794,0x6894,0xABDF,0x6994,0x6A94,0x6B94,0x6C94,0x6D94,0x6E94,0x6F94,0x7094,0xDCD4,0x7194,0x7294,0x7394,0x7494,0x7594,0xC1C8,0x7694,0x7794,0x7894,0x7994,0x7A94,0x7B94,0x7C94,0x7D94,0x7E94,0x8094,0x8194,0x8294,0xACDF,0x8394,0x8494,0x8594,0x8694,0x8794,0xF0BE,0x8894,0x8994,0xADDF,0xA7D6,0x8A94,0x8B94,0x8C94,0x8D94,0xB7EA,0xB6EB,0xD5CA,0x8E94,0xFCD8,0xC4B8,0x8F94,0xA5B9,0x9094,0x9194,0xC5B7,0xFED5,0x9294,0x9394,0x9494,0x9594,0x9694,0xCAB9,0x9794,0x9894,0xA7D0,0xCDF4,0x9994,0x9A94,0xD0B5,0x9B94,0x9C94,0xF4C3,0x9D94,0xC8BE,0x9E94,0x9F94,0xA094,0xB7EB,0xBDB0,0xA194,0xA294,0xCCBD,0xA394,0xB2C1,0xA494,0xD6B1,0xA8B3,0xA594,0xA694,0xA794,0xD2B8,0xA2C9,0xA894,0xA994,0xD8B6,0xAA94,0xAB94,0xAC94,0xAD94,0xB8EB,0xB4BE,0xAE94,0xAF94,0xB094,0xFDCA,0xB194,0xC3C7,0xB294,0xFBD5,0xB394,0xB494,0xF3B7,0xB594,0xB694,0xB794,0xB894,0xB994,0xBA94,0xBB94,0xBC94,0xBD94,0xBE94,0xBF94,0xC094,0xC194,0xC294,0xC394,0xC4CE,0xC494,0xC594,0xC694,0xABD5,0xF3B1,0xC794,0xC894,0xC994,0xB3EC,0xDFB0,0xCA94,0xB5EC,0xCB94,0xCC94,0xCD94,0xB7B6,0xCE94,0xCFC1,0xCF94,0xFAF5,0xB1D0,0xD094,0xD194,0xE5D5,0xD294,0xD3CE,0xD394,0xD494,0xEFBD,0xE2B3,0xD594,0xABB8,0xD694,0xB6D5,0xD794,0xBDED,0xD894,0xCFB6,0xD994,0xB9CB,0xC2D0,0xDA94,0xDB94,0xDC94,0xDD94,0xDE94,0xDF94,0xE094,0xE194,0xBDB7,0xE294,0xE394,0xB6EC,0xA9CA,0xE494,0xE594,0xE694,0xD4C5,0xE794,0xB9EC,0xB8EC,0xC3C2,0xB7EC,0xE894,0xE994,0xEA94,0xEB94,0xFDD0,0xBAEC,0xEC94,0xBBEC,0xE5D7,0xED94,0xEE94,0xBCEC,0xEF94,0xF094,0xF194,0xBDEC,0xECC6,0xF294,0xF394,0xF494,0xF594,0xF694,0xF794,0xF894,0xF994,0xDECE,0xFA94,0xC8BC,0xFB94,0xFC94,0xD5C8,0xA9B5,0xC9BE,0xBCD6,0xE7D4,0xFD94,0xFE94,0xAED1,0xF1D0,0xB8EA,0xB9EA,0xBAEA,0xB5BA,0x4095,0x4195,0x4295,0x4395,0xB1CA,0xF5BF,0x4495,0x4595,0xFACD,0x4695,0x4795,0x4895,0x4995,0x4A95,0xC0EA,0x4B95,0xBAB0,0xBEEA,0x4C95,0x4D95,0xA5C0,0x4E95,0x4F95,0x5095,0xBBEA,0x5195,0xFDB2,0x5295,0xF7C3,0xE8BB,0x5395,0x5495,0x5595,0xD7D2,0xF4CE,0xBFEA,0x5695,0x5795,0x5895,0xBCEA,0x5995,0x5A95,0x5B95,0xC3EA,0x5C95,0xC7D0,0xB3D3,0x5D95,0x5E95,0x5F95,0x6095,0xBAB4,0x6195,0xC1C3,0xF2D7,0x6295,0x6395,0x6495,0x6595,0xD1D5,0x6695,0xC7CA,0x6795,0xC5EA,0x6895,0x6995,0xC4EA,0xC7EA,0xC6EA,0x6A95,0x6B95,0x6C95,0x6D95,0x6E95,0xE7D6,0x6F95,0xD4CF,0x7095,0x7195,0xCBEA,0x7295,0xCEBB,0x7395,0x7495,0x7595,0x7695,0x7795,0x7895,0x7995,0xFABD,0xCEC9,0x7A95,0x7B95,0xCCEA,0x7C95,0x7D95,0xB9C9,0xFECF,0xCAEA,0xCED4,0xCDEA,0xCFEA,0x7E95,0x8095,0xEDCD,0x8195,0x8295,0x8395,0x8495,0xC9EA,0x8595,0xCEEA,0x8695,0x8795,0xEECE,0x8895,0xDEBB,0x8995,0xBFB3,0x8A95,0x8B95,0x8C95,0x8D95,0x8E95,0xD5C6,0xB0BE,0xFACE,0x8F95,0x9095,0x9195,0xE7C7,0x9295,0xA7BE,0xD0EA,0x9395,0x9495,0xC7D6,0x9595,0x9695,0x9795,0xC0C1,0x9895,0x9995,0x9A95,0xDDD4,0x9B95,0xD1EA,0x9C95,0x9D95,0xBECF,0x9E95,0x9F95,0xA095,0xA195,0xD2EA,0xA295,0xA395,0xA495,0xA595,0xEECA,0xA695,0xA795,0xA895,0xA995,0xAFC5,0xB5B0,0xAA95,0xAB95,0xAC95,0xAD95,0xAE95,0xD4EA,0xAF95,0xB095,0xB195,0xB295,0xB395,0xB495,0xB595,0xB695,0xB795,0xD3EA,0xDFF4,0xB895,0xB995,0xBA95,0xBB95,0xBC95,0xBAC4,0xBD95,0xBE95,0xBF95,0xC095,0xC195,0xA9B1,0xC295,0xC395,0xC495,0xC595,0xDFE5,0xC695,0xC795,0xC895,0xC995,0xD5EA,0xCA95,0xCB95,0xCC95,0xCD95,0xCE95,0xCF95,0xD095,0xD195,0xD295,0xD395,0xD495,0xD595,0xD695,0xD795,0xD895,0xD995,0xDA95,0xDB95,0xDC95,0xDD95,0xDE95,0xDF95,0xE095,0xE195,0xE295,0xE395,0xEFCA,0xE495,0xD6EA,0xD7EA,0xD8C6,0xE595,0xE695,0xE795,0xE895,0xE995,0xEA95,0xEB95,0xEC95,0xD8EA,0xED95,0xEE95,0xD9EA,0xEF95,0xF095,0xF195,0xF295,0xF395,0xF495,0xBBD4,0xF595,0xFAC7,0xB7D2,0xFCB8,0xF695,0xF795,0xC2EA,0xF895,0xDCB2,0xF995,0xFA95,0xFCC2,0xFB95,0xF8D4,0xE6CC,0xEED7,0xFC95,0xFD95,0xFE95,0x4096,0x4196,0x4296,0x4396,0xC2D4,0xD0D3,0xC3EB,0xF3C5,0x4496,0xFEB7,0x4596,0x4696,0xD4EB,0x4796,0x4896,0x4996,0xB7CB,0xDEEB,0x4A96,0xCAC0,0x4B96,0x4C96,0x4D96,0xFBCD,0x4E96,0xAFB3,0x4F96,0xDAC6,0x5096,0x5196,0x5296,0x5396,0x5496,0x5596,0xFCEB,0x5696,0xBEC4,0x5796,0xB4CE,0xA9C4,0xBEB1,0xFDD4,0x5896,0xF5CA,0x5996,0xECD6,0x5A96,0x5B96,0xD3C6,0xE4B6,0x5C96,0x5D96,0x5E96,0x5F96,0xFABB,0x6096,0x6196,0xE0D0,0x6296,0x6396,0xB1C9,0x6496,0xD3D4,0xA8C8,0x6596,0x6696,0xCBB8,0x6796,0xBEE8,0xBCC9,0x6896,0x6996,0xBBE8,0x6A96,0xEEC0,0xD3D0,0xC4B2,0xE5B4,0x6B96,0xBCE8,0x6C96,0x6D96,0xC8D5,0x6E96,0x6F96,0x7096,0x7196,0x7296,0xC5B6,0x7396,0xBDE8,0xF8CA,0xDCB8,0xF5CC,0x7496,0x7596,0x7696,0xB4C0,0x7796,0x7896,0xEED1,0xBFE8,0xC2E8,0x7996,0x7A96,0xBCBA,0x7B96,0xADB1,0xDCBD,0x7C96,0xBDEA,0xC3E8,0x7D96,0xC6E8,0x7E96,0xCBE8,0x8096,0x8196,0x8296,0x8396,0xCCE8,0x8496,0xC9CB,0xE5B0,0x8596,0xABBC,0x8696,0x8796,0xB9B9,0x8896,0x8996,0xC1E8,0x8A96,0xF7CD,0x8B96,0xCAE8,0x8C96,0x8D96,0x8E96,0x8F96,0xF6CE,0x9096,0x9196,0x9296,0x9396,0xEDD5,0x9496,0xD6C1,0xC4E8,0x9596,0xB6C3,0x9696,0xFBB9,0xA6D6,0xC8E8,0x9796,0x9896,0x9996,0xE0CA,0xE6D4,0x9A96,0xC0E8,0x9B96,0xC5E8,0xC7E8,0x9C96,0xB9C7,0xE3B7,0x9D96,0xC9E8,0x9E96,0xDDBF,0xD2E8,0x9F96,0xA096,0xD7E8,0xA196,0xD5E8,0xDCBC,0xCFBC,0xDBE8,0xA296,0xA396,0xA496,0xA596,0xA696,0xA796,0xA896,0xA996,0xDEE8,0xAA96,0xDAE8,0xFAB1,0xAB96,0xAC96,0xAD96,0xAE96,0xAF96,0xB096,0xB196,0xB296,0xB396,0xB496,0xD8B0,0xB3C4,0xCCB8,0xE2C6,0xBEC8,0xE1C8,0xB596,0xB696,0xB796,0xCFE8,0xD4E8,0xD6E8,0xB896,0xF1B9,0xD8E8,0xF5D7,0xB996,0xFBC4,0xBA96,0xDCE8,0xBB96,0xBC96,0xE9B2,0xBD96,0xBE96,0xBF96,0xD1E8,0xC096,0xC196,0xEDBC,0xC296,0xC396,0xC2BF,0xCDE8,0xF9D6,0xC496,0xF8C1,0xF1B2,0xC596,0xC696,0xC796,0xC896,0xC996,0xCA96,0xCB96,0xCC96,0xDFE8,0xCD96,0xC1CA,0xD9E8,0xCE96,0xCF96,0xD096,0xD196,0xA4D5,0xD296,0xEAB1,0xBBD5,0xCEE8,0xD0E8,0xB0B6,0xD3E8,0xD396,0xDDE8,0xB8C0,0xD496,0xF7CA,0xD596,0xA8CB,0xD696,0xD796,0xDCC6,0xF5C0,0xD896,0xD996,0xDA96,0xDB96,0xDC96,0xE9E8,0xDD96,0xDE96,0xDF96,0xA3D0,0xE096,0xE196,0xE296,0xE396,0xE496,0xE596,0xE696,0xF2E8,0xEAD6,0xE796,0xE896,0xE996,0xEA96,0xEB96,0xEC96,0xED96,0xE0E8,0xE1E8,0xEE96,0xEF96,0xF096,0xF9D1,0xCBBA,0xF9B8,0xF196,0xF296,0xF1B8,0xD4D4,0xEFE8,0xF396,0xEEE8,0xECE8,0xF0B9,0xD2CC,0xE6E8,0xA6CE,0xF2BF,0xF496,0xB8B0,0xF1E8,0xF0E8,0xF596,0xC0D7,0xF696,0xE4E8,0xF796,0xA9CD,0xA3C9,0xF896,0xB8BB,0xDBBD,0xEAE8,0xF996,0xFA96,0xFB96,0xFC96,0xFD96,0xFE96,0x4097,0x4197,0x4297,0x4397,0xE2E8,0xE3E8,0xE5E8,0xB5B5,0xE7E8,0xC5C7,0xEBE8,0xEDE8,0xB0BD,0xAED7,0x4497,0xF8E8,0x4597,0x4697,0x4797,0x4897,0x4997,0x4A97,0x4B97,0x4C97,0xF5E8,0x4D97,0xB0CD,0xF6E8,0x4E97,0x4F97,0x5097,0x5197,0x5297,0x5397,0x5497,0x5597,0x5697,0xBAC1,0x5797,0xE8E8,0x5897,0xB7C3,0xF0B0,0x5997,0x5A97,0x5B97,0x5C97,0x5D97,0x5E97,0x5F97,0x6097,0xF4E8,0x6197,0x6297,0x6397,0xF7E8,0x6497,0x6597,0x6697,0xA3B9,0x6797,0x6897,0x6997,0x6A97,0x6B97,0x6C97,0x6D97,0x6E97,0x6F97,0x7097,0xD2C9,0x7197,0x7297,0x7397,0xCEC3,0xE0CE,0xE6C0,0x7497,0x7597,0x7697,0x7797,0xF3CB,0x7897,0xDDCC,0xB5D0,0x7997,0x7A97,0xE1CA,0x7B97,0xF3E8,0x7C97,0x7D97,0x7E97,0x8097,0x8197,0x8297,0x8397,0x8497,0x8597,0x8697,0xECBC,0x8797,0xF9E8,0x8897,0x8997,0x8A97,0x8B97,0x8C97,0x8D97,0xDEC3,0x8E97,0xE5C6,0x8F97,0xF7B9,0x9097,0x9197,0x9297,0x9397,0xF4B0,0x9497,0x9597,0xD8D7,0x9697,0x9797,0xACBC,0x9897,0xEFC5,0x9997,0x9A97,0x9B97,0x9C97,0x9D97,0xC4CC,0x9E97,0x9F97,0xA6E9,0xA097,0xA197,0xA297,0xA397,0xA497,0xA597,0xA697,0xA797,0xA897,0xA997,0xADC9,0xAA97,0xA2E9,0xE2C0,0xAB97,0xAC97,0xAD97,0xC3BF,0xAE97,0xAF97,0xB097,0xFEE8,0xD7B9,0xB197,0xFBE8,0xB297,0xB397,0xB497,0xB597,0xA4E9,0xB697,0xB797,0xB897,0xCED2,0xB997,0xBA97,0xBB97,0xBC97,0xBD97,0xA3E9,0xBE97,0xB2D6,0xB5D7,0xBF97,0xA7E9,0xC097,0xB7BD,0xC197,0xC297,0xC397,0xC497,0xC597,0xC697,0xC797,0xC897,0xC997,0xCA97,0xCB97,0xCC97,0xFCE8,0xFDE8,0xCD97,0xCE97,0xCF97,0xA1E9,0xD097,0xD197,0xD297,0xD397,0xD497,0xD597,0xD697,0xD797,0xD6CD,0xD897,0xD997,0xACD2,0xDA97,0xDB97,0xDC97,0xB2E9,0xDD97,0xDE97,0xDF97,0xE097,0xA9E9,0xE197,0xE297,0xE397,0xAAB4,0xE497,0xBBB4,0xE597,0xE697,0xABE9,0xE797,0xE897,0xE997,0xEA97,0xEB97,0xEC97,0xED97,0xEE97,0xEF97,0xF097,0xF197,0xF297,0xF397,0xF497,0xF597,0xF697,0xF797,0xA8D0,0xF897,0xF997,0xA5E9,0xFA97,0xFB97,0xFEB3,0xFC97,0xFD97,0xACE9,0xE3C0,0xFE97,0xAAE9,0x4098,0x4198,0xB9E9,0x4298,0x4398,0xB8E9,0x4498,0x4598,0x4698,0x4798,0xAEE9,0x4898,0x4998,0xFAE8,0x4A98,0x4B98,0xA8E9,0x4C98,0x4D98,0x4E98,0x4F98,0x5098,0xACBF,0xB1E9,0xBAE9,0x5198,0x5298,0xA5C2,0x5398,0x5498,0x5598,0xAFE9,0x5698,0xC5B8,0x5798,0xADE9,0x5898,0xDCD3,0xB4E9,0xB5E9,0xB7E9,0x5998,0x5A98,0x5B98,0xC7E9,0x5C98,0x5D98,0x5E98,0x5F98,0x6098,0x6198,0xC6C0,0xC5E9,0x6298,0x6398,0xB0E9,0x6498,0x6598,0xBBE9,0xF1B0,0x6698,0x6798,0x6898,0x6998,0x6A98,0x6B98,0x6C98,0x6D98,0x6E98,0x6F98,0xBCE9,0xA5D5,0x7098,0x7198,0xBEE9,0x7298,0xBFE9,0x7398,0x7498,0x7598,0xC1E9,0x7698,0x7798,0xF1C1,0x7898,0x7998,0xB6C8,0x7A98,0x7B98,0x7C98,0xBDE9,0x7D98,0x7E98,0x8098,0x8198,0x8298,0xC2E9,0x8398,0x8498,0x8598,0x8698,0x8798,0x8898,0x8998,0x8A98,0xC3E9,0x8B98,0xB3E9,0x8C98,0xB6E9,0x8D98,0xB1BB,0x8E98,0x8F98,0x9098,0xC0E9,0x9198,0x9298,0x9398,0x9498,0x9598,0x9698,0xF7BC,0x9798,0x9898,0x9998,0xC4E9,0xC6E9,0x9A98,0x9B98,0x9C98,0x9D98,0x9E98,0x9F98,0xA098,0xA198,0xA298,0xA398,0xA498,0xA598,0xCAE9,0xA698,0xA798,0xA898,0xA998,0xCEE9,0xAA98,0xAB98,0xAC98,0xAD98,0xAE98,0xAF98,0xB098,0xB198,0xB298,0xB398,0xDBB2,0xB498,0xC8E9,0xB598,0xB698,0xB798,0xB898,0xB998,0xBA98,0xBB98,0xBC98,0xBD98,0xBE98,0xAEB7,0xBF98,0xC098,0xC198,0xC298,0xC398,0xC498,0xC598,0xC698,0xC798,0xC898,0xC998,0xCA98,0xCBE9,0xCCE9,0xCB98,0xCC98,0xCD98,0xCE98,0xCF98,0xD098,0xC1D5,0xD198,0xA3C4,0xD298,0xD398,0xD498,0xD598,0xD698,0xD798,0xD8E9,0xD898,0xE1BA,0xD998,0xDA98,0xDB98,0xDC98,0xC9E9,0xDD98,0xA3D3,0xDE98,0xDF98,0xE098,0xD4E9,0xE198,0xE298,0xE398,0xE498,0xE598,0xE698,0xE798,0xD7E9,0xD0E9,0xE898,0xE998,0xEA98,0xEB98,0xEC98,0xCFE9,0xED98,0xEE98,0xC1C7,0xEF98,0xF098,0xF198,0xF298,0xF398,0xF498,0xF598,0xF698,0xD2E9,0xF798,0xF898,0xF998,0xFA98,0xFB98,0xFC98,0xFD98,0xD9E9,0xC8B3,0xFE98,0xD3E9,0x4099,0x4199,0x4299,0x4399,0x4499,0xF0CF,0x4599,0x4699,0x4799,0xCDE9,0x4899,0x4999,0x4A99,0x4B99,0x4C99,0x4D99,0x4E99,0x4F99,0x5099,0x5199,0x5299,0xF7B3,0x5399,0x5499,0x5599,0x5699,0x5799,0x5899,0x5999,0xD6E9,0x5A99,0x5B99,0xDAE9,0x5C99,0x5D99,0x5E99,0xB4CC,0x5F99,0x6099,0x6199,0xADCF,0x6299,0x6399,0x6499,0x6599,0x6699,0x6799,0x6899,0x6999,0x6A99,0xD5E9,0x6B99,0xDCE9,0xDBE9,0x6C99,0x6D99,0x6E99,0x6F99,0x7099,0xDEE9,0x7199,0x7299,0x7399,0x7499,0x7599,0x7699,0x7799,0x7899,0xD1E9,0x7999,0x7A99,0x7B99,0x7C99,0x7D99,0x7E99,0x8099,0x8199,0xDDE9,0x8299,0xDFE9,0xCAC3,0x8399,0x8499,0x8599,0x8699,0x8799,0x8899,0x8999,0x8A99,0x8B99,0x8C99,0x8D99,0x8E99,0x8F99,0x9099,0x9199,0x9299,0x9399,0x9499,0x9599,0x9699,0x9799,0x9899,0x9999,0x9A99,0x9B99,0x9C99,0x9D99,0x9E99,0x9F99,0xA099,0xA199,0xA299,0xA399,0xA499,0xA599,0xA699,0xA799,0xA899,0xA999,0xAA99,0xAB99,0xAC99,0xAD99,0xAE99,0xAF99,0xB099,0xB199,0xB299,0xB399,0xB499,0xB599,0xB699,0xB799,0xB899,0xB999,0xBA99,0xBB99,0xBC99,0xBD99,0xBE99,0xBF99,0xC099,0xC199,0xC299,0xC399,0xC499,0xC599,0xC699,0xC799,0xC899,0xC999,0xCA99,0xCB99,0xCC99,0xCD99,0xCE99,0xCF99,0xD099,0xD199,0xD299,0xD399,0xD499,0xD599,0xD699,0xD799,0xD899,0xD999,0xDA99,0xDB99,0xDC99,0xDD99,0xDE99,0xDF99,0xE099,0xE199,0xE299,0xE399,0xE499,0xE599,0xE699,0xE799,0xE899,0xE999,0xEA99,0xEB99,0xEC99,0xED99,0xEE99,0xEF99,0xF099,0xF199,0xF299,0xF399,0xF499,0xF599,0xB7C7,0xCEB4,0xB6BB,0xC0D0,0xA3EC,0xF699,0xF799,0xB7C5,0xF899,0xF999,0xFA99,0xFB99,0xFC99,0xFD99,0xFE99,0x409A,0x419A,0x429A,0xFBD3,0x439A,0x449A,0x459A,0x469A,0xA4EC,0x479A,0xA5EC,0xDBC6,0x489A,0x499A,0x4A9A,0xEEBF,0x4B9A,0x4C9A,0x4D9A,0x4E9A,0xA6EC,0x4F9A,0x509A,0xA7EC,0xAAD0,0x519A,0xB8C7,0x529A,0x539A,0xE8B8,0x549A,0x559A,0x569A,0x579A,0x589A,0x599A,0x5A9A,0x5B9A,0x5C9A,0x5D9A,0x5E9A,0x5F9A,0xA8EC,0x609A,0x619A,0x629A,0x639A,0x649A,0x659A,0x669A,0x679A,0xB9D6,0xFDD5,0xCBB4,0xBDB2,0xE4CE,0xE7C6,0x689A,0x699A,0xE1CD,0x6A9A,0x6B9A,0x6C9A,0x6D9A,0x6E9A,0x6F9A,0x709A,0x719A,0x729A,0x739A,0x749A,0x759A,0x769A,0x779A,0xF5B4,0x789A,0xC0CB,0xDFBC,0x799A,0x7A9A,0x7B9A,0x7C9A,0xE2E9,0xE3E9,0xEAD1,0xE5E9,0x7D9A,0xF9B4,0xE4E9,0x7E9A,0xB3D1,0xE2CA,0xD0B2,0x809A,0xE8E9,0x819A,0x829A,0x839A,0x849A,0xE6E9,0xE7E9,0x859A,0x869A,0xB3D6,0x879A,0x889A,0x899A,0xE9E9,0xEAE9,0x8A9A,0x8B9A,0x8C9A,0x8D9A,0x8E9A,0xEBE9,0x8F9A,0x909A,0x919A,0x929A,0x939A,0x949A,0x959A,0x969A,0xECE9,0x979A,0x989A,0x999A,0x9A9A,0x9B9A,0x9C9A,0x9D9A,0x9E9A,0xAFEC,0xB9C5,0xCEB6,0x9F9A,0xF3D2,0xA09A,0xA19A,0xA29A,0xA39A,0xA49A,0xA59A,0xA69A,0xEEB5,0xA79A,0xD9BB,0xB1EC,0xA89A,0xA99A,0xE3D2,0xAA9A,0xAB9A,0xAC9A,0xAD9A,0xAE9A,0xE3CE,0xAF9A,0xB8C4,0xB09A,0xBFC3,0xB19A,0xB29A,0xBEB6,0xB9D8,0xC8B1,0xCFB1,0xD1B1,0xFEC5,0xB39A,0xD0B1,0xB49A,0xABC3,0xB59A,0xB69A,0xB79A,0xB89A,0xB99A,0xB1D5,0xBA9A,0xBB9A,0xBC9A,0xBD9A,0xBE9A,0xBF9A,0xC09A,0xC19A,0xA4EB,0xC1BA,0xC29A,0xC39A,0xC49A,0xBACC,0xC59A,0xC69A,0xC79A,0xA5EB,0xC89A,0xA7EB,0xC99A,0xCA9A,0xCB9A,0xA8EB,0xCC9A,0xCD9A,0xCE9A,0xA6EB,0xCF9A,0xD09A,0xD19A,0xD29A,0xD39A,0xD49A,0xD59A,0xA9EB,0xABEB,0xAAEB,0xD69A,0xD79A,0xD89A,0xD99A,0xDA9A,0xACEB,0xDB9A,0xCFCA,0xB5D8,0xF1C3,0xDC9A,0xA5C3,0xF8C6,0xADEB,0xCAC4,0xDD9A,0xAEEB,0xAFEB,0xB0EB,0xD5B7,0xDE9A,0xDF9A,0xE09A,0xFAB7,0xE19A,0xB1EB,0xE2C7,0xE29A,0xB3EB,0xE39A,0xA4BA,0xF5D1,0xB1B0,0xB2EB,0xB4EB,0xE49A,0xE59A,0xE69A,0xAAB5,0xC8C2,0xE8C7,0xE79A,0xB5EB,0xE89A,0xAECB,0xDFE3,0xE99A,0xEA9A,0xC0D3,0xEB9A,0xEC9A,0xED9A,0xEE9A,0xDBD9,0xEF9A,0xF09A,0xA1CD,0xADD6,0xF3C7,0xF19A,0xF29A,0xF39A,0xE0D9,0xE3BB,0xF49A,0xBABA,0xE2E3,0xF59A,0xF69A,0xF79A,0xF89A,0xF99A,0xABCF,0xFA9A,0xFB9A,0xFC9A,0xE0E3,0xC7C9,0xFD9A,0xB9BA,0xFE9A,0x409B,0x419B,0xB4D1,0xE1E3,0xEAC8,0xAFB9,0xADBD,0xD8B3,0xDBCE,0x429B,0x439B,0xC0CC,0x449B,0x459B,0x469B,0xE8E3,0xE9E3,0xF4CD,0x479B,0x489B,0x499B,0x4A9B,0x4B9B,0xADCC,0x4C9B,0xB3BC,0x4D9B,0xEAE3,0x4E9B,0xEBE3,0x4F9B,0x509B,0xDAD0,0x519B,0x529B,0x539B,0xFBC6,0xDAB7,0x549B,0x559B,0xDFC7,0xCAD2,0xD6CE,0x569B,0xE4E3,0xECE3,0x579B,0xF2C9,0xC1B3,0x589B,0x599B,0xE7E3,0x5A9B,0x5B9B,0xE3C6,0xE5E3,0x5C9B,0x5D9B,0xB3ED,0xE6E3,0x5E9B,0x5F9B,0x609B,0x619B,0xB3C9,0x629B,0xE6C5,0x639B,0x649B,0x659B,0xB5B9,0x669B,0xBBC3,0x679B,0xE3E3,0xBDC5,0xA4C1,0xD9C2,0xD7B2,0x689B,0xEDE3,0xA6BB,0xADC4,0x699B,0xF0E3,0xDABE,0x6A9B,0x6B9B,0xFBE3,0xF5E3,0xD3BA,0x6C9B,0x6D9B,0x6E9B,0x6F9B,0xD0B7,0xCDD3,0x709B,0xCED6,0xD3D5,0xC1B9,0xB4D5,0xD8D1,0x719B,0x729B,0x739B,0x749B,0xB9D0,0xF6C7,0x759B,0x769B,0x779B,0xAAC8,0xB4B2,0x789B,0xDAC3,0x799B,0x7A9B,0x7B9B,0xEEE3,0x7C9B,0x7D9B,0xFCE3,0xEFE3,0xA8B7,0xF7E3,0xF4E3,0x7E9B,0x809B,0x819B,0xBAB7,0x829B,0x839B,0xA2C5,0x849B,0xF6E3,0xDDC5,0xA8B2,0xFCC6,0x859B,0xE0C4,0x869B,0x879B,0xA2D7,0x889B,0xE1C0,0xF9E3,0x899B,0x8A9B,0xFAE3,0xFDE3,0xA9CC,0xF3E3,0x8B9B,0xBED3,0x8C9B,0xC3B1,0xB4ED,0xF1E3,0xF2E3,0x8D9B,0xF8E3,0xBAD0,0xC3C6,0xF3D4,0xFEE3,0x8E9B,0x8F9B,0xE0BD,0x909B,0x919B,0xA7E4,0x929B,0x939B,0xA6E4,0x949B,0x959B,0x969B,0xF3D1,0xA3E4,0x979B,0xA9E4,0x989B,0x999B,0x9A9B,0xF7C8,0x9B9B,0x9C9B,0x9D9B,0x9E9B,0xB4CF,0x9F9B,0xA8E4,0xAEE4,0xE5C2,0xA09B,0xA19B,0xB4B6,0xA29B,0xA39B,0xA49B,0xA59B,0xA69B,0xA79B,0xF2BD,0xA89B,0xA2E4,0xA99B,0xAA9B,0xE9BA,0xAAE4,0xAB9B,0xAC9B,0xACE4,0xAD9B,0xAE9B,0xFDB6,0xDED6,0xB2E4,0xAF9B,0xADE4,0xB09B,0xB19B,0xB29B,0xA1E4,0xB39B,0xEEBB,0xDDCD,0xA2C7,0xC9C5,0xB49B,0xB59B,0xF7C1,0xB69B,0xA4E4,0xB79B,0xB3C7,0xACBD,0xBDBD,0xA5E4,0xB89B,0xC7D7,0xE2B2,0xB99B,0xABE4,0xC3BC,0xAFE4,0xBA9B,0xEBBB,0xB0E4,0xA8C5,0xB1E4,0xBB9B,0xBC9B,0xBD9B,0xBE9B,0xE3D5,0xA3BF,0xBF9B,0xBAE4,0xC09B,0xB7E4,0xC19B,0xBBE4,0xC29B,0xC39B,0xBDE4,0xC49B,0xC59B,0xD6C6,0xC69B,0xC79B,0xC6BA,0xCBC0,0xC89B,0xC99B,0xCA9B,0xA1B8,0xB4E4,0xCB9B,0xCC9B,0xCD9B,0xCE9B,0xA1D4,0xCF9B,0xD09B,0xA3BA,0xFEBD,0xD19B,0xD29B,0xD39B,0xBCE4,0xD49B,0xD59B,0xD69B,0xD79B,0xD89B,0xBFCD,0xD99B,0xDA9B,0xF9C4,0xDB9B,0xDC9B,0xFBCF,0xE6C9,0xDD9B,0xDE9B,0xBFD3,0xDF9B,0xD1CF,0xE09B,0xE19B,0xB3E4,0xE29B,0xB8E4,0xB9E4,0xE9CC,0xE39B,0xE49B,0xE59B,0xE69B,0xE79B,0xCECC,0xE89B,0xD4C0,0xB5E4,0xB0C1,0xB6E4,0xD0CE,0xE99B,0xC1BB,0xD3B5,0xEA9B,0xF3C8,0xA7BD,0xC7D5,0xACC9,0xA2B8,0xCAE4,0xEB9B,0xEC9B,0xCCE4,0xC4D1,0xED9B,0xEE9B,0xBAD2,0xEF9B,0xF09B,0xADBA,0xF19B,0xF29B,0xD4BA,0xF39B,0xF49B,0xF59B,0xF69B,0xF79B,0xF89B,0xC3E4,0xEDB5,0xF99B,0xFA9B,0xFB9B,0xCDD7,0xC0E4,0xFDCF,0xBFE4,0xFC9B,0xFD9B,0xFE9B,0xDCC1,0xCACC,0x409C,0x419C,0x429C,0x439C,0xE7CA,0x449C,0x459C,0x469C,0x479C,0xD7C4,0x489C,0xD4CC,0xC8E4,0x499C,0x4A9C,0x4B9C,0xC7E4,0xC1E4,0x4C9C,0xC4E4,0xADB5,0x4D9C,0x4E9C,0xD9D3,0x4F9C,0xC6E4,0x509C,0x519C,0x529C,0x539C,0xF9D2,0xE3B4,0x549C,0xB4BB,0x559C,0x569C,0xEEC9,0x579C,0xBEB4,0x589C,0x599C,0x5A9C,0xECBB,0x5B9C,0xCDD1,0x5C9C,0xEDCC,0xB5ED,0x5D9C,0x5E9C,0x5F9C,0x609C,0x619C,0x629C,0x639C,0x649C,0xE5C7,0x659C,0x669C,0x679C,0x689C,0xA8D4,0x699C,0xCBE4,0xD5D7,0xC2E4,0x6A9C,0xA5BD,0xC5E4,0x6B9C,0x6C9C,0xE6D3,0x6D9C,0xC9E4,0xF8C9,0x6E9C,0x6F9C,0xBEE4,0x709C,0x719C,0xE5D3,0x729C,0x739C,0xFEC7,0xC9B6,0x749C,0xFCD4,0xB3B2,0xD7E4,0x759C,0x769C,0x779C,0xC2CE,0x789C,0xCDE4,0x799C,0xBCCE,0x7A9C,0xDBB8,0x7B9C,0x7C9C,0xD6E4,0x7D9C,0xCABF,0x7E9C,0x809C,0x819C,0xCED3,0x829C,0xECC3,0x839C,0x849C,0x859C,0x869C,0x879C,0x889C,0x899C,0x8A9C,0xC8C5,0xD8E4,0x8B9C,0x8C9C,0x8D9C,0x8E9C,0x8F9C,0x909C,0x919C,0x929C,0xC4CD,0xCFE4,0x939C,0x949C,0x959C,0x969C,0xD4E4,0xD5E4,0x979C,0xFEBA,0x989C,0xE6CF,0x999C,0x9A9C,0xBFD5,0x9B9C,0x9C9C,0x9D9C,0xD2E4,0x9E9C,0x9F9C,0xA09C,0xA19C,0xA29C,0xA39C,0xA49C,0xA59C,0xA69C,0xA79C,0xA89C,0xD0E4,0xA99C,0xAA9C,0xCEE4,0xAB9C,0xAC9C,0xAD9C,0xAE9C,0xAF9C,0xB09C,0xB19C,0xB29C,0xB39C,0xB49C,0xB59C,0xB69C,0xB79C,0xB89C,0xB99C,0xE5CD,0xAACA,0xBA9C,0xBB9C,0xBC9C,0xA3C0,0xBD9C,0xA6BD,0xD3E4,0xBE9C,0xBF9C,0xC8B8,0xC09C,0xC19C,0xC29C,0xC39C,0xC49C,0xE7E4,0xB4D4,0xC59C,0xC69C,0xC79C,0xC89C,0xC99C,0xCA9C,0xCB9C,0xDBE4,0xCC9C,0xCD9C,0xCE9C,0xEFC1,0xCF9C,0xD09C,0xE9E4,0xD19C,0xD29C,0xE7D2,0xD39C,0xD49C,0xDFE4,0xD59C,0xE0E4,0xD69C,0xD79C,0xAACF,0xD89C,0xD99C,0xDA9C,0xDB9C,0xDDCB,0xDC9C,0xDAE4,0xD1E4,0xDD9C,0xE5E4,0xDE9C,0xDCC8,0xE3E4,0xDF9C,0xE09C,0xE7C4,0xE2E4,0xE19C,0xE1E4,0xE29C,0xE39C,0xE49C,0xFCB3,0xE8E4,0xE59C,0xE69C,0xE79C,0xE89C,0xE1B5,0xE99C,0xEA9C,0xEB9C,0xCCD7,0xEC9C,0xED9C,0xEE9C,0xE6E4,0xEF9C,0xACBB,0xF09C,0xD2D7,0xCFCC,0xF8EB,0xF19C,0xE4E4,0xF29C,0xF39C,0xF6B9,0xF49C,0xF59C,0xF69C,0xCDD6,0xD9E4,0xDCE4,0xFAC2,0xDEE4,0xF79C,0xCBC2,0xC4C0,0xD0C2,0xF89C,0xF5B1,0xB2CC,0xF99C,0xFA9C,0xFB9C,0xFC9C,0xFD9C,0xFE9C,0x409D,0x419D,0x429D,0x439D,0xCEB5,0x449D,0x459D,0x469D,0x479D,0xEFE4,0x489D,0x499D,0x4A9D,0x4B9D,0x4C9D,0x4D9D,0x4E9D,0x4F9D,0xAFC6,0x509D,0x519D,0x529D,0xE1C6,0x539D,0x549D,0xF5E4,0x559D,0x569D,0x579D,0x589D,0x599D,0xA9C2,0x5A9D,0x5B9D,0x5C9D,0xECC0,0xDDD1,0xEEE4,0x5D9D,0x5E9D,0x5F9D,0x609D,0x619D,0x629D,0x639D,0x649D,0x659D,0x669D,0xAEC4,0x679D,0x689D,0x699D,0xEDE4,0x6A9D,0x6B9D,0x6C9D,0x6D9D,0xF6E4,0xF4E4,0xFEC2,0x6E9D,0xDDE4,0x6F9D,0xF0E4,0x709D,0xFECA,0x719D,0xC4D5,0x729D,0x739D,0xF1E4,0x749D,0x759D,0x769D,0x779D,0x789D,0x799D,0x7A9D,0xFAD1,0x7B9D,0x7C9D,0x7D9D,0x7E9D,0x809D,0x819D,0x829D,0xEBE4,0xECE4,0x839D,0x849D,0x859D,0xF2E4,0x869D,0xABCE,0x879D,0x889D,0x899D,0x8A9D,0x8B9D,0x8C9D,0x8D9D,0x8E9D,0x8F9D,0x909D,0xCBC5,0x919D,0x929D,0x939D,0xB1C7,0x949D,0xBAC2,0x959D,0x969D,0x979D,0xEAE4,0x989D,0x999D,0x9A9D,0xCAC1,0x9B9D,0x9C9D,0x9D9D,0x9E9D,0x9F9D,0xA09D,0xB6CC,0xB1B3,0xA19D,0xA29D,0xA39D,0xFBE4,0xA49D,0xF3E4,0xA59D,0xA69D,0xA79D,0xFAE4,0xA89D,0xFDE4,0xA99D,0xFCE4,0xAA9D,0xAB9D,0xAC9D,0xAD9D,0xAE9D,0xAF9D,0xB09D,0xCEB3,0xB19D,0xB29D,0xB39D,0xBAB3,0xF7E4,0xB49D,0xB59D,0xF9E4,0xF8E4,0xECC5,0xB69D,0xB79D,0xB89D,0xB99D,0xBA9D,0xBB9D,0xBC9D,0xBD9D,0xBE9D,0xBF9D,0xC09D,0xC19D,0xC29D,0xBDC0,0xC39D,0xC49D,0xC59D,0xC69D,0xE8D4,0xC79D,0xC89D,0xC99D,0xCA9D,0xCB9D,0xA2E5,0xCC9D,0xCD9D,0xCE9D,0xCF9D,0xD09D,0xD19D,0xD29D,0xD39D,0xD49D,0xD59D,0xD69D,0xC4B0,0xD79D,0xD89D,0xA4E5,0xD99D,0xDA9D,0xA3E5,0xDB9D,0xDC9D,0xDD9D,0xDE9D,0xDF9D,0xE09D,0xA4BC,0xE19D,0xA5E5,0xE29D,0xE39D,0xE49D,0xE59D,0xE69D,0xE79D,0xA1E5,0xE89D,0xE99D,0xEA9D,0xEB9D,0xEC9D,0xED9D,0xEE9D,0xFEE4,0xF4B1,0xEF9D,0xF09D,0xF19D,0xF29D,0xF39D,0xF49D,0xF59D,0xF69D,0xF79D,0xF89D,0xF99D,0xA8E5,0xFA9D,0xA9E5,0xA6E5,0xFB9D,0xFC9D,0xFD9D,0xFE9D,0x409E,0x419E,0x429E,0x439E,0x449E,0x459E,0x469E,0x479E,0xA7E5,0xAAE5,0x489E,0x499E,0x4A9E,0x4B9E,0x4C9E,0x4D9E,0x4E9E,0x4F9E,0x509E,0x519E,0x529E,0x539E,0x549E,0x559E,0x569E,0x579E,0x589E,0x599E,0x5A9E,0x5B9E,0x5C9E,0x5D9E,0x5E9E,0x5F9E,0x609E,0x619E,0x629E,0x639E,0x649E,0x659E,0x669E,0x679E,0x689E,0xD9C6,0x699E,0x6A9E,0x6B9E,0x6C9E,0x6D9E,0x6E9E,0x6F9E,0x709E,0xABE5,0xADE5,0x719E,0x729E,0x739E,0x749E,0x759E,0x769E,0x779E,0xACE5,0x789E,0x799E,0x7A9E,0x7B9E,0x7C9E,0x7D9E,0x7E9E,0x809E,0x819E,0x829E,0x839E,0x849E,0x859E,0x869E,0x879E,0x889E,0x899E,0xAFE5,0x8A9E,0x8B9E,0x8C9E,0xAEE5,0x8D9E,0x8E9E,0x8F9E,0x909E,0x919E,0x929E,0x939E,0x949E,0x959E,0x969E,0x979E,0x989E,0x999E,0x9A9E,0x9B9E,0x9C9E,0x9D9E,0x9E9E,0xE0B9,0x9F9E,0xA09E,0xB0E5,0xA19E,0xA29E,0xA39E,0xA49E,0xA59E,0xA69E,0xA79E,0xA89E,0xA99E,0xAA9E,0xAB9E,0xAC9E,0xAD9E,0xAE9E,0xB1E5,0xAF9E,0xB09E,0xB19E,0xB29E,0xB39E,0xB49E,0xB59E,0xB69E,0xB79E,0xB89E,0xB99E,0xBA9E,0xF0BB,0xE1EC,0xF0C3,0xBB9E,0xC6B5,0xD2BB,0xBC9E,0xBD9E,0xBE9E,0xBF9E,0xE9C1,0xEED4,0xC09E,0xC4BE,0xC19E,0xC29E,0xC39E,0xC6D7,0xC49E,0xD6D4,0xD3B2,0xBEEC,0xC59E,0xC69E,0xC79E,0xC89E,0xC1EA,0xC99E,0xCA9E,0xCB9E,0xAFC2,0xB6B4,0xCC9E,0xCD9E,0xCE9E,0xD7D1,0xCF9E,0xD09E,0xD19E,0xB4B3,0xD29E,0xB2C8,0xBBBF,0xC0EC,0xD39E,0xD49E,0xCBD6,0xD59E,0xD69E,0xBFEC,0xC1EC,0xD79E,0xD89E,0xD99E,0xDA9E,0xDB9E,0xDC9E,0xDD9E,0xDE9E,0xDF9E,0xE09E,0xE19E,0xE29E,0xE39E,0xC5EC,0xE6BE,0xBFCC,0xDAC5,0xBCBE,0xE49E,0xC6EC,0xE59E,0xFEB1,0xE69E,0xE79E,0xE89E,0xC4EC,0xA8D5,0xE3B5,0xE99E,0xC2EC,0xB6C1,0xE3B3,0xEA9E,0xEB9E,0xC3EC,0xB8CB,0xC3C0,0xFECC,0xEC9E,0xED9E,0xEE9E,0xEF9E,0xD2C1,0xF09E,0xC8EC,0xF19E,0xF29E,0xF39E,0xF49E,0xF59E,0xF69E,0xF79E,0xF89E,0xF99E,0xFA9E,0xFB9E,0xFC9E,0xFD9E,0xE6BA,0xD3C0,0xFE9E,0xF2D6,0x409F,0x419F,0x429F,0xCCD1,0x439F,0x449F,0x459F,0x469F,0xBEBF,0x479F,0xB3B7,0xD5C9,0xC7EC,0xE2BB,0x489F,0xCCCC,0xFDBD,0xC8C8,0x499F,0xA9CF,0x4A9F,0x4B9F,0x4C9F,0x4D9F,0x4E9F,0x4F9F,0x509F,0xE9CD,0x519F,0xEBC5,0x529F,0x539F,0x549F,0xE9B7,0x559F,0x569F,0x579F,0x589F,0x599F,0x5A9F,0x5B9F,0x5C9F,0x5D9F,0x5E9F,0x5F9F,0xC9D1,0xB8BA,0x609F,0x619F,0x629F,0x639F,0x649F,0xC9EC,0x659F,0x669F,0xCAEC,0x679F,0xC0BB,0xCBEC,0x689F,0xE2EC,0xBAB1,0xD9B7,0x699F,0x6A9F,0x6B9F,0x6C9F,0x6D9F,0x6E9F,0x6F9F,0x709F,0x719F,0x729F,0x739F,0xB9BD,0x749F,0x759F,0x769F,0x779F,0x789F,0x799F,0x7A9F,0x7B9F,0xCCEC,0xE6D1,0xCDEC,0x7C9F,0x7D9F,0x7E9F,0x809F,0xBBC8,0x819F,0x829F,0x839F,0x849F,0x859F,0x869F,0x879F,0x889F,0x899F,0x8A9F,0x8B9F,0x8C9F,0x8D9F,0x8E9F,0xD1EC,0x8F9F,0x909F,0x919F,0x929F,0xD3EC,0x939F,0xCDBB,0x949F,0xE5BC,0x959F,0x969F,0x979F,0x989F,0x999F,0x9A9F,0x9B9F,0x9C9F,0x9D9F,0x9E9F,0x9F9F,0xA09F,0xA19F,0xCFEC,0xA29F,0xB7C9,0xA39F,0xA49F,0xA59F,0xA69F,0xA79F,0xBAC3,0xA89F,0xE3EC,0xD5D5,0xD0EC,0xA99F,0xAA9F,0xAB9F,0xAC9F,0xAD9F,0xF3D6,0xAE9F,0xAF9F,0xB09F,0xD2EC,0xCEEC,0xB19F,0xB29F,0xB39F,0xB49F,0xD4EC,0xB59F,0xD5EC,0xB69F,0xB79F,0xBFC9,0xB89F,0xB99F,0xBA9F,0xBB9F,0xBC9F,0xBD9F,0xA8CF,0xBE9F,0xBF9F,0xC09F,0xC19F,0xC29F,0xDCD0,0xC39F,0xC49F,0xC59F,0xC69F,0xACD1,0xC79F,0xC89F,0xC99F,0xCA9F,0xDBC8,0xCB9F,0xCC9F,0xCD9F,0xD6EC,0xF5CE,0xCE9F,0xCF9F,0xD09F,0xD19F,0xD29F,0xECCA,0xDAEC,0xD39F,0xD49F,0xD59F,0xD69F,0xD79F,0xD89F,0xD99F,0xD9EC,0xDA9F,0xDB9F,0xDC9F,0xBEB0,0xDD9F,0xDE9F,0xDF9F,0xE09F,0xE19F,0xE29F,0xD7EC,0xE39F,0xD8EC,0xE49F,0xE59F,0xE69F,0xE4EC,0xE79F,0xE89F,0xE99F,0xEA9F,0xEB9F,0xEC9F,0xED9F,0xEE9F,0xEF9F,0xBCC8,0xF09F,0xF19F,0xF29F,0xF39F,0xF49F,0xF59F,0xF69F,0xF79F,0xF89F,0xF99F,0xC7C1,0xFA9F,0xFB9F,0xFC9F,0xFD9F,0xFE9F,0xDCEC,0xE0D1,0x40A0,0x41A0,0x42A0,0x43A0,0x44A0,0x45A0,0x46A0,0x47A0,0x48A0,0x49A0,0xDBEC,0x4AA0,0x4BA0,0x4CA0,0x4DA0,0xEFD4,0x4EA0,0xDDEC,0x4FA0,0x50A0,0x51A0,0x52A0,0x53A0,0x54A0,0xC6DB,0x55A0,0x56A0,0x57A0,0x58A0,0x59A0,0x5AA0,0x5BA0,0x5CA0,0x5DA0,0x5EA0,0xDEEC,0x5FA0,0x60A0,0x61A0,0x62A0,0x63A0,0x64A0,0x65A0,0x66A0,0x67A0,0x68A0,0x69A0,0x6AA0,0xACB1,0x6BA0,0x6CA0,0x6DA0,0x6EA0,0x6FA0,0x70A0,0x71A0,0x72A0,0x73A0,0x74A0,0x75A0,0x76A0,0x77A0,0x78A0,0x79A0,0x7AA0,0x7BA0,0x7CA0,0x7DA0,0x7EA0,0x80A0,0x81A0,0xDFEC,0x82A0,0x83A0,0x84A0,0x85A0,0x86A0,0x87A0,0x88A0,0x89A0,0x8AA0,0x8BA0,0xE0EC,0x8CA0,0xA6D7,0x8DA0,0xC0C5,0x8EA0,0x8FA0,0x90A0,0xBCEB,0xAEB0,0x91A0,0x92A0,0x93A0,0xF4BE,0xB8B8,0xAFD2,0xD6B0,0xF9B5,0x94A0,0xB3D8,0x95A0,0xACCB,0x96A0,0xDDE3,0x97A0,0x98A0,0x99A0,0x9AA0,0x9BA0,0x9CA0,0x9DA0,0xACC6,0xE6B0,0x9EA0,0x9FA0,0xA0A0,0xC6C5,0xB9EB,0xA1A0,0xA2A0,0xA3A0,0xA4A0,0xBAEB,0xA5A0,0xA6A0,0xA7A0,0xBBEB,0xA8A0,0xA9A0,0xC0D1,0xAAA0,0xA3C5,0xABA0,0xF2EA,0xACA0,0xB2C4,0xADA0,0xB5C4,0xCEC0,0xAEA0,0xAFA0,0xB0A0,0xF3EA,0xC1C4,0xB1A0,0xEFCE,0xB2A0,0xB3A0,0xB4A0,0xB5A0,0xF0EA,0xF4EA,0xB6A0,0xB7A0,0xFCC9,0xB8A0,0xB9A0,0xA3C7,0xBAA0,0xBBA0,0xBCA0,0xD8CC,0xFECE,0xBDA0,0xBEA0,0xBFA0,0xF5EA,0xF6EA,0xACCF,0xE7C0,0xC0A0,0xC1A0,0xF7EA,0xC2A0,0xC3A0,0xC4A0,0xC5A0,0xC6A0,0xBFB6,0xF8EA,0xC7A0,0xF9EA,0xC8A0,0xFAEA,0xC9A0,0xCAA0,0xFBEA,0xCBA0,0xCCA0,0xCDA0,0xCEA0,0xCFA0,0xD0A0,0xD1A0,0xD2A0,0xD3A0,0xD4A0,0xD5A0,0xD6A0,0xF1EA,0xD7A0,0xD8A0,0xD9A0,0xDAA0,0xDBA0,0xDCA0,0xDDA0,0xDEA0,0xDFA0,0xE0A0,0xE1A0,0xE2A0,0xAEC8,0xEBE1,0xE3A0,0xB8B7,0xECE1,0xE4A0,0xE5A0,0xE6A0,0xEDE1,0xE7A0,0xB4D7,0xEEE1,0xEFE1,0xCCD3,0xE8A0,0xE9A0,0xEAA0,0xEBA0,0xECA0,0xEDA0,0xEEA0,0xF1E1,0xF1BF,0xF0E1,0xD2B5,0xEFA0,0xF0A0,0xF1A0,0xB7B1,0xF2A0,0xF3A0,0xF4A0,0xF5A0,0xF3E1,0xF2E1,0xF6A0,0xFCBA,0xF7A0,0xF4E1,0xF8A0,0xF9A0,0xFAA0,0xFBA0,0xB7B9,0xFCA0,0xD1BE,0xFDA0,0xFEA0,0x40AA,0x41AA,0xFCC4,0x42AA,0xDDBA,0xC6BD,0x43AA,0x44AA,0x45AA,0x46AA,0x47AA,0x48AA,0xF5E1,0xF7E1,0x49AA,0x4AAA,0xC0B6,0xC1CF,0xA8CA,0xF6E1,0xF8D5,0xFCD3,0xF8E1,0xFCE1,0xF9E1,0x4BAA,0x4CAA,0xFAE1,0xEAC0,0x4DAA,0xFEE1,0xA1E2,0xC7C0,0x4EAA,0x4FAA,0x50AA,0x51AA,0xFBE1,0x52AA,0xFDE1,0x53AA,0x54AA,0x55AA,0x56AA,0x57AA,0x58AA,0xA5E2,0x59AA,0x5AAA,0x5BAA,0xD4C1,0x5CAA,0x5DAA,0x5EAA,0x5FAA,0xA3E2,0x60AA,0xA8E2,0xFEB2,0xA2E2,0x61AA,0x62AA,0x63AA,0xCDC3,0xC2B2,0xA7E2,0xA6E2,0x64AA,0x65AA,0xA4E2,0xA9E2,0x66AA,0x67AA,0xABE2,0x68AA,0x69AA,0x6AAA,0xC9D0,0xEDD6,0xA8C3,0xACE2,0x6BAA,0xD7CF,0x6CAA,0x6DAA,0xAEE2,0x6EAA,0x6FAA,0xEFBA,0x70AA,0x71AA,0xE0E9,0xADE2,0xAAE2,0x72AA,0x73AA,0x74AA,0x75AA,0xABBB,0xB3D4,0x76AA,0x77AA,0x78AA,0x79AA,0x7AAA,0x7BAA,0x7CAA,0x7DAA,0x7EAA,0x80AA,0x81AA,0x82AA,0x83AA,0xB0E2,0x84AA,0x85AA,0xAFE2,0x86AA,0xE1E9,0x87AA,0x88AA,0x89AA,0x8AAA,0xB1E2,0x8BAA,0x8CAA,0x8DAA,0x8EAA,0x8FAA,0x90AA,0x91AA,0x92AA,0xB2E2,0x93AA,0x94AA,0x95AA,0x96AA,0x97AA,0x98AA,0x99AA,0x9AAA,0x9BAA,0x9CAA,0x9DAA,0xB3E2,0xA1CC,0x9EAA,0xB4E2,0x9FAA,0xA0AA,0x40AB,0x41AB,0x42AB,0x43AB,0x44AB,0x45AB,0x46AB,0x47AB,0x48AB,0x49AB,0x4AAB,0x4BAB,0xB5E2,0x4CAB,0x4DAB,0x4EAB,0x4FAB,0x50AB,0xFED0,0x51AB,0x52AB,0xCAC2,0x53AB,0xF1D3,0x54AB,0xF5CD,0x55AB,0x56AB,0xE0E7,0x57AB,0x58AB,0xE1E7,0x59AB,0x5AAB,0x5BAB,0x5CAB,0xC1BE,0x5DAB,0x5EAB,0x5FAB,0x60AB,0xEAC2,0x61AB,0x62AB,0x63AB,0xE4E7,0x64AB,0x65AB,0xE3E7,0x66AB,0x67AB,0x68AB,0x69AB,0x6AAB,0x6BAB,0xE6CD,0x6CAB,0xB5C3,0x6DAB,0x6EAB,0xE2E7,0xB7BB,0xD6CF,0x6FAB,0xE1C1,0xE9E7,0x70AB,0x71AB,0x72AB,0xE8E7,0x73AB,0x74AB,0xF4E7,0xA3B2,0x75AB,0x76AB,0x77AB,0x78AB,0xEAE7,0x79AB,0xE6E7,0x7AAB,0x7BAB,0x7CAB,0x7DAB,0x7EAB,0xECE7,0xEBE7,0xBAC9,0x80AB,0x81AB,0xE4D5,0x82AB,0xE5E7,0xA9B7,0xE7E7,0x83AB,0x84AB,0x85AB,0x86AB,0x87AB,0x88AB,0x89AB,0xEEE7,0x8AAB,0x8BAB,0x8CAB,0x8DAB,0xF3E7,0x8EAB,0xE9D6,0x8FAB,0x90AB,0x91AB,0x92AB,0xEDE7,0x93AB,0xF2E7,0x94AB,0xF1E7,0x95AB,0x96AB,0x97AB,0xE0B0,0x98AB,0x99AB,0x9AAB,0x9BAB,0xF5E7,0x9CAB,0x9DAB,0x9EAB,0x9FAB,0xA0AB,0x40AC,0x41AC,0x42AC,0x43AC,0x44AC,0x45AC,0x46AC,0x47AC,0x48AC,0x49AC,0x4AAC,0xF2C7,0x4BAC,0xC5C0,0xEDC0,0x4CAC,0x4DAC,0xF0C1,0xF0E7,0x4EAC,0x4FAC,0x50AC,0x51AC,0xF6E7,0xF6CB,0x52AC,0x53AC,0x54AC,0x55AC,0x56AC,0x57AC,0x58AC,0x59AC,0x5AAC,0xA2E8,0xA1E8,0x5BAC,0x5CAC,0x5DAC,0x5EAC,0x5FAC,0x60AC,0xC1D7,0x61AC,0x62AC,0xFAE7,0xF9E7,0x63AC,0xFBE7,0x64AC,0xF7E7,0x65AC,0xFEE7,0x66AC,0xFDE7,0x67AC,0xFCE7,0x68AC,0x69AC,0xD5C1,0xD9C7,0xFDC5,0xC3C5,0x6AAC,0x6BAC,0x6CAC,0x6DAC,0x6EAC,0xEDC7,0x6FAC,0x70AC,0x71AC,0x72AC,0xA3E8,0x73AC,0x74AC,0x75AC,0x76AC,0x77AC,0x78AC,0x79AC,0x7AAC,0x7BAC,0x7CAC,0x7DAC,0x7EAC,0x80AC,0x81AC,0x82AC,0x83AC,0x84AC,0x85AC,0x86AC,0xA6E8,0x87AC,0xA5E8,0x88AC,0xA7E8,0xF7BA,0xF8E7,0xA4E8,0x89AC,0xF0C8,0xAAC9,0x8AAC,0x8BAC,0x8CAC,0x8DAC,0x8EAC,0x8FAC,0x90AC,0x91AC,0x92AC,0x93AC,0x94AC,0x95AC,0x96AC,0xA9E8,0x97AC,0x98AC,0xE5B9,0x99AC,0x9AAC,0x9BAC,0x9CAC,0x9DAC,0xFED1,0xA8E8,0x9EAC,0x9FAC,0xA0AC,0x40AD,0x41AD,0x42AD,0xAAE8,0x43AD,0xADE8,0xAEE8,0x44AD,0xA7C1,0x45AD,0x46AD,0x47AD,0xAFE8,0x48AD,0x49AD,0x4AAD,0xB0E8,0x4BAD,0x4CAD,0xACE8,0x4DAD,0xB4E8,0x4EAD,0x4FAD,0x50AD,0x51AD,0x52AD,0x53AD,0x54AD,0x55AD,0x56AD,0x57AD,0x58AD,0xABE8,0x59AD,0xB1E8,0x5AAD,0x5BAD,0x5CAD,0x5DAD,0x5EAD,0x5FAD,0x60AD,0x61AD,0xB5E8,0xB2E8,0xB3E8,0x62AD,0x63AD,0x64AD,0x65AD,0x66AD,0x67AD,0x68AD,0x69AD,0x6AAD,0x6BAD,0x6CAD,0x6DAD,0x6EAD,0x6FAD,0x70AD,0x71AD,0xB7E8,0x72AD,0x73AD,0x74AD,0x75AD,0x76AD,0x77AD,0x78AD,0x79AD,0x7AAD,0x7BAD,0x7CAD,0x7DAD,0x7EAD,0x80AD,0x81AD,0x82AD,0x83AD,0x84AD,0x85AD,0x86AD,0x87AD,0x88AD,0x89AD,0xB6E8,0x8AAD,0x8BAD,0x8CAD,0x8DAD,0x8EAD,0x8FAD,0x90AD,0x91AD,0x92AD,0xCFB9,0x93AD,0xACF0,0x94AD,0xADF0,0x95AD,0xB0C6,0xEAB0,0xBFC8,0x96AD,0xDFCD,0x97AD,0x98AD,0x99AD,0x9AAD,0x9BAD,0x9CAD,0x9DAD,0xCDCE,0xB1EA,0x9EAD,0x9FAD,0xA0AD,0x40AE,0xB2EA,0x41AE,0xBFC6,0xC9B4,0x42AE,0x43AE,0x44AE,0x45AE,0x46AE,0x47AE,0x48AE,0xB3EA,0x49AE,0x4AAE,0x4BAE,0x4CAE,0xE7D5,0x4DAE,0x4EAE,0x4FAE,0x50AE,0x51AE,0x52AE,0x53AE,0x54AE,0xF9DD,0x55AE,0xB4EA,0x56AE,0xB5EA,0x57AE,0xB6EA,0x58AE,0x59AE,0x5AAE,0x5BAE,0xCAB8,0xB0DF,0xF5C9,0x5CAE,0xF0CC,0x5DAE,0x5EAE,0xFAC9,0x5FAE,0x60AE,0x61AE,0x62AE,0x63AE,0xFBC9,0x64AE,0x65AE,0xC3D3,0xA6CB,0x66AE,0xA6B8,0xAEF0,0xC2B1,0x67AE,0xB8E5,0xEFCC,0xC9D3,0xD7BC,0xEAC9,0x68AE,0xE7B5,0x69AE,0xD0C4,0xE9B5,0x6AAE,0xAEEE,0xADBB,0x6BAE,0x6CAE,0xDEE7,0x6DAE,0xAFEE,0x6EAE,0x6FAE,0x70AE,0x71AE,0xA9B3,0x72AE,0x73AE,0xB2EE,0x74AE,0x75AE,0xB1EE,0xE7BD,0x76AE,0xB0EE,0xB7CE,0x77AE,0x78AE,0x79AE,0x7AAE,0xCFC5,0x7BAE,0x7CAE,0x7DAE,0x7EAE,0xF4C1,0xCEDB,0xB3EE,0xF3D0,0x80AE,0x81AE,0x82AE,0x83AE,0x84AE,0x85AE,0x86AE,0x87AE,0xD4C2,0xE8C6,0x88AE,0x89AE,0x8AAE,0xACB7,0x8BAE,0x8CAE,0x8DAE,0x8EAE,0x8FAE,0x90AE,0x91AE,0xB4EE,0x92AE,0xEBB3,0x93AE,0x94AE,0x95AE,0xFBBB,0xB5EE,0x96AE,0x97AE,0x98AE,0x99AE,0x9AAE,0xDCE7,0x9BAE,0x9CAE,0x9DAE,0xB6EE,0x9EAE,0x9FAE,0xAEBD,0xA0AE,0x40AF,0x41AF,0x42AF,0xE2F1,0x43AF,0x44AF,0x45AF,0xE8CA,0x46AF,0xC9D2,0xDAF0,0x47AF,0xDBF0,0x48AF,0xDCF0,0xC6C1,0x49AF,0xEDB8,0xCEBE,0x4AAF,0x4BAF,0xDEF0,0x4CAF,0xB1C5,0xDDF0,0xF1D1,0x4DAF,0xE0F0,0xCCB0,0xEABD,0x4EAF,0x4FAF,0x50AF,0x51AF,0x52AF,0xDFD2,0xDFF0,0x53AF,0xAFB4,0xE8B7,0xE6F0,0xE5F0,0xA3C6,0xE1F0,0xE2F0,0xC3B4,0x54AF,0x55AF,0xE3F0,0xEED5,0x56AF,0x57AF,0xDBCC,0xD2BE,0xB2BC,0x58AF,0x59AF,0x5AAF,0xE8F0,0xE7F0,0xE4F0,0xA1B2,0x5BAF,0xA2D6,0xB8D3,0xB7BE,0xACC8,0x5CAF,0x5DAF,0xEAF0,0x5EAF,0x5FAF,0x60AF,0x61AF,0xF7D1,0x62AF,0xCCD6,0xDBBA,0xE9F0,0x63AF,0xBBB6,0x64AF,0x65AF,0xB4CD,0x66AF,0x67AF,0xA6C6,0x68AF,0x69AF,0x6AAF,0xA1C1,0xEBF0,0xEEF0,0x6BAF,0xEDF0,0xF0F0,0xECF0,0x6CAF,0xBEBB,0xEFF0,0x6DAF,0x6EAF,0x6FAF,0x70AF,0xB5CC,0xF2F0,0x71AF,0x72AF,0xD5B3,0x73AF,0x74AF,0x75AF,0x76AF,0xD4B1,0x77AF,0x78AF,0xF3F0,0x79AF,0x7AAF,0xF4F0,0xF6F0,0xE1B4,0x7BAF,0xF1F0,0x7CAF,0xF7F0,0x7DAF,0x7EAF,0x80AF,0x81AF,0xFAF0,0x82AF,0xF8F0,0x83AF,0x84AF,0x85AF,0xF5F0,0x86AF,0x87AF,0x88AF,0x89AF,0xFDF0,0x8AAF,0xF9F0,0xFCF0,0xFEF0,0x8BAF,0xA1F1,0x8CAF,0x8DAF,0x8EAF,0xC1CE,0xA4F1,0x8FAF,0xA3F1,0x90AF,0xF6C1,0xFBF0,0xDDCA,0x91AF,0x92AF,0xF1B4,0xF1B1,0xB1CC,0x93AF,0xA6F1,0x94AF,0x95AF,0xA7F1,0x96AF,0x97AF,0xACF1,0xCED5,0xA9F1,0x98AF,0x99AF,0xB3C8,0x9AAF,0x9BAF,0x9CAF,0xA2F1,0x9DAF,0xABF1,0xA8F1,0xA5F1,0x9EAF,0x9FAF,0xAAF1,0xA0AF,0x40B0,0x41B0,0x42B0,0x43B0,0x44B0,0x45B0,0x46B0,0xA9B0,0xADF1,0x47B0,0x48B0,0x49B0,0x4AB0,0x4BB0,0x4CB0,0xAFF1,0x4DB0,0xB1F1,0x4EB0,0x4FB0,0x50B0,0x51B0,0x52B0,0xB0F1,0x53B0,0xAEF1,0x54B0,0x55B0,0x56B0,0x57B0,0xA2D1,0x58B0,0x59B0,0x5AB0,0x5BB0,0x5CB0,0x5DB0,0x5EB0,0xB2F1,0x5FB0,0x60B0,0x61B0,0xB3F1,0x62B0,0x63B0,0x64B0,0x65B0,0x66B0,0x67B0,0x68B0,0x69B0,0xEFB9,0x6AB0,0x6BB0,0xC7B5,0x6CB0,0xD7B0,0xD9B0,0x6DB0,0x6EB0,0x6FB0,0xEDD4,0x70B0,0xC4B5,0x71B0,0xD4BD,0xCABB,0xA7F0,0x72B0,0x73B0,0xDEB8,0x74B0,0x75B0,0xA8F0,0x76B0,0x77B0,0xA8B0,0x78B0,0xA9F0,0x79B0,0x7AB0,0xEECD,0x7BB0,0x7CB0,0xAAF0,0x7DB0,0x7EB0,0x80B0,0x81B0,0x82B0,0x83B0,0x84B0,0x85B0,0x86B0,0x87B0,0xABF0,0x88B0,0x89B0,0x8AB0,0x8BB0,0x8CB0,0x8DB0,0x8EB0,0x8FB0,0x90B0,0xA4C6,0x91B0,0x92B0,0xE5D6,0xE4F1,0x93B0,0xE5F1,0x94B0,0x95B0,0x96B0,0x97B0,0x98B0,0x99B0,0x9AB0,0x9BB0,0x9CB0,0x9DB0,0xF3C3,0x9EB0,0x9FB0,0xDBD3,0xA0B0,0x40B1,0xD1D6,0xE8C5,0x41B1,0xAFD3,0x42B1,0xE6D2,0x43B1,0x44B1,0xC1EE,0xBBB0,0xB5D5,0xCED1,0xE0BC,0xD0BA,0x45B1,0xF8BF,0x46B1,0xC7B8,0xC1B5,0xCCC5,0x47B1,0x48B1,0xA2CA,0x49B1,0x4AB1,0x4BB1,0xCBC3,0x4CB1,0x4DB1,0x4EB1,0x4FB1,0x50B1,0xC2EE,0x51B1,0x52B1,0x53B1,0x54B1,0x55B1,0x56B1,0x57B1,0x58B1,0xBFC4,0xA2B6,0x59B1,0xECED,0xA4C3,0x5AB1,0xB1D6,0x5BB1,0x5CB1,0x5DB1,0xE0CF,0xEFED,0x5EB1,0x5FB1,0xCEC5,0x60B1,0xDCB6,0x61B1,0x62B1,0xA1CA,0x63B1,0x64B1,0xEDED,0x65B1,0x66B1,0xF0ED,0xF1ED,0xBCC3,0x67B1,0xB4BF,0x68B1,0xEEED,0x69B1,0x6AB1,0x6BB1,0x6CB1,0x6DB1,0x6EB1,0x6FB1,0x70B1,0x71B1,0x72B1,0x73B1,0xF4ED,0xF2ED,0x74B1,0x75B1,0x76B1,0x77B1,0xE6D5,0xDFC3,0x78B1,0xF3ED,0x79B1,0x7AB1,0x7BB1,0xF6ED,0x7CB1,0xA3D5,0xA3D1,0x7DB1,0x7EB1,0x80B1,0xF5ED,0x81B1,0xD0C3,0x82B1,0x83B1,0x84B1,0x85B1,0x86B1,0xF7ED,0xF4BF,0xECBE,0xF8ED,0x87B1,0xF7CC,0x88B1,0xDBD1,0x89B1,0x8AB1,0x8BB1,0xC5D7,0xF6D5,0x8CB1,0xFCED,0x8DB1,0x8EB1,0x8FB1,0xFBED,0x90B1,0x91B1,0x92B1,0x93B1,0x94B1,0x95B1,0x96B1,0x97B1,0xF9ED,0xFAED,0x98B1,0x99B1,0x9AB1,0x9BB1,0x9CB1,0x9DB1,0x9EB1,0x9FB1,0xFDED,0xA6BE,0xA0B1,0x40B2,0x41B2,0x42B2,0x43B2,0xAFCB,0xA1EE,0xBDB6,0x44B2,0xA2EE,0xC0C4,0x45B2,0xFEED,0x46B2,0x47B2,0xDEBD,0xC7B2,0x48B2,0x49B2,0x4AB2,0x4BB2,0x4CB2,0x4DB2,0x4EB2,0x4FB2,0x50B2,0x51B2,0x52B2,0x53B2,0xC3B6,0x54B2,0x55B2,0x56B2,0xA5EE,0xBAD8,0xA3EE,0xA6EE,0x57B2,0x58B2,0x59B2,0xE9C3,0xF2B3,0x5AB2,0x5BB2,0x5CB2,0x5DB2,0x5EB2,0x5FB2,0xA7EE,0xA4EE,0xB9CF,0x60B2,0x61B2,0xA8EE,0xF7C2,0x62B2,0x63B2,0x64B2,0x65B2,0x66B2,0x67B2,0x68B2,0x69B2,0x6AB2,0x6BB2,0x6CB2,0x6DB2,0xA9EE,0xAAEE,0x6EB2,0xABDE,0x6FB2,0x70B2,0xB3C6,0x71B2,0xC6C7,0x72B2,0xF5D6,0xC9B5,0x73B2,0xB2CB,0x74B2,0x75B2,0x76B2,0xABEE,0x77B2,0x78B2,0xABCD,0x79B2,0xACEE,0x7AB2,0x7BB2,0x7CB2,0x7DB2,0x7EB2,0xB0D5,0x80B2,0xADEE,0x81B2,0xC4F6,0x82B2,0x83B2,0x84B2,0x85B2,0x86B2,0x87B2,0x88B2,0x89B2,0x8AB2,0x8BB2,0x8CB2,0x8DB2,0x8EB2,0xC7DB,0x8FB2,0x90B2,0x91B2,0x92B2,0x93B2,0x94B2,0x95B2,0x96B2,0x97B2,0xA3B4,0x98B2,0x99B2,0x9AB2,0xACC3,0xE6F1,0x9BB2,0x9CB2,0x9DB2,0x9EB2,0x9FB2,0xB8CA,0xD3D2,0xA0B2,0xAAD6,0x40B3,0xF2EF,0x41B3,0xD8BE,0x42B3,0xC3BD,0xF3EF,0xCCB6,0xABB0,0x43B3,0x44B3,0x45B3,0x46B3,0xAFCA,0x47B3,0x48B3,0xB6ED,0x49B3,0xB7ED,0x4AB3,0x4BB3,0x4CB3,0x4DB3,0xF9CE,0xAFB7,0xF3BF,0xB8ED,0xEBC2,0xB0C9,0x4EB3,0x4FB3,0x50B3,0x51B3,0x52B3,0x53B3,0xB9ED,0x54B3,0x55B3,0xF6C6,0xB3BF,0x56B3,0x57B3,0x58B3,0xBCED,0xF8C5,0x59B3,0xD0D1,0x5AB3,0xA9D7,0xBAED,0xBBED,0x5BB3,0xE2D1,0x5CB3,0xBFED,0xC0ED,0x5DB3,0xC4ED,0x5EB3,0x5FB3,0x60B3,0xC8ED,0x61B3,0xC6ED,0xCEED,0xE8D5,0x62B3,0xC9ED,0x63B3,0x64B3,0xC7ED,0xBEED,0x65B3,0x66B3,0xE9C5,0x67B3,0x68B3,0x69B3,0xC6C6,0x6AB3,0x6BB3,0xE9C9,0xD2D4,0xC1ED,0xC2ED,0xC3ED,0xC5ED,0x6CB3,0xF9C0,0x6DB3,0xA1B4,0x6EB3,0x6FB3,0x70B3,0x71B3,0xE8B9,0x72B3,0xD0ED,0x73B3,0x74B3,0x75B3,0x76B3,0xD1ED,0x77B3,0xCAED,0x78B3,0xCFED,0x79B3,0xF8CE,0x7AB3,0x7BB3,0xB6CB,0xCCED,0xCDED,0x7CB3,0x7DB3,0x7EB3,0x80B3,0x81B3,0xF5CF,0x82B3,0x83B3,0x84B3,0x85B3,0x86B3,0x87B3,0x88B3,0x89B3,0x8AB3,0x8BB3,0x8CB3,0x8DB3,0xD2ED,0xF2C1,0xB2D3,0xCBED,0xB7C8,0x8EB3,0x8FB3,0x90B3,0x91B3,0x92B3,0x93B3,0x94B3,0x95B3,0xEFBC,0x96B3,0x97B3,0x98B3,0x99B3,0xF0C5,0x9AB3,0x9BB3,0x9CB3,0x9DB3,0x9EB3,0x9FB3,0xA0B3,0x40B4,0x41B4,0x42B4,0xD6ED,0x43B4,0xEFB5,0x44B4,0x45B4,0xB5C2,0xADB0,0xE9CB,0x46B4,0x47B4,0xAEB1,0x48B4,0xD4ED,0x49B4,0x4AB4,0x4BB4,0xEBCD,0xE2B5,0x4CB4,0xD5ED,0xD3ED,0xD7ED,0x4DB4,0x4EB4,0xFAB5,0x4FB4,0xD8ED,0x50B4,0xD9ED,0x51B4,0xDCED,0x52B4,0xCCB1,0x53B4,0x54B4,0x55B4,0x56B4,0x57B4,0x58B4,0x59B4,0x5AB4,0xF6C5,0xEEBC,0xDAED,0xBCCC,0xEAB2,0x5BB4,0x5CB4,0x5DB4,0x5EB4,0xDBED,0x5FB4,0x60B4,0x61B4,0x62B4,0xEBC4,0x63B4,0x64B4,0xC5B4,0x65B4,0x66B4,0x67B4,0xF5B0,0x68B4,0x69B4,0x6AB4,0xDFED,0xDAC0,0xE8B4,0x6BB4,0x6CB4,0x6DB4,0x6EB4,0xCDC5,0x6FB4,0x70B4,0x71B4,0xDDED,0xC4BF,0x72B4,0x73B4,0x74B4,0xDEED,0x75B4,0x76B4,0x77B4,0x78B4,0x79B4,0x7AB4,0x7BB4,0x7CB4,0x7DB4,0x7EB4,0x80B4,0x81B4,0x82B4,0x83B4,0xA5C4,0x84B4,0x85B4,0x86B4,0xE0ED,0x87B4,0x88B4,0x89B4,0x8AB4,0x8BB4,0xE1ED,0x8CB4,0xE3ED,0x8DB4,0x8EB4,0xD7C1,0x8FB4,0x90B4,0xC7BB,0x91B4,0x92B4,0x93B4,0x94B4,0x95B4,0x96B4,0xB8BD,0x97B4,0x98B4,0x99B4,0xE2ED,0x9AB4,0x9BB4,0x9CB4,0x9DB4,0x9EB4,0x9FB4,0xA0B4,0x40B5,0x41B5,0x42B5,0x43B5,0x44B5,0x45B5,0xE4ED,0x46B5,0x47B5,0x48B5,0x49B5,0x4AB5,0x4BB5,0x4CB5,0x4DB5,0x4EB5,0x4FB5,0xE6ED,0x50B5,0x51B5,0x52B5,0x53B5,0x54B5,0xE5ED,0x55B5,0x56B5,0x57B5,0x58B5,0x59B5,0x5AB5,0x5BB5,0x5CB5,0x5DB5,0x5EB5,0x5FB5,0x60B5,0x61B5,0x62B5,0x63B5,0xE7ED,0x64B5,0x65B5,0x66B5,0x67B5,0x68B5,0xBECA,0xEAEC,0xF1C0,0x69B5,0xE7C9,0x6AB5,0xEBEC,0xEEC6,0x6BB5,0x6CB5,0x6DB5,0x6EB5,0xECEC,0x6FB5,0xEDC6,0xEDEC,0x70B5,0x71B5,0x72B5,0x73B5,0x74B5,0x75B5,0x76B5,0x77B5,0x78B5,0xF0EC,0x79B5,0x7AB5,0xE6D7,0xF3EC,0x7BB5,0x7CB5,0xF1EC,0xEEEC,0xEFEC,0xA3D7,0xF1C9,0xEECB,0xF4EC,0x7DB5,0xF2EC,0x7EB5,0x80B5,0xE9CF,0x81B5,0xF6EC,0xB1C6,0x82B5,0x83B5,0x84B5,0x85B5,0xC0BC,0x86B5,0xF5EC,0x87B5,0x88B5,0x89B5,0x8AB5,0x8BB5,0x8CB5,0x8DB5,0xBBB5,0xF6BB,0x8EB5,0xF7EC,0x8FB5,0x90B5,0x91B5,0x92B5,0x93B5,0xF7D9,0xFBBD,0x94B5,0x95B5,0xBBC2,0xF8EC,0x96B5,0x97B5,0x98B5,0x99B5,0xF9EC,0x9AB5,0x9BB5,0x9CB5,0x9DB5,0xA3B8,0x9EB5,0x9FB5,0xA0B5,0x40B6,0x41B6,0x42B6,0x43B6,0x44B6,0x45B6,0x46B6,0xFAEC,0x47B6,0x48B6,0x49B6,0x4AB6,0x4BB6,0x4CB6,0x4DB6,0x4EB6,0x4FB6,0x50B6,0x51B6,0x52B6,0xFBEC,0x53B6,0x54B6,0x55B6,0x56B6,0x57B6,0x58B6,0x59B6,0x5AB6,0x5BB6,0x5CB6,0x5DB6,0xFCEC,0x5EB6,0x5FB6,0x60B6,0x61B6,0x62B6,0xEDD3,0xAED8,0xEBC0,0x63B6,0xDDC7,0xCCBA,0x64B6,0xE3D0,0xBDCB,0x65B6,0xBACD,0x66B6,0x67B6,0xD1B8,0x68B6,0x69B6,0xFCB1,0x6AB6,0xEFC7,0x6BB6,0xD6D6,0x6CB6,0x6DB6,0x6EB6,0xC6BF,0xEBC3,0x6FB6,0x70B6,0xF5EF,0x71B6,0x72B6,0xD8C3,0x73B6,0x74B6,0x75B6,0x76B6,0x77B6,0x78B6,0xE2D7,0x79B6,0x7AB6,0x7BB6,0xF7EF,0xD3B3,0x7CB6,0xD8C7,0xEDD1,0x7DB6,0xC8D6,0x7EB6,0xF8EF,0x80B6,0xF6EF,0x81B6,0xFDBB,0xC6B3,0x82B6,0x83B6,0x84B6,0x85B6,0x86B6,0x87B6,0x88B6,0xD5BD,0x89B6,0x8AB6,0xC6D2,0x8BB6,0xE0BB,0x8CB6,0x8DB6,0xA1CF,0x8EB6,0xFCEF,0xFBEF,0x8FB6,0x90B6,0xF9EF,0x91B6,0x92B6,0x93B6,0x94B6,0xCCB3,0x95B6,0xD4C9,0xB0CB,0x96B6,0x97B6,0x98B6,0x99B6,0x9AB6,0xFEEF,0x9BB6,0x9CB6,0xDEB0,0x9DB6,0x9EB6,0xC9D6,0x9FB6,0xA0B6,0x40B7,0xFDEF,0x41B7,0xEDB3,0x42B7,0x43B7,0xD5F6,0x44B7,0x45B7,0x46B7,0x47B7,0x48B7,0x49B7,0x4AB7,0x4BB7,0x4CB7,0x4DB7,0x4EB7,0x4FB7,0x50B7,0x51B7,0x52B7,0xC8CE,0x53B7,0x54B7,0x55B7,0xA2F0,0x56B7,0xA1F0,0x57B7,0xBEB5,0xDABC,0xFCBB,0x58B7,0xE5B8,0x59B7,0x5AB7,0x5BB7,0x5CB7,0x5DB7,0x5EB7,0xC2C4,0x5FB7,0x60B7,0x61B7,0x62B7,0x63B7,0x64B7,0x65B7,0x66B7,0x67B7,0x68B7,0xA3F0,0x69B7,0x6AB7,0x6BB7,0x6CB7,0x6DB7,0xEBCB,0x6EB7,0x6FB7,0x70B7,0x71B7,0x72B7,0x73B7,0x74B7,0x75B7,0x76B7,0x77B7,0x78B7,0x79B7,0x7AB7,0x7BB7,0x7CB7,0x7DB7,0x7EB7,0x80B7,0x81B7,0x82B7,0x83B7,0x84B7,0x85B7,0x86B7,0xA6F0,0x87B7,0x88B7,0x89B7,0xA8D1,0x8AB7,0xBFBE,0xEEC7,0xB6F1,0xB7F1,0xD5BF,0x8BB7,0x8CB7,0x8DB7,0x8EB7,0xA9B4,0xB8F1,0xBBCD,0x8FB7,0xD4C7,0xADD5,0x90B7,0xB9F1,0x91B7,0xBAF1,0x92B7,0x93B7,0x94B7,0x95B7,0xCFC7,0x96B7,0x97B7,0x98B7,0xA4D2,0xCFD6,0x99B7,0x9AB7,0xBBF1,0xD1BD,0xB0B4,0xBDBE,0x9BB7,0x9CB7,0x9DB7,0xDCB4,0xD1CE,0x9EB7,0xDFBF,0xBDF1,0x9FB7,0xA0B7,0x40B8,0x41B8,0xFABF,0xBCF1,0x42B8,0xBFF1,0x43B8,0x44B8,0x45B8,0xBEF1,0xC0F1,0x46B8,0x47B8,0x48B8,0x49B8,0x4AB8,0xC1F1,0x4BB8,0x4CB8,0x4DB8,0x4EB8,0x4FB8,0x50B8,0x51B8,0x52B8,0x53B8,0x54B8,0x55B8,0xFEC1,0x56B8,0x57B8,0x58B8,0x59B8,0x5AB8,0x5BB8,0x5CB8,0x5DB8,0x5EB8,0x5FB8,0x60B8,0xA2C1,0x61B8,0x62B8,0x63B8,0x64B8,0x65B8,0x66B8,0x67B8,0x68B8,0x69B8,0x6AB8,0xFACA,0x6BB8,0x6CB8,0xBED5,0x6DB8,0x6EB8,0x6FB8,0x70B8,0xBABE,0xB9BE,0xC2D5,0x71B8,0x72B8,0xA2BF,0x73B8,0xAFCD,0xB5F1,0x74B8,0x75B8,0x76B8,0x77B8,0x78B8,0x79B8,0xDFBD,0x7AB8,0xCBB6,0x7BB8,0x7CB8,0x7DB8,0x7EB8,0x80B8,0x81B8,0x82B8,0x83B8,0x84B8,0xF1D6,0xC3F3,0x85B8,0x86B8,0xC4F3,0x87B8,0xCDB8,0x88B8,0x89B8,0x8AB8,0xC6F3,0xC7F3,0x8BB8,0xCAB0,0x8CB8,0xC5F3,0x8DB8,0xC9F3,0xF1CB,0x8EB8,0x8FB8,0x90B8,0xCBF3,0x91B8,0xA6D0,0x92B8,0x93B8,0xCAB1,0xC8F3,0x94B8,0x95B8,0x96B8,0xCFF3,0x97B8,0xD1B5,0x98B8,0x99B8,0xD7F3,0x9AB8,0xD2F3,0x9BB8,0x9CB8,0x9DB8,0xD4F3,0xD3F3,0xFBB7,0x9EB8,0xBFB1,0x9FB8,0xCEF3,0xCAF3,0xDAB5,0xA0B8,0xD0F3,0x40B9,0x41B9,0xD1F3,0x42B9,0xD5F3,0x43B9,0x44B9,0x45B9,0x46B9,0xCDF3,0x47B9,0xE3BC,0x48B9,0xFDC1,0x49B9,0xD6F3,0x4AB9,0x4BB9,0x4CB9,0x4DB9,0x4EB9,0x4FB9,0xDAF3,0x50B9,0xCCF3,0x51B9,0xC8B5,0x52B9,0xEEBD,0xDCF3,0x53B9,0x54B9,0xA4B7,0xF0BF,0xFED6,0xB2CD,0x55B9,0xF0B4,0x56B9,0xDFB2,0x57B9,0xD8F3,0x58B9,0xD9F3,0xB8C9,0x59B9,0xDDF3,0x5AB9,0x5BB9,0xDEF3,0x5CB9,0xE1F3,0x5DB9,0x5EB9,0x5FB9,0x60B9,0x61B9,0x62B9,0x63B9,0x64B9,0x65B9,0x66B9,0x67B9,0xDFF3,0x68B9,0x69B9,0xE3F3,0xE2F3,0x6AB9,0x6BB9,0xDBF3,0x6CB9,0xEABF,0x6DB9,0xEFB3,0x6EB9,0xE0F3,0x6FB9,0x70B9,0xA9C7,0x71B9,0xF2BC,0x72B9,0x73B9,0x74B9,0x75B9,0xEBF3,0x76B9,0x77B9,0x78B9,0x79B9,0x7AB9,0x7BB9,0x7CB9,0xBFB9,0x7DB9,0x7EB9,0xE4F3,0x80B9,0x81B9,0x82B9,0xADB2,0xFEBB,0x83B9,0xE3CB,0x84B9,0x85B9,0x86B9,0x87B9,0xEDF3,0xE9F3,0x88B9,0x89B9,0x8AB9,0xDCB9,0xEEF3,0x8BB9,0x8CB9,0x8DB9,0xE5F3,0xE6F3,0xEAF3,0xE1C2,0xECF3,0xEFF3,0xE8F3,0xFDBC,0x8EB9,0x8FB9,0x90B9,0xE4CF,0x91B9,0x92B9,0xF0F3,0x93B9,0x94B9,0x95B9,0xE7F3,0x96B9,0x97B9,0x98B9,0x99B9,0x9AB9,0x9BB9,0x9CB9,0x9DB9,0xF2F3,0x9EB9,0x9FB9,0xA0B9,0x40BA,0xADD7,0xAAC6,0x41BA,0x42BA,0x43BA,0x44BA,0xF3F3,0x45BA,0x46BA,0x47BA,0x48BA,0xF1F3,0x49BA,0xA8C2,0x4ABA,0x4BBA,0x4CBA,0x4DBA,0x4EBA,0xDDB8,0xF5F3,0x4FBA,0x50BA,0xF4F3,0x51BA,0x52BA,0x53BA,0xDBB4,0x54BA,0x55BA,0x56BA,0xF6F3,0xF7F3,0x57BA,0x58BA,0x59BA,0xF8F3,0x5ABA,0x5BBA,0x5CBA,0xBAC0,0x5DBA,0x5EBA,0xE9C0,0x5FBA,0x60BA,0x61BA,0x62BA,0x63BA,0xF1C5,0x64BA,0x65BA,0x66BA,0x67BA,0xFBF3,0x68BA,0xFAF3,0x69BA,0x6ABA,0x6BBA,0x6CBA,0x6DBA,0x6EBA,0x6FBA,0x70BA,0xD8B4,0x71BA,0x72BA,0x73BA,0xFEF3,0xF9F3,0x74BA,0x75BA,0xFCF3,0x76BA,0x77BA,0x78BA,0x79BA,0x7ABA,0x7BBA,0xFDF3,0x7CBA,0x7DBA,0x7EBA,0x80BA,0x81BA,0x82BA,0x83BA,0x84BA,0xA1F4,0x85BA,0x86BA,0x87BA,0x88BA,0x89BA,0x8ABA,0xA3F4,0xC9BB,0x8BBA,0x8CBA,0xA2F4,0x8DBA,0x8EBA,0x8FBA,0x90BA,0x91BA,0x92BA,0x93BA,0x94BA,0x95BA,0x96BA,0x97BA,0x98BA,0x99BA,0xA4F4,0x9ABA,0x9BBA,0x9CBA,0x9DBA,0x9EBA,0x9FBA,0xBEB2,0xA6F4,0xA5F4,0xA0BA,0x40BB,0x41BB,0x42BB,0x43BB,0x44BB,0x45BB,0x46BB,0x47BB,0x48BB,0x49BB,0xAEBC,0x4ABB,0x4BBB,0x4CBB,0x4DBB,0x4EBB,0x4FBB,0x50BB,0x51BB,0x52BB,0x53BB,0x54BB,0x55BB,0x56BB,0x57BB,0x58BB,0x59BB,0x5ABB,0x5BBB,0x5CBB,0x5DBB,0x5EBB,0x5FBB,0x60BB,0x61BB,0x62BB,0x63BB,0x64BB,0x65BB,0x66BB,0x67BB,0x68BB,0x69BB,0x6ABB,0x6BBB,0x6CBB,0x6DBB,0x6EBB,0xD7C3,0xE1D9,0x6FBB,0x70BB,0x71BB,0x72BB,0x73BB,0x74BB,0xE0C0,0xCCF4,0xD1D7,0x75BB,0x76BB,0x77BB,0x78BB,0x79BB,0x7ABB,0x7BBB,0x7CBB,0x7DBB,0x7EBB,0x80BB,0xDBB7,0x81BB,0x82BB,0x83BB,0x84BB,0x85BB,0x86BB,0x87BB,0xCEF4,0xA3C1,0x88BB,0x89BB,0xC9C6,0x8ABB,0xD6B4,0xB3D5,0x8BBB,0x8CBB,0x8DBB,0xD0F4,0xCFF4,0xD1F4,0xDACB,0x8EBB,0x8FBB,0xD2F4,0x90BB,0xC1D4,0xE0D6,0x91BB,0x92BB,0x93BB,0x94BB,0xE0B7,0x95BB,0x96BB,0x97BB,0xB8C1,0x98BB,0x99BB,0xBBC1,0xD3F4,0xACBE,0x9ABB,0x9BBB,0x9CBB,0x9DBB,0x9EBB,0xE2B4,0x9FBB,0xA0BB,0xD4F4,0xD5F4,0xABBE,0x40BC,0x41BC,0xD6F4,0x42BC,0x43BC,0x44BC,0xDBF4,0x45BC,0xD7F4,0xDAF4,0x46BC,0xFDBA,0x47BC,0xD8F4,0xD9F4,0x48BC,0x49BC,0x4ABC,0x4BBC,0x4CBC,0x4DBC,0x4EBC,0xE2B8,0xC7CC,0xDCF4,0x4FBC,0xDAB2,0x50BC,0x51BC,0xD3C3,0x52BC,0x53BC,0xE3D4,0xB7BF,0x54BC,0x55BC,0x56BC,0x57BC,0x58BC,0x59BC,0x5ABC,0xDDF4,0x5BBC,0x5CBC,0x5DBC,0x5EBC,0x5FBC,0x60BC,0xB4C5,0x61BC,0x62BC,0x63BC,0x64BC,0x65BC,0x66BC,0x67BC,0x68BC,0xE9F4,0x69BC,0x6ABC,0xB5CF,0x6BBC,0x6CBC,0x6DBC,0x6EBC,0x6FBC,0x70BC,0x71BC,0x72BC,0x73BC,0x74BC,0x75BC,0x76BC,0x77BC,0x78BC,0xC9CE,0x79BC,0x7ABC,0x7BBC,0x7CBC,0x7DBC,0x7EBC,0x80BC,0x81BC,0x82BC,0x83BC,0x84BC,0x85BC,0x86BC,0x87BC,0x88BC,0x89BC,0x8ABC,0x8BBC,0x8CBC,0x8DBC,0x8EBC,0xD8CB,0x8FBC,0xF7CB,0x90BC,0x91BC,0x92BC,0x93BC,0xF4BD,0x94BC,0x95BC,0x96BC,0xCFD7,0x97BC,0x98BC,0x99BC,0xDBC0,0x9ABC,0x9BBC,0x9CBC,0x9DBC,0x9EBC,0x9FBC,0xA0BC,0x40BD,0x41BD,0x42BD,0x43BD,0x44BD,0x45BD,0x46BD,0x47BD,0x48BD,0x49BD,0x4ABD,0x4BBD,0x4CBD,0x4DBD,0x4EBD,0x4FBD,0x50BD,0x51BD,0x52BD,0x53BD,0x54BD,0x55BD,0x56BD,0x57BD,0x58BD,0x59BD,0x5ABD,0x5BBD,0x5CBD,0x5DBD,0x5EBD,0x5FBD,0x60BD,0x61BD,0x62BD,0x63BD,0x64BD,0x65BD,0x66BD,0x67BD,0x68BD,0x69BD,0x6ABD,0x6BBD,0x6CBD,0x6DBD,0x6EBD,0x6FBD,0x70BD,0x71BD,0x72BD,0x73BD,0x74BD,0x75BD,0x76BD,0xF5D0,0x77BD,0x78BD,0x79BD,0x7ABD,0x7BBD,0x7CBD,0x7DBD,0x7EBD,0xEAF4,0x80BD,0x81BD,0x82BD,0x83BD,0x84BD,0x85BD,0x86BD,0x87BD,0x88BD,0x89BD,0x8ABD,0x8BBD,0x8CBD,0x8DBD,0x8EBD,0x8FBD,0x90BD,0x91BD,0x92BD,0x93BD,0x94BD,0x95BD,0x96BD,0x97BD,0x98BD,0x99BD,0x9ABD,0x9BBD,0x9CBD,0x9DBD,0x9EBD,0x9FBD,0xA0BD,0x40BE,0x41BE,0x42BE,0x43BE,0x44BE,0x45BE,0x46BE,0x47BE,0x48BE,0x49BE,0x4ABE,0x4BBE,0x4CBE,0xEBF4,0x4DBE,0x4EBE,0x4FBE,0x50BE,0x51BE,0x52BE,0x53BE,0xECF4,0x54BE,0x55BE,0x56BE,0x57BE,0x58BE,0x59BE,0x5ABE,0x5BBE,0x5CBE,0x5DBE,0x5EBE,0x5FBE,0x60BE,0x61BE,0x62BE,0x63BE,0x64BE,0x65BE,0x66BE,0x67BE,0x68BE,0x69BE,0x6ABE,0x6BBE,0x6CBE,0x6DBE,0x6EBE,0x6FBE,0x70BE,0x71BE,0x72BE,0x73BE,0x74BE,0x75BE,0x76BE,0x77BE,0x78BE,0x79BE,0x7ABE,0x7BBE,0x7CBE,0x7DBE,0x7EBE,0x80BE,0x81BE,0x82BE,0x83BE,0x84BE,0x85BE,0x86BE,0x87BE,0x88BE,0x89BE,0x8ABE,0x8BBE,0x8CBE,0x8DBE,0x8EBE,0x8FBE,0x90BE,0x91BE,0x92BE,0x93BE,0x94BE,0x95BE,0x96BE,0x97BE,0x98BE,0x99BE,0x9ABE,0x9BBE,0x9CBE,0x9DBE,0x9EBE,0x9FBE,0xA0BE,0x40BF,0x41BF,0x42BF,0x43BF,0x44BF,0x45BF,0x46BF,0x47BF,0x48BF,0x49BF,0x4ABF,0x4BBF,0x4CBF,0x4DBF,0x4EBF,0x4FBF,0x50BF,0x51BF,0x52BF,0x53BF,0x54BF,0x55BF,0x56BF,0x57BF,0x58BF,0x59BF,0x5ABF,0x5BBF,0x5CBF,0x5DBF,0x5EBF,0x5FBF,0x60BF,0x61BF,0x62BF,0x63BF,0x64BF,0x65BF,0x66BF,0x67BF,0x68BF,0x69BF,0x6ABF,0x6BBF,0x6CBF,0x6DBF,0x6EBF,0x6FBF,0x70BF,0x71BF,0x72BF,0x73BF,0x74BF,0x75BF,0x76BF,0x77BF,0x78BF,0x79BF,0x7ABF,0x7BBF,0x7CBF,0x7DBF,0x7EBF,0x80BF,0xE3F7,0x81BF,0x82BF,0x83BF,0x84BF,0x85BF,0xB1B7,0x86BF,0x87BF,0x88BF,0x89BF,0x8ABF,0xEDF4,0x8BBF,0x8CBF,0x8DBF,0x8EBF,0x8FBF,0x90BF,0x91BF,0x92BF,0x93BF,0x94BF,0x95BF,0x96BF,0x97BF,0x98BF,0x99BF,0x9ABF,0x9BBF,0x9CBF,0x9DBF,0x9EBF,0x9FBF,0xA0BF,0x40C0,0x41C0,0x42C0,0x43C0,0x44C0,0x45C0,0x46C0,0x47C0,0x48C0,0x49C0,0x4AC0,0x4BC0,0x4CC0,0x4DC0,0x4EC0,0x4FC0,0x50C0,0x51C0,0x52C0,0x53C0,0x54C0,0x55C0,0x56C0,0x57C0,0x58C0,0x59C0,0x5AC0,0x5BC0,0x5CC0,0x5DC0,0x5EC0,0x5FC0,0x60C0,0x61C0,0x62C0,0x63C0,0xEBD7,0x64C0,0x65C0,0x66C0,0x67C0,0x68C0,0x69C0,0x6AC0,0x6BC0,0x6CC0,0x6DC0,0x6EC0,0x6FC0,0x70C0,0x71C0,0x72C0,0x73C0,0x74C0,0x75C0,0x76C0,0x77C0,0x78C0,0x79C0,0x7AC0,0x7BC0,0xEEF4,0x7CC0,0x7DC0,0x7EC0,0xF9E6,0xC0BE,0xFAE6,0xECBA,0xFBE6,0xCBCF,0xFCE6,0xBCD4,0xB6BC,0xFDE6,0xFEE6,0xCDBC,0xD2C8,0xB3CE,0xA1E7,0x80C0,0xBFB4,0xA2E7,0xB4C9,0xD9B8,0xC9C4,0x81C0,0xDDD7,0xDAC2,0xD7B7,0xBDD6,0xC6CE,0xC4B7,0x82C0,0x83C0,0xA6C5,0xA3E7,0xDFCF,0xA4E7,0xA5E7,0xA6E7,0xB7C1,0xE9D7,0xF0C9,0xB8CF,0xAFD6,0xD5D6,0xA7E7,0xEDB0,0xA8E7,0xA9E7,0xDCC9,0xEFD2,0xADBE,0xAAE7,0xF3B0,0xDEC8,0xE1BD,0xABE7,0xC6C8,0x84C0,0xACE7,0xE6BB,0xF8B8,0xA4D1,0xADE7,0xE7C2,0xF8BE,0xCABD,0xB3CD,0xAEE7,0xAFE7,0xEEBE,0xE5D0,0x85C0,0xE7CB,0xD0CC,0xCCBC,0xB0E7,0xA8BC,0xF7D0,0xB1E7,0x86C0,0xF8D0,0xB2E7,0xB3E7,0xC2B4,0xB4E7,0xB5E7,0xFEC9,0xACCE,0xE0C3,0xB7E7,0xC1B1,0xF1B3,0x87C0,0xB8E7,0xB9E7,0xDBD7,0xC0D5,0xBAE7,0xCCC2,0xBAD7,0xBBE7,0xBCE7,0xBDE7,0xEABC,0xE5C3,0xC2C0,0xBEE7,0xBFE7,0xA9BC,0x88C0,0xC0E7,0xC1E7,0xB6E7,0xD0B6,0xC2E7,0x89C0,0xC3E7,0xC4E7,0xBABB,0xDEB5,0xC6C2,0xE0B1,0xC5E7,0xB5D4,0xC6E7,0xBFB8,0xC8E7,0xC7E7,0xECB7,0x8AC0,0xC9E7,0xF8B2,0xCAE7,0xCBE7,0xCCE7,0xCDE7,0xCEE7,0xCFE7,0xD0E7,0xA7D3,0xF5CB,0xD1E7,0xD2E7,0xD3E7,0xD4E7,0xC9C9,0xD5E7,0xD6E7,0xD7E7,0xD8E7,0xD9E7,0xC9BD,0xDAE7,0xBEF3,0x8BC0,0xD7B8,0x8CC0,0xB1C8,0x8DC0,0x8EC0,0x8FC0,0x90C0,0x91C0,0x92C0,0x93C0,0xBFF3,0x94C0,0xC0F3,0xC1F3,0x95C0,0x96C0,0x97C0,0x98C0,0x99C0,0x9AC0,0x9BC0,0x9CC0,0x9DC0,0x9EC0,0xDEB9,0xF8CD,0x9FC0,0xA0C0,0xE8D8,0xB1BA,0x40C1,0xDEC2,0xB7EE,0x41C1,0xA3B7,0x42C1,0x43C1,0x44C1,0x45C1,0xB9EE,0x46C1,0xB8EE,0xD5B0,0x47C1,0x48C1,0x49C1,0x4AC1,0x4BC1,0xBBEE,0xD6D5,0xEFD7,0x4CC1,0x4DC1,0x4EC1,0xC3D6,0x4FC1,0x50C1,0xBDEE,0xF0CA,0x51C1,0xBCEE,0x52C1,0x53C1,0x54C1,0x55C1,0xBEEE,0x56C1,0x57C1,0x58C1,0x59C1,0xC0EE,0x5AC1,0x5BC1,0xBFEE,0x5CC1,0x5DC1,0x5EC1,0x5FC1,0x60C1,0x61C1,0x62C1,0x63C1,0xF2D1,0x64C1,0xBCC7,0x65C1,0xC0C3,0x66C1,0x67C1,0x68C1,0x69C1,0x6AC1,0xE1B8,0x6BC1,0x6CC1,0x6DC1,0x6EC1,0x6FC1,0xE7C1,0x70C1,0x71C1,0xC6F4,0xDFD0,0xC7F4,0x72C1,0xDBCF,0x73C1,0x74C1,0xBAC8,0x75C1,0x76C1,0xC8F4,0x77C1,0x78C1,0x79C1,0x7AC1,0x7BC1,0x7CC1,0x7DC1,0xC9F4,0xCAF4,0x7EC1,0xCBF4,0x80C1,0x81C1,0x82C1,0x83C1,0x84C1,0xFAD9,0xFEB8,0x85C1,0x86C1,0xF1E5,0xF0D3,0x87C1,0xE0F4,0x88C1,0xCCCE,0x89C1,0x8AC1,0x8BC1,0xE1B3,0x8CC1,0x8DC1,0x8EC1,0x8FC1,0xB4F1,0x90C1,0xEED2,0x91C1,0xE1F4,0x92C1,0x93C1,0x94C1,0x95C1,0x96C1,0xE8CF,0xE2F4,0x97C1,0x98C1,0xCCC7,0x99C1,0x9AC1,0x9BC1,0x9CC1,0x9DC1,0x9EC1,0xD4B5,0xE4B4,0xE4F4,0x9FC1,0xA0C1,0x40C2,0xE3F4,0xE5F4,0x41C2,0x42C2,0xE6F4,0x43C2,0x44C2,0x45C2,0x46C2,0xE7F4,0x47C2,0xB2BA,0xBFB0,0x48C2,0xE8F4,0x49C2,0x4AC2,0x4BC2,0x4CC2,0x4DC2,0x4EC2,0x4FC2,0xADB7,0xEDD2,0x50C2,0x51C2,0x52C2,0xABD2,0xCFC0,0x53C2,0xBCBF,0xA3EB,0xDFD5,0xC8EA,0x54C2,0x55C2,0x56C2,0x57C2,0xF3F1,0xF8B6,0xA3CB,0x58C2,0x59C2,0xCDC4,0x5AC2,0xE7F1,0x5BC2,0xE8F1,0xFBB8,0xE9F1,0xC4BA,0xC5D4,0xD2B0,0x5CC2,0x5DC2,0xEAF1,0x5EC2,0x5FC2,0x60C2,0xEBF1,0x61C2,0xECF1,0x62C2,0x63C2,0xEDF1,0xEEF1,0xEFF1,0xF1F1,0xF0F1,0xD5C5,0x64C2,0x65C2,0x66C2,0x67C2,0x68C2,0x69C2,0xF2F1,0x6AC2,0xFAB6,0x6BC2,0xF4F1,0xAED2,0xC7DE,0xCACB,0x6CC2,0x6DC2,0xDCB3,0x6EC2,0xA2B5,0x6FC2,0xA2B9,0x70C2,0x71C2,0xF4C4,0xF5F1,0x72C2,0x73C2,0xF6F1,0x74C2,0x75C2,0x76C2,0xC4C1,0xFBC1,0xB0D6,0xF7F1,0x77C2,0x78C2,0x79C2,0x7AC2,0xF8F1,0x7BC2,0xAAC1,0x7CC2,0x7DC2,0x7EC2,0xB8C6,0x80C2,0xDBBE,0x81C2,0x82C2,0x83C2,0x84C2,0x85C2,0x86C2,0x87C2,0x88C2,0x89C2,0x8AC2,0x8BC2,0x8CC2,0x8DC2,0x8EC2,0xF9F1,0xCFB4,0x8FC2,0x90C2,0x91C2,0x92C2,0x93C2,0x94C2,0xFAF1,0x95C2,0x96C2,0x97C2,0x98C2,0x99C2,0x9AC2,0x9BC2,0x9CC2,0x9DC2,0x9EC2,0x9FC2,0xA0C2,0x40C3,0xB2ED,0xB1ED,0x41C3,0x42C3,0xE0CB,0xDED2,0x43C3,0xC1CB,0xD8D5,0x44C3,0xE2C8,0x45C3,0xDFC0,0xA1BC,0x46C3,0x47C3,0x48C3,0x49C3,0x4AC3,0x4BC3,0xC1EB,0x4CC3,0x4DC3,0xA4D0,0x4EC3,0xE2D6,0x4FC3,0xC7B6,0xD8B8,0xC0EB,0xCEB8,0x50C3,0xBFEB,0xA6B3,0xC9B9,0xABD6,0x51C3,0xF4B7,0xCAB7,0x52C3,0x53C3,0x54C3,0xE7BC,0xBEB7,0xC6EB,0x55C3,0xC7EB,0xB9B0,0xCFBF,0x56C3,0xC5EB,0xFDD3,0x57C3,0xC8EB,0x58C3,0x59C3,0xC9EB,0x5AC3,0x5BC3,0xCEB7,0x5CC3,0xC2EB,0xC4EB,0xF6C9,0xD7D6,0xCDD5,0xB2D0,0xCFEB,0xB8CE,0xD0EB,0x5DC3,0xA8B5,0x5EC3,0x5FC3,0x60C3,0x61C3,0x62C3,0xB3B1,0xD2EB,0xA5CC,0x63C3,0x64C3,0x65C3,0x66C3,0x67C3,0x68C3,0x69C3,0xD6C5,0xD3EB,0x6AC3,0xD1EB,0xDFC5,0xCEEB,0xA4CA,0xD5EB,0xFBB0,0x6BC3,0x6CC3,0xFABA,0x6DC3,0x6EC3,0xB7D8,0xE3F1,0x6FC3,0xCAEB,0xCBEB,0xCCEB,0xCDEB,0xD6EB,0xC0E6,0xD9EB,0x70C3,0xE8BF,0xC8D2,0xD7EB,0xDCEB,0xECB8,0xD8EB,0x71C3,0xBABD,0x72C3,0xD8D0,0x73C3,0xB7B0,0x74C3,0xDDEB,0xDCC4,0x75C3,0x76C3,0x77C3,0x78C3,0xACD6,0x79C3,0x7AC3,0x7BC3,0xE0B4,0x7CC3,0x7DC3,0xF6C2,0xB9BC,0x7EC3,0x80C3,0xDAEB,0xDBEB,0xE0D4,0xEAC6,0xD4C4,0xDFEB,0xA7C5,0xF5D9,0x81C3,0xB1B2,0x82C3,0xE4EB,0x83C3,0xC5BD,0x84C3,0x85C3,0x86C3,0xE2EB,0x87C3,0x88C3,0x89C3,0x8AC3,0x8BC3,0x8CC3,0x8DC3,0x8EC3,0x8FC3,0x90C3,0x91C3,0x92C3,0x93C3,0xE3EB,0x94C3,0x95C3,0xACB8,0x96C3,0xD1CD,0xE5EB,0x97C3,0x98C3,0x99C3,0xE1EB,0x9AC3,0xB3C1,0x9BC3,0x9CC3,0x9DC3,0x9EC3,0x9FC3,0xA2C6,0xA0C3,0x40C4,0x41C4,0x42C4,0x43C4,0x44C4,0x45C4,0xF3CC,0x46C4,0xE6EB,0x47C4,0xB0C0,0xB8D2,0xE7EB,0x48C4,0x49C4,0x4AC4,0xAFB8,0xADB8,0x4BC4,0xE8EB,0xBBC7,0xF3CD,0x4CC4,0x4DC4,0x4EC4,0xEAEB,0xEBEB,0x4FC4,0x50C4,0x51C4,0x52C4,0x53C4,0xEDEB,0x54C4,0x55C4,0x56C4,0x57C4,0xC8D0,0x58C4,0xF2EB,0x59C4,0xEEEB,0x5AC4,0x5BC4,0x5CC4,0xF1EB,0xF9C8,0x5DC4,0xFCD1,0xECEB,0x5EC4,0x5FC4,0xE9EB,0x60C4,0x61C4,0x62C4,0x63C4,0xB9B8,0xD9CF,0xE5C4,0xEFEB,0xF0EB,0xDACC,0xC8CD,0xF2B0,0x64C4,0xF6EB,0x65C4,0x66C4,0x67C4,0x68C4,0x69C4,0xF5EB,0x6AC4,0xB2B2,0x6BC4,0x6CC4,0x6DC4,0x6EC4,0xE0B8,0x6FC4,0xF7EB,0x70C4,0x71C4,0x72C4,0x73C4,0x74C4,0x75C4,0xECB1,0x76C4,0x77C4,0xC5CC,0xA4C4,0xA5CF,0x78C4,0x79C4,0x7AC4,0x7BC4,0x7CC4,0xF9EB,0x7DC4,0x7EC4,0xA2EC,0x80C4,0xF2C5,0x81C4,0xFAEB,0x82C4,0x83C4,0x84C4,0x85C4,0x86C4,0x87C4,0x88C4,0x89C4,0xC5C9,0x8AC4,0x8BC4,0x8CC4,0x8DC4,0x8EC4,0x8FC4,0xDFE2,0xFEEB,0x90C4,0x91C4,0x92C4,0x93C4,0xCECD,0xA1EC,0xDBB1,0xB7D3,0x94C4,0x95C4,0xDCD2,0x96C4,0x97C4,0x98C4,0xFDEB,0x99C4,0xFBEB,0x9AC4,0x9BC4,0x9CC4,0x9DC4,0x9EC4,0x9FC4,0xA0C4,0x40C5,0x41C5,0x42C5,0x43C5,0x44C5,0x45C5,0x46C5,0x47C5,0x48C5,0x49C5,0x4AC5,0x4BC5,0x4CC5,0x4DC5,0x4EC5,0xBCB3,0x4FC5,0x50C5,0x51C5,0xB0EA,0x52C5,0x53C5,0xD4D7,0x54C5,0xABF4,0xF4B3,0x55C5,0x56C5,0x57C5,0x58C5,0x59C5,0xC1D6,0xC2D6,0x5AC5,0x5BC5,0x5CC5,0x5DC5,0x5EC5,0x5FC5,0xE9D5,0xCABE,0x60C5,0xA7F4,0x61C5,0xA8D2,0xA8F4,0xA9F4,0x62C5,0xAAF4,0xCBBE,0xDFD3,0x63C5,0x64C5,0x65C5,0x66C5,0x67C5,0xE0C9,0xE1C9,0x68C5,0x69C5,0xC2F3,0x6AC5,0xE6CA,0x6BC5,0xF2CC,0x6CC5,0x6DC5,0x6EC5,0x6FC5,0x70C5,0x71C5,0xB6E2,0xB4CB,0x72C5,0xE8CE,0xDBD6,0x73C5,0xADF4,0xAEF4,0xAFF4,0x74C5,0x75C5,0x76C5,0x77C5,0xB2F4,0x78C5,0xBDBA,0xB3F4,0xE3B0,0xB0F4,0x79C5,0xB1F4,0xA2BD,0xD5B2,0x7AC5,0xB6F4,0xB7F4,0xE6B6,0xB0B2,0xCFCF,0xB4F4,0xACB4,0x7BC5,0xB5F4,0x7CC5,0x7DC5,0xB8F4,0x7EC5,0x80C5,0x81C5,0x82C5,0x83C5,0xB9F4,0x84C5,0x85C5,0xA7CD,0x86C5,0xBAF4,0x87C5,0xBBF4,0x88C5,0x89C5,0x8AC5,0xBCF4,0x8BC5,0x8CC5,0x8DC5,0x8EC5,0x8FC5,0x90C5,0x91C5,0x92C5,0xD2CB,0x93C5,0xBDF4,0x94C5,0x95C5,0x96C5,0x97C5,0xBEF4,0x98C5,0x99C5,0x9AC5,0x9BC5,0x9CC5,0x9DC5,0x9EC5,0x9FC5,0xBFF4,0xA0C5,0x40C6,0x41C6,0x42C6,0x43C6,0xDEF4,0xBCC1,0xE8BC,0x44C6,0xABC9,0xDED1,0xF5E5,0x45C6,0x46C6,0x47C6,0x48C6,0xB3DC,0xD5D2,0x49C6,0x4AC6,0xB4DC,0xACB0,0xB5DC,0x4BC6,0x4CC6,0xDABD,0x4DC6,0xB9DC,0x4EC6,0x4FC6,0x50C6,0xC2D8,0x51C6,0xB7DC,0xF3D3,0x52C6,0xD6C9,0xBADC,0xB6DC,0x53C6,0xBBDC,0xA2C3,0x54C6,0x55C6,0x56C6,0x57C6,0xBCDC,0xC5DC,0xBDDC,0x58C6,0x59C6,0xDFCE,0xA5D6,0x5AC6,0xCFDC,0x5BC6,0xCDDC,0x5CC6,0x5DC6,0xD2DC,0xE6BD,0xABC2,0x5EC6,0xB8DC,0xCBDC,0xCEDC,0xBEDC,0xD2B7,0xC5B0,0xC7DC,0xBED0,0xC1DC,0xA8BB,0x5FC6,0xBCB7,0xCCDC,0x60C6,0x61C6,0xC6DC,0xBFDC,0xDBC7,0x62C6,0x63C6,0x64C6,0xBFD1,0xC0DC,0x65C6,0x66C6,0xCADC,0x67C6,0x68C6,0xD0DC,0x69C6,0x6AC6,0xADCE,0xC2DC,0x6BC6,0xC3DC,0xC8DC,0xC9DC,0xD4B2,0xD1DC,0xD5CB,0x6CC6,0xB7D4,0xDBDC,0xDFDC,0xA6CC,0xE6DC,0x6DC6,0xE7C3,0xDCDC,0x6EC6,0x6FC6,0xC1BF,0xD9DC,0x70C6,0xFAB0,0xB6B9,0xE5DC,0xD3DC,0x71C6,0xC4DC,0xD6DC,0xF4C8,0xE0BF,0x72C6,0x73C6,0x74C6,0x75C6,0xBBC9,0x76C6,0x77C6,0x78C6,0xBDB1,0x79C6,0xA2D3,0x7AC6,0x7BC6,0xDADC,0x7CC6,0x7DC6,0xD5DC,0x7EC6,0xBBC6,0x80C6,0xDEDC,0x81C6,0x82C6,0x83C6,0x84C6,0x85C6,0xC2D7,0xAFC3,0xB6B7,0xD1C7,0xA9C3,0xE2DC,0xD8DC,0xEBDC,0xD4DC,0x86C6,0x87C6,0xDDDC,0x88C6,0xA5BE,0xD7DC,0x89C6,0xE0DC,0x8AC6,0x8BC6,0xE3DC,0xE4DC,0x8CC6,0xF8DC,0x8DC6,0x8EC6,0xE1DC,0xA2DD,0xE7DC,0x8FC6,0x90C6,0x91C6,0x92C6,0x93C6,0x94C6,0x95C6,0x96C6,0x97C6,0x98C6,0xEBBC,0xC4B4,0x99C6,0x9AC6,0xA3C3,0xE7B2,0xFADC,0x9BC6,0xF2DC,0x9CC6,0xEFDC,0x9DC6,0xFCDC,0xEEDC,0xF0D2,0xE8B2,0x9EC6,0xD7C8,0xE3C8,0xFBDC,0x9FC6,0xEDDC,0xA0C6,0x40C7,0x41C7,0xF7DC,0x42C7,0x43C7,0xF5DC,0x44C7,0x45C7,0xA3BE,0xF4DC,0x46C7,0xDDB2,0x47C7,0x48C7,0x49C7,0x4AC7,0x4BC7,0xF3DC,0xF6BC,0xE8DC,0xC4BB,0x4CC7,0xF3C0,0x4DC7,0x4EC7,0x4FC7,0x50C7,0x51C7,0xD4BC,0xE9DC,0xEADC,0x52C7,0xF1DC,0xF6DC,0xF9DC,0xB4B5,0x53C7,0xD9C8,0xE7BB,0xFEDC,0xFDDC,0xABD3,0xA1DD,0xA3DD,0xA5DD,0xF1D2,0xA4DD,0xA6DD,0xA7DD,0xA9D2,0x54C7,0x55C7,0x56C7,0x57C7,0x58C7,0x59C7,0x5AC7,0xC9BA,0xA9DD,0x5BC7,0x5CC7,0xB6DD,0xB1DD,0xB4DD,0x5DC7,0x5EC7,0x5FC7,0x60C7,0x61C7,0x62C7,0x63C7,0xB0DD,0xCEC6,0x64C7,0x65C7,0xF2C0,0x66C7,0x67C7,0x68C7,0x69C7,0xAFC9,0x6AC7,0x6BC7,0x6CC7,0xECDC,0xAEDD,0x6DC7,0x6EC7,0x6FC7,0x70C7,0xB7DD,0x71C7,0x72C7,0xF0DC,0xAFDD,0x73C7,0xB8DD,0x74C7,0xACDD,0x75C7,0x76C7,0x77C7,0x78C7,0x79C7,0x7AC7,0x7BC7,0xB9DD,0xB3DD,0xADDD,0xAAC4,0x7CC7,0x7DC7,0x7EC7,0x80C7,0xA8DD,0xB3C0,0xABC1,0xAADD,0xABDD,0x81C7,0xB2DD,0xF1BB,0xB5DD,0xA8D3,0xBADD,0x82C7,0xBBDD,0xA7C3,0x83C7,0x84C7,0xD2DD,0xBCDD,0x85C7,0x86C7,0x87C7,0xD1DD,0x88C7,0xBDB9,0x89C7,0x8AC7,0xD5BE,0x8BC7,0xFABE,0x8CC7,0x8DC7,0xCABA,0x8EC7,0x8FC7,0x90C7,0x91C7,0xCADD,0x92C7,0xC5DD,0x93C7,0xBFDD,0x94C7,0x95C7,0x96C7,0xCBB2,0xC3DD,0x97C7,0xCBDD,0xA4B2,0xD5DD,0x98C7,0x99C7,0x9AC7,0xBEDD,0x9BC7,0x9CC7,0x9DC7,0xD0C6,0xD0DD,0x9EC7,0x9FC7,0xA0C7,0x40C8,0x41C8,0xD4DD,0xE2C1,0xC6B7,0x42C8,0x43C8,0x44C8,0x45C8,0x46C8,0xCEDD,0xCFDD,0x47C8,0x48C8,0x49C8,0xC4DD,0x4AC8,0x4BC8,0x4CC8,0xBDDD,0x4DC8,0xCDDD,0xD1CC,0x4EC8,0xC9DD,0x4FC8,0x50C8,0x51C8,0x52C8,0xC2DD,0xC8C3,0xBCC6,0xAECE,0xCCDD,0x53C8,0xC8DD,0x54C8,0x55C8,0x56C8,0x57C8,0x58C8,0x59C8,0xC1DD,0x5AC8,0x5BC8,0x5CC8,0xC6DD,0xDCC2,0x5DC8,0x5EC8,0x5FC8,0x60C8,0x61C8,0x62C8,0xA9D3,0xAAD3,0xD3DD,0xF4CF,0xF8C8,0x63C8,0x64C8,0x65C8,0x66C8,0x67C8,0x68C8,0x69C8,0x6AC8,0xE6DD,0x6BC8,0x6CC8,0x6DC8,0x6EC8,0x6FC8,0x70C8,0xC7DD,0x71C8,0x72C8,0x73C8,0xE0DD,0xE4C2,0x74C8,0x75C8,0x76C8,0x77C8,0x78C8,0x79C8,0x7AC8,0x7BC8,0xE1DD,0x7CC8,0x7DC8,0x7EC8,0x80C8,0x81C8,0x82C8,0x83C8,0x84C8,0x85C8,0x86C8,0xD7DD,0x87C8,0x88C8,0x89C8,0x8AC8,0x8BC8,0xF8D6,0x8CC8,0xD9DD,0xD8DD,0xF0B8,0xD6DD,0x8DC8,0x8EC8,0x8FC8,0x90C8,0xCFC6,0x91C8,0xADB6,0x92C8,0x93C8,0x94C8,0x95C8,0x96C8,0xE2DD,0x97C8,0xF9BA,0xE1D4,0xE7DD,0x98C8,0x99C8,0x9AC8,0xD0B4,0x9BC8,0xDADD,0x9CC8,0xFBBF,0xE3DD,0x9DC8,0xDFDD,0x9EC8,0xDDDD,0x9FC8,0xA0C8,0x40C9,0x41C9,0x42C9,0x43C9,0x44C9,0xD9B5,0x45C9,0x46C9,0x47C9,0x48C9,0xDBDD,0xDCDD,0xDEDD,0x49C9,0xAFBD,0xE4DD,0x4AC9,0xE5DD,0x4BC9,0x4CC9,0x4DC9,0x4EC9,0x4FC9,0x50C9,0x51C9,0x52C9,0xF5DD,0x53C9,0xC9C3,0x54C9,0x55C9,0xE2CB,0x56C9,0x57C9,0x58C9,0x59C9,0xF2DD,0x5AC9,0x5BC9,0x5CC9,0x5DC9,0x5EC9,0x5FC9,0x60C9,0x61C9,0x62C9,0x63C9,0x64C9,0x65C9,0x66C9,0xE1D8,0x67C9,0x68C9,0xD1C6,0x69C9,0xF4DD,0x6AC9,0x6BC9,0x6CC9,0xF4D5,0xF3DD,0xF0DD,0x6DC9,0x6EC9,0xECDD,0x6FC9,0xEFDD,0x70C9,0xE8DD,0x71C9,0x72C9,0xEED0,0x73C9,0x74C9,0x75C9,0x76C9,0xD8C8,0xEEDD,0x77C9,0x78C9,0xE9DD,0x79C9,0x7AC9,0xEADD,0xF2CB,0x7BC9,0xEDDD,0x7CC9,0x7DC9,0xCDB1,0x7EC9,0x80C9,0x81C9,0x82C9,0x83C9,0x84C9,0xB6C0,0x85C9,0xBBBC,0xF1DD,0x86C9,0x87C9,0xF7DD,0x88C9,0xF6DD,0xEBDD,0x89C9,0x8AC9,0x8BC9,0x8CC9,0x8DC9,0xEEC5,0x8EC9,0x8FC9,0x90C9,0xFBDD,0x91C9,0x92C9,0x93C9,0x94C9,0x95C9,0x96C9,0x97C9,0x98C9,0x99C9,0x9AC9,0x9BC9,0xA4DE,0x9CC9,0x9DC9,0xA3DE,0x9EC9,0x9FC9,0xA0C9,0x40CA,0x41CA,0x42CA,0x43CA,0x44CA,0x45CA,0x46CA,0x47CA,0x48CA,0xF8DD,0x49CA,0x4ACA,0x4BCA,0x4CCA,0xEFC3,0x4DCA,0xFBC2,0x4ECA,0x4FCA,0x50CA,0xE1D5,0x51CA,0x52CA,0xB5CE,0x53CA,0x54CA,0x55CA,0x56CA,0xFDDD,0x57CA,0xCCB2,0x58CA,0x59CA,0x5ACA,0x5BCA,0x5CCA,0x5DCA,0x5ECA,0x5FCA,0x60CA,0xE8C4,0xDFCA,0x61CA,0x62CA,0x63CA,0x64CA,0x65CA,0x66CA,0x67CA,0x68CA,0x69CA,0x6ACA,0xBEC7,0xFADD,0xFCDD,0xFEDD,0xA2DE,0xAAB0,0xCEB1,0x6BCA,0x6CCA,0x6DCA,0x6ECA,0x6FCA,0xACDE,0x70CA,0x71CA,0x72CA,0x73CA,0xA6DE,0xB6BD,0xEFC8,0x74CA,0x75CA,0x76CA,0x77CA,0x78CA,0x79CA,0x7ACA,0x7BCA,0x7CCA,0x7DCA,0x7ECA,0xA1DE,0x80CA,0x81CA,0xA5DE,0x82CA,0x83CA,0x84CA,0x85CA,0xA9DE,0x86CA,0x87CA,0x88CA,0x89CA,0x8ACA,0xA8DE,0x8BCA,0x8CCA,0x8DCA,0xA7DE,0x8ECA,0x8FCA,0x90CA,0x91CA,0x92CA,0x93CA,0x94CA,0x95CA,0x96CA,0xADDE,0x97CA,0xCCD4,0x98CA,0x99CA,0x9ACA,0x9BCA,0xB3DE,0xAADE,0xAEDE,0x9CCA,0x9DCA,0xD9C0,0x9ECA,0x9FCA,0xA0CA,0x40CB,0x41CB,0xA1B1,0xB6DE,0x42CB,0xB1DE,0x43CB,0x44CB,0x45CB,0x46CB,0x47CB,0x48CB,0x49CB,0xB2DE,0x4ACB,0x4BCB,0x4CCB,0x4DCB,0x4ECB,0x4FCB,0x50CB,0x51CB,0x52CB,0x53CB,0x54CB,0xA6D1,0xB5DE,0x55CB,0x56CB,0x57CB,0x58CB,0x59CB,0x5ACB,0x5BCB,0xAFDE,0x5CCB,0x5DCB,0x5ECB,0xB0DE,0x5FCB,0xBDD0,0x60CB,0x61CB,0x62CB,0xB4DE,0xEDCA,0xB9DE,0x63CB,0x64CB,0x65CB,0x66CB,0x67CB,0x68CB,0xB8DE,0x69CB,0xB7DE,0x6ACB,0x6BCB,0x6CCB,0x6DCB,0x6ECB,0x6FCB,0x70CB,0xBBDE,0x71CB,0x72CB,0x73CB,0x74CB,0x75CB,0x76CB,0x77CB,0xE5BD,0x78CB,0x79CB,0x7ACB,0x7BCB,0x7CCB,0xD8B2,0xEAC3,0x7DCB,0x7ECB,0xBADE,0x80CB,0xBAC5,0x81CB,0x82CB,0x83CB,0x84CB,0x85CB,0x86CB,0xBCDE,0x87CB,0x88CB,0x89CB,0x8ACB,0x8BCB,0x8CCB,0x8DCB,0xD9CC,0x8ECB,0x8FCB,0x90CB,0x91CB,0xAAB7,0x92CB,0x93CB,0x94CB,0x95CB,0x96CB,0x97CB,0x98CB,0x99CB,0x9ACB,0x9BCB,0x9CCB,0x9DCB,0x9ECB,0x9FCB,0xA0CB,0x40CC,0x41CC,0xE5D4,0x42CC,0x43CC,0x44CC,0xBDDE,0x45CC,0x46CC,0x47CC,0x48CC,0x49CC,0xBFDE,0x4ACC,0x4BCC,0x4CCC,0x4DCC,0x4ECC,0x4FCC,0x50CC,0x51CC,0x52CC,0x53CC,0x54CC,0xA2C4,0x55CC,0x56CC,0x57CC,0x58CC,0xC1DE,0x59CC,0x5ACC,0x5BCC,0x5CCC,0x5DCC,0x5ECC,0x5FCC,0x60CC,0x61CC,0x62CC,0x63CC,0x64CC,0x65CC,0x66CC,0x67CC,0x68CC,0xBEDE,0x69CC,0xC0DE,0x6ACC,0x6BCC,0x6CCC,0x6DCC,0x6ECC,0x6FCC,0x70CC,0x71CC,0x72CC,0x73CC,0x74CC,0x75CC,0x76CC,0x77CC,0xBAD5,0x78CC,0x79CC,0x7ACC,0xC2DE,0x7BCC,0x7CCC,0x7DCC,0x7ECC,0x80CC,0x81CC,0x82CC,0x83CC,0x84CC,0x85CC,0x86CC,0x87CC,0x88CC,0x89CC,0x8ACC,0x8BCC,0xAEF2,0xA2BB,0xB2C2,0xB0C5,0xC7C2,0x8CCC,0x8DCC,0xAFF2,0x8ECC,0x8FCC,0x90CC,0x91CC,0x92CC,0xE9D0,0x93CC,0x94CC,0x95CC,0xDDD3,0x96CC,0x97CC,0x98CC,0xBDEB,0x99CC,0x9ACC,0x9BCC,0x9CCC,0x9DCC,0x9ECC,0x9FCC,0xA0CC,0xE6B3,0xB0F2,0x40CD,0xB1F2,0x41CD,0x42CD,0xADCA,0x43CD,0x44CD,0x45CD,0x46CD,0x47CD,0x48CD,0x49CD,0xE7BA,0xB3F2,0xB5F2,0xB4F2,0xE4CB,0xBACF,0xB2F2,0xB4CA,0xCFD2,0xECC2,0x4ACD,0x4BCD,0x4CCD,0x4DCD,0x4ECD,0x4FCD,0x50CD,0xC3CE,0xB8F2,0xF6B0,0xB7F2,0x51CD,0x52CD,0x53CD,0x54CD,0x55CD,0xBEF2,0x56CD,0xCFB2,0x57CD,0x58CD,0x59CD,0x5ACD,0x5BCD,0x5CCD,0xC1D1,0xBAF2,0x5DCD,0x5ECD,0x5FCD,0x60CD,0x61CD,0xBCF2,0xE9D4,0x62CD,0x63CD,0xBBF2,0xB6F2,0xBFF2,0xBDF2,0x64CD,0xB9F2,0x65CD,0x66CD,0xC7F2,0xC4F2,0xC6F2,0x67CD,0x68CD,0xCAF2,0xC2F2,0xC0F2,0x69CD,0x6ACD,0x6BCD,0xC5F2,0x6CCD,0x6DCD,0x6ECD,0x6FCD,0x70CD,0xFBD6,0x71CD,0x72CD,0x73CD,0xC1F2,0x74CD,0xF9C7,0xDFC9,0x75CD,0xC8F2,0xC6B9,0xB0B5,0x76CD,0x77CD,0xC3F2,0xC9F2,0xD0F2,0xD6F2,0x78CD,0x79CD,0xD7BB,0x7ACD,0x7BCD,0x7CCD,0xD5F2,0xDCCD,0x7DCD,0xEBD6,0x7ECD,0x80CD,0xD2F2,0xD4F2,0x81CD,0x82CD,0x83CD,0x84CD,0xF2B8,0x85CD,0x86CD,0x87CD,0x88CD,0xCBF2,0x89CD,0x8ACD,0x8BCD,0xCEF2,0xF9C2,0x8CCD,0xDDD5,0xCCF2,0xCDF2,0xCFF2,0xD3F2,0x8DCD,0x8ECD,0x8FCD,0xD9F2,0xBCD3,0x90CD,0x91CD,0x92CD,0x93CD,0xEAB6,0x94CD,0xF1CA,0x95CD,0xE4B7,0xD7F2,0x96CD,0x97CD,0x98CD,0xD8F2,0xDAF2,0xDDF2,0xDBF2,0x99CD,0x9ACD,0xDCF2,0x9BCD,0x9CCD,0x9DCD,0x9ECD,0xD1D1,0xD1F2,0x9FCD,0xC9CD,0xA0CD,0xCFCE,0xA9D6,0x40CE,0xE3F2,0x41CE,0xDBC3,0x42CE,0xE0F2,0x43CE,0x44CE,0xAFC0,0xECF2,0xDEF2,0x45CE,0xE1F2,0x46CE,0x47CE,0x48CE,0xE8F2,0x49CE,0x4ACE,0x4BCE,0x4CCE,0xE2F2,0x4DCE,0x4ECE,0xE7F2,0x4FCE,0x50CE,0xE6F2,0x51CE,0x52CE,0xE9F2,0x53CE,0x54CE,0x55CE,0xDFF2,0x56CE,0x57CE,0xE4F2,0xEAF2,0x58CE,0x59CE,0x5ACE,0x5BCE,0x5CCE,0x5DCE,0x5ECE,0xACD3,0xE5F2,0xF5B2,0x5FCE,0x60CE,0xF2F2,0x61CE,0xABD0,0x62CE,0x63CE,0x64CE,0x65CE,0xF5F2,0x66CE,0x67CE,0x68CE,0xC8BB,0x69CE,0xF9F2,0x6ACE,0x6BCE,0x6CCE,0x6DCE,0x6ECE,0x6FCE,0xF0F2,0x70CE,0x71CE,0xF6F2,0xF8F2,0xFAF2,0x72CE,0x73CE,0x74CE,0x75CE,0x76CE,0x77CE,0x78CE,0x79CE,0xF3F2,0x7ACE,0xF1F2,0x7BCE,0x7CCE,0x7DCE,0xFBBA,0x7ECE,0xFBB5,0x80CE,0x81CE,0x82CE,0x83CE,0xEFF2,0xF7F2,0xEDF2,0xEEF2,0x84CE,0x85CE,0x86CE,0xEBF2,0xA6F3,0x87CE,0xA3F3,0x88CE,0x89CE,0xA2F3,0x8ACE,0x8BCE,0xF4F2,0x8CCE,0xDAC8,0x8DCE,0x8ECE,0x8FCE,0x90CE,0x91CE,0xFBF2,0x92CE,0x93CE,0x94CE,0xA5F3,0x95CE,0x96CE,0x97CE,0x98CE,0x99CE,0x9ACE,0x9BCE,0xF8C3,0x9CCE,0x9DCE,0x9ECE,0x9FCE,0xA0CE,0x40CF,0x41CF,0x42CF,0xFDF2,0x43CF,0x44CF,0xA7F3,0xA9F3,0xA4F3,0x45CF,0xFCF2,0x46CF,0x47CF,0x48CF,0xABF3,0x49CF,0xAAF3,0x4ACF,0x4BCF,0x4CCF,0x4DCF,0xDDC2,0x4ECF,0x4FCF,0xAEF3,0x50CF,0x51CF,0xB0F3,0x52CF,0x53CF,0x54CF,0x55CF,0x56CF,0xA1F3,0x57CF,0x58CF,0x59CF,0xB1F3,0xACF3,0x5ACF,0x5BCF,0x5CCF,0x5DCF,0x5ECF,0xAFF3,0xFEF2,0xADF3,0x5FCF,0x60CF,0x61CF,0x62CF,0x63CF,0x64CF,0x65CF,0xB2F3,0x66CF,0x67CF,0x68CF,0x69CF,0xB4F3,0x6ACF,0x6BCF,0x6CCF,0x6DCF,0xA8F3,0x6ECF,0x6FCF,0x70CF,0x71CF,0xB3F3,0x72CF,0x73CF,0x74CF,0xB5F3,0x75CF,0x76CF,0x77CF,0x78CF,0x79CF,0x7ACF,0x7BCF,0x7CCF,0x7DCF,0x7ECF,0xB7D0,0x80CF,0x81CF,0x82CF,0x83CF,0xB8F3,0x84CF,0x85CF,0x86CF,0x87CF,0xF9D9,0x88CF,0x89CF,0x8ACF,0x8BCF,0x8CCF,0x8DCF,0xB9F3,0x8ECF,0x8FCF,0x90CF,0x91CF,0x92CF,0x93CF,0x94CF,0x95CF,0xB7F3,0x96CF,0xE4C8,0xB6F3,0x97CF,0x98CF,0x99CF,0x9ACF,0xBAF3,0x9BCF,0x9CCF,0x9DCF,0x9ECF,0x9FCF,0xBBF3,0xC0B4,0xA0CF,0x40D0,0x41D0,0x42D0,0x43D0,0x44D0,0x45D0,0x46D0,0x47D0,0x48D0,0x49D0,0x4AD0,0x4BD0,0x4CD0,0x4DD0,0xC3EE,0x4ED0,0x4FD0,0x50D0,0x51D0,0x52D0,0x53D0,0xBCF3,0x54D0,0x55D0,0xBDF3,0x56D0,0x57D0,0x58D0,0xAAD1,0x59D0,0x5AD0,0x5BD0,0xACF4,0xC6D0,0x5CD0,0x5DD0,0x5ED0,0x5FD0,0x60D0,0x61D0,0xD0D0,0xDCD1,0x62D0,0x63D0,0x64D0,0x65D0,0x66D0,0x67D0,0xCECF,0x68D0,0x69D0,0xD6BD,0x6AD0,0xC3D1,0x6BD0,0x6CD0,0x6DD0,0x6ED0,0x6FD0,0x70D0,0x71D0,0xE2BA,0xE9E1,0xC2D2,0xC2F1,0xB9B2,0x72D0,0x73D0,0xEDB1,0xC3F1,0x74D0,0xC0C9,0xC4B3,0x75D0,0xF2D9,0x76D0,0xA5CB,0x77D0,0xC4F1,0x78D0,0x79D0,0x7AD0,0x7BD0,0xD4D6,0x7CD0,0x7DD0,0x7ED0,0x80D0,0x81D0,0xC5F1,0xC0F4,0xC6F1,0x82D0,0xACD4,0xC7F1,0x83D0,0xC0B0,0xC1F4,0x84D0,0x85D0,0xC2F4,0x86D0,0x87D0,0xFCB4,0x88D0,0xDBC5,0x89D0,0x8AD0,0x8BD0,0x8CD0,0xBBCC,0x8DD0,0x8ED0,0x8FD0,0xE4D0,0x90D0,0x91D0,0x92D0,0x93D0,0x94D0,0xE0CD,0x95D0,0x96D0,0x97D0,0x98D0,0x99D0,0xC8F1,0x9AD0,0xF3D9,0x9BD0,0x9CD0,0x9DD0,0x9ED0,0x9FD0,0xA0D0,0xBBB1,0x40D1,0xAECF,0x41D1,0x42D1,0x43D1,0xA4B8,0x44D1,0x45D1,0x46D1,0x47D1,0x48D1,0xCAF1,0x49D1,0x4AD1,0x4BD1,0x4CD1,0xCBF1,0x4DD1,0x4ED1,0x4FD1,0x50D1,0xC3B2,0xD1C1,0x51D1,0x52D1,0xB0D7,0xC9F1,0x53D1,0x54D1,0xCCF1,0x55D1,0x56D1,0x57D1,0x58D1,0xCEF1,0x59D1,0x5AD1,0x5BD1,0xF6D9,0x5CD1,0xE1D2,0xA3D4,0x5DD1,0x5ED1,0xC3F4,0xB9C8,0x5FD1,0x60D1,0x61D1,0x62D1,0x63D1,0xC4F4,0x64D1,0x65D1,0xCDF1,0xCFF1,0xE3BF,0xD0F1,0x66D1,0x67D1,0xD4F1,0x68D1,0x69D1,0x6AD1,0x6BD1,0x6CD1,0x6DD1,0x6ED1,0xD6F1,0xD1F1,0x6FD1,0xD1C9,0xE1C5,0x70D1,0x71D1,0x72D1,0xE3C2,0xFCB9,0x73D1,0x74D1,0xD3F1,0x75D1,0xD5F1,0x76D1,0x77D1,0x78D1,0xD3B9,0x79D1,0x7AD1,0x7BD1,0x7CD1,0x7DD1,0x7ED1,0x80D1,0xDBF1,0x81D1,0x82D1,0x83D1,0x84D1,0x85D1,0xD6BA,0x86D1,0xFDB0,0xD9F1,0x87D1,0x88D1,0x89D1,0x8AD1,0x8BD1,0xD8F1,0xD2F1,0xDAF1,0x8CD1,0x8DD1,0x8ED1,0x8FD1,0x90D1,0xD7F1,0x91D1,0x92D1,0x93D1,0xECC8,0x94D1,0x95D1,0x96D1,0x97D1,0xCACD,0xDDF1,0x98D1,0x99D1,0x9AD1,0x9BD1,0xBDE5,0x9CD1,0x9DD1,0x9ED1,0xDCF1,0x9FD1,0xDEF1,0xA0D1,0x40D2,0x41D2,0x42D2,0x43D2,0x44D2,0x45D2,0x46D2,0x47D2,0x48D2,0xDFF1,0x49D2,0x4AD2,0xE5CF,0x4BD2,0x4CD2,0x4DD2,0x4ED2,0x4FD2,0x50D2,0x51D2,0x52D2,0x53D2,0x54D2,0x55D2,0x56D2,0x57D2,0x58D2,0x59D2,0x5AD2,0x5BD2,0x5CD2,0x5DD2,0x5ED2,0x5FD2,0x60D2,0x61D2,0x62D2,0x63D2,0xC5F4,0xF3BD,0x64D2,0x65D2,0x66D2,0x67D2,0x68D2,0x69D2,0xE0F1,0x6AD2,0x6BD2,0x6CD2,0x6DD2,0x6ED2,0x6FD2,0x70D2,0x71D2,0x72D2,0x73D2,0x74D2,0x75D2,0x76D2,0x77D2,0x78D2,0x79D2,0x7AD2,0x7BD2,0x7CD2,0x7DD2,0xE1F1,0x7ED2,0x80D2,0x81D2,0xF7CE,0x82D2,0xAAD2,0x83D2,0xFBF1,0x84D2,0x85D2,0xB2B8,0x86D2,0x87D2,0x88D2,0x89D2,0x8AD2,0x8BD2,0x8CD2,0x8DD2,0x8ED2,0x8FD2,0x90D2,0x91D2,0x92D2,0x93D2,0x94D2,0x95D2,0x96D2,0x97D2,0x98D2,0x99D2,0x9AD2,0x9BD2,0x9CD2,0x9DD2,0x9ED2,0x9FD2,0xA0D2,0x40D3,0x41D3,0x42D3,0x43D3,0x44D3,0x45D3,0x46D3,0x47D3,0x48D3,0x49D3,0x4AD3,0x4BD3,0x4CD3,0x4DD3,0x4ED3,0x4FD3,0x50D3,0x51D3,0x52D3,0x53D3,0x54D3,0x55D3,0x56D3,0x57D3,0x58D3,0x59D3,0x5AD3,0x5BD3,0x5CD3,0x5DD3,0x5ED3,0xFBBC,0xDBB9,0x5FD3,0xE6B9,0xD9C3,0xD3CA,0xE8EA,0xC0C0,0xF5BE,0xE9EA,0xEAEA,0xEBEA,0x60D3,0xECEA,0xEDEA,0xEEEA,0xEFEA,0xC7BD,0x61D3,0x62D3,0x63D3,0xFBF5,0x64D3,0x65D3,0x66D3,0xFDF5,0x67D3,0xFEF5,0x68D3,0xFCF5,0x69D3,0x6AD3,0x6BD3,0x6CD3,0xE2BD,0x6DD3,0xA1F6,0xA5B4,0x6ED3,0x6FD3,0x70D3,0x71D3,0xA2F6,0x72D3,0x73D3,0x74D3,0xA3F6,0x75D3,0x76D3,0x77D3,0xB2EC,0x78D3,0x79D3,0x7AD3,0x7BD3,0x7CD3,0x7DD3,0x7ED3,0x80D3,0x81D3,0x82D3,0x83D3,0x84D3,0xD4D1,0x85D3,0x86D3,0x87D3,0x88D3,0x89D3,0x8AD3,0xEAD9,0x8BD3,0x8CD3,0x8DD3,0x8ED3,0x8FD3,0x90D3,0x91D3,0x92D3,0x93D3,0x94D3,0x95D3,0x96D3,0x97D3,0x98D3,0x99D3,0x9AD3,0x9BD3,0x9CD3,0x9DD3,0x9ED3,0x9FD3,0xA0D3,0x40D4,0x41D4,0x42D4,0x43D4,0x44D4,0x45D4,0x46D4,0x47D4,0x48D4,0x49D4,0x4AD4,0x4BD4,0x4CD4,0x4DD4,0x4ED4,0x4FD4,0x50D4,0x51D4,0x52D4,0x53D4,0x54D4,0x55D4,0x56D4,0x57D4,0x58D4,0x59D4,0x5AD4,0x5BD4,0x5CD4,0x5DD4,0x5ED4,0x5FD4,0xA4F6,0x60D4,0x61D4,0x62D4,0x63D4,0x64D4,0x65D4,0x66D4,0x67D4,0x68D4,0xBAEE,0x69D4,0x6AD4,0x6BD4,0x6CD4,0x6DD4,0x6ED4,0x6FD4,0x70D4,0x71D4,0x72D4,0x73D4,0x74D4,0x75D4,0x76D4,0x77D4,0x78D4,0x79D4,0x7AD4,0x7BD4,0x7CD4,0x7DD4,0x7ED4,0x80D4,0x81D4,0x82D4,0x83D4,0x84D4,0x85D4,0x86D4,0x87D4,0x88D4,0x89D4,0x8AD4,0x8BD4,0x8CD4,0x8DD4,0x8ED4,0x8FD4,0x90D4,0x91D4,0x92D4,0x93D4,0x94D4,0x95D4,0x96D4,0x97D4,0x98D4,0x99D4,0xB2D5,0x9AD4,0x9BD4,0x9CD4,0x9DD4,0x9ED4,0x9FD4,0xA0D4,0x40D5,0x41D5,0x42D5,0x43D5,0x44D5,0x45D5,0x46D5,0x47D5,0xFED3,0xDCCC,0x48D5,0x49D5,0x4AD5,0x4BD5,0x4CD5,0x4DD5,0x4ED5,0x4FD5,0xC4CA,0x50D5,0x51D5,0x52D5,0x53D5,0x54D5,0x55D5,0x56D5,0x57D5,0x58D5,0x59D5,0x5AD5,0x5BD5,0x5CD5,0x5DD5,0x5ED5,0x5FD5,0x60D5,0x61D5,0x62D5,0x63D5,0x64D5,0x65D5,0x66D5,0x67D5,0x68D5,0x69D5,0x6AD5,0x6BD5,0x6CD5,0x6DD5,0x6ED5,0x6FD5,0x70D5,0x71D5,0x72D5,0x73D5,0x74D5,0x75D5,0x76D5,0x77D5,0x78D5,0x79D5,0x7AD5,0x7BD5,0x7CD5,0x7DD5,0x7ED5,0x80D5,0x81D5,0x82D5,0x83D5,0x84D5,0x85D5,0x86D5,0x87D5,0x88D5,0x89D5,0x8AD5,0x8BD5,0x8CD5,0x8DD5,0x8ED5,0x8FD5,0x90D5,0x91D5,0x92D5,0x93D5,0x94D5,0x95D5,0x96D5,0x97D5,0x98D5,0x99D5,0x9AD5,0x9BD5,0x9CD5,0x9DD5,0x9ED5,0x9FD5,0xA0D5,0x40D6,0x41D6,0x42D6,0x43D6,0x44D6,0x45D6,0x46D6,0x47D6,0x48D6,0x49D6,0x4AD6,0x4BD6,0x4CD6,0x4DD6,0x4ED6,0x4FD6,0x50D6,0x51D6,0x52D6,0x53D6,0x54D6,0x55D6,0x56D6,0x57D6,0x58D6,0x59D6,0x5AD6,0x5BD6,0x5CD6,0x5DD6,0x5ED6,0x5FD6,0x60D6,0x61D6,0x62D6,0xC0E5,0x63D6,0x64D6,0x65D6,0x66D6,0x67D6,0x68D6,0x69D6,0x6AD6,0x6BD6,0x6CD6,0x6DD6,0x6ED6,0x6FD6,0x70D6,0x71D6,0x72D6,0x73D6,0x74D6,0x75D6,0x76D6,0x77D6,0x78D6,0x79D6,0x7AD6,0x7BD6,0x7CD6,0x7DD6,0x7ED6,0x80D6,0x81D6,0xA5F6,0x82D6,0x83D6,0x84D6,0x85D6,0x86D6,0x87D6,0x88D6,0x89D6,0x8AD6,0x8BD6,0x8CD6,0x8DD6,0x8ED6,0x8FD6,0x90D6,0x91D6,0x92D6,0x93D6,0x94D6,0x95D6,0x96D6,0x97D6,0x98D6,0x99D6,0x9AD6,0x9BD6,0x9CD6,0x9DD6,0x9ED6,0x9FD6,0xA0D6,0x40D7,0x41D7,0x42D7,0x43D7,0x44D7,0x45D7,0x46D7,0x47D7,0x48D7,0x49D7,0x4AD7,0x4BD7,0x4CD7,0x4DD7,0x4ED7,0x4FD7,0x50D7,0x51D7,0x52D7,0x53D7,0x54D7,0x55D7,0x56D7,0x57D7,0x58D7,0x59D7,0x5AD7,0x5BD7,0x5CD7,0x5DD7,0x5ED7,0x5FD7,0xAFBE,0x60D7,0x61D7,0x62D7,0x63D7,0x64D7,0xA9C6,0x65D7,0x66D7,0x67D7,0x68D7,0x69D7,0x6AD7,0x6BD7,0x6CD7,0x6DD7,0x6ED7,0x6FD7,0x70D7,0x71D7,0x72D7,0x73D7,0x74D7,0x75D7,0x76D7,0x77D7,0x78D7,0x79D7,0x7AD7,0x7BD7,0x7CD7,0x7DD7,0x7ED7,0x80D7,0x81D7,0x82D7,0x83D7,0x84D7,0x85D7,0x86D7,0x87D7,0x88D7,0x89D7,0x8AD7,0x8BD7,0x8CD7,0x8DD7,0x8ED7,0x8FD7,0x90D7,0x91D7,0x92D7,0x93D7,0x94D7,0x95D7,0x96D7,0x97D7,0x98D7,0xA5DA,0xC6BC,0xA9B6,0xBCB8,0xCFC8,0xA5BC,0xA6DA,0xA7DA,0xD6CC,0xC3C8,0xA8DA,0xFDC6,0x99D7,0xB5D1,0xE9D2,0xB6D1,0xC7BC,0x9AD7,0xB2BD,0xE4BB,0xA9DA,0xAADA,0xC8D1,0xABDA,0xEDD0,0xEFB6,0xDBC2,0x9BD7,0xCFCB,0xEDB7,0xE8C9,0xC3B7,0xF7BE,0xA4D6,0xACDA,0xADDA,0xC0C6,0xE7D7,0xB6CA,0x9CD7,0xA9D5,0xDFCB,0xEFD5,0xAEDA,0xDFD6,0xCAB4,0xB0DA,0xAFDA,0x9DD7,0xEBD2,0xB1DA,0xB2DA,0xB3DA,0xD4CA,0xB4DA,0xABCA,0xB5DA,0xB6DA,0xCFB3,0xEFD6,0xB7DA,0xB0BB,0xAEB5,0xB8DA,0xB9DA,0xEEB9,0xAFD1,0xE8D2,0xBADA,0xC3B8,0xEACF,0xEFB2,0xBBDA,0xBCDA,0x9ED7,0xEBBD,0xDCCE,0xEFD3,0xBDDA,0xF3CE,0xBEDA,0xD5D3,0xE5BB,0xBFDA,0xB5CB,0xD0CB,0xC0DA,0xEBC7,0xEED6,0xC1DA,0xB5C5,0xC1B6,0xC2DA,0xCCB7,0xCEBF,0xC3DA,0xC4DA,0xADCB,0xC5DA,0xF7B5,0xC6DA,0xC2C1,0xBBD7,0xC7DA,0xB8CC,0x9FD7,0xEAD2,0xB1C4,0xC8DA,0xFDB5,0xD1BB,0xC9DA,0xB3D0,0xCADA,0xCBDA,0xBDCE,0xCCDA,0xCDDA,0xCEDA,0xF7B2,0xD1DA,0xCFDA,0xE8D1,0xD0DA,0xD5C3,0xD2DA,0xA0D7,0xD3DA,0xD4DA,0xD5DA,0xBBD0,0xA5D2,0xF9B0,0xD6DA,0xABC7,0xD7DA,0xF7BD,0xA1C3,0xD8DA,0xD9DA,0xFDC3,0xB7CC,0xDADA,0xDBDA,0xBEC0,0xD7C6,0xDCDA,0xDDDA,0xB4C7,0xDEDA,0xDFDA,0xC8B9,0x40D8,0x41D8,0x42D8,0x43D8,0x44D8,0x45D8,0x46D8,0x47D8,0x48D8,0xEDBB,0x49D8,0x4AD8,0x4BD8,0x4CD8,0xB9B6,0xF8F4,0x4DD8,0xF9F4,0x4ED8,0x4FD8,0xE3CD,0x50D8,0x51D8,0x52D8,0x53D8,0x54D8,0x55D8,0x56D8,0x57D8,0xB9F5,0x58D8,0x59D8,0x5AD8,0x5BD8,0xE0EB,0x5CD8,0x5DD8,0x5ED8,0x5FD8,0x60D8,0x61D8,0xF3CF,0xBFBB,0x62D8,0x63D8,0x64D8,0x65D8,0x66D8,0x67D8,0x68D8,0xC0BA,0xA5D4,0x69D8,0x6AD8,0x6BD8,0x6CD8,0x6DD8,0x6ED8,0x6FD8,0xD9E1,0x70D8,0x71D8,0x72D8,0x73D8,0xF4F5,0xAAB1,0xF2B2,0x74D8,0x75D8,0x76D8,0x77D8,0x78D8,0x79D8,0x7AD8,0xF5F5,0x7BD8,0x7CD8,0xF7F5,0x7DD8,0x7ED8,0x80D8,0xD1BA,0xF6F5,0x81D8,0xB2C3,0x82D8,0x83D8,0x84D8,0x85D8,0x86D8,0x87D8,0x88D8,0xF9F5,0x89D8,0x8AD8,0x8BD8,0xF8F5,0x8CD8,0x8DD8,0x8ED8,0x8FD8,0x90D8,0x91D8,0x92D8,0x93D8,0x94D8,0x95D8,0x96D8,0x97D8,0x98D8,0x99D8,0x9AD8,0x9BD8,0x9CD8,0x9DD8,0x9ED8,0x9FD8,0xA0D8,0x40D9,0x41D9,0x42D9,0x43D9,0x44D9,0x45D9,0x46D9,0x47D9,0x48D9,0x49D9,0x4AD9,0x4BD9,0x4CD9,0x4DD9,0x4ED9,0x4FD9,0x50D9,0x51D9,0x52D9,0x53D9,0x54D9,0x55D9,0x56D9,0x57D9,0x58D9,0x59D9,0x5AD9,0x5BD9,0x5CD9,0x5DD9,0x5ED9,0x5FD9,0x60D9,0x61D9,0x62D9,0x63D9,0x64D9,0x65D9,0x66D9,0x67D9,0x68D9,0x69D9,0x6AD9,0x6BD9,0x6CD9,0x6DD9,0x6ED9,0x6FD9,0x70D9,0x71D9,0x72D9,0x73D9,0x74D9,0x75D9,0x76D9,0x77D9,0x78D9,0x79D9,0x7AD9,0x7BD9,0x7CD9,0x7DD9,0x7ED9,0x80D9,0x81D9,0x82D9,0x83D9,0x84D9,0x85D9,0x86D9,0x87D9,0x88D9,0x89D9,0x8AD9,0x8BD9,0x8CD9,0x8DD9,0x8ED9,0x8FD9,0x90D9,0x91D9,0x92D9,0x93D9,0x94D9,0x95D9,0x96D9,0x97D9,0x98D9,0x99D9,0x9AD9,0x9BD9,0x9CD9,0x9DD9,0x9ED9,0x9FD9,0xA0D9,0x40DA,0x41DA,0x42DA,0x43DA,0x44DA,0x45DA,0x46DA,0x47DA,0x48DA,0x49DA,0x4ADA,0x4BDA,0x4CDA,0x4DDA,0x4EDA,0xB4B1,0xEAD5,0xBAB8,0x4FDA,0xB1B9,0xC6B2,0xF0D4,0xCDCF,0xDCB0,0xCBD5,0xF5BB,0xCAD6,0xB7B7,0xB0CC,0xB6C6,0xE1B1,0xBAB9,0xFCD6,0xE1B9,0xA1B7,0xFABC,0xDAEA,0xDBEA,0xF9CC,0xF3B9,0xDCEA,0xFBB4,0xB3C3,0xD1B7,0xD8BA,0xDDEA,0xF4D4,0xDEEA,0xD6BC,0xDFBB,0xDFEA,0xDEC1,0xB8C2,0xDFD4,0xCAD7,0xE0EA,0xE1EA,0xE4EA,0xE2EA,0xE3EA,0xDEC9,0xB3B8,0xC4B6,0xE5EA,0xEACA,0xCDC9,0xCDB4,0x50DA,0x51DA,0xD9E2,0xE2C5,0xE6EA,0xB5C0,0x52DA,0xB8D7,0xE7EA,0xACD7,0xFCC8,0xD3D8,0xCDD8,0xDED4,0x53DA,0xF9D4,0xC4C9,0xAED3,0xD3B8,0xE0B3,0x54DA,0xE2C9,0xF6F4,0x55DA,0x56DA,0x57DA,0xD5BA,0x58DA,0xF7F4,0x59DA,0x5ADA,0xDFD7,0x5BDA,0x5CDA,0xF1F4,0xB0B8,0xD4D5,0xCFB8,0xF0C6,0x5DDA,0x5EDA,0x5FDA,0x60DA,0x61DA,0x62DA,0x63DA,0x64DA,0x65DA,0xC3B3,0x66DA,0x67DA,0xF2F4,0xACB3,0x68DA,0x69DA,0x6ADA,0x6BDA,0xBDD4,0xF7C7,0x6CDA,0x6DDA,0x6EDA,0x6FDA,0x70DA,0xF4F4,0x71DA,0x72DA,0xF3F4,0x73DA,0x74DA,0x75DA,0x76DA,0x77DA,0x78DA,0x79DA,0x7ADA,0x7BDA,0x7CDA,0xCBCC,0x7DDA,0x7EDA,0x80DA,0xA4C8,0x81DA,0x82DA,0x83DA,0x84DA,0x85DA,0x86DA,0x87DA,0x88DA,0x89DA,0x8ADA,0x8BDA,0x8CDA,0x8DDA,0xF5F4,0x8EDA,0xE3D7,0xBFC5,0xC0F5,0x8FDA,0x90DA,0xBBF5,0x91DA,0xC3F5,0x92DA,0xC2F5,0x93DA,0xBAD6,0xC1F5,0x94DA,0x95DA,0x96DA,0xBED4,0xC4F5,0x97DA,0xCCF5,0x98DA,0x99DA,0x9ADA,0x9BDA,0xCFB0,0xF8B5,0x9CDA,0xC9F5,0xCAF5,0x9DDA,0xDCC5,0x9EDA,0x9FDA,0xA0DA,0x40DB,0xC5F5,0xC6F5,0x41DB,0x42DB,0xC7F5,0xCBF5,0x43DB,0xE0BE,0xC8F5,0xFAB8,0x44DB,0x45DB,0x46DB,0xD0F5,0xD3F5,0x47DB,0x48DB,0x49DB,0xE7BF,0x4ADB,0xF2B9,0xBCF5,0xCDF5,0x4BDB,0x4CDB,0xB7C2,0x4DDB,0x4EDB,0x4FDB,0xF8CC,0x50DB,0xF9BC,0x51DB,0xCEF5,0xCFF5,0xD1F5,0xE5B6,0xD2F5,0x52DB,0xD5F5,0x53DB,0x54DB,0x55DB,0x56DB,0x57DB,0x58DB,0x59DB,0xBDF5,0x5ADB,0x5BDB,0x5CDB,0xD4F5,0xBBD3,0x5DDB,0xECB3,0x5EDB,0x5FDB,0xA4CC,0x60DB,0x61DB,0x62DB,0x63DB,0xD6F5,0x64DB,0x65DB,0x66DB,0x67DB,0x68DB,0x69DB,0x6ADB,0x6BDB,0xD7F5,0xE1BE,0xD8F5,0x6CDB,0x6DDB,0xDFCC,0xDBF5,0x6EDB,0x6FDB,0x70DB,0x71DB,0x72DB,0xC8B2,0xD9D7,0x73DB,0xD9F5,0x74DB,0xDAF5,0xDCF5,0x75DB,0xE2F5,0x76DB,0x77DB,0x78DB,0xE0F5,0x79DB,0x7ADB,0x7BDB,0xDFF5,0xDDF5,0x7CDB,0x7DDB,0xE1F5,0x7EDB,0x80DB,0xDEF5,0xE4F5,0xE5F5,0x81DB,0xE3CC,0x82DB,0x83DB,0xBFE5,0xB8B5,0xE3F5,0xE8F5,0xA3CC,0x84DB,0x85DB,0x86DB,0x87DB,0x88DB,0xE6F5,0xE7F5,0x89DB,0x8ADB,0x8BDB,0x8CDB,0x8DDB,0x8EDB,0xBEF5,0x8FDB,0x90DB,0x91DB,0x92DB,0x93DB,0x94DB,0x95DB,0x96DB,0x97DB,0x98DB,0x99DB,0x9ADB,0xC4B1,0x9BDB,0x9CDB,0xBFF5,0x9DDB,0x9EDB,0xC5B5,0xE4B2,0x9FDB,0xECF5,0xE9F5,0xA0DB,0xD7B6,0x40DC,0xEDF5,0x41DC,0xEAF5,0x42DC,0x43DC,0x44DC,0x45DC,0x46DC,0xEBF5,0x47DC,0x48DC,0xDAB4,0x49DC,0xEAD4,0x4ADC,0x4BDC,0x4CDC,0xEEF5,0x4DDC,0xF9B3,0x4EDC,0x4FDC,0x50DC,0x51DC,0x52DC,0x53DC,0x54DC,0xEFF5,0xF1F5,0x55DC,0x56DC,0x57DC,0xF0F5,0x58DC,0x59DC,0x5ADC,0x5BDC,0x5CDC,0x5DDC,0x5EDC,0xF2F5,0x5FDC,0xF3F5,0x60DC,0x61DC,0x62DC,0x63DC,0x64DC,0x65DC,0x66DC,0x67DC,0x68DC,0x69DC,0x6ADC,0x6BDC,0xEDC9,0xAAB9,0x6CDC,0x6DDC,0xFBC7,0x6EDC,0x6FDC,0xE3B6,0x70DC,0x71DC,0x72DC,0x73DC,0x74DC,0x75DC,0x76DC,0xC9CC,0x77DC,0x78DC,0x79DC,0x7ADC,0x7BDC,0x7CDC,0x7DDC,0x7EDC,0x80DC,0x81DC,0x82DC,0x83DC,0x84DC,0x85DC,0x86DC,0x87DC,0x88DC,0x89DC,0x8ADC,0xA6EA,0x8BDC,0x8CDC,0x8DDC,0x8EDC,0x8FDC,0x90DC,0x91DC,0x92DC,0x93DC,0x94DC,0x95DC,0x96DC,0x97DC,0x98DC,0x99DC,0x9ADC,0x9BDC,0x9CDC,0x9DDC,0x9EDC,0x9FDC,0xA0DC,0x40DD,0x41DD,0x42DD,0x43DD,0x44DD,0x45DD,0x46DD,0x47DD,0x48DD,0x49DD,0x4ADD,0x4BDD,0x4CDD,0x4DDD,0x4EDD,0x4FDD,0x50DD,0x51DD,0x52DD,0x53DD,0x54DD,0x55DD,0x56DD,0x57DD,0x58DD,0x59DD,0x5ADD,0x5BDD,0x5CDD,0x5DDD,0x5EDD,0x5FDD,0x60DD,0x61DD,0x62DD,0x63DD,0x64DD,0x65DD,0x66DD,0x67DD,0x68DD,0x69DD,0x6ADD,0x6BDD,0x6CDD,0x6DDD,0x6EDD,0x6FDD,0x70DD,0x71DD,0x72DD,0x73DD,0x74DD,0x75DD,0x76DD,0x77DD,0x78DD,0x79DD,0x7ADD,0x7BDD,0x7CDD,0x7DDD,0x7EDD,0x80DD,0x81DD,0x82DD,0x83DD,0x84DD,0x85DD,0x86DD,0x87DD,0x88DD,0x89DD,0x8ADD,0x8BDD,0x8CDD,0x8DDD,0x8EDD,0x8FDD,0x90DD,0x91DD,0x92DD,0x93DD,0x94DD,0x95DD,0x96DD,0x97DD,0x98DD,0x99DD,0x9ADD,0x9BDD,0x9CDD,0x9DDD,0x9EDD,0x9FDD,0xA0DD,0x40DE,0x41DE,0x42DE,0x43DE,0x44DE,0x45DE,0x46DE,0x47DE,0x48DE,0x49DE,0x4ADE,0x4BDE,0x4CDE,0x4DDE,0x4EDE,0x4FDE,0x50DE,0x51DE,0x52DE,0x53DE,0x54DE,0x55DE,0x56DE,0x57DE,0x58DE,0x59DE,0x5ADE,0x5BDE,0x5CDE,0x5DDE,0x5EDE,0x5FDE,0x60DE,0xB5B3,0xFED4,0xECB9,0xF9D0,0x61DE,0xEDE9,0xAAD7,0xEEE9,0xD6C2,0xEDC8,0xE4BA,0xEFE9,0xF0E9,0xF1E9,0xE1D6,0xF2E9,0xF3E9,0xF5E9,0xF4E9,0xF6E9,0xF7E9,0xE1C7,0xF8E9,0xD8D4,0xF9E9,0xCEBD,0x62DE,0xFAE9,0xFBE9,0xCFBD,0xFCE9,0xA8B8,0xBEC1,0xFDE9,0xB2B1,0xD4BB,0xF5B9,0xFEE9,0x63DE,0xA1EA,0xA2EA,0xA3EA,0xF8B7,0xADBC,0x64DE,0xE4CA,0xCEE0,0xAFD4,0xBDCF,0xB7D5,0xA4EA,0xDED5,0xA5EA,0xC1D0,0xBCB9,0x65DE,0xC7B4,0xD9B1,0x66DE,0x67DE,0x68DE,0xB1C0,0x69DE,0x6ADE,0x6BDE,0x6CDE,0xE6B1,0xE7B1,0x6DDE,0xE8B1,0x6EDE,0x6FDE,0x70DE,0x71DE,0xBDB3,0xE8C8,0x72DE,0x73DE,0x74DE,0x75DE,0xC1E5,0x76DE,0x77DE,0xDFB1,0x78DE,0x79DE,0x7ADE,0xC9C1,0xEFB4,0x7BDE,0x7CDE,0xA8C7,0xD8D3,0x7DDE,0xF9C6,0xB8D1,0x7EDE,0xFDB9,0xF5C2,0x80DE,0x81DE,0x82DE,0x83DE,0x84DE,0xADD3,0x85DE,0xCBD4,0xFCBD,0x86DE,0xC2E5,0xB5B7,0xC3E5,0x87DE,0x88DE,0xB9BB,0xE2D5,0x89DE,0xF8BD,0xB6D4,0xA5CE,0xACC1,0xD9B3,0x8ADE,0x8BDE,0xF6CC,0x8CDE,0xC6E5,0xC4E5,0xC8E5,0x8DDE,0xCAE5,0xC7E5,0xCFB5,0xC8C6,0x8EDE,0xFCB5,0xC5E5,0x8FDE,0xF6CA,0x90DE,0x91DE,0xC9E5,0x92DE,0x93DE,0x94DE,0xD4C3,0xC5B1,0xA3BC,0x95DE,0x96DE,0x97DE,0xB7D7,0x98DE,0x99DE,0xCBCD,0xCDCB,0xCACA,0xD3CC,0xCCE5,0xCBE5,0xE6C4,0x9ADE,0x9BDE,0xA1D1,0xB7D1,0xCDE5,0x9CDE,0xD0E5,0x9DDE,0xB8CD,0xF0D6,0xCFE5,0xDDB5,0x9EDE,0xBECD,0x9FDE,0xD1E5,0xBAB6,0xA0DE,0x40DF,0xA8CD,0xE4B9,0x41DF,0xC5CA,0xD1B3,0xD9CB,0xECD4,0xD2E5,0xEAB7,0x42DF,0x43DF,0x44DF,0xCEE5,0x45DF,0x46DF,0x47DF,0x48DF,0x49DF,0x4ADF,0xD5E5,0xFEB4,0xD6E5,0x4BDF,0x4CDF,0x4DDF,0x4EDF,0x4FDF,0xD3E5,0xD4E5,0x50DF,0xDDD2,0x51DF,0x52DF,0xDFC2,0xC6B1,0x53DF,0xE2D3,0x54DF,0x55DF,0xDDB6,0xECCB,0x56DF,0xD7E5,0x57DF,0x58DF,0xF6D3,0x59DF,0x5ADF,0x5BDF,0x5CDF,0x5DDF,0xE9B1,0x5EDF,0xF4B6,0xDAE5,0xD8E5,0xD9E5,0xC0B5,0x5FDF,0x60DF,0x61DF,0xC5D2,0xDCE5,0x62DF,0x63DF,0xDEE5,0x64DF,0x65DF,0x66DF,0x67DF,0x68DF,0x69DF,0xDDE5,0xB2C7,0x6ADF,0xA3D2,0x6BDF,0x6CDF,0xDBE5,0x6DDF,0x6EDF,0x6FDF,0x70DF,0xE2D4,0xDAD5,0x71DF,0x72DF,0x73DF,0x74DF,0x75DF,0xE0E5,0xF1D7,0x76DF,0x77DF,0x78DF,0x79DF,0x7ADF,0x7BDF,0x7CDF,0xE1E5,0x7DDF,0xDCB1,0xFBD1,0x7EDF,0xE2E5,0xE4E5,0x80DF,0x81DF,0x82DF,0x83DF,0xE3E5,0x84DF,0x85DF,0xE5E5,0x86DF,0x87DF,0x88DF,0x89DF,0x8ADF,0xD8D2,0x8BDF,0xCBB5,0x8CDF,0xDFE7,0x8DDF,0xF5DA,0x8EDF,0xF8DA,0x8FDF,0xF6DA,0x90DF,0xF7DA,0x91DF,0x92DF,0x93DF,0xFADA,0xCFD0,0xC7C4,0x94DF,0x95DF,0xEEB0,0x96DF,0x97DF,0x98DF,0xB0D0,0x99DF,0xF9DA,0x9ADF,0xCAD3,0xAABA,0xA2DB,0xF1C7,0x9BDF,0xFCDA,0xFBDA,0xDBC9,0xFDDA,0x9CDF,0xA1DB,0xDED7,0xFEDA,0xDAC1,0x9DDF,0x9EDF,0xA5DB,0x9FDF,0xA0DF,0xF4D3,0x40E0,0x41E0,0xA7DB,0xA4DB,0x42E0,0xA8DB,0x43E0,0x44E0,0xBCBD,0x45E0,0x46E0,0x47E0,0xC9C0,0xA3DB,0xA6DB,0xA3D6,0x48E0,0xA9DB,0x49E0,0x4AE0,0x4BE0,0xADDB,0x4CE0,0x4DE0,0x4EE0,0xAEDB,0xACDB,0xC2BA,0x4FE0,0x50E0,0x51E0,0xA4BF,0xABDB,0x52E0,0x53E0,0x54E0,0xAADB,0xC7D4,0xBFB2,0x55E0,0x56E0,0xAFDB,0x57E0,0xF9B9,0x58E0,0xB0DB,0x59E0,0x5AE0,0x5BE0,0x5CE0,0xBBB3,0x5DE0,0x5EE0,0x5FE0,0xA6B5,0x60E0,0x61E0,0x62E0,0x63E0,0xBCB6,0xB1DB,0x64E0,0x65E0,0x66E0,0xF5B6,0x67E0,0xB2DB,0x68E0,0x69E0,0x6AE0,0x6BE0,0x6CE0,0x6DE0,0x6EE0,0x6FE0,0x70E0,0x71E0,0x72E0,0x73E0,0x74E0,0x75E0,0x76E0,0x77E0,0x78E0,0x79E0,0x7AE0,0x7BE0,0xC9B1,0x7CE0,0x7DE0,0x7EE0,0x80E0,0xB4DB,0x81E0,0x82E0,0x83E0,0xB3DB,0xB5DB,0x84E0,0x85E0,0x86E0,0x87E0,0x88E0,0x89E0,0x8AE0,0x8BE0,0x8CE0,0x8DE0,0x8EE0,0xB7DB,0x8FE0,0xB6DB,0x90E0,0x91E0,0x92E0,0x93E0,0x94E0,0x95E0,0x96E0,0xB8DB,0x97E0,0x98E0,0x99E0,0x9AE0,0x9BE0,0x9CE0,0x9DE0,0x9EE0,0x9FE0,0xB9DB,0xA0E0,0x40E1,0xBADB,0x41E1,0x42E1,0xCFD3,0xFAF4,0xF5C7,0xC3D7,0xE4C5,0xFCF4,0xFDF4,0xFBF4,0x43E1,0xC6BE,0x44E1,0x45E1,0x46E1,0x47E1,0xEFD0,0x48E1,0x49E1,0xD3B7,0x4AE1,0x4BE1,0xCDD4,0xAACC,0x4CE1,0x4DE1,0xA2F5,0xA1F5,0xA8BA,0xFEF4,0xD6CB,0x4EE1,0x4FE1,0x50E1,0xA4F5,0xD2C0,0x51E1,0xEAB3,0x52E1,0xAACD,0xA5F5,0xA3F5,0xB4BD,0xA8F5,0x53E1,0xA9F5,0xCDBD,0xB8C3,0xE1BF,0xE1CB,0xAAF5,0x54E1,0x55E1,0x56E1,0xA6F5,0xA7F5,0xF0C4,0x57E1,0x58E1,0x59E1,0x5AE1,0x5BE1,0xACF5,0x5CE1,0xBCB4,0x5DE1,0xEDD7,0x5EE1,0xD7B4,0xABF5,0xAEF5,0x5FE1,0x60E1,0xADF5,0xAFF5,0xD1D0,0x61E1,0x62E1,0x63E1,0x64E1,0x65E1,0x66E1,0x67E1,0xD1C3,0xA9C8,0x68E1,0x69E1,0x6AE1,0x6BE1,0x6CE1,0x6DE1,0xB0F5,0xB1F5,0x6EE1,0x6FE1,0x70E1,0x71E1,0x72E1,0x73E1,0xB2F5,0x74E1,0x75E1,0xB3F5,0xB4F5,0xB5F5,0x76E1,0x77E1,0x78E1,0x79E1,0xB7F5,0xB6F5,0x7AE1,0x7BE1,0x7CE1,0x7DE1,0xB8F5,0x7EE1,0x80E1,0x81E1,0x82E1,0x83E1,0x84E1,0x85E1,0x86E1,0x87E1,0x88E1,0x89E1,0x8AE1,0xC9B2,0x8BE1,0xD4D3,0xCDCA,0x8CE1,0xEFC0,0xD8D6,0xB0D2,0xBFC1,0x8DE1,0xF0BD,0x8EE1,0x8FE1,0x90E1,0x91E1,0x92E1,0x93E1,0x94E1,0x95E1,0x96E1,0x97E1,0xAAB8,0x98E1,0x99E1,0x9AE1,0x9BE1,0x9CE1,0x9DE1,0x9EE1,0x9FE1,0xA0E1,0x40E2,0x41E2,0x42E2,0x43E2,0x44E2,0x45E2,0x46E2,0x47E2,0x48E2,0x49E2,0x4AE2,0x4BE2,0x4CE2,0x4DE2,0x4EE2,0x4FE2,0x50E2,0x51E2,0x52E2,0x53E2,0x54E2,0x55E2,0x56E2,0x57E2,0x58E2,0x59E2,0x5AE2,0x5BE2,0x5CE2,0x5DE2,0x5EE2,0x5FE2,0x60E2,0x61E2,0x62E2,0x63E2,0x64E2,0x65E2,0x66E2,0x67E2,0x68E2,0x69E2,0x6AE2,0x6BE2,0x6CE2,0x6DE2,0x6EE2,0x6FE2,0x70E2,0x71E2,0x72E2,0x73E2,0x74E2,0x75E2,0x76E2,0x77E2,0x78E2,0x79E2,0x7AE2,0x7BE2,0x7CE2,0x7DE2,0x7EE2,0x80E2,0x81E2,0x82E2,0x83E2,0x84E2,0x85E2,0x86E2,0x87E2,0x88E2,0x89E2,0x8AE2,0x8BE2,0x8CE2,0x8DE2,0x8EE2,0x8FE2,0x90E2,0x91E2,0x92E2,0x93E2,0x94E2,0x95E2,0x96E2,0x97E2,0x98E2,0x99E2,0x9AE2,0x9BE2,0x9CE2,0x9DE2,0x9EE2,0x9FE2,0xA0E2,0x40E3,0x41E3,0x42E3,0x43E3,0x44E3,0x45E3,0x46E3,0x47E3,0x48E3,0x49E3,0x4AE3,0x4BE3,0x4CE3,0x4DE3,0x4EE3,0x4FE3,0x50E3,0x51E3,0x52E3,0x53E3,0x54E3,0x55E3,0x56E3,0x57E3,0x58E3,0x59E3,0x5AE3,0x5BE3,0x5CE3,0x5DE3,0x5EE3,0x5FE3,0x60E3,0x61E3,0x62E3,0x63E3,0x64E3,0x65E3,0x66E3,0x67E3,0x68E3,0x69E3,0x6AE3,0x6BE3,0x6CE3,0x6DE3,0xF8BC,0x6EE3,0x6FE3,0x70E3,0x71E3,0x72E3,0x73E3,0x74E3,0x75E3,0x76E3,0x77E3,0x78E3,0x79E3,0x7AE3,0x7BE3,0x7CE3,0x7DE3,0x7EE3,0x80E3,0x81E3,0x82E3,0x83E3,0x84E3,0x85E3,0x86E3,0x87E3,0xC6F6,0x88E3,0x89E3,0x8AE3,0x8BE3,0x8CE3,0x8DE3,0x8EE3,0x8FE3,0x90E3,0x91E3,0x92E3,0x93E3,0x94E3,0x95E3,0x96E3,0x97E3,0x98E3,0x99E3,0x9AE3,0x9BE3,0x9CE3,0x9DE3,0x9EE3,0x9FE3,0xA0E3,0x40E4,0x41E4,0x42E4,0x43E4,0x44E4,0x45E4,0xC7F6,0x46E4,0x47E4,0x48E4,0x49E4,0x4AE4,0x4BE4,0x4CE4,0x4DE4,0x4EE4,0x4FE4,0x50E4,0x51E4,0x52E4,0x53E4,0x54E4,0x55E4,0x56E4,0x57E4,0x58E4,0x59E4,0x5AE4,0x5BE4,0x5CE4,0x5DE4,0x5EE4,0xC8F6,0x5FE4,0x60E4,0x61E4,0x62E4,0x63E4,0x64E4,0x65E4,0x66E4,0x67E4,0x68E4,0x69E4,0x6AE4,0x6BE4,0x6CE4,0x6DE4,0x6EE4,0x6FE4,0x70E4,0x71E4,0x72E4,0x73E4,0x74E4,0x75E4,0x76E4,0x77E4,0x78E4,0x79E4,0x7AE4,0x7BE4,0x7CE4,0x7DE4,0x7EE4,0x80E4,0x81E4,0x82E4,0x83E4,0x84E4,0x85E4,0x86E4,0x87E4,0x88E4,0x89E4,0x8AE4,0x8BE4,0x8CE4,0x8DE4,0x8EE4,0x8FE4,0x90E4,0x91E4,0x92E4,0x93E4,0x94E4,0x95E4,0x96E4,0x97E4,0x98E4,0x99E4,0x9AE4,0x9BE4,0x9CE4,0x9DE4,0x9EE4,0x9FE4,0xA0E4,0x40E5,0x41E5,0x42E5,0x43E5,0x44E5,0x45E5,0x46E5,0x47E5,0x48E5,0x49E5,0x4AE5,0x4BE5,0x4CE5,0x4DE5,0x4EE5,0x4FE5,0x50E5,0x51E5,0x52E5,0x53E5,0x54E5,0x55E5,0x56E5,0x57E5,0x58E5,0x59E5,0x5AE5,0x5BE5,0x5CE5,0x5DE5,0x5EE5,0x5FE5,0x60E5,0x61E5,0x62E5,0x63E5,0x64E5,0x65E5,0x66E5,0x67E5,0x68E5,0x69E5,0x6AE5,0x6BE5,0x6CE5,0x6DE5,0x6EE5,0x6FE5,0x70E5,0x71E5,0x72E5,0x73E5,0xC9F6,0x74E5,0x75E5,0x76E5,0x77E5,0x78E5,0x79E5,0x7AE5,0x7BE5,0x7CE5,0x7DE5,0x7EE5,0x80E5,0x81E5,0x82E5,0x83E5,0x84E5,0x85E5,0x86E5,0x87E5,0x88E5,0x89E5,0x8AE5,0x8BE5,0x8CE5,0x8DE5,0x8EE5,0x8FE5,0x90E5,0x91E5,0x92E5,0x93E5,0x94E5,0x95E5,0x96E5,0x97E5,0x98E5,0x99E5,0x9AE5,0x9BE5,0x9CE5,0x9DE5,0x9EE5,0x9FE5,0xCAF6,0xA0E5,0x40E6,0x41E6,0x42E6,0x43E6,0x44E6,0x45E6,0x46E6,0x47E6,0x48E6,0x49E6,0x4AE6,0x4BE6,0x4CE6,0x4DE6,0x4EE6,0x4FE6,0x50E6,0x51E6,0x52E6,0x53E6,0x54E6,0x55E6,0x56E6,0x57E6,0x58E6,0x59E6,0x5AE6,0x5BE6,0x5CE6,0x5DE6,0x5EE6,0x5FE6,0x60E6,0x61E6,0x62E6,0xCCF6,0x63E6,0x64E6,0x65E6,0x66E6,0x67E6,0x68E6,0x69E6,0x6AE6,0x6BE6,0x6CE6,0x6DE6,0x6EE6,0x6FE6,0x70E6,0x71E6,0x72E6,0x73E6,0x74E6,0x75E6,0x76E6,0x77E6,0x78E6,0x79E6,0x7AE6,0x7BE6,0x7CE6,0x7DE6,0x7EE6,0x80E6,0x81E6,0x82E6,0x83E6,0x84E6,0x85E6,0x86E6,0x87E6,0x88E6,0x89E6,0x8AE6,0x8BE6,0x8CE6,0x8DE6,0x8EE6,0x8FE6,0x90E6,0x91E6,0x92E6,0x93E6,0x94E6,0x95E6,0x96E6,0x97E6,0x98E6,0x99E6,0x9AE6,0x9BE6,0x9CE6,0x9DE6,0xCBF6,0x9EE6,0x9FE6,0xA0E6,0x40E7,0x41E7,0x42E7,0x43E7,0x44E7,0x45E7,0x46E7,0x47E7,0xE9F7,0x48E7,0x49E7,0x4AE7,0x4BE7,0x4CE7,0x4DE7,0x4EE7,0x4FE7,0x50E7,0x51E7,0x52E7,0x53E7,0x54E7,0x55E7,0x56E7,0x57E7,0x58E7,0x59E7,0x5AE7,0x5BE7,0x5CE7,0x5DE7,0x5EE7,0x5FE7,0x60E7,0x61E7,0x62E7,0x63E7,0x64E7,0x65E7,0x66E7,0x67E7,0x68E7,0x69E7,0x6AE7,0x6BE7,0x6CE7,0x6DE7,0x6EE7,0x6FE7,0x70E7,0x71E7,0x72E7,0x73E7,0x74E7,0x75E7,0x76E7,0x77E7,0x78E7,0x79E7,0x7AE7,0x7BE7,0x7CE7,0x7DE7,0x7EE7,0x80E7,0x81E7,0x82E7,0x83E7,0x84E7,0x85E7,0x86E7,0x87E7,0x88E7,0x89E7,0x8AE7,0x8BE7,0x8CE7,0x8DE7,0x8EE7,0x8FE7,0x90E7,0x91E7,0x92E7,0x93E7,0x94E7,0x95E7,0x96E7,0x97E7,0x98E7,0x99E7,0x9AE7,0x9BE7,0x9CE7,0x9DE7,0x9EE7,0x9FE7,0xA0E7,0x40E8,0x41E8,0x42E8,0x43E8,0x44E8,0x45E8,0x46E8,0x47E8,0x48E8,0x49E8,0x4AE8,0x4BE8,0x4CE8,0x4DE8,0x4EE8,0xCDF6,0x4FE8,0x50E8,0x51E8,0x52E8,0x53E8,0x54E8,0x55E8,0x56E8,0x57E8,0x58E8,0x59E8,0x5AE8,0x5BE8,0x5CE8,0x5DE8,0x5EE8,0x5FE8,0x60E8,0x61E8,0x62E8,0x63E8,0x64E8,0x65E8,0x66E8,0x67E8,0x68E8,0x69E8,0x6AE8,0x6BE8,0x6CE8,0x6DE8,0x6EE8,0x6FE8,0x70E8,0x71E8,0x72E8,0x73E8,0x74E8,0x75E8,0x76E8,0x77E8,0x78E8,0x79E8,0x7AE8,0xCEF6,0x7BE8,0x7CE8,0x7DE8,0x7EE8,0x80E8,0x81E8,0x82E8,0x83E8,0x84E8,0x85E8,0x86E8,0x87E8,0x88E8,0x89E8,0x8AE8,0x8BE8,0x8CE8,0x8DE8,0x8EE8,0x8FE8,0x90E8,0x91E8,0x92E8,0x93E8,0x94E8,0xC4EE,0xC5EE,0xC6EE,0xEBD5,0xA4B6,0xC8EE,0xC7EE,0xC9EE,0xCAEE,0xA5C7,0xCBEE,0xCCEE,0x95E8,0xB0B7,0xF6B5,0xCDEE,0xCFEE,0x96E8,0xCEEE,0x97E8,0xC6B8,0xD0EE,0xD1EE,0xD2EE,0xDBB6,0xAEB3,0xD3D6,0xC6C4,0xB5B1,0xD6B8,0xD3EE,0xD4EE,0xBFD4,0xD5C7,0xFBBE,0xD9CE,0xB3B9,0xD6EE,0xD5EE,0xD8EE,0xD7EE,0xA5C5,0xD9EE,0xDAEE,0xAEC7,0xDBEE,0xAFC7,0xDCEE,0xA7B2,0xDDEE,0xDEEE,0xDFEE,0xE0EE,0xE1EE,0xEAD7,0xE2EE,0xE3EE,0xD8BC,0xE4EE,0xCBD3,0xFACC,0xACB2,0xE5C1,0xE5EE,0xA6C7,0xADC3,0x98E8,0xE6EE,0xE7EE,0xE8EE,0xE9EE,0xEAEE,0xEBEE,0xECEE,0x99E8,0xEDEE,0xEEEE,0xEFEE,0x9AE8,0x9BE8,0xF0EE,0xF1EE,0xF2EE,0xF4EE,0xF3EE,0x9CE8,0xF5EE,0xADCD,0xC1C2,0xF6EE,0xF7EE,0xF8EE,0xA1D5,0xF9EE,0xB3CF,0xFAEE,0xFBEE,0x9DE8,0xFCEE,0xFDEE,0xA1EF,0xFEEE,0xA2EF,0xF5B8,0xFAC3,0xA3EF,0xA4EF,0xC2BD,0xBFD2,0xF9B2,0xA5EF,0xA6EF,0xA7EF,0xF8D2,0xA8EF,0xFDD6,0xA9EF,0xCCC6,0x9EE8,0xAAEF,0xABEF,0xB4C1,0xACEF,0xFACF,0xF8CB,0xAEEF,0xADEF,0xFAB3,0xF8B9,0xAFEF,0xB0EF,0xE2D0,0xB1EF,0xB2EF,0xE6B7,0xBFD0,0xB3EF,0xB4EF,0xB5EF,0xF1C8,0xE0CC,0xB6EF,0xB7EF,0xB8EF,0xB9EF,0xBAEF,0xE0D5,0xBBEF,0xEDB4,0xAAC3,0xBCEF,0x9FE8,0xBDEF,0xBEEF,0xBFEF,0xA0E8,0xFDCE,0xC0EF,0xE0C2,0xB8B4,0xB6D7,0xF5BD,0x40E9,0xC7CF,0xC3EF,0xC1EF,0xC2EF,0xC4EF,0xA7B6,0xFCBC,0xE2BE,0xCCC3,0xC5EF,0xC6EF,0x41E9,0xC7EF,0xCFEF,0xC8EF,0xC9EF,0xCAEF,0xC2C7,0xF1EF,0xCDB6,0xCBEF,0x42E9,0xCCEF,0xCDEF,0xC6B6,0xBEC3,0xCEEF,0x43E9,0xD0EF,0xD1EF,0xD2EF,0xF2D5,0x44E9,0xD3EF,0xF7C4,0x45E9,0xD4EF,0xF8C4,0xD5EF,0xD6EF,0xE4B8,0xF7B0,0xD7EF,0xD8EF,0xD9EF,0x46E9,0xDAEF,0xDBEF,0xDCEF,0xDDEF,0x47E9,0xDEEF,0xB5BE,0xE1EF,0xDFEF,0xE0EF,0x48E9,0xE2EF,0xE3EF,0xCDC1,0xE4EF,0xE5EF,0xE6EF,0xE7EF,0xE8EF,0xE9EF,0xEAEF,0xEBEF,0xECEF,0xD8C0,0x49E9,0xEDEF,0xADC1,0xEEEF,0xEFEF,0xF0EF,0x4AE9,0x4BE9,0xE2CF,0x4CE9,0x4DE9,0x4EE9,0x4FE9,0x50E9,0x51E9,0x52E9,0x53E9,0xA4B3,0x54E9,0x55E9,0x56E9,0x57E9,0x58E9,0x59E9,0x5AE9,0x5BE9,0x5CE9,0x5DE9,0x5EE9,0x5FE9,0x60E9,0x61E9,0x62E9,0x63E9,0x64E9,0x65E9,0x66E9,0x67E9,0x68E9,0x69E9,0x6AE9,0x6BE9,0x6CE9,0x6DE9,0x6EE9,0x6FE9,0x70E9,0x71E9,0x72E9,0x73E9,0x74E9,0x75E9,0x76E9,0x77E9,0x78E9,0x79E9,0x7AE9,0x7BE9,0x7CE9,0x7DE9,0x7EE9,0x80E9,0x81E9,0x82E9,0x83E9,0x84E9,0x85E9,0x86E9,0x87E9,0x88E9,0x89E9,0x8AE9,0x8BE9,0x8CE9,0x8DE9,0x8EE9,0x8FE9,0x90E9,0x91E9,0x92E9,0x93E9,0x94E9,0x95E9,0x96E9,0x97E9,0x98E9,0x99E9,0x9AE9,0x9BE9,0x9CE9,0x9DE9,0x9EE9,0x9FE9,0xA0E9,0x40EA,0x41EA,0x42EA,0x43EA,0x44EA,0x45EA,0x46EA,0x47EA,0x48EA,0x49EA,0x4AEA,0x4BEA,0x4CEA,0x4DEA,0x4EEA,0x4FEA,0x50EA,0x51EA,0x52EA,0x53EA,0x54EA,0x55EA,0x56EA,0x57EA,0x58EA,0x59EA,0x5AEA,0x5BEA,0xC5C3,0xC5E3,0xC1C9,0xC6E3,0x5CEA,0xD5B1,0xCACE,0xB3B4,0xF2C8,0xC7E3,0xD0CF,0xC8E3,0xE4BC,0xC9E3,0xCAE3,0xC6C3,0xA2D5,0xD6C4,0xEBB9,0xC5CE,0xCBE3,0xF6C3,0xCCE3,0x5DEA,0xA7B7,0xF3B8,0xD2BA,0xCDE3,0xCEE3,0xC4D4,0xCFE3,0x5EEA,0xD0E3,0xCBD1,0xD1E3,0xD2E3,0xD3E3,0xD4E3,0xD6D1,0xD5E3,0xFBB2,0xBBC0,0xD6E3,0x5FEA,0xABC0,0xD7E3,0xD8E3,0xD9E3,0x60EA,0xDAE3,0xDBE3,0x61EA,0xB7B8,0xE2DA,0x62EA,0xD3B6,0x63EA,0xE4DA,0xE3DA,0x64EA,0x65EA,0x66EA,0x67EA,0x68EA,0x69EA,0x6AEA,0xE6DA,0x6BEA,0x6CEA,0x6DEA,0xEEC8,0x6EEA,0x6FEA,0xE5DA,0xC0B7,0xF4D1,0xF5D2,0xF3D5,0xD7BD,0x70EA,0x71EA,0x72EA,0x73EA,0xE8D7,0xE8DA,0xE7DA,0x74EA,0xA2B0,0xD3CD,0x75EA,0xE9DA,0x76EA,0xBDB8,0xCABC,0xBDC2,0xA4C2,0xC2B3,0xEADA,0x77EA,0xAAC2,0xB0C4,0xB5BD,0x78EA,0x79EA,0xDECF,0x7AEA,0x7BEA,0x7CEA,0xEBDA,0xC2C9,0x7DEA,0x7EEA,0x80EA,0x81EA,0x82EA,0xDDB1,0x83EA,0x84EA,0x85EA,0xECDA,0x86EA,0xB8B6,0xBAD4,0x87EA,0xFDB3,0x88EA,0x89EA,0xEDDA,0xC9D4,0xD5CF,0xE3C5,0x8AEA,0xEEDA,0x8BEA,0x8CEA,0x8DEA,0x8EEA,0x8FEA,0xEFDA,0x90EA,0xF0DA,0xEAC1,0xD5CC,0xDDCF,0x91EA,0x92EA,0x93EA,0x94EA,0x95EA,0x96EA,0x97EA,0x98EA,0x99EA,0x9AEA,0x9BEA,0x9CEA,0x9DEA,0xE7D3,0xA1C2,0x9EEA,0xF1DA,0x9FEA,0xA0EA,0xE5CB,0x40EB,0xF2DA,0x41EB,0xE6CB,0xFED2,0x42EB,0x43EB,0x44EB,0xF4B8,0x45EB,0x46EB,0xF3DA,0xAFB0,0xB6CF,0x47EB,0x48EB,0xCFD5,0x49EB,0x4AEB,0x4BEB,0x4CEB,0x4DEB,0x4EEB,0x4FEB,0x50EB,0x51EB,0x52EB,0xEDCB,0x53EB,0x54EB,0x55EB,0x56EB,0x57EB,0x58EB,0x59EB,0x5AEB,0xF4DA,0x5BEB,0x5CEB,0xC4E3,0x5DEB,0x5EEB,0xA5C1,0x5FEB,0x60EB,0xBFF6,0x61EB,0x62EB,0xC0F6,0xC1F6,0xD1C4,0x63EB,0xB8C8,0xE3D1,0x64EB,0x65EB,0xDBD0,0xC5D1,0xAFBC,0xCDB9,0x66EB,0xF4EF,0x67EB,0x68EB,0xC6B4,0xBAD3,0xC2F6,0xFBB3,0x69EB,0x6AEB,0xC3F6,0x6BEB,0x6CEB,0xF1B5,0x6DEB,0x6EEB,0x6FEB,0x70EB,0x71EB,0x72EB,0x73EB,0x74EB,0x75EB,0x76EB,0xC5F6,0x77EB,0x78EB,0x79EB,0x7AEB,0x7BEB,0x7CEB,0x7DEB,0xEAD3,0xA7F6,0xA9D1,0x7EEB,0x80EB,0x81EB,0x82EB,0xA9F6,0x83EB,0x84EB,0x85EB,0xA8F6,0x86EB,0x87EB,0xE3C1,0xD7C0,0x88EB,0xA2B1,0x89EB,0x8AEB,0x8BEB,0x8CEB,0xEDCE,0x8DEB,0xE8D0,0xABF6,0x8EEB,0x8FEB,0xF6CF,0x90EB,0xAAF6,0xF0D5,0xACF6,0xB9C3,0x91EB,0x92EB,0x93EB,0xF4BB,0xAEF6,0xADF6,0x94EB,0x95EB,0x96EB,0xDEC4,0x97EB,0x98EB,0xD8C1,0x99EB,0x9AEB,0x9BEB,0x9CEB,0x9DEB,0xAACB,0x9EEB,0xBCCF,0x9FEB,0xA0EB,0x40EC,0x41EC,0x42EC,0x43EC,0x44EC,0x45EC,0x46EC,0x47EC,0x48EC,0xAFF6,0x49EC,0x4AEC,0xB0F6,0x4BEC,0x4CEC,0xB1F6,0x4DEC,0xB6C2,0x4EEC,0x4FEC,0x50EC,0x51EC,0x52EC,0xD4B0,0xF9C5,0x53EC,0x54EC,0x55EC,0x56EC,0xB2F6,0x57EC,0x58EC,0x59EC,0x5AEC,0x5BEC,0x5CEC,0x5DEC,0x5EEC,0x5FEC,0x60EC,0x61EC,0x62EC,0x63EC,0x64EC,0x65EC,0x66EC,0x67EC,0x68EC,0x69EC,0xE0C7,0xA6F6,0x6AEC,0x6BEC,0xB8BE,0x6CEC,0x6DEC,0xB2BE,0x6EEC,0xE5B5,0x6FEC,0x70EC,0xC7B7,0x71EC,0xBFBF,0xD2C3,0xE6C3,0x72EC,0x73EC,0xCCD8,0x74EC,0x75EC,0x76EC,0xEFB8,0x77EC,0x78EC,0x79EC,0x7AEC,0x7BEC,0x7CEC,0x7DEC,0x7EEC,0x80EC,0xF9BD,0xA5D1,0x81EC,0xD0B0,0x82EC,0x83EC,0x84EC,0x85EC,0x86EC,0xB0F7,0x87EC,0x88EC,0x89EC,0x8AEC,0x8BEC,0x8CEC,0x8DEC,0x8EEC,0xB1F7,0x8FEC,0x90EC,0x91EC,0x92EC,0x93EC,0xACD0,0x94EC,0xB0B0,0x95EC,0x96EC,0x97EC,0xB2F7,0xB3F7,0x98EC,0xB4F7,0x99EC,0x9AEC,0x9BEC,0xCAC7,0x9CEC,0x9DEC,0x9EEC,0x9FEC,0xA0EC,0x40ED,0x41ED,0xCFBE,0x42ED,0x43ED,0xB7F7,0x44ED,0x45ED,0x46ED,0x47ED,0x48ED,0x49ED,0x4AED,0xB6F7,0x4BED,0xDEB1,0x4CED,0xB5F7,0x4DED,0x4EED,0xB8F7,0x4FED,0xB9F7,0x50ED,0x51ED,0x52ED,0x53ED,0x54ED,0x55ED,0x56ED,0x57ED,0x58ED,0x59ED,0x5AED,0x5BED,0x5CED,0x5DED,0x5EED,0x5FED,0x60ED,0x61ED,0x62ED,0x63ED,0x64ED,0x65ED,0x66ED,0x67ED,0x68ED,0x69ED,0x6AED,0x6BED,0x6CED,0x6DED,0x6EED,0x6FED,0x70ED,0x71ED,0x72ED,0x73ED,0x74ED,0x75ED,0x76ED,0x77ED,0x78ED,0x79ED,0x7AED,0x7BED,0x7CED,0x7DED,0x7EED,0x80ED,0x81ED,0xA4CE,0xCDC8,0x82ED,0xABBA,0xB8E8,0xB9E8,0xBAE8,0xC2BE,0x83ED,0x84ED,0x85ED,0x86ED,0x87ED,0xF4D2,0x88ED,0xCFD4,0xD8C9,0x89ED,0x8AED,0x8BED,0x8CED,0x8DED,0x8EED,0x8FED,0x90ED,0x91ED,0x92ED,0x93ED,0x94ED,0x95ED,0x96ED,0x97ED,0x98ED,0x99ED,0x9AED,0x9BED,0x9CED,0x9DED,0x9EED,0x9FED,0xA0ED,0x40EE,0x41EE,0x42EE,0x43EE,0x44EE,0x45EE,0x46EE,0x47EE,0x48EE,0x49EE,0x4AEE,0x4BEE,0x4CEE,0x4DEE,0x4EEE,0x4FEE,0x50EE,0x51EE,0x52EE,0x53EE,0x54EE,0x55EE,0x56EE,0x57EE,0x58EE,0x59EE,0x5AEE,0x5BEE,0x5CEE,0x5DEE,0x5EEE,0x5FEE,0x60EE,0x61EE,0x62EE,0x63EE,0x64EE,0x65EE,0x66EE,0x67EE,0x68EE,0x69EE,0x6AEE,0x6BEE,0x6CEE,0x6DEE,0x6EEE,0x6FEE,0x70EE,0x71EE,0x72EE,0x73EE,0x74EE,0x75EE,0x76EE,0x77EE,0x78EE,0x79EE,0x7AEE,0x7BEE,0x7CEE,0x7DEE,0x7EEE,0x80EE,0x81EE,0x82EE,0x83EE,0x84EE,0x85EE,0x86EE,0x87EE,0x88EE,0x89EE,0x8AEE,0x8BEE,0x8CEE,0x8DEE,0x8EEE,0x8FEE,0x90EE,0x91EE,0x92EE,0x93EE,0x94EE,0x95EE,0x96EE,0x97EE,0x98EE,0x99EE,0x9AEE,0x9BEE,0x9CEE,0x9DEE,0x9EEE,0x9FEE,0xA0EE,0x40EF,0x41EF,0x42EF,0x43EF,0x44EF,0x45EF,0xB3D2,0xA5B6,0xEAC7,0xFCF1,0xEECF,0xB3CB,0xEBD0,0xEFE7,0xE7CD,0xCBB9,0xD9B6,0xFDF1,0xE4B0,0xCCCB,0xFEF1,0xA4D4,0xADC2,0xECC1,0xC4C6,0xB1BE,0xA1F2,0xD5BC,0x46EF,0xA2F2,0xA3F2,0x47EF,0xA4F2,0xC3D2,0xB5C6,0x48EF,0xC7CD,0xA5F2,0x49EF,0xB1D3,0xC5BF,0xE2CC,0x4AEF,0xA6F2,0xA7F2,0xD5D1,0xEEB6,0xA8F2,0xA9F2,0xDFB5,0xAAF2,0xABF2,0x4BEF,0xFCB2,0xACF2,0xADF2,0xA7C8,0x4CEF,0x4DEF,0x4EEF,0x4FEF,0x50EF,0x51EF,0x52EF,0x53EF,0x54EF,0x55EF,0x56EF,0x57EF,0x58EF,0x59EF,0x5AEF,0x5BEF,0x5CEF,0x5DEF,0x5EEF,0x5FEF,0x60EF,0x61EF,0x62EF,0x63EF,0x64EF,0x65EF,0x66EF,0x67EF,0x68EF,0x69EF,0x6AEF,0x6BEF,0x6CEF,0x6DEF,0x6EEF,0x6FEF,0x70EF,0x71EF,0xE7B7,0x72EF,0x73EF,0xA9EC,0xAAEC,0xABEC,0x74EF,0xACEC,0x75EF,0x76EF,0xAEC6,0xADEC,0xAEEC,0x77EF,0x78EF,0x79EF,0xC9B7,0xB3CA,0x7AEF,0x7BEF,0x7CEF,0x7DEF,0x7EEF,0x80EF,0x81EF,0xB8E2,0xCFF7,0x82EF,0x83EF,0x84EF,0x85EF,0x86EF,0x87EF,0x88EF,0x89EF,0x8AEF,0x8BEF,0x8CEF,0x8DEF,0x8EEF,0x8FEF,0x90EF,0x91EF,0x92EF,0x93EF,0x94EF,0x95EF,0x96EF,0x97EF,0x98EF,0x99EF,0x9AEF,0x9BEF,0x9CEF,0x9DEF,0x9EEF,0x9FEF,0xA0EF,0x40F0,0x41F0,0x42F0,0x43F0,0x44F0,0xD0F7,0x45F0,0x46F0,0xCDB2,0x47F0,0x48F0,0x49F0,0x4AF0,0x4BF0,0x4CF0,0x4DF0,0x4EF0,0x4FF0,0x50F0,0x51F0,0x52F0,0x53F0,0x54F0,0x55F0,0x56F0,0x57F0,0x58F0,0x59F0,0x5AF0,0x5BF0,0x5CF0,0x5DF0,0x5EF0,0x5FF0,0x60F0,0x61F0,0x62F0,0x63F0,0xD1F7,0x64F0,0x65F0,0x66F0,0x67F0,0x68F0,0x69F0,0x6AF0,0x6BF0,0x6CF0,0x6DF0,0x6EF0,0x6FF0,0x70F0,0x71F0,0x72F0,0x73F0,0x74F0,0x75F0,0x76F0,0x77F0,0x78F0,0x79F0,0x7AF0,0x7BF0,0x7CF0,0x7DF0,0x7EF0,0x80F0,0x81F0,0x82F0,0x83F0,0x84F0,0x85F0,0x86F0,0x87F0,0x88F0,0x89F0,0xD3F7,0xD2F7,0x8AF0,0x8BF0,0x8CF0,0x8DF0,0x8EF0,0x8FF0,0x90F0,0x91F0,0x92F0,0x93F0,0x94F0,0x95F0,0x96F0,0xBBE2,0x97F0,0xA2BC,0x98F0,0xBCE2,0xBDE2,0xBEE2,0xBFE2,0xC0E2,0xC1E2,0xB9B7,0xFBD2,0xA4BD,0xCECA,0xA5B1,0xC7CB,0x99F0,0xC2E2,0xFCB6,0xC4C8,0xC3E2,0x9AF0,0x9BF0,0xC8BD,0x9CF0,0xFDB1,0xC4E2,0x9DF0,0xF6B6,0xC5E2,0xD9C4,0x9EF0,0x9FF0,0xC6E2,0xDACF,0xDDB9,0xC7E2,0xA1C0,0xA0F0,0xC8E2,0xF6B2,0x40F1,0xC9E2,0x41F1,0xF3C1,0xCAE2,0xCBE2,0xF8C2,0xCCE2,0xCDE2,0xCEE2,0xD7CA,0xB8D8,0xE5D9,0xE3CF,0x42F1,0x43F1,0x44F1,0x45F1,0x46F1,0x47F1,0x48F1,0x49F1,0x4AF1,0x4BF1,0x4CF1,0xA5F0,0x4DF1,0x4EF1,0xB0DC,0x4FF1,0x50F1,0x51F1,0x52F1,0x53F1,0x54F1,0x55F1,0x56F1,0x57F1,0x58F1,0x59F1,0x5AF1,0x5BF1,0x5CF1,0x5DF1,0x5EF1,0x5FF1,0x60F1,0x61F1,0x62F1,0x63F1,0x64F1,0x65F1,0x66F1,0x67F1,0x68F1,0x69F1,0x6AF1,0x6BF1,0x6CF1,0x6DF1,0x6EF1,0x6FF1,0x70F1,0x71F1,0x72F1,0x73F1,0x74F1,0x75F1,0x76F1,0x77F1,0x78F1,0x79F1,0x7AF1,0x7BF1,0x7CF1,0x7DF1,0x7EF1,0x80F1,0x81F1,0x82F1,0x83F1,0x84F1,0x85F1,0x86F1,0x87F1,0x88F1,0x89F1,0x8AF1,0x8BF1,0x8CF1,0x8DF1,0x8EF1,0x8FF1,0x90F1,0x91F1,0x92F1,0x93F1,0x94F1,0x95F1,0x96F1,0x97F1,0x98F1,0x99F1,0x9AF1,0x9BF1,0x9CF1,0x9DF1,0x9EF1,0x9FF1,0xA0F1,0x40F2,0x41F2,0x42F2,0x43F2,0x44F2,0x45F2,0x46F2,0x47F2,0x48F2,0x49F2,0x4AF2,0x4BF2,0x4CF2,0x4DF2,0x4EF2,0x4FF2,0x50F2,0x51F2,0x52F2,0x53F2,0x54F2,0x55F2,0x56F2,0x57F2,0x58F2,0x59F2,0x5AF2,0x5BF2,0x5CF2,0x5DF2,0x5EF2,0x5FF2,0x60F2,0x61F2,0x62F2,0x63F2,0x64F2,0x65F2,0x66F2,0x67F2,0x68F2,0x69F2,0x6AF2,0x6BF2,0x6CF2,0x6DF2,0x6EF2,0x6FF2,0x70F2,0x71F2,0x72F2,0x73F2,0x74F2,0x75F2,0x76F2,0x77F2,0x78F2,0x79F2,0x7AF2,0x7BF2,0x7CF2,0x7DF2,0x7EF2,0x80F2,0x81F2,0x82F2,0x83F2,0x84F2,0x85F2,0x86F2,0x87F2,0x88F2,0x89F2,0x8AF2,0x8BF2,0x8CF2,0x8DF2,0x8EF2,0x8FF2,0x90F2,0x91F2,0x92F2,0x93F2,0x94F2,0x95F2,0x96F2,0x97F2,0x98F2,0x99F2,0x9AF2,0x9BF2,0x9CF2,0x9DF2,0x9EF2,0x9FF2,0xA0F2,0x40F3,0x41F3,0x42F3,0x43F3,0x44F3,0x45F3,0x46F3,0x47F3,0x48F3,0x49F3,0x4AF3,0x4BF3,0x4CF3,0x4DF3,0x4EF3,0x4FF3,0x50F3,0x51F3,0xEDC2,0xA6D4,0xD4CD,0xB1D1,0xDBB3,0xFDC7,0x52F3,0xB5B2,0xBFC2,0xE0E6,0xBBCA,0xE1E6,0xE2E6,0xD4BE,0xE3E6,0xA4D7,0xD5CD,0xE5E6,0xDDBC,0xE4E6,0xE6E6,0xE7E6,0xEEC2,0x53F3,0xBEBD,0xE8E6,0xE6C2,0xA7BA,0xE9E6,0x54F3,0xEAE6,0xD2B3,0xE9D1,0x55F3,0x56F3,0xA5BF,0xEBE6,0xEFC6,0xECE6,0xEDE6,0x57F3,0x58F3,0xEEE6,0xADC6,0xEFE6,0x59F3,0xA7C9,0xF0E6,0xF1E6,0xF2E6,0xB9E5,0xF3E6,0xF4E6,0xE2C2,0xF5E6,0xF6E6,0xE8D6,0xF7E6,0x5AF3,0xF8E6,0xC7B9,0x5BF3,0x5CF3,0x5DF3,0x5EF3,0x5FF3,0x60F3,0x61F3,0xBBF7,0xBAF7,0x62F3,0x63F3,0x64F3,0x65F3,0xBEF7,0xBCF7,0xA1BA,0x66F3,0xBFF7,0x67F3,0xC0F7,0x68F3,0x69F3,0x6AF3,0xC2F7,0xC1F7,0xC4F7,0x6BF3,0x6CF3,0xC3F7,0x6DF3,0x6EF3,0x6FF3,0x70F3,0x71F3,0xC5F7,0xC6F7,0x72F3,0x73F3,0x74F3,0x75F3,0xC7F7,0x76F3,0xE8CB,0x77F3,0x78F3,0x79F3,0x7AF3,0xDFB8,0x7BF3,0x7CF3,0x7DF3,0x7EF3,0x80F3,0x81F3,0xD4F7,0x82F3,0xD5F7,0x83F3,0x84F3,0x85F3,0x86F3,0xD6F7,0x87F3,0x88F3,0x89F3,0x8AF3,0xD8F7,0x8BF3,0xDAF7,0x8CF3,0xD7F7,0x8DF3,0x8EF3,0x8FF3,0x90F3,0x91F3,0x92F3,0x93F3,0x94F3,0x95F3,0xDBF7,0x96F3,0xD9F7,0x97F3,0x98F3,0x99F3,0x9AF3,0x9BF3,0x9CF3,0x9DF3,0xD7D7,0x9EF3,0x9FF3,0xA0F3,0x40F4,0xDCF7,0x41F4,0x42F4,0x43F4,0x44F4,0x45F4,0x46F4,0xDDF7,0x47F4,0x48F4,0x49F4,0xDEF7,0x4AF4,0x4BF4,0x4CF4,0x4DF4,0x4EF4,0x4FF4,0x50F4,0x51F4,0x52F4,0x53F4,0x54F4,0xDFF7,0x55F4,0x56F4,0x57F4,0xE0F7,0x58F4,0x59F4,0x5AF4,0x5BF4,0x5CF4,0x5DF4,0x5EF4,0x5FF4,0x60F4,0x61F4,0x62F4,0xCBDB,0x63F4,0x64F4,0xAAD8,0x65F4,0x66F4,0x67F4,0x68F4,0x69F4,0x6AF4,0x6BF4,0x6CF4,0xF7E5,0xEDB9,0x6DF4,0x6EF4,0x6FF4,0x70F4,0xFDBF,0xEABB,0xC9F7,0xC7C6,0xC8F7,0x71F4,0xCAF7,0xCCF7,0xCBF7,0x72F4,0x73F4,0x74F4,0xCDF7,0x75F4,0xBACE,0x76F4,0xCEF7,0x77F4,0x78F4,0xA7C4,0x79F4,0x7AF4,0x7BF4,0x7CF4,0x7DF4,0x7EF4,0x80F4,0x81F4,0x82F4,0x83F4,0x84F4,0x85F4,0x86F4,0x87F4,0x88F4,0x89F4,0x8AF4,0x8BF4,0x8CF4,0x8DF4,0x8EF4,0x8FF4,0x90F4,0x91F4,0x92F4,0x93F4,0x94F4,0x95F4,0x96F4,0x97F4,0x98F4,0x99F4,0x9AF4,0x9BF4,0x9CF4,0x9DF4,0x9EF4,0x9FF4,0xA0F4,0x40F5,0x41F5,0x42F5,0x43F5,0x44F5,0x45F5,0x46F5,0x47F5,0x48F5,0x49F5,0x4AF5,0x4BF5,0x4CF5,0x4DF5,0x4EF5,0x4FF5,0x50F5,0x51F5,0x52F5,0x53F5,0x54F5,0x55F5,0x56F5,0x57F5,0x58F5,0x59F5,0x5AF5,0x5BF5,0x5CF5,0x5DF5,0x5EF5,0x5FF5,0x60F5,0x61F5,0x62F5,0x63F5,0x64F5,0x65F5,0x66F5,0x67F5,0x68F5,0x69F5,0x6AF5,0x6BF5,0x6CF5,0x6DF5,0x6EF5,0x6FF5,0x70F5,0x71F5,0x72F5,0x73F5,0x74F5,0x75F5,0x76F5,0x77F5,0x78F5,0x79F5,0x7AF5,0x7BF5,0x7CF5,0x7DF5,0x7EF5,0x80F5,0x81F5,0x82F5,0x83F5,0x84F5,0x85F5,0x86F5,0x87F5,0x88F5,0x89F5,0x8AF5,0x8BF5,0x8CF5,0x8DF5,0x8EF5,0x8FF5,0x90F5,0x91F5,0x92F5,0x93F5,0x94F5,0x95F5,0x96F5,0x97F5,0x98F5,0x99F5,0x9AF5,0x9BF5,0x9CF5,0x9DF5,0x9EF5,0x9FF5,0xA0F5,0x40F6,0x41F6,0x42F6,0x43F6,0x44F6,0x45F6,0x46F6,0x47F6,0x48F6,0x49F6,0x4AF6,0x4BF6,0x4CF6,0x4DF6,0x4EF6,0x4FF6,0x50F6,0x51F6,0x52F6,0x53F6,0x54F6,0x55F6,0x56F6,0x57F6,0x58F6,0x59F6,0x5AF6,0x5BF6,0x5CF6,0x5DF6,0x5EF6,0x5FF6,0x60F6,0x61F6,0x62F6,0x63F6,0x64F6,0x65F6,0x66F6,0x67F6,0x68F6,0x69F6,0x6AF6,0x6BF6,0x6CF6,0x6DF6,0x6EF6,0x6FF6,0x70F6,0x71F6,0x72F6,0x73F6,0x74F6,0x75F6,0x76F6,0x77F6,0x78F6,0x79F6,0x7AF6,0x7BF6,0x7CF6,0x7DF6,0x7EF6,0x80F6,0x81F6,0x82F6,0x83F6,0x84F6,0x85F6,0x86F6,0x87F6,0x88F6,0x89F6,0x8AF6,0x8BF6,0x8CF6,0x8DF6,0x8EF6,0x8FF6,0x90F6,0x91F6,0x92F6,0x93F6,0x94F6,0x95F6,0x96F6,0x97F6,0x98F6,0x99F6,0x9AF6,0x9BF6,0x9CF6,0x9DF6,0x9EF6,0x9FF6,0xA0F6,0x40F7,0x41F7,0x42F7,0x43F7,0x44F7,0x45F7,0x46F7,0x47F7,0x48F7,0x49F7,0x4AF7,0x4BF7,0x4CF7,0x4DF7,0x4EF7,0x4FF7,0x50F7,0x51F7,0x52F7,0x53F7,0x54F7,0x55F7,0x56F7,0x57F7,0x58F7,0x59F7,0x5AF7,0x5BF7,0x5CF7,0x5DF7,0x5EF7,0x5FF7,0x60F7,0x61F7,0x62F7,0x63F7,0x64F7,0x65F7,0x66F7,0x67F7,0x68F7,0x69F7,0x6AF7,0x6BF7,0x6CF7,0x6DF7,0x6EF7,0x6FF7,0x70F7,0x71F7,0x72F7,0x73F7,0x74F7,0x75F7,0x76F7,0x77F7,0x78F7,0x79F7,0x7AF7,0x7BF7,0x7CF7,0x7DF7,0x7EF7,0x80F7,0xE3D3,0x81F7,0x82F7,0xCFF6,0x83F7,0xB3C2,0xD0F6,0x84F7,0x85F7,0xD1F6,0xD2F6,0xD3F6,0xD4F6,0x86F7,0x87F7,0xD6F6,0x88F7,0xABB1,0xD7F6,0x89F7,0xD8F6,0xD9F6,0xDAF6,0x8AF7,0xDBF6,0xDCF6,0x8BF7,0x8CF7,0x8DF7,0x8EF7,0xDDF6,0xDEF6,0xCACF,0x8FF7,0xDFF6,0xE0F6,0xE1F6,0xE2F6,0xE3F6,0xE4F6,0xF0C0,0xE5F6,0xE6F6,0xE7F6,0xE8F6,0xE9F6,0x90F7,0xEAF6,0x91F7,0xEBF6,0xECF6,0x92F7,0xEDF6,0xEEF6,0xEFF6,0xF0F6,0xF1F6,0xF2F6,0xF3F6,0xF4F6,0xA8BE,0x93F7,0xF5F6,0xF6F6,0xF7F6,0xF8F6,0x94F7,0x95F7,0x96F7,0x97F7,0x98F7,0xFAC8,0xF9F6,0xFAF6,0xFBF6,0xFCF6,0x99F7,0x9AF7,0xFDF6,0xFEF6,0xA1F7,0xA2F7,0xA3F7,0xA4F7,0xA5F7,0x9BF7,0x9CF7,0xA6F7,0xA7F7,0xA8F7,0xEEB1,0xA9F7,0xAAF7,0xABF7,0x9DF7,0x9EF7,0xACF7,0xADF7,0xDBC1,0xAEF7,0x9FF7,0xA0F7,0xAFF7,0x40F8,0x41F8,0x42F8,0x43F8,0x44F8,0x45F8,0x46F8,0x47F8,0x48F8,0x49F8,0x4AF8,0x4BF8,0x4CF8,0x4DF8,0x4EF8,0x4FF8,0x50F8,0x51F8,0x52F8,0x53F8,0x54F8,0x55F8,0x56F8,0x57F8,0x58F8,0x59F8,0x5AF8,0x5BF8,0x5CF8,0x5DF8,0x5EF8,0x5FF8,0x60F8,0x61F8,0x62F8,0x63F8,0x64F8,0x65F8,0x66F8,0x67F8,0x68F8,0x69F8,0x6AF8,0x6BF8,0x6CF8,0x6DF8,0x6EF8,0x6FF8,0x70F8,0x71F8,0x72F8,0x73F8,0x74F8,0x75F8,0x76F8,0x77F8,0x78F8,0x79F8,0x7AF8,0x7BF8,0x7CF8,0x7DF8,0x7EF8,0x80F8,0x81F8,0x82F8,0x83F8,0x84F8,0x85F8,0x86F8,0x87F8,0x88F8,0x89F8,0x8AF8,0x8BF8,0x8CF8,0x8DF8,0x8EF8,0x8FF8,0x90F8,0x91F8,0x92F8,0x93F8,0x94F8,0x95F8,0x96F8,0x97F8,0x98F8,0x99F8,0x9AF8,0x9BF8,0x9CF8,0x9DF8,0x9EF8,0x9FF8,0xA0F8,0x40F9,0x41F9,0x42F9,0x43F9,0x44F9,0x45F9,0x46F9,0x47F9,0x48F9,0x49F9,0x4AF9,0x4BF9,0x4CF9,0x4DF9,0x4EF9,0x4FF9,0x50F9,0x51F9,0x52F9,0x53F9,0x54F9,0x55F9,0x56F9,0x57F9,0x58F9,0x59F9,0x5AF9,0x5BF9,0x5CF9,0x5DF9,0x5EF9,0x5FF9,0x60F9,0x61F9,0x62F9,0x63F9,0x64F9,0x65F9,0x66F9,0x67F9,0x68F9,0x69F9,0x6AF9,0x6BF9,0x6CF9,0x6DF9,0x6EF9,0x6FF9,0x70F9,0x71F9,0x72F9,0x73F9,0x74F9,0x75F9,0x76F9,0x77F9,0x78F9,0x79F9,0x7AF9,0x7BF9,0x7CF9,0x7DF9,0x7EF9,0x80F9,0x81F9,0x82F9,0x83F9,0x84F9,0x85F9,0x86F9,0x87F9,0x88F9,0x89F9,0x8AF9,0x8BF9,0x8CF9,0x8DF9,0x8EF9,0x8FF9,0x90F9,0x91F9,0x92F9,0x93F9,0x94F9,0x95F9,0x96F9,0x97F9,0x98F9,0x99F9,0x9AF9,0x9BF9,0x9CF9,0x9DF9,0x9EF9,0x9FF9,0xA0F9,0x40FA,0x41FA,0x42FA,0x43FA,0x44FA,0x45FA,0x46FA,0x47FA,0x48FA,0x49FA,0x4AFA,0x4BFA,0x4CFA,0x4DFA,0x4EFA,0x4FFA,0x50FA,0x51FA,0x52FA,0x53FA,0x54FA,0x55FA,0x56FA,0x57FA,0x58FA,0x59FA,0x5AFA,0x5BFA,0x5CFA,0x5DFA,0x5EFA,0x5FFA,0x60FA,0x61FA,0x62FA,0x63FA,0x64FA,0x65FA,0x66FA,0x67FA,0x68FA,0x69FA,0x6AFA,0x6BFA,0x6CFA,0x6DFA,0x6EFA,0x6FFA,0x70FA,0x71FA,0x72FA,0x73FA,0x74FA,0x75FA,0x76FA,0x77FA,0x78FA,0x79FA,0x7AFA,0x7BFA,0x7CFA,0x7DFA,0x7EFA,0x80FA,0x81FA,0x82FA,0x83FA,0x84FA,0x85FA,0x86FA,0x87FA,0x88FA,0x89FA,0x8AFA,0x8BFA,0x8CFA,0x8DFA,0x8EFA,0x8FFA,0x90FA,0x91FA,0x92FA,0x93FA,0x94FA,0x95FA,0x96FA,0x97FA,0x98FA,0x99FA,0x9AFA,0x9BFA,0x9CFA,0x9DFA,0x9EFA,0x9FFA,0xA0FA,0x40FB,0x41FB,0x42FB,0x43FB,0x44FB,0x45FB,0x46FB,0x47FB,0x48FB,0x49FB,0x4AFB,0x4BFB,0x4CFB,0x4DFB,0x4EFB,0x4FFB,0x50FB,0x51FB,0x52FB,0x53FB,0x54FB,0x55FB,0x56FB,0x57FB,0x58FB,0x59FB,0x5AFB,0x5BFB,0xF1C4,0xAFF0,0xA6BC,0xB0F0,0xF9C3,0x5CFB,0xB8C5,0xBBD1,0x5DFB,0xB1F0,0xB2F0,0xB3F0,0xB4F0,0xB5F0,0xBCD1,0x5EFB,0xECD1,0x5FFB,0xB7F0,0xB6F0,0xA7D4,0x60FB,0xD2CD,0xB8F0,0xBAF0,0xB9F0,0xBBF0,0xBCF0,0x61FB,0x62FB,0xEBB8,0xBDF0,0xE8BA,0x63FB,0xBEF0,0xBFF0,0xE9BE,0xC0F0,0xECB6,0xC1F0,0xC2F0,0xC3F0,0xC4F0,0xB5C8,0xC5F0,0xC6F0,0x64FB,0xC7F0,0xF4C5,0x65FB,0xC8F0,0x66FB,0x67FB,0x68FB,0xC9F0,0x69FB,0xCAF0,0xBDF7,0x6AFB,0xCBF0,0xCCF0,0xCDF0,0x6BFB,0xCEF0,0x6CFB,0x6DFB,0x6EFB,0x6FFB,0xCFF0,0xD7BA,0x70FB,0xD0F0,0xD1F0,0xD2F0,0xD3F0,0xD4F0,0xD5F0,0xD6F0,0xD8F0,0x71FB,0x72FB,0xA5D3,0xD7F0,0x73FB,0xD9F0,0x74FB,0x75FB,0x76FB,0x77FB,0x78FB,0x79FB,0x7AFB,0x7BFB,0x7CFB,0x7DFB,0xBAF5,0xB9C2,0x7EFB,0x80FB,0xE4F7,0x81FB,0x82FB,0x83FB,0x84FB,0xE5F7,0xE6F7,0x85FB,0x86FB,0xE7F7,0x87FB,0x88FB,0x89FB,0x8AFB,0x8BFB,0x8CFB,0xE8F7,0xB4C2,0x8DFB,0x8EFB,0x8FFB,0x90FB,0x91FB,0x92FB,0x93FB,0x94FB,0x95FB,0xEAF7,0x96FB,0xEBF7,0x97FB,0x98FB,0x99FB,0x9AFB,0x9BFB,0x9CFB,0xF3C2,0x9DFB,0x9EFB,0x9FFB,0xA0FB,0x40FC,0x41FC,0x42FC,0x43FC,0x44FC,0x45FC,0x46FC,0x47FC,0x48FC,0xF0F4,0x49FC,0x4AFC,0x4BFC,0xEFF4,0x4CFC,0x4DFC,0xE9C2,0x4EFC,0xE1F7,0xE2F7,0x4FFC,0x50FC,0x51FC,0x52FC,0x53FC,0xC6BB,0x54FC,0x55FC,0x56FC,0x57FC,0xE4D9,0x58FC,0x59FC,0x5AFC,0xF2CA,0xE8C0,0xA4F0,0x5BFC,0xDABA,0x5CFC,0x5DFC,0xADC7,0x5EFC,0x5FFC,0x60FC,0xACC4,0x61FC,0x62FC,0xECF7,0xEDF7,0xEEF7,0x63FC,0xF0F7,0xEFF7,0x64FC,0xF1F7,0x65FC,0x66FC,0xF4F7,0x67FC,0xF3F7,0x68FC,0xF2F7,0xF5F7,0x69FC,0x6AFC,0x6BFC,0x6CFC,0xF6F7,0x6DFC,0x6EFC,0x6FFC,0x70FC,0x71FC,0x72FC,0x73FC,0x74FC,0x75FC,0xE9ED,0x76FC,0xEAED,0xEBED,0x77FC,0xBCF6,0x78FC,0x79FC,0x7AFC,0x7BFC,0x7CFC,0x7DFC,0x7EFC,0x80FC,0x81FC,0x82FC,0x83FC,0x84FC,0xBDF6,0x85FC,0xBEF6,0xA6B6,0x86FC,0xBED8,0x87FC,0x88FC,0xC4B9,0x89FC,0x8AFC,0x8BFC,0xBBD8,0x8CFC,0xB1DC,0x8DFC,0x8EFC,0x8FFC,0x90FC,0x91FC,0x92FC,0xF3CA,0x93FC,0xF7F7,0x94FC,0x95FC,0x96FC,0x97FC,0x98FC,0x99FC,0x9AFC,0x9BFC,0x9CFC,0xF8F7,0x9DFC,0x9EFC,0xF9F7,0x9FFC,0xA0FC,0x40FD,0x41FD,0x42FD,0x43FD,0x44FD,0xFBF7,0x45FD,0xFAF7,0x46FD,0xC7B1,0x47FD,0xFCF7,0xFDF7,0x48FD,0x49FD,0x4AFD,0x4BFD,0x4CFD,0xFEF7,0x4DFD,0x4EFD,0x4FFD,0x50FD,0x51FD,0x52FD,0x53FD,0x54FD,0x55FD,0x56FD,0x57FD,0xEBC6,0xB4EC,0x58FD,0x59FD,0x5AFD,0x5BFD,0x5CFD,0x5DFD,0x5EFD,0x5FFD,0x60FD,0x61FD,0x62FD,0x63FD,0x64FD,0x65FD,0x66FD,0x67FD,0x68FD,0x69FD,0x6AFD,0x6BFD,0x6CFD,0x6DFD,0x6EFD,0x6FFD,0x70FD,0x71FD,0x72FD,0x73FD,0x74FD,0x75FD,0x76FD,0x77FD,0x78FD,0x79FD,0x7AFD,0x7BFD,0x7CFD,0x7DFD,0x7EFD,0x80FD,0x81FD,0x82FD,0x83FD,0x84FD,0x85FD,0xDDB3,0xB3F6,0x86FD,0x87FD,0xB4F6,0xE4C1,0xB5F6,0xB6F6,0xB7F6,0xB8F6,0xB9F6,0xBAF6,0xA3C8,0xBBF6,0x88FD,0x89FD,0x8AFD,0x8BFD,0x8CFD,0x8DFD,0x8EFD,0x8FFD,0x90FD,0x91FD,0x92FD,0x93FD,0xFAC1,0xA8B9,0xE8ED,0x94FD,0x95FD,0x96FD,0xEAB9,0xDFD9,0x97FD,0x98FD,0x99FD,0x9AFD,0x9BFD,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0x37A43184,0xA1AA,0xA2AA,0xA3AA,0xA4AA,0xA5AA,0xA6AA,0xA7AA,0xA8AA,0xA9AA,0xAAAA,0xABAA,0xACAA,0xADAA,0xAEAA,0xAFAA,0xB0AA,0xB1AA,0xB2AA,0xB3AA,0xB4AA,0xB5AA,0xB6AA,0xB7AA,0xB8AA,0xB9AA,0xBAAA,0xBBAA,0xBCAA,0xBDAA,0xBEAA,0xBFAA,0xC0AA,0xC1AA,0xC2AA,0xC3AA,0xC4AA,0xC5AA,0xC6AA,0xC7AA,0xC8AA,0xC9AA,0xCAAA,0xCBAA,0xCCAA,0xCDAA,0xCEAA,0xCFAA,0xD0AA,0xD1AA,0xD2AA,0xD3AA,0xD4AA,0xD5AA,0xD6AA,0xD7AA,0xD8AA,0xD9AA,0xDAAA,0xDBAA,0xDCAA,0xDDAA,0xDEAA,0xDFAA,0xE0AA,0xE1AA,0xE2AA,0xE3AA,0xE4AA,0xE5AA,0xE6AA,0xE7AA,0xE8AA,0xE9AA,0xEAAA,0xEBAA,0xECAA,0xEDAA,0xEEAA,0xEFAA,0xF0AA,0xF1AA,0xF2AA,0xF3AA,0xF4AA,0xF5AA,0xF6AA,0xF7AA,0xF8AA,0xF9AA,0xFAAA,0xFBAA,0xFCAA,0xFDAA,0xFEAA,0xA1AB,0xA2AB,0xA3AB,0xA4AB,0xA5AB,0xA6AB,0xA7AB,0xA8AB,0xA9AB,0xAAAB,0xABAB,0xACAB,0xADAB,0xAEAB,0xAFAB,0xB0AB,0xB1AB,0xB2AB,0xB3AB,0xB4AB,0xB5AB,0xB6AB,0xB7AB,0xB8AB,0xB9AB,0xBAAB,0xBBAB,0xBCAB,0xBDAB,0xBEAB,0xBFAB,0xC0AB,0xC1AB,0xC2AB,0xC3AB,0xC4AB,0xC5AB,0xC6AB,0xC7AB,0xC8AB,0xC9AB,0xCAAB,0xCBAB,0xCCAB,0xCDAB,0xCEAB,0xCFAB,0xD0AB,0xD1AB,0xD2AB,0xD3AB,0xD4AB,0xD5AB,0xD6AB,0xD7AB,0xD8AB,0xD9AB,0xDAAB,0xDBAB,0xDCAB,0xDDAB,0xDEAB,0xDFAB,0xE0AB,0xE1AB,0xE2AB,0xE3AB,0xE4AB,0xE5AB,0xE6AB,0xE7AB,0xE8AB,0xE9AB,0xEAAB,0xEBAB,0xECAB,0xEDAB,0xEEAB,0xEFAB,0xF0AB,0xF1AB,0xF2AB,0xF3AB,0xF4AB,0xF5AB,0xF6AB,0xF7AB,0xF8AB,0xF9AB,0xFAAB,0xFBAB,0xFCAB,0xFDAB,0xFEAB,0xA1AC,0xA2AC,0xA3AC,0xA4AC,0xA5AC,0xA6AC,0xA7AC,0xA8AC,0xA9AC,0xAAAC,0xABAC,0xACAC,0xADAC,0xAEAC,0xAFAC,0xB0AC,0xB1AC,0xB2AC,0xB3AC,0xB4AC,0xB5AC,0xB6AC,0xB7AC,0xB8AC,0xB9AC,0xBAAC,0xBBAC,0xBCAC,0xBDAC,0xBEAC,0xBFAC,0xC0AC,0xC1AC,0xC2AC,0xC3AC,0xC4AC,0xC5AC,0xC6AC,0xC7AC,0xC8AC,0xC9AC,0xCAAC,0xCBAC,0xCCAC,0xCDAC,0xCEAC,0xCFAC,0xD0AC,0xD1AC,0xD2AC,0xD3AC,0xD4AC,0xD5AC,0xD6AC,0xD7AC,0xD8AC,0xD9AC,0xDAAC,0xDBAC,0xDCAC,0xDDAC,0xDEAC,0xDFAC,0xE0AC,0xE1AC,0xE2AC,0xE3AC,0xE4AC,0xE5AC,0xE6AC,0xE7AC,0xE8AC,0xE9AC,0xEAAC,0xEBAC,0xECAC,0xEDAC,0xEEAC,0xEFAC,0xF0AC,0xF1AC,0xF2AC,0xF3AC,0xF4AC,0xF5AC,0xF6AC,0xF7AC,0xF8AC,0xF9AC,0xFAAC,0xFBAC,0xFCAC,0xFDAC,0xFEAC,0xA1AD,0xA2AD,0xA3AD,0xA4AD,0xA5AD,0xA6AD,0xA7AD,0xA8AD,0xA9AD,0xAAAD,0xABAD,0xACAD,0xADAD,0xAEAD,0xAFAD,0xB0AD,0xB1AD,0xB2AD,0xB3AD,0xB4AD,0xB5AD,0xB6AD,0xB7AD,0xB8AD,0xB9AD,0xBAAD,0xBBAD,0xBCAD,0xBDAD,0xBEAD,0xBFAD,0xC0AD,0xC1AD,0xC2AD,0xC3AD,0xC4AD,0xC5AD,0xC6AD,0xC7AD,0xC8AD,0xC9AD,0xCAAD,0xCBAD,0xCCAD,0xCDAD,0xCEAD,0xCFAD,0xD0AD,0xD1AD,0xD2AD,0xD3AD,0xD4AD,0xD5AD,0xD6AD,0xD7AD,0xD8AD,0xD9AD,0xDAAD,0xDBAD,0xDCAD,0xDDAD,0xDEAD,0xDFAD,0xE0AD,0xE1AD,0xE2AD,0xE3AD,0xE4AD,0xE5AD,0xE6AD,0xE7AD,0xE8AD,0xE9AD,0xEAAD,0xEBAD,0xECAD,0xEDAD,0xEEAD,0xEFAD,0xF0AD,0xF1AD,0xF2AD,0xF3AD,0xF4AD,0xF5AD,0xF6AD,0xF7AD,0xF8AD,0xF9AD,0xFAAD,0xFBAD,0xFCAD,0xFDAD,0xFEAD,0xA1AE,0xA2AE,0xA3AE,0xA4AE,0xA5AE,0xA6AE,0xA7AE,0xA8AE,0xA9AE,0xAAAE,0xABAE,0xACAE,0xADAE,0xAEAE,0xAFAE,0xB0AE,0xB1AE,0xB2AE,0xB3AE,0xB4AE,0xB5AE,0xB6AE,0xB7AE,0xB8AE,0xB9AE,0xBAAE,0xBBAE,0xBCAE,0xBDAE,0xBEAE,0xBFAE,0xC0AE,0xC1AE,0xC2AE,0xC3AE,0xC4AE,0xC5AE,0xC6AE,0xC7AE,0xC8AE,0xC9AE,0xCAAE,0xCBAE,0xCCAE,0xCDAE,0xCEAE,0xCFAE,0xD0AE,0xD1AE,0xD2AE,0xD3AE,0xD4AE,0xD5AE,0xD6AE,0xD7AE,0xD8AE,0xD9AE,0xDAAE,0xDBAE,0xDCAE,0xDDAE,0xDEAE,0xDFAE,0xE0AE,0xE1AE,0xE2AE,0xE3AE,0xE4AE,0xE5AE,0xE6AE,0xE7AE,0xE8AE,0xE9AE,0xEAAE,0xEBAE,0xECAE,0xEDAE,0xEEAE,0xEFAE,0xF0AE,0xF1AE,0xF2AE,0xF3AE,0xF4AE,0xF5AE,0xF6AE,0xF7AE,0xF8AE,0xF9AE,0xFAAE,0xFBAE,0xFCAE,0xFDAE,0xFEAE,0xA1AF,0xA2AF,0xA3AF,0xA4AF,0xA5AF,0xA6AF,0xA7AF,0xA8AF,0xA9AF,0xAAAF,0xABAF,0xACAF,0xADAF,0xAEAF,0xAFAF,0xB0AF,0xB1AF,0xB2AF,0xB3AF,0xB4AF,0xB5AF,0xB6AF,0xB7AF,0xB8AF,0xB9AF,0xBAAF,0xBBAF,0xBCAF,0xBDAF,0xBEAF,0xBFAF,0xC0AF,0xC1AF,0xC2AF,0xC3AF,0xC4AF,0xC5AF,0xC6AF,0xC7AF,0xC8AF,0xC9AF,0xCAAF,0xCBAF,0xCCAF,0xCDAF,0xCEAF,0xCFAF,0xD0AF,0xD1AF,0xD2AF,0xD3AF,0xD4AF,0xD5AF,0xD6AF,0xD7AF,0xD8AF,0xD9AF,0xDAAF,0xDBAF,0xDCAF,0xDDAF,0xDEAF,0xDFAF,0xE0AF,0xE1AF,0xE2AF,0xE3AF,0xE4AF,0xE5AF,0xE6AF,0xE7AF,0xE8AF,0xE9AF,0xEAAF,0xEBAF,0xECAF,0xEDAF,0xEEAF,0xEFAF,0xF0AF,0xF1AF,0xF2AF,0xF3AF,0xF4AF,0xF5AF,0xF6AF,0xF7AF,0xF8AF,0xF9AF,0xFAAF,0xFBAF,0xFCAF,0xFDAF,0xFEAF,0xA1F8,0xA2F8,0xA3F8,0xA4F8,0xA5F8,0xA6F8,0xA7F8,0xA8F8,0xA9F8,0xAAF8,0xABF8,0xACF8,0xADF8,0xAEF8,0xAFF8,0xB0F8,0xB1F8,0xB2F8,0xB3F8,0xB4F8,0xB5F8,0xB6F8,0xB7F8,0xB8F8,0xB9F8,0xBAF8,0xBBF8,0xBCF8,0xBDF8,0xBEF8,0xBFF8,0xC0F8,0xC1F8,0xC2F8,0xC3F8,0xC4F8,0xC5F8,0xC6F8,0xC7F8,0xC8F8,0xC9F8,0xCAF8,0xCBF8,0xCCF8,0xCDF8,0xCEF8,0xCFF8,0xD0F8,0xD1F8,0xD2F8,0xD3F8,0xD4F8,0xD5F8,0xD6F8,0xD7F8,0xD8F8,0xD9F8,0xDAF8,0xDBF8,0xDCF8,0xDDF8,0xDEF8,0xDFF8,0xE0F8,0xE1F8,0xE2F8,0xE3F8,0xE4F8,0xE5F8,0xE6F8,0xE7F8,0xE8F8,0xE9F8,0xEAF8,0xEBF8,0xECF8,0xEDF8,0xEEF8,0xEFF8,0xF0F8,0xF1F8,0xF2F8,0xF3F8,0xF4F8,0xF5F8,0xF6F8,0xF7F8,0xF8F8,0xF9F8,0xFAF8,0xFBF8,0xFCF8,0xFDF8,0xFEF8,0xA1F9,0xA2F9,0xA3F9,0xA4F9,0xA5F9,0xA6F9,0xA7F9,0xA8F9,0xA9F9,0xAAF9,0xABF9,0xACF9,0xADF9,0xAEF9,0xAFF9,0xB0F9,0xB1F9,0xB2F9,0xB3F9,0xB4F9,0xB5F9,0xB6F9,0xB7F9,0xB8F9,0xB9F9,0xBAF9,0xBBF9,0xBCF9,0xBDF9,0xBEF9,0xBFF9,0xC0F9,0xC1F9,0xC2F9,0xC3F9,0xC4F9,0xC5F9,0xC6F9,0xC7F9,0xC8F9,0xC9F9,0xCAF9,0xCBF9,0xCCF9,0xCDF9,0xCEF9,0xCFF9,0xD0F9,0xD1F9,0xD2F9,0xD3F9,0xD4F9,0xD5F9,0xD6F9,0xD7F9,0xD8F9,0xD9F9,0xDAF9,0xDBF9,0xDCF9,0xDDF9,0xDEF9,0xDFF9,0xE0F9,0xE1F9,0xE2F9,0xE3F9,0xE4F9,0xE5F9,0xE6F9,0xE7F9,0xE8F9,0xE9F9,0xEAF9,0xEBF9,0xECF9,0xEDF9,0xEEF9,0xEFF9,0xF0F9,0xF1F9,0xF2F9,0xF3F9,0xF4F9,0xF5F9,0xF6F9,0xF7F9,0xF8F9,0xF9F9,0xFAF9,0xFBF9,0xFCF9,0xFDF9,0xFEF9,0xA1FA,0xA2FA,0xA3FA,0xA4FA,0xA5FA,0xA6FA,0xA7FA,0xA8FA,0xA9FA,0xAAFA,0xABFA,0xACFA,0xADFA,0xAEFA,0xAFFA,0xB0FA,0xB1FA,0xB2FA,0xB3FA,0xB4FA,0xB5FA,0xB6FA,0xB7FA,0xB8FA,0xB9FA,0xBAFA,0xBBFA,0xBCFA,0xBDFA,0xBEFA,0xBFFA,0xC0FA,0xC1FA,0xC2FA,0xC3FA,0xC4FA,0xC5FA,0xC6FA,0xC7FA,0xC8FA,0xC9FA,0xCAFA,0xCBFA,0xCCFA,0xCDFA,0xCEFA,0xCFFA,0xD0FA,0xD1FA,0xD2FA,0xD3FA,0xD4FA,0xD5FA,0xD6FA,0xD7FA,0xD8FA,0xD9FA,0xDAFA,0xDBFA,0xDCFA,0xDDFA,0xDEFA,0xDFFA,0xE0FA,0xE1FA,0xE2FA,0xE3FA,0xE4FA,0xE5FA,0xE6FA,0xE7FA,0xE8FA,0xE9FA,0xEAFA,0xEBFA,0xECFA,0xEDFA,0xEEFA,0xEFFA,0xF0FA,0xF1FA,0xF2FA,0xF3FA,0xF4FA,0xF5FA,0xF6FA,0xF7FA,0xF8FA,0xF9FA,0xFAFA,0xFBFA,0xFCFA,0xFDFA,0xFEFA,0xA1FB,0xA2FB,0xA3FB,0xA4FB,0xA5FB,0xA6FB,0xA7FB,0xA8FB,0xA9FB,0xAAFB,0xABFB,0xACFB,0xADFB,0xAEFB,0xAFFB,0xB0FB,0xB1FB,0xB2FB,0xB3FB,0xB4FB,0xB5FB,0xB6FB,0xB7FB,0xB8FB,0xB9FB,0xBAFB,0xBBFB,0xBCFB,0xBDFB,0xBEFB,0xBFFB,0xC0FB,0xC1FB,0xC2FB,0xC3FB,0xC4FB,0xC5FB,0xC6FB,0xC7FB,0xC8FB,0xC9FB,0xCAFB,0xCBFB,0xCCFB,0xCDFB,0xCEFB,0xCFFB,0xD0FB,0xD1FB,0xD2FB,0xD3FB,0xD4FB,0xD5FB,0xD6FB,0xD7FB,0xD8FB,0xD9FB,0xDAFB,0xDBFB,0xDCFB,0xDDFB,0xDEFB,0xDFFB,0xE0FB,0xE1FB,0xE2FB,0xE3FB,0xE4FB,0xE5FB,0xE6FB,0xE7FB,0xE8FB,0xE9FB,0xEAFB,0xEBFB,0xECFB,0xEDFB,0xEEFB,0xEFFB,0xF0FB,0xF1FB,0xF2FB,0xF3FB,0xF4FB,0xF5FB,0xF6FB,0xF7FB,0xF8FB,0xF9FB,0xFAFB,0xFBFB,0xFCFB,0xFDFB,0xFEFB,0xA1FC,0xA2FC,0xA3FC,0xA4FC,0xA5FC,0xA6FC,0xA7FC,0xA8FC,0xA9FC,0xAAFC,0xABFC,0xACFC,0xADFC,0xAEFC,0xAFFC,0xB0FC,0xB1FC,0xB2FC,0xB3FC,0xB4FC,0xB5FC,0xB6FC,0xB7FC,0xB8FC,0xB9FC,0xBAFC,0xBBFC,0xBCFC,0xBDFC,0xBEFC,0xBFFC,0xC0FC,0xC1FC,0xC2FC,0xC3FC,0xC4FC,0xC5FC,0xC6FC,0xC7FC,0xC8FC,0xC9FC,0xCAFC,0xCBFC,0xCCFC,0xCDFC,0xCEFC,0xCFFC,0xD0FC,0xD1FC,0xD2FC,0xD3FC,0xD4FC,0xD5FC,0xD6FC,0xD7FC,0xD8FC,0xD9FC,0xDAFC,0xDBFC,0xDCFC,0xDDFC,0xDEFC,0xDFFC,0xE0FC,0xE1FC,0xE2FC,0xE3FC,0xE4FC,0xE5FC,0xE6FC,0xE7FC,0xE8FC,0xE9FC,0xEAFC,0xEBFC,0xECFC,0xEDFC,0xEEFC,0xEFFC,0xF0FC,0xF1FC,0xF2FC,0xF3FC,0xF4FC,0xF5FC,0xF6FC,0xF7FC,0xF8FC,0xF9FC,0xFAFC,0xFBFC,0xFCFC,0xFDFC,0xFEFC,0xA1FD,0xA2FD,0xA3FD,0xA4FD,0xA5FD,0xA6FD,0xA7FD,0xA8FD,0xA9FD,0xAAFD,0xABFD,0xACFD,0xADFD,0xAEFD,0xAFFD,0xB0FD,0xB1FD,0xB2FD,0xB3FD,0xB4FD,0xB5FD,0xB6FD,0xB7FD,0xB8FD,0xB9FD,0xBAFD,0xBBFD,0xBCFD,0xBDFD,0xBEFD,0xBFFD,0xC0FD,0xC1FD,0xC2FD,0xC3FD,0xC4FD,0xC5FD,0xC6FD,0xC7FD,0xC8FD,0xC9FD,0xCAFD,0xCBFD,0xCCFD,0xCDFD,0xCEFD,0xCFFD,0xD0FD,0xD1FD,0xD2FD,0xD3FD,0xD4FD,0xD5FD,0xD6FD,0xD7FD,0xD8FD,0xD9FD,0xDAFD,0xDBFD,0xDCFD,0xDDFD,0xDEFD,0xDFFD,0xE0FD,0xE1FD,0xE2FD,0xE3FD,0xE4FD,0xE5FD,0xE6FD,0xE7FD,0xE8FD,0xE9FD,0xEAFD,0xEBFD,0xECFD,0xEDFD,0xEEFD,0xEFFD,0xF0FD,0xF1FD,0xF2FD,0xF3FD,0xF4FD,0xF5FD,0xF6FD,0xF7FD,0xF8FD,0xF9FD,0xFAFD,0xFBFD,0xFCFD,0xFDFD,0xFEFD,0xA1FE,0xA2FE,0xA3FE,0xA4FE,0xA5FE,0xA6FE,0xA7FE,0xA8FE,0xA9FE,0xAAFE,0xABFE,0xACFE,0xADFE,0xAEFE,0xAFFE,0xB0FE,0xB1FE,0xB2FE,0xB3FE,0xB4FE,0xB5FE,0xB6FE,0xB7FE,0xB8FE,0xB9FE,0xBAFE,0xBBFE,0xBCFE,0xBDFE,0xBEFE,0xBFFE,0xC0FE,0xC1FE,0xC2FE,0xC3FE,0xC4FE,0xC5FE,0xC6FE,0xC7FE,0xC8FE,0xC9FE,0xCAFE,0xCBFE,0xCCFE,0xCDFE,0xCEFE,0xCFFE,0xD0FE,0xD1FE,0xD2FE,0xD3FE,0xD4FE,0xD5FE,0xD6FE,0xD7FE,0xD8FE,0xD9FE,0xDAFE,0xDBFE,0xDCFE,0xDDFE,0xDEFE,0xDFFE,0xE0FE,0xE1FE,0xE2FE,0xE3FE,0xE4FE,0xE5FE,0xE6FE,0xE7FE,0xE8FE,0xE9FE,0xEAFE,0xEBFE,0xECFE,0xEDFE,0xEEFE,0xEFFE,0xF0FE,0xF1FE,0xF2FE,0xF3FE,0xF4FE,0xF5FE,0xF6FE,0xF7FE,0xF8FE,0xF9FE,0xFAFE,0xFBFE,0xFCFE,0xFDFE,0xFEFE,0x40A1,0x41A1,0x42A1,0x43A1,0x44A1,0x45A1,0x46A1,0x47A1,0x48A1,0x49A1,0x4AA1,0x4BA1,0x4CA1,0x4DA1,0x4EA1,0x4FA1,0x50A1,0x51A1,0x52A1,0x53A1,0x54A1,0x55A1,0x56A1,0x57A1,0x58A1,0x59A1,0x5AA1,0x5BA1,0x5CA1,0x5DA1,0x5EA1,0x5FA1,0x60A1,0x61A1,0x62A1,0x63A1,0x64A1,0x65A1,0x66A1,0x67A1,0x68A1,0x69A1,0x6AA1,0x6BA1,0x6CA1,0x6DA1,0x6EA1,0x6FA1,0x70A1,0x71A1,0x72A1,0x73A1,0x74A1,0x75A1,0x76A1,0x77A1,0x78A1,0x79A1,0x7AA1,0x7BA1,0x7CA1,0x7DA1,0x7EA1,0x80A1,0x81A1,0x82A1,0x83A1,0x84A1,0x85A1,0x86A1,0x87A1,0x88A1,0x89A1,0x8AA1,0x8BA1,0x8CA1,0x8DA1,0x8EA1,0x8FA1,0x90A1,0x91A1,0x92A1,0x93A1,0x94A1,0x95A1,0x96A1,0x97A1,0x98A1,0x99A1,0x9AA1,0x9BA1,0x9CA1,0x9DA1,0x9EA1,0x9FA1,0xA0A1,0x40A2,0x41A2,0x42A2,0x43A2,0x44A2,0x45A2,0x46A2,0x47A2,0x48A2,0x49A2,0x4AA2,0x4BA2,0x4CA2,0x4DA2,0x4EA2,0x4FA2,0x50A2,0x51A2,0x52A2,0x53A2,0x54A2,0x55A2,0x56A2,0x57A2,0x58A2,0x59A2,0x5AA2,0x5BA2,0x5CA2,0x5DA2,0x5EA2,0x5FA2,0x60A2,0x61A2,0x62A2,0x63A2,0x64A2,0x65A2,0x66A2,0x67A2,0x68A2,0x69A2,0x6AA2,0x6BA2,0x6CA2,0x6DA2,0x6EA2,0x6FA2,0x70A2,0x71A2,0x72A2,0x73A2,0x74A2,0x75A2,0x76A2,0x77A2,0x78A2,0x79A2,0x7AA2,0x7BA2,0x7CA2,0x7DA2,0x7EA2,0x80A2,0x81A2,0x82A2,0x83A2,0x84A2,0x85A2,0x86A2,0x87A2,0x88A2,0x89A2,0x8AA2,0x8BA2,0x8CA2,0x8DA2,0x8EA2,0x8FA2,0x90A2,0x91A2,0x92A2,0x93A2,0x94A2,0x95A2,0x96A2,0x97A2,0x98A2,0x99A2,0x9AA2,0x9BA2,0x9CA2,0x9DA2,0x9EA2,0x9FA2,0xA0A2,0x40A3,0x41A3,0x42A3,0x43A3,0x44A3,0x45A3,0x46A3,0x47A3,0x48A3,0x49A3,0x4AA3,0x4BA3,0x4CA3,0x4DA3,0x4EA3,0x4FA3,0x50A3,0x51A3,0x52A3,0x53A3,0x54A3,0x55A3,0x56A3,0x57A3,0x58A3,0x59A3,0x5AA3,0x5BA3,0x5CA3,0x5DA3,0x5EA3,0x5FA3,0x60A3,0x61A3,0x62A3,0x63A3,0x64A3,0x65A3,0x66A3,0x67A3,0x68A3,0x69A3,0x6AA3,0x6BA3,0x6CA3,0x6DA3,0x6EA3,0x6FA3,0x70A3,0x71A3,0x72A3,0x73A3,0x74A3,0x75A3,0x76A3,0x77A3,0x78A3,0x79A3,0x7AA3,0x7BA3,0x7CA3,0x7DA3,0x7EA3,0x80A3,0x81A3,0x82A3,0x83A3,0x84A3,0x85A3,0x86A3,0x87A3,0x88A3,0x89A3,0x8AA3,0x8BA3,0x8CA3,0x8DA3,0x8EA3,0x8FA3,0x90A3,0x91A3,0x92A3,0x93A3,0x94A3,0x95A3,0x96A3,0x97A3,0x98A3,0x99A3,0x9AA3,0x9BA3,0x9CA3,0x9DA3,0x9EA3,0x9FA3,0xA0A3,0x40A4,0x41A4,0x42A4,0x43A4,0x44A4,0x45A4,0x46A4,0x47A4,0x48A4,0x49A4,0x4AA4,0x4BA4,0x4CA4,0x4DA4,0x4EA4,0x4FA4,0x50A4,0x51A4,0x52A4,0x53A4,0x54A4,0x55A4,0x56A4,0x57A4,0x58A4,0x59A4,0x5AA4,0x5BA4,0x5CA4,0x5DA4,0x5EA4,0x5FA4,0x60A4,0x61A4,0x62A4,0x63A4,0x64A4,0x65A4,0x66A4,0x67A4,0x68A4,0x69A4,0x6AA4,0x6BA4,0x6CA4,0x6DA4,0x6EA4,0x6FA4,0x70A4,0x71A4,0x72A4,0x73A4,0x74A4,0x75A4,0x76A4,0x77A4,0x78A4,0x79A4,0x7AA4,0x7BA4,0x7CA4,0x7DA4,0x7EA4,0x80A4,0x81A4,0x82A4,0x83A4,0x84A4,0x85A4,0x86A4,0x87A4,0x88A4,0x89A4,0x8AA4,0x8BA4,0x8CA4,0x8DA4,0x8EA4,0x8FA4,0x90A4,0x91A4,0x92A4,0x93A4,0x94A4,0x95A4,0x96A4,0x97A4,0x98A4,0x99A4,0x9AA4,0x9BA4,0x9CA4,0x9DA4,0x9EA4,0x9FA4,0xA0A4,0x40A5,0x41A5,0x42A5,0x43A5,0x44A5,0x45A5,0x46A5,0x47A5,0x48A5,0x49A5,0x4AA5,0x4BA5,0x4CA5,0x4DA5,0x4EA5,0x4FA5,0x50A5,0x51A5,0x52A5,0x53A5,0x54A5,0x55A5,0x56A5,0x57A5,0x58A5,0x59A5,0x5AA5,0x5BA5,0x5CA5,0x5DA5,0x5EA5,0x5FA5,0x60A5,0x61A5,0x62A5,0x63A5,0x64A5,0x65A5,0x66A5,0x67A5,0x68A5,0x69A5,0x6AA5,0x6BA5,0x6CA5,0x6DA5,0x6EA5,0x6FA5,0x70A5,0x71A5,0x72A5,0x73A5,0x74A5,0x75A5,0x76A5,0x77A5,0x78A5,0x79A5,0x7AA5,0x7BA5,0x7CA5,0x7DA5,0x7EA5,0x80A5,0x81A5,0x82A5,0x83A5,0x84A5,0x85A5,0x86A5,0x87A5,0x88A5,0x89A5,0x8AA5,0x8BA5,0x8CA5,0x8DA5,0x8EA5,0x8FA5,0x90A5,0x91A5,0x92A5,0x93A5,0x94A5,0x95A5,0x96A5,0x97A5,0x98A5,0x99A5,0x9AA5,0x9BA5,0x9CA5,0x9DA5,0x9EA5,0x9FA5,0xA0A5,0x40A6,0x41A6,0x42A6,0x43A6,0x44A6,0x45A6,0x46A6,0x47A6,0x48A6,0x49A6,0x4AA6,0x4BA6,0x4CA6,0x4DA6,0x4EA6,0x4FA6,0x50A6,0x51A6,0x52A6,0x53A6,0x54A6,0x55A6,0x56A6,0x57A6,0x58A6,0x59A6,0x5AA6,0x5BA6,0x5CA6,0x5DA6,0x5EA6,0x5FA6,0x60A6,0x61A6,0x62A6,0x63A6,0x64A6,0x65A6,0x66A6,0x67A6,0x68A6,0x69A6,0x6AA6,0x6BA6,0x6CA6,0x6DA6,0x6EA6,0x6FA6,0x70A6,0x71A6,0x72A6,0x73A6,0x74A6,0x75A6,0x76A6,0x77A6,0x78A6,0x79A6,0x7AA6,0x7BA6,0x7CA6,0x7DA6,0x7EA6,0x80A6,0x81A6,0x82A6,0x83A6,0x84A6,0x85A6,0x86A6,0x87A6,0x88A6,0x89A6,0x8AA6,0x8BA6,0x8CA6,0x8DA6,0x8EA6,0x8FA6,0x90A6,0x91A6,0x92A6,0x93A6,0x94A6,0x95A6,0x96A6,0x97A6,0x98A6,0x99A6,0x9AA6,0x9BA6,0x9CA6,0x9DA6,0x9EA6,0x9FA6,0xA0A6,0x40A7,0x41A7,0x42A7,0x43A7,0x44A7,0x45A7,0x46A7,0x47A7,0x48A7,0x49A7,0x4AA7,0x4BA7,0x4CA7,0x4DA7,0x4EA7,0x4FA7,0x50A7,0x51A7,0x52A7,0x53A7,0x54A7,0x55A7,0x56A7,0x57A7,0x58A7,0x59A7,0x5AA7,0x5BA7,0x5CA7,0x5DA7,0x5EA7,0x5FA7,0x60A7,0x61A7,0x62A7,0x63A7,0x64A7,0x65A7,0x66A7,0x67A7,0x68A7,0x69A7,0x6AA7,0x6BA7,0x6CA7,0x6DA7,0x6EA7,0x6FA7,0x70A7,0x71A7,0x72A7,0x73A7,0x74A7,0x75A7,0x76A7,0x77A7,0x78A7,0x79A7,0x7AA7,0x7BA7,0x7CA7,0x7DA7,0x7EA7,0x80A7,0x81A7,0x82A7,0x83A7,0x84A7,0x85A7,0x86A7,0x87A7,0x88A7,0x89A7,0x8AA7,0x8BA7,0x8CA7,0x8DA7,0x8EA7,0x8FA7,0x90A7,0x91A7,0x92A7,0x93A7,0x94A7,0x95A7,0x96A7,0x97A7,0x98A7,0x99A7,0x9AA7,0x9BA7,0x9CA7,0x9DA7,0x9EA7,0x9FA7,0xA0A7,0xABA2,0xACA2,0xADA2,0xAEA2,0xAFA2,0xB0A2,0x39C73683,0xE4A2,0xEFA2,0xF0A2,0xFDA2,0xFEA2,0xF4A4,0xF5A4,0xF6A4,0xF7A4,0xF8A4,0xF9A4,0xFAA4,0xFBA4,0xFCA4,0xFDA4,0xFEA4,0xF7A5,0xF8A5,0xF9A5,0xFAA5,0xFBA5,0xFCA5,0xFDA5,0xFEA5,0xB9A6,0xBAA6,0xBBA6,0xBCA6,0xBDA6,0xBEA6,0xBFA6,0xC0A6,0xD9A6,0xDAA6,0xDBA6,0xDCA6,0xDDA6,0xDEA6,0xDFA6,0xECA6,0xEDA6,0xF3A6,0xF6A6,0xF7A6,0xF8A6,0xF9A6,0xFAA6,0xFBA6,0xFCA6,0xFDA6,0xFEA6,0xC2A7,0xC3A7,0xC4A7,0xC5A7,0xC6A7,0xC7A7,0xC8A7,0xC9A7,0xCAA7,0xCBA7,0xCCA7,0xCDA7,0xCEA7,0xCFA7,0xD0A7,0xF2A7,0xF3A7,0xF4A7,0xF5A7,0xF6A7,0xF7A7,0xF8A7,0xF9A7,0xFAA7,0xFBA7,0xFCA7,0xFDA7,0xFEA7,0x96A8,0x97A8,0x98A8,0x99A8,0x9AA8,0x9BA8,0x9CA8,0x9DA8,0x9EA8,0x9FA8,0xA0A8,0x37F43581,0x30C83683,0xC1A8,0xC2A8,0xC3A8,0xC4A8,0xEAA8,0xEBA8,0xECA8,0xEDA8,0xEEA8,0xEFA8,0xF0A8,0xF1A8,0xF2A8,0xF3A8,0xF4A8,0xF5A8,0xF6A8,0xF7A8,0xF8A8,0xF9A8,0xFAA8,0xFBA8,0xFCA8,0xFDA8,0xFEA8,0x58A9,0x5BA9,0x5DA9,0x5EA9,0x5FA9,0x31C83683,0x32C83683,0x33C83683,0x34C83683,0x35C83683,0x36C83683,0x37C83683,0x38C83683,0x39C83683,0x30C93683,0x31C93683,0x32C93683,0x33C93683,0x97A9,0x98A9,0x99A9,0x9AA9,0x9BA9,0x9CA9,0x9DA9,0x9EA9,0x9FA9,0xA0A9,0xA1A9,0xA2A9,0xA3A9,0xF0A9,0xF1A9,0xF2A9,0xF3A9,0xF4A9,0xF5A9,0xF6A9,0xF7A9,0xF8A9,0xF9A9,0xFAA9,0xFBA9,0xFCA9,0xFDA9,0xFEA9,0xFAD7,0xFBD7,0xFCD7,0xFDD7,0xFED7,0x34C93683,0x51FE,0x52FE,0x53FE,0x35C93683,0x36C93683,0x37C93683,0x38C93683,0x39C93683,0x59FE,0x30CA3683,0x31CA3683,0x32CA3683,0x33CA3683,0x34CA3683,0x35CA3683,0x36CA3683,0x61FE,0x37CA3683,0x38CA3683,0x39CA3683,0x30CB3683,0x66FE,0x67FE,0x31CB3683,0x32CB3683,0x33CB3683,0x34CB3683,0x6CFE,0x6DFE,0x35CB3683,0x36CB3683,0x37CB3683,0x38CB3683,0x39CB3683,0x30CC3683,0x31CC3683,0x32CC3683,0x76FE,0x33CC3683,0x34CC3683,0x35CC3683,0x36CC3683,0x37CC3683,0x38CC3683,0x39CC3683,0x7EFE,0x30CD3683,0x31CD3683,0x32CD3683,0x33CD3683,0x34CD3683,0x35CD3683,0x36CD3683,0x37CD3683,0x38CD3683,0x39CD3683,0x30CE3683,0x31CE3683,0x32CE3683,0x33CE3683,0x34CE3683,0x35CE3683,0x90FE,0x91FE,0x36CE3683,0x37CE3683,0x38CE3683,0x39CE3683,0x30CF3683,0x31CF3683,0x32CF3683,0x33CF3683,0x34CF3683,0x35CF3683,0x36CF3683,0x37CF3683,0x38CF3683,0x39CF3683,0xA0FE,0x9CFD,0x35853084,0x36853084,0x37853084,0x38853084,0x39853084,0x30863084,0x31863084,0x32863084,0x33863084,0x34863084,0x35863084,0x36863084,0x37863084,0x38863084,0x39863084,0x30873084,0x31873084,0x32873084,0x33873084,0x34873084,0x35873084,0x36873084,0x37873084,0x38873084,0x39873084,0x30883084,0x31883084,0x32883084,0x33883084,0x34883084,0x35883084,0x36883084,0x37883084,0x38883084,0x39883084,0x30893084,0x31893084,0x32893084,0x33893084,0x34893084,0x35893084,0x36893084,0x37893084,0x38893084,0x39893084,0x308A3084,0x318A3084,0x328A3084,0x338A3084,0x348A3084,0x358A3084,0x368A3084,0x378A3084,0x388A3084,0x398A3084,0x308B3084,0x318B3084,0x328B3084,0x338B3084,0x348B3084,0x358B3084,0x368B3084,0x378B3084,0x388B3084,0x398B3084,0x308C3084,0x318C3084,0x328C3084,0x338C3084,0x348C3084,0x358C3084,0x368C3084,0x378C3084,0x388C3084,0x398C3084,0x308D3084,0x9DFD,0x318D3084,0x328D3084,0x338D3084,0x348D3084,0x358D3084,0x368D3084,0x378D3084,0x388D3084,0x398D3084,0x308E3084,0x318E3084,0x328E3084,0x338E3084,0x348E3084,0x358E3084,0x368E3084,0x378E3084,0x388E3084,0x398E3084,0x308F3084,0x318F3084,0x328F3084,0x338F3084,0x348F3084,0x358F3084,0x368F3084,0x378F3084,0x9EFD,0x388F3084,0x398F3084,0x30903084,0x31903084,0x32903084,0x33903084,0x34903084,0x35903084,0x36903084,0x37903084,0x38903084,0x39903084,0x30913084,0x31913084,0x32913084,0x33913084,0x34913084,0x35913084,0x36913084,0x37913084,0x38913084,0x39913084,0x30923084,0x31923084,0x32923084,0x33923084,0x34923084,0x35923084,0x36923084,0x37923084,0x38923084,0x39923084,0x30933084,0x31933084,0x32933084,0x33933084,0x34933084,0x35933084,0x36933084,0x37933084,0x38933084,0x39933084,0x30943084,0x31943084,0x32943084,0x33943084,0x34943084,0x35943084,0x36943084,0x37943084,0x38943084,0x39943084,0x30953084,0x31953084,0x32953084,0x33953084,0x34953084,0x35953084,0x36953084,0x37953084,0x38953084,0x39953084,0x30963084,0x31963084,0x32963084,0x33963084,0x34963084,0x35963084,0x36963084,0x37963084,0x38963084,0x39963084,0x30973084,0x31973084,0x32973084,0x33973084,0x34973084,0x35973084,0x36973084,0x37973084,0x38973084,0x9FFD,0x39973084,0x30983084,0x31983084,0x32983084,0x33983084,0x34983084,0x35983084,0x36983084,0x37983084,0xA0FD,0x38983084,0x39983084,0x30993084,0x31993084,0x32993084,0x33993084,0x34993084,0x35993084,0x36993084,0x37993084,0x38993084,0x39993084,0x309A3084,0x319A3084,0x329A3084,0x339A3084,0x349A3084,0x359A3084,0x369A3084,0x379A3084,0x389A3084,0x399A3084,0x309B3084,0x319B3084,0x329B3084,0x339B3084,0x40FE,0x41FE,0x42FE,0x43FE,0x349B3084,0x44FE,0x359B3084,0x45FE,0x46FE,0x369B3084,0x379B3084,0x389B3084,0x47FE,0x399B3084,0x309C3084,0x319C3084,0x329C3084,0x339C3084,0x349C3084,0x48FE,0x49FE,0x4AFE,0x359C3084,0x4BFE,0x4CFE,0x369C3084,0x379C3084,0x4DFE,0x4EFE,0x4FFE,0x55A9,0xF2A6,0x38853184,0xF4A6,0xF5A6,0xE0A6,0xE1A6,0xF0A6,0xF1A6,0xE2A6,0xE3A6,0xEEA6,0xEFA6,0xE6A6,0xE7A6,0xE4A6,0xE5A6,0xE8A6,0xE9A6,0xEAA6,0xEBA6,0x39853184,0x30863184,0x31863184,0x32863184,0x68A9,0x69A9,0x6AA9,0x6BA9,0x6CA9,0x6DA9,0x6EA9,0x6FA9,0x70A9,0x71A9,0x33863184,0x72A9,0x73A9,0x74A9,0x75A9,0x34863184,0x76A9,0x77A9,0x78A9,0x79A9,0x7AA9,0x7BA9,0x7CA9,0x7DA9,0x7EA9,0x80A9,0x81A9,0x82A9,0x83A9,0x84A9,0x35863184,0x85A9,0x86A9,0x87A9,0x88A9,0x36863184,0x37863184,0x38863184,0x39863184,0x30873184,0x31873184,0x32873184,0x33873184,0x34873184,0x35873184,0x36873184,0x37873184,0x38873184,0x39873184,0x30883184,0x31883184,0x32883184,0x33883184,0x34883184,0x35883184,0x36883184,0x37883184,0x38883184,0x39883184,0x30893184,0x31893184,0x32893184,0x33893184,0x34893184,0x35893184,0x36893184,0x37893184,0x38893184,0x39893184,0x308A3184,0x318A3184,0x328A3184,0x338A3184,0x348A3184,0x358A3184,0x368A3184,0x378A3184,0x388A3184,0x398A3184,0x308B3184,0x318B3184,0x328B3184,0x338B3184,0x348B3184,0x358B3184,0x368B3184,0x378B3184,0x388B3184,0x398B3184,0x308C3184,0x318C3184,0x328C3184,0x338C3184,0x348C3184,0x358C3184,0x368C3184,0x378C3184,0x388C3184,0x398C3184,0x308D3184,0x318D3184,0x328D3184,0x338D3184,0x348D3184,0x358D3184,0x368D3184,0x378D3184,0x388D3184,0x398D3184,0x308E3184,0x318E3184,0x328E3184,0x338E3184,0x348E3184,0x358E3184,0x368E3184,0x378E3184,0x388E3184,0x398E3184,0x308F3184,0x318F3184,0x328F3184,0x338F3184,0x348F3184,0x358F3184,0x368F3184,0x378F3184,0x388F3184,0x398F3184,0x30903184,0x31903184,0x32903184,0x33903184,0x34903184,0x35903184,0x36903184,0x37903184,0x38903184,0x39903184,0x30913184,0x31913184,0x32913184,0x33913184,0x34913184,0x35913184,0x36913184,0x37913184,0x38913184,0x39913184,0x30923184,0x31923184,0x32923184,0x33923184,0x34923184,0x35923184,0x36923184,0x37923184,0x38923184,0x39923184,0x30933184,0x31933184,0x32933184,0x33933184,0x34933184,0x35933184,0x36933184,0x37933184,0x38933184,0x39933184,0x30943184,0x31943184,0x32943184,0x33943184,0x34943184,0x35943184,0x36943184,0x37943184,0x38943184,0x39943184,0x30953184,0x31953184,0x32953184,0x33953184,0x34953184,0xA1A3,0xA2A3,0xA3A3,0xE7A1,0xA5A3,0xA6A3,0xA7A3,0xA8A3,0xA9A3,0xAAA3,0xABA3,0xACA3,0xADA3,0xAEA3,0xAFA3,0xB0A3,0xB1A3,0xB2A3,0xB3A3,0xB4A3,0xB5A3,0xB6A3,0xB7A3,0xB8A3,0xB9A3,0xBAA3,0xBBA3,0xBCA3,0xBDA3,0xBEA3,0xBFA3,0xC0A3,0xC1A3,0xC2A3,0xC3A3,0xC4A3,0xC5A3,0xC6A3,0xC7A3,0xC8A3,0xC9A3,0xCAA3,0xCBA3,0xCCA3,0xCDA3,0xCEA3,0xCFA3,0xD0A3,0xD1A3,0xD2A3,0xD3A3,0xD4A3,0xD5A3,0xD6A3,0xD7A3,0xD8A3,0xD9A3,0xDAA3,0xDBA3,0xDCA3,0xDDA3,0xDEA3,0xDFA3,0xE0A3,0xE1A3,0xE2A3,0xE3A3,0xE4A3,0xE5A3,0xE6A3,0xE7A3,0xE8A3,0xE9A3,0xEAA3,0xEBA3,0xECA3,0xEDA3,0xEEA3,0xEFA3,0xF0A3,0xF1A3,0xF2A3,0xF3A3,0xF4A3,0xF5A3,0xF6A3,0xF7A3,0xF8A3,0xF9A3,0xFAA3,0xFBA3,0xFCA3,0xFDA3,0xABA1,0x35953184,0x36953184,0x37953184,0x38953184,0x39953184,0x30963184,0x31963184,0x32963184,0x33963184,0x34963184,0x35963184,0x36963184,0x37963184,0x38963184,0x39963184,0x30973184,0x31973184,0x32973184,0x33973184,0x34973184,0x35973184,0x36973184,0x37973184,0x38973184,0x39973184,0x30983184,0x31983184,0x32983184,0x33983184,0x34983184,0x35983184,0x36983184,0x37983184,0x38983184,0x39983184,0x30993184,0x31993184,0x32993184,0x33993184,0x34993184,0x35993184,0x36993184,0x37993184,0x38993184,0x39993184,0x309A3184,0x319A3184,0x329A3184,0x339A3184,0x349A3184,0x359A3184,0x369A3184,0x379A3184,0x389A3184,0x399A3184,0x309B3184,0x319B3184,0x329B3184,0x339B3184,0x349B3184,0x359B3184,0x369B3184,0x379B3184,0x389B3184,0x399B3184,0x309C3184,0x319C3184,0x329C3184,0x339C3184,0x349C3184,0x359C3184,0x369C3184,0x379C3184,0x389C3184,0x399C3184,0x309D3184,0x319D3184,0x329D3184,0x339D3184,0x349D3184,0x359D3184,0x369D3184,0x379D3184,0x389D3184,0x399D3184,0x309E3184,0x319E3184,0x329E3184,0x339E3184,0x349E3184,0x359E3184,0x369E3184,0x379E3184,0x389E3184,0x399E3184,0x309F3184,0x319F3184,0x329F3184,0x339F3184,0x349F3184,0x359F3184,0x369F3184,0x379F3184,0x389F3184,0x399F3184,0x30A03184,0x31A03184,0x32A03184,0x33A03184,0x34A03184,0x35A03184,0x36A03184,0x37A03184,0x38A03184,0x39A03184,0x30A13184,0x31A13184,0x32A13184,0x33A13184,0x34A13184,0x35A13184,0x36A13184,0x37A13184,0x38A13184,0x39A13184,0x30A23184,0x31A23184,0x32A23184,0x33A23184,0xE9A1,0xEAA1,0x56A9,0xFEA3,0x57A9,0xA4A3 \ No newline at end of file diff --git a/src/fast_io/include/fast_io_unit/gb18030_impl/gb18030_uni2_tb.h b/src/fast_io/include/fast_io_unit/gb18030_impl/gb18030_uni2_tb.h new file mode 100644 index 0000000..ba50477 --- /dev/null +++ b/src/fast_io/include/fast_io_unit/gb18030_impl/gb18030_uni2_tb.h @@ -0,0 +1 @@ +0x4E02,0x4E04,0x4E05,0x4E06,0x4E0F,0x4E12,0x4E17,0x4E1F,0x4E20,0x4E21,0x4E23,0x4E26,0x4E29,0x4E2E,0x4E2F,0x4E31,0x4E33,0x4E35,0x4E37,0x4E3C,0x4E40,0x4E41,0x4E42,0x4E44,0x4E46,0x4E4A,0x4E51,0x4E55,0x4E57,0x4E5A,0x4E5B,0x4E62,0x4E63,0x4E64,0x4E65,0x4E67,0x4E68,0x4E6A,0x4E6B,0x4E6C,0x4E6D,0x4E6E,0x4E6F,0x4E72,0x4E74,0x4E75,0x4E76,0x4E77,0x4E78,0x4E79,0x4E7A,0x4E7B,0x4E7C,0x4E7D,0x4E7F,0x4E80,0x4E81,0x4E82,0x4E83,0x4E84,0x4E85,0x4E87,0x4E8A,0x4E90,0x4E96,0x4E97,0x4E99,0x4E9C,0x4E9D,0x4E9E,0x4EA3,0x4EAA,0x4EAF,0x4EB0,0x4EB1,0x4EB4,0x4EB6,0x4EB7,0x4EB8,0x4EB9,0x4EBC,0x4EBD,0x4EBE,0x4EC8,0x4ECC,0x4ECF,0x4ED0,0x4ED2,0x4EDA,0x4EDB,0x4EDC,0x4EE0,0x4EE2,0x4EE6,0x4EE7,0x4EE9,0x4EED,0x4EEE,0x4EEF,0x4EF1,0x4EF4,0x4EF8,0x4EF9,0x4EFA,0x4EFC,0x4EFE,0x4F00,0x4F02,0x4F03,0x4F04,0x4F05,0x4F06,0x4F07,0x4F08,0x4F0B,0x4F0C,0x4F12,0x4F13,0x4F14,0x4F15,0x4F16,0x4F1C,0x4F1D,0x4F21,0x4F23,0x4F28,0x4F29,0x4F2C,0x4F2D,0x4F2E,0x4F31,0x4F33,0x4F35,0x4F37,0x4F39,0x4F3B,0x4F3E,0x4F3F,0x4F40,0x4F41,0x4F42,0x4F44,0x4F45,0x4F47,0x4F48,0x4F49,0x4F4A,0x4F4B,0x4F4C,0x4F52,0x4F54,0x4F56,0x4F61,0x4F62,0x4F66,0x4F68,0x4F6A,0x4F6B,0x4F6D,0x4F6E,0x4F71,0x4F72,0x4F75,0x4F77,0x4F78,0x4F79,0x4F7A,0x4F7D,0x4F80,0x4F81,0x4F82,0x4F85,0x4F86,0x4F87,0x4F8A,0x4F8C,0x4F8E,0x4F90,0x4F92,0x4F93,0x4F95,0x4F96,0x4F98,0x4F99,0x4F9A,0x4F9C,0x4F9E,0x4F9F,0x4FA1,0x4FA2,0x4FA4,0x4FAB,0x4FAD,0x4FB0,0x4FB1,0x4FB2,0x4FB3,0x4FB4,0x4FB6,0x4FB7,0x4FB8,0x4FB9,0x4FBA,0x4FBB,0x4FBC,0x4FBD,0x4FBE,0x4FC0,0x4FC1,0x4FC2,0x4FC6,0x4FC7,0x4FC8,0x4FC9,0x4FCB,0x4FCC,0x4FCD,0x4FD2,0x4FD3,0x4FD4,0x4FD5,0x4FD6,0x4FD9,0x4FDB,0x4FE0,0x4FE2,0x4FE4,0x4FE5,0x4FE7,0x4FEB,0x4FEC,0x4FF0,0x4FF2,0x4FF4,0x4FF5,0x4FF6,0x4FF7,0x4FF9,0x4FFB,0x4FFC,0x4FFD,0x4FFF,0x5000,0x5001,0x5002,0x5003,0x5004,0x5005,0x5006,0x5007,0x5008,0x5009,0x500A,0x500B,0x500E,0x5010,0x5011,0x5013,0x5015,0x5016,0x5017,0x501B,0x501D,0x501E,0x5020,0x5022,0x5023,0x5024,0x5027,0x502B,0x502F,0x5030,0x5031,0x5032,0x5033,0x5034,0x5035,0x5036,0x5037,0x5038,0x5039,0x503B,0x503D,0x503F,0x5040,0x5041,0x5042,0x5044,0x5045,0x5046,0x5049,0x504A,0x504B,0x504D,0x5050,0x5051,0x5052,0x5053,0x5054,0x5056,0x5057,0x5058,0x5059,0x505B,0x505D,0x505E,0x505F,0x5060,0x5061,0x5062,0x5063,0x5064,0x5066,0x5067,0x5068,0x5069,0x506A,0x506B,0x506D,0x506E,0x506F,0x5070,0x5071,0x5072,0x5073,0x5074,0x5075,0x5078,0x5079,0x507A,0x507C,0x507D,0x5081,0x5082,0x5083,0x5084,0x5086,0x5087,0x5089,0x508A,0x508B,0x508C,0x508E,0x508F,0x5090,0x5091,0x5092,0x5093,0x5094,0x5095,0x5096,0x5097,0x5098,0x5099,0x509A,0x509B,0x509C,0x509D,0x509E,0x509F,0x50A0,0x50A1,0x50A2,0x50A4,0x50A6,0x50AA,0x50AB,0x50AD,0x50AE,0x50AF,0x50B0,0x50B1,0x50B3,0x50B4,0x50B5,0x50B6,0x50B7,0x50B8,0x50B9,0x50BC,0x50BD,0x50BE,0x50BF,0x50C0,0x50C1,0x50C2,0x50C3,0x50C4,0x50C5,0x50C6,0x50C7,0x50C8,0x50C9,0x50CA,0x50CB,0x50CC,0x50CD,0x50CE,0x50D0,0x50D1,0x50D2,0x50D3,0x50D4,0x50D5,0x50D7,0x50D8,0x50D9,0x50DB,0x50DC,0x50DD,0x50DE,0x50DF,0x50E0,0x50E1,0x50E2,0x50E3,0x50E4,0x50E5,0x50E8,0x50E9,0x50EA,0x50EB,0x50EF,0x50F0,0x50F1,0x50F2,0x50F4,0x50F6,0x50F7,0x50F8,0x50F9,0x50FA,0x50FC,0x50FD,0x50FE,0x50FF,0x5100,0x5101,0x5102,0x5103,0x5104,0x5105,0x5108,0x5109,0x510A,0x510C,0x510D,0x510E,0x510F,0x5110,0x5111,0x5113,0x5114,0x5115,0x5116,0x5117,0x5118,0x5119,0x511A,0x511B,0x511C,0x511D,0x511E,0x511F,0x5120,0x5122,0x5123,0x5124,0x5125,0x5126,0x5127,0x5128,0x5129,0x512A,0x512B,0x512C,0x512D,0x512E,0x512F,0x5130,0x5131,0x5132,0x5133,0x5134,0x5135,0x5136,0x5137,0x5138,0x5139,0x513A,0x513B,0x513C,0x513D,0x513E,0x5142,0x5147,0x514A,0x514C,0x514E,0x514F,0x5150,0x5152,0x5153,0x5157,0x5158,0x5159,0x515B,0x515D,0x515E,0x515F,0x5160,0x5161,0x5163,0x5164,0x5166,0x5167,0x5169,0x516A,0x516F,0x5172,0x517A,0x517E,0x517F,0x5183,0x5184,0x5186,0x5187,0x518A,0x518B,0x518E,0x518F,0x5190,0x5191,0x5193,0x5194,0x5198,0x519A,0x519D,0x519E,0x519F,0x51A1,0x51A3,0x51A6,0x51A7,0x51A8,0x51A9,0x51AA,0x51AD,0x51AE,0x51B4,0x51B8,0x51B9,0x51BA,0x51BE,0x51BF,0x51C1,0x51C2,0x51C3,0x51C5,0x51C8,0x51CA,0x51CD,0x51CE,0x51D0,0x51D2,0x51D3,0x51D4,0x51D5,0x51D6,0x51D7,0x51D8,0x51D9,0x51DA,0x51DC,0x51DE,0x51DF,0x51E2,0x51E3,0x51E5,0x51E6,0x51E7,0x51E8,0x51E9,0x51EA,0x51EC,0x51EE,0x51F1,0x51F2,0x51F4,0x51F7,0x51FE,0x5204,0x5205,0x5209,0x520B,0x520C,0x520F,0x5210,0x5213,0x5214,0x5215,0x521C,0x521E,0x521F,0x5221,0x5222,0x5223,0x5225,0x5226,0x5227,0x522A,0x522C,0x522F,0x5231,0x5232,0x5234,0x5235,0x523C,0x523E,0x5244,0x5245,0x5246,0x5247,0x5248,0x5249,0x524B,0x524E,0x524F,0x5252,0x5253,0x5255,0x5257,0x5258,0x5259,0x525A,0x525B,0x525D,0x525F,0x5260,0x5262,0x5263,0x5264,0x5266,0x5268,0x526B,0x526C,0x526D,0x526E,0x5270,0x5271,0x5273,0x5274,0x5275,0x5276,0x5277,0x5278,0x5279,0x527A,0x527B,0x527C,0x527E,0x5280,0x5283,0x5284,0x5285,0x5286,0x5287,0x5289,0x528A,0x528B,0x528C,0x528D,0x528E,0x528F,0x5291,0x5292,0x5294,0x5295,0x5296,0x5297,0x5298,0x5299,0x529A,0x529C,0x52A4,0x52A5,0x52A6,0x52A7,0x52AE,0x52AF,0x52B0,0x52B4,0x52B5,0x52B6,0x52B7,0x52B8,0x52B9,0x52BA,0x52BB,0x52BC,0x52BD,0x52C0,0x52C1,0x52C2,0x52C4,0x52C5,0x52C6,0x52C8,0x52CA,0x52CC,0x52CD,0x52CE,0x52CF,0x52D1,0x52D3,0x52D4,0x52D5,0x52D7,0x52D9,0x52DA,0x52DB,0x52DC,0x52DD,0x52DE,0x52E0,0x52E1,0x52E2,0x52E3,0x52E5,0x52E6,0x52E7,0x52E8,0x52E9,0x52EA,0x52EB,0x52EC,0x52ED,0x52EE,0x52EF,0x52F1,0x52F2,0x52F3,0x52F4,0x52F5,0x52F6,0x52F7,0x52F8,0x52FB,0x52FC,0x52FD,0x5301,0x5302,0x5303,0x5304,0x5307,0x5309,0x530A,0x530B,0x530C,0x530E,0x5311,0x5312,0x5313,0x5314,0x5318,0x531B,0x531C,0x531E,0x531F,0x5322,0x5324,0x5325,0x5327,0x5328,0x5329,0x532B,0x532C,0x532D,0x532F,0x5330,0x5331,0x5332,0x5333,0x5334,0x5335,0x5336,0x5337,0x5338,0x533C,0x533D,0x5340,0x5342,0x5344,0x5346,0x534B,0x534C,0x534D,0x5350,0x5354,0x5358,0x5359,0x535B,0x535D,0x5365,0x5368,0x536A,0x536C,0x536D,0x5372,0x5376,0x5379,0x537B,0x537C,0x537D,0x537E,0x5380,0x5381,0x5383,0x5387,0x5388,0x538A,0x538E,0x538F,0x5390,0x5391,0x5392,0x5393,0x5394,0x5396,0x5397,0x5399,0x539B,0x539C,0x539E,0x53A0,0x53A1,0x53A4,0x53A7,0x53AA,0x53AB,0x53AC,0x53AD,0x53AF,0x53B0,0x53B1,0x53B2,0x53B3,0x53B4,0x53B5,0x53B7,0x53B8,0x53B9,0x53BA,0x53BC,0x53BD,0x53BE,0x53C0,0x53C3,0x53C4,0x53C5,0x53C6,0x53C7,0x53CE,0x53CF,0x53D0,0x53D2,0x53D3,0x53D5,0x53DA,0x53DC,0x53DD,0x53DE,0x53E1,0x53E2,0x53E7,0x53F4,0x53FA,0x53FE,0x53FF,0x5400,0x5402,0x5405,0x5407,0x540B,0x5414,0x5418,0x5419,0x541A,0x541C,0x5422,0x5424,0x5425,0x542A,0x5430,0x5433,0x5436,0x5437,0x543A,0x543D,0x543F,0x5441,0x5442,0x5444,0x5445,0x5447,0x5449,0x544C,0x544D,0x544E,0x544F,0x5451,0x545A,0x545D,0x545E,0x545F,0x5460,0x5461,0x5463,0x5465,0x5467,0x5469,0x546A,0x546B,0x546C,0x546D,0x546E,0x546F,0x5470,0x5474,0x5479,0x547A,0x547E,0x547F,0x5481,0x5483,0x5485,0x5487,0x5488,0x5489,0x548A,0x548D,0x5491,0x5493,0x5497,0x5498,0x549C,0x549E,0x549F,0x54A0,0x54A1,0x54A2,0x54A5,0x54AE,0x54B0,0x54B2,0x54B5,0x54B6,0x54B7,0x54B9,0x54BA,0x54BC,0x54BE,0x54C3,0x54C5,0x54CA,0x54CB,0x54D6,0x54D8,0x54DB,0x54E0,0x54E1,0x54E2,0x54E3,0x54E4,0x54EB,0x54EC,0x54EF,0x54F0,0x54F1,0x54F4,0x54F5,0x54F6,0x54F7,0x54F8,0x54F9,0x54FB,0x54FE,0x5500,0x5502,0x5503,0x5504,0x5505,0x5508,0x550A,0x550B,0x550C,0x550D,0x550E,0x5512,0x5513,0x5515,0x5516,0x5517,0x5518,0x5519,0x551A,0x551C,0x551D,0x551E,0x551F,0x5521,0x5525,0x5526,0x5528,0x5529,0x552B,0x552D,0x5532,0x5534,0x5535,0x5536,0x5538,0x5539,0x553A,0x553B,0x553D,0x5540,0x5542,0x5545,0x5547,0x5548,0x554B,0x554C,0x554D,0x554E,0x554F,0x5551,0x5552,0x5553,0x5554,0x5557,0x5558,0x5559,0x555A,0x555B,0x555D,0x555E,0x555F,0x5560,0x5562,0x5563,0x5568,0x5569,0x556B,0x556F,0x5570,0x5571,0x5572,0x5573,0x5574,0x5579,0x557A,0x557D,0x557F,0x5585,0x5586,0x558C,0x558D,0x558E,0x5590,0x5592,0x5593,0x5595,0x5596,0x5597,0x559A,0x559B,0x559E,0x55A0,0x55A1,0x55A2,0x55A3,0x55A4,0x55A5,0x55A6,0x55A8,0x55A9,0x55AA,0x55AB,0x55AC,0x55AD,0x55AE,0x55AF,0x55B0,0x55B2,0x55B4,0x55B6,0x55B8,0x55BA,0x55BC,0x55BF,0x55C0,0x55C1,0x55C2,0x55C3,0x55C6,0x55C7,0x55C8,0x55CA,0x55CB,0x55CE,0x55CF,0x55D0,0x55D5,0x55D7,0x55D8,0x55D9,0x55DA,0x55DB,0x55DE,0x55E0,0x55E2,0x55E7,0x55E9,0x55ED,0x55EE,0x55F0,0x55F1,0x55F4,0x55F6,0x55F8,0x55F9,0x55FA,0x55FB,0x55FC,0x55FF,0x5602,0x5603,0x5604,0x5605,0x5606,0x5607,0x560A,0x560B,0x560D,0x5610,0x5611,0x5612,0x5613,0x5614,0x5615,0x5616,0x5617,0x5619,0x561A,0x561C,0x561D,0x5620,0x5621,0x5622,0x5625,0x5626,0x5628,0x5629,0x562A,0x562B,0x562E,0x562F,0x5630,0x5633,0x5635,0x5637,0x5638,0x563A,0x563C,0x563D,0x563E,0x5640,0x5641,0x5642,0x5643,0x5644,0x5645,0x5646,0x5647,0x5648,0x5649,0x564A,0x564B,0x564F,0x5650,0x5651,0x5652,0x5653,0x5655,0x5656,0x565A,0x565B,0x565D,0x565E,0x565F,0x5660,0x5661,0x5663,0x5665,0x5666,0x5667,0x566D,0x566E,0x566F,0x5670,0x5672,0x5673,0x5674,0x5675,0x5677,0x5678,0x5679,0x567A,0x567D,0x567E,0x567F,0x5680,0x5681,0x5682,0x5683,0x5684,0x5687,0x5688,0x5689,0x568A,0x568B,0x568C,0x568D,0x5690,0x5691,0x5692,0x5694,0x5695,0x5696,0x5697,0x5698,0x5699,0x569A,0x569B,0x569C,0x569D,0x569E,0x569F,0x56A0,0x56A1,0x56A2,0x56A4,0x56A5,0x56A6,0x56A7,0x56A8,0x56A9,0x56AA,0x56AB,0x56AC,0x56AD,0x56AE,0x56B0,0x56B1,0x56B2,0x56B3,0x56B4,0x56B5,0x56B6,0x56B8,0x56B9,0x56BA,0x56BB,0x56BD,0x56BE,0x56BF,0x56C0,0x56C1,0x56C2,0x56C3,0x56C4,0x56C5,0x56C6,0x56C7,0x56C8,0x56C9,0x56CB,0x56CC,0x56CD,0x56CE,0x56CF,0x56D0,0x56D1,0x56D2,0x56D3,0x56D5,0x56D6,0x56D8,0x56D9,0x56DC,0x56E3,0x56E5,0x56E6,0x56E7,0x56E8,0x56E9,0x56EA,0x56EC,0x56EE,0x56EF,0x56F2,0x56F3,0x56F6,0x56F7,0x56F8,0x56FB,0x56FC,0x5700,0x5701,0x5702,0x5705,0x5707,0x570B,0x570C,0x570D,0x570E,0x570F,0x5710,0x5711,0x5712,0x5713,0x5714,0x5715,0x5716,0x5717,0x5718,0x5719,0x571A,0x571B,0x571D,0x571E,0x5720,0x5721,0x5722,0x5724,0x5725,0x5726,0x5727,0x572B,0x5731,0x5732,0x5734,0x5735,0x5736,0x5737,0x5738,0x573C,0x573D,0x573F,0x5741,0x5743,0x5744,0x5745,0x5746,0x5748,0x5749,0x574B,0x5752,0x5753,0x5754,0x5755,0x5756,0x5758,0x5759,0x5762,0x5763,0x5765,0x5767,0x576C,0x576E,0x5770,0x5771,0x5772,0x5774,0x5775,0x5778,0x5779,0x577A,0x577D,0x577E,0x577F,0x5780,0x5781,0x5787,0x5788,0x5789,0x578A,0x578D,0x578E,0x578F,0x5790,0x5791,0x5794,0x5795,0x5796,0x5797,0x5798,0x5799,0x579A,0x579C,0x579D,0x579E,0x579F,0x57A5,0x57A8,0x57AA,0x57AC,0x57AF,0x57B0,0x57B1,0x57B3,0x57B5,0x57B6,0x57B7,0x57B9,0x57BA,0x57BB,0x57BC,0x57BD,0x57BE,0x57BF,0x57C0,0x57C1,0x57C4,0x57C5,0x57C6,0x57C7,0x57C8,0x57C9,0x57CA,0x57CC,0x57CD,0x57D0,0x57D1,0x57D3,0x57D6,0x57D7,0x57DB,0x57DC,0x57DE,0x57E1,0x57E2,0x57E3,0x57E5,0x57E6,0x57E7,0x57E8,0x57E9,0x57EA,0x57EB,0x57EC,0x57EE,0x57F0,0x57F1,0x57F2,0x57F3,0x57F5,0x57F6,0x57F7,0x57FB,0x57FC,0x57FE,0x57FF,0x5801,0x5803,0x5804,0x5805,0x5808,0x5809,0x580A,0x580C,0x580E,0x580F,0x5810,0x5812,0x5813,0x5814,0x5816,0x5817,0x5818,0x581A,0x581B,0x581C,0x581D,0x581F,0x5822,0x5823,0x5825,0x5826,0x5827,0x5828,0x5829,0x582B,0x582C,0x582D,0x582E,0x582F,0x5831,0x5832,0x5833,0x5834,0x5836,0x5837,0x5838,0x5839,0x583A,0x583B,0x583C,0x583D,0x583E,0x583F,0x5840,0x5841,0x5842,0x5843,0x5845,0x5846,0x5847,0x5848,0x5849,0x584A,0x584B,0x584E,0x584F,0x5850,0x5852,0x5853,0x5855,0x5856,0x5857,0x5859,0x585A,0x585B,0x585C,0x585D,0x585F,0x5860,0x5861,0x5862,0x5863,0x5864,0x5866,0x5867,0x5868,0x5869,0x586A,0x586D,0x586E,0x586F,0x5870,0x5871,0x5872,0x5873,0x5874,0x5875,0x5876,0x5877,0x5878,0x5879,0x587A,0x587B,0x587C,0x587D,0x587F,0x5882,0x5884,0x5886,0x5887,0x5888,0x588A,0x588B,0x588C,0x588D,0x588E,0x588F,0x5890,0x5891,0x5894,0x5895,0x5896,0x5897,0x5898,0x589B,0x589C,0x589D,0x58A0,0x58A1,0x58A2,0x58A3,0x58A4,0x58A5,0x58A6,0x58A7,0x58AA,0x58AB,0x58AC,0x58AD,0x58AE,0x58AF,0x58B0,0x58B1,0x58B2,0x58B3,0x58B4,0x58B5,0x58B6,0x58B7,0x58B8,0x58B9,0x58BA,0x58BB,0x58BD,0x58BE,0x58BF,0x58C0,0x58C2,0x58C3,0x58C4,0x58C6,0x58C7,0x58C8,0x58C9,0x58CA,0x58CB,0x58CC,0x58CD,0x58CE,0x58CF,0x58D0,0x58D2,0x58D3,0x58D4,0x58D6,0x58D7,0x58D8,0x58D9,0x58DA,0x58DB,0x58DC,0x58DD,0x58DE,0x58DF,0x58E0,0x58E1,0x58E2,0x58E3,0x58E5,0x58E6,0x58E7,0x58E8,0x58E9,0x58EA,0x58ED,0x58EF,0x58F1,0x58F2,0x58F4,0x58F5,0x58F7,0x58F8,0x58FA,0x58FB,0x58FC,0x58FD,0x58FE,0x58FF,0x5900,0x5901,0x5903,0x5905,0x5906,0x5908,0x5909,0x590A,0x590B,0x590C,0x590E,0x5910,0x5911,0x5912,0x5913,0x5917,0x5918,0x591B,0x591D,0x591E,0x5920,0x5921,0x5922,0x5923,0x5926,0x5928,0x592C,0x5930,0x5932,0x5933,0x5935,0x5936,0x593B,0x593D,0x593E,0x593F,0x5940,0x5943,0x5945,0x5946,0x594A,0x594C,0x594D,0x5950,0x5952,0x5953,0x5959,0x595B,0x595C,0x595D,0x595E,0x595F,0x5961,0x5963,0x5964,0x5966,0x5967,0x5968,0x5969,0x596A,0x596B,0x596C,0x596D,0x596E,0x596F,0x5970,0x5971,0x5972,0x5975,0x5977,0x597A,0x597B,0x597C,0x597E,0x597F,0x5980,0x5985,0x5989,0x598B,0x598C,0x598E,0x598F,0x5990,0x5991,0x5994,0x5995,0x5998,0x599A,0x599B,0x599C,0x599D,0x599F,0x59A0,0x59A1,0x59A2,0x59A6,0x59A7,0x59AC,0x59AD,0x59B0,0x59B1,0x59B3,0x59B4,0x59B5,0x59B6,0x59B7,0x59B8,0x59BA,0x59BC,0x59BD,0x59BF,0x59C0,0x59C1,0x59C2,0x59C3,0x59C4,0x59C5,0x59C7,0x59C8,0x59C9,0x59CC,0x59CD,0x59CE,0x59CF,0x59D5,0x59D6,0x59D9,0x59DB,0x59DE,0x59DF,0x59E0,0x59E1,0x59E2,0x59E4,0x59E6,0x59E7,0x59E9,0x59EA,0x59EB,0x59ED,0x59EE,0x59EF,0x59F0,0x59F1,0x59F2,0x59F3,0x59F4,0x59F5,0x59F6,0x59F7,0x59F8,0x59FA,0x59FC,0x59FD,0x59FE,0x5A00,0x5A02,0x5A0A,0x5A0B,0x5A0D,0x5A0E,0x5A0F,0x5A10,0x5A12,0x5A14,0x5A15,0x5A16,0x5A17,0x5A19,0x5A1A,0x5A1B,0x5A1D,0x5A1E,0x5A21,0x5A22,0x5A24,0x5A26,0x5A27,0x5A28,0x5A2A,0x5A2B,0x5A2C,0x5A2D,0x5A2E,0x5A2F,0x5A30,0x5A33,0x5A35,0x5A37,0x5A38,0x5A39,0x5A3A,0x5A3B,0x5A3D,0x5A3E,0x5A3F,0x5A41,0x5A42,0x5A43,0x5A44,0x5A45,0x5A47,0x5A48,0x5A4B,0x5A4C,0x5A4D,0x5A4E,0x5A4F,0x5A50,0x5A51,0x5A52,0x5A53,0x5A54,0x5A56,0x5A57,0x5A58,0x5A59,0x5A5B,0x5A5C,0x5A5D,0x5A5E,0x5A5F,0x5A60,0x5A61,0x5A63,0x5A64,0x5A65,0x5A66,0x5A68,0x5A69,0x5A6B,0x5A6C,0x5A6D,0x5A6E,0x5A6F,0x5A70,0x5A71,0x5A72,0x5A73,0x5A78,0x5A79,0x5A7B,0x5A7C,0x5A7D,0x5A7E,0x5A80,0x5A81,0x5A82,0x5A83,0x5A84,0x5A85,0x5A86,0x5A87,0x5A88,0x5A89,0x5A8A,0x5A8B,0x5A8C,0x5A8D,0x5A8E,0x5A8F,0x5A90,0x5A91,0x5A93,0x5A94,0x5A95,0x5A96,0x5A97,0x5A98,0x5A99,0x5A9C,0x5A9D,0x5A9E,0x5A9F,0x5AA0,0x5AA1,0x5AA2,0x5AA3,0x5AA4,0x5AA5,0x5AA6,0x5AA7,0x5AA8,0x5AA9,0x5AAB,0x5AAC,0x5AAD,0x5AAE,0x5AAF,0x5AB0,0x5AB1,0x5AB4,0x5AB6,0x5AB7,0x5AB9,0x5ABA,0x5ABB,0x5ABC,0x5ABD,0x5ABF,0x5AC0,0x5AC3,0x5AC4,0x5AC5,0x5AC6,0x5AC7,0x5AC8,0x5ACA,0x5ACB,0x5ACD,0x5ACE,0x5ACF,0x5AD0,0x5AD1,0x5AD3,0x5AD5,0x5AD7,0x5AD9,0x5ADA,0x5ADB,0x5ADD,0x5ADE,0x5ADF,0x5AE2,0x5AE4,0x5AE5,0x5AE7,0x5AE8,0x5AEA,0x5AEC,0x5AED,0x5AEE,0x5AEF,0x5AF0,0x5AF2,0x5AF3,0x5AF4,0x5AF5,0x5AF6,0x5AF7,0x5AF8,0x5AF9,0x5AFA,0x5AFB,0x5AFC,0x5AFD,0x5AFE,0x5AFF,0x5B00,0x5B01,0x5B02,0x5B03,0x5B04,0x5B05,0x5B06,0x5B07,0x5B08,0x5B0A,0x5B0B,0x5B0C,0x5B0D,0x5B0E,0x5B0F,0x5B10,0x5B11,0x5B12,0x5B13,0x5B14,0x5B15,0x5B18,0x5B19,0x5B1A,0x5B1B,0x5B1C,0x5B1D,0x5B1E,0x5B1F,0x5B20,0x5B21,0x5B22,0x5B23,0x5B24,0x5B25,0x5B26,0x5B27,0x5B28,0x5B29,0x5B2A,0x5B2B,0x5B2C,0x5B2D,0x5B2E,0x5B2F,0x5B30,0x5B31,0x5B33,0x5B35,0x5B36,0x5B38,0x5B39,0x5B3A,0x5B3B,0x5B3C,0x5B3D,0x5B3E,0x5B3F,0x5B41,0x5B42,0x5B43,0x5B44,0x5B45,0x5B46,0x5B47,0x5B48,0x5B49,0x5B4A,0x5B4B,0x5B4C,0x5B4D,0x5B4E,0x5B4F,0x5B52,0x5B56,0x5B5E,0x5B60,0x5B61,0x5B67,0x5B68,0x5B6B,0x5B6D,0x5B6E,0x5B6F,0x5B72,0x5B74,0x5B76,0x5B77,0x5B78,0x5B79,0x5B7B,0x5B7C,0x5B7E,0x5B7F,0x5B82,0x5B86,0x5B8A,0x5B8D,0x5B8E,0x5B90,0x5B91,0x5B92,0x5B94,0x5B96,0x5B9F,0x5BA7,0x5BA8,0x5BA9,0x5BAC,0x5BAD,0x5BAE,0x5BAF,0x5BB1,0x5BB2,0x5BB7,0x5BBA,0x5BBB,0x5BBC,0x5BC0,0x5BC1,0x5BC3,0x5BC8,0x5BC9,0x5BCA,0x5BCB,0x5BCD,0x5BCE,0x5BCF,0x5BD1,0x5BD4,0x5BD5,0x5BD6,0x5BD7,0x5BD8,0x5BD9,0x5BDA,0x5BDB,0x5BDC,0x5BE0,0x5BE2,0x5BE3,0x5BE6,0x5BE7,0x5BE9,0x5BEA,0x5BEB,0x5BEC,0x5BED,0x5BEF,0x5BF1,0x5BF2,0x5BF3,0x5BF4,0x5BF5,0x5BF6,0x5BF7,0x5BFD,0x5BFE,0x5C00,0x5C02,0x5C03,0x5C05,0x5C07,0x5C08,0x5C0B,0x5C0C,0x5C0D,0x5C0E,0x5C10,0x5C12,0x5C13,0x5C17,0x5C19,0x5C1B,0x5C1E,0x5C1F,0x5C20,0x5C21,0x5C23,0x5C26,0x5C28,0x5C29,0x5C2A,0x5C2B,0x5C2D,0x5C2E,0x5C2F,0x5C30,0x5C32,0x5C33,0x5C35,0x5C36,0x5C37,0x5C43,0x5C44,0x5C46,0x5C47,0x5C4C,0x5C4D,0x5C52,0x5C53,0x5C54,0x5C56,0x5C57,0x5C58,0x5C5A,0x5C5B,0x5C5C,0x5C5D,0x5C5F,0x5C62,0x5C64,0x5C67,0x5C68,0x5C69,0x5C6A,0x5C6B,0x5C6C,0x5C6D,0x5C70,0x5C72,0x5C73,0x5C74,0x5C75,0x5C76,0x5C77,0x5C78,0x5C7B,0x5C7C,0x5C7D,0x5C7E,0x5C80,0x5C83,0x5C84,0x5C85,0x5C86,0x5C87,0x5C89,0x5C8A,0x5C8B,0x5C8E,0x5C8F,0x5C92,0x5C93,0x5C95,0x5C9D,0x5C9E,0x5C9F,0x5CA0,0x5CA1,0x5CA4,0x5CA5,0x5CA6,0x5CA7,0x5CA8,0x5CAA,0x5CAE,0x5CAF,0x5CB0,0x5CB2,0x5CB4,0x5CB6,0x5CB9,0x5CBA,0x5CBB,0x5CBC,0x5CBE,0x5CC0,0x5CC2,0x5CC3,0x5CC5,0x5CC6,0x5CC7,0x5CC8,0x5CC9,0x5CCA,0x5CCC,0x5CCD,0x5CCE,0x5CCF,0x5CD0,0x5CD1,0x5CD3,0x5CD4,0x5CD5,0x5CD6,0x5CD7,0x5CD8,0x5CDA,0x5CDB,0x5CDC,0x5CDD,0x5CDE,0x5CDF,0x5CE0,0x5CE2,0x5CE3,0x5CE7,0x5CE9,0x5CEB,0x5CEC,0x5CEE,0x5CEF,0x5CF1,0x5CF2,0x5CF3,0x5CF4,0x5CF5,0x5CF6,0x5CF7,0x5CF8,0x5CF9,0x5CFA,0x5CFC,0x5CFD,0x5CFE,0x5CFF,0x5D00,0x5D01,0x5D04,0x5D05,0x5D08,0x5D09,0x5D0A,0x5D0B,0x5D0C,0x5D0D,0x5D0F,0x5D10,0x5D11,0x5D12,0x5D13,0x5D15,0x5D17,0x5D18,0x5D19,0x5D1A,0x5D1C,0x5D1D,0x5D1F,0x5D20,0x5D21,0x5D22,0x5D23,0x5D25,0x5D28,0x5D2A,0x5D2B,0x5D2C,0x5D2F,0x5D30,0x5D31,0x5D32,0x5D33,0x5D35,0x5D36,0x5D37,0x5D38,0x5D39,0x5D3A,0x5D3B,0x5D3C,0x5D3F,0x5D40,0x5D41,0x5D42,0x5D43,0x5D44,0x5D45,0x5D46,0x5D48,0x5D49,0x5D4D,0x5D4E,0x5D4F,0x5D50,0x5D51,0x5D52,0x5D53,0x5D54,0x5D55,0x5D56,0x5D57,0x5D59,0x5D5A,0x5D5C,0x5D5E,0x5D5F,0x5D60,0x5D61,0x5D62,0x5D63,0x5D64,0x5D65,0x5D66,0x5D67,0x5D68,0x5D6A,0x5D6D,0x5D6E,0x5D70,0x5D71,0x5D72,0x5D73,0x5D75,0x5D76,0x5D77,0x5D78,0x5D79,0x5D7A,0x5D7B,0x5D7C,0x5D7D,0x5D7E,0x5D7F,0x5D80,0x5D81,0x5D83,0x5D84,0x5D85,0x5D86,0x5D87,0x5D88,0x5D89,0x5D8A,0x5D8B,0x5D8C,0x5D8D,0x5D8E,0x5D8F,0x5D90,0x5D91,0x5D92,0x5D93,0x5D94,0x5D95,0x5D96,0x5D97,0x5D98,0x5D9A,0x5D9B,0x5D9C,0x5D9E,0x5D9F,0x5DA0,0x5DA1,0x5DA2,0x5DA3,0x5DA4,0x5DA5,0x5DA6,0x5DA7,0x5DA8,0x5DA9,0x5DAA,0x5DAB,0x5DAC,0x5DAD,0x5DAE,0x5DAF,0x5DB0,0x5DB1,0x5DB2,0x5DB3,0x5DB4,0x5DB5,0x5DB6,0x5DB8,0x5DB9,0x5DBA,0x5DBB,0x5DBC,0x5DBD,0x5DBE,0x5DBF,0x5DC0,0x5DC1,0x5DC2,0x5DC3,0x5DC4,0x5DC6,0x5DC7,0x5DC8,0x5DC9,0x5DCA,0x5DCB,0x5DCC,0x5DCE,0x5DCF,0x5DD0,0x5DD1,0x5DD2,0x5DD3,0x5DD4,0x5DD5,0x5DD6,0x5DD7,0x5DD8,0x5DD9,0x5DDA,0x5DDC,0x5DDF,0x5DE0,0x5DE3,0x5DE4,0x5DEA,0x5DEC,0x5DED,0x5DF0,0x5DF5,0x5DF6,0x5DF8,0x5DF9,0x5DFA,0x5DFB,0x5DFC,0x5DFF,0x5E00,0x5E04,0x5E07,0x5E09,0x5E0A,0x5E0B,0x5E0D,0x5E0E,0x5E12,0x5E13,0x5E17,0x5E1E,0x5E1F,0x5E20,0x5E21,0x5E22,0x5E23,0x5E24,0x5E25,0x5E28,0x5E29,0x5E2A,0x5E2B,0x5E2C,0x5E2F,0x5E30,0x5E32,0x5E33,0x5E34,0x5E35,0x5E36,0x5E39,0x5E3A,0x5E3E,0x5E3F,0x5E40,0x5E41,0x5E43,0x5E46,0x5E47,0x5E48,0x5E49,0x5E4A,0x5E4B,0x5E4D,0x5E4E,0x5E4F,0x5E50,0x5E51,0x5E52,0x5E53,0x5E56,0x5E57,0x5E58,0x5E59,0x5E5A,0x5E5C,0x5E5D,0x5E5F,0x5E60,0x5E63,0x5E64,0x5E65,0x5E66,0x5E67,0x5E68,0x5E69,0x5E6A,0x5E6B,0x5E6C,0x5E6D,0x5E6E,0x5E6F,0x5E70,0x5E71,0x5E75,0x5E77,0x5E79,0x5E7E,0x5E81,0x5E82,0x5E83,0x5E85,0x5E88,0x5E89,0x5E8C,0x5E8D,0x5E8E,0x5E92,0x5E98,0x5E9B,0x5E9D,0x5EA1,0x5EA2,0x5EA3,0x5EA4,0x5EA8,0x5EA9,0x5EAA,0x5EAB,0x5EAC,0x5EAE,0x5EAF,0x5EB0,0x5EB1,0x5EB2,0x5EB4,0x5EBA,0x5EBB,0x5EBC,0x5EBD,0x5EBF,0x5EC0,0x5EC1,0x5EC2,0x5EC3,0x5EC4,0x5EC5,0x5EC6,0x5EC7,0x5EC8,0x5ECB,0x5ECC,0x5ECD,0x5ECE,0x5ECF,0x5ED0,0x5ED4,0x5ED5,0x5ED7,0x5ED8,0x5ED9,0x5EDA,0x5EDC,0x5EDD,0x5EDE,0x5EDF,0x5EE0,0x5EE1,0x5EE2,0x5EE3,0x5EE4,0x5EE5,0x5EE6,0x5EE7,0x5EE9,0x5EEB,0x5EEC,0x5EED,0x5EEE,0x5EEF,0x5EF0,0x5EF1,0x5EF2,0x5EF3,0x5EF5,0x5EF8,0x5EF9,0x5EFB,0x5EFC,0x5EFD,0x5F05,0x5F06,0x5F07,0x5F09,0x5F0C,0x5F0D,0x5F0E,0x5F10,0x5F12,0x5F14,0x5F16,0x5F19,0x5F1A,0x5F1C,0x5F1D,0x5F1E,0x5F21,0x5F22,0x5F23,0x5F24,0x5F28,0x5F2B,0x5F2C,0x5F2E,0x5F30,0x5F32,0x5F33,0x5F34,0x5F35,0x5F36,0x5F37,0x5F38,0x5F3B,0x5F3D,0x5F3E,0x5F3F,0x5F41,0x5F42,0x5F43,0x5F44,0x5F45,0x5F46,0x5F47,0x5F48,0x5F49,0x5F4A,0x5F4B,0x5F4C,0x5F4D,0x5F4E,0x5F4F,0x5F51,0x5F54,0x5F59,0x5F5A,0x5F5B,0x5F5C,0x5F5E,0x5F5F,0x5F60,0x5F63,0x5F65,0x5F67,0x5F68,0x5F6B,0x5F6E,0x5F6F,0x5F72,0x5F74,0x5F75,0x5F76,0x5F78,0x5F7A,0x5F7D,0x5F7E,0x5F7F,0x5F83,0x5F86,0x5F8D,0x5F8E,0x5F8F,0x5F91,0x5F93,0x5F94,0x5F96,0x5F9A,0x5F9B,0x5F9D,0x5F9E,0x5F9F,0x5FA0,0x5FA2,0x5FA3,0x5FA4,0x5FA5,0x5FA6,0x5FA7,0x5FA9,0x5FAB,0x5FAC,0x5FAF,0x5FB0,0x5FB1,0x5FB2,0x5FB3,0x5FB4,0x5FB6,0x5FB8,0x5FB9,0x5FBA,0x5FBB,0x5FBE,0x5FBF,0x5FC0,0x5FC1,0x5FC2,0x5FC7,0x5FC8,0x5FCA,0x5FCB,0x5FCE,0x5FD3,0x5FD4,0x5FD5,0x5FDA,0x5FDB,0x5FDC,0x5FDE,0x5FDF,0x5FE2,0x5FE3,0x5FE5,0x5FE6,0x5FE8,0x5FE9,0x5FEC,0x5FEF,0x5FF0,0x5FF2,0x5FF3,0x5FF4,0x5FF6,0x5FF7,0x5FF9,0x5FFA,0x5FFC,0x6007,0x6008,0x6009,0x600B,0x600C,0x6010,0x6011,0x6013,0x6017,0x6018,0x601A,0x601E,0x601F,0x6022,0x6023,0x6024,0x602C,0x602D,0x602E,0x6030,0x6031,0x6032,0x6033,0x6034,0x6036,0x6037,0x6038,0x6039,0x603A,0x603D,0x603E,0x6040,0x6044,0x6045,0x6046,0x6047,0x6048,0x6049,0x604A,0x604C,0x604E,0x604F,0x6051,0x6053,0x6054,0x6056,0x6057,0x6058,0x605B,0x605C,0x605E,0x605F,0x6060,0x6061,0x6065,0x6066,0x606E,0x6071,0x6072,0x6074,0x6075,0x6077,0x607E,0x6080,0x6081,0x6082,0x6085,0x6086,0x6087,0x6088,0x608A,0x608B,0x608E,0x608F,0x6090,0x6091,0x6093,0x6095,0x6097,0x6098,0x6099,0x609C,0x609E,0x60A1,0x60A2,0x60A4,0x60A5,0x60A7,0x60A9,0x60AA,0x60AE,0x60B0,0x60B3,0x60B5,0x60B6,0x60B7,0x60B9,0x60BA,0x60BD,0x60BE,0x60BF,0x60C0,0x60C1,0x60C2,0x60C3,0x60C4,0x60C7,0x60C8,0x60C9,0x60CC,0x60CD,0x60CE,0x60CF,0x60D0,0x60D2,0x60D3,0x60D4,0x60D6,0x60D7,0x60D9,0x60DB,0x60DE,0x60E1,0x60E2,0x60E3,0x60E4,0x60E5,0x60EA,0x60F1,0x60F2,0x60F5,0x60F7,0x60F8,0x60FB,0x60FC,0x60FD,0x60FE,0x60FF,0x6102,0x6103,0x6104,0x6105,0x6107,0x610A,0x610B,0x610C,0x6110,0x6111,0x6112,0x6113,0x6114,0x6116,0x6117,0x6118,0x6119,0x611B,0x611C,0x611D,0x611E,0x6121,0x6122,0x6125,0x6128,0x6129,0x612A,0x612C,0x612D,0x612E,0x612F,0x6130,0x6131,0x6132,0x6133,0x6134,0x6135,0x6136,0x6137,0x6138,0x6139,0x613A,0x613B,0x613C,0x613D,0x613E,0x6140,0x6141,0x6142,0x6143,0x6144,0x6145,0x6146,0x6147,0x6149,0x614B,0x614D,0x614F,0x6150,0x6152,0x6153,0x6154,0x6156,0x6157,0x6158,0x6159,0x615A,0x615B,0x615C,0x615E,0x615F,0x6160,0x6161,0x6163,0x6164,0x6165,0x6166,0x6169,0x616A,0x616B,0x616C,0x616D,0x616E,0x616F,0x6171,0x6172,0x6173,0x6174,0x6176,0x6178,0x6179,0x617A,0x617B,0x617C,0x617D,0x617E,0x617F,0x6180,0x6181,0x6182,0x6183,0x6184,0x6185,0x6186,0x6187,0x6188,0x6189,0x618A,0x618C,0x618D,0x618F,0x6190,0x6191,0x6192,0x6193,0x6195,0x6196,0x6197,0x6198,0x6199,0x619A,0x619B,0x619C,0x619E,0x619F,0x61A0,0x61A1,0x61A2,0x61A3,0x61A4,0x61A5,0x61A6,0x61AA,0x61AB,0x61AD,0x61AE,0x61AF,0x61B0,0x61B1,0x61B2,0x61B3,0x61B4,0x61B5,0x61B6,0x61B8,0x61B9,0x61BA,0x61BB,0x61BC,0x61BD,0x61BF,0x61C0,0x61C1,0x61C3,0x61C4,0x61C5,0x61C6,0x61C7,0x61C9,0x61CC,0x61CD,0x61CE,0x61CF,0x61D0,0x61D3,0x61D5,0x61D6,0x61D7,0x61D8,0x61D9,0x61DA,0x61DB,0x61DC,0x61DD,0x61DE,0x61DF,0x61E0,0x61E1,0x61E2,0x61E3,0x61E4,0x61E5,0x61E7,0x61E8,0x61E9,0x61EA,0x61EB,0x61EC,0x61ED,0x61EE,0x61EF,0x61F0,0x61F1,0x61F2,0x61F3,0x61F4,0x61F6,0x61F7,0x61F8,0x61F9,0x61FA,0x61FB,0x61FC,0x61FD,0x61FE,0x6200,0x6201,0x6202,0x6203,0x6204,0x6205,0x6207,0x6209,0x6213,0x6214,0x6219,0x621C,0x621D,0x621E,0x6220,0x6223,0x6226,0x6227,0x6228,0x6229,0x622B,0x622D,0x622F,0x6230,0x6231,0x6232,0x6235,0x6236,0x6238,0x6239,0x623A,0x623B,0x623C,0x6242,0x6244,0x6245,0x6246,0x624A,0x624F,0x6250,0x6255,0x6256,0x6257,0x6259,0x625A,0x625C,0x625D,0x625E,0x625F,0x6260,0x6261,0x6262,0x6264,0x6265,0x6268,0x6271,0x6272,0x6274,0x6275,0x6277,0x6278,0x627A,0x627B,0x627D,0x6281,0x6282,0x6283,0x6285,0x6286,0x6287,0x6288,0x628B,0x628C,0x628D,0x628E,0x628F,0x6290,0x6294,0x6299,0x629C,0x629D,0x629E,0x62A3,0x62A6,0x62A7,0x62A9,0x62AA,0x62AD,0x62AE,0x62AF,0x62B0,0x62B2,0x62B3,0x62B4,0x62B6,0x62B7,0x62B8,0x62BA,0x62BE,0x62C0,0x62C1,0x62C3,0x62CB,0x62CF,0x62D1,0x62D5,0x62DD,0x62DE,0x62E0,0x62E1,0x62E4,0x62EA,0x62EB,0x62F0,0x62F2,0x62F5,0x62F8,0x62F9,0x62FA,0x62FB,0x6300,0x6303,0x6304,0x6305,0x6306,0x630A,0x630B,0x630C,0x630D,0x630F,0x6310,0x6312,0x6313,0x6314,0x6315,0x6317,0x6318,0x6319,0x631C,0x6326,0x6327,0x6329,0x632C,0x632D,0x632E,0x6330,0x6331,0x6333,0x6334,0x6335,0x6336,0x6337,0x6338,0x633B,0x633C,0x633E,0x633F,0x6340,0x6341,0x6344,0x6347,0x6348,0x634A,0x6351,0x6352,0x6353,0x6354,0x6356,0x6357,0x6358,0x6359,0x635A,0x635B,0x635C,0x635D,0x6360,0x6364,0x6365,0x6366,0x6368,0x636A,0x636B,0x636C,0x636F,0x6370,0x6372,0x6373,0x6374,0x6375,0x6378,0x6379,0x637C,0x637D,0x637E,0x637F,0x6381,0x6383,0x6384,0x6385,0x6386,0x638B,0x638D,0x6391,0x6393,0x6394,0x6395,0x6397,0x6399,0x639A,0x639B,0x639C,0x639D,0x639E,0x639F,0x63A1,0x63A4,0x63A6,0x63AB,0x63AF,0x63B1,0x63B2,0x63B5,0x63B6,0x63B9,0x63BB,0x63BD,0x63BF,0x63C0,0x63C1,0x63C2,0x63C3,0x63C5,0x63C7,0x63C8,0x63CA,0x63CB,0x63CC,0x63D1,0x63D3,0x63D4,0x63D5,0x63D7,0x63D8,0x63D9,0x63DA,0x63DB,0x63DC,0x63DD,0x63DF,0x63E2,0x63E4,0x63E5,0x63E6,0x63E7,0x63E8,0x63EB,0x63EC,0x63EE,0x63EF,0x63F0,0x63F1,0x63F3,0x63F5,0x63F7,0x63F9,0x63FA,0x63FB,0x63FC,0x63FE,0x6403,0x6404,0x6406,0x6407,0x6408,0x6409,0x640A,0x640D,0x640E,0x6411,0x6412,0x6415,0x6416,0x6417,0x6418,0x6419,0x641A,0x641D,0x641F,0x6422,0x6423,0x6424,0x6425,0x6427,0x6428,0x6429,0x642B,0x642E,0x642F,0x6430,0x6431,0x6432,0x6433,0x6435,0x6436,0x6437,0x6438,0x6439,0x643B,0x643C,0x643E,0x6440,0x6442,0x6443,0x6449,0x644B,0x644C,0x644D,0x644E,0x644F,0x6450,0x6451,0x6453,0x6455,0x6456,0x6457,0x6459,0x645A,0x645B,0x645C,0x645D,0x645F,0x6460,0x6461,0x6462,0x6463,0x6464,0x6465,0x6466,0x6468,0x646A,0x646B,0x646C,0x646E,0x646F,0x6470,0x6471,0x6472,0x6473,0x6474,0x6475,0x6476,0x6477,0x647B,0x647C,0x647D,0x647E,0x647F,0x6480,0x6481,0x6483,0x6486,0x6488,0x6489,0x648A,0x648B,0x648C,0x648D,0x648E,0x648F,0x6490,0x6493,0x6494,0x6497,0x6498,0x649A,0x649B,0x649C,0x649D,0x649F,0x64A0,0x64A1,0x64A2,0x64A3,0x64A5,0x64A6,0x64A7,0x64A8,0x64AA,0x64AB,0x64AF,0x64B1,0x64B2,0x64B3,0x64B4,0x64B6,0x64B9,0x64BB,0x64BD,0x64BE,0x64BF,0x64C1,0x64C3,0x64C4,0x64C6,0x64C7,0x64C8,0x64C9,0x64CA,0x64CB,0x64CC,0x64CF,0x64D1,0x64D3,0x64D4,0x64D5,0x64D6,0x64D9,0x64DA,0x64DB,0x64DC,0x64DD,0x64DF,0x64E0,0x64E1,0x64E3,0x64E5,0x64E7,0x64E8,0x64E9,0x64EA,0x64EB,0x64EC,0x64ED,0x64EE,0x64EF,0x64F0,0x64F1,0x64F2,0x64F3,0x64F4,0x64F5,0x64F6,0x64F7,0x64F8,0x64F9,0x64FA,0x64FB,0x64FC,0x64FD,0x64FE,0x64FF,0x6501,0x6502,0x6503,0x6504,0x6505,0x6506,0x6507,0x6508,0x650A,0x650B,0x650C,0x650D,0x650E,0x650F,0x6510,0x6511,0x6513,0x6514,0x6515,0x6516,0x6517,0x6519,0x651A,0x651B,0x651C,0x651D,0x651E,0x651F,0x6520,0x6521,0x6522,0x6523,0x6524,0x6526,0x6527,0x6528,0x6529,0x652A,0x652C,0x652D,0x6530,0x6531,0x6532,0x6533,0x6537,0x653A,0x653C,0x653D,0x6540,0x6541,0x6542,0x6543,0x6544,0x6546,0x6547,0x654A,0x654B,0x654D,0x654E,0x6550,0x6552,0x6553,0x6554,0x6557,0x6558,0x655A,0x655C,0x655F,0x6560,0x6561,0x6564,0x6565,0x6567,0x6568,0x6569,0x656A,0x656D,0x656E,0x656F,0x6571,0x6573,0x6575,0x6576,0x6578,0x6579,0x657A,0x657B,0x657C,0x657D,0x657E,0x657F,0x6580,0x6581,0x6582,0x6583,0x6584,0x6585,0x6586,0x6588,0x6589,0x658A,0x658D,0x658E,0x658F,0x6592,0x6594,0x6595,0x6596,0x6598,0x659A,0x659D,0x659E,0x65A0,0x65A2,0x65A3,0x65A6,0x65A8,0x65AA,0x65AC,0x65AE,0x65B1,0x65B2,0x65B3,0x65B4,0x65B5,0x65B6,0x65B7,0x65B8,0x65BA,0x65BB,0x65BE,0x65BF,0x65C0,0x65C2,0x65C7,0x65C8,0x65C9,0x65CA,0x65CD,0x65D0,0x65D1,0x65D3,0x65D4,0x65D5,0x65D8,0x65D9,0x65DA,0x65DB,0x65DC,0x65DD,0x65DE,0x65DF,0x65E1,0x65E3,0x65E4,0x65EA,0x65EB,0x65F2,0x65F3,0x65F4,0x65F5,0x65F8,0x65F9,0x65FB,0x65FC,0x65FD,0x65FE,0x65FF,0x6601,0x6604,0x6605,0x6607,0x6608,0x6609,0x660B,0x660D,0x6610,0x6611,0x6612,0x6616,0x6617,0x6618,0x661A,0x661B,0x661C,0x661E,0x6621,0x6622,0x6623,0x6624,0x6626,0x6629,0x662A,0x662B,0x662C,0x662E,0x6630,0x6632,0x6633,0x6637,0x6638,0x6639,0x663A,0x663B,0x663D,0x663F,0x6640,0x6642,0x6644,0x6645,0x6646,0x6647,0x6648,0x6649,0x664A,0x664D,0x664E,0x6650,0x6651,0x6658,0x6659,0x665B,0x665C,0x665D,0x665E,0x6660,0x6662,0x6663,0x6665,0x6667,0x6669,0x666A,0x666B,0x666C,0x666D,0x6671,0x6672,0x6673,0x6675,0x6678,0x6679,0x667B,0x667C,0x667D,0x667F,0x6680,0x6681,0x6683,0x6685,0x6686,0x6688,0x6689,0x668A,0x668B,0x668D,0x668E,0x668F,0x6690,0x6692,0x6693,0x6694,0x6695,0x6698,0x6699,0x669A,0x669B,0x669C,0x669E,0x669F,0x66A0,0x66A1,0x66A2,0x66A3,0x66A4,0x66A5,0x66A6,0x66A9,0x66AA,0x66AB,0x66AC,0x66AD,0x66AF,0x66B0,0x66B1,0x66B2,0x66B3,0x66B5,0x66B6,0x66B7,0x66B8,0x66BA,0x66BB,0x66BC,0x66BD,0x66BF,0x66C0,0x66C1,0x66C2,0x66C3,0x66C4,0x66C5,0x66C6,0x66C7,0x66C8,0x66C9,0x66CA,0x66CB,0x66CC,0x66CD,0x66CE,0x66CF,0x66D0,0x66D1,0x66D2,0x66D3,0x66D4,0x66D5,0x66D6,0x66D7,0x66D8,0x66DA,0x66DE,0x66DF,0x66E0,0x66E1,0x66E2,0x66E3,0x66E4,0x66E5,0x66E7,0x66E8,0x66EA,0x66EB,0x66EC,0x66ED,0x66EE,0x66EF,0x66F1,0x66F5,0x66F6,0x66F8,0x66FA,0x66FB,0x66FD,0x6701,0x6702,0x6703,0x6704,0x6705,0x6706,0x6707,0x670C,0x670E,0x670F,0x6711,0x6712,0x6713,0x6716,0x6718,0x6719,0x671A,0x671C,0x671E,0x6720,0x6721,0x6722,0x6723,0x6724,0x6725,0x6727,0x6729,0x672E,0x6730,0x6732,0x6733,0x6736,0x6737,0x6738,0x6739,0x673B,0x673C,0x673E,0x673F,0x6741,0x6744,0x6745,0x6747,0x674A,0x674B,0x674D,0x6752,0x6754,0x6755,0x6757,0x6758,0x6759,0x675A,0x675B,0x675D,0x6762,0x6763,0x6764,0x6766,0x6767,0x676B,0x676C,0x676E,0x6771,0x6774,0x6776,0x6778,0x6779,0x677A,0x677B,0x677D,0x6780,0x6782,0x6783,0x6785,0x6786,0x6788,0x678A,0x678C,0x678D,0x678E,0x678F,0x6791,0x6792,0x6793,0x6794,0x6796,0x6799,0x679B,0x679F,0x67A0,0x67A1,0x67A4,0x67A6,0x67A9,0x67AC,0x67AE,0x67B1,0x67B2,0x67B4,0x67B9,0x67BA,0x67BB,0x67BC,0x67BD,0x67BE,0x67BF,0x67C0,0x67C2,0x67C5,0x67C6,0x67C7,0x67C8,0x67C9,0x67CA,0x67CB,0x67CC,0x67CD,0x67CE,0x67D5,0x67D6,0x67D7,0x67DB,0x67DF,0x67E1,0x67E3,0x67E4,0x67E6,0x67E7,0x67E8,0x67EA,0x67EB,0x67ED,0x67EE,0x67F2,0x67F5,0x67F6,0x67F7,0x67F8,0x67F9,0x67FA,0x67FB,0x67FC,0x67FE,0x6801,0x6802,0x6803,0x6804,0x6806,0x680D,0x6810,0x6812,0x6814,0x6815,0x6818,0x6819,0x681A,0x681B,0x681C,0x681E,0x681F,0x6820,0x6822,0x6823,0x6824,0x6825,0x6826,0x6827,0x6828,0x682B,0x682C,0x682D,0x682E,0x682F,0x6830,0x6831,0x6834,0x6835,0x6836,0x683A,0x683B,0x683F,0x6847,0x684B,0x684D,0x684F,0x6852,0x6856,0x6857,0x6858,0x6859,0x685A,0x685B,0x685C,0x685D,0x685E,0x685F,0x686A,0x686C,0x686D,0x686E,0x686F,0x6870,0x6871,0x6872,0x6873,0x6875,0x6878,0x6879,0x687A,0x687B,0x687C,0x687D,0x687E,0x687F,0x6880,0x6882,0x6884,0x6887,0x6888,0x6889,0x688A,0x688B,0x688C,0x688D,0x688E,0x6890,0x6891,0x6892,0x6894,0x6895,0x6896,0x6898,0x6899,0x689A,0x689B,0x689C,0x689D,0x689E,0x689F,0x68A0,0x68A1,0x68A3,0x68A4,0x68A5,0x68A9,0x68AA,0x68AB,0x68AC,0x68AE,0x68B1,0x68B2,0x68B4,0x68B6,0x68B7,0x68B8,0x68B9,0x68BA,0x68BB,0x68BC,0x68BD,0x68BE,0x68BF,0x68C1,0x68C3,0x68C4,0x68C5,0x68C6,0x68C7,0x68C8,0x68CA,0x68CC,0x68CE,0x68CF,0x68D0,0x68D1,0x68D3,0x68D4,0x68D6,0x68D7,0x68D9,0x68DB,0x68DC,0x68DD,0x68DE,0x68DF,0x68E1,0x68E2,0x68E4,0x68E5,0x68E6,0x68E7,0x68E8,0x68E9,0x68EA,0x68EB,0x68EC,0x68ED,0x68EF,0x68F2,0x68F3,0x68F4,0x68F6,0x68F7,0x68F8,0x68FB,0x68FD,0x68FE,0x68FF,0x6900,0x6902,0x6903,0x6904,0x6906,0x6907,0x6908,0x6909,0x690A,0x690C,0x690F,0x6911,0x6913,0x6914,0x6915,0x6916,0x6917,0x6918,0x6919,0x691A,0x691B,0x691C,0x691D,0x691E,0x6921,0x6922,0x6923,0x6925,0x6926,0x6927,0x6928,0x6929,0x692A,0x692B,0x692C,0x692E,0x692F,0x6931,0x6932,0x6933,0x6935,0x6936,0x6937,0x6938,0x693A,0x693B,0x693C,0x693E,0x6940,0x6941,0x6943,0x6944,0x6945,0x6946,0x6947,0x6948,0x6949,0x694A,0x694B,0x694C,0x694D,0x694E,0x694F,0x6950,0x6951,0x6952,0x6953,0x6955,0x6956,0x6958,0x6959,0x695B,0x695C,0x695F,0x6961,0x6962,0x6964,0x6965,0x6967,0x6968,0x6969,0x696A,0x696C,0x696D,0x696F,0x6970,0x6972,0x6973,0x6974,0x6975,0x6976,0x697A,0x697B,0x697D,0x697E,0x697F,0x6981,0x6983,0x6985,0x698A,0x698B,0x698C,0x698E,0x698F,0x6990,0x6991,0x6992,0x6993,0x6996,0x6997,0x6999,0x699A,0x699D,0x699E,0x699F,0x69A0,0x69A1,0x69A2,0x69A3,0x69A4,0x69A5,0x69A6,0x69A9,0x69AA,0x69AC,0x69AE,0x69AF,0x69B0,0x69B2,0x69B3,0x69B5,0x69B6,0x69B8,0x69B9,0x69BA,0x69BC,0x69BD,0x69BE,0x69BF,0x69C0,0x69C2,0x69C3,0x69C4,0x69C5,0x69C6,0x69C7,0x69C8,0x69C9,0x69CB,0x69CD,0x69CF,0x69D1,0x69D2,0x69D3,0x69D5,0x69D6,0x69D7,0x69D8,0x69D9,0x69DA,0x69DC,0x69DD,0x69DE,0x69E1,0x69E2,0x69E3,0x69E4,0x69E5,0x69E6,0x69E7,0x69E8,0x69E9,0x69EA,0x69EB,0x69EC,0x69EE,0x69EF,0x69F0,0x69F1,0x69F3,0x69F4,0x69F5,0x69F6,0x69F7,0x69F8,0x69F9,0x69FA,0x69FB,0x69FC,0x69FE,0x6A00,0x6A01,0x6A02,0x6A03,0x6A04,0x6A05,0x6A06,0x6A07,0x6A08,0x6A09,0x6A0B,0x6A0C,0x6A0D,0x6A0E,0x6A0F,0x6A10,0x6A11,0x6A12,0x6A13,0x6A14,0x6A15,0x6A16,0x6A19,0x6A1A,0x6A1B,0x6A1C,0x6A1D,0x6A1E,0x6A20,0x6A22,0x6A23,0x6A24,0x6A25,0x6A26,0x6A27,0x6A29,0x6A2B,0x6A2C,0x6A2D,0x6A2E,0x6A30,0x6A32,0x6A33,0x6A34,0x6A36,0x6A37,0x6A38,0x6A39,0x6A3A,0x6A3B,0x6A3C,0x6A3F,0x6A40,0x6A41,0x6A42,0x6A43,0x6A45,0x6A46,0x6A48,0x6A49,0x6A4A,0x6A4B,0x6A4C,0x6A4D,0x6A4E,0x6A4F,0x6A51,0x6A52,0x6A53,0x6A54,0x6A55,0x6A56,0x6A57,0x6A5A,0x6A5C,0x6A5D,0x6A5E,0x6A5F,0x6A60,0x6A62,0x6A63,0x6A64,0x6A66,0x6A67,0x6A68,0x6A69,0x6A6A,0x6A6B,0x6A6C,0x6A6D,0x6A6E,0x6A6F,0x6A70,0x6A72,0x6A73,0x6A74,0x6A75,0x6A76,0x6A77,0x6A78,0x6A7A,0x6A7B,0x6A7D,0x6A7E,0x6A7F,0x6A81,0x6A82,0x6A83,0x6A85,0x6A86,0x6A87,0x6A88,0x6A89,0x6A8A,0x6A8B,0x6A8C,0x6A8D,0x6A8F,0x6A92,0x6A93,0x6A94,0x6A95,0x6A96,0x6A98,0x6A99,0x6A9A,0x6A9B,0x6A9C,0x6A9D,0x6A9E,0x6A9F,0x6AA1,0x6AA2,0x6AA3,0x6AA4,0x6AA5,0x6AA6,0x6AA7,0x6AA8,0x6AAA,0x6AAD,0x6AAE,0x6AAF,0x6AB0,0x6AB1,0x6AB2,0x6AB3,0x6AB4,0x6AB5,0x6AB6,0x6AB7,0x6AB8,0x6AB9,0x6ABA,0x6ABB,0x6ABC,0x6ABD,0x6ABE,0x6ABF,0x6AC0,0x6AC1,0x6AC2,0x6AC3,0x6AC4,0x6AC5,0x6AC6,0x6AC7,0x6AC8,0x6AC9,0x6ACA,0x6ACB,0x6ACC,0x6ACD,0x6ACE,0x6ACF,0x6AD0,0x6AD1,0x6AD2,0x6AD3,0x6AD4,0x6AD5,0x6AD6,0x6AD7,0x6AD8,0x6AD9,0x6ADA,0x6ADB,0x6ADC,0x6ADD,0x6ADE,0x6ADF,0x6AE0,0x6AE1,0x6AE2,0x6AE3,0x6AE4,0x6AE5,0x6AE6,0x6AE7,0x6AE8,0x6AE9,0x6AEA,0x6AEB,0x6AEC,0x6AED,0x6AEE,0x6AEF,0x6AF0,0x6AF1,0x6AF2,0x6AF3,0x6AF4,0x6AF5,0x6AF6,0x6AF7,0x6AF8,0x6AF9,0x6AFA,0x6AFB,0x6AFC,0x6AFD,0x6AFE,0x6AFF,0x6B00,0x6B01,0x6B02,0x6B03,0x6B04,0x6B05,0x6B06,0x6B07,0x6B08,0x6B09,0x6B0A,0x6B0B,0x6B0C,0x6B0D,0x6B0E,0x6B0F,0x6B10,0x6B11,0x6B12,0x6B13,0x6B14,0x6B15,0x6B16,0x6B17,0x6B18,0x6B19,0x6B1A,0x6B1B,0x6B1C,0x6B1D,0x6B1E,0x6B1F,0x6B25,0x6B26,0x6B28,0x6B29,0x6B2A,0x6B2B,0x6B2C,0x6B2D,0x6B2E,0x6B2F,0x6B30,0x6B31,0x6B33,0x6B34,0x6B35,0x6B36,0x6B38,0x6B3B,0x6B3C,0x6B3D,0x6B3F,0x6B40,0x6B41,0x6B42,0x6B44,0x6B45,0x6B48,0x6B4A,0x6B4B,0x6B4D,0x6B4E,0x6B4F,0x6B50,0x6B51,0x6B52,0x6B53,0x6B54,0x6B55,0x6B56,0x6B57,0x6B58,0x6B5A,0x6B5B,0x6B5C,0x6B5D,0x6B5E,0x6B5F,0x6B60,0x6B61,0x6B68,0x6B69,0x6B6B,0x6B6C,0x6B6D,0x6B6E,0x6B6F,0x6B70,0x6B71,0x6B72,0x6B73,0x6B74,0x6B75,0x6B76,0x6B77,0x6B78,0x6B7A,0x6B7D,0x6B7E,0x6B7F,0x6B80,0x6B85,0x6B88,0x6B8C,0x6B8E,0x6B8F,0x6B90,0x6B91,0x6B94,0x6B95,0x6B97,0x6B98,0x6B99,0x6B9C,0x6B9D,0x6B9E,0x6B9F,0x6BA0,0x6BA2,0x6BA3,0x6BA4,0x6BA5,0x6BA6,0x6BA7,0x6BA8,0x6BA9,0x6BAB,0x6BAC,0x6BAD,0x6BAE,0x6BAF,0x6BB0,0x6BB1,0x6BB2,0x6BB6,0x6BB8,0x6BB9,0x6BBA,0x6BBB,0x6BBC,0x6BBD,0x6BBE,0x6BC0,0x6BC3,0x6BC4,0x6BC6,0x6BC7,0x6BC8,0x6BC9,0x6BCA,0x6BCC,0x6BCE,0x6BD0,0x6BD1,0x6BD8,0x6BDA,0x6BDC,0x6BDD,0x6BDE,0x6BDF,0x6BE0,0x6BE2,0x6BE3,0x6BE4,0x6BE5,0x6BE6,0x6BE7,0x6BE8,0x6BE9,0x6BEC,0x6BED,0x6BEE,0x6BF0,0x6BF1,0x6BF2,0x6BF4,0x6BF6,0x6BF7,0x6BF8,0x6BFA,0x6BFB,0x6BFC,0x6BFE,0x6BFF,0x6C00,0x6C01,0x6C02,0x6C03,0x6C04,0x6C08,0x6C09,0x6C0A,0x6C0B,0x6C0C,0x6C0E,0x6C12,0x6C17,0x6C1C,0x6C1D,0x6C1E,0x6C20,0x6C23,0x6C25,0x6C2B,0x6C2C,0x6C2D,0x6C31,0x6C33,0x6C36,0x6C37,0x6C39,0x6C3A,0x6C3B,0x6C3C,0x6C3E,0x6C3F,0x6C43,0x6C44,0x6C45,0x6C48,0x6C4B,0x6C4C,0x6C4D,0x6C4E,0x6C4F,0x6C51,0x6C52,0x6C53,0x6C56,0x6C58,0x6C59,0x6C5A,0x6C62,0x6C63,0x6C65,0x6C66,0x6C67,0x6C6B,0x6C6C,0x6C6D,0x6C6E,0x6C6F,0x6C71,0x6C73,0x6C75,0x6C77,0x6C78,0x6C7A,0x6C7B,0x6C7C,0x6C7F,0x6C80,0x6C84,0x6C87,0x6C8A,0x6C8B,0x6C8D,0x6C8E,0x6C91,0x6C92,0x6C95,0x6C96,0x6C97,0x6C98,0x6C9A,0x6C9C,0x6C9D,0x6C9E,0x6CA0,0x6CA2,0x6CA8,0x6CAC,0x6CAF,0x6CB0,0x6CB4,0x6CB5,0x6CB6,0x6CB7,0x6CBA,0x6CC0,0x6CC1,0x6CC2,0x6CC3,0x6CC6,0x6CC7,0x6CC8,0x6CCB,0x6CCD,0x6CCE,0x6CCF,0x6CD1,0x6CD2,0x6CD8,0x6CD9,0x6CDA,0x6CDC,0x6CDD,0x6CDF,0x6CE4,0x6CE6,0x6CE7,0x6CE9,0x6CEC,0x6CED,0x6CF2,0x6CF4,0x6CF9,0x6CFF,0x6D00,0x6D02,0x6D03,0x6D05,0x6D06,0x6D08,0x6D09,0x6D0A,0x6D0D,0x6D0F,0x6D10,0x6D11,0x6D13,0x6D14,0x6D15,0x6D16,0x6D18,0x6D1C,0x6D1D,0x6D1F,0x6D20,0x6D21,0x6D22,0x6D23,0x6D24,0x6D26,0x6D28,0x6D29,0x6D2C,0x6D2D,0x6D2F,0x6D30,0x6D34,0x6D36,0x6D37,0x6D38,0x6D3A,0x6D3F,0x6D40,0x6D42,0x6D44,0x6D49,0x6D4C,0x6D50,0x6D55,0x6D56,0x6D57,0x6D58,0x6D5B,0x6D5D,0x6D5F,0x6D61,0x6D62,0x6D64,0x6D65,0x6D67,0x6D68,0x6D6B,0x6D6C,0x6D6D,0x6D70,0x6D71,0x6D72,0x6D73,0x6D75,0x6D76,0x6D79,0x6D7A,0x6D7B,0x6D7D,0x6D7E,0x6D7F,0x6D80,0x6D81,0x6D83,0x6D84,0x6D86,0x6D87,0x6D8A,0x6D8B,0x6D8D,0x6D8F,0x6D90,0x6D92,0x6D96,0x6D97,0x6D98,0x6D99,0x6D9A,0x6D9C,0x6DA2,0x6DA5,0x6DAC,0x6DAD,0x6DB0,0x6DB1,0x6DB3,0x6DB4,0x6DB6,0x6DB7,0x6DB9,0x6DBA,0x6DBB,0x6DBC,0x6DBD,0x6DBE,0x6DC1,0x6DC2,0x6DC3,0x6DC8,0x6DC9,0x6DCA,0x6DCD,0x6DCE,0x6DCF,0x6DD0,0x6DD2,0x6DD3,0x6DD4,0x6DD5,0x6DD7,0x6DDA,0x6DDB,0x6DDC,0x6DDF,0x6DE2,0x6DE3,0x6DE5,0x6DE7,0x6DE8,0x6DE9,0x6DEA,0x6DED,0x6DEF,0x6DF0,0x6DF2,0x6DF4,0x6DF5,0x6DF6,0x6DF8,0x6DFA,0x6DFD,0x6DFE,0x6DFF,0x6E00,0x6E01,0x6E02,0x6E03,0x6E04,0x6E06,0x6E07,0x6E08,0x6E09,0x6E0B,0x6E0F,0x6E12,0x6E13,0x6E15,0x6E18,0x6E19,0x6E1B,0x6E1C,0x6E1E,0x6E1F,0x6E22,0x6E26,0x6E27,0x6E28,0x6E2A,0x6E2C,0x6E2E,0x6E30,0x6E31,0x6E33,0x6E35,0x6E36,0x6E37,0x6E39,0x6E3B,0x6E3C,0x6E3D,0x6E3E,0x6E3F,0x6E40,0x6E41,0x6E42,0x6E45,0x6E46,0x6E47,0x6E48,0x6E49,0x6E4A,0x6E4B,0x6E4C,0x6E4F,0x6E50,0x6E51,0x6E52,0x6E55,0x6E57,0x6E59,0x6E5A,0x6E5C,0x6E5D,0x6E5E,0x6E60,0x6E61,0x6E62,0x6E63,0x6E64,0x6E65,0x6E66,0x6E67,0x6E68,0x6E69,0x6E6A,0x6E6C,0x6E6D,0x6E6F,0x6E70,0x6E71,0x6E72,0x6E73,0x6E74,0x6E75,0x6E76,0x6E77,0x6E78,0x6E79,0x6E7A,0x6E7B,0x6E7C,0x6E7D,0x6E80,0x6E81,0x6E82,0x6E84,0x6E87,0x6E88,0x6E8A,0x6E8B,0x6E8C,0x6E8D,0x6E8E,0x6E91,0x6E92,0x6E93,0x6E94,0x6E95,0x6E96,0x6E97,0x6E99,0x6E9A,0x6E9B,0x6E9D,0x6E9E,0x6EA0,0x6EA1,0x6EA3,0x6EA4,0x6EA6,0x6EA8,0x6EA9,0x6EAB,0x6EAC,0x6EAD,0x6EAE,0x6EB0,0x6EB3,0x6EB5,0x6EB8,0x6EB9,0x6EBC,0x6EBE,0x6EBF,0x6EC0,0x6EC3,0x6EC4,0x6EC5,0x6EC6,0x6EC8,0x6EC9,0x6ECA,0x6ECC,0x6ECD,0x6ECE,0x6ED0,0x6ED2,0x6ED6,0x6ED8,0x6ED9,0x6EDB,0x6EDC,0x6EDD,0x6EE3,0x6EE7,0x6EEA,0x6EEB,0x6EEC,0x6EED,0x6EEE,0x6EEF,0x6EF0,0x6EF1,0x6EF2,0x6EF3,0x6EF5,0x6EF6,0x6EF7,0x6EF8,0x6EFA,0x6EFB,0x6EFC,0x6EFD,0x6EFE,0x6EFF,0x6F00,0x6F01,0x6F03,0x6F04,0x6F05,0x6F07,0x6F08,0x6F0A,0x6F0B,0x6F0C,0x6F0D,0x6F0E,0x6F10,0x6F11,0x6F12,0x6F16,0x6F17,0x6F18,0x6F19,0x6F1A,0x6F1B,0x6F1C,0x6F1D,0x6F1E,0x6F1F,0x6F21,0x6F22,0x6F23,0x6F25,0x6F26,0x6F27,0x6F28,0x6F2C,0x6F2E,0x6F30,0x6F32,0x6F34,0x6F35,0x6F37,0x6F38,0x6F39,0x6F3A,0x6F3B,0x6F3C,0x6F3D,0x6F3F,0x6F40,0x6F41,0x6F42,0x6F43,0x6F44,0x6F45,0x6F48,0x6F49,0x6F4A,0x6F4C,0x6F4E,0x6F4F,0x6F50,0x6F51,0x6F52,0x6F53,0x6F54,0x6F55,0x6F56,0x6F57,0x6F59,0x6F5A,0x6F5B,0x6F5D,0x6F5F,0x6F60,0x6F61,0x6F63,0x6F64,0x6F65,0x6F67,0x6F68,0x6F69,0x6F6A,0x6F6B,0x6F6C,0x6F6F,0x6F70,0x6F71,0x6F73,0x6F75,0x6F76,0x6F77,0x6F79,0x6F7B,0x6F7D,0x6F7E,0x6F7F,0x6F80,0x6F81,0x6F82,0x6F83,0x6F85,0x6F86,0x6F87,0x6F8A,0x6F8B,0x6F8F,0x6F90,0x6F91,0x6F92,0x6F93,0x6F94,0x6F95,0x6F96,0x6F97,0x6F98,0x6F99,0x6F9A,0x6F9B,0x6F9D,0x6F9E,0x6F9F,0x6FA0,0x6FA2,0x6FA3,0x6FA4,0x6FA5,0x6FA6,0x6FA8,0x6FA9,0x6FAA,0x6FAB,0x6FAC,0x6FAD,0x6FAE,0x6FAF,0x6FB0,0x6FB1,0x6FB2,0x6FB4,0x6FB5,0x6FB7,0x6FB8,0x6FBA,0x6FBB,0x6FBC,0x6FBD,0x6FBE,0x6FBF,0x6FC1,0x6FC3,0x6FC4,0x6FC5,0x6FC6,0x6FC7,0x6FC8,0x6FCA,0x6FCB,0x6FCC,0x6FCD,0x6FCE,0x6FCF,0x6FD0,0x6FD3,0x6FD4,0x6FD5,0x6FD6,0x6FD7,0x6FD8,0x6FD9,0x6FDA,0x6FDB,0x6FDC,0x6FDD,0x6FDF,0x6FE2,0x6FE3,0x6FE4,0x6FE5,0x6FE6,0x6FE7,0x6FE8,0x6FE9,0x6FEA,0x6FEB,0x6FEC,0x6FED,0x6FF0,0x6FF1,0x6FF2,0x6FF3,0x6FF4,0x6FF5,0x6FF6,0x6FF7,0x6FF8,0x6FF9,0x6FFA,0x6FFB,0x6FFC,0x6FFD,0x6FFE,0x6FFF,0x7000,0x7001,0x7002,0x7003,0x7004,0x7005,0x7006,0x7007,0x7008,0x7009,0x700A,0x700B,0x700C,0x700D,0x700E,0x700F,0x7010,0x7012,0x7013,0x7014,0x7015,0x7016,0x7017,0x7018,0x7019,0x701C,0x701D,0x701E,0x701F,0x7020,0x7021,0x7022,0x7024,0x7025,0x7026,0x7027,0x7028,0x7029,0x702A,0x702B,0x702C,0x702D,0x702E,0x702F,0x7030,0x7031,0x7032,0x7033,0x7034,0x7036,0x7037,0x7038,0x703A,0x703B,0x703C,0x703D,0x703E,0x703F,0x7040,0x7041,0x7042,0x7043,0x7044,0x7045,0x7046,0x7047,0x7048,0x7049,0x704A,0x704B,0x704D,0x704E,0x7050,0x7051,0x7052,0x7053,0x7054,0x7055,0x7056,0x7057,0x7058,0x7059,0x705A,0x705B,0x705C,0x705D,0x705F,0x7060,0x7061,0x7062,0x7063,0x7064,0x7065,0x7066,0x7067,0x7068,0x7069,0x706A,0x706E,0x7071,0x7072,0x7073,0x7074,0x7077,0x7079,0x707A,0x707B,0x707D,0x7081,0x7082,0x7083,0x7084,0x7086,0x7087,0x7088,0x708B,0x708C,0x708D,0x708F,0x7090,0x7091,0x7093,0x7097,0x7098,0x709A,0x709B,0x709E,0x709F,0x70A0,0x70A1,0x70A2,0x70A3,0x70A4,0x70A5,0x70A6,0x70A7,0x70A8,0x70A9,0x70AA,0x70B0,0x70B2,0x70B4,0x70B5,0x70B6,0x70BA,0x70BE,0x70BF,0x70C4,0x70C5,0x70C6,0x70C7,0x70C9,0x70CB,0x70CC,0x70CD,0x70CE,0x70CF,0x70D0,0x70D1,0x70D2,0x70D3,0x70D4,0x70D5,0x70D6,0x70D7,0x70DA,0x70DC,0x70DD,0x70DE,0x70E0,0x70E1,0x70E2,0x70E3,0x70E5,0x70EA,0x70EE,0x70F0,0x70F1,0x70F2,0x70F3,0x70F4,0x70F5,0x70F6,0x70F8,0x70FA,0x70FB,0x70FC,0x70FE,0x70FF,0x7100,0x7101,0x7102,0x7103,0x7104,0x7105,0x7106,0x7107,0x7108,0x710B,0x710C,0x710D,0x710E,0x710F,0x7111,0x7112,0x7114,0x7117,0x711B,0x711C,0x711D,0x711E,0x711F,0x7120,0x7121,0x7122,0x7123,0x7124,0x7125,0x7127,0x7128,0x7129,0x712A,0x712B,0x712C,0x712D,0x712E,0x7132,0x7133,0x7134,0x7135,0x7137,0x7138,0x7139,0x713A,0x713B,0x713C,0x713D,0x713E,0x713F,0x7140,0x7141,0x7142,0x7143,0x7144,0x7146,0x7147,0x7148,0x7149,0x714B,0x714D,0x714F,0x7150,0x7151,0x7152,0x7153,0x7154,0x7155,0x7156,0x7157,0x7158,0x7159,0x715A,0x715B,0x715D,0x715F,0x7160,0x7161,0x7162,0x7163,0x7165,0x7169,0x716A,0x716B,0x716C,0x716D,0x716F,0x7170,0x7171,0x7174,0x7175,0x7176,0x7177,0x7179,0x717B,0x717C,0x717E,0x717F,0x7180,0x7181,0x7182,0x7183,0x7185,0x7186,0x7187,0x7188,0x7189,0x718B,0x718C,0x718D,0x718E,0x7190,0x7191,0x7192,0x7193,0x7195,0x7196,0x7197,0x719A,0x719B,0x719C,0x719D,0x719E,0x71A1,0x71A2,0x71A3,0x71A4,0x71A5,0x71A6,0x71A7,0x71A9,0x71AA,0x71AB,0x71AD,0x71AE,0x71AF,0x71B0,0x71B1,0x71B2,0x71B4,0x71B6,0x71B7,0x71B8,0x71BA,0x71BB,0x71BC,0x71BD,0x71BE,0x71BF,0x71C0,0x71C1,0x71C2,0x71C4,0x71C5,0x71C6,0x71C7,0x71C8,0x71C9,0x71CA,0x71CB,0x71CC,0x71CD,0x71CF,0x71D0,0x71D1,0x71D2,0x71D3,0x71D6,0x71D7,0x71D8,0x71D9,0x71DA,0x71DB,0x71DC,0x71DD,0x71DE,0x71DF,0x71E1,0x71E2,0x71E3,0x71E4,0x71E6,0x71E8,0x71E9,0x71EA,0x71EB,0x71EC,0x71ED,0x71EF,0x71F0,0x71F1,0x71F2,0x71F3,0x71F4,0x71F5,0x71F6,0x71F7,0x71F8,0x71FA,0x71FB,0x71FC,0x71FD,0x71FE,0x71FF,0x7200,0x7201,0x7202,0x7203,0x7204,0x7205,0x7207,0x7208,0x7209,0x720A,0x720B,0x720C,0x720D,0x720E,0x720F,0x7210,0x7211,0x7212,0x7213,0x7214,0x7215,0x7216,0x7217,0x7218,0x7219,0x721A,0x721B,0x721C,0x721E,0x721F,0x7220,0x7221,0x7222,0x7223,0x7224,0x7225,0x7226,0x7227,0x7229,0x722B,0x722D,0x722E,0x722F,0x7232,0x7233,0x7234,0x723A,0x723C,0x723E,0x7240,0x7241,0x7242,0x7243,0x7244,0x7245,0x7246,0x7249,0x724A,0x724B,0x724E,0x724F,0x7250,0x7251,0x7253,0x7254,0x7255,0x7257,0x7258,0x725A,0x725C,0x725E,0x7260,0x7263,0x7264,0x7265,0x7268,0x726A,0x726B,0x726C,0x726D,0x7270,0x7271,0x7273,0x7274,0x7276,0x7277,0x7278,0x727B,0x727C,0x727D,0x7282,0x7283,0x7285,0x7286,0x7287,0x7288,0x7289,0x728C,0x728E,0x7290,0x7291,0x7293,0x7294,0x7295,0x7296,0x7297,0x7298,0x7299,0x729A,0x729B,0x729C,0x729D,0x729E,0x72A0,0x72A1,0x72A2,0x72A3,0x72A4,0x72A5,0x72A6,0x72A7,0x72A8,0x72A9,0x72AA,0x72AB,0x72AE,0x72B1,0x72B2,0x72B3,0x72B5,0x72BA,0x72BB,0x72BC,0x72BD,0x72BE,0x72BF,0x72C0,0x72C5,0x72C6,0x72C7,0x72C9,0x72CA,0x72CB,0x72CC,0x72CF,0x72D1,0x72D3,0x72D4,0x72D5,0x72D6,0x72D8,0x72DA,0x72DB,0xE4C6,0xE4C7,0xE4C8,0xE4C9,0xE4CA,0xE4CB,0xE4CC,0xE4CD,0xE4CE,0xE4CF,0xE4D0,0xE4D1,0xE4D2,0xE4D3,0xE4D4,0xE4D5,0xE4D6,0xE4D7,0xE4D8,0xE4D9,0xE4DA,0xE4DB,0xE4DC,0xE4DD,0xE4DE,0xE4DF,0xE4E0,0xE4E1,0xE4E2,0xE4E3,0xE4E4,0xE4E5,0xE4E6,0xE4E7,0xE4E8,0xE4E9,0xE4EA,0xE4EB,0xE4EC,0xE4ED,0xE4EE,0xE4EF,0xE4F0,0xE4F1,0xE4F2,0xE4F3,0xE4F4,0xE4F5,0xE4F6,0xE4F7,0xE4F8,0xE4F9,0xE4FA,0xE4FB,0xE4FC,0xE4FD,0xE4FE,0xE4FF,0xE500,0xE501,0xE502,0xE503,0xE504,0xE505,0xE506,0xE507,0xE508,0xE509,0xE50A,0xE50B,0xE50C,0xE50D,0xE50E,0xE50F,0xE510,0xE511,0xE512,0xE513,0xE514,0xE515,0xE516,0xE517,0xE518,0xE519,0xE51A,0xE51B,0xE51C,0xE51D,0xE51E,0xE51F,0xE520,0xE521,0xE522,0xE523,0xE524,0xE525,0x3000,0x3001,0x3002,0xB7,0x2C9,0x2C7,0xA8,0x3003,0x3005,0x2014,0xFF5E,0x2016,0x2026,0x2018,0x2019,0x201C,0x201D,0x3014,0x3015,0x3008,0x3009,0x300A,0x300B,0x300C,0x300D,0x300E,0x300F,0x3016,0x3017,0x3010,0x3011,0xB1,0xD7,0xF7,0x2236,0x2227,0x2228,0x2211,0x220F,0x222A,0x2229,0x2208,0x2237,0x221A,0x22A5,0x2225,0x2220,0x2312,0x2299,0x222B,0x222E,0x2261,0x224C,0x2248,0x223D,0x221D,0x2260,0x226E,0x226F,0x2264,0x2265,0x221E,0x2235,0x2234,0x2642,0x2640,0xB0,0x2032,0x2033,0x2103,0xFF04,0xA4,0xFFE0,0xFFE1,0x2030,0xA7,0x2116,0x2606,0x2605,0x25CB,0x25CF,0x25CE,0x25C7,0x25C6,0x25A1,0x25A0,0x25B3,0x25B2,0x203B,0x2192,0x2190,0x2191,0x2193,0x3013,0xE526,0xE527,0xE528,0xE529,0xE52A,0xE52B,0xE52C,0xE52D,0xE52E,0xE52F,0xE530,0xE531,0xE532,0xE533,0xE534,0xE535,0xE536,0xE537,0xE538,0xE539,0xE53A,0xE53B,0xE53C,0xE53D,0xE53E,0xE53F,0xE540,0xE541,0xE542,0xE543,0xE544,0xE545,0xE546,0xE547,0xE548,0xE549,0xE54A,0xE54B,0xE54C,0xE54D,0xE54E,0xE54F,0xE550,0xE551,0xE552,0xE553,0xE554,0xE555,0xE556,0xE557,0xE558,0xE559,0xE55A,0xE55B,0xE55C,0xE55D,0xE55E,0xE55F,0xE560,0xE561,0xE562,0xE563,0xE564,0xE565,0xE566,0xE567,0xE568,0xE569,0xE56A,0xE56B,0xE56C,0xE56D,0xE56E,0xE56F,0xE570,0xE571,0xE572,0xE573,0xE574,0xE575,0xE576,0xE577,0xE578,0xE579,0xE57A,0xE57B,0xE57C,0xE57D,0xE57E,0xE57F,0xE580,0xE581,0xE582,0xE583,0xE584,0xE585,0x2170,0x2171,0x2172,0x2173,0x2174,0x2175,0x2176,0x2177,0x2178,0x2179,0xE766,0xE767,0xE768,0xE769,0xE76A,0xE76B,0x2488,0x2489,0x248A,0x248B,0x248C,0x248D,0x248E,0x248F,0x2490,0x2491,0x2492,0x2493,0x2494,0x2495,0x2496,0x2497,0x2498,0x2499,0x249A,0x249B,0x2474,0x2475,0x2476,0x2477,0x2478,0x2479,0x247A,0x247B,0x247C,0x247D,0x247E,0x247F,0x2480,0x2481,0x2482,0x2483,0x2484,0x2485,0x2486,0x2487,0x2460,0x2461,0x2462,0x2463,0x2464,0x2465,0x2466,0x2467,0x2468,0x2469,0x20AC,0xE76D,0x3220,0x3221,0x3222,0x3223,0x3224,0x3225,0x3226,0x3227,0x3228,0x3229,0xE76E,0xE76F,0x2160,0x2161,0x2162,0x2163,0x2164,0x2165,0x2166,0x2167,0x2168,0x2169,0x216A,0x216B,0xE770,0xE771,0xE586,0xE587,0xE588,0xE589,0xE58A,0xE58B,0xE58C,0xE58D,0xE58E,0xE58F,0xE590,0xE591,0xE592,0xE593,0xE594,0xE595,0xE596,0xE597,0xE598,0xE599,0xE59A,0xE59B,0xE59C,0xE59D,0xE59E,0xE59F,0xE5A0,0xE5A1,0xE5A2,0xE5A3,0xE5A4,0xE5A5,0xE5A6,0xE5A7,0xE5A8,0xE5A9,0xE5AA,0xE5AB,0xE5AC,0xE5AD,0xE5AE,0xE5AF,0xE5B0,0xE5B1,0xE5B2,0xE5B3,0xE5B4,0xE5B5,0xE5B6,0xE5B7,0xE5B8,0xE5B9,0xE5BA,0xE5BB,0xE5BC,0xE5BD,0xE5BE,0xE5BF,0xE5C0,0xE5C1,0xE5C2,0xE5C3,0xE5C4,0xE5C5,0xE5C6,0xE5C7,0xE5C8,0xE5C9,0xE5CA,0xE5CB,0xE5CC,0xE5CD,0xE5CE,0xE5CF,0xE5D0,0xE5D1,0xE5D2,0xE5D3,0xE5D4,0xE5D5,0xE5D6,0xE5D7,0xE5D8,0xE5D9,0xE5DA,0xE5DB,0xE5DC,0xE5DD,0xE5DE,0xE5DF,0xE5E0,0xE5E1,0xE5E2,0xE5E3,0xE5E4,0xE5E5,0xFF01,0xFF02,0xFF03,0xFFE5,0xFF05,0xFF06,0xFF07,0xFF08,0xFF09,0xFF0A,0xFF0B,0xFF0C,0xFF0D,0xFF0E,0xFF0F,0xFF10,0xFF11,0xFF12,0xFF13,0xFF14,0xFF15,0xFF16,0xFF17,0xFF18,0xFF19,0xFF1A,0xFF1B,0xFF1C,0xFF1D,0xFF1E,0xFF1F,0xFF20,0xFF21,0xFF22,0xFF23,0xFF24,0xFF25,0xFF26,0xFF27,0xFF28,0xFF29,0xFF2A,0xFF2B,0xFF2C,0xFF2D,0xFF2E,0xFF2F,0xFF30,0xFF31,0xFF32,0xFF33,0xFF34,0xFF35,0xFF36,0xFF37,0xFF38,0xFF39,0xFF3A,0xFF3B,0xFF3C,0xFF3D,0xFF3E,0xFF3F,0xFF40,0xFF41,0xFF42,0xFF43,0xFF44,0xFF45,0xFF46,0xFF47,0xFF48,0xFF49,0xFF4A,0xFF4B,0xFF4C,0xFF4D,0xFF4E,0xFF4F,0xFF50,0xFF51,0xFF52,0xFF53,0xFF54,0xFF55,0xFF56,0xFF57,0xFF58,0xFF59,0xFF5A,0xFF5B,0xFF5C,0xFF5D,0xFFE3,0xE5E6,0xE5E7,0xE5E8,0xE5E9,0xE5EA,0xE5EB,0xE5EC,0xE5ED,0xE5EE,0xE5EF,0xE5F0,0xE5F1,0xE5F2,0xE5F3,0xE5F4,0xE5F5,0xE5F6,0xE5F7,0xE5F8,0xE5F9,0xE5FA,0xE5FB,0xE5FC,0xE5FD,0xE5FE,0xE5FF,0xE600,0xE601,0xE602,0xE603,0xE604,0xE605,0xE606,0xE607,0xE608,0xE609,0xE60A,0xE60B,0xE60C,0xE60D,0xE60E,0xE60F,0xE610,0xE611,0xE612,0xE613,0xE614,0xE615,0xE616,0xE617,0xE618,0xE619,0xE61A,0xE61B,0xE61C,0xE61D,0xE61E,0xE61F,0xE620,0xE621,0xE622,0xE623,0xE624,0xE625,0xE626,0xE627,0xE628,0xE629,0xE62A,0xE62B,0xE62C,0xE62D,0xE62E,0xE62F,0xE630,0xE631,0xE632,0xE633,0xE634,0xE635,0xE636,0xE637,0xE638,0xE639,0xE63A,0xE63B,0xE63C,0xE63D,0xE63E,0xE63F,0xE640,0xE641,0xE642,0xE643,0xE644,0xE645,0x3041,0x3042,0x3043,0x3044,0x3045,0x3046,0x3047,0x3048,0x3049,0x304A,0x304B,0x304C,0x304D,0x304E,0x304F,0x3050,0x3051,0x3052,0x3053,0x3054,0x3055,0x3056,0x3057,0x3058,0x3059,0x305A,0x305B,0x305C,0x305D,0x305E,0x305F,0x3060,0x3061,0x3062,0x3063,0x3064,0x3065,0x3066,0x3067,0x3068,0x3069,0x306A,0x306B,0x306C,0x306D,0x306E,0x306F,0x3070,0x3071,0x3072,0x3073,0x3074,0x3075,0x3076,0x3077,0x3078,0x3079,0x307A,0x307B,0x307C,0x307D,0x307E,0x307F,0x3080,0x3081,0x3082,0x3083,0x3084,0x3085,0x3086,0x3087,0x3088,0x3089,0x308A,0x308B,0x308C,0x308D,0x308E,0x308F,0x3090,0x3091,0x3092,0x3093,0xE772,0xE773,0xE774,0xE775,0xE776,0xE777,0xE778,0xE779,0xE77A,0xE77B,0xE77C,0xE646,0xE647,0xE648,0xE649,0xE64A,0xE64B,0xE64C,0xE64D,0xE64E,0xE64F,0xE650,0xE651,0xE652,0xE653,0xE654,0xE655,0xE656,0xE657,0xE658,0xE659,0xE65A,0xE65B,0xE65C,0xE65D,0xE65E,0xE65F,0xE660,0xE661,0xE662,0xE663,0xE664,0xE665,0xE666,0xE667,0xE668,0xE669,0xE66A,0xE66B,0xE66C,0xE66D,0xE66E,0xE66F,0xE670,0xE671,0xE672,0xE673,0xE674,0xE675,0xE676,0xE677,0xE678,0xE679,0xE67A,0xE67B,0xE67C,0xE67D,0xE67E,0xE67F,0xE680,0xE681,0xE682,0xE683,0xE684,0xE685,0xE686,0xE687,0xE688,0xE689,0xE68A,0xE68B,0xE68C,0xE68D,0xE68E,0xE68F,0xE690,0xE691,0xE692,0xE693,0xE694,0xE695,0xE696,0xE697,0xE698,0xE699,0xE69A,0xE69B,0xE69C,0xE69D,0xE69E,0xE69F,0xE6A0,0xE6A1,0xE6A2,0xE6A3,0xE6A4,0xE6A5,0x30A1,0x30A2,0x30A3,0x30A4,0x30A5,0x30A6,0x30A7,0x30A8,0x30A9,0x30AA,0x30AB,0x30AC,0x30AD,0x30AE,0x30AF,0x30B0,0x30B1,0x30B2,0x30B3,0x30B4,0x30B5,0x30B6,0x30B7,0x30B8,0x30B9,0x30BA,0x30BB,0x30BC,0x30BD,0x30BE,0x30BF,0x30C0,0x30C1,0x30C2,0x30C3,0x30C4,0x30C5,0x30C6,0x30C7,0x30C8,0x30C9,0x30CA,0x30CB,0x30CC,0x30CD,0x30CE,0x30CF,0x30D0,0x30D1,0x30D2,0x30D3,0x30D4,0x30D5,0x30D6,0x30D7,0x30D8,0x30D9,0x30DA,0x30DB,0x30DC,0x30DD,0x30DE,0x30DF,0x30E0,0x30E1,0x30E2,0x30E3,0x30E4,0x30E5,0x30E6,0x30E7,0x30E8,0x30E9,0x30EA,0x30EB,0x30EC,0x30ED,0x30EE,0x30EF,0x30F0,0x30F1,0x30F2,0x30F3,0x30F4,0x30F5,0x30F6,0xE77D,0xE77E,0xE77F,0xE780,0xE781,0xE782,0xE783,0xE784,0xE6A6,0xE6A7,0xE6A8,0xE6A9,0xE6AA,0xE6AB,0xE6AC,0xE6AD,0xE6AE,0xE6AF,0xE6B0,0xE6B1,0xE6B2,0xE6B3,0xE6B4,0xE6B5,0xE6B6,0xE6B7,0xE6B8,0xE6B9,0xE6BA,0xE6BB,0xE6BC,0xE6BD,0xE6BE,0xE6BF,0xE6C0,0xE6C1,0xE6C2,0xE6C3,0xE6C4,0xE6C5,0xE6C6,0xE6C7,0xE6C8,0xE6C9,0xE6CA,0xE6CB,0xE6CC,0xE6CD,0xE6CE,0xE6CF,0xE6D0,0xE6D1,0xE6D2,0xE6D3,0xE6D4,0xE6D5,0xE6D6,0xE6D7,0xE6D8,0xE6D9,0xE6DA,0xE6DB,0xE6DC,0xE6DD,0xE6DE,0xE6DF,0xE6E0,0xE6E1,0xE6E2,0xE6E3,0xE6E4,0xE6E5,0xE6E6,0xE6E7,0xE6E8,0xE6E9,0xE6EA,0xE6EB,0xE6EC,0xE6ED,0xE6EE,0xE6EF,0xE6F0,0xE6F1,0xE6F2,0xE6F3,0xE6F4,0xE6F5,0xE6F6,0xE6F7,0xE6F8,0xE6F9,0xE6FA,0xE6FB,0xE6FC,0xE6FD,0xE6FE,0xE6FF,0xE700,0xE701,0xE702,0xE703,0xE704,0xE705,0x391,0x392,0x393,0x394,0x395,0x396,0x397,0x398,0x399,0x39A,0x39B,0x39C,0x39D,0x39E,0x39F,0x3A0,0x3A1,0x3A3,0x3A4,0x3A5,0x3A6,0x3A7,0x3A8,0x3A9,0xE785,0xE786,0xE787,0xE788,0xE789,0xE78A,0xE78B,0xE78C,0x3B1,0x3B2,0x3B3,0x3B4,0x3B5,0x3B6,0x3B7,0x3B8,0x3B9,0x3BA,0x3BB,0x3BC,0x3BD,0x3BE,0x3BF,0x3C0,0x3C1,0x3C3,0x3C4,0x3C5,0x3C6,0x3C7,0x3C8,0x3C9,0xFE10,0xFE12,0xFE11,0xFE13,0xFE14,0xFE15,0xFE16,0xFE35,0xFE36,0xFE39,0xFE3A,0xFE3F,0xFE40,0xFE3D,0xFE3E,0xFE41,0xFE42,0xFE43,0xFE44,0xFE17,0xFE18,0xFE3B,0xFE3C,0xFE37,0xFE38,0xFE31,0xFE19,0xFE33,0xFE34,0xE797,0xE798,0xE799,0xE79A,0xE79B,0xE79C,0xE79D,0xE79E,0xE79F,0xE706,0xE707,0xE708,0xE709,0xE70A,0xE70B,0xE70C,0xE70D,0xE70E,0xE70F,0xE710,0xE711,0xE712,0xE713,0xE714,0xE715,0xE716,0xE717,0xE718,0xE719,0xE71A,0xE71B,0xE71C,0xE71D,0xE71E,0xE71F,0xE720,0xE721,0xE722,0xE723,0xE724,0xE725,0xE726,0xE727,0xE728,0xE729,0xE72A,0xE72B,0xE72C,0xE72D,0xE72E,0xE72F,0xE730,0xE731,0xE732,0xE733,0xE734,0xE735,0xE736,0xE737,0xE738,0xE739,0xE73A,0xE73B,0xE73C,0xE73D,0xE73E,0xE73F,0xE740,0xE741,0xE742,0xE743,0xE744,0xE745,0xE746,0xE747,0xE748,0xE749,0xE74A,0xE74B,0xE74C,0xE74D,0xE74E,0xE74F,0xE750,0xE751,0xE752,0xE753,0xE754,0xE755,0xE756,0xE757,0xE758,0xE759,0xE75A,0xE75B,0xE75C,0xE75D,0xE75E,0xE75F,0xE760,0xE761,0xE762,0xE763,0xE764,0xE765,0x410,0x411,0x412,0x413,0x414,0x415,0x401,0x416,0x417,0x418,0x419,0x41A,0x41B,0x41C,0x41D,0x41E,0x41F,0x420,0x421,0x422,0x423,0x424,0x425,0x426,0x427,0x428,0x429,0x42A,0x42B,0x42C,0x42D,0x42E,0x42F,0xE7A0,0xE7A1,0xE7A2,0xE7A3,0xE7A4,0xE7A5,0xE7A6,0xE7A7,0xE7A8,0xE7A9,0xE7AA,0xE7AB,0xE7AC,0xE7AD,0xE7AE,0x430,0x431,0x432,0x433,0x434,0x435,0x451,0x436,0x437,0x438,0x439,0x43A,0x43B,0x43C,0x43D,0x43E,0x43F,0x440,0x441,0x442,0x443,0x444,0x445,0x446,0x447,0x448,0x449,0x44A,0x44B,0x44C,0x44D,0x44E,0x44F,0xE7AF,0xE7B0,0xE7B1,0xE7B2,0xE7B3,0xE7B4,0xE7B5,0xE7B6,0xE7B7,0xE7B8,0xE7B9,0xE7BA,0xE7BB,0x2CA,0x2CB,0x2D9,0x2013,0x2015,0x2025,0x2035,0x2105,0x2109,0x2196,0x2197,0x2198,0x2199,0x2215,0x221F,0x2223,0x2252,0x2266,0x2267,0x22BF,0x2550,0x2551,0x2552,0x2553,0x2554,0x2555,0x2556,0x2557,0x2558,0x2559,0x255A,0x255B,0x255C,0x255D,0x255E,0x255F,0x2560,0x2561,0x2562,0x2563,0x2564,0x2565,0x2566,0x2567,0x2568,0x2569,0x256A,0x256B,0x256C,0x256D,0x256E,0x256F,0x2570,0x2571,0x2572,0x2573,0x2581,0x2582,0x2583,0x2584,0x2585,0x2586,0x2587,0x2588,0x2589,0x258A,0x258B,0x258C,0x258D,0x258E,0x258F,0x2593,0x2594,0x2595,0x25BC,0x25BD,0x25E2,0x25E3,0x25E4,0x25E5,0x2609,0x2295,0x3012,0x301D,0x301E,0xE7BC,0xE7BD,0xE7BE,0xE7BF,0xE7C0,0xE7C1,0xE7C2,0xE7C3,0xE7C4,0xE7C5,0xE7C6,0x101,0xE1,0x1CE,0xE0,0x113,0xE9,0x11B,0xE8,0x12B,0xED,0x1D0,0xEC,0x14D,0xF3,0x1D2,0xF2,0x16B,0xFA,0x1D4,0xF9,0x1D6,0x1D8,0x1DA,0x1DC,0xFC,0xEA,0x251,0x1E3F,0x144,0x148,0x1F9,0x261,0xE7C9,0xE7CA,0xE7CB,0xE7CC,0x3105,0x3106,0x3107,0x3108,0x3109,0x310A,0x310B,0x310C,0x310D,0x310E,0x310F,0x3110,0x3111,0x3112,0x3113,0x3114,0x3115,0x3116,0x3117,0x3118,0x3119,0x311A,0x311B,0x311C,0x311D,0x311E,0x311F,0x3120,0x3121,0x3122,0x3123,0x3124,0x3125,0x3126,0x3127,0x3128,0x3129,0xE7CD,0xE7CE,0xE7CF,0xE7D0,0xE7D1,0xE7D2,0xE7D3,0xE7D4,0xE7D5,0xE7D6,0xE7D7,0xE7D8,0xE7D9,0xE7DA,0xE7DB,0xE7DC,0xE7DD,0xE7DE,0xE7DF,0xE7E0,0xE7E1,0x3021,0x3022,0x3023,0x3024,0x3025,0x3026,0x3027,0x3028,0x3029,0x32A3,0x338E,0x338F,0x339C,0x339D,0x339E,0x33A1,0x33C4,0x33CE,0x33D1,0x33D2,0x33D5,0xFE30,0xFFE2,0xFFE4,0xE7E2,0x2121,0x3231,0xE7E3,0x2010,0xE7E4,0xE7E5,0xE7E6,0x30FC,0x309B,0x309C,0x30FD,0x30FE,0x3006,0x309D,0x309E,0xFE49,0xFE4A,0xFE4B,0xFE4C,0xFE4D,0xFE4E,0xFE4F,0xFE50,0xFE51,0xFE52,0xFE54,0xFE55,0xFE56,0xFE57,0xFE59,0xFE5A,0xFE5B,0xFE5C,0xFE5D,0xFE5E,0xFE5F,0xFE60,0xFE61,0xFE62,0xFE63,0xFE64,0xFE65,0xFE66,0xFE68,0xFE69,0xFE6A,0xFE6B,0x303E,0x2FF0,0x2FF1,0x2FF2,0x2FF3,0x2FF4,0x2FF5,0x2FF6,0x2FF7,0x2FF8,0x2FF9,0x2FFA,0x2FFB,0x3007,0xE7F4,0xE7F5,0xE7F6,0xE7F7,0xE7F8,0xE7F9,0xE7FA,0xE7FB,0xE7FC,0xE7FD,0xE7FE,0xE7FF,0xE800,0x2500,0x2501,0x2502,0x2503,0x2504,0x2505,0x2506,0x2507,0x2508,0x2509,0x250A,0x250B,0x250C,0x250D,0x250E,0x250F,0x2510,0x2511,0x2512,0x2513,0x2514,0x2515,0x2516,0x2517,0x2518,0x2519,0x251A,0x251B,0x251C,0x251D,0x251E,0x251F,0x2520,0x2521,0x2522,0x2523,0x2524,0x2525,0x2526,0x2527,0x2528,0x2529,0x252A,0x252B,0x252C,0x252D,0x252E,0x252F,0x2530,0x2531,0x2532,0x2533,0x2534,0x2535,0x2536,0x2537,0x2538,0x2539,0x253A,0x253B,0x253C,0x253D,0x253E,0x253F,0x2540,0x2541,0x2542,0x2543,0x2544,0x2545,0x2546,0x2547,0x2548,0x2549,0x254A,0x254B,0xE801,0xE802,0xE803,0xE804,0xE805,0xE806,0xE807,0xE808,0xE809,0xE80A,0xE80B,0xE80C,0xE80D,0xE80E,0xE80F,0x72DC,0x72DD,0x72DF,0x72E2,0x72E3,0x72E4,0x72E5,0x72E6,0x72E7,0x72EA,0x72EB,0x72F5,0x72F6,0x72F9,0x72FD,0x72FE,0x72FF,0x7300,0x7302,0x7304,0x7305,0x7306,0x7307,0x7308,0x7309,0x730B,0x730C,0x730D,0x730F,0x7310,0x7311,0x7312,0x7314,0x7318,0x7319,0x731A,0x731F,0x7320,0x7323,0x7324,0x7326,0x7327,0x7328,0x732D,0x732F,0x7330,0x7332,0x7333,0x7335,0x7336,0x733A,0x733B,0x733C,0x733D,0x7340,0x7341,0x7342,0x7343,0x7344,0x7345,0x7346,0x7347,0x7348,0x7349,0x734A,0x734B,0x734C,0x734E,0x734F,0x7351,0x7353,0x7354,0x7355,0x7356,0x7358,0x7359,0x735A,0x735B,0x735C,0x735D,0x735E,0x735F,0x7361,0x7362,0x7363,0x7364,0x7365,0x7366,0x7367,0x7368,0x7369,0x736A,0x736B,0x736E,0x7370,0x7371,0xE000,0xE001,0xE002,0xE003,0xE004,0xE005,0xE006,0xE007,0xE008,0xE009,0xE00A,0xE00B,0xE00C,0xE00D,0xE00E,0xE00F,0xE010,0xE011,0xE012,0xE013,0xE014,0xE015,0xE016,0xE017,0xE018,0xE019,0xE01A,0xE01B,0xE01C,0xE01D,0xE01E,0xE01F,0xE020,0xE021,0xE022,0xE023,0xE024,0xE025,0xE026,0xE027,0xE028,0xE029,0xE02A,0xE02B,0xE02C,0xE02D,0xE02E,0xE02F,0xE030,0xE031,0xE032,0xE033,0xE034,0xE035,0xE036,0xE037,0xE038,0xE039,0xE03A,0xE03B,0xE03C,0xE03D,0xE03E,0xE03F,0xE040,0xE041,0xE042,0xE043,0xE044,0xE045,0xE046,0xE047,0xE048,0xE049,0xE04A,0xE04B,0xE04C,0xE04D,0xE04E,0xE04F,0xE050,0xE051,0xE052,0xE053,0xE054,0xE055,0xE056,0xE057,0xE058,0xE059,0xE05A,0xE05B,0xE05C,0xE05D,0x7372,0x7373,0x7374,0x7375,0x7376,0x7377,0x7378,0x7379,0x737A,0x737B,0x737C,0x737D,0x737F,0x7380,0x7381,0x7382,0x7383,0x7385,0x7386,0x7388,0x738A,0x738C,0x738D,0x738F,0x7390,0x7392,0x7393,0x7394,0x7395,0x7397,0x7398,0x7399,0x739A,0x739C,0x739D,0x739E,0x73A0,0x73A1,0x73A3,0x73A4,0x73A5,0x73A6,0x73A7,0x73A8,0x73AA,0x73AC,0x73AD,0x73B1,0x73B4,0x73B5,0x73B6,0x73B8,0x73B9,0x73BC,0x73BD,0x73BE,0x73BF,0x73C1,0x73C3,0x73C4,0x73C5,0x73C6,0x73C7,0x73CB,0x73CC,0x73CE,0x73D2,0x73D3,0x73D4,0x73D5,0x73D6,0x73D7,0x73D8,0x73DA,0x73DB,0x73DC,0x73DD,0x73DF,0x73E1,0x73E2,0x73E3,0x73E4,0x73E6,0x73E8,0x73EA,0x73EB,0x73EC,0x73EE,0x73EF,0x73F0,0x73F1,0x73F3,0x73F4,0x73F5,0x73F6,0x73F7,0xE05E,0xE05F,0xE060,0xE061,0xE062,0xE063,0xE064,0xE065,0xE066,0xE067,0xE068,0xE069,0xE06A,0xE06B,0xE06C,0xE06D,0xE06E,0xE06F,0xE070,0xE071,0xE072,0xE073,0xE074,0xE075,0xE076,0xE077,0xE078,0xE079,0xE07A,0xE07B,0xE07C,0xE07D,0xE07E,0xE07F,0xE080,0xE081,0xE082,0xE083,0xE084,0xE085,0xE086,0xE087,0xE088,0xE089,0xE08A,0xE08B,0xE08C,0xE08D,0xE08E,0xE08F,0xE090,0xE091,0xE092,0xE093,0xE094,0xE095,0xE096,0xE097,0xE098,0xE099,0xE09A,0xE09B,0xE09C,0xE09D,0xE09E,0xE09F,0xE0A0,0xE0A1,0xE0A2,0xE0A3,0xE0A4,0xE0A5,0xE0A6,0xE0A7,0xE0A8,0xE0A9,0xE0AA,0xE0AB,0xE0AC,0xE0AD,0xE0AE,0xE0AF,0xE0B0,0xE0B1,0xE0B2,0xE0B3,0xE0B4,0xE0B5,0xE0B6,0xE0B7,0xE0B8,0xE0B9,0xE0BA,0xE0BB,0x73F8,0x73F9,0x73FA,0x73FB,0x73FC,0x73FD,0x73FE,0x73FF,0x7400,0x7401,0x7402,0x7404,0x7407,0x7408,0x740B,0x740C,0x740D,0x740E,0x7411,0x7412,0x7413,0x7414,0x7415,0x7416,0x7417,0x7418,0x7419,0x741C,0x741D,0x741E,0x741F,0x7420,0x7421,0x7423,0x7424,0x7427,0x7429,0x742B,0x742D,0x742F,0x7431,0x7432,0x7437,0x7438,0x7439,0x743A,0x743B,0x743D,0x743E,0x743F,0x7440,0x7442,0x7443,0x7444,0x7445,0x7446,0x7447,0x7448,0x7449,0x744A,0x744B,0x744C,0x744D,0x744E,0x744F,0x7450,0x7451,0x7452,0x7453,0x7454,0x7456,0x7458,0x745D,0x7460,0x7461,0x7462,0x7463,0x7464,0x7465,0x7466,0x7467,0x7468,0x7469,0x746A,0x746B,0x746C,0x746E,0x746F,0x7471,0x7472,0x7473,0x7474,0x7475,0x7478,0x7479,0x747A,0xE0BC,0xE0BD,0xE0BE,0xE0BF,0xE0C0,0xE0C1,0xE0C2,0xE0C3,0xE0C4,0xE0C5,0xE0C6,0xE0C7,0xE0C8,0xE0C9,0xE0CA,0xE0CB,0xE0CC,0xE0CD,0xE0CE,0xE0CF,0xE0D0,0xE0D1,0xE0D2,0xE0D3,0xE0D4,0xE0D5,0xE0D6,0xE0D7,0xE0D8,0xE0D9,0xE0DA,0xE0DB,0xE0DC,0xE0DD,0xE0DE,0xE0DF,0xE0E0,0xE0E1,0xE0E2,0xE0E3,0xE0E4,0xE0E5,0xE0E6,0xE0E7,0xE0E8,0xE0E9,0xE0EA,0xE0EB,0xE0EC,0xE0ED,0xE0EE,0xE0EF,0xE0F0,0xE0F1,0xE0F2,0xE0F3,0xE0F4,0xE0F5,0xE0F6,0xE0F7,0xE0F8,0xE0F9,0xE0FA,0xE0FB,0xE0FC,0xE0FD,0xE0FE,0xE0FF,0xE100,0xE101,0xE102,0xE103,0xE104,0xE105,0xE106,0xE107,0xE108,0xE109,0xE10A,0xE10B,0xE10C,0xE10D,0xE10E,0xE10F,0xE110,0xE111,0xE112,0xE113,0xE114,0xE115,0xE116,0xE117,0xE118,0xE119,0x747B,0x747C,0x747D,0x747F,0x7482,0x7484,0x7485,0x7486,0x7488,0x7489,0x748A,0x748C,0x748D,0x748F,0x7491,0x7492,0x7493,0x7494,0x7495,0x7496,0x7497,0x7498,0x7499,0x749A,0x749B,0x749D,0x749F,0x74A0,0x74A1,0x74A2,0x74A3,0x74A4,0x74A5,0x74A6,0x74AA,0x74AB,0x74AC,0x74AD,0x74AE,0x74AF,0x74B0,0x74B1,0x74B2,0x74B3,0x74B4,0x74B5,0x74B6,0x74B7,0x74B8,0x74B9,0x74BB,0x74BC,0x74BD,0x74BE,0x74BF,0x74C0,0x74C1,0x74C2,0x74C3,0x74C4,0x74C5,0x74C6,0x74C7,0x74C8,0x74C9,0x74CA,0x74CB,0x74CC,0x74CD,0x74CE,0x74CF,0x74D0,0x74D1,0x74D3,0x74D4,0x74D5,0x74D6,0x74D7,0x74D8,0x74D9,0x74DA,0x74DB,0x74DD,0x74DF,0x74E1,0x74E5,0x74E7,0x74E8,0x74E9,0x74EA,0x74EB,0x74EC,0x74ED,0x74F0,0x74F1,0x74F2,0xE11A,0xE11B,0xE11C,0xE11D,0xE11E,0xE11F,0xE120,0xE121,0xE122,0xE123,0xE124,0xE125,0xE126,0xE127,0xE128,0xE129,0xE12A,0xE12B,0xE12C,0xE12D,0xE12E,0xE12F,0xE130,0xE131,0xE132,0xE133,0xE134,0xE135,0xE136,0xE137,0xE138,0xE139,0xE13A,0xE13B,0xE13C,0xE13D,0xE13E,0xE13F,0xE140,0xE141,0xE142,0xE143,0xE144,0xE145,0xE146,0xE147,0xE148,0xE149,0xE14A,0xE14B,0xE14C,0xE14D,0xE14E,0xE14F,0xE150,0xE151,0xE152,0xE153,0xE154,0xE155,0xE156,0xE157,0xE158,0xE159,0xE15A,0xE15B,0xE15C,0xE15D,0xE15E,0xE15F,0xE160,0xE161,0xE162,0xE163,0xE164,0xE165,0xE166,0xE167,0xE168,0xE169,0xE16A,0xE16B,0xE16C,0xE16D,0xE16E,0xE16F,0xE170,0xE171,0xE172,0xE173,0xE174,0xE175,0xE176,0xE177,0x74F3,0x74F5,0x74F8,0x74F9,0x74FA,0x74FB,0x74FC,0x74FD,0x74FE,0x7500,0x7501,0x7502,0x7503,0x7505,0x7506,0x7507,0x7508,0x7509,0x750A,0x750B,0x750C,0x750E,0x7510,0x7512,0x7514,0x7515,0x7516,0x7517,0x751B,0x751D,0x751E,0x7520,0x7521,0x7522,0x7523,0x7524,0x7526,0x7527,0x752A,0x752E,0x7534,0x7536,0x7539,0x753C,0x753D,0x753F,0x7541,0x7542,0x7543,0x7544,0x7546,0x7547,0x7549,0x754A,0x754D,0x7550,0x7551,0x7552,0x7553,0x7555,0x7556,0x7557,0x7558,0x755D,0x755E,0x755F,0x7560,0x7561,0x7562,0x7563,0x7564,0x7567,0x7568,0x7569,0x756B,0x756C,0x756D,0x756E,0x756F,0x7570,0x7571,0x7573,0x7575,0x7576,0x7577,0x757A,0x757B,0x757C,0x757D,0x757E,0x7580,0x7581,0x7582,0x7584,0x7585,0x7587,0xE178,0xE179,0xE17A,0xE17B,0xE17C,0xE17D,0xE17E,0xE17F,0xE180,0xE181,0xE182,0xE183,0xE184,0xE185,0xE186,0xE187,0xE188,0xE189,0xE18A,0xE18B,0xE18C,0xE18D,0xE18E,0xE18F,0xE190,0xE191,0xE192,0xE193,0xE194,0xE195,0xE196,0xE197,0xE198,0xE199,0xE19A,0xE19B,0xE19C,0xE19D,0xE19E,0xE19F,0xE1A0,0xE1A1,0xE1A2,0xE1A3,0xE1A4,0xE1A5,0xE1A6,0xE1A7,0xE1A8,0xE1A9,0xE1AA,0xE1AB,0xE1AC,0xE1AD,0xE1AE,0xE1AF,0xE1B0,0xE1B1,0xE1B2,0xE1B3,0xE1B4,0xE1B5,0xE1B6,0xE1B7,0xE1B8,0xE1B9,0xE1BA,0xE1BB,0xE1BC,0xE1BD,0xE1BE,0xE1BF,0xE1C0,0xE1C1,0xE1C2,0xE1C3,0xE1C4,0xE1C5,0xE1C6,0xE1C7,0xE1C8,0xE1C9,0xE1CA,0xE1CB,0xE1CC,0xE1CD,0xE1CE,0xE1CF,0xE1D0,0xE1D1,0xE1D2,0xE1D3,0xE1D4,0xE1D5,0x7588,0x7589,0x758A,0x758C,0x758D,0x758E,0x7590,0x7593,0x7595,0x7598,0x759B,0x759C,0x759E,0x75A2,0x75A6,0x75A7,0x75A8,0x75A9,0x75AA,0x75AD,0x75B6,0x75B7,0x75BA,0x75BB,0x75BF,0x75C0,0x75C1,0x75C6,0x75CB,0x75CC,0x75CE,0x75CF,0x75D0,0x75D1,0x75D3,0x75D7,0x75D9,0x75DA,0x75DC,0x75DD,0x75DF,0x75E0,0x75E1,0x75E5,0x75E9,0x75EC,0x75ED,0x75EE,0x75EF,0x75F2,0x75F3,0x75F5,0x75F6,0x75F7,0x75F8,0x75FA,0x75FB,0x75FD,0x75FE,0x7602,0x7604,0x7606,0x7607,0x7608,0x7609,0x760B,0x760D,0x760E,0x760F,0x7611,0x7612,0x7613,0x7614,0x7616,0x761A,0x761C,0x761D,0x761E,0x7621,0x7623,0x7627,0x7628,0x762C,0x762E,0x762F,0x7631,0x7632,0x7636,0x7637,0x7639,0x763A,0x763B,0x763D,0x7641,0x7642,0x7644,0xE1D6,0xE1D7,0xE1D8,0xE1D9,0xE1DA,0xE1DB,0xE1DC,0xE1DD,0xE1DE,0xE1DF,0xE1E0,0xE1E1,0xE1E2,0xE1E3,0xE1E4,0xE1E5,0xE1E6,0xE1E7,0xE1E8,0xE1E9,0xE1EA,0xE1EB,0xE1EC,0xE1ED,0xE1EE,0xE1EF,0xE1F0,0xE1F1,0xE1F2,0xE1F3,0xE1F4,0xE1F5,0xE1F6,0xE1F7,0xE1F8,0xE1F9,0xE1FA,0xE1FB,0xE1FC,0xE1FD,0xE1FE,0xE1FF,0xE200,0xE201,0xE202,0xE203,0xE204,0xE205,0xE206,0xE207,0xE208,0xE209,0xE20A,0xE20B,0xE20C,0xE20D,0xE20E,0xE20F,0xE210,0xE211,0xE212,0xE213,0xE214,0xE215,0xE216,0xE217,0xE218,0xE219,0xE21A,0xE21B,0xE21C,0xE21D,0xE21E,0xE21F,0xE220,0xE221,0xE222,0xE223,0xE224,0xE225,0xE226,0xE227,0xE228,0xE229,0xE22A,0xE22B,0xE22C,0xE22D,0xE22E,0xE22F,0xE230,0xE231,0xE232,0xE233,0x7645,0x7646,0x7647,0x7648,0x7649,0x764A,0x764B,0x764E,0x764F,0x7650,0x7651,0x7652,0x7653,0x7655,0x7657,0x7658,0x7659,0x765A,0x765B,0x765D,0x765F,0x7660,0x7661,0x7662,0x7664,0x7665,0x7666,0x7667,0x7668,0x7669,0x766A,0x766C,0x766D,0x766E,0x7670,0x7671,0x7672,0x7673,0x7674,0x7675,0x7676,0x7677,0x7679,0x767A,0x767C,0x767F,0x7680,0x7681,0x7683,0x7685,0x7689,0x768A,0x768C,0x768D,0x768F,0x7690,0x7692,0x7694,0x7695,0x7697,0x7698,0x769A,0x769B,0x769C,0x769D,0x769E,0x769F,0x76A0,0x76A1,0x76A2,0x76A3,0x76A5,0x76A6,0x76A7,0x76A8,0x76A9,0x76AA,0x76AB,0x76AC,0x76AD,0x76AF,0x76B0,0x76B3,0x76B5,0x76B6,0x76B7,0x76B8,0x76B9,0x76BA,0x76BB,0x76BC,0x76BD,0x76BE,0x76C0,0x76C1,0x76C3,0x554A,0x963F,0x57C3,0x6328,0x54CE,0x5509,0x54C0,0x7691,0x764C,0x853C,0x77EE,0x827E,0x788D,0x7231,0x9698,0x978D,0x6C28,0x5B89,0x4FFA,0x6309,0x6697,0x5CB8,0x80FA,0x6848,0x80AE,0x6602,0x76CE,0x51F9,0x6556,0x71AC,0x7FF1,0x8884,0x50B2,0x5965,0x61CA,0x6FB3,0x82AD,0x634C,0x6252,0x53ED,0x5427,0x7B06,0x516B,0x75A4,0x5DF4,0x62D4,0x8DCB,0x9776,0x628A,0x8019,0x575D,0x9738,0x7F62,0x7238,0x767D,0x67CF,0x767E,0x6446,0x4F70,0x8D25,0x62DC,0x7A17,0x6591,0x73ED,0x642C,0x6273,0x822C,0x9881,0x677F,0x7248,0x626E,0x62CC,0x4F34,0x74E3,0x534A,0x529E,0x7ECA,0x90A6,0x5E2E,0x6886,0x699C,0x8180,0x7ED1,0x68D2,0x78C5,0x868C,0x9551,0x508D,0x8C24,0x82DE,0x80DE,0x5305,0x8912,0x5265,0x76C4,0x76C7,0x76C9,0x76CB,0x76CC,0x76D3,0x76D5,0x76D9,0x76DA,0x76DC,0x76DD,0x76DE,0x76E0,0x76E1,0x76E2,0x76E3,0x76E4,0x76E6,0x76E7,0x76E8,0x76E9,0x76EA,0x76EB,0x76EC,0x76ED,0x76F0,0x76F3,0x76F5,0x76F6,0x76F7,0x76FA,0x76FB,0x76FD,0x76FF,0x7700,0x7702,0x7703,0x7705,0x7706,0x770A,0x770C,0x770E,0x770F,0x7710,0x7711,0x7712,0x7713,0x7714,0x7715,0x7716,0x7717,0x7718,0x771B,0x771C,0x771D,0x771E,0x7721,0x7723,0x7724,0x7725,0x7727,0x772A,0x772B,0x772C,0x772E,0x7730,0x7731,0x7732,0x7733,0x7734,0x7739,0x773B,0x773D,0x773E,0x773F,0x7742,0x7744,0x7745,0x7746,0x7748,0x7749,0x774A,0x774B,0x774C,0x774D,0x774E,0x774F,0x7752,0x7753,0x7754,0x7755,0x7756,0x7757,0x7758,0x7759,0x775C,0x8584,0x96F9,0x4FDD,0x5821,0x9971,0x5B9D,0x62B1,0x62A5,0x66B4,0x8C79,0x9C8D,0x7206,0x676F,0x7891,0x60B2,0x5351,0x5317,0x8F88,0x80CC,0x8D1D,0x94A1,0x500D,0x72C8,0x5907,0x60EB,0x7119,0x88AB,0x5954,0x82EF,0x672C,0x7B28,0x5D29,0x7EF7,0x752D,0x6CF5,0x8E66,0x8FF8,0x903C,0x9F3B,0x6BD4,0x9119,0x7B14,0x5F7C,0x78A7,0x84D6,0x853D,0x6BD5,0x6BD9,0x6BD6,0x5E01,0x5E87,0x75F9,0x95ED,0x655D,0x5F0A,0x5FC5,0x8F9F,0x58C1,0x81C2,0x907F,0x965B,0x97AD,0x8FB9,0x7F16,0x8D2C,0x6241,0x4FBF,0x53D8,0x535E,0x8FA8,0x8FA9,0x8FAB,0x904D,0x6807,0x5F6A,0x8198,0x8868,0x9CD6,0x618B,0x522B,0x762A,0x5F6C,0x658C,0x6FD2,0x6EE8,0x5BBE,0x6448,0x5175,0x51B0,0x67C4,0x4E19,0x79C9,0x997C,0x70B3,0x775D,0x775E,0x775F,0x7760,0x7764,0x7767,0x7769,0x776A,0x776D,0x776E,0x776F,0x7770,0x7771,0x7772,0x7773,0x7774,0x7775,0x7776,0x7777,0x7778,0x777A,0x777B,0x777C,0x7781,0x7782,0x7783,0x7786,0x7787,0x7788,0x7789,0x778A,0x778B,0x778F,0x7790,0x7793,0x7794,0x7795,0x7796,0x7797,0x7798,0x7799,0x779A,0x779B,0x779C,0x779D,0x779E,0x77A1,0x77A3,0x77A4,0x77A6,0x77A8,0x77AB,0x77AD,0x77AE,0x77AF,0x77B1,0x77B2,0x77B4,0x77B6,0x77B7,0x77B8,0x77B9,0x77BA,0x77BC,0x77BE,0x77C0,0x77C1,0x77C2,0x77C3,0x77C4,0x77C5,0x77C6,0x77C7,0x77C8,0x77C9,0x77CA,0x77CB,0x77CC,0x77CE,0x77CF,0x77D0,0x77D1,0x77D2,0x77D3,0x77D4,0x77D5,0x77D6,0x77D8,0x77D9,0x77DA,0x77DD,0x77DE,0x77DF,0x77E0,0x77E1,0x77E4,0x75C5,0x5E76,0x73BB,0x83E0,0x64AD,0x62E8,0x94B5,0x6CE2,0x535A,0x52C3,0x640F,0x94C2,0x7B94,0x4F2F,0x5E1B,0x8236,0x8116,0x818A,0x6E24,0x6CCA,0x9A73,0x6355,0x535C,0x54FA,0x8865,0x57E0,0x4E0D,0x5E03,0x6B65,0x7C3F,0x90E8,0x6016,0x64E6,0x731C,0x88C1,0x6750,0x624D,0x8D22,0x776C,0x8E29,0x91C7,0x5F69,0x83DC,0x8521,0x9910,0x53C2,0x8695,0x6B8B,0x60ED,0x60E8,0x707F,0x82CD,0x8231,0x4ED3,0x6CA7,0x85CF,0x64CD,0x7CD9,0x69FD,0x66F9,0x8349,0x5395,0x7B56,0x4FA7,0x518C,0x6D4B,0x5C42,0x8E6D,0x63D2,0x53C9,0x832C,0x8336,0x67E5,0x78B4,0x643D,0x5BDF,0x5C94,0x5DEE,0x8BE7,0x62C6,0x67F4,0x8C7A,0x6400,0x63BA,0x8749,0x998B,0x8C17,0x7F20,0x94F2,0x4EA7,0x9610,0x98A4,0x660C,0x7316,0x77E6,0x77E8,0x77EA,0x77EF,0x77F0,0x77F1,0x77F2,0x77F4,0x77F5,0x77F7,0x77F9,0x77FA,0x77FB,0x77FC,0x7803,0x7804,0x7805,0x7806,0x7807,0x7808,0x780A,0x780B,0x780E,0x780F,0x7810,0x7813,0x7815,0x7819,0x781B,0x781E,0x7820,0x7821,0x7822,0x7824,0x7828,0x782A,0x782B,0x782E,0x782F,0x7831,0x7832,0x7833,0x7835,0x7836,0x783D,0x783F,0x7841,0x7842,0x7843,0x7844,0x7846,0x7848,0x7849,0x784A,0x784B,0x784D,0x784F,0x7851,0x7853,0x7854,0x7858,0x7859,0x785A,0x785B,0x785C,0x785E,0x785F,0x7860,0x7861,0x7862,0x7863,0x7864,0x7865,0x7866,0x7867,0x7868,0x7869,0x786F,0x7870,0x7871,0x7872,0x7873,0x7874,0x7875,0x7876,0x7878,0x7879,0x787A,0x787B,0x787D,0x787E,0x787F,0x7880,0x7881,0x7882,0x7883,0x573A,0x5C1D,0x5E38,0x957F,0x507F,0x80A0,0x5382,0x655E,0x7545,0x5531,0x5021,0x8D85,0x6284,0x949E,0x671D,0x5632,0x6F6E,0x5DE2,0x5435,0x7092,0x8F66,0x626F,0x64A4,0x63A3,0x5F7B,0x6F88,0x90F4,0x81E3,0x8FB0,0x5C18,0x6668,0x5FF1,0x6C89,0x9648,0x8D81,0x886C,0x6491,0x79F0,0x57CE,0x6A59,0x6210,0x5448,0x4E58,0x7A0B,0x60E9,0x6F84,0x8BDA,0x627F,0x901E,0x9A8B,0x79E4,0x5403,0x75F4,0x6301,0x5319,0x6C60,0x8FDF,0x5F1B,0x9A70,0x803B,0x9F7F,0x4F88,0x5C3A,0x8D64,0x7FC5,0x65A5,0x70BD,0x5145,0x51B2,0x866B,0x5D07,0x5BA0,0x62BD,0x916C,0x7574,0x8E0C,0x7A20,0x6101,0x7B79,0x4EC7,0x7EF8,0x7785,0x4E11,0x81ED,0x521D,0x51FA,0x6A71,0x53A8,0x8E87,0x9504,0x96CF,0x6EC1,0x9664,0x695A,0x7884,0x7885,0x7886,0x7888,0x788A,0x788B,0x788F,0x7890,0x7892,0x7894,0x7895,0x7896,0x7899,0x789D,0x789E,0x78A0,0x78A2,0x78A4,0x78A6,0x78A8,0x78A9,0x78AA,0x78AB,0x78AC,0x78AD,0x78AE,0x78AF,0x78B5,0x78B6,0x78B7,0x78B8,0x78BA,0x78BB,0x78BC,0x78BD,0x78BF,0x78C0,0x78C2,0x78C3,0x78C4,0x78C6,0x78C7,0x78C8,0x78CC,0x78CD,0x78CE,0x78CF,0x78D1,0x78D2,0x78D3,0x78D6,0x78D7,0x78D8,0x78DA,0x78DB,0x78DC,0x78DD,0x78DE,0x78DF,0x78E0,0x78E1,0x78E2,0x78E3,0x78E4,0x78E5,0x78E6,0x78E7,0x78E9,0x78EA,0x78EB,0x78ED,0x78EE,0x78EF,0x78F0,0x78F1,0x78F3,0x78F5,0x78F6,0x78F8,0x78F9,0x78FB,0x78FC,0x78FD,0x78FE,0x78FF,0x7900,0x7902,0x7903,0x7904,0x7906,0x7907,0x7908,0x7909,0x790A,0x790B,0x790C,0x7840,0x50A8,0x77D7,0x6410,0x89E6,0x5904,0x63E3,0x5DDD,0x7A7F,0x693D,0x4F20,0x8239,0x5598,0x4E32,0x75AE,0x7A97,0x5E62,0x5E8A,0x95EF,0x521B,0x5439,0x708A,0x6376,0x9524,0x5782,0x6625,0x693F,0x9187,0x5507,0x6DF3,0x7EAF,0x8822,0x6233,0x7EF0,0x75B5,0x8328,0x78C1,0x96CC,0x8F9E,0x6148,0x74F7,0x8BCD,0x6B64,0x523A,0x8D50,0x6B21,0x806A,0x8471,0x56F1,0x5306,0x4ECE,0x4E1B,0x51D1,0x7C97,0x918B,0x7C07,0x4FC3,0x8E7F,0x7BE1,0x7A9C,0x6467,0x5D14,0x50AC,0x8106,0x7601,0x7CB9,0x6DEC,0x7FE0,0x6751,0x5B58,0x5BF8,0x78CB,0x64AE,0x6413,0x63AA,0x632B,0x9519,0x642D,0x8FBE,0x7B54,0x7629,0x6253,0x5927,0x5446,0x6B79,0x50A3,0x6234,0x5E26,0x6B86,0x4EE3,0x8D37,0x888B,0x5F85,0x902E,0x790D,0x790E,0x790F,0x7910,0x7911,0x7912,0x7914,0x7915,0x7916,0x7917,0x7918,0x7919,0x791A,0x791B,0x791C,0x791D,0x791F,0x7920,0x7921,0x7922,0x7923,0x7925,0x7926,0x7927,0x7928,0x7929,0x792A,0x792B,0x792C,0x792D,0x792E,0x792F,0x7930,0x7931,0x7932,0x7933,0x7935,0x7936,0x7937,0x7938,0x7939,0x793D,0x793F,0x7942,0x7943,0x7944,0x7945,0x7947,0x794A,0x794B,0x794C,0x794D,0x794E,0x794F,0x7950,0x7951,0x7952,0x7954,0x7955,0x7958,0x7959,0x7961,0x7963,0x7964,0x7966,0x7969,0x796A,0x796B,0x796C,0x796E,0x7970,0x7971,0x7972,0x7973,0x7974,0x7975,0x7976,0x7979,0x797B,0x797C,0x797D,0x797E,0x797F,0x7982,0x7983,0x7986,0x7987,0x7988,0x7989,0x798B,0x798C,0x798D,0x798E,0x7990,0x7991,0x7992,0x6020,0x803D,0x62C5,0x4E39,0x5355,0x90F8,0x63B8,0x80C6,0x65E6,0x6C2E,0x4F46,0x60EE,0x6DE1,0x8BDE,0x5F39,0x86CB,0x5F53,0x6321,0x515A,0x8361,0x6863,0x5200,0x6363,0x8E48,0x5012,0x5C9B,0x7977,0x5BFC,0x5230,0x7A3B,0x60BC,0x9053,0x76D7,0x5FB7,0x5F97,0x7684,0x8E6C,0x706F,0x767B,0x7B49,0x77AA,0x51F3,0x9093,0x5824,0x4F4E,0x6EF4,0x8FEA,0x654C,0x7B1B,0x72C4,0x6DA4,0x7FDF,0x5AE1,0x62B5,0x5E95,0x5730,0x8482,0x7B2C,0x5E1D,0x5F1F,0x9012,0x7F14,0x98A0,0x6382,0x6EC7,0x7898,0x70B9,0x5178,0x975B,0x57AB,0x7535,0x4F43,0x7538,0x5E97,0x60E6,0x5960,0x6DC0,0x6BBF,0x7889,0x53FC,0x96D5,0x51CB,0x5201,0x6389,0x540A,0x9493,0x8C03,0x8DCC,0x7239,0x789F,0x8776,0x8FED,0x8C0D,0x53E0,0x7993,0x7994,0x7995,0x7996,0x7997,0x7998,0x7999,0x799B,0x799C,0x799D,0x799E,0x799F,0x79A0,0x79A1,0x79A2,0x79A3,0x79A4,0x79A5,0x79A6,0x79A8,0x79A9,0x79AA,0x79AB,0x79AC,0x79AD,0x79AE,0x79AF,0x79B0,0x79B1,0x79B2,0x79B4,0x79B5,0x79B6,0x79B7,0x79B8,0x79BC,0x79BF,0x79C2,0x79C4,0x79C5,0x79C7,0x79C8,0x79CA,0x79CC,0x79CE,0x79CF,0x79D0,0x79D3,0x79D4,0x79D6,0x79D7,0x79D9,0x79DA,0x79DB,0x79DC,0x79DD,0x79DE,0x79E0,0x79E1,0x79E2,0x79E5,0x79E8,0x79EA,0x79EC,0x79EE,0x79F1,0x79F2,0x79F3,0x79F4,0x79F5,0x79F6,0x79F7,0x79F9,0x79FA,0x79FC,0x79FE,0x79FF,0x7A01,0x7A04,0x7A05,0x7A07,0x7A08,0x7A09,0x7A0A,0x7A0C,0x7A0F,0x7A10,0x7A11,0x7A12,0x7A13,0x7A15,0x7A16,0x7A18,0x7A19,0x7A1B,0x7A1C,0x4E01,0x76EF,0x53EE,0x9489,0x9876,0x9F0E,0x952D,0x5B9A,0x8BA2,0x4E22,0x4E1C,0x51AC,0x8463,0x61C2,0x52A8,0x680B,0x4F97,0x606B,0x51BB,0x6D1E,0x515C,0x6296,0x6597,0x9661,0x8C46,0x9017,0x75D8,0x90FD,0x7763,0x6BD2,0x728A,0x72EC,0x8BFB,0x5835,0x7779,0x8D4C,0x675C,0x9540,0x809A,0x5EA6,0x6E21,0x5992,0x7AEF,0x77ED,0x953B,0x6BB5,0x65AD,0x7F0E,0x5806,0x5151,0x961F,0x5BF9,0x58A9,0x5428,0x8E72,0x6566,0x987F,0x56E4,0x949D,0x76FE,0x9041,0x6387,0x54C6,0x591A,0x593A,0x579B,0x8EB2,0x6735,0x8DFA,0x8235,0x5241,0x60F0,0x5815,0x86FE,0x5CE8,0x9E45,0x4FC4,0x989D,0x8BB9,0x5A25,0x6076,0x5384,0x627C,0x904F,0x9102,0x997F,0x6069,0x800C,0x513F,0x8033,0x5C14,0x9975,0x6D31,0x4E8C,0x7A1D,0x7A1F,0x7A21,0x7A22,0x7A24,0x7A25,0x7A26,0x7A27,0x7A28,0x7A29,0x7A2A,0x7A2B,0x7A2C,0x7A2D,0x7A2E,0x7A2F,0x7A30,0x7A31,0x7A32,0x7A34,0x7A35,0x7A36,0x7A38,0x7A3A,0x7A3E,0x7A40,0x7A41,0x7A42,0x7A43,0x7A44,0x7A45,0x7A47,0x7A48,0x7A49,0x7A4A,0x7A4B,0x7A4C,0x7A4D,0x7A4E,0x7A4F,0x7A50,0x7A52,0x7A53,0x7A54,0x7A55,0x7A56,0x7A58,0x7A59,0x7A5A,0x7A5B,0x7A5C,0x7A5D,0x7A5E,0x7A5F,0x7A60,0x7A61,0x7A62,0x7A63,0x7A64,0x7A65,0x7A66,0x7A67,0x7A68,0x7A69,0x7A6A,0x7A6B,0x7A6C,0x7A6D,0x7A6E,0x7A6F,0x7A71,0x7A72,0x7A73,0x7A75,0x7A7B,0x7A7C,0x7A7D,0x7A7E,0x7A82,0x7A85,0x7A87,0x7A89,0x7A8A,0x7A8B,0x7A8C,0x7A8E,0x7A8F,0x7A90,0x7A93,0x7A94,0x7A99,0x7A9A,0x7A9B,0x7A9E,0x7AA1,0x7AA2,0x8D30,0x53D1,0x7F5A,0x7B4F,0x4F10,0x4E4F,0x9600,0x6CD5,0x73D0,0x85E9,0x5E06,0x756A,0x7FFB,0x6A0A,0x77FE,0x9492,0x7E41,0x51E1,0x70E6,0x53CD,0x8FD4,0x8303,0x8D29,0x72AF,0x996D,0x6CDB,0x574A,0x82B3,0x65B9,0x80AA,0x623F,0x9632,0x59A8,0x4EFF,0x8BBF,0x7EBA,0x653E,0x83F2,0x975E,0x5561,0x98DE,0x80A5,0x532A,0x8BFD,0x5420,0x80BA,0x5E9F,0x6CB8,0x8D39,0x82AC,0x915A,0x5429,0x6C1B,0x5206,0x7EB7,0x575F,0x711A,0x6C7E,0x7C89,0x594B,0x4EFD,0x5FFF,0x6124,0x7CAA,0x4E30,0x5C01,0x67AB,0x8702,0x5CF0,0x950B,0x98CE,0x75AF,0x70FD,0x9022,0x51AF,0x7F1D,0x8BBD,0x5949,0x51E4,0x4F5B,0x5426,0x592B,0x6577,0x80A4,0x5B75,0x6276,0x62C2,0x8F90,0x5E45,0x6C1F,0x7B26,0x4F0F,0x4FD8,0x670D,0x7AA3,0x7AA4,0x7AA7,0x7AA9,0x7AAA,0x7AAB,0x7AAE,0x7AAF,0x7AB0,0x7AB1,0x7AB2,0x7AB4,0x7AB5,0x7AB6,0x7AB7,0x7AB8,0x7AB9,0x7ABA,0x7ABB,0x7ABC,0x7ABD,0x7ABE,0x7AC0,0x7AC1,0x7AC2,0x7AC3,0x7AC4,0x7AC5,0x7AC6,0x7AC7,0x7AC8,0x7AC9,0x7ACA,0x7ACC,0x7ACD,0x7ACE,0x7ACF,0x7AD0,0x7AD1,0x7AD2,0x7AD3,0x7AD4,0x7AD5,0x7AD7,0x7AD8,0x7ADA,0x7ADB,0x7ADC,0x7ADD,0x7AE1,0x7AE2,0x7AE4,0x7AE7,0x7AE8,0x7AE9,0x7AEA,0x7AEB,0x7AEC,0x7AEE,0x7AF0,0x7AF1,0x7AF2,0x7AF3,0x7AF4,0x7AF5,0x7AF6,0x7AF7,0x7AF8,0x7AFB,0x7AFC,0x7AFE,0x7B00,0x7B01,0x7B02,0x7B05,0x7B07,0x7B09,0x7B0C,0x7B0D,0x7B0E,0x7B10,0x7B12,0x7B13,0x7B16,0x7B17,0x7B18,0x7B1A,0x7B1C,0x7B1D,0x7B1F,0x7B21,0x7B22,0x7B23,0x7B27,0x7B29,0x7B2D,0x6D6E,0x6DAA,0x798F,0x88B1,0x5F17,0x752B,0x629A,0x8F85,0x4FEF,0x91DC,0x65A7,0x812F,0x8151,0x5E9C,0x8150,0x8D74,0x526F,0x8986,0x8D4B,0x590D,0x5085,0x4ED8,0x961C,0x7236,0x8179,0x8D1F,0x5BCC,0x8BA3,0x9644,0x5987,0x7F1A,0x5490,0x5676,0x560E,0x8BE5,0x6539,0x6982,0x9499,0x76D6,0x6E89,0x5E72,0x7518,0x6746,0x67D1,0x7AFF,0x809D,0x8D76,0x611F,0x79C6,0x6562,0x8D63,0x5188,0x521A,0x94A2,0x7F38,0x809B,0x7EB2,0x5C97,0x6E2F,0x6760,0x7BD9,0x768B,0x9AD8,0x818F,0x7F94,0x7CD5,0x641E,0x9550,0x7A3F,0x544A,0x54E5,0x6B4C,0x6401,0x6208,0x9E3D,0x80F3,0x7599,0x5272,0x9769,0x845B,0x683C,0x86E4,0x9601,0x9694,0x94EC,0x4E2A,0x5404,0x7ED9,0x6839,0x8DDF,0x8015,0x66F4,0x5E9A,0x7FB9,0x7B2F,0x7B30,0x7B32,0x7B34,0x7B35,0x7B36,0x7B37,0x7B39,0x7B3B,0x7B3D,0x7B3F,0x7B40,0x7B41,0x7B42,0x7B43,0x7B44,0x7B46,0x7B48,0x7B4A,0x7B4D,0x7B4E,0x7B53,0x7B55,0x7B57,0x7B59,0x7B5C,0x7B5E,0x7B5F,0x7B61,0x7B63,0x7B64,0x7B65,0x7B66,0x7B67,0x7B68,0x7B69,0x7B6A,0x7B6B,0x7B6C,0x7B6D,0x7B6F,0x7B70,0x7B73,0x7B74,0x7B76,0x7B78,0x7B7A,0x7B7C,0x7B7D,0x7B7F,0x7B81,0x7B82,0x7B83,0x7B84,0x7B86,0x7B87,0x7B88,0x7B89,0x7B8A,0x7B8B,0x7B8C,0x7B8E,0x7B8F,0x7B91,0x7B92,0x7B93,0x7B96,0x7B98,0x7B99,0x7B9A,0x7B9B,0x7B9E,0x7B9F,0x7BA0,0x7BA3,0x7BA4,0x7BA5,0x7BAE,0x7BAF,0x7BB0,0x7BB2,0x7BB3,0x7BB5,0x7BB6,0x7BB7,0x7BB9,0x7BBA,0x7BBB,0x7BBC,0x7BBD,0x7BBE,0x7BBF,0x7BC0,0x7BC2,0x7BC3,0x7BC4,0x57C2,0x803F,0x6897,0x5DE5,0x653B,0x529F,0x606D,0x9F9A,0x4F9B,0x8EAC,0x516C,0x5BAB,0x5F13,0x5DE9,0x6C5E,0x62F1,0x8D21,0x5171,0x94A9,0x52FE,0x6C9F,0x82DF,0x72D7,0x57A2,0x6784,0x8D2D,0x591F,0x8F9C,0x83C7,0x5495,0x7B8D,0x4F30,0x6CBD,0x5B64,0x59D1,0x9F13,0x53E4,0x86CA,0x9AA8,0x8C37,0x80A1,0x6545,0x987E,0x56FA,0x96C7,0x522E,0x74DC,0x5250,0x5BE1,0x6302,0x8902,0x4E56,0x62D0,0x602A,0x68FA,0x5173,0x5B98,0x51A0,0x89C2,0x7BA1,0x9986,0x7F50,0x60EF,0x704C,0x8D2F,0x5149,0x5E7F,0x901B,0x7470,0x89C4,0x572D,0x7845,0x5F52,0x9F9F,0x95FA,0x8F68,0x9B3C,0x8BE1,0x7678,0x6842,0x67DC,0x8DEA,0x8D35,0x523D,0x8F8A,0x6EDA,0x68CD,0x9505,0x90ED,0x56FD,0x679C,0x88F9,0x8FC7,0x54C8,0x7BC5,0x7BC8,0x7BC9,0x7BCA,0x7BCB,0x7BCD,0x7BCE,0x7BCF,0x7BD0,0x7BD2,0x7BD4,0x7BD5,0x7BD6,0x7BD7,0x7BD8,0x7BDB,0x7BDC,0x7BDE,0x7BDF,0x7BE0,0x7BE2,0x7BE3,0x7BE4,0x7BE7,0x7BE8,0x7BE9,0x7BEB,0x7BEC,0x7BED,0x7BEF,0x7BF0,0x7BF2,0x7BF3,0x7BF4,0x7BF5,0x7BF6,0x7BF8,0x7BF9,0x7BFA,0x7BFB,0x7BFD,0x7BFF,0x7C00,0x7C01,0x7C02,0x7C03,0x7C04,0x7C05,0x7C06,0x7C08,0x7C09,0x7C0A,0x7C0D,0x7C0E,0x7C10,0x7C11,0x7C12,0x7C13,0x7C14,0x7C15,0x7C17,0x7C18,0x7C19,0x7C1A,0x7C1B,0x7C1C,0x7C1D,0x7C1E,0x7C20,0x7C21,0x7C22,0x7C23,0x7C24,0x7C25,0x7C28,0x7C29,0x7C2B,0x7C2C,0x7C2D,0x7C2E,0x7C2F,0x7C30,0x7C31,0x7C32,0x7C33,0x7C34,0x7C35,0x7C36,0x7C37,0x7C39,0x7C3A,0x7C3B,0x7C3C,0x7C3D,0x7C3E,0x7C42,0x9AB8,0x5B69,0x6D77,0x6C26,0x4EA5,0x5BB3,0x9A87,0x9163,0x61A8,0x90AF,0x97E9,0x542B,0x6DB5,0x5BD2,0x51FD,0x558A,0x7F55,0x7FF0,0x64BC,0x634D,0x65F1,0x61BE,0x608D,0x710A,0x6C57,0x6C49,0x592F,0x676D,0x822A,0x58D5,0x568E,0x8C6A,0x6BEB,0x90DD,0x597D,0x8017,0x53F7,0x6D69,0x5475,0x559D,0x8377,0x83CF,0x6838,0x79BE,0x548C,0x4F55,0x5408,0x76D2,0x8C89,0x9602,0x6CB3,0x6DB8,0x8D6B,0x8910,0x9E64,0x8D3A,0x563F,0x9ED1,0x75D5,0x5F88,0x72E0,0x6068,0x54FC,0x4EA8,0x6A2A,0x8861,0x6052,0x8F70,0x54C4,0x70D8,0x8679,0x9E3F,0x6D2A,0x5B8F,0x5F18,0x7EA2,0x5589,0x4FAF,0x7334,0x543C,0x539A,0x5019,0x540E,0x547C,0x4E4E,0x5FFD,0x745A,0x58F6,0x846B,0x80E1,0x8774,0x72D0,0x7CCA,0x6E56,0x7C43,0x7C44,0x7C45,0x7C46,0x7C47,0x7C48,0x7C49,0x7C4A,0x7C4B,0x7C4C,0x7C4E,0x7C4F,0x7C50,0x7C51,0x7C52,0x7C53,0x7C54,0x7C55,0x7C56,0x7C57,0x7C58,0x7C59,0x7C5A,0x7C5B,0x7C5C,0x7C5D,0x7C5E,0x7C5F,0x7C60,0x7C61,0x7C62,0x7C63,0x7C64,0x7C65,0x7C66,0x7C67,0x7C68,0x7C69,0x7C6A,0x7C6B,0x7C6C,0x7C6D,0x7C6E,0x7C6F,0x7C70,0x7C71,0x7C72,0x7C75,0x7C76,0x7C77,0x7C78,0x7C79,0x7C7A,0x7C7E,0x7C7F,0x7C80,0x7C81,0x7C82,0x7C83,0x7C84,0x7C85,0x7C86,0x7C87,0x7C88,0x7C8A,0x7C8B,0x7C8C,0x7C8D,0x7C8E,0x7C8F,0x7C90,0x7C93,0x7C94,0x7C96,0x7C99,0x7C9A,0x7C9B,0x7CA0,0x7CA1,0x7CA3,0x7CA6,0x7CA7,0x7CA8,0x7CA9,0x7CAB,0x7CAC,0x7CAD,0x7CAF,0x7CB0,0x7CB4,0x7CB5,0x7CB6,0x7CB7,0x7CB8,0x7CBA,0x7CBB,0x5F27,0x864E,0x552C,0x62A4,0x4E92,0x6CAA,0x6237,0x82B1,0x54D7,0x534E,0x733E,0x6ED1,0x753B,0x5212,0x5316,0x8BDD,0x69D0,0x5F8A,0x6000,0x6DEE,0x574F,0x6B22,0x73AF,0x6853,0x8FD8,0x7F13,0x6362,0x60A3,0x5524,0x75EA,0x8C62,0x7115,0x6DA3,0x5BA6,0x5E7B,0x8352,0x614C,0x9EC4,0x78FA,0x8757,0x7C27,0x7687,0x51F0,0x60F6,0x714C,0x6643,0x5E4C,0x604D,0x8C0E,0x7070,0x6325,0x8F89,0x5FBD,0x6062,0x86D4,0x56DE,0x6BC1,0x6094,0x6167,0x5349,0x60E0,0x6666,0x8D3F,0x79FD,0x4F1A,0x70E9,0x6C47,0x8BB3,0x8BF2,0x7ED8,0x8364,0x660F,0x5A5A,0x9B42,0x6D51,0x6DF7,0x8C41,0x6D3B,0x4F19,0x706B,0x83B7,0x6216,0x60D1,0x970D,0x8D27,0x7978,0x51FB,0x573E,0x57FA,0x673A,0x7578,0x7A3D,0x79EF,0x7B95,0x7CBF,0x7CC0,0x7CC2,0x7CC3,0x7CC4,0x7CC6,0x7CC9,0x7CCB,0x7CCE,0x7CCF,0x7CD0,0x7CD1,0x7CD2,0x7CD3,0x7CD4,0x7CD8,0x7CDA,0x7CDB,0x7CDD,0x7CDE,0x7CE1,0x7CE2,0x7CE3,0x7CE4,0x7CE5,0x7CE6,0x7CE7,0x7CE9,0x7CEA,0x7CEB,0x7CEC,0x7CED,0x7CEE,0x7CF0,0x7CF1,0x7CF2,0x7CF3,0x7CF4,0x7CF5,0x7CF6,0x7CF7,0x7CF9,0x7CFA,0x7CFC,0x7CFD,0x7CFE,0x7CFF,0x7D00,0x7D01,0x7D02,0x7D03,0x7D04,0x7D05,0x7D06,0x7D07,0x7D08,0x7D09,0x7D0B,0x7D0C,0x7D0D,0x7D0E,0x7D0F,0x7D10,0x7D11,0x7D12,0x7D13,0x7D14,0x7D15,0x7D16,0x7D17,0x7D18,0x7D19,0x7D1A,0x7D1B,0x7D1C,0x7D1D,0x7D1E,0x7D1F,0x7D21,0x7D23,0x7D24,0x7D25,0x7D26,0x7D28,0x7D29,0x7D2A,0x7D2C,0x7D2D,0x7D2E,0x7D30,0x7D31,0x7D32,0x7D33,0x7D34,0x7D35,0x7D36,0x808C,0x9965,0x8FF9,0x6FC0,0x8BA5,0x9E21,0x59EC,0x7EE9,0x7F09,0x5409,0x6781,0x68D8,0x8F91,0x7C4D,0x96C6,0x53CA,0x6025,0x75BE,0x6C72,0x5373,0x5AC9,0x7EA7,0x6324,0x51E0,0x810A,0x5DF1,0x84DF,0x6280,0x5180,0x5B63,0x4F0E,0x796D,0x5242,0x60B8,0x6D4E,0x5BC4,0x5BC2,0x8BA1,0x8BB0,0x65E2,0x5FCC,0x9645,0x5993,0x7EE7,0x7EAA,0x5609,0x67B7,0x5939,0x4F73,0x5BB6,0x52A0,0x835A,0x988A,0x8D3E,0x7532,0x94BE,0x5047,0x7A3C,0x4EF7,0x67B6,0x9A7E,0x5AC1,0x6B7C,0x76D1,0x575A,0x5C16,0x7B3A,0x95F4,0x714E,0x517C,0x80A9,0x8270,0x5978,0x7F04,0x8327,0x68C0,0x67EC,0x78B1,0x7877,0x62E3,0x6361,0x7B80,0x4FED,0x526A,0x51CF,0x8350,0x69DB,0x9274,0x8DF5,0x8D31,0x89C1,0x952E,0x7BAD,0x4EF6,0x7D37,0x7D38,0x7D39,0x7D3A,0x7D3B,0x7D3C,0x7D3D,0x7D3E,0x7D3F,0x7D40,0x7D41,0x7D42,0x7D43,0x7D44,0x7D45,0x7D46,0x7D47,0x7D48,0x7D49,0x7D4A,0x7D4B,0x7D4C,0x7D4D,0x7D4E,0x7D4F,0x7D50,0x7D51,0x7D52,0x7D53,0x7D54,0x7D55,0x7D56,0x7D57,0x7D58,0x7D59,0x7D5A,0x7D5B,0x7D5C,0x7D5D,0x7D5E,0x7D5F,0x7D60,0x7D61,0x7D62,0x7D63,0x7D64,0x7D65,0x7D66,0x7D67,0x7D68,0x7D69,0x7D6A,0x7D6B,0x7D6C,0x7D6D,0x7D6F,0x7D70,0x7D71,0x7D72,0x7D73,0x7D74,0x7D75,0x7D76,0x7D78,0x7D79,0x7D7A,0x7D7B,0x7D7C,0x7D7D,0x7D7E,0x7D7F,0x7D80,0x7D81,0x7D82,0x7D83,0x7D84,0x7D85,0x7D86,0x7D87,0x7D88,0x7D89,0x7D8A,0x7D8B,0x7D8C,0x7D8D,0x7D8E,0x7D8F,0x7D90,0x7D91,0x7D92,0x7D93,0x7D94,0x7D95,0x7D96,0x7D97,0x7D98,0x5065,0x8230,0x5251,0x996F,0x6E10,0x6E85,0x6DA7,0x5EFA,0x50F5,0x59DC,0x5C06,0x6D46,0x6C5F,0x7586,0x848B,0x6868,0x5956,0x8BB2,0x5320,0x9171,0x964D,0x8549,0x6912,0x7901,0x7126,0x80F6,0x4EA4,0x90CA,0x6D47,0x9A84,0x5A07,0x56BC,0x6405,0x94F0,0x77EB,0x4FA5,0x811A,0x72E1,0x89D2,0x997A,0x7F34,0x7EDE,0x527F,0x6559,0x9175,0x8F7F,0x8F83,0x53EB,0x7A96,0x63ED,0x63A5,0x7686,0x79F8,0x8857,0x9636,0x622A,0x52AB,0x8282,0x6854,0x6770,0x6377,0x776B,0x7AED,0x6D01,0x7ED3,0x89E3,0x59D0,0x6212,0x85C9,0x82A5,0x754C,0x501F,0x4ECB,0x75A5,0x8BEB,0x5C4A,0x5DFE,0x7B4B,0x65A4,0x91D1,0x4ECA,0x6D25,0x895F,0x7D27,0x9526,0x4EC5,0x8C28,0x8FDB,0x9773,0x664B,0x7981,0x8FD1,0x70EC,0x6D78,0x7D99,0x7D9A,0x7D9B,0x7D9C,0x7D9D,0x7D9E,0x7D9F,0x7DA0,0x7DA1,0x7DA2,0x7DA3,0x7DA4,0x7DA5,0x7DA7,0x7DA8,0x7DA9,0x7DAA,0x7DAB,0x7DAC,0x7DAD,0x7DAF,0x7DB0,0x7DB1,0x7DB2,0x7DB3,0x7DB4,0x7DB5,0x7DB6,0x7DB7,0x7DB8,0x7DB9,0x7DBA,0x7DBB,0x7DBC,0x7DBD,0x7DBE,0x7DBF,0x7DC0,0x7DC1,0x7DC2,0x7DC3,0x7DC4,0x7DC5,0x7DC6,0x7DC7,0x7DC8,0x7DC9,0x7DCA,0x7DCB,0x7DCC,0x7DCD,0x7DCE,0x7DCF,0x7DD0,0x7DD1,0x7DD2,0x7DD3,0x7DD4,0x7DD5,0x7DD6,0x7DD7,0x7DD8,0x7DD9,0x7DDA,0x7DDB,0x7DDC,0x7DDD,0x7DDE,0x7DDF,0x7DE0,0x7DE1,0x7DE2,0x7DE3,0x7DE4,0x7DE5,0x7DE6,0x7DE7,0x7DE8,0x7DE9,0x7DEA,0x7DEB,0x7DEC,0x7DED,0x7DEE,0x7DEF,0x7DF0,0x7DF1,0x7DF2,0x7DF3,0x7DF4,0x7DF5,0x7DF6,0x7DF7,0x7DF8,0x7DF9,0x7DFA,0x5C3D,0x52B2,0x8346,0x5162,0x830E,0x775B,0x6676,0x9CB8,0x4EAC,0x60CA,0x7CBE,0x7CB3,0x7ECF,0x4E95,0x8B66,0x666F,0x9888,0x9759,0x5883,0x656C,0x955C,0x5F84,0x75C9,0x9756,0x7ADF,0x7ADE,0x51C0,0x70AF,0x7A98,0x63EA,0x7A76,0x7EA0,0x7396,0x97ED,0x4E45,0x7078,0x4E5D,0x9152,0x53A9,0x6551,0x65E7,0x81FC,0x8205,0x548E,0x5C31,0x759A,0x97A0,0x62D8,0x72D9,0x75BD,0x5C45,0x9A79,0x83CA,0x5C40,0x5480,0x77E9,0x4E3E,0x6CAE,0x805A,0x62D2,0x636E,0x5DE8,0x5177,0x8DDD,0x8E1E,0x952F,0x4FF1,0x53E5,0x60E7,0x70AC,0x5267,0x6350,0x9E43,0x5A1F,0x5026,0x7737,0x5377,0x7EE2,0x6485,0x652B,0x6289,0x6398,0x5014,0x7235,0x89C9,0x51B3,0x8BC0,0x7EDD,0x5747,0x83CC,0x94A7,0x519B,0x541B,0x5CFB,0x7DFB,0x7DFC,0x7DFD,0x7DFE,0x7DFF,0x7E00,0x7E01,0x7E02,0x7E03,0x7E04,0x7E05,0x7E06,0x7E07,0x7E08,0x7E09,0x7E0A,0x7E0B,0x7E0C,0x7E0D,0x7E0E,0x7E0F,0x7E10,0x7E11,0x7E12,0x7E13,0x7E14,0x7E15,0x7E16,0x7E17,0x7E18,0x7E19,0x7E1A,0x7E1B,0x7E1C,0x7E1D,0x7E1E,0x7E1F,0x7E20,0x7E21,0x7E22,0x7E23,0x7E24,0x7E25,0x7E26,0x7E27,0x7E28,0x7E29,0x7E2A,0x7E2B,0x7E2C,0x7E2D,0x7E2E,0x7E2F,0x7E30,0x7E31,0x7E32,0x7E33,0x7E34,0x7E35,0x7E36,0x7E37,0x7E38,0x7E39,0x7E3A,0x7E3C,0x7E3D,0x7E3E,0x7E3F,0x7E40,0x7E42,0x7E43,0x7E44,0x7E45,0x7E46,0x7E48,0x7E49,0x7E4A,0x7E4B,0x7E4C,0x7E4D,0x7E4E,0x7E4F,0x7E50,0x7E51,0x7E52,0x7E53,0x7E54,0x7E55,0x7E56,0x7E57,0x7E58,0x7E59,0x7E5A,0x7E5B,0x7E5C,0x7E5D,0x4FCA,0x7AE3,0x6D5A,0x90E1,0x9A8F,0x5580,0x5496,0x5361,0x54AF,0x5F00,0x63E9,0x6977,0x51EF,0x6168,0x520A,0x582A,0x52D8,0x574E,0x780D,0x770B,0x5EB7,0x6177,0x7CE0,0x625B,0x6297,0x4EA2,0x7095,0x8003,0x62F7,0x70E4,0x9760,0x5777,0x82DB,0x67EF,0x68F5,0x78D5,0x9897,0x79D1,0x58F3,0x54B3,0x53EF,0x6E34,0x514B,0x523B,0x5BA2,0x8BFE,0x80AF,0x5543,0x57A6,0x6073,0x5751,0x542D,0x7A7A,0x6050,0x5B54,0x63A7,0x62A0,0x53E3,0x6263,0x5BC7,0x67AF,0x54ED,0x7A9F,0x82E6,0x9177,0x5E93,0x88E4,0x5938,0x57AE,0x630E,0x8DE8,0x80EF,0x5757,0x7B77,0x4FA9,0x5FEB,0x5BBD,0x6B3E,0x5321,0x7B50,0x72C2,0x6846,0x77FF,0x7736,0x65F7,0x51B5,0x4E8F,0x76D4,0x5CBF,0x7AA5,0x8475,0x594E,0x9B41,0x5080,0x7E5E,0x7E5F,0x7E60,0x7E61,0x7E62,0x7E63,0x7E64,0x7E65,0x7E66,0x7E67,0x7E68,0x7E69,0x7E6A,0x7E6B,0x7E6C,0x7E6D,0x7E6E,0x7E6F,0x7E70,0x7E71,0x7E72,0x7E73,0x7E74,0x7E75,0x7E76,0x7E77,0x7E78,0x7E79,0x7E7A,0x7E7B,0x7E7C,0x7E7D,0x7E7E,0x7E7F,0x7E80,0x7E81,0x7E83,0x7E84,0x7E85,0x7E86,0x7E87,0x7E88,0x7E89,0x7E8A,0x7E8B,0x7E8C,0x7E8D,0x7E8E,0x7E8F,0x7E90,0x7E91,0x7E92,0x7E93,0x7E94,0x7E95,0x7E96,0x7E97,0x7E98,0x7E99,0x7E9A,0x7E9C,0x7E9D,0x7E9E,0x7EAE,0x7EB4,0x7EBB,0x7EBC,0x7ED6,0x7EE4,0x7EEC,0x7EF9,0x7F0A,0x7F10,0x7F1E,0x7F37,0x7F39,0x7F3B,0x7F3C,0x7F3D,0x7F3E,0x7F3F,0x7F40,0x7F41,0x7F43,0x7F46,0x7F47,0x7F48,0x7F49,0x7F4A,0x7F4B,0x7F4C,0x7F4D,0x7F4E,0x7F4F,0x7F52,0x7F53,0x9988,0x6127,0x6E83,0x5764,0x6606,0x6346,0x56F0,0x62EC,0x6269,0x5ED3,0x9614,0x5783,0x62C9,0x5587,0x8721,0x814A,0x8FA3,0x5566,0x83B1,0x6765,0x8D56,0x84DD,0x5A6A,0x680F,0x62E6,0x7BEE,0x9611,0x5170,0x6F9C,0x8C30,0x63FD,0x89C8,0x61D2,0x7F06,0x70C2,0x6EE5,0x7405,0x6994,0x72FC,0x5ECA,0x90CE,0x6717,0x6D6A,0x635E,0x52B3,0x7262,0x8001,0x4F6C,0x59E5,0x916A,0x70D9,0x6D9D,0x52D2,0x4E50,0x96F7,0x956D,0x857E,0x78CA,0x7D2F,0x5121,0x5792,0x64C2,0x808B,0x7C7B,0x6CEA,0x68F1,0x695E,0x51B7,0x5398,0x68A8,0x7281,0x9ECE,0x7BF1,0x72F8,0x79BB,0x6F13,0x7406,0x674E,0x91CC,0x9CA4,0x793C,0x8389,0x8354,0x540F,0x6817,0x4E3D,0x5389,0x52B1,0x783E,0x5386,0x5229,0x5088,0x4F8B,0x4FD0,0x7F56,0x7F59,0x7F5B,0x7F5C,0x7F5D,0x7F5E,0x7F60,0x7F63,0x7F64,0x7F65,0x7F66,0x7F67,0x7F6B,0x7F6C,0x7F6D,0x7F6F,0x7F70,0x7F73,0x7F75,0x7F76,0x7F77,0x7F78,0x7F7A,0x7F7B,0x7F7C,0x7F7D,0x7F7F,0x7F80,0x7F82,0x7F83,0x7F84,0x7F85,0x7F86,0x7F87,0x7F88,0x7F89,0x7F8B,0x7F8D,0x7F8F,0x7F90,0x7F91,0x7F92,0x7F93,0x7F95,0x7F96,0x7F97,0x7F98,0x7F99,0x7F9B,0x7F9C,0x7FA0,0x7FA2,0x7FA3,0x7FA5,0x7FA6,0x7FA8,0x7FA9,0x7FAA,0x7FAB,0x7FAC,0x7FAD,0x7FAE,0x7FB1,0x7FB3,0x7FB4,0x7FB5,0x7FB6,0x7FB7,0x7FBA,0x7FBB,0x7FBE,0x7FC0,0x7FC2,0x7FC3,0x7FC4,0x7FC6,0x7FC7,0x7FC8,0x7FC9,0x7FCB,0x7FCD,0x7FCF,0x7FD0,0x7FD1,0x7FD2,0x7FD3,0x7FD6,0x7FD7,0x7FD9,0x7FDA,0x7FDB,0x7FDC,0x7FDD,0x7FDE,0x7FE2,0x7FE3,0x75E2,0x7ACB,0x7C92,0x6CA5,0x96B6,0x529B,0x7483,0x54E9,0x4FE9,0x8054,0x83B2,0x8FDE,0x9570,0x5EC9,0x601C,0x6D9F,0x5E18,0x655B,0x8138,0x94FE,0x604B,0x70BC,0x7EC3,0x7CAE,0x51C9,0x6881,0x7CB1,0x826F,0x4E24,0x8F86,0x91CF,0x667E,0x4EAE,0x8C05,0x64A9,0x804A,0x50DA,0x7597,0x71CE,0x5BE5,0x8FBD,0x6F66,0x4E86,0x6482,0x9563,0x5ED6,0x6599,0x5217,0x88C2,0x70C8,0x52A3,0x730E,0x7433,0x6797,0x78F7,0x9716,0x4E34,0x90BB,0x9CDE,0x6DCB,0x51DB,0x8D41,0x541D,0x62CE,0x73B2,0x83F1,0x96F6,0x9F84,0x94C3,0x4F36,0x7F9A,0x51CC,0x7075,0x9675,0x5CAD,0x9886,0x53E6,0x4EE4,0x6E9C,0x7409,0x69B4,0x786B,0x998F,0x7559,0x5218,0x7624,0x6D41,0x67F3,0x516D,0x9F99,0x804B,0x5499,0x7B3C,0x7ABF,0x7FE4,0x7FE7,0x7FE8,0x7FEA,0x7FEB,0x7FEC,0x7FED,0x7FEF,0x7FF2,0x7FF4,0x7FF5,0x7FF6,0x7FF7,0x7FF8,0x7FF9,0x7FFA,0x7FFD,0x7FFE,0x7FFF,0x8002,0x8007,0x8008,0x8009,0x800A,0x800E,0x800F,0x8011,0x8013,0x801A,0x801B,0x801D,0x801E,0x801F,0x8021,0x8023,0x8024,0x802B,0x802C,0x802D,0x802E,0x802F,0x8030,0x8032,0x8034,0x8039,0x803A,0x803C,0x803E,0x8040,0x8041,0x8044,0x8045,0x8047,0x8048,0x8049,0x804E,0x804F,0x8050,0x8051,0x8053,0x8055,0x8056,0x8057,0x8059,0x805B,0x805C,0x805D,0x805E,0x805F,0x8060,0x8061,0x8062,0x8063,0x8064,0x8065,0x8066,0x8067,0x8068,0x806B,0x806C,0x806D,0x806E,0x806F,0x8070,0x8072,0x8073,0x8074,0x8075,0x8076,0x8077,0x8078,0x8079,0x807A,0x807B,0x807C,0x807D,0x9686,0x5784,0x62E2,0x9647,0x697C,0x5A04,0x6402,0x7BD3,0x6F0F,0x964B,0x82A6,0x5362,0x9885,0x5E90,0x7089,0x63B3,0x5364,0x864F,0x9C81,0x9E93,0x788C,0x9732,0x8DEF,0x8D42,0x9E7F,0x6F5E,0x7984,0x5F55,0x9646,0x622E,0x9A74,0x5415,0x94DD,0x4FA3,0x65C5,0x5C65,0x5C61,0x7F15,0x8651,0x6C2F,0x5F8B,0x7387,0x6EE4,0x7EFF,0x5CE6,0x631B,0x5B6A,0x6EE6,0x5375,0x4E71,0x63A0,0x7565,0x62A1,0x8F6E,0x4F26,0x4ED1,0x6CA6,0x7EB6,0x8BBA,0x841D,0x87BA,0x7F57,0x903B,0x9523,0x7BA9,0x9AA1,0x88F8,0x843D,0x6D1B,0x9A86,0x7EDC,0x5988,0x9EBB,0x739B,0x7801,0x8682,0x9A6C,0x9A82,0x561B,0x5417,0x57CB,0x4E70,0x9EA6,0x5356,0x8FC8,0x8109,0x7792,0x9992,0x86EE,0x6EE1,0x8513,0x66FC,0x6162,0x6F2B,0x807E,0x8081,0x8082,0x8085,0x8088,0x808A,0x808D,0x808E,0x808F,0x8090,0x8091,0x8092,0x8094,0x8095,0x8097,0x8099,0x809E,0x80A3,0x80A6,0x80A7,0x80A8,0x80AC,0x80B0,0x80B3,0x80B5,0x80B6,0x80B8,0x80B9,0x80BB,0x80C5,0x80C7,0x80C8,0x80C9,0x80CA,0x80CB,0x80CF,0x80D0,0x80D1,0x80D2,0x80D3,0x80D4,0x80D5,0x80D8,0x80DF,0x80E0,0x80E2,0x80E3,0x80E6,0x80EE,0x80F5,0x80F7,0x80F9,0x80FB,0x80FE,0x80FF,0x8100,0x8101,0x8103,0x8104,0x8105,0x8107,0x8108,0x810B,0x810C,0x8115,0x8117,0x8119,0x811B,0x811C,0x811D,0x811F,0x8120,0x8121,0x8122,0x8123,0x8124,0x8125,0x8126,0x8127,0x8128,0x8129,0x812A,0x812B,0x812D,0x812E,0x8130,0x8133,0x8134,0x8135,0x8137,0x8139,0x813A,0x813B,0x813C,0x813D,0x813F,0x8C29,0x8292,0x832B,0x76F2,0x6C13,0x5FD9,0x83BD,0x732B,0x8305,0x951A,0x6BDB,0x77DB,0x94C6,0x536F,0x8302,0x5192,0x5E3D,0x8C8C,0x8D38,0x4E48,0x73AB,0x679A,0x6885,0x9176,0x9709,0x7164,0x6CA1,0x7709,0x5A92,0x9541,0x6BCF,0x7F8E,0x6627,0x5BD0,0x59B9,0x5A9A,0x95E8,0x95F7,0x4EEC,0x840C,0x8499,0x6AAC,0x76DF,0x9530,0x731B,0x68A6,0x5B5F,0x772F,0x919A,0x9761,0x7CDC,0x8FF7,0x8C1C,0x5F25,0x7C73,0x79D8,0x89C5,0x6CCC,0x871C,0x5BC6,0x5E42,0x68C9,0x7720,0x7EF5,0x5195,0x514D,0x52C9,0x5A29,0x7F05,0x9762,0x82D7,0x63CF,0x7784,0x85D0,0x79D2,0x6E3A,0x5E99,0x5999,0x8511,0x706D,0x6C11,0x62BF,0x76BF,0x654F,0x60AF,0x95FD,0x660E,0x879F,0x9E23,0x94ED,0x540D,0x547D,0x8C2C,0x6478,0x8140,0x8141,0x8142,0x8143,0x8144,0x8145,0x8147,0x8149,0x814D,0x814E,0x814F,0x8152,0x8156,0x8157,0x8158,0x815B,0x815C,0x815D,0x815E,0x815F,0x8161,0x8162,0x8163,0x8164,0x8166,0x8168,0x816A,0x816B,0x816C,0x816F,0x8172,0x8173,0x8175,0x8176,0x8177,0x8178,0x8181,0x8183,0x8184,0x8185,0x8186,0x8187,0x8189,0x818B,0x818C,0x818D,0x818E,0x8190,0x8192,0x8193,0x8194,0x8195,0x8196,0x8197,0x8199,0x819A,0x819E,0x819F,0x81A0,0x81A1,0x81A2,0x81A4,0x81A5,0x81A7,0x81A9,0x81AB,0x81AC,0x81AD,0x81AE,0x81AF,0x81B0,0x81B1,0x81B2,0x81B4,0x81B5,0x81B6,0x81B7,0x81B8,0x81B9,0x81BC,0x81BD,0x81BE,0x81BF,0x81C4,0x81C5,0x81C7,0x81C8,0x81C9,0x81CB,0x81CD,0x81CE,0x81CF,0x81D0,0x81D1,0x81D2,0x81D3,0x6479,0x8611,0x6A21,0x819C,0x78E8,0x6469,0x9B54,0x62B9,0x672B,0x83AB,0x58A8,0x9ED8,0x6CAB,0x6F20,0x5BDE,0x964C,0x8C0B,0x725F,0x67D0,0x62C7,0x7261,0x4EA9,0x59C6,0x6BCD,0x5893,0x66AE,0x5E55,0x52DF,0x6155,0x6728,0x76EE,0x7766,0x7267,0x7A46,0x62FF,0x54EA,0x5450,0x94A0,0x90A3,0x5A1C,0x7EB3,0x6C16,0x4E43,0x5976,0x8010,0x5948,0x5357,0x7537,0x96BE,0x56CA,0x6320,0x8111,0x607C,0x95F9,0x6DD6,0x5462,0x9981,0x5185,0x5AE9,0x80FD,0x59AE,0x9713,0x502A,0x6CE5,0x5C3C,0x62DF,0x4F60,0x533F,0x817B,0x9006,0x6EBA,0x852B,0x62C8,0x5E74,0x78BE,0x64B5,0x637B,0x5FF5,0x5A18,0x917F,0x9E1F,0x5C3F,0x634F,0x8042,0x5B7D,0x556E,0x954A,0x954D,0x6D85,0x60A8,0x67E0,0x72DE,0x51DD,0x5B81,0x81D4,0x81D5,0x81D6,0x81D7,0x81D8,0x81D9,0x81DA,0x81DB,0x81DC,0x81DD,0x81DE,0x81DF,0x81E0,0x81E1,0x81E2,0x81E4,0x81E5,0x81E6,0x81E8,0x81E9,0x81EB,0x81EE,0x81EF,0x81F0,0x81F1,0x81F2,0x81F5,0x81F6,0x81F7,0x81F8,0x81F9,0x81FA,0x81FD,0x81FF,0x8203,0x8207,0x8208,0x8209,0x820A,0x820B,0x820E,0x820F,0x8211,0x8213,0x8215,0x8216,0x8217,0x8218,0x8219,0x821A,0x821D,0x8220,0x8224,0x8225,0x8226,0x8227,0x8229,0x822E,0x8232,0x823A,0x823C,0x823D,0x823F,0x8240,0x8241,0x8242,0x8243,0x8245,0x8246,0x8248,0x824A,0x824C,0x824D,0x824E,0x8250,0x8251,0x8252,0x8253,0x8254,0x8255,0x8256,0x8257,0x8259,0x825B,0x825C,0x825D,0x825E,0x8260,0x8261,0x8262,0x8263,0x8264,0x8265,0x8266,0x8267,0x8269,0x62E7,0x6CDE,0x725B,0x626D,0x94AE,0x7EBD,0x8113,0x6D53,0x519C,0x5F04,0x5974,0x52AA,0x6012,0x5973,0x6696,0x8650,0x759F,0x632A,0x61E6,0x7CEF,0x8BFA,0x54E6,0x6B27,0x9E25,0x6BB4,0x85D5,0x5455,0x5076,0x6CA4,0x556A,0x8DB4,0x722C,0x5E15,0x6015,0x7436,0x62CD,0x6392,0x724C,0x5F98,0x6E43,0x6D3E,0x6500,0x6F58,0x76D8,0x78D0,0x76FC,0x7554,0x5224,0x53DB,0x4E53,0x5E9E,0x65C1,0x802A,0x80D6,0x629B,0x5486,0x5228,0x70AE,0x888D,0x8DD1,0x6CE1,0x5478,0x80DA,0x57F9,0x88F4,0x8D54,0x966A,0x914D,0x4F69,0x6C9B,0x55B7,0x76C6,0x7830,0x62A8,0x70F9,0x6F8E,0x5F6D,0x84EC,0x68DA,0x787C,0x7BF7,0x81A8,0x670B,0x9E4F,0x6367,0x78B0,0x576F,0x7812,0x9739,0x6279,0x62AB,0x5288,0x7435,0x6BD7,0x826A,0x826B,0x826C,0x826D,0x8271,0x8275,0x8276,0x8277,0x8278,0x827B,0x827C,0x8280,0x8281,0x8283,0x8285,0x8286,0x8287,0x8289,0x828C,0x8290,0x8293,0x8294,0x8295,0x8296,0x829A,0x829B,0x829E,0x82A0,0x82A2,0x82A3,0x82A7,0x82B2,0x82B5,0x82B6,0x82BA,0x82BB,0x82BC,0x82BF,0x82C0,0x82C2,0x82C3,0x82C5,0x82C6,0x82C9,0x82D0,0x82D6,0x82D9,0x82DA,0x82DD,0x82E2,0x82E7,0x82E8,0x82E9,0x82EA,0x82EC,0x82ED,0x82EE,0x82F0,0x82F2,0x82F3,0x82F5,0x82F6,0x82F8,0x82FA,0x82FC,0x82FD,0x82FE,0x82FF,0x8300,0x830A,0x830B,0x830D,0x8310,0x8312,0x8313,0x8316,0x8318,0x8319,0x831D,0x831E,0x831F,0x8320,0x8321,0x8322,0x8323,0x8324,0x8325,0x8326,0x8329,0x832A,0x832E,0x8330,0x8332,0x8337,0x833B,0x833D,0x5564,0x813E,0x75B2,0x76AE,0x5339,0x75DE,0x50FB,0x5C41,0x8B6C,0x7BC7,0x504F,0x7247,0x9A97,0x98D8,0x6F02,0x74E2,0x7968,0x6487,0x77A5,0x62FC,0x9891,0x8D2B,0x54C1,0x8058,0x4E52,0x576A,0x82F9,0x840D,0x5E73,0x51ED,0x74F6,0x8BC4,0x5C4F,0x5761,0x6CFC,0x9887,0x5A46,0x7834,0x9B44,0x8FEB,0x7C95,0x5256,0x6251,0x94FA,0x4EC6,0x8386,0x8461,0x83E9,0x84B2,0x57D4,0x6734,0x5703,0x666E,0x6D66,0x8C31,0x66DD,0x7011,0x671F,0x6B3A,0x6816,0x621A,0x59BB,0x4E03,0x51C4,0x6F06,0x67D2,0x6C8F,0x5176,0x68CB,0x5947,0x6B67,0x7566,0x5D0E,0x8110,0x9F50,0x65D7,0x7948,0x7941,0x9A91,0x8D77,0x5C82,0x4E5E,0x4F01,0x542F,0x5951,0x780C,0x5668,0x6C14,0x8FC4,0x5F03,0x6C7D,0x6CE3,0x8BAB,0x6390,0x833E,0x833F,0x8341,0x8342,0x8344,0x8345,0x8348,0x834A,0x834B,0x834C,0x834D,0x834E,0x8353,0x8355,0x8356,0x8357,0x8358,0x8359,0x835D,0x8362,0x8370,0x8371,0x8372,0x8373,0x8374,0x8375,0x8376,0x8379,0x837A,0x837E,0x837F,0x8380,0x8381,0x8382,0x8383,0x8384,0x8387,0x8388,0x838A,0x838B,0x838C,0x838D,0x838F,0x8390,0x8391,0x8394,0x8395,0x8396,0x8397,0x8399,0x839A,0x839D,0x839F,0x83A1,0x83A2,0x83A3,0x83A4,0x83A5,0x83A6,0x83A7,0x83AC,0x83AD,0x83AE,0x83AF,0x83B5,0x83BB,0x83BE,0x83BF,0x83C2,0x83C3,0x83C4,0x83C6,0x83C8,0x83C9,0x83CB,0x83CD,0x83CE,0x83D0,0x83D1,0x83D2,0x83D3,0x83D5,0x83D7,0x83D9,0x83DA,0x83DB,0x83DE,0x83E2,0x83E3,0x83E4,0x83E6,0x83E7,0x83E8,0x83EB,0x83EC,0x83ED,0x6070,0x6D3D,0x7275,0x6266,0x948E,0x94C5,0x5343,0x8FC1,0x7B7E,0x4EDF,0x8C26,0x4E7E,0x9ED4,0x94B1,0x94B3,0x524D,0x6F5C,0x9063,0x6D45,0x8C34,0x5811,0x5D4C,0x6B20,0x6B49,0x67AA,0x545B,0x8154,0x7F8C,0x5899,0x8537,0x5F3A,0x62A2,0x6A47,0x9539,0x6572,0x6084,0x6865,0x77A7,0x4E54,0x4FA8,0x5DE7,0x9798,0x64AC,0x7FD8,0x5CED,0x4FCF,0x7A8D,0x5207,0x8304,0x4E14,0x602F,0x7A83,0x94A6,0x4FB5,0x4EB2,0x79E6,0x7434,0x52E4,0x82B9,0x64D2,0x79BD,0x5BDD,0x6C81,0x9752,0x8F7B,0x6C22,0x503E,0x537F,0x6E05,0x64CE,0x6674,0x6C30,0x60C5,0x9877,0x8BF7,0x5E86,0x743C,0x7A77,0x79CB,0x4E18,0x90B1,0x7403,0x6C42,0x56DA,0x914B,0x6CC5,0x8D8B,0x533A,0x86C6,0x66F2,0x8EAF,0x5C48,0x9A71,0x6E20,0x83EE,0x83EF,0x83F3,0x83F4,0x83F5,0x83F6,0x83F7,0x83FA,0x83FB,0x83FC,0x83FE,0x83FF,0x8400,0x8402,0x8405,0x8407,0x8408,0x8409,0x840A,0x8410,0x8412,0x8413,0x8414,0x8415,0x8416,0x8417,0x8419,0x841A,0x841B,0x841E,0x841F,0x8420,0x8421,0x8422,0x8423,0x8429,0x842A,0x842B,0x842C,0x842D,0x842E,0x842F,0x8430,0x8432,0x8433,0x8434,0x8435,0x8436,0x8437,0x8439,0x843A,0x843B,0x843E,0x843F,0x8440,0x8441,0x8442,0x8443,0x8444,0x8445,0x8447,0x8448,0x8449,0x844A,0x844B,0x844C,0x844D,0x844E,0x844F,0x8450,0x8452,0x8453,0x8454,0x8455,0x8456,0x8458,0x845D,0x845E,0x845F,0x8460,0x8462,0x8464,0x8465,0x8466,0x8467,0x8468,0x846A,0x846E,0x846F,0x8470,0x8472,0x8474,0x8477,0x8479,0x847B,0x847C,0x53D6,0x5A36,0x9F8B,0x8DA3,0x53BB,0x5708,0x98A7,0x6743,0x919B,0x6CC9,0x5168,0x75CA,0x62F3,0x72AC,0x5238,0x529D,0x7F3A,0x7094,0x7638,0x5374,0x9E4A,0x69B7,0x786E,0x96C0,0x88D9,0x7FA4,0x7136,0x71C3,0x5189,0x67D3,0x74E4,0x58E4,0x6518,0x56B7,0x8BA9,0x9976,0x6270,0x7ED5,0x60F9,0x70ED,0x58EC,0x4EC1,0x4EBA,0x5FCD,0x97E7,0x4EFB,0x8BA4,0x5203,0x598A,0x7EAB,0x6254,0x4ECD,0x65E5,0x620E,0x8338,0x84C9,0x8363,0x878D,0x7194,0x6EB6,0x5BB9,0x7ED2,0x5197,0x63C9,0x67D4,0x8089,0x8339,0x8815,0x5112,0x5B7A,0x5982,0x8FB1,0x4E73,0x6C5D,0x5165,0x8925,0x8F6F,0x962E,0x854A,0x745E,0x9510,0x95F0,0x6DA6,0x82E5,0x5F31,0x6492,0x6D12,0x8428,0x816E,0x9CC3,0x585E,0x8D5B,0x4E09,0x53C1,0x847D,0x847E,0x847F,0x8480,0x8481,0x8483,0x8484,0x8485,0x8486,0x848A,0x848D,0x848F,0x8490,0x8491,0x8492,0x8493,0x8494,0x8495,0x8496,0x8498,0x849A,0x849B,0x849D,0x849E,0x849F,0x84A0,0x84A2,0x84A3,0x84A4,0x84A5,0x84A6,0x84A7,0x84A8,0x84A9,0x84AA,0x84AB,0x84AC,0x84AD,0x84AE,0x84B0,0x84B1,0x84B3,0x84B5,0x84B6,0x84B7,0x84BB,0x84BC,0x84BE,0x84C0,0x84C2,0x84C3,0x84C5,0x84C6,0x84C7,0x84C8,0x84CB,0x84CC,0x84CE,0x84CF,0x84D2,0x84D4,0x84D5,0x84D7,0x84D8,0x84D9,0x84DA,0x84DB,0x84DC,0x84DE,0x84E1,0x84E2,0x84E4,0x84E7,0x84E8,0x84E9,0x84EA,0x84EB,0x84ED,0x84EE,0x84EF,0x84F1,0x84F2,0x84F3,0x84F4,0x84F5,0x84F6,0x84F7,0x84F8,0x84F9,0x84FA,0x84FB,0x84FD,0x84FE,0x8500,0x8501,0x8502,0x4F1E,0x6563,0x6851,0x55D3,0x4E27,0x6414,0x9A9A,0x626B,0x5AC2,0x745F,0x8272,0x6DA9,0x68EE,0x50E7,0x838E,0x7802,0x6740,0x5239,0x6C99,0x7EB1,0x50BB,0x5565,0x715E,0x7B5B,0x6652,0x73CA,0x82EB,0x6749,0x5C71,0x5220,0x717D,0x886B,0x95EA,0x9655,0x64C5,0x8D61,0x81B3,0x5584,0x6C55,0x6247,0x7F2E,0x5892,0x4F24,0x5546,0x8D4F,0x664C,0x4E0A,0x5C1A,0x88F3,0x68A2,0x634E,0x7A0D,0x70E7,0x828D,0x52FA,0x97F6,0x5C11,0x54E8,0x90B5,0x7ECD,0x5962,0x8D4A,0x86C7,0x820C,0x820D,0x8D66,0x6444,0x5C04,0x6151,0x6D89,0x793E,0x8BBE,0x7837,0x7533,0x547B,0x4F38,0x8EAB,0x6DF1,0x5A20,0x7EC5,0x795E,0x6C88,0x5BA1,0x5A76,0x751A,0x80BE,0x614E,0x6E17,0x58F0,0x751F,0x7525,0x7272,0x5347,0x7EF3,0x8503,0x8504,0x8505,0x8506,0x8507,0x8508,0x8509,0x850A,0x850B,0x850D,0x850E,0x850F,0x8510,0x8512,0x8514,0x8515,0x8516,0x8518,0x8519,0x851B,0x851C,0x851D,0x851E,0x8520,0x8522,0x8523,0x8524,0x8525,0x8526,0x8527,0x8528,0x8529,0x852A,0x852D,0x852E,0x852F,0x8530,0x8531,0x8532,0x8533,0x8534,0x8535,0x8536,0x853E,0x853F,0x8540,0x8541,0x8542,0x8544,0x8545,0x8546,0x8547,0x854B,0x854C,0x854D,0x854E,0x854F,0x8550,0x8551,0x8552,0x8553,0x8554,0x8555,0x8557,0x8558,0x855A,0x855B,0x855C,0x855D,0x855F,0x8560,0x8561,0x8562,0x8563,0x8565,0x8566,0x8567,0x8569,0x856A,0x856B,0x856C,0x856D,0x856E,0x856F,0x8570,0x8571,0x8573,0x8575,0x8576,0x8577,0x8578,0x857C,0x857D,0x857F,0x8580,0x8581,0x7701,0x76DB,0x5269,0x80DC,0x5723,0x5E08,0x5931,0x72EE,0x65BD,0x6E7F,0x8BD7,0x5C38,0x8671,0x5341,0x77F3,0x62FE,0x65F6,0x4EC0,0x98DF,0x8680,0x5B9E,0x8BC6,0x53F2,0x77E2,0x4F7F,0x5C4E,0x9A76,0x59CB,0x5F0F,0x793A,0x58EB,0x4E16,0x67FF,0x4E8B,0x62ED,0x8A93,0x901D,0x52BF,0x662F,0x55DC,0x566C,0x9002,0x4ED5,0x4F8D,0x91CA,0x9970,0x6C0F,0x5E02,0x6043,0x5BA4,0x89C6,0x8BD5,0x6536,0x624B,0x9996,0x5B88,0x5BFF,0x6388,0x552E,0x53D7,0x7626,0x517D,0x852C,0x67A2,0x68B3,0x6B8A,0x6292,0x8F93,0x53D4,0x8212,0x6DD1,0x758F,0x4E66,0x8D4E,0x5B70,0x719F,0x85AF,0x6691,0x66D9,0x7F72,0x8700,0x9ECD,0x9F20,0x5C5E,0x672F,0x8FF0,0x6811,0x675F,0x620D,0x7AD6,0x5885,0x5EB6,0x6570,0x6F31,0x8582,0x8583,0x8586,0x8588,0x8589,0x858A,0x858B,0x858C,0x858D,0x858E,0x8590,0x8591,0x8592,0x8593,0x8594,0x8595,0x8596,0x8597,0x8598,0x8599,0x859A,0x859D,0x859E,0x859F,0x85A0,0x85A1,0x85A2,0x85A3,0x85A5,0x85A6,0x85A7,0x85A9,0x85AB,0x85AC,0x85AD,0x85B1,0x85B2,0x85B3,0x85B4,0x85B5,0x85B6,0x85B8,0x85BA,0x85BB,0x85BC,0x85BD,0x85BE,0x85BF,0x85C0,0x85C2,0x85C3,0x85C4,0x85C5,0x85C6,0x85C7,0x85C8,0x85CA,0x85CB,0x85CC,0x85CD,0x85CE,0x85D1,0x85D2,0x85D4,0x85D6,0x85D7,0x85D8,0x85D9,0x85DA,0x85DB,0x85DD,0x85DE,0x85DF,0x85E0,0x85E1,0x85E2,0x85E3,0x85E5,0x85E6,0x85E7,0x85E8,0x85EA,0x85EB,0x85EC,0x85ED,0x85EE,0x85EF,0x85F0,0x85F1,0x85F2,0x85F3,0x85F4,0x85F5,0x85F6,0x85F7,0x85F8,0x6055,0x5237,0x800D,0x6454,0x8870,0x7529,0x5E05,0x6813,0x62F4,0x971C,0x53CC,0x723D,0x8C01,0x6C34,0x7761,0x7A0E,0x542E,0x77AC,0x987A,0x821C,0x8BF4,0x7855,0x6714,0x70C1,0x65AF,0x6495,0x5636,0x601D,0x79C1,0x53F8,0x4E1D,0x6B7B,0x8086,0x5BFA,0x55E3,0x56DB,0x4F3A,0x4F3C,0x9972,0x5DF3,0x677E,0x8038,0x6002,0x9882,0x9001,0x5B8B,0x8BBC,0x8BF5,0x641C,0x8258,0x64DE,0x55FD,0x82CF,0x9165,0x4FD7,0x7D20,0x901F,0x7C9F,0x50F3,0x5851,0x6EAF,0x5BBF,0x8BC9,0x8083,0x9178,0x849C,0x7B97,0x867D,0x968B,0x968F,0x7EE5,0x9AD3,0x788E,0x5C81,0x7A57,0x9042,0x96A7,0x795F,0x5B59,0x635F,0x7B0B,0x84D1,0x68AD,0x5506,0x7F29,0x7410,0x7D22,0x9501,0x6240,0x584C,0x4ED6,0x5B83,0x5979,0x5854,0x85F9,0x85FA,0x85FC,0x85FD,0x85FE,0x8600,0x8601,0x8602,0x8603,0x8604,0x8606,0x8607,0x8608,0x8609,0x860A,0x860B,0x860C,0x860D,0x860E,0x860F,0x8610,0x8612,0x8613,0x8614,0x8615,0x8617,0x8618,0x8619,0x861A,0x861B,0x861C,0x861D,0x861E,0x861F,0x8620,0x8621,0x8622,0x8623,0x8624,0x8625,0x8626,0x8628,0x862A,0x862B,0x862C,0x862D,0x862E,0x862F,0x8630,0x8631,0x8632,0x8633,0x8634,0x8635,0x8636,0x8637,0x8639,0x863A,0x863B,0x863D,0x863E,0x863F,0x8640,0x8641,0x8642,0x8643,0x8644,0x8645,0x8646,0x8647,0x8648,0x8649,0x864A,0x864B,0x864C,0x8652,0x8653,0x8655,0x8656,0x8657,0x8658,0x8659,0x865B,0x865C,0x865D,0x865F,0x8660,0x8661,0x8663,0x8664,0x8665,0x8666,0x8667,0x8668,0x8669,0x866A,0x736D,0x631E,0x8E4B,0x8E0F,0x80CE,0x82D4,0x62AC,0x53F0,0x6CF0,0x915E,0x592A,0x6001,0x6C70,0x574D,0x644A,0x8D2A,0x762B,0x6EE9,0x575B,0x6A80,0x75F0,0x6F6D,0x8C2D,0x8C08,0x5766,0x6BEF,0x8892,0x78B3,0x63A2,0x53F9,0x70AD,0x6C64,0x5858,0x642A,0x5802,0x68E0,0x819B,0x5510,0x7CD6,0x5018,0x8EBA,0x6DCC,0x8D9F,0x70EB,0x638F,0x6D9B,0x6ED4,0x7EE6,0x8404,0x6843,0x9003,0x6DD8,0x9676,0x8BA8,0x5957,0x7279,0x85E4,0x817E,0x75BC,0x8A8A,0x68AF,0x5254,0x8E22,0x9511,0x63D0,0x9898,0x8E44,0x557C,0x4F53,0x66FF,0x568F,0x60D5,0x6D95,0x5243,0x5C49,0x5929,0x6DFB,0x586B,0x7530,0x751C,0x606C,0x8214,0x8146,0x6311,0x6761,0x8FE2,0x773A,0x8DF3,0x8D34,0x94C1,0x5E16,0x5385,0x542C,0x70C3,0x866D,0x866F,0x8670,0x8672,0x8673,0x8674,0x8675,0x8676,0x8677,0x8678,0x8683,0x8684,0x8685,0x8686,0x8687,0x8688,0x8689,0x868E,0x868F,0x8690,0x8691,0x8692,0x8694,0x8696,0x8697,0x8698,0x8699,0x869A,0x869B,0x869E,0x869F,0x86A0,0x86A1,0x86A2,0x86A5,0x86A6,0x86AB,0x86AD,0x86AE,0x86B2,0x86B3,0x86B7,0x86B8,0x86B9,0x86BB,0x86BC,0x86BD,0x86BE,0x86BF,0x86C1,0x86C2,0x86C3,0x86C5,0x86C8,0x86CC,0x86CD,0x86D2,0x86D3,0x86D5,0x86D6,0x86D7,0x86DA,0x86DC,0x86DD,0x86E0,0x86E1,0x86E2,0x86E3,0x86E5,0x86E6,0x86E7,0x86E8,0x86EA,0x86EB,0x86EC,0x86EF,0x86F5,0x86F6,0x86F7,0x86FA,0x86FB,0x86FC,0x86FD,0x86FF,0x8701,0x8704,0x8705,0x8706,0x870B,0x870C,0x870E,0x870F,0x8710,0x8711,0x8714,0x8716,0x6C40,0x5EF7,0x505C,0x4EAD,0x5EAD,0x633A,0x8247,0x901A,0x6850,0x916E,0x77B3,0x540C,0x94DC,0x5F64,0x7AE5,0x6876,0x6345,0x7B52,0x7EDF,0x75DB,0x5077,0x6295,0x5934,0x900F,0x51F8,0x79C3,0x7A81,0x56FE,0x5F92,0x9014,0x6D82,0x5C60,0x571F,0x5410,0x5154,0x6E4D,0x56E2,0x63A8,0x9893,0x817F,0x8715,0x892A,0x9000,0x541E,0x5C6F,0x81C0,0x62D6,0x6258,0x8131,0x9E35,0x9640,0x9A6E,0x9A7C,0x692D,0x59A5,0x62D3,0x553E,0x6316,0x54C7,0x86D9,0x6D3C,0x5A03,0x74E6,0x889C,0x6B6A,0x5916,0x8C4C,0x5F2F,0x6E7E,0x73A9,0x987D,0x4E38,0x70F7,0x5B8C,0x7897,0x633D,0x665A,0x7696,0x60CB,0x5B9B,0x5A49,0x4E07,0x8155,0x6C6A,0x738B,0x4EA1,0x6789,0x7F51,0x5F80,0x65FA,0x671B,0x5FD8,0x5984,0x5A01,0x8719,0x871B,0x871D,0x871F,0x8720,0x8724,0x8726,0x8727,0x8728,0x872A,0x872B,0x872C,0x872D,0x872F,0x8730,0x8732,0x8733,0x8735,0x8736,0x8738,0x8739,0x873A,0x873C,0x873D,0x8740,0x8741,0x8742,0x8743,0x8744,0x8745,0x8746,0x874A,0x874B,0x874D,0x874F,0x8750,0x8751,0x8752,0x8754,0x8755,0x8756,0x8758,0x875A,0x875B,0x875C,0x875D,0x875E,0x875F,0x8761,0x8762,0x8766,0x8767,0x8768,0x8769,0x876A,0x876B,0x876C,0x876D,0x876F,0x8771,0x8772,0x8773,0x8775,0x8777,0x8778,0x8779,0x877A,0x877F,0x8780,0x8781,0x8784,0x8786,0x8787,0x8789,0x878A,0x878C,0x878E,0x878F,0x8790,0x8791,0x8792,0x8794,0x8795,0x8796,0x8798,0x8799,0x879A,0x879B,0x879C,0x879D,0x879E,0x87A0,0x87A1,0x87A2,0x87A3,0x87A4,0x5DCD,0x5FAE,0x5371,0x97E6,0x8FDD,0x6845,0x56F4,0x552F,0x60DF,0x4E3A,0x6F4D,0x7EF4,0x82C7,0x840E,0x59D4,0x4F1F,0x4F2A,0x5C3E,0x7EAC,0x672A,0x851A,0x5473,0x754F,0x80C3,0x5582,0x9B4F,0x4F4D,0x6E2D,0x8C13,0x5C09,0x6170,0x536B,0x761F,0x6E29,0x868A,0x6587,0x95FB,0x7EB9,0x543B,0x7A33,0x7D0A,0x95EE,0x55E1,0x7FC1,0x74EE,0x631D,0x8717,0x6DA1,0x7A9D,0x6211,0x65A1,0x5367,0x63E1,0x6C83,0x5DEB,0x545C,0x94A8,0x4E4C,0x6C61,0x8BEC,0x5C4B,0x65E0,0x829C,0x68A7,0x543E,0x5434,0x6BCB,0x6B66,0x4E94,0x6342,0x5348,0x821E,0x4F0D,0x4FAE,0x575E,0x620A,0x96FE,0x6664,0x7269,0x52FF,0x52A1,0x609F,0x8BEF,0x6614,0x7199,0x6790,0x897F,0x7852,0x77FD,0x6670,0x563B,0x5438,0x9521,0x727A,0x87A5,0x87A6,0x87A7,0x87A9,0x87AA,0x87AE,0x87B0,0x87B1,0x87B2,0x87B4,0x87B6,0x87B7,0x87B8,0x87B9,0x87BB,0x87BC,0x87BE,0x87BF,0x87C1,0x87C2,0x87C3,0x87C4,0x87C5,0x87C7,0x87C8,0x87C9,0x87CC,0x87CD,0x87CE,0x87CF,0x87D0,0x87D4,0x87D5,0x87D6,0x87D7,0x87D8,0x87D9,0x87DA,0x87DC,0x87DD,0x87DE,0x87DF,0x87E1,0x87E2,0x87E3,0x87E4,0x87E6,0x87E7,0x87E8,0x87E9,0x87EB,0x87EC,0x87ED,0x87EF,0x87F0,0x87F1,0x87F2,0x87F3,0x87F4,0x87F5,0x87F6,0x87F7,0x87F8,0x87FA,0x87FB,0x87FC,0x87FD,0x87FF,0x8800,0x8801,0x8802,0x8804,0x8805,0x8806,0x8807,0x8808,0x8809,0x880B,0x880C,0x880D,0x880E,0x880F,0x8810,0x8811,0x8812,0x8814,0x8817,0x8818,0x8819,0x881A,0x881C,0x881D,0x881E,0x881F,0x8820,0x8823,0x7A00,0x606F,0x5E0C,0x6089,0x819D,0x5915,0x60DC,0x7184,0x70EF,0x6EAA,0x6C50,0x7280,0x6A84,0x88AD,0x5E2D,0x4E60,0x5AB3,0x559C,0x94E3,0x6D17,0x7CFB,0x9699,0x620F,0x7EC6,0x778E,0x867E,0x5323,0x971E,0x8F96,0x6687,0x5CE1,0x4FA0,0x72ED,0x4E0B,0x53A6,0x590F,0x5413,0x6380,0x9528,0x5148,0x4ED9,0x9C9C,0x7EA4,0x54B8,0x8D24,0x8854,0x8237,0x95F2,0x6D8E,0x5F26,0x5ACC,0x663E,0x9669,0x73B0,0x732E,0x53BF,0x817A,0x9985,0x7FA1,0x5BAA,0x9677,0x9650,0x7EBF,0x76F8,0x53A2,0x9576,0x9999,0x7BB1,0x8944,0x6E58,0x4E61,0x7FD4,0x7965,0x8BE6,0x60F3,0x54CD,0x4EAB,0x9879,0x5DF7,0x6A61,0x50CF,0x5411,0x8C61,0x8427,0x785D,0x9704,0x524A,0x54EE,0x56A3,0x9500,0x6D88,0x5BB5,0x6DC6,0x6653,0x8824,0x8825,0x8826,0x8827,0x8828,0x8829,0x882A,0x882B,0x882C,0x882D,0x882E,0x882F,0x8830,0x8831,0x8833,0x8834,0x8835,0x8836,0x8837,0x8838,0x883A,0x883B,0x883D,0x883E,0x883F,0x8841,0x8842,0x8843,0x8846,0x8847,0x8848,0x8849,0x884A,0x884B,0x884E,0x884F,0x8850,0x8851,0x8852,0x8853,0x8855,0x8856,0x8858,0x885A,0x885B,0x885C,0x885D,0x885E,0x885F,0x8860,0x8866,0x8867,0x886A,0x886D,0x886F,0x8871,0x8873,0x8874,0x8875,0x8876,0x8878,0x8879,0x887A,0x887B,0x887C,0x8880,0x8883,0x8886,0x8887,0x8889,0x888A,0x888C,0x888E,0x888F,0x8890,0x8891,0x8893,0x8894,0x8895,0x8897,0x8898,0x8899,0x889A,0x889B,0x889D,0x889E,0x889F,0x88A0,0x88A1,0x88A3,0x88A5,0x88A6,0x88A7,0x88A8,0x88A9,0x88AA,0x5C0F,0x5B5D,0x6821,0x8096,0x5578,0x7B11,0x6548,0x6954,0x4E9B,0x6B47,0x874E,0x978B,0x534F,0x631F,0x643A,0x90AA,0x659C,0x80C1,0x8C10,0x5199,0x68B0,0x5378,0x87F9,0x61C8,0x6CC4,0x6CFB,0x8C22,0x5C51,0x85AA,0x82AF,0x950C,0x6B23,0x8F9B,0x65B0,0x5FFB,0x5FC3,0x4FE1,0x8845,0x661F,0x8165,0x7329,0x60FA,0x5174,0x5211,0x578B,0x5F62,0x90A2,0x884C,0x9192,0x5E78,0x674F,0x6027,0x59D3,0x5144,0x51F6,0x80F8,0x5308,0x6C79,0x96C4,0x718A,0x4F11,0x4FEE,0x7F9E,0x673D,0x55C5,0x9508,0x79C0,0x8896,0x7EE3,0x589F,0x620C,0x9700,0x865A,0x5618,0x987B,0x5F90,0x8BB8,0x84C4,0x9157,0x53D9,0x65ED,0x5E8F,0x755C,0x6064,0x7D6E,0x5A7F,0x7EEA,0x7EED,0x8F69,0x55A7,0x5BA3,0x60AC,0x65CB,0x7384,0x88AC,0x88AE,0x88AF,0x88B0,0x88B2,0x88B3,0x88B4,0x88B5,0x88B6,0x88B8,0x88B9,0x88BA,0x88BB,0x88BD,0x88BE,0x88BF,0x88C0,0x88C3,0x88C4,0x88C7,0x88C8,0x88CA,0x88CB,0x88CC,0x88CD,0x88CF,0x88D0,0x88D1,0x88D3,0x88D6,0x88D7,0x88DA,0x88DB,0x88DC,0x88DD,0x88DE,0x88E0,0x88E1,0x88E6,0x88E7,0x88E9,0x88EA,0x88EB,0x88EC,0x88ED,0x88EE,0x88EF,0x88F2,0x88F5,0x88F6,0x88F7,0x88FA,0x88FB,0x88FD,0x88FF,0x8900,0x8901,0x8903,0x8904,0x8905,0x8906,0x8907,0x8908,0x8909,0x890B,0x890C,0x890D,0x890E,0x890F,0x8911,0x8914,0x8915,0x8916,0x8917,0x8918,0x891C,0x891D,0x891E,0x891F,0x8920,0x8922,0x8923,0x8924,0x8926,0x8927,0x8928,0x8929,0x892C,0x892D,0x892E,0x892F,0x8931,0x8932,0x8933,0x8935,0x8937,0x9009,0x7663,0x7729,0x7EDA,0x9774,0x859B,0x5B66,0x7A74,0x96EA,0x8840,0x52CB,0x718F,0x5FAA,0x65EC,0x8BE2,0x5BFB,0x9A6F,0x5DE1,0x6B89,0x6C5B,0x8BAD,0x8BAF,0x900A,0x8FC5,0x538B,0x62BC,0x9E26,0x9E2D,0x5440,0x4E2B,0x82BD,0x7259,0x869C,0x5D16,0x8859,0x6DAF,0x96C5,0x54D1,0x4E9A,0x8BB6,0x7109,0x54BD,0x9609,0x70DF,0x6DF9,0x76D0,0x4E25,0x7814,0x8712,0x5CA9,0x5EF6,0x8A00,0x989C,0x960E,0x708E,0x6CBF,0x5944,0x63A9,0x773C,0x884D,0x6F14,0x8273,0x5830,0x71D5,0x538C,0x781A,0x96C1,0x5501,0x5F66,0x7130,0x5BB4,0x8C1A,0x9A8C,0x6B83,0x592E,0x9E2F,0x79E7,0x6768,0x626C,0x4F6F,0x75A1,0x7F8A,0x6D0B,0x9633,0x6C27,0x4EF0,0x75D2,0x517B,0x6837,0x6F3E,0x9080,0x8170,0x5996,0x7476,0x8938,0x8939,0x893A,0x893B,0x893C,0x893D,0x893E,0x893F,0x8940,0x8942,0x8943,0x8945,0x8946,0x8947,0x8948,0x8949,0x894A,0x894B,0x894C,0x894D,0x894E,0x894F,0x8950,0x8951,0x8952,0x8953,0x8954,0x8955,0x8956,0x8957,0x8958,0x8959,0x895A,0x895B,0x895C,0x895D,0x8960,0x8961,0x8962,0x8963,0x8964,0x8965,0x8967,0x8968,0x8969,0x896A,0x896B,0x896C,0x896D,0x896E,0x896F,0x8970,0x8971,0x8972,0x8973,0x8974,0x8975,0x8976,0x8977,0x8978,0x8979,0x897A,0x897C,0x897D,0x897E,0x8980,0x8982,0x8984,0x8985,0x8987,0x8988,0x8989,0x898A,0x898B,0x898C,0x898D,0x898E,0x898F,0x8990,0x8991,0x8992,0x8993,0x8994,0x8995,0x8996,0x8997,0x8998,0x8999,0x899A,0x899B,0x899C,0x899D,0x899E,0x899F,0x89A0,0x89A1,0x6447,0x5C27,0x9065,0x7A91,0x8C23,0x59DA,0x54AC,0x8200,0x836F,0x8981,0x8000,0x6930,0x564E,0x8036,0x7237,0x91CE,0x51B6,0x4E5F,0x9875,0x6396,0x4E1A,0x53F6,0x66F3,0x814B,0x591C,0x6DB2,0x4E00,0x58F9,0x533B,0x63D6,0x94F1,0x4F9D,0x4F0A,0x8863,0x9890,0x5937,0x9057,0x79FB,0x4EEA,0x80F0,0x7591,0x6C82,0x5B9C,0x59E8,0x5F5D,0x6905,0x8681,0x501A,0x5DF2,0x4E59,0x77E3,0x4EE5,0x827A,0x6291,0x6613,0x9091,0x5C79,0x4EBF,0x5F79,0x81C6,0x9038,0x8084,0x75AB,0x4EA6,0x88D4,0x610F,0x6BC5,0x5FC6,0x4E49,0x76CA,0x6EA2,0x8BE3,0x8BAE,0x8C0A,0x8BD1,0x5F02,0x7FFC,0x7FCC,0x7ECE,0x8335,0x836B,0x56E0,0x6BB7,0x97F3,0x9634,0x59FB,0x541F,0x94F6,0x6DEB,0x5BC5,0x996E,0x5C39,0x5F15,0x9690,0x89A2,0x89A3,0x89A4,0x89A5,0x89A6,0x89A7,0x89A8,0x89A9,0x89AA,0x89AB,0x89AC,0x89AD,0x89AE,0x89AF,0x89B0,0x89B1,0x89B2,0x89B3,0x89B4,0x89B5,0x89B6,0x89B7,0x89B8,0x89B9,0x89BA,0x89BB,0x89BC,0x89BD,0x89BE,0x89BF,0x89C0,0x89C3,0x89CD,0x89D3,0x89D4,0x89D5,0x89D7,0x89D8,0x89D9,0x89DB,0x89DD,0x89DF,0x89E0,0x89E1,0x89E2,0x89E4,0x89E7,0x89E8,0x89E9,0x89EA,0x89EC,0x89ED,0x89EE,0x89F0,0x89F1,0x89F2,0x89F4,0x89F5,0x89F6,0x89F7,0x89F8,0x89F9,0x89FA,0x89FB,0x89FC,0x89FD,0x89FE,0x89FF,0x8A01,0x8A02,0x8A03,0x8A04,0x8A05,0x8A06,0x8A08,0x8A09,0x8A0A,0x8A0B,0x8A0C,0x8A0D,0x8A0E,0x8A0F,0x8A10,0x8A11,0x8A12,0x8A13,0x8A14,0x8A15,0x8A16,0x8A17,0x8A18,0x8A19,0x8A1A,0x8A1B,0x8A1C,0x8A1D,0x5370,0x82F1,0x6A31,0x5A74,0x9E70,0x5E94,0x7F28,0x83B9,0x8424,0x8425,0x8367,0x8747,0x8FCE,0x8D62,0x76C8,0x5F71,0x9896,0x786C,0x6620,0x54DF,0x62E5,0x4F63,0x81C3,0x75C8,0x5EB8,0x96CD,0x8E0A,0x86F9,0x548F,0x6CF3,0x6D8C,0x6C38,0x607F,0x52C7,0x7528,0x5E7D,0x4F18,0x60A0,0x5FE7,0x5C24,0x7531,0x90AE,0x94C0,0x72B9,0x6CB9,0x6E38,0x9149,0x6709,0x53CB,0x53F3,0x4F51,0x91C9,0x8BF1,0x53C8,0x5E7C,0x8FC2,0x6DE4,0x4E8E,0x76C2,0x6986,0x865E,0x611A,0x8206,0x4F59,0x4FDE,0x903E,0x9C7C,0x6109,0x6E1D,0x6E14,0x9685,0x4E88,0x5A31,0x96E8,0x4E0E,0x5C7F,0x79B9,0x5B87,0x8BED,0x7FBD,0x7389,0x57DF,0x828B,0x90C1,0x5401,0x9047,0x55BB,0x5CEA,0x5FA1,0x6108,0x6B32,0x72F1,0x80B2,0x8A89,0x8A1E,0x8A1F,0x8A20,0x8A21,0x8A22,0x8A23,0x8A24,0x8A25,0x8A26,0x8A27,0x8A28,0x8A29,0x8A2A,0x8A2B,0x8A2C,0x8A2D,0x8A2E,0x8A2F,0x8A30,0x8A31,0x8A32,0x8A33,0x8A34,0x8A35,0x8A36,0x8A37,0x8A38,0x8A39,0x8A3A,0x8A3B,0x8A3C,0x8A3D,0x8A3F,0x8A40,0x8A41,0x8A42,0x8A43,0x8A44,0x8A45,0x8A46,0x8A47,0x8A49,0x8A4A,0x8A4B,0x8A4C,0x8A4D,0x8A4E,0x8A4F,0x8A50,0x8A51,0x8A52,0x8A53,0x8A54,0x8A55,0x8A56,0x8A57,0x8A58,0x8A59,0x8A5A,0x8A5B,0x8A5C,0x8A5D,0x8A5E,0x8A5F,0x8A60,0x8A61,0x8A62,0x8A63,0x8A64,0x8A65,0x8A66,0x8A67,0x8A68,0x8A69,0x8A6A,0x8A6B,0x8A6C,0x8A6D,0x8A6E,0x8A6F,0x8A70,0x8A71,0x8A72,0x8A73,0x8A74,0x8A75,0x8A76,0x8A77,0x8A78,0x8A7A,0x8A7B,0x8A7C,0x8A7D,0x8A7E,0x8A7F,0x8A80,0x6D74,0x5BD3,0x88D5,0x9884,0x8C6B,0x9A6D,0x9E33,0x6E0A,0x51A4,0x5143,0x57A3,0x8881,0x539F,0x63F4,0x8F95,0x56ED,0x5458,0x5706,0x733F,0x6E90,0x7F18,0x8FDC,0x82D1,0x613F,0x6028,0x9662,0x66F0,0x7EA6,0x8D8A,0x8DC3,0x94A5,0x5CB3,0x7CA4,0x6708,0x60A6,0x9605,0x8018,0x4E91,0x90E7,0x5300,0x9668,0x5141,0x8FD0,0x8574,0x915D,0x6655,0x97F5,0x5B55,0x531D,0x7838,0x6742,0x683D,0x54C9,0x707E,0x5BB0,0x8F7D,0x518D,0x5728,0x54B1,0x6512,0x6682,0x8D5E,0x8D43,0x810F,0x846C,0x906D,0x7CDF,0x51FF,0x85FB,0x67A3,0x65E9,0x6FA1,0x86A4,0x8E81,0x566A,0x9020,0x7682,0x7076,0x71E5,0x8D23,0x62E9,0x5219,0x6CFD,0x8D3C,0x600E,0x589E,0x618E,0x66FE,0x8D60,0x624E,0x55B3,0x6E23,0x672D,0x8F67,0x8A81,0x8A82,0x8A83,0x8A84,0x8A85,0x8A86,0x8A87,0x8A88,0x8A8B,0x8A8C,0x8A8D,0x8A8E,0x8A8F,0x8A90,0x8A91,0x8A92,0x8A94,0x8A95,0x8A96,0x8A97,0x8A98,0x8A99,0x8A9A,0x8A9B,0x8A9C,0x8A9D,0x8A9E,0x8A9F,0x8AA0,0x8AA1,0x8AA2,0x8AA3,0x8AA4,0x8AA5,0x8AA6,0x8AA7,0x8AA8,0x8AA9,0x8AAA,0x8AAB,0x8AAC,0x8AAD,0x8AAE,0x8AAF,0x8AB0,0x8AB1,0x8AB2,0x8AB3,0x8AB4,0x8AB5,0x8AB6,0x8AB7,0x8AB8,0x8AB9,0x8ABA,0x8ABB,0x8ABC,0x8ABD,0x8ABE,0x8ABF,0x8AC0,0x8AC1,0x8AC2,0x8AC3,0x8AC4,0x8AC5,0x8AC6,0x8AC7,0x8AC8,0x8AC9,0x8ACA,0x8ACB,0x8ACC,0x8ACD,0x8ACE,0x8ACF,0x8AD0,0x8AD1,0x8AD2,0x8AD3,0x8AD4,0x8AD5,0x8AD6,0x8AD7,0x8AD8,0x8AD9,0x8ADA,0x8ADB,0x8ADC,0x8ADD,0x8ADE,0x8ADF,0x8AE0,0x8AE1,0x8AE2,0x8AE3,0x94E1,0x95F8,0x7728,0x6805,0x69A8,0x548B,0x4E4D,0x70B8,0x8BC8,0x6458,0x658B,0x5B85,0x7A84,0x503A,0x5BE8,0x77BB,0x6BE1,0x8A79,0x7C98,0x6CBE,0x76CF,0x65A9,0x8F97,0x5D2D,0x5C55,0x8638,0x6808,0x5360,0x6218,0x7AD9,0x6E5B,0x7EFD,0x6A1F,0x7AE0,0x5F70,0x6F33,0x5F20,0x638C,0x6DA8,0x6756,0x4E08,0x5E10,0x8D26,0x4ED7,0x80C0,0x7634,0x969C,0x62DB,0x662D,0x627E,0x6CBC,0x8D75,0x7167,0x7F69,0x5146,0x8087,0x53EC,0x906E,0x6298,0x54F2,0x86F0,0x8F99,0x8005,0x9517,0x8517,0x8FD9,0x6D59,0x73CD,0x659F,0x771F,0x7504,0x7827,0x81FB,0x8D1E,0x9488,0x4FA6,0x6795,0x75B9,0x8BCA,0x9707,0x632F,0x9547,0x9635,0x84B8,0x6323,0x7741,0x5F81,0x72F0,0x4E89,0x6014,0x6574,0x62EF,0x6B63,0x653F,0x8AE4,0x8AE5,0x8AE6,0x8AE7,0x8AE8,0x8AE9,0x8AEA,0x8AEB,0x8AEC,0x8AED,0x8AEE,0x8AEF,0x8AF0,0x8AF1,0x8AF2,0x8AF3,0x8AF4,0x8AF5,0x8AF6,0x8AF7,0x8AF8,0x8AF9,0x8AFA,0x8AFB,0x8AFC,0x8AFD,0x8AFE,0x8AFF,0x8B00,0x8B01,0x8B02,0x8B03,0x8B04,0x8B05,0x8B06,0x8B08,0x8B09,0x8B0A,0x8B0B,0x8B0C,0x8B0D,0x8B0E,0x8B0F,0x8B10,0x8B11,0x8B12,0x8B13,0x8B14,0x8B15,0x8B16,0x8B17,0x8B18,0x8B19,0x8B1A,0x8B1B,0x8B1C,0x8B1D,0x8B1E,0x8B1F,0x8B20,0x8B21,0x8B22,0x8B23,0x8B24,0x8B25,0x8B27,0x8B28,0x8B29,0x8B2A,0x8B2B,0x8B2C,0x8B2D,0x8B2E,0x8B2F,0x8B30,0x8B31,0x8B32,0x8B33,0x8B34,0x8B35,0x8B36,0x8B37,0x8B38,0x8B39,0x8B3A,0x8B3B,0x8B3C,0x8B3D,0x8B3E,0x8B3F,0x8B40,0x8B41,0x8B42,0x8B43,0x8B44,0x8B45,0x5E27,0x75C7,0x90D1,0x8BC1,0x829D,0x679D,0x652F,0x5431,0x8718,0x77E5,0x80A2,0x8102,0x6C41,0x4E4B,0x7EC7,0x804C,0x76F4,0x690D,0x6B96,0x6267,0x503C,0x4F84,0x5740,0x6307,0x6B62,0x8DBE,0x53EA,0x65E8,0x7EB8,0x5FD7,0x631A,0x63B7,0x81F3,0x81F4,0x7F6E,0x5E1C,0x5CD9,0x5236,0x667A,0x79E9,0x7A1A,0x8D28,0x7099,0x75D4,0x6EDE,0x6CBB,0x7A92,0x4E2D,0x76C5,0x5FE0,0x949F,0x8877,0x7EC8,0x79CD,0x80BF,0x91CD,0x4EF2,0x4F17,0x821F,0x5468,0x5DDE,0x6D32,0x8BCC,0x7CA5,0x8F74,0x8098,0x5E1A,0x5492,0x76B1,0x5B99,0x663C,0x9AA4,0x73E0,0x682A,0x86DB,0x6731,0x732A,0x8BF8,0x8BDB,0x9010,0x7AF9,0x70DB,0x716E,0x62C4,0x77A9,0x5631,0x4E3B,0x8457,0x67F1,0x52A9,0x86C0,0x8D2E,0x94F8,0x7B51,0x8B46,0x8B47,0x8B48,0x8B49,0x8B4A,0x8B4B,0x8B4C,0x8B4D,0x8B4E,0x8B4F,0x8B50,0x8B51,0x8B52,0x8B53,0x8B54,0x8B55,0x8B56,0x8B57,0x8B58,0x8B59,0x8B5A,0x8B5B,0x8B5C,0x8B5D,0x8B5E,0x8B5F,0x8B60,0x8B61,0x8B62,0x8B63,0x8B64,0x8B65,0x8B67,0x8B68,0x8B69,0x8B6A,0x8B6B,0x8B6D,0x8B6E,0x8B6F,0x8B70,0x8B71,0x8B72,0x8B73,0x8B74,0x8B75,0x8B76,0x8B77,0x8B78,0x8B79,0x8B7A,0x8B7B,0x8B7C,0x8B7D,0x8B7E,0x8B7F,0x8B80,0x8B81,0x8B82,0x8B83,0x8B84,0x8B85,0x8B86,0x8B87,0x8B88,0x8B89,0x8B8A,0x8B8B,0x8B8C,0x8B8D,0x8B8E,0x8B8F,0x8B90,0x8B91,0x8B92,0x8B93,0x8B94,0x8B95,0x8B96,0x8B97,0x8B98,0x8B99,0x8B9A,0x8B9B,0x8B9C,0x8B9D,0x8B9E,0x8B9F,0x8BAC,0x8BB1,0x8BBB,0x8BC7,0x8BD0,0x8BEA,0x8C09,0x8C1E,0x4F4F,0x6CE8,0x795D,0x9A7B,0x6293,0x722A,0x62FD,0x4E13,0x7816,0x8F6C,0x64B0,0x8D5A,0x7BC6,0x6869,0x5E84,0x88C5,0x5986,0x649E,0x58EE,0x72B6,0x690E,0x9525,0x8FFD,0x8D58,0x5760,0x7F00,0x8C06,0x51C6,0x6349,0x62D9,0x5353,0x684C,0x7422,0x8301,0x914C,0x5544,0x7740,0x707C,0x6D4A,0x5179,0x54A8,0x8D44,0x59FF,0x6ECB,0x6DC4,0x5B5C,0x7D2B,0x4ED4,0x7C7D,0x6ED3,0x5B50,0x81EA,0x6E0D,0x5B57,0x9B03,0x68D5,0x8E2A,0x5B97,0x7EFC,0x603B,0x7EB5,0x90B9,0x8D70,0x594F,0x63CD,0x79DF,0x8DB3,0x5352,0x65CF,0x7956,0x8BC5,0x963B,0x7EC4,0x94BB,0x7E82,0x5634,0x9189,0x6700,0x7F6A,0x5C0A,0x9075,0x6628,0x5DE6,0x4F50,0x67DE,0x505A,0x4F5C,0x5750,0x5EA7,0xE810,0xE811,0xE812,0xE813,0xE814,0x8C38,0x8C39,0x8C3A,0x8C3B,0x8C3C,0x8C3D,0x8C3E,0x8C3F,0x8C40,0x8C42,0x8C43,0x8C44,0x8C45,0x8C48,0x8C4A,0x8C4B,0x8C4D,0x8C4E,0x8C4F,0x8C50,0x8C51,0x8C52,0x8C53,0x8C54,0x8C56,0x8C57,0x8C58,0x8C59,0x8C5B,0x8C5C,0x8C5D,0x8C5E,0x8C5F,0x8C60,0x8C63,0x8C64,0x8C65,0x8C66,0x8C67,0x8C68,0x8C69,0x8C6C,0x8C6D,0x8C6E,0x8C6F,0x8C70,0x8C71,0x8C72,0x8C74,0x8C75,0x8C76,0x8C77,0x8C7B,0x8C7C,0x8C7D,0x8C7E,0x8C7F,0x8C80,0x8C81,0x8C83,0x8C84,0x8C86,0x8C87,0x8C88,0x8C8B,0x8C8D,0x8C8E,0x8C8F,0x8C90,0x8C91,0x8C92,0x8C93,0x8C95,0x8C96,0x8C97,0x8C99,0x8C9A,0x8C9B,0x8C9C,0x8C9D,0x8C9E,0x8C9F,0x8CA0,0x8CA1,0x8CA2,0x8CA3,0x8CA4,0x8CA5,0x8CA6,0x8CA7,0x8CA8,0x8CA9,0x8CAA,0x8CAB,0x8CAC,0x8CAD,0x4E8D,0x4E0C,0x5140,0x4E10,0x5EFF,0x5345,0x4E15,0x4E98,0x4E1E,0x9B32,0x5B6C,0x5669,0x4E28,0x79BA,0x4E3F,0x5315,0x4E47,0x592D,0x723B,0x536E,0x6C10,0x56DF,0x80E4,0x9997,0x6BD3,0x777E,0x9F17,0x4E36,0x4E9F,0x9F10,0x4E5C,0x4E69,0x4E93,0x8288,0x5B5B,0x556C,0x560F,0x4EC4,0x538D,0x539D,0x53A3,0x53A5,0x53AE,0x9765,0x8D5D,0x531A,0x53F5,0x5326,0x532E,0x533E,0x8D5C,0x5366,0x5363,0x5202,0x5208,0x520E,0x522D,0x5233,0x523F,0x5240,0x524C,0x525E,0x5261,0x525C,0x84AF,0x527D,0x5282,0x5281,0x5290,0x5293,0x5182,0x7F54,0x4EBB,0x4EC3,0x4EC9,0x4EC2,0x4EE8,0x4EE1,0x4EEB,0x4EDE,0x4F1B,0x4EF3,0x4F22,0x4F64,0x4EF5,0x4F25,0x4F27,0x4F09,0x4F2B,0x4F5E,0x4F67,0x6538,0x4F5A,0x4F5D,0x8CAE,0x8CAF,0x8CB0,0x8CB1,0x8CB2,0x8CB3,0x8CB4,0x8CB5,0x8CB6,0x8CB7,0x8CB8,0x8CB9,0x8CBA,0x8CBB,0x8CBC,0x8CBD,0x8CBE,0x8CBF,0x8CC0,0x8CC1,0x8CC2,0x8CC3,0x8CC4,0x8CC5,0x8CC6,0x8CC7,0x8CC8,0x8CC9,0x8CCA,0x8CCB,0x8CCC,0x8CCD,0x8CCE,0x8CCF,0x8CD0,0x8CD1,0x8CD2,0x8CD3,0x8CD4,0x8CD5,0x8CD6,0x8CD7,0x8CD8,0x8CD9,0x8CDA,0x8CDB,0x8CDC,0x8CDD,0x8CDE,0x8CDF,0x8CE0,0x8CE1,0x8CE2,0x8CE3,0x8CE4,0x8CE5,0x8CE6,0x8CE7,0x8CE8,0x8CE9,0x8CEA,0x8CEB,0x8CEC,0x8CED,0x8CEE,0x8CEF,0x8CF0,0x8CF1,0x8CF2,0x8CF3,0x8CF4,0x8CF5,0x8CF6,0x8CF7,0x8CF8,0x8CF9,0x8CFA,0x8CFB,0x8CFC,0x8CFD,0x8CFE,0x8CFF,0x8D00,0x8D01,0x8D02,0x8D03,0x8D04,0x8D05,0x8D06,0x8D07,0x8D08,0x8D09,0x8D0A,0x8D0B,0x8D0C,0x8D0D,0x4F5F,0x4F57,0x4F32,0x4F3D,0x4F76,0x4F74,0x4F91,0x4F89,0x4F83,0x4F8F,0x4F7E,0x4F7B,0x4FAA,0x4F7C,0x4FAC,0x4F94,0x4FE6,0x4FE8,0x4FEA,0x4FC5,0x4FDA,0x4FE3,0x4FDC,0x4FD1,0x4FDF,0x4FF8,0x5029,0x504C,0x4FF3,0x502C,0x500F,0x502E,0x502D,0x4FFE,0x501C,0x500C,0x5025,0x5028,0x507E,0x5043,0x5055,0x5048,0x504E,0x506C,0x507B,0x50A5,0x50A7,0x50A9,0x50BA,0x50D6,0x5106,0x50ED,0x50EC,0x50E6,0x50EE,0x5107,0x510B,0x4EDD,0x6C3D,0x4F58,0x4F65,0x4FCE,0x9FA0,0x6C46,0x7C74,0x516E,0x5DFD,0x9EC9,0x9998,0x5181,0x5914,0x52F9,0x530D,0x8A07,0x5310,0x51EB,0x5919,0x5155,0x4EA0,0x5156,0x4EB3,0x886E,0x88A4,0x4EB5,0x8114,0x88D2,0x7980,0x5B34,0x8803,0x7FB8,0x51AB,0x51B1,0x51BD,0x51BC,0x8D0E,0x8D0F,0x8D10,0x8D11,0x8D12,0x8D13,0x8D14,0x8D15,0x8D16,0x8D17,0x8D18,0x8D19,0x8D1A,0x8D1B,0x8D1C,0x8D20,0x8D51,0x8D52,0x8D57,0x8D5F,0x8D65,0x8D68,0x8D69,0x8D6A,0x8D6C,0x8D6E,0x8D6F,0x8D71,0x8D72,0x8D78,0x8D79,0x8D7A,0x8D7B,0x8D7C,0x8D7D,0x8D7E,0x8D7F,0x8D80,0x8D82,0x8D83,0x8D86,0x8D87,0x8D88,0x8D89,0x8D8C,0x8D8D,0x8D8E,0x8D8F,0x8D90,0x8D92,0x8D93,0x8D95,0x8D96,0x8D97,0x8D98,0x8D99,0x8D9A,0x8D9B,0x8D9C,0x8D9D,0x8D9E,0x8DA0,0x8DA1,0x8DA2,0x8DA4,0x8DA5,0x8DA6,0x8DA7,0x8DA8,0x8DA9,0x8DAA,0x8DAB,0x8DAC,0x8DAD,0x8DAE,0x8DAF,0x8DB0,0x8DB2,0x8DB6,0x8DB7,0x8DB9,0x8DBB,0x8DBD,0x8DC0,0x8DC1,0x8DC2,0x8DC5,0x8DC7,0x8DC8,0x8DC9,0x8DCA,0x8DCD,0x8DD0,0x8DD2,0x8DD3,0x8DD4,0x51C7,0x5196,0x51A2,0x51A5,0x8BA0,0x8BA6,0x8BA7,0x8BAA,0x8BB4,0x8BB5,0x8BB7,0x8BC2,0x8BC3,0x8BCB,0x8BCF,0x8BCE,0x8BD2,0x8BD3,0x8BD4,0x8BD6,0x8BD8,0x8BD9,0x8BDC,0x8BDF,0x8BE0,0x8BE4,0x8BE8,0x8BE9,0x8BEE,0x8BF0,0x8BF3,0x8BF6,0x8BF9,0x8BFC,0x8BFF,0x8C00,0x8C02,0x8C04,0x8C07,0x8C0C,0x8C0F,0x8C11,0x8C12,0x8C14,0x8C15,0x8C16,0x8C19,0x8C1B,0x8C18,0x8C1D,0x8C1F,0x8C20,0x8C21,0x8C25,0x8C27,0x8C2A,0x8C2B,0x8C2E,0x8C2F,0x8C32,0x8C33,0x8C35,0x8C36,0x5369,0x537A,0x961D,0x9622,0x9621,0x9631,0x962A,0x963D,0x963C,0x9642,0x9649,0x9654,0x965F,0x9667,0x966C,0x9672,0x9674,0x9688,0x968D,0x9697,0x96B0,0x9097,0x909B,0x909D,0x9099,0x90AC,0x90A1,0x90B4,0x90B3,0x90B6,0x90BA,0x8DD5,0x8DD8,0x8DD9,0x8DDC,0x8DE0,0x8DE1,0x8DE2,0x8DE5,0x8DE6,0x8DE7,0x8DE9,0x8DED,0x8DEE,0x8DF0,0x8DF1,0x8DF2,0x8DF4,0x8DF6,0x8DFC,0x8DFE,0x8DFF,0x8E00,0x8E01,0x8E02,0x8E03,0x8E04,0x8E06,0x8E07,0x8E08,0x8E0B,0x8E0D,0x8E0E,0x8E10,0x8E11,0x8E12,0x8E13,0x8E15,0x8E16,0x8E17,0x8E18,0x8E19,0x8E1A,0x8E1B,0x8E1C,0x8E20,0x8E21,0x8E24,0x8E25,0x8E26,0x8E27,0x8E28,0x8E2B,0x8E2D,0x8E30,0x8E32,0x8E33,0x8E34,0x8E36,0x8E37,0x8E38,0x8E3B,0x8E3C,0x8E3E,0x8E3F,0x8E43,0x8E45,0x8E46,0x8E4C,0x8E4D,0x8E4E,0x8E4F,0x8E50,0x8E53,0x8E54,0x8E55,0x8E56,0x8E57,0x8E58,0x8E5A,0x8E5B,0x8E5C,0x8E5D,0x8E5E,0x8E5F,0x8E60,0x8E61,0x8E62,0x8E63,0x8E64,0x8E65,0x8E67,0x8E68,0x8E6A,0x8E6B,0x8E6E,0x8E71,0x90B8,0x90B0,0x90CF,0x90C5,0x90BE,0x90D0,0x90C4,0x90C7,0x90D3,0x90E6,0x90E2,0x90DC,0x90D7,0x90DB,0x90EB,0x90EF,0x90FE,0x9104,0x9122,0x911E,0x9123,0x9131,0x912F,0x9139,0x9143,0x9146,0x520D,0x5942,0x52A2,0x52AC,0x52AD,0x52BE,0x54FF,0x52D0,0x52D6,0x52F0,0x53DF,0x71EE,0x77CD,0x5EF4,0x51F5,0x51FC,0x9B2F,0x53B6,0x5F01,0x755A,0x5DEF,0x574C,0x57A9,0x57A1,0x587E,0x58BC,0x58C5,0x58D1,0x5729,0x572C,0x572A,0x5733,0x5739,0x572E,0x572F,0x575C,0x573B,0x5742,0x5769,0x5785,0x576B,0x5786,0x577C,0x577B,0x5768,0x576D,0x5776,0x5773,0x57AD,0x57A4,0x578C,0x57B2,0x57CF,0x57A7,0x57B4,0x5793,0x57A0,0x57D5,0x57D8,0x57DA,0x57D9,0x57D2,0x57B8,0x57F4,0x57EF,0x57F8,0x57E4,0x57DD,0x8E73,0x8E75,0x8E77,0x8E78,0x8E79,0x8E7A,0x8E7B,0x8E7D,0x8E7E,0x8E80,0x8E82,0x8E83,0x8E84,0x8E86,0x8E88,0x8E89,0x8E8A,0x8E8B,0x8E8C,0x8E8D,0x8E8E,0x8E91,0x8E92,0x8E93,0x8E95,0x8E96,0x8E97,0x8E98,0x8E99,0x8E9A,0x8E9B,0x8E9D,0x8E9F,0x8EA0,0x8EA1,0x8EA2,0x8EA3,0x8EA4,0x8EA5,0x8EA6,0x8EA7,0x8EA8,0x8EA9,0x8EAA,0x8EAD,0x8EAE,0x8EB0,0x8EB1,0x8EB3,0x8EB4,0x8EB5,0x8EB6,0x8EB7,0x8EB8,0x8EB9,0x8EBB,0x8EBC,0x8EBD,0x8EBE,0x8EBF,0x8EC0,0x8EC1,0x8EC2,0x8EC3,0x8EC4,0x8EC5,0x8EC6,0x8EC7,0x8EC8,0x8EC9,0x8ECA,0x8ECB,0x8ECC,0x8ECD,0x8ECF,0x8ED0,0x8ED1,0x8ED2,0x8ED3,0x8ED4,0x8ED5,0x8ED6,0x8ED7,0x8ED8,0x8ED9,0x8EDA,0x8EDB,0x8EDC,0x8EDD,0x8EDE,0x8EDF,0x8EE0,0x8EE1,0x8EE2,0x8EE3,0x8EE4,0x580B,0x580D,0x57FD,0x57ED,0x5800,0x581E,0x5819,0x5844,0x5820,0x5865,0x586C,0x5881,0x5889,0x589A,0x5880,0x99A8,0x9F19,0x61FF,0x8279,0x827D,0x827F,0x828F,0x828A,0x82A8,0x8284,0x828E,0x8291,0x8297,0x8299,0x82AB,0x82B8,0x82BE,0x82B0,0x82C8,0x82CA,0x82E3,0x8298,0x82B7,0x82AE,0x82CB,0x82CC,0x82C1,0x82A9,0x82B4,0x82A1,0x82AA,0x829F,0x82C4,0x82CE,0x82A4,0x82E1,0x8309,0x82F7,0x82E4,0x830F,0x8307,0x82DC,0x82F4,0x82D2,0x82D8,0x830C,0x82FB,0x82D3,0x8311,0x831A,0x8306,0x8314,0x8315,0x82E0,0x82D5,0x831C,0x8351,0x835B,0x835C,0x8308,0x8392,0x833C,0x8334,0x8331,0x839B,0x835E,0x832F,0x834F,0x8347,0x8343,0x835F,0x8340,0x8317,0x8360,0x832D,0x833A,0x8333,0x8366,0x8365,0x8EE5,0x8EE6,0x8EE7,0x8EE8,0x8EE9,0x8EEA,0x8EEB,0x8EEC,0x8EED,0x8EEE,0x8EEF,0x8EF0,0x8EF1,0x8EF2,0x8EF3,0x8EF4,0x8EF5,0x8EF6,0x8EF7,0x8EF8,0x8EF9,0x8EFA,0x8EFB,0x8EFC,0x8EFD,0x8EFE,0x8EFF,0x8F00,0x8F01,0x8F02,0x8F03,0x8F04,0x8F05,0x8F06,0x8F07,0x8F08,0x8F09,0x8F0A,0x8F0B,0x8F0C,0x8F0D,0x8F0E,0x8F0F,0x8F10,0x8F11,0x8F12,0x8F13,0x8F14,0x8F15,0x8F16,0x8F17,0x8F18,0x8F19,0x8F1A,0x8F1B,0x8F1C,0x8F1D,0x8F1E,0x8F1F,0x8F20,0x8F21,0x8F22,0x8F23,0x8F24,0x8F25,0x8F26,0x8F27,0x8F28,0x8F29,0x8F2A,0x8F2B,0x8F2C,0x8F2D,0x8F2E,0x8F2F,0x8F30,0x8F31,0x8F32,0x8F33,0x8F34,0x8F35,0x8F36,0x8F37,0x8F38,0x8F39,0x8F3A,0x8F3B,0x8F3C,0x8F3D,0x8F3E,0x8F3F,0x8F40,0x8F41,0x8F42,0x8F43,0x8F44,0x8368,0x831B,0x8369,0x836C,0x836A,0x836D,0x836E,0x83B0,0x8378,0x83B3,0x83B4,0x83A0,0x83AA,0x8393,0x839C,0x8385,0x837C,0x83B6,0x83A9,0x837D,0x83B8,0x837B,0x8398,0x839E,0x83A8,0x83BA,0x83BC,0x83C1,0x8401,0x83E5,0x83D8,0x5807,0x8418,0x840B,0x83DD,0x83FD,0x83D6,0x841C,0x8438,0x8411,0x8406,0x83D4,0x83DF,0x840F,0x8403,0x83F8,0x83F9,0x83EA,0x83C5,0x83C0,0x8426,0x83F0,0x83E1,0x845C,0x8451,0x845A,0x8459,0x8473,0x8487,0x8488,0x847A,0x8489,0x8478,0x843C,0x8446,0x8469,0x8476,0x848C,0x848E,0x8431,0x846D,0x84C1,0x84CD,0x84D0,0x84E6,0x84BD,0x84D3,0x84CA,0x84BF,0x84BA,0x84E0,0x84A1,0x84B9,0x84B4,0x8497,0x84E5,0x84E3,0x850C,0x750D,0x8538,0x84F0,0x8539,0x851F,0x853A,0x8F45,0x8F46,0x8F47,0x8F48,0x8F49,0x8F4A,0x8F4B,0x8F4C,0x8F4D,0x8F4E,0x8F4F,0x8F50,0x8F51,0x8F52,0x8F53,0x8F54,0x8F55,0x8F56,0x8F57,0x8F58,0x8F59,0x8F5A,0x8F5B,0x8F5C,0x8F5D,0x8F5E,0x8F5F,0x8F60,0x8F61,0x8F62,0x8F63,0x8F64,0x8F65,0x8F6A,0x8F80,0x8F8C,0x8F92,0x8F9D,0x8FA0,0x8FA1,0x8FA2,0x8FA4,0x8FA5,0x8FA6,0x8FA7,0x8FAA,0x8FAC,0x8FAD,0x8FAE,0x8FAF,0x8FB2,0x8FB3,0x8FB4,0x8FB5,0x8FB7,0x8FB8,0x8FBA,0x8FBB,0x8FBC,0x8FBF,0x8FC0,0x8FC3,0x8FC6,0x8FC9,0x8FCA,0x8FCB,0x8FCC,0x8FCD,0x8FCF,0x8FD2,0x8FD6,0x8FD7,0x8FDA,0x8FE0,0x8FE1,0x8FE3,0x8FE7,0x8FEC,0x8FEF,0x8FF1,0x8FF2,0x8FF4,0x8FF5,0x8FF6,0x8FFA,0x8FFB,0x8FFC,0x8FFE,0x8FFF,0x9007,0x9008,0x900C,0x900E,0x9013,0x9015,0x9018,0x8556,0x853B,0x84FF,0x84FC,0x8559,0x8548,0x8568,0x8564,0x855E,0x857A,0x77A2,0x8543,0x8572,0x857B,0x85A4,0x85A8,0x8587,0x858F,0x8579,0x85AE,0x859C,0x8585,0x85B9,0x85B7,0x85B0,0x85D3,0x85C1,0x85DC,0x85FF,0x8627,0x8605,0x8629,0x8616,0x863C,0x5EFE,0x5F08,0x593C,0x5941,0x8037,0x5955,0x595A,0x5958,0x530F,0x5C22,0x5C25,0x5C2C,0x5C34,0x624C,0x626A,0x629F,0x62BB,0x62CA,0x62DA,0x62D7,0x62EE,0x6322,0x62F6,0x6339,0x634B,0x6343,0x63AD,0x63F6,0x6371,0x637A,0x638E,0x63B4,0x636D,0x63AC,0x638A,0x6369,0x63AE,0x63BC,0x63F2,0x63F8,0x63E0,0x63FF,0x63C4,0x63DE,0x63CE,0x6452,0x63C6,0x63BE,0x6445,0x6441,0x640B,0x641B,0x6420,0x640C,0x6426,0x6421,0x645E,0x6484,0x646D,0x6496,0x9019,0x901C,0x9023,0x9024,0x9025,0x9027,0x9028,0x9029,0x902A,0x902B,0x902C,0x9030,0x9031,0x9032,0x9033,0x9034,0x9037,0x9039,0x903A,0x903D,0x903F,0x9040,0x9043,0x9045,0x9046,0x9048,0x9049,0x904A,0x904B,0x904C,0x904E,0x9054,0x9055,0x9056,0x9059,0x905A,0x905C,0x905D,0x905E,0x905F,0x9060,0x9061,0x9064,0x9066,0x9067,0x9069,0x906A,0x906B,0x906C,0x906F,0x9070,0x9071,0x9072,0x9073,0x9076,0x9077,0x9078,0x9079,0x907A,0x907B,0x907C,0x907E,0x9081,0x9084,0x9085,0x9086,0x9087,0x9089,0x908A,0x908C,0x908D,0x908E,0x908F,0x9090,0x9092,0x9094,0x9096,0x9098,0x909A,0x909C,0x909E,0x909F,0x90A0,0x90A4,0x90A5,0x90A7,0x90A8,0x90A9,0x90AB,0x90AD,0x90B2,0x90B7,0x90BC,0x90BD,0x90BF,0x90C0,0x647A,0x64B7,0x64B8,0x6499,0x64BA,0x64C0,0x64D0,0x64D7,0x64E4,0x64E2,0x6509,0x6525,0x652E,0x5F0B,0x5FD2,0x7519,0x5F11,0x535F,0x53F1,0x53FD,0x53E9,0x53E8,0x53FB,0x5412,0x5416,0x5406,0x544B,0x5452,0x5453,0x5454,0x5456,0x5443,0x5421,0x5457,0x5459,0x5423,0x5432,0x5482,0x5494,0x5477,0x5471,0x5464,0x549A,0x549B,0x5484,0x5476,0x5466,0x549D,0x54D0,0x54AD,0x54C2,0x54B4,0x54D2,0x54A7,0x54A6,0x54D3,0x54D4,0x5472,0x54A3,0x54D5,0x54BB,0x54BF,0x54CC,0x54D9,0x54DA,0x54DC,0x54A9,0x54AA,0x54A4,0x54DD,0x54CF,0x54DE,0x551B,0x54E7,0x5520,0x54FD,0x5514,0x54F3,0x5522,0x5523,0x550F,0x5511,0x5527,0x552A,0x5567,0x558F,0x55B5,0x5549,0x556D,0x5541,0x5555,0x553F,0x5550,0x553C,0x90C2,0x90C3,0x90C6,0x90C8,0x90C9,0x90CB,0x90CC,0x90CD,0x90D2,0x90D4,0x90D5,0x90D6,0x90D8,0x90D9,0x90DA,0x90DE,0x90DF,0x90E0,0x90E3,0x90E4,0x90E5,0x90E9,0x90EA,0x90EC,0x90EE,0x90F0,0x90F1,0x90F2,0x90F3,0x90F5,0x90F6,0x90F7,0x90F9,0x90FA,0x90FB,0x90FC,0x90FF,0x9100,0x9101,0x9103,0x9105,0x9106,0x9107,0x9108,0x9109,0x910A,0x910B,0x910C,0x910D,0x910E,0x910F,0x9110,0x9111,0x9112,0x9113,0x9114,0x9115,0x9116,0x9117,0x9118,0x911A,0x911B,0x911C,0x911D,0x911F,0x9120,0x9121,0x9124,0x9125,0x9126,0x9127,0x9128,0x9129,0x912A,0x912B,0x912C,0x912D,0x912E,0x9130,0x9132,0x9133,0x9134,0x9135,0x9136,0x9137,0x9138,0x913A,0x913B,0x913C,0x913D,0x913E,0x913F,0x9140,0x9141,0x9142,0x9144,0x5537,0x5556,0x5575,0x5576,0x5577,0x5533,0x5530,0x555C,0x558B,0x55D2,0x5583,0x55B1,0x55B9,0x5588,0x5581,0x559F,0x557E,0x55D6,0x5591,0x557B,0x55DF,0x55BD,0x55BE,0x5594,0x5599,0x55EA,0x55F7,0x55C9,0x561F,0x55D1,0x55EB,0x55EC,0x55D4,0x55E6,0x55DD,0x55C4,0x55EF,0x55E5,0x55F2,0x55F3,0x55CC,0x55CD,0x55E8,0x55F5,0x55E4,0x8F94,0x561E,0x5608,0x560C,0x5601,0x5624,0x5623,0x55FE,0x5600,0x5627,0x562D,0x5658,0x5639,0x5657,0x562C,0x564D,0x5662,0x5659,0x565C,0x564C,0x5654,0x5686,0x5664,0x5671,0x566B,0x567B,0x567C,0x5685,0x5693,0x56AF,0x56D4,0x56D7,0x56DD,0x56E1,0x56F5,0x56EB,0x56F9,0x56FF,0x5704,0x570A,0x5709,0x571C,0x5E0F,0x5E19,0x5E14,0x5E11,0x5E31,0x5E3B,0x5E3C,0x9145,0x9147,0x9148,0x9151,0x9153,0x9154,0x9155,0x9156,0x9158,0x9159,0x915B,0x915C,0x915F,0x9160,0x9166,0x9167,0x9168,0x916B,0x916D,0x9173,0x917A,0x917B,0x917C,0x9180,0x9181,0x9182,0x9183,0x9184,0x9186,0x9188,0x918A,0x918E,0x918F,0x9193,0x9194,0x9195,0x9196,0x9197,0x9198,0x9199,0x919C,0x919D,0x919E,0x919F,0x91A0,0x91A1,0x91A4,0x91A5,0x91A6,0x91A7,0x91A8,0x91A9,0x91AB,0x91AC,0x91B0,0x91B1,0x91B2,0x91B3,0x91B6,0x91B7,0x91B8,0x91B9,0x91BB,0x91BC,0x91BD,0x91BE,0x91BF,0x91C0,0x91C1,0x91C2,0x91C3,0x91C4,0x91C5,0x91C6,0x91C8,0x91CB,0x91D0,0x91D2,0x91D3,0x91D4,0x91D5,0x91D6,0x91D7,0x91D8,0x91D9,0x91DA,0x91DB,0x91DD,0x91DE,0x91DF,0x91E0,0x91E1,0x91E2,0x91E3,0x91E4,0x91E5,0x5E37,0x5E44,0x5E54,0x5E5B,0x5E5E,0x5E61,0x5C8C,0x5C7A,0x5C8D,0x5C90,0x5C96,0x5C88,0x5C98,0x5C99,0x5C91,0x5C9A,0x5C9C,0x5CB5,0x5CA2,0x5CBD,0x5CAC,0x5CAB,0x5CB1,0x5CA3,0x5CC1,0x5CB7,0x5CC4,0x5CD2,0x5CE4,0x5CCB,0x5CE5,0x5D02,0x5D03,0x5D27,0x5D26,0x5D2E,0x5D24,0x5D1E,0x5D06,0x5D1B,0x5D58,0x5D3E,0x5D34,0x5D3D,0x5D6C,0x5D5B,0x5D6F,0x5D5D,0x5D6B,0x5D4B,0x5D4A,0x5D69,0x5D74,0x5D82,0x5D99,0x5D9D,0x8C73,0x5DB7,0x5DC5,0x5F73,0x5F77,0x5F82,0x5F87,0x5F89,0x5F8C,0x5F95,0x5F99,0x5F9C,0x5FA8,0x5FAD,0x5FB5,0x5FBC,0x8862,0x5F61,0x72AD,0x72B0,0x72B4,0x72B7,0x72B8,0x72C3,0x72C1,0x72CE,0x72CD,0x72D2,0x72E8,0x72EF,0x72E9,0x72F2,0x72F4,0x72F7,0x7301,0x72F3,0x7303,0x72FA,0x91E6,0x91E7,0x91E8,0x91E9,0x91EA,0x91EB,0x91EC,0x91ED,0x91EE,0x91EF,0x91F0,0x91F1,0x91F2,0x91F3,0x91F4,0x91F5,0x91F6,0x91F7,0x91F8,0x91F9,0x91FA,0x91FB,0x91FC,0x91FD,0x91FE,0x91FF,0x9200,0x9201,0x9202,0x9203,0x9204,0x9205,0x9206,0x9207,0x9208,0x9209,0x920A,0x920B,0x920C,0x920D,0x920E,0x920F,0x9210,0x9211,0x9212,0x9213,0x9214,0x9215,0x9216,0x9217,0x9218,0x9219,0x921A,0x921B,0x921C,0x921D,0x921E,0x921F,0x9220,0x9221,0x9222,0x9223,0x9224,0x9225,0x9226,0x9227,0x9228,0x9229,0x922A,0x922B,0x922C,0x922D,0x922E,0x922F,0x9230,0x9231,0x9232,0x9233,0x9234,0x9235,0x9236,0x9237,0x9238,0x9239,0x923A,0x923B,0x923C,0x923D,0x923E,0x923F,0x9240,0x9241,0x9242,0x9243,0x9244,0x9245,0x72FB,0x7317,0x7313,0x7321,0x730A,0x731E,0x731D,0x7315,0x7322,0x7339,0x7325,0x732C,0x7338,0x7331,0x7350,0x734D,0x7357,0x7360,0x736C,0x736F,0x737E,0x821B,0x5925,0x98E7,0x5924,0x5902,0x9963,0x9967,0x9968,0x9969,0x996A,0x996B,0x996C,0x9974,0x9977,0x997D,0x9980,0x9984,0x9987,0x998A,0x998D,0x9990,0x9991,0x9993,0x9994,0x9995,0x5E80,0x5E91,0x5E8B,0x5E96,0x5EA5,0x5EA0,0x5EB9,0x5EB5,0x5EBE,0x5EB3,0x8D53,0x5ED2,0x5ED1,0x5EDB,0x5EE8,0x5EEA,0x81BA,0x5FC4,0x5FC9,0x5FD6,0x5FCF,0x6003,0x5FEE,0x6004,0x5FE1,0x5FE4,0x5FFE,0x6005,0x6006,0x5FEA,0x5FED,0x5FF8,0x6019,0x6035,0x6026,0x601B,0x600F,0x600D,0x6029,0x602B,0x600A,0x603F,0x6021,0x6078,0x6079,0x607B,0x607A,0x6042,0x9246,0x9247,0x9248,0x9249,0x924A,0x924B,0x924C,0x924D,0x924E,0x924F,0x9250,0x9251,0x9252,0x9253,0x9254,0x9255,0x9256,0x9257,0x9258,0x9259,0x925A,0x925B,0x925C,0x925D,0x925E,0x925F,0x9260,0x9261,0x9262,0x9263,0x9264,0x9265,0x9266,0x9267,0x9268,0x9269,0x926A,0x926B,0x926C,0x926D,0x926E,0x926F,0x9270,0x9271,0x9272,0x9273,0x9275,0x9276,0x9277,0x9278,0x9279,0x927A,0x927B,0x927C,0x927D,0x927E,0x927F,0x9280,0x9281,0x9282,0x9283,0x9284,0x9285,0x9286,0x9287,0x9288,0x9289,0x928A,0x928B,0x928C,0x928D,0x928F,0x9290,0x9291,0x9292,0x9293,0x9294,0x9295,0x9296,0x9297,0x9298,0x9299,0x929A,0x929B,0x929C,0x929D,0x929E,0x929F,0x92A0,0x92A1,0x92A2,0x92A3,0x92A4,0x92A5,0x92A6,0x92A7,0x606A,0x607D,0x6096,0x609A,0x60AD,0x609D,0x6083,0x6092,0x608C,0x609B,0x60EC,0x60BB,0x60B1,0x60DD,0x60D8,0x60C6,0x60DA,0x60B4,0x6120,0x6126,0x6115,0x6123,0x60F4,0x6100,0x610E,0x612B,0x614A,0x6175,0x61AC,0x6194,0x61A7,0x61B7,0x61D4,0x61F5,0x5FDD,0x96B3,0x95E9,0x95EB,0x95F1,0x95F3,0x95F5,0x95F6,0x95FC,0x95FE,0x9603,0x9604,0x9606,0x9608,0x960A,0x960B,0x960C,0x960D,0x960F,0x9612,0x9615,0x9616,0x9617,0x9619,0x961A,0x4E2C,0x723F,0x6215,0x6C35,0x6C54,0x6C5C,0x6C4A,0x6CA3,0x6C85,0x6C90,0x6C94,0x6C8C,0x6C68,0x6C69,0x6C74,0x6C76,0x6C86,0x6CA9,0x6CD0,0x6CD4,0x6CAD,0x6CF7,0x6CF8,0x6CF1,0x6CD7,0x6CB2,0x6CE0,0x6CD6,0x6CFA,0x6CEB,0x6CEE,0x6CB1,0x6CD3,0x6CEF,0x6CFE,0x92A8,0x92A9,0x92AA,0x92AB,0x92AC,0x92AD,0x92AF,0x92B0,0x92B1,0x92B2,0x92B3,0x92B4,0x92B5,0x92B6,0x92B7,0x92B8,0x92B9,0x92BA,0x92BB,0x92BC,0x92BD,0x92BE,0x92BF,0x92C0,0x92C1,0x92C2,0x92C3,0x92C4,0x92C5,0x92C6,0x92C7,0x92C9,0x92CA,0x92CB,0x92CC,0x92CD,0x92CE,0x92CF,0x92D0,0x92D1,0x92D2,0x92D3,0x92D4,0x92D5,0x92D6,0x92D7,0x92D8,0x92D9,0x92DA,0x92DB,0x92DC,0x92DD,0x92DE,0x92DF,0x92E0,0x92E1,0x92E2,0x92E3,0x92E4,0x92E5,0x92E6,0x92E7,0x92E8,0x92E9,0x92EA,0x92EB,0x92EC,0x92ED,0x92EE,0x92EF,0x92F0,0x92F1,0x92F2,0x92F3,0x92F4,0x92F5,0x92F6,0x92F7,0x92F8,0x92F9,0x92FA,0x92FB,0x92FC,0x92FD,0x92FE,0x92FF,0x9300,0x9301,0x9302,0x9303,0x9304,0x9305,0x9306,0x9307,0x9308,0x9309,0x6D39,0x6D27,0x6D0C,0x6D43,0x6D48,0x6D07,0x6D04,0x6D19,0x6D0E,0x6D2B,0x6D4D,0x6D2E,0x6D35,0x6D1A,0x6D4F,0x6D52,0x6D54,0x6D33,0x6D91,0x6D6F,0x6D9E,0x6DA0,0x6D5E,0x6D93,0x6D94,0x6D5C,0x6D60,0x6D7C,0x6D63,0x6E1A,0x6DC7,0x6DC5,0x6DDE,0x6E0E,0x6DBF,0x6DE0,0x6E11,0x6DE6,0x6DDD,0x6DD9,0x6E16,0x6DAB,0x6E0C,0x6DAE,0x6E2B,0x6E6E,0x6E4E,0x6E6B,0x6EB2,0x6E5F,0x6E86,0x6E53,0x6E54,0x6E32,0x6E25,0x6E44,0x6EDF,0x6EB1,0x6E98,0x6EE0,0x6F2D,0x6EE2,0x6EA5,0x6EA7,0x6EBD,0x6EBB,0x6EB7,0x6ED7,0x6EB4,0x6ECF,0x6E8F,0x6EC2,0x6E9F,0x6F62,0x6F46,0x6F47,0x6F24,0x6F15,0x6EF9,0x6F2F,0x6F36,0x6F4B,0x6F74,0x6F2A,0x6F09,0x6F29,0x6F89,0x6F8D,0x6F8C,0x6F78,0x6F72,0x6F7C,0x6F7A,0x6FD1,0x930A,0x930B,0x930C,0x930D,0x930E,0x930F,0x9310,0x9311,0x9312,0x9313,0x9314,0x9315,0x9316,0x9317,0x9318,0x9319,0x931A,0x931B,0x931C,0x931D,0x931E,0x931F,0x9320,0x9321,0x9322,0x9323,0x9324,0x9325,0x9326,0x9327,0x9328,0x9329,0x932A,0x932B,0x932C,0x932D,0x932E,0x932F,0x9330,0x9331,0x9332,0x9333,0x9334,0x9335,0x9336,0x9337,0x9338,0x9339,0x933A,0x933B,0x933C,0x933D,0x933F,0x9340,0x9341,0x9342,0x9343,0x9344,0x9345,0x9346,0x9347,0x9348,0x9349,0x934A,0x934B,0x934C,0x934D,0x934E,0x934F,0x9350,0x9351,0x9352,0x9353,0x9354,0x9355,0x9356,0x9357,0x9358,0x9359,0x935A,0x935B,0x935C,0x935D,0x935E,0x935F,0x9360,0x9361,0x9362,0x9363,0x9364,0x9365,0x9366,0x9367,0x9368,0x9369,0x936B,0x6FC9,0x6FA7,0x6FB9,0x6FB6,0x6FC2,0x6FE1,0x6FEE,0x6FDE,0x6FE0,0x6FEF,0x701A,0x7023,0x701B,0x7039,0x7035,0x704F,0x705E,0x5B80,0x5B84,0x5B95,0x5B93,0x5BA5,0x5BB8,0x752F,0x9A9E,0x6434,0x5BE4,0x5BEE,0x8930,0x5BF0,0x8E47,0x8B07,0x8FB6,0x8FD3,0x8FD5,0x8FE5,0x8FEE,0x8FE4,0x8FE9,0x8FE6,0x8FF3,0x8FE8,0x9005,0x9004,0x900B,0x9026,0x9011,0x900D,0x9016,0x9021,0x9035,0x9036,0x902D,0x902F,0x9044,0x9051,0x9052,0x9050,0x9068,0x9058,0x9062,0x905B,0x66B9,0x9074,0x907D,0x9082,0x9088,0x9083,0x908B,0x5F50,0x5F57,0x5F56,0x5F58,0x5C3B,0x54AB,0x5C50,0x5C59,0x5B71,0x5C63,0x5C66,0x7FBC,0x5F2A,0x5F29,0x5F2D,0x8274,0x5F3C,0x9B3B,0x5C6E,0x5981,0x5983,0x598D,0x59A9,0x59AA,0x59A3,0x936C,0x936D,0x936E,0x936F,0x9370,0x9371,0x9372,0x9373,0x9374,0x9375,0x9376,0x9377,0x9378,0x9379,0x937A,0x937B,0x937C,0x937D,0x937E,0x937F,0x9380,0x9381,0x9382,0x9383,0x9384,0x9385,0x9386,0x9387,0x9388,0x9389,0x938A,0x938B,0x938C,0x938D,0x938E,0x9390,0x9391,0x9392,0x9393,0x9394,0x9395,0x9396,0x9397,0x9398,0x9399,0x939A,0x939B,0x939C,0x939D,0x939E,0x939F,0x93A0,0x93A1,0x93A2,0x93A3,0x93A4,0x93A5,0x93A6,0x93A7,0x93A8,0x93A9,0x93AA,0x93AB,0x93AC,0x93AD,0x93AE,0x93AF,0x93B0,0x93B1,0x93B2,0x93B3,0x93B4,0x93B5,0x93B6,0x93B7,0x93B8,0x93B9,0x93BA,0x93BB,0x93BC,0x93BD,0x93BE,0x93BF,0x93C0,0x93C1,0x93C2,0x93C3,0x93C4,0x93C5,0x93C6,0x93C7,0x93C8,0x93C9,0x93CB,0x93CC,0x93CD,0x5997,0x59CA,0x59AB,0x599E,0x59A4,0x59D2,0x59B2,0x59AF,0x59D7,0x59BE,0x5A05,0x5A06,0x59DD,0x5A08,0x59E3,0x59D8,0x59F9,0x5A0C,0x5A09,0x5A32,0x5A34,0x5A11,0x5A23,0x5A13,0x5A40,0x5A67,0x5A4A,0x5A55,0x5A3C,0x5A62,0x5A75,0x80EC,0x5AAA,0x5A9B,0x5A77,0x5A7A,0x5ABE,0x5AEB,0x5AB2,0x5AD2,0x5AD4,0x5AB8,0x5AE0,0x5AE3,0x5AF1,0x5AD6,0x5AE6,0x5AD8,0x5ADC,0x5B09,0x5B17,0x5B16,0x5B32,0x5B37,0x5B40,0x5C15,0x5C1C,0x5B5A,0x5B65,0x5B73,0x5B51,0x5B53,0x5B62,0x9A75,0x9A77,0x9A78,0x9A7A,0x9A7F,0x9A7D,0x9A80,0x9A81,0x9A85,0x9A88,0x9A8A,0x9A90,0x9A92,0x9A93,0x9A96,0x9A98,0x9A9B,0x9A9C,0x9A9D,0x9A9F,0x9AA0,0x9AA2,0x9AA3,0x9AA5,0x9AA7,0x7E9F,0x7EA1,0x7EA3,0x7EA5,0x7EA8,0x7EA9,0x93CE,0x93CF,0x93D0,0x93D1,0x93D2,0x93D3,0x93D4,0x93D5,0x93D7,0x93D8,0x93D9,0x93DA,0x93DB,0x93DC,0x93DD,0x93DE,0x93DF,0x93E0,0x93E1,0x93E2,0x93E3,0x93E4,0x93E5,0x93E6,0x93E7,0x93E8,0x93E9,0x93EA,0x93EB,0x93EC,0x93ED,0x93EE,0x93EF,0x93F0,0x93F1,0x93F2,0x93F3,0x93F4,0x93F5,0x93F6,0x93F7,0x93F8,0x93F9,0x93FA,0x93FB,0x93FC,0x93FD,0x93FE,0x93FF,0x9400,0x9401,0x9402,0x9403,0x9404,0x9405,0x9406,0x9407,0x9408,0x9409,0x940A,0x940B,0x940C,0x940D,0x940E,0x940F,0x9410,0x9411,0x9412,0x9413,0x9414,0x9415,0x9416,0x9417,0x9418,0x9419,0x941A,0x941B,0x941C,0x941D,0x941E,0x941F,0x9420,0x9421,0x9422,0x9423,0x9424,0x9425,0x9426,0x9427,0x9428,0x9429,0x942A,0x942B,0x942C,0x942D,0x942E,0x7EAD,0x7EB0,0x7EBE,0x7EC0,0x7EC1,0x7EC2,0x7EC9,0x7ECB,0x7ECC,0x7ED0,0x7ED4,0x7ED7,0x7EDB,0x7EE0,0x7EE1,0x7EE8,0x7EEB,0x7EEE,0x7EEF,0x7EF1,0x7EF2,0x7F0D,0x7EF6,0x7EFA,0x7EFB,0x7EFE,0x7F01,0x7F02,0x7F03,0x7F07,0x7F08,0x7F0B,0x7F0C,0x7F0F,0x7F11,0x7F12,0x7F17,0x7F19,0x7F1C,0x7F1B,0x7F1F,0x7F21,0x7F22,0x7F23,0x7F24,0x7F25,0x7F26,0x7F27,0x7F2A,0x7F2B,0x7F2C,0x7F2D,0x7F2F,0x7F30,0x7F31,0x7F32,0x7F33,0x7F35,0x5E7A,0x757F,0x5DDB,0x753E,0x9095,0x738E,0x7391,0x73AE,0x73A2,0x739F,0x73CF,0x73C2,0x73D1,0x73B7,0x73B3,0x73C0,0x73C9,0x73C8,0x73E5,0x73D9,0x987C,0x740A,0x73E9,0x73E7,0x73DE,0x73BA,0x73F2,0x740F,0x742A,0x745B,0x7426,0x7425,0x7428,0x7430,0x742E,0x742C,0x942F,0x9430,0x9431,0x9432,0x9433,0x9434,0x9435,0x9436,0x9437,0x9438,0x9439,0x943A,0x943B,0x943C,0x943D,0x943F,0x9440,0x9441,0x9442,0x9443,0x9444,0x9445,0x9446,0x9447,0x9448,0x9449,0x944A,0x944B,0x944C,0x944D,0x944E,0x944F,0x9450,0x9451,0x9452,0x9453,0x9454,0x9455,0x9456,0x9457,0x9458,0x9459,0x945A,0x945B,0x945C,0x945D,0x945E,0x945F,0x9460,0x9461,0x9462,0x9463,0x9464,0x9465,0x9466,0x9467,0x9468,0x9469,0x946A,0x946C,0x946D,0x946E,0x946F,0x9470,0x9471,0x9472,0x9473,0x9474,0x9475,0x9476,0x9477,0x9478,0x9479,0x947A,0x947B,0x947C,0x947D,0x947E,0x947F,0x9480,0x9481,0x9482,0x9483,0x9484,0x9491,0x9496,0x9498,0x94C7,0x94CF,0x94D3,0x94D4,0x94DA,0x94E6,0x94FB,0x951C,0x9520,0x741B,0x741A,0x7441,0x745C,0x7457,0x7455,0x7459,0x7477,0x746D,0x747E,0x749C,0x748E,0x7480,0x7481,0x7487,0x748B,0x749E,0x74A8,0x74A9,0x7490,0x74A7,0x74D2,0x74BA,0x97EA,0x97EB,0x97EC,0x674C,0x6753,0x675E,0x6748,0x6769,0x67A5,0x6787,0x676A,0x6773,0x6798,0x67A7,0x6775,0x67A8,0x679E,0x67AD,0x678B,0x6777,0x677C,0x67F0,0x6809,0x67D8,0x680A,0x67E9,0x67B0,0x680C,0x67D9,0x67B5,0x67DA,0x67B3,0x67DD,0x6800,0x67C3,0x67B8,0x67E2,0x680E,0x67C1,0x67FD,0x6832,0x6833,0x6860,0x6861,0x684E,0x6862,0x6844,0x6864,0x6883,0x681D,0x6855,0x6866,0x6841,0x6867,0x6840,0x683E,0x684A,0x6849,0x6829,0x68B5,0x688F,0x6874,0x6877,0x6893,0x686B,0x68C2,0x696E,0x68FC,0x691F,0x6920,0x68F9,0x9527,0x9533,0x953D,0x9543,0x9548,0x954B,0x9555,0x955A,0x9560,0x956E,0x9574,0x9575,0x9577,0x9578,0x9579,0x957A,0x957B,0x957C,0x957D,0x957E,0x9580,0x9581,0x9582,0x9583,0x9584,0x9585,0x9586,0x9587,0x9588,0x9589,0x958A,0x958B,0x958C,0x958D,0x958E,0x958F,0x9590,0x9591,0x9592,0x9593,0x9594,0x9595,0x9596,0x9597,0x9598,0x9599,0x959A,0x959B,0x959C,0x959D,0x959E,0x959F,0x95A0,0x95A1,0x95A2,0x95A3,0x95A4,0x95A5,0x95A6,0x95A7,0x95A8,0x95A9,0x95AA,0x95AB,0x95AC,0x95AD,0x95AE,0x95AF,0x95B0,0x95B1,0x95B2,0x95B3,0x95B4,0x95B5,0x95B6,0x95B7,0x95B8,0x95B9,0x95BA,0x95BB,0x95BC,0x95BD,0x95BE,0x95BF,0x95C0,0x95C1,0x95C2,0x95C3,0x95C4,0x95C5,0x95C6,0x95C7,0x95C8,0x95C9,0x95CA,0x95CB,0x6924,0x68F0,0x690B,0x6901,0x6957,0x68E3,0x6910,0x6971,0x6939,0x6960,0x6942,0x695D,0x6984,0x696B,0x6980,0x6998,0x6978,0x6934,0x69CC,0x6987,0x6988,0x69CE,0x6989,0x6966,0x6963,0x6979,0x699B,0x69A7,0x69BB,0x69AB,0x69AD,0x69D4,0x69B1,0x69C1,0x69CA,0x69DF,0x6995,0x69E0,0x698D,0x69FF,0x6A2F,0x69ED,0x6A17,0x6A18,0x6A65,0x69F2,0x6A44,0x6A3E,0x6AA0,0x6A50,0x6A5B,0x6A35,0x6A8E,0x6A79,0x6A3D,0x6A28,0x6A58,0x6A7C,0x6A91,0x6A90,0x6AA9,0x6A97,0x6AAB,0x7337,0x7352,0x6B81,0x6B82,0x6B87,0x6B84,0x6B92,0x6B93,0x6B8D,0x6B9A,0x6B9B,0x6BA1,0x6BAA,0x8F6B,0x8F6D,0x8F71,0x8F72,0x8F73,0x8F75,0x8F76,0x8F78,0x8F77,0x8F79,0x8F7A,0x8F7C,0x8F7E,0x8F81,0x8F82,0x8F84,0x8F87,0x8F8B,0x95CC,0x95CD,0x95CE,0x95CF,0x95D0,0x95D1,0x95D2,0x95D3,0x95D4,0x95D5,0x95D6,0x95D7,0x95D8,0x95D9,0x95DA,0x95DB,0x95DC,0x95DD,0x95DE,0x95DF,0x95E0,0x95E1,0x95E2,0x95E3,0x95E4,0x95E5,0x95E6,0x95E7,0x95EC,0x95FF,0x9607,0x9613,0x9618,0x961B,0x961E,0x9620,0x9623,0x9624,0x9625,0x9626,0x9627,0x9628,0x9629,0x962B,0x962C,0x962D,0x962F,0x9630,0x9637,0x9638,0x9639,0x963A,0x963E,0x9641,0x9643,0x964A,0x964E,0x964F,0x9651,0x9652,0x9653,0x9656,0x9657,0x9658,0x9659,0x965A,0x965C,0x965D,0x965E,0x9660,0x9663,0x9665,0x9666,0x966B,0x966D,0x966E,0x966F,0x9670,0x9671,0x9673,0x9678,0x9679,0x967A,0x967B,0x967C,0x967D,0x967E,0x967F,0x9680,0x9681,0x9682,0x9683,0x9684,0x9687,0x9689,0x968A,0x8F8D,0x8F8E,0x8F8F,0x8F98,0x8F9A,0x8ECE,0x620B,0x6217,0x621B,0x621F,0x6222,0x6221,0x6225,0x6224,0x622C,0x81E7,0x74EF,0x74F4,0x74FF,0x750F,0x7511,0x7513,0x6534,0x65EE,0x65EF,0x65F0,0x660A,0x6619,0x6772,0x6603,0x6615,0x6600,0x7085,0x66F7,0x661D,0x6634,0x6631,0x6636,0x6635,0x8006,0x665F,0x6654,0x6641,0x664F,0x6656,0x6661,0x6657,0x6677,0x6684,0x668C,0x66A7,0x669D,0x66BE,0x66DB,0x66DC,0x66E6,0x66E9,0x8D32,0x8D33,0x8D36,0x8D3B,0x8D3D,0x8D40,0x8D45,0x8D46,0x8D48,0x8D49,0x8D47,0x8D4D,0x8D55,0x8D59,0x89C7,0x89CA,0x89CB,0x89CC,0x89CE,0x89CF,0x89D0,0x89D1,0x726E,0x729F,0x725D,0x7266,0x726F,0x727E,0x727F,0x7284,0x728B,0x728D,0x728F,0x7292,0x6308,0x6332,0x63B0,0x968C,0x968E,0x9691,0x9692,0x9693,0x9695,0x9696,0x969A,0x969B,0x969D,0x969E,0x969F,0x96A0,0x96A1,0x96A2,0x96A3,0x96A4,0x96A5,0x96A6,0x96A8,0x96A9,0x96AA,0x96AB,0x96AC,0x96AD,0x96AE,0x96AF,0x96B1,0x96B2,0x96B4,0x96B5,0x96B7,0x96B8,0x96BA,0x96BB,0x96BF,0x96C2,0x96C3,0x96C8,0x96CA,0x96CB,0x96D0,0x96D1,0x96D3,0x96D4,0x96D6,0x96D7,0x96D8,0x96D9,0x96DA,0x96DB,0x96DC,0x96DD,0x96DE,0x96DF,0x96E1,0x96E2,0x96E3,0x96E4,0x96E5,0x96E6,0x96E7,0x96EB,0x96EC,0x96ED,0x96EE,0x96F0,0x96F1,0x96F2,0x96F4,0x96F5,0x96F8,0x96FA,0x96FB,0x96FC,0x96FD,0x96FF,0x9702,0x9703,0x9705,0x970A,0x970B,0x970C,0x9710,0x9711,0x9712,0x9714,0x9715,0x9717,0x9718,0x9719,0x971A,0x971B,0x971D,0x971F,0x9720,0x643F,0x64D8,0x8004,0x6BEA,0x6BF3,0x6BFD,0x6BF5,0x6BF9,0x6C05,0x6C07,0x6C06,0x6C0D,0x6C15,0x6C18,0x6C19,0x6C1A,0x6C21,0x6C29,0x6C24,0x6C2A,0x6C32,0x6535,0x6555,0x656B,0x724D,0x7252,0x7256,0x7230,0x8662,0x5216,0x809F,0x809C,0x8093,0x80BC,0x670A,0x80BD,0x80B1,0x80AB,0x80AD,0x80B4,0x80B7,0x80E7,0x80E8,0x80E9,0x80EA,0x80DB,0x80C2,0x80C4,0x80D9,0x80CD,0x80D7,0x6710,0x80DD,0x80EB,0x80F1,0x80F4,0x80ED,0x810D,0x810E,0x80F2,0x80FC,0x6715,0x8112,0x8C5A,0x8136,0x811E,0x812C,0x8118,0x8132,0x8148,0x814C,0x8153,0x8174,0x8159,0x815A,0x8171,0x8160,0x8169,0x817C,0x817D,0x816D,0x8167,0x584D,0x5AB5,0x8188,0x8182,0x8191,0x6ED5,0x81A3,0x81AA,0x81CC,0x6726,0x81CA,0x81BB,0x9721,0x9722,0x9723,0x9724,0x9725,0x9726,0x9727,0x9728,0x9729,0x972B,0x972C,0x972E,0x972F,0x9731,0x9733,0x9734,0x9735,0x9736,0x9737,0x973A,0x973B,0x973C,0x973D,0x973F,0x9740,0x9741,0x9742,0x9743,0x9744,0x9745,0x9746,0x9747,0x9748,0x9749,0x974A,0x974B,0x974C,0x974D,0x974E,0x974F,0x9750,0x9751,0x9754,0x9755,0x9757,0x9758,0x975A,0x975C,0x975D,0x975F,0x9763,0x9764,0x9766,0x9767,0x9768,0x976A,0x976B,0x976C,0x976D,0x976E,0x976F,0x9770,0x9771,0x9772,0x9775,0x9777,0x9778,0x9779,0x977A,0x977B,0x977D,0x977E,0x977F,0x9780,0x9781,0x9782,0x9783,0x9784,0x9786,0x9787,0x9788,0x9789,0x978A,0x978C,0x978E,0x978F,0x9790,0x9793,0x9795,0x9796,0x9797,0x9799,0x979A,0x979B,0x979C,0x979D,0x81C1,0x81A6,0x6B24,0x6B37,0x6B39,0x6B43,0x6B46,0x6B59,0x98D1,0x98D2,0x98D3,0x98D5,0x98D9,0x98DA,0x6BB3,0x5F40,0x6BC2,0x89F3,0x6590,0x9F51,0x6593,0x65BC,0x65C6,0x65C4,0x65C3,0x65CC,0x65CE,0x65D2,0x65D6,0x7080,0x709C,0x7096,0x709D,0x70BB,0x70C0,0x70B7,0x70AB,0x70B1,0x70E8,0x70CA,0x7110,0x7113,0x7116,0x712F,0x7131,0x7173,0x715C,0x7168,0x7145,0x7172,0x714A,0x7178,0x717A,0x7198,0x71B3,0x71B5,0x71A8,0x71A0,0x71E0,0x71D4,0x71E7,0x71F9,0x721D,0x7228,0x706C,0x7118,0x7166,0x71B9,0x623E,0x623D,0x6243,0x6248,0x6249,0x793B,0x7940,0x7946,0x7949,0x795B,0x795C,0x7953,0x795A,0x7962,0x7957,0x7960,0x796F,0x7967,0x797A,0x7985,0x798A,0x799A,0x79A7,0x79B3,0x5FD1,0x5FD0,0x979E,0x979F,0x97A1,0x97A2,0x97A4,0x97A5,0x97A6,0x97A7,0x97A8,0x97A9,0x97AA,0x97AC,0x97AE,0x97B0,0x97B1,0x97B3,0x97B5,0x97B6,0x97B7,0x97B8,0x97B9,0x97BA,0x97BB,0x97BC,0x97BD,0x97BE,0x97BF,0x97C0,0x97C1,0x97C2,0x97C3,0x97C4,0x97C5,0x97C6,0x97C7,0x97C8,0x97C9,0x97CA,0x97CB,0x97CC,0x97CD,0x97CE,0x97CF,0x97D0,0x97D1,0x97D2,0x97D3,0x97D4,0x97D5,0x97D6,0x97D7,0x97D8,0x97D9,0x97DA,0x97DB,0x97DC,0x97DD,0x97DE,0x97DF,0x97E0,0x97E1,0x97E2,0x97E3,0x97E4,0x97E5,0x97E8,0x97EE,0x97EF,0x97F0,0x97F1,0x97F2,0x97F4,0x97F7,0x97F8,0x97F9,0x97FA,0x97FB,0x97FC,0x97FD,0x97FE,0x97FF,0x9800,0x9801,0x9802,0x9803,0x9804,0x9805,0x9806,0x9807,0x9808,0x9809,0x980A,0x980B,0x980C,0x980D,0x980E,0x603C,0x605D,0x605A,0x6067,0x6041,0x6059,0x6063,0x60AB,0x6106,0x610D,0x615D,0x61A9,0x619D,0x61CB,0x61D1,0x6206,0x8080,0x807F,0x6C93,0x6CF6,0x6DFC,0x77F6,0x77F8,0x7800,0x7809,0x7817,0x7818,0x7811,0x65AB,0x782D,0x781C,0x781D,0x7839,0x783A,0x783B,0x781F,0x783C,0x7825,0x782C,0x7823,0x7829,0x784E,0x786D,0x7856,0x7857,0x7826,0x7850,0x7847,0x784C,0x786A,0x789B,0x7893,0x789A,0x7887,0x789C,0x78A1,0x78A3,0x78B2,0x78B9,0x78A5,0x78D4,0x78D9,0x78C9,0x78EC,0x78F2,0x7905,0x78F4,0x7913,0x7924,0x791E,0x7934,0x9F9B,0x9EF9,0x9EFB,0x9EFC,0x76F1,0x7704,0x770D,0x76F9,0x7707,0x7708,0x771A,0x7722,0x7719,0x772D,0x7726,0x7735,0x7738,0x7750,0x7751,0x7747,0x7743,0x775A,0x7768,0x980F,0x9810,0x9811,0x9812,0x9813,0x9814,0x9815,0x9816,0x9817,0x9818,0x9819,0x981A,0x981B,0x981C,0x981D,0x981E,0x981F,0x9820,0x9821,0x9822,0x9823,0x9824,0x9825,0x9826,0x9827,0x9828,0x9829,0x982A,0x982B,0x982C,0x982D,0x982E,0x982F,0x9830,0x9831,0x9832,0x9833,0x9834,0x9835,0x9836,0x9837,0x9838,0x9839,0x983A,0x983B,0x983C,0x983D,0x983E,0x983F,0x9840,0x9841,0x9842,0x9843,0x9844,0x9845,0x9846,0x9847,0x9848,0x9849,0x984A,0x984B,0x984C,0x984D,0x984E,0x984F,0x9850,0x9851,0x9852,0x9853,0x9854,0x9855,0x9856,0x9857,0x9858,0x9859,0x985A,0x985B,0x985C,0x985D,0x985E,0x985F,0x9860,0x9861,0x9862,0x9863,0x9864,0x9865,0x9866,0x9867,0x9868,0x9869,0x986A,0x986B,0x986C,0x986D,0x986E,0x7762,0x7765,0x777F,0x778D,0x777D,0x7780,0x778C,0x7791,0x779F,0x77A0,0x77B0,0x77B5,0x77BD,0x753A,0x7540,0x754E,0x754B,0x7548,0x755B,0x7572,0x7579,0x7583,0x7F58,0x7F61,0x7F5F,0x8A48,0x7F68,0x7F74,0x7F71,0x7F79,0x7F81,0x7F7E,0x76CD,0x76E5,0x8832,0x9485,0x9486,0x9487,0x948B,0x948A,0x948C,0x948D,0x948F,0x9490,0x9494,0x9497,0x9495,0x949A,0x949B,0x949C,0x94A3,0x94A4,0x94AB,0x94AA,0x94AD,0x94AC,0x94AF,0x94B0,0x94B2,0x94B4,0x94B6,0x94B7,0x94B8,0x94B9,0x94BA,0x94BC,0x94BD,0x94BF,0x94C4,0x94C8,0x94C9,0x94CA,0x94CB,0x94CC,0x94CD,0x94CE,0x94D0,0x94D1,0x94D2,0x94D5,0x94D6,0x94D7,0x94D9,0x94D8,0x94DB,0x94DE,0x94DF,0x94E0,0x94E2,0x94E4,0x94E5,0x94E7,0x94E8,0x94EA,0x986F,0x9870,0x9871,0x9872,0x9873,0x9874,0x988B,0x988E,0x9892,0x9895,0x9899,0x98A3,0x98A8,0x98A9,0x98AA,0x98AB,0x98AC,0x98AD,0x98AE,0x98AF,0x98B0,0x98B1,0x98B2,0x98B3,0x98B4,0x98B5,0x98B6,0x98B7,0x98B8,0x98B9,0x98BA,0x98BB,0x98BC,0x98BD,0x98BE,0x98BF,0x98C0,0x98C1,0x98C2,0x98C3,0x98C4,0x98C5,0x98C6,0x98C7,0x98C8,0x98C9,0x98CA,0x98CB,0x98CC,0x98CD,0x98CF,0x98D0,0x98D4,0x98D6,0x98D7,0x98DB,0x98DC,0x98DD,0x98E0,0x98E1,0x98E2,0x98E3,0x98E4,0x98E5,0x98E6,0x98E9,0x98EA,0x98EB,0x98EC,0x98ED,0x98EE,0x98EF,0x98F0,0x98F1,0x98F2,0x98F3,0x98F4,0x98F5,0x98F6,0x98F7,0x98F8,0x98F9,0x98FA,0x98FB,0x98FC,0x98FD,0x98FE,0x98FF,0x9900,0x9901,0x9902,0x9903,0x9904,0x9905,0x9906,0x9907,0x94E9,0x94EB,0x94EE,0x94EF,0x94F3,0x94F4,0x94F5,0x94F7,0x94F9,0x94FC,0x94FD,0x94FF,0x9503,0x9502,0x9506,0x9507,0x9509,0x950A,0x950D,0x950E,0x950F,0x9512,0x9513,0x9514,0x9515,0x9516,0x9518,0x951B,0x951D,0x951E,0x951F,0x9522,0x952A,0x952B,0x9529,0x952C,0x9531,0x9532,0x9534,0x9536,0x9537,0x9538,0x953C,0x953E,0x953F,0x9542,0x9535,0x9544,0x9545,0x9546,0x9549,0x954C,0x954E,0x954F,0x9552,0x9553,0x9554,0x9556,0x9557,0x9558,0x9559,0x955B,0x955E,0x955F,0x955D,0x9561,0x9562,0x9564,0x9565,0x9566,0x9567,0x9568,0x9569,0x956A,0x956B,0x956C,0x956F,0x9571,0x9572,0x9573,0x953A,0x77E7,0x77EC,0x96C9,0x79D5,0x79ED,0x79E3,0x79EB,0x7A06,0x5D47,0x7A03,0x7A02,0x7A1E,0x7A14,0x9908,0x9909,0x990A,0x990B,0x990C,0x990E,0x990F,0x9911,0x9912,0x9913,0x9914,0x9915,0x9916,0x9917,0x9918,0x9919,0x991A,0x991B,0x991C,0x991D,0x991E,0x991F,0x9920,0x9921,0x9922,0x9923,0x9924,0x9925,0x9926,0x9927,0x9928,0x9929,0x992A,0x992B,0x992C,0x992D,0x992F,0x9930,0x9931,0x9932,0x9933,0x9934,0x9935,0x9936,0x9937,0x9938,0x9939,0x993A,0x993B,0x993C,0x993D,0x993E,0x993F,0x9940,0x9941,0x9942,0x9943,0x9944,0x9945,0x9946,0x9947,0x9948,0x9949,0x994A,0x994B,0x994C,0x994D,0x994E,0x994F,0x9950,0x9951,0x9952,0x9953,0x9956,0x9957,0x9958,0x9959,0x995A,0x995B,0x995C,0x995D,0x995E,0x995F,0x9960,0x9961,0x9962,0x9964,0x9966,0x9973,0x9978,0x9979,0x997B,0x997E,0x9982,0x9983,0x9989,0x7A39,0x7A37,0x7A51,0x9ECF,0x99A5,0x7A70,0x7688,0x768E,0x7693,0x7699,0x76A4,0x74DE,0x74E0,0x752C,0x9E20,0x9E22,0x9E28,0x9E29,0x9E2A,0x9E2B,0x9E2C,0x9E32,0x9E31,0x9E36,0x9E38,0x9E37,0x9E39,0x9E3A,0x9E3E,0x9E41,0x9E42,0x9E44,0x9E46,0x9E47,0x9E48,0x9E49,0x9E4B,0x9E4C,0x9E4E,0x9E51,0x9E55,0x9E57,0x9E5A,0x9E5B,0x9E5C,0x9E5E,0x9E63,0x9E66,0x9E67,0x9E68,0x9E69,0x9E6A,0x9E6B,0x9E6C,0x9E71,0x9E6D,0x9E73,0x7592,0x7594,0x7596,0x75A0,0x759D,0x75AC,0x75A3,0x75B3,0x75B4,0x75B8,0x75C4,0x75B1,0x75B0,0x75C3,0x75C2,0x75D6,0x75CD,0x75E3,0x75E8,0x75E6,0x75E4,0x75EB,0x75E7,0x7603,0x75F1,0x75FC,0x75FF,0x7610,0x7600,0x7605,0x760C,0x7617,0x760A,0x7625,0x7618,0x7615,0x7619,0x998C,0x998E,0x999A,0x999B,0x999C,0x999D,0x999E,0x999F,0x99A0,0x99A1,0x99A2,0x99A3,0x99A4,0x99A6,0x99A7,0x99A9,0x99AA,0x99AB,0x99AC,0x99AD,0x99AE,0x99AF,0x99B0,0x99B1,0x99B2,0x99B3,0x99B4,0x99B5,0x99B6,0x99B7,0x99B8,0x99B9,0x99BA,0x99BB,0x99BC,0x99BD,0x99BE,0x99BF,0x99C0,0x99C1,0x99C2,0x99C3,0x99C4,0x99C5,0x99C6,0x99C7,0x99C8,0x99C9,0x99CA,0x99CB,0x99CC,0x99CD,0x99CE,0x99CF,0x99D0,0x99D1,0x99D2,0x99D3,0x99D4,0x99D5,0x99D6,0x99D7,0x99D8,0x99D9,0x99DA,0x99DB,0x99DC,0x99DD,0x99DE,0x99DF,0x99E0,0x99E1,0x99E2,0x99E3,0x99E4,0x99E5,0x99E6,0x99E7,0x99E8,0x99E9,0x99EA,0x99EB,0x99EC,0x99ED,0x99EE,0x99EF,0x99F0,0x99F1,0x99F2,0x99F3,0x99F4,0x99F5,0x99F6,0x99F7,0x99F8,0x99F9,0x761B,0x763C,0x7622,0x7620,0x7640,0x762D,0x7630,0x763F,0x7635,0x7643,0x763E,0x7633,0x764D,0x765E,0x7654,0x765C,0x7656,0x766B,0x766F,0x7FCA,0x7AE6,0x7A78,0x7A79,0x7A80,0x7A86,0x7A88,0x7A95,0x7AA6,0x7AA0,0x7AAC,0x7AA8,0x7AAD,0x7AB3,0x8864,0x8869,0x8872,0x887D,0x887F,0x8882,0x88A2,0x88C6,0x88B7,0x88BC,0x88C9,0x88E2,0x88CE,0x88E3,0x88E5,0x88F1,0x891A,0x88FC,0x88E8,0x88FE,0x88F0,0x8921,0x8919,0x8913,0x891B,0x890A,0x8934,0x892B,0x8936,0x8941,0x8966,0x897B,0x758B,0x80E5,0x76B2,0x76B4,0x77DC,0x8012,0x8014,0x8016,0x801C,0x8020,0x8022,0x8025,0x8026,0x8027,0x8029,0x8028,0x8031,0x800B,0x8035,0x8043,0x8046,0x804D,0x8052,0x8069,0x8071,0x8983,0x9878,0x9880,0x9883,0x99FA,0x99FB,0x99FC,0x99FD,0x99FE,0x99FF,0x9A00,0x9A01,0x9A02,0x9A03,0x9A04,0x9A05,0x9A06,0x9A07,0x9A08,0x9A09,0x9A0A,0x9A0B,0x9A0C,0x9A0D,0x9A0E,0x9A0F,0x9A10,0x9A11,0x9A12,0x9A13,0x9A14,0x9A15,0x9A16,0x9A17,0x9A18,0x9A19,0x9A1A,0x9A1B,0x9A1C,0x9A1D,0x9A1E,0x9A1F,0x9A20,0x9A21,0x9A22,0x9A23,0x9A24,0x9A25,0x9A26,0x9A27,0x9A28,0x9A29,0x9A2A,0x9A2B,0x9A2C,0x9A2D,0x9A2E,0x9A2F,0x9A30,0x9A31,0x9A32,0x9A33,0x9A34,0x9A35,0x9A36,0x9A37,0x9A38,0x9A39,0x9A3A,0x9A3B,0x9A3C,0x9A3D,0x9A3E,0x9A3F,0x9A40,0x9A41,0x9A42,0x9A43,0x9A44,0x9A45,0x9A46,0x9A47,0x9A48,0x9A49,0x9A4A,0x9A4B,0x9A4C,0x9A4D,0x9A4E,0x9A4F,0x9A50,0x9A51,0x9A52,0x9A53,0x9A54,0x9A55,0x9A56,0x9A57,0x9A58,0x9A59,0x9889,0x988C,0x988D,0x988F,0x9894,0x989A,0x989B,0x989E,0x989F,0x98A1,0x98A2,0x98A5,0x98A6,0x864D,0x8654,0x866C,0x866E,0x867F,0x867A,0x867C,0x867B,0x86A8,0x868D,0x868B,0x86AC,0x869D,0x86A7,0x86A3,0x86AA,0x8693,0x86A9,0x86B6,0x86C4,0x86B5,0x86CE,0x86B0,0x86BA,0x86B1,0x86AF,0x86C9,0x86CF,0x86B4,0x86E9,0x86F1,0x86F2,0x86ED,0x86F3,0x86D0,0x8713,0x86DE,0x86F4,0x86DF,0x86D8,0x86D1,0x8703,0x8707,0x86F8,0x8708,0x870A,0x870D,0x8709,0x8723,0x873B,0x871E,0x8725,0x872E,0x871A,0x873E,0x8748,0x8734,0x8731,0x8729,0x8737,0x873F,0x8782,0x8722,0x877D,0x877E,0x877B,0x8760,0x8770,0x874C,0x876E,0x878B,0x8753,0x8763,0x877C,0x8764,0x8759,0x8765,0x8793,0x87AF,0x87A8,0x87D2,0x9A5A,0x9A5B,0x9A5C,0x9A5D,0x9A5E,0x9A5F,0x9A60,0x9A61,0x9A62,0x9A63,0x9A64,0x9A65,0x9A66,0x9A67,0x9A68,0x9A69,0x9A6A,0x9A6B,0x9A72,0x9A83,0x9A89,0x9A8D,0x9A8E,0x9A94,0x9A95,0x9A99,0x9AA6,0x9AA9,0x9AAA,0x9AAB,0x9AAC,0x9AAD,0x9AAE,0x9AAF,0x9AB2,0x9AB3,0x9AB4,0x9AB5,0x9AB9,0x9ABB,0x9ABD,0x9ABE,0x9ABF,0x9AC3,0x9AC4,0x9AC6,0x9AC7,0x9AC8,0x9AC9,0x9ACA,0x9ACD,0x9ACE,0x9ACF,0x9AD0,0x9AD2,0x9AD4,0x9AD5,0x9AD6,0x9AD7,0x9AD9,0x9ADA,0x9ADB,0x9ADC,0x9ADD,0x9ADE,0x9AE0,0x9AE2,0x9AE3,0x9AE4,0x9AE5,0x9AE7,0x9AE8,0x9AE9,0x9AEA,0x9AEC,0x9AEE,0x9AF0,0x9AF1,0x9AF2,0x9AF3,0x9AF4,0x9AF5,0x9AF6,0x9AF7,0x9AF8,0x9AFA,0x9AFC,0x9AFD,0x9AFE,0x9AFF,0x9B00,0x9B01,0x9B02,0x9B04,0x9B05,0x9B06,0x87C6,0x8788,0x8785,0x87AD,0x8797,0x8783,0x87AB,0x87E5,0x87AC,0x87B5,0x87B3,0x87CB,0x87D3,0x87BD,0x87D1,0x87C0,0x87CA,0x87DB,0x87EA,0x87E0,0x87EE,0x8816,0x8813,0x87FE,0x880A,0x881B,0x8821,0x8839,0x883C,0x7F36,0x7F42,0x7F44,0x7F45,0x8210,0x7AFA,0x7AFD,0x7B08,0x7B03,0x7B04,0x7B15,0x7B0A,0x7B2B,0x7B0F,0x7B47,0x7B38,0x7B2A,0x7B19,0x7B2E,0x7B31,0x7B20,0x7B25,0x7B24,0x7B33,0x7B3E,0x7B1E,0x7B58,0x7B5A,0x7B45,0x7B75,0x7B4C,0x7B5D,0x7B60,0x7B6E,0x7B7B,0x7B62,0x7B72,0x7B71,0x7B90,0x7BA6,0x7BA7,0x7BB8,0x7BAC,0x7B9D,0x7BA8,0x7B85,0x7BAA,0x7B9C,0x7BA2,0x7BAB,0x7BB4,0x7BD1,0x7BC1,0x7BCC,0x7BDD,0x7BDA,0x7BE5,0x7BE6,0x7BEA,0x7C0C,0x7BFE,0x7BFC,0x7C0F,0x7C16,0x7C0B,0x9B07,0x9B09,0x9B0A,0x9B0B,0x9B0C,0x9B0D,0x9B0E,0x9B10,0x9B11,0x9B12,0x9B14,0x9B15,0x9B16,0x9B17,0x9B18,0x9B19,0x9B1A,0x9B1B,0x9B1C,0x9B1D,0x9B1E,0x9B20,0x9B21,0x9B22,0x9B24,0x9B25,0x9B26,0x9B27,0x9B28,0x9B29,0x9B2A,0x9B2B,0x9B2C,0x9B2D,0x9B2E,0x9B30,0x9B31,0x9B33,0x9B34,0x9B35,0x9B36,0x9B37,0x9B38,0x9B39,0x9B3A,0x9B3D,0x9B3E,0x9B3F,0x9B40,0x9B46,0x9B4A,0x9B4B,0x9B4C,0x9B4E,0x9B50,0x9B52,0x9B53,0x9B55,0x9B56,0x9B57,0x9B58,0x9B59,0x9B5A,0x9B5B,0x9B5C,0x9B5D,0x9B5E,0x9B5F,0x9B60,0x9B61,0x9B62,0x9B63,0x9B64,0x9B65,0x9B66,0x9B67,0x9B68,0x9B69,0x9B6A,0x9B6B,0x9B6C,0x9B6D,0x9B6E,0x9B6F,0x9B70,0x9B71,0x9B72,0x9B73,0x9B74,0x9B75,0x9B76,0x9B77,0x9B78,0x9B79,0x9B7A,0x9B7B,0x7C1F,0x7C2A,0x7C26,0x7C38,0x7C41,0x7C40,0x81FE,0x8201,0x8202,0x8204,0x81EC,0x8844,0x8221,0x8222,0x8223,0x822D,0x822F,0x8228,0x822B,0x8238,0x823B,0x8233,0x8234,0x823E,0x8244,0x8249,0x824B,0x824F,0x825A,0x825F,0x8268,0x887E,0x8885,0x8888,0x88D8,0x88DF,0x895E,0x7F9D,0x7F9F,0x7FA7,0x7FAF,0x7FB0,0x7FB2,0x7C7C,0x6549,0x7C91,0x7C9D,0x7C9C,0x7C9E,0x7CA2,0x7CB2,0x7CBC,0x7CBD,0x7CC1,0x7CC7,0x7CCC,0x7CCD,0x7CC8,0x7CC5,0x7CD7,0x7CE8,0x826E,0x66A8,0x7FBF,0x7FCE,0x7FD5,0x7FE5,0x7FE1,0x7FE6,0x7FE9,0x7FEE,0x7FF3,0x7CF8,0x7D77,0x7DA6,0x7DAE,0x7E47,0x7E9B,0x9EB8,0x9EB4,0x8D73,0x8D84,0x8D94,0x8D91,0x8DB1,0x8D67,0x8D6D,0x8C47,0x8C49,0x914A,0x9150,0x914E,0x914F,0x9164,0x9B7C,0x9B7D,0x9B7E,0x9B7F,0x9B80,0x9B81,0x9B82,0x9B83,0x9B84,0x9B85,0x9B86,0x9B87,0x9B88,0x9B89,0x9B8A,0x9B8B,0x9B8C,0x9B8D,0x9B8E,0x9B8F,0x9B90,0x9B91,0x9B92,0x9B93,0x9B94,0x9B95,0x9B96,0x9B97,0x9B98,0x9B99,0x9B9A,0x9B9B,0x9B9C,0x9B9D,0x9B9E,0x9B9F,0x9BA0,0x9BA1,0x9BA2,0x9BA3,0x9BA4,0x9BA5,0x9BA6,0x9BA7,0x9BA8,0x9BA9,0x9BAA,0x9BAB,0x9BAC,0x9BAD,0x9BAE,0x9BAF,0x9BB0,0x9BB1,0x9BB2,0x9BB3,0x9BB4,0x9BB5,0x9BB6,0x9BB7,0x9BB8,0x9BB9,0x9BBA,0x9BBB,0x9BBC,0x9BBD,0x9BBE,0x9BBF,0x9BC0,0x9BC1,0x9BC2,0x9BC3,0x9BC4,0x9BC5,0x9BC6,0x9BC7,0x9BC8,0x9BC9,0x9BCA,0x9BCB,0x9BCC,0x9BCD,0x9BCE,0x9BCF,0x9BD0,0x9BD1,0x9BD2,0x9BD3,0x9BD4,0x9BD5,0x9BD6,0x9BD7,0x9BD8,0x9BD9,0x9BDA,0x9BDB,0x9162,0x9161,0x9170,0x9169,0x916F,0x917D,0x917E,0x9172,0x9174,0x9179,0x918C,0x9185,0x9190,0x918D,0x9191,0x91A2,0x91A3,0x91AA,0x91AD,0x91AE,0x91AF,0x91B5,0x91B4,0x91BA,0x8C55,0x9E7E,0x8DB8,0x8DEB,0x8E05,0x8E59,0x8E69,0x8DB5,0x8DBF,0x8DBC,0x8DBA,0x8DC4,0x8DD6,0x8DD7,0x8DDA,0x8DDE,0x8DCE,0x8DCF,0x8DDB,0x8DC6,0x8DEC,0x8DF7,0x8DF8,0x8DE3,0x8DF9,0x8DFB,0x8DE4,0x8E09,0x8DFD,0x8E14,0x8E1D,0x8E1F,0x8E2C,0x8E2E,0x8E23,0x8E2F,0x8E3A,0x8E40,0x8E39,0x8E35,0x8E3D,0x8E31,0x8E49,0x8E41,0x8E42,0x8E51,0x8E52,0x8E4A,0x8E70,0x8E76,0x8E7C,0x8E6F,0x8E74,0x8E85,0x8E8F,0x8E94,0x8E90,0x8E9C,0x8E9E,0x8C78,0x8C82,0x8C8A,0x8C85,0x8C98,0x8C94,0x659B,0x89D6,0x89DE,0x89DA,0x89DC,0x9BDC,0x9BDD,0x9BDE,0x9BDF,0x9BE0,0x9BE1,0x9BE2,0x9BE3,0x9BE4,0x9BE5,0x9BE6,0x9BE7,0x9BE8,0x9BE9,0x9BEA,0x9BEB,0x9BEC,0x9BED,0x9BEE,0x9BEF,0x9BF0,0x9BF1,0x9BF2,0x9BF3,0x9BF4,0x9BF5,0x9BF6,0x9BF7,0x9BF8,0x9BF9,0x9BFA,0x9BFB,0x9BFC,0x9BFD,0x9BFE,0x9BFF,0x9C00,0x9C01,0x9C02,0x9C03,0x9C04,0x9C05,0x9C06,0x9C07,0x9C08,0x9C09,0x9C0A,0x9C0B,0x9C0C,0x9C0D,0x9C0E,0x9C0F,0x9C10,0x9C11,0x9C12,0x9C13,0x9C14,0x9C15,0x9C16,0x9C17,0x9C18,0x9C19,0x9C1A,0x9C1B,0x9C1C,0x9C1D,0x9C1E,0x9C1F,0x9C20,0x9C21,0x9C22,0x9C23,0x9C24,0x9C25,0x9C26,0x9C27,0x9C28,0x9C29,0x9C2A,0x9C2B,0x9C2C,0x9C2D,0x9C2E,0x9C2F,0x9C30,0x9C31,0x9C32,0x9C33,0x9C34,0x9C35,0x9C36,0x9C37,0x9C38,0x9C39,0x9C3A,0x9C3B,0x89E5,0x89EB,0x89EF,0x8A3E,0x8B26,0x9753,0x96E9,0x96F3,0x96EF,0x9706,0x9701,0x9708,0x970F,0x970E,0x972A,0x972D,0x9730,0x973E,0x9F80,0x9F83,0x9F85,0x9F86,0x9F87,0x9F88,0x9F89,0x9F8A,0x9F8C,0x9EFE,0x9F0B,0x9F0D,0x96B9,0x96BC,0x96BD,0x96CE,0x96D2,0x77BF,0x96E0,0x928E,0x92AE,0x92C8,0x933E,0x936A,0x93CA,0x938F,0x943E,0x946B,0x9C7F,0x9C82,0x9C85,0x9C86,0x9C87,0x9C88,0x7A23,0x9C8B,0x9C8E,0x9C90,0x9C91,0x9C92,0x9C94,0x9C95,0x9C9A,0x9C9B,0x9C9E,0x9C9F,0x9CA0,0x9CA1,0x9CA2,0x9CA3,0x9CA5,0x9CA6,0x9CA7,0x9CA8,0x9CA9,0x9CAB,0x9CAD,0x9CAE,0x9CB0,0x9CB1,0x9CB2,0x9CB3,0x9CB4,0x9CB5,0x9CB6,0x9CB7,0x9CBA,0x9CBB,0x9CBC,0x9CBD,0x9CC4,0x9CC5,0x9CC6,0x9CC7,0x9CCA,0x9CCB,0x9C3C,0x9C3D,0x9C3E,0x9C3F,0x9C40,0x9C41,0x9C42,0x9C43,0x9C44,0x9C45,0x9C46,0x9C47,0x9C48,0x9C49,0x9C4A,0x9C4B,0x9C4C,0x9C4D,0x9C4E,0x9C4F,0x9C50,0x9C51,0x9C52,0x9C53,0x9C54,0x9C55,0x9C56,0x9C57,0x9C58,0x9C59,0x9C5A,0x9C5B,0x9C5C,0x9C5D,0x9C5E,0x9C5F,0x9C60,0x9C61,0x9C62,0x9C63,0x9C64,0x9C65,0x9C66,0x9C67,0x9C68,0x9C69,0x9C6A,0x9C6B,0x9C6C,0x9C6D,0x9C6E,0x9C6F,0x9C70,0x9C71,0x9C72,0x9C73,0x9C74,0x9C75,0x9C76,0x9C77,0x9C78,0x9C79,0x9C7A,0x9C7B,0x9C7D,0x9C7E,0x9C80,0x9C83,0x9C84,0x9C89,0x9C8A,0x9C8C,0x9C8F,0x9C93,0x9C96,0x9C97,0x9C98,0x9C99,0x9C9D,0x9CAA,0x9CAC,0x9CAF,0x9CB9,0x9CBE,0x9CBF,0x9CC0,0x9CC1,0x9CC2,0x9CC8,0x9CC9,0x9CD1,0x9CD2,0x9CDA,0x9CDB,0x9CE0,0x9CE1,0x9CCC,0x9CCD,0x9CCE,0x9CCF,0x9CD0,0x9CD3,0x9CD4,0x9CD5,0x9CD7,0x9CD8,0x9CD9,0x9CDC,0x9CDD,0x9CDF,0x9CE2,0x977C,0x9785,0x9791,0x9792,0x9794,0x97AF,0x97AB,0x97A3,0x97B2,0x97B4,0x9AB1,0x9AB0,0x9AB7,0x9E58,0x9AB6,0x9ABA,0x9ABC,0x9AC1,0x9AC0,0x9AC5,0x9AC2,0x9ACB,0x9ACC,0x9AD1,0x9B45,0x9B43,0x9B47,0x9B49,0x9B48,0x9B4D,0x9B51,0x98E8,0x990D,0x992E,0x9955,0x9954,0x9ADF,0x9AE1,0x9AE6,0x9AEF,0x9AEB,0x9AFB,0x9AED,0x9AF9,0x9B08,0x9B0F,0x9B13,0x9B1F,0x9B23,0x9EBD,0x9EBE,0x7E3B,0x9E82,0x9E87,0x9E88,0x9E8B,0x9E92,0x93D6,0x9E9D,0x9E9F,0x9EDB,0x9EDC,0x9EDD,0x9EE0,0x9EDF,0x9EE2,0x9EE9,0x9EE7,0x9EE5,0x9EEA,0x9EEF,0x9F22,0x9F2C,0x9F2F,0x9F39,0x9F37,0x9F3D,0x9F3E,0x9F44,0x9CE3,0x9CE4,0x9CE5,0x9CE6,0x9CE7,0x9CE8,0x9CE9,0x9CEA,0x9CEB,0x9CEC,0x9CED,0x9CEE,0x9CEF,0x9CF0,0x9CF1,0x9CF2,0x9CF3,0x9CF4,0x9CF5,0x9CF6,0x9CF7,0x9CF8,0x9CF9,0x9CFA,0x9CFB,0x9CFC,0x9CFD,0x9CFE,0x9CFF,0x9D00,0x9D01,0x9D02,0x9D03,0x9D04,0x9D05,0x9D06,0x9D07,0x9D08,0x9D09,0x9D0A,0x9D0B,0x9D0C,0x9D0D,0x9D0E,0x9D0F,0x9D10,0x9D11,0x9D12,0x9D13,0x9D14,0x9D15,0x9D16,0x9D17,0x9D18,0x9D19,0x9D1A,0x9D1B,0x9D1C,0x9D1D,0x9D1E,0x9D1F,0x9D20,0x9D21,0x9D22,0x9D23,0x9D24,0x9D25,0x9D26,0x9D27,0x9D28,0x9D29,0x9D2A,0x9D2B,0x9D2C,0x9D2D,0x9D2E,0x9D2F,0x9D30,0x9D31,0x9D32,0x9D33,0x9D34,0x9D35,0x9D36,0x9D37,0x9D38,0x9D39,0x9D3A,0x9D3B,0x9D3C,0x9D3D,0x9D3E,0x9D3F,0x9D40,0x9D41,0x9D42,0xE234,0xE235,0xE236,0xE237,0xE238,0xE239,0xE23A,0xE23B,0xE23C,0xE23D,0xE23E,0xE23F,0xE240,0xE241,0xE242,0xE243,0xE244,0xE245,0xE246,0xE247,0xE248,0xE249,0xE24A,0xE24B,0xE24C,0xE24D,0xE24E,0xE24F,0xE250,0xE251,0xE252,0xE253,0xE254,0xE255,0xE256,0xE257,0xE258,0xE259,0xE25A,0xE25B,0xE25C,0xE25D,0xE25E,0xE25F,0xE260,0xE261,0xE262,0xE263,0xE264,0xE265,0xE266,0xE267,0xE268,0xE269,0xE26A,0xE26B,0xE26C,0xE26D,0xE26E,0xE26F,0xE270,0xE271,0xE272,0xE273,0xE274,0xE275,0xE276,0xE277,0xE278,0xE279,0xE27A,0xE27B,0xE27C,0xE27D,0xE27E,0xE27F,0xE280,0xE281,0xE282,0xE283,0xE284,0xE285,0xE286,0xE287,0xE288,0xE289,0xE28A,0xE28B,0xE28C,0xE28D,0xE28E,0xE28F,0xE290,0xE291,0x9D43,0x9D44,0x9D45,0x9D46,0x9D47,0x9D48,0x9D49,0x9D4A,0x9D4B,0x9D4C,0x9D4D,0x9D4E,0x9D4F,0x9D50,0x9D51,0x9D52,0x9D53,0x9D54,0x9D55,0x9D56,0x9D57,0x9D58,0x9D59,0x9D5A,0x9D5B,0x9D5C,0x9D5D,0x9D5E,0x9D5F,0x9D60,0x9D61,0x9D62,0x9D63,0x9D64,0x9D65,0x9D66,0x9D67,0x9D68,0x9D69,0x9D6A,0x9D6B,0x9D6C,0x9D6D,0x9D6E,0x9D6F,0x9D70,0x9D71,0x9D72,0x9D73,0x9D74,0x9D75,0x9D76,0x9D77,0x9D78,0x9D79,0x9D7A,0x9D7B,0x9D7C,0x9D7D,0x9D7E,0x9D7F,0x9D80,0x9D81,0x9D82,0x9D83,0x9D84,0x9D85,0x9D86,0x9D87,0x9D88,0x9D89,0x9D8A,0x9D8B,0x9D8C,0x9D8D,0x9D8E,0x9D8F,0x9D90,0x9D91,0x9D92,0x9D93,0x9D94,0x9D95,0x9D96,0x9D97,0x9D98,0x9D99,0x9D9A,0x9D9B,0x9D9C,0x9D9D,0x9D9E,0x9D9F,0x9DA0,0x9DA1,0x9DA2,0xE292,0xE293,0xE294,0xE295,0xE296,0xE297,0xE298,0xE299,0xE29A,0xE29B,0xE29C,0xE29D,0xE29E,0xE29F,0xE2A0,0xE2A1,0xE2A2,0xE2A3,0xE2A4,0xE2A5,0xE2A6,0xE2A7,0xE2A8,0xE2A9,0xE2AA,0xE2AB,0xE2AC,0xE2AD,0xE2AE,0xE2AF,0xE2B0,0xE2B1,0xE2B2,0xE2B3,0xE2B4,0xE2B5,0xE2B6,0xE2B7,0xE2B8,0xE2B9,0xE2BA,0xE2BB,0xE2BC,0xE2BD,0xE2BE,0xE2BF,0xE2C0,0xE2C1,0xE2C2,0xE2C3,0xE2C4,0xE2C5,0xE2C6,0xE2C7,0xE2C8,0xE2C9,0xE2CA,0xE2CB,0xE2CC,0xE2CD,0xE2CE,0xE2CF,0xE2D0,0xE2D1,0xE2D2,0xE2D3,0xE2D4,0xE2D5,0xE2D6,0xE2D7,0xE2D8,0xE2D9,0xE2DA,0xE2DB,0xE2DC,0xE2DD,0xE2DE,0xE2DF,0xE2E0,0xE2E1,0xE2E2,0xE2E3,0xE2E4,0xE2E5,0xE2E6,0xE2E7,0xE2E8,0xE2E9,0xE2EA,0xE2EB,0xE2EC,0xE2ED,0xE2EE,0xE2EF,0x9DA3,0x9DA4,0x9DA5,0x9DA6,0x9DA7,0x9DA8,0x9DA9,0x9DAA,0x9DAB,0x9DAC,0x9DAD,0x9DAE,0x9DAF,0x9DB0,0x9DB1,0x9DB2,0x9DB3,0x9DB4,0x9DB5,0x9DB6,0x9DB7,0x9DB8,0x9DB9,0x9DBA,0x9DBB,0x9DBC,0x9DBD,0x9DBE,0x9DBF,0x9DC0,0x9DC1,0x9DC2,0x9DC3,0x9DC4,0x9DC5,0x9DC6,0x9DC7,0x9DC8,0x9DC9,0x9DCA,0x9DCB,0x9DCC,0x9DCD,0x9DCE,0x9DCF,0x9DD0,0x9DD1,0x9DD2,0x9DD3,0x9DD4,0x9DD5,0x9DD6,0x9DD7,0x9DD8,0x9DD9,0x9DDA,0x9DDB,0x9DDC,0x9DDD,0x9DDE,0x9DDF,0x9DE0,0x9DE1,0x9DE2,0x9DE3,0x9DE4,0x9DE5,0x9DE6,0x9DE7,0x9DE8,0x9DE9,0x9DEA,0x9DEB,0x9DEC,0x9DED,0x9DEE,0x9DEF,0x9DF0,0x9DF1,0x9DF2,0x9DF3,0x9DF4,0x9DF5,0x9DF6,0x9DF7,0x9DF8,0x9DF9,0x9DFA,0x9DFB,0x9DFC,0x9DFD,0x9DFE,0x9DFF,0x9E00,0x9E01,0x9E02,0xE2F0,0xE2F1,0xE2F2,0xE2F3,0xE2F4,0xE2F5,0xE2F6,0xE2F7,0xE2F8,0xE2F9,0xE2FA,0xE2FB,0xE2FC,0xE2FD,0xE2FE,0xE2FF,0xE300,0xE301,0xE302,0xE303,0xE304,0xE305,0xE306,0xE307,0xE308,0xE309,0xE30A,0xE30B,0xE30C,0xE30D,0xE30E,0xE30F,0xE310,0xE311,0xE312,0xE313,0xE314,0xE315,0xE316,0xE317,0xE318,0xE319,0xE31A,0xE31B,0xE31C,0xE31D,0xE31E,0xE31F,0xE320,0xE321,0xE322,0xE323,0xE324,0xE325,0xE326,0xE327,0xE328,0xE329,0xE32A,0xE32B,0xE32C,0xE32D,0xE32E,0xE32F,0xE330,0xE331,0xE332,0xE333,0xE334,0xE335,0xE336,0xE337,0xE338,0xE339,0xE33A,0xE33B,0xE33C,0xE33D,0xE33E,0xE33F,0xE340,0xE341,0xE342,0xE343,0xE344,0xE345,0xE346,0xE347,0xE348,0xE349,0xE34A,0xE34B,0xE34C,0xE34D,0x9E03,0x9E04,0x9E05,0x9E06,0x9E07,0x9E08,0x9E09,0x9E0A,0x9E0B,0x9E0C,0x9E0D,0x9E0E,0x9E0F,0x9E10,0x9E11,0x9E12,0x9E13,0x9E14,0x9E15,0x9E16,0x9E17,0x9E18,0x9E19,0x9E1A,0x9E1B,0x9E1C,0x9E1D,0x9E1E,0x9E24,0x9E27,0x9E2E,0x9E30,0x9E34,0x9E3B,0x9E3C,0x9E40,0x9E4D,0x9E50,0x9E52,0x9E53,0x9E54,0x9E56,0x9E59,0x9E5D,0x9E5F,0x9E60,0x9E61,0x9E62,0x9E65,0x9E6E,0x9E6F,0x9E72,0x9E74,0x9E75,0x9E76,0x9E77,0x9E78,0x9E79,0x9E7A,0x9E7B,0x9E7C,0x9E7D,0x9E80,0x9E81,0x9E83,0x9E84,0x9E85,0x9E86,0x9E89,0x9E8A,0x9E8C,0x9E8D,0x9E8E,0x9E8F,0x9E90,0x9E91,0x9E94,0x9E95,0x9E96,0x9E97,0x9E98,0x9E99,0x9E9A,0x9E9B,0x9E9C,0x9E9E,0x9EA0,0x9EA1,0x9EA2,0x9EA3,0x9EA4,0x9EA5,0x9EA7,0x9EA8,0x9EA9,0x9EAA,0xE34E,0xE34F,0xE350,0xE351,0xE352,0xE353,0xE354,0xE355,0xE356,0xE357,0xE358,0xE359,0xE35A,0xE35B,0xE35C,0xE35D,0xE35E,0xE35F,0xE360,0xE361,0xE362,0xE363,0xE364,0xE365,0xE366,0xE367,0xE368,0xE369,0xE36A,0xE36B,0xE36C,0xE36D,0xE36E,0xE36F,0xE370,0xE371,0xE372,0xE373,0xE374,0xE375,0xE376,0xE377,0xE378,0xE379,0xE37A,0xE37B,0xE37C,0xE37D,0xE37E,0xE37F,0xE380,0xE381,0xE382,0xE383,0xE384,0xE385,0xE386,0xE387,0xE388,0xE389,0xE38A,0xE38B,0xE38C,0xE38D,0xE38E,0xE38F,0xE390,0xE391,0xE392,0xE393,0xE394,0xE395,0xE396,0xE397,0xE398,0xE399,0xE39A,0xE39B,0xE39C,0xE39D,0xE39E,0xE39F,0xE3A0,0xE3A1,0xE3A2,0xE3A3,0xE3A4,0xE3A5,0xE3A6,0xE3A7,0xE3A8,0xE3A9,0xE3AA,0xE3AB,0x9EAB,0x9EAC,0x9EAD,0x9EAE,0x9EAF,0x9EB0,0x9EB1,0x9EB2,0x9EB3,0x9EB5,0x9EB6,0x9EB7,0x9EB9,0x9EBA,0x9EBC,0x9EBF,0x9EC0,0x9EC1,0x9EC2,0x9EC3,0x9EC5,0x9EC6,0x9EC7,0x9EC8,0x9ECA,0x9ECB,0x9ECC,0x9ED0,0x9ED2,0x9ED3,0x9ED5,0x9ED6,0x9ED7,0x9ED9,0x9EDA,0x9EDE,0x9EE1,0x9EE3,0x9EE4,0x9EE6,0x9EE8,0x9EEB,0x9EEC,0x9EED,0x9EEE,0x9EF0,0x9EF1,0x9EF2,0x9EF3,0x9EF4,0x9EF5,0x9EF6,0x9EF7,0x9EF8,0x9EFA,0x9EFD,0x9EFF,0x9F00,0x9F01,0x9F02,0x9F03,0x9F04,0x9F05,0x9F06,0x9F07,0x9F08,0x9F09,0x9F0A,0x9F0C,0x9F0F,0x9F11,0x9F12,0x9F14,0x9F15,0x9F16,0x9F18,0x9F1A,0x9F1B,0x9F1C,0x9F1D,0x9F1E,0x9F1F,0x9F21,0x9F23,0x9F24,0x9F25,0x9F26,0x9F27,0x9F28,0x9F29,0x9F2A,0x9F2B,0x9F2D,0x9F2E,0x9F30,0x9F31,0xE3AC,0xE3AD,0xE3AE,0xE3AF,0xE3B0,0xE3B1,0xE3B2,0xE3B3,0xE3B4,0xE3B5,0xE3B6,0xE3B7,0xE3B8,0xE3B9,0xE3BA,0xE3BB,0xE3BC,0xE3BD,0xE3BE,0xE3BF,0xE3C0,0xE3C1,0xE3C2,0xE3C3,0xE3C4,0xE3C5,0xE3C6,0xE3C7,0xE3C8,0xE3C9,0xE3CA,0xE3CB,0xE3CC,0xE3CD,0xE3CE,0xE3CF,0xE3D0,0xE3D1,0xE3D2,0xE3D3,0xE3D4,0xE3D5,0xE3D6,0xE3D7,0xE3D8,0xE3D9,0xE3DA,0xE3DB,0xE3DC,0xE3DD,0xE3DE,0xE3DF,0xE3E0,0xE3E1,0xE3E2,0xE3E3,0xE3E4,0xE3E5,0xE3E6,0xE3E7,0xE3E8,0xE3E9,0xE3EA,0xE3EB,0xE3EC,0xE3ED,0xE3EE,0xE3EF,0xE3F0,0xE3F1,0xE3F2,0xE3F3,0xE3F4,0xE3F5,0xE3F6,0xE3F7,0xE3F8,0xE3F9,0xE3FA,0xE3FB,0xE3FC,0xE3FD,0xE3FE,0xE3FF,0xE400,0xE401,0xE402,0xE403,0xE404,0xE405,0xE406,0xE407,0xE408,0xE409,0x9F32,0x9F33,0x9F34,0x9F35,0x9F36,0x9F38,0x9F3A,0x9F3C,0x9F3F,0x9F40,0x9F41,0x9F42,0x9F43,0x9F45,0x9F46,0x9F47,0x9F48,0x9F49,0x9F4A,0x9F4B,0x9F4C,0x9F4D,0x9F4E,0x9F4F,0x9F52,0x9F53,0x9F54,0x9F55,0x9F56,0x9F57,0x9F58,0x9F59,0x9F5A,0x9F5B,0x9F5C,0x9F5D,0x9F5E,0x9F5F,0x9F60,0x9F61,0x9F62,0x9F63,0x9F64,0x9F65,0x9F66,0x9F67,0x9F68,0x9F69,0x9F6A,0x9F6B,0x9F6C,0x9F6D,0x9F6E,0x9F6F,0x9F70,0x9F71,0x9F72,0x9F73,0x9F74,0x9F75,0x9F76,0x9F77,0x9F78,0x9F79,0x9F7A,0x9F7B,0x9F7C,0x9F7D,0x9F7E,0x9F81,0x9F82,0x9F8D,0x9F8E,0x9F8F,0x9F90,0x9F91,0x9F92,0x9F93,0x9F94,0x9F95,0x9F96,0x9F97,0x9F98,0x9F9C,0x9F9D,0x9F9E,0x9FA1,0x9FA2,0x9FA3,0x9FA4,0x9FA5,0xF92C,0xF979,0xF995,0xF9E7,0xF9F1,0xE40A,0xE40B,0xE40C,0xE40D,0xE40E,0xE40F,0xE410,0xE411,0xE412,0xE413,0xE414,0xE415,0xE416,0xE417,0xE418,0xE419,0xE41A,0xE41B,0xE41C,0xE41D,0xE41E,0xE41F,0xE420,0xE421,0xE422,0xE423,0xE424,0xE425,0xE426,0xE427,0xE428,0xE429,0xE42A,0xE42B,0xE42C,0xE42D,0xE42E,0xE42F,0xE430,0xE431,0xE432,0xE433,0xE434,0xE435,0xE436,0xE437,0xE438,0xE439,0xE43A,0xE43B,0xE43C,0xE43D,0xE43E,0xE43F,0xE440,0xE441,0xE442,0xE443,0xE444,0xE445,0xE446,0xE447,0xE448,0xE449,0xE44A,0xE44B,0xE44C,0xE44D,0xE44E,0xE44F,0xE450,0xE451,0xE452,0xE453,0xE454,0xE455,0xE456,0xE457,0xE458,0xE459,0xE45A,0xE45B,0xE45C,0xE45D,0xE45E,0xE45F,0xE460,0xE461,0xE462,0xE463,0xE464,0xE465,0xE466,0xE467,0xFA0C,0xFA0D,0xFA0E,0xFA0F,0xFA11,0xFA13,0xFA14,0xFA18,0xFA1F,0xFA20,0xFA21,0xFA23,0xFA24,0xFA27,0xFA28,0xFA29,0x2E81,0x20087,0x20089,0x200CC,0x2E84,0x3473,0x3447,0x2E88,0x2E8B,0x9FB4,0x359E,0x361A,0x360E,0x2E8C,0x2E97,0x396E,0x3918,0x9FB5,0x39CF,0x39DF,0x3A73,0x39D0,0x9FB6,0x9FB7,0x3B4E,0x3C6E,0x3CE0,0x2EA7,0x215D7,0x9FB8,0x2EAA,0x4056,0x415F,0x2EAE,0x4337,0x2EB3,0x2EB6,0x2EB7,0x2298F,0x43B1,0x43AC,0x2EBB,0x43DD,0x44D6,0x4661,0x464C,0x9FB9,0x4723,0x4729,0x477C,0x478D,0x2ECA,0x4947,0x497A,0x497D,0x4982,0x4983,0x4985,0x4986,0x499F,0x499B,0x49B7,0x49B6,0x9FBA,0x241FE,0x4CA3,0x4C9F,0x4CA0,0x4CA1,0x4C77,0x4CA2,0x4D13,0x4D14,0x4D15,0x4D16,0x4D17,0x4D18,0x4D19,0x4DAE,0x9FBB,0xE468,0xE469,0xE46A,0xE46B,0xE46C,0xE46D,0xE46E,0xE46F,0xE470,0xE471,0xE472,0xE473,0xE474,0xE475,0xE476,0xE477,0xE478,0xE479,0xE47A,0xE47B,0xE47C,0xE47D,0xE47E,0xE47F,0xE480,0xE481,0xE482,0xE483,0xE484,0xE485,0xE486,0xE487,0xE488,0xE489,0xE48A,0xE48B,0xE48C,0xE48D,0xE48E,0xE48F,0xE490,0xE491,0xE492,0xE493,0xE494,0xE495,0xE496,0xE497,0xE498,0xE499,0xE49A,0xE49B,0xE49C,0xE49D,0xE49E,0xE49F,0xE4A0,0xE4A1,0xE4A2,0xE4A3,0xE4A4,0xE4A5,0xE4A6,0xE4A7,0xE4A8,0xE4A9,0xE4AA,0xE4AB,0xE4AC,0xE4AD,0xE4AE,0xE4AF,0xE4B0,0xE4B1,0xE4B2,0xE4B3,0xE4B4,0xE4B5,0xE4B6,0xE4B7,0xE4B8,0xE4B9,0xE4BA,0xE4BB,0xE4BC,0xE4BD,0xE4BE,0xE4BF,0xE4C0,0xE4C1,0xE4C2,0xE4C3,0xE4C4,0xE4C5 \ No newline at end of file diff --git a/src/fast_io/include/fast_io_unit/gb18030_impl/gb18030_uni4_tb.h b/src/fast_io/include/fast_io_unit/gb18030_impl/gb18030_uni4_tb.h new file mode 100644 index 0000000..4f54418 --- /dev/null +++ b/src/fast_io/include/fast_io_unit/gb18030_impl/gb18030_uni4_tb.h @@ -0,0 +1 @@ +0x2011,0x2012,0x2017,0x201A,0x201B,0x201E,0x201F,0x2020,0x2021,0x2022,0x2023,0x2024,0x2027,0x2028,0x2029,0x202A,0x202B,0x202C,0x202D,0x202E,0x202F,0x2031,0x2034,0x2036,0x2037,0x2038,0x2039,0x203A,0x203C,0x203D,0x203E,0x203F,0x2040,0x2041,0x2042,0x2043,0x2044,0x2045,0x2046,0x2047,0x2048,0x2049,0x204A,0x204B,0x204C,0x204D,0x204E,0x204F,0x2050,0x2051,0x2052,0x2053,0x2054,0x2055,0x2056,0x2057,0x2058,0x2059,0x205A,0x205B,0x205C,0x205D,0x205E,0x205F,0x2060,0x2061,0x2062,0x2063,0x2064,0x2065,0x2066,0x2067,0x2068,0x2069,0x206A,0x206B,0x206C,0x206D,0x206E,0x206F,0x2070,0x2071,0x2072,0x2073,0x2074,0x2075,0x2076,0x2077,0x2078,0x2079,0x207A,0x207B,0x207C,0x207D,0x207E,0x207F,0x2080,0x2081,0x2082,0x2083,0x2084,0x2085,0x2086,0x2087,0x2088,0x2089,0x208A,0x208B,0x208C,0x208D,0x208E,0x208F,0x2090,0x2091,0x2092,0x2093,0x2094,0x2095,0x2096,0x2097,0x2098,0x2099,0x209A,0x209B,0x209C,0x209D,0x209E,0x209F,0x20A0,0x20A1,0x20A2,0x20A3,0x20A4,0x20A5,0x20A6,0x20A7,0x20A8,0x20A9,0x20AA,0x20AB,0x20AD,0x20AE,0x20AF,0x20B0,0x20B1,0x20B2,0x20B3,0x20B4,0x20B5,0x20B6,0x20B7,0x20B8,0x20B9,0x20BA,0x20BB,0x20BC,0x20BD,0x20BE,0x20BF,0x20C0,0x20C1,0x20C2,0x20C3,0x20C4,0x20C5,0x20C6,0x20C7,0x20C8,0x20C9,0x20CA,0x20CB,0x20CC,0x20CD,0x20CE,0x20CF,0x20D0,0x20D1,0x20D2,0x20D3,0x20D4,0x20D5,0x20D6,0x20D7,0x20D8,0x20D9,0x20DA,0x20DB,0x20DC,0x20DD,0x20DE,0x20DF,0x20E0,0x20E1,0x20E2,0x20E3,0x20E4,0x20E5,0x20E6,0x20E7,0x20E8,0x20E9,0x20EA,0x20EB,0x20EC,0x20ED,0x20EE,0x20EF,0x20F0,0x20F1,0x20F2,0x20F3,0x20F4,0x20F5,0x20F6,0x20F7,0x20F8,0x20F9,0x20FA,0x20FB,0x20FC,0x20FD,0x20FE,0x20FF,0x2100,0x2101,0x2102,0x2104,0x2106,0x2107,0x2108,0x210A,0x210B,0x210C,0x210D,0x210E,0x210F,0x2110,0x2111,0x2112,0x2113,0x2114,0x2115,0x2117,0x2118,0x2119,0x211A,0x211B,0x211C,0x211D,0x211E,0x211F,0x2120,0x2122,0x2123,0x2124,0x2125,0x2126,0x2127,0x2128,0x2129,0x212A,0x212B,0x212C,0x212D,0x212E,0x212F,0x2130,0x2131,0x2132,0x2133,0x2134,0x2135,0x2136,0x2137,0x2138,0x2139,0x213A,0x213B,0x213C,0x213D,0x213E,0x213F,0x2140,0x2141,0x2142,0x2143,0x2144,0x2145,0x2146,0x2147,0x2148,0x2149,0x214A,0x214B,0x214C,0x214D,0x214E,0x214F,0x2150,0x2151,0x2152,0x2153,0x2154,0x2155,0x2156,0x2157,0x2158,0x2159,0x215A,0x215B,0x215C,0x215D,0x215E,0x215F,0x216C,0x216D,0x216E,0x216F,0x217A,0x217B,0x217C,0x217D,0x217E,0x217F,0x2180,0x2181,0x2182,0x2183,0x2184,0x2185,0x2186,0x2187,0x2188,0x2189,0x218A,0x218B,0x218C,0x218D,0x218E,0x218F,0x2194,0x2195,0x219A,0x219B,0x219C,0x219D,0x219E,0x219F,0x21A0,0x21A1,0x21A2,0x21A3,0x21A4,0x21A5,0x21A6,0x21A7,0x21A8,0x21A9,0x21AA,0x21AB,0x21AC,0x21AD,0x21AE,0x21AF,0x21B0,0x21B1,0x21B2,0x21B3,0x21B4,0x21B5,0x21B6,0x21B7,0x21B8,0x21B9,0x21BA,0x21BB,0x21BC,0x21BD,0x21BE,0x21BF,0x21C0,0x21C1,0x21C2,0x21C3,0x21C4,0x21C5,0x21C6,0x21C7,0x21C8,0x21C9,0x21CA,0x21CB,0x21CC,0x21CD,0x21CE,0x21CF,0x21D0,0x21D1,0x21D2,0x21D3,0x21D4,0x21D5,0x21D6,0x21D7,0x21D8,0x21D9,0x21DA,0x21DB,0x21DC,0x21DD,0x21DE,0x21DF,0x21E0,0x21E1,0x21E2,0x21E3,0x21E4,0x21E5,0x21E6,0x21E7,0x21E8,0x21E9,0x21EA,0x21EB,0x21EC,0x21ED,0x21EE,0x21EF,0x21F0,0x21F1,0x21F2,0x21F3,0x21F4,0x21F5,0x21F6,0x21F7,0x21F8,0x21F9,0x21FA,0x21FB,0x21FC,0x21FD,0x21FE,0x21FF,0x2200,0x2201,0x2202,0x2203,0x2204,0x2205,0x2206,0x2207,0x2209,0x220A,0x220B,0x220C,0x220D,0x220E,0x2210,0x2212,0x2213,0x2214,0x2216,0x2217,0x2218,0x2219,0x221B,0x221C,0x2221,0x2222,0x2224,0x2226,0x222C,0x222D,0x222F,0x2230,0x2231,0x2232,0x2233,0x2238,0x2239,0x223A,0x223B,0x223C,0x223E,0x223F,0x2240,0x2241,0x2242,0x2243,0x2244,0x2245,0x2246,0x2247,0x2249,0x224A,0x224B,0x224D,0x224E,0x224F,0x2250,0x2251,0x2253,0x2254,0x2255,0x2256,0x2257,0x2258,0x2259,0x225A,0x225B,0x225C,0x225D,0x225E,0x225F,0x2262,0x2263,0x2268,0x2269,0x226A,0x226B,0x226C,0x226D,0x2270,0x2271,0x2272,0x2273,0x2274,0x2275,0x2276,0x2277,0x2278,0x2279,0x227A,0x227B,0x227C,0x227D,0x227E,0x227F,0x2280,0x2281,0x2282,0x2283,0x2284,0x2285,0x2286,0x2287,0x2288,0x2289,0x228A,0x228B,0x228C,0x228D,0x228E,0x228F,0x2290,0x2291,0x2292,0x2293,0x2294,0x2296,0x2297,0x2298,0x229A,0x229B,0x229C,0x229D,0x229E,0x229F,0x22A0,0x22A1,0x22A2,0x22A3,0x22A4,0x22A6,0x22A7,0x22A8,0x22A9,0x22AA,0x22AB,0x22AC,0x22AD,0x22AE,0x22AF,0x22B0,0x22B1,0x22B2,0x22B3,0x22B4,0x22B5,0x22B6,0x22B7,0x22B8,0x22B9,0x22BA,0x22BB,0x22BC,0x22BD,0x22BE,0x22C0,0x22C1,0x22C2,0x22C3,0x22C4,0x22C5,0x22C6,0x22C7,0x22C8,0x22C9,0x22CA,0x22CB,0x22CC,0x22CD,0x22CE,0x22CF,0x22D0,0x22D1,0x22D2,0x22D3,0x22D4,0x22D5,0x22D6,0x22D7,0x22D8,0x22D9,0x22DA,0x22DB,0x22DC,0x22DD,0x22DE,0x22DF,0x22E0,0x22E1,0x22E2,0x22E3,0x22E4,0x22E5,0x22E6,0x22E7,0x22E8,0x22E9,0x22EA,0x22EB,0x22EC,0x22ED,0x22EE,0x22EF,0x22F0,0x22F1,0x22F2,0x22F3,0x22F4,0x22F5,0x22F6,0x22F7,0x22F8,0x22F9,0x22FA,0x22FB,0x22FC,0x22FD,0x22FE,0x22FF,0x2300,0x2301,0x2302,0x2303,0x2304,0x2305,0x2306,0x2307,0x2308,0x2309,0x230A,0x230B,0x230C,0x230D,0x230E,0x230F,0x2310,0x2311,0x2313,0x2314,0x2315,0x2316,0x2317,0x2318,0x2319,0x231A,0x231B,0x231C,0x231D,0x231E,0x231F,0x2320,0x2321,0x2322,0x2323,0x2324,0x2325,0x2326,0x2327,0x2328,0x2329,0x232A,0x232B,0x232C,0x232D,0x232E,0x232F,0x2330,0x2331,0x2332,0x2333,0x2334,0x2335,0x2336,0x2337,0x2338,0x2339,0x233A,0x233B,0x233C,0x233D,0x233E,0x233F,0x2340,0x2341,0x2342,0x2343,0x2344,0x2345,0x2346,0x2347,0x2348,0x2349,0x234A,0x234B,0x234C,0x234D,0x234E,0x234F,0x2350,0x2351,0x2352,0x2353,0x2354,0x2355,0x2356,0x2357,0x2358,0x2359,0x235A,0x235B,0x235C,0x235D,0x235E,0x235F,0x2360,0x2361,0x2362,0x2363,0x2364,0x2365,0x2366,0x2367,0x2368,0x2369,0x236A,0x236B,0x236C,0x236D,0x236E,0x236F,0x2370,0x2371,0x2372,0x2373,0x2374,0x2375,0x2376,0x2377,0x2378,0x2379,0x237A,0x237B,0x237C,0x237D,0x237E,0x237F,0x2380,0x2381,0x2382,0x2383,0x2384,0x2385,0x2386,0x2387,0x2388,0x2389,0x238A,0x238B,0x238C,0x238D,0x238E,0x238F,0x2390,0x2391,0x2392,0x2393,0x2394,0x2395,0x2396,0x2397,0x2398,0x2399,0x239A,0x239B,0x239C,0x239D,0x239E,0x239F,0x23A0,0x23A1,0x23A2,0x23A3,0x23A4,0x23A5,0x23A6,0x23A7,0x23A8,0x23A9,0x23AA,0x23AB,0x23AC,0x23AD,0x23AE,0x23AF,0x23B0,0x23B1,0x23B2,0x23B3,0x23B4,0x23B5,0x23B6,0x23B7,0x23B8,0x23B9,0x23BA,0x23BB,0x23BC,0x23BD,0x23BE,0x23BF,0x23C0,0x23C1,0x23C2,0x23C3,0x23C4,0x23C5,0x23C6,0x23C7,0x23C8,0x23C9,0x23CA,0x23CB,0x23CC,0x23CD,0x23CE,0x23CF,0x23D0,0x23D1,0x23D2,0x23D3,0x23D4,0x23D5,0x23D6,0x23D7,0x23D8,0x23D9,0x23DA,0x23DB,0x23DC,0x23DD,0x23DE,0x23DF,0x23E0,0x23E1,0x23E2,0x23E3,0x23E4,0x23E5,0x23E6,0x23E7,0x23E8,0x23E9,0x23EA,0x23EB,0x23EC,0x23ED,0x23EE,0x23EF,0x23F0,0x23F1,0x23F2,0x23F3,0x23F4,0x23F5,0x23F6,0x23F7,0x23F8,0x23F9,0x23FA,0x23FB,0x23FC,0x23FD,0x23FE,0x23FF,0x2400,0x2401,0x2402,0x2403,0x2404,0x2405,0x2406,0x2407,0x2408,0x2409,0x240A,0x240B,0x240C,0x240D,0x240E,0x240F,0x2410,0x2411,0x2412,0x2413,0x2414,0x2415,0x2416,0x2417,0x2418,0x2419,0x241A,0x241B,0x241C,0x241D,0x241E,0x241F,0x2420,0x2421,0x2422,0x2423,0x2424,0x2425,0x2426,0x2427,0x2428,0x2429,0x242A,0x242B,0x242C,0x242D,0x242E,0x242F,0x2430,0x2431,0x2432,0x2433,0x2434,0x2435,0x2436,0x2437,0x2438,0x2439,0x243A,0x243B,0x243C,0x243D,0x243E,0x243F,0x2440,0x2441,0x2442,0x2443,0x2444,0x2445,0x2446,0x2447,0x2448,0x2449,0x244A,0x244B,0x244C,0x244D,0x244E,0x244F,0x2450,0x2451,0x2452,0x2453,0x2454,0x2455,0x2456,0x2457,0x2458,0x2459,0x245A,0x245B,0x245C,0x245D,0x245E,0x245F,0x246A,0x246B,0x246C,0x246D,0x246E,0x246F,0x2470,0x2471,0x2472,0x2473,0x249C,0x249D,0x249E,0x249F,0x24A0,0x24A1,0x24A2,0x24A3,0x24A4,0x24A5,0x24A6,0x24A7,0x24A8,0x24A9,0x24AA,0x24AB,0x24AC,0x24AD,0x24AE,0x24AF,0x24B0,0x24B1,0x24B2,0x24B3,0x24B4,0x24B5,0x24B6,0x24B7,0x24B8,0x24B9,0x24BA,0x24BB,0x24BC,0x24BD,0x24BE,0x24BF,0x24C0,0x24C1,0x24C2,0x24C3,0x24C4,0x24C5,0x24C6,0x24C7,0x24C8,0x24C9,0x24CA,0x24CB,0x24CC,0x24CD,0x24CE,0x24CF,0x24D0,0x24D1,0x24D2,0x24D3,0x24D4,0x24D5,0x24D6,0x24D7,0x24D8,0x24D9,0x24DA,0x24DB,0x24DC,0x24DD,0x24DE,0x24DF,0x24E0,0x24E1,0x24E2,0x24E3,0x24E4,0x24E5,0x24E6,0x24E7,0x24E8,0x24E9,0x24EA,0x24EB,0x24EC,0x24ED,0x24EE,0x24EF,0x24F0,0x24F1,0x24F2,0x24F3,0x24F4,0x24F5,0x24F6,0x24F7,0x24F8,0x24F9,0x24FA,0x24FB,0x24FC,0x24FD,0x24FE,0x24FF,0x254C,0x254D,0x254E,0x254F,0x2574,0x2575,0x2576,0x2577,0x2578,0x2579,0x257A,0x257B,0x257C,0x257D,0x257E,0x257F,0x2580,0x2590,0x2591,0x2592,0x2596,0x2597,0x2598,0x2599,0x259A,0x259B,0x259C,0x259D,0x259E,0x259F,0x25A2,0x25A3,0x25A4,0x25A5,0x25A6,0x25A7,0x25A8,0x25A9,0x25AA,0x25AB,0x25AC,0x25AD,0x25AE,0x25AF,0x25B0,0x25B1,0x25B4,0x25B5,0x25B6,0x25B7,0x25B8,0x25B9,0x25BA,0x25BB,0x25BE,0x25BF,0x25C0,0x25C1,0x25C2,0x25C3,0x25C4,0x25C5,0x25C8,0x25C9,0x25CA,0x25CC,0x25CD,0x25D0,0x25D1,0x25D2,0x25D3,0x25D4,0x25D5,0x25D6,0x25D7,0x25D8,0x25D9,0x25DA,0x25DB,0x25DC,0x25DD,0x25DE,0x25DF,0x25E0,0x25E1,0x25E6,0x25E7,0x25E8,0x25E9,0x25EA,0x25EB,0x25EC,0x25ED,0x25EE,0x25EF,0x25F0,0x25F1,0x25F2,0x25F3,0x25F4,0x25F5,0x25F6,0x25F7,0x25F8,0x25F9,0x25FA,0x25FB,0x25FC,0x25FD,0x25FE,0x25FF,0x2600,0x2601,0x2602,0x2603,0x2604,0x2607,0x2608,0x260A,0x260B,0x260C,0x260D,0x260E,0x260F,0x2610,0x2611,0x2612,0x2613,0x2614,0x2615,0x2616,0x2617,0x2618,0x2619,0x261A,0x261B,0x261C,0x261D,0x261E,0x261F,0x2620,0x2621,0x2622,0x2623,0x2624,0x2625,0x2626,0x2627,0x2628,0x2629,0x262A,0x262B,0x262C,0x262D,0x262E,0x262F,0x2630,0x2631,0x2632,0x2633,0x2634,0x2635,0x2636,0x2637,0x2638,0x2639,0x263A,0x263B,0x263C,0x263D,0x263E,0x263F,0x2641,0x2E82,0x2E83,0x2E85,0x2E86,0x2E87,0x2E89,0x2E8A,0x2E8D,0x2E8E,0x2E8F,0x2E90,0x2E91,0x2E92,0x2E93,0x2E94,0x2E95,0x2E96,0x2E98,0x2E99,0x2E9A,0x2E9B,0x2E9C,0x2E9D,0x2E9E,0x2E9F,0x2EA0,0x2EA1,0x2EA2,0x2EA3,0x2EA4,0x2EA5,0x2EA6,0x2EA8,0x2EA9,0x2EAB,0x2EAC,0x2EAD,0x2EAF,0x2EB0,0x2EB1,0x2EB2,0x2EB4,0x2EB5,0x2EB8,0x2EB9,0x2EBA,0x2EBC,0x2EBD,0x2EBE,0x2EBF,0x2EC0,0x2EC1,0x2EC2,0x2EC3,0x2EC4,0x2EC5,0x2EC6,0x2EC7,0x2EC8,0x2EC9,0x2ECB,0x2ECC,0x2ECD,0x2ECE,0x2ECF,0x2ED0,0x2ED1,0x2ED2,0x2ED3,0x2ED4,0x2ED5,0x2ED6,0x2ED7,0x2ED8,0x2ED9,0x2EDA,0x2EDB,0x2EDC,0x2EDD,0x2EDE,0x2EDF,0x2EE0,0x2EE1,0x2EE2,0x2EE3,0x2EE4,0x2EE5,0x2EE6,0x2EE7,0x2EE8,0x2EE9,0x2EEA,0x2EEB,0x2EEC,0x2EED,0x2EEE,0x2EEF,0x2EF0,0x2EF1,0x2EF2,0x2EF3,0x2EF4,0x2EF5,0x2EF6,0x2EF7,0x2EF8,0x2EF9,0x2EFA,0x2EFB,0x2EFC,0x2EFD,0x2EFE,0x2EFF,0x2F00,0x2F01,0x2F02,0x2F03,0x2F04,0x2F05,0x2F06,0x2F07,0x2F08,0x2F09,0x2F0A,0x2F0B,0x2F0C,0x2F0D,0x2F0E,0x2F0F,0x2F10,0x2F11,0x2F12,0x2F13,0x2F14,0x2F15,0x2F16,0x2F17,0x2F18,0x2F19,0x2F1A,0x2F1B,0x2F1C,0x2F1D,0x2F1E,0x2F1F,0x2F20,0x2F21,0x2F22,0x2F23,0x2F24,0x2F25,0x2F26,0x2F27,0x2F28,0x2F29,0x2F2A,0x2F2B,0x2F2C,0x2F2D,0x2F2E,0x2F2F,0x2F30,0x2F31,0x2F32,0x2F33,0x2F34,0x2F35,0x2F36,0x2F37,0x2F38,0x2F39,0x2F3A,0x2F3B,0x2F3C,0x2F3D,0x2F3E,0x2F3F,0x2F40,0x2F41,0x2F42,0x2F43,0x2F44,0x2F45,0x2F46,0x2F47,0x2F48,0x2F49,0x2F4A,0x2F4B,0x2F4C,0x2F4D,0x2F4E,0x2F4F,0x2F50,0x2F51,0x2F52,0x2F53,0x2F54,0x2F55,0x2F56,0x2F57,0x2F58,0x2F59,0x2F5A,0x2F5B,0x2F5C,0x2F5D,0x2F5E,0x2F5F,0x2F60,0x2F61,0x2F62,0x2F63,0x2F64,0x2F65,0x2F66,0x2F67,0x2F68,0x2F69,0x2F6A,0x2F6B,0x2F6C,0x2F6D,0x2F6E,0x2F6F,0x2F70,0x2F71,0x2F72,0x2F73,0x2F74,0x2F75,0x2F76,0x2F77,0x2F78,0x2F79,0x2F7A,0x2F7B,0x2F7C,0x2F7D,0x2F7E,0x2F7F,0x2F80,0x2F81,0x2F82,0x2F83,0x2F84,0x2F85,0x2F86,0x2F87,0x2F88,0x2F89,0x2F8A,0x2F8B,0x2F8C,0x2F8D,0x2F8E,0x2F8F,0x2F90,0x2F91,0x2F92,0x2F93,0x2F94,0x2F95,0x2F96,0x2F97,0x2F98,0x2F99,0x2F9A,0x2F9B,0x2F9C,0x2F9D,0x2F9E,0x2F9F,0x2FA0,0x2FA1,0x2FA2,0x2FA3,0x2FA4,0x2FA5,0x2FA6,0x2FA7,0x2FA8,0x2FA9,0x2FAA,0x2FAB,0x2FAC,0x2FAD,0x2FAE,0x2FAF,0x2FB0,0x2FB1,0x2FB2,0x2FB3,0x2FB4,0x2FB5,0x2FB6,0x2FB7,0x2FB8,0x2FB9,0x2FBA,0x2FBB,0x2FBC,0x2FBD,0x2FBE,0x2FBF,0x2FC0,0x2FC1,0x2FC2,0x2FC3,0x2FC4,0x2FC5,0x2FC6,0x2FC7,0x2FC8,0x2FC9,0x2FCA,0x2FCB,0x2FCC,0x2FCD,0x2FCE,0x2FCF,0x2FD0,0x2FD1,0x2FD2,0x2FD3,0x2FD4,0x2FD5,0x2FD6,0x2FD7,0x2FD8,0x2FD9,0x2FDA,0x2FDB,0x2FDC,0x2FDD,0x2FDE,0x2FDF,0x2FE0,0x2FE1,0x2FE2,0x2FE3,0x2FE4,0x2FE5,0x2FE6,0x2FE7,0x2FE8,0x2FE9,0x2FEA,0x2FEB,0x2FEC,0x2FED,0x2FEE,0x2FEF,0x2FFC,0x2FFD,0x2FFE,0x2FFF,0x3004,0x3018,0x3019,0x301A,0x301B,0x301C,0x301F,0x3020,0x302A,0x302B,0x302C,0x302D,0x302E,0x302F,0x3030,0x3031,0x3032,0x3033,0x3034,0x3035,0x3036,0x3037,0x3038,0x3039,0x303A,0x303B,0x303C,0x303D,0x303F,0x3040,0x3094,0x3095,0x3096,0x3097,0x3098,0x3099,0x309A,0x309F,0x30A0,0x30F7,0x30F8,0x30F9,0x30FA,0x30FB,0x30FF,0x3100,0x3101,0x3102,0x3103,0x3104,0x312A,0x312B,0x312C,0x312D,0x312E,0x312F,0x3130,0x3131,0x3132,0x3133,0x3134,0x3135,0x3136,0x3137,0x3138,0x3139,0x313A,0x313B,0x313C,0x313D,0x313E,0x313F,0x3140,0x3141,0x3142,0x3143,0x3144,0x3145,0x3146,0x3147,0x3148,0x3149,0x314A,0x314B,0x314C,0x314D,0x314E,0x314F,0x3150,0x3151,0x3152,0x3153,0x3154,0x3155,0x3156,0x3157,0x3158,0x3159,0x315A,0x315B,0x315C,0x315D,0x315E,0x315F,0x3160,0x3161,0x3162,0x3163,0x3164,0x3165,0x3166,0x3167,0x3168,0x3169,0x316A,0x316B,0x316C,0x316D,0x316E,0x316F,0x3170,0x3171,0x3172,0x3173,0x3174,0x3175,0x3176,0x3177,0x3178,0x3179,0x317A,0x317B,0x317C,0x317D,0x317E,0x317F,0x3180,0x3181,0x3182,0x3183,0x3184,0x3185,0x3186,0x3187,0x3188,0x3189,0x318A,0x318B,0x318C,0x318D,0x318E,0x318F,0x3190,0x3191,0x3192,0x3193,0x3194,0x3195,0x3196,0x3197,0x3198,0x3199,0x319A,0x319B,0x319C,0x319D,0x319E,0x319F,0x31A0,0x31A1,0x31A2,0x31A3,0x31A4,0x31A5,0x31A6,0x31A7,0x31A8,0x31A9,0x31AA,0x31AB,0x31AC,0x31AD,0x31AE,0x31AF,0x31B0,0x31B1,0x31B2,0x31B3,0x31B4,0x31B5,0x31B6,0x31B7,0x31B8,0x31B9,0x31BA,0x31BB,0x31BC,0x31BD,0x31BE,0x31BF,0x31C0,0x31C1,0x31C2,0x31C3,0x31C4,0x31C5,0x31C6,0x31C7,0x31C8,0x31C9,0x31CA,0x31CB,0x31CC,0x31CD,0x31CE,0x31CF,0x31D0,0x31D1,0x31D2,0x31D3,0x31D4,0x31D5,0x31D6,0x31D7,0x31D8,0x31D9,0x31DA,0x31DB,0x31DC,0x31DD,0x31DE,0x31DF,0x31E0,0x31E1,0x31E2,0x31E3,0x31E4,0x31E5,0x31E6,0x31E7,0x31E8,0x31E9,0x31EA,0x31EB,0x31EC,0x31ED,0x31EE,0x31EF,0x31F0,0x31F1,0x31F2,0x31F3,0x31F4,0x31F5,0x31F6,0x31F7,0x31F8,0x31F9,0x31FA,0x31FB,0x31FC,0x31FD,0x31FE,0x31FF,0x3200,0x3201,0x3202,0x3203,0x3204,0x3205,0x3206,0x3207,0x3208,0x3209,0x320A,0x320B,0x320C,0x320D,0x320E,0x320F,0x3210,0x3211,0x3212,0x3213,0x3214,0x3215,0x3216,0x3217,0x3218,0x3219,0x321A,0x321B,0x321C,0x321D,0x321E,0x321F,0x322A,0x322B,0x322C,0x322D,0x322E,0x322F,0x3230,0x3232,0x3233,0x3234,0x3235,0x3236,0x3237,0x3238,0x3239,0x323A,0x323B,0x323C,0x323D,0x323E,0x323F,0x3240,0x3241,0x3242,0x3243,0x3244,0x3245,0x3246,0x3247,0x3248,0x3249,0x324A,0x324B,0x324C,0x324D,0x324E,0x324F,0x3250,0x3251,0x3252,0x3253,0x3254,0x3255,0x3256,0x3257,0x3258,0x3259,0x325A,0x325B,0x325C,0x325D,0x325E,0x325F,0x3260,0x3261,0x3262,0x3263,0x3264,0x3265,0x3266,0x3267,0x3268,0x3269,0x326A,0x326B,0x326C,0x326D,0x326E,0x326F,0x3270,0x3271,0x3272,0x3273,0x3274,0x3275,0x3276,0x3277,0x3278,0x3279,0x327A,0x327B,0x327C,0x327D,0x327E,0x327F,0x3280,0x3281,0x3282,0x3283,0x3284,0x3285,0x3286,0x3287,0x3288,0x3289,0x328A,0x328B,0x328C,0x328D,0x328E,0x328F,0x3290,0x3291,0x3292,0x3293,0x3294,0x3295,0x3296,0x3297,0x3298,0x3299,0x329A,0x329B,0x329C,0x329D,0x329E,0x329F,0x32A0,0x32A1,0x32A2,0x32A4,0x32A5,0x32A6,0x32A7,0x32A8,0x32A9,0x32AA,0x32AB,0x32AC,0x32AD,0x32AE,0x32AF,0x32B0,0x32B1,0x32B2,0x32B3,0x32B4,0x32B5,0x32B6,0x32B7,0x32B8,0x32B9,0x32BA,0x32BB,0x32BC,0x32BD,0x32BE,0x32BF,0x32C0,0x32C1,0x32C2,0x32C3,0x32C4,0x32C5,0x32C6,0x32C7,0x32C8,0x32C9,0x32CA,0x32CB,0x32CC,0x32CD,0x32CE,0x32CF,0x32D0,0x32D1,0x32D2,0x32D3,0x32D4,0x32D5,0x32D6,0x32D7,0x32D8,0x32D9,0x32DA,0x32DB,0x32DC,0x32DD,0x32DE,0x32DF,0x32E0,0x32E1,0x32E2,0x32E3,0x32E4,0x32E5,0x32E6,0x32E7,0x32E8,0x32E9,0x32EA,0x32EB,0x32EC,0x32ED,0x32EE,0x32EF,0x32F0,0x32F1,0x32F2,0x32F3,0x32F4,0x32F5,0x32F6,0x32F7,0x32F8,0x32F9,0x32FA,0x32FB,0x32FC,0x32FD,0x32FE,0x32FF,0x3300,0x3301,0x3302,0x3303,0x3304,0x3305,0x3306,0x3307,0x3308,0x3309,0x330A,0x330B,0x330C,0x330D,0x330E,0x330F,0x3310,0x3311,0x3312,0x3313,0x3314,0x3315,0x3316,0x3317,0x3318,0x3319,0x331A,0x331B,0x331C,0x331D,0x331E,0x331F,0x3320,0x3321,0x3322,0x3323,0x3324,0x3325,0x3326,0x3327,0x3328,0x3329,0x332A,0x332B,0x332C,0x332D,0x332E,0x332F,0x3330,0x3331,0x3332,0x3333,0x3334,0x3335,0x3336,0x3337,0x3338,0x3339,0x333A,0x333B,0x333C,0x333D,0x333E,0x333F,0x3340,0x3341,0x3342,0x3343,0x3344,0x3345,0x3346,0x3347,0x3348,0x3349,0x334A,0x334B,0x334C,0x334D,0x334E,0x334F,0x3350,0x3351,0x3352,0x3353,0x3354,0x3355,0x3356,0x3357,0x3358,0x3359,0x335A,0x335B,0x335C,0x335D,0x335E,0x335F,0x3360,0x3361,0x3362,0x3363,0x3364,0x3365,0x3366,0x3367,0x3368,0x3369,0x336A,0x336B,0x336C,0x336D,0x336E,0x336F,0x3370,0x3371,0x3372,0x3373,0x3374,0x3375,0x3376,0x3377,0x3378,0x3379,0x337A,0x337B,0x337C,0x337D,0x337E,0x337F,0x3380,0x3381,0x3382,0x3383,0x3384,0x3385,0x3386,0x3387,0x3388,0x3389,0x338A,0x338B,0x338C,0x338D,0x3390,0x3391,0x3392,0x3393,0x3394,0x3395,0x3396,0x3397,0x3398,0x3399,0x339A,0x339B,0x339F,0x33A0,0x33A2,0x33A3,0x33A4,0x33A5,0x33A6,0x33A7,0x33A8,0x33A9,0x33AA,0x33AB,0x33AC,0x33AD,0x33AE,0x33AF,0x33B0,0x33B1,0x33B2,0x33B3,0x33B4,0x33B5,0x33B6,0x33B7,0x33B8,0x33B9,0x33BA,0x33BB,0x33BC,0x33BD,0x33BE,0x33BF,0x33C0,0x33C1,0x33C2,0x33C3,0x33C5,0x33C6,0x33C7,0x33C8,0x33C9,0x33CA,0x33CB,0x33CC,0x33CD,0x33CF,0x33D0,0x33D3,0x33D4,0x33D6,0x33D7,0x33D8,0x33D9,0x33DA,0x33DB,0x33DC,0x33DD,0x33DE,0x33DF,0x33E0,0x33E1,0x33E2,0x33E3,0x33E4,0x33E5,0x33E6,0x33E7,0x33E8,0x33E9,0x33EA,0x33EB,0x33EC,0x33ED,0x33EE,0x33EF,0x33F0,0x33F1,0x33F2,0x33F3,0x33F4,0x33F5,0x33F6,0x33F7,0x33F8,0x33F9,0x33FA,0x33FB,0x33FC,0x33FD,0x33FE,0x33FF,0x3400,0x3401,0x3402,0x3403,0x3404,0x3405,0x3406,0x3407,0x3408,0x3409,0x340A,0x340B,0x340C,0x340D,0x340E,0x340F,0x3410,0x3411,0x3412,0x3413,0x3414,0x3415,0x3416,0x3417,0x3418,0x3419,0x341A,0x341B,0x341C,0x341D,0x341E,0x341F,0x3420,0x3421,0x3422,0x3423,0x3424,0x3425,0x3426,0x3427,0x3428,0x3429,0x342A,0x342B,0x342C,0x342D,0x342E,0x342F,0x3430,0x3431,0x3432,0x3433,0x3434,0x3435,0x3436,0x3437,0x3438,0x3439,0x343A,0x343B,0x343C,0x343D,0x343E,0x343F,0x3440,0x3441,0x3442,0x3443,0x3444,0x3445,0x3446,0x3448,0x3449,0x344A,0x344B,0x344C,0x344D,0x344E,0x344F,0x3450,0x3451,0x3452,0x3453,0x3454,0x3455,0x3456,0x3457,0x3458,0x3459,0x345A,0x345B,0x345C,0x345D,0x345E,0x345F,0x3460,0x3461,0x3462,0x3463,0x3464,0x3465,0x3466,0x3467,0x3468,0x3469,0x346A,0x346B,0x346C,0x346D,0x346E,0x346F,0x3470,0x3471,0x3472,0x3474,0x3475,0x3476,0x3477,0x3478,0x3479,0x347A,0x347B,0x347C,0x347D,0x347E,0x347F,0x3480,0x3481,0x3482,0x3483,0x3484,0x3485,0x3486,0x3487,0x3488,0x3489,0x348A,0x348B,0x348C,0x348D,0x348E,0x348F,0x3490,0x3491,0x3492,0x3493,0x3494,0x3495,0x3496,0x3497,0x3498,0x3499,0x349A,0x349B,0x349C,0x349D,0x349E,0x349F,0x34A0,0x34A1,0x34A2,0x34A3,0x34A4,0x34A5,0x34A6,0x34A7,0x34A8,0x34A9,0x34AA,0x34AB,0x34AC,0x34AD,0x34AE,0x34AF,0x34B0,0x34B1,0x34B2,0x34B3,0x34B4,0x34B5,0x34B6,0x34B7,0x34B8,0x34B9,0x34BA,0x34BB,0x34BC,0x34BD,0x34BE,0x34BF,0x34C0,0x34C1,0x34C2,0x34C3,0x34C4,0x34C5,0x34C6,0x34C7,0x34C8,0x34C9,0x34CA,0x34CB,0x34CC,0x34CD,0x34CE,0x34CF,0x34D0,0x34D1,0x34D2,0x34D3,0x34D4,0x34D5,0x34D6,0x34D7,0x34D8,0x34D9,0x34DA,0x34DB,0x34DC,0x34DD,0x34DE,0x34DF,0x34E0,0x34E1,0x34E2,0x34E3,0x34E4,0x34E5,0x34E6,0x34E7,0x34E8,0x34E9,0x34EA,0x34EB,0x34EC,0x34ED,0x34EE,0x34EF,0x34F0,0x34F1,0x34F2,0x34F3,0x34F4,0x34F5,0x34F6,0x34F7,0x34F8,0x34F9,0x34FA,0x34FB,0x34FC,0x34FD,0x34FE,0x34FF,0x3500,0x3501,0x3502,0x3503,0x3504,0x3505,0x3506,0x3507,0x3508,0x3509,0x350A,0x350B,0x350C,0x350D,0x350E,0x350F,0x3510,0x3511,0x3512,0x3513,0x3514,0x3515,0x3516,0x3517,0x3518,0x3519,0x351A,0x351B,0x351C,0x351D,0x351E,0x351F,0x3520,0x3521,0x3522,0x3523,0x3524,0x3525,0x3526,0x3527,0x3528,0x3529,0x352A,0x352B,0x352C,0x352D,0x352E,0x352F,0x3530,0x3531,0x3532,0x3533,0x3534,0x3535,0x3536,0x3537,0x3538,0x3539,0x353A,0x353B,0x353C,0x353D,0x353E,0x353F,0x3540,0x3541,0x3542,0x3543,0x3544,0x3545,0x3546,0x3547,0x3548,0x3549,0x354A,0x354B,0x354C,0x354D,0x354E,0x354F,0x3550,0x3551,0x3552,0x3553,0x3554,0x3555,0x3556,0x3557,0x3558,0x3559,0x355A,0x355B,0x355C,0x355D,0x355E,0x355F,0x3560,0x3561,0x3562,0x3563,0x3564,0x3565,0x3566,0x3567,0x3568,0x3569,0x356A,0x356B,0x356C,0x356D,0x356E,0x356F,0x3570,0x3571,0x3572,0x3573,0x3574,0x3575,0x3576,0x3577,0x3578,0x3579,0x357A,0x357B,0x357C,0x357D,0x357E,0x357F,0x3580,0x3581,0x3582,0x3583,0x3584,0x3585,0x3586,0x3587,0x3588,0x3589,0x358A,0x358B,0x358C,0x358D,0x358E,0x358F,0x3590,0x3591,0x3592,0x3593,0x3594,0x3595,0x3596,0x3597,0x3598,0x3599,0x359A,0x359B,0x359C,0x359D,0x359F,0x35A0,0x35A1,0x35A2,0x35A3,0x35A4,0x35A5,0x35A6,0x35A7,0x35A8,0x35A9,0x35AA,0x35AB,0x35AC,0x35AD,0x35AE,0x35AF,0x35B0,0x35B1,0x35B2,0x35B3,0x35B4,0x35B5,0x35B6,0x35B7,0x35B8,0x35B9,0x35BA,0x35BB,0x35BC,0x35BD,0x35BE,0x35BF,0x35C0,0x35C1,0x35C2,0x35C3,0x35C4,0x35C5,0x35C6,0x35C7,0x35C8,0x35C9,0x35CA,0x35CB,0x35CC,0x35CD,0x35CE,0x35CF,0x35D0,0x35D1,0x35D2,0x35D3,0x35D4,0x35D5,0x35D6,0x35D7,0x35D8,0x35D9,0x35DA,0x35DB,0x35DC,0x35DD,0x35DE,0x35DF,0x35E0,0x35E1,0x35E2,0x35E3,0x35E4,0x35E5,0x35E6,0x35E7,0x35E8,0x35E9,0x35EA,0x35EB,0x35EC,0x35ED,0x35EE,0x35EF,0x35F0,0x35F1,0x35F2,0x35F3,0x35F4,0x35F5,0x35F6,0x35F7,0x35F8,0x35F9,0x35FA,0x35FB,0x35FC,0x35FD,0x35FE,0x35FF,0x3600,0x3601,0x3602,0x3603,0x3604,0x3605,0x3606,0x3607,0x3608,0x3609,0x360A,0x360B,0x360C,0x360D,0x360F,0x3610,0x3611,0x3612,0x3613,0x3614,0x3615,0x3616,0x3617,0x3618,0x3619,0x3919,0x391A,0x391B,0x391C,0x391D,0x391E,0x391F,0x3920,0x3921,0x3922,0x3923,0x3924,0x3925,0x3926,0x3927,0x3928,0x3929,0x392A,0x392B,0x392C,0x392D,0x392E,0x392F,0x3930,0x3931,0x3932,0x3933,0x3934,0x3935,0x3936,0x3937,0x3938,0x3939,0x393A,0x393B,0x393C,0x393D,0x393E,0x393F,0x3940,0x3941,0x3942,0x3943,0x3944,0x3945,0x3946,0x3947,0x3948,0x3949,0x394A,0x394B,0x394C,0x394D,0x394E,0x394F,0x3950,0x3951,0x3952,0x3953,0x3954,0x3955,0x3956,0x3957,0x3958,0x3959,0x395A,0x395B,0x395C,0x395D,0x395E,0x395F,0x3960,0x3961,0x3962,0x3963,0x3964,0x3965,0x3966,0x3967,0x3968,0x3969,0x396A,0x396B,0x396C,0x396D,0x396F,0x3970,0x3971,0x3972,0x3973,0x3974,0x3975,0x3976,0x3977,0x3978,0x3979,0x397A,0x397B,0x397C,0x397D,0x397E,0x397F,0x3980,0x3981,0x3982,0x3983,0x3984,0x3985,0x3986,0x3987,0x3988,0x3989,0x398A,0x398B,0x398C,0x398D,0x398E,0x398F,0x3990,0x3991,0x3992,0x3993,0x3994,0x3995,0x3996,0x3997,0x3998,0x3999,0x399A,0x399B,0x399C,0x399D,0x399E,0x399F,0x39A0,0x39A1,0x39A2,0x39A3,0x39A4,0x39A5,0x39A6,0x39A7,0x39A8,0x39A9,0x39AA,0x39AB,0x39AC,0x39AD,0x39AE,0x39AF,0x39B0,0x39B1,0x39B2,0x39B3,0x39B4,0x39B5,0x39B6,0x39B7,0x39B8,0x39B9,0x39BA,0x39BB,0x39BC,0x39BD,0x39BE,0x39BF,0x39C0,0x39C1,0x39C2,0x39C3,0x39C4,0x39C5,0x39C6,0x39C7,0x39C8,0x39C9,0x39CA,0x39CB,0x39CC,0x39CD,0x39CE,0x39D1,0x39D2,0x39D3,0x39D4,0x39D5,0x39D6,0x39D7,0x39D8,0x39D9,0x39DA,0x39DB,0x39DC,0x39DD,0x39DE,0x39E0,0x39E1,0x39E2,0x39E3,0x39E4,0x39E5,0x39E6,0x39E7,0x39E8,0x39E9,0x39EA,0x39EB,0x39EC,0x39ED,0x39EE,0x39EF,0x39F0,0x39F1,0x39F2,0x39F3,0x39F4,0x39F5,0x39F6,0x39F7,0x39F8,0x39F9,0x39FA,0x39FB,0x39FC,0x39FD,0x39FE,0x39FF,0x3A00,0x3A01,0x3A02,0x3A03,0x3A04,0x3A05,0x3A06,0x3A07,0x3A08,0x3A09,0x3A0A,0x3A0B,0x3A0C,0x3A0D,0x3A0E,0x3A0F,0x3A10,0x3A11,0x3A12,0x3A13,0x3A14,0x3A15,0x3A16,0x3A17,0x3A18,0x3A19,0x3A1A,0x3A1B,0x3A1C,0x3A1D,0x3A1E,0x3A1F,0x3A20,0x3A21,0x3A22,0x3A23,0x3A24,0x3A25,0x3A26,0x3A27,0x3A28,0x3A29,0x3A2A,0x3A2B,0x3A2C,0x3A2D,0x3A2E,0x3A2F,0x3A30,0x3A31,0x3A32,0x3A33,0x3A34,0x3A35,0x3A36,0x3A37,0x3A38,0x3A39,0x3A3A,0x3A3B,0x3A3C,0x3A3D,0x3A3E,0x3A3F,0x3A40,0x3A41,0x3A42,0x3A43,0x3A44,0x3A45,0x3A46,0x3A47,0x3A48,0x3A49,0x3A4A,0x3A4B,0x3A4C,0x3A4D,0x3A4E,0x3A4F,0x3A50,0x3A51,0x3A52,0x3A53,0x3A54,0x3A55,0x3A56,0x3A57,0x3A58,0x3A59,0x3A5A,0x3A5B,0x3A5C,0x3A5D,0x3A5E,0x3A5F,0x3A60,0x3A61,0x3A62,0x3A63,0x3A64,0x3A65,0x3A66,0x3A67,0x3A68,0x3A69,0x3A6A,0x3A6B,0x3A6C,0x3A6D,0x3A6E,0x3A6F,0x3A70,0x3A71,0x3A72,0x3A74,0x3A75,0x3A76,0x3A77,0x3A78,0x3A79,0x3A7A,0x3A7B,0x3A7C,0x3A7D,0x3A7E,0x3A7F,0x3A80,0x3A81,0x3A82,0x3A83,0x3A84,0x3A85,0x3A86,0x3A87,0x3A88,0x3A89,0x3A8A,0x3A8B,0x3A8C,0x3A8D,0x3A8E,0x3A8F,0x3A90,0x3A91,0x3A92,0x3A93,0x3A94,0x3A95,0x3A96,0x3A97,0x3A98,0x3A99,0x3A9A,0x3A9B,0x3A9C,0x3A9D,0x3A9E,0x3A9F,0x3AA0,0x3AA1,0x3AA2,0x3AA3,0x3AA4,0x3AA5,0x3AA6,0x3AA7,0x3AA8,0x3AA9,0x3AAA,0x3AAB,0x3AAC,0x3AAD,0x3AAE,0x3AAF,0x3AB0,0x3AB1,0x3AB2,0x3AB3,0x3AB4,0x3AB5,0x3AB6,0x3AB7,0x3AB8,0x3AB9,0x3ABA,0x3ABB,0x3ABC,0x3ABD,0x3ABE,0x3ABF,0x3AC0,0x3AC1,0x3AC2,0x3AC3,0x3AC4,0x3AC5,0x3AC6,0x3AC7,0x3AC8,0x3AC9,0x3ACA,0x3ACB,0x3ACC,0x3ACD,0x3ACE,0x3ACF,0x3AD0,0x3AD1,0x3AD2,0x3AD3,0x3AD4,0x3AD5,0x3AD6,0x3AD7,0x3AD8,0x3AD9,0x3ADA,0x3ADB,0x3ADC,0x3ADD,0x3ADE,0x3ADF,0x3AE0,0x3AE1,0x3AE2,0x3AE3,0x3AE4,0x3AE5,0x3AE6,0x3AE7,0x3AE8,0x3AE9,0x3AEA,0x3AEB,0x3AEC,0x3AED,0x3AEE,0x3AEF,0x3AF0,0x3AF1,0x3AF2,0x3AF3,0x3AF4,0x3AF5,0x3AF6,0x3AF7,0x3AF8,0x3AF9,0x3AFA,0x3AFB,0x3AFC,0x3AFD,0x3AFE,0x3AFF,0x3B00,0x3B01,0x3B02,0x3B03,0x3B04,0x3B05,0x3B06,0x3B07,0x3B08,0x3B09,0x3B0A,0x3B0B,0x3B0C,0x3B0D,0x3B0E,0x3B0F,0x3B10,0x3B11,0x3B12,0x3B13,0x3B14,0x3B15,0x3B16,0x3B17,0x3B18,0x3B19,0x3B1A,0x3B1B,0x3B1C,0x3B1D,0x3B1E,0x3B1F,0x3B20,0x3B21,0x3B22,0x3B23,0x3B24,0x3B25,0x3B26,0x3B27,0x3B28,0x3B29,0x3B2A,0x3B2B,0x3B2C,0x3B2D,0x3B2E,0x3B2F,0x3B30,0x3B31,0x3B32,0x3B33,0x3B34,0x3B35,0x3B36,0x3B37,0x3B38,0x3B39,0x3B3A,0x3B3B,0x3B3C,0x3B3D,0x3B3E,0x3B3F,0x3B40,0x3B41,0x3B42,0x3B43,0x3B44,0x3B45,0x3B46,0x3B47,0x3B48,0x3B49,0x3B4A,0x3B4B,0x3B4C,0x3B4D,0x3B4F,0x3B50,0x3B51,0x3B52,0x3B53,0x3B54,0x3B55,0x3B56,0x3B57,0x3B58,0x3B59,0x3B5A,0x3B5B,0x3B5C,0x3B5D,0x3B5E,0x3B5F,0x3B60,0x3B61,0x3B62,0x3B63,0x3B64,0x3B65,0x3B66,0x3B67,0x3B68,0x3B69,0x3B6A,0x3B6B,0x3B6C,0x3B6D,0x3B6E,0x3B6F,0x3B70,0x3B71,0x3B72,0x3B73,0x3B74,0x3B75,0x3B76,0x3B77,0x3B78,0x3B79,0x3B7A,0x3B7B,0x3B7C,0x3B7D,0x3B7E,0x3B7F,0x3B80,0x3B81,0x3B82,0x3B83,0x3B84,0x3B85,0x3B86,0x3B87,0x3B88,0x3B89,0x3B8A,0x3B8B,0x3B8C,0x3B8D,0x3B8E,0x3B8F,0x3B90,0x3B91,0x3B92,0x3B93,0x3B94,0x3B95,0x3B96,0x3B97,0x3B98,0x3B99,0x3B9A,0x3B9B,0x3B9C,0x3B9D,0x3B9E,0x3B9F,0x3BA0,0x3BA1,0x3BA2,0x3BA3,0x3BA4,0x3BA5,0x3BA6,0x3BA7,0x3BA8,0x3BA9,0x3BAA,0x3BAB,0x3BAC,0x3BAD,0x3BAE,0x3BAF,0x3BB0,0x3BB1,0x3BB2,0x3BB3,0x3BB4,0x3BB5,0x3BB6,0x3BB7,0x3BB8,0x3BB9,0x3BBA,0x3BBB,0x3BBC,0x3BBD,0x3BBE,0x3BBF,0x3BC0,0x3BC1,0x3BC2,0x3BC3,0x3BC4,0x3BC5,0x3BC6,0x3BC7,0x3BC8,0x3BC9,0x3BCA,0x3BCB,0x3BCC,0x3BCD,0x3BCE,0x3BCF,0x3BD0,0x3BD1,0x3BD2,0x3BD3,0x3BD4,0x3BD5,0x3BD6,0x3BD7,0x3BD8,0x3BD9,0x3BDA,0x3BDB,0x3BDC,0x3BDD,0x3BDE,0x3BDF,0x3BE0,0x3BE1,0x3BE2,0x3BE3,0x3BE4,0x3BE5,0x3BE6,0x3BE7,0x3BE8,0x3BE9,0x3BEA,0x3BEB,0x3BEC,0x3BED,0x3BEE,0x3BEF,0x3BF0,0x3BF1,0x3BF2,0x3BF3,0x3BF4,0x3BF5,0x3BF6,0x3BF7,0x3BF8,0x3BF9,0x3BFA,0x3BFB,0x3BFC,0x3BFD,0x3BFE,0x3BFF,0x3C00,0x3C01,0x3C02,0x3C03,0x3C04,0x3C05,0x3C06,0x3C07,0x3C08,0x3C09,0x3C0A,0x3C0B,0x3C0C,0x3C0D,0x3C0E,0x3C0F,0x3C10,0x3C11,0x3C12,0x3C13,0x3C14,0x3C15,0x3C16,0x3C17,0x3C18,0x3C19,0x3C1A,0x3C1B,0x3C1C,0x3C1D,0x3C1E,0x3C1F,0x3C20,0x3C21,0x3C22,0x3C23,0x3C24,0x3C25,0x3C26,0x3C27,0x3C28,0x3C29,0x3C2A,0x3C2B,0x3C2C,0x3C2D,0x3C2E,0x3C2F,0x3C30,0x3C31,0x3C32,0x3C33,0x3C34,0x3C35,0x3C36,0x3C37,0x3C38,0x3C39,0x3C3A,0x3C3B,0x3C3C,0x3C3D,0x3C3E,0x3C3F,0x3C40,0x3C41,0x3C42,0x3C43,0x3C44,0x3C45,0x3C46,0x3C47,0x3C48,0x3C49,0x3C4A,0x3C4B,0x3C4C,0x3C4D,0x3C4E,0x3C4F,0x3C50,0x3C51,0x3C52,0x3C53,0x3C54,0x3C55,0x3C56,0x3C57,0x3C58,0x3C59,0x3C5A,0x3C5B,0x3C5C,0x3C5D,0x3C5E,0x3C5F,0x3C60,0x3C61,0x3C62,0x3C63,0x3C64,0x3C65,0x3C66,0x3C67,0x3C68,0x3C69,0x3C6A,0x3C6B,0x3C6C,0x3C6D,0x3C6F,0x3C70,0x3C71,0x3C72,0x3C73,0x3C74,0x3C75,0x3C76,0x3C77,0x3C78,0x3C79,0x3C7A,0x3C7B,0x3C7C,0x3C7D,0x3C7E,0x3C7F,0x3C80,0x3C81,0x3C82,0x3C83,0x3C84,0x3C85,0x3C86,0x3C87,0x3C88,0x3C89,0x3C8A,0x3C8B,0x3C8C,0x3C8D,0x3C8E,0x3C8F,0x3C90,0x3C91,0x3C92,0x3C93,0x3C94,0x3C95,0x3C96,0x3C97,0x3C98,0x3C99,0x3C9A,0x3C9B,0x3C9C,0x3C9D,0x3C9E,0x3C9F,0x3CA0,0x3CA1,0x3CA2,0x3CA3,0x3CA4,0x3CA5,0x3CA6,0x3CA7,0x3CA8,0x3CA9,0x3CAA,0x3CAB,0x3CAC,0x3CAD,0x3CAE,0x3CAF,0x3CB0,0x3CB1,0x3CB2,0x3CB3,0x3CB4,0x3CB5,0x3CB6,0x3CB7,0x3CB8,0x3CB9,0x3CBA,0x3CBB,0x3CBC,0x3CBD,0x3CBE,0x3CBF,0x3CC0,0x3CC1,0x3CC2,0x3CC3,0x3CC4,0x3CC5,0x3CC6,0x3CC7,0x3CC8,0x3CC9,0x3CCA,0x3CCB,0x3CCC,0x3CCD,0x3CCE,0x3CCF,0x3CD0,0x3CD1,0x3CD2,0x3CD3,0x3CD4,0x3CD5,0x3CD6,0x3CD7,0x3CD8,0x3CD9,0x3CDA,0x3CDB,0x3CDC,0x3CDD,0x3CDE,0x3CDF,0x4057,0x4058,0x4059,0x405A,0x405B,0x405C,0x405D,0x405E,0x405F,0x4060,0x4061,0x4062,0x4063,0x4064,0x4065,0x4066,0x4067,0x4068,0x4069,0x406A,0x406B,0x406C,0x406D,0x406E,0x406F,0x4070,0x4071,0x4072,0x4073,0x4074,0x4075,0x4076,0x4077,0x4078,0x4079,0x407A,0x407B,0x407C,0x407D,0x407E,0x407F,0x4080,0x4081,0x4082,0x4083,0x4084,0x4085,0x4086,0x4087,0x4088,0x4089,0x408A,0x408B,0x408C,0x408D,0x408E,0x408F,0x4090,0x4091,0x4092,0x4093,0x4094,0x4095,0x4096,0x4097,0x4098,0x4099,0x409A,0x409B,0x409C,0x409D,0x409E,0x409F,0x40A0,0x40A1,0x40A2,0x40A3,0x40A4,0x40A5,0x40A6,0x40A7,0x40A8,0x40A9,0x40AA,0x40AB,0x40AC,0x40AD,0x40AE,0x40AF,0x40B0,0x40B1,0x40B2,0x40B3,0x40B4,0x40B5,0x40B6,0x40B7,0x40B8,0x40B9,0x40BA,0x40BB,0x40BC,0x40BD,0x40BE,0x40BF,0x40C0,0x40C1,0x40C2,0x40C3,0x40C4,0x40C5,0x40C6,0x40C7,0x40C8,0x40C9,0x40CA,0x40CB,0x40CC,0x40CD,0x40CE,0x40CF,0x40D0,0x40D1,0x40D2,0x40D3,0x40D4,0x40D5,0x40D6,0x40D7,0x40D8,0x40D9,0x40DA,0x40DB,0x40DC,0x40DD,0x40DE,0x40DF,0x40E0,0x40E1,0x40E2,0x40E3,0x40E4,0x40E5,0x40E6,0x40E7,0x40E8,0x40E9,0x40EA,0x40EB,0x40EC,0x40ED,0x40EE,0x40EF,0x40F0,0x40F1,0x40F2,0x40F3,0x40F4,0x40F5,0x40F6,0x40F7,0x40F8,0x40F9,0x40FA,0x40FB,0x40FC,0x40FD,0x40FE,0x40FF,0x4100,0x4101,0x4102,0x4103,0x4104,0x4105,0x4106,0x4107,0x4108,0x4109,0x410A,0x410B,0x410C,0x410D,0x410E,0x410F,0x4110,0x4111,0x4112,0x4113,0x4114,0x4115,0x4116,0x4117,0x4118,0x4119,0x411A,0x411B,0x411C,0x411D,0x411E,0x411F,0x4120,0x4121,0x4122,0x4123,0x4124,0x4125,0x4126,0x4127,0x4128,0x4129,0x412A,0x412B,0x412C,0x412D,0x412E,0x412F,0x4130,0x4131,0x4132,0x4133,0x4134,0x4135,0x4136,0x4137,0x4138,0x4139,0x413A,0x413B,0x413C,0x413D,0x413E,0x413F,0x4140,0x4141,0x4142,0x4143,0x4144,0x4145,0x4146,0x4147,0x4148,0x4149,0x414A,0x414B,0x414C,0x414D,0x414E,0x414F,0x4150,0x4151,0x4152,0x4153,0x4154,0x4155,0x4156,0x4157,0x4158,0x4159,0x415A,0x415B,0x415C,0x415D,0x415E,0x4338,0x4339,0x433A,0x433B,0x433C,0x433D,0x433E,0x433F,0x4340,0x4341,0x4342,0x4343,0x4344,0x4345,0x4346,0x4347,0x4348,0x4349,0x434A,0x434B,0x434C,0x434D,0x434E,0x434F,0x4350,0x4351,0x4352,0x4353,0x4354,0x4355,0x4356,0x4357,0x4358,0x4359,0x435A,0x435B,0x435C,0x435D,0x435E,0x435F,0x4360,0x4361,0x4362,0x4363,0x4364,0x4365,0x4366,0x4367,0x4368,0x4369,0x436A,0x436B,0x436C,0x436D,0x436E,0x436F,0x4370,0x4371,0x4372,0x4373,0x4374,0x4375,0x4376,0x4377,0x4378,0x4379,0x437A,0x437B,0x437C,0x437D,0x437E,0x437F,0x4380,0x4381,0x4382,0x4383,0x4384,0x4385,0x4386,0x4387,0x4388,0x4389,0x438A,0x438B,0x438C,0x438D,0x438E,0x438F,0x4390,0x4391,0x4392,0x4393,0x4394,0x4395,0x4396,0x4397,0x4398,0x4399,0x439A,0x439B,0x439C,0x439D,0x439E,0x439F,0x43A0,0x43A1,0x43A2,0x43A3,0x43A4,0x43A5,0x43A6,0x43A7,0x43A8,0x43A9,0x43AA,0x43AB,0x43AD,0x43AE,0x43AF,0x43B0,0x43B2,0x43B3,0x43B4,0x43B5,0x43B6,0x43B7,0x43B8,0x43B9,0x43BA,0x43BB,0x43BC,0x43BD,0x43BE,0x43BF,0x43C0,0x43C1,0x43C2,0x43C3,0x43C4,0x43C5,0x43C6,0x43C7,0x43C8,0x43C9,0x43CA,0x43CB,0x43CC,0x43CD,0x43CE,0x43CF,0x43D0,0x43D1,0x43D2,0x43D3,0x43D4,0x43D5,0x43D6,0x43D7,0x43D8,0x43D9,0x43DA,0x43DB,0x43DC,0x43DE,0x43DF,0x43E0,0x43E1,0x43E2,0x43E3,0x43E4,0x43E5,0x43E6,0x43E7,0x43E8,0x43E9,0x43EA,0x43EB,0x43EC,0x43ED,0x43EE,0x43EF,0x43F0,0x43F1,0x43F2,0x43F3,0x43F4,0x43F5,0x43F6,0x43F7,0x43F8,0x43F9,0x43FA,0x43FB,0x43FC,0x43FD,0x43FE,0x43FF,0x4400,0x4401,0x4402,0x4403,0x4404,0x4405,0x4406,0x4407,0x4408,0x4409,0x440A,0x440B,0x440C,0x440D,0x440E,0x440F,0x4410,0x4411,0x4412,0x4413,0x4414,0x4415,0x4416,0x4417,0x4418,0x4419,0x441A,0x441B,0x441C,0x441D,0x441E,0x441F,0x4420,0x4421,0x4422,0x4423,0x4424,0x4425,0x4426,0x4427,0x4428,0x4429,0x442A,0x442B,0x442C,0x442D,0x442E,0x442F,0x4430,0x4431,0x4432,0x4433,0x4434,0x4435,0x4436,0x4437,0x4438,0x4439,0x443A,0x443B,0x443C,0x443D,0x443E,0x443F,0x4440,0x4441,0x4442,0x4443,0x4444,0x4445,0x4446,0x4447,0x4448,0x4449,0x444A,0x444B,0x444C,0x444D,0x444E,0x444F,0x4450,0x4451,0x4452,0x4453,0x4454,0x4455,0x4456,0x4457,0x4458,0x4459,0x445A,0x445B,0x445C,0x445D,0x445E,0x445F,0x4460,0x4461,0x4462,0x4463,0x4464,0x4465,0x4466,0x4467,0x4468,0x4469,0x446A,0x446B,0x446C,0x446D,0x446E,0x446F,0x4470,0x4471,0x4472,0x4473,0x4474,0x4475,0x4476,0x4477,0x4478,0x4479,0x447A,0x447B,0x447C,0x447D,0x447E,0x447F,0x4480,0x4481,0x4482,0x4483,0x4484,0x4485,0x4486,0x4487,0x4488,0x4489,0x448A,0x448B,0x448C,0x448D,0x448E,0x448F,0x4490,0x4491,0x4492,0x4493,0x4494,0x4495,0x4496,0x4497,0x4498,0x4499,0x449A,0x449B,0x449C,0x449D,0x449E,0x449F,0x44A0,0x44A1,0x44A2,0x44A3,0x44A4,0x44A5,0x44A6,0x44A7,0x44A8,0x44A9,0x44AA,0x44AB,0x44AC,0x44AD,0x44AE,0x44AF,0x44B0,0x44B1,0x44B2,0x44B3,0x44B4,0x44B5,0x44B6,0x44B7,0x44B8,0x44B9,0x44BA,0x44BB,0x44BC,0x44BD,0x44BE,0x44BF,0x44C0,0x44C1,0x44C2,0x44C3,0x44C4,0x44C5,0x44C6,0x44C7,0x44C8,0x44C9,0x44CA,0x44CB,0x44CC,0x44CD,0x44CE,0x44CF,0x44D0,0x44D1,0x44D2,0x44D3,0x44D4,0x44D5,0x464D,0x464E,0x464F,0x4650,0x4651,0x4652,0x4653,0x4654,0x4655,0x4656,0x4657,0x4658,0x4659,0x465A,0x465B,0x465C,0x465D,0x465E,0x465F,0x4660,0x4662,0x4663,0x4664,0x4665,0x4666,0x4667,0x4668,0x4669,0x466A,0x466B,0x466C,0x466D,0x466E,0x466F,0x4670,0x4671,0x4672,0x4673,0x4674,0x4675,0x4676,0x4677,0x4678,0x4679,0x467A,0x467B,0x467C,0x467D,0x467E,0x467F,0x4680,0x4681,0x4682,0x4683,0x4684,0x4685,0x4686,0x4687,0x4688,0x4689,0x468A,0x468B,0x468C,0x468D,0x468E,0x468F,0x4690,0x4691,0x4692,0x4693,0x4694,0x4695,0x4696,0x4697,0x4698,0x4699,0x469A,0x469B,0x469C,0x469D,0x469E,0x469F,0x46A0,0x46A1,0x46A2,0x46A3,0x46A4,0x46A5,0x46A6,0x46A7,0x46A8,0x46A9,0x46AA,0x46AB,0x46AC,0x46AD,0x46AE,0x46AF,0x46B0,0x46B1,0x46B2,0x46B3,0x46B4,0x46B5,0x46B6,0x46B7,0x46B8,0x46B9,0x46BA,0x46BB,0x46BC,0x46BD,0x46BE,0x46BF,0x46C0,0x46C1,0x46C2,0x46C3,0x46C4,0x46C5,0x46C6,0x46C7,0x46C8,0x46C9,0x46CA,0x46CB,0x46CC,0x46CD,0x46CE,0x46CF,0x46D0,0x46D1,0x46D2,0x46D3,0x46D4,0x46D5,0x46D6,0x46D7,0x46D8,0x46D9,0x46DA,0x46DB,0x46DC,0x46DD,0x46DE,0x46DF,0x46E0,0x46E1,0x46E2,0x46E3,0x46E4,0x46E5,0x46E6,0x46E7,0x46E8,0x46E9,0x46EA,0x46EB,0x46EC,0x46ED,0x46EE,0x46EF,0x46F0,0x46F1,0x46F2,0x46F3,0x46F4,0x46F5,0x46F6,0x46F7,0x46F8,0x46F9,0x46FA,0x46FB,0x46FC,0x46FD,0x46FE,0x46FF,0x4700,0x4701,0x4702,0x4703,0x4704,0x4705,0x4706,0x4707,0x4708,0x4709,0x470A,0x470B,0x470C,0x470D,0x470E,0x470F,0x4710,0x4711,0x4712,0x4713,0x4714,0x4715,0x4716,0x4717,0x4718,0x4719,0x471A,0x471B,0x471C,0x471D,0x471E,0x471F,0x4720,0x4721,0x4722,0x4724,0x4725,0x4726,0x4727,0x4728,0x472A,0x472B,0x472C,0x472D,0x472E,0x472F,0x4730,0x4731,0x4732,0x4733,0x4734,0x4735,0x4736,0x4737,0x4738,0x4739,0x473A,0x473B,0x473C,0x473D,0x473E,0x473F,0x4740,0x4741,0x4742,0x4743,0x4744,0x4745,0x4746,0x4747,0x4748,0x4749,0x474A,0x474B,0x474C,0x474D,0x474E,0x474F,0x4750,0x4751,0x4752,0x4753,0x4754,0x4755,0x4756,0x4757,0x4758,0x4759,0x475A,0x475B,0x475C,0x475D,0x475E,0x475F,0x4760,0x4761,0x4762,0x4763,0x4764,0x4765,0x4766,0x4767,0x4768,0x4769,0x476A,0x476B,0x476C,0x476D,0x476E,0x476F,0x4770,0x4771,0x4772,0x4773,0x4774,0x4775,0x4776,0x4777,0x4778,0x4779,0x477A,0x477B,0x477D,0x477E,0x477F,0x4780,0x4781,0x4782,0x4783,0x4784,0x4785,0x4786,0x4787,0x4788,0x4789,0x478A,0x478B,0x478C,0x4948,0x4949,0x494A,0x494B,0x494C,0x494D,0x494E,0x494F,0x4950,0x4951,0x4952,0x4953,0x4954,0x4955,0x4956,0x4957,0x4958,0x4959,0x495A,0x495B,0x495C,0x495D,0x495E,0x495F,0x4960,0x4961,0x4962,0x4963,0x4964,0x4965,0x4966,0x4967,0x4968,0x4969,0x496A,0x496B,0x496C,0x496D,0x496E,0x496F,0x4970,0x4971,0x4972,0x4973,0x4974,0x4975,0x4976,0x4977,0x4978,0x4979,0x497B,0x497C,0x497E,0x497F,0x4980,0x4981,0x4984,0x4987,0x4988,0x4989,0x498A,0x498B,0x498C,0x498D,0x498E,0x498F,0x4990,0x4991,0x4992,0x4993,0x4994,0x4995,0x4996,0x4997,0x4998,0x4999,0x499A,0x499C,0x499D,0x499E,0x49A0,0x49A1,0x49A2,0x49A3,0x49A4,0x49A5,0x49A6,0x49A7,0x49A8,0x49A9,0x49AA,0x49AB,0x49AC,0x49AD,0x49AE,0x49AF,0x49B0,0x49B1,0x49B2,0x49B3,0x49B4,0x49B5,0x4C78,0x4C79,0x4C7A,0x4C7B,0x4C7C,0x4C7D,0x4C7E,0x4C7F,0x4C80,0x4C81,0x4C82,0x4C83,0x4C84,0x4C85,0x4C86,0x4C87,0x4C88,0x4C89,0x4C8A,0x4C8B,0x4C8C,0x4C8D,0x4C8E,0x4C8F,0x4C90,0x4C91,0x4C92,0x4C93,0x4C94,0x4C95,0x4C96,0x4C97,0x4C98,0x4C99,0x4C9A,0x4C9B,0x4C9C,0x4C9D,0x4C9E,0x4CA4,0x4CA5,0x4CA6,0x4CA7,0x4CA8,0x4CA9,0x4CAA,0x4CAB,0x4CAC,0x4CAD,0x4CAE,0x4CAF,0x4CB0,0x4CB1,0x4CB2,0x4CB3,0x4CB4,0x4CB5,0x4CB6,0x4CB7,0x4CB8,0x4CB9,0x4CBA,0x4CBB,0x4CBC,0x4CBD,0x4CBE,0x4CBF,0x4CC0,0x4CC1,0x4CC2,0x4CC3,0x4CC4,0x4CC5,0x4CC6,0x4CC7,0x4CC8,0x4CC9,0x4CCA,0x4CCB,0x4CCC,0x4CCD,0x4CCE,0x4CCF,0x4CD0,0x4CD1,0x4CD2,0x4CD3,0x4CD4,0x4CD5,0x4CD6,0x4CD7,0x4CD8,0x4CD9,0x4CDA,0x4CDB,0x4CDC,0x4CDD,0x4CDE,0x4CDF,0x4CE0,0x4CE1,0x4CE2,0x4CE3,0x4CE4,0x4CE5,0x4CE6,0x4CE7,0x4CE8,0x4CE9,0x4CEA,0x4CEB,0x4CEC,0x4CED,0x4CEE,0x4CEF,0x4CF0,0x4CF1,0x4CF2,0x4CF3,0x4CF4,0x4CF5,0x4CF6,0x4CF7,0x4CF8,0x4CF9,0x4CFA,0x4CFB,0x4CFC,0x4CFD,0x4CFE,0x4CFF,0x4D00,0x4D01,0x4D02,0x4D03,0x4D04,0x4D05,0x4D06,0x4D07,0x4D08,0x4D09,0x4D0A,0x4D0B,0x4D0C,0x4D0D,0x4D0E,0x4D0F,0x4D10,0x4D11,0x4D12,0x4D1A,0x4D1B,0x4D1C,0x4D1D,0x4D1E,0x4D1F,0x4D20,0x4D21,0x4D22,0x4D23,0x4D24,0x4D25,0x4D26,0x4D27,0x4D28,0x4D29,0x4D2A,0x4D2B,0x4D2C,0x4D2D,0x4D2E,0x4D2F,0x4D30,0x4D31,0x4D32,0x4D33,0x4D34,0x4D35,0x4D36,0x4D37,0x4D38,0x4D39,0x4D3A,0x4D3B,0x4D3C,0x4D3D,0x4D3E,0x4D3F,0x4D40,0x4D41,0x4D42,0x4D43,0x4D44,0x4D45,0x4D46,0x4D47,0x4D48,0x4D49,0x4D4A,0x4D4B,0x4D4C,0x4D4D,0x4D4E,0x4D4F,0x4D50,0x4D51,0x4D52,0x4D53,0x4D54,0x4D55,0x4D56,0x4D57,0x4D58,0x4D59,0x4D5A,0x4D5B,0x4D5C,0x4D5D,0x4D5E,0x4D5F,0x4D60,0x4D61,0x4D62,0x4D63,0x4D64,0x4D65,0x4D66,0x4D67,0x4D68,0x4D69,0x4D6A,0x4D6B,0x4D6C,0x4D6D,0x4D6E,0x4D6F,0x4D70,0x4D71,0x4D72,0x4D73,0x4D74,0x4D75,0x4D76,0x4D77,0x4D78,0x4D79,0x4D7A,0x4D7B,0x4D7C,0x4D7D,0x4D7E,0x4D7F,0x4D80,0x4D81,0x4D82,0x4D83,0x4D84,0x4D85,0x4D86,0x4D87,0x4D88,0x4D89,0x4D8A,0x4D8B,0x4D8C,0x4D8D,0x4D8E,0x4D8F,0x4D90,0x4D91,0x4D92,0x4D93,0x4D94,0x4D95,0x4D96,0x4D97,0x4D98,0x4D99,0x4D9A,0x4D9B,0x4D9C,0x4D9D,0x4D9E,0x4D9F,0x4DA0,0x4DA1,0x4DA2,0x4DA3,0x4DA4,0x4DA5,0x4DA6,0x4DA7,0x4DA8,0x4DA9,0x4DAA,0x4DAB,0x4DAC,0x4DAD,0x4DAF,0x4DB0,0x4DB1,0x4DB2,0x4DB3,0x4DB4,0x4DB5,0x4DB6,0x4DB7,0x4DB8,0x4DB9,0x4DBA,0x4DBB,0x4DBC,0x4DBD,0x4DBE,0x4DBF,0x4DC0,0x4DC1,0x4DC2,0x4DC3,0x4DC4,0x4DC5,0x4DC6,0x4DC7,0x4DC8,0x4DC9,0x4DCA,0x4DCB,0x4DCC,0x4DCD,0x4DCE,0x4DCF,0x4DD0,0x4DD1,0x4DD2,0x4DD3,0x4DD4,0x4DD5,0x4DD6,0x4DD7,0x4DD8,0x4DD9,0x4DDA,0x4DDB,0x4DDC,0x4DDD,0x4DDE,0x4DDF,0x4DE0,0x4DE1,0x4DE2,0x4DE3,0x4DE4,0x4DE5,0x4DE6,0x4DE7,0x4DE8,0x4DE9,0x4DEA,0x4DEB,0x4DEC,0x4DED,0x4DEE,0x4DEF,0x4DF0,0x4DF1,0x4DF2,0x4DF3,0x4DF4,0x4DF5,0x4DF6,0x4DF7,0x4DF8,0x4DF9,0x4DFA,0x4DFB,0x4DFC,0x4DFD,0x4DFE,0x4DFF,0xE76C,0xFFFD,0xE7C8,0xE7E7,0xE7E8,0xE7E9,0xE7EA,0xE7EB,0xE7EC,0xE7ED,0xE7EE,0xE7EF,0xE7F0,0xE7F1,0xE7F2,0xE7F3,0xE815,0xE819,0xE81A,0xE81B,0xE81C,0xE81D,0xE81F,0xE820,0xE821,0xE822,0xE823,0xE824,0xE825,0xE827,0xE828,0xE829,0xE82A,0xE82D,0xE82E,0xE82F,0xE830,0xE833,0xE834,0xE835,0xE836,0xE837,0xE838,0xE839,0xE83A,0xE83C,0xE83D,0xE83E,0xE83F,0xE840,0xE841,0xE842,0xE844,0xE845,0xE846,0xE847,0xE848,0xE849,0xE84A,0xE84B,0xE84C,0xE84D,0xE84E,0xE84F,0xE850,0xE851,0xE852,0xE853,0xE856,0xE857,0xE858,0xE859,0xE85A,0xE85B,0xE85C,0xE85D,0xE85E,0xE85F,0xE860,0xE861,0xE862,0xE863,0xF92D,0xF92E,0xF92F,0xF930,0xF931,0xF932,0xF933,0xF934,0xF935,0xF936,0xF937,0xF938,0xF939,0xF93A,0xF93B,0xF93C,0xF93D,0xF93E,0xF93F,0xF940,0xF941,0xF942,0xF943,0xF944,0xF945,0xF946,0xF947,0xF948,0xF949,0xF94A,0xF94B,0xF94C,0xF94D,0xF94E,0xF94F,0xF950,0xF951,0xF952,0xF953,0xF954,0xF955,0xF956,0xF957,0xF958,0xF959,0xF95A,0xF95B,0xF95C,0xF95D,0xF95E,0xF95F,0xF960,0xF961,0xF962,0xF963,0xF964,0xF965,0xF966,0xF967,0xF968,0xF969,0xF96A,0xF96B,0xF96C,0xF96D,0xF96E,0xF96F,0xF970,0xF971,0xF972,0xF973,0xF974,0xF975,0xF976,0xF977,0xF978,0xF97A,0xF97B,0xF97C,0xF97D,0xF97E,0xF97F,0xF980,0xF981,0xF982,0xF983,0xF984,0xF985,0xF986,0xF987,0xF988,0xF989,0xF98A,0xF98B,0xF98C,0xF98D,0xF98E,0xF98F,0xF990,0xF991,0xF992,0xF993,0xF994,0xF996,0xF997,0xF998,0xF999,0xF99A,0xF99B,0xF99C,0xF99D,0xF99E,0xF99F,0xF9A0,0xF9A1,0xF9A2,0xF9A3,0xF9A4,0xF9A5,0xF9A6,0xF9A7,0xF9A8,0xF9A9,0xF9AA,0xF9AB,0xF9AC,0xF9AD,0xF9AE,0xF9AF,0xF9B0,0xF9B1,0xF9B2,0xF9B3,0xF9B4,0xF9B5,0xF9B6,0xF9B7,0xF9B8,0xF9B9,0xF9BA,0xF9BB,0xF9BC,0xF9BD,0xF9BE,0xF9BF,0xF9C0,0xF9C1,0xF9C2,0xF9C3,0xF9C4,0xF9C5,0xF9C6,0xF9C7,0xF9C8,0xF9C9,0xF9CA,0xF9CB,0xF9CC,0xF9CD,0xF9CE,0xF9CF,0xF9D0,0xF9D1,0xF9D2,0xF9D3,0xF9D4,0xF9D5,0xF9D6,0xF9D7,0xF9D8,0xF9D9,0xF9DA,0xF9DB,0xF9DC,0xF9DD,0xF9DE,0xF9DF,0xF9E0,0xF9E1,0xF9E2,0xF9E3,0xF9E4,0xF9E5,0xF9E6,0xF9E8,0xF9E9,0xF9EA,0xF9EB,0xF9EC,0xF9ED,0xF9EE,0xF9EF,0xF9F0,0xF9F2,0xF9F3,0xF9F4,0xF9F5,0xF9F6,0xF9F7,0xF9F8,0xF9F9,0xF9FA,0xF9FB,0xF9FC,0xF9FD,0xF9FE,0xF9FF,0xFA00,0xFA01,0xFA02,0xFA03,0xFA04,0xFA05,0xFA06,0xFA07,0xFA08,0xFA09,0xFA0A,0xFA0B,0xFA10,0xFA12,0xFA15,0xFA16,0xFA17,0xFA19,0xFA1A,0xFA1B,0xFA1C,0xFA1D,0xFA1E,0xFA22,0xFA25,0xFA26,0xFE32,0xFE45,0xFE46,0xFE47,0xFE48,0xFE53,0xFE58,0xFE67,0xFE6C,0xFE6D,0xFE6E,0xFE6F,0xFE70,0xFE71,0xFE72,0xFE73,0xFE74,0xFE75,0xFE76,0xFE77,0xFE78,0xFE79,0xFE7A,0xFE7B,0xFE7C,0xFE7D,0xFE7E,0xFE7F,0xFE80,0xFE81,0xFE82,0xFE83,0xFE84,0xFE85,0xFE86,0xFE87,0xFE88,0xFE89,0xFE8A,0xFE8B,0xFE8C,0xFE8D,0xFE8E,0xFE8F,0xFE90,0xFE91,0xFE92,0xFE93,0xFE94,0xFE95,0xFE96,0xFE97,0xFE98,0xFE99,0xFE9A,0xFE9B,0xFE9C,0xFE9D,0xFE9E,0xFE9F,0xFEA0,0xFEA1,0xFEA2,0xFEA3,0xFEA4,0xFEA5,0xFEA6,0xFEA7,0xFEA8,0xFEA9,0xFEAA,0xFEAB,0xFEAC,0xFEAD,0xFEAE,0xFEAF,0xFEB0,0xFEB1,0xFEB2,0xFEB3,0xFEB4,0xFEB5,0xFEB6,0xFEB7,0xFEB8,0xFEB9,0xFEBA,0xFEBB,0xFEBC,0xFEBD,0xFEBE,0xFEBF,0xFEC0,0xFEC1,0xFEC2,0xFEC3,0xFEC4,0xFEC5,0xFEC6,0xFEC7,0xFEC8,0xFEC9,0xFECA,0xFECB,0xFECC,0xFECD,0xFECE,0xFECF,0xFED0,0xFED1,0xFED2,0xFED3,0xFED4,0xFED5,0xFED6,0xFED7,0xFED8,0xFED9,0xFEDA,0xFEDB,0xFEDC,0xFEDD,0xFEDE,0xFEDF,0xFEE0,0xFEE1,0xFEE2,0xFEE3,0xFEE4,0xFEE5,0xFEE6,0xFEE7,0xFEE8,0xFEE9,0xFEEA,0xFEEB,0xFEEC,0xFEED,0xFEEE,0xFEEF,0xFEF0,0xFEF1,0xFEF2,0xFEF3,0xFEF4,0xFEF5,0xFEF6,0xFEF7,0xFEF8,0xFEF9,0xFEFA,0xFEFB,0xFEFC,0xFEFD,0xFEFE,0xFEFF,0xFF00,0xFF5F,0xFF60,0xFF61,0xFF62,0xFF63,0xFF64,0xFF65,0xFF66,0xFF67,0xFF68,0xFF69,0xFF6A,0xFF6B,0xFF6C,0xFF6D,0xFF6E,0xFF6F,0xFF70,0xFF71,0xFF72,0xFF73,0xFF74,0xFF75,0xFF76,0xFF77,0xFF78,0xFF79,0xFF7A,0xFF7B,0xFF7C,0xFF7D,0xFF7E,0xFF7F,0xFF80,0xFF81,0xFF82,0xFF83,0xFF84,0xFF85,0xFF86,0xFF87,0xFF88,0xFF89,0xFF8A,0xFF8B,0xFF8C,0xFF8D,0xFF8E,0xFF8F,0xFF90,0xFF91,0xFF92,0xFF93,0xFF94,0xFF95,0xFF96,0xFF97,0xFF98,0xFF99,0xFF9A,0xFF9B,0xFF9C,0xFF9D,0xFF9E,0xFF9F,0xFFA0,0xFFA1,0xFFA2,0xFFA3,0xFFA4,0xFFA5,0xFFA6,0xFFA7,0xFFA8,0xFFA9,0xFFAA,0xFFAB,0xFFAC,0xFFAD,0xFFAE,0xFFAF,0xFFB0,0xFFB1,0xFFB2,0xFFB3,0xFFB4,0xFFB5,0xFFB6,0xFFB7,0xFFB8,0xFFB9,0xFFBA,0xFFBB,0xFFBC,0xFFBD,0xFFBE,0xFFBF,0xFFC0,0xFFC1,0xFFC2,0xFFC3,0xFFC4,0xFFC5,0xFFC6,0xFFC7,0xFFC8,0xFFC9,0xFFCA,0xFFCB,0xFFCC,0xFFCD,0xFFCE,0xFFCF,0xFFD0,0xFFD1,0xFFD2,0xFFD3,0xFFD4,0xFFD5,0xFFD6,0xFFD7,0xFFD8,0xFFD9,0xFFDA,0xFFDB,0xFFDC,0xFFDD,0xFFDE,0xFFDF \ No newline at end of file diff --git a/src/fast_io/include/fast_io_unit/string.h b/src/fast_io/include/fast_io_unit/string.h new file mode 100644 index 0000000..c4c8317 --- /dev/null +++ b/src/fast_io/include/fast_io_unit/string.h @@ -0,0 +1,4 @@ +#pragma once + + +#include"string_impl/impl.h" diff --git a/src/fast_io/include/fast_io_unit/string_impl/concat.h b/src/fast_io/include/fast_io_unit/string_impl/concat.h new file mode 100644 index 0000000..3e2e05b --- /dev/null +++ b/src/fast_io/include/fast_io_unit/string_impl/concat.h @@ -0,0 +1,196 @@ +#pragma once + +namespace fast_io +{ + +template +[[nodiscard]] inline +#if __cpp_lib_constexpr_string >= 201907L +constexpr +#endif +std::string concat(Args&& ...args) +{ + constexpr bool type_error{print_freestanding_okay<::fast_io::details::dummy_buffer_output_stream,Args...>}; + if constexpr(type_error) + { + return details::decay::basic_general_concat_phase1_decay_impl(io_print_forward(io_print_alias(args))...); + } + else + { +static_assert(type_error,"some types are not printable, so we cannot concat std::string"); + return {}; + } +} + +template +[[nodiscard]] inline +#if __cpp_lib_constexpr_string >= 201907L +constexpr +#endif +std::basic_string wconcat(Args&& ...args) +{ + constexpr bool type_error{print_freestanding_okay<::fast_io::details::dummy_buffer_output_stream,Args...>}; + if constexpr(type_error) + { + return details::decay::basic_general_concat_phase1_decay_impl>(io_print_forward(io_print_alias(args))...); + } + else + { +static_assert(type_error,"some types are not printable, so we cannot concat std::wstring"); + return {}; + } +} + +template +[[nodiscard]] inline +#if __cpp_lib_constexpr_string >= 201907L +constexpr +#endif +std::u8string u8concat(Args&& ...args) +{ + constexpr bool type_error{print_freestanding_okay<::fast_io::details::dummy_buffer_output_stream,Args...>}; + if constexpr(type_error) + { + return details::decay::basic_general_concat_phase1_decay_impl(io_print_forward(io_print_alias(args))...); + } + else + { +static_assert(type_error,"some types are not printable, so we cannot concat std::u8string"); + return {}; + } +} + +template +[[nodiscard]] inline +#if __cpp_lib_constexpr_string >= 201907L +constexpr +#endif +std::u16string u16concat(Args&& ...args) +{ + constexpr bool type_error{print_freestanding_okay<::fast_io::details::dummy_buffer_output_stream,Args...>}; + if constexpr(type_error) + { + return details::decay::basic_general_concat_phase1_decay_impl(io_print_forward(io_print_alias(args))...); + } + else + { +static_assert(type_error,"some types are not printable, so we cannot concat std::u16string"); + return {}; + } +} + +template +[[nodiscard]] inline +#if __cpp_lib_constexpr_string >= 201907L +constexpr +#endif +std::u32string u32concat(Args&& ...args) +{ + constexpr bool type_error{print_freestanding_okay<::fast_io::details::dummy_buffer_output_stream,Args...>}; + if constexpr(type_error) + { + return details::decay::basic_general_concat_phase1_decay_impl(io_print_forward(io_print_alias(args))...); + } + else + { +static_assert(type_error,"some types are not printable, so we cannot concat std::u32string"); + return {}; + } +} + +template +[[nodiscard]] inline +#if __cpp_lib_constexpr_string >= 201907L +constexpr +#endif +std::basic_string concatln(Args&& ...args) +{ + constexpr bool type_error{print_freestanding_okay<::fast_io::details::dummy_buffer_output_stream,Args...>}; + if constexpr(type_error) + { + return details::decay::basic_general_concat_phase1_decay_impl>(io_print_forward(io_print_alias(args))...); + } + else + { +static_assert(type_error,"some types are not printable, so we cannot concatln std::wstring"); + return {}; + } +} + +template +[[nodiscard]] inline +#if __cpp_lib_constexpr_string >= 201907L +constexpr +#endif +std::basic_string wconcatln(Args&& ...args) +{ + constexpr bool type_error{print_freestanding_okay<::fast_io::details::dummy_buffer_output_stream,Args...>}; + if constexpr(type_error) + { + return details::decay::basic_general_concat_phase1_decay_impl>(io_print_forward(io_print_alias(args))...); + } + else + { +static_assert(type_error,"some types are not printable, so we cannot concatln std::wstring"); + return {}; + } +} + +template +[[nodiscard]] inline +#if __cpp_lib_constexpr_string >= 201907L +constexpr +#endif +std::u8string u8concatln(Args&& ...args) +{ + constexpr bool type_error{print_freestanding_okay<::fast_io::details::dummy_buffer_output_stream,Args...>}; + if constexpr(type_error) + { + return details::decay::basic_general_concat_phase1_decay_impl(io_print_forward(io_print_alias(args))...); + } + else + { +static_assert(type_error,"some types are not printable, so we cannot concatln std::u8string"); + return {}; + } +} + +template +[[nodiscard]] inline +#if __cpp_lib_constexpr_string >= 201907L +constexpr +#endif +std::u16string u16concatln(Args&& ...args) +{ + constexpr bool type_error{print_freestanding_okay<::fast_io::details::dummy_buffer_output_stream,Args...>}; + if constexpr(type_error) + { + return details::decay::basic_general_concat_phase1_decay_impl(io_print_forward(io_print_alias(args))...); + } + else + { +static_assert(type_error,"some types are not printable, so we cannot concatln std::u16string"); + return {}; + } +} + +template +[[nodiscard]] inline +#if __cpp_lib_constexpr_string >= 201907L +constexpr +#endif +std::u32string u32concatln(Args&& ...args) +{ + constexpr bool type_error{print_freestanding_okay<::fast_io::details::dummy_buffer_output_stream,Args...>}; + if constexpr(type_error) + { + return details::decay::basic_general_concat_phase1_decay_impl(io_print_forward(io_print_alias(args))...); + } + else + { +static_assert(type_error,"some types are not printable, so we cannot concatln std::u32string"); + return {}; + } +} + +} diff --git a/src/fast_io/include/fast_io_unit/string_impl/impl.h b/src/fast_io/include/fast_io_unit/string_impl/impl.h new file mode 100644 index 0000000..c698dc0 --- /dev/null +++ b/src/fast_io/include/fast_io_unit/string_impl/impl.h @@ -0,0 +1,15 @@ +#pragma once + +#if defined(_LIBCPP_VERSION) +#include"libc++.h" +#elif defined(__GLIBCXX__) +#include"libstdc++.h" +#elif defined(_MSVC_STL_UPDATE) +#include"msvc_stl.h" +#else +#error "Anyone knows how to hack brutal std::basic_string internal on this platform?" +#endif + +#include"ostring_ref.h" +#include"concat.h" +#include"scan_str_ctx_impl.h" diff --git a/src/fast_io/include/fast_io_unit/string_impl/lc_concat.h b/src/fast_io/include/fast_io_unit/string_impl/lc_concat.h new file mode 100644 index 0000000..8d5438f --- /dev/null +++ b/src/fast_io/include/fast_io_unit/string_impl/lc_concat.h @@ -0,0 +1,290 @@ +#pragma once + +namespace fast_io +{ + +namespace details::decay +{ + +template +inline constexpr std::size_t lc_calculate_scatter_dynamic_reserve_size_with_scatter(basic_lc_all const* all,[[maybe_unused]] T t,Args... args) +{ + if constexpr((!(lc_dynamic_reserve_printable||lc_scatter_printable)&&((!(lc_dynamic_reserve_printable||lc_scatter_printable))&&...))) + return calculate_scatter_dynamic_reserve_size_with_scatter(t,args...); + else if constexpr(lc_dynamic_reserve_printable) + { + std::size_t res{print_reserve_size(all,t)}; + if constexpr(sizeof...(Args)==0) + return res; + else + return ::fast_io::details::intrinsics::add_or_overflow_die(res,lc_calculate_scatter_dynamic_reserve_size_with_scatter(all,args...)); + } + else if constexpr(lc_scatter_printable) + { + std::size_t res{print_scatter_define(all,t).len}; + if constexpr(sizeof...(Args)==0) + return res; + else + return ::fast_io::details::intrinsics::add_or_overflow_die(res,lc_calculate_scatter_dynamic_reserve_size_with_scatter(all,args...)); + } + else if constexpr(dynamic_reserve_printable) + { + std::size_t res{print_reserve_size(io_reserve_type,t)}; + if constexpr(sizeof...(Args)==0) + return res; + else + return ::fast_io::details::intrinsics::add_or_overflow_die(res,lc_calculate_scatter_dynamic_reserve_size_with_scatter(all,args...)); + } + else if constexpr(scatter_printable) + { + std::size_t res{print_scatter_define(io_reserve_type>,t).len}; + if constexpr(sizeof...(Args)==0) + return res; + else + return ::fast_io::details::intrinsics::add_or_overflow_die(res,lc_calculate_scatter_dynamic_reserve_size_with_scatter(all,args...)); + } + else + { + if constexpr(sizeof...(Args)==0) + return 0; + else + return lc_calculate_scatter_dynamic_reserve_size_with_scatter(all,args...); + } +} + +template +inline constexpr ptr_type lc_print_reserve_define_chain_scatter_impl(basic_lc_all const* all,ptr_type p,T t,Args ...args) +{ + if constexpr((!(lc_dynamic_reserve_printable||lc_scatter_printable)&&((!(lc_dynamic_reserve_printable||lc_scatter_printable))&&...))) + return print_reserve_define_chain_scatter_impl(p,t,args...); + else if constexpr(lc_dynamic_reserve_printable) + p = print_reserve_define(all,p,t); + else if constexpr(lc_scatter_printable) + { + basic_io_scatter_t sc{print_scatter_define(all,t)}; + p = non_overlapped_copy_n(sc.base,sc.len,p); + } + else if constexpr(dynamic_reserve_printable||reserve_printable) + p = print_reserve_define(io_reserve_type>,p,t); + else + { + basic_io_scatter_t sc{print_scatter_define(io_reserve_type>,t)}; + p = non_overlapped_copy_n(sc.base,sc.len,p); + } + if constexpr(sizeof...(Args)==0) + { + if constexpr(line) + { + *p=char_literal_v; + ++p; + } + return p; + } + else + return lc_print_reserve_define_chain_scatter_impl(all,p,args...); +} + +template +inline constexpr basic_io_scatter_t lc_print_scatter_define_extract_one(basic_lc_all const* all,T t) +{ + return print_scatter_define(all,t); +} + +template +inline constexpr T lc_concat_decay_impl(basic_lc_all const* all,Args ...args) +{ + using ch_type = typename T::value_type; + using ostring_ref_type = basic_ostring_ref; + if constexpr(((!(lc_dynamic_reserve_printable||lc_scatter_printable||lc_printable))&&...)) + { + return ::fast_io::details::decay::basic_general_concat_phase1_decay_impl(args...); + } + else if constexpr(sizeof...(Args)==0) + { + if constexpr(line) + { + return T(1,char_literal_v); + } + else + { + return {}; + } + } + else if constexpr(((reserve_printable||scatter_printable||dynamic_reserve_printable||lc_scatter_printable||lc_dynamic_reserve_printable)&&...)) + { + constexpr std::size_t sz_with_line{static_cast(line)}; + if constexpr((!line)&&sizeof...(args)==1&&(lc_scatter_printable&&...)) + { + basic_io_scatter_t scatter{lc_print_scatter_define_extract_one(all,args...)}; + return T(scatter.base,scatter.len); + } + else + { + std::size_t total_size{::fast_io::details::intrinsics::add_or_overflow_die(sz_with_line,lc_calculate_scatter_dynamic_reserve_size_with_scatter(all,args...))}; + T str; + str.reserve(total_size); + set_basic_string_ptr(str,lc_print_reserve_define_chain_scatter_impl(all,str.data(),args...)); + return str; + } + } + else + { + T str; + basic_ostring_ref ref{__builtin_addressof(str)}; + lc_print_status_define_further_decay(all,ref,args...); + return str; + } +} + +template +concept l10ntypes_impl = requires(T& loc) +{ + {loc.loc} -> std::same_as<::fast_io::lc_locale>; +}; + +} + +template +inline constexpr T basic_lc_concat_decay(basic_lc_all const* all,Args ...args) +{ + return ::fast_io::details::decay::lc_concat_decay_impl(all,args...); +} +template +inline constexpr T basic_lc_concatln_decay(basic_lc_all const* all,Args ...args) +{ + return ::fast_io::details::decay::lc_concat_decay_impl(all,args...); +} + +template +inline constexpr T basic_lc_concat(basic_lc_all const* all,Args ...args) +{ + return ::fast_io::details::decay::lc_concat_decay_impl(all,io_print_forward(io_print_alias(args))...); +} + +template +inline constexpr T basic_lc_concatln(basic_lc_all const* all,Args ...args) +{ + return ::fast_io::details::decay::lc_concat_decay_impl(all,io_print_forward(io_print_alias(args))...); +} + +template +inline +#if __cpp_lib_constexpr_string >= 201907L +constexpr +#endif +std::basic_string lc_concat(basic_lc_all const* all,Args ...args) +{ + return ::fast_io::details::decay::lc_concat_decay_impl>(all,io_print_forward(io_print_alias(args))...); +} + +template +inline +#if __cpp_lib_constexpr_string >= 201907L +constexpr +#endif +std::basic_string lc_concatln(basic_lc_all const* all,Args ...args) +{ + return ::fast_io::details::decay::lc_concat_decay_impl(all,io_print_forward(io_print_alias(args))...); +} + +template<::fast_io::details::decay::l10ntypes_impl T,typename ...Args> +inline +#if __cpp_lib_constexpr_string >= 201907L +constexpr +#endif +std::string lc_concat(T& loc,Args&& ...args) +{ + return ::fast_io::details::decay::lc_concat_decay_impl(loc.loc.all,io_print_forward(io_print_alias(args))...); +} + +template<::fast_io::details::decay::l10ntypes_impl T,typename ...Args> +inline +#if __cpp_lib_constexpr_string >= 201907L +constexpr +#endif +std::string lc_concatln(T& loc,Args&& ...args) +{ + return ::fast_io::details::decay::lc_concat_decay_impl(loc.loc.all,io_print_forward(io_print_alias(args))...); +} + +template<::fast_io::details::decay::l10ntypes_impl T,typename ...Args> +inline +#if __cpp_lib_constexpr_string >= 201907L +constexpr +#endif +std::basic_string wlc_concat(T& loc,Args&& ...args) +{ + return ::fast_io::details::decay::lc_concat_decay_impl>(loc.loc.wall,io_print_forward(io_print_alias(args))...); +} + +template<::fast_io::details::decay::l10ntypes_impl T,typename ...Args> +inline +#if __cpp_lib_constexpr_string >= 201907L +constexpr +#endif +std::basic_string wlc_concatln(T& loc,Args&& ...args) +{ + return ::fast_io::details::decay::lc_concat_decay_impl>(loc.loc.wall,io_print_forward(io_print_alias(args))...); +} + +template<::fast_io::details::decay::l10ntypes_impl T,typename ...Args> +inline +#if __cpp_lib_constexpr_string >= 201907L +constexpr +#endif +std::u8string u8lc_concat(T& loc,Args&& ...args) +{ + return ::fast_io::details::decay::lc_concat_decay_impl(loc.loc.u8all,io_print_forward(io_print_alias(args))...); +} + +template<::fast_io::details::decay::l10ntypes_impl T,typename ...Args> +inline +#if __cpp_lib_constexpr_string >= 201907L +constexpr +#endif +std::u8string u8lc_concatln(T& loc,Args&& ...args) +{ + return ::fast_io::details::decay::lc_concat_decay_impl(loc.loc.u8all,io_print_forward(io_print_alias(args))...); +} + +template<::fast_io::details::decay::l10ntypes_impl T,typename ...Args> +inline +#if __cpp_lib_constexpr_string >= 201907L +constexpr +#endif +std::u16string u16lc_concat(T& loc,Args&& ...args) +{ + return ::fast_io::details::decay::lc_concat_decay_impl(loc.loc.u16all,io_print_forward(io_print_alias(args))...); +} + +template<::fast_io::details::decay::l10ntypes_impl T,typename ...Args> +inline +#if __cpp_lib_constexpr_string >= 201907L +constexpr +#endif +std::u16string u16lc_concatln(T& loc,Args&& ...args) +{ + return ::fast_io::details::decay::lc_concat_decay_impl(loc.loc.u16all,io_print_forward(io_print_alias(args))...); +} + +template<::fast_io::details::decay::l10ntypes_impl T,typename ...Args> +inline +#if __cpp_lib_constexpr_string >= 201907L +constexpr +#endif +std::u32string u32lc_concat(T& loc,Args&& ...args) +{ + return ::fast_io::details::decay::lc_concat_decay_impl(loc.loc.u32all,io_print_forward(io_print_alias(args))...); +} + +template<::fast_io::details::decay::l10ntypes_impl T,typename ...Args> +inline +#if __cpp_lib_constexpr_string >= 201907L +constexpr +#endif +std::u32string u32lc_concatln(T& loc,Args&& ...args) +{ + return ::fast_io::details::decay::lc_concat_decay_impl(loc.loc.u32all,io_print_forward(io_print_alias(args))...); +} + +} diff --git a/src/fast_io/include/fast_io_unit/string_impl/libc++.h b/src/fast_io/include/fast_io_unit/string_impl/libc++.h new file mode 100644 index 0000000..5acff97 --- /dev/null +++ b/src/fast_io/include/fast_io_unit/string_impl/libc++.h @@ -0,0 +1,134 @@ +#pragma once +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC system_header +#endif +/* +https://github.com/llvm-mirror/libcxx/blob/78d6a7767ed57b50122a161b91f59f19c9bd0d19/include/string#L703 + +*/ + +namespace fast_io::details::string_hack +{ + +template +struct +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +model +{ + typedef _Traits traits_type; + typedef _CharT value_type; + typedef _Allocator allocator_type; + typedef std::allocator_traits __alloc_traits; + typedef typename __alloc_traits::size_type size_type; + typedef typename __alloc_traits::difference_type difference_type; + typedef value_type& reference; + typedef value_type const& const_reference; + typedef typename __alloc_traits::pointer pointer; + typedef typename __alloc_traits::const_pointer const_pointer; +#ifdef _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT + struct __long + { + pointer __data_; + size_type __size_; + size_type __cap_ : sizeof(size_type) * CHAR_BIT - 1; + size_type __is_long_ : 1; + }; + + enum {__min_cap = (sizeof(__long) - 1)/sizeof(value_type) > 2 ? + (sizeof(__long) - 1)/sizeof(value_type) : 2}; + + struct __short + { + value_type __data_[__min_cap]; + unsigned char __padding_[sizeof(value_type) - 1]; + unsigned char __size_ : 7; + unsigned char __is_long_ : 1; + }; + + +#else + + struct __long + { + size_type __is_long_ : 1; + size_type __cap_ : sizeof(size_type) * CHAR_BIT - 1; + size_type __size_; + pointer __data_; + }; + + enum {__min_cap = (sizeof(__long) - 1)/sizeof(value_type) > 2 ? + (sizeof(__long) - 1)/sizeof(value_type) : 2}; + + struct __short + { + unsigned char __is_long_ : 1; + unsigned char __size_ : 7; + char __padding_[sizeof(value_type) - 1]; + value_type __data_[__min_cap]; + }; + +#endif // _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT + + union __ulx{__long __lx; __short __lxx;}; + + enum {__n_words = sizeof(__ulx) / sizeof(size_type)}; + + struct __raw + { + size_type __words[__n_words]; + }; + + struct __rep + { + union + { + __long __l; + __short __s; + __raw __r; + }; + }; + ::std::__compressed_pair<__rep, allocator_type> __r_; +}; + +template +inline decltype(auto) hack_rep(std::basic_string& str) noexcept +{ + using model_t = model; + using __rep = typename model_t::__rep; + using alias_pointer +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif + = typename ::std::__compressed_pair<__rep, alloc>*; + return reinterpret_cast(reinterpret_cast(__builtin_addressof(str))+__builtin_offsetof(model_t,__r_))->first(); +} + +template +inline void set_size(std::basic_string& str,typename std::basic_string::size_type s) noexcept +{ + decltype(auto) __r_{hack_rep(str)}; + if (bool(__r_.__s.__is_long_)) + __r_.__l.__size_=s; + else + { + __r_.__s.__size_ = (unsigned char)(s); + } +} + +template +inline constexpr void set_end_ptr(T& str,typename T::value_type* ptr) noexcept +{ + set_size(str,static_cast(ptr-str.data())); +} + +template +inline constexpr std::size_t local_capacity() noexcept +{ + using model_type = model; + constexpr std::size_t mcapminus1{static_cast(model_type::__min_cap-static_cast(1u))}; + return mcapminus1; +} + +} diff --git a/src/fast_io/include/fast_io_unit/string_impl/libstdc++.h b/src/fast_io/include/fast_io_unit/string_impl/libstdc++.h new file mode 100644 index 0000000..50f91f2 --- /dev/null +++ b/src/fast_io/include/fast_io_unit/string_impl/libstdc++.h @@ -0,0 +1,82 @@ +#pragma once + +namespace fast_io::details::string_hack +{ + +/* +https://github.com/gcc-mirror/gcc/blob/47fe96341d28ff9e68990038b1beb8a760ff26d0/libstdc%2B%2B-v3/include/bits/basic_string.h#L150 +*/ + +template +struct +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +model +{ +using value_type = typename T::value_type; +using size_type = typename T::size_type; +using pointer = typename T::pointer; +using const_pointer = typename T::const_pointer; +using allocator_type = typename T::allocator_type; +struct _Alloc_hider : allocator_type // TODO check __is_final +{ +#if __cplusplus < 201103L +_Alloc_hider(pointer __dat, allocator_type const& __a = allocator_type()) +: allocator_type(__a), _M_p(__dat) { } +#else +_Alloc_hider(pointer __dat, allocator_type const& __a) +: allocator_type(__a), _M_p(__dat) { } + +_Alloc_hider(pointer __dat, allocator_type&& __a = allocator_type()) +: allocator_type(::std::move(__a)), _M_p(__dat) { } +#endif + +pointer _M_p; // The actual data. +}; + +_Alloc_hider _M_dataplus; +size_type _M_string_length; + +enum { _S_local_capacity = 15 / sizeof(value_type) }; + +union +{ +value_type _M_local_buf[_S_local_capacity + 1]; +size_type _M_allocated_capacity; +}; + +}; + + +template +inline decltype(auto) hack_M_data(T& str) noexcept +{ + using model_t = model; + using alloc_hider = typename model_t::_Alloc_hider; + using pointer = typename T::pointer; + return *reinterpret_cast(reinterpret_cast(__builtin_addressof(str))+__builtin_offsetof(model_t,_M_dataplus)+__builtin_offsetof(alloc_hider,_M_p)); +} + +template +inline decltype(auto) hack_M_string_length(T& str) noexcept +{ + using model_t = model; + using size_type = typename T::size_type; + return *reinterpret_cast(reinterpret_cast(__builtin_addressof(str))+__builtin_offsetof(model_t,_M_string_length)); +} + +template +inline constexpr void set_end_ptr(T& str,typename T::value_type* ptr) noexcept +{ + hack_M_string_length(str)=static_cast(ptr-::std::to_address(hack_M_data(str))); +} + +template +inline constexpr std::size_t local_capacity() noexcept +{ + using model_type = model; + return model_type::_S_local_capacity; +} + +} diff --git a/src/fast_io/include/fast_io_unit/string_impl/msvc_stl.h b/src/fast_io/include/fast_io_unit/string_impl/msvc_stl.h new file mode 100644 index 0000000..f9ea544 --- /dev/null +++ b/src/fast_io/include/fast_io_unit/string_impl/msvc_stl.h @@ -0,0 +1,59 @@ +#pragma once + +namespace fast_io::details::string_hack +{ + +/* +https://github.com/microsoft/STL/blob/master/stl/inc/xstring +*/ + +template , class _Alloc = std::allocator<_Elem>> +struct +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +model +{ + using _Alty = std::_Rebind_alloc_t<_Alloc, _Elem>; + using _Alty_traits = std::allocator_traits<_Alty>; + using _Scary_val = std::_String_val, std::_Simple_types<_Elem>, + std::_String_iter_types<_Elem, typename _Alty_traits::size_type, typename _Alty_traits::difference_type, + typename _Alty_traits::pointer, typename _Alty_traits::const_pointer +#if _MSVC_STL_UPDATE < 202306L + , _Elem &, _Elem const & +#endif + >>>; + using compress_pair_type = std::_Compressed_pair<_Alty, _Scary_val>; + compress_pair_type _Mypair; +}; + +template +inline constexpr decltype(auto) hack_scary_val(std::basic_string& str) noexcept +{ + using model_t = model; + using compress_pair_type = typename model_t::compress_pair_type; + using scary_ptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = typename model_t::_Scary_val*; + return *reinterpret_cast(reinterpret_cast(__builtin_addressof(str))+offsetof(model_t,_Mypair)+offsetof(compress_pair_type,_Myval2)); +} + +template +inline constexpr void set_end_ptr(T& str,typename T::value_type* ptr) noexcept +{ + decltype(auto) scv{hack_scary_val(str)}; + scv._Mysize=static_cast(ptr-str.data()); +} + +template +inline constexpr std::size_t local_capacity() noexcept +{ + using model_t = model; + using _Scary_val = typename model_t::_Scary_val; + return _Scary_val::_BUF_SIZE-1; +} + +} diff --git a/src/fast_io/include/fast_io_unit/string_impl/ostring_ref.h b/src/fast_io/include/fast_io_unit/string_impl/ostring_ref.h new file mode 100644 index 0000000..9b32896 --- /dev/null +++ b/src/fast_io/include/fast_io_unit/string_impl/ostring_ref.h @@ -0,0 +1,140 @@ +#pragma once + +namespace fast_io +{ + +template +inline constexpr auto strlike_construct_define(io_strlike_type_t>,char_type const* first,char_type const* last) +{ + return ::std::basic_string(first,last); +} + +template +inline constexpr auto strlike_construct_single_character_define(io_strlike_type_t>,char_type ch) +{ + return ::std::basic_string(1,ch); +} + +#if (!defined(__GLIBCXX__) || defined(_LIBCPP_VERSION) || defined(_GLIBCXX_USE_CXX11_ABI)) + +template +inline constexpr char_type* strlike_begin(io_strlike_type_t>,::std::basic_string& str) noexcept +{ + return str.data(); +} + +template +inline constexpr char_type* strlike_curr(io_strlike_type_t>,::std::basic_string& str) noexcept +{ + return str.data()+str.size(); +} + +template +inline constexpr char_type* strlike_end(io_strlike_type_t>,::std::basic_string& str) noexcept +{ + return str.data()+str.capacity(); +} +#if __cpp_lib_string_resize_and_overwrite >= 202110L +namespace details +{ + +template +struct empty_string_set_ptr +{ + std::size_t realsize{}; + inline constexpr std::size_t operator()(char_type const*,size_type) noexcept + { + return realsize; + } +}; + +} +#endif + +template +inline constexpr void strlike_set_curr(io_strlike_type_t>,::std::basic_string& str,char_type* p) +{ +#if (__cpp_lib_is_constant_evaluated >=201811L || __cpp_if_consteval >= 202106L) && (__cpp_lib_string_resize_and_overwrite >= 202110L || __cpp_constexpr_dynamic_alloc >= 201907L) +#if __cpp_if_consteval >= 202106L + if consteval +#else + if(std::is_constant_evaluated()) +#endif + { + auto old_ptr{str.data()}; + std::size_t const sz{static_cast(p-str.data())}; +#if __cpp_lib_string_resize_and_overwrite >= 202110L + + str.resize_and_overwrite(sz, + ::fast_io::details::empty_string_set_ptr::size_type>{sz}); +#else + auto curr_ptr{str.data()+str.size()}; + if(p(p-curr_ptr)}; + ::fast_io::details::local_operator_new_array_ptr buffer(diff); + for(std::size_t i{};i!=diff;++i) + buffer[i]=curr_ptr[i]; + str.append(diff,0); + auto newp{str.data()+oldsz}; + for(std::size_t i{};i!=diff;++i) + newp[i]=buffer[i]; + } +#endif + if(old_ptr!=str.data()) + ::fast_io::fast_terminate(); + } + else +#endif + { + traits_type::assign(*p, char_type()); + ::fast_io::details::string_hack::set_end_ptr(str,p); + } +} + +template +inline constexpr void strlike_reserve(io_strlike_type_t>,::std::basic_string& str,std::size_t n) +{ + str.reserve(n); +} +#endif +template +inline constexpr void strlike_append(io_strlike_type_t>,::std::basic_string& str,char_type const* first,char_type const* last) +{ + str.append(first,last); +} + +template +inline constexpr void strlike_push_back(io_strlike_type_t>,::std::basic_string& str,char_type ch) +{ + str.push_back(ch); +} +#if (!defined(__GLIBCXX__) || defined(_LIBCPP_VERSION) || defined(_GLIBCXX_USE_CXX11_ABI)) +template +inline constexpr std::size_t strlike_sso_size(io_strlike_type_t>) noexcept +{ + return ::fast_io::details::string_hack::local_capacity<::std::basic_string>(); +} +#endif +template +inline constexpr io_strlike_reference_wrapper> io_strlike_ref(io_alias_t,::std::basic_string& str) noexcept +{ + return {__builtin_addressof(str)}; +} + + +template,typename Allocator = std::allocator> +using basic_ostring_ref = io_strlike_reference_wrapper>; +using ostring_ref = basic_ostring_ref; +using wostring_ref = basic_ostring_ref; +using u8ostring_ref = basic_ostring_ref; +using u16ostring_ref = basic_ostring_ref; +using u32ostring_ref = basic_ostring_ref; + +static_assert(value_based_stream); +} diff --git a/src/fast_io/include/fast_io_unit/string_impl/scan_str_ctx_impl.h b/src/fast_io/include/fast_io_unit/string_impl/scan_str_ctx_impl.h new file mode 100644 index 0000000..c63af70 --- /dev/null +++ b/src/fast_io/include/fast_io_unit/string_impl/scan_str_ctx_impl.h @@ -0,0 +1,170 @@ +#pragma once + +namespace fast_io +{ + +struct scan_string_context +{ + bool copying{}; +}; + +namespace details +{ + +template +inline constexpr ::fast_io::parse_result scan_context_define_string_impl(bool& skip_space_done,char_type const* first,char_type const* last,::std::basic_string& ref) +{ + auto it{first}; + if constexpr(!noskipws&&!line) + { + if(!skip_space_done) + { + it=::fast_io::find_none_c_space(it,last); + if(it==last) + return {it,::fast_io::parse_code::partial}; + skip_space_done=true; + ref.clear(); + } + } + auto it_space{it}; + if constexpr(line) + it_space=::fast_io::find_lf(it_space,last); + else + it_space=::fast_io::find_c_space(it_space,last); + if constexpr(noskipws||line) + { + if(!skip_space_done) + { + ref.assign(it,it_space); + skip_space_done=true; + } + else + ref.append(it,it_space); + } + else + { + ref.append(it,it_space); + } + if(it_space==last) + return {it_space,::fast_io::parse_code::partial}; + if constexpr(line) + ++it_space; + return {it_space,::fast_io::parse_code::ok}; +} + +inline constexpr ::fast_io::parse_code scan_context_eof_string_define_impl(bool skip_space_done) noexcept +{ + if(skip_space_done) + return ::fast_io::parse_code::ok; + else + return ::fast_io::parse_code::end_of_file; +} + +template +inline constexpr ::fast_io::manipulators::scalar_flags string_default_scalar_flags{.noskipws=noskipws,.line=line}; + + +template<::std::integral char_type,typename traits,typename allocator_type> +inline constexpr ::fast_io::parse_result scan_context_define_whole_string_impl(bool& notfirstround,char_type const* first,char_type const* last,::std::basic_string& ref) +{ + if(!notfirstround)[[unlikely]] + { + ref.assign(first,last); + notfirstround=true; + } + else + { + ref.append(first,last); + } + return {last,::fast_io::parse_code::partial}; +} + +template<::std::integral char_type,typename traits,typename allocator_type> +inline constexpr ::fast_io::parse_code scan_context_define_whole_string_eof_impl(bool notfirstround,::std::basic_string& ref) +{ + if(!notfirstround) + ref.clear(); + return ::fast_io::parse_code::ok; +} + +} + +template +inline constexpr io_type_t scan_context_type(io_reserve_type_t&>>) noexcept +{ + return {}; +} + +template<::std::integral char_type,::fast_io::manipulators::scalar_flags flags,typename traits,typename allocator_type> +inline constexpr parse_result scan_context_define( + io_reserve_type_t&>>, + scan_string_context& skip_space_done, + char_type const* first,char_type const* last, + ::fast_io::manipulators::scalar_manip_t&> str) +{ + return ::fast_io::details::scan_context_define_string_impl(skip_space_done.copying,first,last,str.reference); +} + +template<::fast_io::manipulators::scalar_flags flags,std::integral char_type,typename traits,typename allocator_type> +inline constexpr ::fast_io::parse_code scan_context_eof_define(io_reserve_type_t&>>, + scan_string_context skip_space_done,::fast_io::manipulators::scalar_manip_t&> str) noexcept +{ + if constexpr(flags.line||flags.noskipws) + { + if(str.reference.empty()) + return ::fast_io::parse_code::end_of_file; + else + return ::fast_io::parse_code::ok; + } + else + return ::fast_io::details::scan_context_eof_string_define_impl(skip_space_done.copying); +} + +template +inline constexpr ::fast_io::manipulators::scalar_manip_t<::fast_io::details::string_default_scalar_flags,::std::basic_string&> scan_alias_define(io_alias_t,::std::basic_string& t) noexcept +{ + return {t}; +} + + +template +inline constexpr io_type_t<::fast_io::scan_string_context> scan_context_type(io_reserve_type_t&>>) noexcept +{ + return {}; +} + +template<::std::integral char_type,typename traits,typename allocator_type> +inline constexpr parse_result scan_context_define( + io_reserve_type_t&>>, + ::fast_io::scan_string_context &ctx, + char_type const* first,char_type const* last, + ::fast_io::manipulators::whole_get_t<::std::basic_string&> str) +{ + return ::fast_io::details::scan_context_define_whole_string_impl(ctx.copying,first,last,str.reference); +} + +template +inline constexpr ::fast_io::parse_code scan_context_eof_define(io_reserve_type_t&>>, + ::fast_io::scan_string_context ctx,::fast_io::manipulators::whole_get_t<::std::basic_string&> str) noexcept +{ + return ::fast_io::details::scan_context_define_whole_string_eof_impl(ctx.copying,str.reference); +} + +namespace manipulators +{ + +template +inline constexpr ::fast_io::manipulators::scalar_manip_t<::fast_io::details::string_default_scalar_flags,::std::basic_string&> line_get(::std::basic_string& line_str) noexcept +{ + return {line_str}; +} + +template +inline constexpr ::fast_io::manipulators::whole_get_t<::std::basic_string&> whole_get(::std::basic_string& whole_str) noexcept +{ + return {whole_str}; +} + +} + +} diff --git a/src/fast_io/include/fast_io_unit/timespec.h b/src/fast_io/include/fast_io_unit/timespec.h new file mode 100644 index 0000000..e8bfc57 --- /dev/null +++ b/src/fast_io/include/fast_io_unit/timespec.h @@ -0,0 +1,89 @@ +#pragma once + +namespace fast_io +{ + +namespace details +{ + +inline constexpr bool denom_is_natural_pow10(std::int_least64_t denom) noexcept +{ + if(denom<0) + return false; + std::uint_least64_t den{static_cast(denom)}; + for(;!(den%10u);den/=10u); + return den==1; +} + +} +#if !defined(__MSDOS__) && !defined(__AVR__) && (!defined(__MINGW32__) || __has_include(<_mingw_stat64.h>)) + +template +constexpr std::size_t print_reserve_size(io_reserve_type_t) noexcept +{ + return print_reserve_size(io_reserve_type)+1+print_reserve_size(io_reserve_type); +} + +namespace details +{ + +inline constexpr std::size_t denom_natural_log10(std::uint_least64_t den) noexcept +{ + std::size_t logarithm{}; + for(;!(den%10u);den/=10u) + ++logarithm; + return logarithm; +} + +template +inline constexpr Iter subseconds_part_print_sz_impl(Iter it,uint_type nsec) noexcept +{ + if constexpr(std::numeric_limits::max()>=lim) + { + constexpr uint_type lmt{static_cast(lim)}; + if((!nsec)||lmt<=nsec) + return it; + } + else + { + if(!nsec) + return it; + } + *it=char_literal_v; + ++it; + constexpr std::size_t lgsz{denom_natural_log10(lim)}; + std::size_t sz{lgsz}; + for(;nsec%10==0;--sz) + nsec/=10; + if constexpr(sizeof(uint_type)<=sizeof(unsigned)) + with_length_output_unsigned(it,static_cast(nsec),sz); + else + with_length_output_unsigned(it,nsec,sz); + return it+sz; +} + +template +inline constexpr Iter timespec_print_impl(Iter it,struct timespec spc) noexcept +{ + return subseconds_part_print_sz_impl<1000000000UL,char_type>( + print_reserve_define(io_reserve_type,it,spc.tv_sec), + static_cast(spc.tv_nsec)); +} + +} + +template +constexpr char_type* print_reserve_define(io_reserve_type_t, char_type* it,struct timespec spc) noexcept +{ + return details::timespec_print_impl(it,spc); +} + +inline constexpr unix_timestamp timespec_to_unix_timestamp(struct timespec tsc) noexcept +{ + constexpr std::uint_least64_t mul_factor{uint_least64_subseconds_per_second/1000000000u}; + return {static_cast(tsc.tv_sec),static_cast(tsc.tv_nsec)*mul_factor}; +} + +#endif + +} diff --git a/src/fast_io/readme.md b/src/fast_io/readme.md new file mode 100644 index 0000000..1521427 --- /dev/null +++ b/src/fast_io/readme.md @@ -0,0 +1,338 @@ +# fast_io + +fast_io is a C++20 input/output library that provides [exceptional speed](readme.md#Benchmarks) and is designed to replace the commonly used `` and `` libraries. It is a header-only library and is licensed under the [MIT license](license.txt), making it easy to include in any project. However, it requires a C++20 compiler that supports concepts. + +*The original repository for fast_io has been archived due to git bloat over time, but older commits can still be found there.* +*old commits were [here](https://bitbucket.org/ejsvifq_mabmip/fast_io_archive-2022-01-23).* + +## Examples +### Print to `stdout` +```cpp +#include + +int main() { + print("Hello, fast_io world!\n"); +} +``` +### Memory map file +```cpp +#include + +int main() { + fast_io::native_file_loader file_data("text.txt"); + // file_data satisfies std::ranges::contiguous_range +} +``` +### Other examples + +For other up-to-date examples, please look in the [`examples/`](examples/) folder. + +Deprecated examples are [here](https://bitbucket.org/ejsvifq_mabmip/fast_io_deprecated) +but they might not work anymore. + +This i18n repo stores the i18n source files. + +[https://bitbucket.org/ejsvifq_mabmip/fast_io_i18n](https://bitbucket.org/ejsvifq_mabmip/fast_io_i18n) + +## F.A.Q. +### What does "fast" mean in fast_io? + +The term ```fast``` in ```fast_io``` does not necessarily imply that it is the fastest input/output library available (as it would have been named as ```fastest_io``` instead). Instead, the term refers to the fact that ```fast_io``` is notably faster than `````` and `````` libraries in all cases. + +### What are the supported platforms, compilers...? +See [support.md](support.md) for a list of supported things and platform specific usage notes. + +### Other questions? +You can ask questions on the [fast_io discord server](https://discord.gg/wYfh8kk) +or QQ group: `801441303`. + +## Documentation +See either https://ewindy.gitee.io/fast_io_rst/index.html or https://gitee.com/qabeowjbtkwb/fast_io/wikis. + +## Features +- As close to system call as possible. +- Unicode support (UTF-8, UTF-16, UTF-32) + codecvt for GB18030 and UTF-EBCDIC (no libc correctly deals with it) +- RAII for C `FILE*`, POSIX `fd` and win32/NT `HANDLE` +- Interop with `` and `` +- No easily misused stuff like `std::endl` +- Static I/O manipulators instead of format strings. +- Optional locale. +- Stateless I/O manipulation. +- Consistent error handling; when available, exceptions as the **only** error reporting mechanism (no `std::error_code`, `std::system_error` or useless bounds checking) +- Freestanding mode. +- Address Sanitizer special code for protecting memory safety issues. +- Dynamic Instrumentation Support + +- Supports POSIX iconv. You can use fast_io for your coding conversion. +- Binary serialization for trivially copyable types and standard containers +- Plays well with C++ containers (e.g. `std::vector` is valid) +- Basic/Lua/Python/etc format (print, scan). No support for C and C++ since they are security hazards. +- Provide APIs to expose the internal implementation of `FILE*` and C++ streams. + +- Native Handle Interface +- Extremely easy to support custom devices +- C and C++ style compile time open mode parsing. +- No `traits_type` and `EOF` +- Dynamic Type Support +- Multi Process +- Memory mapping +- debugging IO (optionally with GUI) +- Round-trip floating point algorithm +- Hash algorithms support: intrinsic SHA-1, intrinsic HMAC-SHA1, intrinsic SHA-256, intrinsic HMAC-SHA256, SHA-512, HMAC-SHA512 as well as non crypto hash algorithms, such as Jenkins Hash. +- zlib compression/decompression +- Filesystem +- OpenSSL BIO, Qt QFile, MFC CFile support + +### Post C++20 + 1. Module support + 2. Coroutine support for async IO + 3. Improve and refactor code once [Zero-overhead deterministic exceptions](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0709r0.pdf) are added to the standard + +## Benchmarks + +1. I/O 10M integers + +Goal: Print out ten million integers from 0 to 10M to file. Then reopen that file to scan back. + +All benchmarks are in benchmarks/0000.10m_size_t/unit. + +Notice: I modified libstdc++'s BUFSIZ 1048576 due to BUFSIZ is too small (512 bytes) for MinGW-W64, or it performs horribly. + + +| Platform | Windows |MinGW-W64 GCC 11.0.0 | MSVCRT + libstdc++ | +|--------------------------------|-------------------------|-----------------------|------------------------------------------------------| +| | + +| Method | Output time | Input time | Comment | +|--------------------------------|-------------------------|-----------------------|------------------------------------------------------| +| stdio.h(fprintf/fscanf) | 2.412987s | 5.607791s | | +| fstream | 0.462012s | 1.192s | | +| fstream with rdbuf.sputc trick | 0.33895s | 1.170173s | | +| fast_io::i/obuf_file | 0.04903s | 0.080996s | | +| fast_io::i/obuf_file_mutex | 0.146064s | 0.113155s | thread safe | +| c_locale_i/obuf_file ("C") | 0.065988s | 0.086012s | imbued with locale, locale "C" | +| c_locale_i/obuf_file local | 0.153995s | :x: | imbued with locale, locale "" | +| fmt::format_int+obuf_file | 0.122999s | :x: | | +| fmt::format_int+ofstream | 0.209055s | :x: | | +| fmt::format+ofstream | 0.548s | :x: | fmt makes things slower | +| fmt::print | 0.663996s | :x: | fmt makes things slower | +| std::to_chars+obuf_file | 0.12s | :x: | | +| std::to_chars+ofstream | 0.192s | :x: | | +| fast_io::c_file_unlocked | 0.098999s | 0.126003s | I hacked MSVCRT's FILE* implementation | +| fast_io::c_file | 0.298988s | 0.318001s | Thread Safe. I hacked MSVCRT's FILE* implementation | +| fast_io::filebuf_file | 0.048999s | 0.081s | I hacked libstdc++'s streambuf/filebuf implementation| +| fast_io::iobuf_utf8_file_char16| 0.124s | 0.112001s | UTF-16=>UTF-8 with SSE| +| fast_io::iobuf_utf8_file_char32| 0.110999s | 0.111011s | UTF-32=>UTF-8 with SSE| +| std::wofstream | 2.64s | 3.843735s | wofstream with std::locale codecvt. Extremely slow tbh.| +| fast_io::wfilebuf_io_observer | 2.415692s | 2.497704s | wofstream with std::locale codecvt. This proves fstream can never get fixed.| +| Rust language | 0.483s | :x: | RUST IS SLOW. Also Rust does not deal with locale. Think how bad it is. | +| Rust itoa library 0.4.6 | > 0.165s | :x: | I ignored the `\n` part for it to ensure no bias. | + + +Rust language is 10x slower than fast\_io. + binary bloat and itoa library is still extremely slow and usable for me. It is at least 3x slower than fast\_io. + + +Run the same test on MSVC 19.26.28805. + + +| Platform | Windows | MSVC 19.26.28805 | Install fmtlib wastes time of my life | +|--------------------------------|-------------------------|-----------------------|------------------------------------------------------| +| | + +| Method | Output time | Input time | Comment | +|--------------------------------|-------------------------|-----------------------|------------------------------------------------------| +| stdio.h(fprintf/fscanf) | 1.5353597s | 1.4157233s | | +| fstream | 3.6350262s | 3.8420339s | | +| fstream with rdbuf.sputc trick | 3.3735902s | 3.8145566s | | +| fast_io::i/obuf_file | 0.0631433s | 0.1030554s | | +| fast_io::i/obuf_file_mutex | 0.2190659s | 0.2485886s | thread safe | +| std::to_chars+obuf_file | 0.1641641s | :x: | | +| std::to_chars+ofstream | 0.5461922s | :x: | | +| fast_io::c_file_unlocked | 0.1102575s | 0.2399757s | I hacked Universal CRT's FILE* implementation | +| fast_io::c_file | 0.2034755s | 0.2621148s | Thread Safe. I hacked UCRT's FILE* implementation | +| fast_io::filebuf_file | 0.126661s | 0.2378803s | I hacked MSVC STL's streambuf/filebuf implementation | + +Run the same test on GCC 11. glibc + libstdc++ + + +| Platform | Linux | GCC 11.0.0 | glibc + libstdc++ | +|--------------------------------|-------------------------|-----------------------|------------------------------------------------------| +| | + +| Method | Output time | Input time | Comment | +|--------------------------------|-------------------------|-----------------------|------------------------------------------------------| +| stdio.h(fprintf/fscanf) | 0.532792935s | 0.591907111s | | +| fstream with rdbuf.sputc trick | 0.318896068s | 0.429406415s | | +| fast_io::i/obuf_file | 0.050300857s | 0.065372395s | | +| fast_io::i/obuf_file_mutex | 0.05290654s | 0.083040518s | thread safe | +| c_locale_i/obuf_file ("C") | 0.051939052s | 0.065820056s | imbued with locale, locale "C" | +| c_locale_i/obuf_file local | 0.162406082s | :x: | imbued with locale, locale "" | +| std::to_chars+obuf_file | 0.115453587s | :x: | | +| fmt::format_int+obuf_file | 0.1183587s | :x: | | +| fmt::format_int+ofstream | 0.195914384s | :x: | | +| fmt::format+ofstream | 0.633590975s | :x: | fmt makes things slower | +| fmt::print | 0.495270371s | :x: | fmt makes things slower | +| boost::iostreams | 0.400906063s | 0.444717051s | Using boost iostreams does not make your code faster | +| fast_io::c_file_unlocked | 0.060076723s | 0.073299716s | I hacked glibc's FILE* implementation | +| fast_io::c_file | 0.092490191s | 0.104545535s | Thread Safe. I hacked glibc's FILE* implementation | +| fast_io::filebuf_file | 0.052251608s | 0.06655806s | I hacked libstdc++'s streambuf/filebuf implementation| + +You can see fast_io can also boost the performance of existing facilities for 10x! Yes, it can even improve FILE* and fstream's performance for 10x depending on platforms since I use concepts to abstract them all. fmtlib actually slows down I/O performance. + +2. Output 10M double in round-trip mode with Ryu algorithm + +We only perform this test for MSVC since only msvc's charconv implements it. Yes. fast_io defeats msvc's charconv for over 20% for running the same algorithm. + +All benchmarks are in benchmarks/0001.10m_double/charconv. + +Run the same test on MSVC 19.26.28805. + + +| Platform | Windows | MSVC 19.26.28805 | | +|--------------------------------|-------------------------|-----------------------|------------------------------------------------------| +| | + +| Method | Output time | Comment | +|--------------------------------|-------------------------|------------------------------------------------------------------------------| +| i/obuf_file | 0.4653818s | | +| charconv + obuf_file | 0.6011s | | + +3. Raw I/O Performance + +All benchmarks are in benchmarks/0014.file_io/file_io. + +Output 100000000x "Hello World\n" + +Notice: I modified libstdc++'s std::filebuf's BUFSIZ to 1048576 due to BUFSIZ is too small (512 bytes) for MinGW-W64 or it performs horribly. + + + +| Platform | Windows |MinGW-W64 GCC 11.0.0 | MSVCRT + libstdc++ | +|--------------------------------|-------------------------|-----------------------|------------------------------------------------------| +| | + +| Method | Output time | Comment | +|--------------------------------|-------------------------|------------------------------------------------------------------------------| +| fwrite | 2.524001s | | +| fstream | 1.013001s | | +| fast_io::obuf_file | 0.437998s | | +| fast_io::obuf_file_mutex | 1.371s |Thread safe | +| fast_io::c_file_unlocked | 1.164997s |I hacked MSVCRT's FILE* implementation | +| fast_io::c_file | 3.337945s |Thread Safe. I hacked MSVCRT's FILE* implementation. Need further optimization| +| fast_io::filebuf_file | 0.467001s |I hacked libstdc++'s std::filebuf implementation | + + +| Platform | Linux | GCC 11.0.0 | glibc + libstdc++ | +|--------------------------------|-------------------------|-----------------------|------------------------------------------------------| +| | + +| Method | Output time | Comment | +|--------------------------------|-------------------------|------------------------------------------------------------------------------| +| fwrite | 1.457288317s | | +| fstream | 1.249783346s | | +| fast_io::obuf_file | 0.494827134s | | +| fast_io::obuf_file_mutex | 0.497138826s |Thread safe | +| fast_io::c_file_unlocked | 0.687976666s |I hacked glibc's FILE* implementation | +| fast_io::c_file | 0.910792697s |Thread Safe. I hacked glibc's FILE* implementation | +| fast_io::filebuf_file | 0.526955039s |I hacked libstdc++'s std::filebuf implementation | + + +| Platform | Windows | MSVC 19.26.28805 | UCRT + MSVC STL | +|--------------------------------|-------------------------|-----------------------|------------------------------------------------------| +| | + +| Method | Output time | Comment | +|--------------------------------|-------------------------|------------------------------------------------------------------------------| +| fwrite | 3.3139122s | | +| fstream | 1.7184119s | | +| fast_io::obuf_file | 0.7996034s | | +| fast_io::obuf_file_mutex | 2.2949221s |Thread safe. It looks like std::mutex is horribly slow for MSVC STL. | +| fast_io::c_file_unlocked | 1.2103924s |I hacked UCRT's FILE* implementation | +| fast_io::c_file | 2.3604295s |Thread Safe. I hacked UCRT's FILE* implementation | +| fast_io::filebuf_file | 1.2805368s |I hacked MSVC STL's std::filebuf implementation | + + +4. Binary Size +Just use the benchmark in benchmarks/0014.file_io/file_io. +Dude, you should avoid stream as plague tbh. It is not healthy. + + +| Platform | Windows |MinGW-W64 GCC 11.0.0 | MSVCRT + libstdc++ + static compile | +|--------------------------------|-------------------------|-----------------------|------------------------------------------------------| +| | + +| Method | Binary Size | Comment | +|--------------------------------|-------------------------|------------------------------------------------------------------------------| +| fstream | 925KB |Use fstream is not good for your health since std::locale bloats your binary. | +| fast_io::obuf_file | 155KB | | +| fast_io::c_file_unlocked | 157KB |I hacked MSVCRT's FILE* implementation | +| fast_io::c_file | 157KB |Thread Safe. I hacked MSVCRT's FILE* implementation | +| fast_io::filebuf_file | 933KB |I hacked libstdc++'s std::filebuf implementation. C++ stream sucks | + + +5. Code Convert + +Generate 100000000 🚄 emojis by using the program in benchmarks/0020.utf/fill_nc.cc + +Benchmarks are in examples/0043.iconv +Universal iconv. (UTF-8 to GB18030 as an example) +iconv test: +| Platform | Windows |MinGW-W64 GCC 11.0.0 | MSVCRT + libstdc++ | +|--------------------------------|-------------------------|-----------------------|------------------------------------------------------| +| | + +| Method | Elapsed time | Comment | +|--------------------------------|-------------------------|------------------------------------------------------------------------------| +| iconv command | 1.529s | | +| universal.cc | 1.293s | use POSIX libiconv | + + +UTF8->UTF16LE + +Benchmarks are in examples/0022.utf + +iconv test: +| Platform | Windows |MinGW-W64 GCC 11.0.0 | MSVCRT + libstdc++ | +|--------------------------------|-------------------------|-----------------------|------------------------------------------------------| +| | + +| Method | Elapsed time | Comment | +|--------------------------------|-------------------------|------------------------------------------------------------------------------| +| iconv command | 0.967s | GNU iconv. No BOM which sucks | +| utf8_file_to_utf16_file.cc | 0.498s | I use the SSE algorithms provided by the utf-utils project. | + +UTF8->UTF32LE + +Benchmarks are in examples/0022.utf + +iconv test: +| Platform | Windows |MinGW-W64 GCC 11.0.0 | MSVCRT + libstdc++ | +|--------------------------------|-------------------------|-----------------------|------------------------------------------------------| +| | + +| Method | Elapsed time | Comment | +|--------------------------------|-------------------------|------------------------------------------------------------------------------| +| iconv command | 0.844s | GNU iconv. No BOM which sucks | +| utf8_file_to_utf32_file.cc | 0.442s | I use the SSE algorithms provided by the utf-utils project. | + +## Credits + +The creation and development of this project were made possible thanks to the valuable contributions of various open-source projects. While the code was not copied directly from these projects, I used them as references and re-implemented them to suit the specific purposes of this library. In some cases, integration issues arose that required modifications to the original code. I am grateful to these projects and their developers for their commitment to making their code open and accessible to the wider community. + +|Project | Url +|-----------------|----------------------------------------- +|Grisu-Exact |https://github.com/jk-jeon/Grisu-Exact +|Ryu |https://github.com/ulfjack/ryu +|SHA-Intrinsics |https://github.com/noloader/SHA-Intrinsics +|SHA1 |https://github.com/vog/sha1 +|UTF-utils |https://github.com/BobSteagall/utf_utils +|jenkins-hash-java|https://github.com/vkandy/jenkins-hash-java +|md5 |https://github.com/JieweiWei/md5 +|ReactOS |https://github.com/reactos/reactos +|dirent_h |https://github.com/win32ports/dirent_h +|GNU C library |https://www.gnu.org/software/libc/ +|GNU Newlib |https://sourceware.org/newlib/ +|Dragonbox |https://github.com/jk-jeon/dragonbox +|JEAIII |https://github.com/jeaiii/itoa +|Crypto++ |https://github.com/weidai11/cryptopp +|MyItoA |https://gitee.com/xjkp2283572185/MyStd diff --git a/src/fast_io/support.md b/src/fast_io/support.md new file mode 100644 index 0000000..56f3fdf --- /dev/null +++ b/src/fast_io/support.md @@ -0,0 +1,147 @@ +## Compiler Support +- GCC >= 14 +- Clang >= 17 +- Microsoft Visual C++ cl >= 19.36.32522 + +## C++ standard library support +- GCC libstdc++ +- LLVM libc++ +- MSVC STL + +## Architecture Support +- alpha +- i686 +- x86_64 +- arm +- aarch64 +- riscv +- riscv64 +- powerpc64 +- wasm32-wasi +- mips-abi32 +- mips-abin32 +- mips-abi64 +- avr +- ia64 +- loongarch64 +- xtensa-esp32 +- All other architectures should work, they just aren't tested due to time not being infinite. + +## Platform Support +- Windows 10/12 +- Windows Server 2019 +- Linux +- BSD platforms (Including FreeBSD, NetBSD, OpenBSD) +- Apple Darwin (MacOS) +- Apple IOS +- Microsoft DOS +- FreeDOS +- Barebone (No any operating system.) +- Cygwin/MSYS2 +- Android +- Wine +- Wine GCC +- ReactOS +- Windows Runtime +- Nintendo DS (devkitPro) +- Webassembly +- Managarm +- Vinix +- limine Bootloader +- AVR +- Banana +- LemonOS +- LLVM `raw_fd_ostream` +- Windows Kernel Driver +- Linux Kernel Module +- wasm2lua (Compile fast_io to Lua!) +- Intel PinTool (Dynamic Instrumentation) +- Any other platform (if you want me to support it, tell me, including your own OS) + +## Kernel Driver Support +- Windows NT kernel Driver +- Linux kernel Module + +## Legacy Windows Version Support +**You need define `_WIN32_WINNT` and `_WIN32_WINDOWS` version by yourself.** + +On Windows 95 or 95 Plus! you can enable `-O3` but not `-Ofast`. You'll also need `msvcrt.dll`. +- Windows 95 +- Windows 95 Plus! +- Windows Nashville +- Microsoft Memphis +- Windows 98 FE +- Windows 98 SE +- Windows ME +- Microsoft Neptune +- Windows NT +- Windows Odyssey +- Windows 2000 +- Windows Whistler +- Windows XP +- Windows Server 2003 +- Windows Longhorn +- Windows Vista +- Windows Server 2008 +- Windows Vienna +- Windows 7 +- Windows 8 +- Windows 8.1 +- Windows Home Server 2011 +- Windows Server 2012 +- Windows Server 2016 +- Windows 11. Windows 11 was a significant mistake. + +## Legacy Windows Version Support with DJGPP toolchain +- Windows 1.0 +- Windows 2.0 +- Windows 3.0 +- Windows 3.1 +- Microsoft Chicago +- Windows 95 +- Windows 95 Plus! +- Microsoft Memphis +- Windows 98 FE +- Windows 98 SE +- Windows ME + +## Supported libc FILE* hacks platforms +- glibc +- MSVCRT +- Universal CRT +- Universal CRT with MSVC debugging +- Wine's MSVCRT +- Wine's UCRT 9.11+ + +See wine bug [PR53960](https://gitlab.winehq.org/wine/wine/-/merge_requests/5752) + +- ReactOS MSVCRT +- ReactOS UCRT +- BSD libc/Apple Darwin +- MUSL libc +- DJGPP +- Newlib +- Bionic(Android) +- uclibc-ng +- wasi libc +- mlibc (this is a new libc which still contains a lot of bugs currently) +- avrlibc +- picolibc +- SerenityOS libc (untested) +- LLVM libc (untested) + +## Supported C++ standard library `std::streambuf`/`std::filebuf` hacks platforms +- GCC libstdc++ +- LLVM libc++ +- MSVC STL + +## Remote Debugger Support +- WinDbg +- Visual Studio Debugger +- DbgViewer +- Android ADB + +## Special Support +- LLVM Address Sanitizer +- Full freestanding support (which means we do not have any headers besides freestanding headers. Tested with GCC's --disable-hosted-libstdcxx without any libc, including newlib) +- Pintool support diff --git a/src/zip/DeflateFileWriter.cpp b/src/zip/DeflateFileWriter.cpp index d00752a..ad44303 100644 --- a/src/zip/DeflateFileWriter.cpp +++ b/src/zip/DeflateFileWriter.cpp @@ -9,21 +9,21 @@ namespace fs ////////////////////////////////////////////////////////////////////////// -DeflateFileWriter::DeflateFileWriter(AbsPath i_filePath, tl::lent_ref i_filesystem, uint8_t i_compressionLevel) - : m_filePath(std::move(i_filePath)) - , m_filesystem(std::move(i_filesystem)) - , m_compressionLevel(i_compressionLevel) +DeflateFileWriter::DeflateFileWriter(AbsPathView filePath, tl::lent_ref filesystem, uint8_t compressionLevel) + : m_filePath(std::move(filePath)) + , m_filesystem(std::move(filesystem)) + , m_compressionLevel(compressionLevel) { } ////////////////////////////////////////////////////////////////////////// -ZipWriter::DataWriterResult DeflateFileWriter::operator()(IStreamSink& i_sink) +ZipWriter::DataWriterResult DeflateFileWriter::operator()(IStreamSink& sink) { auto result = m_filesystem->openSource(m_filePath); if (result.has_error()) return tl::make_generic_error("Error opening input file '{}' to deflate: {}", m_filePath, result.error()); - return DeflateSinkWriter(*result.value(), m_compressionLevel)(i_sink); + return DeflateSinkWriter(*result.value(), m_compressionLevel)(sink); } ////////////////////////////////////////////////////////////////////////// diff --git a/src/zip/StoreFileWriter.cpp b/src/zip/StoreFileWriter.cpp index 8e2d2f4..d98f3e1 100644 --- a/src/zip/StoreFileWriter.cpp +++ b/src/zip/StoreFileWriter.cpp @@ -10,22 +10,22 @@ namespace fs ////////////////////////////////////////////////////////////////////////// -StoreFileWriter::StoreFileWriter(AbsPath i_filePath, tl::lent_ref i_filesystem) - : m_filePath(std::move(i_filePath)) - , m_filesystem(std::move(i_filesystem)) +StoreFileWriter::StoreFileWriter(AbsPathView filePath, tl::lent_ref filesystem) + : m_filePath(std::move(filePath)) + , m_filesystem(std::move(filesystem)) { } ////////////////////////////////////////////////////////////////////////// -ZipWriter::DataWriterResult StoreFileWriter::operator()(IStreamSink& i_sink) +ZipWriter::DataWriterResult StoreFileWriter::operator()(IStreamSink& sink) { auto openResult = m_filesystem->openSource(m_filePath); if (openResult.has_error()) return tl::make_generic_error("Error opening input file '{}' to store: {}", m_filePath, openResult.error()); const tl::unique_ref inputSource = std::move(openResult.value()); - return StoreSinkWriter(*inputSource)(i_sink); + return StoreSinkWriter(*inputSource)(sink); } ////////////////////////////////////////////////////////////////////////// diff --git a/src/zip/ZipPack.cpp b/src/zip/ZipPack.cpp index 5b3b3c9..48fd87c 100644 --- a/src/zip/ZipPack.cpp +++ b/src/zip/ZipPack.cpp @@ -24,7 +24,7 @@ namespace fs { namespace { -uint64_t computePersistentHash(const AbsPath& path) +uint64_t computePersistentHash(AbsPathView path) { uint64_t hash = 0; for (const tl::string& e : path) @@ -45,7 +45,7 @@ ZipPack::ZipPack(tl::unique_ref zipFileSource, ZipReader zipReader) ////////////////////////////////////////////////////////////////////////// -ZipPack::ZipPack(tl::lent_ref filesystem, AbsPath zipFileLocation, ZipReader zipReader) +ZipPack::ZipPack(tl::lent_ref filesystem, AbsPathView zipFileLocation, ZipReader zipReader) : m_filesystem(std::move(filesystem)) , m_zipFileLocation(std::move(zipFileLocation)) { @@ -74,7 +74,7 @@ ZipPack::CreateResult ZipPack::create(tl::unique_ref zipFileSource) ////////////////////////////////////////////////////////////////////////// -ZipPack::CreateResult ZipPack::create(tl::lent_ref filesystem, AbsPath zipFileLocation) +ZipPack::CreateResult ZipPack::create(tl::lent_ref filesystem, AbsPathView zipFileLocation) { tl::result, Error> openResult = filesystem->openSource(zipFileLocation); if (openResult.has_error()) @@ -236,7 +236,7 @@ void ZipPack::createEntries(ZipReader zipReader) ////////////////////////////////////////////////////////////////////////// -uint16_t ZipPack::getOrAddFolder(AbsPath folderPath, tl::vector>& io_childrenIndices) +uint16_t ZipPack::getOrAddFolder(AbsPathView folderPath, tl::vector>& io_childrenIndices) { if (folderPath.empty()) return 0; @@ -253,8 +253,7 @@ uint16_t ZipPack::getOrAddFolder(AbsPath folderPath, tl::vector(ErrorCode::BadPath, "Invalid Path"); @@ -328,7 +327,7 @@ OpenSourceResult ZipPack::openSource(const AbsPath& path, IPack::SourceFlags fla ////////////////////////////////////////////////////////////////////////// -OpenStreamSourceResult ZipPack::openStreamSource(const AbsPath& path, IPack::SourceFlags flags) const +OpenStreamSourceResult ZipPack::openStreamSource(AbsPathView path, IPack::SourceFlags flags) const { if (!path.is_valid()) return tl::make_error(ErrorCode::BadPath, "Invalid Path"); @@ -346,7 +345,7 @@ OpenStreamSourceResult ZipPack::openStreamSource(const AbsPath& path, IPack::Sou ////////////////////////////////////////////////////////////////////////// -OpenMapSourceResult ZipPack::openMapSource(const AbsPath& path, MapView mapView, SourceFlags flags) const +OpenMapSourceResult ZipPack::openMapSource(AbsPathView path, MapView mapView, SourceFlags flags) const { if (!path.is_valid()) return tl::make_error(ErrorCode::BadPath, "Invalid Path"); @@ -376,14 +375,14 @@ OpenMapSourceResult ZipPack::openMapSource(const AbsPath& path, MapView mapView, ////////////////////////////////////////////////////////////////////////// -ConvertToNativePathResult ZipPack::convertToNativePath(const AbsPath& path) const +ConvertToNativePathResult ZipPack::convertToNativePath(AbsPathView path) const { return tl::make_error(ErrorCode::NotAllowed, "Cannot convert zip paths to native ones '{}'", path); } ////////////////////////////////////////////////////////////////////////// -IsFileResult ZipPack::isFile(const AbsPath& path) const +IsFileResult ZipPack::isFile(AbsPathView path) const { if (!path.is_valid()) return tl::make_error(ErrorCode::BadPath, "Invalid Path"); @@ -398,7 +397,7 @@ IsFileResult ZipPack::isFile(const AbsPath& path) const ////////////////////////////////////////////////////////////////////////// -IsFolderResult ZipPack::isFolder(const AbsPath& path) const +IsFolderResult ZipPack::isFolder(AbsPathView path) const { if (!path.is_valid()) return tl::make_error(ErrorCode::BadPath, "Invalid Path"); @@ -413,7 +412,7 @@ IsFolderResult ZipPack::isFolder(const AbsPath& path) const ////////////////////////////////////////////////////////////////////////// -ExistsResult ZipPack::exists(const AbsPath& path) const +ExistsResult ZipPack::exists(AbsPathView path) const { if (!path.is_valid()) return tl::make_error(ErrorCode::BadPath, "Invalid Path"); @@ -423,7 +422,7 @@ ExistsResult ZipPack::exists(const AbsPath& path) const ////////////////////////////////////////////////////////////////////////// -GetStatResult ZipPack::getStat(const AbsPath& path) const +GetStatResult ZipPack::getStat(AbsPathView path) const { if (!path.is_valid()) return tl::make_error(ErrorCode::BadPath, "Invalid Path"); @@ -442,7 +441,7 @@ GetStatResult ZipPack::getStat(const AbsPath& path) const ////////////////////////////////////////////////////////////////////////// -cppcoro::generator ZipPack::enumerate(const AbsPath& path) const +cppcoro::generator ZipPack::enumerate(AbsPathView path) const { TL_ASSERT(path.is_valid()); @@ -509,7 +508,7 @@ void ZipPack::buildUpPath(RelPath& path, const File& file, uint32_t toIndex) con } -cppcoro::generator ZipPack::enumerateRecursively(const AbsPath& path) const +cppcoro::generator ZipPack::enumerateRecursively(AbsPathView path) const { TL_ASSERT(path.is_valid()); diff --git a/src/zip/ZipUtils.cpp b/src/zip/ZipUtils.cpp index fbb3a21..9f41c82 100644 --- a/src/zip/ZipUtils.cpp +++ b/src/zip/ZipUtils.cpp @@ -12,7 +12,7 @@ namespace fs namespace { -UnzipResult unzip(IFilesystem& dstFilesystem, const AbsPath& filePath, tl::unique_ref zipPack) +UnzipResult unzip(IFilesystem& dstFilesystem, AbsPathView filePath, tl::unique_ref zipPack) { MakeFolderResult makeFolderResult = dstFilesystem.makeFolder(filePath); if (makeFolderResult.has_error()) @@ -21,7 +21,7 @@ UnzipResult unzip(IFilesystem& dstFilesystem, const AbsPath& filePath, tl::uniqu for (const EnumerateEntry& ee: zipPack->enumerateRecursively(AbsPath("/"))) { AbsPath dstPath = filePath + ee.path; - OUTCOME_TRY(dstFilesystem.makeFolder(ee.isFolder ? dstPath : dstPath.parent())); + OUTCOME_TRY(dstFilesystem.makeFolder(ee.isFolder ? AbsPathView(dstPath) : dstPath.parent())); if (!ee.isFolder) { OUTCOME_TRY(auto source, zipPack->openStreamSource(AbsPath("/") + ee.path)); @@ -34,20 +34,20 @@ UnzipResult unzip(IFilesystem& dstFilesystem, const AbsPath& filePath, tl::uniqu } } -UnzipResult unzipSource(IFilesystem& dstFilesystem, const AbsPath& filePath, tl::unique_ref source) +UnzipResult unzipSource(IFilesystem& dstFilesystem, AbsPathView filePath, tl::unique_ref source) { OUTCOME_TRY(auto pack, ZipPack::create(std::move(source))); return unzip(dstFilesystem, filePath, std::move(pack)); } -UnzipResult unzipFile(IFilesystem& dstFilesystem, const AbsPath& filePath, tl::lent_ref filesystem, AbsPath srcFilePath) +UnzipResult unzipFile(IFilesystem& dstFilesystem, AbsPathView filePath, tl::lent_ref filesystem, AbsPathView srcFilePath) { OUTCOME_TRY(auto pack, ZipPack::create(std::move(filesystem), std::move(srcFilePath))); return unzip(dstFilesystem, filePath, std::move(pack)); } -ZipResult zipToSink(ISink& sink, tl::lent_ref filesystem, const AbsPath& path, uint8_t compressionLevel, size_t fileDataAlignment) +ZipResult zipToSink(ISink& sink, tl::lent_ref filesystem, AbsPathView path, uint8_t compressionLevel, size_t fileDataAlignment) { ZipWriter writer(sink, fileDataAlignment); @@ -67,7 +67,7 @@ ZipResult zipToSink(ISink& sink, tl::lent_ref filesystem, const Abs { if (!ee.isFolder) { - tl::result addResult = writer.addFile(ee.path.get_as(), [&filesystem, &path, &ee, compressionLevel](IStreamSink& sink) + tl::result addResult = writer.addFile(ee.path.str(), [&filesystem, &path, &ee, compressionLevel](IStreamSink& sink) { return DeflateFileWriter(path + ee.path, filesystem, compressionLevel)(sink); }); @@ -81,7 +81,7 @@ ZipResult zipToSink(ISink& sink, tl::lent_ref filesystem, const Abs return tl::success(); } -ZipResult zipToFile(IFilesystem& dstFilesystem, const AbsPath& dstFilePath, tl::lent_ref filesystem, const AbsPath& path, uint8_t compressionLevel, size_t fileDataAlignment) +ZipResult zipToFile(IFilesystem& dstFilesystem, AbsPathView dstFilePath, tl::lent_ref filesystem, AbsPathView path, uint8_t compressionLevel, size_t fileDataAlignment) { OUTCOME_TRY(const auto sink, dstFilesystem.openSink(dstFilePath, Mode::CreateOrOpenAndClear)); return zipToSink(*sink, std::move(filesystem), path, compressionLevel, fileDataAlignment);