2025-07-23 16:05:53 +08:00
|
|
|
#pragma once
|
|
|
|
|
#include "../macro/os_detector.hpp"
|
2025-07-31 22:25:14 +08:00
|
|
|
#include "../macro/stl_detector.hpp"
|
2025-07-23 16:05:53 +08:00
|
|
|
#include "../macro/class_copy_move.hpp"
|
2025-07-31 22:25:14 +08:00
|
|
|
#include <string>
|
|
|
|
|
#include <string_view>
|
2025-08-12 17:34:03 +08:00
|
|
|
#include <variant>
|
|
|
|
|
#include <optional>
|
2025-07-31 22:25:14 +08:00
|
|
|
#include <expected>
|
2025-07-23 16:05:53 +08:00
|
|
|
|
|
|
|
|
// Choose the backend of PyCodec module
|
2025-08-05 14:04:20 +08:00
|
|
|
#if defined(YYCC_FEAT_ICONV)
|
|
|
|
|
// We try Iconv first in any cases.
|
2025-08-12 16:32:59 +08:00
|
|
|
#include "../encoding/iconv.hpp"
|
2025-07-23 16:05:53 +08:00
|
|
|
#define YYCC_PYCODEC_ICONV_BACKEND
|
2025-07-31 22:25:14 +08:00
|
|
|
#define YYCC_PYCODEC_BACKEND_NS ::yycc::encoding::iconv
|
2025-08-05 14:04:20 +08:00
|
|
|
#elif defined(YYCC_OS_WINDOWS) && defined(YYCC_STL_MSSTL)
|
|
|
|
|
// If we can not use Iconv, we try to fallback to Windows implementation.
|
2025-08-12 16:32:59 +08:00
|
|
|
#include "../encoding/windows.hpp"
|
2025-08-05 14:04:20 +08:00
|
|
|
#define YYCC_PYCODEC_WIN32_BACKEND
|
|
|
|
|
#define YYCC_PYCODEC_BACKEND_NS ::yycc::encoding::windows
|
2025-07-31 22:25:14 +08:00
|
|
|
#else
|
2025-08-05 14:04:20 +08:00
|
|
|
// No viable implementation.
|
2025-07-31 22:25:14 +08:00
|
|
|
#error "Can not find viable encoding convertion solution in current environment for PyCodec module."
|
2025-07-23 16:05:53 +08:00
|
|
|
#endif
|
|
|
|
|
|
2025-08-12 16:32:59 +08:00
|
|
|
namespace yycc::carton::pycodec {
|
2025-07-23 16:05:53 +08:00
|
|
|
|
2025-07-31 22:25:14 +08:00
|
|
|
/// @brief The universal name of encoding.
|
|
|
|
|
using EncodingName = std::u8string_view;
|
2025-07-23 16:05:53 +08:00
|
|
|
|
2025-08-12 17:34:03 +08:00
|
|
|
/// @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.
|
|
|
|
|
};
|
|
|
|
|
|
2025-07-31 22:25:14 +08:00
|
|
|
/// @brief The possible error occurs in this module.
|
|
|
|
|
class ConvError {
|
|
|
|
|
public:
|
2025-08-12 17:34:03 +08:00
|
|
|
ConvError(const ConvBackendError& err);
|
|
|
|
|
ConvError(const ConvFrontendError& err);
|
|
|
|
|
ConvError(ConvBackendError&& err) noexcept;
|
|
|
|
|
ConvError(ConvFrontendError&& err) noexcept;
|
2025-07-31 22:25:14 +08:00
|
|
|
YYCC_DEFAULT_COPY_MOVE(ConvError)
|
|
|
|
|
|
|
|
|
|
private:
|
2025-08-12 17:34:03 +08:00
|
|
|
std::variant<ConvBackendError, ConvFrontendError> inner;
|
2025-07-23 16:05:53 +08:00
|
|
|
};
|
|
|
|
|
|
2025-07-31 22:25:14 +08:00
|
|
|
/// @brief The result type of this module.
|
2025-07-23 16:05:53 +08:00
|
|
|
template<typename T>
|
2025-07-31 22:25:14 +08:00
|
|
|
using ConvResult = std::expected<T, ConvError>;
|
2025-07-23 16:05:53 +08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @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);
|
|
|
|
|
|
2025-07-31 22:25:14 +08:00
|
|
|
/// @brief Char -> UTF8
|
2025-07-23 16:05:53 +08:00
|
|
|
class CharToUtf8 {
|
|
|
|
|
public:
|
|
|
|
|
CharToUtf8(const EncodingName& name);
|
|
|
|
|
~CharToUtf8();
|
|
|
|
|
YYCC_DELETE_COPY(CharToUtf8)
|
|
|
|
|
YYCC_DEFAULT_MOVE(CharToUtf8)
|
|
|
|
|
|
|
|
|
|
public:
|
2025-07-31 22:25:14 +08:00
|
|
|
ConvResult<std::u8string> to_utf8(const std::string_view& src);
|
2025-07-23 16:05:53 +08:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
#if defined(YYCC_PYCODEC_WIN32_BACKEND)
|
2025-08-12 17:34:03 +08:00
|
|
|
std::optional<YYCC_PYCODEC_BACKEND_NS::CodePage> inner;
|
2025-07-23 16:05:53 +08:00
|
|
|
#else
|
2025-08-12 17:34:03 +08:00
|
|
|
std::optional<YYCC_PYCODEC_BACKEND_NS::CharToUtf8> inner;
|
2025-07-23 16:05:53 +08:00
|
|
|
#endif
|
|
|
|
|
};
|
|
|
|
|
|
2025-07-31 22:25:14 +08:00
|
|
|
/// @brief UTF8 -> Char
|
2025-07-23 16:05:53 +08:00
|
|
|
class Utf8ToChar {
|
|
|
|
|
public:
|
|
|
|
|
Utf8ToChar(const EncodingName& name);
|
|
|
|
|
~Utf8ToChar();
|
|
|
|
|
YYCC_DELETE_COPY(Utf8ToChar)
|
|
|
|
|
YYCC_DEFAULT_MOVE(Utf8ToChar)
|
|
|
|
|
|
|
|
|
|
public:
|
2025-07-31 22:25:14 +08:00
|
|
|
ConvResult<std::string> to_char(const std::u8string_view& src);
|
2025-07-23 16:05:53 +08:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
#if defined(YYCC_PYCODEC_WIN32_BACKEND)
|
2025-08-12 17:34:03 +08:00
|
|
|
std::optional<YYCC_PYCODEC_BACKEND_NS::CodePage> inner;
|
2025-07-23 16:05:53 +08:00
|
|
|
#else
|
2025-08-12 17:34:03 +08:00
|
|
|
std::optional<YYCC_PYCODEC_BACKEND_NS::Utf8ToChar> inner;
|
2025-07-23 16:05:53 +08:00
|
|
|
#endif
|
|
|
|
|
};
|
|
|
|
|
|
2025-07-31 22:25:14 +08:00
|
|
|
/// @brief WChar -> UTF8
|
2025-07-23 16:05:53 +08:00
|
|
|
class WcharToUtf8 {
|
|
|
|
|
public:
|
|
|
|
|
WcharToUtf8();
|
|
|
|
|
~WcharToUtf8();
|
|
|
|
|
YYCC_DELETE_COPY(WcharToUtf8)
|
|
|
|
|
YYCC_DEFAULT_MOVE(WcharToUtf8)
|
|
|
|
|
|
|
|
|
|
public:
|
2025-07-31 22:25:14 +08:00
|
|
|
ConvResult<std::u8string> to_utf8(const std::wstring_view& src);
|
2025-07-23 16:05:53 +08:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
#if defined(YYCC_PYCODEC_ICONV_BACKEND)
|
2025-07-31 22:25:14 +08:00
|
|
|
YYCC_PYCODEC_BACKEND_NS::WcharToUtf8 inner;
|
2025-07-23 16:05:53 +08:00
|
|
|
#endif
|
|
|
|
|
};
|
|
|
|
|
|
2025-07-31 22:25:14 +08:00
|
|
|
/// @brief UTF8 -> WChar
|
2025-07-23 16:05:53 +08:00
|
|
|
class Utf8ToWchar {
|
|
|
|
|
public:
|
|
|
|
|
Utf8ToWchar();
|
|
|
|
|
~Utf8ToWchar();
|
|
|
|
|
YYCC_DELETE_COPY(Utf8ToWchar)
|
|
|
|
|
YYCC_DEFAULT_MOVE(Utf8ToWchar)
|
|
|
|
|
|
|
|
|
|
public:
|
2025-07-31 22:25:14 +08:00
|
|
|
ConvResult<std::wstring> to_wchar(const std::u8string_view& src);
|
2025-07-23 16:05:53 +08:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
#if defined(YYCC_PYCODEC_ICONV_BACKEND)
|
2025-07-31 22:25:14 +08:00
|
|
|
YYCC_PYCODEC_BACKEND_NS::Utf8ToWchar inner;
|
2025-07-23 16:05:53 +08:00
|
|
|
#endif
|
|
|
|
|
};
|
|
|
|
|
|
2025-07-31 22:25:14 +08:00
|
|
|
/// @brief UTF8 -> UTF16
|
2025-07-23 16:05:53 +08:00
|
|
|
class Utf8ToUtf16 {
|
|
|
|
|
public:
|
|
|
|
|
Utf8ToUtf16();
|
|
|
|
|
~Utf8ToUtf16();
|
|
|
|
|
YYCC_DELETE_COPY(Utf8ToUtf16)
|
|
|
|
|
YYCC_DEFAULT_MOVE(Utf8ToUtf16)
|
|
|
|
|
|
|
|
|
|
public:
|
2025-07-31 22:25:14 +08:00
|
|
|
ConvResult<std::u16string> to_utf16(const std::u8string_view& src);
|
2025-07-23 16:05:53 +08:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
#if defined(YYCC_PYCODEC_ICONV_BACKEND)
|
2025-07-31 22:25:14 +08:00
|
|
|
YYCC_PYCODEC_BACKEND_NS::Utf8ToUtf16 inner;
|
2025-07-23 16:05:53 +08:00
|
|
|
#endif
|
|
|
|
|
};
|
|
|
|
|
|
2025-07-31 22:25:14 +08:00
|
|
|
/// @brief UTF16 -> UTF8
|
2025-07-23 16:05:53 +08:00
|
|
|
class Utf16ToUtf8 {
|
|
|
|
|
public:
|
|
|
|
|
Utf16ToUtf8();
|
|
|
|
|
~Utf16ToUtf8();
|
|
|
|
|
YYCC_DELETE_COPY(Utf16ToUtf8)
|
|
|
|
|
YYCC_DEFAULT_MOVE(Utf16ToUtf8)
|
|
|
|
|
|
|
|
|
|
public:
|
2025-07-31 22:25:14 +08:00
|
|
|
ConvResult<std::u8string> to_utf8(const std::u16string_view& src);
|
2025-07-23 16:05:53 +08:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
#if defined(YYCC_PYCODEC_ICONV_BACKEND)
|
2025-07-31 22:25:14 +08:00
|
|
|
YYCC_PYCODEC_BACKEND_NS::Utf16ToUtf8 inner;
|
2025-07-23 16:05:53 +08:00
|
|
|
#endif
|
|
|
|
|
};
|
|
|
|
|
|
2025-07-31 22:25:14 +08:00
|
|
|
/// @brief UTF8 -> UTF32
|
2025-07-23 16:05:53 +08:00
|
|
|
class Utf8ToUtf32 {
|
|
|
|
|
public:
|
|
|
|
|
Utf8ToUtf32();
|
|
|
|
|
~Utf8ToUtf32();
|
|
|
|
|
YYCC_DELETE_COPY(Utf8ToUtf32)
|
|
|
|
|
YYCC_DEFAULT_MOVE(Utf8ToUtf32)
|
|
|
|
|
|
|
|
|
|
public:
|
2025-07-31 22:25:14 +08:00
|
|
|
ConvResult<std::u32string> to_utf32(const std::u8string_view& src);
|
2025-07-23 16:05:53 +08:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
#if defined(YYCC_PYCODEC_ICONV_BACKEND)
|
2025-07-31 22:25:14 +08:00
|
|
|
YYCC_PYCODEC_BACKEND_NS::Utf8ToUtf32 inner;
|
2025-07-23 16:05:53 +08:00
|
|
|
#endif
|
|
|
|
|
};
|
|
|
|
|
|
2025-07-31 22:25:14 +08:00
|
|
|
/// @brief UTF32 -> UTF8
|
2025-07-23 16:05:53 +08:00
|
|
|
class Utf32ToUtf8 {
|
|
|
|
|
public:
|
|
|
|
|
Utf32ToUtf8();
|
|
|
|
|
~Utf32ToUtf8();
|
|
|
|
|
YYCC_DELETE_COPY(Utf32ToUtf8)
|
|
|
|
|
YYCC_DEFAULT_MOVE(Utf32ToUtf8)
|
|
|
|
|
|
|
|
|
|
public:
|
2025-07-31 22:25:14 +08:00
|
|
|
ConvResult<std::u8string> to_utf8(const std::u32string_view& src);
|
2025-07-23 16:05:53 +08:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
#if defined(YYCC_PYCODEC_ICONV_BACKEND)
|
2025-07-31 22:25:14 +08:00
|
|
|
YYCC_PYCODEC_BACKEND_NS::Utf32ToUtf8 inner;
|
2025-07-23 16:05:53 +08:00
|
|
|
#endif
|
|
|
|
|
};
|
|
|
|
|
|
2025-08-12 17:34:03 +08:00
|
|
|
} // namespace yycc::carton::pycodec
|