Compare commits

..

2 Commits

Author SHA1 Message Date
cea0a4e0ed Add circular buffer to coral library
All checks were successful
continuous-integration/drone/push Build is passing
2023-02-20 21:58:36 +00:00
37b2586eaa Export app::readable_file for API use 2023-02-20 16:12:29 +00:00
2 changed files with 183 additions and 70 deletions

View File

@ -11,6 +11,7 @@ import coral.math;
import oar;
namespace app {
struct file_reader : public coral::file_reader {
enum class [[nodiscard]] close_result {
ok,
@ -95,6 +96,7 @@ struct file_reader : public coral::file_reader {
::SDL_RWops * rw_ops;
};
}
struct base_directory : public coral::fs {
base_directory() : directory_path{} {
@ -122,13 +124,13 @@ struct base_directory : public coral::fs {
void read_file(coral::path const & file_path, coral::callable<void(coral::file_reader &)> const & then) override {
if (this->directory_path.length == 0) return;
file_reader reader{this};
app::file_reader reader{this};
if (reader.open(file_path) != file_reader::open_result::ok) return;
if (reader.open(file_path) != app::file_reader::open_result::ok) return;
then(reader);
if (reader.close() != file_reader::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 {
@ -165,13 +167,13 @@ struct user_directory : public coral::fs {
void read_file(coral::path const & file_path, coral::callable<void(coral::file_reader &)> const & then) override {
if (this->directory_path.length == 0) return;
file_reader reader{this};
app::file_reader reader{this};
if (reader.open(file_path) != file_reader::open_result::ok) return;
if (reader.open(file_path) != app::file_reader::open_result::ok) return;
then(reader);
if (reader.close() != file_reader::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 {

View File

@ -452,12 +452,34 @@ export namespace coral {
unavailable,
};
/**
* Readable resource interface.
*/
struct reader {
virtual expected<usize, io_error> read(slice<u8> const & buffer) = 0;
virtual ~reader() {}
/**
* Attempts to fill `data` with whatever data the reader has to offer, returning the number
* of bytes actually read.
*
* Should the read operation fail for any reason, a [io_error] is returned instead.
*/
virtual expected<usize, io_error> read(slice<u8> const & data) = 0;
};
/**
* Writable resource interface.
*/
struct writer {
virtual expected<usize, io_error> write(slice<u8 const> const & buffer) = 0;
virtual ~writer() {}
/**
* Attempts to write `data` out to the writer, returning the number of bytes actually
* written.
*
* Should the write operation fail for any reason, a [io_error] is returned instead.
*/
virtual expected<usize, io_error> write(slice<u8 const> const & data) = 0;
};
}
@ -617,4 +639,93 @@ export namespace coral {
return a;
}
/**
* Multiplexing byte buffer of `capacity` size that may be used for memory-backed I/O
* operations and lightweight data construction.
*/
template<usize capacity> struct ring_buffer : public writer, public reader {
ring_buffer(coral::u8 fill_value) : data{fill_value} {}
/**
* Returns the base pointer of the buffer data.
*/
u8 * begin() {
return this->data;
}
/**
* Returns the base pointer of the buffer data.
*/
u8 const * begin() const {
return this->data;
}
/**
* Returns the tail pointer of the buffer data.
*/
u8 * end() {
return this->data + this->cursor;
}
/**
* Returns the tail pointer of the buffer data.
*/
u8 const * end() const {
return this->data + this->cursor;
}
/**
* Returns `true` if the buffer has been completely filled with data.
*/
bool is_full() const {
return this->filled == capacity;
}
/**
* Reads whatever data is in the buffer into `data`, returning the number of bytes read
* from the buffer.
*/
expected<usize, io_error> read(slice<u8> const & data) override {
slice const readable_data{this->data, min(this->filled, data.length)};
this->filled -= readable_data.length;
for (usize index = 0; index < readable_data.length; index += 1) {
data[index] = this->data[this->read_index];
this->read_index = (this->read_index + 1) % capacity;
}
return readable_data.length;
}
/**
* Attempts to write `data` to the buffer, returning the number of bytes written or
* [io_error::unavailable] if it has been completely filled and no more bytes can be
* written.
*/
expected<usize, io_error> write(slice<u8 const> const & data) override {
if (this->is_full()) return io_error::unavailable;
slice const writable_data{data.sliced(0, min(data.length, this->filled))};
this->filled += writable_data.length;
for (usize index = 0; index < writable_data.length; index += 1) {
this->data[this->write_index] = data[index];
this->write_index = (this->write_index + 1) % capacity;
}
return writable_data.length;
}
private:
usize filled = 0;
usize read_index = 0;
usize write_index = 0;
u8 data[capacity];
};
}