// UUTextCodec.cpp : 定义静态库的函数。 // #include "UTextCodec.h" #include #include #include #include #include #include #include namespace uns { // ICU中转封装 static icu_74::UnicodeString fromWString(const std::wstring& wstr) { #if WCHAR_MAX == 0xFFFF return icu_74::UnicodeString(reinterpret_cast(wstr.c_str()), (int32_t)wstr.length()); #else std::u16string u16; for (wchar_t wc : wstr) { if (wc <= 0xFFFF) u16.push_back(static_cast(wc)); else { wc -= 0x10000; u16.push_back((wc >> 10) + 0xD800); u16.push_back((wc & 0x3FF) + 0xDC00); } } return icu_74::UnicodeString(reinterpret_cast(u16.c_str()), u16.length()); #endif } static std::wstring toWString(const icu_74::UnicodeString& ustr) { std::wstring wstr; int32_t i = 0; while (i < ustr.length()) { UChar32 c; U16_NEXT(ustr.getBuffer(), i, ustr.length(), c); #if WCHAR_MAX == 0xFFFF if (c <= 0xFFFF) wstr.push_back(static_cast(c)); else { c -= 0x10000; wstr.push_back((c >> 10) + 0xD800); wstr.push_back((c & 0x3FF) + 0xDC00); } #else wstr.push_back(static_cast(c)); #endif } return wstr; } static icu_74::UnicodeString fromU32String(const std::u32string& str) { std::u16string u16; for (char32_t c : str) { if (c <= 0xFFFF) u16.push_back(static_cast(c)); else { c -= 0x10000; u16.push_back((c >> 10) + 0xD800); u16.push_back((c & 0x3FF) + 0xDC00); } } return icu_74::UnicodeString(reinterpret_cast(u16.c_str()), (int32_t)u16.length()); } static std::u32string toU32String(const icu_74::UnicodeString& ustr) { std::u32string result; int32_t i = 0; while (i < ustr.length()) { UChar32 c; U16_NEXT(ustr.getBuffer(), i, ustr.length(), c); result.push_back(c); } return result; } } std::wstring UTextCodec::UTF8to16(const std::string& utf8) { icu_74::UnicodeString ustr = icu_74::UnicodeString::fromUTF8(utf8); return uns::toWString(ustr); } std::string UTextCodec::UTF16to8(const std::wstring& wstr) { icu_74::UnicodeString ustr = uns::fromWString(wstr); std::string result; ustr.toUTF8String(result); return result; } std::u32string UTextCodec::UTF8to32(const std::string& utf8) { icu_74::UnicodeString ustr = icu_74::UnicodeString::fromUTF8(utf8); return uns::toU32String(ustr); } std::string UTextCodec::UTF32to8(const std::u32string& u32str) { icu_74::UnicodeString ustr = uns::fromU32String(u32str); std::string result; ustr.toUTF8String(result); return result; } std::u32string UTextCodec::WtoUTF32(const std::wstring& wstr) { return uns::toU32String(uns::fromWString(wstr)); } std::wstring UTextCodec::UTF32toW(const std::u32string& u32str) { return uns::toWString(uns::fromU32String(u32str)); } std::wstring UTextCodec::StoW(const std::string& str) { #ifdef _WIN32 return AtoW(str); #else // 默认按 UTF-8 解码 icu_74::UnicodeString ustr = icu_74::UnicodeString::fromUTF8(str); return uns::toWString(ustr); #endif } std::string UTextCodec::WtoS(const std::wstring& wstr) { #ifdef _WIN32 return WtoA(wstr); #else // 默认按 UTF-8 编码 icu_74::UnicodeString ustr = uns::fromWString(wstr); std::string result; ustr.toUTF8String(result); return result; #endif } #ifdef _WIN32 std::wstring UTextCodec::AtoW(const std::string& ansi, UINT codePage) { // 空指针 if (ansi.empty()) return L""; // 计算长度 int nNeedSize = MultiByteToWideChar(codePage, 0, ansi.c_str(), -1, NULL, 0); if (0 == nNeedSize) return L""; // 分配空间,转换 std::wstring strRet(L""); wchar_t* pRet = new wchar_t[nNeedSize + 1]; memset(pRet, 0, (nNeedSize + 1) * sizeof(wchar_t)); if (0 == MultiByteToWideChar(codePage, 0, ansi.c_str(), -1, pRet, nNeedSize)) { } else strRet = pRet; delete[]pRet; return strRet; } std::string UTextCodec::WtoA(const std::wstring& wstr, UINT codePage) { // 空指针输入 if (wstr.empty()) return ""; // 无法计算需要的长度. int nNeedSize = WideCharToMultiByte(codePage, 0, wstr.c_str(), -1, NULL, 0, NULL, NULL); if (0 == nNeedSize) return ""; // 分配空间,转换. char* pRet = new char[nNeedSize + 1]; // 虽然返回WideCharToMultiByte的长度是包含 null 字符的长度, 还是多+一个字符. memset(pRet, 0, nNeedSize + 1); std::string strRet(""); if (0 == WideCharToMultiByte(codePage, 0, wstr.c_str(), -1, pRet, nNeedSize, NULL, NULL)) { } else strRet = pRet; delete[] pRet; return strRet; } #endif std::string UTextCodec::DetectEncoding() { #ifdef _WIN32 UINT cp = GetACP(); return "CP" + std::to_string(cp); #else const char* locale = std::getenv("LC_CTYPE"); if (!locale || std::string(locale).empty()) locale = std::getenv("LANG"); if (!locale || std::string(locale).empty()) return "unknown"; std::string loc(locale); // locale 典型格式如 en_US.UTF-8,截取点号后面的编码 auto pos = loc.find('.'); if (pos != std::string::npos) { std::string encoding = loc.substr(pos + 1); // 有些编码后面有 @variant,比如 UTF-8@xxx,去掉后面部分 auto atPos = encoding.find('@'); if (atPos != std::string::npos) encoding = encoding.substr(0, atPos); return encoding; } return "unknown"; #endif }