[ox/mc] Fix string support in MC and add support for ox::BasicString
This commit is contained in:
parent
fd7510d14f
commit
df782129bb
4
deps/ox/src/ox/mc/read.cpp
vendored
4
deps/ox/src/ox/mc/read.cpp
vendored
@ -109,6 +109,10 @@ Error MetalClawReader::field(const char*, SerStr val) noexcept {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
Error MetalClawReader::fieldCString(const char *name, char **val, int len) noexcept {
|
||||
return field(name, SerStr(val, len));
|
||||
}
|
||||
|
||||
Result<ArrayLength> MetalClawReader::arrayLength(const char*, bool pass) noexcept {
|
||||
if ((m_unionIdx == -1 || m_unionIdx == m_field) && m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||
// read the length
|
||||
|
46
deps/ox/src/ox/mc/read.hpp
vendored
46
deps/ox/src/ox/mc/read.hpp
vendored
@ -72,11 +72,16 @@ class MetalClawReader {
|
||||
template<typename U>
|
||||
Error field(const char*, UnionView<U> val) noexcept;
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
Error field(const char*, BasicString<SmallStringSize> *val) noexcept;
|
||||
|
||||
template<std::size_t L>
|
||||
Error field(const char*, BString<L> *val) noexcept;
|
||||
|
||||
Error field(const char*, SerStr val) noexcept;
|
||||
|
||||
Error fieldCString(const char *name, char **val, int len) noexcept;
|
||||
|
||||
/**
|
||||
* Reads an array length from the current location in the buffer.
|
||||
* @param pass indicates that the parsing should iterate past the array length
|
||||
@ -158,6 +163,38 @@ Error MetalClawReader::field(const char*, UnionView<U> val) noexcept {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
Error MetalClawReader::field(const char*, BasicString<SmallStringSize> *val) noexcept {
|
||||
if (m_unionIdx == -1 || m_unionIdx == m_field) {
|
||||
if (m_fieldPresence.get(static_cast<std::size_t>(m_field))) {
|
||||
// read the length
|
||||
if (m_buffIt >= m_buffLen) {
|
||||
return OxError(MC_BUFFENDED);
|
||||
}
|
||||
std::size_t bytesRead = 0;
|
||||
oxRequire(size, mc::decodeInteger<StringLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead));
|
||||
m_buffIt += bytesRead;
|
||||
const auto cap = size;
|
||||
*val = BasicString<SmallStringSize>(cap);
|
||||
auto data = val->data();
|
||||
// read the string
|
||||
if (static_cast<StringLength>(cap) < size) {
|
||||
return OxError(MC_OUTBUFFENDED);
|
||||
}
|
||||
if (m_buffIt + size > m_buffLen) {
|
||||
return OxError(MC_BUFFENDED);
|
||||
}
|
||||
memcpy(data, &m_buff[m_buffIt], size);
|
||||
data[size] = 0;
|
||||
m_buffIt += size;
|
||||
} else {
|
||||
*val = "";
|
||||
}
|
||||
}
|
||||
++m_field;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<std::size_t L>
|
||||
Error MetalClawReader::field(const char *name, BString<L> *val) noexcept {
|
||||
return field(name, SerStr(val->data(), val->cap()));
|
||||
@ -201,7 +238,7 @@ Error MetalClawReader::field(const char *name, T *val, std::size_t valLen) noexc
|
||||
if (valLen >= len) {
|
||||
auto reader = child("");
|
||||
reader.setTypeInfo("List", static_cast<int>(len));
|
||||
for (std::size_t i = 0; i < len; i++) {
|
||||
for (std::size_t i = 0; i < len; ++i) {
|
||||
oxReturnError(reader.field("", &val[i]));
|
||||
}
|
||||
} else {
|
||||
@ -225,15 +262,14 @@ Error MetalClawReader::field(const char*, HashMap<String, T> *val) noexcept {
|
||||
std::size_t bytesRead = 0;
|
||||
oxRequire(len, mc::decodeInteger<ArrayLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead));
|
||||
m_buffIt += bytesRead;
|
||||
|
||||
// read the list
|
||||
auto reader = child("");
|
||||
reader.setTypeInfo("List", static_cast<int>(len));
|
||||
for (std::size_t i = 0; i < len; i++) {
|
||||
for (std::size_t i = 0; i < len; ++i) {
|
||||
const auto keyLen = reader.stringLength(nullptr);
|
||||
auto wkey = ox_malloca(keyLen + 1, char, 0);
|
||||
auto wkeyPtr = wkey.get();
|
||||
oxReturnError(reader.field("", SerStr(&wkeyPtr, static_cast<int>(keyLen))));
|
||||
oxReturnError(reader.fieldCString("", &wkeyPtr, static_cast<int>(keyLen + 1)));
|
||||
oxReturnError(reader.field("", &val->operator[](wkey.get())));
|
||||
}
|
||||
}
|
||||
@ -257,7 +293,7 @@ Error MetalClawReader::field(const char*, Handler handler) noexcept {
|
||||
// read the list
|
||||
auto reader = child("");
|
||||
reader.setTypeInfo("List", static_cast<int>(len));
|
||||
for (std::size_t i = 0; i < len; i++) {
|
||||
for (std::size_t i = 0; i < len; ++i) {
|
||||
T val;
|
||||
oxReturnError(reader.field("", &val));
|
||||
oxReturnError(handler(i, &val));
|
||||
|
81
deps/ox/src/ox/mc/test/tests.cpp
vendored
81
deps/ox/src/ox/mc/test/tests.cpp
vendored
@ -23,7 +23,7 @@ union TestUnion {
|
||||
static constexpr auto Fields = 3;
|
||||
bool Bool;
|
||||
uint32_t Int = 5;
|
||||
char String[32];
|
||||
char CString[32];
|
||||
};
|
||||
|
||||
struct TestStructNest {
|
||||
@ -31,7 +31,7 @@ struct TestStructNest {
|
||||
static constexpr auto Fields = 3;
|
||||
bool Bool = false;
|
||||
uint32_t Int = 0;
|
||||
ox::BString<32> String = "";
|
||||
ox::BString<32> BString = "";
|
||||
};
|
||||
|
||||
struct TestStruct {
|
||||
@ -48,7 +48,8 @@ struct TestStruct {
|
||||
int32_t Int7 = 0;
|
||||
int32_t Int8 = 0;
|
||||
TestUnion Union;
|
||||
ox::BString<32> String = "";
|
||||
ox::String String = "";
|
||||
ox::BString<32> BString = "";
|
||||
uint32_t List[4] = {0, 0, 0, 0};
|
||||
ox::HashMap<ox::String, int> Map;
|
||||
TestStructNest EmptyStruct;
|
||||
@ -60,18 +61,15 @@ constexpr ox::Error model(T *io, TestUnion *obj) noexcept {
|
||||
io->template setTypeInfo<TestUnion>();
|
||||
oxReturnError(io->field("Bool", &obj->Bool));
|
||||
oxReturnError(io->field("Int", &obj->Int));
|
||||
oxReturnError(io->field("String", ox::SerStr(obj->String)));
|
||||
oxReturnError(io->field("CString", ox::SerStr(obj->CString)));
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr ox::Error model(T *io, TestStructNest *obj) noexcept {
|
||||
io->template setTypeInfo<TestStructNest>();
|
||||
oxReturnError(io->field("Bool", &obj->Bool));
|
||||
oxReturnError(io->field("Int", &obj->Int));
|
||||
oxReturnError(io->field("String", &obj->String));
|
||||
return OxError(0);
|
||||
}
|
||||
oxModelBegin(TestStructNest)
|
||||
oxModelField(Bool)
|
||||
oxModelField(Int)
|
||||
oxModelField(BString)
|
||||
oxModelEnd()
|
||||
|
||||
template<typename T>
|
||||
constexpr ox::Error model(T *io, TestStruct *obj) noexcept {
|
||||
@ -88,6 +86,7 @@ constexpr ox::Error model(T *io, TestStruct *obj) noexcept {
|
||||
oxReturnError(io->field("Int8", &obj->Int8));
|
||||
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, 1}));
|
||||
oxReturnError(io->field("String", &obj->String));
|
||||
oxReturnError(io->field("BString", &obj->BString));
|
||||
oxReturnError(io->field("List", obj->List, 4));
|
||||
oxReturnError(io->field("Map", &obj->Map));
|
||||
oxReturnError(io->field("EmptyStruct", &obj->EmptyStruct));
|
||||
@ -119,7 +118,8 @@ std::map<std::string, ox::Error(*)()> tests = {
|
||||
testIn.Bool = true;
|
||||
testIn.Int = 42;
|
||||
testIn.Union.Int = 42;
|
||||
testIn.String = "Test String 1";
|
||||
testIn.String = "Test String 0";
|
||||
testIn.BString = "Test String 1";
|
||||
testIn.List[0] = 1;
|
||||
testIn.List[1] = 2;
|
||||
testIn.List[2] = 3;
|
||||
@ -128,36 +128,37 @@ std::map<std::string, ox::Error(*)()> tests = {
|
||||
testIn.Map["aoeu"] = 94;
|
||||
testIn.Struct.Bool = false;
|
||||
testIn.Struct.Int = 300;
|
||||
testIn.Struct.String = "Test String 2";
|
||||
testIn.Struct.BString = "Test String 2";
|
||||
|
||||
oxAssert(ox::writeMC(buff, buffLen, &testIn), "writeMC failed");
|
||||
oxAssert(ox::readMC(buff, buffLen, &testOut), "readMC failed");
|
||||
//std::cout << testIn.Union.Int << "|" << testOut.Union.Int << "|\n";
|
||||
|
||||
oxAssert(testIn.Bool == testOut.Bool, "Bool value mismatch");
|
||||
oxAssert(testIn.Int == testOut.Int, "Int value mismatch");
|
||||
oxAssert(testIn.Int1 == testOut.Int1, "Int1 value mismatch");
|
||||
oxAssert(testIn.Int2 == testOut.Int2, "Int2 value mismatch");
|
||||
oxAssert(testIn.Int3 == testOut.Int3, "Int3 value mismatch");
|
||||
oxAssert(testIn.Int4 == testOut.Int4, "Int4 value mismatch");
|
||||
oxAssert(testIn.Int5 == testOut.Int5, "Int5 value mismatch");
|
||||
oxAssert(testIn.Int6 == testOut.Int6, "Int6 value mismatch");
|
||||
oxAssert(testIn.Int7 == testOut.Int7, "Int7 value mismatch");
|
||||
oxAssert(testIn.Int8 == testOut.Int8, "Int8 value mismatch");
|
||||
oxAssert(testIn.Union.Int == testOut.Union.Int, "Union.Int value mismatch");
|
||||
oxAssert(testIn.String == testOut.String, "String value mismatch");
|
||||
oxAssert(testIn.List[0] == testOut.List[0], "List[0] value mismatch");
|
||||
oxAssert(testIn.List[1] == testOut.List[1], "List[1] value mismatch");
|
||||
oxAssert(testIn.List[2] == testOut.List[2], "List[2] value mismatch");
|
||||
oxAssert(testIn.List[3] == testOut.List[3], "List[3] value mismatch");
|
||||
oxAssert(testIn.Map["asdf"] == testOut.Map["asdf"], "Map[\"asdf\"] value mismatch");
|
||||
oxAssert(testIn.Map["aoeu"] == testOut.Map["aoeu"], "Map[\"aoeu\"] value mismatch");
|
||||
oxAssert(testIn.EmptyStruct.Bool == testOut.EmptyStruct.Bool, "EmptyStruct.Bool value mismatch");
|
||||
oxAssert(testIn.EmptyStruct.Int == testOut.EmptyStruct.Int, "EmptyStruct.Int value mismatch");
|
||||
oxAssert(testIn.EmptyStruct.String == testOut.EmptyStruct.String, "EmptyStruct.String value mismatch");
|
||||
oxAssert(testIn.Struct.Int == testOut.Struct.Int, "Struct.Int value mismatch");
|
||||
oxAssert(testIn.Struct.String == testOut.Struct.String, "Struct.String value mismatch");
|
||||
oxAssert(testIn.Struct.Bool == testOut.Struct.Bool, "Struct.Bool value mismatch");
|
||||
oxAssert(testIn.Bool == testOut.Bool, "Bool value mismatch");
|
||||
oxAssert(testIn.Int == testOut.Int, "Int value mismatch");
|
||||
oxAssert(testIn.Int1 == testOut.Int1, "Int1 value mismatch");
|
||||
oxAssert(testIn.Int2 == testOut.Int2, "Int2 value mismatch");
|
||||
oxAssert(testIn.Int3 == testOut.Int3, "Int3 value mismatch");
|
||||
oxAssert(testIn.Int4 == testOut.Int4, "Int4 value mismatch");
|
||||
oxAssert(testIn.Int5 == testOut.Int5, "Int5 value mismatch");
|
||||
oxAssert(testIn.Int6 == testOut.Int6, "Int6 value mismatch");
|
||||
oxAssert(testIn.Int7 == testOut.Int7, "Int7 value mismatch");
|
||||
oxAssert(testIn.Int8 == testOut.Int8, "Int8 value mismatch");
|
||||
oxAssert(testIn.Union.Int == testOut.Union.Int, "Union.Int value mismatch");
|
||||
oxAssert(testIn.String == testOut.String, "String value mismatch");
|
||||
oxAssert(testIn.BString == testOut.BString, "BString value mismatch");
|
||||
oxAssert(testIn.List[0] == testOut.List[0], "List[0] value mismatch");
|
||||
oxAssert(testIn.List[1] == testOut.List[1], "List[1] value mismatch");
|
||||
oxAssert(testIn.List[2] == testOut.List[2], "List[2] value mismatch");
|
||||
oxAssert(testIn.List[3] == testOut.List[3], "List[3] value mismatch");
|
||||
oxAssert(testIn.Map["asdf"] == testOut.Map["asdf"], "Map[\"asdf\"] value mismatch");
|
||||
oxAssert(testIn.Map["aoeu"] == testOut.Map["aoeu"], "Map[\"aoeu\"] value mismatch");
|
||||
oxAssert(testIn.EmptyStruct.Bool == testOut.EmptyStruct.Bool, "EmptyStruct.Bool value mismatch");
|
||||
oxAssert(testIn.EmptyStruct.Int == testOut.EmptyStruct.Int, "EmptyStruct.Int value mismatch");
|
||||
oxAssert(testIn.EmptyStruct.BString == testOut.EmptyStruct.BString, "EmptyStruct.BString value mismatch");
|
||||
oxAssert(testIn.Struct.Int == testOut.Struct.Int, "Struct.Int value mismatch");
|
||||
oxAssert(testIn.Struct.BString == testOut.Struct.BString, "Struct.BString value mismatch");
|
||||
oxAssert(testIn.Struct.Bool == testOut.Struct.Bool, "Struct.Bool value mismatch");
|
||||
|
||||
return OxError(0);
|
||||
}
|
||||
@ -277,14 +278,14 @@ std::map<std::string, ox::Error(*)()> tests = {
|
||||
|
||||
testIn.Bool = true;
|
||||
testIn.Int = 42;
|
||||
testIn.String = "Test String 1";
|
||||
testIn.BString = "Test String 1";
|
||||
testIn.List[0] = 1;
|
||||
testIn.List[1] = 2;
|
||||
testIn.List[2] = 3;
|
||||
testIn.List[3] = 4;
|
||||
testIn.Struct.Bool = false;
|
||||
testIn.Struct.Int = 300;
|
||||
testIn.Struct.String = "Test String 2";
|
||||
testIn.Struct.BString = "Test String 2";
|
||||
|
||||
oxAssert(ox::writeMC(dataBuff, dataBuffLen, &testIn), "Data generation failed");
|
||||
auto type = ox::buildTypeDef(&testIn);
|
||||
|
2
deps/ox/src/ox/mc/write.cpp
vendored
2
deps/ox/src/ox/mc/write.cpp
vendored
@ -90,7 +90,7 @@ Error MetalClawWriter::field(const char*, SerStr val) noexcept {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
std::size_t MetalClawWriter::size() noexcept {
|
||||
std::size_t MetalClawWriter::size() const noexcept {
|
||||
return m_buffIt;
|
||||
}
|
||||
|
||||
|
29
deps/ox/src/ox/mc/write.hpp
vendored
29
deps/ox/src/ox/mc/write.hpp
vendored
@ -60,6 +60,9 @@ class MetalClawWriter {
|
||||
template<typename T>
|
||||
Error field(const char*, HashMap<String, T> *val) noexcept;
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
Error field(const char*, BasicString<SmallStringSize> *val) noexcept;
|
||||
|
||||
template<std::size_t L>
|
||||
Error field(const char*, BString<L> *val) noexcept;
|
||||
|
||||
@ -75,7 +78,7 @@ class MetalClawWriter {
|
||||
void setTypeInfo(const char *name = T::TypeName, int fields = countFields<T>()) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
std::size_t size() noexcept;
|
||||
std::size_t size() const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr auto opType() noexcept {
|
||||
@ -88,6 +91,28 @@ class MetalClawWriter {
|
||||
|
||||
};
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
Error MetalClawWriter::field(const char*, BasicString<SmallStringSize> *val) noexcept {
|
||||
bool fieldSet = false;
|
||||
if (val->len() && (m_unionIdx == -1 || m_unionIdx == m_field)) {
|
||||
// write the length
|
||||
const auto strLen = mc::encodeInteger(val->len());
|
||||
if (m_buffIt + strLen.length + static_cast<std::size_t>(val->len()) < m_buffLen) {
|
||||
memcpy(&m_buff[m_buffIt], strLen.data, strLen.length);
|
||||
m_buffIt += strLen.length;
|
||||
// write the string
|
||||
memcpy(&m_buff[m_buffIt], val->c_str(), static_cast<std::size_t>(val->len()));
|
||||
m_buffIt += static_cast<std::size_t>(val->len());
|
||||
fieldSet = true;
|
||||
} else {
|
||||
return OxError(MC_BUFFENDED);
|
||||
}
|
||||
}
|
||||
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
|
||||
++m_field;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<std::size_t L>
|
||||
Error MetalClawWriter::field(const char *name, BString<L> *val) noexcept {
|
||||
return field(name, SerStr(val->data(), val->cap()));
|
||||
@ -108,7 +133,7 @@ Error MetalClawWriter::field(const char*, T *val) noexcept {
|
||||
}
|
||||
}
|
||||
oxReturnError(m_fieldPresence.set(static_cast<std::size_t>(m_field), fieldSet));
|
||||
m_field++;
|
||||
++m_field;
|
||||
return OxError(0);
|
||||
}
|
||||
}
|
||||
|
8
deps/ox/src/ox/model/types.hpp
vendored
8
deps/ox/src/ox/model/types.hpp
vendored
@ -94,9 +94,11 @@ class SerStr {
|
||||
|
||||
constexpr char *data(std::size_t sz = 0) noexcept {
|
||||
if (m_tgt && sz) {
|
||||
*m_tgt = new char[sz];
|
||||
m_str = *m_tgt;
|
||||
m_cap = static_cast<int>(sz);
|
||||
if (!*m_tgt || sz > static_cast<std::size_t>(m_cap)) {
|
||||
*m_tgt = new char[sz];
|
||||
m_str = *m_tgt;
|
||||
m_cap = static_cast<int>(sz);
|
||||
}
|
||||
}
|
||||
return m_str;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user