#include "codec.h" #include #include #ifdef _WIN32 #ifndef NOMINMAX #define NOMINMAX #endif #include #endif #ifdef _WIN32 static std::wstring mb_to_wide(UINT code_page, const std::string& s) { if (s.empty()) { return {}; } const DWORD flags = (code_page == CP_UTF8) ? MB_ERR_INVALID_CHARS : 0; const int wide_len = MultiByteToWideChar( code_page, flags, s.data(), static_cast(s.size()), nullptr, 0 ); if (wide_len <= 0) { throw std::runtime_error("MultiByteToWideChar failed"); } std::wstring w(static_cast(wide_len), L'\0'); const int written = MultiByteToWideChar( code_page, flags, s.data(), static_cast(s.size()), w.data(), wide_len ); if (written <= 0) { throw std::runtime_error("MultiByteToWideChar failed"); } return w; } static std::string wide_to_mb(UINT code_page, const std::wstring& w) { if (w.empty()) { return {}; } const int mb_len = WideCharToMultiByte( code_page, 0, w.data(), static_cast(w.size()), nullptr, 0, nullptr, nullptr ); if (mb_len <= 0) { throw std::runtime_error("WideCharToMultiByte failed"); } std::string s(static_cast(mb_len), '\0'); const int written = WideCharToMultiByte( code_page, 0, w.data(), static_cast(w.size()), s.data(), mb_len, nullptr, nullptr ); if (written <= 0) { throw std::runtime_error("WideCharToMultiByte failed"); } return s; } #endif namespace Psc { // 项目内部 UTF-8 -> 平台窄字符串 // Windows: UTF-8 -> UTF-16 -> ACP / 当前系统 ANSI code page // Linux/macOS: UTF-8 原样返回 std::string utf8_2_platform(const std::string& utf8_path) { #ifdef _WIN32 return wide_to_mb(CP_ACP, mb_to_wide(CP_UTF8, utf8_path)); #else return utf8_path; #endif } // 平台窄字符串 -> 项目内部 UTF-8 // Windows: ACP / 当前系统 ANSI code page -> UTF-16 -> UTF-8 // Linux/macOS: UTF-8 原样返回 std::string platform_2_utf8(const std::string& platform_path) { #ifdef _WIN32 return wide_to_mb(CP_UTF8, mb_to_wide(CP_ACP, platform_path)); #else return platform_path; #endif } // 如果外部接口传进来的是 UTF-8 字符串,用这个构造 fs::path std::filesystem::path path_from_utf8(const std::string& utf8_path) { return std::filesystem::path(utf8_2_platform(utf8_path)); } // fs::path -> 项目内部 UTF-8 std::string path_to_utf8(const std::filesystem::path& p) { #ifdef _WIN32 // Windows 下不要通过 p.string() 中转到 ACP,直接 wide -> UTF-8 更稳 return wide_to_mb(CP_UTF8, p.wstring()); #else return p.string(); #endif } }