moved higher level buffer impl to parent and adjusted some encoding code to guarantee resizes

This commit is contained in:
keldu.magnus 2020-11-16 22:48:04 +01:00
parent ee4e48e0b2
commit c3c325d662
4 changed files with 174 additions and 111 deletions

View File

@ -7,6 +7,79 @@
#include <sstream> #include <sstream>
namespace gin { 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} { RingBuffer::RingBuffer() : read_position{0}, write_position{0} {
buffer.resize(RING_BUFFER_MAX_SIZE); buffer.resize(RING_BUFFER_MAX_SIZE);
} }
@ -123,76 +196,77 @@ const uint8_t &RingBuffer::write(size_t i) const {
return noError(); return noError();
} }
*/ */
Error RingBuffer::push(const uint8_t &value) { Error RingBuffer::writeRequireLength(size_t bytes) {
size_t write_remain = writeCompositeLength(); size_t write_remain = writeCompositeLength();
if (write_remain > 0) { if (bytes > write_remain) {
write() = value;
writeAdvance(1);
} else {
return recoverableError("Buffer too small"); return recoverableError("Buffer too small");
} }
return noError(); return noError();
} }
Error RingBuffer::push(const uint8_t &buffer, size_t size) { ArrayBuffer::ArrayBuffer(size_t size) : read_position{0}, write_position{0} {
if (writeCompositeLength() >= size) { buffer.resize(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 {
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 recoverableError("Buffer too small");
} }
return noError(); 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 } // namespace gin

View File

@ -14,8 +14,7 @@ namespace gin {
* Access class to reduce templated BufferSegments bloat * Access class to reduce templated BufferSegments bloat
*/ */
class Buffer { class Buffer {
private: protected:
friend class RingBuffer;
~Buffer() = default; ~Buffer() = default;
public: public:
@ -43,13 +42,13 @@ public:
*/ */
virtual Error writeRequireLength(size_t bytes) = 0; virtual Error writeRequireLength(size_t bytes) = 0;
virtual Error push(const uint8_t &value) = 0; Error push(const uint8_t &value);
virtual Error push(const uint8_t &buffer, size_t size) = 0; Error push(const uint8_t &buffer, size_t size);
virtual Error pop(uint8_t &value) = 0; Error pop(uint8_t &value);
virtual Error pop(uint8_t &buffer, size_t size) = 0; Error pop(uint8_t &buffer, size_t size);
virtual std::string toString() const = 0; std::string toString() const;
virtual std::string toHex() const = 0; std::string toHex() const;
}; };
/* /*
* Buffer size meant for default allocation size of the ringbuffer since * Buffer size meant for default allocation size of the ringbuffer since
@ -91,13 +90,7 @@ public:
uint8_t &write(size_t i = 0) override; uint8_t &write(size_t i = 0) override;
const uint8_t &write(size_t i = 0) const override; const uint8_t &write(size_t i = 0) const override;
Error push(const uint8_t &value) override; Error writeRequireLength(size_t bytes) 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;
}; };
/* /*
@ -129,10 +122,7 @@ public:
uint8_t &write(size_t i = 0) override; uint8_t &write(size_t i = 0) override;
const uint8_t &write(size_t i = 0) const override; const uint8_t &write(size_t i = 0) const override;
Error push(const uint8_t &value) override; Error writeRequireLength(size_t bytes) 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;
}; };
class ChainArrayBuffer : public Buffer { class ChainArrayBuffer : public Buffer {
@ -161,9 +151,6 @@ public:
uint8_t &write(size_t i = 0) override; uint8_t &write(size_t i = 0) override;
const uint8_t &write(size_t i = 0) const override; const uint8_t &write(size_t i = 0) const override;
Error push(const uint8_t &value) override; Error writeRequireLength(size_t bytes) 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;
}; };
} // namespace gin } // namespace gin

View File

@ -31,25 +31,23 @@ public:
return recoverableError("Buffer too small"); return recoverableError("Buffer too small");
} }
uint16_t& raw = reinterpret_cast<uint16_t&>(val); uint16_t raw = 0;
uint8_t buf[sizeof(T)] = 0;
Error error = buffer.pop(buf, sizeof(T));
if(error.failed()){
return error;
}
for (size_t i = 0; i < sizeof(T); ++i) { 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(); return noError();
} }
inline static Error encode(const T &val, Buffer &buffer) { inline static Error encode(const T &val, Buffer &buffer) {
if (buffer.writeCompositeLength() < sizeof(T)) { Error error = buffer.writeRequireLength(sizeof(T));
return recoverableError("Buffer too small"); if (error.failed()) {
return error;
} }
uint16_t raw; uint16_t raw;
memcpy(&raw, &val, sizeof(T)); memcpy(&raw, &val, sizeof(T));
@ -83,9 +81,11 @@ public:
} }
inline static Error encode(const T &val, Buffer &buffer) { inline static Error encode(const T &val, Buffer &buffer) {
if (buffer.writeCompositeLength() < sizeof(T)) { Error error = buffer.writeRequireLength(sizeof(T));
return recoverableError("Buffer too small"); if (error.failed()) {
return error;
} }
uint32_t raw; uint32_t raw;
memcpy(&raw, &val, sizeof(T)); memcpy(&raw, &val, sizeof(T));
@ -119,9 +119,11 @@ public:
} }
inline static Error encode(const T &val, Buffer &buffer) { inline static Error encode(const T &val, Buffer &buffer) {
if (buffer.writeCompositeLength() < sizeof(T)) { Error error = buffer.writeRequireLength(sizeof(T));
return recoverableError("Buffer too small"); if (error.failed()) {
return error;
} }
uint64_t raw; uint64_t raw;
memcpy(&raw, &val, sizeof(T)); memcpy(&raw, &val, sizeof(T));