refactor: update all modules for UTF8 string. waiting for debugging

This commit is contained in:
yyc12345 2024-06-28 15:46:58 +08:00
parent 44dbbb1c99
commit ccb729c718
15 changed files with 170 additions and 155 deletions

View File

@ -54,7 +54,7 @@ namespace YYCC::ConsoleHelper {
*/ */
template<bool _bIsConsole> template<bool _bIsConsole>
static std::string WinConsoleRead(HANDLE hStdIn) { static yycc_u8string WinConsoleRead(HANDLE hStdIn) {
using _TChar = std::conditional_t<_bIsConsole, wchar_t, char>; using _TChar = std::conditional_t<_bIsConsole, wchar_t, char>;
// Prepare an internal buffer because the read data may not be fully used. // Prepare an internal buffer because the read data may not be fully used.
@ -113,21 +113,21 @@ namespace YYCC::ConsoleHelper {
} }
// post-process for return value // post-process for return value
std::string real_return_buffer; yycc_u8string real_return_buffer;
if constexpr (_bIsConsole) { if constexpr (_bIsConsole) {
// console mode need convert wchar to utf8 // console mode need convert wchar to utf8
YYCC::EncodingHelper::WcharToUTF8(return_buffer.c_str(), real_return_buffer); YYCC::EncodingHelper::WcharToUTF8(return_buffer, real_return_buffer);
} else { } else {
// non-console just copt the result // non-console just copt the result
real_return_buffer = return_buffer; real_return_buffer = EncodingHelper::ToUTF8(return_buffer);
} }
// every mode need delete \r words // every mode need delete \r words
YYCC::StringHelper::Replace(real_return_buffer, "\r", ""); YYCC::StringHelper::Replace(real_return_buffer, YYCC_U8("\r"), YYCC_U8(""));
// return value // return value
return real_return_buffer; return real_return_buffer;
} }
static void WinConsoleWrite(const std::string& strl, bool to_stderr) { static void WinConsoleWrite(const yycc_u8string& strl, bool to_stderr) {
// Prepare some Win32 variables // Prepare some Win32 variables
// fetch stdout handle first // fetch stdout handle first
HANDLE hStdOut = GetStdHandle(to_stderr ? STD_ERROR_HANDLE : STD_OUTPUT_HANDLE); HANDLE hStdOut = GetStdHandle(to_stderr ? STD_ERROR_HANDLE : STD_OUTPUT_HANDLE);
@ -139,7 +139,7 @@ namespace YYCC::ConsoleHelper {
if (GetConsoleMode(hStdOut, &dwConsoleMode)) { if (GetConsoleMode(hStdOut, &dwConsoleMode)) {
// console handle, use WriteConsoleW. // console handle, use WriteConsoleW.
// convert utf8 string to wide char first // convert utf8 string to wide char first
std::wstring wstrl(YYCC::EncodingHelper::UTF8ToWchar(strl.c_str())); std::wstring wstrl(YYCC::EncodingHelper::UTF8ToWchar(strl));
size_t wstrl_size = wstrl.size(); size_t wstrl_size = wstrl.size();
// write string with size check // write string with size check
if (wstrl_size <= std::numeric_limits<DWORD>::max()) { if (wstrl_size <= std::numeric_limits<DWORD>::max()) {
@ -176,7 +176,7 @@ namespace YYCC::ConsoleHelper {
#endif #endif
} }
std::string ReadLine() { yycc_u8string ReadLine() {
#if YYCC_OS == YYCC_OS_WINDOWS #if YYCC_OS == YYCC_OS_WINDOWS
// get stdin mode // get stdin mode
@ -188,24 +188,24 @@ namespace YYCC::ConsoleHelper {
} else { } else {
return WinConsoleRead<false>(hStdIn); return WinConsoleRead<false>(hStdIn);
} }
#else #else
// in linux, directly use C++ function to fetch. // in linux, directly use C++ function to fetch.
std::string cmd; std::string cmd;
if (std::getline(std::cin, cmd).fail()) cmd.clear(); if (std::getline(std::cin, cmd).fail()) cmd.clear();
return cmd; return EncodingHelper::ToUTF8(cmd);
#endif #endif
} }
template<bool bNeedFmt, bool bIsErr, bool bHasEOL> template<bool bNeedFmt, bool bIsErr, bool bHasEOL>
static void RawWrite(const char* u8_fmt, va_list argptr) { static void RawWrite(const yycc_char8_t* u8_fmt, va_list argptr) {
// Buiild string need to be written first // Buiild string need to be written first
// If no format string or plain string for writing, return. // If no format string or plain string for writing, return.
if (u8_fmt == nullptr) return; if (u8_fmt == nullptr) return;
// Build or simply copy string // Build or simply copy string
std::string strl; yycc_u8string strl;
if constexpr (bNeedFmt) { if constexpr (bNeedFmt) {
// treat as format string // treat as format string
va_list argcpy; va_list argcpy;
@ -218,62 +218,62 @@ namespace YYCC::ConsoleHelper {
} }
// Checkout whether add EOL // Checkout whether add EOL
if constexpr (bHasEOL) { if constexpr (bHasEOL) {
strl += "\n"; strl += YYCC_U8("\n");
} }
#if YYCC_OS == YYCC_OS_WINDOWS #if YYCC_OS == YYCC_OS_WINDOWS
// call Windows specific writer // call Windows specific writer
WinConsoleWrite(strl, bIsErr); WinConsoleWrite(strl, bIsErr);
#else #else
// in linux, directly use C function to write. // in linux, directly use C function to write.
std::fputs(strl.c_str(), bIsErr ? stderr : stdout); std::fputs(EncodingHelper::ToNative(strl.c_str()), bIsErr ? stderr : stdout);
#endif #endif
} }
void Format(const char* u8_fmt, ...) { void Format(const yycc_char8_t* u8_fmt, ...) {
va_list argptr; va_list argptr;
va_start(argptr, u8_fmt); va_start(argptr, u8_fmt);
RawWrite<true, false, false>(u8_fmt, argptr); RawWrite<true, false, false>(u8_fmt, argptr);
va_end(argptr); va_end(argptr);
} }
void FormatLine(const char* u8_fmt, ...) { void FormatLine(const yycc_char8_t* u8_fmt, ...) {
va_list argptr; va_list argptr;
va_start(argptr, u8_fmt); va_start(argptr, u8_fmt);
RawWrite<true, false, true>(u8_fmt, argptr); RawWrite<true, false, true>(u8_fmt, argptr);
va_end(argptr); va_end(argptr);
} }
void Write(const char* u8_strl) { void Write(const yycc_char8_t* u8_strl) {
va_list empty{}; va_list empty{};
RawWrite<false, false, false>(u8_strl, empty); RawWrite<false, false, false>(u8_strl, empty);
} }
void WriteLine(const char* u8_strl) { void WriteLine(const yycc_char8_t* u8_strl) {
va_list empty{}; va_list empty{};
RawWrite<false, false, true>(u8_strl, empty); RawWrite<false, false, true>(u8_strl, empty);
} }
void ErrFormat(const char* u8_fmt, ...) { void ErrFormat(const yycc_char8_t* u8_fmt, ...) {
va_list argptr; va_list argptr;
va_start(argptr, u8_fmt); va_start(argptr, u8_fmt);
RawWrite<true, true, false>(u8_fmt, argptr); RawWrite<true, true, false>(u8_fmt, argptr);
va_end(argptr); va_end(argptr);
} }
void ErrFormatLine(const char* u8_fmt, ...) { void ErrFormatLine(const yycc_char8_t* u8_fmt, ...) {
va_list argptr; va_list argptr;
va_start(argptr, u8_fmt); va_start(argptr, u8_fmt);
RawWrite<true, true, true>(u8_fmt, argptr); RawWrite<true, true, true>(u8_fmt, argptr);
va_end(argptr); va_end(argptr);
} }
void ErrWrite(const char* u8_strl) { void ErrWrite(const yycc_char8_t* u8_strl) {
va_list empty{}; va_list empty{};
RawWrite<false, true, false>(u8_strl, empty); RawWrite<false, true, false>(u8_strl, empty);
} }
void ErrWriteLine(const char* u8_strl) { void ErrWriteLine(const yycc_char8_t* u8_strl) {
va_list empty{}; va_list empty{};
RawWrite<false, true, true>(u8_strl, empty); RawWrite<false, true, true>(u8_strl, empty);
} }

View File

@ -124,52 +124,52 @@ namespace YYCC::ConsoleHelper {
* This function also can be used as ordering user press Enter key by * This function also can be used as ordering user press Enter key by
* simply calling this function and ignoring its return value. * simply calling this function and ignoring its return value.
*/ */
std::string ReadLine(); yycc_u8string ReadLine();
/** /**
* @brief Universal console write function with format feature. * @brief Universal console write function with format feature.
* @param[in] u8_fmt The format string. * @param[in] u8_fmt The format string.
* @param[in] ... The arguments to be formatted. * @param[in] ... The arguments to be formatted.
*/ */
void Format(const char* u8_fmt, ...); void Format(const yycc_char8_t* u8_fmt, ...);
/** /**
* @brief Universal console write function with format and auto EOL feature. * @brief Universal console write function with format and auto EOL feature.
* @param[in] u8_fmt The format string. * @param[in] u8_fmt The format string.
* @param[in] ... The arguments to be formatted. * @param[in] ... The arguments to be formatted.
*/ */
void FormatLine(const char* u8_fmt, ...); void FormatLine(const yycc_char8_t* u8_fmt, ...);
/** /**
* @brief Universal console write function. * @brief Universal console write function.
* @param[in] u8_strl The string to be written. * @param[in] u8_strl The string to be written.
*/ */
void Write(const char* u8_strl); void Write(const yycc_char8_t* u8_strl);
/** /**
* @brief Universal console write function with auto EOL feature. * @brief Universal console write function with auto EOL feature.
* @param[in] u8_strl The string to be written. * @param[in] u8_strl The string to be written.
*/ */
void WriteLine(const char* u8_strl); void WriteLine(const yycc_char8_t* u8_strl);
/** /**
* @brief Universal console error write function with format and feature. * @brief Universal console error write function with format and feature.
* @param[in] u8_fmt The format string. * @param[in] u8_fmt The format string.
* @param[in] ... The arguments to be formatted. * @param[in] ... The arguments to be formatted.
*/ */
void ErrFormat(const char* u8_fmt, ...); void ErrFormat(const yycc_char8_t* u8_fmt, ...);
/** /**
* @brief Universal console error write function with format and auto EOL feature. * @brief Universal console error write function with format and auto EOL feature.
* @param[in] u8_fmt The format string. * @param[in] u8_fmt The format string.
* @param[in] ... The arguments to be formatted. * @param[in] ... The arguments to be formatted.
*/ */
void ErrFormatLine(const char* u8_fmt, ...); void ErrFormatLine(const yycc_char8_t* u8_fmt, ...);
/** /**
* @brief Universal console error write function. * @brief Universal console error write function.
* @param[in] u8_strl The string to be written. * @param[in] u8_strl The string to be written.
*/ */
void ErrWrite(const char* u8_strl); void ErrWrite(const yycc_char8_t* u8_strl);
/** /**
* @brief Universal console error write function with auto EOL feature. * @brief Universal console error write function with auto EOL feature.
* @param[in] u8_strl The string to be written. * @param[in] u8_strl The string to be written.
*/ */
void ErrWriteLine(const char* u8_strl); void ErrWriteLine(const yycc_char8_t* u8_strl);
} }

View File

@ -8,16 +8,16 @@ namespace YYCC::DialogHelper {
#pragma region FileFilters #pragma region FileFilters
bool FileFilters::Add(const char* filter_name, std::initializer_list<const char*> il) { bool FileFilters::Add(const yycc_char8_t* filter_name, std::initializer_list<const yycc_char8_t*> il) {
// assign filter name // assign filter name
if (filter_name == nullptr) return false; if (filter_name == nullptr) return false;
FilterName name(filter_name); FilterName name(filter_name);
// assign filter patterns // assign filter patterns
FilterModes modes; FilterModes modes;
for (const char* pattern : il) { for (const yycc_char8_t* pattern : il) {
if (pattern != nullptr) if (pattern != nullptr)
modes.emplace_back(std::string(pattern)); modes.emplace_back(yycc_u8string(pattern));
} }
// check filter patterns // check filter patterns
@ -36,13 +36,13 @@ namespace YYCC::DialogHelper {
for (const auto& it : m_Filters) { for (const auto& it : m_Filters) {
// convert name to wchar // convert name to wchar
WinFileFilters::WinFilterName name; WinFileFilters::WinFilterName name;
if (!YYCC::EncodingHelper::UTF8ToWchar(it.first.c_str(), name)) if (!YYCC::EncodingHelper::UTF8ToWchar(it.first, name))
return false; return false;
// convert pattern and join them // convert pattern and join them
std::string joined_modes(YYCC::StringHelper::Join(it.second, ";")); yycc_u8string joined_modes(YYCC::StringHelper::Join(it.second, YYCC_U8(";")));
WinFileFilters::WinFilterModes modes; WinFileFilters::WinFilterModes modes;
if (!YYCC::EncodingHelper::UTF8ToWchar(joined_modes.c_str(), modes)) if (!YYCC::EncodingHelper::UTF8ToWchar(joined_modes, modes))
return false; return false;
// append new pair // append new pair
@ -94,12 +94,12 @@ namespace YYCC::DialogHelper {
// build title and init file name // build title and init file name
if (m_HasTitle) { if (m_HasTitle) {
if (!YYCC::EncodingHelper::UTF8ToWchar(m_Title.c_str(), win_result.m_WinTitle)) if (!YYCC::EncodingHelper::UTF8ToWchar(m_Title, win_result.m_WinTitle))
return false; return false;
win_result.m_HasTitle = true; win_result.m_HasTitle = true;
} }
if (m_HasInitFileName) { if (m_HasInitFileName) {
if (!YYCC::EncodingHelper::UTF8ToWchar(m_InitFileName.c_str(), win_result.m_WinInitFileName)) if (!YYCC::EncodingHelper::UTF8ToWchar(m_InitFileName, win_result.m_WinInitFileName))
return false; return false;
win_result.m_HasInitFileName = true; win_result.m_HasInitFileName = true;
} }
@ -108,7 +108,7 @@ namespace YYCC::DialogHelper {
if (m_HasInitDirectory) { if (m_HasInitDirectory) {
// convert to wpath // convert to wpath
std::wstring w_init_directory; std::wstring w_init_directory;
if (!YYCC::EncodingHelper::UTF8ToWchar(m_InitDirectory.c_str(), w_init_directory)) if (!YYCC::EncodingHelper::UTF8ToWchar(m_InitDirectory, w_init_directory))
return false; return false;
// fetch IShellItem* // fetch IShellItem*
@ -143,7 +143,7 @@ namespace YYCC::DialogHelper {
* @return True if success, otherwise false. * @return True if success, otherwise false.
* @remarks This is an assist function of CommonFileDialog. * @remarks This is an assist function of CommonFileDialog.
*/ */
static bool ExtractDisplayName(IShellItem* item, std::string& ret) { static bool ExtractDisplayName(IShellItem* item, yycc_u8string& ret) {
// fetch display name from IShellItem* // fetch display name from IShellItem*
LPWSTR _name; LPWSTR _name;
HRESULT hr = item->GetDisplayName(SIGDN_FILESYSPATH, &_name); HRESULT hr = item->GetDisplayName(SIGDN_FILESYSPATH, &_name);
@ -168,7 +168,7 @@ namespace YYCC::DialogHelper {
* @remarks This function is the real underlying function of all dialog functions. * @remarks This function is the real underlying function of all dialog functions.
*/ */
template<CommonFileDialogType EDialogType> template<CommonFileDialogType EDialogType>
static bool CommonFileDialog(const FileDialog& params, std::vector<std::string>& ret) { static bool CommonFileDialog(const FileDialog& params, std::vector<yycc_u8string>& ret) {
// Reference: https://learn.microsoft.com/en-us/windows/win32/shell/common-file-dialog // Reference: https://learn.microsoft.com/en-us/windows/win32/shell/common-file-dialog
// prepare result variable // prepare result variable
HRESULT hr; HRESULT hr;
@ -289,7 +289,7 @@ namespace YYCC::DialogHelper {
COMHelper::SmartIShellItem result_item(_item); COMHelper::SmartIShellItem result_item(_item);
// extract display name // extract display name
std::string result_name; yycc_u8string result_name;
if (!ExtractDisplayName(result_item.get(), result_name)) if (!ExtractDisplayName(result_item.get(), result_name))
return false; return false;
@ -326,7 +326,7 @@ namespace YYCC::DialogHelper {
COMHelper::SmartIShellItem result_item(_item); COMHelper::SmartIShellItem result_item(_item);
// extract display name // extract display name
std::string result_name; yycc_u8string result_name;
if (!ExtractDisplayName(result_item.get(), result_name)) if (!ExtractDisplayName(result_item.get(), result_name))
return false; return false;
@ -347,24 +347,24 @@ namespace YYCC::DialogHelper {
#pragma region Wrapper Functions #pragma region Wrapper Functions
bool OpenFileDialog(const FileDialog& params, std::string& ret) { bool OpenFileDialog(const FileDialog& params, yycc_u8string& ret) {
std::vector<std::string> cache; std::vector<yycc_u8string> cache;
bool isok = CommonFileDialog<CommonFileDialogType::OpenFile>(params, cache); bool isok = CommonFileDialog<CommonFileDialogType::OpenFile>(params, cache);
if (isok) ret = cache.front(); if (isok) ret = cache.front();
return isok; return isok;
} }
bool OpenMultipleFileDialog(const FileDialog& params, std::vector<std::string>& ret) { bool OpenMultipleFileDialog(const FileDialog& params, std::vector<yycc_u8string>& ret) {
return CommonFileDialog<CommonFileDialogType::OpenMultipleFiles>(params, ret); return CommonFileDialog<CommonFileDialogType::OpenMultipleFiles>(params, ret);
} }
bool SaveFileDialog(const FileDialog& params, std::string& ret) { bool SaveFileDialog(const FileDialog& params, yycc_u8string& ret) {
std::vector<std::string> cache; std::vector<yycc_u8string> cache;
bool isok = CommonFileDialog<CommonFileDialogType::SaveFile>(params, cache); bool isok = CommonFileDialog<CommonFileDialogType::SaveFile>(params, cache);
if (isok) ret = cache.front(); if (isok) ret = cache.front();
return isok; return isok;
} }
bool OpenFolderDialog(const FileDialog& params, std::string& ret) { bool OpenFolderDialog(const FileDialog& params, yycc_u8string& ret) {
std::vector<std::string> cache; std::vector<yycc_u8string> cache;
bool isok = CommonFileDialog<CommonFileDialogType::OpenFolder>(params, cache); bool isok = CommonFileDialog<CommonFileDialogType::OpenFolder>(params, cache);
if (isok) ret = cache.front(); if (isok) ret = cache.front();
return isok; return isok;

View File

@ -65,7 +65,7 @@ namespace YYCC::DialogHelper {
* @remarks This function allow you register multiple filter patterns for single friendly name. * @remarks This function allow you register multiple filter patterns for single friendly name.
* For example: `Add("Microsoft Word (*.doc; *.docx)", {"*.doc", "*.docx"})` * For example: `Add("Microsoft Word (*.doc; *.docx)", {"*.doc", "*.docx"})`
*/ */
bool Add(const char* filter_name, std::initializer_list<const char*> il); bool Add(const yycc_char8_t* filter_name, std::initializer_list<const yycc_char8_t*> il);
/** /**
* @brief Clear filter pairs for following re-use. * @brief Clear filter pairs for following re-use.
*/ */
@ -85,8 +85,8 @@ namespace YYCC::DialogHelper {
bool Generate(WinFileFilters& win_result) const; bool Generate(WinFileFilters& win_result) const;
protected: protected:
using FilterModes = std::vector<std::string>; using FilterModes = std::vector<yycc_u8string>;
using FilterName = std::string; using FilterName = yycc_u8string;
using FilterPair = std::pair<FilterName, FilterModes>; using FilterPair = std::pair<FilterName, FilterModes>;
std::vector<FilterPair> m_Filters; std::vector<FilterPair> m_Filters;
@ -159,7 +159,7 @@ namespace YYCC::DialogHelper {
m_HasTitle(false), m_HasInitFileName(false), m_HasInitDirectory(false) {} m_HasTitle(false), m_HasInitFileName(false), m_HasInitDirectory(false) {}
void SetOwner(HWND owner) { m_Owner = owner; } void SetOwner(HWND owner) { m_Owner = owner; }
void SetTitle(const char* title) { void SetTitle(const yycc_char8_t* title) {
if (m_HasTitle = title != nullptr) if (m_HasTitle = title != nullptr)
m_Title = title; m_Title = title;
} }
@ -167,11 +167,11 @@ namespace YYCC::DialogHelper {
return m_FileTypes; return m_FileTypes;
} }
void SetDefaultFileTypeIndex(size_t idx) { m_DefaultFileTypeIndex = idx; } void SetDefaultFileTypeIndex(size_t idx) { m_DefaultFileTypeIndex = idx; }
void SetInitFileName(const char* init_filename) { void SetInitFileName(const yycc_char8_t* init_filename) {
if (m_HasInitFileName = init_filename != nullptr) if (m_HasInitFileName = init_filename != nullptr)
m_InitFileName = init_filename; m_InitFileName = init_filename;
} }
void SetInitDirectory(const char* init_dir) { void SetInitDirectory(const yycc_char8_t* init_dir) {
if (m_HasInitDirectory = init_dir != nullptr) if (m_HasInitDirectory = init_dir != nullptr)
m_InitDirectory = init_dir; m_InitDirectory = init_dir;
} }
@ -200,7 +200,7 @@ namespace YYCC::DialogHelper {
protected: protected:
HWND m_Owner; HWND m_Owner;
bool m_HasTitle, m_HasInitFileName, m_HasInitDirectory; bool m_HasTitle, m_HasInitFileName, m_HasInitDirectory;
std::string m_Title, m_InitFileName, m_InitDirectory; yycc_u8string m_Title, m_InitFileName, m_InitDirectory;
FileFilters m_FileTypes; FileFilters m_FileTypes;
/** /**
* @brief The default selected file type in dialog * @brief The default selected file type in dialog
@ -210,11 +210,11 @@ namespace YYCC::DialogHelper {
size_t m_DefaultFileTypeIndex; size_t m_DefaultFileTypeIndex;
}; };
bool OpenFileDialog(const FileDialog& params, std::string& ret); bool OpenFileDialog(const FileDialog& params, yycc_u8string& ret);
bool OpenMultipleFileDialog(const FileDialog& params, std::vector<std::string>& ret); bool OpenMultipleFileDialog(const FileDialog& params, std::vector<yycc_u8string>& ret);
bool SaveFileDialog(const FileDialog& params, std::string& ret); bool SaveFileDialog(const FileDialog& params, yycc_u8string& ret);
bool OpenFolderDialog(const FileDialog& params, std::string& ret); bool OpenFolderDialog(const FileDialog& params, yycc_u8string& ret);
} }

View File

@ -50,7 +50,7 @@
*/ */
namespace YYCC::EncodingHelper { namespace YYCC::EncodingHelper {
#define YYCC_U8(strl) (reinterpret_cast<const yycc_char8_t*>(u8 ## strl)) #define YYCC_U8(strl) (reinterpret_cast<const ::YYCC::yycc_char8_t*>(u8 ## strl))
const yycc_char8_t* ToUTF8(const char* src); const yycc_char8_t* ToUTF8(const char* src);
yycc_char8_t* ToUTF8(char* src); yycc_char8_t* ToUTF8(char* src);

View File

@ -59,50 +59,50 @@ namespace YYCC::ExceptionHelper {
* @param[in] code Exception code * @param[in] code Exception code
* @return The const string pointer to corresponding exception explanation string. * @return The const string pointer to corresponding exception explanation string.
*/ */
static const char* UExceptionGetCodeName(DWORD code) { static const yycc_char8_t* UExceptionGetCodeName(DWORD code) {
switch (code) { switch (code) {
case EXCEPTION_ACCESS_VIOLATION: case EXCEPTION_ACCESS_VIOLATION:
return "access violation"; return YYCC_U8("access violation");
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
return "array index out of bound"; return YYCC_U8("array index out of bound");
case EXCEPTION_BREAKPOINT: case EXCEPTION_BREAKPOINT:
return "breakpoint reached"; return YYCC_U8("breakpoint reached");
case EXCEPTION_DATATYPE_MISALIGNMENT: case EXCEPTION_DATATYPE_MISALIGNMENT:
return "misaligned data access"; return YYCC_U8("misaligned data access");
case EXCEPTION_FLT_DENORMAL_OPERAND: case EXCEPTION_FLT_DENORMAL_OPERAND:
return "operand had denormal value"; return YYCC_U8("operand had denormal value");
case EXCEPTION_FLT_DIVIDE_BY_ZERO: case EXCEPTION_FLT_DIVIDE_BY_ZERO:
return "floating-point division by zero"; return YYCC_U8("floating-point division by zero");
case EXCEPTION_FLT_INEXACT_RESULT: case EXCEPTION_FLT_INEXACT_RESULT:
return "no decimal fraction representation for value"; return YYCC_U8("no decimal fraction representation for value");
case EXCEPTION_FLT_INVALID_OPERATION: case EXCEPTION_FLT_INVALID_OPERATION:
return "invalid floating-point operation"; return YYCC_U8("invalid floating-point operation");
case EXCEPTION_FLT_OVERFLOW: case EXCEPTION_FLT_OVERFLOW:
return "floating-point overflow"; return YYCC_U8("floating-point overflow");
case EXCEPTION_FLT_STACK_CHECK: case EXCEPTION_FLT_STACK_CHECK:
return "floating-point stack corruption"; return YYCC_U8("floating-point stack corruption");
case EXCEPTION_FLT_UNDERFLOW: case EXCEPTION_FLT_UNDERFLOW:
return "floating-point underflow"; return YYCC_U8("floating-point underflow");
case EXCEPTION_ILLEGAL_INSTRUCTION: case EXCEPTION_ILLEGAL_INSTRUCTION:
return "illegal instruction"; return YYCC_U8("illegal instruction");
case EXCEPTION_IN_PAGE_ERROR: case EXCEPTION_IN_PAGE_ERROR:
return "inaccessible page"; return YYCC_U8("inaccessible page");
case EXCEPTION_INT_DIVIDE_BY_ZERO: case EXCEPTION_INT_DIVIDE_BY_ZERO:
return "integer division by zero"; return YYCC_U8("integer division by zero");
case EXCEPTION_INT_OVERFLOW: case EXCEPTION_INT_OVERFLOW:
return "integer overflow"; return YYCC_U8("integer overflow");
case EXCEPTION_INVALID_DISPOSITION: case EXCEPTION_INVALID_DISPOSITION:
return "documentation says this should never happen"; return YYCC_U8("documentation says this should never happen");
case EXCEPTION_NONCONTINUABLE_EXCEPTION: case EXCEPTION_NONCONTINUABLE_EXCEPTION:
return "can't continue after a noncontinuable exception"; return YYCC_U8("can't continue after a noncontinuable exception");
case EXCEPTION_PRIV_INSTRUCTION: case EXCEPTION_PRIV_INSTRUCTION:
return "attempted to execute a privileged instruction"; return YYCC_U8("attempted to execute a privileged instruction");
case EXCEPTION_SINGLE_STEP: case EXCEPTION_SINGLE_STEP:
return "one instruction has been executed"; return YYCC_U8("one instruction has been executed");
case EXCEPTION_STACK_OVERFLOW: case EXCEPTION_STACK_OVERFLOW:
return "stack overflow"; return YYCC_U8("stack overflow");
default: default:
return "unknown exception"; return YYCC_U8("unknown exception");
} }
} }
@ -117,12 +117,12 @@ namespace YYCC::ExceptionHelper {
* @param[in] fmt The format string. * @param[in] fmt The format string.
* @param[in] ... The argument to be formatted. * @param[in] ... The argument to be formatted.
*/ */
static void UExceptionErrLogFormatLine(std::FILE* fs, const char* fmt, ...) { static void UExceptionErrLogFormatLine(std::FILE* fs, const yycc_char8_t* fmt, ...) {
// write to file // write to file
if (fs != nullptr) { if (fs != nullptr) {
va_list arg1; va_list arg1;
va_start(arg1, fmt); va_start(arg1, fmt);
std::vfprintf(fs, fmt, arg1); std::vfprintf(fs, EncodingHelper::ToNative(fmt), arg1);
std::fputs("\n", fs); std::fputs("\n", fs);
va_end(arg1); va_end(arg1);
} }
@ -142,10 +142,10 @@ namespace YYCC::ExceptionHelper {
* If it is nullptr, function will skip writing for file stream. * If it is nullptr, function will skip writing for file stream.
* @param[in] strl The string to be written. * @param[in] strl The string to be written.
*/ */
static void UExceptionErrLogWriteLine(std::FILE* fs, const char* strl) { static void UExceptionErrLogWriteLine(std::FILE* fs, const yycc_char8_t* strl) {
// write to file // write to file
if (fs != nullptr) { if (fs != nullptr) {
std::fputs(strl, fs); std::fputs(EncodingHelper::ToNative(strl), fs);
std::fputs("\n", fs); std::fputs("\n", fs);
} }
// write to stderr // write to stderr
@ -163,7 +163,7 @@ namespace YYCC::ExceptionHelper {
// init symbol // init symbol
if (!SymInitialize(process, 0, TRUE)) { if (!SymInitialize(process, 0, TRUE)) {
// fail to init. return // fail to init. return
UExceptionErrLogWriteLine(fs, "Fail to initialize symbol handle for process!"); UExceptionErrLogWriteLine(fs, YYCC_U8("Fail to initialize symbol handle for process!"));
return; return;
} }
@ -215,13 +215,13 @@ namespace YYCC::ExceptionHelper {
// depth breaker // depth breaker
--maxdepth; --maxdepth;
if (maxdepth < 0) { if (maxdepth < 0) {
UExceptionErrLogWriteLine(fs, "..."); // indicate there are some frames not listed UExceptionErrLogWriteLine(fs, YYCC_U8("...")); // indicate there are some frames not listed
break; break;
} }
// get module name // get module name
const char* module_name = "<unknown module>"; const yycc_char8_t* module_name = YYCC_U8("<unknown module>");
std::string module_name_raw; yycc_u8string module_name_raw;
DWORD64 module_base; DWORD64 module_base;
if (module_base = SymGetModuleBase64(process, frame.AddrPC.Offset)) { if (module_base = SymGetModuleBase64(process, frame.AddrPC.Offset)) {
if (WinFctHelper::GetModuleFileName((HINSTANCE)module_base, module_name_raw)) { if (WinFctHelper::GetModuleFileName((HINSTANCE)module_base, module_name_raw)) {
@ -230,18 +230,18 @@ namespace YYCC::ExceptionHelper {
} }
// get source file and line // get source file and line
const char* source_file = "<unknown source>"; const yycc_char8_t* source_file = YYCC_U8("<unknown source>");
DWORD64 source_file_line = 0; DWORD64 source_file_line = 0;
DWORD dwDisplacement; DWORD dwDisplacement;
IMAGEHLP_LINE64 winline; IMAGEHLP_LINE64 winline;
winline.SizeOfStruct = sizeof(IMAGEHLP_LINE64); winline.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
if (SymGetLineFromAddr64(process, frame.AddrPC.Offset, &dwDisplacement, &winline)) { if (SymGetLineFromAddr64(process, frame.AddrPC.Offset, &dwDisplacement, &winline)) {
source_file = winline.FileName; source_file = EncodingHelper::ToUTF8(winline.FileName); // TODO: check whether there is UNICODE file name.
source_file_line = winline.LineNumber; source_file_line = winline.LineNumber;
} }
// write to file // write to file
UExceptionErrLogFormatLine(fs, "0x%" PRI_XPTR_LEFT_PADDING PRIXPTR "[%s+0x%" PRI_XPTR_LEFT_PADDING PRIXPTR "]\t%s#L%" PRIu64, UExceptionErrLogFormatLine(fs, YYCC_U8("0x%" PRI_XPTR_LEFT_PADDING PRIXPTR "[%s+0x%" PRI_XPTR_LEFT_PADDING PRIXPTR "]\t%s#L%" PRIu64),
frame.AddrPC.Offset, // memory adress frame.AddrPC.Offset, // memory adress
module_name, frame.AddrPC.Offset - module_base, // module name + relative address module_name, frame.AddrPC.Offset - module_base, // module name + relative address
source_file, source_file_line // source file + source line source_file, source_file_line // source file + source line
@ -255,16 +255,16 @@ namespace YYCC::ExceptionHelper {
SymCleanup(process); SymCleanup(process);
} }
static void UExceptionErrorLog(const std::string& u8_filename, LPEXCEPTION_POINTERS info) { static void UExceptionErrorLog(const yycc_u8string& u8_filename, LPEXCEPTION_POINTERS info) {
// open file stream if we have file name // open file stream if we have file name
std::FILE* fs = nullptr; std::FILE* fs = nullptr;
if (!u8_filename.empty()) { if (!u8_filename.empty()) {
fs = IOHelper::UTF8FOpen(u8_filename.c_str(), "wb"); fs = IOHelper::UTF8FOpen(u8_filename.c_str(), YYCC_U8("wb"));
} }
// record exception type first // record exception type first
PEXCEPTION_RECORD rec = info->ExceptionRecord; PEXCEPTION_RECORD rec = info->ExceptionRecord;
UExceptionErrLogFormatLine(fs, "Unhandled exception occured at 0x%" PRI_XPTR_LEFT_PADDING PRIXPTR ": %s (%" PRIu32 ").", UExceptionErrLogFormatLine(fs, YYCC_U8("Unhandled exception occured at 0x%" PRI_XPTR_LEFT_PADDING PRIXPTR ": %s (%" PRIu32 ")."),
rec->ExceptionAddress, rec->ExceptionAddress,
UExceptionGetCodeName(rec->ExceptionCode), UExceptionGetCodeName(rec->ExceptionCode),
rec->ExceptionCode rec->ExceptionCode
@ -276,7 +276,7 @@ namespace YYCC::ExceptionHelper {
const char* op = const char* op =
rec->ExceptionInformation[0] == 0 ? "read" : rec->ExceptionInformation[0] == 0 ? "read" :
rec->ExceptionInformation[0] == 1 ? "written" : "executed"; rec->ExceptionInformation[0] == 1 ? "written" : "executed";
UExceptionErrLogFormatLine(fs, "The data at memory address 0x%" PRI_XPTR_LEFT_PADDING PRIxPTR " could not be %s.", UExceptionErrLogFormatLine(fs, YYCC_U8("The data at memory address 0x%" PRI_XPTR_LEFT_PADDING PRIxPTR " could not be %s."),
rec->ExceptionInformation[1], op); rec->ExceptionInformation[1], op);
} }
} }
@ -290,12 +290,12 @@ namespace YYCC::ExceptionHelper {
} }
} }
static void UExceptionCoreDump(const std::string& u8_filename, LPEXCEPTION_POINTERS info) { static void UExceptionCoreDump(const yycc_u8string& u8_filename, LPEXCEPTION_POINTERS info) {
// convert file encoding // convert file encoding
std::wstring filename; std::wstring filename;
if (u8_filename.empty()) if (u8_filename.empty())
return; // if no given file name, return return; // if no given file name, return
if (!YYCC::EncodingHelper::UTF8ToWchar(u8_filename.c_str(), filename)) if (!YYCC::EncodingHelper::UTF8ToWchar(u8_filename, filename))
return; // if convertion failed, return return; // if convertion failed, return
// open file and write // open file and write
@ -315,18 +315,18 @@ namespace YYCC::ExceptionHelper {
} }
} }
static bool UExceptionFetchRecordPath(std::string& log_path, std::string& coredump_path) { static bool UExceptionFetchRecordPath(yycc_u8string& log_path, yycc_u8string& coredump_path) {
// build two file names like: "module.dll.1234.log" and "module.dll.1234.dmp". // build two file names like: "module.dll.1234.log" and "module.dll.1234.dmp".
// "module.dll" is the name of current module. "1234" is current process id. // "module.dll" is the name of current module. "1234" is current process id.
// get self module name // get self module name
std::string u8_self_module_name; yycc_u8string u8_self_module_name;
{ {
// get module handle // get module handle
HMODULE hSelfModule = YYCC::WinFctHelper::GetCurrentModule(); HMODULE hSelfModule = YYCC::WinFctHelper::GetCurrentModule();
if (hSelfModule == nullptr) if (hSelfModule == nullptr)
return false; return false;
// get full path of self module // get full path of self module
std::string u8_self_module_path; yycc_u8string u8_self_module_path;
if (!YYCC::WinFctHelper::GetModuleFileName(hSelfModule, u8_self_module_path)) if (!YYCC::WinFctHelper::GetModuleFileName(hSelfModule, u8_self_module_path))
return false; return false;
// extract file name from full path by std::filesystem::path // extract file name from full path by std::filesystem::path
@ -336,22 +336,22 @@ namespace YYCC::ExceptionHelper {
// then get process id // then get process id
DWORD process_id = GetCurrentProcessId(); DWORD process_id = GetCurrentProcessId();
// conbine them as a file name prefix // conbine them as a file name prefix
std::string u8_filename_prefix; yycc_u8string u8_filename_prefix;
if (!YYCC::StringHelper::Printf(u8_filename_prefix, "%s.%" PRIu32, u8_self_module_name.c_str(), process_id)) if (!YYCC::StringHelper::Printf(u8_filename_prefix, YYCC_U8("%s.%" PRIu32), u8_self_module_name.c_str(), process_id))
return false; return false;
// then get file name for log and minidump // then get file name for log and minidump
std::string u8_log_filename = u8_filename_prefix + ".log"; yycc_u8string u8_log_filename = u8_filename_prefix + YYCC_U8(".log");
std::string u8_coredump_filename = u8_filename_prefix + ".dmp"; yycc_u8string u8_coredump_filename = u8_filename_prefix + YYCC_U8(".dmp");
// fetch crash report path // fetch crash report path
// get local appdata folder // get local appdata folder
std::string u8_localappdata_path; yycc_u8string u8_localappdata_path;
if (!WinFctHelper::GetLocalAppData(u8_localappdata_path)) if (!WinFctHelper::GetLocalAppData(u8_localappdata_path))
return false; return false;
// convert to std::filesystem::path // convert to std::filesystem::path
std::filesystem::path crash_report_path(FsPathPatch::FromUTF8Path(u8_localappdata_path.c_str())); std::filesystem::path crash_report_path(FsPathPatch::FromUTF8Path(u8_localappdata_path.c_str()));
// slash into crash report folder // slash into crash report folder
crash_report_path /= FsPathPatch::FromUTF8Path("CrashDumps"); crash_report_path /= FsPathPatch::FromUTF8Path(YYCC_U8("CrashDumps"));
// use create function to make sure it is existing // use create function to make sure it is existing
std::filesystem::create_directories(crash_report_path); std::filesystem::create_directories(crash_report_path);
@ -375,18 +375,18 @@ namespace YYCC::ExceptionHelper {
// core implementation // core implementation
{ {
// fetch error report path first // fetch error report path first
std::string log_path, coredump_path; yycc_u8string log_path, coredump_path;
if (!UExceptionFetchRecordPath(log_path, coredump_path)) { if (!UExceptionFetchRecordPath(log_path, coredump_path)) {
// fail to fetch path, clear them. // fail to fetch path, clear them.
// we still can handle crash without them // we still can handle crash without them
log_path.clear(); log_path.clear();
coredump_path.clear(); coredump_path.clear();
// and tell user we can not output file // and tell user we can not output file
ConsoleHelper::ErrWriteLine("Crash occurs, but we can not create crash log and coredump!"); ConsoleHelper::ErrWriteLine(YYCC_U8("Crash occurs, but we can not create crash log and coredump!"));
} else { } else {
// okey. output file path to tell user the path where you can find. // okey. output file path to tell user the path where you can find.
ConsoleHelper::ErrFormatLine("Crash Log: %s", log_path.c_str()); ConsoleHelper::ErrFormatLine(YYCC_U8("Crash Log: %s"), log_path.c_str());
ConsoleHelper::ErrFormatLine("Crash Coredump: %s", coredump_path.c_str()); ConsoleHelper::ErrFormatLine(YYCC_U8("Crash Coredump: %s"), coredump_path.c_str());
} }
// write crash log // write crash log

View File

@ -6,7 +6,7 @@
namespace YYCC::FsPathPatch { namespace YYCC::FsPathPatch {
std::filesystem::path FromUTF8Path(const char* u8_path) { std::filesystem::path FromUTF8Path(const yycc_char8_t* u8_path) {
#if YYCC_OS == YYCC_OS_WINDOWS #if YYCC_OS == YYCC_OS_WINDOWS
// convert path to wchar // convert path to wchar
@ -14,19 +14,19 @@ namespace YYCC::FsPathPatch {
if (!YYCC::EncodingHelper::UTF8ToWchar(u8_path, wpath)) if (!YYCC::EncodingHelper::UTF8ToWchar(u8_path, wpath))
throw std::invalid_argument("Fail to convert given UTF8 string."); throw std::invalid_argument("Fail to convert given UTF8 string.");
// call microsoft specified fopen which support wchar as argument. // return path with wchar_t ctor
return std::filesystem::path(wpath); return std::filesystem::path(wpath);
#else #else
return std::filesystem::path(u8_path); return std::filesystem::path(EncodingHelper::ToNative(u8_path));
#endif #endif
} }
std::string ToUTF8Path(const std::filesystem::path& path) { yycc_u8string ToUTF8Path(const std::filesystem::path& path) {
#if YYCC_OS == YYCC_OS_WINDOWS #if YYCC_OS == YYCC_OS_WINDOWS
// get and convert to utf8 // get and convert to utf8
std::string u8_path; yycc_u8string u8_path;
if (!YYCC::EncodingHelper::WcharToUTF8(path.c_str(), u8_path)) if (!YYCC::EncodingHelper::WcharToUTF8(path.c_str(), u8_path))
throw std::invalid_argument("Fail to convert to UTF8 string."); throw std::invalid_argument("Fail to convert to UTF8 string.");
@ -34,7 +34,7 @@ namespace YYCC::FsPathPatch {
return u8_path; return u8_path;
#else #else
return path.string(); return EncodingHelper::ToUTF8(path.string());
#endif #endif
} }

View File

@ -28,7 +28,7 @@ namespace YYCC::FsPathPatch {
* @return std::filesystem::path instance. * @return std::filesystem::path instance.
* @exception std::invalid_argument Fail to parse given UTF8 string (maybe invalid?). * @exception std::invalid_argument Fail to parse given UTF8 string (maybe invalid?).
*/ */
std::filesystem::path FromUTF8Path(const char* u8_path); std::filesystem::path FromUTF8Path(const yycc_char8_t* u8_path);
/** /**
* @brief Returns the UTF8 representation of the pathname * @brief Returns the UTF8 representation of the pathname
@ -36,6 +36,6 @@ namespace YYCC::FsPathPatch {
* @return UTF8 encoded string representing given path. * @return UTF8 encoded string representing given path.
* @exception std::invalid_argument Fail to parse to UTF8 string. * @exception std::invalid_argument Fail to parse to UTF8 string.
*/ */
std::string ToUTF8Path(const std::filesystem::path& path); yycc_u8string ToUTF8Path(const std::filesystem::path& path);
} }

View File

@ -14,7 +14,7 @@
namespace YYCC::IOHelper { namespace YYCC::IOHelper {
FILE* UTF8FOpen(const char* u8_filepath, const char* u8_mode) { FILE* UTF8FOpen(const yycc_char8_t* u8_filepath, const yycc_char8_t* u8_mode) {
#if YYCC_OS == YYCC_OS_WINDOWS #if YYCC_OS == YYCC_OS_WINDOWS
// convert mode and file path to wchar // convert mode and file path to wchar

View File

@ -32,6 +32,6 @@ namespace YYCC::IOHelper {
* On other platforms, this function will delegate request directly to std::fopen. * On other platforms, this function will delegate request directly to std::fopen.
* @return FILE* of the file to be opened, or nullptr if failed. * @return FILE* of the file to be opened, or nullptr if failed.
*/ */
FILE* UTF8FOpen(const char* u8_filepath, const char* u8_mode); FILE* UTF8FOpen(const yycc_char8_t* u8_filepath, const yycc_char8_t* u8_mode);
} }

View File

@ -14,11 +14,15 @@ namespace YYCC::ParserHelper {
// Reference: https://zh.cppreference.com/w/cpp/utility/from_chars // Reference: https://zh.cppreference.com/w/cpp/utility/from_chars
template<typename _Ty, std::enable_if_t<std::is_floating_point_v<_Ty>, int> = 0> template<typename _Ty, std::enable_if_t<std::is_floating_point_v<_Ty>, int> = 0>
bool TryParse(const std::string& strl, _Ty& num) { bool TryParse(const yycc_u8string_view& strl, _Ty& num) {
auto [ptr, ec] = std::from_chars(strl.c_str(), strl.c_str() + strl.size(), num, std::chars_format::general); auto [ptr, ec] = std::from_chars(
EncodingHelper::ToNative(strl.data()),
EncodingHelper::ToNative(strl.data() + strl.size()),
num, std::chars_format::general
);
if (ec == std::errc()) { if (ec == std::errc()) {
// check whether the full string is matched // check whether the full string is matched
return ptr == strl.c_str() + strl.size(); return ptr == EncodingHelper::ToNative(strl.data() + strl.size());
} else if (ec == std::errc::invalid_argument) { } else if (ec == std::errc::invalid_argument) {
// given string is invalid // given string is invalid
return false; return false;
@ -31,11 +35,15 @@ namespace YYCC::ParserHelper {
} }
} }
template<typename _Ty, std::enable_if_t<std::is_integral_v<_Ty> && !std::is_same_v<_Ty, bool>, int> = 0> template<typename _Ty, std::enable_if_t<std::is_integral_v<_Ty> && !std::is_same_v<_Ty, bool>, int> = 0>
bool TryParse(const std::string& strl, _Ty& num, int base = 10) { bool TryParse(const yycc_u8string_view& strl, _Ty& num, int base = 10) {
auto [ptr, ec] = std::from_chars(strl.c_str(), strl.c_str() + strl.size(), num, base); auto [ptr, ec] = std::from_chars(
EncodingHelper::ToNative(strl.data()),
EncodingHelper::ToNative(strl.data() + strl.size()),
num, base
);
if (ec == std::errc()) { if (ec == std::errc()) {
// check whether the full string is matched // check whether the full string is matched
return ptr == strl.c_str() + strl.size(); return ptr == EncodingHelper::ToNative(strl.data() + strl.size());
} else if (ec == std::errc::invalid_argument) { } else if (ec == std::errc::invalid_argument) {
// given string is invalid // given string is invalid
return false; return false;
@ -48,15 +56,15 @@ namespace YYCC::ParserHelper {
} }
} }
template<typename _Ty, std::enable_if_t<std::is_same_v<_Ty, bool>, int> = 0> template<typename _Ty, std::enable_if_t<std::is_same_v<_Ty, bool>, int> = 0>
bool TryParse(const std::string& strl, _Ty& num) { bool TryParse(const yycc_u8string_view& strl, _Ty& num) {
if (strl == "true") num = true; if (strl == YYCC_U8("true")) num = true;
else if (strl == "false") num = false; else if (strl == YYCC_U8("false")) num = false;
else return false; else return false;
return true; return true;
} }
template<typename _Ty, std::enable_if_t<std::is_arithmetic_v<_Ty>, int> = 0> template<typename _Ty, std::enable_if_t<std::is_arithmetic_v<_Ty>, int> = 0>
_Ty Parse(const std::string& strl) { _Ty Parse(const yycc_u8string_view& strl) {
_Ty ret; _Ty ret;
TryParse(strl, ret); TryParse(strl, ret);
return ret; return ret;
@ -65,11 +73,15 @@ namespace YYCC::ParserHelper {
// Reference: https://en.cppreference.com/w/cpp/utility/to_chars // Reference: https://en.cppreference.com/w/cpp/utility/to_chars
template<typename _Ty, std::enable_if_t<std::is_arithmetic_v<_Ty> && !std::is_same_v<_Ty, bool>, int> = 0> template<typename _Ty, std::enable_if_t<std::is_arithmetic_v<_Ty> && !std::is_same_v<_Ty, bool>, int> = 0>
std::string ToString(_Ty num) { yycc_u8string ToString(_Ty num) {
std::array<char, 64> buffer; std::array<yycc_char8_t, 64> buffer;
auto [ptr, ec] = std::to_chars(buffer.data(), buffer.data() + buffer.size(), num); auto [ptr, ec] = std::to_chars(
EncodingHelper::ToNative(buffer.data()),
EncodingHelper::ToNative(buffer.data() + buffer.size()),
num
);
if (ec == std::errc()) { if (ec == std::errc()) {
return std::string(buffer.data(), ptr - buffer.data()); return yycc_u8string(buffer.data(), ptr - buffer.data());
} else if (ec == std::errc::value_too_large) { } else if (ec == std::errc::value_too_large) {
// too short buffer // too short buffer
// this should not happend // this should not happend
@ -80,9 +92,9 @@ namespace YYCC::ParserHelper {
} }
} }
template<typename _Ty, std::enable_if_t<std::is_same_v<_Ty, bool>, int> = 0> template<typename _Ty, std::enable_if_t<std::is_same_v<_Ty, bool>, int> = 0>
std::string ToString(_Ty num) { yycc_u8string ToString(_Ty num) {
if (num) return std::string("true"); if (num) return yycc_u8string(YYCC_U8("true"));
else return std::string("false"); else return yycc_u8string(YYCC_U8("false"));
} }
} }

View File

@ -17,7 +17,7 @@ namespace YYCC::WinFctHelper {
return hModule; return hModule;
} }
bool GetTempDirectory(std::string& ret) { bool GetTempDirectory(yycc_u8string& ret) {
// create wchar buffer for receiving the temp path. // create wchar buffer for receiving the temp path.
std::wstring wpath(MAX_PATH + 1u, L'\0'); std::wstring wpath(MAX_PATH + 1u, L'\0');
DWORD expected_size; DWORD expected_size;
@ -41,10 +41,10 @@ namespace YYCC::WinFctHelper {
// resize result // resize result
wpath.resize(expected_size); wpath.resize(expected_size);
// convert to utf8 and return // convert to utf8 and return
return YYCC::EncodingHelper::WcharToUTF8(wpath.c_str(), ret); return YYCC::EncodingHelper::WcharToUTF8(wpath, ret);
} }
bool GetModuleFileName(HINSTANCE hModule, std::string& ret) { bool GetModuleFileName(HINSTANCE hModule, yycc_u8string& ret) {
// create wchar buffer for receiving the temp path. // create wchar buffer for receiving the temp path.
std::wstring wpath(MAX_PATH + 1u, L'\0'); std::wstring wpath(MAX_PATH + 1u, L'\0');
DWORD copied_size; DWORD copied_size;
@ -68,10 +68,13 @@ namespace YYCC::WinFctHelper {
// resize result // resize result
wpath.resize(copied_size); wpath.resize(copied_size);
// convert to utf8 and return // convert to utf8 and return
return YYCC::EncodingHelper::WcharToUTF8(wpath.c_str(), ret); return YYCC::EncodingHelper::WcharToUTF8(wpath, ret);
} }
bool GetLocalAppData(std::string& ret) { bool GetLocalAppData(yycc_u8string& ret) {
// check whether com initialized
if (!COMHelper::IsInitialized()) return false;
// fetch path // fetch path
LPWSTR _known_path; LPWSTR _known_path;
HRESULT hr = SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, NULL, &_known_path); HRESULT hr = SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, NULL, &_known_path);

View File

@ -36,7 +36,7 @@ namespace YYCC::WinFctHelper {
* The variable receiving UTF8 encoded path to Windows temp folder. * The variable receiving UTF8 encoded path to Windows temp folder.
* @return True if success, otherwise false. * @return True if success, otherwise false.
*/ */
bool GetTempDirectory(std::string& ret); bool GetTempDirectory(yycc_u8string& ret);
/** /**
* @brief Get the file name of given module HANDLE * @brief Get the file name of given module HANDLE
@ -47,7 +47,7 @@ namespace YYCC::WinFctHelper {
* The variable receiving UTF8 encoded file name of given module. * The variable receiving UTF8 encoded file name of given module.
* @return True if success, otherwise false. * @return True if success, otherwise false.
*/ */
bool GetModuleFileName(HINSTANCE hModule, std::string& ret); bool GetModuleFileName(HINSTANCE hModule, yycc_u8string& ret);
/** /**
* @brief Get the path to LOCALAPPDATA. * @brief Get the path to LOCALAPPDATA.
@ -56,7 +56,7 @@ namespace YYCC::WinFctHelper {
* The variable receiving UTF8 encoded path to LOCALAPPDATA. * The variable receiving UTF8 encoded path to LOCALAPPDATA.
* @return * @return
*/ */
bool GetLocalAppData(std::string& ret); bool GetLocalAppData(yycc_u8string& ret);
} }

View File

@ -8,7 +8,7 @@
#include "COMHelper.hpp" #include "COMHelper.hpp"
#include "DialogHelper.hpp" #include "DialogHelper.hpp"
#include "ParserHelper.hpp" #include "ParserHelper.hpp"
#include "ExceptionHelper.hpp"
#include "IOHelper.hpp" #include "IOHelper.hpp"
#include "WinFctHelper.hpp" #include "WinFctHelper.hpp"
#include "FsPathPatch.hpp" #include "FsPathPatch.hpp"
#include "ExceptionHelper.hpp"

View File

@ -23,12 +23,12 @@ namespace YYCCTestbench {
#define TEST_UNICODE_STR_EMOJI "\U0001F363 \u2716 \U0001F37A" // sushi x beer mug #define TEST_UNICODE_STR_EMOJI "\U0001F363 \u2716 \U0001F37A" // sushi x beer mug
#define CONCAT(prefix, strl) prefix ## strl #define CONCAT(prefix, strl) prefix ## strl
#define CPP_U8_LITERAL(strl) reinterpret_cast<const char*>(CONCAT(u8, strl)) #define CPP_U8_LITERAL(strl) YYCC_U8(strl)
#define CPP_U16_LITERAL(strl) CONCAT(u, strl) #define CPP_U16_LITERAL(strl) CONCAT(u, strl)
#define CPP_U32_LITERAL(strl) CONCAT(U, strl) #define CPP_U32_LITERAL(strl) CONCAT(U, strl)
#define CPP_WSTR_LITERAL(strl) CONCAT(L, strl) #define CPP_WSTR_LITERAL(strl) CONCAT(L, strl)
static std::vector<std::string> c_UTF8TestStrTable { static std::vector<YYCC::yycc_u8string> c_UTF8TestStrTable {
CPP_U8_LITERAL(TEST_UNICODE_STR_JAPAN), CPP_U8_LITERAL(TEST_UNICODE_STR_JAPAN),
CPP_U8_LITERAL(TEST_UNICODE_STR_CHINA), CPP_U8_LITERAL(TEST_UNICODE_STR_CHINA),
CPP_U8_LITERAL(TEST_UNICODE_STR_KOREA), CPP_U8_LITERAL(TEST_UNICODE_STR_KOREA),