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;
|
local_loop = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EventLoop::turnLoop(){
|
bool EventLoop::turnLoop() {
|
||||||
size_t turn_step = 0;
|
size_t turn_step = 0;
|
||||||
while (head && turn_step < 65536) {
|
while (head && turn_step < 65536) {
|
||||||
if (!turn()) {
|
if (!turn()) {
|
||||||
|
|
|
@ -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);
|
size_t ArrayBuffer::readPosition() const { return read_position; }
|
||||||
memcpy(&write(), buffer_ptr, segment);
|
|
||||||
writeAdvance(segment);
|
size_t ArrayBuffer::readCompositeLength() const {
|
||||||
size -= segment;
|
return write_position - read_position;
|
||||||
buffer_ptr += segment;
|
}
|
||||||
}
|
|
||||||
} else {
|
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
|
||||||
|
|
|
@ -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:
|
||||||
|
@ -36,29 +35,29 @@ public:
|
||||||
virtual const uint8_t &write(size_t i = 0) const = 0;
|
virtual const uint8_t &write(size_t i = 0) const = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sometime buffers need to grow with a little more control
|
* Sometime buffers need to grow with a little more control
|
||||||
* than with push and pop for more efficient calls.
|
* than with push and pop for more efficient calls.
|
||||||
* There is nothing you can do if read hasn't been filled, but at
|
* There is nothing you can do if read hasn't been filled, but at
|
||||||
* least write can be increased if it is demanded.
|
* least write can be increased if it is demanded.
|
||||||
*/
|
*/
|
||||||
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
|
||||||
* this class currently doesn't support proper resizing
|
* this class currently doesn't support proper resizing
|
||||||
*/
|
*/
|
||||||
constexpr size_t RING_BUFFER_MAX_SIZE = 4096;
|
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 {
|
class RingBuffer final : public Buffer {
|
||||||
private:
|
private:
|
||||||
std::vector<uint8_t> buffer;
|
std::vector<uint8_t> buffer;
|
||||||
|
@ -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
|
||||||
|
|
|
@ -12,12 +12,12 @@ template <typename T, size_t size = sizeof(T)> class ShiftStreamValue;
|
||||||
template <typename T> class ShiftStreamValue<T, 1> {
|
template <typename T> class ShiftStreamValue<T, 1> {
|
||||||
public:
|
public:
|
||||||
inline static Error decode(T &val, Buffer &buffer) {
|
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));
|
return buffer.pop(raw, sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static Error encode(const T &val, Buffer &buffer) {
|
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));
|
return buffer.push(raw, sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,26 +30,24 @@ public:
|
||||||
if (buffer.readCompositeLength() < sizeof(T)) {
|
if (buffer.readCompositeLength() < sizeof(T)) {
|
||||||
return recoverableError("Buffer too small");
|
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));
|
uint16_t raw = 0;
|
||||||
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));
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue