Compare commits

..

No commits in common. "5d4f40393b8b98a984315c2f5273757185a3afc6" and "cea0a4e0ed90c54dc743f1ec78a87ad280948287" have entirely different histories.

2 changed files with 38 additions and 134 deletions

View File

@ -12,24 +12,7 @@ import coral.math;
import oar; import oar;
namespace app { namespace app {
struct directory : public coral::fs { struct file_reader : public coral::file_reader {
struct rules {
bool can_read;
bool can_write;
};
virtual rules access_rules() const = 0;
virtual coral::slice<char const> native_path() const = 0;
};
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,
@ -42,8 +25,8 @@ namespace app {
not_found, not_found,
}; };
file(directory * file_directory) : rw_ops{nullptr} { file_reader(coral::fs * fs) : rw_ops{nullptr} {
this->file_directory = file_directory; this->fs = fs;
} }
close_result close() { close_result close() {
@ -58,65 +41,28 @@ namespace app {
return this->rw_ops != nullptr; return this->rw_ops != nullptr;
} }
open_result open(coral::path const & file_path, open_mode mode) { open_result open(coral::path const & file_path) {
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;
default: coral::unreachable(); default: coral::unreachable();
} }
// Windows system path max is something like 512 bytes (depending on the version) and this->rw_ops = ::SDL_RWFromFile(reinterpret_cast<char const *>(this->path_buffer), "r");
// on Linux it's 4096.
coral::fixed_buffer<4096> path_buffer{0};
if (!path_buffer.write(this->file_directory->native_path().as_bytes()).is_ok())
// What kind of directory path is being used that would be longer than 4096 bytes?
return open_result::not_found;
if (!path_buffer.write(file_path.as_slice().as_bytes()).is_ok())
// This happening is still implausible but slightly more reasonable?
return open_result::not_found;
// No room for zero terminator.
if (path_buffer.is_full()) return open_result::not_found;
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 & data) override { coral::expected<coral::usize, coral::io_error> read(coral::slice<coral::u8> const & buffer) override {
if (!this->is_open()) return coral::io_error::unavailable; if (!this->is_open()) return coral::io_error::unavailable;
coral::usize const data_read{::SDL_RWread(this->rw_ops, data.pointer, sizeof(uint8_t), data.length)}; coral::usize const bytes_read{::SDL_RWread(this->rw_ops, buffer.pointer, sizeof(uint8_t), buffer.length)};
if ((data_read == 0) && (::SDL_GetError() != nullptr)) return coral::io_error::unavailable; if ((bytes_read == 0) && (::SDL_GetError() != nullptr)) return coral::io_error::unavailable;
return data_read; return bytes_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 {
@ -141,24 +87,18 @@ 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; static constexpr coral::usize path_max{4096};
coral::u8 path_buffer[path_max];
coral::fs * fs;
::SDL_RWops * rw_ops; ::SDL_RWops * rw_ops;
}; };
} }
struct base_directory : public app::directory { struct base_directory : public coral::fs {
base_directory() : directory_path{} { base_directory() : directory_path{} {
char * const path{::SDL_GetBasePath()}; char * const path{::SDL_GetBasePath()};
@ -181,28 +121,16 @@ 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 {
return this->directory_path;
}
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 file{this}; app::file_reader reader{this};
if (file.open(file_path, app::file::open_mode::read_only) != app::file::open_result::ok) if (reader.open(file_path) != app::file_reader::open_result::ok) return;
return;
then(file); then(reader);
if (file.close() != app::file::close_result::ok) return; if (reader.close() != app::file_reader::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 {
@ -213,7 +141,7 @@ struct base_directory : public app::directory {
coral::slice<char> directory_path; coral::slice<char> directory_path;
}; };
struct user_directory : public app::directory { struct user_directory : public coral::fs {
user_directory(coral::path const & title) : directory_path{} { user_directory(coral::path const & title) : directory_path{} {
char * const path{::SDL_GetPrefPath("ona", title.begin())}; char * const path{::SDL_GetPrefPath("ona", title.begin())};
@ -236,41 +164,20 @@ 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 {
return this->directory_path;
}
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 file{this}; app::file_reader reader{this};
if (file.open(file_path, app::file::open_mode::read_only) != app::file::open_result::ok) if (reader.open(file_path) != app::file_reader::open_result::ok) return;
return;
then(file); then(reader);
if (file.close() != app::file::close_result::ok) return; if (reader.close() != app::file_reader::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 {
if (this->directory_path.length == 0) return; // Directory is read-only.
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:
@ -285,11 +192,10 @@ export namespace app {
}; };
struct system { struct system {
system(coral::path const & title) : user_directory{title}, system(coral::path const & title) : res{&base, "base_directory.oar"}, user{title} {}
res_archive{&base_directory, res_archive_path} {}
app::directory & base_dir() { coral::fs & base_fs() {
return this->base_directory; return this->base;
} }
bool poll() { bool poll() {
@ -303,7 +209,7 @@ export namespace app {
} }
coral::fs & res_fs() { coral::fs & res_fs() {
return this->res_archive; return this->res;
} }
void log(app::log_level level, coral::slice<char const> const & message) { void log(app::log_level level, coral::slice<char const> const & message) {
@ -318,13 +224,11 @@ export namespace app {
return this->allocator; return this->allocator;
} }
app::directory & user_dir() { coral::fs & user_fs() {
return this->user_directory; return this->user;
} }
private: private:
static constexpr coral::path res_archive_path{"base.oar"};
::SDL_Event sdl_event; ::SDL_Event sdl_event;
struct : public coral::allocator { struct : public coral::allocator {
@ -337,11 +241,11 @@ export namespace app {
} }
} allocator; } allocator;
struct base_directory base_directory; base_directory base;
struct user_directory user_directory; user_directory user;
oar::archive res_archive; oar::archive res;
}; };
struct graphics { struct graphics {

View File

@ -641,11 +641,11 @@ export namespace coral {
} }
/** /**
* Multiplexing byte-based ring buffer of `capacity` size that may be used for memory-backed * Multiplexing byte buffer of `capacity` size that may be used for memory-backed I/O
* I/O operations and lightweight data construction. * operations and lightweight data construction.
*/ */
template<usize capacity> struct fixed_buffer : public writer, public reader { template<usize capacity> struct ring_buffer : public writer, public reader {
fixed_buffer(coral::u8 fill_value) : data{fill_value} {} ring_buffer(coral::u8 fill_value) : data{fill_value} {}
/** /**
* Returns the base pointer of the buffer data. * Returns the base pointer of the buffer data.