Tidy up main coral module file
This commit is contained in:
parent
809b45dc3c
commit
cd3fd2f04a
197
source/coral.cpp
197
source/coral.cpp
|
@ -94,17 +94,14 @@ export namespace coral {
|
|||
/**
|
||||
* Number of `type` elements referenced.
|
||||
*/
|
||||
usize length;
|
||||
usize length{0};
|
||||
|
||||
/**
|
||||
* Base element address referenced.
|
||||
*/
|
||||
type * pointer;
|
||||
type * pointer{nullptr};
|
||||
|
||||
constexpr slice() {
|
||||
this->length = 0;
|
||||
this->pointer = nullptr;
|
||||
}
|
||||
constexpr slice() = default;
|
||||
|
||||
constexpr slice(char const *&& zstring) {
|
||||
this->pointer = zstring;
|
||||
|
@ -268,6 +265,24 @@ export [[nodiscard]] void * operator new[](coral::usize requested_size, coral::a
|
|||
return allocator.reallocate(nullptr, requested_size);
|
||||
}
|
||||
|
||||
/**
|
||||
* If `pointer` is a non-`nullptr` value, the referenced memory will be deallocated using
|
||||
* `allocator`. Otherwise, the function has no side-effects.
|
||||
*
|
||||
* *Note*: passing a `pointer` value that was not allocated by `allocator` will result in erroneous
|
||||
* behavior defined by the [coral::allocator] implementation.
|
||||
*/
|
||||
export void operator delete(void * pointer, coral::allocator & allocator) {
|
||||
return allocator.deallocate(pointer);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export void operator delete[](void * pointer, coral::allocator & allocator) {
|
||||
return allocator.deallocate(pointer);
|
||||
}
|
||||
|
||||
// Wrapper types.
|
||||
export namespace coral {
|
||||
/**
|
||||
|
@ -558,174 +573,4 @@ export namespace coral {
|
|||
a = b;
|
||||
b = temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Streams the data from `input` to `output`, using `buffer` as temporary transfer space.
|
||||
*
|
||||
* The returned [expected] can be used to introspect if `input` or `output` encountered any
|
||||
* issues during streaming, otherwise it will contain the number of bytes streamed.
|
||||
*
|
||||
* *Note*: if `buffer` has a length of `0`, no data will be streamed as there is nowhere to
|
||||
* temporarily place data during streaming.
|
||||
*/
|
||||
expected<usize, io_error> stream(writer & output, reader & input, slice<u8> const & buffer) {
|
||||
usize total_bytes_written = 0;
|
||||
expected bytes_read = input.read(buffer);
|
||||
|
||||
if (!bytes_read.is_ok()) return bytes_read.error();
|
||||
|
||||
usize read = bytes_read.value();
|
||||
|
||||
while (read != 0) {
|
||||
expected const bytes_written = output.write(buffer.sliced(0, read));
|
||||
|
||||
if (!bytes_written.is_ok()) return bytes_read.error();
|
||||
|
||||
total_bytes_written += bytes_written.value();
|
||||
bytes_read = input.read(buffer);
|
||||
|
||||
if (!bytes_read.is_ok()) return bytes_read.error();
|
||||
|
||||
read = bytes_read.value();
|
||||
}
|
||||
|
||||
return total_bytes_written;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to format and print `value` as an unsigned integer out to `output`.
|
||||
*
|
||||
* The returned [expected] can be used to introspect if `output` encountered any issues during
|
||||
* printing, otherwise it will contain the number of characters used to print `value` as text.
|
||||
*/
|
||||
expected<usize, io_error> print_unsigned(writer & output, u64 value) {
|
||||
if (value == 0) return output.write(slice{"0"}.as_bytes());
|
||||
|
||||
u8 buffer[20]{0};
|
||||
usize buffer_count{0};
|
||||
|
||||
while (value != 0) {
|
||||
constexpr usize radix{10};
|
||||
|
||||
buffer[buffer_count] = static_cast<u8>((value % radix) + '0');
|
||||
value = (value / radix);
|
||||
buffer_count += 1;
|
||||
}
|
||||
|
||||
usize const half_buffer_count{buffer_count / 2};
|
||||
|
||||
for (usize i = 0; i < half_buffer_count; i += 1)
|
||||
swap(buffer[i], buffer[buffer_count - i - 1]);
|
||||
|
||||
return output.write({buffer, buffer_count});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to a shared [allocator] which will always return `nullptr` on calls to
|
||||
* [allocator::reallocate].
|
||||
*/
|
||||
allocator & null_allocator() {
|
||||
static struct : public allocator {
|
||||
u8 * reallocate(u8 * maybe_allocation, usize requested_size) override {
|
||||
if (maybe_allocation != nullptr) unreachable();
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void deallocate(void * allocation) override {
|
||||
if (allocation != nullptr) unreachable();
|
||||
}
|
||||
} a;
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplexing byte-based ring buffer of `capacity` size that may be used for memory-backed
|
||||
* I/O operations and lightweight data construction.
|
||||
*/
|
||||
template<usize capacity> struct fixed_buffer : public writer, public reader {
|
||||
fixed_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];
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue