Tidy up and fix app::file API
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
fd62ec5966
commit
5d4f40393b
104
source/app.cpp
104
source/app.cpp
|
@ -13,10 +13,23 @@ import oar;
|
||||||
|
|
||||||
namespace app {
|
namespace app {
|
||||||
struct directory : public coral::fs {
|
struct directory : public coral::fs {
|
||||||
|
struct rules {
|
||||||
|
bool can_read;
|
||||||
|
|
||||||
|
bool can_write;
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual rules access_rules() const = 0;
|
||||||
|
|
||||||
virtual coral::slice<char const> native_path() const = 0;
|
virtual coral::slice<char const> native_path() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct file_reader : public coral::file_reader {
|
struct file : public coral::file_reader, public coral::file_writer {
|
||||||
|
enum class open_mode {
|
||||||
|
read_only,
|
||||||
|
overwrite,
|
||||||
|
};
|
||||||
|
|
||||||
enum class [[nodiscard]] close_result {
|
enum class [[nodiscard]] close_result {
|
||||||
ok,
|
ok,
|
||||||
io_unavailable,
|
io_unavailable,
|
||||||
|
@ -29,7 +42,7 @@ namespace app {
|
||||||
not_found,
|
not_found,
|
||||||
};
|
};
|
||||||
|
|
||||||
file_reader(directory * file_directory) : rw_ops{nullptr} {
|
file(directory * file_directory) : rw_ops{nullptr} {
|
||||||
this->file_directory = file_directory;
|
this->file_directory = file_directory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +58,7 @@ namespace app {
|
||||||
return this->rw_ops != nullptr;
|
return this->rw_ops != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
open_result open(coral::path const & file_path) {
|
open_result open(coral::path const & file_path, open_mode mode) {
|
||||||
if (this->is_open()) switch (this->close()) {
|
if (this->is_open()) switch (this->close()) {
|
||||||
case close_result::ok: break;
|
case close_result::ok: break;
|
||||||
case close_result::io_unavailable: return open_result::io_unavailable;
|
case close_result::io_unavailable: return open_result::io_unavailable;
|
||||||
|
@ -67,21 +80,43 @@ namespace app {
|
||||||
// No room for zero terminator.
|
// No room for zero terminator.
|
||||||
if (path_buffer.is_full()) return open_result::not_found;
|
if (path_buffer.is_full()) return open_result::not_found;
|
||||||
|
|
||||||
this->rw_ops = ::SDL_RWFromFile(reinterpret_cast<char const *>(path_buffer.begin()), "r");
|
switch (mode) {
|
||||||
|
case open_mode::read_only: {
|
||||||
|
if (!this->file_directory->access_rules().can_read)
|
||||||
|
return open_result::access_denied;
|
||||||
|
|
||||||
|
this->rw_ops = ::SDL_RWFromFile(
|
||||||
|
reinterpret_cast<char const *>(path_buffer.begin()), "rb");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case open_mode::overwrite: {
|
||||||
|
if (!this->file_directory->access_rules().can_write)
|
||||||
|
return open_result::access_denied;
|
||||||
|
|
||||||
|
this->rw_ops = ::SDL_RWFromFile(
|
||||||
|
reinterpret_cast<char const *>(path_buffer.begin()), "wb");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: coral::unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
if (this->rw_ops == nullptr) return open_result::not_found;
|
if (this->rw_ops == nullptr) return open_result::not_found;
|
||||||
|
|
||||||
return open_result::ok;
|
return open_result::ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
coral::expected<coral::usize, coral::io_error> read(coral::slice<coral::u8> const & buffer) override {
|
coral::expected<coral::usize, coral::io_error> read(coral::slice<coral::u8> const & data) override {
|
||||||
if (!this->is_open()) return coral::io_error::unavailable;
|
if (!this->is_open()) return coral::io_error::unavailable;
|
||||||
|
|
||||||
coral::usize const bytes_read{::SDL_RWread(this->rw_ops, buffer.pointer, sizeof(uint8_t), buffer.length)};
|
coral::usize const data_read{::SDL_RWread(this->rw_ops, data.pointer, sizeof(uint8_t), data.length)};
|
||||||
|
|
||||||
if ((bytes_read == 0) && (::SDL_GetError() != nullptr)) return coral::io_error::unavailable;
|
if ((data_read == 0) && (::SDL_GetError() != nullptr)) return coral::io_error::unavailable;
|
||||||
|
|
||||||
return bytes_read;
|
return data_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
coral::expected<coral::u64, coral::io_error> seek(coral::u64 offset) override {
|
coral::expected<coral::u64, coral::io_error> seek(coral::u64 offset) override {
|
||||||
|
@ -106,6 +141,16 @@ namespace app {
|
||||||
return static_cast<coral::u64>(byte_position);
|
return static_cast<coral::u64>(byte_position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
coral::expected<coral::usize, coral::io_error> write(coral::slice<coral::u8 const> const & data) override {
|
||||||
|
if (!this->is_open()) return coral::io_error::unavailable;
|
||||||
|
|
||||||
|
coral::usize const data_written{::SDL_RWwrite(this->rw_ops, data.pointer, sizeof(uint8_t), data.length)};
|
||||||
|
|
||||||
|
if ((data_written == 0) && (::SDL_GetError() != nullptr)) return coral::io_error::unavailable;
|
||||||
|
|
||||||
|
return data_written;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
directory * file_directory;
|
directory * file_directory;
|
||||||
|
|
||||||
|
@ -136,6 +181,13 @@ struct base_directory : public app::directory {
|
||||||
::SDL_free(this->directory_path.begin());
|
::SDL_free(this->directory_path.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rules access_rules() const override {
|
||||||
|
return {
|
||||||
|
.can_read = true,
|
||||||
|
.can_write = false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
coral::slice<const char> native_path() const override {
|
coral::slice<const char> native_path() const override {
|
||||||
return this->directory_path;
|
return this->directory_path;
|
||||||
}
|
}
|
||||||
|
@ -143,13 +195,14 @@ struct base_directory : public app::directory {
|
||||||
void read_file(coral::path const & file_path, coral::callable<void(coral::file_reader &)> const & then) override {
|
void read_file(coral::path const & file_path, coral::callable<void(coral::file_reader &)> const & then) override {
|
||||||
if (this->directory_path.length == 0) return;
|
if (this->directory_path.length == 0) return;
|
||||||
|
|
||||||
app::file_reader reader{this};
|
app::file file{this};
|
||||||
|
|
||||||
if (reader.open(file_path) != app::file_reader::open_result::ok) return;
|
if (file.open(file_path, app::file::open_mode::read_only) != app::file::open_result::ok)
|
||||||
|
return;
|
||||||
|
|
||||||
then(reader);
|
then(file);
|
||||||
|
|
||||||
if (reader.close() != app::file_reader::close_result::ok) return;
|
if (file.close() != app::file::close_result::ok) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_file(coral::path const & file_path, coral::callable<void(coral::file_writer &)> const & then) override {
|
void write_file(coral::path const & file_path, coral::callable<void(coral::file_writer &)> const & then) override {
|
||||||
|
@ -183,6 +236,13 @@ struct user_directory : public app::directory {
|
||||||
::SDL_free(this->directory_path.begin());
|
::SDL_free(this->directory_path.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rules access_rules() const override {
|
||||||
|
return {
|
||||||
|
.can_read = true,
|
||||||
|
.can_write = false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
coral::slice<const char> native_path() const override {
|
coral::slice<const char> native_path() const override {
|
||||||
return this->directory_path;
|
return this->directory_path;
|
||||||
}
|
}
|
||||||
|
@ -190,17 +250,27 @@ struct user_directory : public app::directory {
|
||||||
void read_file(coral::path const & file_path, coral::callable<void(coral::file_reader &)> const & then) override {
|
void read_file(coral::path const & file_path, coral::callable<void(coral::file_reader &)> const & then) override {
|
||||||
if (this->directory_path.length == 0) return;
|
if (this->directory_path.length == 0) return;
|
||||||
|
|
||||||
app::file_reader reader{this};
|
app::file file{this};
|
||||||
|
|
||||||
if (reader.open(file_path) != app::file_reader::open_result::ok) return;
|
if (file.open(file_path, app::file::open_mode::read_only) != app::file::open_result::ok)
|
||||||
|
return;
|
||||||
|
|
||||||
then(reader);
|
then(file);
|
||||||
|
|
||||||
if (reader.close() != app::file_reader::close_result::ok) return;
|
if (file.close() != app::file::close_result::ok) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_file(coral::path const & file_path, coral::callable<void(coral::file_writer &)> const & then) override {
|
void write_file(coral::path const & file_path, coral::callable<void(coral::file_writer &)> const & then) override {
|
||||||
// Directory is read-only.
|
if (this->directory_path.length == 0) return;
|
||||||
|
|
||||||
|
app::file file{this};
|
||||||
|
|
||||||
|
if (file.open(file_path, app::file::open_mode::overwrite) != app::file::open_result::ok)
|
||||||
|
return;
|
||||||
|
|
||||||
|
then(file);
|
||||||
|
|
||||||
|
if (file.close() != app::file::close_result::ok) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
Loading…
Reference in New Issue