From 1c5a657af06a920a340eaa8c8899f231b0e3603f Mon Sep 17 00:00:00 2001 From: trcrsired Date: Thu, 12 Jun 2025 18:04:05 +0800 Subject: [PATCH 01/81] unfinshed overhual of c's fwrite/fread etc --- include/fast_io_driver/qt_impl/qiodevice.h | 2 +- include/fast_io_legacy_impl/c/general.h | 309 ++++++++++++++++++--- 2 files changed, 276 insertions(+), 35 deletions(-) diff --git a/include/fast_io_driver/qt_impl/qiodevice.h b/include/fast_io_driver/qt_impl/qiodevice.h index 5b520a71b..aa72aae58 100644 --- a/include/fast_io_driver/qt_impl/qiodevice.h +++ b/include/fast_io_driver/qt_impl/qiodevice.h @@ -112,7 +112,7 @@ inline Iter read(basic_general_qdevice_io_observer qiob, Iter begin, template <::std::integral ch_type, typename T> requires(sizeof(ch_type) == 1) -inline ::std::pair try_get(basic_general_qdevice_io_observer qiob) +inline ::fast_io::try_get_result try_get(basic_general_qdevice_io_observer qiob) { char ch; bool ef{qiob.qdevice->getChar(&ch)}; diff --git a/include/fast_io_legacy_impl/c/general.h b/include/fast_io_legacy_impl/c/general.h index 7fd22b04b..4aa9466b8 100644 --- a/include/fast_io_legacy_impl/c/general.h +++ b/include/fast_io_legacy_impl/c/general.h @@ -23,29 +23,153 @@ inline auto fgetc_unlocked_impl(FILE *fp) noexcept { if constexpr (::std::same_as || ::std::same_as) { + +#pragma push_macro("FAST_IO_FGETC_UNLOCKED") +#pragma push_macro("FAST_IO_FGETC") +#pragma push_macro("FAST_IO_PLATFORM_SUPPORTS_FGETC_UNLOCKED") +#pragma push_macro("FAST_IO_FGETC_UNLOCKED_IMPL") + +#undef FAST_IO_FGETC_UNLOCKED +#undef FAST_IO_FGETC +#undef FAST_IO_PLATFORM_SUPPORTS_FGETC_UNLOCKED +#undef FAST_IO_FGETC_UNLOCKED_IMPL + #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); +#ifdef _fgetc_nolock +#define FAST_IO_FGETC_UNLOCKED(...) ::_fgetc_nolock(__VA_ARGS__) +#else +#define FAST_IO_FGETC_UNLOCKED(...) ::fast_io::noexcept_call(::_fgetc_nolock, __VA_ARGS__) +#endif +#elif defined(__BIONIC__) +#define FAST_IO_FGETC_UNLOCKED(...) ::fast_io::noexcept_call(::getc_unlocked, __VA_ARGS__) +#endif + +#ifndef FAST_IO_FGETC_UNLOCKED +#if defined(__GLIBC__) || defined(__LLVM_LIBC_TYPES_FILE_H__) +#define FAST_IO_FGETC_UNLOCKED(...) ::fgetc_unlocked(__VA_ARGS__) +#elif defined(fgetc_unlocked) +#define FAST_IO_FGETC_UNLOCKED(...) fgetc_unlocked(__VA_ARGS__) +#else +#define FAST_IO_FGETC_UNLOCKED(...) ::fast_io::noexcept_call(::fgetc_unlocked, __VA_ARGS__) +#endif +#endif + + +#if defined(__GLIBC__) || defined(__LLVM_LIBC_TYPES_FILE_H__) +#define FAST_IO_FGETC(...) ::fgetc(__VA_ARGS__) +#elif defined(fgetc_unlocked) +#define FAST_IO_FGETC(...) fgetc(__VA_ARGS__) #else - return fgetc(fp); +#define FAST_IO_FGETC(...) ::fast_io::noexcept_call(::fgetc, __VA_ARGS__) +#endif + +#if defined(__BIONIC__) +#define FAST_IO_PLATFORM_SUPPORTS_FGETC_UNLOCKED 1 +#elif defined(_WIN32) && !defined(__WINE__) +#define FAST_IO_PLATFORM_SUPPORTS_FGETC_UNLOCKED 1 +#elif defined(__LLVM_LIBC_TYPES_FILE_H__) +#define FAST_IO_PLATFORM_SUPPORTS_FGETC_UNLOCKED 1 +#elif defined(__NEWLIB__) +#if __GNU_VISIBLE +#define FAST_IO_PLATFORM_SUPPORTS_FGETC_UNLOCKED 1 #endif +#elif _POSIX_C_SOURCE >= 199309L || _XOPEN_SOURCE || _POSIX_SOURCE || _BSD_SOURCE || _SVID_SOURCE +#define FAST_IO_PLATFORM_SUPPORTS_FGETC_UNLOCKED 1 +#endif + +#if defined(FAST_IO_PLATFORM_SUPPORTS_FGETC_UNLOCKED) +#define FAST_IO_FGETC_UNLOCKED_IMPL(...) FAST_IO_FGETC_UNLOCKED(__VA_ARGS__) +#else +#define FAST_IO_FGETC_UNLOCKED_IMPL(...) FAST_IO_FGETC(__VA_ARGS__) +#endif + + return FAST_IO_FGETC_UNLOCKED_IMPL(fp); + +#pragma pop_macro("FAST_IO_FGETC_UNLOCKED_IMPL") +#pragma pop_macro("FAST_IO_PLATFORM_SUPPORTS_FGETC_UNLOCKED") +#pragma pop_macro("FAST_IO_FGETC") +#pragma pop_macro("FAST_IO_FGETC_UNLOCKED") } else { +#pragma push_macro("FAST_IO_FGETWC_UNLOCKED") +#pragma push_macro("FAST_IO_FGETWC") +#pragma push_macro("FAST_IO_PLATFORM_SUPPORTS_FGETWC_UNLOCKED") +#pragma push_macro("FAST_IO_PLATFORM_NOT_SUPPORTS_FGETWC") +#pragma push_macro("FAST_IO_FGETWC_UNLOCKED_IMPL") + +#undef FAST_IO_FGETWC_UNLOCKED +#undef FAST_IO_FGETWC +#undef FAST_IO_PLATFORM_SUPPORTS_FGETWC_UNLOCKED +#undef FAST_IO_PLATFORM_NOT_SUPPORTS_FGETWC +#undef FAST_IO_FGETWC_UNLOCKED_IMPL + +#if (defined(_WIN32) && !defined(__WINE__)) +#ifdef _fgetwc_nolock +#define FAST_IO_FGETWC_UNLOCKED(...) _fgetwc_nolock(__VA_ARGS__) +#else +#define FAST_IO_FGETWC_UNLOCKED(...) ::fast_io::noexcept_call(::_fgetwc_nolock, __VA_ARGS__) +#endif +#elif defined(__BIONIC__) +#define FAST_IO_FGETWC_UNLOCKED(...) ::fast_io::noexcept_call(::getc_unlocked, __VA_ARGS__) +#endif + +#ifndef FAST_IO_FGETWC_UNLOCKED +#if defined(__GLIBC__) || defined(__LLVM_LIBC_TYPES_FILE_H__) +#define FAST_IO_FGETWC_UNLOCKED(...) ::fgetwc_unlocked(__VA_ARGS__) +#elif defined(fgetwc_unlocked) +#define FAST_IO_FGETWC_UNLOCKED(...) fgetwc_unlocked(__VA_ARGS__) +#else +#define FAST_IO_FGETWC_UNLOCKED(...) ::fast_io::noexcept_call(::fgetwc_unlocked, __VA_ARGS__) +#endif +#endif + + +#if defined(__GLIBC__) || defined(__LLVM_LIBC_TYPES_FILE_H__) +#define FAST_IO_FGETWC(...) ::fgetwc(__VA_ARGS__) +#elif defined(fgetwc_unlocked) +#define FAST_IO_FGETWC(...) fgetwc(__VA_ARGS__) +#else +#define FAST_IO_FGETWC(...) ::fast_io::noexcept_call(::fgetwc, __VA_ARGS__) +#endif + +#if defined(__serenity__) +#define FAST_IO_PLATFORM_NOT_SUPPORTS_FGETWC 1 +#elif defined(__BIONIC__) +#if defined(__BIONIC_AVAILABILITY_GUARD) +#if __BIONIC_AVAILABILITY_GUARD(28) +#define FAST_IO_PLATFORM_SUPPORTS_FGETWC_UNLOCKED 1 +#endif +#endif +#elif defined(_WIN32) && !defined(__WINE__) #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; +#define FAST_IO_PLATFORM_SUPPORTS_FGETWC_UNLOCKED 1 +#endif +#elif defined(__LLVM_LIBC_TYPES_FILE_H__) +#define FAST_IO_PLATFORM_SUPPORTS_FGETWC_UNLOCKED 1 +#elif defined(__NEWLIB__) +#if __GNU_VISIBLE +#define FAST_IO_PLATFORM_SUPPORTS_FGETWC_UNLOCKED 1 +#endif +#elif _POSIX_C_SOURCE >= 199309L || _XOPEN_SOURCE || _POSIX_SOURCE || _BSD_SOURCE || _SVID_SOURCE +#define FAST_IO_PLATFORM_SUPPORTS_FGETWC_UNLOCKED 1 +#endif + +#if defined(FAST_IO_PLATFORM_NOT_SUPPORTS_FGETWC) +#define FAST_IO_FGETWC_UNLOCKED_IMPL(...) EOF +#elif defined(FAST_IO_PLATFORM_SUPPORTS_FGETWC_UNLOCKED) +#define FAST_IO_FGETWC_UNLOCKED_IMPL(...) FAST_IO_FGETWC_UNLOCKED(__VA_ARGS__) #else - return fgetwc(fp); +#define FAST_IO_FGETWC_UNLOCKED_IMPL(...) FAST_IO_FGETWC(__VA_ARGS__) #endif + + return FAST_IO_FGETWC_UNLOCKED_IMPL(fp); + +#pragma pop_macro("FAST_IO_FGETWC_UNLOCKED_IMPL") +#pragma pop_macro("FAST_IO_PLATFORM_NOT_SUPPORTS_FGETWC") +#pragma pop_macro("FAST_IO_PLATFORM_SUPPORTS_FGETWC_UNLOCKED") +#pragma pop_macro("FAST_IO_FGETWC") +#pragma pop_macro("FAST_IO_FGETWC_UNLOCKED") } } @@ -67,29 +191,146 @@ inline constexpr bool equals_to_eof_macro(int_type inv) noexcept template <::std::integral char_type> 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); + +#pragma push_macro("FAST_IO_UNGETC_UNLOCKED") +#pragma push_macro("FAST_IO_UNGETC") +#pragma push_macro("FAST_IO_PLATFORM_SUPPORTS_UNGETC_UNLOCKED") +#pragma push_macro("FAST_IO_UNGETC_UNLOCKED_IMPL") + +#undef FAST_IO_UNGETC_UNLOCKED +#undef FAST_IO_UNGETC +#undef FAST_IO_PLATFORM_SUPPORTS_UNGETC_UNLOCKED +#undef FAST_IO_UNGETC_UNLOCKED_IMPL + +#if (defined(_WIN32) && !defined(__WINE__)) +#ifdef _ungetc_nolock +#define FAST_IO_UNGETC_UNLOCKED(...) _ungetc_nolock(__VA_ARGS__) +#else +#define FAST_IO_UNGETC_UNLOCKED(...) ::fast_io::noexcept_call(::_ungetc_nolock, __VA_ARGS__) +#endif +#endif + +#ifndef FAST_IO_UNGETC_UNLOCKED +#if defined(__GLIBC__) || defined(__LLVM_LIBC_TYPES_FILE_H__) +#define FAST_IO_UNGETC_UNLOCKED(...) ::ungetc_unlocked(__VA_ARGS__) +#elif defined(ungetc_unlocked) +#define FAST_IO_UNGETC_UNLOCKED(...) ungetc_unlocked(__VA_ARGS__) +#else +#define FAST_IO_UNGETC_UNLOCKED(...) ::fast_io::noexcept_call(::ungetc_unlocked, __VA_ARGS__) +#endif +#endif + + +#if defined(__GLIBC__) || defined(__LLVM_LIBC_TYPES_FILE_H__) +#define FAST_IO_UNGETC(...) ::ungetc(__VA_ARGS__) +#elif defined(ungetc_unlocked) +#define FAST_IO_UNGETC(...) ungetc(__VA_ARGS__) #else - return ungetc(ch, fp); +#define FAST_IO_UNGETC(...) ::fast_io::noexcept_call(::ungetc, __VA_ARGS__) +#endif + +#if defined(__BIONIC__) +#define FAST_IO_PLATFORM_SUPPORTS_UNGETC_UNLOCKED 1 +#elif defined(_WIN32) && !defined(__WINE__) +#define FAST_IO_PLATFORM_SUPPORTS_UNGETC_UNLOCKED 1 +#elif defined(__LLVM_LIBC_TYPES_FILE_H__) +#define FAST_IO_PLATFORM_SUPPORTS_UNGETC_UNLOCKED 1 +#elif defined(__NEWLIB__) +#if __GNU_VISIBLE +#define FAST_IO_PLATFORM_SUPPORTS_UNGETC_UNLOCKED 1 +#endif +#elif _POSIX_C_SOURCE >= 199309L || _XOPEN_SOURCE || _POSIX_SOURCE || _BSD_SOURCE || _SVID_SOURCE +#define FAST_IO_PLATFORM_SUPPORTS_UNGETC_UNLOCKED 1 #endif + +#if defined(FAST_IO_PLATFORM_SUPPORTS_UNGETC_UNLOCKED) +#define FAST_IO_UNGETC_UNLOCKED_IMPL(...) FAST_IO_UNGETC_UNLOCKED(__VA_ARGS__) +#else +#define FAST_IO_UNGETC_UNLOCKED_IMPL(...) FAST_IO_UNGETC(__VA_ARGS__) +#endif + + return FAST_IO_UNGETC_UNLOCKED_IMPL(ch, fp); + +#pragma pop_macro("FAST_IO_UNGETC_UNLOCKED_IMPL") +#pragma pop_macro("FAST_IO_PLATFORM_SUPPORTS_UNGETC_UNLOCKED") +#pragma pop_macro("FAST_IO_UNGETC") +#pragma pop_macro("FAST_IO_UNGETC_UNLOCKED") } 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); +#pragma push_macro("FAST_IO_UNGETWC_UNLOCKED") +#pragma push_macro("FAST_IO_UNGETWC") +#pragma push_macro("FAST_IO_PLATFORM_SUPPORTS_UNGETWC_UNLOCKED") +#pragma push_macro("FAST_IO_PLATFORM_NOT_SUPPORTS_UNGETWC") +#pragma push_macro("FAST_IO_UNGETWC_UNLOCKED_IMPL") + +#undef FAST_IO_UNGETWC_UNLOCKED +#undef FAST_IO_UNGETWC +#undef FAST_IO_PLATFORM_SUPPORTS_UNGETWC_UNLOCKED +#undef FAST_IO_PLATFORM_NOT_SUPPORTS_UNGETWC +#undef FAST_IO_UNGETWC_UNLOCKED_IMPL + +#if (defined(_WIN32) && !defined(__WINE__)) +#ifdef _ungetwc_nolock +#define FAST_IO_UNGETWC_UNLOCKED(...) ::_ungetwc_nolock(__VA_ARGS__) #else - return ungetwc(ch, fp); +#define FAST_IO_UNGETWC_UNLOCKED(...) ::fast_io::noexcept_call(::_ungetwc_nolock, __VA_ARGS__) #endif +#endif + +#ifndef FAST_IO_UNGETWC_UNLOCKED +#if defined(__GLIBC__) || defined(__LLVM_LIBC_TYPES_FILE_H__) +#define FAST_IO_UNGETWC_UNLOCKED(...) ::ungetwc_unlocked(__VA_ARGS__) +#elif defined(ungetwc_unlocked) +#define FAST_IO_UNGETWC_UNLOCKED(...) ungetwc_unlocked(__VA_ARGS__) +#else +#define FAST_IO_UNGETWC_UNLOCKED(...) ::fast_io::noexcept_call(::ungetwc_unlocked, __VA_ARGS__) +#endif +#endif + + +#if defined(__GLIBC__) || defined(__LLVM_LIBC_TYPES_FILE_H__) +#define FAST_IO_UNGETWC(...) ::ungetwc(__VA_ARGS__) +#elif defined(ungetwc_unlocked) +#define FAST_IO_UNGETWC(...) ungetwc(__VA_ARGS__) +#else +#define FAST_IO_UNGETWC(...) ::fast_io::noexcept_call(::ungetwc, __VA_ARGS__) +#endif + +#if defined(__BIONIC__) +#define FAST_IO_PLATFORM_SUPPORTS_UNGETWC_UNLOCKED 1 +#elif defined(_WIN32) && !defined(__WINE__) +#define FAST_IO_PLATFORM_SUPPORTS_UNGETWC_UNLOCKED 1 +#elif defined(__LLVM_LIBC_TYPES_FILE_H__) +#define FAST_IO_PLATFORM_SUPPORTS_UNGETWC_UNLOCKED 1 +#elif defined(__NEWLIB__) +#if __GNU_VISIBLE +#define FAST_IO_PLATFORM_SUPPORTS_UNGETWC_UNLOCKED 1 +#endif +#elif _POSIX_C_SOURCE >= 199309L || _XOPEN_SOURCE || _POSIX_SOURCE || _BSD_SOURCE || _SVID_SOURCE +#define FAST_IO_PLATFORM_SUPPORTS_UNGETWC_UNLOCKED 1 + +#endif + +#if defined(FAST_IO_PLATFORM_NOT_SUPPORTS_UNGETWC) +#define FAST_IO_UNGETWC_UNLOCKED_IMPL(...) WEOF +#elif defined(FAST_IO_PLATFORM_SUPPORTS_UNGETWC_UNLOCKED) +#define FAST_IO_UNGETWC_UNLOCKED_IMPL(...) FAST_IO_UNGETWC_UNLOCKED(__VA_ARGS__) +#else +#define FAST_IO_UNGETWC_UNLOCKED_IMPL(...) FAST_IO_UNGETWC(__VA_ARGS__) +#endif + + return FAST_IO_UNGETWC_UNLOCKED_IMPL(ch, fp); + +#pragma pop_macro("FAST_IO_UNGETWC_UNLOCKED_IMPL") +#pragma pop_macro("FAST_IO_PLATFORM_NOT_SUPPORTS_UNGETWC") +#pragma pop_macro("FAST_IO_PLATFORM_SUPPORTS_UNGETWC_UNLOCKED") +#pragma pop_macro("FAST_IO_UNGETWC") +#pragma pop_macro("FAST_IO_UNGETWC_UNLOCKED") } } inline void ferror_throw_ex_impl(FILE *fp) @@ -112,12 +353,12 @@ template <::std::integral char_type> || ::std::same_as #endif || ::std::same_as) -inline ::std::pair try_get(basic_c_io_observer_unlocked ciob) +inline ::fast_io::try_get_result try_get(::fast_io::basic_c_io_observer_unlocked ciob) { - auto ret{details::fgetc_unlocked_impl(ciob.fp)}; - if (details::equals_to_eof_macro(ret)) + auto ret{::fast_io::details::fgetc_unlocked_impl(ciob.fp)}; + if (::fast_io::details::equals_to_eof_macro(ret)) { - details::ferror_throw_ex_impl(ciob.fp); + ::fast_io::details::ferror_throw_ex_impl(ciob.fp); return {0, false}; } return {static_cast(ret), true}; @@ -126,9 +367,9 @@ inline ::std::pair try_get(basic_c_io_observer_unlocked requires(::std::same_as || ::std::same_as || ::std::same_as) -inline void try_unget(basic_c_io_observer_unlocked ciob, char_type ch) noexcept +inline void try_unget(::fast_io::basic_c_io_observer_unlocked ciob, char_type ch) noexcept { - details::ungetc_unlocked_impl(ch, ciob.fp); + ::fast_io::details::ungetc_unlocked_impl(ch, ciob.fp); } } // namespace fast_io From 35aa4f4c03ccf39f41c1cdc09bdf712639d23f25 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Thu, 12 Jun 2025 20:46:20 +0800 Subject: [PATCH 02/81] done --- include/fast_io_legacy_impl/c/done.h | 196 +++++++++++++++++++----- include/fast_io_legacy_impl/c/general.h | 27 +--- 2 files changed, 157 insertions(+), 66 deletions(-) diff --git a/include/fast_io_legacy_impl/c/done.h b/include/fast_io_legacy_impl/c/done.h index f4b823995..00bbf6755 100644 --- a/include/fast_io_legacy_impl/c/done.h +++ b/include/fast_io_legacy_impl/c/done.h @@ -55,33 +55,78 @@ inline ::std::size_t c_fwrite_unlocked_impl(void const *__restrict begin, ::std: 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) + +#pragma push_macro("FAST_IO_FWRITE_UNLOCKED") +#pragma push_macro("FAST_IO_FWRITE") +#pragma push_macro("FAST_IO_PLATFORM_SUPPORTS_FWRITE_UNLOCKED") +#pragma push_macro("FAST_IO_FWRITE_UNLOCKED_IMPL") + +#undef FAST_IO_FWRITE_UNLOCKED +#undef FAST_IO_FWRITE +#undef FAST_IO_PLATFORM_SUPPORTS_FWRITE_UNLOCKED +#undef FAST_IO_FWRITE_UNLOCKED_IMPL + +#ifdef __has_builtin #if __has_builtin(__builtin_fwrite_unlocked) - __builtin_fwrite_unlocked(begin, type_size, count, fp) -#else - fwrite_unlocked(begin, type_size, count, fp) +#define FAST_IO_FWRITE_UNLOCKED(...) __builtin_fwrite_unlocked(__VA_ARGS__) #endif +#endif +#ifndef FAST_IO_FWRITE_UNLOCKED +#if defined(__GLIBC__) || defined(__LLVM_LIBC_TYPES_FILE_H__) +#define FAST_IO_FWRITE_UNLOCKED(...) ::fwrite_unlocked(__VA_ARGS__) +#elif defined(fwrite_unlocked) +#define FAST_IO_FWRITE_UNLOCKED(...) fwrite_unlocked(__VA_ARGS__) #else - fwrite_unlocked(begin, type_size, count, fp) +#define FAST_IO_FWRITE_UNLOCKED(...) ::fast_io::noexcept_call(::fwrite_unlocked, __VA_ARGS__) +#endif #endif -#elif !defined(fwrite) && defined(__has_builtin) + +#ifdef __has_builtin #if __has_builtin(__builtin_fwrite) - __builtin_fwrite(begin, type_size, count, fp) +#define FAST_IO_FWRITE(...) __builtin_fwrite(__VA_ARGS__) +#endif +#endif +#ifndef FAST_IO_FWRITE +#if defined(__GLIBC__) || defined(__LLVM_LIBC_TYPES_FILE_H__) +#define FAST_IO_FWRITE(...) ::fwrite(__VA_ARGS__) +#elif defined(fwrite) +#define FAST_IO_FWRITE(...) fwrite(__VA_ARGS__) #else - fwrite(begin, type_size, count, fp) +#define FAST_IO_FWRITE(...) ::fast_io::noexcept_call(::fwrite, __VA_ARGS__) +#endif +#endif + +#if defined(__BIONIC__) +#if defined(__BIONIC_AVAILABILITY_GUARD) +#if __BIONIC_AVAILABILITY_GUARD(28) +#define FAST_IO_PLATFORM_SUPPORTS_FWRITE_UNLOCKED 1 +#endif #endif +#elif defined(__LLVM_LIBC_TYPES_FILE_H__) +#define FAST_IO_PLATFORM_SUPPORTS_FWRITE_UNLOCKED 1 +#elif defined(__USE_MISC) || defined(__BSD_VISIBLE) +#define FAST_IO_PLATFORM_SUPPORTS_FWRITE_UNLOCKED 1 +#endif + +#if defined(__CYGWIN__) +#define FAST_IO_FWRITE_UNLOCKED_IMPL(...) my_cygwin_fwrite_unlocked(__VA_ARGS__) +#elif defined(FAST_IO_PLATFORM_SUPPORTS_FWRITE_UNLOCKED) +#define FAST_IO_FWRITE_UNLOCKED_IMPL(...) FAST_IO_FWRITE_UNLOCKED(__VA_ARGS__) #else - fwrite(begin, type_size, count, fp) +#define FAST_IO_FWRITE_UNLOCKED_IMPL(...) FAST_IO_FWRITE(__VA_ARGS__) #endif - }; + + ::std::size_t const written_count{FAST_IO_FWRITE_UNLOCKED_IMPL(begin, type_size, count, fp)}; + +#pragma pop_macro("FAST_IO_FWRITE_UNLOCKED_IMPL") +#pragma pop_macro("FAST_IO_PLATFORM_SUPPORTS_FWRITE_UNLOCKED") +#pragma pop_macro("FAST_IO_FWRITE") +#pragma pop_macro("FAST_IO_FWRITE_UNLOCKED") if (!written_count) [[unlikely]] { throw_posix_error(); } + #endif return written_count; } @@ -110,29 +155,77 @@ inline ::std::size_t c_fread_unlocked_impl(void *__restrict begin, ::std::size_t } } #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) + +#pragma push_macro("FAST_IO_FREAD_UNLOCKED") +#pragma push_macro("FAST_IO_FREAD") +#pragma push_macro("FAST_IO_PLATFORM_SUPPORTS_FREAD_UNLOCKED") +#pragma push_macro("FAST_IO_FREAD_UNLOCKED_IMPL") + +#undef FAST_IO_FREAD_UNLOCKED +#undef FAST_IO_FREAD +#undef FAST_IO_PLATFORM_SUPPORTS_FREAD_UNLOCKED +#undef FAST_IO_FREAD_UNLOCKED_IMPL + +// Define FAST_IO_FREAD_UNLOCKED +#ifdef __has_builtin #if __has_builtin(__builtin_fread_unlocked) - __builtin_fread_unlocked(begin, type_size, count, fp) -#else - fread_unlocked(begin, type_size, count, fp) +#define FAST_IO_FREAD_UNLOCKED(...) __builtin_fread_unlocked(__VA_ARGS__) +#endif #endif +#ifndef FAST_IO_FREAD_UNLOCKED +#if defined(__GLIBC__) || defined(__LLVM_LIBC_TYPES_FILE_H__) +#define FAST_IO_FREAD_UNLOCKED(...) ::fread_unlocked(__VA_ARGS__) +#elif defined(fread_unlocked) +#define FAST_IO_FREAD_UNLOCKED(...) fread_unlocked(__VA_ARGS__) #else - fread_unlocked(begin, type_size, count, fp) +#define FAST_IO_FREAD_UNLOCKED(...) ::fast_io::noexcept_call(::fread_unlocked, __VA_ARGS__) #endif -#elif !defined(fread) && defined(__has_builtin) +#endif + +// Define FAST_IO_FREAD +#ifdef __has_builtin #if __has_builtin(__builtin_fread) - __builtin_fread(begin, type_size, count, fp) +#define FAST_IO_FREAD(...) __builtin_fread(__VA_ARGS__) +#endif +#endif +#ifndef FAST_IO_FREAD +#if defined(__GLIBC__) || defined(__LLVM_LIBC_TYPES_FILE_H__) +#define FAST_IO_FREAD(...) ::fread(__VA_ARGS__) +#elif defined(fread) +#define FAST_IO_FREAD(...) fread(__VA_ARGS__) #else - fread(begin, type_size, count, fp) +#define FAST_IO_FREAD(...) ::fast_io::noexcept_call(::fread, __VA_ARGS__) +#endif +#endif + +// Detect whether platform supports fread_unlocked +#if defined(__BIONIC__) +#if defined(__BIONIC_AVAILABILITY_GUARD) +#if __BIONIC_AVAILABILITY_GUARD(28) +#define FAST_IO_PLATFORM_SUPPORTS_FREAD_UNLOCKED 1 +#endif #endif +#elif defined(__LLVM_LIBC_TYPES_FILE_H__) +#define FAST_IO_PLATFORM_SUPPORTS_FREAD_UNLOCKED 1 +#elif defined(__USE_MISC) || defined(__BSD_VISIBLE) +#define FAST_IO_PLATFORM_SUPPORTS_FREAD_UNLOCKED 1 +#endif + +// Define the unified dispatch macro +#if defined(__CYGWIN__) +#define FAST_IO_FREAD_UNLOCKED_IMPL(...) my_cygwin_fread_unlocked(__VA_ARGS__) +#elif defined(FAST_IO_PLATFORM_SUPPORTS_FREAD_UNLOCKED) +#define FAST_IO_FREAD_UNLOCKED_IMPL(...) FAST_IO_FREAD_UNLOCKED(__VA_ARGS__) #else - fread(begin, type_size, count, fp) +#define FAST_IO_FREAD_UNLOCKED_IMPL(...) FAST_IO_FREAD(__VA_ARGS__) #endif - }; + + ::std::size_t const read_count{FAST_IO_FREAD_UNLOCKED_IMPL(begin, type_size, count, fp)}; + +#pragma pop_macro("FAST_IO_FREAD_UNLOCKED_IMPL") +#pragma pop_macro("FAST_IO_PLATFORM_SUPPORTS_FREAD_UNLOCKED") +#pragma pop_macro("FAST_IO_FREAD") +#pragma pop_macro("FAST_IO_FREAD_UNLOCKED") if (read_count == 0) [[unlikely]] { if ( @@ -179,18 +272,27 @@ inline ::std::size_t c_fwrite_impl(void const *__restrict begin, ::std::size_t t throw_posix_error(rent._errno); } #else +#pragma push_macro("FAST_IO_FWRITE") +#undef FAST_IO_FWRITE - ::std::size_t written_count{ -#if !defined(fwrite) && defined(__has_builtin) +#ifdef __has_builtin #if __has_builtin(__builtin_fwrite) - __builtin_fwrite(begin, type_size, count, fp) -#else - fwrite(begin, type_size, count, fp) +#define FAST_IO_FWRITE(...) __builtin_fwrite(__VA_ARGS__) +#endif #endif +#ifndef FAST_IO_FWRITE +#if defined(__GLIBC__) || defined(__LLVM_LIBC_TYPES_FILE_H__) +#define FAST_IO_FWRITE(...) ::fwrite(__VA_ARGS__) +#elif defined(fwrite) +#define FAST_IO_FWRITE(...) fwrite(__VA_ARGS__) #else - fwrite(begin, type_size, count, fp) +#define FAST_IO_FWRITE(...) ::fast_io::noexcept_call(::fwrite, __VA_ARGS__) #endif - }; +#endif + + ::std::size_t const written_count{FAST_IO_FWRITE(begin, type_size, count, fp)}; + +#pragma pop_macro("FAST_IO_FWRITE") if (!written_count) [[unlikely]] { throw_posix_error(); @@ -217,17 +319,27 @@ inline ::std::size_t c_fread_impl(void *__restrict begin, ::std::size_t type_siz } } #else - ::std::size_t read_count{ -#if !defined(fread) && defined(__has_builtin) +#pragma push_macro("FAST_IO_FREAD") +#undef FAST_IO_FREAD + +#ifdef __has_builtin #if __has_builtin(__builtin_fread) - __builtin_fread(begin, type_size, count, fp) -#else - fread(begin, type_size, count, fp) +#define FAST_IO_FREAD(...) __builtin_fread(__VA_ARGS__) #endif +#endif +#ifndef FAST_IO_FREAD +#if defined(__GLIBC__) || defined(__LLVM_LIBC_TYPES_FILE_H__) +#define FAST_IO_FREAD(...) ::fread(__VA_ARGS__) +#elif defined(fread) +#define FAST_IO_FREAD(...) fread(__VA_ARGS__) #else - fread(begin, type_size, count, fp) +#define FAST_IO_FREAD(...) ::fast_io::noexcept_call(::fread, __VA_ARGS__) #endif - }; +#endif + + ::std::size_t const read_count{FAST_IO_FREAD(begin, type_size, count, fp)}; + +#pragma pop_macro("FAST_IO_FREAD") if (read_count == 0) [[unlikely]] { if ( diff --git a/include/fast_io_legacy_impl/c/general.h b/include/fast_io_legacy_impl/c/general.h index 4aa9466b8..3f0b0ce20 100644 --- a/include/fast_io_legacy_impl/c/general.h +++ b/include/fast_io_legacy_impl/c/general.h @@ -227,23 +227,13 @@ inline auto ungetc_unlocked_impl(char_type ch, FILE *fp) noexcept #if defined(__GLIBC__) || defined(__LLVM_LIBC_TYPES_FILE_H__) #define FAST_IO_UNGETC(...) ::ungetc(__VA_ARGS__) -#elif defined(ungetc_unlocked) +#elif defined(ungetc) #define FAST_IO_UNGETC(...) ungetc(__VA_ARGS__) #else #define FAST_IO_UNGETC(...) ::fast_io::noexcept_call(::ungetc, __VA_ARGS__) #endif -#if defined(__BIONIC__) -#define FAST_IO_PLATFORM_SUPPORTS_UNGETC_UNLOCKED 1 -#elif defined(_WIN32) && !defined(__WINE__) -#define FAST_IO_PLATFORM_SUPPORTS_UNGETC_UNLOCKED 1 -#elif defined(__LLVM_LIBC_TYPES_FILE_H__) -#define FAST_IO_PLATFORM_SUPPORTS_UNGETC_UNLOCKED 1 -#elif defined(__NEWLIB__) -#if __GNU_VISIBLE -#define FAST_IO_PLATFORM_SUPPORTS_UNGETC_UNLOCKED 1 -#endif -#elif _POSIX_C_SOURCE >= 199309L || _XOPEN_SOURCE || _POSIX_SOURCE || _BSD_SOURCE || _SVID_SOURCE +#if !defined(__BIONIC__) && defined(_MSC_VER) #define FAST_IO_PLATFORM_SUPPORTS_UNGETC_UNLOCKED 1 #endif @@ -301,19 +291,8 @@ inline auto ungetc_unlocked_impl(char_type ch, FILE *fp) noexcept #define FAST_IO_UNGETWC(...) ::fast_io::noexcept_call(::ungetwc, __VA_ARGS__) #endif -#if defined(__BIONIC__) -#define FAST_IO_PLATFORM_SUPPORTS_UNGETWC_UNLOCKED 1 -#elif defined(_WIN32) && !defined(__WINE__) -#define FAST_IO_PLATFORM_SUPPORTS_UNGETWC_UNLOCKED 1 -#elif defined(__LLVM_LIBC_TYPES_FILE_H__) -#define FAST_IO_PLATFORM_SUPPORTS_UNGETWC_UNLOCKED 1 -#elif defined(__NEWLIB__) -#if __GNU_VISIBLE -#define FAST_IO_PLATFORM_SUPPORTS_UNGETWC_UNLOCKED 1 -#endif -#elif _POSIX_C_SOURCE >= 199309L || _XOPEN_SOURCE || _POSIX_SOURCE || _BSD_SOURCE || _SVID_SOURCE +#if !defined(__BIONIC__) && defined(_MSC_VER) #define FAST_IO_PLATFORM_SUPPORTS_UNGETWC_UNLOCKED 1 - #endif #if defined(FAST_IO_PLATFORM_NOT_SUPPORTS_UNGETWC) From 418ccc01c98b834ec6c17f66a6cc526ddb61c4d6 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Thu, 12 Jun 2025 21:40:35 +0800 Subject: [PATCH 03/81] self-reference for pyobject_file --- include/fast_io_driver/python/pyobject.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/fast_io_driver/python/pyobject.h b/include/fast_io_driver/python/pyobject.h index cac3306d1..292068786 100644 --- a/include/fast_io_driver/python/pyobject.h +++ b/include/fast_io_driver/python/pyobject.h @@ -141,6 +141,10 @@ class pyobject_file : public pyobject_io_observer } pyobject_file &operator=(pyobject_file &&pob) noexcept { + if (__builtin_addressof(pob) == this) + { + return *this; + } ::fast_io::details::py_inc_dec_ref_impl(this->p); this->p = pob.p; pob.p = nullptr; From f1a78682819752d07b25e82960d13845da77f59b Mon Sep 17 00:00:00 2001 From: trcrsired Date: Fri, 13 Jun 2025 13:41:30 +0800 Subject: [PATCH 04/81] No exemption of ANY devices for this library for anti-tivo It is scary to think self-driving cars could be planted with backdoors to kill anyone. That is INSANE --- license-zhCN.txt | 8 ++------ license.txt | 6 +----- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/license-zhCN.txt b/license-zhCN.txt index 85944a587..71e1c86e9 100644 --- a/license-zhCN.txt +++ b/license-zhCN.txt @@ -19,11 +19,7 @@ 如果某平台 故意破坏开放互联网的使用(例如通过封闭框架限制 渐进式网络应用 (PWA) 的运行),则该平台上的软件 必须 采用 GPLv3 许可证,确保用户拥有完整的修改和安装权利。 4. 例外情况 -以下类别的设备 可免除 第 2 条和第 3 条的限制,可使用本软件而无需满足修改要求: - -医疗设备:用于生命支持、医疗诊断或其他关键医疗用途的设备。 - -汽车系统:用于自动驾驶、车辆控制或安全关键功能的软件。 +没有任何类别的设备可免于此条款限制。 5. 执行与非强制性行动 版权持有人 保留执行本许可证的权利,但 无义务 进行强制执行。 @@ -33,4 +29,4 @@ 本许可证 不受任何政府管辖,包括但不限于 美国政府。 6. 免责声明 -本软件按 “现状” 提供,不提供任何明示或暗示的保证。开发者 不承担 因使用本软件而导致的任何损害或责任。 \ No newline at end of file +本软件按 “现状” 提供,不提供任何明示或暗示的保证。开发者 不承担 因使用本软件而导致的任何损害或责任。 diff --git a/license.txt b/license.txt index 262f4726c..912ea5c0e 100644 --- a/license.txt +++ b/license.txt @@ -19,11 +19,7 @@ When PWA (Progressive Web Applications) or Wine and other cross-platform technol If a platform deliberately undermines open internet access (e.g., restricting the use of Progressive Web Applications (PWA) through a closed framework), then all software on that platform must be licensed under GPLv3, ensuring users have full modification and installation rights. 4. Exceptions -The following categories of devices are exempt from Sections 2 and 3 and may use this software without modification requirements: - -Medical Equipment: Devices used for life support, diagnostics, or critical healthcare applications. - -Automotive Systems: Software used in autonomous driving, vehicle control, or safety-critical functions. +No devices are exempted from this license. 5. Enforcement & Non-Mandatory Action The copyright holder reserves the right to enforce this license but is not obligated to do so. From 0d67eb2889f088e549f6831d75bf3e92deeee1dc Mon Sep 17 00:00:00 2001 From: trcrsired Date: Fri, 13 Jun 2025 17:37:13 +0800 Subject: [PATCH 05/81] [Qt] qiodevice uses new mechanism --- include/fast_io_driver/qt_impl/qiodevice.h | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/include/fast_io_driver/qt_impl/qiodevice.h b/include/fast_io_driver/qt_impl/qiodevice.h index aa72aae58..32966deab 100644 --- a/include/fast_io_driver/qt_impl/qiodevice.h +++ b/include/fast_io_driver/qt_impl/qiodevice.h @@ -92,22 +92,18 @@ inline ::std::uintmax_t qio_device_seek_impl(QIODevice *__restrict qdevice, ::st } // namespace details -template <::std::integral ch_type, typename T, ::std::contiguous_iterator Iter> -inline Iter write(basic_general_qdevice_io_observer qiob, Iter begin, Iter end) +template <::std::integral ch_type, typename T> +inline ::std::byte const *write_some_bytes_define(basic_general_qdevice_io_observer qiob, ::std::byte const *begin, ::std::byte const *end) { - return begin + details::qio_device_write_impl( - qiob.qdevice, ::std::to_address(begin), - static_cast<::std::size_t>(::std::to_address(end) - ::std::to_address(begin)) * sizeof(*begin)) / - sizeof(*begin); + return begin + ::fast_io::details::qio_device_write_impl( + qiob.qdevice, begin, static_cast<::std::size_t>(end - begin)); } -template <::std::integral ch_type, typename T, ::std::contiguous_iterator Iter> -inline Iter read(basic_general_qdevice_io_observer qiob, Iter begin, Iter end) +template <::std::integral ch_type, typename T> +inline ::std::byte *read_some_bytes_define(basic_general_qdevice_io_observer qiob, , ::std::byte *begin, ::std::byte *end) { - return begin + details::qio_device_read_impl( - qiob.qdevice, ::std::to_address(begin), - static_cast<::std::size_t>(::std::to_address(end) - ::std::to_address(begin)) * sizeof(*begin)) / - sizeof(*begin); + return begin + ::fast_io::details::qio_device_read_impl( + qiob.qdevice, begin, static_cast<::std::size_t>(end - begin)); } template <::std::integral ch_type, typename T> From 745a89c6289cda273433603b3880be1fd4471e71 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Fri, 13 Jun 2025 17:40:11 +0800 Subject: [PATCH 06/81] qiodevice --- include/fast_io_driver/qt_impl/qiodevice.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/fast_io_driver/qt_impl/qiodevice.h b/include/fast_io_driver/qt_impl/qiodevice.h index 32966deab..35e816f8c 100644 --- a/include/fast_io_driver/qt_impl/qiodevice.h +++ b/include/fast_io_driver/qt_impl/qiodevice.h @@ -135,7 +135,7 @@ using basic_qt_io_observer = basic_general_qdevice_io_observer template <::std::integral ch_type, typename T> inline constexpr basic_qiodevice_io_observer -io_value_handle(basic_general_qdevice_io_observer gqiob) noexcept +io_stream_ref_define(basic_general_qdevice_io_observer gqiob) noexcept { return {gqiob.qdevice}; } From 14f1975a05717ccaecf92c20d0258e142844eed6 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Mon, 16 Jun 2025 16:23:50 +0800 Subject: [PATCH 07/81] initial_attempt for strbset --- .../fast_io_dsal/impl/associative_string.h | 20 +++++ include/fast_io_dsal/impl/strbset.h | 90 +++++++++++++++++++ 2 files changed, 110 insertions(+) create mode 100644 include/fast_io_dsal/impl/associative_string.h create mode 100644 include/fast_io_dsal/impl/strbset.h diff --git a/include/fast_io_dsal/impl/associative_string.h b/include/fast_io_dsal/impl/associative_string.h new file mode 100644 index 000000000..61cf48375 --- /dev/null +++ b/include/fast_io_dsal/impl/associative_string.h @@ -0,0 +1,20 @@ +#pragma once + +namespace fast_io::details +{ +/* +The string is null terminated +*/ +template<::integral chtype> +struct associative_string +{ + using char_type = chtype; + using size_type = ::std::size_t; + char_type* ptr; + size_type n; + constexpr ::fast_io::basic_string_view strvw() const noexcept + { + return ::fast_io::basic_string_view(ptr,n); + } +}; +} diff --git a/include/fast_io_dsal/impl/strbset.h b/include/fast_io_dsal/impl/strbset.h new file mode 100644 index 000000000..9556a607d --- /dev/null +++ b/include/fast_io_dsal/impl/strbset.h @@ -0,0 +1,90 @@ +#pragma once + +namespace fast_io::containers +{ + +namespace details +{ + +template<::integral chtype, ::std::size_t keys_number> +struct btree_strset_node +{ + using char_type = chtype; + ::std::size_t size; + ::fast_io::details::associative_string keys[keys]; + btree_strset_node *childrens[keys_number+1u]; + btree_strset_node *parent; +}; + +struct find_btree_node_insert_position_result +{ + ::std::size_t pos{}; + bool found{}; +}; + +template +inline constexpr find_btree_insert_position_result find_btree_node_insert_position(nodetype* node, + typename nodetype::char_type const* keystrptr,::std::size_t keystrn) +{ + using char_type = typename nodetype::char_type; + auto *b{node->keys}, *i{b},*e{b+node->size}; + bool found{}; + ::fast_io::basic_string_view newkey(keystrptr,keystrn); + for (;i != e; ++i) + { + auto cmpres{newkey<=>i->strvw()}; + if(cmpres<=0) + { + found=(cmpres==0); + break; + } + } + return {static_cast<::std::size_t>(i-b), found}; +} + +template +inline constexpr bool insert_key(nodetype* node, + typename nodetype::char_type const* keystrptr,::std::size_t keystrn) +{ + +} + +} + +template<::std::integral chtype, typename T, bool ranked, typename Allocator, ::std::size_t keys_number = 63> +class basic_btree_strset +{ +public: + using char_type = chtype; + using string_view_type = ::fast_io::basic_string_view; + using cstring_view_type = ::fast_io::basic_cstring_view; + using value_type = T; + using allocator_type = Allocator; + + explicit constexpr basic_btree_strset(::std::initializer_list ilist) noexcept + { + + } + + constexpr bool contains(string_view_type) const noexcept + { + } + constexpr bool is_empty() const noexcept + { + } + constexpr bool erase_key(string_view_type) noexcept + { + } + constexpr bool insert_key(string_view_type) noexcept + { + } + constexpr void clear() noexcept + { + } + constexpr void clear_destroy() noexcept + { + this->clear(); + } +}; + +} \ No newline at end of file From c91541a682ad07e25d9c3777afc43475c1ee0b94 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Mon, 16 Jun 2025 20:36:06 +0800 Subject: [PATCH 08/81] initial attempt for str_btreeset.h --- include/fast_io_dsal/impl/str_btreeset.h | 236 +++++++++++++++++++++++ include/fast_io_dsal/impl/strbset.h | 90 --------- 2 files changed, 236 insertions(+), 90 deletions(-) create mode 100644 include/fast_io_dsal/impl/str_btreeset.h delete mode 100644 include/fast_io_dsal/impl/strbset.h diff --git a/include/fast_io_dsal/impl/str_btreeset.h b/include/fast_io_dsal/impl/str_btreeset.h new file mode 100644 index 000000000..4009ef733 --- /dev/null +++ b/include/fast_io_dsal/impl/str_btreeset.h @@ -0,0 +1,236 @@ +#pragma once + +namespace fast_io::containers +{ + +namespace details +{ + +template <::std::integral chtype, ::std::size_t keys_number> +struct str_btreeset_node +{ + using char_type = chtype; + ::std::size_t size; // Number of keys currently stored + bool leaf; // Indicates whether the node is a leaf + ::fast_io::details::associative_string keys[keys_number]; // Array of keys + str_btreeset_node *childrens[keys_number + 1u]; // Array of child pointers + str_btreeset_node *parent; // Pointer to parent node +}; + + +struct find_btree_node_insert_position_result +{ + ::std::size_t pos{}; + bool found{}; +}; + +template +inline constexpr find_btree_insert_position_result find_str_btree_node_insert_position(nodetype *node, + typename nodetype::char_type const *keystrptr, ::std::size_t keystrn) noexcept +{ + using char_type = typename nodetype::char_type; + auto *b{node->keys}, *i{b}, *e{b + node->size}; + bool found{}; + ::fast_io::basic_string_view newkey(keystrptr, keystrn); + for (; i != e; ++i) + { + auto cmpres{newkey <=> i->strvw()}; + if (cmpres <= 0) + { + found = (cmpres == 0); + break; + } + } + return {static_cast<::std::size_t>(i - b), found}; +} + +template +inline constexpr void str_btree_split_node(nodetype* node) noexcept; + +template +inline constexpr bool str_btree_insert_key(nodetype *node, + typename nodetype::char_type const *keystrptr, ::std::size_t keystrn, bool ismoved) noexcept +{ + using char_type = typename nodetype::char_type; + // **Find the correct position for insertion** + auto [pos, found] = find_str_btree_node_insert_position<::fast_io::containers::details::find_str_btree_node_insert_position>(node, keystrptr, keystrn); + + // **If the key already exists, return false (no duplicate keys)** + if (found) + return false; + + // **If the node is a leaf** + if (node->leaf) + { + // **If there is space, insert the key directly** + if (node->size < keys_number) + { + for (::std::size_t j = node->size; pos < j ; --j) + { + node->keys[j] = node->keys[j - 1]; + } + ::fast_io::details::associative_string astr; + if (ismoved) + { + astr.ptr = keystrptr; + astr.n = keystrn; + } + else + { + astr = ::fast_io::details::create_associative_string{keystrptr, keystrn}; + } + node->keys[pos] = astr; + ++node->size; + return true; + } + else + { + // **If the node is full, split it** + str_btree_split_node(node); + return str_btree_insert_key(node->parent, keystrptr, keystrn, ismoved); + } + } + else + { + // **Recursively insert into the correct child** + return str_btree_insert_key(node->childrens[pos], keystrptr, keystrn, ismoved); + } +} + +template +inline constexpr void str_btree_split_node(nodetype* node) noexcept +{ + using char_type = typename nodetype::char_type; + using typed_allocator_type = ::fast_io::typed_generic_allocator_adapter; + constexpr + ::std::size_t keys_number_div2{keys_number>>1u}; + constexpr + ::std::size_t keys_number_p1{keys_number+1u}; + constexpr + ::std::size_t mid{keys_number_div2}; + constexpr + ::std::size_t midp1{mid + 1u}; + constexpr + ::std::size_t keys_number_sub_midp1{keys_number - midp1}; + + // **Allocate a new node using the stateless allocator** + nodetype* new_node{typed_allocator_type::allocate(1)}; + + new_node->parent = node->parent; + new_node->leaf = node->leaf; + + // **Move the right half of the keys to the new node** + for (::std::size_t j{midp1}, k{}; j != keys_number; ++j, ++k) + new_node->keys[k] = node->keys[j]; + + new_node->size = keys_number_sub_midp1; + + // **Handle child pointers (if not a leaf)** + if (!node->leaf) + { + for (::std::size_t j{midp1}, k{}; j != keys_number_p1; ++j, ++k) + { + auto &ck{new_node->childrens[k]}; + ck = node->childrens[j]; + auto ckv{ck}; + if (ckv) + { + ckv->parent = new_node; + } + } + } + + node->size = mid; // **Keep only the left half in the current node** + + // **Promote the middle key to the parent node** + if (node->parent == nullptr) + { + // **Allocate a new root using the stateless allocator** + nodetype* new_root{typed_allocator_type::allocate(1)}; + new_root->keys[0] = node->keys[mid]; + new_root->size = 1; + new_root->childrens[0] = node; + new_root->childrens[1] = new_node; + new_root->leaf = false; + node->parent = new_root; + new_node->parent = new_root; + } + else + { + // **Insert the middle key into the parent node** + str_btree_insert_key(node->parent, node->keys[mid].ptr, node->keys[mid].n, true); + node->parent->childrens[node->parent->size] = new_node; + new_node->parent = node->parent; + } +} + +template +inline constexpr bool str_btree_insert_key_with_root(nodetype *&node, + typename nodetype::char_type const *keystrptr, ::std::size_t keystrn) noexcept +{ + using typed_allocator_type = ::fast_io::typed_generic_allocator_adapter; + + // **If the tree is empty, allocate a new root** + if (node == nullptr) + { + node = typed_allocator_type::allocate(1); + node->size = 1; + node->leaf = true; + node->parent = nullptr; + *(node->keys) = ::fast_io::details::create_associative_string(keystrptr, keystrn); + return true; + } + return ::fast_io::containers::details::str_btree_insert_key(node,keystrptr,keystrn, false); +} + +} // namespace details + +template <::std::integral chtype, typename T, typename Allocator, ::std::size_t keys_number = 63> +class basic_str_btreeset +{ + using node_type = ::fast_io::containers::details::str_btreeset_node; + +public: + using char_type = chtype; + using string_view_type = ::fast_io::basic_string_view; + using cstring_view_type = ::fast_io::basic_cstring_view; + using value_type = T; + using allocator_type = Allocator; + node_type *root{}; + + constexpr basic_str_btreeset() noexcept = default; + + explicit constexpr basic_str_btreeset(::std::initializer_list ilist) noexcept + { + for (auto const &e : ilist) + { + this->insert_key(e); + } + } + + constexpr bool contains(string_view_type) const noexcept + { + return false; + } + constexpr bool is_empty() const noexcept + { + return false; + } + constexpr bool erase_key(string_view_type) noexcept + { + return false; + } + constexpr bool insert_key(string_view_type strvw) noexcept + { + return ::fast_io::containers::details::str_btree_insert_key_with_root(this->root, strvw.data(), strvw.size()); + } + constexpr void clear() noexcept + { + } + constexpr void clear_destroy() noexcept + { + this->clear(); + } +}; + +} // namespace fast_io::containers \ No newline at end of file diff --git a/include/fast_io_dsal/impl/strbset.h b/include/fast_io_dsal/impl/strbset.h deleted file mode 100644 index 9556a607d..000000000 --- a/include/fast_io_dsal/impl/strbset.h +++ /dev/null @@ -1,90 +0,0 @@ -#pragma once - -namespace fast_io::containers -{ - -namespace details -{ - -template<::integral chtype, ::std::size_t keys_number> -struct btree_strset_node -{ - using char_type = chtype; - ::std::size_t size; - ::fast_io::details::associative_string keys[keys]; - btree_strset_node *childrens[keys_number+1u]; - btree_strset_node *parent; -}; - -struct find_btree_node_insert_position_result -{ - ::std::size_t pos{}; - bool found{}; -}; - -template -inline constexpr find_btree_insert_position_result find_btree_node_insert_position(nodetype* node, - typename nodetype::char_type const* keystrptr,::std::size_t keystrn) -{ - using char_type = typename nodetype::char_type; - auto *b{node->keys}, *i{b},*e{b+node->size}; - bool found{}; - ::fast_io::basic_string_view newkey(keystrptr,keystrn); - for (;i != e; ++i) - { - auto cmpres{newkey<=>i->strvw()}; - if(cmpres<=0) - { - found=(cmpres==0); - break; - } - } - return {static_cast<::std::size_t>(i-b), found}; -} - -template -inline constexpr bool insert_key(nodetype* node, - typename nodetype::char_type const* keystrptr,::std::size_t keystrn) -{ - -} - -} - -template<::std::integral chtype, typename T, bool ranked, typename Allocator, ::std::size_t keys_number = 63> -class basic_btree_strset -{ -public: - using char_type = chtype; - using string_view_type = ::fast_io::basic_string_view; - using cstring_view_type = ::fast_io::basic_cstring_view; - using value_type = T; - using allocator_type = Allocator; - - explicit constexpr basic_btree_strset(::std::initializer_list ilist) noexcept - { - - } - - constexpr bool contains(string_view_type) const noexcept - { - } - constexpr bool is_empty() const noexcept - { - } - constexpr bool erase_key(string_view_type) noexcept - { - } - constexpr bool insert_key(string_view_type) noexcept - { - } - constexpr void clear() noexcept - { - } - constexpr void clear_destroy() noexcept - { - this->clear(); - } -}; - -} \ No newline at end of file From e31d5c5060b3254b3fe9503f19b86457a0b5de04 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Tue, 17 Jun 2025 00:02:25 +0800 Subject: [PATCH 09/81] btree --- .../fast_io_dsal/impl/associative_string.h | 33 +- include/fast_io_dsal/impl/str_btree_set.h | 385 ++++++++++++++++++ include/fast_io_dsal/impl/str_btreeset.h | 236 ----------- 3 files changed, 409 insertions(+), 245 deletions(-) create mode 100644 include/fast_io_dsal/impl/str_btree_set.h delete mode 100644 include/fast_io_dsal/impl/str_btreeset.h diff --git a/include/fast_io_dsal/impl/associative_string.h b/include/fast_io_dsal/impl/associative_string.h index 61cf48375..6e1e751c5 100644 --- a/include/fast_io_dsal/impl/associative_string.h +++ b/include/fast_io_dsal/impl/associative_string.h @@ -5,16 +5,31 @@ namespace fast_io::details /* The string is null terminated */ -template<::integral chtype> +template <::std::integral chtype> struct associative_string { - using char_type = chtype; - using size_type = ::std::size_t; - char_type* ptr; - size_type n; - constexpr ::fast_io::basic_string_view strvw() const noexcept - { - return ::fast_io::basic_string_view(ptr,n); - } + using char_type = chtype; + using size_type = ::std::size_t; + char_type const *ptr; + size_type n; + constexpr ::fast_io::basic_string_view strvw() const noexcept + { + return ::fast_io::basic_string_view(ptr, n); + } }; + +template +inline constexpr ::fast_io::details::associative_string create_associative_string(char_type const *p, ::std::size_t n) noexcept +{ + using typed_allocator_type = ::fast_io::typed_generic_allocator_adapter; + if (n == SIZE_MAX) [[unlikely]] + { + ::fast_io::fast_terminate(); + } + ::std::size_t const np1{static_cast<::std::size_t>(n + 1u)}; + char_type *newp{typed_allocator_type::allocate(np1)}; + *::fast_io::details::non_overlapped_copy_n(p, n, newp) = 0; + return {newp, n}; } + +} // namespace fast_io::details \ No newline at end of file diff --git a/include/fast_io_dsal/impl/str_btree_set.h b/include/fast_io_dsal/impl/str_btree_set.h new file mode 100644 index 000000000..e2c8107c9 --- /dev/null +++ b/include/fast_io_dsal/impl/str_btree_set.h @@ -0,0 +1,385 @@ +#pragma once + +namespace fast_io::containers +{ + +namespace details +{ + +template <::std::integral chtype, ::std::size_t keys_number> +struct str_btree_set_node +{ + using char_type = chtype; + ::std::size_t size; // Number of keys currently stored + bool leaf; // Indicates whether the node is a leaf + ::fast_io::details::associative_string keys[keys_number]; // Array of keys + str_btree_set_node *childrens[keys_number + 1u]; // Array of child pointers + str_btree_set_node *parent; // Pointer to parent node +}; + + +struct find_btree_node_insert_position_result +{ + ::std::size_t pos{}; + bool found{}; +}; + +template +inline constexpr find_btree_node_insert_position_result find_str_btree_node_insert_position(nodetype *node, + typename nodetype::char_type const *keystrptr, ::std::size_t keystrn) noexcept +{ + using char_type = typename nodetype::char_type; + auto *b{node->keys}, *i{b}, *e{b + node->size}; + bool found{}; + ::fast_io::basic_string_view newkey(keystrptr, keystrn); + for (; i != e; ++i) + { + auto cmpres{newkey <=> i->strvw()}; + if (cmpres <= 0) + { + found = (cmpres == 0); + break; + } + } + return {static_cast<::std::size_t>(i - b), found}; +} + +template +inline constexpr void str_btree_split_node(nodetype *node) noexcept; + +template +inline constexpr bool str_btree_insert_key(nodetype *node, + typename nodetype::char_type const *keystrptr, ::std::size_t keystrn, bool ismoved) noexcept +{ + using char_type = typename nodetype::char_type; + // **Find the correct position for insertion** + auto [pos, found] = find_str_btree_node_insert_position(node, keystrptr, keystrn); + + // **If the key already exists, return false (no duplicate keys)** + if (found) + { + return false; + } + + // **If the node is a leaf** + if (node->leaf) + { + // **If there is space, insert the key directly** + if (node->size < keys_number) + { + for (::std::size_t j = node->size; pos < j; --j) + { + node->keys[j] = node->keys[j - 1]; + } + ::fast_io::details::associative_string astr; + if (ismoved) + { + astr.ptr = keystrptr; + astr.n = keystrn; + } + else + { + astr = ::fast_io::details::create_associative_string(keystrptr, keystrn); + } + node->keys[pos] = astr; + ++node->size; + return true; + } + else + { + // **If the node is full, split it** + str_btree_split_node(node); + return str_btree_insert_key(node->parent, keystrptr, keystrn, ismoved); + } + } + else + { + // **Recursively insert into the correct child** + return str_btree_insert_key(node->childrens[pos], keystrptr, keystrn, ismoved); + } +} + +template +inline constexpr void str_btree_split_node(nodetype *node) noexcept +{ + using char_type = typename nodetype::char_type; + using typed_allocator_type = ::fast_io::typed_generic_allocator_adapter; + constexpr ::std::size_t keys_number_div2{keys_number >> 1u}; + constexpr ::std::size_t keys_number_p1{keys_number + 1u}; + constexpr ::std::size_t mid{keys_number_div2}; + constexpr ::std::size_t midp1{mid + 1u}; + constexpr ::std::size_t keys_number_sub_midp1{keys_number - midp1}; + + // **Allocate a new node using the stateless allocator** + nodetype *new_node{typed_allocator_type::allocate(1)}; + + new_node->parent = node->parent; + new_node->leaf = node->leaf; + + // **Move the right half of the keys to the new node** + for (::std::size_t j{midp1}, k{}; j != keys_number; ++j, ++k) + { + new_node->keys[k] = node->keys[j]; + } + + new_node->size = keys_number_sub_midp1; + + // **Handle child pointers (if not a leaf)** + if (!node->leaf) + { + for (::std::size_t j{midp1}, k{}; j != keys_number_p1; ++j, ++k) + { + auto &ck{new_node->childrens[k]}; + ck = node->childrens[j]; + auto ckv{ck}; + if (ckv) + { + ckv->parent = new_node; + } + } + } + + node->size = mid; // **Keep only the left half in the current node** + + // **Promote the middle key to the parent node** + if (node->parent == nullptr) + { + // **Allocate a new root using the stateless allocator** + nodetype *new_root{typed_allocator_type::allocate(1)}; + new_root->keys[0] = node->keys[mid]; + new_root->size = 1; + new_root->childrens[0] = node; + new_root->childrens[1] = new_node; + new_root->leaf = false; + node->parent = new_root; + new_node->parent = new_root; + } + else + { + // **Insert the middle key into the parent node** + str_btree_insert_key(node->parent, node->keys[mid].ptr, node->keys[mid].n, true); + node->parent->childrens[node->parent->size] = new_node; + new_node->parent = node->parent; + } +} + +template +inline constexpr bool str_btree_insert_key_with_root(nodetype *&node, + typename nodetype::char_type const *keystrptr, ::std::size_t keystrn) noexcept +{ + using typed_allocator_type = ::fast_io::typed_generic_allocator_adapter; + + // **If the tree is empty, allocate a new root** + if (node == nullptr) + { + node = typed_allocator_type::allocate(1); + node->size = 1; + node->leaf = true; + node->parent = nullptr; + *(node->keys) = ::fast_io::details::create_associative_string(keystrptr, keystrn); + return true; + } + return ::fast_io::containers::details::str_btree_insert_key(node, keystrptr, keystrn, false); +} +#if 0 +template <::std::integral chtype, ::std::size_t keys_number> +struct str_btree_set_iterator +{ + ::fast_io::containers::str_btree_set_node* node{}; + ::std::size_t pos{}; + constexpr str_btree_set_iterator& operator++() noexcept + { + if (node == nullptr) + return *this; + + // **If there are more keys in the current node, move right** + if (pos + 1 < node->size) + { + ++pos; + return *this; + } + + // **If there is a right child, move to the smallest key in the right subtree** + if (!node->leaf) + { + node = node->childrens[pos + 1]; + while (!node->leaf) + node = node->childrens[0]; + pos = 0; + return *this; + } + + // **Otherwise, move up until we find a larger key** + while (node->parent && node == node->parent->childrens[node->parent->size]) + node = node->parent; + + if (node->parent) + { + pos = 0; + node = node->parent; + } + else + { + node = nullptr; // **End of iteration** + } + } +#if 0 + constexpr str_btree_set_iterator& operator--() noexcept + { + + } +#endif + constexpr ::fast_io::containers::basic_cstring_view operator*() const noexcept + { + auto &def{this->node->keys[this->pos]}; + return def.strvw(); + } +}; + +template <::std::integral chtype, ::std::size_t keys_number> +inline constexpr bool operator==(::fast_io::containers::details::str_btree_set_iterator a, + ::fast_io::containers::details::str_btree_set_iterator b) +{ + return a.node == b.node && a.pos == b.pos; +} + +template <::std::integral chtype, ::std::size_t keys_number> +inline constexpr bool operator!=(::fast_io::containers::details::str_btree_set_iterator a, + ::fast_io::containers::details::str_btree_set_iterator b) +{ + return !(a==b); +} +#endif + +template <::std::integral chtype, ::std::size_t keys_number = 63> +struct btree_set_root +{ + using node_type = ::fast_io::containers::details::str_btree_set_node; + node_type *root{}; + node_type *last{}; + node_type *prev{}; +}; +} // namespace details + +template <::std::integral chtype, typename Allocator, ::std::size_t keys_number = 63> +class basic_str_btree_set +{ + using node_type = ::fast_io::containers::details::str_btree_set_node; + using untyped_allocator_type = Allocator; + using typed_allocator_type = ::fast_io::typed_generic_allocator_adapter; + +public: + using char_type = chtype; + using string_view_type = ::fast_io::basic_string_view; + using cstring_view_type = ::fast_io::basic_cstring_view; + using allocator_type = Allocator; +#if 0 + using const_iterator = ::fast_io::details::str_btree_set_iterator; + using iterator = ::fast_io::details::str_btree_set_iterator; + ::fast_io::containers::details::btree_set_root root; +#endif + node_type *root{}; + + constexpr basic_str_btree_set() noexcept = default; + + explicit constexpr basic_str_btree_set(::std::initializer_list ilist) noexcept + { + for (auto const &e : ilist) + { + this->insert_key(e); + } + } + + constexpr bool contains(string_view_type) const noexcept + { + return false; + } + constexpr bool is_empty() const noexcept + { + return false; + } + constexpr bool erase_key(string_view_type) noexcept + { + return false; + } + constexpr bool insert_key(string_view_type strvw) noexcept + { + return ::fast_io::containers::details::str_btree_insert_key_with_root(this->root, strvw.data(), strvw.size()); + } + +private: + static inline constexpr void clear_node(node_type *node) noexcept + { + if (node == nullptr) + { + return; + } + ::std::size_t const n{node->size}; + for (::std::size_t i{}; i != n; ++i) + { + if (!node->leaf) + { + clear_node(node->childrens[i]); + } + + ::fast_io::io::debug_println(::fast_io::mnp::pointervw(node), + i, " ", ::fast_io::mnp::pointervw(node->keys + i), " ", node->keys[i].strvw()); + + auto ki{node->keys[i]}; + ::fast_io::typed_generic_allocator_adapter::deallocate_n(const_cast(ki.ptr), + static_cast<::std::size_t>(ki.n + 1u)); + } +#if 0 + if (!node->leaf) + { + clear_node(node->childrens[n]); + + auto ki{node->childrens[node->size]}; + ::fast_io::typed_generic_allocator_adapter::deallocate_n(, + static_cast<::std::size_t>(ki.n+1u)); + } +#endif + + // **Deallocate the node using the allocator** + typed_allocator_type::deallocate_n(node, 1); + } + +public: + constexpr void clear() noexcept + { + clear_node(this->root); + this->root = nullptr; + } + constexpr void clear_destroy() noexcept + { + this->clear(); + } + + constexpr basic_str_btree_set(basic_str_btree_set const &) noexcept = delete; + constexpr basic_str_btree_set &operator=(basic_str_btree_set const &) noexcept = delete; + + constexpr basic_str_btree_set(basic_str_btree_set &&other) noexcept : root{other.root} + { + other.root = nullptr; + } + constexpr basic_str_btree_set &operator=(basic_str_btree_set &&other) noexcept + { + if (::std::addressof(other) == this) + { + return *this; + } + this->root = other.root; + other.root = nullptr; + return *this; + } + constexpr ~basic_str_btree_set() + { + clear_node(this->root); + } +#if 0 + constexpr iters() const noexcept + {} +#endif +}; + +} // namespace fast_io::containers \ No newline at end of file diff --git a/include/fast_io_dsal/impl/str_btreeset.h b/include/fast_io_dsal/impl/str_btreeset.h deleted file mode 100644 index 4009ef733..000000000 --- a/include/fast_io_dsal/impl/str_btreeset.h +++ /dev/null @@ -1,236 +0,0 @@ -#pragma once - -namespace fast_io::containers -{ - -namespace details -{ - -template <::std::integral chtype, ::std::size_t keys_number> -struct str_btreeset_node -{ - using char_type = chtype; - ::std::size_t size; // Number of keys currently stored - bool leaf; // Indicates whether the node is a leaf - ::fast_io::details::associative_string keys[keys_number]; // Array of keys - str_btreeset_node *childrens[keys_number + 1u]; // Array of child pointers - str_btreeset_node *parent; // Pointer to parent node -}; - - -struct find_btree_node_insert_position_result -{ - ::std::size_t pos{}; - bool found{}; -}; - -template -inline constexpr find_btree_insert_position_result find_str_btree_node_insert_position(nodetype *node, - typename nodetype::char_type const *keystrptr, ::std::size_t keystrn) noexcept -{ - using char_type = typename nodetype::char_type; - auto *b{node->keys}, *i{b}, *e{b + node->size}; - bool found{}; - ::fast_io::basic_string_view newkey(keystrptr, keystrn); - for (; i != e; ++i) - { - auto cmpres{newkey <=> i->strvw()}; - if (cmpres <= 0) - { - found = (cmpres == 0); - break; - } - } - return {static_cast<::std::size_t>(i - b), found}; -} - -template -inline constexpr void str_btree_split_node(nodetype* node) noexcept; - -template -inline constexpr bool str_btree_insert_key(nodetype *node, - typename nodetype::char_type const *keystrptr, ::std::size_t keystrn, bool ismoved) noexcept -{ - using char_type = typename nodetype::char_type; - // **Find the correct position for insertion** - auto [pos, found] = find_str_btree_node_insert_position<::fast_io::containers::details::find_str_btree_node_insert_position>(node, keystrptr, keystrn); - - // **If the key already exists, return false (no duplicate keys)** - if (found) - return false; - - // **If the node is a leaf** - if (node->leaf) - { - // **If there is space, insert the key directly** - if (node->size < keys_number) - { - for (::std::size_t j = node->size; pos < j ; --j) - { - node->keys[j] = node->keys[j - 1]; - } - ::fast_io::details::associative_string astr; - if (ismoved) - { - astr.ptr = keystrptr; - astr.n = keystrn; - } - else - { - astr = ::fast_io::details::create_associative_string{keystrptr, keystrn}; - } - node->keys[pos] = astr; - ++node->size; - return true; - } - else - { - // **If the node is full, split it** - str_btree_split_node(node); - return str_btree_insert_key(node->parent, keystrptr, keystrn, ismoved); - } - } - else - { - // **Recursively insert into the correct child** - return str_btree_insert_key(node->childrens[pos], keystrptr, keystrn, ismoved); - } -} - -template -inline constexpr void str_btree_split_node(nodetype* node) noexcept -{ - using char_type = typename nodetype::char_type; - using typed_allocator_type = ::fast_io::typed_generic_allocator_adapter; - constexpr - ::std::size_t keys_number_div2{keys_number>>1u}; - constexpr - ::std::size_t keys_number_p1{keys_number+1u}; - constexpr - ::std::size_t mid{keys_number_div2}; - constexpr - ::std::size_t midp1{mid + 1u}; - constexpr - ::std::size_t keys_number_sub_midp1{keys_number - midp1}; - - // **Allocate a new node using the stateless allocator** - nodetype* new_node{typed_allocator_type::allocate(1)}; - - new_node->parent = node->parent; - new_node->leaf = node->leaf; - - // **Move the right half of the keys to the new node** - for (::std::size_t j{midp1}, k{}; j != keys_number; ++j, ++k) - new_node->keys[k] = node->keys[j]; - - new_node->size = keys_number_sub_midp1; - - // **Handle child pointers (if not a leaf)** - if (!node->leaf) - { - for (::std::size_t j{midp1}, k{}; j != keys_number_p1; ++j, ++k) - { - auto &ck{new_node->childrens[k]}; - ck = node->childrens[j]; - auto ckv{ck}; - if (ckv) - { - ckv->parent = new_node; - } - } - } - - node->size = mid; // **Keep only the left half in the current node** - - // **Promote the middle key to the parent node** - if (node->parent == nullptr) - { - // **Allocate a new root using the stateless allocator** - nodetype* new_root{typed_allocator_type::allocate(1)}; - new_root->keys[0] = node->keys[mid]; - new_root->size = 1; - new_root->childrens[0] = node; - new_root->childrens[1] = new_node; - new_root->leaf = false; - node->parent = new_root; - new_node->parent = new_root; - } - else - { - // **Insert the middle key into the parent node** - str_btree_insert_key(node->parent, node->keys[mid].ptr, node->keys[mid].n, true); - node->parent->childrens[node->parent->size] = new_node; - new_node->parent = node->parent; - } -} - -template -inline constexpr bool str_btree_insert_key_with_root(nodetype *&node, - typename nodetype::char_type const *keystrptr, ::std::size_t keystrn) noexcept -{ - using typed_allocator_type = ::fast_io::typed_generic_allocator_adapter; - - // **If the tree is empty, allocate a new root** - if (node == nullptr) - { - node = typed_allocator_type::allocate(1); - node->size = 1; - node->leaf = true; - node->parent = nullptr; - *(node->keys) = ::fast_io::details::create_associative_string(keystrptr, keystrn); - return true; - } - return ::fast_io::containers::details::str_btree_insert_key(node,keystrptr,keystrn, false); -} - -} // namespace details - -template <::std::integral chtype, typename T, typename Allocator, ::std::size_t keys_number = 63> -class basic_str_btreeset -{ - using node_type = ::fast_io::containers::details::str_btreeset_node; - -public: - using char_type = chtype; - using string_view_type = ::fast_io::basic_string_view; - using cstring_view_type = ::fast_io::basic_cstring_view; - using value_type = T; - using allocator_type = Allocator; - node_type *root{}; - - constexpr basic_str_btreeset() noexcept = default; - - explicit constexpr basic_str_btreeset(::std::initializer_list ilist) noexcept - { - for (auto const &e : ilist) - { - this->insert_key(e); - } - } - - constexpr bool contains(string_view_type) const noexcept - { - return false; - } - constexpr bool is_empty() const noexcept - { - return false; - } - constexpr bool erase_key(string_view_type) noexcept - { - return false; - } - constexpr bool insert_key(string_view_type strvw) noexcept - { - return ::fast_io::containers::details::str_btree_insert_key_with_root(this->root, strvw.data(), strvw.size()); - } - constexpr void clear() noexcept - { - } - constexpr void clear_destroy() noexcept - { - this->clear(); - } -}; - -} // namespace fast_io::containers \ No newline at end of file From 6222c2ec785ae5f03c4954e2e7fc1116ea5bbf19 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Tue, 17 Jun 2025 00:02:41 +0800 Subject: [PATCH 10/81] btreeset --- .../str_btree_set/str_btree_set.cc | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 examples/0029.containers/str_btree_set/str_btree_set.cc diff --git a/examples/0029.containers/str_btree_set/str_btree_set.cc b/examples/0029.containers/str_btree_set/str_btree_set.cc new file mode 100644 index 000000000..9ed8935db --- /dev/null +++ b/examples/0029.containers/str_btree_set/str_btree_set.cc @@ -0,0 +1,44 @@ +#include +#include +#include +#include + +template <::std::integral chtype, ::std::size_t keys_number> +inline constexpr void str_btree_set_inorder_traverse( + ::fast_io::containers::details::str_btree_set_node *node, + auto &&callback) noexcept +{ + if (node == nullptr) + { + return; + } + + // **Traverse left subtree** + for (::std::size_t i{}; i != node->size; ++i) + { + if (!node->leaf) + { + str_btree_set_inorder_traverse(node->childrens[i], callback); + } + + // **Visit current key** + callback(node->keys[i].strvw()); + } + + // **Traverse rightmost subtree** + if (!node->leaf) + { + str_btree_set_inorder_traverse(node->childrens[node->size], callback); + } +} + +int main() +{ + ::fast_io::containers::basic_str_btree_set bset; + bset.insert_key("asfasf"); + bset.insert_key("asfasfsf"); + bset.insert_key("aaa"); + str_btree_set_inorder_traverse(bset.root, [](::fast_io::string_view v) { + ::fast_io::io::println(v); + }); +} From bf8fca89690b1f4b535033ca6e0f3746c31a2c63 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Tue, 17 Jun 2025 00:03:51 +0800 Subject: [PATCH 11/81] [btree_set] testing --- examples/0029.containers/str_btree_set/str_btree_set.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/0029.containers/str_btree_set/str_btree_set.cc b/examples/0029.containers/str_btree_set/str_btree_set.cc index 9ed8935db..bd3ea60f7 100644 --- a/examples/0029.containers/str_btree_set/str_btree_set.cc +++ b/examples/0029.containers/str_btree_set/str_btree_set.cc @@ -38,7 +38,7 @@ int main() bset.insert_key("asfasf"); bset.insert_key("asfasfsf"); bset.insert_key("aaa"); - str_btree_set_inorder_traverse(bset.root, [](::fast_io::string_view v) { + str_btree_set_inorder_traverse(bset.root, [](::fast_io::string_view v) { ::fast_io::io::println(v); }); } From 1407b2c85c6717be4b8019d5e84c60ed723cca03 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Tue, 17 Jun 2025 00:05:38 +0800 Subject: [PATCH 12/81] [str_btree_set] move the example to test --- .../0026.container/0013.str_btree_set}/str_btree_set.cc | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {examples/0029.containers/str_btree_set => tests/0026.container/0013.str_btree_set}/str_btree_set.cc (100%) diff --git a/examples/0029.containers/str_btree_set/str_btree_set.cc b/tests/0026.container/0013.str_btree_set/str_btree_set.cc similarity index 100% rename from examples/0029.containers/str_btree_set/str_btree_set.cc rename to tests/0026.container/0013.str_btree_set/str_btree_set.cc From 71e41fe8cbe3f466abbb457047a72284ec122d70 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Tue, 17 Jun 2025 00:11:36 +0800 Subject: [PATCH 13/81] set --- .../0013.str_btree_set/str_btree_set.cc | 30 ++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/tests/0026.container/0013.str_btree_set/str_btree_set.cc b/tests/0026.container/0013.str_btree_set/str_btree_set.cc index bd3ea60f7..e0d4bd29b 100644 --- a/tests/0026.container/0013.str_btree_set/str_btree_set.cc +++ b/tests/0026.container/0013.str_btree_set/str_btree_set.cc @@ -34,10 +34,32 @@ inline constexpr void str_btree_set_inorder_traverse( int main() { - ::fast_io::containers::basic_str_btree_set bset; - bset.insert_key("asfasf"); - bset.insert_key("asfasfsf"); - bset.insert_key("aaa"); + ::fast_io::containers::basic_str_btree_set bset; + bset.insert_key("apple"); + bset.insert_key("banana"); + bset.insert_key("cherry"); + bset.insert_key("date"); + bset.insert_key("elderberry"); + bset.insert_key("fig"); + bset.insert_key("grape"); + bset.insert_key("honeydew"); + bset.insert_key("kiwi"); + bset.insert_key("lemon"); + bset.insert_key("mango"); + bset.insert_key("nectarine"); + bset.insert_key("orange"); + bset.insert_key("papaya"); + bset.insert_key("quince"); + bset.insert_key("raspberry"); + bset.insert_key("strawberry"); + bset.insert_key("tangerine"); + bset.insert_key("ugli"); + bset.insert_key("vanilla"); + bset.insert_key("watermelon"); + bset.insert_key("xigua"); + bset.insert_key("yellowfruit"); + bset.insert_key("zucchini"); + str_btree_set_inorder_traverse(bset.root, [](::fast_io::string_view v) { ::fast_io::io::println(v); }); From dd08783e043ef817afe87c7461a341cc36d89a9d Mon Sep 17 00:00:00 2001 From: trcrsired Date: Wed, 25 Jun 2025 00:47:01 +0800 Subject: [PATCH 14/81] [btree] root needs to change in the case when node->parent == nullptr --- include/fast_io_dsal/impl/str_btree_set.h | 149 +++++++++++++++++++--- 1 file changed, 129 insertions(+), 20 deletions(-) diff --git a/include/fast_io_dsal/impl/str_btree_set.h b/include/fast_io_dsal/impl/str_btree_set.h index e2c8107c9..5ac548032 100644 --- a/include/fast_io_dsal/impl/str_btree_set.h +++ b/include/fast_io_dsal/impl/str_btree_set.h @@ -5,6 +5,11 @@ namespace fast_io::containers namespace details { +struct btree_node_common +{ + void *root; + void *next; +}; template <::std::integral chtype, ::std::size_t keys_number> struct str_btree_set_node @@ -17,6 +22,19 @@ struct str_btree_set_node str_btree_set_node *parent; // Pointer to parent node }; +template <::std::size_t keys_number> +struct +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +str_btree_set_common +{ + ::std::size_t size; + bool leaf; + ::fast_io::io_scatter_t keys[keys_number]; + void *childrens[keys_number + 1u]; + void *parent; +}; struct find_btree_node_insert_position_result { @@ -26,7 +44,7 @@ struct find_btree_node_insert_position_result template inline constexpr find_btree_node_insert_position_result find_str_btree_node_insert_position(nodetype *node, - typename nodetype::char_type const *keystrptr, ::std::size_t keystrn) noexcept + typename nodetype::char_type const *keystrptr, ::std::size_t keystrn) noexcept { using char_type = typename nodetype::char_type; auto *b{node->keys}, *i{b}, *e{b + node->size}; @@ -49,7 +67,7 @@ inline constexpr void str_btree_split_node(nodetype *node) noexcept; template inline constexpr bool str_btree_insert_key(nodetype *node, - typename nodetype::char_type const *keystrptr, ::std::size_t keystrn, bool ismoved) noexcept + typename nodetype::char_type const *keystrptr, ::std::size_t keystrn, bool ismoved, nodetype** proot) noexcept { using char_type = typename nodetype::char_type; // **Find the correct position for insertion** @@ -64,6 +82,7 @@ inline constexpr bool str_btree_insert_key(nodetype *node, // **If the node is a leaf** if (node->leaf) { + // **If there is space, insert the key directly** if (node->size < keys_number) { @@ -88,19 +107,19 @@ inline constexpr bool str_btree_insert_key(nodetype *node, else { // **If the node is full, split it** - str_btree_split_node(node); - return str_btree_insert_key(node->parent, keystrptr, keystrn, ismoved); + str_btree_split_node(node, proot); + return str_btree_insert_key(node->parent, keystrptr, keystrn, ismoved, proot); } } else { // **Recursively insert into the correct child** - return str_btree_insert_key(node->childrens[pos], keystrptr, keystrn, ismoved); + return str_btree_insert_key(node->childrens[pos], keystrptr, keystrn, ismoved, proot); } } template -inline constexpr void str_btree_split_node(nodetype *node) noexcept +inline constexpr void str_btree_split_node(nodetype *node, nodetype** proot) noexcept { using char_type = typename nodetype::char_type; using typed_allocator_type = ::fast_io::typed_generic_allocator_adapter; @@ -146,9 +165,10 @@ inline constexpr void str_btree_split_node(nodetype *node) noexcept { // **Allocate a new root using the stateless allocator** nodetype *new_root{typed_allocator_type::allocate(1)}; - new_root->keys[0] = node->keys[mid]; + *proot = new_root; + *(new_root->keys) = node->keys[mid]; new_root->size = 1; - new_root->childrens[0] = node; + *(new_root->childrens) = node; new_root->childrens[1] = new_node; new_root->leaf = false; node->parent = new_root; @@ -157,18 +177,20 @@ inline constexpr void str_btree_split_node(nodetype *node) noexcept else { // **Insert the middle key into the parent node** - str_btree_insert_key(node->parent, node->keys[mid].ptr, node->keys[mid].n, true); + str_btree_insert_key(node->parent, node->keys[mid].ptr, node->keys[mid].n, true, proot); node->parent->childrens[node->parent->size] = new_node; new_node->parent = node->parent; } } template -inline constexpr bool str_btree_insert_key_with_root(nodetype *&node, +inline constexpr bool str_btree_insert_key_with_root(nodetype **proot, typename nodetype::char_type const *keystrptr, ::std::size_t keystrn) noexcept { using typed_allocator_type = ::fast_io::typed_generic_allocator_adapter; + auto node{*proot}; + // **If the tree is empty, allocate a new root** if (node == nullptr) { @@ -177,9 +199,10 @@ inline constexpr bool str_btree_insert_key_with_root(nodetype *&node, node->leaf = true; node->parent = nullptr; *(node->keys) = ::fast_io::details::create_associative_string(keystrptr, keystrn); + *proot = node; return true; } - return ::fast_io::containers::details::str_btree_insert_key(node, keystrptr, keystrn, false); + return ::fast_io::containers::details::str_btree_insert_key(node, keystrptr, keystrn, false, proot); } #if 0 template <::std::integral chtype, ::std::size_t keys_number> @@ -251,14 +274,97 @@ inline constexpr bool operator!=(::fast_io::containers::details::str_btree_set_i } #endif -template <::std::integral chtype, ::std::size_t keys_number = 63> -struct btree_set_root +template <::std::integral chtype, ::std::size_t keys_number, bool isrev> +struct str_btree_set_iterator { - using node_type = ::fast_io::containers::details::str_btree_set_node; - node_type *root{}; - node_type *last{}; - node_type *prev{}; + using char_type = chtype; + using value_type = char_type; + using cstring_view_type = ::fast_io::basic_cstring_view; + using const_iterator = ::fast_io::containers::details::str_btree_set_iterator; + using iterator = const_iterator; + ::fast_io::containers::details::str_btree_set_node *ptr{}; + inline constexpr const_iterator operator++() noexcept + { + return {}; + } + inline constexpr const_iterator operator++(int) noexcept + { + auto tmp{*this}; + ++*this; + return tmp; + } +}; + +template <::std::integral chtype, ::std::size_t keys_number, bool isrev> +inline constexpr bool operator==(::fast_io::containers::details::str_btree_set_iterator a, + ::fast_io::containers::details::str_btree_set_iterator b) noexcept +{ + return a.ptr == b.ptr; +} + +template <::std::integral chtype, ::std::size_t keys_number, bool isrev> +inline constexpr bool operator!=(::fast_io::containers::details::str_btree_set_iterator a, + ::fast_io::containers::details::str_btree_set_iterator b) noexcept +{ + return a.ptr != b.ptr; +} + +template <::std::integral chtype, ::std::size_t keys_number, bool isrev> +inline constexpr bool operator==(::fast_io::containers::details::str_btree_set_iterator a, + ::std::default_sentinel_t) noexcept +{ + return a.ptr == nullptr; +} + +template <::std::integral chtype, ::std::size_t keys_number, bool isrev> +inline constexpr bool operator==(::std::default_sentinel_t, + ::fast_io::containers::details::str_btree_set_iterator a) noexcept +{ + return a.ptr == nullptr; +} + + +template <::std::integral chtype, ::std::size_t keys_number, bool isrev> +inline constexpr bool operator!=(::fast_io::containers::details::str_btree_set_iterator a, + ::std::default_sentinel_t) noexcept +{ + return a.ptr != nullptr; +} + +template <::std::integral chtype, ::std::size_t keys_number, bool isrev> +inline constexpr bool operator!=(::std::default_sentinel_t, + ::fast_io::containers::details::str_btree_set_iterator a) noexcept +{ + return a.ptr != nullptr; +} + +template <::std::integral chtype, ::std::size_t keys_number, bool isrev> +struct str_btree_set_iters_type +{ + using char_type = chtype; + using value_type = char_type; + using cstring_view_type = ::fast_io::basic_cstring_view; + using const_iterator = ::fast_io::containers::details::str_btree_set_iterator; + using iterator = const_iterator; + const_iterator i; + constexpr const_iterator cbegin() const noexcept + { + return i; + } + constexpr ::std::default_sentinel_t cend() const noexcept + { + return {}; + } + constexpr const_iterator begin() const noexcept + { + return i; + } + constexpr ::std::default_sentinel_t end() const noexcept + { + return {}; + } }; + } // namespace details template <::std::integral chtype, typename Allocator, ::std::size_t keys_number = 63> @@ -273,10 +379,12 @@ class basic_str_btree_set using string_view_type = ::fast_io::basic_string_view; using cstring_view_type = ::fast_io::basic_cstring_view; using allocator_type = Allocator; + using const_iters_type = ::fast_io::containers::details::str_btree_set_iters_type; + using const_reverse_iters_type = ::fast_io::containers::details::str_btree_set_iters_type; #if 0 using const_iterator = ::fast_io::details::str_btree_set_iterator; using iterator = ::fast_io::details::str_btree_set_iterator; - ::fast_io::containers::details::btree_set_root root; + ::fast_io::containers::details::btree_node_common root; #endif node_type *root{}; @@ -304,7 +412,7 @@ class basic_str_btree_set } constexpr bool insert_key(string_view_type strvw) noexcept { - return ::fast_io::containers::details::str_btree_insert_key_with_root(this->root, strvw.data(), strvw.size()); + return ::fast_io::containers::details::str_btree_insert_key_with_root(__builtin_addressof(this->root), strvw.data(), strvw.size()); } private: @@ -350,6 +458,7 @@ class basic_str_btree_set clear_node(this->root); this->root = nullptr; } + constexpr void clear_destroy() noexcept { this->clear(); @@ -377,7 +486,7 @@ class basic_str_btree_set clear_node(this->root); } #if 0 - constexpr iters() const noexcept + constexpr citers() const noexcept {} #endif }; From 1afe32967adf1381c3bbf191d011c0be84d3d779 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Wed, 25 Jun 2025 00:50:53 +0800 Subject: [PATCH 15/81] str --- include/fast_io_dsal/impl/str_btree_set.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/fast_io_dsal/impl/str_btree_set.h b/include/fast_io_dsal/impl/str_btree_set.h index 5ac548032..1a4771cd8 100644 --- a/include/fast_io_dsal/impl/str_btree_set.h +++ b/include/fast_io_dsal/impl/str_btree_set.h @@ -63,7 +63,7 @@ inline constexpr find_btree_node_insert_position_result find_str_btree_node_inse } template -inline constexpr void str_btree_split_node(nodetype *node) noexcept; +inline constexpr void str_btree_split_node(nodetype *node, nodetype** proot) noexcept; template inline constexpr bool str_btree_insert_key(nodetype *node, From 3cab6b481f3d932af34431acbe5c20669927068b Mon Sep 17 00:00:00 2001 From: trcrsired Date: Wed, 25 Jun 2025 01:00:03 +0800 Subject: [PATCH 16/81] [btree] set nullptr for root? --- include/fast_io_dsal/impl/str_btree_set.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/fast_io_dsal/impl/str_btree_set.h b/include/fast_io_dsal/impl/str_btree_set.h index 1a4771cd8..5c24f2c65 100644 --- a/include/fast_io_dsal/impl/str_btree_set.h +++ b/include/fast_io_dsal/impl/str_btree_set.h @@ -171,6 +171,7 @@ inline constexpr void str_btree_split_node(nodetype *node, nodetype** proot) noe *(new_root->childrens) = node; new_root->childrens[1] = new_node; new_root->leaf = false; + new_node->parent = nullptr; node->parent = new_root; new_node->parent = new_root; } From 90b1b9480a97efa0b57f1984eea30fee676142e7 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Sun, 29 Jun 2025 10:42:16 +0800 Subject: [PATCH 17/81] str_btree_set --- include/fast_io_dsal/impl/str_btree_set.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/fast_io_dsal/impl/str_btree_set.h b/include/fast_io_dsal/impl/str_btree_set.h index 5c24f2c65..dd2d67bbf 100644 --- a/include/fast_io_dsal/impl/str_btree_set.h +++ b/include/fast_io_dsal/impl/str_btree_set.h @@ -86,7 +86,7 @@ inline constexpr bool str_btree_insert_key(nodetype *node, // **If there is space, insert the key directly** if (node->size < keys_number) { - for (::std::size_t j = node->size; pos < j; --j) + for (::std::size_t j{node->size}; pos < j; --j) { node->keys[j] = node->keys[j - 1]; } @@ -430,10 +430,10 @@ class basic_str_btree_set { clear_node(node->childrens[i]); } - +#if 0 ::fast_io::io::debug_println(::fast_io::mnp::pointervw(node), i, " ", ::fast_io::mnp::pointervw(node->keys + i), " ", node->keys[i].strvw()); - +#endif auto ki{node->keys[i]}; ::fast_io::typed_generic_allocator_adapter::deallocate_n(const_cast(ki.ptr), static_cast<::std::size_t>(ki.n + 1u)); From e1c83bc845efebb962110763c1760a2254e78bdb Mon Sep 17 00:00:00 2001 From: trcrsired Date: Tue, 1 Jul 2025 12:39:26 +0800 Subject: [PATCH 18/81] str_btree_set2.h --- include/fast_io_dsal/impl/str_btree_set2.h | 495 +++++++++++++++++++++ 1 file changed, 495 insertions(+) create mode 100644 include/fast_io_dsal/impl/str_btree_set2.h diff --git a/include/fast_io_dsal/impl/str_btree_set2.h b/include/fast_io_dsal/impl/str_btree_set2.h new file mode 100644 index 000000000..dd2d67bbf --- /dev/null +++ b/include/fast_io_dsal/impl/str_btree_set2.h @@ -0,0 +1,495 @@ +#pragma once + +namespace fast_io::containers +{ + +namespace details +{ +struct btree_node_common +{ + void *root; + void *next; +}; + +template <::std::integral chtype, ::std::size_t keys_number> +struct str_btree_set_node +{ + using char_type = chtype; + ::std::size_t size; // Number of keys currently stored + bool leaf; // Indicates whether the node is a leaf + ::fast_io::details::associative_string keys[keys_number]; // Array of keys + str_btree_set_node *childrens[keys_number + 1u]; // Array of child pointers + str_btree_set_node *parent; // Pointer to parent node +}; + +template <::std::size_t keys_number> +struct +#if __has_cpp_attribute(__gnu__::__may_alias__) +[[__gnu__::__may_alias__]] +#endif +str_btree_set_common +{ + ::std::size_t size; + bool leaf; + ::fast_io::io_scatter_t keys[keys_number]; + void *childrens[keys_number + 1u]; + void *parent; +}; + +struct find_btree_node_insert_position_result +{ + ::std::size_t pos{}; + bool found{}; +}; + +template +inline constexpr find_btree_node_insert_position_result find_str_btree_node_insert_position(nodetype *node, + typename nodetype::char_type const *keystrptr, ::std::size_t keystrn) noexcept +{ + using char_type = typename nodetype::char_type; + auto *b{node->keys}, *i{b}, *e{b + node->size}; + bool found{}; + ::fast_io::basic_string_view newkey(keystrptr, keystrn); + for (; i != e; ++i) + { + auto cmpres{newkey <=> i->strvw()}; + if (cmpres <= 0) + { + found = (cmpres == 0); + break; + } + } + return {static_cast<::std::size_t>(i - b), found}; +} + +template +inline constexpr void str_btree_split_node(nodetype *node, nodetype** proot) noexcept; + +template +inline constexpr bool str_btree_insert_key(nodetype *node, + typename nodetype::char_type const *keystrptr, ::std::size_t keystrn, bool ismoved, nodetype** proot) noexcept +{ + using char_type = typename nodetype::char_type; + // **Find the correct position for insertion** + auto [pos, found] = find_str_btree_node_insert_position(node, keystrptr, keystrn); + + // **If the key already exists, return false (no duplicate keys)** + if (found) + { + return false; + } + + // **If the node is a leaf** + if (node->leaf) + { + + // **If there is space, insert the key directly** + if (node->size < keys_number) + { + for (::std::size_t j{node->size}; pos < j; --j) + { + node->keys[j] = node->keys[j - 1]; + } + ::fast_io::details::associative_string astr; + if (ismoved) + { + astr.ptr = keystrptr; + astr.n = keystrn; + } + else + { + astr = ::fast_io::details::create_associative_string(keystrptr, keystrn); + } + node->keys[pos] = astr; + ++node->size; + return true; + } + else + { + // **If the node is full, split it** + str_btree_split_node(node, proot); + return str_btree_insert_key(node->parent, keystrptr, keystrn, ismoved, proot); + } + } + else + { + // **Recursively insert into the correct child** + return str_btree_insert_key(node->childrens[pos], keystrptr, keystrn, ismoved, proot); + } +} + +template +inline constexpr void str_btree_split_node(nodetype *node, nodetype** proot) noexcept +{ + using char_type = typename nodetype::char_type; + using typed_allocator_type = ::fast_io::typed_generic_allocator_adapter; + constexpr ::std::size_t keys_number_div2{keys_number >> 1u}; + constexpr ::std::size_t keys_number_p1{keys_number + 1u}; + constexpr ::std::size_t mid{keys_number_div2}; + constexpr ::std::size_t midp1{mid + 1u}; + constexpr ::std::size_t keys_number_sub_midp1{keys_number - midp1}; + + // **Allocate a new node using the stateless allocator** + nodetype *new_node{typed_allocator_type::allocate(1)}; + + new_node->parent = node->parent; + new_node->leaf = node->leaf; + + // **Move the right half of the keys to the new node** + for (::std::size_t j{midp1}, k{}; j != keys_number; ++j, ++k) + { + new_node->keys[k] = node->keys[j]; + } + + new_node->size = keys_number_sub_midp1; + + // **Handle child pointers (if not a leaf)** + if (!node->leaf) + { + for (::std::size_t j{midp1}, k{}; j != keys_number_p1; ++j, ++k) + { + auto &ck{new_node->childrens[k]}; + ck = node->childrens[j]; + auto ckv{ck}; + if (ckv) + { + ckv->parent = new_node; + } + } + } + + node->size = mid; // **Keep only the left half in the current node** + + // **Promote the middle key to the parent node** + if (node->parent == nullptr) + { + // **Allocate a new root using the stateless allocator** + nodetype *new_root{typed_allocator_type::allocate(1)}; + *proot = new_root; + *(new_root->keys) = node->keys[mid]; + new_root->size = 1; + *(new_root->childrens) = node; + new_root->childrens[1] = new_node; + new_root->leaf = false; + new_node->parent = nullptr; + node->parent = new_root; + new_node->parent = new_root; + } + else + { + // **Insert the middle key into the parent node** + str_btree_insert_key(node->parent, node->keys[mid].ptr, node->keys[mid].n, true, proot); + node->parent->childrens[node->parent->size] = new_node; + new_node->parent = node->parent; + } +} + +template +inline constexpr bool str_btree_insert_key_with_root(nodetype **proot, + typename nodetype::char_type const *keystrptr, ::std::size_t keystrn) noexcept +{ + using typed_allocator_type = ::fast_io::typed_generic_allocator_adapter; + + auto node{*proot}; + + // **If the tree is empty, allocate a new root** + if (node == nullptr) + { + node = typed_allocator_type::allocate(1); + node->size = 1; + node->leaf = true; + node->parent = nullptr; + *(node->keys) = ::fast_io::details::create_associative_string(keystrptr, keystrn); + *proot = node; + return true; + } + return ::fast_io::containers::details::str_btree_insert_key(node, keystrptr, keystrn, false, proot); +} +#if 0 +template <::std::integral chtype, ::std::size_t keys_number> +struct str_btree_set_iterator +{ + ::fast_io::containers::str_btree_set_node* node{}; + ::std::size_t pos{}; + constexpr str_btree_set_iterator& operator++() noexcept + { + if (node == nullptr) + return *this; + + // **If there are more keys in the current node, move right** + if (pos + 1 < node->size) + { + ++pos; + return *this; + } + + // **If there is a right child, move to the smallest key in the right subtree** + if (!node->leaf) + { + node = node->childrens[pos + 1]; + while (!node->leaf) + node = node->childrens[0]; + pos = 0; + return *this; + } + + // **Otherwise, move up until we find a larger key** + while (node->parent && node == node->parent->childrens[node->parent->size]) + node = node->parent; + + if (node->parent) + { + pos = 0; + node = node->parent; + } + else + { + node = nullptr; // **End of iteration** + } + } +#if 0 + constexpr str_btree_set_iterator& operator--() noexcept + { + + } +#endif + constexpr ::fast_io::containers::basic_cstring_view operator*() const noexcept + { + auto &def{this->node->keys[this->pos]}; + return def.strvw(); + } +}; + +template <::std::integral chtype, ::std::size_t keys_number> +inline constexpr bool operator==(::fast_io::containers::details::str_btree_set_iterator a, + ::fast_io::containers::details::str_btree_set_iterator b) +{ + return a.node == b.node && a.pos == b.pos; +} + +template <::std::integral chtype, ::std::size_t keys_number> +inline constexpr bool operator!=(::fast_io::containers::details::str_btree_set_iterator a, + ::fast_io::containers::details::str_btree_set_iterator b) +{ + return !(a==b); +} +#endif + +template <::std::integral chtype, ::std::size_t keys_number, bool isrev> +struct str_btree_set_iterator +{ + using char_type = chtype; + using value_type = char_type; + using cstring_view_type = ::fast_io::basic_cstring_view; + using const_iterator = ::fast_io::containers::details::str_btree_set_iterator; + using iterator = const_iterator; + ::fast_io::containers::details::str_btree_set_node *ptr{}; + inline constexpr const_iterator operator++() noexcept + { + return {}; + } + inline constexpr const_iterator operator++(int) noexcept + { + auto tmp{*this}; + ++*this; + return tmp; + } +}; + +template <::std::integral chtype, ::std::size_t keys_number, bool isrev> +inline constexpr bool operator==(::fast_io::containers::details::str_btree_set_iterator a, + ::fast_io::containers::details::str_btree_set_iterator b) noexcept +{ + return a.ptr == b.ptr; +} + +template <::std::integral chtype, ::std::size_t keys_number, bool isrev> +inline constexpr bool operator!=(::fast_io::containers::details::str_btree_set_iterator a, + ::fast_io::containers::details::str_btree_set_iterator b) noexcept +{ + return a.ptr != b.ptr; +} + +template <::std::integral chtype, ::std::size_t keys_number, bool isrev> +inline constexpr bool operator==(::fast_io::containers::details::str_btree_set_iterator a, + ::std::default_sentinel_t) noexcept +{ + return a.ptr == nullptr; +} + +template <::std::integral chtype, ::std::size_t keys_number, bool isrev> +inline constexpr bool operator==(::std::default_sentinel_t, + ::fast_io::containers::details::str_btree_set_iterator a) noexcept +{ + return a.ptr == nullptr; +} + + +template <::std::integral chtype, ::std::size_t keys_number, bool isrev> +inline constexpr bool operator!=(::fast_io::containers::details::str_btree_set_iterator a, + ::std::default_sentinel_t) noexcept +{ + return a.ptr != nullptr; +} + +template <::std::integral chtype, ::std::size_t keys_number, bool isrev> +inline constexpr bool operator!=(::std::default_sentinel_t, + ::fast_io::containers::details::str_btree_set_iterator a) noexcept +{ + return a.ptr != nullptr; +} + +template <::std::integral chtype, ::std::size_t keys_number, bool isrev> +struct str_btree_set_iters_type +{ + using char_type = chtype; + using value_type = char_type; + using cstring_view_type = ::fast_io::basic_cstring_view; + using const_iterator = ::fast_io::containers::details::str_btree_set_iterator; + using iterator = const_iterator; + const_iterator i; + constexpr const_iterator cbegin() const noexcept + { + return i; + } + constexpr ::std::default_sentinel_t cend() const noexcept + { + return {}; + } + constexpr const_iterator begin() const noexcept + { + return i; + } + constexpr ::std::default_sentinel_t end() const noexcept + { + return {}; + } +}; + +} // namespace details + +template <::std::integral chtype, typename Allocator, ::std::size_t keys_number = 63> +class basic_str_btree_set +{ + using node_type = ::fast_io::containers::details::str_btree_set_node; + using untyped_allocator_type = Allocator; + using typed_allocator_type = ::fast_io::typed_generic_allocator_adapter; + +public: + using char_type = chtype; + using string_view_type = ::fast_io::basic_string_view; + using cstring_view_type = ::fast_io::basic_cstring_view; + using allocator_type = Allocator; + using const_iters_type = ::fast_io::containers::details::str_btree_set_iters_type; + using const_reverse_iters_type = ::fast_io::containers::details::str_btree_set_iters_type; +#if 0 + using const_iterator = ::fast_io::details::str_btree_set_iterator; + using iterator = ::fast_io::details::str_btree_set_iterator; + ::fast_io::containers::details::btree_node_common root; +#endif + node_type *root{}; + + constexpr basic_str_btree_set() noexcept = default; + + explicit constexpr basic_str_btree_set(::std::initializer_list ilist) noexcept + { + for (auto const &e : ilist) + { + this->insert_key(e); + } + } + + constexpr bool contains(string_view_type) const noexcept + { + return false; + } + constexpr bool is_empty() const noexcept + { + return false; + } + constexpr bool erase_key(string_view_type) noexcept + { + return false; + } + constexpr bool insert_key(string_view_type strvw) noexcept + { + return ::fast_io::containers::details::str_btree_insert_key_with_root(__builtin_addressof(this->root), strvw.data(), strvw.size()); + } + +private: + static inline constexpr void clear_node(node_type *node) noexcept + { + if (node == nullptr) + { + return; + } + ::std::size_t const n{node->size}; + for (::std::size_t i{}; i != n; ++i) + { + if (!node->leaf) + { + clear_node(node->childrens[i]); + } +#if 0 + ::fast_io::io::debug_println(::fast_io::mnp::pointervw(node), + i, " ", ::fast_io::mnp::pointervw(node->keys + i), " ", node->keys[i].strvw()); +#endif + auto ki{node->keys[i]}; + ::fast_io::typed_generic_allocator_adapter::deallocate_n(const_cast(ki.ptr), + static_cast<::std::size_t>(ki.n + 1u)); + } +#if 0 + if (!node->leaf) + { + clear_node(node->childrens[n]); + + auto ki{node->childrens[node->size]}; + ::fast_io::typed_generic_allocator_adapter::deallocate_n(, + static_cast<::std::size_t>(ki.n+1u)); + } +#endif + + // **Deallocate the node using the allocator** + typed_allocator_type::deallocate_n(node, 1); + } + +public: + constexpr void clear() noexcept + { + clear_node(this->root); + this->root = nullptr; + } + + constexpr void clear_destroy() noexcept + { + this->clear(); + } + + constexpr basic_str_btree_set(basic_str_btree_set const &) noexcept = delete; + constexpr basic_str_btree_set &operator=(basic_str_btree_set const &) noexcept = delete; + + constexpr basic_str_btree_set(basic_str_btree_set &&other) noexcept : root{other.root} + { + other.root = nullptr; + } + constexpr basic_str_btree_set &operator=(basic_str_btree_set &&other) noexcept + { + if (::std::addressof(other) == this) + { + return *this; + } + this->root = other.root; + other.root = nullptr; + return *this; + } + constexpr ~basic_str_btree_set() + { + clear_node(this->root); + } +#if 0 + constexpr citers() const noexcept + {} +#endif +}; + +} // namespace fast_io::containers \ No newline at end of file From 313b6d478a36f0eeb37f4f9473d8498e324e4196 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Mon, 7 Jul 2025 03:17:55 +0800 Subject: [PATCH 19/81] put debugging information in it first --- include/fast_io_dsal/impl/str_btree_set.h | 530 +++++++++++----------- 1 file changed, 258 insertions(+), 272 deletions(-) diff --git a/include/fast_io_dsal/impl/str_btree_set.h b/include/fast_io_dsal/impl/str_btree_set.h index dd2d67bbf..4fb4a5cff 100644 --- a/include/fast_io_dsal/impl/str_btree_set.h +++ b/include/fast_io_dsal/impl/str_btree_set.h @@ -20,14 +20,15 @@ struct str_btree_set_node ::fast_io::details::associative_string keys[keys_number]; // Array of keys str_btree_set_node *childrens[keys_number + 1u]; // Array of child pointers str_btree_set_node *parent; // Pointer to parent node + ::std::size_t parent_pos; // Position in Parent }; template <::std::size_t keys_number> struct #if __has_cpp_attribute(__gnu__::__may_alias__) -[[__gnu__::__may_alias__]] + [[__gnu__::__may_alias__]] #endif -str_btree_set_common + str_btree_set_common { ::std::size_t size; bool leaf; @@ -44,7 +45,7 @@ struct find_btree_node_insert_position_result template inline constexpr find_btree_node_insert_position_result find_str_btree_node_insert_position(nodetype *node, - typename nodetype::char_type const *keystrptr, ::std::size_t keystrn) noexcept + typename nodetype::char_type const *keystrptr, ::std::size_t keystrn) noexcept { using char_type = typename nodetype::char_type; auto *b{node->keys}, *i{b}, *e{b + node->size}; @@ -62,126 +63,285 @@ inline constexpr find_btree_node_insert_position_result find_str_btree_node_inse return {static_cast<::std::size_t>(i - b), found}; } -template -inline constexpr void str_btree_split_node(nodetype *node, nodetype** proot) noexcept; - template inline constexpr bool str_btree_insert_key(nodetype *node, - typename nodetype::char_type const *keystrptr, ::std::size_t keystrn, bool ismoved, nodetype** proot) noexcept + typename nodetype::char_type const *keystrptr, ::std::size_t keystrn, nodetype **proot) noexcept { using char_type = typename nodetype::char_type; + using typed_allocator_type = ::fast_io::typed_generic_allocator_adapter; + ::std::size_t pos; // **Find the correct position for insertion** - auto [pos, found] = find_str_btree_node_insert_position(node, keystrptr, keystrn); - - // **If the key already exists, return false (no duplicate keys)** - if (found) + for (;;) { - return false; - } - - // **If the node is a leaf** - if (node->leaf) - { - - // **If there is space, insert the key directly** - if (node->size < keys_number) + auto [postemp, found] = find_str_btree_node_insert_position(node, keystrptr, keystrn); + pos = postemp; + // **If the key already exists, return false (no duplicate keys)** + if (found) { - for (::std::size_t j{node->size}; pos < j; --j) - { - node->keys[j] = node->keys[j - 1]; - } - ::fast_io::details::associative_string astr; - if (ismoved) - { - astr.ptr = keystrptr; - astr.n = keystrn; - } - else - { - astr = ::fast_io::details::create_associative_string(keystrptr, keystrn); - } - node->keys[pos] = astr; - ++node->size; - return true; + return false; } - else + // **If the node is a leaf** + if (node->leaf) { - // **If the node is full, split it** - str_btree_split_node(node, proot); - return str_btree_insert_key(node->parent, keystrptr, keystrn, ismoved, proot); + break; } + node = node->childrens[pos]; } - else + auto tempkey = ::fast_io::details::create_associative_string(keystrptr, keystrn); + + __builtin_printf("%s %d %s\n",__FILE__,__LINE__,tempkey.ptr); + auto keys{node->keys}; + auto n{node->size}; + auto keysit{keys + pos}; + auto keysed{keys + keys_number}; + // **If there is space, insert the key directly** + if (n != keys_number) { - // **Recursively insert into the correct child** - return str_btree_insert_key(node->childrens[pos], keystrptr, keystrn, ismoved, proot); + ::fast_io::freestanding::overlapped_copy(keysit, keysed, keysit + 1); + *keysit = tempkey; + ++node->size; + return true; } -} -template -inline constexpr void str_btree_split_node(nodetype *node, nodetype** proot) noexcept -{ - using char_type = typename nodetype::char_type; - using typed_allocator_type = ::fast_io::typed_generic_allocator_adapter; - constexpr ::std::size_t keys_number_div2{keys_number >> 1u}; - constexpr ::std::size_t keys_number_p1{keys_number + 1u}; - constexpr ::std::size_t mid{keys_number_div2}; - constexpr ::std::size_t midp1{mid + 1u}; - constexpr ::std::size_t keys_number_sub_midp1{keys_number - midp1}; + constexpr ::std::size_t keys_number_half{keys_number >> (1u)}; + constexpr ::std::size_t keys_number_half_m1{keys_number_half - 1u}; + constexpr ::std::size_t keys_number_half_p1{keys_number_half + 1u}; + // ** Split now + auto rightchild{typed_allocator_type::allocate(1)}; + node->leaf = rightchild->leaf = true; + node->size = rightchild->size = keys_number_half; - // **Allocate a new node using the stateless allocator** - nodetype *new_node{typed_allocator_type::allocate(1)}; + auto rightchildkeys{rightchild->keys}; + // auto rightchildchildrens{rightchild->childrens}; - new_node->parent = node->parent; - new_node->leaf = node->leaf; + char_type const *movekeystrptr{}; + ::std::size_t movekeystrn{}; - // **Move the right half of the keys to the new node** - for (::std::size_t j{midp1}, k{}; j != keys_number; ++j, ++k) + __builtin_printf("%s %d %s\n",__FILE__,__LINE__,tempkey.ptr); + auto midptr{keys + keys_number_half}; + auto poskeys_number_halfcmp{pos <=> keys_number_half}; + if (poskeys_number_halfcmp < 0) + { + ::fast_io::details::non_overlapped_copy_n(midptr, keys_number_half, rightchildkeys); + ::fast_io::freestanding::overlapped_copy(keys + pos, keys + keys_number_half, keys + pos + 1); + auto &keystrptrkeysnumber{midptr[-1]}; + movekeystrptr = keystrptrkeysnumber.ptr; + movekeystrn = keystrptrkeysnumber.n; + keys[pos] = tempkey; + } + else if (poskeys_number_halfcmp == 0) { - new_node->keys[k] = node->keys[j]; + ::fast_io::details::non_overlapped_copy_n(midptr, keys_number_half, rightchildkeys); + movekeystrptr = tempkey.ptr; + movekeystrn = tempkey.n; } + else + { + auto &keystrptrkeysnumber{*midptr}; + movekeystrptr = keystrptrkeysnumber.ptr; + movekeystrn = keystrptrkeysnumber.n; + auto it{::fast_io::details::non_overlapped_copy(midptr + 1, keysit, rightchildkeys)}; + *it = tempkey; + ++it; + ::fast_io::details::non_overlapped_copy(keysit, keysed, it); + } + __builtin_printf("%s %d %s node->parent=%p\n",__FILE__,__LINE__,tempkey.ptr,node->parent); + ::std::size_t child_pos{node->parent_pos}; + for (auto j{node->parent}; j; j = j->parent) + { + auto jkeys{j->keys}; + auto jchildrens{j->childrens}; + auto jn{j->size}; + __builtin_printf("%s %d %s j=%p\n",__FILE__,__LINE__,tempkey.ptr, j); + // If parent node has space, insert the promoted key and return + if (jn != keys_number) + { + __builtin_printf("%s %d %s j=%p\n",__FILE__,__LINE__,tempkey.ptr, j); + // Shift keys and children to make room for the promoted key and new child + ::fast_io::freestanding::overlapped_copy(jkeys + child_pos, jkeys + jn, jkeys + child_pos + 1); + jkeys[child_pos].ptr = movekeystrptr; + jkeys[child_pos].n = movekeystrn; + + ::fast_io::freestanding::overlapped_copy(jchildrens + child_pos + 1, jchildrens + jn + 1, jchildrens + child_pos + 2); + jchildrens[child_pos + 1] = rightchild; + rightchild->parent = j; + rightchild->parent_pos = child_pos + 1; + + for(auto k{jchildrens+(child_pos+2)},ked{jchildrens+(jn+2)};k!=ked;++k) + { + (*k)->parent_pos = static_cast<::std::size_t>(k-jchildrens); + } + ++j->size; + return true; + } + __builtin_printf("%s %d %s j=%p\n",__FILE__,__LINE__,tempkey.ptr, j); + // Parent is full, must split upward + auto new_right = typed_allocator_type::allocate(1); + node->leaf = new_right->leaf = false; + j->size = new_right->size = keys_number_half; + + auto jmidptr = jkeys + keys_number_half; +#if 0 + + auto child_poskeys_number_halfcmp{child_pos <=> keys_number_half}; + // CASE 1: promoted child is in the left half (before the mid key) + if (child_poskeys_number_halfcmp < 0) + { + ::fast_io::details::non_overlapped_copy_n(jmidptr, keys_number_half, new_right->keys); + ::fast_io::freestanding::overlapped_copy(jkeys + child_pos, jmidptr, jkeys + child_pos + 1); + jkeys[child_pos].ptr = movekeystrptr; + jkeys[child_pos].n = movekeystrn; - new_node->size = keys_number_sub_midp1; + auto &midkey = jmidptr[-1]; + movekeystrptr = midkey.ptr; + movekeystrn = midkey.n; - // **Handle child pointers (if not a leaf)** - if (!node->leaf) - { - for (::std::size_t j{midp1}, k{}; j != keys_number_p1; ++j, ++k) + ::fast_io::details::non_overlapped_copy_n(jchildrens + keys_number_half + 1, keys_number_half, new_right->childrens); + ::fast_io::freestanding::overlapped_copy(jchildrens + child_pos + 1, jchildrens + keys_number_half + 1, jchildrens + child_pos + 2); + jchildrens[child_pos + 1] = rightchild; + + for (::std::size_t i{}; i != keys_number_half; ++i) + { + auto p = new_right->childrens[i]; + p->parent = new_right; + p->parent_pos = i; + } + } + // CASE 2: promoted child goes exactly after the mid key (replace middle) + else if (child_poskeys_number_halfcmp == 0) + { + ::fast_io::details::non_overlapped_copy_n(jmidptr + 1, keys_number_half, new_right->keys); + movekeystrptr = tempkey.ptr; + movekeystrn = tempkey.n; + + ::fast_io::details::non_overlapped_copy_n(jchildrens + keys_number_half + 1, keys_number_half, new_right->childrens); + *(new_right->childrens) = rightchild; + + for (::std::size_t i{}; i != keys_number_half + 1; ++i) + { + auto p = new_right->childrens[i]; + p->parent = new_right; + p->parent_pos = i; + } + } + // CASE 3: promoted child is in the right half (after the mid key) + else { - auto &ck{new_node->childrens[k]}; - ck = node->childrens[j]; - auto ckv{ck}; - if (ckv) + auto &midkey = *jmidptr; + movekeystrptr = midkey.ptr; + movekeystrn = midkey.n; + + ::fast_io::details::non_overlapped_copy_n(jmidptr + 1, keys_number_half, new_right->keys); + auto it = ::fast_io::details::non_overlapped_copy(jmidptr + 2, jkeys + child_pos, new_right->keys); + *it = tempkey; + ++it; + ::fast_io::details::non_overlapped_copy(jkeys + child_pos, jkeys + keys_number, it); + + auto itc = ::fast_io::details::non_overlapped_copy(jchildrens + keys_number_half + 2, jchildrens + child_pos + 1, new_right->childrens + 1); + *itc = rightchild; + ++itc; + ::fast_io::details::non_overlapped_copy(jchildrens + child_pos + 1, jchildrens + keys_number + 1, itc); + + for (::std::size_t i{}; i != keys_number_half + 1; ++i) { - ckv->parent = new_node; + auto p = new_right->childrens[i]; + p->parent = new_right; + p->parent_pos = i; } } - } +#else + + __builtin_printf("%s %d %s j=%p\n",__FILE__,__LINE__,tempkey.ptr, j); + auto new_right_keys{new_right->keys}; + auto new_right_childrens{new_right->childrens}; + auto child_poskeys_number_halfcmp{child_pos <=> keys_number_half}; + __builtin_printf("%s %d %s j=%p\n",__FILE__,__LINE__,tempkey.ptr, j); + // CASE 1: promoted child is in the left half (before the mid key) + if (child_poskeys_number_halfcmp < 0) + { + __builtin_printf("%s %d %s j=%p\n",__FILE__,__LINE__,tempkey.ptr, j); + ::fast_io::details::non_overlapped_copy_n(jmidptr, keys_number_half, new_right_keys); + ::fast_io::freestanding::overlapped_copy(jkeys + child_pos, jmidptr, jkeys + child_pos + 1); + jkeys[child_pos].ptr = movekeystrptr; + jkeys[child_pos].n = movekeystrn; + + auto &jmidkey = jmidptr[-1]; + movekeystrptr = jmidkey.ptr; + movekeystrn = jmidkey.n; + __builtin_printf("%s %d %s j=%p\n",__FILE__,__LINE__,tempkey.ptr, j); + ::fast_io::details::non_overlapped_copy_n(jchildrens + keys_number_half_p1, keys_number_half, new_right_childrens); + ::fast_io::freestanding::overlapped_copy(jchildrens + child_pos + 1, jchildrens + keys_number_half_p1, jchildrens + child_pos + 2); + jchildrens[child_pos + 1] = rightchild; + rightchild->parent = node; + rightchild->parent_pos = child_pos + 1; + + for (::std::size_t i{child_pos + 2}; i != keys_number_half_p1; ++i) + { + jchildrens[i]->parent_pos = i; + } - node->size = mid; // **Keep only the left half in the current node** - // **Promote the middle key to the parent node** - if (node->parent == nullptr) - { - // **Allocate a new root using the stateless allocator** - nodetype *new_root{typed_allocator_type::allocate(1)}; - *proot = new_root; - *(new_root->keys) = node->keys[mid]; - new_root->size = 1; - *(new_root->childrens) = node; - new_root->childrens[1] = new_node; - new_root->leaf = false; - new_node->parent = nullptr; - node->parent = new_root; - new_node->parent = new_root; - } - else - { - // **Insert the middle key into the parent node** - str_btree_insert_key(node->parent, node->keys[mid].ptr, node->keys[mid].n, true, proot); - node->parent->childrens[node->parent->size] = new_node; - new_node->parent = node->parent; + } + else if (child_poskeys_number_halfcmp == 0) + { + __builtin_printf("%s %d %s j=%p\n",__FILE__,__LINE__,tempkey.ptr, j); + ::fast_io::details::non_overlapped_copy_n(jmidptr, keys_number_half, new_right_keys); + ::fast_io::details::non_overlapped_copy_n(jchildrens + keys_number_half_p1, keys_number_half, new_right_childrens); + *(new_right->childrens) = rightchild; + rightchild->parent = node; + rightchild->parent_pos = child_pos + 1; + } + else + { + __builtin_printf("%s %d %s j=%p child_pos=%zu\n",__FILE__,__LINE__,tempkey.ptr, j, child_pos); + auto &jkeystrptrkeysnumber{*jmidptr}; + movekeystrptr = jkeystrptrkeysnumber.ptr; + movekeystrn = jkeystrptrkeysnumber.n; + __builtin_printf("%s %d %s j=%p child_pos=%zu\n",__FILE__,__LINE__,tempkey.ptr, j, child_pos); + auto jkeysit{jkeys + child_pos}; + auto jkeysed{jkeys + keys_number}; + auto it{::fast_io::details::non_overlapped_copy(jmidptr + 1, jkeysit, new_right_keys)}; + __builtin_printf("%s %d %s j=%p child_pos=%zu\n",__FILE__,__LINE__,tempkey.ptr, j, child_pos); + *it = tempkey; + ++it; + ::fast_io::details::non_overlapped_copy(jkeysit, jkeysed, it); + __builtin_printf("%s %d %s j=%p\n",__FILE__,__LINE__,tempkey.ptr, j); + auto jchildrensit{jchildrens + child_pos}; + auto jchildrensed{jchildrens + keys_number}; + auto kit{::fast_io::details::non_overlapped_copy(jchildrens + keys_number_half_p1, jchildrensit, new_right_childrens)}; + *kit = rightchild; + ++kit; + ::fast_io::details::non_overlapped_copy(jchildrensit, jchildrensed, kit); + + } + + for (auto k{new_right_childrens},ked{new_right_childrens+keys_number_half_p1}; k != ked; ++k) + { + auto kref{**k}; + kref.parent = new_right; + kref.parent_pos = static_cast<::std::size_t>(k-new_right_childrens); + } +#endif + rightchild = new_right; + child_pos = j->parent_pos; } + __builtin_printf("%s %d %s\n",__FILE__,__LINE__,tempkey.ptr); + auto new_root = typed_allocator_type::allocate(1); + new_root->leaf = false; + new_root->size = 1; + new_root->keys->ptr = movekeystrptr; + new_root->keys->n = movekeystrn; + new_root->parent = nullptr; + new_root->parent_pos = 0; + *(new_root->childrens) = node; + new_root->childrens[1] = rightchild; + node->parent = new_root; + node->parent_pos = 0; + rightchild->parent = new_root; + rightchild->parent_pos = 1; + + *proot = new_root; + return true; } template @@ -199,172 +359,13 @@ inline constexpr bool str_btree_insert_key_with_root(nodetype **proot, node->size = 1; node->leaf = true; node->parent = nullptr; + node->parent_pos = 0; *(node->keys) = ::fast_io::details::create_associative_string(keystrptr, keystrn); *proot = node; return true; } - return ::fast_io::containers::details::str_btree_insert_key(node, keystrptr, keystrn, false, proot); + return ::fast_io::containers::details::str_btree_insert_key(node, keystrptr, keystrn, proot); } -#if 0 -template <::std::integral chtype, ::std::size_t keys_number> -struct str_btree_set_iterator -{ - ::fast_io::containers::str_btree_set_node* node{}; - ::std::size_t pos{}; - constexpr str_btree_set_iterator& operator++() noexcept - { - if (node == nullptr) - return *this; - - // **If there are more keys in the current node, move right** - if (pos + 1 < node->size) - { - ++pos; - return *this; - } - - // **If there is a right child, move to the smallest key in the right subtree** - if (!node->leaf) - { - node = node->childrens[pos + 1]; - while (!node->leaf) - node = node->childrens[0]; - pos = 0; - return *this; - } - - // **Otherwise, move up until we find a larger key** - while (node->parent && node == node->parent->childrens[node->parent->size]) - node = node->parent; - - if (node->parent) - { - pos = 0; - node = node->parent; - } - else - { - node = nullptr; // **End of iteration** - } - } -#if 0 - constexpr str_btree_set_iterator& operator--() noexcept - { - - } -#endif - constexpr ::fast_io::containers::basic_cstring_view operator*() const noexcept - { - auto &def{this->node->keys[this->pos]}; - return def.strvw(); - } -}; - -template <::std::integral chtype, ::std::size_t keys_number> -inline constexpr bool operator==(::fast_io::containers::details::str_btree_set_iterator a, - ::fast_io::containers::details::str_btree_set_iterator b) -{ - return a.node == b.node && a.pos == b.pos; -} - -template <::std::integral chtype, ::std::size_t keys_number> -inline constexpr bool operator!=(::fast_io::containers::details::str_btree_set_iterator a, - ::fast_io::containers::details::str_btree_set_iterator b) -{ - return !(a==b); -} -#endif - -template <::std::integral chtype, ::std::size_t keys_number, bool isrev> -struct str_btree_set_iterator -{ - using char_type = chtype; - using value_type = char_type; - using cstring_view_type = ::fast_io::basic_cstring_view; - using const_iterator = ::fast_io::containers::details::str_btree_set_iterator; - using iterator = const_iterator; - ::fast_io::containers::details::str_btree_set_node *ptr{}; - inline constexpr const_iterator operator++() noexcept - { - return {}; - } - inline constexpr const_iterator operator++(int) noexcept - { - auto tmp{*this}; - ++*this; - return tmp; - } -}; - -template <::std::integral chtype, ::std::size_t keys_number, bool isrev> -inline constexpr bool operator==(::fast_io::containers::details::str_btree_set_iterator a, - ::fast_io::containers::details::str_btree_set_iterator b) noexcept -{ - return a.ptr == b.ptr; -} - -template <::std::integral chtype, ::std::size_t keys_number, bool isrev> -inline constexpr bool operator!=(::fast_io::containers::details::str_btree_set_iterator a, - ::fast_io::containers::details::str_btree_set_iterator b) noexcept -{ - return a.ptr != b.ptr; -} - -template <::std::integral chtype, ::std::size_t keys_number, bool isrev> -inline constexpr bool operator==(::fast_io::containers::details::str_btree_set_iterator a, - ::std::default_sentinel_t) noexcept -{ - return a.ptr == nullptr; -} - -template <::std::integral chtype, ::std::size_t keys_number, bool isrev> -inline constexpr bool operator==(::std::default_sentinel_t, - ::fast_io::containers::details::str_btree_set_iterator a) noexcept -{ - return a.ptr == nullptr; -} - - -template <::std::integral chtype, ::std::size_t keys_number, bool isrev> -inline constexpr bool operator!=(::fast_io::containers::details::str_btree_set_iterator a, - ::std::default_sentinel_t) noexcept -{ - return a.ptr != nullptr; -} - -template <::std::integral chtype, ::std::size_t keys_number, bool isrev> -inline constexpr bool operator!=(::std::default_sentinel_t, - ::fast_io::containers::details::str_btree_set_iterator a) noexcept -{ - return a.ptr != nullptr; -} - -template <::std::integral chtype, ::std::size_t keys_number, bool isrev> -struct str_btree_set_iters_type -{ - using char_type = chtype; - using value_type = char_type; - using cstring_view_type = ::fast_io::basic_cstring_view; - using const_iterator = ::fast_io::containers::details::str_btree_set_iterator; - using iterator = const_iterator; - const_iterator i; - constexpr const_iterator cbegin() const noexcept - { - return i; - } - constexpr ::std::default_sentinel_t cend() const noexcept - { - return {}; - } - constexpr const_iterator begin() const noexcept - { - return i; - } - constexpr ::std::default_sentinel_t end() const noexcept - { - return {}; - } -}; } // namespace details @@ -380,13 +381,7 @@ class basic_str_btree_set using string_view_type = ::fast_io::basic_string_view; using cstring_view_type = ::fast_io::basic_cstring_view; using allocator_type = Allocator; - using const_iters_type = ::fast_io::containers::details::str_btree_set_iters_type; - using const_reverse_iters_type = ::fast_io::containers::details::str_btree_set_iters_type; -#if 0 - using const_iterator = ::fast_io::details::str_btree_set_iterator; - using iterator = ::fast_io::details::str_btree_set_iterator; - ::fast_io::containers::details::btree_node_common root; -#endif + node_type *root{}; constexpr basic_str_btree_set() noexcept = default; @@ -438,16 +433,11 @@ class basic_str_btree_set ::fast_io::typed_generic_allocator_adapter::deallocate_n(const_cast(ki.ptr), static_cast<::std::size_t>(ki.n + 1u)); } -#if 0 if (!node->leaf) { clear_node(node->childrens[n]); - auto ki{node->childrens[node->size]}; - ::fast_io::typed_generic_allocator_adapter::deallocate_n(, - static_cast<::std::size_t>(ki.n+1u)); } -#endif // **Deallocate the node using the allocator** typed_allocator_type::deallocate_n(node, 1); @@ -486,10 +476,6 @@ class basic_str_btree_set { clear_node(this->root); } -#if 0 - constexpr citers() const noexcept - {} -#endif }; } // namespace fast_io::containers \ No newline at end of file From 771b5abafec386f26ef8491c8e1975f11d311552 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Tue, 8 Jul 2025 19:17:32 +0800 Subject: [PATCH 20/81] [str_btree_set] implement more logic for btree --- include/fast_io_dsal/impl/str_btree_set.h | 114 ++++------------------ 1 file changed, 17 insertions(+), 97 deletions(-) diff --git a/include/fast_io_dsal/impl/str_btree_set.h b/include/fast_io_dsal/impl/str_btree_set.h index 4fb4a5cff..942bbd1f2 100644 --- a/include/fast_io_dsal/impl/str_btree_set.h +++ b/include/fast_io_dsal/impl/str_btree_set.h @@ -89,7 +89,6 @@ inline constexpr bool str_btree_insert_key(nodetype *node, } auto tempkey = ::fast_io::details::create_associative_string(keystrptr, keystrn); - __builtin_printf("%s %d %s\n",__FILE__,__LINE__,tempkey.ptr); auto keys{node->keys}; auto n{node->size}; auto keysit{keys + pos}; @@ -104,7 +103,6 @@ inline constexpr bool str_btree_insert_key(nodetype *node, } constexpr ::std::size_t keys_number_half{keys_number >> (1u)}; - constexpr ::std::size_t keys_number_half_m1{keys_number_half - 1u}; constexpr ::std::size_t keys_number_half_p1{keys_number_half + 1u}; // ** Split now auto rightchild{typed_allocator_type::allocate(1)}; @@ -117,7 +115,6 @@ inline constexpr bool str_btree_insert_key(nodetype *node, char_type const *movekeystrptr{}; ::std::size_t movekeystrn{}; - __builtin_printf("%s %d %s\n",__FILE__,__LINE__,tempkey.ptr); auto midptr{keys + keys_number_half}; auto poskeys_number_halfcmp{pos <=> keys_number_half}; if (poskeys_number_halfcmp < 0) @@ -145,18 +142,15 @@ inline constexpr bool str_btree_insert_key(nodetype *node, ++it; ::fast_io::details::non_overlapped_copy(keysit, keysed, it); } - __builtin_printf("%s %d %s node->parent=%p\n",__FILE__,__LINE__,tempkey.ptr,node->parent); ::std::size_t child_pos{node->parent_pos}; for (auto j{node->parent}; j; j = j->parent) { auto jkeys{j->keys}; auto jchildrens{j->childrens}; auto jn{j->size}; - __builtin_printf("%s %d %s j=%p\n",__FILE__,__LINE__,tempkey.ptr, j); // If parent node has space, insert the promoted key and return if (jn != keys_number) { - __builtin_printf("%s %d %s j=%p\n",__FILE__,__LINE__,tempkey.ptr, j); // Shift keys and children to make room for the promoted key and new child ::fast_io::freestanding::overlapped_copy(jkeys + child_pos, jkeys + jn, jkeys + child_pos + 1); jkeys[child_pos].ptr = movekeystrptr; @@ -174,88 +168,16 @@ inline constexpr bool str_btree_insert_key(nodetype *node, ++j->size; return true; } - __builtin_printf("%s %d %s j=%p\n",__FILE__,__LINE__,tempkey.ptr, j); // Parent is full, must split upward auto new_right = typed_allocator_type::allocate(1); - node->leaf = new_right->leaf = false; + j->leaf = new_right->leaf = false; j->size = new_right->size = keys_number_half; auto jmidptr = jkeys + keys_number_half; -#if 0 - - auto child_poskeys_number_halfcmp{child_pos <=> keys_number_half}; - // CASE 1: promoted child is in the left half (before the mid key) - if (child_poskeys_number_halfcmp < 0) - { - ::fast_io::details::non_overlapped_copy_n(jmidptr, keys_number_half, new_right->keys); - ::fast_io::freestanding::overlapped_copy(jkeys + child_pos, jmidptr, jkeys + child_pos + 1); - jkeys[child_pos].ptr = movekeystrptr; - jkeys[child_pos].n = movekeystrn; - - auto &midkey = jmidptr[-1]; - movekeystrptr = midkey.ptr; - movekeystrn = midkey.n; - - ::fast_io::details::non_overlapped_copy_n(jchildrens + keys_number_half + 1, keys_number_half, new_right->childrens); - ::fast_io::freestanding::overlapped_copy(jchildrens + child_pos + 1, jchildrens + keys_number_half + 1, jchildrens + child_pos + 2); - jchildrens[child_pos + 1] = rightchild; - - for (::std::size_t i{}; i != keys_number_half; ++i) - { - auto p = new_right->childrens[i]; - p->parent = new_right; - p->parent_pos = i; - } - } - // CASE 2: promoted child goes exactly after the mid key (replace middle) - else if (child_poskeys_number_halfcmp == 0) - { - ::fast_io::details::non_overlapped_copy_n(jmidptr + 1, keys_number_half, new_right->keys); - movekeystrptr = tempkey.ptr; - movekeystrn = tempkey.n; - - ::fast_io::details::non_overlapped_copy_n(jchildrens + keys_number_half + 1, keys_number_half, new_right->childrens); - *(new_right->childrens) = rightchild; - - for (::std::size_t i{}; i != keys_number_half + 1; ++i) - { - auto p = new_right->childrens[i]; - p->parent = new_right; - p->parent_pos = i; - } - } - // CASE 3: promoted child is in the right half (after the mid key) - else - { - auto &midkey = *jmidptr; - movekeystrptr = midkey.ptr; - movekeystrn = midkey.n; - - ::fast_io::details::non_overlapped_copy_n(jmidptr + 1, keys_number_half, new_right->keys); - auto it = ::fast_io::details::non_overlapped_copy(jmidptr + 2, jkeys + child_pos, new_right->keys); - *it = tempkey; - ++it; - ::fast_io::details::non_overlapped_copy(jkeys + child_pos, jkeys + keys_number, it); - auto itc = ::fast_io::details::non_overlapped_copy(jchildrens + keys_number_half + 2, jchildrens + child_pos + 1, new_right->childrens + 1); - *itc = rightchild; - ++itc; - ::fast_io::details::non_overlapped_copy(jchildrens + child_pos + 1, jchildrens + keys_number + 1, itc); - - for (::std::size_t i{}; i != keys_number_half + 1; ++i) - { - auto p = new_right->childrens[i]; - p->parent = new_right; - p->parent_pos = i; - } - } -#else - - __builtin_printf("%s %d %s j=%p\n",__FILE__,__LINE__,tempkey.ptr, j); auto new_right_keys{new_right->keys}; auto new_right_childrens{new_right->childrens}; auto child_poskeys_number_halfcmp{child_pos <=> keys_number_half}; - __builtin_printf("%s %d %s j=%p\n",__FILE__,__LINE__,tempkey.ptr, j); // CASE 1: promoted child is in the left half (before the mid key) if (child_poskeys_number_halfcmp < 0) { @@ -268,8 +190,8 @@ inline constexpr bool str_btree_insert_key(nodetype *node, auto &jmidkey = jmidptr[-1]; movekeystrptr = jmidkey.ptr; movekeystrn = jmidkey.n; - __builtin_printf("%s %d %s j=%p\n",__FILE__,__LINE__,tempkey.ptr, j); - ::fast_io::details::non_overlapped_copy_n(jchildrens + keys_number_half_p1, keys_number_half, new_right_childrens); +// __builtin_printf("%s %d %s j=%p\n",__FILE__,__LINE__,tempkey.ptr, j); + ::fast_io::details::non_overlapped_copy_n(jchildrens + keys_number_half, keys_number_half_p1, new_right_childrens); ::fast_io::freestanding::overlapped_copy(jchildrens + child_pos + 1, jchildrens + keys_number_half_p1, jchildrens + child_pos + 2); jchildrens[child_pos + 1] = rightchild; rightchild->parent = node; @@ -284,30 +206,29 @@ inline constexpr bool str_btree_insert_key(nodetype *node, } else if (child_poskeys_number_halfcmp == 0) { - __builtin_printf("%s %d %s j=%p\n",__FILE__,__LINE__,tempkey.ptr, j); +// __builtin_printf("%s %d %s j=%p\n",__FILE__,__LINE__,tempkey.ptr, j); ::fast_io::details::non_overlapped_copy_n(jmidptr, keys_number_half, new_right_keys); - ::fast_io::details::non_overlapped_copy_n(jchildrens + keys_number_half_p1, keys_number_half, new_right_childrens); + ::fast_io::details::non_overlapped_copy_n(jchildrens + keys_number_half_p1, keys_number_half_p1, new_right_childrens); *(new_right->childrens) = rightchild; rightchild->parent = node; - rightchild->parent_pos = child_pos + 1; + rightchild->parent_pos = 0; } else { - __builtin_printf("%s %d %s j=%p child_pos=%zu\n",__FILE__,__LINE__,tempkey.ptr, j, child_pos); - auto &jkeystrptrkeysnumber{*jmidptr}; - movekeystrptr = jkeystrptrkeysnumber.ptr; - movekeystrn = jkeystrptrkeysnumber.n; - __builtin_printf("%s %d %s j=%p child_pos=%zu\n",__FILE__,__LINE__,tempkey.ptr, j, child_pos); auto jkeysit{jkeys + child_pos}; auto jkeysed{jkeys + keys_number}; auto it{::fast_io::details::non_overlapped_copy(jmidptr + 1, jkeysit, new_right_keys)}; - __builtin_printf("%s %d %s j=%p child_pos=%zu\n",__FILE__,__LINE__,tempkey.ptr, j, child_pos); - *it = tempkey; + it->ptr = movekeystrptr; + it->n = movekeystrn; ++it; ::fast_io::details::non_overlapped_copy(jkeysit, jkeysed, it); - __builtin_printf("%s %d %s j=%p\n",__FILE__,__LINE__,tempkey.ptr, j); - auto jchildrensit{jchildrens + child_pos}; - auto jchildrensed{jchildrens + keys_number}; + + auto &jkeystrptrkeysnumber{*jmidptr}; + movekeystrptr = jkeystrptrkeysnumber.ptr; + movekeystrn = jkeystrptrkeysnumber.n; + + auto jchildrensit{jchildrens + child_pos + 1}; + auto jchildrensed{jchildrens + keys_number + 1}; auto kit{::fast_io::details::non_overlapped_copy(jchildrens + keys_number_half_p1, jchildrensit, new_right_childrens)}; *kit = rightchild; ++kit; @@ -321,11 +242,10 @@ inline constexpr bool str_btree_insert_key(nodetype *node, kref.parent = new_right; kref.parent_pos = static_cast<::std::size_t>(k-new_right_childrens); } -#endif rightchild = new_right; child_pos = j->parent_pos; + node = j; } - __builtin_printf("%s %d %s\n",__FILE__,__LINE__,tempkey.ptr); auto new_root = typed_allocator_type::allocate(1); new_root->leaf = false; new_root->size = 1; @@ -339,8 +259,8 @@ inline constexpr bool str_btree_insert_key(nodetype *node, node->parent_pos = 0; rightchild->parent = new_root; rightchild->parent_pos = 1; - *proot = new_root; + return true; } From 15f909ebe90a80b88bccf9fb4b94a3d35467bb96 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Wed, 9 Jul 2025 01:39:55 +0800 Subject: [PATCH 21/81] [btreeset] more logic for fix up --- include/fast_io_dsal/impl/str_btree_set.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/include/fast_io_dsal/impl/str_btree_set.h b/include/fast_io_dsal/impl/str_btree_set.h index 942bbd1f2..01dc54081 100644 --- a/include/fast_io_dsal/impl/str_btree_set.h +++ b/include/fast_io_dsal/impl/str_btree_set.h @@ -67,6 +67,7 @@ template inline constexpr bool str_btree_insert_key(nodetype *node, typename nodetype::char_type const *keystrptr, ::std::size_t keystrn, nodetype **proot) noexcept { + __builtin_printf("\n\n%s %d %s\n",__FILE__,__LINE__,keystrptr); using char_type = typename nodetype::char_type; using typed_allocator_type = ::fast_io::typed_generic_allocator_adapter; ::std::size_t pos; @@ -142,9 +143,12 @@ inline constexpr bool str_btree_insert_key(nodetype *node, ++it; ::fast_io::details::non_overlapped_copy(keysit, keysed, it); } + + __builtin_printf("%s %d %s\n",__FILE__,__LINE__,keystrptr); ::std::size_t child_pos{node->parent_pos}; for (auto j{node->parent}; j; j = j->parent) { + __builtin_printf("%s %d %s j=%p\n",__FILE__,__LINE__,movekeystrptr, j); auto jkeys{j->keys}; auto jchildrens{j->childrens}; auto jn{j->size}; @@ -168,6 +172,8 @@ inline constexpr bool str_btree_insert_key(nodetype *node, ++j->size; return true; } + + __builtin_printf("%s %d %s j=%p\n",__FILE__,__LINE__,movekeystrptr, j); // Parent is full, must split upward auto new_right = typed_allocator_type::allocate(1); j->leaf = new_right->leaf = false; @@ -215,6 +221,7 @@ inline constexpr bool str_btree_insert_key(nodetype *node, } else { + __builtin_printf("%s %d %s j=%p\n",__FILE__,__LINE__,movekeystrptr, j); auto jkeysit{jkeys + child_pos}; auto jkeysed{jkeys + keys_number}; auto it{::fast_io::details::non_overlapped_copy(jmidptr + 1, jkeysit, new_right_keys)}; @@ -233,7 +240,7 @@ inline constexpr bool str_btree_insert_key(nodetype *node, *kit = rightchild; ++kit; ::fast_io::details::non_overlapped_copy(jchildrensit, jchildrensed, kit); - + __builtin_printf("%s %d %s j=%p\n",__FILE__,__LINE__,movekeystrptr, j); } for (auto k{new_right_childrens},ked{new_right_childrens+keys_number_half_p1}; k != ked; ++k) @@ -246,6 +253,7 @@ inline constexpr bool str_btree_insert_key(nodetype *node, child_pos = j->parent_pos; node = j; } + __builtin_printf("%s %d %s\n",__FILE__,__LINE__,movekeystrptr); auto new_root = typed_allocator_type::allocate(1); new_root->leaf = false; new_root->size = 1; From f8287edda442482e9c6381da13469198a2355d64 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Wed, 9 Jul 2025 14:53:12 +0800 Subject: [PATCH 22/81] [BTree] Fix & missing in str_btree_set.h --- include/fast_io_dsal/impl/str_btree_set.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/fast_io_dsal/impl/str_btree_set.h b/include/fast_io_dsal/impl/str_btree_set.h index 01dc54081..5059dbb49 100644 --- a/include/fast_io_dsal/impl/str_btree_set.h +++ b/include/fast_io_dsal/impl/str_btree_set.h @@ -245,7 +245,7 @@ inline constexpr bool str_btree_insert_key(nodetype *node, for (auto k{new_right_childrens},ked{new_right_childrens+keys_number_half_p1}; k != ked; ++k) { - auto kref{**k}; + auto& kref{**k}; kref.parent = new_right; kref.parent_pos = static_cast<::std::size_t>(k-new_right_childrens); } From ad7653fc6bacf28c0ae310fe76443bfe8d53d9e7 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Wed, 9 Jul 2025 14:59:50 +0800 Subject: [PATCH 23/81] btree --- include/fast_io_dsal/impl/str_btree_set.h | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/include/fast_io_dsal/impl/str_btree_set.h b/include/fast_io_dsal/impl/str_btree_set.h index 5059dbb49..426d4aef9 100644 --- a/include/fast_io_dsal/impl/str_btree_set.h +++ b/include/fast_io_dsal/impl/str_btree_set.h @@ -67,7 +67,6 @@ template inline constexpr bool str_btree_insert_key(nodetype *node, typename nodetype::char_type const *keystrptr, ::std::size_t keystrn, nodetype **proot) noexcept { - __builtin_printf("\n\n%s %d %s\n",__FILE__,__LINE__,keystrptr); using char_type = typename nodetype::char_type; using typed_allocator_type = ::fast_io::typed_generic_allocator_adapter; ::std::size_t pos; @@ -144,11 +143,9 @@ inline constexpr bool str_btree_insert_key(nodetype *node, ::fast_io::details::non_overlapped_copy(keysit, keysed, it); } - __builtin_printf("%s %d %s\n",__FILE__,__LINE__,keystrptr); ::std::size_t child_pos{node->parent_pos}; for (auto j{node->parent}; j; j = j->parent) { - __builtin_printf("%s %d %s j=%p\n",__FILE__,__LINE__,movekeystrptr, j); auto jkeys{j->keys}; auto jchildrens{j->childrens}; auto jn{j->size}; @@ -173,7 +170,6 @@ inline constexpr bool str_btree_insert_key(nodetype *node, return true; } - __builtin_printf("%s %d %s j=%p\n",__FILE__,__LINE__,movekeystrptr, j); // Parent is full, must split upward auto new_right = typed_allocator_type::allocate(1); j->leaf = new_right->leaf = false; @@ -187,7 +183,6 @@ inline constexpr bool str_btree_insert_key(nodetype *node, // CASE 1: promoted child is in the left half (before the mid key) if (child_poskeys_number_halfcmp < 0) { - __builtin_printf("%s %d %s j=%p\n",__FILE__,__LINE__,tempkey.ptr, j); ::fast_io::details::non_overlapped_copy_n(jmidptr, keys_number_half, new_right_keys); ::fast_io::freestanding::overlapped_copy(jkeys + child_pos, jmidptr, jkeys + child_pos + 1); jkeys[child_pos].ptr = movekeystrptr; @@ -196,7 +191,6 @@ inline constexpr bool str_btree_insert_key(nodetype *node, auto &jmidkey = jmidptr[-1]; movekeystrptr = jmidkey.ptr; movekeystrn = jmidkey.n; -// __builtin_printf("%s %d %s j=%p\n",__FILE__,__LINE__,tempkey.ptr, j); ::fast_io::details::non_overlapped_copy_n(jchildrens + keys_number_half, keys_number_half_p1, new_right_childrens); ::fast_io::freestanding::overlapped_copy(jchildrens + child_pos + 1, jchildrens + keys_number_half_p1, jchildrens + child_pos + 2); jchildrens[child_pos + 1] = rightchild; @@ -212,7 +206,6 @@ inline constexpr bool str_btree_insert_key(nodetype *node, } else if (child_poskeys_number_halfcmp == 0) { -// __builtin_printf("%s %d %s j=%p\n",__FILE__,__LINE__,tempkey.ptr, j); ::fast_io::details::non_overlapped_copy_n(jmidptr, keys_number_half, new_right_keys); ::fast_io::details::non_overlapped_copy_n(jchildrens + keys_number_half_p1, keys_number_half_p1, new_right_childrens); *(new_right->childrens) = rightchild; @@ -221,7 +214,6 @@ inline constexpr bool str_btree_insert_key(nodetype *node, } else { - __builtin_printf("%s %d %s j=%p\n",__FILE__,__LINE__,movekeystrptr, j); auto jkeysit{jkeys + child_pos}; auto jkeysed{jkeys + keys_number}; auto it{::fast_io::details::non_overlapped_copy(jmidptr + 1, jkeysit, new_right_keys)}; @@ -240,7 +232,6 @@ inline constexpr bool str_btree_insert_key(nodetype *node, *kit = rightchild; ++kit; ::fast_io::details::non_overlapped_copy(jchildrensit, jchildrensed, kit); - __builtin_printf("%s %d %s j=%p\n",__FILE__,__LINE__,movekeystrptr, j); } for (auto k{new_right_childrens},ked{new_right_childrens+keys_number_half_p1}; k != ked; ++k) @@ -253,7 +244,6 @@ inline constexpr bool str_btree_insert_key(nodetype *node, child_pos = j->parent_pos; node = j; } - __builtin_printf("%s %d %s\n",__FILE__,__LINE__,movekeystrptr); auto new_root = typed_allocator_type::allocate(1); new_root->leaf = false; new_root->size = 1; From e76e82e4e54ba6b171d4d8511900ee7304d2879e Mon Sep 17 00:00:00 2001 From: trcrsired Date: Wed, 9 Jul 2025 15:39:12 +0800 Subject: [PATCH 24/81] [str_btree_set] Fix str_btree_set.h --- include/fast_io_dsal/impl/str_btree_set.h | 19 +- include/fast_io_dsal/impl/str_btree_set2.h | 495 --------------------- 2 files changed, 8 insertions(+), 506 deletions(-) delete mode 100644 include/fast_io_dsal/impl/str_btree_set2.h diff --git a/include/fast_io_dsal/impl/str_btree_set.h b/include/fast_io_dsal/impl/str_btree_set.h index 426d4aef9..1ab178112 100644 --- a/include/fast_io_dsal/impl/str_btree_set.h +++ b/include/fast_io_dsal/impl/str_btree_set.h @@ -162,9 +162,9 @@ inline constexpr bool str_btree_insert_key(nodetype *node, rightchild->parent = j; rightchild->parent_pos = child_pos + 1; - for(auto k{jchildrens+(child_pos+2)},ked{jchildrens+(jn+2)};k!=ked;++k) + for (auto k{jchildrens + (child_pos + 2)}, ked{jchildrens + (jn + 2)}; k != ked; ++k) { - (*k)->parent_pos = static_cast<::std::size_t>(k-jchildrens); + (*k)->parent_pos = static_cast<::std::size_t>(k - jchildrens); } ++j->size; return true; @@ -201,14 +201,12 @@ inline constexpr bool str_btree_insert_key(nodetype *node, { jchildrens[i]->parent_pos = i; } - - } else if (child_poskeys_number_halfcmp == 0) { ::fast_io::details::non_overlapped_copy_n(jmidptr, keys_number_half, new_right_keys); - ::fast_io::details::non_overlapped_copy_n(jchildrens + keys_number_half_p1, keys_number_half_p1, new_right_childrens); - *(new_right->childrens) = rightchild; + *new_right_childrens = rightchild; + ::fast_io::details::non_overlapped_copy_n(jchildrens + keys_number_half_p1, keys_number_half, new_right_childrens + 1); rightchild->parent = node; rightchild->parent_pos = 0; } @@ -234,11 +232,11 @@ inline constexpr bool str_btree_insert_key(nodetype *node, ::fast_io::details::non_overlapped_copy(jchildrensit, jchildrensed, kit); } - for (auto k{new_right_childrens},ked{new_right_childrens+keys_number_half_p1}; k != ked; ++k) + for (auto k{new_right_childrens}, ked{new_right_childrens + keys_number_half_p1}; k != ked; ++k) { - auto& kref{**k}; + auto &kref{**k}; kref.parent = new_right; - kref.parent_pos = static_cast<::std::size_t>(k-new_right_childrens); + kref.parent_pos = static_cast<::std::size_t>(k - new_right_childrens); } rightchild = new_right; child_pos = j->parent_pos; @@ -354,7 +352,6 @@ class basic_str_btree_set if (!node->leaf) { clear_node(node->childrens[n]); - } // **Deallocate the node using the allocator** @@ -396,4 +393,4 @@ class basic_str_btree_set } }; -} // namespace fast_io::containers \ No newline at end of file +} // namespace fast_io::containers diff --git a/include/fast_io_dsal/impl/str_btree_set2.h b/include/fast_io_dsal/impl/str_btree_set2.h deleted file mode 100644 index dd2d67bbf..000000000 --- a/include/fast_io_dsal/impl/str_btree_set2.h +++ /dev/null @@ -1,495 +0,0 @@ -#pragma once - -namespace fast_io::containers -{ - -namespace details -{ -struct btree_node_common -{ - void *root; - void *next; -}; - -template <::std::integral chtype, ::std::size_t keys_number> -struct str_btree_set_node -{ - using char_type = chtype; - ::std::size_t size; // Number of keys currently stored - bool leaf; // Indicates whether the node is a leaf - ::fast_io::details::associative_string keys[keys_number]; // Array of keys - str_btree_set_node *childrens[keys_number + 1u]; // Array of child pointers - str_btree_set_node *parent; // Pointer to parent node -}; - -template <::std::size_t keys_number> -struct -#if __has_cpp_attribute(__gnu__::__may_alias__) -[[__gnu__::__may_alias__]] -#endif -str_btree_set_common -{ - ::std::size_t size; - bool leaf; - ::fast_io::io_scatter_t keys[keys_number]; - void *childrens[keys_number + 1u]; - void *parent; -}; - -struct find_btree_node_insert_position_result -{ - ::std::size_t pos{}; - bool found{}; -}; - -template -inline constexpr find_btree_node_insert_position_result find_str_btree_node_insert_position(nodetype *node, - typename nodetype::char_type const *keystrptr, ::std::size_t keystrn) noexcept -{ - using char_type = typename nodetype::char_type; - auto *b{node->keys}, *i{b}, *e{b + node->size}; - bool found{}; - ::fast_io::basic_string_view newkey(keystrptr, keystrn); - for (; i != e; ++i) - { - auto cmpres{newkey <=> i->strvw()}; - if (cmpres <= 0) - { - found = (cmpres == 0); - break; - } - } - return {static_cast<::std::size_t>(i - b), found}; -} - -template -inline constexpr void str_btree_split_node(nodetype *node, nodetype** proot) noexcept; - -template -inline constexpr bool str_btree_insert_key(nodetype *node, - typename nodetype::char_type const *keystrptr, ::std::size_t keystrn, bool ismoved, nodetype** proot) noexcept -{ - using char_type = typename nodetype::char_type; - // **Find the correct position for insertion** - auto [pos, found] = find_str_btree_node_insert_position(node, keystrptr, keystrn); - - // **If the key already exists, return false (no duplicate keys)** - if (found) - { - return false; - } - - // **If the node is a leaf** - if (node->leaf) - { - - // **If there is space, insert the key directly** - if (node->size < keys_number) - { - for (::std::size_t j{node->size}; pos < j; --j) - { - node->keys[j] = node->keys[j - 1]; - } - ::fast_io::details::associative_string astr; - if (ismoved) - { - astr.ptr = keystrptr; - astr.n = keystrn; - } - else - { - astr = ::fast_io::details::create_associative_string(keystrptr, keystrn); - } - node->keys[pos] = astr; - ++node->size; - return true; - } - else - { - // **If the node is full, split it** - str_btree_split_node(node, proot); - return str_btree_insert_key(node->parent, keystrptr, keystrn, ismoved, proot); - } - } - else - { - // **Recursively insert into the correct child** - return str_btree_insert_key(node->childrens[pos], keystrptr, keystrn, ismoved, proot); - } -} - -template -inline constexpr void str_btree_split_node(nodetype *node, nodetype** proot) noexcept -{ - using char_type = typename nodetype::char_type; - using typed_allocator_type = ::fast_io::typed_generic_allocator_adapter; - constexpr ::std::size_t keys_number_div2{keys_number >> 1u}; - constexpr ::std::size_t keys_number_p1{keys_number + 1u}; - constexpr ::std::size_t mid{keys_number_div2}; - constexpr ::std::size_t midp1{mid + 1u}; - constexpr ::std::size_t keys_number_sub_midp1{keys_number - midp1}; - - // **Allocate a new node using the stateless allocator** - nodetype *new_node{typed_allocator_type::allocate(1)}; - - new_node->parent = node->parent; - new_node->leaf = node->leaf; - - // **Move the right half of the keys to the new node** - for (::std::size_t j{midp1}, k{}; j != keys_number; ++j, ++k) - { - new_node->keys[k] = node->keys[j]; - } - - new_node->size = keys_number_sub_midp1; - - // **Handle child pointers (if not a leaf)** - if (!node->leaf) - { - for (::std::size_t j{midp1}, k{}; j != keys_number_p1; ++j, ++k) - { - auto &ck{new_node->childrens[k]}; - ck = node->childrens[j]; - auto ckv{ck}; - if (ckv) - { - ckv->parent = new_node; - } - } - } - - node->size = mid; // **Keep only the left half in the current node** - - // **Promote the middle key to the parent node** - if (node->parent == nullptr) - { - // **Allocate a new root using the stateless allocator** - nodetype *new_root{typed_allocator_type::allocate(1)}; - *proot = new_root; - *(new_root->keys) = node->keys[mid]; - new_root->size = 1; - *(new_root->childrens) = node; - new_root->childrens[1] = new_node; - new_root->leaf = false; - new_node->parent = nullptr; - node->parent = new_root; - new_node->parent = new_root; - } - else - { - // **Insert the middle key into the parent node** - str_btree_insert_key(node->parent, node->keys[mid].ptr, node->keys[mid].n, true, proot); - node->parent->childrens[node->parent->size] = new_node; - new_node->parent = node->parent; - } -} - -template -inline constexpr bool str_btree_insert_key_with_root(nodetype **proot, - typename nodetype::char_type const *keystrptr, ::std::size_t keystrn) noexcept -{ - using typed_allocator_type = ::fast_io::typed_generic_allocator_adapter; - - auto node{*proot}; - - // **If the tree is empty, allocate a new root** - if (node == nullptr) - { - node = typed_allocator_type::allocate(1); - node->size = 1; - node->leaf = true; - node->parent = nullptr; - *(node->keys) = ::fast_io::details::create_associative_string(keystrptr, keystrn); - *proot = node; - return true; - } - return ::fast_io::containers::details::str_btree_insert_key(node, keystrptr, keystrn, false, proot); -} -#if 0 -template <::std::integral chtype, ::std::size_t keys_number> -struct str_btree_set_iterator -{ - ::fast_io::containers::str_btree_set_node* node{}; - ::std::size_t pos{}; - constexpr str_btree_set_iterator& operator++() noexcept - { - if (node == nullptr) - return *this; - - // **If there are more keys in the current node, move right** - if (pos + 1 < node->size) - { - ++pos; - return *this; - } - - // **If there is a right child, move to the smallest key in the right subtree** - if (!node->leaf) - { - node = node->childrens[pos + 1]; - while (!node->leaf) - node = node->childrens[0]; - pos = 0; - return *this; - } - - // **Otherwise, move up until we find a larger key** - while (node->parent && node == node->parent->childrens[node->parent->size]) - node = node->parent; - - if (node->parent) - { - pos = 0; - node = node->parent; - } - else - { - node = nullptr; // **End of iteration** - } - } -#if 0 - constexpr str_btree_set_iterator& operator--() noexcept - { - - } -#endif - constexpr ::fast_io::containers::basic_cstring_view operator*() const noexcept - { - auto &def{this->node->keys[this->pos]}; - return def.strvw(); - } -}; - -template <::std::integral chtype, ::std::size_t keys_number> -inline constexpr bool operator==(::fast_io::containers::details::str_btree_set_iterator a, - ::fast_io::containers::details::str_btree_set_iterator b) -{ - return a.node == b.node && a.pos == b.pos; -} - -template <::std::integral chtype, ::std::size_t keys_number> -inline constexpr bool operator!=(::fast_io::containers::details::str_btree_set_iterator a, - ::fast_io::containers::details::str_btree_set_iterator b) -{ - return !(a==b); -} -#endif - -template <::std::integral chtype, ::std::size_t keys_number, bool isrev> -struct str_btree_set_iterator -{ - using char_type = chtype; - using value_type = char_type; - using cstring_view_type = ::fast_io::basic_cstring_view; - using const_iterator = ::fast_io::containers::details::str_btree_set_iterator; - using iterator = const_iterator; - ::fast_io::containers::details::str_btree_set_node *ptr{}; - inline constexpr const_iterator operator++() noexcept - { - return {}; - } - inline constexpr const_iterator operator++(int) noexcept - { - auto tmp{*this}; - ++*this; - return tmp; - } -}; - -template <::std::integral chtype, ::std::size_t keys_number, bool isrev> -inline constexpr bool operator==(::fast_io::containers::details::str_btree_set_iterator a, - ::fast_io::containers::details::str_btree_set_iterator b) noexcept -{ - return a.ptr == b.ptr; -} - -template <::std::integral chtype, ::std::size_t keys_number, bool isrev> -inline constexpr bool operator!=(::fast_io::containers::details::str_btree_set_iterator a, - ::fast_io::containers::details::str_btree_set_iterator b) noexcept -{ - return a.ptr != b.ptr; -} - -template <::std::integral chtype, ::std::size_t keys_number, bool isrev> -inline constexpr bool operator==(::fast_io::containers::details::str_btree_set_iterator a, - ::std::default_sentinel_t) noexcept -{ - return a.ptr == nullptr; -} - -template <::std::integral chtype, ::std::size_t keys_number, bool isrev> -inline constexpr bool operator==(::std::default_sentinel_t, - ::fast_io::containers::details::str_btree_set_iterator a) noexcept -{ - return a.ptr == nullptr; -} - - -template <::std::integral chtype, ::std::size_t keys_number, bool isrev> -inline constexpr bool operator!=(::fast_io::containers::details::str_btree_set_iterator a, - ::std::default_sentinel_t) noexcept -{ - return a.ptr != nullptr; -} - -template <::std::integral chtype, ::std::size_t keys_number, bool isrev> -inline constexpr bool operator!=(::std::default_sentinel_t, - ::fast_io::containers::details::str_btree_set_iterator a) noexcept -{ - return a.ptr != nullptr; -} - -template <::std::integral chtype, ::std::size_t keys_number, bool isrev> -struct str_btree_set_iters_type -{ - using char_type = chtype; - using value_type = char_type; - using cstring_view_type = ::fast_io::basic_cstring_view; - using const_iterator = ::fast_io::containers::details::str_btree_set_iterator; - using iterator = const_iterator; - const_iterator i; - constexpr const_iterator cbegin() const noexcept - { - return i; - } - constexpr ::std::default_sentinel_t cend() const noexcept - { - return {}; - } - constexpr const_iterator begin() const noexcept - { - return i; - } - constexpr ::std::default_sentinel_t end() const noexcept - { - return {}; - } -}; - -} // namespace details - -template <::std::integral chtype, typename Allocator, ::std::size_t keys_number = 63> -class basic_str_btree_set -{ - using node_type = ::fast_io::containers::details::str_btree_set_node; - using untyped_allocator_type = Allocator; - using typed_allocator_type = ::fast_io::typed_generic_allocator_adapter; - -public: - using char_type = chtype; - using string_view_type = ::fast_io::basic_string_view; - using cstring_view_type = ::fast_io::basic_cstring_view; - using allocator_type = Allocator; - using const_iters_type = ::fast_io::containers::details::str_btree_set_iters_type; - using const_reverse_iters_type = ::fast_io::containers::details::str_btree_set_iters_type; -#if 0 - using const_iterator = ::fast_io::details::str_btree_set_iterator; - using iterator = ::fast_io::details::str_btree_set_iterator; - ::fast_io::containers::details::btree_node_common root; -#endif - node_type *root{}; - - constexpr basic_str_btree_set() noexcept = default; - - explicit constexpr basic_str_btree_set(::std::initializer_list ilist) noexcept - { - for (auto const &e : ilist) - { - this->insert_key(e); - } - } - - constexpr bool contains(string_view_type) const noexcept - { - return false; - } - constexpr bool is_empty() const noexcept - { - return false; - } - constexpr bool erase_key(string_view_type) noexcept - { - return false; - } - constexpr bool insert_key(string_view_type strvw) noexcept - { - return ::fast_io::containers::details::str_btree_insert_key_with_root(__builtin_addressof(this->root), strvw.data(), strvw.size()); - } - -private: - static inline constexpr void clear_node(node_type *node) noexcept - { - if (node == nullptr) - { - return; - } - ::std::size_t const n{node->size}; - for (::std::size_t i{}; i != n; ++i) - { - if (!node->leaf) - { - clear_node(node->childrens[i]); - } -#if 0 - ::fast_io::io::debug_println(::fast_io::mnp::pointervw(node), - i, " ", ::fast_io::mnp::pointervw(node->keys + i), " ", node->keys[i].strvw()); -#endif - auto ki{node->keys[i]}; - ::fast_io::typed_generic_allocator_adapter::deallocate_n(const_cast(ki.ptr), - static_cast<::std::size_t>(ki.n + 1u)); - } -#if 0 - if (!node->leaf) - { - clear_node(node->childrens[n]); - - auto ki{node->childrens[node->size]}; - ::fast_io::typed_generic_allocator_adapter::deallocate_n(, - static_cast<::std::size_t>(ki.n+1u)); - } -#endif - - // **Deallocate the node using the allocator** - typed_allocator_type::deallocate_n(node, 1); - } - -public: - constexpr void clear() noexcept - { - clear_node(this->root); - this->root = nullptr; - } - - constexpr void clear_destroy() noexcept - { - this->clear(); - } - - constexpr basic_str_btree_set(basic_str_btree_set const &) noexcept = delete; - constexpr basic_str_btree_set &operator=(basic_str_btree_set const &) noexcept = delete; - - constexpr basic_str_btree_set(basic_str_btree_set &&other) noexcept : root{other.root} - { - other.root = nullptr; - } - constexpr basic_str_btree_set &operator=(basic_str_btree_set &&other) noexcept - { - if (::std::addressof(other) == this) - { - return *this; - } - this->root = other.root; - other.root = nullptr; - return *this; - } - constexpr ~basic_str_btree_set() - { - clear_node(this->root); - } -#if 0 - constexpr citers() const noexcept - {} -#endif -}; - -} // namespace fast_io::containers \ No newline at end of file From 0b77c15678d76b30a30426d23683504695361e2b Mon Sep 17 00:00:00 2001 From: trcrsired Date: Wed, 9 Jul 2025 15:49:51 +0800 Subject: [PATCH 25/81] [str_btree_set] Some changes to fuzz the code --- include/fast_io_dsal/impl/str_btree_set.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/fast_io_dsal/impl/str_btree_set.h b/include/fast_io_dsal/impl/str_btree_set.h index 1ab178112..a05b2de32 100644 --- a/include/fast_io_dsal/impl/str_btree_set.h +++ b/include/fast_io_dsal/impl/str_btree_set.h @@ -207,8 +207,6 @@ inline constexpr bool str_btree_insert_key(nodetype *node, ::fast_io::details::non_overlapped_copy_n(jmidptr, keys_number_half, new_right_keys); *new_right_childrens = rightchild; ::fast_io::details::non_overlapped_copy_n(jchildrens + keys_number_half_p1, keys_number_half, new_right_childrens + 1); - rightchild->parent = node; - rightchild->parent_pos = 0; } else { From 1fe6f4414e021036025f525fe83e79b54b7d367d Mon Sep 17 00:00:00 2001 From: trcrsired Date: Wed, 9 Jul 2025 15:59:31 +0800 Subject: [PATCH 26/81] [btree] Fix btree --- include/fast_io_dsal/impl/associative_string.h | 6 +++--- include/fast_io_dsal/impl/str_btree_set.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/fast_io_dsal/impl/associative_string.h b/include/fast_io_dsal/impl/associative_string.h index 6e1e751c5..ac0aa3bd7 100644 --- a/include/fast_io_dsal/impl/associative_string.h +++ b/include/fast_io_dsal/impl/associative_string.h @@ -12,9 +12,9 @@ struct associative_string using size_type = ::std::size_t; char_type const *ptr; size_type n; - constexpr ::fast_io::basic_string_view strvw() const noexcept + constexpr ::fast_io::containers::basic_string_view strvw() const noexcept { - return ::fast_io::basic_string_view(ptr, n); + return ::fast_io::containers::basic_string_view(ptr, n); } }; @@ -32,4 +32,4 @@ inline constexpr ::fast_io::details::associative_string create_associ return {newp, n}; } -} // namespace fast_io::details \ No newline at end of file +} // namespace fast_io::details diff --git a/include/fast_io_dsal/impl/str_btree_set.h b/include/fast_io_dsal/impl/str_btree_set.h index a05b2de32..bdbe27132 100644 --- a/include/fast_io_dsal/impl/str_btree_set.h +++ b/include/fast_io_dsal/impl/str_btree_set.h @@ -50,7 +50,7 @@ inline constexpr find_btree_node_insert_position_result find_str_btree_node_inse using char_type = typename nodetype::char_type; auto *b{node->keys}, *i{b}, *e{b + node->size}; bool found{}; - ::fast_io::basic_string_view newkey(keystrptr, keystrn); + ::fast_io::containers::basic_string_view newkey(keystrptr, keystrn); for (; i != e; ++i) { auto cmpres{newkey <=> i->strvw()}; @@ -292,8 +292,8 @@ class basic_str_btree_set public: using char_type = chtype; - using string_view_type = ::fast_io::basic_string_view; - using cstring_view_type = ::fast_io::basic_cstring_view; + using string_view_type = ::fast_io::containers::basic_string_view; + using cstring_view_type = ::fast_io::containers::basic_cstring_view; using allocator_type = Allocator; node_type *root{}; From 1329622ce998d0b466ae3fc6efa2f09a8f8ab09e Mon Sep 17 00:00:00 2001 From: trcrsired Date: Wed, 9 Jul 2025 16:00:53 +0800 Subject: [PATCH 27/81] [btree] add fuzzing to debug the code --- fuzzing/0007.containers/btree/str_btree_set.cc | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 fuzzing/0007.containers/btree/str_btree_set.cc diff --git a/fuzzing/0007.containers/btree/str_btree_set.cc b/fuzzing/0007.containers/btree/str_btree_set.cc new file mode 100644 index 000000000..fbb9b37c6 --- /dev/null +++ b/fuzzing/0007.containers/btree/str_btree_set.cc @@ -0,0 +1,18 @@ +#include +#include +#include +#include + +thread_local ::fast_io::containers::basic_str_btree_set bset; +thread_local ::std::size_t n{}; + +extern "C" int LLVMFuzzerTestOneInput(::std::uint8_t *data, ::std::size_t size) +{ + if(n==100000) + { + bset.clear_destroy(); + } + bset.insert_key(::fast_io::string_view(reinterpret_cast(data),size)); + ++n; + return 0; +} \ No newline at end of file From 89a8d5f30f935e433748fc258d08a182e2211205 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Fri, 11 Jul 2025 15:23:52 +0800 Subject: [PATCH 28/81] rd --- .../0013.str_btree_set/str_btree_set_rd.cc | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 tests/0026.container/0013.str_btree_set/str_btree_set_rd.cc diff --git a/tests/0026.container/0013.str_btree_set/str_btree_set_rd.cc b/tests/0026.container/0013.str_btree_set/str_btree_set_rd.cc new file mode 100644 index 000000000..3c4fc55ef --- /dev/null +++ b/tests/0026.container/0013.str_btree_set/str_btree_set_rd.cc @@ -0,0 +1,85 @@ +#include +#include +#include +#include + +template <::std::integral chtype, ::std::size_t keys_number> +inline constexpr void str_btree_set_inorder_traverse( + ::fast_io::containers::details::str_btree_set_node *node, + auto &&callback) noexcept +{ + if (node == nullptr) + { + return; + } + + // **Traverse left subtree** + for (::std::size_t i{}; i != node->size; ++i) + { + if (!node->leaf) + { + str_btree_set_inorder_traverse(node->childrens[i], callback); + } + + // **Visit current key** + callback(node->keys[i].strvw()); + } + + // **Traverse rightmost subtree** + if (!node->leaf) + { + str_btree_set_inorder_traverse(node->childrens[node->size], callback); + } +} + +int main() +{ + ::fast_io::containers::basic_str_btree_set bset; + bset.insert_key("kiwi"); + bset.insert_key("ugli"); + bset.insert_key("lemon"); + bset.insert_key("fig"); + bset.insert_key("zucchini"); + bset.insert_key("honeydew"); + bset.insert_key("raspberry"); + bset.insert_key("orange"); + bset.insert_key("vanilla"); + bset.insert_key("yellowfruit"); + bset.insert_key("date"); + bset.insert_key("grape"); + bset.insert_key("strawberry"); + + ::fast_io::io::println(::std::source_location::current()); + str_btree_set_inorder_traverse(bset.root, [](::fast_io::string_view v) { + ::fast_io::io::println(v); + }); + ::fast_io::io::print("\n\n"); + bset.insert_key("cherry"); + bset.insert_key("quince"); + bset.insert_key("apple"); + bset.insert_key("elderberry"); + bset.insert_key("banana"); + + ::fast_io::io::println(::std::source_location::current()); + str_btree_set_inorder_traverse(bset.root, [](::fast_io::string_view v) { + ::fast_io::io::println(v); + }); + ::fast_io::io::print("\n\n"); + + bset.insert_key("nectarine"); + ::fast_io::io::println(::std::source_location::current()); + str_btree_set_inorder_traverse(bset.root, [](::fast_io::string_view v) { + ::fast_io::io::println(v); + }); + ::fast_io::io::print("\n\n"); + bset.insert_key("watermelon"); + bset.insert_key("xigua"); + bset.insert_key("papaya"); + bset.insert_key("mango"); + + ::fast_io::io::println(::std::source_location::current()); + str_btree_set_inorder_traverse(bset.root, [](::fast_io::string_view v) { + ::fast_io::io::println(v); + }); + ::fast_io::io::print("\n\n"); +} From b05a40b55facb07d7808e1f8edb1b2a4554b07e1 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Fri, 11 Jul 2025 21:03:06 +0800 Subject: [PATCH 29/81] fix bug in str_bree_set --- include/fast_io_dsal/impl/str_btree_set.h | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/include/fast_io_dsal/impl/str_btree_set.h b/include/fast_io_dsal/impl/str_btree_set.h index bdbe27132..355ed4692 100644 --- a/include/fast_io_dsal/impl/str_btree_set.h +++ b/include/fast_io_dsal/impl/str_btree_set.h @@ -111,7 +111,6 @@ inline constexpr bool str_btree_insert_key(nodetype *node, auto rightchildkeys{rightchild->keys}; // auto rightchildchildrens{rightchild->childrens}; - char_type const *movekeystrptr{}; ::std::size_t movekeystrn{}; @@ -119,11 +118,12 @@ inline constexpr bool str_btree_insert_key(nodetype *node, auto poskeys_number_halfcmp{pos <=> keys_number_half}; if (poskeys_number_halfcmp < 0) { - ::fast_io::details::non_overlapped_copy_n(midptr, keys_number_half, rightchildkeys); - ::fast_io::freestanding::overlapped_copy(keys + pos, keys + keys_number_half, keys + pos + 1); auto &keystrptrkeysnumber{midptr[-1]}; movekeystrptr = keystrptrkeysnumber.ptr; movekeystrn = keystrptrkeysnumber.n; + ::fast_io::details::non_overlapped_copy_n(midptr, keys_number_half, rightchildkeys); + ::fast_io::freestanding::overlapped_copy(keys + pos, keys + keys_number_half, keys + pos + 1); + keys[pos] = tempkey; } else if (poskeys_number_halfcmp == 0) @@ -156,7 +156,6 @@ inline constexpr bool str_btree_insert_key(nodetype *node, ::fast_io::freestanding::overlapped_copy(jkeys + child_pos, jkeys + jn, jkeys + child_pos + 1); jkeys[child_pos].ptr = movekeystrptr; jkeys[child_pos].n = movekeystrn; - ::fast_io::freestanding::overlapped_copy(jchildrens + child_pos + 1, jchildrens + jn + 1, jchildrens + child_pos + 2); jchildrens[child_pos + 1] = rightchild; rightchild->parent = j; @@ -169,7 +168,6 @@ inline constexpr bool str_btree_insert_key(nodetype *node, ++j->size; return true; } - // Parent is full, must split upward auto new_right = typed_allocator_type::allocate(1); j->leaf = new_right->leaf = false; @@ -339,10 +337,6 @@ class basic_str_btree_set { clear_node(node->childrens[i]); } -#if 0 - ::fast_io::io::debug_println(::fast_io::mnp::pointervw(node), - i, " ", ::fast_io::mnp::pointervw(node->keys + i), " ", node->keys[i].strvw()); -#endif auto ki{node->keys[i]}; ::fast_io::typed_generic_allocator_adapter::deallocate_n(const_cast(ki.ptr), static_cast<::std::size_t>(ki.n + 1u)); From 726336380e9eecb38c17d68b981406cfc08ae761 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Sat, 12 Jul 2025 01:50:43 +0800 Subject: [PATCH 30/81] fix branch in str_btree_set.h --- include/fast_io_dsal/impl/str_btree_set.h | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/include/fast_io_dsal/impl/str_btree_set.h b/include/fast_io_dsal/impl/str_btree_set.h index 355ed4692..5a43df219 100644 --- a/include/fast_io_dsal/impl/str_btree_set.h +++ b/include/fast_io_dsal/impl/str_btree_set.h @@ -181,14 +181,19 @@ inline constexpr bool str_btree_insert_key(nodetype *node, // CASE 1: promoted child is in the left half (before the mid key) if (child_poskeys_number_halfcmp < 0) { + + auto &jmidkey = jmidptr[-1]; + auto tmpptr{jmidkey.ptr}; + auto tmpn{jmidkey.n}; + ::fast_io::details::non_overlapped_copy_n(jmidptr, keys_number_half, new_right_keys); ::fast_io::freestanding::overlapped_copy(jkeys + child_pos, jmidptr, jkeys + child_pos + 1); - jkeys[child_pos].ptr = movekeystrptr; - jkeys[child_pos].n = movekeystrn; + auto &jkeyschildpos{jkeys[child_pos]}; + jkeyschildpos.ptr = movekeystrptr; + jkeyschildpos.n = movekeystrn; + movekeystrptr = tmpptr; + movekeystrn = tmpn; - auto &jmidkey = jmidptr[-1]; - movekeystrptr = jmidkey.ptr; - movekeystrn = jmidkey.n; ::fast_io::details::non_overlapped_copy_n(jchildrens + keys_number_half, keys_number_half_p1, new_right_childrens); ::fast_io::freestanding::overlapped_copy(jchildrens + child_pos + 1, jchildrens + keys_number_half_p1, jchildrens + child_pos + 2); jchildrens[child_pos + 1] = rightchild; @@ -208,6 +213,8 @@ inline constexpr bool str_btree_insert_key(nodetype *node, } else { + + ::fast_io::io::debug_println(::std::source_location::current()); auto jkeysit{jkeys + child_pos}; auto jkeysed{jkeys + keys_number}; auto it{::fast_io::details::non_overlapped_copy(jmidptr + 1, jkeysit, new_right_keys)}; @@ -345,7 +352,6 @@ class basic_str_btree_set { clear_node(node->childrens[n]); } - // **Deallocate the node using the allocator** typed_allocator_type::deallocate_n(node, 1); } From ea31a40884aff76b031fc55fbbd2b6844fcb94d0 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Sat, 12 Jul 2025 01:53:18 +0800 Subject: [PATCH 31/81] fix str_btree_set --- include/fast_io_dsal/impl/str_btree_set.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/fast_io_dsal/impl/str_btree_set.h b/include/fast_io_dsal/impl/str_btree_set.h index 5a43df219..354b074ee 100644 --- a/include/fast_io_dsal/impl/str_btree_set.h +++ b/include/fast_io_dsal/impl/str_btree_set.h @@ -213,8 +213,6 @@ inline constexpr bool str_btree_insert_key(nodetype *node, } else { - - ::fast_io::io::debug_println(::std::source_location::current()); auto jkeysit{jkeys + child_pos}; auto jkeysed{jkeys + keys_number}; auto it{::fast_io::details::non_overlapped_copy(jmidptr + 1, jkeysit, new_right_keys)}; From 274ae08121e5cfd3882682de23a631fac887d127 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Sat, 12 Jul 2025 01:55:16 +0800 Subject: [PATCH 32/81] update test --- .../str_btree_set_reverse.cc | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 tests/0026.container/0013.str_btree_set/str_btree_set_reverse.cc diff --git a/tests/0026.container/0013.str_btree_set/str_btree_set_reverse.cc b/tests/0026.container/0013.str_btree_set/str_btree_set_reverse.cc new file mode 100644 index 000000000..c5e17abfd --- /dev/null +++ b/tests/0026.container/0013.str_btree_set/str_btree_set_reverse.cc @@ -0,0 +1,74 @@ +#include +#include +#include +#include + +template <::std::integral chtype, ::std::size_t keys_number> +inline constexpr void str_btree_set_inorder_traverse( + ::fast_io::containers::details::str_btree_set_node *node, + auto &&callback) noexcept +{ + if (node == nullptr) + { + return; + } + + // **Traverse left subtree** + for (::std::size_t i{}; i != node->size; ++i) + { + if (!node->leaf) + { + str_btree_set_inorder_traverse(node->childrens[i], callback); + } + + // **Visit current key** + callback(node->keys[i].strvw()); + } + + // **Traverse rightmost subtree** + if (!node->leaf) + { + str_btree_set_inorder_traverse(node->childrens[node->size], callback); + } +} + +int main() +{ + ::fast_io::containers::basic_str_btree_set bset; + constexpr + ::fast_io::string_view fruits[]{ + ::fast_io::string_view("zucchini"), + ::fast_io::string_view("yellowfruit"), + ::fast_io::string_view("xigua"), + ::fast_io::string_view("watermelon"), + ::fast_io::string_view("vanilla"), + ::fast_io::string_view("ugli"), + ::fast_io::string_view("tangerine"), + ::fast_io::string_view("strawberry"), + ::fast_io::string_view("raspberry"), + ::fast_io::string_view("quince"), + ::fast_io::string_view("papaya"), + ::fast_io::string_view("orange"), + ::fast_io::string_view("nectarine"), + ::fast_io::string_view("mango"), + ::fast_io::string_view("lemon"), + ::fast_io::string_view("kiwi"), + ::fast_io::string_view("grape"), + ::fast_io::string_view("fig"), + ::fast_io::string_view("elderberry"), + ::fast_io::string_view("date"), + ::fast_io::string_view("cherry"), + ::fast_io::string_view("banana"), + ::fast_io::string_view("apple"), + ::fast_io::string_view("honeydew") +}; + + for(auto const & e : fruits) + { + bset.insert_key(e); + } + + str_btree_set_inorder_traverse(bset.root, [](::fast_io::string_view v) { + ::fast_io::io::println(v); + }); +} From 2eeda2fb2a54f44f60bd1bf128e1a06493d26a6f Mon Sep 17 00:00:00 2001 From: trcrsired Date: Sat, 12 Jul 2025 01:55:47 +0800 Subject: [PATCH 33/81] clang-format for str_btree_set_reverse.cc --- .../str_btree_set_reverse.cc | 54 +++++++++---------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/tests/0026.container/0013.str_btree_set/str_btree_set_reverse.cc b/tests/0026.container/0013.str_btree_set/str_btree_set_reverse.cc index c5e17abfd..a591f1c28 100644 --- a/tests/0026.container/0013.str_btree_set/str_btree_set_reverse.cc +++ b/tests/0026.container/0013.str_btree_set/str_btree_set_reverse.cc @@ -35,35 +35,33 @@ inline constexpr void str_btree_set_inorder_traverse( int main() { ::fast_io::containers::basic_str_btree_set bset; - constexpr - ::fast_io::string_view fruits[]{ - ::fast_io::string_view("zucchini"), - ::fast_io::string_view("yellowfruit"), - ::fast_io::string_view("xigua"), - ::fast_io::string_view("watermelon"), - ::fast_io::string_view("vanilla"), - ::fast_io::string_view("ugli"), - ::fast_io::string_view("tangerine"), - ::fast_io::string_view("strawberry"), - ::fast_io::string_view("raspberry"), - ::fast_io::string_view("quince"), - ::fast_io::string_view("papaya"), - ::fast_io::string_view("orange"), - ::fast_io::string_view("nectarine"), - ::fast_io::string_view("mango"), - ::fast_io::string_view("lemon"), - ::fast_io::string_view("kiwi"), - ::fast_io::string_view("grape"), - ::fast_io::string_view("fig"), - ::fast_io::string_view("elderberry"), - ::fast_io::string_view("date"), - ::fast_io::string_view("cherry"), - ::fast_io::string_view("banana"), - ::fast_io::string_view("apple"), - ::fast_io::string_view("honeydew") -}; + constexpr ::fast_io::string_view fruits[]{ + ::fast_io::string_view("zucchini"), + ::fast_io::string_view("yellowfruit"), + ::fast_io::string_view("xigua"), + ::fast_io::string_view("watermelon"), + ::fast_io::string_view("vanilla"), + ::fast_io::string_view("ugli"), + ::fast_io::string_view("tangerine"), + ::fast_io::string_view("strawberry"), + ::fast_io::string_view("raspberry"), + ::fast_io::string_view("quince"), + ::fast_io::string_view("papaya"), + ::fast_io::string_view("orange"), + ::fast_io::string_view("nectarine"), + ::fast_io::string_view("mango"), + ::fast_io::string_view("lemon"), + ::fast_io::string_view("kiwi"), + ::fast_io::string_view("grape"), + ::fast_io::string_view("fig"), + ::fast_io::string_view("elderberry"), + ::fast_io::string_view("date"), + ::fast_io::string_view("cherry"), + ::fast_io::string_view("banana"), + ::fast_io::string_view("apple"), + ::fast_io::string_view("honeydew")}; - for(auto const & e : fruits) + for (auto const &e : fruits) { bset.insert_key(e); } From 9cba1405ddaec394978e829f7ba7059afa3aec29 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Sat, 12 Jul 2025 02:10:03 +0800 Subject: [PATCH 34/81] str_btree_set --- fuzzing/0007.containers/btree/str_btree_set.cc | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/fuzzing/0007.containers/btree/str_btree_set.cc b/fuzzing/0007.containers/btree/str_btree_set.cc index fbb9b37c6..fc3bbf638 100644 --- a/fuzzing/0007.containers/btree/str_btree_set.cc +++ b/fuzzing/0007.containers/btree/str_btree_set.cc @@ -8,11 +8,12 @@ thread_local ::std::size_t n{}; extern "C" int LLVMFuzzerTestOneInput(::std::uint8_t *data, ::std::size_t size) { - if(n==100000) - { - bset.clear_destroy(); - } - bset.insert_key(::fast_io::string_view(reinterpret_cast(data),size)); - ++n; - return 0; + if (n == 100000) + { + bset.clear_destroy(); + n = 0; + } + bset.insert_key(::fast_io::string_view(reinterpret_cast(data), size)); + ++n; + return 0; } \ No newline at end of file From c389fda3c8aea2865839cc1a9d4b3afe16fc02be Mon Sep 17 00:00:00 2001 From: trcrsired Date: Sat, 12 Jul 2025 04:19:28 +0800 Subject: [PATCH 35/81] add a test for str_btree_set_input --- .../0013.str_btree_set/name.txt | 36 ++++++++++++++ .../0013.str_btree_set/str_btree_set_input.cc | 49 +++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 tests/0026.container/0013.str_btree_set/name.txt create mode 100644 tests/0026.container/0013.str_btree_set/str_btree_set_input.cc diff --git a/tests/0026.container/0013.str_btree_set/name.txt b/tests/0026.container/0013.str_btree_set/name.txt new file mode 100644 index 000000000..8d103d09d --- /dev/null +++ b/tests/0026.container/0013.str_btree_set/name.txt @@ -0,0 +1,36 @@ +eittusgab +hoesruteanar +rcowha +mihsoiiydd +ietdyahrr +tnieume +rtsisih +cfanemclwiae +lnycaaerwahn +oswceoresie +aoanooftoae +aeieoeeehtn +ybhehgiftueu +ornsfdh +ritdhtidus +ecaepsow +eepdernchser +ybnebwdot +scgiiaewetal +avrtdao +bteelusirla +cptttet +duaslaeda +itosdaeto +sassmfatmter +moehonoblue +ttdlscea +anttoa +osrewcao +nyndeesdrst +rhtrseluj +hemaotd +fsowddw +iyasflneczi +egouwbvh + diff --git a/tests/0026.container/0013.str_btree_set/str_btree_set_input.cc b/tests/0026.container/0013.str_btree_set/str_btree_set_input.cc new file mode 100644 index 000000000..98bb87b88 --- /dev/null +++ b/tests/0026.container/0013.str_btree_set/str_btree_set_input.cc @@ -0,0 +1,49 @@ +#include +#include +#include +#include +#include +#include + +template <::std::integral chtype, ::std::size_t keys_number> +inline constexpr void str_btree_set_inorder_traverse( + ::fast_io::containers::details::str_btree_set_node *node, + auto &&callback) noexcept +{ + if (node == nullptr) + { + return; + } + + // **Traverse left subtree** + for (::std::size_t i{}; i != node->size; ++i) + { + if (!node->leaf) + { + str_btree_set_inorder_traverse(node->childrens[i], callback); + } + + // **Visit current key** + callback(node->keys[i].strvw()); + } + + // **Traverse rightmost subtree** + if (!node->leaf) + { + str_btree_set_inorder_traverse(node->childrens[node->size], callback); + } +} + +int main() +{ + ::fast_io::containers::basic_str_btree_set bset; + ::fast_io::ibuf_file ibf("name.txt"); + for(::fast_io::string str; scan(ibf, str);) + { + bset.insert_key(::fast_io::mnp::os_c_str(str)); + }; + + str_btree_set_inorder_traverse(bset.root, [](::fast_io::string_view v) { + ::fast_io::io::println(v); + }); +} From d07206fc26399c1c9f48c055196079ad5abedafd Mon Sep 17 00:00:00 2001 From: trcrsired Date: Sat, 12 Jul 2025 18:11:26 +0800 Subject: [PATCH 36/81] [btree] fix one more bug here --- include/fast_io_dsal/impl/str_btree_set.h | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/include/fast_io_dsal/impl/str_btree_set.h b/include/fast_io_dsal/impl/str_btree_set.h index 354b074ee..077281bbc 100644 --- a/include/fast_io_dsal/impl/str_btree_set.h +++ b/include/fast_io_dsal/impl/str_btree_set.h @@ -96,7 +96,7 @@ inline constexpr bool str_btree_insert_key(nodetype *node, // **If there is space, insert the key directly** if (n != keys_number) { - ::fast_io::freestanding::overlapped_copy(keysit, keysed, keysit + 1); + ::fast_io::freestanding::overlapped_copy(keysit, keys + n, keysit + 1); *keysit = tempkey; ++node->size; return true; @@ -113,14 +113,15 @@ inline constexpr bool str_btree_insert_key(nodetype *node, // auto rightchildchildrens{rightchild->childrens}; char_type const *movekeystrptr{}; ::std::size_t movekeystrn{}; - auto midptr{keys + keys_number_half}; auto poskeys_number_halfcmp{pos <=> keys_number_half}; + if (poskeys_number_halfcmp < 0) { auto &keystrptrkeysnumber{midptr[-1]}; movekeystrptr = keystrptrkeysnumber.ptr; movekeystrn = keystrptrkeysnumber.n; + ::fast_io::details::non_overlapped_copy_n(midptr, keys_number_half, rightchildkeys); ::fast_io::freestanding::overlapped_copy(keys + pos, keys + keys_number_half, keys + pos + 1); @@ -142,20 +143,21 @@ inline constexpr bool str_btree_insert_key(nodetype *node, ++it; ::fast_io::details::non_overlapped_copy(keysit, keysed, it); } - ::std::size_t child_pos{node->parent_pos}; for (auto j{node->parent}; j; j = j->parent) { auto jkeys{j->keys}; auto jchildrens{j->childrens}; auto jn{j->size}; + // If parent node has space, insert the promoted key and return if (jn != keys_number) { // Shift keys and children to make room for the promoted key and new child ::fast_io::freestanding::overlapped_copy(jkeys + child_pos, jkeys + jn, jkeys + child_pos + 1); - jkeys[child_pos].ptr = movekeystrptr; - jkeys[child_pos].n = movekeystrn; + auto &jkeyschildpos{jkeys[child_pos]}; + jkeyschildpos.ptr = movekeystrptr; + jkeyschildpos.n = movekeystrn; ::fast_io::freestanding::overlapped_copy(jchildrens + child_pos + 1, jchildrens + jn + 1, jchildrens + child_pos + 2); jchildrens[child_pos + 1] = rightchild; rightchild->parent = j; @@ -166,6 +168,7 @@ inline constexpr bool str_btree_insert_key(nodetype *node, (*k)->parent_pos = static_cast<::std::size_t>(k - jchildrens); } ++j->size; + return true; } // Parent is full, must split upward @@ -197,7 +200,7 @@ inline constexpr bool str_btree_insert_key(nodetype *node, ::fast_io::details::non_overlapped_copy_n(jchildrens + keys_number_half, keys_number_half_p1, new_right_childrens); ::fast_io::freestanding::overlapped_copy(jchildrens + child_pos + 1, jchildrens + keys_number_half_p1, jchildrens + child_pos + 2); jchildrens[child_pos + 1] = rightchild; - rightchild->parent = node; + rightchild->parent = j; rightchild->parent_pos = child_pos + 1; for (::std::size_t i{child_pos + 2}; i != keys_number_half_p1; ++i) From 47fadd94b38900a88405b6ef58db5c7a07279377 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Sat, 12 Jul 2025 18:31:20 +0800 Subject: [PATCH 37/81] [str_btree_set] add fast_io_dsal/str_btree_set.h --- .../0007.containers/btree/str_btree_set.cc | 6 +- include/fast_io_dsal/str_btree_set.h | 79 +++++++++++++++++++ 2 files changed, 81 insertions(+), 4 deletions(-) create mode 100644 include/fast_io_dsal/str_btree_set.h diff --git a/fuzzing/0007.containers/btree/str_btree_set.cc b/fuzzing/0007.containers/btree/str_btree_set.cc index fc3bbf638..4da4e2e43 100644 --- a/fuzzing/0007.containers/btree/str_btree_set.cc +++ b/fuzzing/0007.containers/btree/str_btree_set.cc @@ -1,7 +1,5 @@ #include -#include -#include -#include +#include thread_local ::fast_io::containers::basic_str_btree_set bset; thread_local ::std::size_t n{}; @@ -13,7 +11,7 @@ extern "C" int LLVMFuzzerTestOneInput(::std::uint8_t *data, ::std::size_t size) bset.clear_destroy(); n = 0; } - bset.insert_key(::fast_io::string_view(reinterpret_cast(data), size)); + bset.insert_key(::fast_io::containers::basic_string_view(reinterpret_cast(data), size)); ++n; return 0; } \ No newline at end of file diff --git a/include/fast_io_dsal/str_btree_set.h b/include/fast_io_dsal/str_btree_set.h new file mode 100644 index 000000000..c727f1841 --- /dev/null +++ b/include/fast_io_dsal/str_btree_set.h @@ -0,0 +1,79 @@ +#pragma once + +#if !defined(__cplusplus) +#error "You must be using a C++ compiler" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "impl/misc/push_macros.h" +#include "impl/misc/push_warnings.h" +#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 "impl/freestanding.h" +#include "impl/common.h" +#include "impl/associative_string.h" +#include "impl/string_view.h" +#include "impl/cstring_view.h" +#include "impl/str_btree_set.h" + +#if ((__STDC_HOSTED__ == 1 && (!defined(_GLIBCXX_HOSTED) || _GLIBCXX_HOSTED == 1) && \ + !defined(_LIBCPP_FREESTANDING)) || \ + defined(FAST_IO_ENABLE_HOSTED_FEATURES)) + +namespace fast_io +{ + +template <::std::integral T, typename Alloc = ::fast_io::native_global_allocator> +using basic_str_btree_set = ::fast_io::containers::basic_str_btree_set; + +using str_btree_set = ::fast_io::basic_str_btree_set; +using wstr_btree_set = ::fast_io::basic_str_btree_set; +using u8str_btree_set = ::fast_io::basic_str_btree_set; +using u16str_btree_set = ::fast_io::basic_str_btree_set; +using u32str_btree_set = ::fast_io::basic_str_btree_set; + +namespace containers +{ + +#if 0 +template <::std::input_iterator InputIt> +basic_str_btree_set(InputIt, InputIt) -> basic_str_btree_set::value_type, ::fast_io::native_global_allocator>; + +#ifdef __cpp_lib_containers_ranges +template <::std::ranges::input_range R> +basic_str_btree_set(::std::from_range_t, R &&) -> basic_str_btree_set<::std::ranges::range_value_t, ::fast_io::native_global_allocator>; +#endif +#endif +} // namespace containers + +namespace tlc +{ +template +using basic_str_btree_set = ::fast_io::containers::basic_str_btree_set; + +using str_btree_set = ::fast_io::tlc::basic_str_btree_set; +using wstr_btree_set = ::fast_io::tlc::basic_str_btree_set; +using u8str_btree_set = ::fast_io::tlc::basic_str_btree_set; +using u16str_btree_set = ::fast_io::tlc::basic_str_btree_set; +using u32str_btree_set = ::fast_io::tlc::basic_str_btree_set; +} // namespace tlc + +} // namespace fast_io + +#endif + +#include "impl/misc/pop_macros.h" +#include "impl/misc/pop_warnings.h" From a0ac2a1318c7c201429559ee3b31555470cc1692 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Sat, 12 Jul 2025 18:45:15 +0800 Subject: [PATCH 38/81] [str_btree_set] fix str_btree_set.h --- .../0011.containers/str_btree_set/gentest.h | 38 +++++++++++++++++++ include/fast_io_dsal/str_btree_set.h | 3 +- 2 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 benchmark/0011.containers/str_btree_set/gentest.h diff --git a/benchmark/0011.containers/str_btree_set/gentest.h b/benchmark/0011.containers/str_btree_set/gentest.h new file mode 100644 index 000000000..05063c465 --- /dev/null +++ b/benchmark/0011.containers/str_btree_set/gentest.h @@ -0,0 +1,38 @@ +#pragma once + +#include +#include +#include + +inline ::fast_io::vector<::fast_io::string> gentest() +{ + ::fast_io::vector<::fast_io::string> vec; + ::fast_io::mt19937_64 eng; + ::std::uniform_int_distribution ud(0, 61); + ::std::uniform_int_distribution rlen(8, 20); + for (::std::size_t i(0); i != 1000000; ++i) + { + ::fast_io::string tempstr; + ::std::size_t n{rlen(eng)}; + temp.reserve(n); + for (std::size_t j(0); j != s; ++j) + { + char8_t ch(static_cast(ud(eng))); + if (ch < 10u) + { + ch += u8'0'; + } + else if (ch < 36u) + { + ch = ch - 10u + u8'a'; + } + else + { + ch = ch - 36u + u8'A'; + } + tempstr.push_back_unchecked(ch); + } + vec.emplace_back(::std::move(tempstr)); + } + return vec; +} diff --git a/include/fast_io_dsal/str_btree_set.h b/include/fast_io_dsal/str_btree_set.h index c727f1841..33a891c99 100644 --- a/include/fast_io_dsal/str_btree_set.h +++ b/include/fast_io_dsal/str_btree_set.h @@ -24,9 +24,8 @@ #include "impl/freestanding.h" #include "impl/common.h" +#include "string_view.h" #include "impl/associative_string.h" -#include "impl/string_view.h" -#include "impl/cstring_view.h" #include "impl/str_btree_set.h" #if ((__STDC_HOSTED__ == 1 && (!defined(_GLIBCXX_HOSTED) || _GLIBCXX_HOSTED == 1) && \ From d73eb785da59de130a4b6b41b81f37c6ac596a3f Mon Sep 17 00:00:00 2001 From: trcrsired Date: Sat, 12 Jul 2025 19:14:42 +0800 Subject: [PATCH 39/81] [str_btree_set] add a benchmark for str_btree_set --- .../0011.containers/str_btree_set/gentest.h | 17 ++--- .../0011.containers/str_btree_set/std_set.cc | 19 ++++++ .../str_btree_set/str_btree_set.cc | 18 +++++ include/fast_io_dsal/impl/str_btree_set.h | 67 ++++++++++++++++++- 4 files changed, 111 insertions(+), 10 deletions(-) create mode 100644 benchmark/0011.containers/str_btree_set/std_set.cc create mode 100644 benchmark/0011.containers/str_btree_set/str_btree_set.cc diff --git a/benchmark/0011.containers/str_btree_set/gentest.h b/benchmark/0011.containers/str_btree_set/gentest.h index 05063c465..c59bda309 100644 --- a/benchmark/0011.containers/str_btree_set/gentest.h +++ b/benchmark/0011.containers/str_btree_set/gentest.h @@ -4,18 +4,19 @@ #include #include -inline ::fast_io::vector<::fast_io::string> gentest() +template +inline ::fast_io::vector gentest() { - ::fast_io::vector<::fast_io::string> vec; - ::fast_io::mt19937_64 eng; + ::fast_io::vector vec; + ::std::mt19937_64 eng; ::std::uniform_int_distribution ud(0, 61); ::std::uniform_int_distribution rlen(8, 20); - for (::std::size_t i(0); i != 1000000; ++i) + for (::std::size_t i{}; i != 1000000; ++i) { - ::fast_io::string tempstr; + T tempstr; ::std::size_t n{rlen(eng)}; - temp.reserve(n); - for (std::size_t j(0); j != s; ++j) + tempstr.reserve(n); + for (::std::size_t j{}; j != n; ++j) { char8_t ch(static_cast(ud(eng))); if (ch < 10u) @@ -30,7 +31,7 @@ inline ::fast_io::vector<::fast_io::string> gentest() { ch = ch - 36u + u8'A'; } - tempstr.push_back_unchecked(ch); + tempstr.push_back(ch); } vec.emplace_back(::std::move(tempstr)); } diff --git a/benchmark/0011.containers/str_btree_set/std_set.cc b/benchmark/0011.containers/str_btree_set/std_set.cc new file mode 100644 index 000000000..a05006d26 --- /dev/null +++ b/benchmark/0011.containers/str_btree_set/std_set.cc @@ -0,0 +1,19 @@ +#include +#include +#include +#include +#include "gentest.h" + +int main() +{ + auto vec{::gentest()}; + ::fast_io::timer t(u8"str_btree_set"); + ::std::set<::fast_io::string> bset; + { + ::fast_io::timer t(u8"insert"); + for (auto const &e : vec) + { + bset.insert(e); + } + } +} \ No newline at end of file diff --git a/benchmark/0011.containers/str_btree_set/str_btree_set.cc b/benchmark/0011.containers/str_btree_set/str_btree_set.cc new file mode 100644 index 000000000..c7657a844 --- /dev/null +++ b/benchmark/0011.containers/str_btree_set/str_btree_set.cc @@ -0,0 +1,18 @@ +#include +#include +#include +#include "gentest.h" + +int main() +{ + auto vec{::gentest()}; + ::fast_io::timer t(u8"str_btree_set"); + ::fast_io::str_btree_set bset; + { + ::fast_io::timer t(u8"insert_key"); + for (auto const &e : vec) + { + bset.insert_key(::fast_io::mnp::os_c_str(e)); + } + } +} \ No newline at end of file diff --git a/include/fast_io_dsal/impl/str_btree_set.h b/include/fast_io_dsal/impl/str_btree_set.h index 077281bbc..673167a0f 100644 --- a/include/fast_io_dsal/impl/str_btree_set.h +++ b/include/fast_io_dsal/impl/str_btree_set.h @@ -42,6 +42,65 @@ struct find_btree_node_insert_position_result ::std::size_t pos{}; bool found{}; }; +#if 0 +template +inline constexpr find_btree_node_insert_position_result find_str_btree_node_insert_position(nodetype *node, + typename nodetype::char_type const *keystrptr, ::std::size_t keystrn) noexcept +{ + using char_type = typename nodetype::char_type; + auto *b{node->keys}; + ::std::size_t size{node->size}; + + ::fast_io::containers::basic_string_view newkey(keystrptr, keystrn); + + bool found {}; + + // Threshold for using linear search; adjust as needed for performance + constexpr ::std::size_t linear_threshold{4}; + + if (size < linear_threshold) + { + // Linear search for small nodes + auto *i = b; + auto *e = b + size; + for (; i != e; ++i) + { + auto cmpres = newkey <=> i->strvw(); + if (cmpres <= 0) + { + found = (cmpres == 0); + return {static_cast<::std::size_t>(i - b), found}; + } + } + return {size, false}; // Key goes at the end + } + + + // Binary search for larger nodes + ::std::size_t left = 0, right = size; + while (left < right) + { + ::std::size_t mid = left + (right - left) / 2; + auto cmpres = newkey <=> b[mid].strvw(); + if (cmpres < 0) + { + right = mid; + } + else if (0 < cmpres) + { + left = mid + 1; + } + else + { + found = true; + right = mid; // Insert position should be at the first equal key + } + } + + return {left, found}; +} + +#else template inline constexpr find_btree_node_insert_position_result find_str_btree_node_insert_position(nodetype *node, @@ -49,8 +108,10 @@ inline constexpr find_btree_node_insert_position_result find_str_btree_node_inse { using char_type = typename nodetype::char_type; auto *b{node->keys}, *i{b}, *e{b + node->size}; - bool found{}; + ::fast_io::containers::basic_string_view newkey(keystrptr, keystrn); + + bool found{}; for (; i != e; ++i) { auto cmpres{newkey <=> i->strvw()}; @@ -63,6 +124,8 @@ inline constexpr find_btree_node_insert_position_result find_str_btree_node_inse return {static_cast<::std::size_t>(i - b), found}; } +#endif + template inline constexpr bool str_btree_insert_key(nodetype *node, typename nodetype::char_type const *keystrptr, ::std::size_t keystrn, nodetype **proot) noexcept @@ -289,7 +352,7 @@ inline constexpr bool str_btree_insert_key_with_root(nodetype **proot, } // namespace details -template <::std::integral chtype, typename Allocator, ::std::size_t keys_number = 63> +template <::std::integral chtype, typename Allocator, ::std::size_t keys_number = 15> class basic_str_btree_set { using node_type = ::fast_io::containers::details::str_btree_set_node; From f9f88c276cc07eb768e12841b883d4ecc456a104 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Sat, 12 Jul 2025 19:25:31 +0800 Subject: [PATCH 40/81] [str_btree_set] add contains --- .../0011.containers/str_btree_set/std_set.cc | 11 ++++++ .../str_btree_set/str_btree_set.cc | 11 ++++++ include/fast_io_dsal/impl/str_btree_set.h | 36 ++++++++++++++++--- 3 files changed, 54 insertions(+), 4 deletions(-) diff --git a/benchmark/0011.containers/str_btree_set/std_set.cc b/benchmark/0011.containers/str_btree_set/std_set.cc index a05006d26..81ed12865 100644 --- a/benchmark/0011.containers/str_btree_set/std_set.cc +++ b/benchmark/0011.containers/str_btree_set/std_set.cc @@ -16,4 +16,15 @@ int main() bset.insert(e); } } + { + ::std::size_t count{}; + { + ::fast_io::timer t(u8"contains"); + for (auto const &e : vec) + { + count += static_cast<::std::size_t>(bset.contains(e)); + } + } + ::fast_io::io::perrln("count=", count); + } } \ No newline at end of file diff --git a/benchmark/0011.containers/str_btree_set/str_btree_set.cc b/benchmark/0011.containers/str_btree_set/str_btree_set.cc index c7657a844..76a6434b9 100644 --- a/benchmark/0011.containers/str_btree_set/str_btree_set.cc +++ b/benchmark/0011.containers/str_btree_set/str_btree_set.cc @@ -15,4 +15,15 @@ int main() bset.insert_key(::fast_io::mnp::os_c_str(e)); } } + { + ::std::size_t count{}; + { + ::fast_io::timer t(u8"contains"); + for (auto const &e : vec) + { + count += static_cast<::std::size_t>(bset.contains(::fast_io::mnp::os_c_str(e))); + } + } + ::fast_io::io::perrln("count=", count); + } } \ No newline at end of file diff --git a/include/fast_io_dsal/impl/str_btree_set.h b/include/fast_io_dsal/impl/str_btree_set.h index 673167a0f..484554380 100644 --- a/include/fast_io_dsal/impl/str_btree_set.h +++ b/include/fast_io_dsal/impl/str_btree_set.h @@ -126,6 +126,34 @@ inline constexpr find_btree_node_insert_position_result find_str_btree_node_inse #endif +template +inline constexpr bool str_btree_contains(nodetype *node, typename nodetype::char_type const *keystrptr, ::std::size_t keystrn) noexcept +{ + if (node == nullptr) + { + return false; + } + ::std::size_t pos; + // **Find the correct position for insertion** + for (;;) + { + auto [postemp, found] = find_str_btree_node_insert_position(node, keystrptr, keystrn); + pos = postemp; + // **If the key already exists, return false (no duplicate keys)** + if (found) + { + return true; + } + // **If the node is a leaf** + if (node->leaf) + { + break; + } + node = node->childrens[pos]; + } + return false; +} + template inline constexpr bool str_btree_insert_key(nodetype *node, typename nodetype::char_type const *keystrptr, ::std::size_t keystrn, nodetype **proot) noexcept @@ -377,13 +405,13 @@ class basic_str_btree_set } } - constexpr bool contains(string_view_type) const noexcept + constexpr bool contains(string_view_type strvw) const noexcept { - return false; + return ::fast_io::containers::details::str_btree_contains(this->root, strvw.ptr, strvw.n); } constexpr bool is_empty() const noexcept { - return false; + return root == nullptr; } constexpr bool erase_key(string_view_type) noexcept { @@ -391,7 +419,7 @@ class basic_str_btree_set } constexpr bool insert_key(string_view_type strvw) noexcept { - return ::fast_io::containers::details::str_btree_insert_key_with_root(__builtin_addressof(this->root), strvw.data(), strvw.size()); + return ::fast_io::containers::details::str_btree_insert_key_with_root(__builtin_addressof(this->root), strvw.ptr, strvw.n); } private: From 3a4ccc655e49fa6ba92893b084d1f7df0bbdbb25 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Sat, 12 Jul 2025 19:32:55 +0800 Subject: [PATCH 41/81] [str_btree_set] add ::std::unordered_set bench --- .../str_btree_set/std_unordered_set.cc | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 benchmark/0011.containers/str_btree_set/std_unordered_set.cc diff --git a/benchmark/0011.containers/str_btree_set/std_unordered_set.cc b/benchmark/0011.containers/str_btree_set/std_unordered_set.cc new file mode 100644 index 000000000..429a977f3 --- /dev/null +++ b/benchmark/0011.containers/str_btree_set/std_unordered_set.cc @@ -0,0 +1,30 @@ +#include +#include +#include +#include +#include "gentest.h" + +int main() +{ + auto vec{::gentest()}; + ::fast_io::timer t(u8"str_btree_set"); + ::std::unordered_set<::std::string> bset; + { + ::fast_io::timer t(u8"insert"); + for (auto const &e : vec) + { + bset.insert(e); + } + } + { + ::std::size_t count{}; + { + ::fast_io::timer t(u8"contains"); + for (auto const &e : vec) + { + count += static_cast<::std::size_t>(bset.contains(e)); + } + } + ::fast_io::io::perrln("count=", count); + } +} \ No newline at end of file From c249561e35e64885a918a96d36d1c391188b063e Mon Sep 17 00:00:00 2001 From: trcrsired Date: Sat, 12 Jul 2025 20:35:20 +0800 Subject: [PATCH 42/81] [str_btree_set] fix up str btree set --- include/fast_io_dsal/impl/str_btree_set.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/include/fast_io_dsal/impl/str_btree_set.h b/include/fast_io_dsal/impl/str_btree_set.h index 484554380..d8d91f5e9 100644 --- a/include/fast_io_dsal/impl/str_btree_set.h +++ b/include/fast_io_dsal/impl/str_btree_set.h @@ -133,12 +133,10 @@ inline constexpr bool str_btree_contains(nodetype *node, typename nodetype::char { return false; } - ::std::size_t pos; // **Find the correct position for insertion** for (;;) { auto [postemp, found] = find_str_btree_node_insert_position(node, keystrptr, keystrn); - pos = postemp; // **If the key already exists, return false (no duplicate keys)** if (found) { @@ -149,7 +147,7 @@ inline constexpr bool str_btree_contains(nodetype *node, typename nodetype::char { break; } - node = node->childrens[pos]; + node = node->childrens[postemp]; } return false; } @@ -380,7 +378,7 @@ inline constexpr bool str_btree_insert_key_with_root(nodetype **proot, } // namespace details -template <::std::integral chtype, typename Allocator, ::std::size_t keys_number = 15> +template <::std::integral chtype, typename Allocator, ::std::size_t keys_number = 16> class basic_str_btree_set { using node_type = ::fast_io::containers::details::str_btree_set_node; From 7c381aae866f808ed4b9e605fe388b67e2133054 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Sat, 12 Jul 2025 21:29:18 +0800 Subject: [PATCH 43/81] [str_tree_set] btree should only allow even numbers of key --- include/fast_io_dsal/impl/str_btree_set.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/fast_io_dsal/impl/str_btree_set.h b/include/fast_io_dsal/impl/str_btree_set.h index d8d91f5e9..c3db05f4e 100644 --- a/include/fast_io_dsal/impl/str_btree_set.h +++ b/include/fast_io_dsal/impl/str_btree_set.h @@ -379,6 +379,7 @@ inline constexpr bool str_btree_insert_key_with_root(nodetype **proot, } // namespace details template <::std::integral chtype, typename Allocator, ::std::size_t keys_number = 16> + requires((keys_number != 0) && ((keys_number & 1) == 0)) class basic_str_btree_set { using node_type = ::fast_io::containers::details::str_btree_set_node; From e37dc7be593180c75e8af2d28726df9ee21a41cd Mon Sep 17 00:00:00 2001 From: trcrsired Date: Sat, 12 Jul 2025 23:59:34 +0800 Subject: [PATCH 44/81] [str_btree_set] add some benchmarks --- .../str_btree_set/abseil_btree_set.cc | 32 ++++++++++++ .../0011.containers/str_btree_set/gentest.h | 2 +- .../str_btree_set/rustbtree/Cargo.toml | 7 +++ .../str_btree_set/rustbtree/src/main.rs | 52 +++++++++++++++++++ .../0011.containers/str_btree_set/std_set.cc | 6 +-- .../str_btree_set/std_set_fast_io.cc | 30 +++++++++++ .../str_btree_set/u8str_btree_set.cc | 29 +++++++++++ 7 files changed, 154 insertions(+), 4 deletions(-) create mode 100644 benchmark/0011.containers/str_btree_set/abseil_btree_set.cc create mode 100644 benchmark/0011.containers/str_btree_set/rustbtree/Cargo.toml create mode 100644 benchmark/0011.containers/str_btree_set/rustbtree/src/main.rs create mode 100644 benchmark/0011.containers/str_btree_set/std_set_fast_io.cc create mode 100644 benchmark/0011.containers/str_btree_set/u8str_btree_set.cc diff --git a/benchmark/0011.containers/str_btree_set/abseil_btree_set.cc b/benchmark/0011.containers/str_btree_set/abseil_btree_set.cc new file mode 100644 index 000000000..d2919a8db --- /dev/null +++ b/benchmark/0011.containers/str_btree_set/abseil_btree_set.cc @@ -0,0 +1,32 @@ +#include +#include +#include +#include +#include +#include +#include "gentest.h" + +int main() +{ + auto vec{::gentest()}; + ::fast_io::timer t(u8"str_btree_set"); + ::absl::btree_set<::fast_io::string> bset; + { + ::fast_io::timer t(u8"insert"); + for (auto const &e : vec) + { + bset.insert(e); + } + } + { + ::std::size_t count{}; + { + ::fast_io::timer t(u8"contains"); + for (auto const &e : vec) + { + count += static_cast<::std::size_t>(bset.contains(e)); + } + } + ::fast_io::io::perrln("count=", count); + } +} \ No newline at end of file diff --git a/benchmark/0011.containers/str_btree_set/gentest.h b/benchmark/0011.containers/str_btree_set/gentest.h index c59bda309..fd04bb9e1 100644 --- a/benchmark/0011.containers/str_btree_set/gentest.h +++ b/benchmark/0011.containers/str_btree_set/gentest.h @@ -10,7 +10,7 @@ inline ::fast_io::vector gentest() ::fast_io::vector vec; ::std::mt19937_64 eng; ::std::uniform_int_distribution ud(0, 61); - ::std::uniform_int_distribution rlen(8, 20); + ::std::uniform_int_distribution rlen(25, 30); for (::std::size_t i{}; i != 1000000; ++i) { T tempstr; diff --git a/benchmark/0011.containers/str_btree_set/rustbtree/Cargo.toml b/benchmark/0011.containers/str_btree_set/rustbtree/Cargo.toml new file mode 100644 index 000000000..4e55cdbb2 --- /dev/null +++ b/benchmark/0011.containers/str_btree_set/rustbtree/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "rustbtree" +version = "0.1.0" +edition = "2024" + +[dependencies] +rand = "0.9.1" diff --git a/benchmark/0011.containers/str_btree_set/rustbtree/src/main.rs b/benchmark/0011.containers/str_btree_set/rustbtree/src/main.rs new file mode 100644 index 000000000..2e704bf53 --- /dev/null +++ b/benchmark/0011.containers/str_btree_set/rustbtree/src/main.rs @@ -0,0 +1,52 @@ +use rand::rngs::StdRng; +use rand::{Rng, SeedableRng}; + +fn generate_test_data() -> Vec { + let mut vec = Vec::with_capacity(1_000_000); + let mut rng = StdRng::seed_from_u64(0xDEADBEEF); // deterministic seed + + for _ in 0..1_000_000 { + let len = rng.random_range(8..21); // replaces Uniform(8, 20) + let mut s = String::with_capacity(len); + + for _ in 0..len { + let x = rng.random_range(0..62); // replaces Uniform(0, 61) + let ch = match x { + x if x < 10 => (b'0' + x as u8) as char, + x if x < 36 => (b'a' + (x - 10) as u8) as char, + _ => (b'A' + (x - 36) as u8) as char, + }; + s.push(ch); + } + + vec.push(s); + } + + vec +} + +fn main() { + let vec = generate_test_data(); + let start_total = Instant::now(); + println!("str_btree_set test started"); + + let mut bset = BTreeSet::new(); + + let start_insert = Instant::now(); + for s in &vec { + bset.insert(s.clone()); // cloning to move into BTreeSet + } + println!("insert_key: {:.2?}", start_insert.elapsed()); + + let mut count = 0; + let start_contains = Instant::now(); + for s in &vec { + if bset.contains_key(s) { + count += 1; + } + } + println!("contains: {:.2?}", start_contains.elapsed()); + + println!("count = {}", count); + println!("total time: {:.2?}", start_total.elapsed()); +} diff --git a/benchmark/0011.containers/str_btree_set/std_set.cc b/benchmark/0011.containers/str_btree_set/std_set.cc index 81ed12865..d0647857b 100644 --- a/benchmark/0011.containers/str_btree_set/std_set.cc +++ b/benchmark/0011.containers/str_btree_set/std_set.cc @@ -6,9 +6,9 @@ int main() { - auto vec{::gentest()}; + auto vec{::gentest<::std::string>()}; ::fast_io::timer t(u8"str_btree_set"); - ::std::set<::fast_io::string> bset; + ::std::set bset; { ::fast_io::timer t(u8"insert"); for (auto const &e : vec) @@ -27,4 +27,4 @@ int main() } ::fast_io::io::perrln("count=", count); } -} \ No newline at end of file +} diff --git a/benchmark/0011.containers/str_btree_set/std_set_fast_io.cc b/benchmark/0011.containers/str_btree_set/std_set_fast_io.cc new file mode 100644 index 000000000..81ed12865 --- /dev/null +++ b/benchmark/0011.containers/str_btree_set/std_set_fast_io.cc @@ -0,0 +1,30 @@ +#include +#include +#include +#include +#include "gentest.h" + +int main() +{ + auto vec{::gentest()}; + ::fast_io::timer t(u8"str_btree_set"); + ::std::set<::fast_io::string> bset; + { + ::fast_io::timer t(u8"insert"); + for (auto const &e : vec) + { + bset.insert(e); + } + } + { + ::std::size_t count{}; + { + ::fast_io::timer t(u8"contains"); + for (auto const &e : vec) + { + count += static_cast<::std::size_t>(bset.contains(e)); + } + } + ::fast_io::io::perrln("count=", count); + } +} \ No newline at end of file diff --git a/benchmark/0011.containers/str_btree_set/u8str_btree_set.cc b/benchmark/0011.containers/str_btree_set/u8str_btree_set.cc new file mode 100644 index 000000000..1a4956309 --- /dev/null +++ b/benchmark/0011.containers/str_btree_set/u8str_btree_set.cc @@ -0,0 +1,29 @@ +#include +#include +#include +#include "gentest.h" + +int main() +{ + auto vec{::gentest<::fast_io::u8string>()}; + ::fast_io::timer t(u8"str_btree_set"); + ::fast_io::u8str_btree_set bset; + { + ::fast_io::timer t(u8"insert_key"); + for (auto const &e : vec) + { + bset.insert_key(::fast_io::mnp::os_c_str(e)); + } + } + { + ::std::size_t count{}; + { + ::fast_io::timer t(u8"contains"); + for (auto const &e : vec) + { + count += static_cast<::std::size_t>(bset.contains(::fast_io::mnp::os_c_str(e))); + } + } + ::fast_io::io::perrln("count=", count); + } +} From 50c16697104d6b001649517809dde0157ecca869 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Sun, 13 Jul 2025 00:02:48 +0800 Subject: [PATCH 45/81] [str_btree_set] fix main.rs in rustbtree bench --- benchmark/0011.containers/str_btree_set/rustbtree/src/main.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/benchmark/0011.containers/str_btree_set/rustbtree/src/main.rs b/benchmark/0011.containers/str_btree_set/rustbtree/src/main.rs index 2e704bf53..9a1c77acd 100644 --- a/benchmark/0011.containers/str_btree_set/rustbtree/src/main.rs +++ b/benchmark/0011.containers/str_btree_set/rustbtree/src/main.rs @@ -1,3 +1,5 @@ +use std::collections::BTreeSet; +use std::time::Instant; use rand::rngs::StdRng; use rand::{Rng, SeedableRng}; From 59e7dcd2579541437077b14eeb71e7da999dd8b9 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Sun, 13 Jul 2025 10:53:15 +0800 Subject: [PATCH 46/81] [str_btree_set] fix main.rs --- benchmark/0011.containers/str_btree_set/rustbtree/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benchmark/0011.containers/str_btree_set/rustbtree/src/main.rs b/benchmark/0011.containers/str_btree_set/rustbtree/src/main.rs index 9a1c77acd..66e6be909 100644 --- a/benchmark/0011.containers/str_btree_set/rustbtree/src/main.rs +++ b/benchmark/0011.containers/str_btree_set/rustbtree/src/main.rs @@ -43,7 +43,7 @@ fn main() { let mut count = 0; let start_contains = Instant::now(); for s in &vec { - if bset.contains_key(s) { + if bset.contains(s) { count += 1; } } From 77ea2593ddb2e80c13e72f447414390b7e22fcf8 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Sun, 13 Jul 2025 11:00:12 +0800 Subject: [PATCH 47/81] [str_btree_set] rust is a bs lang wtf design a random number generate without std + low...=high or low... high_exclusive --- benchmark/0011.containers/str_btree_set/rustbtree/src/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/benchmark/0011.containers/str_btree_set/rustbtree/src/main.rs b/benchmark/0011.containers/str_btree_set/rustbtree/src/main.rs index 66e6be909..955043c52 100644 --- a/benchmark/0011.containers/str_btree_set/rustbtree/src/main.rs +++ b/benchmark/0011.containers/str_btree_set/rustbtree/src/main.rs @@ -8,11 +8,11 @@ fn generate_test_data() -> Vec { let mut rng = StdRng::seed_from_u64(0xDEADBEEF); // deterministic seed for _ in 0..1_000_000 { - let len = rng.random_range(8..21); // replaces Uniform(8, 20) + let len = rng.random_range(25..=30); // replaces Uniform(8, 20) let mut s = String::with_capacity(len); for _ in 0..len { - let x = rng.random_range(0..62); // replaces Uniform(0, 61) + let x = rng.random_range(0..=61); // replaces Uniform(0, 61) let ch = match x { x if x < 10 => (b'0' + x as u8) as char, x if x < 36 => (b'a' + (x - 10) as u8) as char, From 37c2efc3f41ac1ce25a0d91afb9fe9dcf1f94e43 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Sun, 13 Jul 2025 11:06:47 +0800 Subject: [PATCH 48/81] [str_btree_set] use two string types --- .../str_btree_set/abseil_btree_set.cc | 6 ++-- .../str_btree_set/abseil_btree_set_fast_io.cc | 32 +++++++++++++++++++ 2 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 benchmark/0011.containers/str_btree_set/abseil_btree_set_fast_io.cc diff --git a/benchmark/0011.containers/str_btree_set/abseil_btree_set.cc b/benchmark/0011.containers/str_btree_set/abseil_btree_set.cc index d2919a8db..9c51c3229 100644 --- a/benchmark/0011.containers/str_btree_set/abseil_btree_set.cc +++ b/benchmark/0011.containers/str_btree_set/abseil_btree_set.cc @@ -8,9 +8,9 @@ int main() { - auto vec{::gentest()}; + auto vec{::gentest<::std::string>()}; ::fast_io::timer t(u8"str_btree_set"); - ::absl::btree_set<::fast_io::string> bset; + ::absl::btree_set bset; { ::fast_io::timer t(u8"insert"); for (auto const &e : vec) @@ -29,4 +29,4 @@ int main() } ::fast_io::io::perrln("count=", count); } -} \ No newline at end of file +} diff --git a/benchmark/0011.containers/str_btree_set/abseil_btree_set_fast_io.cc b/benchmark/0011.containers/str_btree_set/abseil_btree_set_fast_io.cc new file mode 100644 index 000000000..d2919a8db --- /dev/null +++ b/benchmark/0011.containers/str_btree_set/abseil_btree_set_fast_io.cc @@ -0,0 +1,32 @@ +#include +#include +#include +#include +#include +#include +#include "gentest.h" + +int main() +{ + auto vec{::gentest()}; + ::fast_io::timer t(u8"str_btree_set"); + ::absl::btree_set<::fast_io::string> bset; + { + ::fast_io::timer t(u8"insert"); + for (auto const &e : vec) + { + bset.insert(e); + } + } + { + ::std::size_t count{}; + { + ::fast_io::timer t(u8"contains"); + for (auto const &e : vec) + { + count += static_cast<::std::size_t>(bset.contains(e)); + } + } + ::fast_io::io::perrln("count=", count); + } +} \ No newline at end of file From 14f148bcf9ac52e2b78341dc4b1381dfebbec6f8 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Sun, 13 Jul 2025 12:47:27 +0800 Subject: [PATCH 49/81] disable benchmark for str_btree_set --- benchmark/0011.containers/.test_prop.toml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 benchmark/0011.containers/.test_prop.toml diff --git a/benchmark/0011.containers/.test_prop.toml b/benchmark/0011.containers/.test_prop.toml new file mode 100644 index 000000000..3d86d282b --- /dev/null +++ b/benchmark/0011.containers/.test_prop.toml @@ -0,0 +1,3 @@ +["str_btree_set"] +ignore = true + From c287d9d87c9f4a85a48f371098e0800befebce8c Mon Sep 17 00:00:00 2001 From: trcrsired Date: Sun, 13 Jul 2025 14:45:19 +0800 Subject: [PATCH 50/81] [str_btree_set] Fix the test CI --- .../0013.str_btree_set/name.txt | 36 -------------- .../0013.str_btree_set/str_btree_set_input.cc | 49 ------------------- 2 files changed, 85 deletions(-) delete mode 100644 tests/0026.container/0013.str_btree_set/name.txt delete mode 100644 tests/0026.container/0013.str_btree_set/str_btree_set_input.cc diff --git a/tests/0026.container/0013.str_btree_set/name.txt b/tests/0026.container/0013.str_btree_set/name.txt deleted file mode 100644 index 8d103d09d..000000000 --- a/tests/0026.container/0013.str_btree_set/name.txt +++ /dev/null @@ -1,36 +0,0 @@ -eittusgab -hoesruteanar -rcowha -mihsoiiydd -ietdyahrr -tnieume -rtsisih -cfanemclwiae -lnycaaerwahn -oswceoresie -aoanooftoae -aeieoeeehtn -ybhehgiftueu -ornsfdh -ritdhtidus -ecaepsow -eepdernchser -ybnebwdot -scgiiaewetal -avrtdao -bteelusirla -cptttet -duaslaeda -itosdaeto -sassmfatmter -moehonoblue -ttdlscea -anttoa -osrewcao -nyndeesdrst -rhtrseluj -hemaotd -fsowddw -iyasflneczi -egouwbvh - diff --git a/tests/0026.container/0013.str_btree_set/str_btree_set_input.cc b/tests/0026.container/0013.str_btree_set/str_btree_set_input.cc deleted file mode 100644 index 98bb87b88..000000000 --- a/tests/0026.container/0013.str_btree_set/str_btree_set_input.cc +++ /dev/null @@ -1,49 +0,0 @@ -#include -#include -#include -#include -#include -#include - -template <::std::integral chtype, ::std::size_t keys_number> -inline constexpr void str_btree_set_inorder_traverse( - ::fast_io::containers::details::str_btree_set_node *node, - auto &&callback) noexcept -{ - if (node == nullptr) - { - return; - } - - // **Traverse left subtree** - for (::std::size_t i{}; i != node->size; ++i) - { - if (!node->leaf) - { - str_btree_set_inorder_traverse(node->childrens[i], callback); - } - - // **Visit current key** - callback(node->keys[i].strvw()); - } - - // **Traverse rightmost subtree** - if (!node->leaf) - { - str_btree_set_inorder_traverse(node->childrens[node->size], callback); - } -} - -int main() -{ - ::fast_io::containers::basic_str_btree_set bset; - ::fast_io::ibuf_file ibf("name.txt"); - for(::fast_io::string str; scan(ibf, str);) - { - bset.insert_key(::fast_io::mnp::os_c_str(str)); - }; - - str_btree_set_inorder_traverse(bset.root, [](::fast_io::string_view v) { - ::fast_io::io::println(v); - }); -} From 3c77f6bb4d690368f8d6a7a03ade55fe8132298b Mon Sep 17 00:00:00 2001 From: trcrsired Date: Sun, 13 Jul 2025 20:15:37 +0800 Subject: [PATCH 51/81] [str_tree_set] add iterator implementation for str_btree_set --- .../fast_io_dsal/impl/associative_string.h | 4 +- include/fast_io_dsal/impl/str_btree_set.h | 80 +++++++++++++++++++ 2 files changed, 82 insertions(+), 2 deletions(-) diff --git a/include/fast_io_dsal/impl/associative_string.h b/include/fast_io_dsal/impl/associative_string.h index ac0aa3bd7..2cdccfa50 100644 --- a/include/fast_io_dsal/impl/associative_string.h +++ b/include/fast_io_dsal/impl/associative_string.h @@ -12,9 +12,9 @@ struct associative_string using size_type = ::std::size_t; char_type const *ptr; size_type n; - constexpr ::fast_io::containers::basic_string_view strvw() const noexcept + constexpr ::fast_io::containers::basic_cstring_view strvw() const noexcept { - return ::fast_io::containers::basic_string_view(ptr, n); + return ::fast_io::containers::basic_cstring_view(::fast_io::null_terminated, ptr, n); } }; diff --git a/include/fast_io_dsal/impl/str_btree_set.h b/include/fast_io_dsal/impl/str_btree_set.h index c3db05f4e..17d3b0594 100644 --- a/include/fast_io_dsal/impl/str_btree_set.h +++ b/include/fast_io_dsal/impl/str_btree_set.h @@ -35,6 +35,7 @@ struct ::fast_io::io_scatter_t keys[keys_number]; void *childrens[keys_number + 1u]; void *parent; + ::std::size_t parent_pos; }; struct find_btree_node_insert_position_result @@ -376,6 +377,85 @@ inline constexpr bool str_btree_insert_key_with_root(nodetype **proot, return ::fast_io::containers::details::str_btree_insert_key(node, keystrptr, keystrn, proot); } +struct str_btree_set_iterator_common +{ + void const *ptr{}; + ::std::size_t pos{}; +}; + +template <::std::size_t keys_number> +inline constexpr void str_btree_set_next_node(str_btree_set_iterator_common &c) noexcept +{ + auto ptrv{static_cast<::fast_io::containers::details::str_btree_set_common const *>(c.ptr)}; + + auto leaf{ptrv->leaf}; + if (leaf) + { + if (++c.pos == ptrv->size) + { + auto parent{ptrv->parent}; + auto parent_pos{ptrv->parent_pos}; + for (; parent; parent = ptrv->parent) + { + auto parentn{parent->size}; + if (parent_pos != parentn) + { + break; + } + parent_pos = ptrv->parent_pos; + } + c.ptr = parent; + c.pos = parent_pos; + } + } + else + { + auto nextptr{ptrv->childrens[c.pos + 1]}; + for (; !nextptr->leaf; nextptr = *ptrv->childrens) + { + } + c.ptr = nextptr; + c.pos = 0; + } +} + +template <::std::integral chtype, ::std::size_t keys_number> +class str_btree_set_iterator +{ +public: + ::fast_io::containers::details::str_btree_set_iterator_common node; + + constexpr str_btree_set_iterator &operator++() noexcept + { + ::fast_io::containers::details::str_btree_set_next_node(node); + return *this; + } + constexpr str_btree_set_iterator operator++(int) noexcept + { + auto tmp{*this}; + ++*this; + return tmp; + } + constexpr ::fast_io::containers::basic_cstring_view operator*() const noexcept + { + return static_cast<::fast_io::containers::details::str_btree_set_node const *>(node.ptr)->keys[node.pos].strvw(); + } +}; + +template <::std::integral chtype, ::std::size_t keys_number> +inline constexpr bool operator==(::fast_io::containers::details::str_btree_set_iterator a, + ::fast_io::containers::details::str_btree_set_iterator b) noexcept +{ + return a.node.ptr == b.node.ptr && a.node.n == b.node.n; +} + +template <::std::integral chtype, ::std::size_t keys_number> +inline constexpr bool operator!=(::fast_io::containers::details::str_btree_set_iterator a, + ::fast_io::containers::details::str_btree_set_iterator b) noexcept +{ + return !operator==(a, b); +} + } // namespace details template <::std::integral chtype, typename Allocator, ::std::size_t keys_number = 16> From a3ef4f9e73ffbca13fe1a2bc3854edf27fbc6d34 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Mon, 14 Jul 2025 00:38:28 +0800 Subject: [PATCH 52/81] [str_btree_set] str_btree_set add leftmost and rightmost --- include/fast_io_dsal/impl/str_btree_set.h | 189 +++++++++------------- 1 file changed, 73 insertions(+), 116 deletions(-) diff --git a/include/fast_io_dsal/impl/str_btree_set.h b/include/fast_io_dsal/impl/str_btree_set.h index 17d3b0594..d79d4f691 100644 --- a/include/fast_io_dsal/impl/str_btree_set.h +++ b/include/fast_io_dsal/impl/str_btree_set.h @@ -5,10 +5,11 @@ namespace fast_io::containers namespace details { -struct btree_node_common +struct btree_imp { void *root; - void *next; + void *leftmost; + void *rightmost; }; template <::std::integral chtype, ::std::size_t keys_number> @@ -43,65 +44,6 @@ struct find_btree_node_insert_position_result ::std::size_t pos{}; bool found{}; }; -#if 0 -template -inline constexpr find_btree_node_insert_position_result find_str_btree_node_insert_position(nodetype *node, - typename nodetype::char_type const *keystrptr, ::std::size_t keystrn) noexcept -{ - using char_type = typename nodetype::char_type; - auto *b{node->keys}; - ::std::size_t size{node->size}; - - ::fast_io::containers::basic_string_view newkey(keystrptr, keystrn); - - bool found {}; - - // Threshold for using linear search; adjust as needed for performance - constexpr ::std::size_t linear_threshold{4}; - - if (size < linear_threshold) - { - // Linear search for small nodes - auto *i = b; - auto *e = b + size; - for (; i != e; ++i) - { - auto cmpres = newkey <=> i->strvw(); - if (cmpres <= 0) - { - found = (cmpres == 0); - return {static_cast<::std::size_t>(i - b), found}; - } - } - return {size, false}; // Key goes at the end - } - - - // Binary search for larger nodes - ::std::size_t left = 0, right = size; - while (left < right) - { - ::std::size_t mid = left + (right - left) / 2; - auto cmpres = newkey <=> b[mid].strvw(); - if (cmpres < 0) - { - right = mid; - } - else if (0 < cmpres) - { - left = mid + 1; - } - else - { - found = true; - right = mid; // Insert position should be at the first equal key - } - } - - return {left, found}; -} - -#else template inline constexpr find_btree_node_insert_position_result find_str_btree_node_insert_position(nodetype *node, @@ -125,8 +67,6 @@ inline constexpr find_btree_node_insert_position_result find_str_btree_node_inse return {static_cast<::std::size_t>(i - b), found}; } -#endif - template inline constexpr bool str_btree_contains(nodetype *node, typename nodetype::char_type const *keystrptr, ::std::size_t keystrn) noexcept { @@ -154,48 +94,30 @@ inline constexpr bool str_btree_contains(nodetype *node, typename nodetype::char } template -inline constexpr bool str_btree_insert_key(nodetype *node, - typename nodetype::char_type const *keystrptr, ::std::size_t keystrn, nodetype **proot) noexcept +#if __has_cpp_attribute(__gnu__::__cold__) +[[__gnu__::__cold__]] +#endif +inline constexpr bool str_btree_insert_key_cold(nodetype *node, ::std::size_t pos, + typename nodetype::char_type const *tempkeystrptr, ::std::size_t tempkeystrn, + ::fast_io::containers::details::btree_imp &imp) noexcept { using char_type = typename nodetype::char_type; using typed_allocator_type = ::fast_io::typed_generic_allocator_adapter; - ::std::size_t pos; - // **Find the correct position for insertion** - for (;;) - { - auto [postemp, found] = find_str_btree_node_insert_position(node, keystrptr, keystrn); - pos = postemp; - // **If the key already exists, return false (no duplicate keys)** - if (found) - { - return false; - } - // **If the node is a leaf** - if (node->leaf) - { - break; - } - node = node->childrens[pos]; - } - auto tempkey = ::fast_io::details::create_associative_string(keystrptr, keystrn); + auto keys{node->keys}; auto n{node->size}; auto keysit{keys + pos}; auto keysed{keys + keys_number}; - // **If there is space, insert the key directly** - if (n != keys_number) - { - ::fast_io::freestanding::overlapped_copy(keysit, keys + n, keysit + 1); - *keysit = tempkey; - ++node->size; - return true; - } constexpr ::std::size_t keys_number_half{keys_number >> (1u)}; constexpr ::std::size_t keys_number_half_p1{keys_number_half + 1u}; // ** Split now auto rightchild{typed_allocator_type::allocate(1)}; + if (node == imp.rightmost) + { + imp.rightmost = rightchild; + } node->leaf = rightchild->leaf = true; node->size = rightchild->size = keys_number_half; @@ -215,13 +137,13 @@ inline constexpr bool str_btree_insert_key(nodetype *node, ::fast_io::details::non_overlapped_copy_n(midptr, keys_number_half, rightchildkeys); ::fast_io::freestanding::overlapped_copy(keys + pos, keys + keys_number_half, keys + pos + 1); - keys[pos] = tempkey; + keys[pos] = {tempkeystrptr, tempkeystrn}; } else if (poskeys_number_halfcmp == 0) { ::fast_io::details::non_overlapped_copy_n(midptr, keys_number_half, rightchildkeys); - movekeystrptr = tempkey.ptr; - movekeystrn = tempkey.n; + movekeystrptr = tempkeystrptr; + movekeystrn = tempkeystrn; } else { @@ -229,7 +151,7 @@ inline constexpr bool str_btree_insert_key(nodetype *node, movekeystrptr = keystrptrkeysnumber.ptr; movekeystrn = keystrptrkeysnumber.n; auto it{::fast_io::details::non_overlapped_copy(midptr + 1, keysit, rightchildkeys)}; - *it = tempkey; + *it = {tempkeystrptr, tempkeystrn}; ++it; ::fast_io::details::non_overlapped_copy(keysit, keysed, it); } @@ -349,18 +271,19 @@ inline constexpr bool str_btree_insert_key(nodetype *node, node->parent_pos = 0; rightchild->parent = new_root; rightchild->parent_pos = 1; - *proot = new_root; + imp.root = new_root; return true; } template -inline constexpr bool str_btree_insert_key_with_root(nodetype **proot, +inline constexpr bool str_btree_insert_key_with_root(::fast_io::containers::details::btree_imp &imp, typename nodetype::char_type const *keystrptr, ::std::size_t keystrn) noexcept { + using char_type = typename nodetype::char_type; using typed_allocator_type = ::fast_io::typed_generic_allocator_adapter; - auto node{*proot}; + auto node{static_cast<::fast_io::containers::details::str_btree_set_node *>(imp.root)}; // **If the tree is empty, allocate a new root** if (node == nullptr) @@ -370,17 +293,50 @@ inline constexpr bool str_btree_insert_key_with_root(nodetype **proot, node->leaf = true; node->parent = nullptr; node->parent_pos = 0; - *(node->keys) = ::fast_io::details::create_associative_string(keystrptr, keystrn); - *proot = node; + *(node->keys) = ::fast_io::details::create_associative_string(keystrptr, keystrn); + imp.rightmost = imp.leftmost = imp.root = node; + return true; + } + + ::std::size_t pos; + // **Find the correct position for insertion** + for (;;) + { + auto [postemp, found] = find_str_btree_node_insert_position(node, keystrptr, keystrn); + pos = postemp; + // **If the key already exists, return false (no duplicate keys)** + if (found) + { + return false; + } + // **If the node is a leaf** + if (node->leaf) + { + break; + } + node = node->childrens[pos]; + } + + auto tempkey = ::fast_io::details::create_associative_string(keystrptr, keystrn); + auto n{node->size}; + // **If there is space, insert the key directly** + if (n != keys_number) + { + auto keys{node->keys}; + auto keysit{keys + pos}; + ::fast_io::freestanding::overlapped_copy(keysit, keys + n, keysit + 1); + *keysit = tempkey; + ++node->size; return true; } - return ::fast_io::containers::details::str_btree_insert_key(node, keystrptr, keystrn, proot); + return ::fast_io::containers::details::str_btree_insert_key_cold(node, pos, tempkey.ptr, tempkey.n, imp); } struct str_btree_set_iterator_common { void const *ptr{}; ::std::size_t pos{}; + void const *last{}; }; template <::std::size_t keys_number> @@ -427,7 +383,7 @@ class str_btree_set_iterator constexpr str_btree_set_iterator &operator++() noexcept { - ::fast_io::containers::details::str_btree_set_next_node(node); + ::fast_io::containers::details::str_btree_set_next_node(this->node); return *this; } constexpr str_btree_set_iterator operator++(int) noexcept @@ -472,7 +428,7 @@ class basic_str_btree_set using cstring_view_type = ::fast_io::containers::basic_cstring_view; using allocator_type = Allocator; - node_type *root{}; + ::fast_io::containers::details::btree_imp imp{nullptr, nullptr, nullptr}; constexpr basic_str_btree_set() noexcept = default; @@ -486,11 +442,11 @@ class basic_str_btree_set constexpr bool contains(string_view_type strvw) const noexcept { - return ::fast_io::containers::details::str_btree_contains(this->root, strvw.ptr, strvw.n); + return ::fast_io::containers::details::str_btree_contains(static_cast(this->imp.root), strvw.ptr, strvw.n); } constexpr bool is_empty() const noexcept { - return root == nullptr; + return this->imp.root == nullptr; } constexpr bool erase_key(string_view_type) noexcept { @@ -498,12 +454,13 @@ class basic_str_btree_set } constexpr bool insert_key(string_view_type strvw) noexcept { - return ::fast_io::containers::details::str_btree_insert_key_with_root(__builtin_addressof(this->root), strvw.ptr, strvw.n); + return ::fast_io::containers::details::str_btree_insert_key_with_root(this->imp, strvw.ptr, strvw.n); } private: - static inline constexpr void clear_node(node_type *node) noexcept + static inline constexpr void clear_node(void *nodev) noexcept { + auto node{static_cast(nodev)}; if (node == nullptr) { return; @@ -530,8 +487,8 @@ class basic_str_btree_set public: constexpr void clear() noexcept { - clear_node(this->root); - this->root = nullptr; + clear_node(this->imp.root); + this->imp = {nullptr, nullptr, nullptr}; } constexpr void clear_destroy() noexcept @@ -542,23 +499,23 @@ class basic_str_btree_set constexpr basic_str_btree_set(basic_str_btree_set const &) noexcept = delete; constexpr basic_str_btree_set &operator=(basic_str_btree_set const &) noexcept = delete; - constexpr basic_str_btree_set(basic_str_btree_set &&other) noexcept : root{other.root} + constexpr basic_str_btree_set(basic_str_btree_set &&other) noexcept : imp(other.imp) { - other.root = nullptr; + other.imp = {nullptr, nullptr, nullptr}; } constexpr basic_str_btree_set &operator=(basic_str_btree_set &&other) noexcept { - if (::std::addressof(other) == this) + if (__builtin_addressof(other) == this) { return *this; } - this->root = other.root; - other.root = nullptr; + this->imp = other.imp; + other.imp = {nullptr, nullptr, nullptr}; return *this; } constexpr ~basic_str_btree_set() { - clear_node(this->root); + clear_node(this->imp.root); } }; From 3429902421c87189a6e9dc222248a5a1ac8a723d Mon Sep 17 00:00:00 2001 From: trcrsired Date: Mon, 14 Jul 2025 09:21:18 +0800 Subject: [PATCH 53/81] [str_tree_set] implement str_btree iterator --- include/fast_io_dsal/impl/str_btree_set.h | 182 ++++++++++++++++-- .../0013.str_btree_set/str_btree_set_rd.cc | 96 +++++---- 2 files changed, 211 insertions(+), 67 deletions(-) diff --git a/include/fast_io_dsal/impl/str_btree_set.h b/include/fast_io_dsal/impl/str_btree_set.h index d79d4f691..fd3265d19 100644 --- a/include/fast_io_dsal/impl/str_btree_set.h +++ b/include/fast_io_dsal/impl/str_btree_set.h @@ -332,33 +332,40 @@ inline constexpr bool str_btree_insert_key_with_root(::fast_io::containers::deta return ::fast_io::containers::details::str_btree_insert_key_cold(node, pos, tempkey.ptr, tempkey.n, imp); } +/* Common structure used for str_btree_set iterator. +Holds the current node pointer, position within node, and optional 'last' for reversed iteration fallback. */ struct str_btree_set_iterator_common { - void const *ptr{}; - ::std::size_t pos{}; - void const *last{}; + void const *ptr{}; // Pointer to current node + std::size_t pos{}; // Position within current node + void const *last{}; // Pointer to last node (used for -- from end) }; +/* Advances the iterator to the next key in str_btree_set. +Traverses leaf nodes linearly, and climbs up the parent chain when leaf ends. +For internal nodes, descends leftmost into the right child. */ template <::std::size_t keys_number> inline constexpr void str_btree_set_next_node(str_btree_set_iterator_common &c) noexcept { auto ptrv{static_cast<::fast_io::containers::details::str_btree_set_common const *>(c.ptr)}; - auto leaf{ptrv->leaf}; - if (leaf) + if (ptrv->leaf) { + // Move to next key inside leaf if (++c.pos == ptrv->size) { + // Reached end of leaf, climb parent chain to find next sibling auto parent{ptrv->parent}; - auto parent_pos{ptrv->parent_pos}; - for (; parent; parent = ptrv->parent) + auto parent_pos{static_cast<::fast_io::containers::details::str_btree_set_common const *>(ptrv)->parent_pos}; + while (parent) { - auto parentn{parent->size}; + auto parentn{static_cast<::fast_io::containers::details::str_btree_set_common const *>(parent)->size}; if (parent_pos != parentn) { - break; + break; // Found next available key in parent } - parent_pos = ptrv->parent_pos; + parent_pos = static_cast<::fast_io::containers::details::str_btree_set_common const *>(parent)->parent_pos; + parent = static_cast<::fast_io::containers::details::str_btree_set_common const *>(parent)->parent; } c.ptr = parent; c.pos = parent_pos; @@ -366,19 +373,85 @@ inline constexpr void str_btree_set_next_node(str_btree_set_iterator_common &c) } else { + // Internal node: descend into leftmost key of right child auto nextptr{ptrv->childrens[c.pos + 1]}; - for (; !nextptr->leaf; nextptr = *ptrv->childrens) + while (!static_cast<::fast_io::containers::details::str_btree_set_common const *>(nextptr)->leaf) { + nextptr = *(static_cast<::fast_io::containers::details::str_btree_set_common const *>(nextptr)->childrens); } c.ptr = nextptr; c.pos = 0; } } +/* Moves the iterator to the previous key in str_btree_set. +From null (end), restores last node. In leaf, moves left or climbs parent. +For internal node, descends rightmost into the left child. */ +template <::std::size_t keys_number> +inline constexpr void str_btree_set_prev_node(str_btree_set_iterator_common &c) noexcept +{ + if (c.ptr == nullptr) + { + // Iterator was at end(); fallback to last node if known + c.ptr = c.last; + c.pos = 0; + if (c.ptr) + { + // Set to last key of last node + c.pos = static_cast<::std::size_t>(static_cast<::fast_io::containers::details::str_btree_set_common const *>(c.ptr)->size - 1u); + } + return; + } + + auto ptrv{static_cast<::fast_io::containers::details::str_btree_set_common const *>(c.ptr)}; + + if (ptrv->leaf) + { + if (!c.pos) + { + // Start of leaf, need to go up to parent and find left sibling + auto parent{ptrv->parent}; + auto parent_pos{static_cast<::fast_io::containers::details::str_btree_set_common const *>(ptrv)->parent_pos}; + while (parent) + { + if (parent_pos) + { + break; // Found non-zero position in parent + } + parent_pos = static_cast<::std::size_t>(static_cast<::fast_io::containers::details::str_btree_set_common const *>(parent)->parent_pos); + parent = static_cast<::fast_io::containers::details::str_btree_set_common const *>(parent)->parent; + } + c.ptr = parent; + c.pos = 0; + if (parent) + { + c.pos = static_cast<::std::size_t>(parent_pos - 1u); + } + return; + } + --c.pos; // Move left inside leaf + } + else + { + // Internal node: descend into rightmost key of left child + auto prevptr{ptrv->childrens[c.pos]}; + while (!static_cast<::fast_io::containers::details::str_btree_set_common const *>(prevptr)->leaf) + { + auto e{static_cast<::fast_io::containers::details::str_btree_set_common const *>(prevptr)}; + prevptr = e->childrens[e->size - 1u]; + } + c.ptr = prevptr; + c.pos = static_cast<::std::size_t>(static_cast<::fast_io::containers::details::str_btree_set_common const *>(c.ptr)->size - 1u); + } +} + template <::std::integral chtype, ::std::size_t keys_number> class str_btree_set_iterator { public: + using value_type = ::fast_io::containers::basic_cstring_view; + using iterator_tag = ::std::bidirectional_iterator_tag; + using difference_type = ::std::ptrdiff_t; ::fast_io::containers::details::str_btree_set_iterator_common node; constexpr str_btree_set_iterator &operator++() noexcept @@ -392,22 +465,33 @@ class str_btree_set_iterator ++*this; return tmp; } - constexpr ::fast_io::containers::basic_cstring_view operator*() const noexcept + constexpr str_btree_set_iterator &operator--() noexcept + { + ::fast_io::containers::details::str_btree_set_prev_node(this->node); + return *this; + } + constexpr str_btree_set_iterator operator--(int) noexcept + { + auto tmp{*this}; + --*this; + return tmp; + } + constexpr value_type operator*() const noexcept { return static_cast<::fast_io::containers::details::str_btree_set_node const *>(node.ptr)->keys[node.pos].strvw(); } }; template <::std::integral chtype, ::std::size_t keys_number> -inline constexpr bool operator==(::fast_io::containers::details::str_btree_set_iterator a, - ::fast_io::containers::details::str_btree_set_iterator b) noexcept +inline constexpr bool operator==(::fast_io::containers::details::str_btree_set_iterator const &a, + ::fast_io::containers::details::str_btree_set_iterator const &b) noexcept { - return a.node.ptr == b.node.ptr && a.node.n == b.node.n; + return a.node.ptr == b.node.ptr && a.node.pos == b.node.pos; } template <::std::integral chtype, ::std::size_t keys_number> -inline constexpr bool operator!=(::fast_io::containers::details::str_btree_set_iterator a, - ::fast_io::containers::details::str_btree_set_iterator b) noexcept +inline constexpr bool operator!=(::fast_io::containers::details::str_btree_set_iterator const &a, + ::fast_io::containers::details::str_btree_set_iterator const &b) noexcept { return !operator==(a, b); } @@ -427,6 +511,10 @@ class basic_str_btree_set using string_view_type = ::fast_io::containers::basic_string_view; using cstring_view_type = ::fast_io::containers::basic_cstring_view; using allocator_type = Allocator; + using const_iterator = ::fast_io::containers::details::str_btree_set_iterator; + using iterator = const_iterator; + using const_reverse_iterator = ::std::reverse_iterator; + using reverse_iterator = const_reverse_iterator; ::fast_io::containers::details::btree_imp imp{nullptr, nullptr, nullptr}; @@ -513,6 +601,66 @@ class basic_str_btree_set other.imp = {nullptr, nullptr, nullptr}; return *this; } + constexpr const_iterator cbegin() const noexcept + { + return {this->imp.leftmost, 0, this->imp.rightmost}; + } + + constexpr const_iterator cend() const noexcept + { + return {nullptr, 0, this->imp.rightmost}; + } + constexpr const_iterator begin() const noexcept + { + return this->cbegin(); + } + constexpr const_iterator end() const noexcept + { + return this->cend(); + } + + constexpr const_reverse_iterator crbegin() const noexcept + { + return reverse_iterator(cend()); + } + + constexpr const_reverse_iterator crend() const noexcept + { + return reverse_iterator(cbegin()); + } + constexpr const_reverse_iterator rbegin() const noexcept + { + return this->crbegin(); + } + constexpr const_reverse_iterator rend() const noexcept + { + return this->crend(); + } + constexpr cstring_view_type front() const noexcept + { + if (this->imp.leftmost == nullptr) [[unlikely]] + { + ::fast_io::fast_terminate(); + } + return this->front_unchecked(); + } + constexpr cstring_view_type back() const noexcept + { + if (this->imp.rightmost == nullptr) [[unlikely]] + { + ::fast_io::fast_terminate(); + } + return this->back_unchecked(); + } + constexpr cstring_view_type front_unchecked() const noexcept + { + return static_cast<::fast_io::containers::details::str_btree_set_node const *>(this->imp.leftmost)->keys->strvw(); + } + constexpr cstring_view_type back_unchecked() const noexcept + { + auto &e{*static_cast<::fast_io::containers::details::str_btree_set_node const *>(this->imp.rightmost)}; + return e.keys[e.size - 1u].strvw(); + } constexpr ~basic_str_btree_set() { clear_node(this->imp.root); diff --git a/tests/0026.container/0013.str_btree_set/str_btree_set_rd.cc b/tests/0026.container/0013.str_btree_set/str_btree_set_rd.cc index 3c4fc55ef..70027a626 100644 --- a/tests/0026.container/0013.str_btree_set/str_btree_set_rd.cc +++ b/tests/0026.container/0013.str_btree_set/str_btree_set_rd.cc @@ -1,13 +1,13 @@ -#include -#include -#include -#include +#include +#include +#if 0 template <::std::integral chtype, ::std::size_t keys_number> inline constexpr void str_btree_set_inorder_traverse( ::fast_io::containers::details::str_btree_set_node *node, auto &&callback) noexcept { +// ::fast_io::io::debug_println(::std::source_location::current()," node->size=",node->size, " node->leaf=",node->leaf); if (node == nullptr) { return; @@ -20,10 +20,11 @@ inline constexpr void str_btree_set_inorder_traverse( { str_btree_set_inorder_traverse(node->childrens[i], callback); } - +// ::fast_io::io::debug_println(::std::source_location::current()," node->size=",node->size, " node->leaf=",node->leaf, " i=",i); // **Visit current key** callback(node->keys[i].strvw()); } +// ::fast_io::io::debug_println(::std::source_location::current()," node->size=",node->size, " node->leaf=",node->leaf); // **Traverse rightmost subtree** if (!node->leaf) @@ -31,55 +32,50 @@ inline constexpr void str_btree_set_inorder_traverse( str_btree_set_inorder_traverse(node->childrens[node->size], callback); } } - +#endif int main() { - ::fast_io::containers::basic_str_btree_set bset; - bset.insert_key("kiwi"); - bset.insert_key("ugli"); - bset.insert_key("lemon"); - bset.insert_key("fig"); - bset.insert_key("zucchini"); - bset.insert_key("honeydew"); - bset.insert_key("raspberry"); - bset.insert_key("orange"); - bset.insert_key("vanilla"); - bset.insert_key("yellowfruit"); - bset.insert_key("date"); - bset.insert_key("grape"); - bset.insert_key("strawberry"); + ::fast_io::str_btree_set bset; + constexpr ::fast_io::string_view fruits[]{ + ::fast_io::string_view("kiwi"), + ::fast_io::string_view("ugli"), + ::fast_io::string_view("lemon"), + ::fast_io::string_view("fig"), + ::fast_io::string_view("zucchini"), + ::fast_io::string_view("honeydew"), + ::fast_io::string_view("raspberry"), + ::fast_io::string_view("orange"), + ::fast_io::string_view("vanilla"), + ::fast_io::string_view("yellowfruit"), + ::fast_io::string_view("date"), + ::fast_io::string_view("grape"), + ::fast_io::string_view("strawberry"), + ::fast_io::string_view("cherry"), + ::fast_io::string_view("quince"), + ::fast_io::string_view("apple"), + ::fast_io::string_view("elderberry"), + ::fast_io::string_view("banana"), + ::fast_io::string_view("nectarine"), + ::fast_io::string_view("watermelon"), + ::fast_io::string_view("xigua"), + ::fast_io::string_view("papaya"), + ::fast_io::string_view("mango")}; - ::fast_io::io::println(::std::source_location::current()); - str_btree_set_inorder_traverse(bset.root, [](::fast_io::string_view v) { - ::fast_io::io::println(v); - }); - ::fast_io::io::print("\n\n"); - bset.insert_key("cherry"); - bset.insert_key("quince"); - bset.insert_key("apple"); - bset.insert_key("elderberry"); - bset.insert_key("banana"); + for (auto const &e : fruits) + { + bset.insert_key(e); + } - ::fast_io::io::println(::std::source_location::current()); - str_btree_set_inorder_traverse(bset.root, [](::fast_io::string_view v) { - ::fast_io::io::println(v); - }); - ::fast_io::io::print("\n\n"); + for (auto const &e : bset) + { + ::fast_io::io::println(e); + } - bset.insert_key("nectarine"); - ::fast_io::io::println(::std::source_location::current()); - str_btree_set_inorder_traverse(bset.root, [](::fast_io::string_view v) { - ::fast_io::io::println(v); - }); - ::fast_io::io::print("\n\n"); - bset.insert_key("watermelon"); - bset.insert_key("xigua"); - bset.insert_key("papaya"); - bset.insert_key("mango"); + ::fast_io::io::print("\nreverse:\n"); + for (auto const &e : ::std::ranges::reverse_view(bset)) + { + ::fast_io::io::println(e); + } - ::fast_io::io::println(::std::source_location::current()); - str_btree_set_inorder_traverse(bset.root, [](::fast_io::string_view v) { - ::fast_io::io::println(v); - }); - ::fast_io::io::print("\n\n"); + ::fast_io::io::println("\nfront()=", bset.front(), "\tback()=", bset.back()); } From 78aaf15344443037f1f1f83345ed46c7bc119608 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Mon, 14 Jul 2025 10:10:14 +0800 Subject: [PATCH 54/81] [str_btree_set] add benchmarks for iteration --- .../str_btree_set/abseil_btree_set.cc | 11 ++++++++++ .../0011.containers/str_btree_set/std_set.cc | 22 +++++++++++++++++++ .../str_btree_set/std_set_fast_io.cc | 22 +++++++++++++++++++ .../str_btree_set/str_btree_set.cc | 22 +++++++++++++++++++ 4 files changed, 77 insertions(+) diff --git a/benchmark/0011.containers/str_btree_set/abseil_btree_set.cc b/benchmark/0011.containers/str_btree_set/abseil_btree_set.cc index 9c51c3229..dae68c8b8 100644 --- a/benchmark/0011.containers/str_btree_set/abseil_btree_set.cc +++ b/benchmark/0011.containers/str_btree_set/abseil_btree_set.cc @@ -29,4 +29,15 @@ int main() } ::fast_io::io::perrln("count=", count); } + { + ::std::size_t total_size{}; + { + ::fast_io::timer t(u8"iteration"); + for (auto const &e : bset) + { + total_size += e.size(); + } + } + ::fast_io::io::perrln("total_size=", total_size); + } } diff --git a/benchmark/0011.containers/str_btree_set/std_set.cc b/benchmark/0011.containers/str_btree_set/std_set.cc index d0647857b..cf79e6e05 100644 --- a/benchmark/0011.containers/str_btree_set/std_set.cc +++ b/benchmark/0011.containers/str_btree_set/std_set.cc @@ -27,4 +27,26 @@ int main() } ::fast_io::io::perrln("count=", count); } + { + ::std::size_t total_size{}; + { + ::fast_io::timer t(u8"iteration"); + for (auto const &e : bset) + { + total_size += e.size(); + } + } + ::fast_io::io::perrln("total_size=", total_size); + } + { + ::std::size_t total_size{}; + { + ::fast_io::timer t(u8"reverse iteration"); + for (auto const &e : ::std::ranges::reverse_view(bset)) + { + total_size += e.size(); + } + } + ::fast_io::io::perrln("total_size=", total_size); + } } diff --git a/benchmark/0011.containers/str_btree_set/std_set_fast_io.cc b/benchmark/0011.containers/str_btree_set/std_set_fast_io.cc index 81ed12865..373708101 100644 --- a/benchmark/0011.containers/str_btree_set/std_set_fast_io.cc +++ b/benchmark/0011.containers/str_btree_set/std_set_fast_io.cc @@ -27,4 +27,26 @@ int main() } ::fast_io::io::perrln("count=", count); } + { + ::std::size_t total_size{}; + { + ::fast_io::timer t(u8"iteration"); + for (auto const &e : bset) + { + total_size += e.size(); + } + } + ::fast_io::io::perrln("total_size=", total_size); + } + { + ::std::size_t total_size{}; + { + ::fast_io::timer t(u8"reverse iteration"); + for (auto const &e : ::std::ranges::reverse_view(bset)) + { + total_size += e.size(); + } + } + ::fast_io::io::perrln("total_size=", total_size); + } } \ No newline at end of file diff --git a/benchmark/0011.containers/str_btree_set/str_btree_set.cc b/benchmark/0011.containers/str_btree_set/str_btree_set.cc index 76a6434b9..659b03db0 100644 --- a/benchmark/0011.containers/str_btree_set/str_btree_set.cc +++ b/benchmark/0011.containers/str_btree_set/str_btree_set.cc @@ -26,4 +26,26 @@ int main() } ::fast_io::io::perrln("count=", count); } + { + ::std::size_t total_size{}; + { + ::fast_io::timer t(u8"iteration"); + for (auto const &e : bset) + { + total_size += e.size(); + } + } + ::fast_io::io::perrln("total_size=", total_size); + } + { + ::std::size_t total_size{}; + { + ::fast_io::timer t(u8"reverse iteration"); + for (auto const &e : ::std::ranges::reverse_view(bset)) + { + total_size += e.size(); + } + } + ::fast_io::io::perrln("total_size=", total_size); + } } \ No newline at end of file From 93101a2f47142cab00af6b2d0a725979f61e0314 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Mon, 14 Jul 2025 10:18:41 +0800 Subject: [PATCH 55/81] [str_btree_set] remove nullptr check for -- iterator --- include/fast_io_dsal/impl/str_btree_set.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/include/fast_io_dsal/impl/str_btree_set.h b/include/fast_io_dsal/impl/str_btree_set.h index fd3265d19..3443f572a 100644 --- a/include/fast_io_dsal/impl/str_btree_set.h +++ b/include/fast_io_dsal/impl/str_btree_set.h @@ -394,12 +394,8 @@ inline constexpr void str_btree_set_prev_node(str_btree_set_iterator_common &c) { // Iterator was at end(); fallback to last node if known c.ptr = c.last; - c.pos = 0; - if (c.ptr) - { - // Set to last key of last node - c.pos = static_cast<::std::size_t>(static_cast<::fast_io::containers::details::str_btree_set_common const *>(c.ptr)->size - 1u); - } + // c.ptr must not be nullptr or it is on empty container which is undefined behavior + c.pos = static_cast<::std::size_t>(static_cast<::fast_io::containers::details::str_btree_set_common const *>(c.ptr)->size - 1u); return; } From cac1b390544895292016433f5122e65868f84b89 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Mon, 14 Jul 2025 10:32:33 +0800 Subject: [PATCH 56/81] [str_btree_set] fix operator-- for iterator --- include/fast_io_dsal/impl/str_btree_set.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/fast_io_dsal/impl/str_btree_set.h b/include/fast_io_dsal/impl/str_btree_set.h index 3443f572a..f93aa466c 100644 --- a/include/fast_io_dsal/impl/str_btree_set.h +++ b/include/fast_io_dsal/impl/str_btree_set.h @@ -434,7 +434,7 @@ inline constexpr void str_btree_set_prev_node(str_btree_set_iterator_common &c) while (!static_cast<::fast_io::containers::details::str_btree_set_common const *>(prevptr)->leaf) { auto e{static_cast<::fast_io::containers::details::str_btree_set_common const *>(prevptr)}; - prevptr = e->childrens[e->size - 1u]; + prevptr = e->childrens[e->size]; } c.ptr = prevptr; c.pos = static_cast<::std::size_t>(static_cast<::fast_io::containers::details::str_btree_set_common const *>(c.ptr)->size - 1u); From 9bdb2bb982620e15f44da8fc199a8fb62f6fc466 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Mon, 14 Jul 2025 10:36:32 +0800 Subject: [PATCH 57/81] [str_btree_set] add iteration bench for abseil --- .../0011.containers/str_btree_set/abseil_btree_set.cc | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/benchmark/0011.containers/str_btree_set/abseil_btree_set.cc b/benchmark/0011.containers/str_btree_set/abseil_btree_set.cc index dae68c8b8..20f78a132 100644 --- a/benchmark/0011.containers/str_btree_set/abseil_btree_set.cc +++ b/benchmark/0011.containers/str_btree_set/abseil_btree_set.cc @@ -40,4 +40,15 @@ int main() } ::fast_io::io::perrln("total_size=", total_size); } + { + ::std::size_t total_size{}; + { + ::fast_io::timer t(u8"reverse iteration"); + for (auto const &e : ::std::ranges::reverse_view(bset)) + { + total_size += e.size(); + } + } + ::fast_io::io::perrln("total_size=", total_size); + } } From f638c412b9da1acefa0a36c249d63b9ee4070b8e Mon Sep 17 00:00:00 2001 From: trcrsired Date: Mon, 14 Jul 2025 10:40:22 +0800 Subject: [PATCH 58/81] [btree] add the bench to rust code --- .../str_btree_set/rustbtree/src/main.rs | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/benchmark/0011.containers/str_btree_set/rustbtree/src/main.rs b/benchmark/0011.containers/str_btree_set/rustbtree/src/main.rs index 955043c52..cf61a68b3 100644 --- a/benchmark/0011.containers/str_btree_set/rustbtree/src/main.rs +++ b/benchmark/0011.containers/str_btree_set/rustbtree/src/main.rs @@ -1,7 +1,7 @@ -use std::collections::BTreeSet; -use std::time::Instant; use rand::rngs::StdRng; use rand::{Rng, SeedableRng}; +use std::collections::BTreeSet; +use std::time::Instant; fn generate_test_data() -> Vec { let mut vec = Vec::with_capacity(1_000_000); @@ -48,6 +48,29 @@ fn main() { } } println!("contains: {:.2?}", start_contains.elapsed()); + // 🚀 Forward iteration benchmark + let mut total_size = 0; + let start_iter = Instant::now(); + for s in &bset { + total_size += s.len(); + } + println!( + "forward iteration total_size = {}, elapsed: {:.2?}", + total_size, + start_iter.elapsed() + ); + + // 🔄 Reverse iteration benchmark + let mut total_size = 0; + let start_rev_iter = Instant::now(); + for s in bset.iter().rev() { + total_size += s.len(); + } + println!( + "reverse iteration total_size = {}, elapsed: {:.2?}", + total_size, + start_rev_iter.elapsed() + ); println!("count = {}", count); println!("total time: {:.2?}", start_total.elapsed()); From 6e9aff9b18768b25099801363a796dbd3e458070 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Mon, 14 Jul 2025 11:17:06 +0800 Subject: [PATCH 59/81] [btree] add iteration bench for abseil_btree_set_fast_io --- .../str_btree_set/abseil_btree_set_fast_io.cc | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/benchmark/0011.containers/str_btree_set/abseil_btree_set_fast_io.cc b/benchmark/0011.containers/str_btree_set/abseil_btree_set_fast_io.cc index d2919a8db..ed8df2844 100644 --- a/benchmark/0011.containers/str_btree_set/abseil_btree_set_fast_io.cc +++ b/benchmark/0011.containers/str_btree_set/abseil_btree_set_fast_io.cc @@ -29,4 +29,26 @@ int main() } ::fast_io::io::perrln("count=", count); } + { + ::std::size_t total_size{}; + { + ::fast_io::timer t(u8"iteration"); + for (auto const &e : bset) + { + total_size += e.size(); + } + } + ::fast_io::io::perrln("total_size=", total_size); + } + { + ::std::size_t total_size{}; + { + ::fast_io::timer t(u8"reverse iteration"); + for (auto const &e : ::std::ranges::reverse_view(bset)) + { + total_size += e.size(); + } + } + ::fast_io::io::perrln("total_size=", total_size); + } } \ No newline at end of file From f9905d1b2527313bc7c86189cfb8de68d23b2b32 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Mon, 14 Jul 2025 19:10:59 +0800 Subject: [PATCH 60/81] [str_btree_set] add find method --- include/fast_io_dsal/impl/str_btree_set.h | 54 ++++++++++- .../0013.str_btree_set/str_btree_set.cc | 90 ++++++++----------- .../0013.str_btree_set/str_btree_set_rd.cc | 81 ----------------- .../str_btree_set_reverse.cc | 72 --------------- 4 files changed, 87 insertions(+), 210 deletions(-) delete mode 100644 tests/0026.container/0013.str_btree_set/str_btree_set_rd.cc delete mode 100644 tests/0026.container/0013.str_btree_set/str_btree_set_reverse.cc diff --git a/include/fast_io_dsal/impl/str_btree_set.h b/include/fast_io_dsal/impl/str_btree_set.h index f93aa466c..b3913e146 100644 --- a/include/fast_io_dsal/impl/str_btree_set.h +++ b/include/fast_io_dsal/impl/str_btree_set.h @@ -46,8 +46,8 @@ struct find_btree_node_insert_position_result }; template -inline constexpr find_btree_node_insert_position_result find_str_btree_node_insert_position(nodetype *node, - typename nodetype::char_type const *keystrptr, ::std::size_t keystrn) noexcept +inline constexpr ::fast_io::containers::details::find_btree_node_insert_position_result find_str_btree_node_insert_position(nodetype *node, + typename nodetype::char_type const *keystrptr, ::std::size_t keystrn) noexcept { using char_type = typename nodetype::char_type; auto *b{node->keys}, *i{b}, *e{b + node->size}; @@ -67,6 +67,39 @@ inline constexpr find_btree_node_insert_position_result find_str_btree_node_inse return {static_cast<::std::size_t>(i - b), found}; } + +struct find_btree_insert_result +{ + void *node{}; + ::std::size_t pos{}; +}; + +template +inline constexpr ::fast_io::containers::details::find_btree_insert_result str_btree_find(nodetype *node, typename nodetype::char_type const *keystrptr, ::std::size_t keystrn) noexcept +{ + if (node == nullptr) + { + return {}; + } + // **Find the correct position for insertion** + for (;;) + { + auto [postemp, found] = ::fast_io::containers::details::find_str_btree_node_insert_position(node, keystrptr, keystrn); + // **If the key already exists, return false (no duplicate keys)** + if (found) + { + return {node, postemp}; + } + // **If the node is a leaf** + if (node->leaf) + { + break; + } + node = node->childrens[postemp]; + } + return {}; +} + template inline constexpr bool str_btree_contains(nodetype *node, typename nodetype::char_type const *keystrptr, ::std::size_t keystrn) noexcept { @@ -77,7 +110,7 @@ inline constexpr bool str_btree_contains(nodetype *node, typename nodetype::char // **Find the correct position for insertion** for (;;) { - auto [postemp, found] = find_str_btree_node_insert_position(node, keystrptr, keystrn); + auto [postemp, found] = ::fast_io::containers::details::find_str_btree_node_insert_position(node, keystrptr, keystrn); // **If the key already exists, return false (no duplicate keys)** if (found) { @@ -302,7 +335,7 @@ inline constexpr bool str_btree_insert_key_with_root(::fast_io::containers::deta // **Find the correct position for insertion** for (;;) { - auto [postemp, found] = find_str_btree_node_insert_position(node, keystrptr, keystrn); + auto [postemp, found] = ::fast_io::containers::details::find_str_btree_node_insert_position(node, keystrptr, keystrn); pos = postemp; // **If the key already exists, return false (no duplicate keys)** if (found) @@ -511,6 +544,8 @@ class basic_str_btree_set using iterator = const_iterator; using const_reverse_iterator = ::std::reverse_iterator; using reverse_iterator = const_reverse_iterator; + using size_type = ::std::size_t; + using difference_type = ::std::ptrdiff_t; ::fast_io::containers::details::btree_imp imp{nullptr, nullptr, nullptr}; @@ -528,14 +563,25 @@ class basic_str_btree_set { return ::fast_io::containers::details::str_btree_contains(static_cast(this->imp.root), strvw.ptr, strvw.n); } + constexpr size_type count(string_view_type strvw) const noexcept + { + return static_cast(this->contains(strvw)); + } + constexpr const_iterator find(string_view_type strvw) const noexcept + { + auto [ptr, pos] = ::fast_io::containers::details::str_btree_find(static_cast(this->imp.root), strvw.ptr, strvw.n); + return {ptr, pos, this->imp.rightmost}; + } constexpr bool is_empty() const noexcept { return this->imp.root == nullptr; } +#if 0 constexpr bool erase_key(string_view_type) noexcept { return false; } +#endif constexpr bool insert_key(string_view_type strvw) noexcept { return ::fast_io::containers::details::str_btree_insert_key_with_root(this->imp, strvw.ptr, strvw.n); diff --git a/tests/0026.container/0013.str_btree_set/str_btree_set.cc b/tests/0026.container/0013.str_btree_set/str_btree_set.cc index e0d4bd29b..064b53b89 100644 --- a/tests/0026.container/0013.str_btree_set/str_btree_set.cc +++ b/tests/0026.container/0013.str_btree_set/str_btree_set.cc @@ -1,66 +1,50 @@ + #include -#include -#include -#include +#include -template <::std::integral chtype, ::std::size_t keys_number> -inline constexpr void str_btree_set_inorder_traverse( - ::fast_io::containers::details::str_btree_set_node *node, - auto &&callback) noexcept +int main() { - if (node == nullptr) + ::fast_io::str_btree_set bset; + constexpr ::fast_io::string_view fruits[]{ + ::fast_io::string_view("kiwi"), + ::fast_io::string_view("ugli"), + ::fast_io::string_view("lemon"), + ::fast_io::string_view("fig"), + ::fast_io::string_view("zucchini"), + ::fast_io::string_view("honeydew"), + ::fast_io::string_view("raspberry"), + ::fast_io::string_view("orange"), + ::fast_io::string_view("vanilla"), + ::fast_io::string_view("yellowfruit"), + ::fast_io::string_view("date"), + ::fast_io::string_view("grape"), + ::fast_io::string_view("strawberry"), + ::fast_io::string_view("cherry"), + ::fast_io::string_view("quince"), + ::fast_io::string_view("apple"), + ::fast_io::string_view("elderberry"), + ::fast_io::string_view("banana"), + ::fast_io::string_view("nectarine"), + ::fast_io::string_view("watermelon"), + ::fast_io::string_view("xigua"), + ::fast_io::string_view("papaya"), + ::fast_io::string_view("mango")}; + + for (auto const &e : fruits) { - return; + bset.insert_key(e); } - // **Traverse left subtree** - for (::std::size_t i{}; i != node->size; ++i) + for (auto const &e : bset) { - if (!node->leaf) - { - str_btree_set_inorder_traverse(node->childrens[i], callback); - } - - // **Visit current key** - callback(node->keys[i].strvw()); + ::fast_io::io::println(e); } - // **Traverse rightmost subtree** - if (!node->leaf) + ::fast_io::io::print("\nreverse:\n"); + for (auto const &e : ::std::ranges::reverse_view(bset)) { - str_btree_set_inorder_traverse(node->childrens[node->size], callback); + ::fast_io::io::println(e); } -} - -int main() -{ - ::fast_io::containers::basic_str_btree_set bset; - bset.insert_key("apple"); - bset.insert_key("banana"); - bset.insert_key("cherry"); - bset.insert_key("date"); - bset.insert_key("elderberry"); - bset.insert_key("fig"); - bset.insert_key("grape"); - bset.insert_key("honeydew"); - bset.insert_key("kiwi"); - bset.insert_key("lemon"); - bset.insert_key("mango"); - bset.insert_key("nectarine"); - bset.insert_key("orange"); - bset.insert_key("papaya"); - bset.insert_key("quince"); - bset.insert_key("raspberry"); - bset.insert_key("strawberry"); - bset.insert_key("tangerine"); - bset.insert_key("ugli"); - bset.insert_key("vanilla"); - bset.insert_key("watermelon"); - bset.insert_key("xigua"); - bset.insert_key("yellowfruit"); - bset.insert_key("zucchini"); - str_btree_set_inorder_traverse(bset.root, [](::fast_io::string_view v) { - ::fast_io::io::println(v); - }); + ::fast_io::io::println("\nfront()=", bset.front(), "\tback()=", bset.back()); } diff --git a/tests/0026.container/0013.str_btree_set/str_btree_set_rd.cc b/tests/0026.container/0013.str_btree_set/str_btree_set_rd.cc deleted file mode 100644 index 70027a626..000000000 --- a/tests/0026.container/0013.str_btree_set/str_btree_set_rd.cc +++ /dev/null @@ -1,81 +0,0 @@ - -#include -#include -#if 0 -template <::std::integral chtype, ::std::size_t keys_number> -inline constexpr void str_btree_set_inorder_traverse( - ::fast_io::containers::details::str_btree_set_node *node, - auto &&callback) noexcept -{ -// ::fast_io::io::debug_println(::std::source_location::current()," node->size=",node->size, " node->leaf=",node->leaf); - if (node == nullptr) - { - return; - } - - // **Traverse left subtree** - for (::std::size_t i{}; i != node->size; ++i) - { - if (!node->leaf) - { - str_btree_set_inorder_traverse(node->childrens[i], callback); - } -// ::fast_io::io::debug_println(::std::source_location::current()," node->size=",node->size, " node->leaf=",node->leaf, " i=",i); - // **Visit current key** - callback(node->keys[i].strvw()); - } -// ::fast_io::io::debug_println(::std::source_location::current()," node->size=",node->size, " node->leaf=",node->leaf); - - // **Traverse rightmost subtree** - if (!node->leaf) - { - str_btree_set_inorder_traverse(node->childrens[node->size], callback); - } -} -#endif -int main() -{ - ::fast_io::str_btree_set bset; - constexpr ::fast_io::string_view fruits[]{ - ::fast_io::string_view("kiwi"), - ::fast_io::string_view("ugli"), - ::fast_io::string_view("lemon"), - ::fast_io::string_view("fig"), - ::fast_io::string_view("zucchini"), - ::fast_io::string_view("honeydew"), - ::fast_io::string_view("raspberry"), - ::fast_io::string_view("orange"), - ::fast_io::string_view("vanilla"), - ::fast_io::string_view("yellowfruit"), - ::fast_io::string_view("date"), - ::fast_io::string_view("grape"), - ::fast_io::string_view("strawberry"), - ::fast_io::string_view("cherry"), - ::fast_io::string_view("quince"), - ::fast_io::string_view("apple"), - ::fast_io::string_view("elderberry"), - ::fast_io::string_view("banana"), - ::fast_io::string_view("nectarine"), - ::fast_io::string_view("watermelon"), - ::fast_io::string_view("xigua"), - ::fast_io::string_view("papaya"), - ::fast_io::string_view("mango")}; - - for (auto const &e : fruits) - { - bset.insert_key(e); - } - - for (auto const &e : bset) - { - ::fast_io::io::println(e); - } - - ::fast_io::io::print("\nreverse:\n"); - for (auto const &e : ::std::ranges::reverse_view(bset)) - { - ::fast_io::io::println(e); - } - - ::fast_io::io::println("\nfront()=", bset.front(), "\tback()=", bset.back()); -} diff --git a/tests/0026.container/0013.str_btree_set/str_btree_set_reverse.cc b/tests/0026.container/0013.str_btree_set/str_btree_set_reverse.cc deleted file mode 100644 index a591f1c28..000000000 --- a/tests/0026.container/0013.str_btree_set/str_btree_set_reverse.cc +++ /dev/null @@ -1,72 +0,0 @@ -#include -#include -#include -#include - -template <::std::integral chtype, ::std::size_t keys_number> -inline constexpr void str_btree_set_inorder_traverse( - ::fast_io::containers::details::str_btree_set_node *node, - auto &&callback) noexcept -{ - if (node == nullptr) - { - return; - } - - // **Traverse left subtree** - for (::std::size_t i{}; i != node->size; ++i) - { - if (!node->leaf) - { - str_btree_set_inorder_traverse(node->childrens[i], callback); - } - - // **Visit current key** - callback(node->keys[i].strvw()); - } - - // **Traverse rightmost subtree** - if (!node->leaf) - { - str_btree_set_inorder_traverse(node->childrens[node->size], callback); - } -} - -int main() -{ - ::fast_io::containers::basic_str_btree_set bset; - constexpr ::fast_io::string_view fruits[]{ - ::fast_io::string_view("zucchini"), - ::fast_io::string_view("yellowfruit"), - ::fast_io::string_view("xigua"), - ::fast_io::string_view("watermelon"), - ::fast_io::string_view("vanilla"), - ::fast_io::string_view("ugli"), - ::fast_io::string_view("tangerine"), - ::fast_io::string_view("strawberry"), - ::fast_io::string_view("raspberry"), - ::fast_io::string_view("quince"), - ::fast_io::string_view("papaya"), - ::fast_io::string_view("orange"), - ::fast_io::string_view("nectarine"), - ::fast_io::string_view("mango"), - ::fast_io::string_view("lemon"), - ::fast_io::string_view("kiwi"), - ::fast_io::string_view("grape"), - ::fast_io::string_view("fig"), - ::fast_io::string_view("elderberry"), - ::fast_io::string_view("date"), - ::fast_io::string_view("cherry"), - ::fast_io::string_view("banana"), - ::fast_io::string_view("apple"), - ::fast_io::string_view("honeydew")}; - - for (auto const &e : fruits) - { - bset.insert_key(e); - } - - str_btree_set_inorder_traverse(bset.root, [](::fast_io::string_view v) { - ::fast_io::io::println(v); - }); -} From 29e2bfa76f4568bef61bd34c888294025e14b4b0 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Mon, 14 Jul 2025 19:23:12 +0800 Subject: [PATCH 61/81] [str_btree_set] implement find() --- .../0013.str_btree_set/str_btree_set.cc | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/tests/0026.container/0013.str_btree_set/str_btree_set.cc b/tests/0026.container/0013.str_btree_set/str_btree_set.cc index 064b53b89..cae2566e9 100644 --- a/tests/0026.container/0013.str_btree_set/str_btree_set.cc +++ b/tests/0026.container/0013.str_btree_set/str_btree_set.cc @@ -46,5 +46,29 @@ int main() ::fast_io::io::println(e); } - ::fast_io::io::println("\nfront()=", bset.front(), "\tback()=", bset.back()); + ::fast_io::io::print("\nfront()=", bset.front(), "\tback()=", bset.back(), "\nbset.find(\"xigua\"):\n"); + { + auto it{bset.find("xigua")}; + if (it == bset.cend()) + { + ::fast_io::io::print("not found\n"); + } + else + { + ::fast_io::io::println("found: ", *it); + } + } + + ::fast_io::io::print("bset.find(\"buffalo\"):\n"); + { + auto it{bset.find("buffalo")}; + if (it == bset.cend()) + { + ::fast_io::io::print("not found\n"); + } + else + { + ::fast_io::io::println("found: ", *it); + } + } } From b6d5beb3167aae3ee25f552c1a637497c467bff8 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Mon, 14 Jul 2025 20:10:25 +0800 Subject: [PATCH 62/81] [str_btree_set] put a placeholder for erase --- include/fast_io_dsal/impl/str_btree_set.h | 58 ++++++++++++++++++----- 1 file changed, 46 insertions(+), 12 deletions(-) diff --git a/include/fast_io_dsal/impl/str_btree_set.h b/include/fast_io_dsal/impl/str_btree_set.h index b3913e146..cd8ce614d 100644 --- a/include/fast_io_dsal/impl/str_btree_set.h +++ b/include/fast_io_dsal/impl/str_btree_set.h @@ -365,6 +365,30 @@ inline constexpr bool str_btree_insert_key_with_root(::fast_io::containers::deta return ::fast_io::containers::details::str_btree_insert_key_cold(node, pos, tempkey.ptr, tempkey.n, imp); } +template +inline constexpr bool str_btree_erase(::fast_io::containers::details::btree_imp &imp, + typename nodetype::char_type const *keystrptr, ::std::size_t keystrn) noexcept +{ + using char_type = typename nodetype::char_type; + using typed_allocator_type = ::fast_io::typed_generic_allocator_adapter; + + auto [it, pos] = ::fast_io::containers::details::str_btree_find(imp, keystrptr, keystrn); + if (it == nullptr) + { + return false; + } +#if 0 + constexpr + ::std::size_t keys_number_half{keys_number>>1u}; + auto itv{static_cast<::fast_io::containers::details::str_btree_set_common*>(it)}; + if(itv->leaf) + { + + } +#endif + return false; +} + /* Common structure used for str_btree_set iterator. Holds the current node pointer, position within node, and optional 'last' for reversed iteration fallback. */ struct str_btree_set_iterator_common @@ -559,32 +583,30 @@ class basic_str_btree_set } } - constexpr bool contains(string_view_type strvw) const noexcept + constexpr bool contains(string_view_type key) const noexcept { - return ::fast_io::containers::details::str_btree_contains(static_cast(this->imp.root), strvw.ptr, strvw.n); + return ::fast_io::containers::details::str_btree_contains(static_cast(this->imp.root), key.ptr, key.n); } - constexpr size_type count(string_view_type strvw) const noexcept + constexpr size_type count(string_view_type key) const noexcept { - return static_cast(this->contains(strvw)); + return static_cast(this->contains(key)); } - constexpr const_iterator find(string_view_type strvw) const noexcept + constexpr const_iterator find(string_view_type key) const noexcept { - auto [ptr, pos] = ::fast_io::containers::details::str_btree_find(static_cast(this->imp.root), strvw.ptr, strvw.n); + auto [ptr, pos] = ::fast_io::containers::details::str_btree_find(static_cast(this->imp.root), key.ptr, key.n); return {ptr, pos, this->imp.rightmost}; } constexpr bool is_empty() const noexcept { return this->imp.root == nullptr; } -#if 0 - constexpr bool erase_key(string_view_type) noexcept + constexpr size_type erase_key(string_view_type key) noexcept { - return false; + return ::fast_io::containers::details::str_btree_erase(this->imp, key.ptr, strkeyvw.n); } -#endif - constexpr bool insert_key(string_view_type strvw) noexcept + constexpr bool insert_key(string_view_type key) noexcept { - return ::fast_io::containers::details::str_btree_insert_key_with_root(this->imp, strvw.ptr, strvw.n); + return ::fast_io::containers::details::str_btree_insert_key_with_root(this->imp, key.ptr, strkeyvw.n); } private: @@ -666,6 +688,18 @@ class basic_str_btree_set return reverse_iterator(cend()); } + static inline constexpr size_type max_size() noexcept + { + constexpr size_type mx{::std::numeric_limits::max() / sizeof(node_type)}; + return mx; + } + + static inline constexpr size_type max_size_bytes() noexcept + { + constexpr size_type mx{::std::numeric_limits::max() / sizeof(node_type) * sizeof(node_type)}; + return mx; + } + constexpr const_reverse_iterator crend() const noexcept { return reverse_iterator(cbegin()); From bdb2cd41cc66a8404358e43cc61e22b1977f3477 Mon Sep 17 00:00:00 2001 From: ombhntlar Date: Fri, 18 Jul 2025 10:51:16 +0800 Subject: [PATCH 63/81] [str_btree_set] fix around str_btree_set --- include/fast_io_dsal/impl/str_btree_set.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/fast_io_dsal/impl/str_btree_set.h b/include/fast_io_dsal/impl/str_btree_set.h index cd8ce614d..19c5870a8 100644 --- a/include/fast_io_dsal/impl/str_btree_set.h +++ b/include/fast_io_dsal/impl/str_btree_set.h @@ -602,11 +602,11 @@ class basic_str_btree_set } constexpr size_type erase_key(string_view_type key) noexcept { - return ::fast_io::containers::details::str_btree_erase(this->imp, key.ptr, strkeyvw.n); + return ::fast_io::containers::details::str_btree_erase(this->imp, key.ptr, key.n); } constexpr bool insert_key(string_view_type key) noexcept { - return ::fast_io::containers::details::str_btree_insert_key_with_root(this->imp, key.ptr, strkeyvw.n); + return ::fast_io::containers::details::str_btree_insert_key_with_root(this->imp, key.ptr, key.n); } private: From 72115c791bb045df89d6bd0c49c9c1202bce9185 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Sat, 26 Jul 2025 18:01:40 +0800 Subject: [PATCH 64/81] [str_btree_set] merge code --- include/fast_io_dsal/impl/str_btree_set.h | 29 +++++++++++++++-------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/include/fast_io_dsal/impl/str_btree_set.h b/include/fast_io_dsal/impl/str_btree_set.h index cd8ce614d..6185d5764 100644 --- a/include/fast_io_dsal/impl/str_btree_set.h +++ b/include/fast_io_dsal/impl/str_btree_set.h @@ -377,16 +377,25 @@ inline constexpr bool str_btree_erase(::fast_io::containers::details::btree_imp { return false; } -#if 0 - constexpr - ::std::size_t keys_number_half{keys_number>>1u}; - auto itv{static_cast<::fast_io::containers::details::str_btree_set_common*>(it)}; - if(itv->leaf) + constexpr ::std::size_t keys_number_half{keys_number >> 1u}; + auto itv{static_cast<::fast_io::containers::details::str_btree_set_common *>(it)}; + auto keys{it->keys}; + auto keyspos{keys + pos}; + ::fast_io::details::deallocate_associative_string(keyspos->ptr, keyspos->n); + ::std::size_t n{itv->size}; + if (itv->leaf) + { + if (itv->parent == nullptr || keys_number_half < n) + { + ::fast_io::freestanding::overlapped_copy(keyspos + 1, keys + n, keyspos); + --itv->size; + return true; + } + } + else { - } -#endif - return false; + return true; } /* Common structure used for str_btree_set iterator. @@ -602,11 +611,11 @@ class basic_str_btree_set } constexpr size_type erase_key(string_view_type key) noexcept { - return ::fast_io::containers::details::str_btree_erase(this->imp, key.ptr, strkeyvw.n); + return ::fast_io::containers::details::str_btree_erase(this->imp, key.ptr, key.n); } constexpr bool insert_key(string_view_type key) noexcept { - return ::fast_io::containers::details::str_btree_insert_key_with_root(this->imp, key.ptr, strkeyvw.n); + return ::fast_io::containers::details::str_btree_insert_key_with_root(this->imp, key.ptr, key.n); } private: From bc6f5a0236fa1a216aa0e65e67ca8353393bda59 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Sun, 3 Aug 2025 19:51:27 +0800 Subject: [PATCH 65/81] Add sock_protocol QUIC --- include/fast_io_core_impl/socket/sock_family.h | 1 + include/fast_io_core_impl/socket/sock_protocol.h | 3 ++- include/fast_io_hosted/platforms/posix_netmode.h | 4 ++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/include/fast_io_core_impl/socket/sock_family.h b/include/fast_io_core_impl/socket/sock_family.h index abdd32dfc..e0c6ea38e 100644 --- a/include/fast_io_core_impl/socket/sock_family.h +++ b/include/fast_io_core_impl/socket/sock_family.h @@ -89,6 +89,7 @@ enum class sock_family wanpipe, /* Wanpipe API sockets. */ x25, /* Reserved for X.25 project. */ xdp, /* XDP sockets. */ + quic, /* QUIC */ }; } // namespace fast_io diff --git a/include/fast_io_core_impl/socket/sock_protocol.h b/include/fast_io_core_impl/socket/sock_protocol.h index c99387525..0a88a93d3 100644 --- a/include/fast_io_core_impl/socket/sock_protocol.h +++ b/include/fast_io_core_impl/socket/sock_protocol.h @@ -60,7 +60,8 @@ enum class sock_protocol tp, /* SO Transport Protocol Class 4. */ udp, /* User Datagram Protocol. */ udplite, /* UDP-Lite protocol. */ - vrrp + vrrp, + quic /* QUIC protocol */ }; } // namespace fast_io diff --git a/include/fast_io_hosted/platforms/posix_netmode.h b/include/fast_io_hosted/platforms/posix_netmode.h index 101693dd6..a7aabcd8a 100644 --- a/include/fast_io_hosted/platforms/posix_netmode.h +++ b/include/fast_io_hosted/platforms/posix_netmode.h @@ -555,6 +555,10 @@ inline constexpr int to_posix_sock_protocol(sock_protocol dom) noexcept #ifdef IPPROTO_VRRP case sock_protocol::vrrp: return IPPROTO_VRRP; +#endif +#ifdef IPPROTO_QUIC + case sock_protocol::quic: + return IPPROTO_QUIC; #endif default: return -1; From 951067d3177362ebdaf56997a48084f09c615086 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Thu, 7 Aug 2025 01:15:24 +0800 Subject: [PATCH 66/81] add some content to str_btree_set --- include/fast_io_core_impl/concepts/type.h | 4 +- .../fast_io_dsal/impl/associative_string.h | 8 + include/fast_io_dsal/impl/str_btree_set.h | 182 +++++++++++++++++- .../0013.str_btree_set/str_btree_set.cc | 3 + 4 files changed, 189 insertions(+), 8 deletions(-) diff --git a/include/fast_io_core_impl/concepts/type.h b/include/fast_io_core_impl/concepts/type.h index 30eb7dd11..3021f1d3a 100644 --- a/include/fast_io_core_impl/concepts/type.h +++ b/include/fast_io_core_impl/concepts/type.h @@ -32,7 +32,7 @@ struct basic_message_hdr 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) { @@ -110,7 +110,7 @@ struct deco_result out_char_type *output_result_ptr{}; }; -enum class seekdir +enum class seekdir : ::std::uint_least8_t { beg = 0, // SEEK_SET cur = 1, // SEEK_CUR diff --git a/include/fast_io_dsal/impl/associative_string.h b/include/fast_io_dsal/impl/associative_string.h index 2cdccfa50..882248a86 100644 --- a/include/fast_io_dsal/impl/associative_string.h +++ b/include/fast_io_dsal/impl/associative_string.h @@ -32,4 +32,12 @@ inline constexpr ::fast_io::details::associative_string create_associ return {newp, n}; } +template +inline constexpr void deallocate_associative_string(void const *p, ::std::size_t n) noexcept +{ + using typed_allocator_type = ::fast_io::typed_generic_allocator_adapter; + ::std::size_t const np1{static_cast<::std::size_t>(n + 1u)}; + typed_allocator_type::deallocate_n(static_cast(const_cast(p)), np1); +} + } // namespace fast_io::details diff --git a/include/fast_io_dsal/impl/str_btree_set.h b/include/fast_io_dsal/impl/str_btree_set.h index 6185d5764..172063329 100644 --- a/include/fast_io_dsal/impl/str_btree_set.h +++ b/include/fast_io_dsal/impl/str_btree_set.h @@ -369,32 +369,202 @@ template inline constexpr bool str_btree_erase(::fast_io::containers::details::btree_imp &imp, typename nodetype::char_type const *keystrptr, ::std::size_t keystrn) noexcept { + // unfinished using char_type = typename nodetype::char_type; - using typed_allocator_type = ::fast_io::typed_generic_allocator_adapter; + using typed_allocator_type = ::fast_io::typed_generic_allocator_adapter>; + using nodeptr +#if __has_cpp_attribute(__gnu__::__may_alias__) + [[__gnu__::__may_alias__]] +#endif + = ::fast_io::containers::details::str_btree_set_common *; + auto node{static_cast<::fast_io::containers::details::str_btree_set_node *>(imp.root)}; - auto [it, pos] = ::fast_io::containers::details::str_btree_find(imp, keystrptr, keystrn); + auto [it, pos] = ::fast_io::containers::details::str_btree_find(node, keystrptr, keystrn); if (it == nullptr) { return false; } constexpr ::std::size_t keys_number_half{keys_number >> 1u}; - auto itv{static_cast<::fast_io::containers::details::str_btree_set_common *>(it)}; - auto keys{it->keys}; + auto itv{static_cast(it)}; + auto keys{itv->keys}; auto keyspos{keys + pos}; - ::fast_io::details::deallocate_associative_string(keyspos->ptr, keyspos->n); + ::fast_io::details::deallocate_associative_string(keyspos->base, keyspos->len); ::std::size_t n{itv->size}; + + auto parent{static_cast(itv->parent)}; if (itv->leaf) { - if (itv->parent == nullptr || keys_number_half < n) + if (keys_number_half < n) { ::fast_io::freestanding::overlapped_copy(keyspos + 1, keys + n, keyspos); --itv->size; + + return true; + } + else if (parent == nullptr) + { + ::fast_io::freestanding::overlapped_copy(keyspos + 1, keys + n, keyspos); + if (!(--itv->size)) + { + // **Deallocate the node using the allocator** + typed_allocator_type::deallocate_n(itv, 1); + imp = {}; + } + return true; + } + ::std::size_t parpos{itv->parent_pos}; + ::std::size_t parent_size{parent->size}; + nodeptr rightbrother{}; + if (parpos != parent_size) + { + rightbrother = static_cast(parent->childrens[parpos + 1]); + ::std::size_t rightbrothern{rightbrother->size}; + if (rightbrothern < keys_number_half) + { + // Borrow from right brother's leftmost key + auto rightbrotherkeys{rightbrother->keys}; + auto &borrowed_key = *rightbrotherkeys; + auto &parent_key = parent->keys[parpos]; + + // Move borrowed key to current node + keys[n] = parent_key; + ++itv->size; + + // Update parent key + parent_key = borrowed_key; + + // Shift right brother's keys left + ::fast_io::freestanding::overlapped_copy( + rightbrotherkeys + 1, + rightbrotherkeys + rightbrothern, + rightbrotherkeys); + --rightbrother->size; + + return true; + } + } + // Try left brother if right failed + nodeptr leftbrother{}; + if (parpos != 0) + { + leftbrother = static_cast(parent->childrens[parpos - 1]); + ::std::size_t leftbrothern{leftbrother->size}; + if (keys_number_half < leftbrothern) + { + // Borrow from left brother's rightmost key + auto &borrowed_key = leftbrother->keys[leftbrothern - 1]; + auto &parent_key = parent->keys[parpos - 1]; + + // Shift current keys right + ::fast_io::freestanding::overlapped_copy( + keyspos, + keys + n, + keyspos + 1); + + // Insert parent key + *keys = parent_key; + ++itv->size; + + // Update parent key + parent_key = borrowed_key; + --leftbrother->size; + + return true; + } + } + // Merge with sibling (prefer right if possible) + if (parpos != parent_size) + { + // Merge with right brother + keys[n] = parent->keys[parpos]; + ::fast_io::freestanding::non_overlapped_copy( + rightbrother->keys, + rightbrother->keys + rightbrother->size, + keys + n + 1); + itv->size += rightbrother->size + 1; + + // Deallocate right brother + typed_allocator_type::deallocate_n(rightbrother, 1); + + // Shift parent's keys and children + ::fast_io::freestanding::overlapped_copy( + parent->keys + parpos + 1, + parent->keys + parent_size, + parent->keys + parpos); + ::fast_io::freestanding::overlapped_copy( + parent->childrens + parpos + 2, + parent->childrens + parent_size + 1, + parent->childrens + parpos + 1); + --parent->size; + + return true; + } + else + { + // Merge with left brother + auto &merge_key = parent->keys[parpos - 1]; + ::fast_io::freestanding::non_overlapped_copy( + keys, + keys + n, + leftbrother->keys + leftbrother->size + 1); + leftbrother->keys[leftbrother->size] = merge_key; + leftbrother->size += n + 1; + + // Deallocate current node + typed_allocator_type::deallocate_n(itv, 1); + + // Shift parent's keys and children + ::fast_io::freestanding::overlapped_copy( + parent->keys + parpos, + parent->keys + parent_size, + parent->keys + parpos - 1); + ::fast_io::freestanding::overlapped_copy( + parent->childrens + parpos + 1, + parent->childrens + parent_size + 1, + parent->childrens + parpos); + --parent->size; + return true; } } + +#if 0 + + ::fast_io::io::debug_println(::std::source_location::current(),"\t", ::fast_io::mnp::os_c_str_with_known_size(keystrptr, keystrn)); + + + for (auto j{parent}; j; j = static_cast<::fast_io::containers::details::str_btree_set_common *>(j->parent)) + { + bool isroot{itv==imp.root}; + + ::std::size_t parent_size{parent->size}, + parentsizep1{static_cast<::std::size_t>(parent_size+1u)};; + ::std::size_t parent_pos{itv->parent_pos}; + ::std::size_t parent_pos_p1{static_cast<::std::size_t>(parent_pos+1u)}; + auto parentchildrens{parent->childrens}; + if(parent_pos!=parentsizep1) + { + auto nextnode{static_cast(parentchildrens[parent_pos_p1])}; + ::std::size_t const nextsize{nextnode->size}; + if(keys_number_half <= nextsize) + { + + } + else + { + + } + } + else + { + } + } + else { } +#endif return true; } diff --git a/tests/0026.container/0013.str_btree_set/str_btree_set.cc b/tests/0026.container/0013.str_btree_set/str_btree_set.cc index cae2566e9..e78a3fb31 100644 --- a/tests/0026.container/0013.str_btree_set/str_btree_set.cc +++ b/tests/0026.container/0013.str_btree_set/str_btree_set.cc @@ -71,4 +71,7 @@ int main() ::fast_io::io::println("found: ", *it); } } + + bset.erase_key("apple"); + //bset.erase_key("banana"); } From 93469bc8a95328879e9508849d3280b7df82626e Mon Sep 17 00:00:00 2001 From: trcrsired Date: Tue, 12 Aug 2025 22:59:52 +0800 Subject: [PATCH 67/81] btree --- include/fast_io_dsal/impl/str_btree_set.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/include/fast_io_dsal/impl/str_btree_set.h b/include/fast_io_dsal/impl/str_btree_set.h index 172063329..24c2c315c 100644 --- a/include/fast_io_dsal/impl/str_btree_set.h +++ b/include/fast_io_dsal/impl/str_btree_set.h @@ -395,6 +395,7 @@ inline constexpr bool str_btree_erase(::fast_io::containers::details::btree_imp auto parent{static_cast(itv->parent)}; if (itv->leaf) { + __builtin_printf("hello world: %s %d\n",__FILE__,__LINE__); if (keys_number_half < n) { ::fast_io::freestanding::overlapped_copy(keyspos + 1, keys + n, keyspos); @@ -415,6 +416,7 @@ inline constexpr bool str_btree_erase(::fast_io::containers::details::btree_imp } ::std::size_t parpos{itv->parent_pos}; ::std::size_t parent_size{parent->size}; + __builtin_printf("hello world: %s %d\n",__FILE__,__LINE__); nodeptr rightbrother{}; if (parpos != parent_size) { @@ -444,6 +446,7 @@ inline constexpr bool str_btree_erase(::fast_io::containers::details::btree_imp return true; } } + __builtin_printf("hello world: %s %d\n",__FILE__,__LINE__); // Try left brother if right failed nodeptr leftbrother{}; if (parpos != 0) @@ -469,7 +472,7 @@ inline constexpr bool str_btree_erase(::fast_io::containers::details::btree_imp // Update parent key parent_key = borrowed_key; --leftbrother->size; - + __builtin_printf("hello world: %s %d\n",__FILE__,__LINE__); return true; } } @@ -497,7 +500,7 @@ inline constexpr bool str_btree_erase(::fast_io::containers::details::btree_imp parent->childrens + parent_size + 1, parent->childrens + parpos + 1); --parent->size; - + __builtin_printf("hello world: %s %d\n",__FILE__,__LINE__); return true; } else @@ -528,7 +531,7 @@ inline constexpr bool str_btree_erase(::fast_io::containers::details::btree_imp return true; } } - + __builtin_printf("hello world: %s %d\n",__FILE__,__LINE__); #if 0 ::fast_io::io::debug_println(::std::source_location::current(),"\t", ::fast_io::mnp::os_c_str_with_known_size(keystrptr, keystrn)); From ebe94cc9b6c2280031b9c386527c3995ef10fead Mon Sep 17 00:00:00 2001 From: trcrsired Date: Thu, 14 Aug 2025 22:59:24 +0800 Subject: [PATCH 68/81] add a simple wifianalyzer --- examples/.test_prop.toml | 3 + examples/0040.wifianalyzer/win32.cc | 105 ++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 examples/0040.wifianalyzer/win32.cc diff --git a/examples/.test_prop.toml b/examples/.test_prop.toml index bc8d292b2..7eb3b0f5d 100644 --- a/examples/.test_prop.toml +++ b/examples/.test_prop.toml @@ -39,3 +39,6 @@ interactive = true ["0039.gen_win32_mangling"] ignore = true + +["0040".wifianalyzer"] +ignore = true diff --git a/examples/0040.wifianalyzer/win32.cc b/examples/0040.wifianalyzer/win32.cc new file mode 100644 index 000000000..8b574db08 --- /dev/null +++ b/examples/0040.wifianalyzer/win32.cc @@ -0,0 +1,105 @@ +#define NOMINMAX 1 +#define WIN32_LEAN_AND_MEAN 1 +#include +#include +#include +#include +#include +#pragma comment(lib, "wlanapi.lib") + +class win32_wlan_file { +public: + explicit constexpr win32_wlan_file() noexcept = default; + + explicit win32_wlan_file(::std::uint_least32_t version) { + ::std::uint_least32_t negotiated_version{}; + if (WlanOpenHandle(version, nullptr, reinterpret_cast(::std::addressof(negotiated_version)), reinterpret_cast(&handle)) != ERROR_SUCCESS) { + ::fast_io::io::panic("WlanOpenHandle failed\n"); + } + } + + ~win32_wlan_file() { + if (handle) WlanCloseHandle(reinterpret_cast(handle), nullptr); + } + + void* handle = nullptr; + + win32_wlan_file(const win32_wlan_file&) = delete; + win32_wlan_file& operator=(const win32_wlan_file&) = delete; + + constexpr win32_wlan_file(win32_wlan_file&& other) noexcept : handle(other.handle) { + other.handle = nullptr; + } + + win32_wlan_file& operator=(win32_wlan_file&& other) noexcept { + if (this != &other) { + if (handle) WlanCloseHandle(reinterpret_cast(handle), nullptr); + handle = other.handle; + other.handle = nullptr; + } + return *this; + } +}; + +class win32_wlan_memory_file { +public: + explicit constexpr win32_wlan_memory_file() noexcept = default; + + ~win32_wlan_memory_file() { + if (hd) WlanFreeMemory(hd); + } + + void* hd = nullptr; + + win32_wlan_memory_file(const win32_wlan_memory_file&) = delete; + win32_wlan_memory_file& operator=(const win32_wlan_memory_file&) = delete; + + constexpr win32_wlan_memory_file(win32_wlan_memory_file&& other) noexcept : hd(other.hd) { + other.hd = nullptr; + } + + win32_wlan_memory_file& operator=(win32_wlan_memory_file&& other) noexcept { + if (this != &other) { + if (hd) WlanFreeMemory(hd); + hd = other.hd; + other.hd = nullptr; + } + return *this; + } +}; + +int main() { + win32_wlan_file wlan(2); + + win32_wlan_memory_file if_mem; + if (WlanEnumInterfaces(wlan.handle, nullptr, + reinterpret_cast(::std::addressof(if_mem.hd))) != ERROR_SUCCESS) { + ::fast_io::io::panic("WlanEnumInterfaces failed\n"); + } + + auto* if_list = reinterpret_cast(if_mem.hd); + for (::std::uint_least32_t i{}; i != if_list->dwNumberOfItems; ++i) { + GUID guid = if_list->InterfaceInfo[i].InterfaceGuid; + + win32_wlan_memory_file bss_mem; + if (WlanGetNetworkBssList(wlan.handle, ::std::addressof(guid), nullptr, + dot11_BSS_type_any, FALSE, nullptr, + reinterpret_cast(::std::addressof(bss_mem.hd))) != ERROR_SUCCESS) { + ::fast_io::io::perrln("WlanGetNetworkBssList failed:", i ); + continue; + } + + auto* bss_list{reinterpret_cast(bss_mem.hd)}; + for (::std::uint_least32_t j{}; j != bss_list->dwNumberOfItems; ++j) { + const WLAN_BSS_ENTRY& entry = bss_list->wlanBssEntries[j]; + ::fast_io::string_view ssid(reinterpret_cast(entry.dot11Ssid.ucSSID), entry.dot11Ssid.uSSIDLength); + if (ssid.is_empty()) + { + ssid=::fast_io::string_view("[Hidden]"); + } + ::fast_io::io::print("SSID:", ssid, "\t", + "Signal:", entry.lRssi, " dBm\t" + "Frequency:",entry.ulChCenterFrequency,"kHz\n"); + } + } +} From c853a84260920f3386404db02b4ecab5e8e006f5 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Thu, 14 Aug 2025 23:24:58 +0800 Subject: [PATCH 69/81] add scanning logic --- examples/0040.wifianalyzer/win32.cc | 75 ++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 7 deletions(-) diff --git a/examples/0040.wifianalyzer/win32.cc b/examples/0040.wifianalyzer/win32.cc index 8b574db08..7fab4c946 100644 --- a/examples/0040.wifianalyzer/win32.cc +++ b/examples/0040.wifianalyzer/win32.cc @@ -68,15 +68,74 @@ class win32_wlan_memory_file { } }; +inline void WINAPI wlan_notification_callback(PWLAN_NOTIFICATION_DATA data, void* ctx) { + if (!data || !ctx) return; + if (data->NotificationCode == wlan_notification_acm_scan_complete) { + ::fast_io::io::print("[+] Scan complete\n"); + } else if (data->NotificationCode == wlan_notification_acm_scan_fail) { + ::fast_io::io::print("[-] Scan failed\n"); + } + if(!SetEvent(ctx)) + { + ::fast_io::io::panic("SetEvent failure\n"); + } +} +inline constexpr std::uint_least32_t frequency_to_channel(std::uint_least32_t freq_khz) noexcept { + std::uint_least32_t freq_mhz = freq_khz / 1000; + if (freq_mhz >= 2412 && freq_mhz <= 2472) { + return (freq_mhz - 2407) / 5; // Channels 1–13 + } else if (freq_mhz == 2484) { + return 14; + } else if (freq_mhz >= 5180 && freq_mhz <= 5825) { + return (freq_mhz - 5000) / 5; // Channels 36–165 + } else if (freq_mhz >= 5955 && freq_mhz <= 7115) { + return (freq_mhz - 5950) / 5; // Wi-Fi 6E channels + } + return 0; // Unknown or unsupported +} +inline constexpr ::fast_io::cstring_view frequency_to_band(std::uint_least32_t freq_khz) noexcept { + std::uint_least32_t freq_mhz = freq_khz / 1000; + if (freq_mhz >= 2400 && freq_mhz <= 2500) { + return ::fast_io::cstring_view("2.4 GHz"); + } else if (freq_mhz >= 5000 && freq_mhz <= 5900) { + return ::fast_io::cstring_view("5 GHz"); + } else if (freq_mhz >= 5925 && freq_mhz <= 7125) { + return ::fast_io::cstring_view("6 GHz"); + } + return ::fast_io::cstring_view("Unknown"); +} int main() { win32_wlan_file wlan(2); + HANDLE scan_event = CreateEvent(nullptr, TRUE, FALSE, nullptr); + if (!scan_event) { + ::fast_io::io::panic("CreateEvent failed\n"); + } + ::fast_io::win32_file scan_event_file(scan_event); + // Get interface win32_wlan_memory_file if_mem; - if (WlanEnumInterfaces(wlan.handle, nullptr, - reinterpret_cast(::std::addressof(if_mem.hd))) != ERROR_SUCCESS) { - ::fast_io::io::panic("WlanEnumInterfaces failed\n"); - } + WlanEnumInterfaces(wlan.handle, nullptr, + reinterpret_cast(&if_mem.hd)); + { + auto* if_list = reinterpret_cast(if_mem.hd); + GUID interface_guid = if_list->InterfaceInfo[0].InterfaceGuid; + // Register callback + WlanRegisterNotification(wlan.handle, WLAN_NOTIFICATION_SOURCE_ACM, TRUE, + wlan_notification_callback, scan_event, nullptr, nullptr); + + // Trigger scan + WlanScan(wlan.handle, &interface_guid, nullptr, nullptr, nullptr); + } + // Wait for scan to complete (e.g., Sleep or message loop) + auto start_time {::fast_io::posix_clock_gettime(::fast_io::posix_clock_id::realtime)}; + DWORD wait_result = WaitForSingleObject(scan_event, 10000); // 10s timeout + if (wait_result != WAIT_OBJECT_0) { + ::fast_io::io::perrln("Scan did not complete in time"); + return 1; + } + ::fast_io::io::print("Elapsed time for scanning: ", + ::fast_io::posix_clock_gettime(::fast_io::posix_clock_id::realtime)-start_time, "s\n"); auto* if_list = reinterpret_cast(if_mem.hd); for (::std::uint_least32_t i{}; i != if_list->dwNumberOfItems; ++i) { GUID guid = if_list->InterfaceInfo[i].InterfaceGuid; @@ -91,15 +150,17 @@ int main() { auto* bss_list{reinterpret_cast(bss_mem.hd)}; for (::std::uint_least32_t j{}; j != bss_list->dwNumberOfItems; ++j) { - const WLAN_BSS_ENTRY& entry = bss_list->wlanBssEntries[j]; + WLAN_BSS_ENTRY const& entry = bss_list->wlanBssEntries[j]; ::fast_io::string_view ssid(reinterpret_cast(entry.dot11Ssid.ucSSID), entry.dot11Ssid.uSSIDLength); if (ssid.is_empty()) { ssid=::fast_io::string_view("[Hidden]"); } - ::fast_io::io::print("SSID:", ssid, "\t", + ::fast_io::io::println("SSID:", ssid, "\t", "Signal:", entry.lRssi, " dBm\t" - "Frequency:",entry.ulChCenterFrequency,"kHz\n"); + "Frequency:",entry.ulChCenterFrequency,"kHz\t", + "Band:",frequency_to_band(entry.ulChCenterFrequency), "\t" + "Channel:",frequency_to_channel(entry.ulChCenterFrequency)); } } } From c1d0fc03dce51da6585ff720fc09c7bc0d9fa168 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Thu, 14 Aug 2025 23:28:01 +0800 Subject: [PATCH 70/81] add logic to print out even after scanning timeout --- examples/0040.wifianalyzer/win32.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/0040.wifianalyzer/win32.cc b/examples/0040.wifianalyzer/win32.cc index 7fab4c946..81183895b 100644 --- a/examples/0040.wifianalyzer/win32.cc +++ b/examples/0040.wifianalyzer/win32.cc @@ -132,7 +132,6 @@ int main() { DWORD wait_result = WaitForSingleObject(scan_event, 10000); // 10s timeout if (wait_result != WAIT_OBJECT_0) { ::fast_io::io::perrln("Scan did not complete in time"); - return 1; } ::fast_io::io::print("Elapsed time for scanning: ", ::fast_io::posix_clock_gettime(::fast_io::posix_clock_id::realtime)-start_time, "s\n"); From 385e9b561b08e9c54709c80119b712097d2ae659 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Thu, 14 Aug 2025 23:40:30 +0800 Subject: [PATCH 71/81] wifi quality --- examples/0040.wifianalyzer/win32.cc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/examples/0040.wifianalyzer/win32.cc b/examples/0040.wifianalyzer/win32.cc index 81183895b..86520df51 100644 --- a/examples/0040.wifianalyzer/win32.cc +++ b/examples/0040.wifianalyzer/win32.cc @@ -80,6 +80,13 @@ inline void WINAPI wlan_notification_callback(PWLAN_NOTIFICATION_DATA data, void ::fast_io::io::panic("SetEvent failure\n"); } } +inline ::fast_io::cstring_view signal_quality(::std::int_least32_t rssi_dbm) noexcept { + if (rssi_dbm >= -55) return ::fast_io::cstring_view("Excellent"); + if (rssi_dbm >= -65) return ::fast_io::cstring_view("Good"); + if (rssi_dbm >= -75) return ::fast_io::cstring_view("Fair"); + if (rssi_dbm >= -85) return ::fast_io::cstring_view("Weak"); + return ::fast_io::cstring_view("Very Weak"); +} inline constexpr std::uint_least32_t frequency_to_channel(std::uint_least32_t freq_khz) noexcept { std::uint_least32_t freq_mhz = freq_khz / 1000; if (freq_mhz >= 2412 && freq_mhz <= 2472) { @@ -156,7 +163,7 @@ int main() { ssid=::fast_io::string_view("[Hidden]"); } ::fast_io::io::println("SSID:", ssid, "\t", - "Signal:", entry.lRssi, " dBm\t" + "Signal:", entry.lRssi, " dBm (Quality:",signal_quality(entry.lRssi),")\t" "Frequency:",entry.ulChCenterFrequency,"kHz\t", "Band:",frequency_to_band(entry.ulChCenterFrequency), "\t" "Channel:",frequency_to_channel(entry.ulChCenterFrequency)); From e227c1c4d717f69ac0bb5a49437d814dcc17aa1f Mon Sep 17 00:00:00 2001 From: trcrsired Date: Fri, 15 Aug 2025 00:04:35 +0800 Subject: [PATCH 72/81] win32 --- examples/0040.wifianalyzer/win32.cc | 47 ++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/examples/0040.wifianalyzer/win32.cc b/examples/0040.wifianalyzer/win32.cc index 86520df51..7e58bf8fc 100644 --- a/examples/0040.wifianalyzer/win32.cc +++ b/examples/0040.wifianalyzer/win32.cc @@ -87,8 +87,8 @@ inline ::fast_io::cstring_view signal_quality(::std::int_least32_t rssi_dbm) noe if (rssi_dbm >= -85) return ::fast_io::cstring_view("Weak"); return ::fast_io::cstring_view("Very Weak"); } -inline constexpr std::uint_least32_t frequency_to_channel(std::uint_least32_t freq_khz) noexcept { - std::uint_least32_t freq_mhz = freq_khz / 1000; +inline constexpr ::std::uint_least32_t frequency_to_channel(::std::uint_least32_t freq_khz) noexcept { + ::std::uint_least32_t freq_mhz = freq_khz / 1000u; if (freq_mhz >= 2412 && freq_mhz <= 2472) { return (freq_mhz - 2407) / 5; // Channels 1–13 } else if (freq_mhz == 2484) { @@ -100,8 +100,8 @@ inline constexpr std::uint_least32_t frequency_to_channel(std::uint_least32_t fr } return 0; // Unknown or unsupported } -inline constexpr ::fast_io::cstring_view frequency_to_band(std::uint_least32_t freq_khz) noexcept { - std::uint_least32_t freq_mhz = freq_khz / 1000; +inline constexpr ::fast_io::cstring_view frequency_to_band(::std::uint_least32_t freq_khz) noexcept { + std::uint_least32_t freq_mhz = freq_khz / 1000u; if (freq_mhz >= 2400 && freq_mhz <= 2500) { return ::fast_io::cstring_view("2.4 GHz"); } else if (freq_mhz >= 5000 && freq_mhz <= 5900) { @@ -111,6 +111,41 @@ inline constexpr ::fast_io::cstring_view frequency_to_band(std::uint_least32_t } return ::fast_io::cstring_view("Unknown"); } +struct channel_range +{ + ::std::uint_least32_t from, to; +}; +// Estimate the occupied channel range based on center frequency in kHz +inline constexpr channel_range estimated_channel_range(::std::uint_least32_t freq_khz) noexcept { + // Convert frequency from kHz to MHz for easier comparison + ::std::uint_least32_t freq_mhz = freq_khz / 1000; + + // Map center frequency to its corresponding WiFi channel number + ::std::uint_least32_t center = frequency_to_channel(freq_khz); + + // Initialize lower and upper bounds of the channel range + ::std::uint_least32_t lower = center; + ::std::uint_least32_t upper = center; + + // For 2.4 GHz band (typically 20 MHz wide), assume ±2 channels + if (freq_mhz >= 2400 && freq_mhz <= 2500) { + lower = 2 < center ? center - 2 : 1; // Prevent underflow; channel must be ≥1 + upper = center + 2; + } + // For 5 GHz band (often 80 MHz wide), assume ±4 channels + else if (freq_mhz >= 5000 && freq_mhz <= 5900) { + lower = 4 < center ? center - 4 : 36; // Prevent underflow; lowest legal channel is 36 + upper = center + 4; + } + // For 6 GHz band (variable width), conservatively assume ±4 channels + else if (freq_mhz >= 5925 && freq_mhz <= 7125) { + lower = 4 < center ? center - 4 : center; // No strict lower bound defined + upper = center + 4; + } + + // Return the estimated channel range + return {lower, upper}; +} int main() { win32_wlan_file wlan(2); HANDLE scan_event = CreateEvent(nullptr, TRUE, FALSE, nullptr); @@ -162,11 +197,13 @@ int main() { { ssid=::fast_io::string_view("[Hidden]"); } + auto [ch_start,ch_end] = estimated_channel_range(entry.ulChCenterFrequency); ::fast_io::io::println("SSID:", ssid, "\t", "Signal:", entry.lRssi, " dBm (Quality:",signal_quality(entry.lRssi),")\t" "Frequency:",entry.ulChCenterFrequency,"kHz\t", "Band:",frequency_to_band(entry.ulChCenterFrequency), "\t" - "Channel:",frequency_to_channel(entry.ulChCenterFrequency)); + "Channel:",frequency_to_channel(entry.ulChCenterFrequency)," " + "(covers:",ch_start, "-", ch_end,")\n"); } } } From e5e77f97e1b6f89240b7763352d6df09a3a441a5 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Fri, 15 Aug 2025 00:13:11 +0800 Subject: [PATCH 73/81] add covers --- examples/0040.wifianalyzer/win32.cc | 90 +++++++++++++++-------------- 1 file changed, 47 insertions(+), 43 deletions(-) diff --git a/examples/0040.wifianalyzer/win32.cc b/examples/0040.wifianalyzer/win32.cc index 7e58bf8fc..a13ba2d75 100644 --- a/examples/0040.wifianalyzer/win32.cc +++ b/examples/0040.wifianalyzer/win32.cc @@ -111,41 +111,7 @@ inline constexpr ::fast_io::cstring_view frequency_to_band(::std::uint_least32_ } return ::fast_io::cstring_view("Unknown"); } -struct channel_range -{ - ::std::uint_least32_t from, to; -}; -// Estimate the occupied channel range based on center frequency in kHz -inline constexpr channel_range estimated_channel_range(::std::uint_least32_t freq_khz) noexcept { - // Convert frequency from kHz to MHz for easier comparison - ::std::uint_least32_t freq_mhz = freq_khz / 1000; - - // Map center frequency to its corresponding WiFi channel number - ::std::uint_least32_t center = frequency_to_channel(freq_khz); - // Initialize lower and upper bounds of the channel range - ::std::uint_least32_t lower = center; - ::std::uint_least32_t upper = center; - - // For 2.4 GHz band (typically 20 MHz wide), assume ±2 channels - if (freq_mhz >= 2400 && freq_mhz <= 2500) { - lower = 2 < center ? center - 2 : 1; // Prevent underflow; channel must be ≥1 - upper = center + 2; - } - // For 5 GHz band (often 80 MHz wide), assume ±4 channels - else if (freq_mhz >= 5000 && freq_mhz <= 5900) { - lower = 4 < center ? center - 4 : 36; // Prevent underflow; lowest legal channel is 36 - upper = center + 4; - } - // For 6 GHz band (variable width), conservatively assume ±4 channels - else if (freq_mhz >= 5925 && freq_mhz <= 7125) { - lower = 4 < center ? center - 4 : center; // No strict lower bound defined - upper = center + 4; - } - - // Return the estimated channel range - return {lower, upper}; -} int main() { win32_wlan_file wlan(2); HANDLE scan_event = CreateEvent(nullptr, TRUE, FALSE, nullptr); @@ -193,17 +159,55 @@ int main() { for (::std::uint_least32_t j{}; j != bss_list->dwNumberOfItems; ++j) { WLAN_BSS_ENTRY const& entry = bss_list->wlanBssEntries[j]; ::fast_io::string_view ssid(reinterpret_cast(entry.dot11Ssid.ucSSID), entry.dot11Ssid.uSSIDLength); - if (ssid.is_empty()) - { - ssid=::fast_io::string_view("[Hidden]"); + if (ssid.is_empty()) { + ssid = ::fast_io::string_view("[Hidden]"); + } + + // Default to 20 MHz if no IE is found + std::uint_least32_t channel_width_mhz = 20; + + // Parse IEs to determine actual channel width + std::uint_least8_t const* ie_data = reinterpret_cast(&entry) + entry.ulIeOffset; + for (std::uint_least32_t i{}; i + 2 < entry.ulIeSize;) { + std::uint_least8_t id = ie_data[i]; + std::uint_least8_t len = ie_data[i + 1]; + if (i + 2 + len > entry.ulIeSize) break; // prevent overflow + + std::uint_least8_t const* data = &ie_data[i + 2]; + + // HT Operation IE (ID 0x3D) + if (id == 0x3D && len >= 3) { + std::uint_least8_t ht_info = data[1]; + std::uint_least8_t channel_width_flag = data[2]; // bit 0: 0 = 20 MHz, 1 = 40 MHz + if (channel_width_flag & 0x01) { + channel_width_mhz = 40; + } + } + + // VHT Operation IE (ID 0xC0) + else if (id == 0xC0 && len >= 1) { + std::uint_least8_t vht_channel_width = data[0]; // 0 = 20/40, 1 = 80, 2 = 160 or 80+80 + if (vht_channel_width == 1) channel_width_mhz = 80; + else if (vht_channel_width == 2) channel_width_mhz = 160; + } + + // You can add HE parsing here if needed + + i += 2 + len; } - auto [ch_start,ch_end] = estimated_channel_range(entry.ulChCenterFrequency); + + // Estimate channel range based on actual width + std::uint_least32_t center_channel = frequency_to_channel(entry.ulChCenterFrequency); + std::uint_least32_t ch_span = channel_width_mhz / 20; + std::uint_least32_t ch_start = center_channel >= ch_span ? center_channel - ch_span : center_channel; + std::uint_least32_t ch_end = center_channel + ch_span; + ::fast_io::io::println("SSID:", ssid, "\t", - "Signal:", entry.lRssi, " dBm (Quality:",signal_quality(entry.lRssi),")\t" - "Frequency:",entry.ulChCenterFrequency,"kHz\t", - "Band:",frequency_to_band(entry.ulChCenterFrequency), "\t" - "Channel:",frequency_to_channel(entry.ulChCenterFrequency)," " - "(covers:",ch_start, "-", ch_end,")\n"); + "Signal:", entry.lRssi, " dBm (Quality:", signal_quality(entry.lRssi), ")\t" + "Frequency:", entry.ulChCenterFrequency, "kHz\t", + "Band:", frequency_to_band(entry.ulChCenterFrequency), "\t" + "Channel:", center_channel, " " + "(width:", channel_width_mhz, " MHz, covers:", ch_start, "-", ch_end, ")\n"); } } } From 2b31a387e9ee77fa9283ecf1c0a578f3bed7a0c1 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Fri, 15 Aug 2025 00:13:36 +0800 Subject: [PATCH 74/81] remove ln --- examples/0040.wifianalyzer/win32.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/0040.wifianalyzer/win32.cc b/examples/0040.wifianalyzer/win32.cc index a13ba2d75..88e48962f 100644 --- a/examples/0040.wifianalyzer/win32.cc +++ b/examples/0040.wifianalyzer/win32.cc @@ -202,7 +202,7 @@ int main() { std::uint_least32_t ch_start = center_channel >= ch_span ? center_channel - ch_span : center_channel; std::uint_least32_t ch_end = center_channel + ch_span; - ::fast_io::io::println("SSID:", ssid, "\t", + ::fast_io::io::print("SSID:", ssid, "\t", "Signal:", entry.lRssi, " dBm (Quality:", signal_quality(entry.lRssi), ")\t" "Frequency:", entry.ulChCenterFrequency, "kHz\t", "Band:", frequency_to_band(entry.ulChCenterFrequency), "\t" From 049cb6b5e61fc98702ca925bec47973749bdd56d Mon Sep 17 00:00:00 2001 From: trcrsired Date: Sat, 13 Sep 2025 08:13:02 +0800 Subject: [PATCH 75/81] pin12 --- examples/0014.random/pin12.cc | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 examples/0014.random/pin12.cc diff --git a/examples/0014.random/pin12.cc b/examples/0014.random/pin12.cc new file mode 100644 index 000000000..af04f0aec --- /dev/null +++ b/examples/0014.random/pin12.cc @@ -0,0 +1,27 @@ +#include +#include +#include + +using namespace fast_io::io; + +int main(int argc, char **argv) +{ + std::size_t n{100}; + if (1 < argc) + { + n = fast_io::to(fast_io::mnp::os_c_str(argv[1])); + } + fast_io::u8obuf_file obf(u"pin12.txt"); + fast_io::ibuf_white_hole_engine eng; + std::uniform_int_distribution ud(0, 9); + for (std::size_t i{}; i != n; ++i) + { + for (std::size_t j{}; j != 12u; ++j) + { + char8_t ch(static_cast(ud(eng))); + ch += u8'0'; + print(obf, fast_io::mnp::chvw(ch)); + } + println(obf); + } +} From 67fc49dfda268a22ce7279fd2169d0827047ba0c Mon Sep 17 00:00:00 2001 From: trcrsired Date: Wed, 24 Sep 2025 05:08:33 +0800 Subject: [PATCH 76/81] Fix warnings for char32_t casting --- .../char_category/char_category.h | 14 +++--- .../char_category/char_category_traits.h | 2 +- include/fast_io_core_impl/codecvt/general.h | 36 +++++++-------- include/fast_io_core_impl/codecvt/utf.h | 4 +- .../fast_io_core_impl/codecvt/utf_ebcdic.h | 44 +++++++++---------- include/fast_io_core_impl/ebcdic.h | 6 +-- include/fast_io_unit/gb18030.h | 28 ++++++------ 7 files changed, 67 insertions(+), 67 deletions(-) diff --git a/include/fast_io_core_impl/char_category/char_category.h b/include/fast_io_core_impl/char_category/char_category.h index 205ec1e9c..78e2f0da9 100644 --- a/include/fast_io_core_impl/char_category/char_category.h +++ b/include/fast_io_core_impl/char_category/char_category.h @@ -1556,7 +1556,7 @@ namespace details { inline constexpr char32_t to_c_upper_ascii_impl(char32_t ch) noexcept { - constexpr char32_t alphanum{static_cast(26u)}; + constexpr char32_t alphanum{static_cast(static_cast<::std::uint_least32_t>(26u))}; char32_t res{ch - U'a'}; if (res < alphanum) { @@ -1567,7 +1567,7 @@ inline constexpr char32_t to_c_upper_ascii_impl(char32_t ch) noexcept inline constexpr char32_t to_c_lower_ascii_impl(char32_t ch) noexcept { - constexpr char32_t alphanum{static_cast(26u)}; + constexpr char32_t alphanum{static_cast(static_cast<::std::uint_least32_t>(26u))}; char32_t res{ch - U'A'}; if (res < alphanum) { @@ -1797,7 +1797,7 @@ inline constexpr bool is_html_whitespace_wide_impl(wchar_t ch) noexcept inline constexpr bool is_dos_path_invalid_character_impl(char32_t ch) noexcept { - if (ch < static_cast(32u)) + if (ch < static_cast(static_cast<::std::uint_least32_t>(32u))) { return true; } @@ -1863,7 +1863,7 @@ inline constexpr bool is_c_halfwidth(char_type ch) noexcept } else if constexpr (!::std::same_as && sizeof(char_type) == sizeof(char32_t)) { - return is_c_halfwidth(static_cast(ch)); + return is_c_halfwidth(static_cast(static_cast<::std::uint_least32_t>(ch))); } else if constexpr (::std::signed_integral) { @@ -1895,7 +1895,7 @@ inline constexpr bool is_c_fullwidth(char_type ch) noexcept } else if constexpr (!::std::same_as && sizeof(char_type) == sizeof(char32_t)) { - return is_c_fullwidth(static_cast(ch)); + return is_c_fullwidth(static_cast(static_cast<::std::uint_least32_t>(ch))); } else if constexpr (::std::signed_integral) { @@ -1930,7 +1930,7 @@ inline constexpr bool is_dos_path_invalid_character(T ch) noexcept } else { - return ::fast_io::char_category::details::is_dos_path_invalid_character_impl(static_cast(ch)); + return ::fast_io::char_category::details::is_dos_path_invalid_character_impl(static_cast(static_cast<::std::uint_least32_t>(ch))); } } @@ -1943,7 +1943,7 @@ inline constexpr bool is_dos_path_invalid_prefix_character(T ch) noexcept } else { - return ::fast_io::char_category::details::is_dos_path_invalid_prefix_character_impl(static_cast(ch)); + return ::fast_io::char_category::details::is_dos_path_invalid_prefix_character_impl(static_cast(static_cast<::std::uint_least32_t>(ch))); } } diff --git a/include/fast_io_core_impl/char_category/char_category_traits.h b/include/fast_io_core_impl/char_category/char_category_traits.h index fd637cea7..c2dc3973b 100644 --- a/include/fast_io_core_impl/char_category/char_category_traits.h +++ b/include/fast_io_core_impl/char_category/char_category_traits.h @@ -493,7 +493,7 @@ struct to_c_common_fn_impl } else if constexpr (!::std::same_as && sizeof(char_type) == sizeof(char32_t)) { - return static_cast(operator()(static_cast(ch))); + return static_cast(operator()(static_cast(static_cast<::std::uint_least32_t>(ch)))); } else if constexpr (::std::signed_integral) { diff --git a/include/fast_io_core_impl/codecvt/general.h b/include/fast_io_core_impl/codecvt/general.h index 2165601fc..bd4105eb7 100644 --- a/include/fast_io_core_impl/codecvt/general.h +++ b/include/fast_io_core_impl/codecvt/general.h @@ -107,7 +107,7 @@ general_code_cvt(src_char_type const *src_first, src_char_type const *src_last, 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); + dst += get_utf_code_units(static_cast(static_cast<::std::uint_least32_t>(*src_first)), dst); } return {src_last, dst}; } @@ -186,7 +186,7 @@ general_code_cvt(src_char_type const *src_first, src_char_type const *src_last, } else { - dst += get_utf_code_units(static_cast(code), dst); + dst += get_utf_code_units(static_cast(static_cast<::std::uint_least32_t>(code)), dst); } } } @@ -204,7 +204,7 @@ general_code_cvt(src_char_type const *src_first, src_char_type const *src_last, constexpr ::std::size_t m128i_size{16}; while (m128i_size < static_cast<::std::size_t>(src_last - src_first)) { - if (static_cast(*src_first) < 0x80) + if (static_cast(static_cast<::std::uint_least8_t>(*src_first)) < 0x80) { auto [new_src, new_dst] = convert_ascii_with_sse(src_first, dst); src_first = new_src; @@ -223,7 +223,7 @@ general_code_cvt(src_char_type const *src_first, src_char_type const *src_last, } else { - dst += get_utf_code_units(static_cast(code), dst); + dst += get_utf_code_units(static_cast(static_cast<::std::uint_least32_t>(code)), dst); } } else @@ -237,7 +237,7 @@ general_code_cvt(src_char_type const *src_first, src_char_type const *src_last, } else { - dst += get_utf_code_units(static_cast(code), dst); + dst += get_utf_code_units(static_cast(static_cast<::std::uint_least32_t>(code)), dst); } } } @@ -251,7 +251,7 @@ general_code_cvt(src_char_type const *src_first, src_char_type const *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)) + if (adv == static_cast(static_cast<::std::uint_least8_t>(-1))) { break; } @@ -267,12 +267,12 @@ general_code_cvt(src_char_type const *src_first, src_char_type const *src_last, } else { - dst += get_utf_code_units(static_cast(code), dst); + dst += get_utf_code_units(static_cast(static_cast<::std::uint_least32_t>(code)), dst); } } else { - if (static_cast(*src_first) < 0x80) + if (static_cast(static_cast<::std::uint_least8_t>(*src_first)) < 0x80) { if constexpr (encoding_scheme::utf_ebcdic == encoding) { @@ -280,7 +280,7 @@ general_code_cvt(src_char_type const *src_first, src_char_type const *src_last, } else { - *dst = static_cast(static_cast(*src_first)); + *dst = static_cast(static_cast(static_cast<::std::uint_least8_t>(*src_first))); } if constexpr (sizeof(dest_char_type) != 1 && encoding_is_utf(encoding) && !is_native_scheme(encoding)) @@ -295,7 +295,7 @@ general_code_cvt(src_char_type const *src_first, src_char_type const *src_last, if constexpr (src_encoding != encoding_scheme::utf) { auto [code, adv] = general_advance(src_first, src_last - src_first); - if (adv == static_cast(-1)) + if (adv == static_cast(static_cast<::std::uint_least8_t>(-1))) { break; } @@ -311,7 +311,7 @@ general_code_cvt(src_char_type const *src_first, src_char_type const *src_last, } else { - dst += get_utf_code_units(static_cast(code), dst); + dst += get_utf_code_units(static_cast(static_cast<::std::uint_least32_t>(code)), dst); } } else @@ -333,7 +333,7 @@ general_code_cvt(src_char_type const *src_first, src_char_type const *src_last, } else { - dst += get_utf_code_units(static_cast(code), dst); + dst += get_utf_code_units(static_cast(static_cast<::std::uint_least32_t>(code)), dst); } } } @@ -457,7 +457,7 @@ inline constexpr dest_char_type *general_code_cvt(state_type &__restrict state, if (failed) { non_overlapped_copy_n(bytes, state_bytesm1, state.bytes); - state.size = static_cast(total_bytes); + state.size = static_cast(static_cast<::std::uint_least8_t>(total_bytes)); return dst; } if constexpr (sizeof(dest_char_type) == 4) @@ -471,17 +471,17 @@ inline constexpr dest_char_type *general_code_cvt(state_type &__restrict state, } else { - dst += get_utf_code_units(static_cast(code), dst); + dst += get_utf_code_units(static_cast(static_cast<::std::uint_least32_t>(code)), dst); } src_first += static_cast<::std::size_t>(bytes_src - bytes - state_size); } else { auto [code, adv] = general_advance(bytes, total_bytes); - if (adv == static_cast(-1)) + if (adv == static_cast(static_cast<::std::uint_least8_t>(-1))) { non_overlapped_copy_n(bytes, state_bytesm1, state.bytes); - state.size = static_cast(total_bytes); + state.size = static_cast(static_cast<::std::uint_least8_t>(total_bytes)); return dst; } if constexpr (sizeof(dest_char_type) == 4) @@ -495,14 +495,14 @@ inline constexpr dest_char_type *general_code_cvt(state_type &__restrict state, } else { - dst += get_utf_code_units(static_cast(code), dst); + dst += get_utf_code_units(static_cast(static_cast<::std::uint_least32_t>(code)), dst); } src_first += static_cast<::std::size_t>(static_cast<::std::size_t>(adv) - state_size); } } auto [new_src, new_dst] = general_code_cvt(src_first, src_last, dst); ::std::size_t diff{static_cast<::std::size_t>(src_last - new_src)}; - state.size = static_cast(diff); + state.size = static_cast(static_cast<::std::uint_least8_t>(diff)); non_overlapped_copy_n(new_src, diff, state.bytes); return new_dst; } diff --git a/include/fast_io_core_impl/codecvt/utf.h b/include/fast_io_core_impl/codecvt/utf.h index c38fc042c..c907bf20a 100644 --- a/include/fast_io_core_impl/codecvt/utf.h +++ b/include/fast_io_core_impl/codecvt/utf.h @@ -633,7 +633,7 @@ template <::std::integral T> 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 + char32_t cdpt{static_cast(static_cast<::std::uint_least32_t>(*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 < curr;) { @@ -663,7 +663,7 @@ template <::std::integral T> 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 + char32_t cdpt{static_cast(static_cast<::std::uint_least32_t>(*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 < curr;) diff --git a/include/fast_io_core_impl/codecvt/utf_ebcdic.h b/include/fast_io_core_impl/codecvt/utf_ebcdic.h index 260adf80f..8103e439a 100644 --- a/include/fast_io_core_impl/codecvt/utf_ebcdic.h +++ b/include/fast_io_core_impl/codecvt/utf_ebcdic.h @@ -73,42 +73,42 @@ inline constexpr ::std::size_t get_utf_ebcdic_code_units(char32_t code, T *dst) } else if (code < 0x400) { - *dst = static_cast(bm_i8_to_ebcdic[static_cast(0b11000000) | (code >> 5)]); + *dst = static_cast(bm_i8_to_ebcdic[static_cast(static_cast<::std::uint_least32_t>(0b11000000)) | (code >> 5)]); dst[1] = static_cast( - bm_i8_to_ebcdic[static_cast(0b10100000) | (code & static_cast(0b11111))]); + bm_i8_to_ebcdic[static_cast(static_cast<::std::uint_least32_t>(0b10100000)) | (code & static_cast(static_cast<::std::uint_least32_t>(0b11111)))]); return 2; } else if (code < 0x4000) { - *dst = static_cast(bm_i8_to_ebcdic[static_cast(0b11100000) | (code >> 10)]); + *dst = static_cast(bm_i8_to_ebcdic[static_cast(static_cast<::std::uint_least32_t>(0b11100000)) | (code >> 10)]); dst[1] = static_cast( - bm_i8_to_ebcdic[static_cast(0b10100000) | ((code >> 5) & static_cast(0b11111))]); + bm_i8_to_ebcdic[static_cast(static_cast<::std::uint_least32_t>(0b10100000)) | ((code >> 5) & static_cast(static_cast<::std::uint_least32_t>(0b11111)))]); dst[2] = static_cast( - bm_i8_to_ebcdic[static_cast(0b10100000) | (code & static_cast(0b11111))]); + bm_i8_to_ebcdic[static_cast(static_cast<::std::uint_least32_t>(0b10100000)) | (code & static_cast(static_cast<::std::uint_least32_t>(0b11111)))]); return 3; } else if (code < 0x40000) { - *dst = static_cast(bm_i8_to_ebcdic[static_cast(0b11110000) | (code >> 15)]); + *dst = static_cast(bm_i8_to_ebcdic[static_cast(static_cast<::std::uint_least32_t>(0b11110000)) | (code >> 15)]); dst[1] = static_cast( - bm_i8_to_ebcdic[static_cast(0b10100000) | ((code >> 10) & static_cast(0b11111))]); + bm_i8_to_ebcdic[static_cast(static_cast<::std::uint_least32_t>(0b10100000)) | ((code >> 10) & static_cast(static_cast<::std::uint_least32_t>(0b11111)))]); dst[2] = static_cast( - bm_i8_to_ebcdic[static_cast(0b10100000) | ((code >> 5) & static_cast(0b11111))]); + bm_i8_to_ebcdic[static_cast(static_cast<::std::uint_least32_t>(0b10100000)) | ((code >> 5) & static_cast(static_cast<::std::uint_least32_t>(0b11111)))]); dst[3] = static_cast( - bm_i8_to_ebcdic[static_cast(0b10100000) | (code & static_cast(0b11111))]); + bm_i8_to_ebcdic[static_cast(static_cast<::std::uint_least32_t>(0b10100000)) | (code & static_cast(static_cast<::std::uint_least32_t>(0b11111)))]); return 4; } else if (code < 0x110000) { - *dst = static_cast(bm_i8_to_ebcdic[static_cast(0b11111000) | (code >> 20)]); + *dst = static_cast(bm_i8_to_ebcdic[static_cast(static_cast<::std::uint_least32_t>(0b11111000)) | (code >> 20)]); dst[1] = static_cast( - bm_i8_to_ebcdic[static_cast(0b10100000) | ((code >> 15) & static_cast(0b11111))]); + bm_i8_to_ebcdic[static_cast(static_cast<::std::uint_least32_t>(0b10100000)) | ((code >> 15) & static_cast(static_cast<::std::uint_least32_t>(0b11111)))]); dst[2] = static_cast( - bm_i8_to_ebcdic[static_cast(0b10100000) | ((code >> 10) & static_cast(0b11111))]); + bm_i8_to_ebcdic[static_cast(static_cast<::std::uint_least32_t>(0b10100000)) | ((code >> 10) & static_cast(static_cast<::std::uint_least32_t>(0b11111)))]); dst[3] = static_cast( - bm_i8_to_ebcdic[static_cast(0b10100000) | ((code >> 5) & static_cast(0b11111))]); + bm_i8_to_ebcdic[static_cast(static_cast<::std::uint_least32_t>(0b10100000)) | ((code >> 5) & static_cast(static_cast<::std::uint_least32_t>(0b11111)))]); dst[4] = static_cast( - bm_i8_to_ebcdic[static_cast(0b10100000) | (code & static_cast(0b11111))]); + bm_i8_to_ebcdic[static_cast(static_cast<::std::uint_least32_t>(0b10100000)) | (code & static_cast(static_cast<::std::uint_least32_t>(0b11111)))]); return 5; } return get_utf_ebcdic_invalid_code_units(dst); @@ -124,11 +124,11 @@ template <::std::integral T> 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 src0(static_cast(static_cast<::std::uint_least8_t>(*src_first))); char8_t shadow{utfebcdic_shadow_flags[src0]}; if (shadow < 2) { - return {static_cast(bm_ebcdic_to_i8[src0]), 1}; + return {static_cast(static_cast<::std::uint_least32_t>(bm_ebcdic_to_i8[src0])), 1}; } if (shadow == 9) { @@ -136,12 +136,12 @@ inline constexpr from_ebcdic_result utf_ebcdic_advance(T *src_first, ::std::size } if (sz < shadow) { - return {0, static_cast(-1)}; + return {0, static_cast(static_cast<::std::uint_least8_t>(-1))}; } char32_t res{}; for (char8_t i{1}; i != shadow; ++i) { - char8_t code(bm_ebcdic_to_i8[static_cast(src_first[i])]); + char8_t code(bm_ebcdic_to_i8[static_cast(static_cast<::std::uint_least8_t>(src_first[i]))]); if ((code >> 5) != 0b101) [[unlikely]] { return {0xFFFD, i}; @@ -152,13 +152,13 @@ inline constexpr from_ebcdic_result utf_ebcdic_advance(T *src_first, ::std::size switch (shadow) { case 2: - return {((static_cast(src0i18 & 0b11111)) << 5) | res, 2}; + return {((static_cast(static_cast<::std::uint_least32_t>(src0i18 & 0b11111))) << 5) | res, 2}; case 3: - return {((static_cast(src0i18 & 0b1111)) << 10) | res, 3}; + return {((static_cast(static_cast<::std::uint_least32_t>(src0i18 & 0b1111))) << 10) | res, 3}; case 4: - return {((static_cast(src0i18 & 0b111)) << 15) | res, 4}; + return {((static_cast(static_cast<::std::uint_least32_t>(src0i18 & 0b111))) << 15) | res, 4}; case 5: - return {((static_cast(src0i18 & 0b1)) << 20) | res, 5}; + return {((static_cast(static_cast<::std::uint_least32_t>(src0i18 & 0b1))) << 20) | res, 5}; default: return {0xFFFD, shadow}; }; diff --git a/include/fast_io_core_impl/ebcdic.h b/include/fast_io_core_impl/ebcdic.h index 8eb67e09b..af09e92cc 100644 --- a/include/fast_io_core_impl/ebcdic.h +++ b/include/fast_io_core_impl/ebcdic.h @@ -20,13 +20,13 @@ inline constexpr bool exec_charset_is_ebcdic() noexcept } else if constexpr (sizeof(wchar_t) == sizeof(char32_t)) { - constexpr char32_t value{static_cast(L'A')}; + constexpr char32_t value{static_cast(static_cast<::std::uint_least32_t>(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'; + return static_cast(static_cast<::std::uint_least32_t>(L'A')) != U'A'; } } else @@ -48,7 +48,7 @@ inline constexpr bool wexec_charset_is_utf_none_native_endian() noexcept } else { - constexpr char32_t value{static_cast(L'A')}; + constexpr char32_t value{static_cast(static_cast<::std::uint_least32_t>(L'A'))}; constexpr char32_t swapped{::fast_io::byte_swap(value)}; return value != U'A' && swapped == U'A'; } diff --git a/include/fast_io_unit/gb18030.h b/include/fast_io_unit/gb18030.h index 5c6342d56..cd40c76b5 100644 --- a/include/fast_io_unit/gb18030.h +++ b/include/fast_io_unit/gb18030.h @@ -14,7 +14,7 @@ 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; + return ((a * static_cast(static_cast<::std::uint_least32_t>(10)) + b) * static_cast(static_cast<::std::uint_least32_t>(126)) + c) * static_cast(static_cast<::std::uint_least32_t>(10))tic_cast<::std::uint_least32_t>(10)) + d; } inline constexpr char32_t linear_18030_base{linear_18030(0x81, 0x30, 0x81, 0x30)}; @@ -66,7 +66,7 @@ inline constexpr ::std::size_t lookup_uni_to_gb18030(char32_t cdpt, T *p_dst) no { char32_t v{lookup_uni_to_gb18030_tb[cdpt]}; char16_t v2{static_cast(v)}; - if (static_cast(v2) == v) + if (static_cast(static_cast<::std::uint_least32_t>(v2)) == v) { if constexpr ((!::std::is_volatile_v) && (::std::endian::native == ::std::endian::little || ::std::endian::native == ::std::endian::big)) @@ -141,9 +141,9 @@ inline constexpr ::std::size_t get_gb18030_code_units_unhappy(char32_t cdpt, T * auto const &e{gb18030_ranges[i]}; auto const e0{e[0]}; auto const e1{e[1]}; - char32_t diff{static_cast(e1 - e0)}; + char32_t diff{static_cast(static_cast<::std::uint_least32_t>(e1 - e0))}; sum += diff; - if (static_cast(cdpt - e0) < diff) + if (static_cast(static_cast<::std::uint_least32_t>(cdpt - e0)) < diff) { char32_t e2{e[2]}; char32_t gb{cdpt - e0 + e2}; @@ -157,7 +157,7 @@ inline constexpr ::std::size_t get_gb18030_code_units_unhappy(char32_t cdpt, T * *p_dst = static_cast(0x81 + gb); return 4; } - else if (static_cast(cdpt - e1) < static_cast(gb18030_ranges[i + 1][0] - e1)) + else if (static_cast(static_cast<::std::uint_least32_t>(cdpt - e1)) < static_cast(static_cast<::std::uint_least32_t>(gb18030_ranges[i + 1][0] - e1))) { return lookup_uni_to_gb18030(cdpt - sum, p_dst); } @@ -172,7 +172,7 @@ inline constexpr ::std::size_t lookup_uni_to_gb18030_pdsz(char32_t cdpt, T *p_ds { char32_t v{lookup_uni_to_gb18030_tb[cdpt]}; char16_t v2{static_cast(v)}; - if (static_cast(v2) == v) + if (static_cast(static_cast<::std::uint_least32_t>(v2)) == v) { if (pdstsz < 2) { @@ -254,9 +254,9 @@ inline constexpr ::std::size_t get_gb18030_code_units_unhappy_pdstsz(char32_t u3 auto const &e{gb18030_ranges[i]}; auto const e0{e[0]}; auto const e1{e[1]}; - char32_t diff{static_cast(e1 - e0)}; + char32_t diff{static_cast(static_cast<::std::uint_least32_t>(e1 - e0))}; sum += diff; - if (static_cast(u32 - e0) < diff) + if (static_cast(static_cast<::std::uint_least32_t>(u32 - e0)) < diff) { char32_t e2{e[2]}; char32_t gb{u32 - e0 + e2}; @@ -274,7 +274,7 @@ inline constexpr ::std::size_t get_gb18030_code_units_unhappy_pdstsz(char32_t u3 *p_dst = static_cast(0x81 + gb); return 4; } - else if (static_cast(u32 - e1) < static_cast(gb18030_ranges[i + 1][0] - e1)) + else if (static_cast(static_cast<::std::uint_least32_t>(u32 - e1)) < static_cast(static_cast<::std::uint_least32_t>(gb18030_ranges[i + 1][0] - e1))) { return lookup_uni_to_gb18030(u32 - sum, p_dst); } @@ -315,11 +315,11 @@ inline constexpr char32_t utf32cp_by_gb18030_index(char32_t index) noexcept auto const &e{gb18030_ranges[i]}; auto const e0{e[0]}; auto const e1{e[1]}; - sum += static_cast(e1 - e0); + sum += static_cast(static_cast<::std::uint_least32_t>(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) + char32_t diff{static_cast(static_cast<::std::uint_least32_t>(e3 - e2))}; + if (static_cast(static_cast<::std::uint_least32_t>(index - e2)) <= diff) { return index - e[2] + e[0]; } @@ -361,7 +361,7 @@ inline constexpr gb18030_advance_unchecked_result gb18030_advance_unchecked(T --c; } return { - lookup_gb18030_to_uni2_tb[static_cast((static_cast(src0) - 0x81) * 190u + (c - 0x40))], + lookup_gb18030_to_uni2_tb[static_cast((static_cast(static_cast<::std::uint_least32_t>(src0)) - 0x81) * 190u + (c - 0x40))], 2}; } else if ((src1 < 0x30) | (src1 == 0xFF)) @@ -415,7 +415,7 @@ inline constexpr gb18030_advance_unchecked_result gb18030_advance(T const *sr --c; } return { - lookup_gb18030_to_uni2_tb[static_cast((static_cast(src0) - 0x81) * 190u + (c - 0x40))], + lookup_gb18030_to_uni2_tb[static_cast((static_cast(static_cast<::std::uint_least32_t>(src0)) - 0x81) * 190u + (c - 0x40))], 2}; } else if ((src1 < 0x30) | (src1 == 0xFF)) From e84e9ff802bbd56188b7b75c0f09fbbff5a41b4f Mon Sep 17 00:00:00 2001 From: trcrsired Date: Wed, 24 Sep 2025 05:13:45 +0800 Subject: [PATCH 77/81] correctly ignore wifianalyzer example --- examples/.test_prop.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/.test_prop.toml b/examples/.test_prop.toml index 7eb3b0f5d..405e56a33 100644 --- a/examples/.test_prop.toml +++ b/examples/.test_prop.toml @@ -40,5 +40,5 @@ interactive = true ["0039.gen_win32_mangling"] ignore = true -["0040".wifianalyzer"] +["0040.wifianalyzer"] ignore = true From d5ed92b810981ebc03e947fdf587bd4dda950143 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Wed, 24 Sep 2025 05:20:24 +0800 Subject: [PATCH 78/81] remove unused variable --- include/fast_io_dsal/impl/str_btree_set.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/fast_io_dsal/impl/str_btree_set.h b/include/fast_io_dsal/impl/str_btree_set.h index 24c2c315c..183430fbc 100644 --- a/include/fast_io_dsal/impl/str_btree_set.h +++ b/include/fast_io_dsal/impl/str_btree_set.h @@ -139,7 +139,6 @@ inline constexpr bool str_btree_insert_key_cold(nodetype *node, ::std::size_t po auto keys{node->keys}; - auto n{node->size}; auto keysit{keys + pos}; auto keysed{keys + keys_number}; From edeeefd5308db5b983589a421091cb9cacd11ce7 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Wed, 24 Sep 2025 05:25:24 +0800 Subject: [PATCH 79/81] Use reverse_iterator instead of reverse_view since CI does not support it --- tests/0026.container/0013.str_btree_set/str_btree_set.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/0026.container/0013.str_btree_set/str_btree_set.cc b/tests/0026.container/0013.str_btree_set/str_btree_set.cc index e78a3fb31..47199bd8d 100644 --- a/tests/0026.container/0013.str_btree_set/str_btree_set.cc +++ b/tests/0026.container/0013.str_btree_set/str_btree_set.cc @@ -41,8 +41,13 @@ int main() } ::fast_io::io::print("\nreverse:\n"); +/* +// ::std::ranges::reverse_view does not pass CI for (auto const &e : ::std::ranges::reverse_view(bset)) +*/ + for(auto i{bset.crbegin()},ed{bset.crend()};i!=ed;++i) { + auto& e{*i}; ::fast_io::io::println(e); } From 7541ee0fbfb7e30ae6e4bf2907e4a6cfed8efe71 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Wed, 24 Sep 2025 05:36:33 +0800 Subject: [PATCH 80/81] Fix str_btree_set.cc --- tests/0026.container/0013.str_btree_set/str_btree_set.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/0026.container/0013.str_btree_set/str_btree_set.cc b/tests/0026.container/0013.str_btree_set/str_btree_set.cc index 47199bd8d..11c49ddb7 100644 --- a/tests/0026.container/0013.str_btree_set/str_btree_set.cc +++ b/tests/0026.container/0013.str_btree_set/str_btree_set.cc @@ -47,7 +47,7 @@ int main() */ for(auto i{bset.crbegin()},ed{bset.crend()};i!=ed;++i) { - auto& e{*i}; + auto const& e{*i}; ::fast_io::io::println(e); } From e77453e0646395902fdced1b929f6020ae6e5021 Mon Sep 17 00:00:00 2001 From: trcrsired Date: Wed, 24 Sep 2025 05:49:59 +0800 Subject: [PATCH 81/81] fix ifdef issue for printf --- include/fast_io_dsal/impl/str_btree_set.h | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/include/fast_io_dsal/impl/str_btree_set.h b/include/fast_io_dsal/impl/str_btree_set.h index 183430fbc..1c6945238 100644 --- a/include/fast_io_dsal/impl/str_btree_set.h +++ b/include/fast_io_dsal/impl/str_btree_set.h @@ -394,7 +394,9 @@ inline constexpr bool str_btree_erase(::fast_io::containers::details::btree_imp auto parent{static_cast(itv->parent)}; if (itv->leaf) { +#ifdef TESTING_STR_BTREE_SET __builtin_printf("hello world: %s %d\n",__FILE__,__LINE__); +#endif if (keys_number_half < n) { ::fast_io::freestanding::overlapped_copy(keyspos + 1, keys + n, keyspos); @@ -415,7 +417,9 @@ inline constexpr bool str_btree_erase(::fast_io::containers::details::btree_imp } ::std::size_t parpos{itv->parent_pos}; ::std::size_t parent_size{parent->size}; +#ifdef TESTING_STR_BTREE_SET __builtin_printf("hello world: %s %d\n",__FILE__,__LINE__); +#endif nodeptr rightbrother{}; if (parpos != parent_size) { @@ -445,7 +449,9 @@ inline constexpr bool str_btree_erase(::fast_io::containers::details::btree_imp return true; } } +#ifdef TESTING_STR_BTREE_SET __builtin_printf("hello world: %s %d\n",__FILE__,__LINE__); +#endif // Try left brother if right failed nodeptr leftbrother{}; if (parpos != 0) @@ -471,8 +477,10 @@ inline constexpr bool str_btree_erase(::fast_io::containers::details::btree_imp // Update parent key parent_key = borrowed_key; --leftbrother->size; +#ifdef TESTING_STR_BTREE_SET __builtin_printf("hello world: %s %d\n",__FILE__,__LINE__); - return true; +#endif + return true; } } // Merge with sibling (prefer right if possible) @@ -499,7 +507,9 @@ inline constexpr bool str_btree_erase(::fast_io::containers::details::btree_imp parent->childrens + parent_size + 1, parent->childrens + parpos + 1); --parent->size; +#ifdef TESTING_STR_BTREE_SET __builtin_printf("hello world: %s %d\n",__FILE__,__LINE__); +#endif return true; } else @@ -530,9 +540,11 @@ inline constexpr bool str_btree_erase(::fast_io::containers::details::btree_imp return true; } } - __builtin_printf("hello world: %s %d\n",__FILE__,__LINE__); -#if 0 +#ifdef TESTING_STR_BTREE_SET + __builtin_printf("hello world: %s %d\n",__FILE__,__LINE__); +#endif +#if 0 ::fast_io::io::debug_println(::std::source_location::current(),"\t", ::fast_io::mnp::os_c_str_with_known_size(keystrptr, keystrn));