fix: fix utf-8 output error.

- I figure out how UTF-8 output bug happend, but I don't have any clues proving why this happend.
	- it seems that we can simply remove utf8 string literal heading to solve this issue (u8"" -> "")
	- the compiled string char array in executable application already is wrong.
	- compiler generated string bytes is `'original string'.encode('utf-8').decode(your pc encoding).encode('utf-8')`.
	- idk why, as the compromise, I remove all utf8 string literal heading to solve this issue.
	- I highly think this is a bug of MSVC. because everything is okey if I use MSVC native project file to build.
	- I have compared the build flags between native project and cmake generated project but I can't find any difference.
- add full testbench code for ParserHelper.
This commit is contained in:
yyc12345 2024-05-30 14:53:46 +08:00
parent 5726c81fdb
commit e1e8a33c50
3 changed files with 53 additions and 13 deletions

View File

@ -77,7 +77,7 @@ namespace YYCC::DialogHelper {
return false; return false;
// convert pattern and join them // convert pattern and join them
std::string joined_modes(YYCC::StringHelper::Join(it.second, u8";")); std::string joined_modes(YYCC::StringHelper::Join(it.second, ";"));
WinFileFilters::WinFilterModes modes; WinFileFilters::WinFilterModes modes;
if (!YYCC::EncodingHelper::UTF8ToWchar(joined_modes.c_str(), modes)) if (!YYCC::EncodingHelper::UTF8ToWchar(joined_modes.c_str(), modes))
return false; return false;

View File

@ -57,7 +57,8 @@ namespace YYCC::ParserHelper {
return false; return false;
} }
} }
bool TryParse(const std::string& strl, bool& num) { template<typename _Ty, std::enable_if_t<std::is_same_v<_Ty, bool>, int> = 0>
bool TryParse(const std::string& strl, _Ty& num) {
if (strl == "true") num = true; if (strl == "true") num = true;
else if (strl == "false") num = false; else if (strl == "false") num = false;
else return false; else return false;

View File

@ -5,23 +5,23 @@ namespace Testbench {
static void Assert(bool condition, const char* description) { static void Assert(bool condition, const char* description) {
if (condition) { if (condition) {
YYCC::TerminalHelper::FPrintf(stdout, YYCC_TERMCOL_LIGHT_GREEN(u8"OK: %s\n"), description); YYCC::TerminalHelper::FPrintf(stdout, YYCC_TERMCOL_LIGHT_GREEN("OK: %s\n"), description);
} else { } else {
YYCC::TerminalHelper::FPrintf(stdout, YYCC_TERMCOL_LIGHT_RED(u8"Failed: %s\n"), description); YYCC::TerminalHelper::FPrintf(stdout, YYCC_TERMCOL_LIGHT_RED("Failed: %s\n"), description);
std::abort(); std::abort();
} }
} }
static void TerminalTestbench() { static void TerminalTestbench() {
YYCC::TerminalHelper::EnsureTerminalUTF8(stdout); YYCC::TerminalHelper::EnsureTerminalUTF8(stdout);
YYCC::TerminalHelper::FPuts(u8"你好世界\n", stdout); YYCC::TerminalHelper::FPuts("你好世界\n", stdout);
YYCC::TerminalHelper::EnsureTerminalColor(stdout); YYCC::TerminalHelper::EnsureTerminalColor(stdout);
YYCC::TerminalHelper::FPuts(YYCC_TERMCOL_LIGHT_CYAN(u8"Colorful Terminal\n"), stdout); YYCC::TerminalHelper::FPuts(YYCC_TERMCOL_LIGHT_CYAN("Colorful Terminal\n"), stdout);
} }
static void StringTestbench() { static void StringTestbench() {
auto test_printf = YYCC::StringHelper::Printf(u8"%s == %s", u8"Hello World", u8"你好世界"); auto test_printf = YYCC::StringHelper::Printf("%s == %s", "Hello World", "你好世界");
Assert(test_printf == u8"Hello World == 你好世界", "YYCC::StringHelper::Printf"); Assert(test_printf == "Hello World == 你好世界", "YYCC::StringHelper::Printf");
auto test_lower = YYCC::StringHelper::Lower("LOWER"); auto test_lower = YYCC::StringHelper::Lower("LOWER");
Assert(test_lower == "lower", "YYCC::StringHelper::Lower"); Assert(test_lower == "lower", "YYCC::StringHelper::Lower");
@ -54,6 +54,45 @@ namespace Testbench {
static void ParserTestbench() { static void ParserTestbench() {
// Test success TryParse
#define TEST_MACRO(type_t, value, string_value) { \
std::string cache_string(string_value); \
type_t cache; \
Assert(YYCC::ParserHelper::TryParse<type_t>(cache_string, cache) && cache == value, "YYCC::StringHelper::TryParse<" #type_t ">"); \
}
TEST_MACRO(int8_t, INT8_C(-61), "-61");
TEST_MACRO(uint8_t, UINT8_C(200), "200");
TEST_MACRO(int16_t, INT16_C(6161), "6161");
TEST_MACRO(uint16_t, UINT16_C(32800), "32800");
TEST_MACRO(int32_t, INT32_C(61616161), "61616161");
TEST_MACRO(uint32_t, UINT32_C(4294967293), "4294967293");
TEST_MACRO(int64_t, INT64_C(616161616161), "616161616161");
TEST_MACRO(uint64_t, UINT64_C(9223372036854775807), "9223372036854775807");
TEST_MACRO(bool, true, "true");
#undef TEST_MACRO
// Test failed TryParse
#define TEST_MACRO(type_t, value, string_value) { \
std::string cache_string(string_value); \
type_t cache; \
Assert(!YYCC::ParserHelper::TryParse<type_t>(cache_string, cache), "YYCC::StringHelper::TryParse<" #type_t ">"); \
}
TEST_MACRO(int8_t, INT8_C(-61), "6161");
TEST_MACRO(uint8_t, UINT8_C(200), "32800");
TEST_MACRO(int16_t, INT16_C(6161), "61616161");
TEST_MACRO(uint16_t, UINT16_C(32800), "4294967293");
TEST_MACRO(int32_t, INT32_C(61616161), "616161616161");
TEST_MACRO(uint32_t, UINT32_C(4294967293), "9223372036854775807");
TEST_MACRO(int64_t, INT64_C(616161616161), "616161616161616161616161");
TEST_MACRO(uint64_t, UINT64_C(9223372036854775807), "92233720368547758079223372036854775807");
TEST_MACRO(bool, true, "hello, world!");
#undef TEST_MACRO
// Test ToString
#define TEST_MACRO(type_t, value, string_value) { \ #define TEST_MACRO(type_t, value, string_value) { \
type_t cache = value; \ type_t cache = value; \
std::string ret(YYCC::ParserHelper::ToString<type_t>(cache)); \ std::string ret(YYCC::ParserHelper::ToString<type_t>(cache)); \
@ -91,20 +130,20 @@ namespace Testbench {
filters.Add("All Files (*.*)", {"*.*"}); filters.Add("All Files (*.*)", {"*.*"});
params.SetDefaultFileTypeIndex(0u); params.SetDefaultFileTypeIndex(0u);
if (YYCC::DialogHelper::OpenFileDialog(params, ret)) { if (YYCC::DialogHelper::OpenFileDialog(params, ret)) {
YYCC::TerminalHelper::FPrintf(stdout, u8"Open File: %s\n", ret.c_str()); YYCC::TerminalHelper::FPrintf(stdout, "Open File: %s\n", ret.c_str());
} }
if (YYCC::DialogHelper::OpenMultipleFileDialog(params, rets)) { if (YYCC::DialogHelper::OpenMultipleFileDialog(params, rets)) {
YYCC::TerminalHelper::FPuts(u8"Open Multiple Files:\n", stdout); YYCC::TerminalHelper::FPuts("Open Multiple Files:\n", stdout);
for (const auto& item : rets) { for (const auto& item : rets) {
YYCC::TerminalHelper::FPrintf(stdout, u8"\t%s\n", item.c_str()); YYCC::TerminalHelper::FPrintf(stdout, "\t%s\n", item.c_str());
} }
} }
if (YYCC::DialogHelper::SaveFileDialog(params, ret)) { if (YYCC::DialogHelper::SaveFileDialog(params, ret)) {
YYCC::TerminalHelper::FPrintf(stdout, u8"Save File: %s\n", ret.c_str()); YYCC::TerminalHelper::FPrintf(stdout, "Save File: %s\n", ret.c_str());
} }
params.Clear(); params.Clear();
if (YYCC::DialogHelper::OpenFolderDialog(params, ret)) { if (YYCC::DialogHelper::OpenFolderDialog(params, ret)) {
YYCC::TerminalHelper::FPrintf(stdout, u8"Open Folder: %s\n", ret.c_str()); YYCC::TerminalHelper::FPrintf(stdout, "Open Folder: %s\n", ret.c_str());
} }
} }