moved higher level buffer impl to parent and adjusted some encoding code to guarantee resizes
This commit is contained in:
parent
ee4e48e0b2
commit
c3c325d662
|
@ -165,7 +165,7 @@ void EventLoop::leaveScope() {
|
|||
local_loop = nullptr;
|
||||
}
|
||||
|
||||
bool EventLoop::turnLoop(){
|
||||
bool EventLoop::turnLoop() {
|
||||
size_t turn_step = 0;
|
||||
while (head && turn_step < 65536) {
|
||||
if (!turn()) {
|
||||
|
|
|
@ -7,6 +7,79 @@
|
|||
#include <sstream>
|
||||
|
||||
namespace gin {
|
||||
Error Buffer::push(const uint8_t &value) {
|
||||
size_t write_remain = writeCompositeLength();
|
||||
if (write_remain > 0) {
|
||||
write() = value;
|
||||
writeAdvance(1);
|
||||
} else {
|
||||
return recoverableError("Buffer too small");
|
||||
}
|
||||
return noError();
|
||||
}
|
||||
|
||||
Error Buffer::push(const uint8_t &buffer, size_t size) {
|
||||
Error error = writeRequireLength(size);
|
||||
if (error.failed()) {
|
||||
return error;
|
||||
}
|
||||
const uint8_t *buffer_ptr = &buffer;
|
||||
while (size > 0) {
|
||||
size_t segment = std::min(writeSegmentLength(), size);
|
||||
memcpy(&write(), buffer_ptr, segment);
|
||||
writeAdvance(segment);
|
||||
size -= segment;
|
||||
buffer_ptr += segment;
|
||||
}
|
||||
return noError();
|
||||
}
|
||||
|
||||
Error Buffer::pop(uint8_t &value) {
|
||||
if (readCompositeLength() > 0) {
|
||||
value = read();
|
||||
readAdvance(1);
|
||||
} else {
|
||||
return recoverableError("Buffer too small");
|
||||
}
|
||||
return noError();
|
||||
}
|
||||
|
||||
Error Buffer::pop(uint8_t &buffer, size_t size) {
|
||||
if (readCompositeLength() >= size) {
|
||||
uint8_t *buffer_ptr = &buffer;
|
||||
while (size > 0) {
|
||||
size_t segment = std::min(readSegmentLength(), size);
|
||||
memcpy(buffer_ptr, &read(), segment);
|
||||
readAdvance(segment);
|
||||
size -= segment;
|
||||
buffer_ptr += segment;
|
||||
}
|
||||
} else {
|
||||
return recoverableError("Buffer too small");
|
||||
}
|
||||
return noError();
|
||||
}
|
||||
|
||||
std::string Buffer::toString() const {
|
||||
std::ostringstream oss;
|
||||
for (size_t i = 0; i < readCompositeLength(); ++i) {
|
||||
oss << read(i);
|
||||
}
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
std::string Buffer::toHex() const {
|
||||
std::ostringstream oss;
|
||||
oss << std::hex << std::setfill('0');
|
||||
for (size_t i = 0; i < readCompositeLength(); ++i) {
|
||||
oss << std::setw(2) << (uint16_t)read(i);
|
||||
if ((i + 1) < readCompositeLength()) {
|
||||
oss << ((i % 4 == 3) ? '\n' : ' ');
|
||||
}
|
||||
}
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
RingBuffer::RingBuffer() : read_position{0}, write_position{0} {
|
||||
buffer.resize(RING_BUFFER_MAX_SIZE);
|
||||
}
|
||||
|
@ -123,76 +196,77 @@ const uint8_t &RingBuffer::write(size_t i) const {
|
|||
return noError();
|
||||
}
|
||||
*/
|
||||
Error RingBuffer::push(const uint8_t &value) {
|
||||
Error RingBuffer::writeRequireLength(size_t bytes) {
|
||||
size_t write_remain = writeCompositeLength();
|
||||
if (write_remain > 0) {
|
||||
write() = value;
|
||||
writeAdvance(1);
|
||||
} else {
|
||||
if (bytes > write_remain) {
|
||||
return recoverableError("Buffer too small");
|
||||
}
|
||||
return noError();
|
||||
}
|
||||
|
||||
Error RingBuffer::push(const uint8_t &buffer, size_t size) {
|
||||
if (writeCompositeLength() >= size) {
|
||||
const uint8_t *buffer_ptr = &buffer;
|
||||
while (size > 0) {
|
||||
size_t segment = std::min(writeSegmentLength(), size);
|
||||
memcpy(&write(), buffer_ptr, segment);
|
||||
writeAdvance(segment);
|
||||
size -= segment;
|
||||
buffer_ptr += segment;
|
||||
}
|
||||
} else {
|
||||
ArrayBuffer::ArrayBuffer(size_t size) : read_position{0}, write_position{0} {
|
||||
buffer.resize(size);
|
||||
}
|
||||
|
||||
size_t ArrayBuffer::readPosition() const { return read_position; }
|
||||
|
||||
size_t ArrayBuffer::readCompositeLength() const {
|
||||
return write_position - read_position;
|
||||
}
|
||||
|
||||
size_t ArrayBuffer::readSegmentLength() const {
|
||||
return write_position - read_position;
|
||||
}
|
||||
|
||||
void ArrayBuffer::readAdvance(size_t bytes) {
|
||||
assert(bytes <= readCompositeLength());
|
||||
read_position += bytes;
|
||||
}
|
||||
|
||||
uint8_t &ArrayBuffer::read(size_t i) {
|
||||
assert(i < readCompositeLength());
|
||||
|
||||
return buffer[i + read_position];
|
||||
}
|
||||
|
||||
const uint8_t &ArrayBuffer::read(size_t i) const {
|
||||
assert(i + read_position < buffer.size());
|
||||
|
||||
return buffer[i + read_position];
|
||||
}
|
||||
|
||||
size_t ArrayBuffer::writePosition() const { return write_position; }
|
||||
|
||||
size_t ArrayBuffer::writeCompositeLength() const {
|
||||
assert(write_position <= buffer.size());
|
||||
return buffer.size() - write_position;
|
||||
}
|
||||
|
||||
size_t ArrayBuffer::writeSegmentLength() const {
|
||||
assert(write_position <= buffer.size());
|
||||
return buffer.size() - write_position;
|
||||
}
|
||||
|
||||
void ArrayBuffer::writeAdvance(size_t bytes) {
|
||||
assert(bytes <= writeCompositeLength());
|
||||
write_position += bytes;
|
||||
}
|
||||
|
||||
uint8_t &ArrayBuffer::write(size_t i) {
|
||||
assert(i < writeCompositeLength());
|
||||
return buffer[i + write_position];
|
||||
}
|
||||
|
||||
const uint8_t &ArrayBuffer::write(size_t i) const {
|
||||
assert(i < writeCompositeLength());
|
||||
return buffer[i + write_position];
|
||||
}
|
||||
Error ArrayBuffer::writeRequireLength(size_t bytes) {
|
||||
size_t write_remain = writeCompositeLength();
|
||||
if (bytes > write_remain) {
|
||||
return recoverableError("Buffer too small");
|
||||
}
|
||||
return noError();
|
||||
}
|
||||
|
||||
Error RingBuffer::pop(uint8_t &value) {
|
||||
if (readCompositeLength() > 0) {
|
||||
value = read();
|
||||
readAdvance(1);
|
||||
} else {
|
||||
return recoverableError("Buffer too small");
|
||||
}
|
||||
return noError();
|
||||
}
|
||||
|
||||
Error RingBuffer::pop(uint8_t &buffer, size_t size) {
|
||||
if (readCompositeLength() >= size) {
|
||||
uint8_t *buffer_ptr = &buffer;
|
||||
while (size > 0) {
|
||||
size_t segment = std::min(readSegmentLength(), size);
|
||||
memcpy(buffer_ptr, &read(), segment);
|
||||
readAdvance(segment);
|
||||
size -= segment;
|
||||
buffer_ptr += segment;
|
||||
}
|
||||
} else {
|
||||
return recoverableError("Buffer too small");
|
||||
}
|
||||
return noError();
|
||||
}
|
||||
|
||||
std::string RingBuffer::toString() const {
|
||||
std::ostringstream oss;
|
||||
for (size_t i = 0; i < readCompositeLength(); ++i) {
|
||||
oss << read(i);
|
||||
}
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
std::string RingBuffer::toHex() const {
|
||||
std::ostringstream oss;
|
||||
oss << std::hex << std::setfill('0');
|
||||
for (size_t i = 0; i < readCompositeLength(); ++i) {
|
||||
oss << std::setw(2) << (uint16_t)read(i);
|
||||
if ((i + 1) < readCompositeLength()) {
|
||||
oss << ((i % 4 == 3) ? '\n' : ' ');
|
||||
}
|
||||
}
|
||||
return oss.str();
|
||||
}
|
||||
} // namespace gin
|
||||
|
|
|
@ -14,8 +14,7 @@ namespace gin {
|
|||
* Access class to reduce templated BufferSegments bloat
|
||||
*/
|
||||
class Buffer {
|
||||
private:
|
||||
friend class RingBuffer;
|
||||
protected:
|
||||
~Buffer() = default;
|
||||
|
||||
public:
|
||||
|
@ -36,29 +35,29 @@ public:
|
|||
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.
|
||||
*/
|
||||
* 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;
|
||||
|
||||
virtual Error push(const uint8_t &value) = 0;
|
||||
virtual Error push(const uint8_t &buffer, size_t size) = 0;
|
||||
virtual Error pop(uint8_t &value) = 0;
|
||||
virtual Error pop(uint8_t &buffer, size_t size) = 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);
|
||||
|
||||
virtual std::string toString() const = 0;
|
||||
virtual std::string toHex() const = 0;
|
||||
std::string toString() const;
|
||||
std::string toHex() const;
|
||||
};
|
||||
/*
|
||||
* Buffer size meant for default allocation size of the ringbuffer since
|
||||
* this class currently doesn't support proper resizing
|
||||
*/
|
||||
* 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
|
||||
*/
|
||||
* Buffer wrapping around if read caught up
|
||||
*/
|
||||
class RingBuffer final : public Buffer {
|
||||
private:
|
||||
std::vector<uint8_t> buffer;
|
||||
|
@ -91,13 +90,7 @@ public:
|
|||
uint8_t &write(size_t i = 0) override;
|
||||
const uint8_t &write(size_t i = 0) const override;
|
||||
|
||||
Error push(const uint8_t &value) override;
|
||||
Error push(const uint8_t &buffer, size_t size) override;
|
||||
Error pop(uint8_t &value) override;
|
||||
Error pop(uint8_t &buffer, size_t size) override;
|
||||
|
||||
std::string toString() const override;
|
||||
std::string toHex() const override;
|
||||
Error writeRequireLength(size_t bytes) override;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -129,10 +122,7 @@ public:
|
|||
uint8_t &write(size_t i = 0) override;
|
||||
const uint8_t &write(size_t i = 0) const override;
|
||||
|
||||
Error push(const uint8_t &value) override;
|
||||
Error push(const uint8_t &buffer, size_t size) override;
|
||||
Error pop(uint8_t &value) override;
|
||||
Error pop(uint8_t &buffer, size_t size) override;
|
||||
Error writeRequireLength(size_t bytes) override;
|
||||
};
|
||||
|
||||
class ChainArrayBuffer : public Buffer {
|
||||
|
@ -161,9 +151,6 @@ public:
|
|||
uint8_t &write(size_t i = 0) override;
|
||||
const uint8_t &write(size_t i = 0) const override;
|
||||
|
||||
Error push(const uint8_t &value) override;
|
||||
Error push(const uint8_t &buffer, size_t size) override;
|
||||
Error pop(uint8_t &value) override;
|
||||
Error pop(uint8_t &buffer, size_t size) override;
|
||||
Error writeRequireLength(size_t bytes) override;
|
||||
};
|
||||
} // namespace gin
|
||||
|
|
|
@ -12,12 +12,12 @@ template <typename T, size_t size = sizeof(T)> class ShiftStreamValue;
|
|||
template <typename T> class ShiftStreamValue<T, 1> {
|
||||
public:
|
||||
inline static Error decode(T &val, Buffer &buffer) {
|
||||
uint8_t& raw = reinterpret_cast<uint8_t&>(val);
|
||||
uint8_t &raw = reinterpret_cast<uint8_t &>(val);
|
||||
return buffer.pop(raw, sizeof(T));
|
||||
}
|
||||
|
||||
inline static Error encode(const T &val, Buffer &buffer) {
|
||||
uint8_t& raw = reinterpret_cast<uint8_t&>(val);
|
||||
uint8_t &raw = reinterpret_cast<uint8_t &>(val);
|
||||
return buffer.push(raw, sizeof(T));
|
||||
}
|
||||
|
||||
|
@ -30,26 +30,24 @@ public:
|
|||
if (buffer.readCompositeLength() < sizeof(T)) {
|
||||
return recoverableError("Buffer too small");
|
||||
}
|
||||
|
||||
uint16_t& raw = reinterpret_cast<uint16_t&>(val);
|
||||
uint8_t buf[sizeof(T)] = 0;
|
||||
|
||||
Error error = buffer.pop(buf, sizeof(T));
|
||||
if(error.failed()){
|
||||
return error;
|
||||
}
|
||||
uint16_t raw = 0;
|
||||
|
||||
for (size_t i = 0; i < sizeof(T); ++i) {
|
||||
raw |= buf[i] << (i * 8);
|
||||
raw |= buffer.read(i) << (i * 8);
|
||||
}
|
||||
memcpy(&val, &raw, sizeof(T));
|
||||
buffer.readAdvance(sizeof(T));
|
||||
|
||||
return noError();
|
||||
}
|
||||
|
||||
inline static Error encode(const T &val, Buffer &buffer) {
|
||||
if (buffer.writeCompositeLength() < sizeof(T)) {
|
||||
return recoverableError("Buffer too small");
|
||||
Error error = buffer.writeRequireLength(sizeof(T));
|
||||
if (error.failed()) {
|
||||
return error;
|
||||
}
|
||||
|
||||
uint16_t raw;
|
||||
memcpy(&raw, &val, sizeof(T));
|
||||
|
||||
|
@ -83,9 +81,11 @@ public:
|
|||
}
|
||||
|
||||
inline static Error encode(const T &val, Buffer &buffer) {
|
||||
if (buffer.writeCompositeLength() < sizeof(T)) {
|
||||
return recoverableError("Buffer too small");
|
||||
Error error = buffer.writeRequireLength(sizeof(T));
|
||||
if (error.failed()) {
|
||||
return error;
|
||||
}
|
||||
|
||||
uint32_t raw;
|
||||
memcpy(&raw, &val, sizeof(T));
|
||||
|
||||
|
@ -119,9 +119,11 @@ public:
|
|||
}
|
||||
|
||||
inline static Error encode(const T &val, Buffer &buffer) {
|
||||
if (buffer.writeCompositeLength() < sizeof(T)) {
|
||||
return recoverableError("Buffer too small");
|
||||
Error error = buffer.writeRequireLength(sizeof(T));
|
||||
if (error.failed()) {
|
||||
return error;
|
||||
}
|
||||
|
||||
uint64_t raw;
|
||||
memcpy(&raw, &val, sizeof(T));
|
||||
|
||||
|
|
Loading…
Reference in New Issue