196 lines
5.2 KiB
C++
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
|