Init commit
This commit is contained in:
@@ -0,0 +1,296 @@
|
||||
#include "../include/tool.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <vector>
|
||||
#include <random>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#elif defined(__linux__)
|
||||
#include <locale>
|
||||
#include <codecvt>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
std::wstring Z::HResultToWString(HRESULT hr) {
|
||||
LPWSTR buffer = nullptr;
|
||||
|
||||
DWORD flags =
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS;
|
||||
|
||||
DWORD len = FormatMessageW(
|
||||
flags, nullptr, hr,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
reinterpret_cast<LPWSTR>(&buffer), 0, nullptr);
|
||||
|
||||
// 如果是 HRESULT_FROM_WIN32(...) 形式,尝试取低 16 位 Win32 error code
|
||||
if (len == 0 && HRESULT_FACILITY(hr) == FACILITY_WIN32) {
|
||||
len = FormatMessageW(
|
||||
flags,
|
||||
nullptr,
|
||||
HRESULT_CODE(hr),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
reinterpret_cast<LPWSTR>(&buffer),
|
||||
0,
|
||||
nullptr
|
||||
);
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
wchar_t fallback[64];
|
||||
swprintf_s(fallback, L"Unknown HRESULT: 0x%08X", static_cast<unsigned>(hr));
|
||||
return fallback;
|
||||
}
|
||||
|
||||
std::wstring message(buffer, len);
|
||||
LocalFree(buffer);
|
||||
|
||||
return message;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
namespace {
|
||||
std::once_flag initflag{};
|
||||
}
|
||||
|
||||
//region 字符串转换(UTF8 - WSTRING)
|
||||
namespace Z {
|
||||
#ifdef _WIN32
|
||||
std::string wstring_to_u8(const std::wstring &wstr) {
|
||||
if (wstr.empty())return {};
|
||||
int len = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(),
|
||||
static_cast<int>(wstr.size()),
|
||||
nullptr, 0, nullptr, nullptr);
|
||||
if (len <= 0) throw std::runtime_error("Z::wstring_to_u8 compute length error.");
|
||||
|
||||
std::string str(len, '\0');
|
||||
len = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(),
|
||||
static_cast<int>(wstr.size()),
|
||||
str.data(), len, nullptr, nullptr);
|
||||
if (len <= 0)throw std::runtime_error("Z::wstring_to_u8 escape error.");
|
||||
return str;
|
||||
}
|
||||
|
||||
std::wstring u8_to_wstring(const std::string &u8str) {
|
||||
if (u8str.empty())return {};
|
||||
int len = MultiByteToWideChar(CP_UTF8, 0, u8str.c_str(), -1, nullptr, 0);
|
||||
if (len <= 0) throw std::runtime_error("Z::u8_to_wstring compute length error.");
|
||||
|
||||
std::wstring ws(len, L'\0');
|
||||
len = MultiByteToWideChar(CP_UTF8, 0, u8str.c_str(), -1, ws.data(), len);
|
||||
if (len <= 0) throw std::runtime_error("Z::u8_to_wstring escape error.");
|
||||
return ws;
|
||||
}
|
||||
#else
|
||||
std::string wstring_to_u8(const std::wstring &wstr) {
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
|
||||
return conv.to_bytes(wstr);
|
||||
}
|
||||
|
||||
std::wstring u8_to_wstring(const std::string &u8str) {
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
|
||||
return conv.from_bytes(str);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
//region filesystem相关
|
||||
namespace Z {
|
||||
std::filesystem::path get_module_path() {
|
||||
#if defined(_WIN32)
|
||||
#if defined(UNICODE) || defined(_UNICODE)
|
||||
// Windows Unicode / wide char variant
|
||||
std::wstring buffer(MAX_PATH, L'\0');
|
||||
DWORD length = GetModuleFileNameW(
|
||||
nullptr,
|
||||
buffer.data(),
|
||||
static_cast<DWORD>(buffer.size())
|
||||
);
|
||||
if (length == 0) {
|
||||
throw std::runtime_error("GetModuleFileNameW failed");
|
||||
}
|
||||
// 如果路径长度刚好达到 buffer 大小,可能被截断,动态扩容
|
||||
while (length == buffer.size()) {
|
||||
buffer.resize(buffer.size() * 2);
|
||||
length = GetModuleFileNameW(
|
||||
nullptr,
|
||||
buffer.data(),
|
||||
static_cast<DWORD>(buffer.size())
|
||||
);
|
||||
if (length == 0) {
|
||||
throw std::runtime_error("GetModuleFileNameW failed");
|
||||
}
|
||||
}
|
||||
buffer.resize(length);
|
||||
return std::filesystem::path(buffer);
|
||||
|
||||
#else
|
||||
// Windows non-Unicode / narrow char variant
|
||||
std::string buffer(MAX_PATH, '\0');
|
||||
DWORD length = GetModuleFileNameA(
|
||||
nullptr,
|
||||
buffer.data(),
|
||||
static_cast<DWORD>(buffer.size())
|
||||
);
|
||||
if (length == 0) {
|
||||
throw std::runtime_error("GetModuleFileNameA failed");
|
||||
}
|
||||
// 如果路径长度刚好达到 buffer 大小,可能被截断,动态扩容
|
||||
while (length == buffer.size()) {
|
||||
buffer.resize(buffer.size() * 2);
|
||||
length = GetModuleFileNameA(
|
||||
nullptr,
|
||||
buffer.data(),
|
||||
static_cast<DWORD>(buffer.size())
|
||||
);
|
||||
if (length == 0) {
|
||||
throw std::runtime_error("GetModuleFileNameA failed");
|
||||
}
|
||||
}
|
||||
|
||||
buffer.resize(length);
|
||||
return std::filesystem::path(buffer);
|
||||
|
||||
#endif
|
||||
#elif defined(__linux__)
|
||||
// Linux / GCC variant
|
||||
std::vector<char> buffer(PATH_MAX);
|
||||
while (true) {
|
||||
ssize_t length = readlink(
|
||||
"/proc/self/exe",
|
||||
buffer.data(),
|
||||
buffer.size()
|
||||
);
|
||||
if (length == -1) {
|
||||
throw std::runtime_error("readlink /proc/self/exe failed");
|
||||
}
|
||||
// readlink 不会自动追加 '\0'
|
||||
if (static_cast<size_t>(length) < buffer.size()) {
|
||||
return std::filesystem::path(
|
||||
std::string(buffer.data(), static_cast<size_t>(length))
|
||||
);
|
||||
}
|
||||
|
||||
// 缓冲区不够,扩容重试
|
||||
buffer.resize(buffer.size() * 2);
|
||||
}
|
||||
|
||||
#else
|
||||
#error "get_module_path is not implemented for this platform"
|
||||
#endif
|
||||
}
|
||||
|
||||
std::filesystem::path get_module_dir() {
|
||||
return get_module_path().parent_path();
|
||||
}
|
||||
}
|
||||
|
||||
//region 其他
|
||||
namespace Z {
|
||||
void print_obj_memory(const void *obj, size_t len) {
|
||||
auto bytes = static_cast<const unsigned char *>(obj);
|
||||
int l = static_cast<int>(len);
|
||||
int w = 1;
|
||||
while ((l /= 10) > 0) {
|
||||
w++;
|
||||
}
|
||||
for (size_t i = 0; i < len; i += 8) {
|
||||
for (size_t j = 0; j < 8; ++j) {
|
||||
auto sum = i + j;
|
||||
if (sum == len) break;
|
||||
std::cout << '[' << std::setfill('0') << std::setw(w) << sum << ']'
|
||||
<< std::setw(3) << static_cast<int>(bytes[sum]) << ' ';
|
||||
}
|
||||
std::cout << '\n';
|
||||
}
|
||||
std::cout << std::flush;
|
||||
}
|
||||
|
||||
bool Random::bInitialized = false;
|
||||
void *Random::m_gen = nullptr;
|
||||
uint32_t Random::m_seed = 0;
|
||||
int Random::Get(int min, int max) {
|
||||
InitOnce();
|
||||
std::uniform_int_distribution dist(min, max);
|
||||
return dist(*static_cast<std::mt19937 *>(m_gen));
|
||||
}
|
||||
float Random::Get(float min, float max) {
|
||||
InitOnce();
|
||||
std::uniform_real_distribution dist(min, max);
|
||||
return dist(*static_cast<std::mt19937 *>(m_gen));
|
||||
}
|
||||
double Random::Get(double min, double max) {
|
||||
InitOnce();
|
||||
std::uniform_real_distribution dist(min, max);
|
||||
return dist(*static_cast<std::mt19937 *>(m_gen));
|
||||
}
|
||||
void Random::GenerateSequence() {
|
||||
if (!bInitialized) {
|
||||
InitOnce();
|
||||
} else {
|
||||
GenSequence();
|
||||
}
|
||||
}
|
||||
void Random::GenerateSequence(uint32_t seed) {
|
||||
if (!bInitialized) {
|
||||
InitOnce();
|
||||
}
|
||||
GenSequence(seed);
|
||||
}
|
||||
void Random::InitOnce() {
|
||||
std::call_once(initflag, []() {
|
||||
GenSequence();
|
||||
std::atexit(CleanUp);
|
||||
bInitialized = true;
|
||||
});
|
||||
}
|
||||
void Random::GenSequence() {
|
||||
if (m_gen) {
|
||||
auto *_gen = static_cast<std::mt19937 *>(m_gen);
|
||||
delete _gen;
|
||||
}
|
||||
std::random_device rd{};
|
||||
m_seed = rd();
|
||||
m_gen = new std::mt19937(m_seed);
|
||||
}
|
||||
void Random::GenSequence(uint32_t seed) {
|
||||
m_seed = seed;
|
||||
if (m_gen) {
|
||||
auto *_gen = static_cast<std::mt19937 *>(m_gen);
|
||||
delete _gen;
|
||||
}
|
||||
m_gen = new std::mt19937(seed);
|
||||
}
|
||||
void Random::CleanUp() {
|
||||
if (m_gen) {
|
||||
auto *_gen = static_cast<std::mt19937 *>(m_gen);
|
||||
delete _gen;
|
||||
m_gen = nullptr;
|
||||
bInitialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user