forstio/source/forstio/buffer.h

196 lines
5.2 KiB
C++

#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