diff options
Diffstat (limited to 'src/core/buffer.h')
-rw-r--r-- | src/core/buffer.h | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/src/core/buffer.h b/src/core/buffer.h new file mode 100644 index 0000000..4485ff1 --- /dev/null +++ b/src/core/buffer.h @@ -0,0 +1,195 @@ +#pragma once + +#include "error.h" + +#include <array> +#include <cstdint> +#include <deque> +#include <list> +#include <string> +#include <vector> + +namespace saw { +/* + * Access class to reduce templated BufferSegments bloat + */ +class buffer { +protected: + ~buffer() = default; + +public: + virtual size_t read_position() const = 0; + virtual size_t read_composite_length() const = 0; + virtual size_t read_segment_length(size_t offset = 0) const = 0; + virtual void read_advance(size_t bytes) = 0; + + virtual uint8_t &read(size_t i = 0) = 0; + virtual const uint8_t &read(size_t i = 0) const = 0; + + virtual size_t write_position() const = 0; + virtual size_t write_composite_length() const = 0; + virtual size_t write_segment_length(size_t offset = 0) const = 0; + virtual void write_advance(size_t bytes) = 0; + + virtual uint8_t &write(size_t i = 0) = 0; + virtual const uint8_t &write(size_t i = 0) const = 0; + + /* + * Sometime buffers need to grow with a little more control + * than with push and pop for more efficient calls. + * There is nothing you can do if read hasn't been filled, but at + * least write can be increased if it is demanded. + */ + virtual error write_require_length(size_t bytes) = 0; + + error push(const uint8_t &value); + error push(const uint8_t &buffer, size_t size); + error pop(uint8_t &value); + error pop(uint8_t &buffer, size_t size); + + /* + * Subject to change + */ + std::string to_string() const; + std::string to_hex() const; +}; + +/* + * A viewer class for buffers. + * Working on the reference buffer invalidates the buffer view + */ +class buffer_view : public buffer { +private: + buffer &buffer_; + size_t read_offset_; + size_t write_offset_; + +public: + buffer_view(buffer &); + + size_t read_position() const override; + size_t read_composite_length() const override; + size_t read_segment_length(size_t offset = 0) const override; + void read_advance(size_t bytes) override; + + uint8_t &read(size_t i = 0) override; + const uint8_t &read(size_t i = 0) const override; + + size_t write_position() const override; + size_t write_composite_length() const override; + size_t write_segment_length(size_t offset = 0) const override; + void write_advance(size_t bytes) override; + + uint8_t &write(size_t i = 0) override; + const uint8_t &write(size_t i = 0) const override; + + error write_require_length(size_t bytes) override; + + size_t read_offset() const; + size_t write_offset() const; +}; + +/* + * Buffer size meant for default allocation size of the ringbuffer since + * this class currently doesn't support proper resizing + */ +constexpr size_t RING_BUFFER_MAX_SIZE = 4096; +/* + * Buffer wrapping around if read caught up + */ +class ring_buffer final : public buffer { +private: + std::vector<uint8_t> buffer_; + size_t read_position_; + size_t write_position_; + bool write_reached_read_ = false; + +public: + ring_buffer(); + ring_buffer(size_t size); + + inline size_t size() const { return buffer_.size(); } + + inline uint8_t &operator[](size_t i) { return buffer_[i]; } + inline const uint8_t &operator[](size_t i) const { return buffer_[i]; } + + size_t read_position() const override; + size_t read_composite_length() const override; + size_t read_segment_length(size_t offset = 0) const override; + void read_advance(size_t bytes) override; + + uint8_t &read(size_t i = 0) override; + const uint8_t &read(size_t i = 0) const override; + + size_t write_position() const override; + size_t write_composite_length() const override; + size_t write_segment_length(size_t offset = 0) const override; + void write_advance(size_t bytes) override; + + uint8_t &write(size_t i = 0) override; + const uint8_t &write(size_t i = 0) const override; + + error write_require_length(size_t bytes) override; +}; + +/* + * One time buffer + */ +class array_buffer : public buffer { +private: + std::vector<uint8_t> buffer_; + + size_t read_position_; + size_t write_position_; + +public: + array_buffer(size_t size); + + size_t read_position() const override; + size_t read_composite_length() const override; + size_t read_segment_length(size_t offset = 0) const override; + void read_advance(size_t bytes) override; + + uint8_t &read(size_t i = 0) override; + const uint8_t &read(size_t i = 0) const override; + + size_t write_position() const override; + size_t write_composite_length() const override; + size_t write_segment_length(size_t offset = 0) const override; + void write_advance(size_t bytes) override; + + uint8_t &write(size_t i = 0) override; + const uint8_t &write(size_t i = 0) const override; + + error write_require_length(size_t bytes) override; +}; + +class chain_array_buffer : public buffer { +private: + std::deque<array_buffer> buffer_; + + size_t read_position_; + size_t write_position_; + +public: + chain_array_buffer(); + + size_t read_position() const override; + size_t read_composite_length() const override; + size_t read_segment_length(size_t offset = 0) const override; + void read_advance(size_t bytes) override; + + uint8_t &read(size_t i = 0) override; + const uint8_t &read(size_t i = 0) const override; + + size_t write_position() const override; + size_t write_composite_length() const override; + size_t write_segment_length(size_t offset = 0) const override; + void write_advance(size_t bytes) override; + + uint8_t &write(size_t i = 0) override; + const uint8_t &write(size_t i = 0) const override; + + error write_require_length(size_t bytes) override; +}; +} // namespace saw |