From c3c8b5048afdfd6a1ffbca56141596136de42db1 Mon Sep 17 00:00:00 2001 From: kdmcser Date: Sun, 20 Apr 2025 00:23:41 +0800 Subject: [PATCH] extract functions of string <-> boost::filesystem::path to TextOperations.h --- lib/filesystem/CFilesystemLoader.cpp | 16 +++------------- lib/mapping/CMapInfo.cpp | 8 +------- lib/texts/TextOperations.cpp | 18 ++++++++++++++++++ lib/texts/TextOperations.h | 7 +++++++ 4 files changed, 29 insertions(+), 20 deletions(-) diff --git a/lib/filesystem/CFilesystemLoader.cpp b/lib/filesystem/CFilesystemLoader.cpp index 0346292c7..34f09f1d8 100644 --- a/lib/filesystem/CFilesystemLoader.cpp +++ b/lib/filesystem/CFilesystemLoader.cpp @@ -13,8 +13,7 @@ #include "CFileInputStream.h" #include "../ExceptionsCommon.h" - -#include +#include "../texts/TextOperations.h" VCMI_LIB_NAMESPACE_BEGIN @@ -93,11 +92,7 @@ bool CFilesystemLoader::createResource(const std::string & requestedFilename, bo } filename = filename.substr(mountPoint.size()); -#ifdef VCMI_WINDOWS - boost::filesystem::path filePath(boost::locale::conv::utf_to_utf(filename)); -#else - boost::filesystem::path filePath(filename.string()); -#endif + boost::filesystem::path filePath = TextOperations::Utf8TofilesystemPath(filename); if (!update) { @@ -180,12 +175,7 @@ std::unordered_map CFilesystemLoader::lis filename = it->path().filename(); std::string resName; - -#ifdef VCMI_WINDOWS - std::string filenameUtf8 = boost::locale::conv::utf_to_utf(filename.native()); -#else - std::string filenameUtf8 = filename.string(); -#endif + std::string filenameUtf8 = TextOperations::filesystemPathToUtf8(filename); if (boost::filesystem::path::preferred_separator != '/') { diff --git a/lib/mapping/CMapInfo.cpp b/lib/mapping/CMapInfo.cpp index 1c7bf5f15..75f9ef6d0 100644 --- a/lib/mapping/CMapInfo.cpp +++ b/lib/mapping/CMapInfo.cpp @@ -27,8 +27,6 @@ #include "../IGameSettings.h" #include "../CConfigHandler.h" - #include - VCMI_LIB_NAMESPACE_BEGIN CMapInfo::CMapInfo() @@ -45,11 +43,7 @@ CMapInfo::~CMapInfo() std::string CMapInfo::getFullFileURI(const ResourcePath & file) const { auto path = boost::filesystem::canonical(*CResourceHandler::get()->getResourceName(file)); -#ifdef VCMI_WINDOWS - return boost::locale::conv::utf_to_utf(path.native()); -#else - return path.string(); -#endif + return TextOperations::filesystemPathToUtf8(path); } void CMapInfo::mapInit(const std::string & fname) diff --git a/lib/texts/TextOperations.cpp b/lib/texts/TextOperations.cpp index 7c17562b2..f2502dca2 100644 --- a/lib/texts/TextOperations.cpp +++ b/lib/texts/TextOperations.cpp @@ -405,4 +405,22 @@ std::optional TextOperations::textSearchSimilarityScore(const std::string & return (minDist > maxAllowedDistance) ? std::nullopt : std::optional{ minDist }; } +std::string TextOperations::filesystemPathToUtf8(const boost::filesystem::path& path) +{ +#ifdef VCMI_WINDOWS + return boost::locale::conv::utf_to_utf(path.native()); +#else + return path.string(); +#endif +} + +boost::filesystem::path TextOperations::Utf8TofilesystemPath(const std::string& path) +{ +#ifdef VCMI_WINDOWS + return boost::filesystem::path(boost::locale::conv::utf_to_utf(path)); +#else + return boost::filesystem::path(path.string()); +#endif +} + VCMI_LIB_NAMESPACE_END diff --git a/lib/texts/TextOperations.h b/lib/texts/TextOperations.h index 9bdc8fdd2..63933ae56 100644 --- a/lib/texts/TextOperations.h +++ b/lib/texts/TextOperations.h @@ -84,6 +84,13 @@ namespace TextOperations /// other values = Levenshtein distance, returns std::nullopt for unrelated word (bad match). DLL_LINKAGE std::optional textSearchSimilarityScore(const std::string & s, const std::string & t); + /// This function is mainly used to avoid garbled text when reading or writing files + /// with non-ASCII (e.g. Chinese) characters in the path, especially on Windows. + /// Call this before passing the path to file I/O functions that take std::string. + DLL_LINKAGE std::string filesystemPathToUtf8(const boost::filesystem::path& path); + + // Used for handling paths with non-ASCII characters. + DLL_LINKAGE boost::filesystem::path Utf8TofilesystemPath(const std::string& path); }; template