mirror of https://github.com/cemu-project/Cemu.git
FSC: Use utf8 path strings instead of wchar
Also introduced helper function _utf8ToPath() to convert a utf8-encoded string to fs::path
This commit is contained in:
parent
1ce629126a
commit
168ecf8825
|
@ -183,7 +183,7 @@ void fsc_unmountAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
// lookup virtual path and find mounted device and relative device directory
|
// lookup virtual path and find mounted device and relative device directory
|
||||||
bool fsc_lookupPath(const char* path, std::wstring& devicePathOut, fscDeviceC** fscDeviceOut, void** ctxOut, sint32 priority = FSC_PRIORITY_BASE)
|
bool fsc_lookupPath(const char* path, std::string& devicePathOut, fscDeviceC** fscDeviceOut, void** ctxOut, sint32 priority = FSC_PRIORITY_BASE)
|
||||||
{
|
{
|
||||||
FSCPath parsedPath(path);
|
FSCPath parsedPath(path);
|
||||||
FSCMountPathNode* nodeParent = s_fscRootNodePerPrio[priority];
|
FSCMountPathNode* nodeParent = s_fscRootNodePerPrio[priority];
|
||||||
|
@ -214,11 +214,11 @@ bool fsc_lookupPath(const char* path, std::wstring& devicePathOut, fscDeviceC**
|
||||||
{
|
{
|
||||||
if (nodeParent->device)
|
if (nodeParent->device)
|
||||||
{
|
{
|
||||||
devicePathOut = boost::nowide::widen(nodeParent->deviceTargetPath);
|
devicePathOut = nodeParent->deviceTargetPath;
|
||||||
for (size_t f = i; f < parsedPath.GetNodeCount(); f++)
|
for (size_t f = i; f < parsedPath.GetNodeCount(); f++)
|
||||||
{
|
{
|
||||||
auto nodeName = parsedPath.GetNodeName(f);
|
auto nodeName = parsedPath.GetNodeName(f);
|
||||||
devicePathOut.append(boost::nowide::widen(nodeName));
|
devicePathOut.append(nodeName);
|
||||||
if (f < (parsedPath.GetNodeCount() - 1))
|
if (f < (parsedPath.GetNodeCount() - 1))
|
||||||
devicePathOut.push_back('/');
|
devicePathOut.push_back('/');
|
||||||
}
|
}
|
||||||
|
@ -353,11 +353,9 @@ private:
|
||||||
FSCVirtualFile* fsc_open(const char* path, FSC_ACCESS_FLAG accessFlags, sint32* fscStatus, sint32 maxPriority)
|
FSCVirtualFile* fsc_open(const char* path, FSC_ACCESS_FLAG accessFlags, sint32* fscStatus, sint32 maxPriority)
|
||||||
{
|
{
|
||||||
cemu_assert_debug(HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::OPEN_FILE) || HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::OPEN_DIR)); // must open either file or directory
|
cemu_assert_debug(HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::OPEN_FILE) || HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::OPEN_DIR)); // must open either file or directory
|
||||||
|
|
||||||
FSCVirtualFile* dirList[FSC_PRIORITY_COUNT];
|
FSCVirtualFile* dirList[FSC_PRIORITY_COUNT];
|
||||||
uint8 dirListCount = 0;
|
uint8 dirListCount = 0;
|
||||||
|
std::string devicePath;
|
||||||
std::wstring devicePath;
|
|
||||||
fscDeviceC* fscDevice = NULL;
|
fscDeviceC* fscDevice = NULL;
|
||||||
*fscStatus = FSC_STATUS_UNDEFINED;
|
*fscStatus = FSC_STATUS_UNDEFINED;
|
||||||
void* ctx;
|
void* ctx;
|
||||||
|
@ -448,7 +446,7 @@ bool fsc_createDir(char* path, sint32* fscStatus)
|
||||||
fscDeviceC* fscDevice = NULL;
|
fscDeviceC* fscDevice = NULL;
|
||||||
*fscStatus = FSC_STATUS_UNDEFINED;
|
*fscStatus = FSC_STATUS_UNDEFINED;
|
||||||
void* ctx;
|
void* ctx;
|
||||||
std::wstring devicePath;
|
std::string devicePath;
|
||||||
fscEnter();
|
fscEnter();
|
||||||
if( fsc_lookupPath(path, devicePath, &fscDevice, &ctx) )
|
if( fsc_lookupPath(path, devicePath, &fscDevice, &ctx) )
|
||||||
{
|
{
|
||||||
|
@ -465,8 +463,8 @@ bool fsc_createDir(char* path, sint32* fscStatus)
|
||||||
*/
|
*/
|
||||||
bool fsc_rename(char* srcPath, char* dstPath, sint32* fscStatus)
|
bool fsc_rename(char* srcPath, char* dstPath, sint32* fscStatus)
|
||||||
{
|
{
|
||||||
std::wstring srcDevicePath;
|
std::string srcDevicePath;
|
||||||
std::wstring dstDevicePath;
|
std::string dstDevicePath;
|
||||||
void* srcCtx;
|
void* srcCtx;
|
||||||
void* dstCtx;
|
void* dstCtx;
|
||||||
fscDeviceC* fscSrcDevice = NULL;
|
fscDeviceC* fscSrcDevice = NULL;
|
||||||
|
@ -485,7 +483,7 @@ bool fsc_rename(char* srcPath, char* dstPath, sint32* fscStatus)
|
||||||
*/
|
*/
|
||||||
bool fsc_remove(char* path, sint32* fscStatus)
|
bool fsc_remove(char* path, sint32* fscStatus)
|
||||||
{
|
{
|
||||||
std::wstring devicePath;
|
std::string devicePath;
|
||||||
fscDeviceC* fscDevice = NULL;
|
fscDeviceC* fscDevice = NULL;
|
||||||
*fscStatus = FSC_STATUS_UNDEFINED;
|
*fscStatus = FSC_STATUS_UNDEFINED;
|
||||||
void* ctx;
|
void* ctx;
|
||||||
|
|
|
@ -57,25 +57,25 @@ struct FSCDirEntry
|
||||||
class fscDeviceC
|
class fscDeviceC
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual FSCVirtualFile* fscDeviceOpenByPath(std::wstring_view path, FSC_ACCESS_FLAG accessFlags, void* ctx, sint32* fscStatus)
|
virtual FSCVirtualFile* fscDeviceOpenByPath(std::string_view path, FSC_ACCESS_FLAG accessFlags, void* ctx, sint32* fscStatus)
|
||||||
{
|
{
|
||||||
cemu_assert_unimplemented();
|
cemu_assert_unimplemented();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool fscDeviceCreateDir(std::wstring_view path, void* ctx, sint32* fscStatus)
|
virtual bool fscDeviceCreateDir(std::string_view path, void* ctx, sint32* fscStatus)
|
||||||
{
|
{
|
||||||
cemu_assert_unimplemented();
|
cemu_assert_unimplemented();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool fscDeviceRemoveFileOrDir(std::wstring_view path, void* ctx, sint32* fscStatus)
|
virtual bool fscDeviceRemoveFileOrDir(std::string_view path, void* ctx, sint32* fscStatus)
|
||||||
{
|
{
|
||||||
cemu_assert_unimplemented();
|
cemu_assert_unimplemented();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool fscDeviceRename(std::wstring_view srcPath, std::wstring_view dstPath, void* ctx, sint32* fscStatus)
|
virtual bool fscDeviceRename(std::string_view srcPath, std::string_view dstPath, void* ctx, sint32* fscStatus)
|
||||||
{
|
{
|
||||||
cemu_assert_unimplemented();
|
cemu_assert_unimplemented();
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -221,36 +221,36 @@ FSCVirtualFile* FSCVirtualFile_Host::OpenFile(const fs::path& path, FSC_ACCESS_F
|
||||||
class fscDeviceHostFSC : public fscDeviceC
|
class fscDeviceHostFSC : public fscDeviceC
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FSCVirtualFile* fscDeviceOpenByPath(std::wstring_view path, FSC_ACCESS_FLAG accessFlags, void* ctx, sint32* fscStatus) override
|
FSCVirtualFile* fscDeviceOpenByPath(std::string_view path, FSC_ACCESS_FLAG accessFlags, void* ctx, sint32* fscStatus) override
|
||||||
{
|
{
|
||||||
*fscStatus = FSC_STATUS_OK;
|
*fscStatus = FSC_STATUS_OK;
|
||||||
FSCVirtualFile* vf = FSCVirtualFile_Host::OpenFile(path, accessFlags, *fscStatus);
|
FSCVirtualFile* vf = FSCVirtualFile_Host::OpenFile(_utf8ToPath(path), accessFlags, *fscStatus);
|
||||||
cemu_assert_debug((bool)vf == (*fscStatus == FSC_STATUS_OK));
|
cemu_assert_debug((bool)vf == (*fscStatus == FSC_STATUS_OK));
|
||||||
return vf;
|
return vf;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fscDeviceCreateDir(std::wstring_view path, void* ctx, sint32* fscStatus) override
|
bool fscDeviceCreateDir(std::string_view path, void* ctx, sint32* fscStatus) override
|
||||||
{
|
{
|
||||||
fs::path dirPath(path);
|
fs::path dirPath = _utf8ToPath(path);
|
||||||
if (fs::exists(path))
|
if (fs::exists(dirPath))
|
||||||
{
|
{
|
||||||
if (!fs::is_directory(dirPath))
|
if (!fs::is_directory(dirPath))
|
||||||
cemuLog_force("CreateDir: {} already exists but is not a directory", _utf8Wrapper(dirPath));
|
cemuLog_force("CreateDir: {} already exists but is not a directory", path);
|
||||||
*fscStatus = FSC_STATUS_ALREADY_EXISTS;
|
*fscStatus = FSC_STATUS_ALREADY_EXISTS;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
bool r = fs::create_directories(dirPath, ec);
|
bool r = fs::create_directories(dirPath, ec);
|
||||||
if(!r)
|
if (!r)
|
||||||
cemuLog_force("CreateDir: Failed to create {}", _utf8Wrapper(dirPath));
|
cemuLog_force("CreateDir: Failed to create {}", path);
|
||||||
*fscStatus = FSC_STATUS_OK;
|
*fscStatus = FSC_STATUS_OK;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fscDeviceRemoveFileOrDir(std::wstring_view path, void* ctx, sint32* fscStatus) override
|
bool fscDeviceRemoveFileOrDir(std::string_view path, void* ctx, sint32* fscStatus) override
|
||||||
{
|
{
|
||||||
*fscStatus = FSC_STATUS_OK;
|
*fscStatus = FSC_STATUS_OK;
|
||||||
fs::path _path(path);
|
fs::path _path = _utf8ToPath(path);
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
if (!fs::exists(_path, ec))
|
if (!fs::exists(_path, ec))
|
||||||
{
|
{
|
||||||
|
@ -266,11 +266,11 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fscDeviceRename(std::wstring_view srcPath, std::wstring_view dstPath, void* ctx, sint32* fscStatus) override
|
bool fscDeviceRename(std::string_view srcPath, std::string_view dstPath, void* ctx, sint32* fscStatus) override
|
||||||
{
|
{
|
||||||
*fscStatus = FSC_STATUS_OK;
|
*fscStatus = FSC_STATUS_OK;
|
||||||
fs::path _srcPath(srcPath);
|
fs::path _srcPath = _utf8ToPath(srcPath);
|
||||||
fs::path _dstPath(dstPath);
|
fs::path _dstPath = _utf8ToPath(dstPath);
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
if (!fs::exists(_srcPath, ec))
|
if (!fs::exists(_srcPath, ec))
|
||||||
{
|
{
|
||||||
|
|
|
@ -29,11 +29,10 @@ void fscDeviceRedirect_add(std::string_view virtualSourcePath, const fs::path& t
|
||||||
|
|
||||||
class fscDeviceTypeRedirect : public fscDeviceC
|
class fscDeviceTypeRedirect : public fscDeviceC
|
||||||
{
|
{
|
||||||
FSCVirtualFile* fscDeviceOpenByPath(std::wstring_view pathW, FSC_ACCESS_FLAG accessFlags, void* ctx, sint32* fscStatus) override
|
FSCVirtualFile* fscDeviceOpenByPath(std::string_view path, FSC_ACCESS_FLAG accessFlags, void* ctx, sint32* fscStatus) override
|
||||||
{
|
{
|
||||||
RedirectEntry* redirectionEntry;
|
RedirectEntry* redirectionEntry;
|
||||||
std::string pathTmp = boost::nowide::narrow(pathW);
|
if (redirectTree.getFile(path, redirectionEntry))
|
||||||
if (redirectTree.getFile(pathTmp, redirectionEntry))
|
|
||||||
return FSCVirtualFile_Host::OpenFile(redirectionEntry->dstPath, accessFlags, *fscStatus);
|
return FSCVirtualFile_Host::OpenFile(redirectionEntry->dstPath, accessFlags, *fscStatus);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,14 +119,12 @@ private:
|
||||||
|
|
||||||
class fscDeviceWUAC : public fscDeviceC
|
class fscDeviceWUAC : public fscDeviceC
|
||||||
{
|
{
|
||||||
FSCVirtualFile* fscDeviceOpenByPath(std::wstring_view path, FSC_ACCESS_FLAG accessFlags, void* ctx, sint32* fscStatus) override
|
FSCVirtualFile* fscDeviceOpenByPath(std::string_view path, FSC_ACCESS_FLAG accessFlags, void* ctx, sint32* fscStatus) override
|
||||||
{
|
{
|
||||||
ZArchiveReader* archive = (ZArchiveReader*)ctx;
|
ZArchiveReader* archive = (ZArchiveReader*)ctx;
|
||||||
cemu_assert_debug(!HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::WRITE_PERMISSION)); // writing to WUA is not supported
|
cemu_assert_debug(!HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::WRITE_PERMISSION)); // writing to WUA is not supported
|
||||||
|
|
||||||
std::string pathU8 = boost::nowide::narrow(path.data(), path.size());
|
ZArchiveNodeHandle fileHandle = archive->LookUp(path, true, true);
|
||||||
|
|
||||||
ZArchiveNodeHandle fileHandle = archive->LookUp(pathU8, true, true);
|
|
||||||
if (fileHandle == ZARCHIVE_INVALID_NODE)
|
if (fileHandle == ZARCHIVE_INVALID_NODE)
|
||||||
{
|
{
|
||||||
*fscStatus = FSC_STATUS_FILE_NOT_FOUND;
|
*fscStatus = FSC_STATUS_FILE_NOT_FOUND;
|
||||||
|
|
|
@ -120,16 +120,15 @@ private:
|
||||||
|
|
||||||
class fscDeviceWUDC : public fscDeviceC
|
class fscDeviceWUDC : public fscDeviceC
|
||||||
{
|
{
|
||||||
FSCVirtualFile* fscDeviceOpenByPath(std::wstring_view path, FSC_ACCESS_FLAG accessFlags, void* ctx, sint32* fscStatus) override
|
FSCVirtualFile* fscDeviceOpenByPath(std::string_view path, FSC_ACCESS_FLAG accessFlags, void* ctx, sint32* fscStatus) override
|
||||||
{
|
{
|
||||||
FSTVolume* mountedVolume = (FSTVolume*)ctx;
|
FSTVolume* mountedVolume = (FSTVolume*)ctx;
|
||||||
cemu_assert_debug(!HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::WRITE_PERMISSION)); // writing to FST is never allowed
|
cemu_assert_debug(!HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::WRITE_PERMISSION)); // writing to FST is never allowed
|
||||||
|
|
||||||
std::string pathU8 = boost::nowide::narrow(path.data(), path.size());
|
|
||||||
if (HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::OPEN_FILE))
|
if (HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::OPEN_FILE))
|
||||||
{
|
{
|
||||||
FSTFileHandle fstFileHandle;
|
FSTFileHandle fstFileHandle;
|
||||||
if (mountedVolume->OpenFile(pathU8, fstFileHandle, true))
|
if (mountedVolume->OpenFile(path, fstFileHandle, true))
|
||||||
{
|
{
|
||||||
*fscStatus = FSC_STATUS_OK;
|
*fscStatus = FSC_STATUS_OK;
|
||||||
return new FSCDeviceWudFileCtx(mountedVolume, fstFileHandle);
|
return new FSCDeviceWudFileCtx(mountedVolume, fstFileHandle);
|
||||||
|
@ -138,7 +137,7 @@ class fscDeviceWUDC : public fscDeviceC
|
||||||
if (HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::OPEN_DIR))
|
if (HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::OPEN_DIR))
|
||||||
{
|
{
|
||||||
FSTDirectoryIterator dirIterator;
|
FSTDirectoryIterator dirIterator;
|
||||||
if (mountedVolume->OpenDirectoryIterator(pathU8, dirIterator))
|
if (mountedVolume->OpenDirectoryIterator(path, dirIterator))
|
||||||
{
|
{
|
||||||
*fscStatus = FSC_STATUS_OK;
|
*fscStatus = FSC_STATUS_OK;
|
||||||
return new FSCDeviceWudFileCtx(mountedVolume, dirIterator);
|
return new FSCDeviceWudFileCtx(mountedVolume, dirIterator);
|
||||||
|
|
|
@ -79,7 +79,7 @@ void CafeTitleList::LoadCacheFile()
|
||||||
cacheEntry.titleDataFormat = format;
|
cacheEntry.titleDataFormat = format;
|
||||||
cacheEntry.region = region;
|
cacheEntry.region = region;
|
||||||
cacheEntry.titleName = name;
|
cacheEntry.titleName = name;
|
||||||
cacheEntry.path = _asUtf8(path);
|
cacheEntry.path = _utf8ToPath(path);
|
||||||
cacheEntry.subPath = sub_path;
|
cacheEntry.subPath = sub_path;
|
||||||
cacheEntry.group_id = group_id;
|
cacheEntry.group_id = group_id;
|
||||||
cacheEntry.app_type = app_type;
|
cacheEntry.app_type = app_type;
|
||||||
|
|
|
@ -435,10 +435,11 @@ inline std::string _utf8Wrapper(const fs::path& path)
|
||||||
return _utf8Wrapper(path.generic_u8string());
|
return _utf8Wrapper(path.generic_u8string());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::u8string_view _asUtf8(std::string_view input)
|
// convert utf8 encoded string to fs::path
|
||||||
|
inline fs::path _utf8ToPath(std::string_view input)
|
||||||
{
|
{
|
||||||
std::basic_string_view<char8_t> v((char8_t*)input.data(), input.size());
|
std::basic_string_view<char8_t> v((char8_t*)input.data(), input.size());
|
||||||
return v;
|
return fs::path(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
class RunAtCemuBoot // -> replaces this with direct function calls. Linkers other than MSVC may optimize way object files entirely if they are not referenced from outside. So a source file self-registering using this would be causing issues
|
class RunAtCemuBoot // -> replaces this with direct function calls. Linkers other than MSVC may optimize way object files entirely if they are not referenced from outside. So a source file self-registering using this would be causing issues
|
||||||
|
|
|
@ -47,7 +47,7 @@ public:
|
||||||
{
|
{
|
||||||
cemu_assert_debug(format.empty() || (format[0] != '/' && format[0] != '\\'));
|
cemu_assert_debug(format.empty() || (format[0] != '/' && format[0] != '\\'));
|
||||||
auto tmp = fmt::format(fmt::runtime(format), std::forward<TArgs>(args)...);
|
auto tmp = fmt::format(fmt::runtime(format), std::forward<TArgs>(args)...);
|
||||||
return GetMlcPath() / fs::path(_asUtf8(tmp));
|
return GetMlcPath() / _utf8ToPath(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ...TArgs>
|
template <typename ...TArgs>
|
||||||
|
|
Loading…
Reference in New Issue