73 lines
1.6 KiB
C++
73 lines
1.6 KiB
C++
#include <psemek/io/file_stream.hpp>
|
|
#include <psemek/util/system_error.hpp>
|
|
|
|
#include <cstring>
|
|
#include <codecvt>
|
|
|
|
namespace psemek::io
|
|
{
|
|
|
|
static 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());
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
file_istream::file_istream(std::filesystem::path const & path)
|
|
: file_{safe_fopen(path.c_str(), "rb")}
|
|
{}
|
|
|
|
void file_istream::reset()
|
|
{
|
|
if (file_)
|
|
std::fclose(file_);
|
|
file_ = nullptr;
|
|
}
|
|
|
|
std::size_t file_istream::read(char * p, std::size_t size)
|
|
{
|
|
if (!file_) throw null_istream{};
|
|
return std::fread(p, 1, size, file_);
|
|
}
|
|
|
|
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))}
|
|
{}
|
|
|
|
void file_ostream::reset()
|
|
{
|
|
if (file_)
|
|
std::fclose(file_);
|
|
file_ = nullptr;
|
|
}
|
|
|
|
std::size_t file_ostream::write(char const * p, std::size_t size)
|
|
{
|
|
if (!file_) throw null_ostream{};
|
|
return std::fwrite(p, 1, size, file_);
|
|
}
|
|
|
|
void file_ostream::flush()
|
|
{
|
|
if (!file_) throw null_ostream{};
|
|
std::fflush(file_);
|
|
}
|
|
|
|
}
|