mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-23 06:15:38 +00:00
FileSystem: Use wide strings for FindFiles and StatFile on Windows
This commit is contained in:
parent
2eb9384275
commit
ede8de92f6
|
@ -700,8 +700,8 @@ static u32 RecursiveFindFiles(const char* OriginPath, const char* ParentPath, co
|
||||||
tempStr = StringUtil::StdStringFromFormat("%s\\*", OriginPath);
|
tempStr = StringUtil::StdStringFromFormat("%s\\*", OriginPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
WIN32_FIND_DATA wfd;
|
WIN32_FIND_DATAW wfd;
|
||||||
HANDLE hFind = FindFirstFileA(tempStr.c_str(), &wfd);
|
HANDLE hFind = FindFirstFileW(StringUtil::UTF8StringToWideString(tempStr).c_str(), &wfd);
|
||||||
if (hFind == INVALID_HANDLE_VALUE)
|
if (hFind == INVALID_HANDLE_VALUE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -715,21 +715,28 @@ static u32 RecursiveFindFiles(const char* OriginPath, const char* ParentPath, co
|
||||||
wildCardMatchAll = !(std::strcmp(Pattern, "*"));
|
wildCardMatchAll = !(std::strcmp(Pattern, "*"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// holder for utf-8 conversion
|
||||||
|
std::string utf8_filename;
|
||||||
|
utf8_filename.reserve(countof(wfd.cFileName) * 2);
|
||||||
|
|
||||||
// iterate results
|
// iterate results
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (wfd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN && !(Flags & FILESYSTEM_FIND_HIDDEN_FILES))
|
if (wfd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN && !(Flags & FILESYSTEM_FIND_HIDDEN_FILES))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (wfd.cFileName[0] == '.')
|
if (wfd.cFileName[0] == L'.')
|
||||||
{
|
{
|
||||||
if (wfd.cFileName[1] == '\0' || (wfd.cFileName[1] == '.' && wfd.cFileName[2] == '\0'))
|
if (wfd.cFileName[1] == L'\0' || (wfd.cFileName[1] == L'.' && wfd.cFileName[2] == L'\0'))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!(Flags & FILESYSTEM_FIND_HIDDEN_FILES))
|
if (!(Flags & FILESYSTEM_FIND_HIDDEN_FILES))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!StringUtil::WideStringToUTF8String(utf8_filename, wfd.cFileName))
|
||||||
|
continue;
|
||||||
|
|
||||||
FILESYSTEM_FIND_DATA outData;
|
FILESYSTEM_FIND_DATA outData;
|
||||||
outData.Attributes = 0;
|
outData.Attributes = 0;
|
||||||
|
|
||||||
|
@ -741,11 +748,11 @@ static u32 RecursiveFindFiles(const char* OriginPath, const char* ParentPath, co
|
||||||
if (ParentPath != nullptr)
|
if (ParentPath != nullptr)
|
||||||
{
|
{
|
||||||
const std::string recurseDir = StringUtil::StdStringFromFormat("%s\\%s", ParentPath, Path);
|
const std::string recurseDir = StringUtil::StdStringFromFormat("%s\\%s", ParentPath, Path);
|
||||||
nFiles += RecursiveFindFiles(OriginPath, recurseDir.c_str(), wfd.cFileName, Pattern, Flags, pResults);
|
nFiles += RecursiveFindFiles(OriginPath, recurseDir.c_str(), utf8_filename.c_str(), Pattern, Flags, pResults);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nFiles += RecursiveFindFiles(OriginPath, Path, wfd.cFileName, Pattern, Flags, pResults);
|
nFiles += RecursiveFindFiles(OriginPath, Path, utf8_filename.c_str(), Pattern, Flags, pResults);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -766,12 +773,12 @@ static u32 RecursiveFindFiles(const char* OriginPath, const char* ParentPath, co
|
||||||
// match the filename
|
// match the filename
|
||||||
if (hasWildCards)
|
if (hasWildCards)
|
||||||
{
|
{
|
||||||
if (!wildCardMatchAll && !StringUtil::WildcardMatch(wfd.cFileName, Pattern))
|
if (!wildCardMatchAll && !StringUtil::WildcardMatch(utf8_filename.c_str(), Pattern))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (std::strcmp(wfd.cFileName, Pattern) != 0)
|
if (std::strcmp(utf8_filename.c_str(), Pattern) != 0)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -781,20 +788,20 @@ static u32 RecursiveFindFiles(const char* OriginPath, const char* ParentPath, co
|
||||||
{
|
{
|
||||||
if (ParentPath != nullptr)
|
if (ParentPath != nullptr)
|
||||||
outData.FileName =
|
outData.FileName =
|
||||||
StringUtil::StdStringFromFormat("%s\\%s\\%s\\%s", OriginPath, ParentPath, Path, wfd.cFileName);
|
StringUtil::StdStringFromFormat("%s\\%s\\%s\\%s", OriginPath, ParentPath, Path, utf8_filename.c_str());
|
||||||
else if (Path != nullptr)
|
else if (Path != nullptr)
|
||||||
outData.FileName = StringUtil::StdStringFromFormat("%s\\%s\\%s", OriginPath, Path, wfd.cFileName);
|
outData.FileName = StringUtil::StdStringFromFormat("%s\\%s\\%s", OriginPath, Path, utf8_filename.c_str());
|
||||||
else
|
else
|
||||||
outData.FileName = StringUtil::StdStringFromFormat("%s\\%s", OriginPath, wfd.cFileName);
|
outData.FileName = StringUtil::StdStringFromFormat("%s\\%s", OriginPath, utf8_filename.c_str());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (ParentPath != nullptr)
|
if (ParentPath != nullptr)
|
||||||
outData.FileName = StringUtil::StdStringFromFormat("%s\\%s\\%s", ParentPath, Path, wfd.cFileName);
|
outData.FileName = StringUtil::StdStringFromFormat("%s\\%s\\%s", ParentPath, Path, utf8_filename.c_str());
|
||||||
else if (Path != nullptr)
|
else if (Path != nullptr)
|
||||||
outData.FileName = StringUtil::StdStringFromFormat("%s\\%s", Path, wfd.cFileName);
|
outData.FileName = StringUtil::StdStringFromFormat("%s\\%s", Path, utf8_filename.c_str());
|
||||||
else
|
else
|
||||||
outData.FileName = wfd.cFileName;
|
outData.FileName = utf8_filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
outData.ModificationTime.SetWindowsFileTime(&wfd.ftLastWriteTime);
|
outData.ModificationTime.SetWindowsFileTime(&wfd.ftLastWriteTime);
|
||||||
|
@ -802,7 +809,7 @@ static u32 RecursiveFindFiles(const char* OriginPath, const char* ParentPath, co
|
||||||
|
|
||||||
nFiles++;
|
nFiles++;
|
||||||
pResults->push_back(std::move(outData));
|
pResults->push_back(std::move(outData));
|
||||||
} while (FindNextFileA(hFind, &wfd) == TRUE);
|
} while (FindNextFileW(hFind, &wfd) == TRUE);
|
||||||
FindClose(hFind);
|
FindClose(hFind);
|
||||||
|
|
||||||
return nFiles;
|
return nFiles;
|
||||||
|
@ -822,14 +829,27 @@ bool FileSystem::FindFiles(const char* Path, const char* Pattern, u32 Flags, Fin
|
||||||
return (RecursiveFindFiles(Path, nullptr, nullptr, Pattern, Flags, pResults) > 0);
|
return (RecursiveFindFiles(Path, nullptr, nullptr, Pattern, Flags, pResults) > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileSystem::StatFile(const char* Path, FILESYSTEM_STAT_DATA* pStatData)
|
bool FileSystem::StatFile(const char* path, FILESYSTEM_STAT_DATA* pStatData)
|
||||||
{
|
{
|
||||||
// has a path
|
// has a path
|
||||||
if (Path[0] == '\0')
|
if (path[0] == '\0')
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// convert to wide string
|
||||||
|
int len = static_cast<int>(std::strlen(path));
|
||||||
|
int wlen = MultiByteToWideChar(CP_UTF8, 0, path, len, nullptr, 0);
|
||||||
|
if (wlen <= 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
wchar_t* wpath = static_cast<wchar_t*>(alloca(sizeof(wchar_t) * (wlen + 1)));
|
||||||
|
wlen = MultiByteToWideChar(CP_UTF8, 0, path, len, wpath, wlen);
|
||||||
|
if (wlen <= 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
wpath[wlen] = 0;
|
||||||
|
|
||||||
// determine attributes for the path. if it's a directory, things have to be handled differently..
|
// determine attributes for the path. if it's a directory, things have to be handled differently..
|
||||||
DWORD fileAttributes = GetFileAttributesA(Path);
|
DWORD fileAttributes = GetFileAttributesW(wpath);
|
||||||
if (fileAttributes == INVALID_FILE_ATTRIBUTES)
|
if (fileAttributes == INVALID_FILE_ATTRIBUTES)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -837,12 +857,12 @@ bool FileSystem::StatFile(const char* Path, FILESYSTEM_STAT_DATA* pStatData)
|
||||||
HANDLE hFile;
|
HANDLE hFile;
|
||||||
if (fileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
if (fileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||||
{
|
{
|
||||||
hFile = CreateFileA(Path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr,
|
hFile = CreateFileW(wpath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr,
|
||||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
|
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
hFile = CreateFileA(Path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr,
|
hFile = CreateFileW(wpath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr,
|
||||||
OPEN_EXISTING, 0, nullptr);
|
OPEN_EXISTING, 0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -167,33 +167,51 @@ std::size_t Strlcpy(char* dst, const std::string_view& src, std::size_t size)
|
||||||
|
|
||||||
std::wstring UTF8StringToWideString(const std::string_view& str)
|
std::wstring UTF8StringToWideString(const std::string_view& str)
|
||||||
{
|
{
|
||||||
int wlen = MultiByteToWideChar(CP_UTF8, 0, str.data(), static_cast<int>(str.length()), nullptr, 0);
|
|
||||||
if (wlen <= 0)
|
|
||||||
return {};
|
|
||||||
|
|
||||||
std::wstring ret;
|
std::wstring ret;
|
||||||
ret.resize(wlen);
|
if (!UTF8StringToWideString(ret, str))
|
||||||
if (MultiByteToWideChar(CP_UTF8, 0, str.data(), static_cast<int>(str.length()), ret.data(), wlen) <= 0)
|
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool UTF8StringToWideString(std::wstring& dest, const std::string_view& str)
|
||||||
|
{
|
||||||
|
int wlen = MultiByteToWideChar(CP_UTF8, 0, str.data(), static_cast<int>(str.length()), nullptr, 0);
|
||||||
|
if (wlen < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
dest.resize(wlen);
|
||||||
|
if (wlen > 0 && MultiByteToWideChar(CP_UTF8, 0, str.data(), static_cast<int>(str.length()), dest.data(), wlen) < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
std::string WideStringToUTF8String(const std::wstring_view& str)
|
std::string WideStringToUTF8String(const std::wstring_view& str)
|
||||||
{
|
{
|
||||||
int mblen = WideCharToMultiByte(CP_UTF8, 0, str.data(), static_cast<int>(str.length()), nullptr, 0, nullptr, nullptr);
|
|
||||||
if (mblen <= 0)
|
|
||||||
return {};
|
|
||||||
|
|
||||||
std::string ret;
|
std::string ret;
|
||||||
ret.resize(mblen);
|
if (!WideStringToUTF8String(ret, str))
|
||||||
if (WideCharToMultiByte(CP_UTF8, 0, str.data(), static_cast<int>(str.length()), ret.data(), mblen, nullptr, nullptr) <
|
|
||||||
0)
|
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WideStringToUTF8String(std::string& dest, const std::wstring_view& str)
|
||||||
|
{
|
||||||
|
int mblen = WideCharToMultiByte(CP_UTF8, 0, str.data(), static_cast<int>(str.length()), nullptr, 0, nullptr, nullptr);
|
||||||
|
if (mblen < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
dest.resize(mblen);
|
||||||
|
if (mblen > 0 && WideCharToMultiByte(CP_UTF8, 0, str.data(), static_cast<int>(str.length()), dest.data(), mblen,
|
||||||
|
nullptr, nullptr) < 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} // namespace StringUtil
|
} // namespace StringUtil
|
||||||
|
|
|
@ -117,9 +117,11 @@ ALWAYS_INLINE static bool StartsWith(const std::string_view& str, const char* pr
|
||||||
|
|
||||||
/// Converts the specified UTF-8 string to a wide string.
|
/// Converts the specified UTF-8 string to a wide string.
|
||||||
std::wstring UTF8StringToWideString(const std::string_view& str);
|
std::wstring UTF8StringToWideString(const std::string_view& str);
|
||||||
|
bool UTF8StringToWideString(std::wstring& dest, const std::string_view& str);
|
||||||
|
|
||||||
/// Converts the specified wide string to a UTF-8 string.
|
/// Converts the specified wide string to a UTF-8 string.
|
||||||
std::string WideStringToUTF8String(const std::wstring_view& str);
|
std::string WideStringToUTF8String(const std::wstring_view& str);
|
||||||
|
bool WideStringToUTF8String(std::string& dest, const std::wstring_view& str);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue