[ox/mc] Use VLI encoding for integers
This commit is contained in:
parent
817e3fcef1
commit
e0605edb6e
33
deps/ox/src/ox/mc/read.cpp
vendored
33
deps/ox/src/ox/mc/read.cpp
vendored
@ -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<LittleEndian<StringLength>*>(&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<StringLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead);
|
||||
m_buffIt += bytesRead;
|
||||
oxReturnError(size.error);
|
||||
|
||||
// read the string
|
||||
if (val.cap() > -1 && static_cast<StringLength>(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<LittleEndian<ArrayLength>*>(&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<StringLength>(&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<LittleEndian<StringLength>*>(&m_buff[m_buffIt]);
|
||||
}
|
||||
std::size_t bytesRead = 0;
|
||||
return mc::decodeInteger<StringLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead);
|
||||
}
|
||||
return len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MetalClawReader::setTypeInfo(const char*, int fields) {
|
||||
|
37
deps/ox/src/ox/mc/read.hpp
vendored
37
deps/ox/src/ox/mc/read.hpp
vendored
@ -15,6 +15,7 @@
|
||||
#include <ox/std/vector.hpp>
|
||||
|
||||
#include "err.hpp"
|
||||
#include "intops.hpp"
|
||||
#include "presenceindicator.hpp"
|
||||
#include "types.hpp"
|
||||
|
||||
@ -106,11 +107,10 @@ class MetalClawReader {
|
||||
template<typename T>
|
||||
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<L> *val) {
|
||||
|
||||
template<typename I>
|
||||
Error MetalClawReader::readInteger(I *val) {
|
||||
Error err = 0;
|
||||
if (m_fieldPresence.get(m_field)) {
|
||||
if (m_buffIt + sizeof(I) < m_buffLen) {
|
||||
*val = *reinterpret_cast<LittleEndian<I>*>(&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<I>(&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<typename T>
|
||||
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<LittleEndian<ArrayLength>*>(&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<StringLength>(&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;
|
||||
};
|
||||
|
||||
|
1
deps/ox/src/ox/mc/test/CMakeLists.txt
vendored
1
deps/ox/src/ox/mc/test/CMakeLists.txt
vendored
@ -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)
|
||||
|
8
deps/ox/src/ox/mc/test/tests.cpp
vendored
8
deps/ox/src/ox/mc/test/tests.cpp
vendored
@ -107,6 +107,7 @@ std::map<std::string, ox::Error(*)()> 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<std::string, ox::Error(*)()> 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<std::string, ox::Error(*)()> 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<std::string, ox::Error(*)()> 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 = {};
|
||||
|
7
deps/ox/src/ox/mc/write.cpp
vendored
7
deps/ox/src/ox/mc/write.cpp
vendored
@ -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<LittleEndian<StringLength>*>(&m_buff[m_buffIt]) = static_cast<StringLength>(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());
|
||||
|
32
deps/ox/src/ox/mc/write.hpp
vendored
32
deps/ox/src/ox/mc/write.hpp
vendored
@ -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<LittleEndian<ArrayLength>*>(&m_buff[m_buffIt]) = static_cast<ArrayLength>(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<I> leVal = val;
|
||||
// bits needed to represent number factoring in space possibly needed
|
||||
// for signed bit
|
||||
const auto bits = mc::highestBit(val) + (ox::is_signed<I> ? 1 : 0) / 8;
|
||||
// bytes needed to store value
|
||||
std::size_t bytes = bits / 8 + (bits % 8 != 0);
|
||||
const auto bytesIndicator = onMask<uint8_t>(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<LittleEndian<I>*>(&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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user