From b79df0c65ed1cae305a6e82934eb098d3862e68b Mon Sep 17 00:00:00 2001 From: yyc12345 Date: Fri, 25 Jul 2025 10:49:07 +0800 Subject: [PATCH] refactor: continue refactor project from C++17 to 23 --- src/CMakeLists.txt | 5 +- src/yycc/encoding/stlcvt.cpp | 154 +++------- src/yycc/encoding/stlcvt.hpp | 57 ++-- src/yycc/encoding/windows.cpp | 265 ++++-------------- src/yycc/encoding/windows.hpp | 144 ++++++---- src/yycc/macro/compiler_detector.hpp | 25 ++ src/yycc/macro/endian_detector.hpp | 21 ++ src/yycc/macro/os_detector.hpp | 22 ++ src/yycc/prelude/core.hpp | 21 -- src/yycc/rust/option.hpp | 10 +- src/yycc/rust/panic.cpp | 7 - src/yycc/rust/panic.hpp | 10 - .../{prelude/rust.hpp => rust/prelude.hpp} | 17 +- src/yycc/{ => rust}/primitive.hpp | 2 +- src/yycc/rust/result.hpp | 8 - src/yycc/string/op.cpp | 2 +- src/yycc/string/op.hpp | 4 +- src/yycc/windows/com.cpp | 0 src/yycc/windows/com.hpp | 0 src/yycc/windows/dialog.cpp | 0 src/yycc/windows/dialog.hpp | 0 src/yycc/windows/import_guard_head.hpp | 20 +- 22 files changed, 296 insertions(+), 498 deletions(-) delete mode 100644 src/yycc/prelude/core.hpp rename src/yycc/{prelude/rust.hpp => rust/prelude.hpp} (78%) rename src/yycc/{ => rust}/primitive.hpp (94%) delete mode 100644 src/yycc/windows/com.cpp delete mode 100644 src/yycc/windows/com.hpp delete mode 100644 src/yycc/windows/dialog.cpp delete mode 100644 src/yycc/windows/dialog.hpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6c23d52..cc064a3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -26,9 +26,6 @@ FILES # Headers yycc.hpp yycc/version.hpp - yycc/primitive.hpp - yycc/prelude/core.hpp - yycc/prelude/rust.hpp yycc/macro/version_cmp.hpp yycc/macro/os_detector.hpp yycc/macro/endian_detector.hpp @@ -38,6 +35,8 @@ FILES yycc/string/op.hpp yycc/num/parse.hpp yycc/num/stringify.hpp + yycc/rust/prelude.hpp + yycc/rust/primitive.hpp yycc/rust/panic.hpp yycc/rust/option.hpp yycc/rust/result.hpp diff --git a/src/yycc/encoding/stlcvt.cpp b/src/yycc/encoding/stlcvt.cpp index 7f438b1..2aa5142 100644 --- a/src/yycc/encoding/stlcvt.cpp +++ b/src/yycc/encoding/stlcvt.cpp @@ -1,38 +1,26 @@ #include "stlcvt.hpp" #include -#define NS_YYCC_STRING ::yycc::string -#define NS_YYCC_PATCH_EXPECTED ::yycc::patch::expected - namespace yycc::encoding::stlcvt { #pragma region Generic Converter /* - * NOTE: + * YYC MARK: * According to the documentation introduced in CppReference. * The standard library is guaranteed to provide several specific specializations of \c std::codecvt. - * The UTF8 char type in UTF8 related specializations of \c std::codecvt is different. - * It is also independend from we defined char type. - * So it is essential define a type which can correctly trigger specific specializations of \c std::codecv in there. + * The UTF8 char type in UTF8 related specializations of \c std::codecvt is different in different C++ standard. + * But the oldest C++ version YYCC supported is C++ 23, char8_t is the only viable UTF8 char type for \c std::codecvt. + * So we can simply and safely use it to correctly trigger specific specializations of \c std::codecv in there. */ -#if defined(YYCC_CPPFEAT_UTF8) - using CodecvtUtf8Char = char8_t; -#else - using CodecvtUtf8Char = char; -#endif + template + requires(std::is_same_v || std::is_same_v) + using CodecvtFacet = std::codecvt; - template || std::is_same_v, int> - = 0> - using CodecvtFacet = std::codecvt; - - template || std::is_same_v, int> - = 0> - static ConvResult> generic_to_utf_other( - const NS_YYCC_STRING::u8string_view& src) { + template + requires(std::is_same_v || std::is_same_v) + static ConvResult> generic_to_utf_other(const std::u8string_view& src) { // Reference: // https://en.cppreference.com/w/cpp/locale/codecvt/in @@ -52,38 +40,27 @@ namespace yycc::encoding::stlcvt { // convertion preparation std::mbstate_t mb{}; dst.resize(src.size()); - const CodecvtUtf8Char *intern_from = reinterpret_cast(src.data()), - *intern_from_end = reinterpret_cast( - src.data() + src.size()), - *intern_from_next = nullptr; - TChar *extern_to = dst.data(), *extern_to_end = dst.data() + dst.size(), - *extern_to_next = nullptr; + const char8_t *intern_from = reinterpret_cast(src.data()), + *intern_from_end = reinterpret_cast(src.data() + src.size()), *intern_from_next = nullptr; + TChar *extern_to = dst.data(), *extern_to_end = dst.data() + dst.size(), *extern_to_next = nullptr; // do convertion - auto result = this_codecvt.in(mb, - intern_from, - intern_from_end, - intern_from_next, - extern_to, - extern_to_end, - extern_to_next); + auto result = this_codecvt.in(mb, intern_from, intern_from_end, intern_from_next, extern_to, extern_to_end, extern_to_next); // check result - if (result != CodecvtFacet::ok) return ConvError(); + if (result != CodecvtFacet::ok) return std::unexpected(ConvError{}); // resize result and return dst.resize(extern_to_next - dst.data()); return dst; } - template || std::is_same_v, int> - = 0> - static ConvResult generic_to_utf8( - const std::basic_string_view& src) { + template + requires(std::is_same_v || std::is_same_v) + static ConvResult generic_to_utf8(const std::basic_string_view& src) { // Reference: // https://en.cppreference.com/w/cpp/locale/codecvt/out // prepare return value - NS_YYCC_STRING::u8string dst; + std::u8string dst; // if src is empty, return directly if (src.empty()) { @@ -99,102 +76,43 @@ namespace yycc::encoding::stlcvt { // do convertion preparation std::mbstate_t mb{}; dst.resize(src.size() * this_codecvt.max_length()); - const TChar *intern_from = src.data(), *intern_from_end = src.data() + src.size(), - *intern_from_next = nullptr; - CodecvtUtf8Char *extern_to = reinterpret_cast(dst.data()), - *extern_to_end = reinterpret_cast(dst.data() + dst.size()), - *extern_to_next = nullptr; + const TChar *intern_from = src.data(), *intern_from_end = src.data() + src.size(), *intern_from_next = nullptr; + char8_t *extern_to = reinterpret_cast(dst.data()), *extern_to_end = reinterpret_cast(dst.data() + dst.size()), + *extern_to_next = nullptr; // do convertion - auto result = this_codecvt.out(mb, - intern_from, - intern_from_end, - intern_from_next, - extern_to, - extern_to_end, - extern_to_next); + auto result = this_codecvt.out(mb, intern_from, intern_from_end, intern_from_next, extern_to, extern_to_end, extern_to_next); // check result - if (result != CodecvtFacet::ok) return ConvError(); + if (result != CodecvtFacet::ok) return std::unexpected(ConvError{}); // resize result and retuen - dst.resize(extern_to_next - reinterpret_cast(dst.data())); + dst.resize(extern_to_next - reinterpret_cast(dst.data())); return dst; } -#pragma endregion +#pragma endregion Converter -#pragma region Help Macros +#pragma region -#define CONVFN_TYPE1(fct_name, src_char_type, dst_char_type) \ - namespace expected = NS_YYCC_PATCH_EXPECTED; \ - auto rv = priv_##fct_name(src); \ - if (expected::is_value(rv)) { \ - dst = std::move(expected::get_value(rv)); \ - return true; \ - } else { \ - return false; \ - } - -#define CONVFN_TYPE2(fct_name, src_char_type, dst_char_type) \ - std::basic_string rv; \ - if (fct_name(src, rv)) return rv; \ - else throw std::runtime_error("fail to convert utf string"); - -#pragma endregion - -#pragma region UTF8 -> UTF16 - - ConvResult priv_to_utf16(const NS_YYCC_STRING::u8string_view& src) { + ConvResult to_utf16(const std::u8string_view& src) { + // UTF8 -> UTF16 return generic_to_utf_other(src); } - bool to_utf16(const NS_YYCC_STRING::u8string_view& src, std::u16string& dst) { - CONVFN_TYPE1(to_utf16, NS_YYCC_STRING::u8char, char16_t); - } - std::u16string to_utf16(const NS_YYCC_STRING::u8string_view& src) { - CONVFN_TYPE2(to_utf16, NS_YYCC_STRING::u8char, char16_t); - } -#pragma endregion - -#pragma region UTF16 -> UTF8 - - ConvResult priv_to_utf8(const std::u16string_view& src) { + ConvResult to_utf8(const std::u16string_view& src) { + // UTF16 -> UTF8 return generic_to_utf8(src); } - bool to_utf8(const std::u16string_view& src, NS_YYCC_STRING::u8string& dst) { - CONVFN_TYPE1(to_utf8, char16_t, NS_YYCC_STRING::u8char); - } - NS_YYCC_STRING::u8string to_utf8(const std::u16string_view& src) { - CONVFN_TYPE2(to_utf8, char16_t, NS_YYCC_STRING::u8char); - } -#pragma endregion - -#pragma region UTF8 -> UTF32 - - ConvResult priv_to_utf32(const NS_YYCC_STRING::u8string_view& src) { + ConvResult to_utf32(const std::u8string_view& src) { + // UTF8 -> UTF32 return generic_to_utf_other(src); } - bool to_utf32(const NS_YYCC_STRING::u8string_view& src, std::u32string& dst) { - CONVFN_TYPE1(to_utf32, NS_YYCC_STRING::u8char, char32_t); - } - std::u32string to_utf32(const NS_YYCC_STRING::u8string_view& src) { - CONVFN_TYPE2(to_utf32, NS_YYCC_STRING::u8char, char32_t); - } -#pragma endregion - -#pragma region UTF32 -> UTF8 - - ConvResult priv_to_utf8(const std::u32string_view& src) { + ConvResult to_utf8(const std::u32string_view& src) { + // UTF32 -> UTF8 return generic_to_utf8(src); } - bool to_utf8(const std::u32string_view& src, NS_YYCC_STRING::u8string& dst) { - CONVFN_TYPE1(to_utf8, char32_t, NS_YYCC_STRING::u8char); - } - NS_YYCC_STRING::u8string to_utf8(const std::u32string_view& src) { - CONVFN_TYPE2(to_utf8, char32_t, NS_YYCC_STRING::u8char); - } #pragma endregion -} // namespace yycc::encoding::utf +} // namespace yycc::encoding::stlcvt diff --git a/src/yycc/encoding/stlcvt.hpp b/src/yycc/encoding/stlcvt.hpp index 4f16a1b..f6f8ee1 100644 --- a/src/yycc/encoding/stlcvt.hpp +++ b/src/yycc/encoding/stlcvt.hpp @@ -1,40 +1,43 @@ #pragma once -#include "../string.hpp" -#include "../patch/expected.hpp" - -#define NS_YYCC_STRING ::yycc::string -#define NS_YYCC_PATCH_EXPECTED ::yycc::patch::expected +#include +#include +#include namespace yycc::encoding::stlcvt { - /// @private + /// @brief Possible convertion error occurs in this module. struct ConvError {}; - /// @private + /// @brief The result type of this module. template - using ConvResult = NS_YYCC_PATCH_EXPECTED::Expected; + using ConvResult = std::expected; - // UTF8 -> UTF16 - ConvResult priv_to_utf16(const NS_YYCC_STRING::u8string_view& src); - bool to_utf16(const NS_YYCC_STRING::u8string_view& src, std::u16string& dst); - std::u16string to_utf16(const NS_YYCC_STRING::u8string_view& src); + /** + * @brief UTF8 -> UTF16 + * @param src + * @return + */ + ConvResult to_utf16(const std::u8string_view& src); - // UTF16 -> UTF8 - ConvResult priv_to_utf8(const std::u16string_view& src); - bool to_utf8(const std::u16string_view& src, NS_YYCC_STRING::u8string& dst); - NS_YYCC_STRING::u8string to_utf8(const std::u16string_view& src); + /** + * @brief UTF16 -> UTF8 + * @param src + * @return + */ + ConvResult to_utf8(const std::u16string_view& src); - // UTF8 -> UTF32 - ConvResult priv_to_utf32(const NS_YYCC_STRING::u8string_view& src); - bool to_utf32(const NS_YYCC_STRING::u8string_view& src, std::u32string& dst); - std::u32string to_utf32(const NS_YYCC_STRING::u8string_view& src); + /** + * @brief UTF8 -> UTF32 + * @param src + * @return + */ + ConvResult to_utf32(const std::u8string_view& src); - // UTF32 -> UTF8 - ConvResult priv_to_utf8(const std::u32string_view& src); - bool to_utf8(const std::u32string_view& src, NS_YYCC_STRING::u8string& dst); - NS_YYCC_STRING::u8string to_utf8(const std::u32string_view& src); + /** + * @brief UTF32 -> UTF8 + * @param src + * @return + */ + ConvResult utf8(const std::u32string_view& src); } - -#undef NS_YYCC_PATCH_EXPECTED -#undef NS_YYCC_STRING diff --git a/src/yycc/encoding/windows.cpp b/src/yycc/encoding/windows.cpp index 43ef690..474113e 100644 --- a/src/yycc/encoding/windows.cpp +++ b/src/yycc/encoding/windows.cpp @@ -11,34 +11,14 @@ #include #include "../windows/import_guard_tail.hpp" -#define NS_YYCC_STRING ::yycc::string #define NS_YYCC_STRING_REINTERPRET ::yycc::string::reinterpret -#define NS_YYCC_PATCH_EXPECTED ::yycc::patch::expected namespace yycc::encoding::windows { -#pragma region Help Macros +#pragma region WideCharToMultiByte and MultiByteToWideChar stuff -#define CONVFN_TYPE1(fct_name, src_char_type, dst_char_type, ...) \ - namespace expected = NS_YYCC_PATCH_EXPECTED; \ - auto rv = priv_##fct_name(src, ##__VA_ARGS__); \ - if (expected::is_value(rv)) { \ - dst = std::move(expected::get_value(rv)); \ - return true; \ - } else { \ - return false; \ - } - -#define CONVFN_TYPE2(fct_name, src_char_type, dst_char_type, ...) \ - std::basic_string rv; \ - if (fct_name(src, rv, ##__VA_ARGS__)) return rv; \ - else throw std::runtime_error("fail to convert string in Win32 function"); - -#pragma endregion - -#pragma region WChar -> Char - - ConvResult priv_to_char(const std::wstring_view& src, CodePage code_page) { + // WChar -> Char + ConvResult to_char(const std::wstring_view& src, CodePage code_page) { // prepare result std::string dst; @@ -52,36 +32,25 @@ namespace yycc::encoding::windows { LPCWCH lpWideCharStr = reinterpret_cast(src.data()); // check whether source string is too large. size_t cSrcSize = src.size(); - if (cSrcSize > std::numeric_limits::max()) return ConvError::TooLargeLength; + if (cSrcSize > std::numeric_limits::max()) return std::unexpected(ConvError::TooLargeLength); int cchWideChar = static_cast(src.size()); // do convertion // do a dry-run first to fetch desired size. int desired_size = WideCharToMultiByte(code_page, 0, lpWideCharStr, cchWideChar, NULL, 0, NULL, NULL); - if (desired_size <= 0) return ConvError::NoDesiredSize; + if (desired_size <= 0) return std::unexpected(ConvError::NoDesiredSize); // resize dest for receiving result dst.resize(static_cast(desired_size)); // do real convertion int write_result = WideCharToMultiByte(code_page, 0, lpWideCharStr, cchWideChar, reinterpret_cast(dst.data()), desired_size, NULL, NULL); - if (write_result <= 0) return ConvError::BadWrittenSize; + if (write_result <= 0) return std::unexpected(ConvError::BadWrittenSize); return dst; } - bool to_char(const std::wstring_view& src, std::string& dst, CodePage code_page) { - CONVFN_TYPE1(to_char, wchar_t, char, code_page); - } - - std::string to_char(const std::wstring_view& src, CodePage code_page) { - CONVFN_TYPE2(to_char, wchar_t, char, code_page); - } - -#pragma endregion - -#pragma region Char -> WChar - - ConvResult priv_to_wchar(const std::string_view& src, CodePage code_page) { + // Char -> WChar + ConvResult to_wchar(const std::string_view& src, CodePage code_page) { // prepare result std::wstring dst; @@ -95,134 +64,53 @@ namespace yycc::encoding::windows { LPCCH lpMultiByteStr = reinterpret_cast(src.data()); // check whether source string is too large. size_t cSrcSize = src.size(); - if (cSrcSize > std::numeric_limits::max()) return ConvError::TooLargeLength; + if (cSrcSize > std::numeric_limits::max()) return std::unexpected(ConvError::TooLargeLength); int cbMultiByte = static_cast(src.size()); // do convertion // do a dry-run first to fetch desired size. int desired_size = MultiByteToWideChar(code_page, 0, lpMultiByteStr, cbMultiByte, NULL, 0); - if (desired_size <= 0) return ConvError::NoDesiredSize; + if (desired_size <= 0) return std::unexpected(ConvError::NoDesiredSize); // resize dest for receiving result dst.resize(static_cast(desired_size)); // do real convertion int write_result = MultiByteToWideChar(code_page, 0, lpMultiByteStr, cbMultiByte, reinterpret_cast(dst.data()), desired_size); - if (write_result <= 0) return ConvError::BadWrittenSize; + if (write_result <= 0) return std::unexpected(ConvError::BadWrittenSize); return dst; } - bool to_wchar(const std::string_view& src, std::wstring& dst, CodePage code_page) { - CONVFN_TYPE1(to_wchar, char, wchar_t, code_page); + // Char -> Char + ConvResult to_char(const std::string_view& src, CodePage src_code_page, CodePage dst_code_page) { + auto first_rv = to_wchar(src, src_code_page); + return first_rv.and_then([dst_code_page](const auto& src) { return to_char(src, dst_code_page); }); } - std::wstring to_wchar(const std::string_view& src, CodePage code_page) { - CONVFN_TYPE2(to_wchar, char, wchar_t, code_page); + // WChar -> UTF8 + ConvResult to_utf8(const std::wstring_view& src) { + auto rv = to_char(src, CP_UTF8); + return rv.transform([](const auto& dst) { return NS_YYCC_STRING_REINTERPRET::as_utf8(dst); }); + } + + // UTF8 -> WChar + ConvResult to_wchar(const std::u8string_view& src) { + return to_wchar(NS_YYCC_STRING_REINTERPRET::as_ordinary_view(src), CP_UTF8); + } + + // Char -> UTF8 + ConvResult to_utf8(const std::string_view& src, CodePage code_page) { + auto rv = to_char(src, code_page, CP_UTF8); + return rv.transform([](const auto& dst) { return NS_YYCC_STRING_REINTERPRET::as_utf8(dst); }); + } + + // UTF8 -> Char + ConvResult to_char(const std::u8string_view& src, CodePage code_page) { + return to_char(NS_YYCC_STRING_REINTERPRET::as_ordinary_view(src), CP_UTF8, code_page); } #pragma endregion -#pragma region Char -> Char - - ConvResult priv_to_char(const std::string_view& src, CodePage src_code_page, CodePage dst_code_page) { - namespace expected = NS_YYCC_PATCH_EXPECTED; - - // Perform first convertion - auto first_rv = priv_to_wchar(src, src_code_page); - if (expected::is_error(first_rv)) { - return expected::get_error(first_rv); - } - // Perform second convertion - auto second_rv = to_char(std::get(first_rv), dst_code_page); - return second_rv; - } - - bool to_char(const std::string_view& src, std::string& dst, CodePage src_code_page, CodePage dst_code_page) { - CONVFN_TYPE1(to_char, char, char, src_code_page, dst_code_page); - } - - std::string to_char(const std::string_view& src, CodePage src_code_page, CodePage dst_code_page) { - CONVFN_TYPE2(to_char, char, char, src_code_page, dst_code_page); - } - -#pragma endregion - -#pragma region WChar -> UTF8 - - ConvResult priv_to_utf8(const std::wstring_view& src) { - namespace expected = NS_YYCC_PATCH_EXPECTED; - - auto rv = priv_to_char(src, CP_UTF8); - if (expected::is_value(rv)) { - return NS_YYCC_STRING_REINTERPRET::as_utf8(expected::get_value(rv)); - } else { - return expected::get_error(rv); - } - } - - bool to_utf8(const std::wstring_view& src, NS_YYCC_STRING::u8string& dst) { - CONVFN_TYPE1(to_utf8, wchar_t, NS_YYCC_STRING::u8char); - } - - NS_YYCC_STRING::u8string to_utf8(const std::wstring_view& src) { - CONVFN_TYPE2(to_utf8, wchar_t, NS_YYCC_STRING::u8char); - } - -#pragma endregion - -#pragma region UTF8 -> WChar - - ConvResult priv_to_wchar(const NS_YYCC_STRING::u8string_view& src) { - return priv_to_wchar(NS_YYCC_STRING_REINTERPRET::as_ordinary_view(src), CP_UTF8); - } - - bool to_wchar(const NS_YYCC_STRING::u8string_view& src, std::wstring& dst) { - CONVFN_TYPE1(to_wchar, NS_YYCC_STRING::u8char, wchar_t); - } - - std::wstring to_wchar(const NS_YYCC_STRING::u8string_view& src) { - CONVFN_TYPE2(to_wchar, NS_YYCC_STRING::u8char, wchar_t); - } - -#pragma endregion - -#pragma region Char -> UTF8 - - ConvResult priv_to_utf8(const std::string_view& src, CodePage code_page) { - namespace expected = NS_YYCC_PATCH_EXPECTED; - - auto rv = priv_to_char(src, code_page, CP_UTF8); - if (expected::is_value(rv)) { - return NS_YYCC_STRING_REINTERPRET::as_utf8(expected::get_value(rv)); - } else { - return expected::get_error(rv); - } - } - - bool to_utf8(const std::string_view& src, NS_YYCC_STRING::u8string& dst, CodePage code_page) { - CONVFN_TYPE1(to_utf8, char, NS_YYCC_STRING::u8char, code_page); - } - - NS_YYCC_STRING::u8string to_utf8(const std::string_view& src, CodePage code_page) { - CONVFN_TYPE2(to_utf8, char, NS_YYCC_STRING::u8char, code_page); - } - -#pragma endregion - -#pragma region UTF8 -> Char - - ConvResult priv_to_char(const NS_YYCC_STRING::u8string_view& src, CodePage code_page) { - return priv_to_char(NS_YYCC_STRING_REINTERPRET::as_ordinary_view(src), CP_UTF8, code_page); - } - - bool to_char(const NS_YYCC_STRING::u8string_view& src, std::string& dst, CodePage code_page) { - CONVFN_TYPE1(to_char, NS_YYCC_STRING::u8char, char, code_page); - } - - std::string to_char(const NS_YYCC_STRING::u8string_view& src, CodePage code_page) { - CONVFN_TYPE2(to_char, NS_YYCC_STRING::u8char, char, code_page); - } - -#pragma endregion +#pragma region UTF stuff // YYC MARK: // The convertion between UTF is implemented by c16rtomb, c32rtomb, mbrtoc16 and mbrtoc32. @@ -239,9 +127,8 @@ namespace yycc::encoding::windows { constexpr size_t MULTIPLE_UTF8_TO_UTF32 = 1u; constexpr size_t MULTIPLE_UTF32_TO_UTF8 = 4u; -#pragma region UTF8 -> UTF16 - - ConvResult priv_to_utf16(const NS_YYCC_STRING::u8string_view& src) { + // UTF8 -> UTF16 + ConvResult to_utf16(const std::u8string_view& src) { std::u16string dst; dst.reserve(src.size() * MULTIPLE_UTF8_TO_UTF16); @@ -253,8 +140,8 @@ namespace yycc::encoding::windows { while (ptr < end) { size_t rc = std::mbrtoc16(&c16, ptr, end - ptr, &state); - if (rc == (size_t) -1) return ConvError::EncodeUtf8; - else if (rc == (size_t) -2) return ConvError::IncompleteUtf8; + if (rc == (size_t) -1) return std::unexpected(ConvError::EncodeUtf8); + else if (rc == (size_t) -2) return std::unexpected(ConvError::IncompleteUtf8); else if (rc != (size_t) -3) dst.push_back(c16); // from earlier surrogate pair else { dst.push_back(c16); @@ -264,20 +151,9 @@ namespace yycc::encoding::windows { return dst; } - bool to_utf16(const NS_YYCC_STRING::u8string_view& src, std::u16string& dst) { - CONVFN_TYPE1(to_utf16, NS_YYCC_STRING::u8char, char16_t); - } - - std::u16string to_utf16(const NS_YYCC_STRING::u8string_view& src) { - CONVFN_TYPE2(to_utf16, NS_YYCC_STRING::u8char, char16_t); - } - -#pragma endregion - -#pragma region UTF16 -> UTF8 - - ConvResult priv_to_utf8(const std::u16string_view& src) { - NS_YYCC_STRING::u8string dst; + // UTF16 -> UTF8 + ConvResult to_utf8(const std::u16string_view& src) { + std::u8string dst; dst.reserve(src.size() * MULTIPLE_UTF16_TO_UTF8); std::mbstate_t state{}; @@ -285,25 +161,14 @@ namespace yycc::encoding::windows { for (char16_t c : src) { size_t rc = std::c16rtomb(mbout, c, &state); - if (rc != (size_t) -1) dst.append(reinterpret_cast(mbout), rc); - else return ConvError::InvalidUtf16; + if (rc != (size_t) -1) dst.append(reinterpret_cast(mbout), rc); + else return std::unexpected(ConvError::InvalidUtf16); } return dst; } - bool to_utf8(const std::u16string_view& src, NS_YYCC_STRING::u8string& dst) { - CONVFN_TYPE1(to_utf8, char16_t, NS_YYCC_STRING::u8char); - } - - NS_YYCC_STRING::u8string to_utf8(const std::u16string_view& src) { - CONVFN_TYPE2(to_utf8, char16_t, NS_YYCC_STRING::u8char); - } - -#pragma endregion - -#pragma region UTF8 -> UTF32 - - ConvResult priv_to_utf32(const NS_YYCC_STRING::u8string_view& src) { + // UTF8 -> UTF32 + ConvResult to_utf32(const std::u8string_view& src) { std::u32string dst; dst.reserve(src.size() * MULTIPLE_UTF8_TO_UTF32); @@ -315,8 +180,8 @@ namespace yycc::encoding::windows { while (ptr < end) { size_t rc = std::mbrtoc32(&c32, ptr, end - ptr, &state); - if (rc == (size_t) -1) return ConvError::EncodeUtf8; - else if (rc == (size_t) -2) return ConvError::IncompleteUtf8; + if (rc == (size_t) -1) return std::unexpected(ConvError::EncodeUtf8); + else if (rc == (size_t) -2) return std::unexpected(ConvError::IncompleteUtf8); else if (rc != (size_t) -3) throw std::runtime_error("no surrogates in UTF-32"); else dst.push_back(c32); @@ -325,20 +190,9 @@ namespace yycc::encoding::windows { return dst; } - bool to_utf32(const NS_YYCC_STRING::u8string_view& src, std::u32string& dst) { - CONVFN_TYPE1(to_utf32, NS_YYCC_STRING::u8char, char32_t); - } - - std::u32string to_utf32(const NS_YYCC_STRING::u8string_view& src) { - CONVFN_TYPE2(to_utf32, NS_YYCC_STRING::u8char, char32_t); - } - -#pragma endregion - -#pragma region UTF32 -> UTF8 - - ConvResult priv_to_utf8(const std::u32string_view& src) { - NS_YYCC_STRING::u8string dst; + // UTF32 -> UTF8 + ConvResult to_utf8(const std::u32string_view& src) { + std::u8string dst; dst.reserve(src.size() * MULTIPLE_UTF32_TO_UTF8); std::mbstate_t state{}; @@ -346,25 +200,14 @@ namespace yycc::encoding::windows { for (char32_t c : src) { size_t rc = std::c32rtomb(mbout, c, &state); - if (rc != (size_t) -1) dst.append(reinterpret_cast(mbout), rc); - else return ConvError::InvalidUtf32; + if (rc != (size_t) -1) dst.append(reinterpret_cast(mbout), rc); + else return std::unexpected(ConvError::InvalidUtf32); } return dst; } - bool to_utf8(const std::u32string_view& src, NS_YYCC_STRING::u8string& dst) { - CONVFN_TYPE1(to_utf8, char32_t, NS_YYCC_STRING::u8char); - } - - NS_YYCC_STRING::u8string to_utf8(const std::u32string_view& src) { - CONVFN_TYPE2(to_utf8, char32_t, NS_YYCC_STRING::u8char); - } - #pragma endregion -#undef CONVFN_TYPE1 -#undef CONVFN_TYPE2 - } // namespace yycc::encoding::windows #endif diff --git a/src/yycc/encoding/windows.hpp b/src/yycc/encoding/windows.hpp index 4e81d79..762372b 100644 --- a/src/yycc/encoding/windows.hpp +++ b/src/yycc/encoding/windows.hpp @@ -3,18 +3,17 @@ #if defined(YYCC_OS_WINDOWS) -#include "../patch/expected.hpp" -#include "../string.hpp" +#include +#include +#include #include -#define NS_YYCC_STRING ::yycc::string -#define NS_YYCC_PATCH_EXPECTED ::yycc::patch::expected - namespace yycc::encoding::windows { + /// @brief The type of Windows code page. using CodePage = uint32_t; - /// @private + /// @brief The possible error kind occurs in this module. enum class ConvError { TooLargeLength, ///< The length of given string is too large exceeding the maximum capacity of Win32 function. NoDesiredSize, ///< Can not compute the desired size of result string. @@ -25,73 +24,98 @@ namespace yycc::encoding::windows { IncompleteUtf8, ///< Given UTF8 string is incomplete. }; - /// @private + /// @brief The result type in this module. template - using ConvResult = NS_YYCC_PATCH_EXPECTED::Expected; + using ConvResult = std::expected; - // WChar -> Char - ConvResult priv_to_char(const std::wstring_view& src, CodePage code_page); - bool to_char(const std::wstring_view& src, std::string& dst, CodePage code_page); - std::string to_char(const std::wstring_view& src, CodePage code_page); + /** + * @brief WChar -> Char + * @param src + * @param code_page + * @return + */ + ConvResult to_char(const std::wstring_view& src, CodePage code_page); - // Char -> WChar - ConvResult priv_to_wchar(const std::string_view& src, CodePage code_page); - bool to_wchar(const std::string_view& src, std::wstring& dst, CodePage code_page); - std::wstring to_wchar(const std::string_view& src, CodePage code_page); + /** + * @brief Char -> WChar + * @param src + * @param code_page + * @return + */ + ConvResult to_wchar(const std::string_view& src, CodePage code_page); - // Char -> Char - // This is the combination of "WChar -> Char" and "Char -> WChar" - ConvResult priv_to_char(const std::string_view& src, CodePage src_code_page, CodePage dst_code_page); - bool to_char(const std::string_view& src, std::string& dst, CodePage src_code_page, CodePage dst_code_page); - std::string to_char(const std::string_view& src, CodePage src_code_page, CodePage dst_code_page); + /** + * @brief Char -> Char + * @details This is the combination of "WChar -> Char" and "Char -> WChar" + * @param src + * @param src_code_page + * @param dst_code_page + * @return + */ + ConvResult to_char(const std::string_view& src, CodePage src_code_page, CodePage dst_code_page); - // WChar -> UTF8 - // This is the specialization of "WChar -> Char" - ConvResult priv_to_utf8(const std::wstring_view& src); - bool to_utf8(const std::wstring_view& src, NS_YYCC_STRING::u8string& dst); - NS_YYCC_STRING::u8string to_utf8(const std::wstring_view& src); + /** + * @brief WChar -> UTF8 + * @details This is the specialization of "WChar -> Char" + * @param src + * @return + */ + ConvResult to_utf8(const std::wstring_view& src); - // UTF8 -> WChar - // This is the specialization of "Char -> WChar" - ConvResult priv_to_wchar(const NS_YYCC_STRING::u8string_view& src); - bool to_wchar(const NS_YYCC_STRING::u8string_view& src, std::wstring& dst); - std::wstring to_wchar(const NS_YYCC_STRING::u8string_view& src); + /** + * @brief UTF8 -> WChar + * @details This is the specialization of "Char -> WChar" + * @param src + * @return + */ + ConvResult to_wchar(const std::u8string_view& src); - // Char -> UTF8 - // This is the specialization of "Char -> Char" - ConvResult priv_to_utf8(const std::string_view& src, CodePage code_page); - bool to_utf8(const std::string_view& src, NS_YYCC_STRING::u8string& dst, CodePage code_page); - NS_YYCC_STRING::u8string to_utf8(const std::string_view& src, CodePage code_page); + /** + * @brief Char -> UTF8 + * @details This is the specialization of "Char -> Char" + * @param src + * @param code_page + * @return + */ + ConvResult to_utf8(const std::string_view& src, CodePage code_page); - // UTF8 -> Char - // This is the specialization of "Char -> Char" - ConvResult priv_to_char(const NS_YYCC_STRING::u8string_view& src, CodePage code_page); - bool to_char(const NS_YYCC_STRING::u8string_view& src, std::string& dst, CodePage code_page); - std::string to_char(const NS_YYCC_STRING::u8string_view& src, CodePage code_page); + /** + * @brief UTF8 -> Char + * @details This is the specialization of "Char -> Char" + * @param src + * @param code_page + * @return + */ + ConvResult to_char(const std::u8string_view& src, CodePage code_page); - // UTF8 -> UTF16 - ConvResult priv_to_utf16(const NS_YYCC_STRING::u8string_view& src); - bool to_utf16(const NS_YYCC_STRING::u8string_view& src, std::u16string& dst); - std::u16string to_utf16(const NS_YYCC_STRING::u8string_view& src); + /** + * @brief UTF8 -> UTF16 + * @param src + * @return + */ + ConvResult to_utf16(const std::u8string_view& src); - // UTF16 -> UTF8 - ConvResult priv_to_utf8(const std::u16string_view& src); - bool to_utf8(const std::u16string_view& src, NS_YYCC_STRING::u8string& dst); - NS_YYCC_STRING::u8string to_utf8(const std::u16string_view& src); + /** + * @brief UTF16 -> UTF8 + * @param src + * @return + */ + ConvResult to_utf8(const std::u16string_view& src); - // UTF8 -> UTF32 - ConvResult priv_to_utf32(const NS_YYCC_STRING::u8string_view& src); - bool to_utf32(const NS_YYCC_STRING::u8string_view& src, std::u32string& dst); - std::u32string to_utf32(const NS_YYCC_STRING::u8string_view& src); + /** + * @brief UTF8 -> UTF32 + * @param src + * @return + */ + ConvResult to_utf32(const std::u8string_view& src); - // UTF32 -> UTF8 - ConvResult priv_to_utf8(const std::u32string_view& src); - bool to_utf8(const std::u32string_view& src, NS_YYCC_STRING::u8string& dst); - NS_YYCC_STRING::u8string to_utf8(const std::u32string_view& src); + /** + * @brief UTF32 -> UTF8 + * @param src + * @return + */ + ConvResult to_utf8(const std::u32string_view& src); } // namespace yycc::encoding::windows -#undef NS_YYCC_PATCH_EXPECTED -#undef NS_YYCC_STRING - #endif diff --git a/src/yycc/macro/compiler_detector.hpp b/src/yycc/macro/compiler_detector.hpp index afff48f..770d8e2 100644 --- a/src/yycc/macro/compiler_detector.hpp +++ b/src/yycc/macro/compiler_detector.hpp @@ -3,3 +3,28 @@ #if (defined(YYCC_CC_MSVC) + defined(YYCC_CC_GCC) + defined(YYCC_CC_CLANG)) != 1 #error "Current compiler is not supported!" #endif + +namespace yycc::macro::compiler { + + /// @brief The kind of compiler. + enum class CompilerKind { + Msvc, ///< MSVC + Gcc, ///< GCC + Clang, ///< Clang + }; + + /** + * @brief Fetch the compiler type. + * @return The kind of compiler. + */ + inline constexpr CompilerKind get_compiler() { +#if defined(YYCC_CC_MSVC) + return CompilerKind::Msvc; +#elif defined(YYCC_CC_GCC) + return CompilerKind::Gcc; +#else + return CompilerKind::Clang; +#endif + } + +} // namespace yycc::macro::compiler diff --git a/src/yycc/macro/endian_detector.hpp b/src/yycc/macro/endian_detector.hpp index 87efbbf..9c0c775 100644 --- a/src/yycc/macro/endian_detector.hpp +++ b/src/yycc/macro/endian_detector.hpp @@ -5,3 +5,24 @@ #error "Current system endian (byte order) is not supported!" #endif +namespace yycc::macro::endian { + + /// @brief The endian kind of OS. + enum class EndianKind { + Little, ///< Little endian. + Big, ///< Big endian. + }; + + /** + * @brief Fetch the endian of OS. + * @return The endian of OS. + */ + inline constexpr EndianKind get_endian() { +#if defined(YYCC_ENDIAN_LITTLE) + return EndianKind::Little; +#else + return EndianKind::Big; +#endif + } + +} // namespace yycc::macro::endian diff --git a/src/yycc/macro/os_detector.hpp b/src/yycc/macro/os_detector.hpp index 8f58633..98ec1cb 100644 --- a/src/yycc/macro/os_detector.hpp +++ b/src/yycc/macro/os_detector.hpp @@ -4,3 +4,25 @@ #if (defined(YYCC_OS_WINDOWS) + defined(YYCC_OS_LINUX)) != 1 #error "Current operating system is not supported!" #endif + +namespace yycc::macro::os { + + /// @brief The operating system kind. + enum class OsKind { + Windows, ///< Microsoft Windows + Linux, ///< GNU/Linux + }; + + /** + * @brief Fetch the operating system + * @return The kind of operating system. + */ + inline constexpr OsKind get_os() { +#if defined(YYCC_OS_WINDOWS) + return OsKind::Windows; +#else + return OsKind::Linux; +#endif + } + +} // namespace yycc::macro::os diff --git a/src/yycc/prelude/core.hpp b/src/yycc/prelude/core.hpp deleted file mode 100644 index 83ed97c..0000000 --- a/src/yycc/prelude/core.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -// Suppress unsafe warning on Windows -#include "../windows/unsafe_suppressor.hpp" - -// Prelude section -#include "../string.hpp" -namespace yycc::prelude { - -#define NS_YYCC_STRING ::yycc::string - - using u8char = NS_YYCC_STRING::u8char; - using u8string = NS_YYCC_STRING::u8string; - using u8string_view = NS_YYCC_STRING::u8string_view; - -#undef NS_YYCC_STRING - -} // namespace yycc::prelude - -// Expose all members -using namespace yycc::prelude; diff --git a/src/yycc/rust/option.hpp b/src/yycc/rust/option.hpp index 11288f6..f327433 100644 --- a/src/yycc/rust/option.hpp +++ b/src/yycc/rust/option.hpp @@ -1,10 +1,12 @@ #pragma once #include -/// @brief The reproduction of Rust Option type. -/// @details -/// This namespace reproduce Rust Option type, and its members Some and None in C++. -/// However Option is not important than Result, so its implementation is very casual. +/** + * @brief The reproduction of Rust Option type. + * @details + * This namespace reproduce Rust Option type, and its members Some and None in C++. + * However Option is not important than Result, so its implementation is very casual. + */ namespace yycc::rust::option { template diff --git a/src/yycc/rust/panic.cpp b/src/yycc/rust/panic.cpp index 998f2f4..01bb8eb 100644 --- a/src/yycc/rust/panic.cpp +++ b/src/yycc/rust/panic.cpp @@ -1,12 +1,9 @@ #include "panic.hpp" -#include "../macro/feature_probe.hpp" #include #include #include -#if defined(YYCC_CPPFEAT_STACKTRACE) #include -#endif namespace yycc::rust::panic { @@ -24,12 +21,8 @@ namespace yycc::rust::panic { // User custom message dst << "note: " << msg << std::endl; // Stacktrace message if we support it. -#if defined(YYCC_CPPFEAT_STACKTRACE) dst << "stacktrace: " << std::endl; dst << std::stacktrace::current() << std::endl; -#else - dst << "there is no stacktrace because your C++ runtime do not support it." << std::endl; -#endif // // Restore color // dst << RESET; diff --git a/src/yycc/rust/panic.hpp b/src/yycc/rust/panic.hpp index 1d70b28..fcf3a35 100644 --- a/src/yycc/rust/panic.hpp +++ b/src/yycc/rust/panic.hpp @@ -1,10 +1,6 @@ #pragma once -#include "../macro/feature_probe.hpp" #include - -#if defined(YYCC_CPPFEAT_FORMAT) #include -#endif /** * @brief Provides Rust-style panic functionality for immediate program termination on unrecoverable errors. @@ -38,13 +34,7 @@ namespace yycc::rust::panic { * The macro parameters are the message to format and its arguments, following \c std::format syntax. * This macro essentially calls \c std::format internally. */ -#if defined(YYCC_CPPFEAT_FORMAT) -#if defined(YYCC_CPPFEAT_VA_OPT) #define RS_PANICF(msg, ...) RS_PANIC(std::format(msg __VA_OPT__(, ) __VA_ARGS__)) -#else -#define RS_PANICF(msg, ...) RS_PANIC(std::format(msg, ##__VA_ARGS__)) -#endif -#endif /** * @brief Immediately crashes the entire program like Rust's \c panic! macro. diff --git a/src/yycc/prelude/rust.hpp b/src/yycc/rust/prelude.hpp similarity index 78% rename from src/yycc/prelude/rust.hpp rename to src/yycc/rust/prelude.hpp index 8ad4525..af16733 100644 --- a/src/yycc/prelude/rust.hpp +++ b/src/yycc/rust/prelude.hpp @@ -1,16 +1,13 @@ #pragma once -// Include YYCC prelude first -#include "core.hpp" - // Rust prelude section -#include "../rust/primitive.hpp" -#include "../rust/result.hpp" -#include "../rust/option.hpp" -#include "../rust/panic.hpp" +#include "primitive.hpp" +#include "result.hpp" +#include "option.hpp" +#include "panic.hpp" #include -namespace yycc::prelude::rust { +namespace yycc::rust::prelude { // Include primitive types #define NS_RUST_PRIMITIVE ::yycc::rust::primitive @@ -35,7 +32,7 @@ namespace yycc::prelude::rust { #undef NS_RUST_PRIMITIVE // Other types - using String = ::yycc::string::u8string; + using String = std::u8string; template using Vec = std::vector; @@ -49,4 +46,4 @@ namespace yycc::prelude::rust { } // namespace yycc::prelude::rust // Expose all members -using namespace yycc::prelude::rust; +using namespace ::yycc::rust::prelude; diff --git a/src/yycc/primitive.hpp b/src/yycc/rust/primitive.hpp similarity index 94% rename from src/yycc/primitive.hpp rename to src/yycc/rust/primitive.hpp index a4ffa83..72d2d61 100644 --- a/src/yycc/primitive.hpp +++ b/src/yycc/rust/primitive.hpp @@ -3,7 +3,7 @@ #include #include -namespace yycc::primitive { +namespace yycc::rust::primitive { // `bool` is keyword so should not declare it anymore. // `char` is keyword so should not declare it anymore. diff --git a/src/yycc/rust/result.hpp b/src/yycc/rust/result.hpp index be8be32..aab4103 100644 --- a/src/yycc/rust/result.hpp +++ b/src/yycc/rust/result.hpp @@ -1,9 +1,5 @@ #pragma once -#include "../macro/feature_probe.hpp" - -#if defined(YYCC_CPPFEAT_EXPECTED) #include -#endif /** * @brief The reproduction of Rust Option type. @@ -42,8 +38,6 @@ */ namespace yycc::rust::result { -#if defined(YYCC_CPPFEAT_EXPECTED) - /** * @brief Equivalent Rust \c Result in C++ * @tparam T The type of the expected value. @@ -80,6 +74,4 @@ namespace yycc::rust::result { return ResultType(std::unexpect, std::forward(args)...); } -#endif - } // namespace yycc::rust::result diff --git a/src/yycc/string/op.cpp b/src/yycc/string/op.cpp index 2087143..b95c44a 100644 --- a/src/yycc/string/op.cpp +++ b/src/yycc/string/op.cpp @@ -27,7 +27,7 @@ namespace yycc::string::op { // Check expected size. if (count < 0) { // Invalid length returned by vsnprintf. - return std::unexpected(FormatError::NoExpSize); + return std::unexpected(FormatError::NoDesiredSize); } va_end(args1); diff --git a/src/yycc/string/op.hpp b/src/yycc/string/op.hpp index c439ee7..53e37fb 100644 --- a/src/yycc/string/op.hpp +++ b/src/yycc/string/op.hpp @@ -9,8 +9,8 @@ namespace yycc::string::op { enum class FormatError { - NullFormat, ///< Given format string is nullptr. - NoExpSize, ///< Fail to fetch the expected size of result. + NullFormat, ///< Given format string is nullptr. + NoDesiredSize, ///< Fail to fetch the expected size of result. BadWrittenSize, ///< The written size is different with expected size. }; diff --git a/src/yycc/windows/com.cpp b/src/yycc/windows/com.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/src/yycc/windows/com.hpp b/src/yycc/windows/com.hpp deleted file mode 100644 index e69de29..0000000 diff --git a/src/yycc/windows/dialog.cpp b/src/yycc/windows/dialog.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/src/yycc/windows/dialog.hpp b/src/yycc/windows/dialog.hpp deleted file mode 100644 index e69de29..0000000 diff --git a/src/yycc/windows/import_guard_head.hpp b/src/yycc/windows/import_guard_head.hpp index 7ce6f0a..b55a26b 100644 --- a/src/yycc/windows/import_guard_head.hpp +++ b/src/yycc/windows/import_guard_head.hpp @@ -2,18 +2,8 @@ // Because this header is the part of wrapper, not a real header. // #pragma once -#include "../macro/os_detector.hpp" - -#if defined(YYCC_OS_WINDOWS) - -// Define 2 macros to disallow Windows generate MIN and MAX macros -// which cause std::min and std::max can not function as normal. -#if !defined(WIN32_LEAN_AND_MEAN) -#define WIN32_LEAN_AND_MEAN -#endif - -#if !defined(NOMINMAX) -#define NOMINMAX -#endif - -#endif +// YYC MARK: +// Since YYCC 2.0 version, we use CMake to handle Windows shitty macros, +// so we do not need declare WIN32_LEAN_AND_MEAN or NOMINMAX in there. +// But for keep the pair of this guard, we still keep this header file, +// although it do nothing.