Use wide strings for io::file_stream on Windows

This commit is contained in:
Nikita Lisitsa 2025-03-04 18:12:21 +03:00
parent dab7b6327e
commit ef85eec178

View file

@ -1,27 +1,72 @@
#include <psemek/io/file_stream.hpp>
#include <psemek/util/system_error.hpp>
#include <psemek/util/enum.hpp>
#include <cstring>
#include <codecvt>
namespace psemek::io
{
static void throw_fopen [[noreturn]] (std::filesystem::path const & path)
namespace
{
throw util::system_error(std::error_code{errno, std::system_category()}, "Failed to open " + path.string());
}
static FILE * safe_fopen(std::filesystem::path const & path, const char * mode)
{
std::string path_str = path.string();
auto f = std::fopen(path_str.c_str(), mode);
if (!f) throw_fopen(path);
return f;
void throw_fopen [[noreturn]] (std::filesystem::path const & path)
{
throw util::system_error(std::error_code{errno, std::system_category()}, "Failed to open " + path.string());
}
#ifdef __WIN32__
wchar_t const * fopen_read_mode()
{
return L"rb";
}
wchar_t const * fopen_write_mode(unsigned flags)
{
switch (flags)
{
case 0: return L"wb";
case file_ostream::append: return L"ab";
}
throw util::exception("Unknown file_ostream open flags");
}
FILE * safe_fopen(std::filesystem::path const & path, wchar_t const * mode)
{
auto f = _wfopen(path.c_str(), mode);
if (!f) throw_fopen(path);
return f;
}
#else
char const * fopen_read_mode()
{
return "rb";
}
char const * fopen_write_mode(unsigned flags)
{
switch (flags)
{
case 0: return "wb";
case file_ostream::append: return "ab";
}
throw util::exception("Unknown file_ostream open flags");
}
FILE * safe_fopen(std::filesystem::path const & path, char const * mode)
{
auto f = std::fopen(path.c_str(), mode);
if (!f) throw_fopen(path);
return f;
}
#endif
}
file_istream::file_istream(std::filesystem::path const & path)
: file_{safe_fopen(path.c_str(), "rb")}
: file_{safe_fopen(path, fopen_read_mode())}
{}
void file_istream::reset()
@ -43,18 +88,8 @@ namespace psemek::io
return std::feof(file_) != 0;
}
static char const * fopen_write_mode(unsigned flags)
{
switch (flags)
{
case 0: return "wb";
case file_ostream::append: return "ab";
default: throw util::exception("Unknown file_ostream open flags");
}
}
file_ostream::file_ostream(std::filesystem::path const & path, unsigned flags)
: file_{safe_fopen(path.c_str(), fopen_write_mode(flags))}
: file_{safe_fopen(path, fopen_write_mode(flags))}
{}
void file_ostream::reset()