diff options
Diffstat (limited to 'source/Utils.cpp')
-rw-r--r-- | source/Utils.cpp | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/source/Utils.cpp b/source/Utils.cpp new file mode 100644 index 0000000..d47f35b --- /dev/null +++ b/source/Utils.cpp @@ -0,0 +1,58 @@ +#include "Utils.hpp" + +#ifdef _WIN32 +# include <Windows.h> +#endif + +#ifdef _WIN32 +# define BRUSSEL_MODE_STRING(string) L##string +#else +# define BRUSSEL_MODE_STRING(string) string +#endif + +#if _WIN32 +using FopenModeString = const wchar_t*; +#else +using FopenModeString = const char*; +#endif + +static FopenModeString GetModeString(Utils::IoMode mode, bool binary) { + using namespace Utils; + if (binary) { + switch (mode) { + case Read: return BRUSSEL_MODE_STRING("r"); + case WriteTruncate: return BRUSSEL_MODE_STRING("w"); + case WriteAppend: return BRUSSEL_MODE_STRING("a"); + } + } else { + switch (mode) { + case Read: return BRUSSEL_MODE_STRING("rb"); + case WriteTruncate: return BRUSSEL_MODE_STRING("wb"); + case WriteAppend: return BRUSSEL_MODE_STRING("ab"); + } + } + return nullptr; +} + +FILE* Utils::OpenCstdioFile(const std::filesystem::path& path, IoMode mode, bool binary) { +#ifdef _WIN32 + // std::filesystem::path::c_str() returns `const wchar_t*` under Windows, because NT uses UTF-16 natively + // NOTE: _wfopen() only affects the type of path parameter, otherwise the file stream created is identical to the one by fopen() + return _wfopen(path.c_str(), ::GetModeString(mode, binary)); +#else + return fopen(path.c_str(), ::GetModeString(mode, binary)); +#endif +} + +FILE* Utils::OpenCstdioFile(const char* path, IoMode mode, bool binary) { +#ifdef _WIN32 + // On Windows, fopen() accepts ANSI codepage encoded path, convert our UTF-8 string to UTF-16 to ensure that no matter what the locale is, the path continues to work + WCHAR platformPath[MAX_PATH]; + if (MultiByteToWideChar(CP_UTF8, 0, path, -1, platformPath, MAX_PATH) == 0) { + return nullptr; + } + return _wfopen(platformPath, ::GetModeString(mode, binary)); +#else + return fopen(path, ::GetModeString(mode, binary)); +#endif +} |