Replace implicit convertions from std::filesystem::path to std::string with correctly converting functions.

crashfix_debugdraw
Project579 3 years ago
parent 4d47e8d055
commit a13709c510

@ -9,6 +9,7 @@
#include <components/bsa/compressedbsafile.hpp>
#include <components/misc/strings/algorithm.hpp>
#include <components/files/configurationmanager.hpp>
#include <components/files/conversion.hpp>
#define BSATOOL_VERSION 1.1
@ -179,17 +180,17 @@ int list(std::unique_ptr<File>& bsa, Arguments& info)
template<typename File>
int extract(std::unique_ptr<File>& 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<File>& 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<File>& 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<typename File>
int add(std::unique_ptr<File>& 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;
}

@ -33,7 +33,6 @@ namespace
namespace bpo = boost::program_options;
using StringsVector = std::vector<std::string>;
using PathsVector = std::vector<std::filesystem::path>;
bpo::options_description makeOptionsDescription()
{
@ -146,7 +145,7 @@ namespace
const auto fsStrict = variables["fs-strict"].as<bool>();
const auto resDir = variables["resources"].as<Files::MaybeQuotedPath>();
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);

@ -18,6 +18,7 @@
#include <components/files/openfile.hpp>
#include <components/misc/strings/algorithm.hpp>
#include <components/files/configurationmanager.hpp>
#include <components/files/conversion.hpp>
#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<std::ifstream>&& 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;
}

@ -289,7 +289,7 @@ namespace EsmTool
int loadTes4(const Arguments& info, std::unique_ptr<std::ifstream>&& 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
{

@ -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));

@ -12,6 +12,7 @@
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/variables_map.hpp>
#include <components/files/conversion.hpp>
#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("<br><b>Could not create directory %0</b><br><br> \
Please make sure you have the right permissions \
and try again.<br>").arg(userConfigDir.canonicalPath())
and try again.<br>").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("<br><b>Could not create %0</b><br><br> \
Please make sure you have the right permissions \
and try again.<br>").arg(userPath));
and try again.<br>").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 = "<br><b>Error writing settings.cfg</b><br><br>" +
settingsPath.string() + "<br><br>" + e.what(); //TODO(Project579): This will probably break in windows with unicode paths
Files::pathToUnicodeString(settingsPath) + "<br><br>" + 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

@ -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;

@ -8,6 +8,7 @@
#include <components/misc/strings/lower.hpp>
#include <components/esm3/esmreader.hpp>
#include <components/misc/timeconvert.hpp>
#include <components/files/conversion.hpp>
@ -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();
}

@ -24,6 +24,7 @@
#include <components/esm3/readerscache.hpp>
#include <components/platform/platform.hpp>
#include <components/detournavigator/agentbounds.hpp>
#include <components/files/conversion.hpp>
#include <osg/Vec3f>
@ -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<std::uint64_t>(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;

@ -10,6 +10,7 @@
#include <components/vfs/bsaarchive.hpp>
#include <components/vfs/filesystemarchive.hpp>
#include <components/files/configurationmanager.hpp>
#include <components/files/conversion.hpp>
#include <boost/program_options.hpp>
@ -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<VFS::Archive>&& 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)

@ -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");

@ -89,7 +89,7 @@ namespace CS
void cancelFileDialog();
void loadDocument();
void openFiles (const std::filesystem::path &path, const std::vector<std::filesystem::path> &discoveredFiles = std::vector<std::filesystem::path>());
void openFiles (const std::filesystem::path &path, const std::vector<std::filesystem::path> &discoveredFiles = {});
void createNewFile (const std::filesystem::path& path);
void createNewGame (const std::filesystem::path& file);

@ -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());
}

@ -5,6 +5,7 @@
#include <cassert>
#include <memory>
#include <filesystem>
#include <utility>
#include "../world/defaultgmsts.hpp"
@ -13,7 +14,7 @@
#endif
#include <components/debug/debuglog.hpp>
#include <utility>
#include <components/files/conversion.hpp>
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<std::string> contentFiles;
std::vector<std::filesystem::path> contentFiles;
for (std::vector<std::filesystem::path>::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);

@ -1,5 +1,7 @@
#include "loader.hpp"
#include <components/files/conversion.hpp>
#include <iostream>
#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
{

@ -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<std::string>::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<std::string>& contentFiles, const std::string& startupInstruction)
const std::vector<std::filesystem::path> &contentFiles, const std::string& startupInstruction)
{
mProfile = profile;
mContentFiles = contentFiles;

@ -25,7 +25,7 @@ namespace CSMDoc
QProcess mProcess;
bool mRunning;
ESM::DebugProfile mProfile;
std::vector<std::string> mContentFiles;
std::vector<std::filesystem::path> 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<std::string>& contentFiles,
const std::vector<std::filesystem::path> &contentFiles,
const std::string& startupInstruction);
QTextDocument *getLog();

@ -4,6 +4,7 @@
#include <filesystem>
#include <components/esm3/loaddial.hpp>
#include <components/files/conversion.hpp>
#include "../world/infocollection.hpp"
#include "../world/cellcoordinates.hpp"
@ -72,8 +73,8 @@ void CSMDoc::WriteHeaderStage::perform (int stage, Messages& messages)
for (std::vector<std::filesystem::path>::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);
}

@ -95,7 +95,9 @@ void CSMWorld::CommandDispatcher::setEditLock (bool locked)
void CSMWorld::CommandDispatcher::setSelection (const std::vector<std::string>& 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());
}

@ -169,7 +169,9 @@ void CSMWorld::RegionMap::updateRegions (const std::vector<std::string>& regions
{
std::vector<std::string> 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<CellCoordinates, CellDescription>::const_iterator iter (mMap.begin());

@ -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;

@ -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))

@ -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);

@ -30,6 +30,7 @@
#include <components/misc/helpviewer.hpp>
#include <components/version/version.hpp>
#include <components/files/conversion.hpp>
#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 << " *";

@ -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);

@ -102,7 +102,7 @@ void CSVTools::Merge::configure (CSMDoc::Document *document)
for (std::vector<std::filesystem::path>::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<CSMDoc::Document> target (
mDocumentManager.makeDocument (files, files[0], true));

@ -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<osg::Image> 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

@ -21,6 +21,7 @@
#include <components/files/memorystream.hpp>
#include <components/misc/timeconvert.hpp>
#include <components/files/conversion.hpp>
#include <components/esm3/loadclas.hpp>
@ -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;

@ -6,6 +6,7 @@
#include <extern/oics/ICSInputControlSystem.h>
#include <components/sdlutil/sdlmappings.hpp>
#include <components/files/conversion.hpp>
#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)

@ -7,6 +7,8 @@
#include <components/debug/debuglog.hpp>
#include <components/sdlutil/sdlmappings.hpp>
#include <components/misc/stringops.hpp>
#include <components/files/conversion.hpp>
#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

@ -23,6 +23,7 @@
#include <components/vfs/manager.hpp>
#include <components/stereo/multiview.hpp>
#include <components/stereo/stereomanager.hpp>
#include <components/files/conversion.hpp>
#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();
}

@ -243,16 +243,16 @@ osg::ref_ptr<osg::Image> 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<osg::Image>();
}
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();
}

@ -24,6 +24,7 @@
#include <components/esm3/loadcrea.hpp>
#include <components/vfs/manager.hpp>
#include <components/files/conversion.hpp>
#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) + "'");
}
}
};

@ -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());
}

@ -13,6 +13,7 @@
#include <components/loadinglistener/loadinglistener.hpp>
#include <components/settings/settings.hpp>
#include <components/files/conversion.hpp>
#include <osg/Image>
@ -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();

@ -3,6 +3,7 @@
#include <components/esm3/esmreader.hpp>
#include <components/esm3/readerscache.hpp>
#include <components/files/conversion.hpp>
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<std::size_t>(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();
}

@ -44,6 +44,7 @@
#include <components/detournavigator/navigatorimpl.hpp>
#include <components/loadinglistener/loadinglistener.hpp>
#include <components/files/conversion.hpp>
#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);

@ -1,5 +1,6 @@
#include <components/files/hash.hpp>
#include <components/files/constrainedfilestream.hpp>
#include <components/files/conversion.hpp>
#include <gtest/gtest.h>
#include <gmock/gmock.h>
@ -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<std::streamsize>(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(

@ -11,6 +11,7 @@
#include <components/esm/records.hpp>
#include <components/loadinglistener/loadinglistener.hpp>
#include <components/misc/strings/algorithm.hpp>
#include <components/files/conversion.hpp>
#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:

@ -1,5 +1,6 @@
#include <apps/openmw/options.hpp>
#include <components/files/configurationmanager.hpp>
#include <components/files/conversion.hpp>
#include <gtest/gtest.h>
#include <gmock/gmock.h>
@ -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 <class T>
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<Files::MaybeQuotedPath>().string(), "save.omwsave");
EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), "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<Files::MaybeQuotedPath>().string(), "save.omwsave");
EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), "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<Files::MaybeQuotedPath>().string(), "/home/user/openmw/save.omwsave");
EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), "/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<Files::MaybeQuotedPath>().string(), R"(C:\OpenMW\save.omwsave)");
EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), 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<Files::MaybeQuotedPath>().string(), "my save.omwsave");
EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), "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<Files::MaybeQuotedPath>().string(), "my#save.omwsave");
EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), "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<Files::MaybeQuotedPath>().string(), "my@save.omwsave");
EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), "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<Files::MaybeQuotedPath>().string(), R"(my"save.omwsave)");
EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), 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<Files::MaybeQuotedPath>().string(), R"(save)");
EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), 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<Files::MaybeQuotedPath>().string(), R"(save".omwsave)");
EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), 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<Files::MaybeQuotedPath>().string(), "save.omwsave&");
EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), "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<Files::MaybeQuotedPath>().string(), "save&.omwsave");
EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), "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<Files::MaybeQuotedPath>().string(), R"(my"save".omwsave)");
EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), 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<Files::MaybeQuotedPath>().string(), path);
EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), 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<Files::MaybeQuotedPath>().string(), "save.omwsave");
EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), "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<Files::MaybeQuotedPath>().string(), "save.omwsave");
EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), "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<Files::MaybeQuotedPath>().string(), "");
EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), "");
}
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<Files::MaybeQuotedPath>().string(), "my save.omwsave");
EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), "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<Files::MaybeQuotedPath>().string(), "save#.omwsave");
EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), "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<Files::MaybeQuotedPath>().string(), "save@.omwsave");
EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), "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<Files::MaybeQuotedPath>().string(), R"(save".omwsave)");
EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), 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<Files::MaybeQuotedPath>().string(), R"(one "two)");
EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), 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<Files::MaybeQuotedPath>().string(), R"(one "two)");
EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), 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<Files::MaybeQuotedPath>().string(), "");
EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), "");
}
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<Files::MaybeQuotedPath>().string(), "");
EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), "");
}
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<Files::MaybeQuotedPath>().string(), "save.omwsave");
EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), "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<Files::MaybeQuotedPath>().string(), "/home/user/openmw/save.omwsave");
EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), "/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<Files::MaybeQuotedPath>().string(), R"(C:\OpenMW\save.omwsave)");
EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), 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<Files::MaybeQuotedPath>().string(), R"(save".omwsave)");
EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), 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<Files::MaybeQuotedPath>().string(), "save.omwsave&");
EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), "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<Files::MaybeQuotedPath>().string(), "save&.omwsave");
EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), "save&.omwsave");
}
struct OpenMWOptionsFromConfigStrings : TestWithParam<std::string> {};
@ -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<Files::MaybeQuotedPath>().string(), path);
EXPECT_EQ(Files::pathToUnicodeString(variables["load-savegame"].as<Files::MaybeQuotedPath>()), path);
}
INSTANTIATE_TEST_SUITE_P(

@ -1,4 +1,5 @@
#include <components/shader/shadermanager.hpp>
#include <components/files/conversion.hpp>
#include <fstream>
@ -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));
});
}
}

@ -6,6 +6,7 @@
#include <components/vfs/archive.hpp>
#include <components/vfs/manager.hpp>
#include <components/misc/stringops.hpp>
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)

@ -4,6 +4,8 @@
#include <QFileDialog>
#include <QMessageBox>
#include <components/files/conversion.hpp>
#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);

@ -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());
}

@ -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

@ -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

@ -30,6 +30,7 @@
#include <filesystem>
#include <components/files/istreamptr.hpp>
#include <components/files/conversion.hpp>
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);
}
};

@ -48,6 +48,7 @@
#include <components/bsa/memorystream.hpp>
#include <components/misc/strings/lower.hpp>
#include <components/files/constrainedfilestream.hpp>
#include <components/files/conversion.hpp>
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<Files::StreamWithBuffer<MemoryInputStream>>(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<uint64_t>(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<uint64_t>(hash) << 32;
return result;

@ -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;

@ -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())

@ -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);

@ -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

@ -8,9 +8,11 @@
#include <components/crashcatcher/crashcatcher.hpp>
#include <components/files/configurationmanager.hpp>
#include <components/files/conversion.hpp>
#ifdef _WIN32
#include <components/crashcatcher/windows_crashcatcher.hpp>
#include <components/windows.hpp>
#include <components/files/conversion.hpp>
#endif
#include <SDL_messagebox.h>
@ -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);
}

@ -2,7 +2,8 @@
#include <mutex>
#include <components/files/configurationmanager.hpp>
#include <components/files/conversion.hpp>
#include <components/misc/stringops.hpp>
namespace Debug
{

@ -4,6 +4,7 @@
#include "recastglobalallocator.hpp"
#include <components/debug/debuglog.hpp>
#include <components/files/conversion.hpp>
namespace DetourNavigator
{
@ -16,7 +17,7 @@ namespace DetourNavigator
{
try
{
db = std::make_unique<NavMeshDb>((userDataPath / "navmesh.db").string(), settings.mMaxDbFileSize); //TODO(Project579): This will probably break in windows with unicode paths
db = std::make_unique<NavMeshDb>(Files::pathToUnicodeString(userDataPath / "navmesh.db"), settings.mMaxDbFileSize);
}
catch (const std::exception& e)
{

@ -4,6 +4,7 @@
#include <components/misc/strings/algorithm.hpp>
#include <components/files/openfile.hpp>
#include <components/files/conversion.hpp>
#include <stdexcept>
#include <sstream>
@ -73,7 +74,7 @@ void ESMReader::resolveParentFileIndices(ReadersCache& readers)
const ESM::ReadersCache::BusyItem reader = readers.get(static_cast<std::size_t>(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())

@ -131,7 +131,7 @@ namespace ESM
{
if(!overriding)
mWater = std::numeric_limits<float>::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;

@ -51,6 +51,7 @@
#include <components/misc/strings/lower.hpp>
#include <components/files/constrainedfilestream.hpp>
#include <components/to_utf8/to_utf8.hpp>
#include <components/files/conversion.hpp>
#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())

@ -20,6 +20,7 @@
#include <components/misc/strings/lower.hpp>
#include <components/esm3/readerscache.hpp>
#include <components/loadinglistener/loadinglistener.hpp>
#include <components/files/conversion.hpp>
#include <algorithm>
#include <filesystem>
@ -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())
{

@ -1,4 +1,5 @@
#include "collections.hpp"
#include "conversion.hpp"
#include <components/misc/strings/algorithm.hpp>
#include <components/misc/strings/lower.hpp>
@ -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;
}
}

@ -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;

@ -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 */

@ -105,16 +105,6 @@ typedef std::vector<MaybeQuotedPath> 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 */

@ -0,0 +1,29 @@
#include "conversion.hpp"
#include <components/misc/stringops.hpp>
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);
}

@ -0,0 +1,18 @@
#ifndef COMPONENTS_FILES_CONVERSION_HPP
#define COMPONENTS_FILES_CONVERSION_HPP
#include <filesystem>
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

@ -1,4 +1,5 @@
#include "hash.hpp"
#include "conversion.hpp"
#include <extern/smhasher/MurmurHash3.h>
@ -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;
}

@ -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)

@ -1,4 +1,5 @@
#include "multidircollection.hpp"
#include "conversion.hpp"
#include <filesystem>
@ -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);

@ -1,4 +1,5 @@
#include "openfile.hpp"
#include "conversion.hpp"
#include <cstring>
#include <fstream>
@ -9,7 +10,7 @@ namespace Files
{
auto stream = std::make_unique<std::ifstream>(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;
}

@ -2,6 +2,7 @@
#include <array>
#include <string>
#include <utility>
#include <osg/Texture1D>
#include <osg/Texture2D>
@ -16,6 +17,7 @@
#include <components/sceneutil/util.hpp>
#include <components/resource/imagemanager.hpp>
#include <components/debug/debuglog.hpp>
#include <components/files/conversion.hpp>
#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)

@ -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();

@ -8,6 +8,7 @@
#include <components/debug/debuglog.hpp>
#include <components/vfs/manager.hpp>
#include <components/files/conversion.hpp>
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<std::string>());
return res;

@ -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<char>(fin)), std::istreambuf_iterator<char>());
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();

@ -7,6 +7,7 @@
#include <MyGUI_DataFileStream.h>
#include <components/vfs/manager.hpp>
#include <components/files/conversion.hpp>
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;
}

@ -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()

@ -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);

@ -21,6 +21,7 @@
#include <components/nif/parent.hpp>
#include <components/settings/settings.hpp>
#include <components/files/conversion.hpp>
namespace
{
@ -187,7 +188,7 @@ osg::ref_ptr<Resource::BulletShape> 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())
{

@ -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<const Nif::NiTextureEffect*>(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)

@ -48,6 +48,7 @@
#include <components/files/hash.hpp>
#include <components/files/memorystream.hpp>
#include <components/files/conversion.hpp>
#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)

@ -2,6 +2,7 @@
#include <components/debug/debuglog.hpp>
#include <components/sceneutil/workqueue.hpp>
#include <components/files/conversion.hpp>
#include <osg/ref_ptr>
#include <osg/Image>
@ -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<WorkQueue> queue,

@ -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();

@ -15,6 +15,7 @@
#include <components/serialization/osgyaml.hpp>
#include <components/debug/debuglog.hpp>
#include <components/files/conversion.hpp>
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"])

@ -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;

@ -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;

@ -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.

@ -6,6 +6,7 @@
#include <components/debug/debuglog.hpp>
#include <components/files/constrainedfilestream.hpp>
#include <components/files/conversion.hpp>
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);
}
// ----------------------------------------------------------------------------------

@ -5,6 +5,8 @@
#include <algorithm>
#include <components/misc/strings/lower.hpp>
#include <components/files/configurationmanager.hpp>
#include <components/files/conversion.hpp>
#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

@ -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<FileSystemArchive>(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;
}
}

Loading…
Cancel
Save