Files
CPP_Core/psc_global_include/codec.cpp
T
2026-06-16 10:56:40 +08:00

143 lines
2.9 KiB
C++

#include "codec.h"
#include <fstream>
#include <stdexcept>
#ifdef _WIN32
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
#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<int>(s.size()),
nullptr,
0
);
if (wide_len <= 0) {
throw std::runtime_error("MultiByteToWideChar failed");
}
std::wstring w(static_cast<size_t>(wide_len), L'\0');
const int written = MultiByteToWideChar(
code_page,
flags,
s.data(),
static_cast<int>(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<int>(w.size()),
nullptr,
0,
nullptr,
nullptr
);
if (mb_len <= 0) {
throw std::runtime_error("WideCharToMultiByte failed");
}
std::string s(static_cast<size_t>(mb_len), '\0');
const int written = WideCharToMultiByte(
code_page,
0,
w.data(),
static_cast<int>(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
}
}