Files
pl/include/prelude/file.hpp

80 lines
1.7 KiB
C++

#pragma once
#include "prelude/string.hpp"
#include <cstdio>
class File
{
public:
enum class Mode
{
WRITE,
READ,
};
private:
File(FILE* handle, Mode mode)
: m_handle(handle), m_mode(mode) {}
public:
static File Open(const StringView& filename, Mode mode)
{
StringBuilder sb;
switch(mode)
{
case Mode::WRITE:
sb.Append('w');
break;
case Mode::READ:
sb.Append('r');
break;
}
FILE* handle = fopen(filename.c_str(), sb.c_str());
return File(handle, mode);
}
private:
inline bool Writable() const { return m_mode == File::Mode::WRITE; }
inline bool Readable() const { return m_mode == File::Mode::READ; }
public:
bool Write(const StringView& content)
{
assert(Writable() && "attempt to write to a file in read only mode");
if (fwrite(content.c_str(), sizeof(char), content.size - 1, m_handle) == 0)
{
return false;
}
return true;
}
public:
StringView ReadAll(bool* status = nullptr)
{
auto fail = [&]() -> StringView {
if (status) *status = false;
return {};
};
if (status) *status = true;
assert(Readable() && "attempt to read from a file in write only mode");
if (fseek(m_handle, 0, SEEK_END) != 0) return fail();
auto size = ftell(m_handle);
if (size == -1 && status) return fail();
StringBuilder sb;
sb.ensure_extra(size);
size_t wrote = fread(sb.data, sizeof(char), size, m_handle);
if (wrote == 0) return fail();
sb.size = wrote;
return sb.view();
}
private:
FILE* m_handle;
Mode m_mode;
};