#pragma once #include "error.h" #include #include #include #include #include #include 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); }; /** * Converts a buffer to a string for convenience cases */ std::string convert_to_string(const buffer& buf); /** * */ /* * 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 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 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 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