From e0605edb6ea267a044b64080cf87da31763e756f Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Sun, 17 Mar 2019 03:03:21 -0500 Subject: [PATCH] [ox/mc] Use VLI encoding for integers --- deps/ox/src/ox/mc/read.cpp | 33 ++++++++++++------------ deps/ox/src/ox/mc/read.hpp | 37 +++++++++++++-------------- deps/ox/src/ox/mc/test/CMakeLists.txt | 1 + deps/ox/src/ox/mc/test/tests.cpp | 8 ++++-- deps/ox/src/ox/mc/write.cpp | 7 ++--- deps/ox/src/ox/mc/write.hpp | 32 ++++++----------------- 6 files changed, 53 insertions(+), 65 deletions(-) diff --git a/deps/ox/src/ox/mc/read.cpp b/deps/ox/src/ox/mc/read.cpp index 330e588d..fde36eb6 100644 --- a/deps/ox/src/ox/mc/read.cpp +++ b/deps/ox/src/ox/mc/read.cpp @@ -66,15 +66,15 @@ Error MetalClawReader::op(const char*, bool *val) { } Error MetalClawReader::op(const char*, SerStr val) { - if (m_fieldPresence.get(m_field)) { + if (m_fieldPresence.get(m_field++)) { // read the length - StringLength size = 0; - if (m_buffIt + sizeof(StringLength) < m_buffLen) { - size = *reinterpret_cast*>(&m_buff[m_buffIt]); - m_buffIt += sizeof(StringLength); - } else { + if (m_buffIt >= m_buffLen) { return OxError(MC_BUFFENDED); } + std::size_t bytesRead = 0; + auto size = mc::decodeInteger(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead); + m_buffIt += bytesRead; + oxReturnError(size.error); // read the string if (val.cap() > -1 && static_cast(val.cap()) >= size) { @@ -90,7 +90,6 @@ Error MetalClawReader::op(const char*, SerStr val) { } else { val.data()[0] = 0; } - m_field++; return OxError(0); } @@ -98,25 +97,25 @@ Error MetalClawReader::op(const char*, SerStr val) { std::size_t len = 0; if (m_fieldPresence.get(m_field)) { // read the length - if (m_buffIt + sizeof(ArrayLength) < m_buffLen) { - len = *reinterpret_cast*>(&m_buff[m_buffIt]); - if (pass) { - m_buffIt += sizeof(ArrayLength); - } + if (m_buffIt >= m_buffLen) { + return OxError(MC_BUFFENDED); + } + std::size_t bytesRead = 0; + len = mc::decodeInteger(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead); + if (pass) { + m_buffIt += sizeof(ArrayLength); } } return len; } [[nodiscard]] StringLength MetalClawReader::stringLength() { - std::size_t len = 0; if (m_fieldPresence.get(m_field)) { // read the length - if (m_buffIt + sizeof(StringLength) < m_buffLen) { - len = *reinterpret_cast*>(&m_buff[m_buffIt]); - } + std::size_t bytesRead = 0; + return mc::decodeInteger(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead); } - return len; + return 0; } void MetalClawReader::setTypeInfo(const char*, int fields) { diff --git a/deps/ox/src/ox/mc/read.hpp b/deps/ox/src/ox/mc/read.hpp index 377165ea..4a9414f8 100644 --- a/deps/ox/src/ox/mc/read.hpp +++ b/deps/ox/src/ox/mc/read.hpp @@ -15,6 +15,7 @@ #include #include "err.hpp" +#include "intops.hpp" #include "presenceindicator.hpp" #include "types.hpp" @@ -106,11 +107,10 @@ class MetalClawReader { template Error MetalClawReader::op(const char*, T *val) { Error err = 0; - if (val && m_fieldPresence.get(m_field)) { + if (val && m_fieldPresence.get(m_field++)) { auto reader = child(); err |= ioOp(&reader, val); } - m_field++; return err; }; @@ -121,34 +121,34 @@ Error MetalClawReader::op(const char *name, ox::BString *val) { template Error MetalClawReader::readInteger(I *val) { - Error err = 0; - if (m_fieldPresence.get(m_field)) { - if (m_buffIt + sizeof(I) < m_buffLen) { - *val = *reinterpret_cast*>(&m_buff[m_buffIt]); - m_buffIt += sizeof(I); - } else { - err = OxError(MC_BUFFENDED); + if (m_fieldPresence.get(m_field++)) { + std::size_t bytesRead = 0; + if (m_buffIt >= m_buffLen) { + return OxError(MC_BUFFENDED); } + auto valErr = mc::decodeInteger(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead); + m_buffIt += bytesRead; + oxReturnError(valErr.error); + *val = valErr.value; } else { *val = 0; } - m_field++; - return err; + return OxError(0); }; // array handler template Error MetalClawReader::op(const char*, T *val, std::size_t valLen) { Error err = 0; - if (m_fieldPresence.get(m_field)) { + if (m_fieldPresence.get(m_field++)) { // read the length - ArrayLength len = 0; - if (m_buffIt + sizeof(ArrayLength) < m_buffLen) { - len = *reinterpret_cast*>(&m_buff[m_buffIt]); - m_buffIt += sizeof(ArrayLength); - } else { - err = OxError(MC_BUFFENDED); + if (m_buffIt >= m_buffLen) { + return OxError(MC_BUFFENDED); } + std::size_t bytesRead = 0; + auto len = mc::decodeInteger(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead); + m_buffIt += bytesRead; + oxReturnError(len.error); // read the list if (valLen >= len) { @@ -161,7 +161,6 @@ Error MetalClawReader::op(const char*, T *val, std::size_t valLen) { err = OxError(MC_OUTBUFFENDED); } } - m_field++; return err; }; diff --git a/deps/ox/src/ox/mc/test/CMakeLists.txt b/deps/ox/src/ox/mc/test/CMakeLists.txt index 43a8f3b5..febeba47 100644 --- a/deps/ox/src/ox/mc/test/CMakeLists.txt +++ b/deps/ox/src/ox/mc/test/CMakeLists.txt @@ -10,5 +10,6 @@ target_link_libraries( add_test("Test\\ McTest\\ Writer" McTest MetalClawWriter) add_test("Test\\ McTest\\ Reader" McTest MetalClawReader) +add_test("Test\\ McTest\\ MetalClawDef" McTest MetalClawDef) add_test("Test\\ McTest\\ encodeInteger" McTest encodeInteger) add_test("Test\\ McTest\\ decodeInteger" McTest decodeInteger) diff --git a/deps/ox/src/ox/mc/test/tests.cpp b/deps/ox/src/ox/mc/test/tests.cpp index eaba734e..7f23d967 100644 --- a/deps/ox/src/ox/mc/test/tests.cpp +++ b/deps/ox/src/ox/mc/test/tests.cpp @@ -107,6 +107,7 @@ std::map tests = { oxAssert(ox::writeMC(buff, buffLen, &testIn), "writeMC failed"); oxAssert(ox::readMC(buff, buffLen, &testOut), "writeMC failed"); + std::cout << testIn.Int << " " << testOut.Int << '\n'; oxAssert(testIn.Bool == testOut.Bool, "Bool value mismatch"); oxAssert(testIn.Int == testOut.Int, "Int value mismatch"); @@ -217,12 +218,15 @@ std::map tests = { } return OxError(result.value != val); }; + oxAssert(check(uint32_t(14)), "Decode of 14 failed."); oxAssert(check(int64_t(1)), "Decode of 1 failed."); oxAssert(check(int64_t(2)), "Decode of 2 failed."); + oxAssert(check(int64_t(42)), "Decode of 42 failed."); oxAssert(check(int64_t(130)), "Decode of 130 failed."); oxAssert(check(int64_t(131)), "Decode of 131 failed."); oxAssert(check(uint64_t(1)), "Decode of 1 failed."); oxAssert(check(uint64_t(2)), "Decode of 2 failed."); + oxAssert(check(uint64_t(42)), "Decode of 42 failed."); oxAssert(check(uint64_t(130)), "Decode of 130 failed."); oxAssert(check(uint64_t(131)), "Decode of 131 failed."); oxAssert(check(0xffffffff), "Decode of 0xffffffff failed."); @@ -262,7 +266,7 @@ std::map tests = { auto fieldName = f.fieldName.c_str(); switch (f.type->primitiveType) { case ox::PrimitiveType::UnsignedInteger: - std::cout << fieldName << ":\tuint" << f.type->length << "_t:\t"; + std::cout << fieldName << ":\tuint" << f.type->length * 8 << "_t:\t"; switch (f.type->length) { case 1: { uint8_t i = {}; @@ -292,7 +296,7 @@ std::map tests = { std::cout << '\n'; break; case ox::PrimitiveType::SignedInteger: - std::cout << fieldName << ":\tint" << f.type->length << "_t:\t"; + std::cout << fieldName << ":\tint" << f.type->length * 8 << "_t:\t"; switch (f.type->length) { case 1: { int8_t i = {}; diff --git a/deps/ox/src/ox/mc/write.cpp b/deps/ox/src/ox/mc/write.cpp index c3b846d0..ff77386f 100644 --- a/deps/ox/src/ox/mc/write.cpp +++ b/deps/ox/src/ox/mc/write.cpp @@ -65,9 +65,10 @@ Error MetalClawWriter::op(const char*, SerStr val) { bool fieldSet = false; if (val.cap()) { // write the length - if (m_buffIt + sizeof(StringLength) + val.bytes() < m_buffLen) { - *reinterpret_cast*>(&m_buff[m_buffIt]) = static_cast(val.bytes()); - m_buffIt += sizeof(StringLength); + const auto strLen = mc::encodeInteger(val.bytes()); + if (m_buffIt + strLen.length + val.bytes() < m_buffLen) { + ox_memcpy(&m_buff[m_buffIt], strLen.data, strLen.length); + m_buffIt += strLen.length; // write the string ox_memcpy(&m_buff[m_buffIt], val.c_str(), val.bytes()); diff --git a/deps/ox/src/ox/mc/write.hpp b/deps/ox/src/ox/mc/write.hpp index 94f2eea2..662b07ee 100644 --- a/deps/ox/src/ox/mc/write.hpp +++ b/deps/ox/src/ox/mc/write.hpp @@ -111,9 +111,10 @@ Error MetalClawWriter::op(const char*, T *val, std::size_t len) { if (len) { // write the length - if (m_buffIt + sizeof(ArrayLength) < m_buffLen) { - *reinterpret_cast*>(&m_buff[m_buffIt]) = static_cast(len); - m_buffIt += sizeof(ArrayLength); + const auto arrLen = mc::encodeInteger(len); + if (m_buffIt + arrLen.length < m_buffLen) { + ox_memcpy(&m_buff[m_buffIt], arrLen.data, arrLen.length); + m_buffIt += arrLen.length; } else { err = MC_BUFFENDED; } @@ -140,28 +141,11 @@ Error MetalClawWriter::appendInteger(I val) { Error err = 0; bool fieldSet = false; if (val) { - if (m_buffIt + sizeof(I) < m_buffLen) { - LittleEndian leVal = val; - // bits needed to represent number factoring in space possibly needed - // for signed bit - const auto bits = mc::highestBit(val) + (ox::is_signed ? 1 : 0) / 8; - // bytes needed to store value - std::size_t bytes = bits / 8 + (bits % 8 != 0); - const auto bytesIndicator = onMask(bytes - 1) << (7 - bytes); - // factor in bits needed for bytesIndicator (does not affect bytesIndicator) - // bits for integer + bits needed to represent bytes > bits available - if (bits + bytes > bytes * 8) { - ++bytes; - } - - if (bytes == 9) { - m_buff[m_buffIt++] = bytesIndicator; - - } else { - } - *reinterpret_cast*>(&m_buff[m_buffIt]) = leVal; + auto mi = mc::encodeInteger(val); + if (mi.length < m_buffLen) { fieldSet = true; - m_buffIt += sizeof(I); + ox_memcpy(&m_buff[m_buffIt], mi.data, mi.length); + m_buffIt += mi.length; } else { err |= MC_BUFFENDED; }