From e1e8a33c505d437c29b9e39dc749301b1a62f4fc Mon Sep 17 00:00:00 2001 From: yyc12345 Date: Thu, 30 May 2024 14:53:46 +0800 Subject: [PATCH] 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. --- src/DialogHelper.cpp | 2 +- src/ParserHelper.hpp | 3 ++- testbench/main.cpp | 61 ++++++++++++++++++++++++++++++++++++-------- 3 files changed, 53 insertions(+), 13 deletions(-) diff --git a/src/DialogHelper.cpp b/src/DialogHelper.cpp index 7c37bc0..995f0e2 100644 --- a/src/DialogHelper.cpp +++ b/src/DialogHelper.cpp @@ -77,7 +77,7 @@ namespace YYCC::DialogHelper { return false; // 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; if (!YYCC::EncodingHelper::UTF8ToWchar(joined_modes.c_str(), modes)) return false; diff --git a/src/ParserHelper.hpp b/src/ParserHelper.hpp index e9aff72..062679c 100644 --- a/src/ParserHelper.hpp +++ b/src/ParserHelper.hpp @@ -57,7 +57,8 @@ namespace YYCC::ParserHelper { return false; } } - bool TryParse(const std::string& strl, bool& num) { + template, int> = 0> + bool TryParse(const std::string& strl, _Ty& num) { if (strl == "true") num = true; else if (strl == "false") num = false; else return false; diff --git a/testbench/main.cpp b/testbench/main.cpp index e0d7e8b..aff8989 100644 --- a/testbench/main.cpp +++ b/testbench/main.cpp @@ -5,23 +5,23 @@ namespace Testbench { static void Assert(bool condition, const char* description) { 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 { - 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(); } } static void TerminalTestbench() { YYCC::TerminalHelper::EnsureTerminalUTF8(stdout); - YYCC::TerminalHelper::FPuts(u8"你好世界\n", stdout); + YYCC::TerminalHelper::FPuts("你好世界\n", 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() { - auto test_printf = YYCC::StringHelper::Printf(u8"%s == %s", u8"Hello World", u8"你好世界"); - Assert(test_printf == u8"Hello World == 你好世界", "YYCC::StringHelper::Printf"); + auto test_printf = YYCC::StringHelper::Printf("%s == %s", "Hello World", "你好世界"); + Assert(test_printf == "Hello World == 你好世界", "YYCC::StringHelper::Printf"); auto test_lower = YYCC::StringHelper::Lower("LOWER"); Assert(test_lower == "lower", "YYCC::StringHelper::Lower"); @@ -54,6 +54,45 @@ namespace Testbench { 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(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(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) { \ type_t cache = value; \ std::string ret(YYCC::ParserHelper::ToString(cache)); \ @@ -91,20 +130,20 @@ namespace Testbench { filters.Add("All Files (*.*)", {"*.*"}); params.SetDefaultFileTypeIndex(0u); 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)) { - YYCC::TerminalHelper::FPuts(u8"Open Multiple Files:\n", stdout); + YYCC::TerminalHelper::FPuts("Open Multiple Files:\n", stdout); 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)) { - 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(); 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()); } }