From a13709c510bb1224eb4ad2743cec420c443b4989 Mon Sep 17 00:00:00 2001 From: Project579 Date: Sun, 3 Jul 2022 00:02:29 +0200 Subject: [PATCH] Replace implicit convertions from std::filesystem::path to std::string with correctly converting functions. --- apps/bsatool/bsatool.cpp | 21 +++--- apps/bulletobjecttool/main.cpp | 3 +- apps/esmtool/esmtool.cpp | 13 ++-- apps/esmtool/tes4.cpp | 2 +- apps/launcher/datafilespage.cpp | 8 +-- apps/launcher/maindialog.cpp | 32 ++++----- apps/launcher/settingspage.cpp | 8 +-- apps/mwiniimporter/importer.cpp | 3 +- apps/navmeshtool/main.cpp | 5 +- apps/niftest/niftest.cpp | 7 +- apps/opencs/editor.cpp | 2 +- apps/opencs/editor.hpp | 2 +- apps/opencs/model/doc/blacklist.cpp | 2 +- apps/opencs/model/doc/document.cpp | 17 ++--- apps/opencs/model/doc/loader.cpp | 4 +- apps/opencs/model/doc/runner.cpp | 11 ++- apps/opencs/model/doc/runner.hpp | 4 +- apps/opencs/model/doc/savingstages.cpp | 5 +- apps/opencs/model/world/commanddispatcher.cpp | 4 +- apps/opencs/model/world/regionmap.cpp | 4 +- apps/opencs/model/world/scriptcontext.cpp | 4 +- apps/opencs/view/doc/adjusterwidget.cpp | 12 ++-- apps/opencs/view/doc/loader.cpp | 2 +- apps/opencs/view/doc/view.cpp | 3 +- apps/opencs/view/doc/viewmanager.cpp | 2 +- apps/opencs/view/tools/merge.cpp | 4 +- apps/openmw/engine.cpp | 20 +++--- apps/openmw/mwgui/savegamedialog.cpp | 3 +- apps/openmw/mwinput/bindingsmanager.cpp | 5 +- apps/openmw/mwinput/controllermanager.cpp | 6 +- apps/openmw/mwrender/postprocessor.cpp | 11 +-- apps/openmw/mwrender/water.cpp | 6 +- apps/openmw/mwscript/miscextensions.cpp | 3 +- apps/openmw/mwscript/scriptmanagerimp.cpp | 2 +- apps/openmw/mwstate/statemanagerimp.cpp | 7 +- apps/openmw/mwworld/esmloader.cpp | 7 +- apps/openmw/mwworld/worldimp.cpp | 13 ++-- apps/openmw_test_suite/files/hash.cpp | 9 +-- apps/openmw_test_suite/mwworld/test_store.cpp | 5 +- apps/openmw_test_suite/openmw/options.cpp | 67 ++++++++++--------- .../shader/shadermanager.cpp | 21 +++--- apps/openmw_test_suite/testing_util.hpp | 3 +- apps/wizard/installationtargetpage.cpp | 4 +- apps/wizard/mainwizard.cpp | 2 +- components/CMakeLists.txt | 2 +- components/bsa/bsa_file.cpp | 2 +- components/bsa/bsa_file.hpp | 3 +- components/bsa/compressedbsafile.cpp | 48 ++++++------- components/bsa/compressedbsafile.hpp | 2 +- components/config/gamesettings.cpp | 4 +- components/config/launchersettings.cpp | 2 +- .../crashcatcher/windows_crashcatcher.cpp | 2 +- components/debug/debugging.cpp | 6 +- components/debug/debuglog.cpp | 3 +- components/detournavigator/navigator.cpp | 3 +- components/esm3/esmreader.cpp | 5 +- components/esm3/loadcell.cpp | 2 +- components/esm4/reader.cpp | 10 +-- components/esmloader/load.cpp | 3 +- components/files/collections.cpp | 12 ++-- components/files/collections.hpp | 4 +- components/files/configurationmanager.cpp | 25 ------- components/files/configurationmanager.hpp | 10 --- components/files/conversion.cpp | 29 ++++++++ components/files/conversion.hpp | 18 +++++ components/files/hash.cpp | 3 +- components/files/linuxpath.cpp | 4 +- components/files/multidircollection.cpp | 12 ++-- components/files/openfile.cpp | 3 +- components/fx/technique.cpp | 8 ++- components/fx/technique.hpp | 2 +- components/lua/luastate.cpp | 3 +- components/lua/storage.cpp | 4 +- components/myguiplatform/myguidatamanager.cpp | 3 +- components/myguiplatform/myguiloglistener.cpp | 2 +- components/nif/niffile.cpp | 2 +- components/nifbullet/bulletnifloader.cpp | 3 +- components/nifosg/nifloader.cpp | 54 +++++++-------- components/resource/scenemanager.cpp | 5 +- components/sceneutil/screencapture.cpp | 3 +- components/settings/parser.cpp | 2 +- components/settings/shadermanager.hpp | 5 +- components/shader/shadermanager.cpp | 4 +- components/version/version.cpp | 2 +- components/version/version.hpp | 2 +- components/vfs/filesystemarchive.cpp | 9 +-- components/vfs/manager.cpp | 10 +-- components/vfs/registerarchives.cpp | 4 +- 88 files changed, 394 insertions(+), 328 deletions(-) create mode 100644 components/files/conversion.cpp create mode 100644 components/files/conversion.hpp diff --git a/apps/bsatool/bsatool.cpp b/apps/bsatool/bsatool.cpp index 6313b92e95..26fa981cb3 100644 --- a/apps/bsatool/bsatool.cpp +++ b/apps/bsatool/bsatool.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #define BSATOOL_VERSION 1.1 @@ -179,17 +180,17 @@ int list(std::unique_ptr& bsa, Arguments& info) template int extract(std::unique_ptr& bsa, Arguments& info) { - std::string archivePath = info.extractfile.string(); //TODO(Project579): This will probably break in windows with unicode paths - Misc::StringUtils::replaceAll(archivePath, "/", "\\"); + auto archivePath = info.extractfile.u8string(); + Misc::StringUtils::replaceAll(archivePath, u8"/", u8"\\"); - std::string extractPath = info.extractfile.string(); //TODO(Project579): This will probably break in windows with unicode paths - Misc::StringUtils::replaceAll(extractPath, "\\", "/"); + auto extractPath = info.extractfile.u8string(); + Misc::StringUtils::replaceAll(extractPath, u8"\\", u8"/"); Files::IStreamPtr stream; // Get a stream for the file to extract for (auto it = bsa->getList().rbegin(); it != bsa->getList().rend(); ++it) { - if (Misc::StringUtils::ciEqual(std::string(it->name()), archivePath)) + if (Misc::StringUtils::ciEqual(Misc::StringUtils::stringToU8String(it->name()), archivePath)) { stream = bsa->getFile(&*it); break; @@ -197,8 +198,8 @@ int extract(std::unique_ptr& bsa, Arguments& info) } if (!stream) { - std::cout << "ERROR: file '" << archivePath << "' not found\n"; - std::cout << "In archive: " << info.filename << std::endl; + std::cout << "ERROR: file '" << Misc::StringUtils::u8StringToString(archivePath) << "' not found\n"; + std::cout << "In archive: " << Files::pathToUnicodeString(info.filename) << std::endl; return 3; } @@ -217,14 +218,14 @@ int extract(std::unique_ptr& bsa, Arguments& info) std::filesystem::file_status s = std::filesystem::status(target.parent_path()); if (!std::filesystem::is_directory(s)) { - std::cout << "ERROR: " << target.parent_path() << " is not a directory." << std::endl; + std::cout << "ERROR: " << Files::pathToUnicodeString(target.parent_path()) << " is not a directory." << std::endl; return 3; } std::ofstream out(target, std::ios::binary); // Write the file to disk - std::cout << "Extracting " << info.extractfile << " to " << target << std::endl; //TODO(Project579): This will probably break in windows with unicode paths + std::cout << "Extracting " << Files::pathToUnicodeString(info.extractfile) << " to " << Files::pathToUnicodeString(target) << std::endl; out << stream->rdbuf(); out.close(); @@ -271,7 +272,7 @@ template int add(std::unique_ptr& bsa, Arguments& info) { std::fstream stream(info.addfile, std::ios_base::binary | std::ios_base::out | std::ios_base::in); - bsa->addFile(info.addfile.string(), stream); //TODO(Project579): This will probably break in windows with unicode paths + bsa->addFile(Files::pathToUnicodeString(info.addfile), stream); return 0; } diff --git a/apps/bulletobjecttool/main.cpp b/apps/bulletobjecttool/main.cpp index 6f9e7ac376..5acd57dbb1 100644 --- a/apps/bulletobjecttool/main.cpp +++ b/apps/bulletobjecttool/main.cpp @@ -33,7 +33,6 @@ namespace namespace bpo = boost::program_options; using StringsVector = std::vector; - using PathsVector = std::vector; bpo::options_description makeOptionsDescription() { @@ -146,7 +145,7 @@ namespace const auto fsStrict = variables["fs-strict"].as(); const auto resDir = variables["resources"].as(); - Version::Version v = Version::getOpenmwVersion(resDir); + const auto v = Version::getOpenmwVersion(resDir); Log(Debug::Info) << v.describe(); dataDirs.insert(dataDirs.begin(), resDir / "vfs"); const auto fileCollections = Files::Collections(dataDirs, !fsStrict); diff --git a/apps/esmtool/esmtool.cpp b/apps/esmtool/esmtool.cpp index f95777d0ef..74e471b948 100644 --- a/apps/esmtool/esmtool.cpp +++ b/apps/esmtool/esmtool.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include "record.hpp" #include "labels.hpp" @@ -288,7 +289,7 @@ void loadCell(const Arguments& info, ESM::Cell &cell, ESM::ESMReader &esm, ESMDa void printRawTes3(const std::filesystem::path &path) { - std::cout << "TES3 RAW file listing: " << path << '\n'; //TODO(Project579): This will probably break in windows with unicode paths + std::cout << "TES3 RAW file listing: " << path << '\n'; ESM::ESMReader esm; esm.openRaw(path); while(esm.hasMoreRecs()) @@ -312,7 +313,7 @@ void printRawTes3(const std::filesystem::path &path) int loadTes3(const Arguments& info, std::unique_ptr&& stream, ESMData* data) { - std::cout << "Loading TES3 file: " << info.filename << '\n'; //TODO(Project579): This will probably break in windows with unicode paths + std::cout << "Loading TES3 file: " << info.filename << '\n'; ESM::ESMReader esm; ToUTF8::Utf8Encoder encoder (ToUTF8::calculateEncoding(info.encoding)); @@ -421,7 +422,7 @@ int load(const Arguments& info, ESMData* data) printRawTes3(info.filename); break; case ESM::Format::Tes4: - std::cout << "Printing raw TES4 file is not supported: " << info.filename << "\n"; //TODO(Project579): This will probably break in windows with unicode paths + std::cout << "Printing raw TES4 file is not supported: " << Files::pathToUnicodeString(info.filename) << "\n"; break; } return 0; @@ -492,7 +493,7 @@ int clone(const Arguments& info) if (i % 3 != 0) std::cout << '\n'; - std::cout << "\nSaving records to: " << info.outname << "...\n"; //TODO(Project579): This will probably break in windows with unicode paths + std::cout << "\nSaving records to: " << Files::pathToUnicodeString(info.outname) << "...\n"; ESM::ESMWriter esm; ToUTF8::Utf8Encoder encoder (ToUTF8::calculateEncoding(info.encoding)); @@ -565,14 +566,14 @@ int comp(const Arguments& info) ESMData dataOne; if (load(fileOne, &dataOne) != 0) { - std::cout << "Failed to load " << info.filename << ", aborting comparison." << std::endl; //TODO(Project579): This will probably break in windows with unicode paths + std::cout << "Failed to load " << Files::pathToUnicodeString(info.filename) << ", aborting comparison." << std::endl; return 1; } ESMData dataTwo; if (load(fileTwo, &dataTwo) != 0) { - std::cout << "Failed to load " << info.outname << ", aborting comparison." << std::endl; //TODO(Project579): This will probably break in windows with unicode paths + std::cout << "Failed to load " << Files::pathToUnicodeString(info.outname) << ", aborting comparison." << std::endl; return 1; } diff --git a/apps/esmtool/tes4.cpp b/apps/esmtool/tes4.cpp index 02e722631d..815eb6dd34 100644 --- a/apps/esmtool/tes4.cpp +++ b/apps/esmtool/tes4.cpp @@ -289,7 +289,7 @@ namespace EsmTool int loadTes4(const Arguments& info, std::unique_ptr&& stream) { - std::cout << "Loading TES4 file: " << info.filename << '\n'; //TODO(Project579): This will probably break in windows with unicode paths + std::cout << "Loading TES4 file: " << info.filename << '\n'; try { diff --git a/apps/launcher/datafilespage.cpp b/apps/launcher/datafilespage.cpp index d5f2259f2e..3495d04502 100644 --- a/apps/launcher/datafilespage.cpp +++ b/apps/launcher/datafilespage.cpp @@ -230,9 +230,9 @@ void Launcher::DataFilesPage::populateFileViews(const QString& contentModelName) if (!mDataLocal.isEmpty()) directories.insert(0, mDataLocal); - const auto globalDataDir = QString(mGameSettings.getGlobalDataDir().string().c_str()); //TODO(Project579): This will probably break in windows with unicode paths - if (!globalDataDir.isEmpty()) - directories.insert(0, globalDataDir); + const auto& globalDataDir = mGameSettings.getGlobalDataDir(); + if (!globalDataDir.empty()) + directories.insert(0, QString::fromStdWString(globalDataDir.wstring())); // normalize user supplied directories: resolve symlink, convert to native separator, make absolute for (auto& currentDir : directories) @@ -264,7 +264,7 @@ void Launcher::DataFilesPage::populateFileViews(const QString& contentModelName) } // deactivate data-local and global data directory: they are always included - if (currentDir == mDataLocal || currentDir == globalDataDir) + if (currentDir == mDataLocal || std::filesystem::path(currentDir.toStdWString()) == globalDataDir) { auto flags = item->flags(); item->setFlags(flags & ~(Qt::ItemIsDragEnabled|Qt::ItemIsDropEnabled|Qt::ItemIsEnabled)); diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index 447dcb5193..7b5fbe5c4c 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -12,6 +12,7 @@ #include #include +#include #include "playpage.hpp" #include "graphicspage.hpp" @@ -155,14 +156,14 @@ Launcher::FirstRunDialogResult Launcher::MainDialog::showFirstRunDialog() return FirstRunDialogResultFailure; // Dialog wizard and setup will fail if the config directory does not already exist - QDir userConfigDir = QDir(QString::fromStdString(mCfgMgr.getUserConfigPath().string())); //TODO(Project579): This will probably break in windows with unicode paths, in Qt 6 it's possible to convert directly from std::filesystem::path to QDir and that would solve the issue - if ( ! userConfigDir.exists() ) { - if ( ! userConfigDir.mkpath(".") ) + const auto& userConfigDir = mCfgMgr.getUserConfigPath(); + if ( ! exists(userConfigDir) ) { + if ( ! create_directory(userConfigDir) ) { cfgError(tr("Error opening OpenMW configuration file"), tr("
Could not create directory %0

\ Please make sure you have the right permissions \ - and try again.
").arg(userConfigDir.canonicalPath()) + and try again.
").arg(QString::fromStdWString(canonical(userConfigDir).wstring())) ); return FirstRunDialogResultFailure; } @@ -295,7 +296,7 @@ bool Launcher::MainDialog::setupLauncherSettings() mLauncherSettings.setMultiValueEnabled(true); - QString userPath = QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str()); //TODO(Project579): This will probably break in windows with unicode paths + QString userPath = QString::fromStdWString(mCfgMgr.getUserConfigPath().wstring()); QStringList paths; paths.append(QString(Config::LauncherSettings::sLauncherConfigFileName)); @@ -328,9 +329,9 @@ bool Launcher::MainDialog::setupGameSettings() { mGameSettings.clear(); - QString localPath = QString::fromUtf8(mCfgMgr.getLocalPath().string().c_str()); //TODO(Project579): This will probably break in windows with unicode paths - QString userPath = QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str()); //TODO(Project579): This will probably break in windows with unicode paths - QString globalPath = QString::fromUtf8(mCfgMgr.getGlobalPath().string().c_str()); //TODO(Project579): This will probably break in windows with unicode paths + QString localPath = QString::fromStdWString(mCfgMgr.getLocalPath().wstring()); + QString userPath = QString::fromStdWString(mCfgMgr.getUserConfigPath().wstring()); + QString globalPath = QString::fromStdWString(mCfgMgr.getGlobalPath().wstring()); QFile file; @@ -479,21 +480,20 @@ bool Launcher::MainDialog::writeSettings() mSettingsPage->saveSettings(); mAdvancedPage->saveSettings(); - QString userPath = QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str()); //TODO(Project579): This will probably break in windows with unicode paths - QDir dir(userPath); + const auto& userPath = mCfgMgr.getUserConfigPath(); - if (!dir.exists()) { - if (!dir.mkpath(userPath)) { + if (!exists(userPath)) { + if (!create_directory(userPath)) { cfgError(tr("Error creating OpenMW configuration directory"), tr("
Could not create %0

\ Please make sure you have the right permissions \ - and try again.
").arg(userPath)); + and try again.
").arg(QString::fromStdWString(userPath.wstring()))); return false; } } // Game settings - QFile file(userPath + QString("openmw.cfg")); + QFile file(QString::fromStdWString((userPath / "openmw.cfg").wstring())); if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) { // File cannot be opened or created @@ -515,13 +515,13 @@ bool Launcher::MainDialog::writeSettings() } catch (std::exception& e) { std::string msg = "
Error writing settings.cfg

" + - settingsPath.string() + "

" + e.what(); //TODO(Project579): This will probably break in windows with unicode paths + Files::pathToUnicodeString(settingsPath) + "

" + e.what(); cfgError(tr("Error writing user settings file"), tr(msg.c_str())); return false; } // Launcher settings - file.setFileName(userPath + QString(Config::LauncherSettings::sLauncherConfigFileName)); + file.setFileName(QString::fromStdWString((userPath / Config::LauncherSettings::sLauncherConfigFileName).wstring())); if (!file.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate)) { // File cannot be opened or created diff --git a/apps/launcher/settingspage.cpp b/apps/launcher/settingspage.cpp index 77d45e48ec..1a9670a292 100644 --- a/apps/launcher/settingspage.cpp +++ b/apps/launcher/settingspage.cpp @@ -102,9 +102,9 @@ void Launcher::SettingsPage::on_importerButton_clicked() mMain->writeSettings(); // Create the file if it doesn't already exist, else the importer will fail - QString path(QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str())); //TODO(Project579): This will probably break in windows with unicode paths - path.append(QLatin1String("openmw.cfg")); - QFile file(path); + auto path = mCfgMgr.getUserConfigPath(); + path /= "openmw.cfg"; + QFile file(QString::fromStdWString(path.wstring())); if (!file.exists()) { if (!file.open(QIODevice::ReadWrite)) { @@ -137,7 +137,7 @@ void Launcher::SettingsPage::on_importerButton_clicked() arguments.append(QString("--ini")); arguments.append(settingsComboBox->currentText()); arguments.append(QString("--cfg")); - arguments.append(path); + arguments.append(QString::fromStdWString(path.wstring())); qDebug() << "arguments " << arguments; diff --git a/apps/mwiniimporter/importer.cpp b/apps/mwiniimporter/importer.cpp index 912aa2d5ed..ed962c4c5f 100644 --- a/apps/mwiniimporter/importer.cpp +++ b/apps/mwiniimporter/importer.cpp @@ -8,6 +8,7 @@ #include #include #include +#include @@ -944,7 +945,7 @@ void MwIniImporter::importGameFiles(multistrmap &cfg, const multistrmap &ini, co { dependencies.push_back(gameFile.name); } - unsortedFiles.emplace_back(reader.getName().filename().string(), dependencies); //TODO(Project579): This will probably break in windows with unicode paths + unsortedFiles.emplace_back(Files::pathToUnicodeString(reader.getName().filename()), dependencies); reader.close(); } diff --git a/apps/navmeshtool/main.cpp b/apps/navmeshtool/main.cpp index 21751dca79..3d80454499 100644 --- a/apps/navmeshtool/main.cpp +++ b/apps/navmeshtool/main.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include @@ -179,9 +180,9 @@ namespace NavMeshTool const osg::Vec3f agentHalfExtents = Settings::Manager::getVector3("default actor pathfind half extents", "Game"); const DetourNavigator::AgentBounds agentBounds {agentCollisionShape, agentHalfExtents}; const std::uint64_t maxDbFileSize = static_cast(Settings::Manager::getInt64("max navmeshdb file size", "Navigator")); - const auto dbPath = config.getUserDataPath() / "navmesh.db"; + const auto dbPath = Files::pathToUnicodeString(config.getUserDataPath() / "navmesh.db"); - DetourNavigator::NavMeshDb db(dbPath.string(), maxDbFileSize); //TODO(Project579): This will probably break in windows with unicode paths + DetourNavigator::NavMeshDb db(dbPath, maxDbFileSize); ESM::ReadersCache readers; EsmLoader::Query query; diff --git a/apps/niftest/niftest.cpp b/apps/niftest/niftest.cpp index 68d5a0f898..4919b923c9 100644 --- a/apps/niftest/niftest.cpp +++ b/apps/niftest/niftest.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include @@ -19,7 +20,7 @@ namespace bpo = boost::program_options; ///See if the file has the named extension bool hasExtension(const std::filesystem::path& filename, const std::string& extensionToFind) { - std::string extension = filename.extension().string(); //TODO(Project579): let's hope unicode characters are never used in these extensions on windows or this will break + const auto extension = Files::pathToUnicodeString(filename.extension()); return Misc::StringUtils::ciEqual(extension, extensionToFind); } @@ -42,7 +43,7 @@ void readVFS(std::unique_ptr&& anArchive, const std::filesystem::p myManager.addArchive(std::move(anArchive)); myManager.buildIndex(); - for(const auto& name : myManager.getRecursiveDirectoryIterator("")) //TODO(Project579): This will probably break in windows with unicode paths + for(const auto& name : myManager.getRecursiveDirectoryIterator("")) { try{ if(isNIF(name)) @@ -142,7 +143,7 @@ int main(int argc, char **argv) } else { - std::cerr << "ERROR: \"" << path << "\" is not a nif file, bsa file, or directory!" << std::endl; //TODO(Project579): This will probably break in windows with unicode paths + std::cerr << "ERROR: \"" << Files::pathToUnicodeString(path) << "\" is not a nif file, bsa file, or directory!" << std::endl; } } catch (std::exception& e) diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index 8dee97bd46..669fa83a4c 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -393,7 +393,7 @@ int CS::Editor::run() } discoveredFiles.push_back(mFileToLoad); - QString extension = QString::fromStdString(mFileToLoad.extension().string()).toLower(); //TODO(Project579): let's hope unicode characters are never used in these extensions on windows or this will break + QString extension = QString::fromStdWString(mFileToLoad.extension().wstring()).toLower(); if (extension == ".esm") { mFileToLoad.replace_extension(".omwgame"); diff --git a/apps/opencs/editor.hpp b/apps/opencs/editor.hpp index 26f45744c6..c9dba37193 100644 --- a/apps/opencs/editor.hpp +++ b/apps/opencs/editor.hpp @@ -89,7 +89,7 @@ namespace CS void cancelFileDialog(); void loadDocument(); - void openFiles (const std::filesystem::path &path, const std::vector &discoveredFiles = std::vector()); + void openFiles (const std::filesystem::path &path, const std::vector &discoveredFiles = {}); void createNewFile (const std::filesystem::path& path); void createNewGame (const std::filesystem::path& file); diff --git a/apps/opencs/model/doc/blacklist.cpp b/apps/opencs/model/doc/blacklist.cpp index 49db56f7f4..cd96618288 100644 --- a/apps/opencs/model/doc/blacklist.cpp +++ b/apps/opencs/model/doc/blacklist.cpp @@ -25,6 +25,6 @@ void CSMDoc::Blacklist::add (CSMWorld::UniversalId::Type type, list.resize (size+ids.size()); - std::transform (ids.begin(), ids.end(), list.begin()+size, Misc::StringUtils::lowerCase); + std::transform (ids.begin(), ids.end(), list.begin()+size, [](const std::string& s) { return Misc::StringUtils::lowerCase(s); } ); std::sort (list.begin(), list.end()); } diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 9a93430dc6..779c9431d1 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "../world/defaultgmsts.hpp" @@ -13,7 +14,7 @@ #endif #include -#include +#include void CSMDoc::Document::addGmsts() { @@ -294,11 +295,11 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, if (mNew || !std::filesystem::exists (mProjectPath)) { - std::filesystem::path filtersPath (configuration.getUserDataPath() / "defaultfilters"); + auto filtersPath = configuration.getUserDataPath() / "defaultfilters"; std::ofstream destination(mProjectPath, std::ios::out | std::ios::binary); if (!destination.is_open()) - throw std::runtime_error("Can not create project file: " + mProjectPath.string()); //TODO(Project579): This will probably break in windows with unicode paths + throw std::runtime_error("Can not create project file: " + Files::pathToUnicodeString(mProjectPath)); destination.exceptions(std::ios::failbit | std::ios::badbit); if (!std::filesystem::exists (filtersPath)) @@ -306,7 +307,7 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, std::ifstream source(filtersPath, std::ios::in | std::ios::binary); if (!source.is_open()) - throw std::runtime_error("Can not read filters file: " + filtersPath.string()); //TODO(Project579): This will probably break in windows with unicode paths + throw std::runtime_error("Can not read filters file: " + Files::pathToUnicodeString(filtersPath)); source.exceptions(std::ios::failbit | std::ios::badbit); destination << source.rdbuf(); @@ -480,11 +481,11 @@ bool CSMDoc::Document::isBlacklisted (const CSMWorld::UniversalId& id) void CSMDoc::Document::startRunning (const std::string& profile, const std::string& startupInstruction) { - std::vector contentFiles; + std::vector contentFiles; - for (std::vector::const_iterator iter (mContentFiles.begin()); - iter!=mContentFiles.end(); ++iter) - contentFiles.push_back (iter->filename().string()); //TODO(Project579): let's hope unicode characters are never used in these filenames on windows or this will break + for (const auto & mContentFile : mContentFiles) { + contentFiles.emplace_back(mContentFile.filename()); + } mRunner.configure (getData().getDebugProfiles().getRecord (profile).get(), contentFiles, startupInstruction); diff --git a/apps/opencs/model/doc/loader.cpp b/apps/opencs/model/doc/loader.cpp index 70d114c47e..a851707811 100644 --- a/apps/opencs/model/doc/loader.cpp +++ b/apps/opencs/model/doc/loader.cpp @@ -1,5 +1,7 @@ #include "loader.hpp" +#include + #include #include "../tools/reportmodel.hpp" @@ -93,7 +95,7 @@ void CSMDoc::Loader::load() iter->second.mRecordsLeft = true; iter->second.mRecordsLoaded = 0; - emit nextStage (document, path.filename().string(), steps); //TODO(Project579): let's hope unicode characters are never used in these filenames on windows or this will break + emit nextStage (document, Files::pathToUnicodeString(path.filename()), steps); } else if (iter->second.mFile==size) // start loading the last (project) file { diff --git a/apps/opencs/model/doc/runner.cpp b/apps/opencs/model/doc/runner.cpp index c1db116a52..2b16ea3eff 100644 --- a/apps/opencs/model/doc/runner.cpp +++ b/apps/opencs/model/doc/runner.cpp @@ -83,18 +83,17 @@ void CSMDoc::Runner::start (bool delayed) arguments << ("--script-run="+mStartup->fileName()); arguments << - QString::fromUtf8 (("--data=\""+mProjectPath.parent_path().string()+"\"").c_str()); //TODO(Project579): This will probably break in windows with unicode paths + QString::fromStdWString (L"--data=\""+mProjectPath.parent_path().wstring()+L"\""); arguments << "--replace=content"; - for (std::vector::const_iterator iter (mContentFiles.begin()); - iter!=mContentFiles.end(); ++iter) + for (const auto & mContentFile : mContentFiles) { - arguments << QString::fromUtf8 (("--content="+*iter).c_str()); + arguments << QString::fromStdWString (L"--content="+mContentFile.wstring()); } arguments - << QString::fromUtf8 (("--content="+mProjectPath.filename().string()).c_str()); //TODO(Project579): let's hope unicode characters are never used in these filenames on windows or this will break + << QString::fromStdWString (L"--content="+mProjectPath.filename().wstring()); mProcess.start (path, arguments); } @@ -123,7 +122,7 @@ bool CSMDoc::Runner::isRunning() const } void CSMDoc::Runner::configure (const ESM::DebugProfile& profile, - const std::vector& contentFiles, const std::string& startupInstruction) + const std::vector &contentFiles, const std::string& startupInstruction) { mProfile = profile; mContentFiles = contentFiles; diff --git a/apps/opencs/model/doc/runner.hpp b/apps/opencs/model/doc/runner.hpp index fcc12d2f0e..c3ef4477c3 100644 --- a/apps/opencs/model/doc/runner.hpp +++ b/apps/opencs/model/doc/runner.hpp @@ -25,7 +25,7 @@ namespace CSMDoc QProcess mProcess; bool mRunning; ESM::DebugProfile mProfile; - std::vector mContentFiles; + std::vector mContentFiles; std::string mStartupInstruction; QTemporaryFile *mStartup; QTextDocument mLog; @@ -48,7 +48,7 @@ namespace CSMDoc bool isRunning() const; void configure (const ESM::DebugProfile& profile, - const std::vector& contentFiles, + const std::vector &contentFiles, const std::string& startupInstruction); QTextDocument *getLog(); diff --git a/apps/opencs/model/doc/savingstages.cpp b/apps/opencs/model/doc/savingstages.cpp index 20f3ca4ba6..841c930cf0 100644 --- a/apps/opencs/model/doc/savingstages.cpp +++ b/apps/opencs/model/doc/savingstages.cpp @@ -4,6 +4,7 @@ #include #include +#include #include "../world/infocollection.hpp" #include "../world/cellcoordinates.hpp" @@ -72,8 +73,8 @@ void CSMDoc::WriteHeaderStage::perform (int stage, Messages& messages) for (std::vector::const_iterator iter (dependencies.begin()); iter!=end; ++iter) { - std::string name = iter->filename().string(); //TODO(Project579): let's hope unicode characters are never used in these filenames on windows or this will break - uint64_t size = std::filesystem::file_size (*iter); + auto name = Files::pathToUnicodeString(iter->filename()); + auto size = std::filesystem::file_size (*iter); mState.getWriter().addMaster (name, size); } diff --git a/apps/opencs/model/world/commanddispatcher.cpp b/apps/opencs/model/world/commanddispatcher.cpp index 96b8ac6297..00d949f450 100644 --- a/apps/opencs/model/world/commanddispatcher.cpp +++ b/apps/opencs/model/world/commanddispatcher.cpp @@ -95,7 +95,9 @@ void CSMWorld::CommandDispatcher::setEditLock (bool locked) void CSMWorld::CommandDispatcher::setSelection (const std::vector& selection) { mSelection = selection; - std::for_each (mSelection.begin(), mSelection.end(), Misc::StringUtils::lowerCaseInPlace); + for (auto& sel : mSelection) { + Misc::StringUtils::lowerCaseInPlace(sel); + } std::sort (mSelection.begin(), mSelection.end()); } diff --git a/apps/opencs/model/world/regionmap.cpp b/apps/opencs/model/world/regionmap.cpp index de1c34a5cc..910572af91 100644 --- a/apps/opencs/model/world/regionmap.cpp +++ b/apps/opencs/model/world/regionmap.cpp @@ -169,7 +169,9 @@ void CSMWorld::RegionMap::updateRegions (const std::vector& regions { std::vector regions2 (regions); - std::for_each (regions2.begin(), regions2.end(), Misc::StringUtils::lowerCaseInPlace); + for (auto& region2 : regions2) { + Misc::StringUtils::lowerCaseInPlace(region2); + } std::sort (regions2.begin(), regions2.end()); for (std::map::const_iterator iter (mMap.begin()); diff --git a/apps/opencs/model/world/scriptcontext.cpp b/apps/opencs/model/world/scriptcontext.cpp index 0bf7de9d95..1088a58a00 100644 --- a/apps/opencs/model/world/scriptcontext.cpp +++ b/apps/opencs/model/world/scriptcontext.cpp @@ -94,7 +94,9 @@ bool CSMWorld::ScriptContext::isId (const std::string& name) const { mIds = mData.getIds(); - std::for_each (mIds.begin(), mIds.end(), &Misc::StringUtils::lowerCaseInPlace); + for (auto& id : mIds) { + Misc::StringUtils::lowerCaseInPlace(id); + } std::sort (mIds.begin(), mIds.end()); mIdsUpdated = true; diff --git a/apps/opencs/view/doc/adjusterwidget.cpp b/apps/opencs/view/doc/adjusterwidget.cpp index 0e6ae73fe6..6eb479d694 100644 --- a/apps/opencs/view/doc/adjusterwidget.cpp +++ b/apps/opencs/view/doc/adjusterwidget.cpp @@ -68,12 +68,12 @@ void CSVDoc::AdjusterWidget::setName (const QString& name, bool addon) } else { - std::filesystem::path path (name.toUtf8().data()); //TODO(Project579): Replace with char8_t in C++20 + std::filesystem::path path (name.toStdWString()); - std::string extension = Misc::StringUtils::lowerCase(path.extension().string()); //TODO(Project579): let's hope unicode characters are never used in these extensions on windows or this will break + const auto extension = Misc::StringUtils::lowerCase(path.extension().u8string()); - bool isLegacyPath = (extension == ".esm" || - extension == ".esp"); + bool isLegacyPath = (extension == u8".esm" || + extension == u8".esp"); bool isFilePathChanged = (path.parent_path() != mLocalData); @@ -85,7 +85,7 @@ void CSVDoc::AdjusterWidget::setName (const QString& name, bool addon) if (!isFilePathChanged && !isLegacyPath) { // path already points to the local data directory - message = QString::fromUtf8 (("Will be saved as: " + path.string()).c_str()); //TODO(Project579): This is probably broken on windows with unicode paths + message = QString::fromStdWString (L"Will be saved as: " + path.wstring()); mResultPath = path; } //in all other cases, ensure the path points to data-local and do an existing file check @@ -95,7 +95,7 @@ void CSVDoc::AdjusterWidget::setName (const QString& name, bool addon) if (isFilePathChanged) path = mLocalData / path.filename(); - message = QString::fromUtf8 (("Will be saved as: " + path.string()).c_str()); //TODO(Project579): This is probably broken on windows with unicode paths + message = QString::fromStdWString (L"Will be saved as: " + path.wstring()); mResultPath = path; if (std::filesystem::exists (path)) diff --git a/apps/opencs/view/doc/loader.cpp b/apps/opencs/view/doc/loader.cpp index 188827db2f..ffd1d66756 100644 --- a/apps/opencs/view/doc/loader.cpp +++ b/apps/opencs/view/doc/loader.cpp @@ -19,7 +19,7 @@ void CSVDoc::LoadingDocument::closeEvent (QCloseEvent *event) CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document) : mDocument (document), mTotalRecordsLabel (0), mRecordsLabel (0), mAborted (false), mMessages (nullptr), mRecords(0) { - setWindowTitle (QString::fromUtf8((std::string("Opening ") + document->getSavePath().filename().string()).c_str())); //TODO(Project579): let's hope unicode characters are never used in these filenames on windows or this will break + setWindowTitle (QString::fromStdWString(L"Opening " + document->getSavePath().filename().wstring())); setMinimumWidth (400); diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index eaeb6d3957..e47ce65654 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -30,6 +30,7 @@ #include #include +#include #include "viewmanager.hpp" #include "operations.hpp" @@ -387,7 +388,7 @@ void CSVDoc::View::updateTitle() { std::ostringstream stream; - stream << mDocument->getSavePath().filename().string(); //TODO(Project579): let's hope unicode characters are never used in these filenames on windows or this will break + stream << Files::pathToUnicodeString(mDocument->getSavePath().filename()); if (mDocument->getState() & CSMDoc::State_Modified) stream << " *"; diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 92144ca668..71e8987bb1 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -261,7 +261,7 @@ bool CSVDoc::ViewManager::showModifiedDocumentMessageBox (CSVDoc::View *view) QMessageBox messageBox(view); CSMDoc::Document *document = view->getDocument(); - messageBox.setWindowTitle (QString::fromUtf8(document->getSavePath().filename().string().c_str())); //TODO(Project579): let's hope unicode characters are never used in these filenames on windows or this will break + messageBox.setWindowTitle (QString::fromStdWString(document->getSavePath().filename().wstring())); messageBox.setText ("The document has been modified."); messageBox.setInformativeText ("Do you want to save your changes?"); messageBox.setStandardButtons (QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); diff --git a/apps/opencs/view/tools/merge.cpp b/apps/opencs/view/tools/merge.cpp index 0efce2aec3..6c4d076849 100644 --- a/apps/opencs/view/tools/merge.cpp +++ b/apps/opencs/view/tools/merge.cpp @@ -102,7 +102,7 @@ void CSVTools::Merge::configure (CSMDoc::Document *document) for (std::vector::const_iterator iter (files.begin()); iter!=files.end(); ++iter) - mFiles->addItem (QString::fromUtf8 (iter->filename().string().c_str())); //TODO(Project579): let's hope unicode characters are never used in these filenames on windows or this will break + mFiles->addItem (QString::fromStdWString(iter->filename().wstring())); } void CSVTools::Merge::setLocalData (const std::filesystem::path& localData) @@ -125,7 +125,7 @@ void CSVTools::Merge::accept() { if ((mDocument->getState() & CSMDoc::State_Merging)==0) { - std::vector< std::filesystem::path > files (1, mAdjuster->getPath()); + std::vector< std::filesystem::path > files { mAdjuster->getPath() }; std::unique_ptr target ( mDocumentManager.makeDocument (files, files[0], true)); diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 22cd339b36..163fb31ccd 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -711,7 +711,7 @@ void OMW::Engine::setWindowIcon() const auto windowIcon = mResDir / "openmw.png"; windowIconStream.open(windowIcon, std::ios_base::in | std::ios_base::binary); if (windowIconStream.fail()) - Log(Debug::Error) << "Error: Failed to open " << windowIcon; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Error) << "Error: Failed to open " << windowIcon; osgDB::ReaderWriter* reader = osgDB::Registry::instance()->getReaderWriterForExtension("png"); if (!reader) { @@ -720,7 +720,7 @@ void OMW::Engine::setWindowIcon() } osgDB::ReaderWriter::ReadResult result = reader->readImage(windowIconStream); if (!result.success()) - Log(Debug::Error) << "Error: Failed to read " << windowIcon << ": " << result.message() << " code " << result.status(); //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Error) << "Error: Failed to read " << windowIcon << ": " << result.message() << " code " << result.status(); else { osg::ref_ptr image = result.getImage(); @@ -790,11 +790,11 @@ void OMW::Engine::prepareEngine() const auto input2 = (mCfgMgr.getUserConfigPath() / "input_v2.xml"); if(std::filesystem::exists(input2)) { keybinderUserExists = std::filesystem::copy_file(input2, keybinderUser); - Log(Debug::Info) << "Loading keybindings file: " << keybinderUser; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Info) << "Loading keybindings file: " << keybinderUser; } } else - Log(Debug::Info) << "Loading keybindings file: " << keybinderUser; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Info) << "Loading keybindings file: " << keybinderUser; const auto userdefault = mCfgMgr.getUserConfigPath() / "gamecontrollerdb.txt"; const auto localdefault = mCfgMgr.getLocalPath() / "gamecontrollerdb.txt"; @@ -1032,13 +1032,17 @@ void OMW::Engine::go() prepareEngine(); std::ofstream stats; - if (const auto path = std::getenv("OPENMW_OSG_STATS_FILE")) //TODO(Project579): This will probably break in windows with unicode paths +#ifdef _WIN32 + if (const auto path = std::filesystem::path{_wgetenv(L"OPENMW_OSG_STATS_FILE")}; !path.empty()) +#else + if (const auto path = std::filesystem::path{std::getenv("OPENMW_OSG_STATS_FILE")}; !path.empty()) +#endif { - stats.open(path, std::ios_base::out); //TODO(Project579): This will probably break in windows with unicode paths + stats.open(path, std::ios_base::out); if (stats.is_open()) - Log(Debug::Info) << "Stats will be written to: " << path; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Info) << "Stats will be written to: " << path; else - Log(Debug::Warning) << "Failed to open file for stats: " << path; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Warning) << "Failed to open file for stats: " << path; } // Setup profiler diff --git a/apps/openmw/mwgui/savegamedialog.cpp b/apps/openmw/mwgui/savegamedialog.cpp index 69082bd6bb..ebf22b5c83 100644 --- a/apps/openmw/mwgui/savegamedialog.cpp +++ b/apps/openmw/mwgui/savegamedialog.cpp @@ -21,6 +21,7 @@ #include #include +#include #include @@ -200,7 +201,7 @@ namespace MWGui if (mCurrentCharacter == &*it || (!mCurrentCharacter && !mSaving && directory==Misc::StringUtils::lowerCase ( - it->begin()->mPath.parent_path().filename().string()))) //TODO(Project579): let's hope unicode characters are never used in these filenames on windows or this will break + Files::pathToUnicodeString(it->begin()->mPath.parent_path().filename())))) { mCurrentCharacter = &*it; selectedIndex = mCharacterSelection->getItemCount()-1; diff --git a/apps/openmw/mwinput/bindingsmanager.cpp b/apps/openmw/mwinput/bindingsmanager.cpp index 376a8a145f..c799056f45 100644 --- a/apps/openmw/mwinput/bindingsmanager.cpp +++ b/apps/openmw/mwinput/bindingsmanager.cpp @@ -6,6 +6,7 @@ #include #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/inputmanager.hpp" @@ -44,7 +45,7 @@ namespace MWInput { public: InputControlSystem(const std::filesystem::path &bindingsFile) - : ICS::InputControlSystem(bindingsFile.string(), true, nullptr, nullptr, A_Last) //TODO(Project579): This is probably broken on windows with unicode paths + : ICS::InputControlSystem(Files::pathToUnicodeString(bindingsFile), true, nullptr, nullptr, A_Last) { } }; @@ -192,7 +193,7 @@ namespace MWInput BindingsManager::~BindingsManager() { - mInputBinder->save(mUserFile.string()); //TODO(Project579): This will probably break in windows with unicode paths + mInputBinder->save(Files::pathToUnicodeString(mUserFile)); } void BindingsManager::update(float dt) diff --git a/apps/openmw/mwinput/controllermanager.cpp b/apps/openmw/mwinput/controllermanager.cpp index c95a924280..96d14a3720 100644 --- a/apps/openmw/mwinput/controllermanager.cpp +++ b/apps/openmw/mwinput/controllermanager.cpp @@ -7,6 +7,8 @@ #include #include +#include +#include #include "../mwbase/environment.hpp" #include "../mwbase/inputmanager.hpp" @@ -43,12 +45,12 @@ namespace MWInput { if (!controllerBindingsFile.empty()) { - SDL_GameControllerAddMappingsFromFile(controllerBindingsFile.string().c_str()); //TODO(Project579): This will probably break in windows with unicode paths + SDL_GameControllerAddMappingsFromFile(Files::pathToUnicodeString(controllerBindingsFile).c_str()); } if (!userControllerBindingsFile.empty()) { - SDL_GameControllerAddMappingsFromFile(userControllerBindingsFile.string().c_str()); //TODO(Project579): This will probably break in windows with unicode paths + SDL_GameControllerAddMappingsFromFile(Files::pathToUnicodeString(userControllerBindingsFile).c_str()); } // Open all presently connected sticks diff --git a/apps/openmw/mwrender/postprocessor.cpp b/apps/openmw/mwrender/postprocessor.cpp index be84d8fdff..555baa7efe 100644 --- a/apps/openmw/mwrender/postprocessor.cpp +++ b/apps/openmw/mwrender/postprocessor.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include "../mwbase/world.hpp" #include "../mwbase/environment.hpp" @@ -217,12 +218,12 @@ namespace MWRender { for (const auto& name : mVFS->getRecursiveDirectoryIterator(fx::Technique::sSubdir)) { - std::filesystem::path path = name; - std::string fileExt = Misc::StringUtils::lowerCase(path.extension().string()); //TODO(Project579): let's hope unicode characters are never used in these extensions on windows or this will break + std::filesystem::path path = Files::pathFromUnicodeString(name); + std::string fileExt = Misc::StringUtils::lowerCase(Files::pathToUnicodeString(path.extension())); if (!path.parent_path().has_parent_path() && fileExt == fx::Technique::sExt) { - const auto absolutePath = mVFS->getAbsoluteFileName(name); //TODO(Project579): let's hope unicode characters are never used in these filenames on windows or this will break - mTechniqueFileMap[absolutePath.stem().string()] = absolutePath; //TODO(Project579): This will probably break in windows with unicode paths + const auto absolutePath = mVFS->getAbsoluteFileName(path); + mTechniqueFileMap[Files::pathToUnicodeString(absolutePath.stem())] = absolutePath; } } } @@ -387,7 +388,7 @@ namespace MWRender std::this_thread::sleep_for(std::chrono::milliseconds(5)); if (technique->compile()) - Log(Debug::Info) << "Reloaded technique : " << mTechniqueFileMap[technique->getName()].string(); //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Info) << "Reloaded technique : " << mTechniqueFileMap[technique->getName()]; mReload = technique->isValid(); } diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 8ad7997c2e..d57fbe731e 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -243,16 +243,16 @@ osg::ref_ptr readPngImage (const std::filesystem::path& file) std::ifstream inStream; inStream.open(file, std::ios_base::in | std::ios_base::binary); if (inStream.fail()) - Log(Debug::Error) << "Error: Failed to open " << file; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Error) << "Error: Failed to open " << file; osgDB::ReaderWriter* reader = osgDB::Registry::instance()->getReaderWriterForExtension("png"); if (!reader) { - Log(Debug::Error) << "Error: Failed to read " << file << ", no png readerwriter found"; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Error) << "Error: Failed to read " << file << ", no png readerwriter found"; return osg::ref_ptr(); } osgDB::ReaderWriter::ReadResult result = reader->readImage(inStream); if (!result.success()) - Log(Debug::Error) << "Error: Failed to read " << file << ": " << result.message() << " code " << result.status(); //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Error) << "Error: Failed to read " << file << ": " << result.message() << " code " << result.status(); return result.getImage(); } diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index eb82eb9d2e..24c9542d64 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -24,6 +24,7 @@ #include #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/windowmanager.hpp" @@ -1528,7 +1529,7 @@ namespace MWScript else { const auto filename = MWBase::Environment::get().getWorld()->exportSceneGraph(ptr); - runtime.getContext().report("Wrote '" + filename.string() + "'"); //TODO(Project579): This will probably break in windows with unicode paths + runtime.getContext().report("Wrote '" + Files::pathToUnicodeString(filename) + "'"); } } }; diff --git a/apps/openmw/mwscript/scriptmanagerimp.cpp b/apps/openmw/mwscript/scriptmanagerimp.cpp index 7a22cda8b1..35593efcba 100644 --- a/apps/openmw/mwscript/scriptmanagerimp.cpp +++ b/apps/openmw/mwscript/scriptmanagerimp.cpp @@ -35,7 +35,7 @@ namespace MWScript mScriptBlacklist.resize (scriptBlacklist.size()); std::transform (scriptBlacklist.begin(), scriptBlacklist.end(), - mScriptBlacklist.begin(), Misc::StringUtils::lowerCase); + mScriptBlacklist.begin(), [](const std::string& s) { return Misc::StringUtils::lowerCase(s); }); std::sort (mScriptBlacklist.begin(), mScriptBlacklist.end()); } diff --git a/apps/openmw/mwstate/statemanagerimp.cpp b/apps/openmw/mwstate/statemanagerimp.cpp index 3142b495a4..814535489e 100644 --- a/apps/openmw/mwstate/statemanagerimp.cpp +++ b/apps/openmw/mwstate/statemanagerimp.cpp @@ -13,6 +13,7 @@ #include #include +#include #include @@ -305,7 +306,7 @@ void MWState::StateManager::saveGame (const std::string& description, const Slot throw std::runtime_error("Write operation failed (file stream)"); Settings::Manager::setString ("character", "Saves", - slot->mPath.parent_path().filename().string()); //TODO(Project579): let's hope unicode characters are never used in these filenames on windows or this will break + Files::pathToUnicodeString(slot->mPath.parent_path().filename())); const auto finish = std::chrono::steady_clock::now(); @@ -388,7 +389,7 @@ void MWState::StateManager::loadGame (const Character *character, const std::fil { cleanup(); - Log(Debug::Info) << "Reading save file " << filepath.filename(); //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Info) << "Reading save file " << filepath.filename(); ESM::ESMReader reader; reader.open (filepath); @@ -521,7 +522,7 @@ void MWState::StateManager::loadGame (const Character *character, const std::fil if (character) Settings::Manager::setString ("character", "Saves", - character->getPath().filename().string()); //TODO(Project579): let's hope unicode characters are never used in these filenames on windows or this will break + Files::pathToUnicodeString(character->getPath().filename())); MWBase::Environment::get().getWindowManager()->setNewGame(false); MWBase::Environment::get().getWorld()->saveLoaded(); diff --git a/apps/openmw/mwworld/esmloader.cpp b/apps/openmw/mwworld/esmloader.cpp index 861401d60e..66dd5b856e 100644 --- a/apps/openmw/mwworld/esmloader.cpp +++ b/apps/openmw/mwworld/esmloader.cpp @@ -3,6 +3,7 @@ #include #include +#include namespace MWWorld { @@ -28,7 +29,7 @@ void EsmLoader::load(const std::filesystem::path& filepath, int& index, Loading: assert(reader->getGameFiles().size() == reader->getParentFileIndices().size()); for (std::size_t i = 0, n = reader->getParentFileIndices().size(); i < n; ++i) if (i == static_cast(reader->getIndex())) - throw std::runtime_error("File " + reader->getName().string() + " asks for parent file " //TODO(Project579): This will probably break in windows with unicode paths + throw std::runtime_error("File " + Files::pathToUnicodeString(reader->getName()) + " asks for parent file " + reader->getGameFiles()[i].name + ", but it is not available or has been loaded in the wrong order. " "Please run the launcher to fix this issue."); @@ -36,8 +37,8 @@ void EsmLoader::load(const std::filesystem::path& filepath, int& index, Loading: mESMVersions[index] = reader->getVer(); mStore.load(*reader, listener, mDialogue); - if (!mMasterFileFormat.has_value() && (Misc::StringUtils::ciEndsWith(reader->getName().string(), ".esm") //TODO(Project579): This will probably break in windows with unicode paths - || Misc::StringUtils::ciEndsWith(reader->getName().string(), ".omwgame"))) //TODO(Project579): This will probably break in windows with unicode paths + if (!mMasterFileFormat.has_value() && (Misc::StringUtils::ciEndsWith(reader->getName().u8string(), u8".esm") + || Misc::StringUtils::ciEndsWith(reader->getName().u8string(), u8".omwgame"))) mMasterFileFormat = reader->getFormat(); } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index b0828fd69a..ed19b352d2 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -44,6 +44,7 @@ #include #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/soundmanager.hpp" @@ -104,19 +105,19 @@ namespace MWWorld void load(const std::filesystem::path& filepath, int& index, Loading::Listener* listener) override { - const auto it = mLoaders.find(Misc::StringUtils::lowerCase(filepath.extension().string())); //TODO(Project579): let's hope unicode characters are never used in these extensions on windows or this will break + const auto it = mLoaders.find(Misc::StringUtils::lowerCase( Files::pathToUnicodeString(filepath.extension()))); if (it != mLoaders.end()) { - const std::string filename = filepath.filename().string(); //TODO(Project579): let's hope unicode characters are never used in these filenames on windows or this will break + const auto filename = filepath.filename(); Log(Debug::Info) << "Loading content file " << filename; if (listener != nullptr) - listener->setLabel(MyGUI::TextIterator::toTagsString(filename)); + listener->setLabel(MyGUI::TextIterator::toTagsString(Files::pathToUnicodeString(filename))); it->second->load(filepath, index, listener); } else { std::string msg("Cannot load file: "); - msg += filepath.string(); //TODO(Project579): This will probably break in windows with unicode paths + msg += Files::pathToUnicodeString(filepath); throw std::runtime_error(msg.c_str()); } } @@ -2963,8 +2964,8 @@ namespace MWWorld int idx = 0; for (const std::string &file : content) { - std::filesystem::path filename(file); - const Files::MultiDirCollection& col = fileCollections.getCollection(filename.extension().string()); //TODO(Project579): let's hope unicode characters are never used in these extensions on windows or this will break + const auto filename = Files::pathFromUnicodeString( file); + const Files::MultiDirCollection& col = fileCollections.getCollection(Files::pathToUnicodeString(filename.extension())); if (col.doesExist(file)) { gameContentLoader.load(col.getPath(file), idx, listener); diff --git a/apps/openmw_test_suite/files/hash.cpp b/apps/openmw_test_suite/files/hash.cpp index dcace6b34e..ab18d20be7 100644 --- a/apps/openmw_test_suite/files/hash.cpp +++ b/apps/openmw_test_suite/files/hash.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -50,11 +51,11 @@ namespace std::replace(fileName.begin(), fileName.end(), '/', '_'); std::string content; std::fill_n(std::back_inserter(content), GetParam().mSize, 'a'); - fileName = outputFilePath(fileName).string(); //TODO(Project579): This will probably break in windows with unicode paths - std::fstream(fileName, std::ios_base::out | std::ios_base::binary) + const auto file = outputFilePath(fileName); + std::fstream(file, std::ios_base::out | std::ios_base::binary) .write(content.data(), static_cast(content.size())); - const auto stream = Files::openConstrainedFileStream(fileName, 0, content.size()); //TODO(Project579): This will probably break in windows with unicode paths - EXPECT_EQ(getHash(fileName, *stream), GetParam().mHash); + const auto stream = Files::openConstrainedFileStream(file, 0, content.size()); + EXPECT_EQ(getHash(file, *stream), GetParam().mHash); } INSTANTIATE_TEST_SUITE_P(Params, FilesGetHash, Values( diff --git a/apps/openmw_test_suite/mwworld/test_store.cpp b/apps/openmw_test_suite/mwworld/test_store.cpp index ba0abd293d..d3c7176540 100644 --- a/apps/openmw_test_suite/mwworld/test_store.cpp +++ b/apps/openmw_test_suite/mwworld/test_store.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include "apps/openmw/mwworld/esmstore.hpp" #include "apps/openmw/mwmechanics/spelllist.hpp" @@ -124,7 +125,7 @@ TEST_F(ContentFileTest, dialogue_merging_test) stream << std::endl; } - std::cout << "dialogue_merging_test successful, results printed to " << file << std::endl; //TODO(Project579): This will probably break in windows with unicode paths + std::cout << "dialogue_merging_test successful, results printed to " << Files::pathToUnicodeString(file) << std::endl; } // Note: here we don't test records that don't use string names (e.g. Land, Pathgrid, Cell) @@ -194,7 +195,7 @@ TEST_F(ContentFileTest, content_diagnostics_test) RUN_TEST_FOR_TYPES(printRecords, mEsmStore, stream); - std::cout << "diagnostics_test successful, results printed to " << file << std::endl; //TODO(Project579): This will probably break in windows with unicode paths + std::cout << "diagnostics_test successful, results printed to " << Files::pathToUnicodeString(file) << std::endl; } // TODO: diff --git a/apps/openmw_test_suite/openmw/options.cpp b/apps/openmw_test_suite/openmw/options.cpp index 33c38da5df..06b848dd16 100644 --- a/apps/openmw_test_suite/openmw/options.cpp +++ b/apps/openmw_test_suite/openmw/options.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -38,7 +39,7 @@ namespace return result; } - MATCHER_P(IsPath, v, "") { return arg.string() == v; } + MATCHER_P(IsPath, v, "") { return Files::pathToUnicodeString(arg) == v; } template void parseArgs(const T& arguments, bpo::variables_map& variables, bpo::options_description& description) @@ -52,7 +53,7 @@ namespace const std::array arguments {"openmw", "--load-savegame=save.omwsave"}; bpo::variables_map variables; parseArgs(arguments, variables, description); - EXPECT_EQ(variables["load-savegame"].as().string(), "save.omwsave"); + EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as()), "save.omwsave"); } TEST(OpenMWOptionsFromArguments, should_support_single_word_load_savegame_path) @@ -61,7 +62,7 @@ namespace const std::array arguments {"openmw", "--load-savegame", "save.omwsave"}; bpo::variables_map variables; parseArgs(arguments, variables, description); - EXPECT_EQ(variables["load-savegame"].as().string(), "save.omwsave"); + EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as()), "save.omwsave"); } TEST(OpenMWOptionsFromArguments, should_support_multi_component_load_savegame_path) @@ -70,7 +71,7 @@ namespace const std::array arguments {"openmw", "--load-savegame", "/home/user/openmw/save.omwsave"}; bpo::variables_map variables; parseArgs(arguments, variables, description); - EXPECT_EQ(variables["load-savegame"].as().string(), "/home/user/openmw/save.omwsave"); + EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as()), "/home/user/openmw/save.omwsave"); } TEST(OpenMWOptionsFromArguments, should_support_windows_multi_component_load_savegame_path) @@ -79,7 +80,7 @@ namespace const std::array arguments {"openmw", "--load-savegame", R"(C:\OpenMW\save.omwsave)"}; bpo::variables_map variables; parseArgs(arguments, variables, description); - EXPECT_EQ(variables["load-savegame"].as().string(), R"(C:\OpenMW\save.omwsave)"); + EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as()), R"(C:\OpenMW\save.omwsave)"); } TEST(OpenMWOptionsFromArguments, should_support_load_savegame_path_with_spaces) @@ -88,7 +89,7 @@ namespace const std::array arguments {"openmw", "--load-savegame", "my save.omwsave"}; bpo::variables_map variables; parseArgs(arguments, variables, description); - EXPECT_EQ(variables["load-savegame"].as().string(), "my save.omwsave"); + EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as()), "my save.omwsave"); } TEST(OpenMWOptionsFromArguments, should_support_load_savegame_path_with_octothorpe) @@ -97,7 +98,7 @@ namespace const std::array arguments {"openmw", "--load-savegame", "my#save.omwsave"}; bpo::variables_map variables; parseArgs(arguments, variables, description); - EXPECT_EQ(variables["load-savegame"].as().string(), "my#save.omwsave"); + EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as()), "my#save.omwsave"); } TEST(OpenMWOptionsFromArguments, should_support_load_savegame_path_with_at_sign) @@ -106,7 +107,7 @@ namespace const std::array arguments {"openmw", "--load-savegame", "my@save.omwsave"}; bpo::variables_map variables; parseArgs(arguments, variables, description); - EXPECT_EQ(variables["load-savegame"].as().string(), "my@save.omwsave"); + EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as()), "my@save.omwsave"); } TEST(OpenMWOptionsFromArguments, should_support_load_savegame_path_with_quote) @@ -115,7 +116,7 @@ namespace const std::array arguments {"openmw", "--load-savegame", R"(my"save.omwsave)"}; bpo::variables_map variables; parseArgs(arguments, variables, description); - EXPECT_EQ(variables["load-savegame"].as().string(), R"(my"save.omwsave)"); + EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as()), R"(my"save.omwsave)"); } TEST(OpenMWOptionsFromArguments, should_support_quoted_load_savegame_path) @@ -124,7 +125,7 @@ namespace const std::array arguments {"openmw", "--load-savegame", R"("save".omwsave)"}; bpo::variables_map variables; parseArgs(arguments, variables, description); - EXPECT_EQ(variables["load-savegame"].as().string(), R"(save)"); + EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as()), R"(save)"); } TEST(OpenMWOptionsFromArguments, should_support_quoted_load_savegame_path_with_escaped_quote_by_ampersand) @@ -133,7 +134,7 @@ namespace const std::array arguments {"openmw", "--load-savegame", R"("save&".omwsave")"}; bpo::variables_map variables; parseArgs(arguments, variables, description); - EXPECT_EQ(variables["load-savegame"].as().string(), R"(save".omwsave)"); + EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as()), R"(save".omwsave)"); } TEST(OpenMWOptionsFromArguments, should_support_quoted_load_savegame_path_with_escaped_ampersand) @@ -142,7 +143,7 @@ namespace const std::array arguments {"openmw", "--load-savegame", R"("save.omwsave&&")"}; bpo::variables_map variables; parseArgs(arguments, variables, description); - EXPECT_EQ(variables["load-savegame"].as().string(), "save.omwsave&"); + EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as()), "save.omwsave&"); } TEST(OpenMWOptionsFromArguments, should_support_load_savegame_path_with_ampersand) @@ -151,7 +152,7 @@ namespace const std::array arguments {"openmw", "--load-savegame", "save&.omwsave"}; bpo::variables_map variables; parseArgs(arguments, variables, description); - EXPECT_EQ(variables["load-savegame"].as().string(), "save&.omwsave"); + EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as()), "save&.omwsave"); } TEST(OpenMWOptionsFromArguments, should_support_load_savegame_path_with_multiple_quotes) @@ -160,7 +161,7 @@ namespace const std::array arguments {"openmw", "--load-savegame", R"(my"save".omwsave)"}; bpo::variables_map variables; parseArgs(arguments, variables, description); - EXPECT_EQ(variables["load-savegame"].as().string(), R"(my"save".omwsave)"); + EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as()), R"(my"save".omwsave)"); } TEST(OpenMWOptionsFromArguments, should_compose_data) @@ -199,7 +200,7 @@ namespace const std::array arguments {"openmw", "--load-savegame", pathArgument.c_str()}; bpo::variables_map variables; parseArgs(arguments, variables, description); - EXPECT_EQ(variables["load-savegame"].as().string(), path); + EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as()), path); } INSTANTIATE_TEST_SUITE_P( @@ -214,7 +215,7 @@ namespace std::istringstream stream("load-savegame=save.omwsave"); bpo::variables_map variables; Files::parseConfig(stream, variables, description); - EXPECT_EQ(variables["load-savegame"].as().string(), "save.omwsave"); + EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as()), "save.omwsave"); } TEST(OpenMWOptionsFromConfig, should_strip_quotes_from_load_savegame_path) @@ -223,7 +224,7 @@ namespace std::istringstream stream(R"(load-savegame="save.omwsave")"); bpo::variables_map variables; Files::parseConfig(stream, variables, description); - EXPECT_EQ(variables["load-savegame"].as().string(), "save.omwsave"); + EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as()), "save.omwsave"); } TEST(OpenMWOptionsFromConfig, should_strip_outer_quotes_from_load_savegame_path) @@ -232,7 +233,7 @@ namespace std::istringstream stream(R"(load-savegame=""save".omwsave")"); bpo::variables_map variables; Files::parseConfig(stream, variables, description); - EXPECT_EQ(variables["load-savegame"].as().string(), ""); + EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as()), ""); } TEST(OpenMWOptionsFromConfig, should_strip_quotes_from_load_savegame_path_with_space) @@ -241,7 +242,7 @@ namespace std::istringstream stream(R"(load-savegame="my save.omwsave")"); bpo::variables_map variables; Files::parseConfig(stream, variables, description); - EXPECT_EQ(variables["load-savegame"].as().string(), "my save.omwsave"); + EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as()), "my save.omwsave"); } TEST(OpenMWOptionsFromConfig, should_support_quoted_load_savegame_path_with_octothorpe) @@ -250,7 +251,7 @@ namespace std::istringstream stream("load-savegame=save#.omwsave"); bpo::variables_map variables; Files::parseConfig(stream, variables, description); - EXPECT_EQ(variables["load-savegame"].as().string(), "save#.omwsave"); + EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as()), "save#.omwsave"); } TEST(OpenMWOptionsFromConfig, should_support_quoted_load_savegame_path_with_at_sign) @@ -259,7 +260,7 @@ namespace std::istringstream stream("load-savegame=save@.omwsave"); bpo::variables_map variables; Files::parseConfig(stream, variables, description); - EXPECT_EQ(variables["load-savegame"].as().string(), "save@.omwsave"); + EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as()), "save@.omwsave"); } TEST(OpenMWOptionsFromConfig, should_support_quoted_load_savegame_path_with_quote) @@ -268,7 +269,7 @@ namespace std::istringstream stream(R"(load-savegame=save".omwsave)"); bpo::variables_map variables; Files::parseConfig(stream, variables, description); - EXPECT_EQ(variables["load-savegame"].as().string(), R"(save".omwsave)"); + EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as()), R"(save".omwsave)"); } TEST(OpenMWOptionsFromConfig, should_support_confusing_savegame_path_with_lots_going_on) @@ -277,7 +278,7 @@ namespace std::istringstream stream(R"(load-savegame="one &"two"three".omwsave")"); bpo::variables_map variables; Files::parseConfig(stream, variables, description); - EXPECT_EQ(variables["load-savegame"].as().string(), R"(one "two)"); + EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as()), R"(one "two)"); } TEST(OpenMWOptionsFromConfig, should_support_confusing_savegame_path_with_even_more_going_on) @@ -286,7 +287,7 @@ namespace std::istringstream stream(R"(load-savegame="one &"two"three ".omwsave")"); bpo::variables_map variables; Files::parseConfig(stream, variables, description); - EXPECT_EQ(variables["load-savegame"].as().string(), R"(one "two)"); + EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as()), R"(one "two)"); } TEST(OpenMWOptionsFromConfig, should_ignore_commented_option) @@ -295,7 +296,7 @@ namespace std::istringstream stream("#load-savegame=save.omwsave"); bpo::variables_map variables; Files::parseConfig(stream, variables, description); - EXPECT_EQ(variables["load-savegame"].as().string(), ""); + EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as()), ""); } TEST(OpenMWOptionsFromConfig, should_ignore_whitespace_prefixed_commented_option) @@ -304,7 +305,7 @@ namespace std::istringstream stream(" \t#load-savegame=save.omwsave"); bpo::variables_map variables; Files::parseConfig(stream, variables, description); - EXPECT_EQ(variables["load-savegame"].as().string(), ""); + EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as()), ""); } TEST(OpenMWOptionsFromConfig, should_support_whitespace_around_option) @@ -313,7 +314,7 @@ namespace std::istringstream stream(" load-savegame = save.omwsave "); bpo::variables_map variables; Files::parseConfig(stream, variables, description); - EXPECT_EQ(variables["load-savegame"].as().string(), "save.omwsave"); + EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as()), "save.omwsave"); } TEST(OpenMWOptionsFromConfig, should_throw_on_multiple_load_savegame) @@ -330,7 +331,7 @@ namespace std::istringstream stream("load-savegame=/home/user/openmw/save.omwsave"); bpo::variables_map variables; Files::parseConfig(stream, variables, description); - EXPECT_EQ(variables["load-savegame"].as().string(), "/home/user/openmw/save.omwsave"); + EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as()), "/home/user/openmw/save.omwsave"); } TEST(OpenMWOptionsFromConfig, should_support_windows_multi_component_load_savegame_path) @@ -339,7 +340,7 @@ namespace std::istringstream stream(R"(load-savegame=C:\OpenMW\save.omwsave)"); bpo::variables_map variables; Files::parseConfig(stream, variables, description); - EXPECT_EQ(variables["load-savegame"].as().string(), R"(C:\OpenMW\save.omwsave)"); + EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as()), R"(C:\OpenMW\save.omwsave)"); } TEST(OpenMWOptionsFromConfig, should_compose_data) @@ -357,7 +358,7 @@ namespace std::istringstream stream(R"(load-savegame="save&".omwsave")"); bpo::variables_map variables; Files::parseConfig(stream, variables, description); - EXPECT_EQ(variables["load-savegame"].as().string(), R"(save".omwsave)"); + EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as()), R"(save".omwsave)"); } TEST(OpenMWOptionsFromConfig, should_support_quoted_load_savegame_path_with_escaped_ampersand) @@ -366,7 +367,7 @@ namespace std::istringstream stream(R"(load-savegame="save.omwsave&&")"); bpo::variables_map variables; Files::parseConfig(stream, variables, description); - EXPECT_EQ(variables["load-savegame"].as().string(), "save.omwsave&"); + EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as()), "save.omwsave&"); } TEST(OpenMWOptionsFromConfig, should_support_load_savegame_path_with_ampersand) @@ -375,7 +376,7 @@ namespace std::istringstream stream("load-savegame=save&.omwsave"); bpo::variables_map variables; Files::parseConfig(stream, variables, description); - EXPECT_EQ(variables["load-savegame"].as().string(), "save&.omwsave"); + EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as()), "save&.omwsave"); } struct OpenMWOptionsFromConfigStrings : TestWithParam {}; @@ -387,7 +388,7 @@ namespace std::istringstream stream("load-savegame=\"" + path + "\""); bpo::variables_map variables; Files::parseConfig(stream, variables, description); - EXPECT_EQ(variables["load-savegame"].as().string(), path); + EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as()), path); } INSTANTIATE_TEST_SUITE_P( diff --git a/apps/openmw_test_suite/shader/shadermanager.cpp b/apps/openmw_test_suite/shader/shadermanager.cpp index 9e4808b073..425f6d391f 100644 --- a/apps/openmw_test_suite/shader/shadermanager.cpp +++ b/apps/openmw_test_suite/shader/shadermanager.cpp @@ -1,4 +1,5 @@ #include +#include #include @@ -48,7 +49,7 @@ namespace const std::string content; withShaderFile(content, [this] (const std::filesystem::path& templateName) { - EXPECT_TRUE(mManager.getShader(templateName.string(), {}, osg::Shader::VERTEX)); //TODO(Project579): This will probably break in windows with unicode paths + EXPECT_TRUE(mManager.getShader(Files::pathToUnicodeString(templateName), {}, osg::Shader::VERTEX)); }); } @@ -59,7 +60,7 @@ namespace "void main() {}\n"; withShaderFile(content, [&] (const std::filesystem::path& templateName) { - const auto shader = mManager.getShader(templateName.string(), mDefines, osg::Shader::VERTEX); //TODO(Project579): This will probably break in windows with unicode paths + const auto shader = mManager.getShader(Files::pathToUnicodeString(templateName), mDefines, osg::Shader::VERTEX); ASSERT_TRUE(shader); EXPECT_EQ(shader->getShaderSource(), content); }); @@ -72,17 +73,17 @@ namespace withShaderFile("_0", content0, [&] (const std::filesystem::path& templateName0) { const std::string content1 = - "#include \"" + templateName0.string() + "\"\n" //TODO(Project579): This will probably break in windows with unicode paths + "#include \"" + Files::pathToUnicodeString(templateName0) + "\"\n" "void bar() { foo() }\n"; withShaderFile("_1", content1, [&] (const std::filesystem::path& templateName1) { const std::string content2 = "#version 120\n" - "#include \"" + templateName1.string() + "\"\n" //TODO(Project579): This will probably break in windows with unicode paths + "#include \"" + Files::pathToUnicodeString(templateName1) + "\"\n" "void main() { bar() }\n"; withShaderFile(content2, [&] (const std::filesystem::path& templateName2) { - const auto shader = mManager.getShader(templateName2.string(), mDefines, osg::Shader::VERTEX); //TODO(Project579): This will probably break in windows with unicode paths + const auto shader = mManager.getShader(Files::pathToUnicodeString(templateName2), mDefines, osg::Shader::VERTEX); ASSERT_TRUE(shader); const std::string expected = "#version 120\n" @@ -113,7 +114,7 @@ namespace withShaderFile(content, [&] (const std::filesystem::path& templateName) { mDefines["flag"] = "1"; - const auto shader = mManager.getShader(templateName.string(), mDefines, osg::Shader::VERTEX); //TODO(Project579): This will probably break in windows with unicode paths + const auto shader = mManager.getShader(Files::pathToUnicodeString(templateName), mDefines, osg::Shader::VERTEX); ASSERT_TRUE(shader); const std::string expected = "#version 120\n" @@ -135,7 +136,7 @@ namespace withShaderFile(content, [&] (const std::filesystem::path& templateName) { mDefines["list"] = "1,2,3"; - const auto shader = mManager.getShader(templateName.string(), mDefines, osg::Shader::VERTEX); //TODO(Project579): This will probably break in windows with unicode paths + const auto shader = mManager.getShader(Files::pathToUnicodeString(templateName), mDefines, osg::Shader::VERTEX); ASSERT_TRUE(shader); const std::string expected = "#version 120\n" @@ -176,7 +177,7 @@ namespace withShaderFile(content, [&] (const std::filesystem::path& templateName) { mDefines["list"] = "1,2,3"; - const auto shader = mManager.getShader(templateName.string(), mDefines, osg::Shader::VERTEX); //TODO(Project579): This will probably break in windows with unicode paths + const auto shader = mManager.getShader(Files::pathToUnicodeString(templateName), mDefines, osg::Shader::VERTEX); ASSERT_TRUE(shader); const std::string expected = "#version 120\n" @@ -223,7 +224,7 @@ namespace ; withShaderFile(content, [&] (const std::filesystem::path& templateName) { - EXPECT_FALSE(mManager.getShader(templateName.string(), mDefines, osg::Shader::VERTEX)); //TODO(Project579): This will probably break in windows with unicode paths + EXPECT_FALSE(mManager.getShader(Files::pathToUnicodeString(templateName), mDefines, osg::Shader::VERTEX)); }); } @@ -236,7 +237,7 @@ namespace ; withShaderFile(content, [&] (const std::filesystem::path& templateName) { - EXPECT_FALSE(mManager.getShader(templateName.string(), mDefines, osg::Shader::VERTEX)); //TODO(Project579): This will probably break in windows with unicode paths + EXPECT_FALSE(mManager.getShader(Files::pathToUnicodeString(templateName), mDefines, osg::Shader::VERTEX)); }); } } diff --git a/apps/openmw_test_suite/testing_util.hpp b/apps/openmw_test_suite/testing_util.hpp index 7b6b008501..ce364d6db6 100644 --- a/apps/openmw_test_suite/testing_util.hpp +++ b/apps/openmw_test_suite/testing_util.hpp @@ -6,6 +6,7 @@ #include #include +#include namespace TestingOpenMW { @@ -14,7 +15,7 @@ namespace TestingOpenMW { std::filesystem::path dir("tests_output"); std::filesystem::create_directory(dir); - return dir / name; + return dir / Misc::StringUtils::stringToU8String(name); } inline std::filesystem::path temporaryFilePath(const std::string name) diff --git a/apps/wizard/installationtargetpage.cpp b/apps/wizard/installationtargetpage.cpp index 0a41d57f14..521395f632 100644 --- a/apps/wizard/installationtargetpage.cpp +++ b/apps/wizard/installationtargetpage.cpp @@ -4,6 +4,8 @@ #include #include +#include + #include "mainwizard.hpp" Wizard::InstallationTargetPage::InstallationTargetPage(QWidget *parent, const Files::ConfigurationManager &cfg) : @@ -19,7 +21,7 @@ Wizard::InstallationTargetPage::InstallationTargetPage(QWidget *parent, const Fi void Wizard::InstallationTargetPage::initializePage() { - QString path(QFile::decodeName(mCfgMgr.getUserDataPath().string().c_str())); //TODO(Project579): This will probably break in windows with unicode paths + QString path(QFile::decodeName(Files::pathToUnicodeString(mCfgMgr.getUserDataPath()).c_str())); path.append(QDir::separator() + QLatin1String("basedata")); QDir dir(path); diff --git a/apps/wizard/mainwizard.cpp b/apps/wizard/mainwizard.cpp index a597b11df8..759fe7edd7 100644 --- a/apps/wizard/mainwizard.cpp +++ b/apps/wizard/mainwizard.cpp @@ -471,5 +471,5 @@ bool Wizard::MainWizard::findFiles(const QString &name, const QString &path) QString Wizard::MainWizard::toQString(const std::filesystem::path& path) { - return QString::fromUtf8(path.string().c_str()); //TODO(Project579): This will probably break in windows with unicode paths + return QString::fromStdWString(path.wstring()); } diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 2e259c2136..9ddfc4eb5b 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -214,7 +214,7 @@ IF(NOT WIN32 AND NOT APPLE) ENDIF() add_component_dir (files linuxpath androidpath windowspath macospath fixedpath multidircollection collections configurationmanager - constrainedfilestream memorystream hash configfileparser openfile constrainedfilestreambuf + constrainedfilestream memorystream hash configfileparser openfile constrainedfilestreambuf conversion ) add_component_dir (compiler diff --git a/components/bsa/bsa_file.cpp b/components/bsa/bsa_file.cpp index 65d184cf75..76d8e9b092 100644 --- a/components/bsa/bsa_file.cpp +++ b/components/bsa/bsa_file.cpp @@ -37,7 +37,7 @@ using namespace Bsa; /// Error handling [[noreturn]] void BSAFile::fail(const std::string &msg) { - throw std::runtime_error("BSA Error: " + msg + "\nArchive: " + mFilepath.string()); //TODO(Project579): This will probably break in windows with unicode paths + throw std::runtime_error("BSA Error: " + msg + "\nArchive: " + Files::pathToUnicodeString(mFilepath)); } //the getHash code is from bsapack from ghostwheel diff --git a/components/bsa/bsa_file.hpp b/components/bsa/bsa_file.hpp index d01fb6d421..0d1bda6134 100644 --- a/components/bsa/bsa_file.hpp +++ b/components/bsa/bsa_file.hpp @@ -30,6 +30,7 @@ #include #include +#include namespace Bsa { @@ -134,7 +135,7 @@ public: std::string getFilename() const { - return mFilepath.string(); //TODO(Project579): This will probably break in windows with unicode paths + return Files::pathToUnicodeString(mFilepath); } }; diff --git a/components/bsa/compressedbsafile.cpp b/components/bsa/compressedbsafile.cpp index 337570cad1..ee7204bd9e 100644 --- a/components/bsa/compressedbsafile.cpp +++ b/components/bsa/compressedbsafile.cpp @@ -48,6 +48,7 @@ #include #include #include +#include namespace Bsa { @@ -214,7 +215,7 @@ void CompressedBSAFile::readHeader() if ((archiveFlags & 0x1) != 0) getBZString(folder, input); - folderHash = generateHash(folder, std::string()); + folderHash = generateHash(folder, {}); auto iter = mFolders.find(folderHash); if (iter == mFolders.end()) @@ -309,13 +310,11 @@ CompressedBSAFile::FileRecord CompressedBSAFile::getFileRecord(const std::string std::replace(path.begin(), path.end(), '\\', '/'); #endif - std::filesystem::path p(path); - std::string stem = p.stem().string(); - std::string ext = p.extension().string(); - p.remove_filename(); + auto p = Files::pathFromUnicodeString(path); + const auto stem = p.stem(); + const auto ext = p.extension().u8string(); - std::string folder = p.string(); - std::uint64_t folderHash = generateHash(folder, std::string()); + std::uint64_t folderHash = generateHash(p.parent_path(), {}); auto it = mFolders.find(folderHash); if (it == mFolders.end()) @@ -358,7 +357,7 @@ Files::IStreamPtr CompressedBSAFile::getFile(const FileRecord& fileRecord) size_t size = fileRecord.getSizeWithoutCompressionFlag(); size_t uncompressedSize = size; bool compressed = fileRecord.isCompressed(mCompressedByDefault); - Files::IStreamPtr streamPtr = Files::openConstrainedFileStream(mFilename, fileRecord.offset, size); + Files::IStreamPtr streamPtr = Files::openConstrainedFileStream(mFilepath, fileRecord.offset, size); std::istream* fileStream = streamPtr.get(); if (mEmbeddedFileNames) { @@ -395,10 +394,10 @@ Files::IStreamPtr CompressedBSAFile::getFile(const FileRecord& fileRecord) LZ4F_decompressOptions_t options = {}; LZ4F_errorCode_t errorCode = LZ4F_decompress(context, memoryStreamPtr->getRawData(), &uncompressedSize, buffer.data(), &size, &options); if (LZ4F_isError(errorCode)) - fail("LZ4 decompression error (file " + mFilename + "): " + LZ4F_getErrorName(errorCode)); + fail("LZ4 decompression error (file " + Files::pathToUnicodeString(mFilepath) + "): " + LZ4F_getErrorName(errorCode)); errorCode = LZ4F_freeDecompressionContext(context); if (LZ4F_isError(errorCode)) - fail("LZ4 decompression error (file " + mFilename + "): " + LZ4F_getErrorName(errorCode)); + fail("LZ4 decompression error (file " + Files::pathToUnicodeString(mFilepath) + "): " + LZ4F_getErrorName(errorCode)); } } else @@ -409,9 +408,9 @@ Files::IStreamPtr CompressedBSAFile::getFile(const FileRecord& fileRecord) return std::make_unique>(std::move(memoryStreamPtr)); } -BsaVersion CompressedBSAFile::detectVersion(const std::string& filePath) +BsaVersion CompressedBSAFile::detectVersion(const std::filesystem::path &filePath) { - std::ifstream input(std::filesystem::path(filePath), std::ios_base::binary); + std::ifstream input(filePath, std::ios_base::binary); // Total archive size std::streamoff fsize = 0; @@ -460,7 +459,7 @@ void CompressedBSAFile::convertCompressedSizesToUncompressed() continue; } - Files::IStreamPtr dataBegin = Files::openConstrainedFileStream(mFilename, fileRecord.offset, fileRecord.getSizeWithoutCompressionFlag()); + Files::IStreamPtr dataBegin = Files::openConstrainedFileStream(mFilepath, fileRecord.offset, fileRecord.getSizeWithoutCompressionFlag()); if (mEmbeddedFileNames) { @@ -472,30 +471,31 @@ void CompressedBSAFile::convertCompressedSizesToUncompressed() } } -std::uint64_t CompressedBSAFile::generateHash(std::string stem, std::string extension) +std::uint64_t CompressedBSAFile::generateHash(const std::filesystem::path& stem, std::u8string extension) { - size_t len = stem.length(); + auto str = stem.u8string(); + size_t len = str.length(); if (len == 0) return 0; - std::replace(stem.begin(), stem.end(), '/', '\\'); - Misc::StringUtils::lowerCaseInPlace(stem); - uint64_t result = stem[len-1] | (len >= 3 ? (stem[len-2] << 8) : 0) | (len << 16) | (stem[0] << 24); + std::replace(str.begin(), str.end(), u8'/', u8'\\'); + Misc::StringUtils::lowerCaseInPlace(str); + uint64_t result = str[len-1] | (len >= 3 ? (str[len-2] << 8) : 0) | (len << 16) | (str[0] << 24); if (len >= 4) { uint32_t hash = 0; for (size_t i = 1; i <= len-3; ++i) - hash = hash * 0x1003f + stem[i]; + hash = hash * 0x1003f + str[i]; result += static_cast(hash) << 32; } if (extension.empty()) return result; Misc::StringUtils::lowerCaseInPlace(extension); - if (extension == ".kf") result |= 0x80; - else if (extension == ".nif") result |= 0x8000; - else if (extension == ".dds") result |= 0x8080; - else if (extension == ".wav") result |= 0x80000000; + if (extension == u8".kf") result |= 0x80; + else if (extension == u8".nif") result |= 0x8000; + else if (extension == u8".dds") result |= 0x8080; + else if (extension == u8".wav") result |= 0x80000000; uint32_t hash = 0; - for (const char &c : extension) + for (const auto &c : extension) hash = hash * 0x1003f + c; result += static_cast(hash) << 32; return result; diff --git a/components/bsa/compressedbsafile.hpp b/components/bsa/compressedbsafile.hpp index 53dcf8f522..71727bfade 100644 --- a/components/bsa/compressedbsafile.hpp +++ b/components/bsa/compressedbsafile.hpp @@ -83,7 +83,7 @@ namespace Bsa //mFiles used by OpenMW will contain uncompressed file sizes void convertCompressedSizesToUncompressed(); /// \brief Normalizes given filename or folder and generates format-compatible hash. See https://en.uesp.net/wiki/Tes4Mod:Hash_Calculation. - static std::uint64_t generateHash(std::filesystem::path stem, std::string extension) ; + static std::uint64_t generateHash(const std::filesystem::path& stem, std::u8string extension) ; Files::IStreamPtr getFile(const FileRecord& fileRecord); public: using BSAFile::open; diff --git a/components/config/gamesettings.cpp b/components/config/gamesettings.cpp index 0fe36720f5..e99e31372a 100644 --- a/components/config/gamesettings.cpp +++ b/components/config/gamesettings.cpp @@ -32,7 +32,7 @@ void Config::GameSettings::validatePaths() mDataDirs.clear(); for (auto & dataDir : dataDirs) { - QString path = QString::fromUtf8(dataDir.string().c_str()); //TODO(Project579): This will probably break in windows with unicode paths + QString path = QString::fromStdWString(dataDir.wstring()); QDir dir(path); if (dir.exists()) @@ -57,7 +57,7 @@ void Config::GameSettings::validatePaths() mCfgMgr.processPaths(dataDirs, /*basePath=*/""); if (!dataDirs.empty()) { - QString path = QString::fromUtf8(dataDirs.front().string().c_str()); //TODO(Project579): This will probably break in windows with unicode paths + QString path = QString::fromStdWString(dataDirs.front().wstring()); QDir dir(path); if (dir.exists()) diff --git a/components/config/launchersettings.cpp b/components/config/launchersettings.cpp index 129d04dcc1..2932a211cf 100644 --- a/components/config/launchersettings.cpp +++ b/components/config/launchersettings.cpp @@ -119,7 +119,7 @@ void Config::LauncherSettings::setContentList(const GameSettings& gameSettings) } // global and local data directories are not part of any profile - const auto globalDataDir = QString(gameSettings.getGlobalDataDir().string().c_str()); //TODO(Project579): This will probably break in windows with unicode paths + const auto globalDataDir = QString::fromStdWString(gameSettings.getGlobalDataDir().wstring()); const auto dataLocal = gameSettings.getDataLocal(); dirs.removeAll(globalDataDir); dirs.removeAll(dataLocal); diff --git a/components/crashcatcher/windows_crashcatcher.cpp b/components/crashcatcher/windows_crashcatcher.cpp index c62a066c59..47f1ba6c2c 100644 --- a/components/crashcatcher/windows_crashcatcher.cpp +++ b/components/crashcatcher/windows_crashcatcher.cpp @@ -140,7 +140,7 @@ namespace Crash const auto str = crashLogPath.u8string(); size_t length = str.length(); if (length >= MAX_LONG_PATH) length = MAX_LONG_PATH - 1; - strncpy_s(mShm->mStartup.mLogFilePath, sizeof mShm->mStartup.mLogFilePath, Misc::StringUtils::char8_to_char(str.c_str()), length); //TODO(Project579): This will probably break in windows with unicode paths + strncpy_s(mShm->mStartup.mLogFilePath, sizeof mShm->mStartup.mLogFilePath, Misc::StringUtils::u8StringToString(str).c_str(), length); mShm->mStartup.mLogFilePath[length] = '\0'; // note that we don't need to lock the SHM here, the other process has not started yet diff --git a/components/debug/debugging.cpp b/components/debug/debugging.cpp index e6f159bf81..71f27036e8 100644 --- a/components/debug/debugging.cpp +++ b/components/debug/debugging.cpp @@ -8,9 +8,11 @@ #include #include +#include #ifdef _WIN32 #include #include +#include #endif #include @@ -318,12 +320,12 @@ int wrapApplication(int (*innerApplication)(int argc, char *argv[]), int argc, c { #if defined(_WIN32) const std::string crashLogName = Misc::StringUtils::lowerCase(appName) + "-crash.dmp"; - Crash::CrashCatcher crashy(argc, argv, (cfgMgr.getLogPath() / crashLogName).make_preferred().string()); + Crash::CrashCatcher crashy(argc, argv, Files::pathToUnicodeString(cfgMgr.getLogPath() / crashLogName)); #else const std::string crashLogName = Misc::StringUtils::lowerCase(appName) + "-crash.log"; // install the crash handler as soon as possible. note that the log path // does not depend on config being read. - crashCatcherInstall(argc, argv, (cfgMgr.getLogPath() / crashLogName).string()); + crashCatcherInstall(argc, argv, Files::pathToUnicodeString(cfgMgr.getLogPath() / crashLogName)); #endif ret = innerApplication(argc, argv); } diff --git a/components/debug/debuglog.cpp b/components/debug/debuglog.cpp index ef453283e8..bb0c4b57e8 100644 --- a/components/debug/debuglog.cpp +++ b/components/debug/debuglog.cpp @@ -2,7 +2,8 @@ #include -#include +#include +#include namespace Debug { diff --git a/components/detournavigator/navigator.cpp b/components/detournavigator/navigator.cpp index 200582216d..c473221322 100644 --- a/components/detournavigator/navigator.cpp +++ b/components/detournavigator/navigator.cpp @@ -4,6 +4,7 @@ #include "recastglobalallocator.hpp" #include +#include namespace DetourNavigator { @@ -16,7 +17,7 @@ namespace DetourNavigator { try { - db = std::make_unique((userDataPath / "navmesh.db").string(), settings.mMaxDbFileSize); //TODO(Project579): This will probably break in windows with unicode paths + db = std::make_unique(Files::pathToUnicodeString(userDataPath / "navmesh.db"), settings.mMaxDbFileSize); } catch (const std::exception& e) { diff --git a/components/esm3/esmreader.cpp b/components/esm3/esmreader.cpp index 5877951d43..b1c4bea329 100644 --- a/components/esm3/esmreader.cpp +++ b/components/esm3/esmreader.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -73,7 +74,7 @@ void ESMReader::resolveParentFileIndices(ReadersCache& readers) const ESM::ReadersCache::BusyItem reader = readers.get(static_cast(i)); if (reader->getFileSize() == 0) continue; // Content file in non-ESM format - std::string fnamecandidate = reader->getName().filename().string(); //TODO(Project579): let's hope unicode characters are never used in these filenames on windows or this will break + const auto fnamecandidate = Files::pathToUnicodeString(reader->getName().filename()); if (Misc::StringUtils::ciEqual(fname, fnamecandidate)) { index = i; @@ -359,7 +360,7 @@ std::string ESMReader::getString(int size) std::stringstream ss; ss << "ESM Error: " << msg; - ss << "\n File: " << mCtx.filename; //TODO(Project579): This will probably break in windows with unicode paths + ss << "\n File: " << Files::pathToUnicodeString(mCtx.filename); ss << "\n Record: " << mCtx.recName.toStringView(); ss << "\n Subrecord: " << mCtx.subName.toStringView(); if (mEsm.get()) diff --git a/components/esm3/loadcell.cpp b/components/esm3/loadcell.cpp index 2d92bf561e..dc32ee6a43 100644 --- a/components/esm3/loadcell.cpp +++ b/components/esm3/loadcell.cpp @@ -131,7 +131,7 @@ namespace ESM { if(!overriding) mWater = std::numeric_limits::max(); - Log(Debug::Warning) << "Warning: Encountered invalid water level in cell " << mName << " defined in " << esm.getContext().filename; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Warning) << "Warning: Encountered invalid water level in cell " << mName << " defined in " << esm.getContext().filename; } else mWater = waterLevel; diff --git a/components/esm4/reader.cpp b/components/esm4/reader.cpp index 4a8e908913..a5696c461b 100644 --- a/components/esm4/reader.cpp +++ b/components/esm4/reader.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #include "formid.hpp" @@ -184,12 +185,7 @@ void Reader::open(Files::IStreamPtr&& stream, const std::filesystem::path &filen throw std::runtime_error("Unknown file format"); // can't yet use fail() as mCtx is not setup } -void Reader::openRaw(const std::string& filename) -{ - openRaw(Files::openConstrainedFileStream(filename), filename); -} - -void Reader::open(const std::string& filename) +void Reader::open(const std::filesystem::path& filename) { open(Files::openConstrainedFileStream(filename), filename); } @@ -637,7 +633,7 @@ void Reader::adjustGRUPFormId() std::stringstream ss; ss << "ESM Error: " << msg; - ss << "\n File: " << mCtx.filename.string(); //TODO(Project579): This will probably break in windows with unicode paths + ss << "\n File: " << Files::pathToUnicodeString(mCtx.filename); ss << "\n Record: " << ESM::printName(mCtx.recordHeader.record.typeId); ss << "\n Subrecord: " << ESM::printName(mCtx.subRecordHeader.typeId); if (mStream.get()) diff --git a/components/esmloader/load.cpp b/components/esmloader/load.cpp index 99d8159f04..66e859bf20 100644 --- a/components/esmloader/load.cpp +++ b/components/esmloader/load.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -228,7 +229,7 @@ namespace EsmLoader for (std::size_t i = 0; i < contentFiles.size(); ++i) { const std::string &file = contentFiles[i]; - const std::string extension = Misc::StringUtils::lowerCase(std::filesystem::path(file).extension().string()); //TODO(Project579): let's hope unicode characters are never used in these extensions on windows or this will break + const std::string extension = Misc::StringUtils::lowerCase(Files::pathToUnicodeString(std::filesystem::path(file).extension())); if (supportedFormats.find(extension) == supportedFormats.end()) { diff --git a/components/files/collections.cpp b/components/files/collections.cpp index 0929336075..575beb988d 100644 --- a/components/files/collections.cpp +++ b/components/files/collections.cpp @@ -1,4 +1,5 @@ #include "collections.hpp" +#include "conversion.hpp" #include #include @@ -42,12 +43,14 @@ namespace Files std::filesystem::directory_iterator (mDirectorie)) { const auto& path = iter2.path(); + const auto str = Files::pathToUnicodeString(path.filename()); + if (mFoldCase) { - if (Misc::StringUtils::ciEqual(file, path.filename().string())) //TODO(Project579): This will probably break in windows with unicode paths + if (Misc::StringUtils::ciEqual(file, str)) return path; } - else if (path.filename().string() == file) //TODO(Project579): This will probably break in windows with unicode paths + else if (str == file) return path; } } @@ -63,13 +66,14 @@ namespace Files std::filesystem::directory_iterator (mDirectorie)) { const auto& path = iter2.path(); + const auto str = Files::pathToUnicodeString(path.filename()); if (mFoldCase) { - if (Misc::StringUtils::ciEqual(file, path.filename().string())) //TODO(Project579): This will probably break in windows with unicode paths + if (Misc::StringUtils::ciEqual(file, str)) return true; } - else if (path.filename().string() == file) //TODO(Project579): This will probably break in windows with unicode paths + else if (str == file) return true; } } diff --git a/components/files/collections.hpp b/components/files/collections.hpp index 69ae7d0d84..000160bae7 100644 --- a/components/files/collections.hpp +++ b/components/files/collections.hpp @@ -19,14 +19,14 @@ namespace Files /// leading dot and must be all lower-case. const MultiDirCollection& getCollection(const std::string& extension) const; - std::filesystem::path getPath(const std::string& file) const; //TODO(Project579): let's hope unicode characters are never used in these filenames on windows or this will break + std::filesystem::path getPath(const std::string& file) const; ///< Return full path (including filename) of \a file. /// /// If the file does not exist in any of the collection's /// directories, an exception is thrown. \a file must include the /// extension. - bool doesExist(const std::string& file) const; //TODO(Project579): let's hope unicode characters are never used in these filenames on windows or this will break + bool doesExist(const std::string& file) const; ///< \return Does a file with the given name exist? const Files::PathContainer& getPaths() const; diff --git a/components/files/configurationmanager.cpp b/components/files/configurationmanager.cpp index cddab2f8b2..8f4bc12c6b 100644 --- a/components/files/configurationmanager.cpp +++ b/components/files/configurationmanager.cpp @@ -460,29 +460,4 @@ PathContainer asPathContainer(const MaybeQuotedPathContainer& MaybeQuotedPathCon return res; } -std::string pathToUnicodeString(const std::filesystem::path& path) -{ - return Misc::StringUtils::u8StringToString(path.u8string()); -} - -std::string pathToUnicodeString(std::filesystem::path&& path) -{ - return Misc::StringUtils::u8StringToString(path.u8string()); -} - -std::filesystem::path unicodeStringToPath(const std::string_view path) -{ - return Misc::StringUtils::stringToU8String(path); -} - -std::filesystem::path unicodeStringToPath(std::string&& path) -{ - return Misc::StringUtils::stringToU8String(std::move(path)); -} - -std::filesystem::path unicodeStringToPath(const char* path) -{ - return Misc::StringUtils::stringToU8String(path); -} - } /* namespace Files */ diff --git a/components/files/configurationmanager.hpp b/components/files/configurationmanager.hpp index e10d528404..7c999ebd6e 100644 --- a/components/files/configurationmanager.hpp +++ b/components/files/configurationmanager.hpp @@ -105,16 +105,6 @@ typedef std::vector MaybeQuotedPathContainer; PathContainer asPathContainer(const MaybeQuotedPathContainer& MaybeQuotedPathContainer); -std::string pathToUnicodeString(const std::filesystem::path& path); - -std::string pathToUnicodeString(std::filesystem::path&& path); - -std::filesystem::path unicodeStringToPath(const std::string_view path); - -std::filesystem::path unicodeStringToPath(std::string&& path); - -std::filesystem::path unicodeStringToPath(const char* path); - } /* namespace Files */ #endif /* COMPONENTS_FILES_CONFIGURATIONMANAGER_HPP */ diff --git a/components/files/conversion.cpp b/components/files/conversion.cpp new file mode 100644 index 0000000000..ab32158ff9 --- /dev/null +++ b/components/files/conversion.cpp @@ -0,0 +1,29 @@ + +#include "conversion.hpp" + +#include + +std::string Files::pathToUnicodeString(const std::filesystem::path& path) +{ + return Misc::StringUtils::u8StringToString(path.u8string()); +} + +std::string Files::pathToUnicodeString(std::filesystem::path&& path) +{ + return Misc::StringUtils::u8StringToString(path.u8string()); +} + +std::filesystem::path Files::pathFromUnicodeString(std::string_view path) +{ + return Misc::StringUtils::stringToU8String(path); +} + +std::filesystem::path Files::pathFromUnicodeString(std::string&& path) +{ + return Misc::StringUtils::stringToU8String(std::move(path)); +} + +std::filesystem::path Files::pathFromUnicodeString(const char* path) +{ + return Misc::StringUtils::stringToU8String(path); +} diff --git a/components/files/conversion.hpp b/components/files/conversion.hpp new file mode 100644 index 0000000000..7eb3ebf7b4 --- /dev/null +++ b/components/files/conversion.hpp @@ -0,0 +1,18 @@ +#ifndef COMPONENTS_FILES_CONVERSION_HPP +#define COMPONENTS_FILES_CONVERSION_HPP + +#include + +namespace Files { + std::string pathToUnicodeString(const std::filesystem::path& path); + + std::string pathToUnicodeString(std::filesystem::path&& path); + + std::filesystem::path pathFromUnicodeString(std::string_view path); + + std::filesystem::path pathFromUnicodeString(std::string&& path); + + std::filesystem::path pathFromUnicodeString(const char* path); +} + +#endif //COMPONENTS_FILES_CONFIGURATIONMANAGER_HPP diff --git a/components/files/hash.cpp b/components/files/hash.cpp index e8d4c2a3b0..946ff06272 100644 --- a/components/files/hash.cpp +++ b/components/files/hash.cpp @@ -1,4 +1,5 @@ #include "hash.hpp" +#include "conversion.hpp" #include @@ -34,7 +35,7 @@ namespace Files } catch (const std::exception& e) { - throw std::runtime_error("Error while reading \"" + fileName.string() + "\" to get hash: " + std::string(e.what())); //TODO(Project579): This will probably break in windows with unicode paths + throw std::runtime_error("Error while reading \"" + Files::pathToUnicodeString(fileName) + "\" to get hash: " + e.what()); } return hash; } diff --git a/components/files/linuxpath.cpp b/components/files/linuxpath.cpp index 94f02f8f7c..c085a07682 100644 --- a/components/files/linuxpath.cpp +++ b/components/files/linuxpath.cpp @@ -24,9 +24,9 @@ namespace } } if (dir == nullptr) - return std::filesystem::path(); + return {}; else - return std::filesystem::path(dir); + return dir; } std::filesystem::path getEnv(const std::string& envVariable, const std::filesystem::path& fallback) diff --git a/components/files/multidircollection.cpp b/components/files/multidircollection.cpp index ad7b54b463..752a1d0275 100644 --- a/components/files/multidircollection.cpp +++ b/components/files/multidircollection.cpp @@ -1,4 +1,5 @@ #include "multidircollection.hpp" +#include "conversion.hpp" #include @@ -30,19 +31,18 @@ namespace Files { if (!std::filesystem::is_directory(directory)) { - Log(Debug::Info) << "Skipping invalid directory: " << directory.string(); //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Info) << "Skipping invalid directory: " << directory; continue; } - for (std::filesystem::directory_iterator dirIter(directory); - dirIter != std::filesystem::directory_iterator(); ++dirIter) + for (const auto& dirIter : std::filesystem::directory_iterator(directory)) { - std::filesystem::path path = *dirIter; + const auto& path = dirIter.path(); - if (!equal (extension, path.extension().string())) //TODO(Project579): let's hope unicode characters are never used in these extensions on windows or this will break + if (!equal (extension, Files::pathToUnicodeString(path.extension()))) continue; - std::string filename = path.filename().string(); //TODO(Project579): let's hope unicode characters are never used in these filenames on windows or this will break + const auto filename = Files::pathToUnicodeString(path.filename()); TIter result = mFiles.find (filename); diff --git a/components/files/openfile.cpp b/components/files/openfile.cpp index 6eb0ee51c8..9ffe134e4a 100644 --- a/components/files/openfile.cpp +++ b/components/files/openfile.cpp @@ -1,4 +1,5 @@ #include "openfile.hpp" +#include "conversion.hpp" #include #include @@ -9,7 +10,7 @@ namespace Files { auto stream = std::make_unique(path, std::ios::binary); if (!stream->is_open()) - throw std::runtime_error("Failed to open '" + path.string() + "' for reading: " + std::strerror(errno)); //TODO(Project579): This will probably break in windows with unicode paths + throw std::runtime_error("Failed to open '" + Files::pathToUnicodeString(path) + "' for reading: " + std::strerror(errno)); stream->exceptions(std::ios::badbit); return stream; } diff --git a/components/fx/technique.cpp b/components/fx/technique.cpp index 357d8448d1..c2de7aaa89 100644 --- a/components/fx/technique.cpp +++ b/components/fx/technique.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -16,6 +17,7 @@ #include #include #include +#include #include "parse_constants.hpp" @@ -37,9 +39,9 @@ namespace namespace fx { - Technique::Technique(const VFS::Manager& vfs, Resource::ImageManager& imageManager, const std::string& name, int width, int height, bool ubo, bool supportsNormals) - : mName(name) - , mFileName((std::filesystem::path(Technique::sSubdir) / (mName + Technique::sExt)).string()) //TODO(Project579): let's hope unicode characters are never used in these filenames on windows or this will break + Technique::Technique(const VFS::Manager& vfs, Resource::ImageManager& imageManager, std::string name, int width, int height, bool ubo, bool supportsNormals) + : mName(std::move(name)) + , mFileName(Files::pathToUnicodeString((Files::pathFromUnicodeString(Technique::sSubdir) / (mName + Technique::sExt)))) , mLastModificationTime(std::filesystem::file_time_type()) , mWidth(width) , mHeight(height) diff --git a/components/fx/technique.hpp b/components/fx/technique.hpp index 4b1c9f19bb..4c01e2a92d 100644 --- a/components/fx/technique.hpp +++ b/components/fx/technique.hpp @@ -123,7 +123,7 @@ namespace fx static constexpr FlagsType Flag_Disable_SunGlare = (1 << 4); static constexpr FlagsType Flag_Hidden = (1 << 5); - Technique(const VFS::Manager& vfs, Resource::ImageManager& imageManager, const std::string& name, int width, int height, bool ubo, bool supportsNormals); + Technique(const VFS::Manager& vfs, Resource::ImageManager& imageManager, std::string name, int width, int height, bool ubo, bool supportsNormals); bool compile(); diff --git a/components/lua/luastate.cpp b/components/lua/luastate.cpp index a78eea6dde..8dacdd5267 100644 --- a/components/lua/luastate.cpp +++ b/components/lua/luastate.cpp @@ -8,6 +8,7 @@ #include #include +#include namespace LuaUtil { @@ -270,7 +271,7 @@ namespace LuaUtil sol::function LuaState::loadInternalLib(std::string_view libName) { const auto path = packageNameToPath(libName, mLibSearchPaths); - sol::load_result res = mLua.load_file(path.string(), sol::load_mode::text); //TODO(Project579): This will probably break in windows with unicode paths + sol::load_result res = mLua.load_file(Files::pathToUnicodeString(path), sol::load_mode::text); if (!res.valid()) throw std::runtime_error("Lua error: " + res.get()); return res; diff --git a/components/lua/storage.cpp b/components/lua/storage.cpp index ffb4f8af82..c80181f977 100644 --- a/components/lua/storage.cpp +++ b/components/lua/storage.cpp @@ -160,7 +160,7 @@ namespace LuaUtil assert(mData.empty()); // Shouldn't be used before loading try { - Log(Debug::Info) << "Loading Lua storage \"" << path << "\" (" << std::filesystem::file_size(path) << " bytes)"; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Info) << "Loading Lua storage \"" << path << "\" (" << std::filesystem::file_size(path) << " bytes)"; std::ifstream fin(path, std::fstream::binary); std::string serializedData((std::istreambuf_iterator(fin)), std::istreambuf_iterator()); sol::table data = deserialize(mLua, serializedData); @@ -186,7 +186,7 @@ namespace LuaUtil data[sectionName] = section->asTable(); } std::string serializedData = serialize(data); - Log(Debug::Info) << "Saving Lua storage \"" << path << "\" (" << serializedData.size() << " bytes)"; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Info) << "Saving Lua storage \"" << path << "\" (" << serializedData.size() << " bytes)"; std::ofstream fout(path, std::fstream::binary); fout.write(serializedData.data(), serializedData.size()); fout.close(); diff --git a/components/myguiplatform/myguidatamanager.cpp b/components/myguiplatform/myguidatamanager.cpp index 3078650a47..5696cec58f 100644 --- a/components/myguiplatform/myguidatamanager.cpp +++ b/components/myguiplatform/myguidatamanager.cpp @@ -7,6 +7,7 @@ #include #include +#include namespace { @@ -68,7 +69,7 @@ const std::string &DataManager::getDataPath(const std::string &name) const if (!isDataExist(name)) return result; - result = (mResourcePath / name).string(); //TODO(Project579): This is broken on windows with unicode paths + result = Files::pathToUnicodeString(mResourcePath / name); return result; } diff --git a/components/myguiplatform/myguiloglistener.cpp b/components/myguiplatform/myguiloglistener.cpp index e22b96680a..0ca1af3415 100644 --- a/components/myguiplatform/myguiloglistener.cpp +++ b/components/myguiplatform/myguiloglistener.cpp @@ -10,7 +10,7 @@ namespace osgMyGUI { mStream.open(mFileName, std::ios_base::out); if (!mStream.is_open()) - Log(Debug::Error) << "Unable to create MyGUI log with path " << mFileName; //TODO(Project579): This is broken on windows with unicode paths + Log(Debug::Error) << "Unable to create MyGUI log with path " << mFileName; } void CustomLogListener::close() diff --git a/components/nif/niffile.cpp b/components/nif/niffile.cpp index 08d80b0f67..8b525e8ae7 100644 --- a/components/nif/niffile.cpp +++ b/components/nif/niffile.cpp @@ -316,7 +316,7 @@ void NIFFile::parse(Files::IStreamPtr&& stream) r = entry->second(); if (!supportedVersion) - Log(Debug::Verbose) << "NIF Debug: Reading record of type " << rec << ", index " << i << " (" << filename << ")"; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Verbose) << "NIF Debug: Reading record of type " << rec << ", index " << i << " (" << filename << ")"; assert(r != nullptr); assert(r->recType != RC_MISSING); diff --git a/components/nifbullet/bulletnifloader.cpp b/components/nifbullet/bulletnifloader.cpp index aeaf57c5f4..dcf406ecb2 100644 --- a/components/nifbullet/bulletnifloader.cpp +++ b/components/nifbullet/bulletnifloader.cpp @@ -21,6 +21,7 @@ #include #include +#include namespace { @@ -187,7 +188,7 @@ osg::ref_ptr BulletNifLoader::load(const Nif::File& nif) if (node) roots.emplace_back(node); } - const std::string filename = nif.getFilename().string(); //TODO(Project579): This will probably break in windows with unicode paths + const std::string filename = Files::pathToUnicodeString(nif.getFilename()); mShape->mFileName = filename; if (roots.empty()) { diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 39ccafdceb..5db3e9280c 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -299,7 +299,7 @@ namespace NifOsg setupController(key, callback, /*animflags*/0); if (!target.mKeyframeControllers.emplace(strdata->string, callback).second) - Log(Debug::Verbose) << "Controller " << strdata->string << " present more than once in " << nif->getFilename() << ", ignoring later version"; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Verbose) << "Controller " << strdata->string << " present more than once in " << nif->getFilename() << ", ignoring later version"; } } @@ -485,20 +485,20 @@ namespace NifOsg { if (nifNode->recType != Nif::RC_NiTextureEffect) { - Log(Debug::Info) << "Unhandled effect " << nifNode->recName << " in " << mFilename; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Info) << "Unhandled effect " << nifNode->recName << " in " << mFilename; return; } const Nif::NiTextureEffect* textureEffect = static_cast(nifNode); if (textureEffect->textureType != Nif::NiTextureEffect::Environment_Map) { - Log(Debug::Info) << "Unhandled NiTextureEffect type " << textureEffect->textureType << " in " << mFilename; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Info) << "Unhandled NiTextureEffect type " << textureEffect->textureType << " in " << mFilename; return; } if (textureEffect->texture.empty()) { - Log(Debug::Info) << "NiTextureEffect missing source texture in " << mFilename; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Info) << "NiTextureEffect missing source texture in " << mFilename; return; } @@ -515,7 +515,7 @@ namespace NifOsg texGen->setMode(osg::TexGen::SPHERE_MAP); break; default: - Log(Debug::Info) << "Unhandled NiTextureEffect coordGenType " << textureEffect->coordGenType << " in " << mFilename; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Info) << "Unhandled NiTextureEffect coordGenType " << textureEffect->coordGenType << " in " << mFilename; return; } @@ -875,7 +875,7 @@ namespace NifOsg // These controllers are handled elsewhere } else - Log(Debug::Info) << "Unhandled controller " << ctrl->recName << " on node " << nifNode->recIndex << " in " << mFilename; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Info) << "Unhandled controller " << ctrl->recName << " on node " << nifNode->recIndex << " in " << mFilename; } } @@ -915,7 +915,7 @@ namespace NifOsg composite->addController(osgctrl); } else - Log(Debug::Info) << "Unexpected material controller " << ctrl->recType << " in " << mFilename; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Info) << "Unexpected material controller " << ctrl->recType << " in " << mFilename; } } @@ -959,7 +959,7 @@ namespace NifOsg composite->addController(callback); } else - Log(Debug::Info) << "Unexpected texture controller " << ctrl->recName << " in " << mFilename; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Info) << "Unexpected texture controller " << ctrl->recName << " in " << mFilename; } } @@ -994,7 +994,7 @@ namespace NifOsg // unused } else - Log(Debug::Info) << "Unhandled particle modifier " << affectors->recName << " in " << mFilename; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Info) << "Unhandled particle modifier " << affectors->recName << " in " << mFilename; } for (; !colliders.empty(); colliders = colliders->next) { @@ -1009,7 +1009,7 @@ namespace NifOsg program->addOperator(new SphericalCollider(sphericalcollider)); } else - Log(Debug::Info) << "Unhandled particle collider " << colliders->recName << " in " << mFilename; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Info) << "Unhandled particle collider " << colliders->recName << " in " << mFilename; } } @@ -1152,7 +1152,7 @@ namespace NifOsg } if (!partctrl) { - Log(Debug::Info) << "No particle controller found in " << mFilename; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Info) << "No particle controller found in " << mFilename; return; } @@ -1247,7 +1247,7 @@ namespace NifOsg unsigned int uvSet = *it; if (uvSet >= uvlist.size()) { - Log(Debug::Verbose) << "Out of bounds UV set " << uvSet << " on shape \"" << name << "\" in " << mFilename; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Verbose) << "Out of bounds UV set " << uvSet << " on shape \"" << name << "\" in " << mFilename; if (uvlist.empty()) continue; uvSet = 0; @@ -1419,7 +1419,7 @@ namespace NifOsg case 9: return osg::BlendFunc::ONE_MINUS_DST_ALPHA; case 10: return osg::BlendFunc::SRC_ALPHA_SATURATE; default: - Log(Debug::Info) << "Unexpected blend mode: "<< mode << " in " << mFilename; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Info) << "Unexpected blend mode: "<< mode << " in " << mFilename; return osg::BlendFunc::SRC_ALPHA; } } @@ -1437,7 +1437,7 @@ namespace NifOsg case 6: return osg::AlphaFunc::GEQUAL; case 7: return osg::AlphaFunc::NEVER; default: - Log(Debug::Info) << "Unexpected blend mode: " << mode << " in " << mFilename; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Info) << "Unexpected blend mode: " << mode << " in " << mFilename; return osg::AlphaFunc::LEQUAL; } } @@ -1455,7 +1455,7 @@ namespace NifOsg case 6: return osg::Stencil::GEQUAL; case 7: return osg::Stencil::ALWAYS; default: - Log(Debug::Info) << "Unexpected stencil function: " << func << " in " << mFilename; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Info) << "Unexpected stencil function: " << func << " in " << mFilename; return osg::Stencil::NEVER; } } @@ -1471,7 +1471,7 @@ namespace NifOsg case 4: return osg::Stencil::DECR; case 5: return osg::Stencil::INVERT; default: - Log(Debug::Info) << "Unexpected stencil operation: " << op << " in " << mFilename; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Info) << "Unexpected stencil operation: " << op << " in " << mFilename; return osg::Stencil::KEEP; } } @@ -1514,7 +1514,7 @@ namespace NifOsg packing = 4; break; default: - Log(Debug::Info) << "Unhandled internal pixel format " << pixelData->fmt << " in " << mFilename; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Info) << "Unhandled internal pixel format " << pixelData->fmt << " in " << mFilename; return nullptr; } @@ -1572,7 +1572,7 @@ namespace NifOsg { if (pixelData->palette.empty() || pixelData->bpp != 8) { - Log(Debug::Info) << "Palettized texture in " << mFilename << " is invalid, ignoring"; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Info) << "Palettized texture in " << mFilename << " is invalid, ignoring"; return nullptr; } pixelformat = pixelData->fmt == Nif::NiPixelData::NIPXFMT_PAL8 ? GL_RGB : GL_RGBA; @@ -1644,7 +1644,7 @@ namespace NifOsg break; default: { - Log(Debug::Info) << "Unhandled texture stage " << i << " on shape \"" << nodeName << "\" in " << mFilename; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Info) << "Unhandled texture stage " << i << " on shape \"" << nodeName << "\" in " << mFilename; continue; } } @@ -1658,7 +1658,7 @@ namespace NifOsg if(tex.texture.empty() && texprop->controller.empty()) { if (i == 0) - Log(Debug::Warning) << "Base texture is in use but empty on shape \"" << nodeName << "\" in " << mFilename; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Warning) << "Base texture is in use but empty on shape \"" << nodeName << "\" in " << mFilename; continue; } @@ -1815,7 +1815,7 @@ namespace NifOsg break; default: { - Log(Debug::Info) << "Unhandled texture stage " << i << " on shape \"" << nodeName << "\" in " << mFilename; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Info) << "Unhandled texture stage " << i << " on shape \"" << nodeName << "\" in " << mFilename; continue; } } @@ -1859,10 +1859,10 @@ namespace NifOsg case Nif::BSShaderType::ShaderType_Water: case Nif::BSShaderType::ShaderType_Lighting30: case Nif::BSShaderType::ShaderType_Tile: - Log(Debug::Warning) << "Unhandled BSShaderType " << type << " in " << mFilename; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Warning) << "Unhandled BSShaderType " << type << " in " << mFilename; return std::string_view(); } - Log(Debug::Warning) << "Unknown BSShaderType " << type << " in " << mFilename; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Warning) << "Unknown BSShaderType " << type << " in " << mFilename; return std::string_view(); } @@ -1891,10 +1891,10 @@ namespace NifOsg case Nif::BSLightingShaderType::ShaderType_LODNoise: case Nif::BSLightingShaderType::ShaderType_MultitexLandLODBlend: case Nif::BSLightingShaderType::ShaderType_Dismemberment: - Log(Debug::Warning) << "Unhandled BSLightingShaderType " << type << " in " << mFilename; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Warning) << "Unhandled BSLightingShaderType " << type << " in " << mFilename; return std::string_view(); } - Log(Debug::Warning) << "Unknown BSLightingShaderType " << type << " in " << mFilename; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Warning) << "Unknown BSLightingShaderType " << type << " in " << mFilename; return std::string_view(); } @@ -2057,7 +2057,7 @@ namespace NifOsg break; } default: - Log(Debug::Info) << "Unhandled " << property->recName << " in " << mFilename; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Info) << "Unhandled " << property->recName << " in " << mFilename; break; } } @@ -2304,7 +2304,7 @@ namespace NifOsg else if (type == Nif::RC_NiClusterAccumulator) setBin_BackToFront(stateset); else - Log(Debug::Error) << "Unrecognized NiAccumulator in " << mFilename; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Error) << "Unrecognized NiAccumulator in " << mFilename; }; switch (mPushedSorter->mMode) diff --git a/components/resource/scenemanager.cpp b/components/resource/scenemanager.cpp index ef8d1c66e3..db08631666 100644 --- a/components/resource/scenemanager.cpp +++ b/components/resource/scenemanager.cpp @@ -48,6 +48,7 @@ #include #include +#include #include "imagemanager.hpp" #include "niffilemanager.hpp" @@ -498,14 +499,14 @@ namespace Resource osgDB::ReaderWriter::ReadResult readImage(const std::string& filename, const osgDB::Options* options) override { - std::filesystem::path filePath(filename); //TODO(Project579): This will probably break in windows with unicode paths + auto filePath = Files::pathFromUnicodeString(filename); if (filePath.is_absolute()) // It is a hack. Needed because either OSG or libcollada-dom tries to make an absolute path from // our relative VFS path by adding current working directory. filePath = std::filesystem::relative(filename, osgDB::getCurrentWorkingDirectory()); try { - return osgDB::ReaderWriter::ReadResult(mImageManager->getImage(filePath.string()), //TODO(Project579): This will probably break in windows with unicode paths + return osgDB::ReaderWriter::ReadResult(mImageManager->getImage(Files::pathToUnicodeString(filePath)), osgDB::ReaderWriter::ReadResult::FILE_LOADED); } catch (std::exception& e) diff --git a/components/sceneutil/screencapture.cpp b/components/sceneutil/screencapture.cpp index 6adff9323d..6c73191014 100644 --- a/components/sceneutil/screencapture.cpp +++ b/components/sceneutil/screencapture.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -129,7 +130,7 @@ namespace SceneUtil if (fileName.empty()) mCallback("Failed to save screenshot"); else - mCallback(fileName.string() + " has been saved"); //TODO(Project579): This will probably break in windows with unicode paths + mCallback(Files::pathToUnicodeString(fileName) + " has been saved"); } AsyncScreenCaptureOperation::AsyncScreenCaptureOperation(osg::ref_ptr queue, diff --git a/components/settings/parser.cpp b/components/settings/parser.cpp index 44016ad010..1c1eeccc90 100644 --- a/components/settings/parser.cpp +++ b/components/settings/parser.cpp @@ -304,7 +304,7 @@ void Settings::SettingsFileParser::saveSettingsFile(const std::filesystem::path // Now install the newly written file in the requested place. if (changed) { - Log(Debug::Info) << "Updating settings file: " << file; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Info) << "Updating settings file: " << file; std::ofstream ofstream; ofstream.open(file); ofstream << ostream.rdbuf(); diff --git a/components/settings/shadermanager.hpp b/components/settings/shadermanager.hpp index effedf63d2..6aa14e73ef 100644 --- a/components/settings/shadermanager.hpp +++ b/components/settings/shadermanager.hpp @@ -15,6 +15,7 @@ #include #include +#include namespace Settings { @@ -109,7 +110,7 @@ namespace Settings mData = YAML::Null; mPath = path; - Log(Debug::Info) << "Loading shader settings file: " << mPath; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Info) << "Loading shader settings file: " << mPath; if (!std::filesystem::exists(mPath)) { @@ -123,7 +124,7 @@ namespace Settings try { - mData = YAML::LoadFile(mPath.string()); //TODO(Project579): This will probably break in windows with unicode paths + mData = YAML::LoadFile(Files::pathToUnicodeString(mPath)); mData.SetStyle(YAML::EmitterStyle::Block); if (!mData["config"]) diff --git a/components/shader/shadermanager.cpp b/components/shader/shadermanager.cpp index 1e48cf337e..189881fe97 100644 --- a/components/shader/shadermanager.cpp +++ b/components/shader/shadermanager.cpp @@ -126,7 +126,7 @@ namespace Shader includeFstream.open(includePath); if (includeFstream.fail()) { - Log(Debug::Error) << "Shader " << fileName << " error: Failed to open include " << includePath.string(); //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Error) << "Shader " << fileName << " error: Failed to open include " << includePath; return false; } int includedFileNumber = fileNumber++; @@ -472,7 +472,7 @@ namespace Shader stream.open(path); if (stream.fail()) { - Log(Debug::Error) << "Failed to open " << path.string(); //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Error) << "Failed to open " << path; return nullptr; } std::stringstream buffer; diff --git a/components/version/version.cpp b/components/version/version.cpp index a280bf38d3..eec374b97a 100644 --- a/components/version/version.cpp +++ b/components/version/version.cpp @@ -17,7 +17,7 @@ Version getOpenmwVersion(const std::filesystem::path &resourcePath) return v; } -std::string Version::describe() +std::string Version::describe() const { std::string str = "OpenMW version " + mVersion; std::string rev = mCommitHash; diff --git a/components/version/version.hpp b/components/version/version.hpp index 0248f869a9..6c1998bb60 100644 --- a/components/version/version.hpp +++ b/components/version/version.hpp @@ -13,7 +13,7 @@ namespace Version std::string mCommitHash; std::string mTagHash; - std::string describe(); + std::string describe() const; }; /// Read OpenMW version from the version file located in resourcePath. diff --git a/components/vfs/filesystemarchive.cpp b/components/vfs/filesystemarchive.cpp index f6b01a89c4..d04b827d62 100644 --- a/components/vfs/filesystemarchive.cpp +++ b/components/vfs/filesystemarchive.cpp @@ -6,6 +6,7 @@ #include #include +#include namespace VFS { @@ -21,7 +22,7 @@ namespace VFS { if (!mBuiltIndex) { - const auto str = mPath.string(); //TODO(Project579): This will probably break in windows with unicode paths + const auto str = mPath.u8string(); size_t prefix = str.size (); if (!mPath.empty() && str [prefix - 1] != '\\' && str [prefix - 1] != '/') @@ -34,7 +35,7 @@ namespace VFS continue; const auto& path = i.path (); - const auto& proper = path.string (); //TODO(Project579): This will probably break in windows with unicode paths + const auto& proper = Files::pathToUnicodeString(path); FileSystemArchiveFile file(path); @@ -44,7 +45,7 @@ namespace VFS const auto inserted = mIndex.insert(std::make_pair(searchable, file)); if (!inserted.second) - Log(Debug::Warning) << "Warning: found duplicate file for '" << proper << "', please check your file system for two files with the same name in different cases."; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Warning) << "Warning: found duplicate file for '" << proper << "', please check your file system for two files with the same name in different cases."; else out[inserted.first->first] = &inserted.first->second; } @@ -66,7 +67,7 @@ namespace VFS std::string FileSystemArchive::getDescription() const { - return std::string{"DIR: "} + mPath.string(); //TODO(Project579): This will probably break in windows with unicode paths + return "DIR: " + Files::pathToUnicodeString(mPath); } // ---------------------------------------------------------------------------------- diff --git a/components/vfs/manager.cpp b/components/vfs/manager.cpp index 8f3963f3f7..118227a5f1 100644 --- a/components/vfs/manager.cpp +++ b/components/vfs/manager.cpp @@ -5,6 +5,8 @@ #include #include +#include +#include #include "archive.hpp" @@ -56,7 +58,7 @@ namespace VFS mIndex.clear(); for (const auto& archive : mArchives) - archive->listResources(mIndex, mStrict ? &strict_normalize_char : &nonstrict_normalize_char); //TODO(Project579): This will probably break in windows with unicode paths + archive->listResources(mIndex, mStrict ? &strict_normalize_char : &nonstrict_normalize_char); } Files::IStreamPtr Manager::get(std::string_view name) const @@ -104,13 +106,13 @@ namespace VFS std::filesystem::path Manager::getAbsoluteFileName(const std::filesystem::path &name) const { - std::string normalized(name); //TODO(Project579): This will probably break in windows with unicode paths - normalize_path(normalized, mStrict); //TODO(Project579): This will probably break in windows with unicode paths + std::string normalized = Files::pathToUnicodeString(name); + normalize_path(normalized, mStrict); const auto found = mIndex.find(normalized); if (found == mIndex.end()) throw std::runtime_error("Resource '" + normalized + "' not found"); - return found->second->getPath();//TODO(Project579): This will probably break in windows with unicode paths + return found->second->getPath(); } namespace diff --git a/components/vfs/registerarchives.cpp b/components/vfs/registerarchives.cpp index dd8287818e..b496958381 100644 --- a/components/vfs/registerarchives.cpp +++ b/components/vfs/registerarchives.cpp @@ -23,7 +23,7 @@ namespace VFS { // Last BSA has the highest priority const auto archivePath = collections.getPath(*archive); - Log(Debug::Info) << "Adding BSA archive " << archivePath; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Info) << "Adding BSA archive " << archivePath; Bsa::BsaVersion bsaVersion = Bsa::CompressedBSAFile::detectVersion(archivePath); if (bsaVersion == Bsa::BSAVER_COMPRESSED) @@ -49,7 +49,7 @@ namespace VFS vfs->addArchive(std::make_unique(dataDir)); } else - Log(Debug::Info) << "Ignoring duplicate data directory " << dataDir; //TODO(Project579): This will probably break in windows with unicode paths + Log(Debug::Info) << "Ignoring duplicate data directory " << dataDir; } }