From 09a5ac476132db5334d48af34af10e18960f95f0 Mon Sep 17 00:00:00 2001 From: tomcw Date: Fri, 25 Sep 2020 18:17:03 +0100 Subject: [PATCH] libyaml supports UTF-8 and not accented ANSI characters - so convert to UTF-8 (Fixes GH#838) --- source/YamlHelper.cpp | 53 ++++++++++++++++++++++++++++++++++++++++--- source/YamlHelper.h | 1 + 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/source/YamlHelper.cpp b/source/YamlHelper.cpp index 5198e33d..e00b6038 100644 --- a/source/YamlHelper.cpp +++ b/source/YamlHelper.cpp @@ -57,8 +57,10 @@ void YamlHelper::GetNextEvent(bool bInMap /*= false*/) { if (!yaml_parser_parse(&m_parser, &m_newEvent)) { - //printf("Parser error %d\n", m_parser.error); - throw std::string("Parser error"); + std::string error = std::string("Save-state parser error: "); + if (m_parser.problem != NULL) error += std::string(m_parser.problem); + else error += std::string("unknown"); + throw error; } } @@ -451,7 +453,52 @@ void YamlSaveHelper::SaveBool(const char* key, bool value) void YamlSaveHelper::SaveString(const char* key, const char* value) { - Save("%s: %s\n", key, (value[0] != 0) ? value : "\"\""); + if (value[0] == 0) + value = "\"\""; + + LPWSTR pWcStr = NULL; + LPSTR pMbStr = NULL; + + // libyaml supports UTF-8 and not accented ANSI characters (GH#838) + // . So convert ANSI to UTF-8, which is a 2-step process: + + // 1) ANSI -> unicode + { + int wcStrSize = MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, value, -1, NULL, 0); + if (wcStrSize == 0) + { + delete[] pWcStr; delete[] pMbStr; + throw std::string("Unable to convert to unicode: ") + std::string(value); + } + pWcStr = new WCHAR[wcStrSize]; + int res = MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, value, -1, pWcStr, wcStrSize); + if (!res) + { + delete[] pWcStr; delete[] pMbStr; + throw std::string("Unable to convert to unicode: ") + std::string(value); + } + } + + // 2) unicode -> UTF-8 + { + // NB. WC_ERR_INVALID_CHARS only defined when WIN_VER >= 0x600 - but stdafx.h defines it as 0x500 + int mbStrSize = WideCharToMultiByte(CP_UTF8, 0/*WC_ERR_INVALID_CHARS*/, pWcStr, -1, NULL, 0, NULL, NULL); + if (mbStrSize == 0) + { + delete[] pWcStr; delete[] pMbStr; + throw std::string("Unable to convert to UTF-8: ") + std::string(value); + } + pMbStr = new char[mbStrSize]; + int res = WideCharToMultiByte(CP_UTF8, 0/*WC_ERR_INVALID_CHARS*/, pWcStr, -1, pMbStr, mbStrSize, NULL, NULL); + if (!res) + { + delete [] pWcStr; delete [] pMbStr; + throw std::string("Unable to convert to UTF-8: ") + std::string(value); + } + } + + Save("%s: %s\n", key, pMbStr); + delete[] pWcStr; delete[] pMbStr; } void YamlSaveHelper::SaveString(const char* key, const std::string & value) diff --git a/source/YamlHelper.h b/source/YamlHelper.h index 5b46f2ef..a809afbe 100644 --- a/source/YamlHelper.h +++ b/source/YamlHelper.h @@ -29,6 +29,7 @@ public: YamlHelper(void) : m_hFile(NULL) { + memset(&m_parser, 0, sizeof(m_parser)); MakeAsciiToHexTable(); }