From 5d95b188d8ff5d3e4be0951af7e236de383be596 Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Thu, 9 Apr 2020 22:49:56 -0500 Subject: [PATCH] [ox/model] Harmonize make the interface for walking over models --- deps/ox/src/ox/mc/mc.hpp | 1 - deps/ox/src/ox/mc/read.cpp | 9 +- deps/ox/src/ox/mc/read.hpp | 18 +-- deps/ox/src/ox/mc/test/tests.cpp | 8 +- deps/ox/src/ox/mc/walk.hpp | 22 --- deps/ox/src/ox/mc/write.cpp | 8 +- deps/ox/src/ox/mc/write.hpp | 3 +- deps/ox/src/ox/model/descwrite.hpp | 10 +- deps/ox/src/ox/model/optype.hpp | 17 +- deps/ox/src/ox/model/types.hpp | 4 - deps/ox/src/ox/model/walk.hpp | 19 ++- deps/ox/src/ox/oc/read.cpp | 202 ++++++++++++++++++----- deps/ox/src/ox/oc/read.hpp | 72 ++++++--- deps/ox/src/ox/oc/test/CMakeLists.txt | 1 + deps/ox/src/ox/oc/test/tests.cpp | 222 +++++++++++++------------- deps/ox/src/ox/oc/write.cpp | 7 +- deps/ox/src/ox/oc/write.hpp | 7 +- 17 files changed, 376 insertions(+), 254 deletions(-) delete mode 100644 deps/ox/src/ox/mc/walk.hpp diff --git a/deps/ox/src/ox/mc/mc.hpp b/deps/ox/src/ox/mc/mc.hpp index 0032fe16..b7e69905 100644 --- a/deps/ox/src/ox/mc/mc.hpp +++ b/deps/ox/src/ox/mc/mc.hpp @@ -11,5 +11,4 @@ #include "intops.hpp" #include "read.hpp" #include "types.hpp" -#include "walk.hpp" #include "write.hpp" diff --git a/deps/ox/src/ox/mc/read.cpp b/deps/ox/src/ox/mc/read.cpp index d691e5e2..03704a37 100644 --- a/deps/ox/src/ox/mc/read.cpp +++ b/deps/ox/src/ox/mc/read.cpp @@ -81,6 +81,7 @@ Error MetalClawReader::field(const char*, SerStr val) { if (val.cap() > -1 && static_cast(val.cap()) >= size) { if (m_buffIt + size <= m_buffLen) { ox_memcpy(val.data(), &m_buff[m_buffIt], size); + val.data()[size] = 0; m_buffIt += size; } else { return OxError(MC_BUFFENDED); @@ -94,7 +95,7 @@ Error MetalClawReader::field(const char*, SerStr val) { return OxError(0); } -[[nodiscard]] ValErr MetalClawReader::arrayLength(bool pass) { +[[nodiscard]] ValErr MetalClawReader::arrayLength(const char*, bool pass) { if (m_fieldPresence.get(m_field)) { // read the length if (m_buffIt >= m_buffLen) { @@ -110,7 +111,7 @@ Error MetalClawReader::field(const char*, SerStr val) { return OxError(1); } -[[nodiscard]] StringLength MetalClawReader::stringLength() { +[[nodiscard]] StringLength MetalClawReader::stringLength(const char*) { if (m_fieldPresence.get(m_field)) { // read the length std::size_t bytesRead = 0; @@ -127,11 +128,11 @@ void MetalClawReader::setTypeInfo(const char*, int fields) { m_fieldPresence.setMaxLen(m_buffIt); } -MetalClawReader MetalClawReader::child() { +MetalClawReader MetalClawReader::child(const char*) { return MetalClawReader(m_buff + m_buffIt, m_buffLen - m_buffIt, this); } -bool MetalClawReader::fieldPresent() const { +bool MetalClawReader::fieldPresent(const char*) const { return m_fieldPresence.get(m_field).value; } diff --git a/deps/ox/src/ox/mc/read.hpp b/deps/ox/src/ox/mc/read.hpp index a9a56492..150f8587 100644 --- a/deps/ox/src/ox/mc/read.hpp +++ b/deps/ox/src/ox/mc/read.hpp @@ -77,24 +77,24 @@ class MetalClawReader { * Reads an array length from the current location in the buffer. * @param pass indicates that the parsing should iterate past the array length */ - [[nodiscard]] ValErr arrayLength(bool pass = true); + [[nodiscard]] ValErr arrayLength(const char *name, bool pass = true); /** * Reads an string length from the current location in the buffer. */ - [[nodiscard]] StringLength stringLength(); + [[nodiscard]] StringLength stringLength(const char *name); void setTypeInfo(const char *name, int fields); /** * Returns a MetalClawReader to parse a child object. */ - [[nodiscard]] MetalClawReader child(); + [[nodiscard]] MetalClawReader child(const char *name); /** * Indicates whether or not the next field to be read is present. */ - bool fieldPresent() const; + bool fieldPresent(const char *name) const; /** * Indicates whether or not the given field is present. @@ -103,7 +103,7 @@ class MetalClawReader { void nextField() noexcept; - static constexpr OpType opType() { + static constexpr auto opType() { return OpType::Read; } @@ -116,7 +116,7 @@ class MetalClawReader { template Error MetalClawReader::field(const char*, T *val) { if (val && m_fieldPresence.get(m_field++)) { - auto reader = child(); + auto reader = child(""); oxReturnError(model(&reader, val)); } return OxError(0); @@ -160,7 +160,7 @@ Error MetalClawReader::field(const char *name, T *val, std::size_t valLen) { // read the list if (valLen >= len.value) { - auto reader = child(); + auto reader = child(""); reader.setTypeInfo("List", len.value); for (std::size_t i = 0; i < len.value; i++) { oxReturnError(reader.field("", &val[i])); @@ -186,7 +186,7 @@ Error MetalClawReader::field(const char*, Handler handler) { oxReturnError(len.error); // read the list - auto reader = child(); + auto reader = child(""); reader.setTypeInfo("List", len.value); for (std::size_t i = 0; i < len.value; i++) { T val; @@ -200,7 +200,7 @@ Error MetalClawReader::field(const char*, Handler handler) { template Error MetalClawReader::field(const char* name, ox::Vector *val) { if (m_fieldPresence.get(m_field)) { - const auto [len, err] = arrayLength(false); + const auto [len, err] = arrayLength(name, false); oxReturnError(err); val->resize(len); return field(name, val->data(), val->size()); diff --git a/deps/ox/src/ox/mc/test/tests.cpp b/deps/ox/src/ox/mc/test/tests.cpp index cbdea9c5..4e3bfb65 100644 --- a/deps/ox/src/ox/mc/test/tests.cpp +++ b/deps/ox/src/ox/mc/test/tests.cpp @@ -109,7 +109,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'; + //std::cout << testIn.String.c_str() << "|" << testOut.String.c_str() << "|\n"; oxAssert(testIn.Bool == testOut.Bool, "Bool value mismatch"); oxAssert(testIn.Int == testOut.Int, "Int value mismatch"); @@ -260,9 +260,9 @@ std::map tests = { testIn.Struct.String = "Test String 2"; oxAssert(ox::writeMC(dataBuff, dataBuffLen, &testIn), "Data generation failed"); - auto type = ox::buildMCDef(&testIn); + auto type = ox::buildTypeDef(&testIn); oxAssert(type.error, "Descriptor write failed"); - ox::walkMC(type.value, dataBuff, dataBuffLen, + ox::walkModel(type.value, dataBuff, dataBuffLen, [](const ox::Vector&, const ox::Vector&, const ox::DescriptorField &f, ox::MetalClawReader *rdr) -> ox::Error { //std::cout << f.fieldName.c_str() << '\n'; auto fieldName = f.fieldName.c_str(); @@ -334,7 +334,7 @@ std::map tests = { break; } case ox::PrimitiveType::String: { - ox::Vector v(rdr->stringLength()); + ox::Vector v(rdr->stringLength(fieldName) + 1); //std::cout << rdr->stringLength() << '\n'; oxAssert(rdr->field(fieldName, ox::SerStr(v.data(), v.size())), "Walking model failed."); std::cout << fieldName << ":\t" << "string: " << v.data() << '\n'; diff --git a/deps/ox/src/ox/mc/walk.hpp b/deps/ox/src/ox/mc/walk.hpp deleted file mode 100644 index c39f4216..00000000 --- a/deps/ox/src/ox/mc/walk.hpp +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2015 - 2018 gtalent2@gmail.com - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#pragma once - -#include - -namespace ox { - -template -ox::Error walkMC(DescriptorType *type, uint8_t *data, std::size_t dataLen, Handler handler) { - DataWalker walker(type, handler); - Reader rdr(data, dataLen); - return model(&rdr, &walker); -} - -} diff --git a/deps/ox/src/ox/mc/write.cpp b/deps/ox/src/ox/mc/write.cpp index 89397c57..b1276d32 100644 --- a/deps/ox/src/ox/mc/write.cpp +++ b/deps/ox/src/ox/mc/write.cpp @@ -65,14 +65,14 @@ Error MetalClawWriter::field(const char*, SerStr val) { bool fieldSet = false; if (val.cap()) { // write the length - const auto strLen = mc::encodeInteger(val.bytes()); - if (m_buffIt + strLen.length + val.bytes() < m_buffLen) { + const auto strLen = mc::encodeInteger(val.len()); + if (m_buffIt + strLen.length + val.len() < 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()); - m_buffIt += val.bytes(); + ox_memcpy(&m_buff[m_buffIt], val.c_str(), val.len()); + m_buffIt += val.len(); fieldSet = true; } else { err = OxError(MC_BUFFENDED); diff --git a/deps/ox/src/ox/mc/write.hpp b/deps/ox/src/ox/mc/write.hpp index 3f4382df..e58ad043 100644 --- a/deps/ox/src/ox/mc/write.hpp +++ b/deps/ox/src/ox/mc/write.hpp @@ -68,13 +68,14 @@ class MetalClawWriter { std::size_t size(); - static constexpr OpType opType() { + static constexpr auto opType() { return OpType::Write; } private: template Error appendInteger(I val); + }; template diff --git a/deps/ox/src/ox/model/descwrite.hpp b/deps/ox/src/ox/model/descwrite.hpp index 75f67268..31041d1f 100644 --- a/deps/ox/src/ox/model/descwrite.hpp +++ b/deps/ox/src/ox/model/descwrite.hpp @@ -78,7 +78,7 @@ class TypeDescWriter { return m_type; } - static constexpr OpType opType() { + static constexpr auto opType() { return OpType::WriteDefinition; } @@ -163,18 +163,18 @@ DescriptorType *TypeDescWriter::type(T *val, bool *alreadyExisted) { } template -[[nodiscard]] ValErr buildMCDef(T *val) { +[[nodiscard]] ValErr buildTypeDef(T *val) { TypeDescWriter writer; Error err = model(&writer, val); return {writer.definition(), err}; } template -Error writeMCDef(uint8_t *buff, std::size_t buffLen, T *val, std::size_t *sizeOut = nullptr) { - auto def = buildMCDef(val); +Error writeTypeDef(uint8_t *buff, std::size_t buffLen, T *val, std::size_t *sizeOut = nullptr) { + auto def = buildTypeDef(val); auto err = def.error; if (!err) { - err |= writeMC(buff, buffLen, def.value, sizeOut); + oxReturnError(writeType(buff, buffLen, def.value, sizeOut)); } delete def.value; return err; diff --git a/deps/ox/src/ox/model/optype.hpp b/deps/ox/src/ox/model/optype.hpp index 95571234..92e3dac9 100644 --- a/deps/ox/src/ox/model/optype.hpp +++ b/deps/ox/src/ox/model/optype.hpp @@ -9,14 +9,15 @@ #pragma once #include +#include namespace ox { -enum class OpType { - Read = 1, - Write = 2, - WriteDefinition = 3, -}; +namespace OpType { + constexpr auto Read = "Read"; + constexpr auto Write = "Write"; + constexpr auto WriteDefinition = "WriteDefinition"; +} // empty default implementations of model functions @@ -37,11 +38,11 @@ ox::Error modelWriteDefinition(T*, O*) { template ox::Error model(T *io, O *obj) { - if constexpr(T::opType() == ox::OpType::Read) { + if constexpr(ox_strcmp(T::opType(), ox::OpType::Read) == 0) { return modelRead(io, obj); - } else if constexpr(T::opType() == ox::OpType::Write) { + } else if constexpr(ox_strcmp(T::opType(), ox::OpType::Write) == 0) { return modelWrite(io, obj); - } else if constexpr(T::opType() == ox::OpType::WriteDefinition) { + } else if constexpr(ox_strcmp(T::opType(), ox::OpType::WriteDefinition) == 0) { return modelWriteDefinition(io, obj); } return OxError(1); diff --git a/deps/ox/src/ox/model/types.hpp b/deps/ox/src/ox/model/types.hpp index 3cf52db4..bd19d169 100644 --- a/deps/ox/src/ox/model/types.hpp +++ b/deps/ox/src/ox/model/types.hpp @@ -45,10 +45,6 @@ class SerStr { return ox_strlen(m_str); } - constexpr int bytes() noexcept { - return ox_strlen(m_str) + 1; // adds 1 for \0 - } - constexpr int cap() noexcept { return m_cap; } diff --git a/deps/ox/src/ox/model/walk.hpp b/deps/ox/src/ox/model/walk.hpp index 79b9ffb8..460f9309 100644 --- a/deps/ox/src/ox/model/walk.hpp +++ b/deps/ox/src/ox/model/walk.hpp @@ -86,14 +86,14 @@ static ox::Error parseField(const DescriptorField &field, Reader *rdr, DataWalke walker->pushNamePath(field.fieldName); if (field.subscriptLevels) { // add array handling - const auto [arrayLen, err] = rdr->arrayLength(true); + const auto [arrayLen, err] = rdr->arrayLength(field.fieldName.c_str(), true); oxReturnError(err); - auto child = rdr->child(); + auto child = rdr->child(field.fieldName.c_str()); child.setTypeInfo(field.fieldName.c_str(), arrayLen); DescriptorField f(field); // create mutable copy --f.subscriptLevels; BString<100> subscript; - for (ArrayLength i = 0; i < arrayLen; i++) { + for (std::size_t i = 0; i < arrayLen; i++) { subscript = "["; subscript += i; subscript += "]"; @@ -111,8 +111,8 @@ static ox::Error parseField(const DescriptorField &field, Reader *rdr, DataWalke oxReturnError(walker->read(field, rdr)); break; case PrimitiveType::Struct: - if (rdr->fieldPresent()) { - auto child = rdr->child(); + if (rdr->fieldPresent(field.fieldName.c_str())) { + auto child = rdr->child(field.fieldName.c_str()); walker->pushType(field.type); oxReturnError(model(&child, walker)); walker->popType(); @@ -120,7 +120,7 @@ static ox::Error parseField(const DescriptorField &field, Reader *rdr, DataWalke } else { // skip and discard absent field int discard; - oxReturnError(rdr->field("", &discard)); + oxReturnError(rdr->field(field.fieldName.c_str(), &discard)); } break; } @@ -144,4 +144,11 @@ ox::Error model(Reader *rdr, DataWalker *walker) { return OxError(0); } +template +ox::Error walkModel(DescriptorType *type, uint8_t *data, std::size_t dataLen, Handler handler) { + DataWalker walker(type, handler); + Reader rdr(data, dataLen); + return model(&rdr, &walker); +} + } diff --git a/deps/ox/src/ox/oc/read.cpp b/deps/ox/src/ox/oc/read.cpp index fef0afc3..77dbf132 100644 --- a/deps/ox/src/ox/oc/read.cpp +++ b/deps/ox/src/ox/oc/read.cpp @@ -1,108 +1,220 @@ /* - * Copyright 2015 - 2018 gtalent2@gmail.com + * Copyright 2015 - 2020 gtalent2@gmail.com * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include + #include "read.hpp" namespace ox { template -OrganicClawReader::OrganicClawReader(Json::Value json) { +OrganicClawReader::OrganicClawReader(const uint8_t *buff, std::size_t buffSize) { + auto json = bit_cast(buff); + auto jsonLen = ox_strnlen(json, buffSize); + Json::CharReaderBuilder parserBuilder; + auto parser = std::unique_ptr(parserBuilder.newCharReader()); + if (!parser->parse(json, json + jsonLen, &m_json, nullptr)) { + throw OxError(1, "Could not parse JSON"); + } +} + +template +OrganicClawReader::OrganicClawReader(const char *json, std::size_t jsonLen) { + Json::CharReaderBuilder parserBuilder; + auto parser = std::unique_ptr(parserBuilder.newCharReader()); + if (!parser->parse(json, json + jsonLen, &m_json, nullptr)) { + throw OxError(1, "Could not parse JSON"); + } +} + +template +OrganicClawReader::OrganicClawReader(const Json::Value &json) { m_json = json; } -template -OrganicClawReader::~OrganicClawReader() { -} - template Error OrganicClawReader::field(Key key, int8_t *val) { - *val = static_cast(m_json[key].asInt()); - return OxError(0); + const auto &jv = value(key); + ++m_fieldIt; + if (jv.empty()) { + return OxError(0); + } + if (jv.isInt()) { + *val = static_cast(jv.asInt()); + return OxError(0); + } + return OxError(1, "Type mismatch"); } template Error OrganicClawReader::field(Key key, int16_t *val) { - *val = static_cast(m_json[key].asInt()); - return OxError(0); + const auto &jv = value(key); + ++m_fieldIt; + if (jv.empty()) { + return OxError(0); + } + if (jv.isInt()) { + *val = static_cast(jv.asInt()); + return OxError(0); + } + return OxError(1, "Type mismatch"); } template Error OrganicClawReader::field(Key key, int32_t *val) { - *val = static_cast(m_json[key].asInt()); - return OxError(0); + const auto &jv = value(key); + ++m_fieldIt; + if (jv.empty()) { + return OxError(0); + } + if (jv.isInt()) { + *val = static_cast(jv.asInt()); + return OxError(0); + } + return OxError(1, "Type mismatch"); } template Error OrganicClawReader::field(Key key, int64_t *val) { - *val = static_cast(m_json[key].asInt64()); - return OxError(0); + const auto &jv = value(key); + ++m_fieldIt; + if (jv.empty()) { + return OxError(0); + } + if (jv.isInt() || jv.isInt64()) { + *val = static_cast(jv.asInt64()); + return OxError(0); + } + return OxError(1, "Type mismatch"); } template Error OrganicClawReader::field(Key key, uint8_t *val) { - *val = static_cast(m_json[key].asUInt()); - return OxError(0); + const auto &jv = value(key); + ++m_fieldIt; + if (jv.empty()) { + return OxError(0); + } + if (jv.isUInt()) { + *val = static_cast(jv.asUInt()); + return OxError(0); + } + return OxError(1, "Type mismatch"); } template Error OrganicClawReader::field(Key key, uint16_t *val) { - *val = static_cast(m_json[key].asUInt()); - return OxError(0); + const auto &jv = value(key); + ++m_fieldIt; + if (jv.empty()) { + return OxError(0); + } + if (jv.isUInt()) { + *val = static_cast(jv.asUInt()); + return OxError(0); + } + return OxError(1, "Type mismatch"); } template Error OrganicClawReader::field(Key key, uint32_t *val) { - *val = static_cast(m_json[key].asUInt()); - return OxError(0); + const auto &jv = value(key); + ++m_fieldIt; + if (jv.empty()) { + return OxError(0); + } + if (jv.isUInt()) { + *val = static_cast(jv.asUInt()); + return OxError(0); + } + return OxError(1, "Type mismatch"); } template Error OrganicClawReader::field(Key key, uint64_t *val) { - *val = static_cast(m_json[key].asUInt64()); - return OxError(0); + const auto &jv = value(key); + ++m_fieldIt; + if (jv.empty()) { + return OxError(0); + } + if (jv.isUInt() || jv.isUInt64()) { + *val = static_cast(jv.asUInt64()); + return OxError(0); + } + return OxError(1, "Type mismatch"); } template Error OrganicClawReader::field(Key key, bool *val) { - *val = m_json[key].asBool(); - return OxError(0); + const auto &jv = value(key); + ++m_fieldIt; + if (jv.empty()) { + return OxError(0); + } + if (jv.isBool()) { + *val = jv.asBool(); + return OxError(0); + } + return OxError(1, "Type mismatch"); } template Error OrganicClawReader::field(Key key, SerStr val) { const char *begin = nullptr, *end = nullptr; - m_json[key].getString(&begin, &end); - auto strSize = end - begin; - if (strSize >= val.cap()) { - return OxError(1); + const auto &jv = value(key); + ++m_fieldIt; + if (jv.empty()) { + return OxError(0); } - ox_memcpy(val.data(), begin, static_cast(strSize)); - val.data()[strSize] = 0; - return OxError(0); + if (jv.isString()) { + jv.getString(&begin, &end); + auto strSize = end - begin; + if (strSize >= val.cap()) { + return OxError(1, "String size exceeds capacity of destination"); + } + ox_memcpy(val.data(), begin, static_cast(strSize)); + val.data()[strSize] = 0; + return OxError(0); + } + return OxError(1, "Type mismatch"); } template -[[nodiscard]] std::size_t OrganicClawReader::arrayLength(Key key, bool) { - return m_json[key].size(); +[[nodiscard]] ValErr OrganicClawReader::arrayLength(Key key, bool) { + const auto &jv = value(key); + ++m_fieldIt; + if (jv.empty()) { + return 0; + } + if (jv.isArray()) { + return jv.size(); + } + return OxError(1, "Type mismatch"); } template [[nodiscard]] std::size_t OrganicClawReader::stringLength(Key key) { const char *begin = nullptr, *end = nullptr; - m_json[key].getString(&begin, &end); - return static_cast(end - begin); + const auto &jv = value(key); + ++m_fieldIt; + if (jv.empty()) { + return 0; + } + if (jv.isString()) { + jv.getString(&begin, &end); + return static_cast(end - begin); + } + return OxError(1, "Type mismatch"); } template -void OrganicClawReader::setTypeInfo(const char*, int fields) { - m_fields = fields; - m_buffIt = static_cast((fields / 8 + 1) - (fields % 8 == 0)); +void OrganicClawReader::setTypeInfo(const char*, int) { } template @@ -110,6 +222,20 @@ OrganicClawReader OrganicClawReader::child(Key key) { return OrganicClawReader(m_json[key]); } +template +bool OrganicClawReader::fieldPresent(Key key) { + return !m_json[key].empty(); +} + +template +Json::Value &OrganicClawReader::value(Key key) { + if (m_json.isArray()) { + return m_json[m_fieldIt]; + } else { + return m_json[key]; + } +} + template class OrganicClawReader; template class OrganicClawReader; diff --git a/deps/ox/src/ox/oc/read.hpp b/deps/ox/src/ox/oc/read.hpp index 378715b3..803dab0f 100644 --- a/deps/ox/src/ox/oc/read.hpp +++ b/deps/ox/src/ox/oc/read.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2015 - 2018 gtalent2@gmail.com + * Copyright 2015 - 2020 gtalent2@gmail.com * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -23,16 +23,16 @@ class OrganicClawReader { private: Json::Value m_json; - int m_fields = 0; - int m_field = 0; - std::size_t m_buffIt = 0; - std::size_t m_buffLen = 0; - uint8_t *m_buff = nullptr; + Json::ArrayIndex m_fieldIt = 0; public: - OrganicClawReader(Json::Value json = {}); + OrganicClawReader() = default; - ~OrganicClawReader(); + OrganicClawReader(const uint8_t *buff, std::size_t buffSize); + + OrganicClawReader(const char *json, std::size_t buffSize); + + OrganicClawReader(const Json::Value &json); [[nodiscard]] Error field(Key key, int8_t *val); [[nodiscard]] Error field(Key key, int16_t *val); @@ -65,7 +65,7 @@ class OrganicClawReader { * Reads an array length from the current location in the buffer. * @param pass indicates that the parsing should iterate past the array length */ - [[nodiscard]] std::size_t arrayLength(Key key, bool pass = true); + [[nodiscard]] ValErr arrayLength(Key key, bool pass = true); /** * Reads an string length from the current location in the buffer. @@ -79,18 +79,34 @@ class OrganicClawReader { */ [[nodiscard]] OrganicClawReader child(Key key); - static constexpr OpType opType() { + // compatibility stub + constexpr void nextField() noexcept {} + + bool fieldPresent(Key key); + + static constexpr auto opType() { return OpType::Read; } + private: + + Json::Value &value(Key key); + }; template template Error OrganicClawReader::field(Key key, T *val) { if (val) { - auto reader = child(key); - oxReturnError(model(&reader, val)); + const auto &jv = value(key); + ++m_fieldIt; + if (jv.empty()) { + return OxError(0); + } + if (jv.isObject()) { + auto reader = child(key); + return model(&reader, val); + } } return OxError(0); } @@ -110,9 +126,9 @@ Error OrganicClawReader::field(Key key, T *val, std::size_t valLen) { if (srcSize > valLen) { return OxError(1); } - OrganicClawReader r(srcVal); + OrganicClawReader r(srcVal); for (decltype(srcSize) i = 0; i < srcSize; ++i) { - oxReturnError(r.field(i, &val[i])); + oxReturnError(r.field("", &val[i])); } return OxError(0); } @@ -124,16 +140,28 @@ Error OrganicClawReader::field(Key key, ox::Vector *val) { } template -ValErr readOC(const char *json) { - Json::Value doc; - Json::CharReaderBuilder parserBuilder; - auto parser = std::unique_ptr(parserBuilder.newCharReader()); - if (!parser->parse(json, json + ox_strlen(json), &doc, nullptr)) { - return OxError(1, "Could not parse JSON"); +Error readOC(const char *json, std::size_t jsonSize, T *val) noexcept { + // OrganicClawReader constructor can throw, but readOC should return its errors. + try { + Json::Value doc; + Json::CharReaderBuilder parserBuilder; + auto parser = std::unique_ptr(parserBuilder.newCharReader()); + if (!parser->parse(json, json + jsonSize, &doc, nullptr)) { + return OxError(1, "Could not parse JSON"); + } + OrganicClawReader reader(json, jsonSize); + return model(&reader, val); + } catch (Error err) { + return err; + } catch (...) { + return OxError(1, "Unkown Error"); } - OrganicClawReader reader(doc); +} + +template +ValErr readOC(const char *json) { T val; - oxReturnError(model(&reader, &val)); + oxReturnError(readOC(json, ox_strlen(json), &val)); return {std::move(val), OxError(0)}; } diff --git a/deps/ox/src/ox/oc/test/CMakeLists.txt b/deps/ox/src/ox/oc/test/CMakeLists.txt index d4175837..39281829 100644 --- a/deps/ox/src/ox/oc/test/CMakeLists.txt +++ b/deps/ox/src/ox/oc/test/CMakeLists.txt @@ -10,3 +10,4 @@ target_link_libraries( add_test("Test\\ OcTest\\ Writer" OcTest OrganicClawWriter) add_test("Test\\ OcTest\\ Reader" OcTest OrganicClawReader) +add_test("Test\\ OcTest\\ OrganicClawDef" OcTest OrganicClawDef) diff --git a/deps/ox/src/ox/oc/test/tests.cpp b/deps/ox/src/ox/oc/test/tests.cpp index 3bbb84ef..e6235574 100644 --- a/deps/ox/src/ox/oc/test/tests.cpp +++ b/deps/ox/src/ox/oc/test/tests.cpp @@ -8,14 +8,12 @@ #undef NDEBUG -#include #include #include -#include #include -#include -#include + #include +#include #include struct TestStructNest { @@ -128,119 +126,115 @@ std::map tests = { return OxError(0); } }, - //{ - // "OrganicClawDef", - // [] { - // auto err = OxError(0); - // //constexpr size_t descBuffLen = 1024; - // //uint8_t descBuff[descBuffLen]; - // constexpr size_t dataBuffLen = 1024; - // uint8_t dataBuff[dataBuffLen]; - // TestStruct testIn, testOut; + { + "OrganicClawDef", + [] { + TestStruct testIn, testOut; - // testIn.Bool = true; - // testIn.Int = 42; - // testIn.String = "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.Bool = true; + testIn.Int = 42; + testIn.String = "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"; - // oxAssert(ox::writeOC(&testIn), "Data generation failed"); - // auto type = ox::buildMCDef(&testIn); - // oxAssert(type.error, "Descriptor write failed"); - // ox::walkMC>(type.value, dataBuff, dataBuffLen, - // [](const ox::Vector&, const ox::Vector&, const ox::DescriptorField &f, ox::OrganicClawReader *rdr) -> ox::Error { - // //std::cout << f.fieldName.c_str() << '\n'; - // auto fieldName = f.fieldName.c_str(); - // switch (f.type->primitiveType) { - // case ox::PrimitiveType::UnsignedInteger: - // std::cout << fieldName << ":\tuint" << f.type->length * 8 << "_t:\t"; - // switch (f.type->length) { - // case 1: { - // uint8_t i = {}; - // oxAssert(rdr->field(fieldName, &i), "Walking model failed."); - // std::cout << i; - // break; - // } - // case 2: { - // uint16_t i = {}; - // oxAssert(rdr->field(fieldName, &i), "Walking model failed."); - // std::cout << i; - // break; - // } - // case 4: { - // uint32_t i = {}; - // oxAssert(rdr->field(fieldName, &i), "Walking model failed."); - // std::cout << i; - // break; - // } - // case 8: { - // uint64_t i = {}; - // oxAssert(rdr->field(fieldName, &i), "Walking model failed."); - // std::cout << i; - // break; - // } - // } - // std::cout << '\n'; - // break; - // case ox::PrimitiveType::SignedInteger: - // std::cout << fieldName << ":\tint" << f.type->length * 8 << "_t:\t"; - // switch (f.type->length) { - // case 1: { - // int8_t i = {}; - // oxAssert(rdr->field(fieldName, &i), "Walking model failed."); - // std::cout << i; - // break; - // } - // case 2: { - // int16_t i = {}; - // oxAssert(rdr->field(fieldName, &i), "Walking model failed."); - // std::cout << i; - // break; - // } - // case 4: { - // int32_t i = {}; - // oxAssert(rdr->field(fieldName, &i), "Walking model failed."); - // std::cout << i; - // break; - // } - // case 8: { - // int64_t i = {}; - // oxAssert(rdr->field(fieldName, &i), "Walking model failed."); - // std::cout << i; - // break; - // } - // } - // std::cout << '\n'; - // break; - // case ox::PrimitiveType::Bool: { - // bool i = {}; - // oxAssert(rdr->field(fieldName, &i), "Walking model failed."); - // std::cout << fieldName << ":\t" << "bool:\t" << (i ? "true" : "false") << '\n'; - // break; - // } - // case ox::PrimitiveType::String: { - // ox::Vector v(rdr->stringLength()); - // //std::cout << rdr->stringLength() << '\n'; - // oxAssert(rdr->field(fieldName, ox::SerStr(v.data(), v.size())), "Walking model failed."); - // std::cout << fieldName << ":\t" << "string: " << v.data() << '\n'; - // break; - // } - // case ox::PrimitiveType::Struct: - // break; - // } - // return OxError(0); - // } - // ); - // delete type.value; + auto [oc, ocErr] = ox::writeOC(&testIn); + oxAssert(ocErr, "Data generation failed"); + auto type = ox::buildTypeDef(&testIn); + oxAssert(type.error, "Descriptor write failed"); + ox::walkModel>(type.value, ox::bit_cast(oc.c_str()), oc.len() + 1, + [](const ox::Vector&, const ox::Vector&, const ox::DescriptorField &f, ox::OrganicClawReader *rdr) -> ox::Error { + //std::cout << f.fieldName.c_str() << '\n'; + auto fieldName = f.fieldName.c_str(); + switch (f.type->primitiveType) { + case ox::PrimitiveType::UnsignedInteger: + std::cout << fieldName << ":\tuint" << f.type->length * 8 << "_t:\t"; + switch (f.type->length) { + case 1: { + uint8_t i = {}; + oxAssert(rdr->field(fieldName, &i), "Walking model failed."); + std::cout << i; + break; + } + case 2: { + uint16_t i = {}; + oxAssert(rdr->field(fieldName, &i), "Walking model failed."); + std::cout << i; + break; + } + case 4: { + uint32_t i = {}; + oxAssert(rdr->field(fieldName, &i), "Walking model failed."); + std::cout << i; + break; + } + case 8: { + uint64_t i = {}; + oxAssert(rdr->field(fieldName, &i), "Walking model failed."); + std::cout << i; + break; + } + } + std::cout << '\n'; + break; + case ox::PrimitiveType::SignedInteger: + std::cout << fieldName << ":\tint" << f.type->length * 8 << "_t:\t"; + switch (f.type->length) { + case 1: { + int8_t i = {}; + oxAssert(rdr->field(fieldName, &i), "Walking model failed."); + std::cout << i; + break; + } + case 2: { + int16_t i = {}; + oxAssert(rdr->field(fieldName, &i), "Walking model failed."); + std::cout << i; + break; + } + case 4: { + int32_t i = {}; + oxAssert(rdr->field(fieldName, &i), "Walking model failed."); + std::cout << i; + break; + } + case 8: { + int64_t i = {}; + oxAssert(rdr->field(fieldName, &i), "Walking model failed."); + std::cout << i; + break; + } + } + std::cout << '\n'; + break; + case ox::PrimitiveType::Bool: { + bool i = {}; + oxAssert(rdr->field(fieldName, &i), "Walking model failed."); + std::cout << fieldName << ":\t" << "bool:\t" << (i ? "true" : "false") << '\n'; + break; + } + case ox::PrimitiveType::String: { + ox::Vector v(rdr->stringLength(fieldName) + 1); + //std::cout << rdr->stringLength() << '\n'; + oxAssert(rdr->field(fieldName, ox::SerStr(v.data(), v.size())), "Walking model failed."); + std::cout << fieldName << ":\t" << "string: " << v.data() << '\n'; + break; + } + case ox::PrimitiveType::Struct: + break; + } + return OxError(0); + } + ); + delete type.value; - // return err; - // } - //}, + return OxError(0); + } + }, } }; diff --git a/deps/ox/src/ox/oc/write.cpp b/deps/ox/src/ox/oc/write.cpp index d9520258..6aa62f4a 100644 --- a/deps/ox/src/ox/oc/write.cpp +++ b/deps/ox/src/ox/oc/write.cpp @@ -15,10 +15,6 @@ OrganicClawWriter::OrganicClawWriter(Json::Value json) { m_json = json; } -template -OrganicClawWriter::~OrganicClawWriter() { -} - template Error OrganicClawWriter::field(Key key, int8_t *val) { if (*val) { @@ -109,8 +105,7 @@ Error OrganicClawWriter::field(Key key, SerStr val) { } template -void OrganicClawWriter::setTypeInfo(const char*, int fields) { - m_fields = fields; +void OrganicClawWriter::setTypeInfo(const char*, int) { } template class OrganicClawWriter; diff --git a/deps/ox/src/ox/oc/write.hpp b/deps/ox/src/ox/oc/write.hpp index 8959f577..bda8b339 100644 --- a/deps/ox/src/ox/oc/write.hpp +++ b/deps/ox/src/ox/oc/write.hpp @@ -26,17 +26,12 @@ class OrganicClawWriter { protected: Json::Value m_json; - int m_fields = 0; - int m_field = 0; - uint8_t *m_buff = nullptr; public: OrganicClawWriter() = default; OrganicClawWriter(Json::Value json); - ~OrganicClawWriter(); - Error field(Key, int8_t *val); Error field(Key, int16_t *val); Error field(Key, int32_t *val); @@ -67,7 +62,7 @@ class OrganicClawWriter { void setTypeInfo(const char *name, int fields); - static constexpr OpType opType() { + static constexpr auto opType() { return OpType::Write; }