forstio/source/forstio/buffer.h

193 lines
5.0 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 readPosition() const = 0;
virtual size_t readCompositeLength() const = 0;
virtual size_t readSegmentLength(size_t offset = 0) const = 0;
virtual void readAdvance(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 writePosition() const = 0;
virtual size_t writeCompositeLength() const = 0;
virtual size_t writeSegmentLength(size_t offset = 0) const = 0;
virtual void writeAdvance(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 writeRequireLength(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);
std::string toString() const;
std::string toHex() const;
};
/*
* A viewer class for buffers.
* Working on the reference buffer invalidates the buffer view
*/
class BufferView : public Buffer {
private:
Buffer &buffer;
size_t read_offset;
size_t write_offset;
public:
BufferView(Buffer &);
size_t readPosition() const override;
size_t readCompositeLength() const override;
size_t readSegmentLength(size_t offset = 0) const override;
void readAdvance(size_t bytes) override;
uint8_t &read(size_t i = 0) override;
const uint8_t &read(size_t i = 0) const override;
size_t writePosition() const override;
size_t writeCompositeLength() const override;
size_t writeSegmentLength(size_t offset = 0) const override;
void writeAdvance(size_t bytes) override;
uint8_t &write(size_t i = 0) override;
const uint8_t &write(size_t i = 0) const override;
Error writeRequireLength(size_t bytes) override;
size_t readOffset() const;
size_t writeOffset() 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 RingBuffer final : public Buffer {
private:
std::vector<uint8_t> buffer;
size_t read_position;
size_t write_position;
bool write_reached_read = false;
public:
RingBuffer();
RingBuffer(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 readPosition() const override;
size_t readCompositeLength() const override;
size_t readSegmentLength(size_t offset = 0) const override;
void readAdvance(size_t bytes) override;
uint8_t &read(size_t i = 0) override;
const uint8_t &read(size_t i = 0) const override;
size_t writePosition() const override;
size_t writeCompositeLength() const override;
size_t writeSegmentLength(size_t offset = 0) const override;
void writeAdvance(size_t bytes) override;
uint8_t &write(size_t i = 0) override;
const uint8_t &write(size_t i = 0) const override;
Error writeRequireLength(size_t bytes) override;
};
/*
* One time buffer
*/
class ArrayBuffer : public Buffer {
private:
std::vector<uint8_t> buffer;
size_t read_position;
size_t write_position;
public:
ArrayBuffer(size_t size);
size_t readPosition() const override;
size_t readCompositeLength() const override;
size_t readSegmentLength(size_t offset = 0) const override;
void readAdvance(size_t bytes) override;
uint8_t &read(size_t i = 0) override;
const uint8_t &read(size_t i = 0) const override;
size_t writePosition() const override;
size_t writeCompositeLength() const override;
size_t writeSegmentLength(size_t offset = 0) const override;
void writeAdvance(size_t bytes) override;
uint8_t &write(size_t i = 0) override;
const uint8_t &write(size_t i = 0) const override;
Error writeRequireLength(size_t bytes) override;
};
class ChainArrayBuffer : public Buffer {
private:
std::deque<ArrayBuffer> buffer;
size_t read_position;
size_t write_position;
public:
ChainArrayBuffer();
size_t readPosition() const override;
size_t readCompositeLength() const override;
size_t readSegmentLength(size_t offset = 0) const override;
void readAdvance(size_t bytes) override;
uint8_t &read(size_t i = 0) override;
const uint8_t &read(size_t i = 0) const override;
size_t writePosition() const override;
size_t writeCompositeLength() const override;
size_t writeSegmentLength(size_t offset = 0) const override;
void writeAdvance(size_t bytes) override;
uint8_t &write(size_t i = 0) override;
const uint8_t &write(size_t i = 0) const override;
Error writeRequireLength(size_t bytes) override;
};
} // namespace saw