80 lines
1.7 KiB
C++
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;
|
|
};
|