|
|
|
@ -2,9 +2,10 @@ export module coral.sequence;
|
|
|
|
|
|
|
|
|
|
import coral;
|
|
|
|
|
|
|
|
|
|
// Collections.
|
|
|
|
|
export namespace coral {
|
|
|
|
|
/**
|
|
|
|
|
* Result codes used by [sequence]-derived types when they are appended to in any way.
|
|
|
|
|
* Result codes used by [contiguous_range]-derived types when they are appended to in any way.
|
|
|
|
|
*
|
|
|
|
|
* [append_result::ok] indicates that an append operation was successful.
|
|
|
|
|
*
|
|
|
|
@ -17,27 +18,36 @@ export namespace coral {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Base type for all sequence-like types.
|
|
|
|
|
* Base type for all collections which store their elements as a single block of contiguous
|
|
|
|
|
* memory.
|
|
|
|
|
*
|
|
|
|
|
* Sequences are any data structure which owns a linear, non-unique set of elements which may
|
|
|
|
|
* be queried and/or mutated.
|
|
|
|
|
*/
|
|
|
|
|
template<typename element> struct sequence {
|
|
|
|
|
virtual ~sequence() {};
|
|
|
|
|
template<typename element> struct contiguous_range {
|
|
|
|
|
virtual ~contiguous_range() {};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Attempts to append `source_elements` to the sequence.
|
|
|
|
|
* Attempts to append `source_elements` to the contiguous_range.
|
|
|
|
|
*
|
|
|
|
|
* The returned [append_result] indicates whether the operation was successful or not.
|
|
|
|
|
*
|
|
|
|
|
* If the returned [append_result] is anything but [append_result::ok], the [sequence] will
|
|
|
|
|
* be left in an implementation-defined state.
|
|
|
|
|
* If the returned [append_result] is anything but [append_result::ok], the
|
|
|
|
|
* [contiguous_range] will be left in an implementation-defined state.
|
|
|
|
|
*/
|
|
|
|
|
virtual append_result append(slice<element const> const & source_elements) = 0;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns a read-only [slice] of the current range values.
|
|
|
|
|
*
|
|
|
|
|
* *Note*: the behavior of retaining the returned value past the scope of the source
|
|
|
|
|
* [contiguous_range] or any subsequent modifications to it is implementation-defined.
|
|
|
|
|
*/
|
|
|
|
|
virtual slice<element const> as_slice() = 0;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Last-in-first-out linear sequence of `element` values.
|
|
|
|
|
* Last-in-first-out contiguous range of `element` values.
|
|
|
|
|
*
|
|
|
|
|
* [stack] types will default to using an inline array of `init_capacity` at first. After all
|
|
|
|
|
* local storage has been exhausted, the [stack] will switch to a dynamic buffer. Because of
|
|
|
|
@ -48,7 +58,7 @@ export namespace coral {
|
|
|
|
|
* *Note*: the [allocator] referenced in the stack must remain valid for the duration of the
|
|
|
|
|
* stack lifetime.
|
|
|
|
|
*/
|
|
|
|
|
template<typename element, usize init_capacity = 1> struct stack : public sequence<element> {
|
|
|
|
|
template<typename element, usize init_capacity = 1> struct stack : public contiguous_range<element> {
|
|
|
|
|
stack(allocator * dynamic_allocator) {
|
|
|
|
|
this->dynamic_allocator = dynamic_allocator;
|
|
|
|
|
}
|
|
|
|
@ -89,31 +99,13 @@ export namespace coral {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns the beginning of the elements as a mutable pointer.
|
|
|
|
|
* Returns a read-only [slice] of the current stack values.
|
|
|
|
|
*
|
|
|
|
|
* *Note*: the returned slice should be considered invalid if any mutable operation is
|
|
|
|
|
* performed on the source [stack] or it is no longer in scope.
|
|
|
|
|
*/
|
|
|
|
|
element * begin() {
|
|
|
|
|
return this->elements.pointer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns the beginning of the elements as a const pointer.
|
|
|
|
|
*/
|
|
|
|
|
element const * begin() const {
|
|
|
|
|
return this->elements.pointer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns the ending of the elements as a mutable pointer.
|
|
|
|
|
*/
|
|
|
|
|
element * end() {
|
|
|
|
|
return this->elements.pointer + this->filled;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns the ending of the elements as a const pointer.
|
|
|
|
|
*/
|
|
|
|
|
element const * end() const {
|
|
|
|
|
return this->elements.pointer + this->filled;
|
|
|
|
|
slice<element const> as_slice() override {
|
|
|
|
|
return this->elements.sliced(0, this->filled);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@ -200,17 +192,22 @@ export namespace coral {
|
|
|
|
|
|
|
|
|
|
u8 local_buffer[init_capacity]{0};
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
using contiguous_byte_range = coral::contiguous_range<coral::u8>;
|
|
|
|
|
|
|
|
|
|
// Reader / writers.
|
|
|
|
|
export namespace coral {
|
|
|
|
|
/**
|
|
|
|
|
* Writable type for appending data to a [sequence] containing [u8] values.
|
|
|
|
|
* Readable type for streaming data from a [contiguous_range] containing [u8] values.
|
|
|
|
|
*/
|
|
|
|
|
struct sequence_writer : public writer {
|
|
|
|
|
sequence_writer(sequence<u8> * output_sequence) {
|
|
|
|
|
this->output_sequence = output_sequence;
|
|
|
|
|
struct contiguous_reader : public reader {
|
|
|
|
|
contiguous_reader(contiguous_byte_range * range) {
|
|
|
|
|
this->range = range;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
expected<usize, io_error> write(slice<u8 const> const & buffer) {
|
|
|
|
|
switch (output_sequence->append(buffer)) {
|
|
|
|
|
switch (this->range->append(buffer)) {
|
|
|
|
|
case append_result::ok: return buffer.length;
|
|
|
|
|
case append_result::out_of_memory: return io_error::unavailable;
|
|
|
|
|
default: unreachable();
|
|
|
|
@ -218,6 +215,26 @@ export namespace coral {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
sequence<u8> * output_sequence;
|
|
|
|
|
contiguous_byte_range * range;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Writable type for appending data to a [contiguous_range] containing [u8] values.
|
|
|
|
|
*/
|
|
|
|
|
struct contiguous_writer : public writer {
|
|
|
|
|
contiguous_writer(contiguous_byte_range * range) {
|
|
|
|
|
this->range = range;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
expected<usize, io_error> write(slice<u8 const> const & buffer) {
|
|
|
|
|
switch (this->range->append(buffer)) {
|
|
|
|
|
case append_result::ok: return buffer.length;
|
|
|
|
|
case append_result::out_of_memory: return io_error::unavailable;
|
|
|
|
|
default: unreachable();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
contiguous_byte_range * range;
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|