mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-26 15:45:42 +00:00
StringUtil: Add wide string<->utf8 conversion for Windows
This commit is contained in:
parent
ebf9f3b2e2
commit
3edb8e113e
|
@ -1,7 +1,12 @@
|
||||||
#include "string_util.h"
|
#include "string_util.h"
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
#include <codecvt>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#include "windows_headers.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace StringUtil {
|
namespace StringUtil {
|
||||||
|
|
||||||
std::string StdStringFromFormat(const char* format, ...)
|
std::string StdStringFromFormat(const char* format, ...)
|
||||||
|
@ -158,4 +163,37 @@ std::size_t Strlcpy(char* dst, const std::string_view& src, std::size_t size)
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
|
||||||
|
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;
|
||||||
|
ret.resize(wlen);
|
||||||
|
if (MultiByteToWideChar(CP_UTF8, 0, str.data(), static_cast<int>(str.length()), ret.data(), wlen) <= 0)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
ret.resize(mblen);
|
||||||
|
if (WideCharToMultiByte(CP_UTF8, 0, str.data(), static_cast<int>(str.length()), ret.data(), mblen, nullptr, nullptr) <
|
||||||
|
0)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace StringUtil
|
} // namespace StringUtil
|
||||||
|
|
|
@ -53,7 +53,7 @@ static inline int Strncasecmp(const char* s1, const char* s2, std::size_t n)
|
||||||
|
|
||||||
/// Wrapper arond std::from_chars
|
/// Wrapper arond std::from_chars
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline std::optional<T> FromChars(std::string_view str)
|
inline std::optional<T> FromChars(const std::string_view& str)
|
||||||
{
|
{
|
||||||
T value;
|
T value;
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ inline std::optional<T> FromChars(std::string_view str)
|
||||||
|
|
||||||
/// Explicit override for booleans
|
/// Explicit override for booleans
|
||||||
template<>
|
template<>
|
||||||
inline std::optional<bool> FromChars(std::string_view str)
|
inline std::optional<bool> FromChars(const std::string_view& str)
|
||||||
{
|
{
|
||||||
if (Strncasecmp("true", str.data(), str.length()) == 0 || Strncasecmp("yes", str.data(), str.length()) == 0 ||
|
if (Strncasecmp("true", str.data(), str.length()) == 0 || Strncasecmp("yes", str.data(), str.length()) == 0 ||
|
||||||
Strncasecmp("on", str.data(), str.length()) == 0 || Strncasecmp("1", str.data(), str.length()) == 0)
|
Strncasecmp("on", str.data(), str.length()) == 0 || Strncasecmp("1", str.data(), str.length()) == 0)
|
||||||
|
@ -94,7 +94,7 @@ inline std::optional<bool> FromChars(std::string_view str)
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
/// from_chars doesn't seem to work with floats on gcc
|
/// from_chars doesn't seem to work with floats on gcc
|
||||||
template<>
|
template<>
|
||||||
inline std::optional<float> FromChars(std::string_view str)
|
inline std::optional<float> FromChars(const std::string_view& str)
|
||||||
{
|
{
|
||||||
float value;
|
float value;
|
||||||
std::string temp(str);
|
std::string temp(str);
|
||||||
|
@ -108,9 +108,19 @@ inline std::optional<float> FromChars(std::string_view str)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// starts_with from C++20
|
/// starts_with from C++20
|
||||||
ALWAYS_INLINE static bool StartsWith(std::string_view str, const char* prefix)
|
ALWAYS_INLINE static bool StartsWith(const std::string_view& str, const char* prefix)
|
||||||
{
|
{
|
||||||
return (str.compare(0, std::strlen(prefix), prefix) == 0);
|
return (str.compare(0, std::strlen(prefix), prefix) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
|
||||||
|
/// Converts the specified UTF-8 string to a wide string.
|
||||||
|
std::wstring UTF8StringToWideString(const std::string_view& str);
|
||||||
|
|
||||||
|
/// Converts the specified wide string to a UTF-8 string.
|
||||||
|
std::string WideStringToUTF8String(const std::wstring_view& str);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace StringUtil
|
} // namespace StringUtil
|
||||||
|
|
|
@ -626,22 +626,11 @@ void CommonHostInterface::SetUserDirectory()
|
||||||
PWSTR documents_directory;
|
PWSTR documents_directory;
|
||||||
if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_Documents, 0, NULL, &documents_directory)))
|
if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_Documents, 0, NULL, &documents_directory)))
|
||||||
{
|
{
|
||||||
const size_t documents_directory_len = std::wcslen(documents_directory);
|
const std::string documents_directory_str(StringUtil::WideStringToUTF8String(documents_directory));
|
||||||
int documents_directory_u8len = WideCharToMultiByte(
|
if (!documents_directory_str.empty())
|
||||||
CP_UTF8, 0, documents_directory, static_cast<int>(documents_directory_len), nullptr, 0, nullptr, nullptr);
|
|
||||||
if (documents_directory_u8len > 0)
|
|
||||||
{
|
{
|
||||||
std::string documents_directory_str;
|
m_user_directory = StringUtil::StdStringFromFormat("%s%c%s", documents_directory_str.c_str(),
|
||||||
documents_directory_str.resize(documents_directory_u8len);
|
FS_OSPATH_SEPERATOR_CHARACTER, "DuckStation");
|
||||||
documents_directory_u8len = WideCharToMultiByte(
|
|
||||||
CP_UTF8, 0, documents_directory, static_cast<int>(documents_directory_len), documents_directory_str.data(),
|
|
||||||
static_cast<int>(documents_directory_str.size()), 0, nullptr);
|
|
||||||
if (documents_directory_u8len > 0)
|
|
||||||
{
|
|
||||||
documents_directory_str.resize(documents_directory_u8len);
|
|
||||||
m_user_directory = StringUtil::StdStringFromFormat("%s%c%s", documents_directory_str.c_str(),
|
|
||||||
FS_OSPATH_SEPERATOR_CHARACTER, "DuckStation");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
CoTaskMemFree(documents_directory);
|
CoTaskMemFree(documents_directory);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue