#pragma once #include "../macro/os_detector.hpp" #include "../macro/stl_detector.hpp" #include "../macro/class_copy_move.hpp" #include #include #include #include #include // Choose the backend of PyCodec module #if defined(YYCC_FEAT_ICONV) // We try Iconv first in any cases. #include "../encoding/iconv.hpp" #define YYCC_PYCODEC_ICONV_BACKEND #define YYCC_PYCODEC_BACKEND_NS ::yycc::encoding::iconv #elif defined(YYCC_OS_WINDOWS) && defined(YYCC_STL_MSSTL) // If we can not use Iconv, we try to fallback to Windows implementation. #include "../encoding/windows.hpp" #define YYCC_PYCODEC_WIN32_BACKEND #define YYCC_PYCODEC_BACKEND_NS ::yycc::encoding::windows #else // No viable implementation. #error "Can not find viable encoding convertion solution in current environment for PyCodec module." #endif namespace yycc::carton::pycodec { /// @brief The universal name of encoding. using EncodingName = std::u8string_view; /// @brief The alias to error type of backend. using ConvBackendError = YYCC_PYCODEC_BACKEND_NS::ConvError; /// @brief The error occurs in this module self. enum class ConvFrontendError { NoSuchName, ///< Can not find suitable backend token for given encoding name. }; /// @brief The possible error occurs in this module. class ConvError { public: ConvError(const ConvBackendError& err); ConvError(const ConvFrontendError& err); ConvError(ConvBackendError&& err) noexcept; ConvError(ConvFrontendError&& err) noexcept; YYCC_DEFAULT_COPY_MOVE(ConvError) private: std::variant inner; }; /// @brief The result type of this module. template using ConvResult = std::expected; /** * @brief Check whether given name is a valid encoding name in PyCodec. * @param[in] name The name to be checked. * @return True if it is valid, otherwise false. */ bool is_valid_encoding_name(const EncodingName& name); /// @brief Char -> UTF8 class CharToUtf8 { public: CharToUtf8(const EncodingName& name); ~CharToUtf8(); YYCC_DELETE_COPY(CharToUtf8) YYCC_DEFAULT_MOVE(CharToUtf8) public: ConvResult to_utf8(const std::string_view& src); private: #if defined(YYCC_PYCODEC_WIN32_BACKEND) std::optional inner; #else std::optional inner; #endif }; /// @brief UTF8 -> Char class Utf8ToChar { public: Utf8ToChar(const EncodingName& name); ~Utf8ToChar(); YYCC_DELETE_COPY(Utf8ToChar) YYCC_DEFAULT_MOVE(Utf8ToChar) public: ConvResult to_char(const std::u8string_view& src); private: #if defined(YYCC_PYCODEC_WIN32_BACKEND) std::optional inner; #else std::optional inner; #endif }; /// @brief WChar -> UTF8 class WcharToUtf8 { public: WcharToUtf8(); ~WcharToUtf8(); YYCC_DELETE_COPY(WcharToUtf8) YYCC_DEFAULT_MOVE(WcharToUtf8) public: ConvResult to_utf8(const std::wstring_view& src); private: #if defined(YYCC_PYCODEC_ICONV_BACKEND) YYCC_PYCODEC_BACKEND_NS::WcharToUtf8 inner; #endif }; /// @brief UTF8 -> WChar class Utf8ToWchar { public: Utf8ToWchar(); ~Utf8ToWchar(); YYCC_DELETE_COPY(Utf8ToWchar) YYCC_DEFAULT_MOVE(Utf8ToWchar) public: ConvResult to_wchar(const std::u8string_view& src); private: #if defined(YYCC_PYCODEC_ICONV_BACKEND) YYCC_PYCODEC_BACKEND_NS::Utf8ToWchar inner; #endif }; /// @brief UTF8 -> UTF16 class Utf8ToUtf16 { public: Utf8ToUtf16(); ~Utf8ToUtf16(); YYCC_DELETE_COPY(Utf8ToUtf16) YYCC_DEFAULT_MOVE(Utf8ToUtf16) public: ConvResult to_utf16(const std::u8string_view& src); private: #if defined(YYCC_PYCODEC_ICONV_BACKEND) YYCC_PYCODEC_BACKEND_NS::Utf8ToUtf16 inner; #endif }; /// @brief UTF16 -> UTF8 class Utf16ToUtf8 { public: Utf16ToUtf8(); ~Utf16ToUtf8(); YYCC_DELETE_COPY(Utf16ToUtf8) YYCC_DEFAULT_MOVE(Utf16ToUtf8) public: ConvResult to_utf8(const std::u16string_view& src); private: #if defined(YYCC_PYCODEC_ICONV_BACKEND) YYCC_PYCODEC_BACKEND_NS::Utf16ToUtf8 inner; #endif }; /// @brief UTF8 -> UTF32 class Utf8ToUtf32 { public: Utf8ToUtf32(); ~Utf8ToUtf32(); YYCC_DELETE_COPY(Utf8ToUtf32) YYCC_DEFAULT_MOVE(Utf8ToUtf32) public: ConvResult to_utf32(const std::u8string_view& src); private: #if defined(YYCC_PYCODEC_ICONV_BACKEND) YYCC_PYCODEC_BACKEND_NS::Utf8ToUtf32 inner; #endif }; /// @brief UTF32 -> UTF8 class Utf32ToUtf8 { public: Utf32ToUtf8(); ~Utf32ToUtf8(); YYCC_DELETE_COPY(Utf32ToUtf8) YYCC_DEFAULT_MOVE(Utf32ToUtf8) public: ConvResult to_utf8(const std::u32string_view& src); private: #if defined(YYCC_PYCODEC_ICONV_BACKEND) YYCC_PYCODEC_BACKEND_NS::Utf32ToUtf8 inner; #endif }; } // namespace yycc::carton::pycodec