psemek/libs/io/source/file_stream.cpp

72 lines
1.5 KiB
C++

#include <psemek/io/file_stream.hpp>
#include <cstring>
#include <codecvt>
namespace psemek::io
{
static void throw_fopen [[noreturn]] (std::filesystem::path const & path)
{
throw std::runtime_error("Failed to open " + path.string() + ": " + std::string(std::strerror(errno)));
}
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 std::runtime_error("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_);
}
}