mirror of
https://github.com/MaaAssistantArknights/MaaAssistantArknights.git
synced 2026-07-17 18:01:26 +08:00
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
181 lines
4.9 KiB
C++
181 lines
4.9 KiB
C++
#pragma once
|
|
|
|
#include <filesystem>
|
|
#include <fstream>
|
|
#include <iostream>
|
|
#include <optional>
|
|
#include <sstream>
|
|
#include <string>
|
|
#include <string_view>
|
|
|
|
#include "Meta.hpp"
|
|
|
|
#ifdef _WIN32
|
|
#include "MaaUtils/SafeWindows.hpp"
|
|
#include <io.h>
|
|
#include <locale.h>
|
|
|
|
namespace asst::utils
|
|
{
|
|
template <typename _ = void>
|
|
inline std::string ansi_to_utf8(std::string_view ansi_str)
|
|
{
|
|
const char* src_str = ansi_str.data();
|
|
const int byte_len = static_cast<int>(ansi_str.length() * sizeof(char));
|
|
int len = MultiByteToWideChar(CP_ACP, 0, src_str, byte_len, nullptr, 0);
|
|
const std::size_t wstr_length = static_cast<std::size_t>(len) + 1U;
|
|
auto wstr = new wchar_t[wstr_length];
|
|
memset(wstr, 0, sizeof(wstr[0]) * wstr_length);
|
|
MultiByteToWideChar(CP_ACP, 0, src_str, byte_len, wstr, len);
|
|
|
|
len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, nullptr, 0, nullptr, nullptr);
|
|
const std::size_t str_length = static_cast<std::size_t>(len) + 1;
|
|
auto str = new char[str_length];
|
|
memset(str, 0, sizeof(str[0]) * str_length);
|
|
WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, len, nullptr, nullptr);
|
|
std::string strTemp = str;
|
|
|
|
delete[] wstr;
|
|
wstr = nullptr;
|
|
delete[] str;
|
|
str = nullptr;
|
|
|
|
return strTemp;
|
|
}
|
|
|
|
template <typename _ = void>
|
|
inline std::string utf8_to_ansi(std::string_view utf8_str)
|
|
{
|
|
const char* src_str = utf8_str.data();
|
|
const int byte_len = static_cast<int>(utf8_str.length() * sizeof(char));
|
|
int len = MultiByteToWideChar(CP_UTF8, 0, src_str, byte_len, nullptr, 0);
|
|
const std::size_t wsz_ansi_length = static_cast<std::size_t>(len) + 1U;
|
|
auto wsz_ansi = new wchar_t[wsz_ansi_length];
|
|
memset(wsz_ansi, 0, sizeof(wsz_ansi[0]) * wsz_ansi_length);
|
|
MultiByteToWideChar(CP_UTF8, 0, src_str, byte_len, wsz_ansi, len);
|
|
|
|
len = WideCharToMultiByte(CP_ACP, 0, wsz_ansi, -1, nullptr, 0, nullptr, nullptr);
|
|
const std::size_t sz_ansi_length = static_cast<std::size_t>(len) + 1;
|
|
auto sz_ansi = new char[sz_ansi_length];
|
|
memset(sz_ansi, 0, sizeof(sz_ansi[0]) * sz_ansi_length);
|
|
WideCharToMultiByte(CP_ACP, 0, wsz_ansi, -1, sz_ansi, len, nullptr, nullptr);
|
|
std::string strTemp(sz_ansi);
|
|
|
|
delete[] wsz_ansi;
|
|
wsz_ansi = nullptr;
|
|
delete[] sz_ansi;
|
|
sz_ansi = nullptr;
|
|
|
|
return strTemp;
|
|
}
|
|
|
|
template <typename _ = void>
|
|
inline std::string utf8_to_unicode_escape(std::string_view utf8_str)
|
|
{
|
|
const char* src_str = utf8_str.data();
|
|
int len = MultiByteToWideChar(CP_UTF8, 0, src_str, -1, nullptr, 0);
|
|
const std::size_t wstr_length = static_cast<std::size_t>(len) + 1U;
|
|
auto wstr = new wchar_t[wstr_length];
|
|
memset(wstr, 0, sizeof(wstr[0]) * wstr_length);
|
|
MultiByteToWideChar(CP_UTF8, 0, src_str, -1, wstr, len);
|
|
|
|
std::string unicode_escape_str = {};
|
|
constinit static char hexcode[] = "0123456789abcdef";
|
|
for (const wchar_t* pchr = wstr; *pchr; ++pchr) {
|
|
const wchar_t& chr = *pchr;
|
|
if (chr > 255) {
|
|
unicode_escape_str += "\\u";
|
|
unicode_escape_str.push_back(hexcode[chr >> 12]);
|
|
unicode_escape_str.push_back(hexcode[(chr >> 8) & 15]);
|
|
unicode_escape_str.push_back(hexcode[(chr >> 4) & 15]);
|
|
unicode_escape_str.push_back(hexcode[chr & 15]);
|
|
}
|
|
else {
|
|
unicode_escape_str.push_back(chr & 255);
|
|
}
|
|
}
|
|
|
|
delete[] wstr;
|
|
wstr = nullptr;
|
|
|
|
return unicode_escape_str;
|
|
}
|
|
|
|
inline std::string load_file_without_bom(const std::filesystem::path& path)
|
|
{
|
|
std::ifstream ifs(path, std::ios::in);
|
|
if (!ifs.is_open()) {
|
|
return {};
|
|
}
|
|
std::stringstream iss;
|
|
iss << ifs.rdbuf();
|
|
ifs.close();
|
|
std::string str = iss.str();
|
|
|
|
if (str.starts_with("\xEF\xBB\xBF")) {
|
|
str.assign(str.begin() + 3, str.end());
|
|
}
|
|
|
|
return str;
|
|
}
|
|
|
|
class utf8_scope
|
|
{
|
|
#ifdef _WIN32
|
|
bool active;
|
|
int thread_mode;
|
|
std::string old_locale;
|
|
|
|
static bool is_console_ostream(std::ostream& ofs)
|
|
{
|
|
if (&ofs == &std::cout) {
|
|
return _isatty(_fileno(stdout));
|
|
}
|
|
if (&ofs == &std::cerr) {
|
|
return _isatty(_fileno(stderr));
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public:
|
|
utf8_scope(std::nullptr_t)
|
|
{
|
|
active = false;
|
|
thread_mode = 0;
|
|
}
|
|
|
|
~utf8_scope()
|
|
{
|
|
if (!active) {
|
|
return;
|
|
}
|
|
if (!old_locale.empty()) {
|
|
setlocale(LC_ALL, old_locale.c_str());
|
|
}
|
|
_configthreadlocale(_DISABLE_PER_THREAD_LOCALE);
|
|
}
|
|
|
|
utf8_scope(std::ostream& ofs)
|
|
{
|
|
if (is_console_ostream(ofs)) {
|
|
active = true;
|
|
thread_mode = _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
|
|
auto old_locale_ptr = setlocale(LC_ALL, ".UTF-8");
|
|
if (old_locale_ptr) {
|
|
old_locale = old_locale_ptr;
|
|
}
|
|
}
|
|
else {
|
|
active = false;
|
|
}
|
|
}
|
|
#else
|
|
public:
|
|
utf8_scope(std::ostream&) {}
|
|
#endif
|
|
};
|
|
|
|
} // namespace asst::utils
|
|
|
|
#endif
|