From d0f5819072c031606ee59a02ae452b52f9f23c9e Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Mon, 13 Apr 2020 23:36:27 -0500 Subject: [PATCH] [ox/oc] Add union support --- deps/ox/src/ox/oc/read.cpp | 289 ++++++++++++++++--------------- deps/ox/src/ox/oc/read.hpp | 99 ++++++----- deps/ox/src/ox/oc/test/tests.cpp | 34 +++- deps/ox/src/ox/oc/write.cpp | 98 ++++++----- deps/ox/src/ox/oc/write.hpp | 106 +++++++----- 5 files changed, 351 insertions(+), 275 deletions(-) diff --git a/deps/ox/src/ox/oc/read.cpp b/deps/ox/src/ox/oc/read.cpp index 77dbf132..4875207b 100644 --- a/deps/ox/src/ox/oc/read.cpp +++ b/deps/ox/src/ox/oc/read.cpp @@ -12,8 +12,7 @@ namespace ox { -template -OrganicClawReader::OrganicClawReader(const uint8_t *buff, std::size_t buffSize) { +OrganicClawReader::OrganicClawReader(const uint8_t *buff, std::size_t buffSize) { auto json = bit_cast(buff); auto jsonLen = ox_strnlen(json, buffSize); Json::CharReaderBuilder parserBuilder; @@ -23,8 +22,7 @@ OrganicClawReader::OrganicClawReader(const uint8_t *buff, std::size_t buffS } } -template -OrganicClawReader::OrganicClawReader(const char *json, std::size_t jsonLen) { +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)) { @@ -32,163 +30,182 @@ OrganicClawReader::OrganicClawReader(const char *json, std::size_t jsonLen) } } -template -OrganicClawReader::OrganicClawReader(const Json::Value &json) { - m_json = json; +OrganicClawReader::OrganicClawReader(const Json::Value &json, int unionIdx): + m_json(json), + m_unionIdx(unionIdx) { } -template -Error OrganicClawReader::field(Key key, int8_t *val) { - const auto &jv = value(key); +Error OrganicClawReader::field(const char *key, int8_t *val) { + auto err = OxError(0); + if (targetValid()) { + const auto &jv = value(key); + if (jv.empty()) { + *val = 0; + } else if (jv.isInt()) { + *val = static_cast(jv.asInt()); + } else { + err = OxError(1, "Type mismatch"); + } + } ++m_fieldIt; - if (jv.empty()) { - return OxError(0); - } - if (jv.isInt()) { - *val = static_cast(jv.asInt()); - return OxError(0); - } - return OxError(1, "Type mismatch"); + return err; } -template -Error OrganicClawReader::field(Key key, int16_t *val) { - const auto &jv = value(key); +Error OrganicClawReader::field(const char *key, int16_t *val) { + auto err = OxError(0); + if (targetValid()) { + const auto &jv = value(key); + if (jv.empty()) { + *val = 0; + } else if (jv.isInt()) { + *val = static_cast(jv.asInt()); + } else { + err = OxError(1, "Type mismatch"); + } + } ++m_fieldIt; - if (jv.empty()) { - return OxError(0); - } - if (jv.isInt()) { - *val = static_cast(jv.asInt()); - return OxError(0); - } - return OxError(1, "Type mismatch"); + return err; } -template -Error OrganicClawReader::field(Key key, int32_t *val) { - const auto &jv = value(key); +Error OrganicClawReader::field(const char *key, int32_t *val) { + auto err = OxError(0); + if (targetValid()) { + const auto &jv = value(key); + if (jv.empty()) { + *val = 0; + } else if (jv.isInt()) { + *val = static_cast(jv.asInt()); + } else { + err = OxError(1, "Type mismatch"); + } + } ++m_fieldIt; - if (jv.empty()) { - return OxError(0); - } - if (jv.isInt()) { - *val = static_cast(jv.asInt()); - return OxError(0); - } - return OxError(1, "Type mismatch"); + return err; } -template -Error OrganicClawReader::field(Key key, int64_t *val) { - const auto &jv = value(key); +Error OrganicClawReader::field(const char *key, int64_t *val) { + auto err = OxError(0); + if (targetValid()) { + const auto &jv = value(key); + if (jv.empty()) { + *val = 0; + } else if (jv.isInt() || jv.isInt64()) { + *val = static_cast(jv.asInt64()); + } else { + err = OxError(1, "Type mismatch"); + } + } ++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"); + return err; } -template -Error OrganicClawReader::field(Key key, uint8_t *val) { - const auto &jv = value(key); +Error OrganicClawReader::field(const char *key, uint8_t *val) { + auto err = OxError(0); + if (targetValid()) { + const auto &jv = value(key); + if (jv.empty()) { + *val = 0; + } else if (jv.isUInt()) { + *val = static_cast(jv.asUInt()); + } else { + err = OxError(1, "Type mismatch"); + } + } ++m_fieldIt; - if (jv.empty()) { - return OxError(0); - } - if (jv.isUInt()) { - *val = static_cast(jv.asUInt()); - return OxError(0); - } - return OxError(1, "Type mismatch"); + return err; } -template -Error OrganicClawReader::field(Key key, uint16_t *val) { - const auto &jv = value(key); +Error OrganicClawReader::field(const char *key, uint16_t *val) { + auto err = OxError(0); + if (targetValid()) { + const auto &jv = value(key); + if (jv.empty()) { + *val = 0; + } else if (jv.isUInt()) { + *val = static_cast(jv.asUInt()); + } else { + err = OxError(1, "Type mismatch"); + } + } ++m_fieldIt; - if (jv.empty()) { - return OxError(0); - } - if (jv.isUInt()) { - *val = static_cast(jv.asUInt()); - return OxError(0); - } - return OxError(1, "Type mismatch"); + return err; } -template -Error OrganicClawReader::field(Key key, uint32_t *val) { - const auto &jv = value(key); +Error OrganicClawReader::field(const char *key, uint32_t *val) { + auto err = OxError(0); + if (targetValid()) { + const auto &jv = value(key); + if (jv.empty()) { + *val = 0; + } else if (jv.isUInt()) { + *val = static_cast(jv.asUInt()); + } else { + err = OxError(1, "Type mismatch"); + } + } ++m_fieldIt; - if (jv.empty()) { - return OxError(0); - } - if (jv.isUInt()) { - *val = static_cast(jv.asUInt()); - return OxError(0); - } - return OxError(1, "Type mismatch"); + return err; } -template -Error OrganicClawReader::field(Key key, uint64_t *val) { - const auto &jv = value(key); +Error OrganicClawReader::field(const char *key, uint64_t *val) { + auto err = OxError(0); + if (targetValid()) { + const auto &jv = value(key); + if (jv.empty()) { + *val = 0; + } else if (jv.isUInt() || jv.isUInt64()) { + *val = static_cast(jv.asUInt64()); + } else { + err = OxError(1, "Type mismatch"); + } + } ++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"); + return err; } -template -Error OrganicClawReader::field(Key key, bool *val) { - const auto &jv = value(key); +Error OrganicClawReader::field(const char *key, bool *val) { + auto err = OxError(0); + if (targetValid()) { + const auto &jv = value(key); + if (jv.empty()) { + *val = false; + } else if (jv.isBool()) { + *val = jv.asBool(); + } else { + err = OxError(1, "Type mismatch"); + } + } ++m_fieldIt; - if (jv.empty()) { - return OxError(0); - } - if (jv.isBool()) { - *val = jv.asBool(); - return OxError(0); - } - return OxError(1, "Type mismatch"); + return err; } -template -Error OrganicClawReader::field(Key key, SerStr val) { +Error OrganicClawReader::field(const char *key, SerStr val) { + auto err = OxError(0); const char *begin = nullptr, *end = nullptr; const auto &jv = value(key); - ++m_fieldIt; - if (jv.empty()) { - 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"); + if (targetValid()) { + if (jv.empty()) { + val.data()[0] = 0; + } else if (jv.isString()) { + jv.getString(&begin, &end); + auto strSize = end - begin; + if (strSize >= val.cap()) { + err = OxError(1, "String size exceeds capacity of destination"); + } else { + ox_memcpy(val.data(), begin, static_cast(strSize)); + val.data()[strSize] = 0; + } + } else { + err = OxError(1, "Type mismatch"); } - ox_memcpy(val.data(), begin, static_cast(strSize)); - val.data()[strSize] = 0; - return OxError(0); } - return OxError(1, "Type mismatch"); + ++m_fieldIt; + return err; } -template -[[nodiscard]] ValErr OrganicClawReader::arrayLength(Key key, bool) { +[[nodiscard]] ValErr OrganicClawReader::arrayLength(const char *key, bool) { const auto &jv = value(key); - ++m_fieldIt; if (jv.empty()) { return 0; } @@ -198,11 +215,9 @@ template return OxError(1, "Type mismatch"); } -template -[[nodiscard]] std::size_t OrganicClawReader::stringLength(Key key) { +[[nodiscard]] std::size_t OrganicClawReader::stringLength(const char *key) { const char *begin = nullptr, *end = nullptr; const auto &jv = value(key); - ++m_fieldIt; if (jv.empty()) { return 0; } @@ -213,22 +228,15 @@ template return OxError(1, "Type mismatch"); } -template -void OrganicClawReader::setTypeInfo(const char*, int) { +OrganicClawReader OrganicClawReader::child(const char *key, int unionIdx) { + return OrganicClawReader(m_json[key], unionIdx); } -template -OrganicClawReader OrganicClawReader::child(Key key) { - return OrganicClawReader(m_json[key]); -} - -template -bool OrganicClawReader::fieldPresent(Key key) { +bool OrganicClawReader::fieldPresent(const char *key) { return !m_json[key].empty(); } -template -Json::Value &OrganicClawReader::value(Key key) { +Json::Value &OrganicClawReader::value(const char *key) { if (m_json.isArray()) { return m_json[m_fieldIt]; } else { @@ -236,7 +244,8 @@ Json::Value &OrganicClawReader::value(Key key) { } } -template class OrganicClawReader; -template class OrganicClawReader; +bool OrganicClawReader::targetValid() noexcept { + return static_cast(m_fieldIt) == m_unionIdx || m_unionIdx == -1; +} } diff --git a/deps/ox/src/ox/oc/read.hpp b/deps/ox/src/ox/oc/read.hpp index 803dab0f..3415a2eb 100644 --- a/deps/ox/src/ox/oc/read.hpp +++ b/deps/ox/src/ox/oc/read.hpp @@ -18,12 +18,12 @@ namespace ox { -template class OrganicClawReader { private: Json::Value m_json; Json::ArrayIndex m_fieldIt = 0; + int m_unionIdx = -1; public: OrganicClawReader() = default; @@ -32,57 +32,62 @@ class OrganicClawReader { OrganicClawReader(const char *json, std::size_t buffSize); - OrganicClawReader(const Json::Value &json); + OrganicClawReader(const Json::Value &json, int unionIdx = -1); - [[nodiscard]] Error field(Key key, int8_t *val); - [[nodiscard]] Error field(Key key, int16_t *val); - [[nodiscard]] Error field(Key key, int32_t *val); - [[nodiscard]] Error field(Key key, int64_t *val); + [[nodiscard]] Error field(const char *key, int8_t *val); + [[nodiscard]] Error field(const char *key, int16_t *val); + [[nodiscard]] Error field(const char *key, int32_t *val); + [[nodiscard]] Error field(const char *key, int64_t *val); - [[nodiscard]] Error field(Key key, uint8_t *val); - [[nodiscard]] Error field(Key key, uint16_t *val); - [[nodiscard]] Error field(Key key, uint32_t *val); - [[nodiscard]] Error field(Key key, uint64_t *val); + [[nodiscard]] Error field(const char *key, uint8_t *val); + [[nodiscard]] Error field(const char *key, uint16_t *val); + [[nodiscard]] Error field(const char *key, uint32_t *val); + [[nodiscard]] Error field(const char *key, uint64_t *val); - [[nodiscard]] Error field(Key key, bool *val); + [[nodiscard]] Error field(const char *key, bool *val); // array handler template - [[nodiscard]] Error field(Key key, T *val, std::size_t len); + [[nodiscard]] Error field(const char *key, T *val, std::size_t len); template - [[nodiscard]] Error field(Key key, ox::Vector *val); + [[nodiscard]] Error field(const char *key, ox::Vector *val); template - [[nodiscard]] Error field(Key key, T *val); + [[nodiscard]] Error field(const char *key, T *val); + + template + [[nodiscard]] Error field(const char *key, UnionView val); template - [[nodiscard]] Error field(Key key, ox::BString *val); + [[nodiscard]] Error field(const char *key, ox::BString *val); - [[nodiscard]] Error field(Key key, SerStr val); + [[nodiscard]] Error field(const char *key, SerStr val); /** * 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(Key key, bool pass = true); + [[nodiscard]] ValErr arrayLength(const char *key, bool pass = true); /** * Reads an string length from the current location in the buffer. */ - [[nodiscard]] std::size_t stringLength(Key name); + [[nodiscard]] std::size_t stringLength(const char *name); - void setTypeInfo(const char *name, int fields); + template + constexpr void setTypeInfo(const char* = T::TypeName, int = T::Fields) { + } /** * Returns a OrganicClawReader to parse a child object. */ - [[nodiscard]] OrganicClawReader child(Key key); + [[nodiscard]] OrganicClawReader child(const char *key, int unionIdx = -1); // compatibility stub constexpr void nextField() noexcept {} - bool fieldPresent(Key key); + bool fieldPresent(const char *key); static constexpr auto opType() { return OpType::Read; @@ -90,52 +95,66 @@ class OrganicClawReader { private: - Json::Value &value(Key key); + Json::Value &value(const char *key); + + bool targetValid() noexcept; }; -template template -Error OrganicClawReader::field(Key key, T *val) { - if (val) { +Error OrganicClawReader::field(const char *key, T *val) { + auto err = OxError(0); + if (targetValid()) { const auto &jv = value(key); - ++m_fieldIt; - if (jv.empty()) { - return OxError(0); - } - if (jv.isObject()) { + if (jv.empty() || jv.isObject()) { auto reader = child(key); return model(&reader, val); + } else { + err = OxError(1, "Type mismatch"); } } - return OxError(0); + ++m_fieldIt; + return err; +} + +template +Error OrganicClawReader::field(const char *key, UnionView val) { + auto err = OxError(0); + if (targetValid()) { + const auto &jv = value(key); + if (jv.empty() || jv.isObject()) { + auto reader = child(key, val.idx()); + return model(&reader, val.get()); + } else { + err = OxError(1, "Type mismatch"); + } + } + ++m_fieldIt; + return err; } -template template -Error OrganicClawReader::field(Key name, ox::BString *val) { +Error OrganicClawReader::field(const char *name, ox::BString *val) { return field(name, SerStr(val->data(), val->cap())); } // array handler -template template -Error OrganicClawReader::field(Key key, T *val, std::size_t valLen) { - const auto &srcVal = m_json[key]; +Error OrganicClawReader::field(const char *key, T *val, std::size_t valLen) { + const auto &srcVal = value(key); auto srcSize = srcVal.size(); if (srcSize > valLen) { return OxError(1); } - OrganicClawReader r(srcVal); + OrganicClawReader r(srcVal); for (decltype(srcSize) i = 0; i < srcSize; ++i) { oxReturnError(r.field("", &val[i])); } return OxError(0); } -template template -Error OrganicClawReader::field(Key key, ox::Vector *val) { +Error OrganicClawReader::field(const char *key, ox::Vector *val) { return field(nullptr, val->data(), val->size()); } @@ -149,7 +168,7 @@ Error readOC(const char *json, std::size_t jsonSize, T *val) noexcept { if (!parser->parse(json, json + jsonSize, &doc, nullptr)) { return OxError(1, "Could not parse JSON"); } - OrganicClawReader reader(json, jsonSize); + OrganicClawReader reader(json, jsonSize); return model(&reader, val); } catch (Error err) { return err; diff --git a/deps/ox/src/ox/oc/test/tests.cpp b/deps/ox/src/ox/oc/test/tests.cpp index bb58483f..e17e35e6 100644 --- a/deps/ox/src/ox/oc/test/tests.cpp +++ b/deps/ox/src/ox/oc/test/tests.cpp @@ -16,6 +16,14 @@ #include #include +union TestUnion { + static constexpr auto TypeName = "TestUnion"; + static constexpr auto Fields = 3; + bool Bool; + uint32_t Int = 5; + char String[32]; +}; + struct TestStructNest { bool Bool = false; uint32_t Int = 0; @@ -33,20 +41,29 @@ struct TestStruct { int32_t Int6 = 0; int32_t Int7 = 0; int32_t Int8 = 0; + TestUnion Union; ox::BString<32> String = ""; uint32_t List[4] = {0, 0, 0 , 0}; TestStructNest EmptyStruct; TestStructNest Struct; }; +template +ox::Error model(T *io, TestUnion *obj) { + io->template setTypeInfo(); + oxReturnError(io->field("Bool", &obj->Bool)); + oxReturnError(io->field("Int", &obj->Int)); + oxReturnError(io->field("String", ox::SerStr(obj->String))); + return OxError(0); +} + template ox::Error model(T *io, TestStructNest *obj) { - auto err = OxError(0); io->setTypeInfo("TestStructNest", 3); - err |= io->field("Bool", &obj->Bool); - err |= io->field("Int", &obj->Int); - err |= io->field("String", &obj->String); - return err; + oxReturnError(io->field("Bool", &obj->Bool)); + oxReturnError(io->field("Int", &obj->Int)); + oxReturnError(io->field("String", &obj->String)); + return OxError(0); } template @@ -62,6 +79,7 @@ ox::Error model(T *io, TestStruct *obj) { oxReturnError(io->field("Int6", &obj->Int6)); oxReturnError(io->field("Int7", &obj->Int7)); oxReturnError(io->field("Int8", &obj->Int8)); + oxReturnError(io->field("Union", ox::UnionView{&obj->Union, 1})); oxReturnError(io->field("String", &obj->String)); oxReturnError(io->field("List", obj->List, 4)); oxReturnError(io->field("EmptyStruct", &obj->EmptyStruct)); @@ -86,6 +104,7 @@ std::map tests = { TestStruct testIn; testIn.Bool = true; testIn.Int = 42; + testIn.Union.Int = 52; testIn.String = "Test String 1"; testIn.List[0] = 1; testIn.List[1] = 2; @@ -111,6 +130,7 @@ std::map tests = { 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"); @@ -146,8 +166,8 @@ std::map tests = { 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 { + 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) { diff --git a/deps/ox/src/ox/oc/write.cpp b/deps/ox/src/ox/oc/write.cpp index 6aa62f4a..febde95c 100644 --- a/deps/ox/src/ox/oc/write.cpp +++ b/deps/ox/src/ox/oc/write.cpp @@ -10,105 +10,109 @@ namespace ox { -template -OrganicClawWriter::OrganicClawWriter(Json::Value json) { - m_json = json; +OrganicClawWriter::OrganicClawWriter(int unionIdx): m_unionIdx(unionIdx) { } -template -Error OrganicClawWriter::field(Key key, int8_t *val) { +OrganicClawWriter::OrganicClawWriter(Json::Value json, int unionIdx): + m_json(json), + m_unionIdx(unionIdx) { +} + +Error OrganicClawWriter::field(const char *key, int8_t *val) { if (*val) { - m_json[key] = *val; + value(key) = *val; } + ++m_fieldIt; return OxError(0); } -template -Error OrganicClawWriter::field(Key key, int16_t *val) { +Error OrganicClawWriter::field(const char *key, int16_t *val) { if (*val) { - m_json[key] = *val; + value(key) = *val; } + ++m_fieldIt; return OxError(0); } -template -Error OrganicClawWriter::field(Key key, int32_t *val) { +Error OrganicClawWriter::field(const char *key, int32_t *val) { if (*val) { - m_json[key] = *val; + value(key) = *val; } + ++m_fieldIt; return OxError(0); } -template -Error OrganicClawWriter::field(Key key, int64_t *val) { +Error OrganicClawWriter::field(const char *key, int64_t *val) { if (*val) { - m_json[key] = *val; + value(key) = *val; } + ++m_fieldIt; return OxError(0); } -template -Error OrganicClawWriter::field(Key key, uint8_t *val) { +Error OrganicClawWriter::field(const char *key, uint8_t *val) { if (*val) { - m_json[key] = *val; + value(key) = *val; } + ++m_fieldIt; return OxError(0); } -template -Error OrganicClawWriter::field(Key key, uint16_t *val) { - if (*val) { - m_json[key] = *val; +Error OrganicClawWriter::field(const char *key, uint16_t *val) { + if (targetValid() && *val) { + value(key) = *val; } + ++m_fieldIt; return OxError(0); } -template -Error OrganicClawWriter::field(Key key, uint32_t *val) { - if (*val) { - m_json[key] = *val; +Error OrganicClawWriter::field(const char *key, uint32_t *val) { + if (targetValid() && *val) { + value(key) = *val; } + ++m_fieldIt; return OxError(0); } -template -Error OrganicClawWriter::field(Key key, uint64_t *val) { - if (*val) { - m_json[key] = *val; +Error OrganicClawWriter::field(const char *key, uint64_t *val) { + if (targetValid() && *val) { + value(key) = *val; } + ++m_fieldIt; return OxError(0); } -template -Error OrganicClawWriter::field(Key key, bool *val) { - if (*val) { - m_json[key] = *val; +Error OrganicClawWriter::field(const char *key, bool *val) { + if (targetValid() && *val) { + value(key) = *val; } + ++m_fieldIt; return OxError(0); } -template -Error OrganicClawWriter::field(Key key, ox::String val) { - if (val.len()) { - m_json[key] = val.c_str(); +Error OrganicClawWriter::field(const char *key, ox::String val) { + if (targetValid() && val.len()) { + value(key) = val.c_str(); } + ++m_fieldIt; return OxError(0); } -template -Error OrganicClawWriter::field(Key key, SerStr val) { - if (val.len()) { - m_json[key] = val.c_str(); +Error OrganicClawWriter::field(const char *key, SerStr val) { + if (targetValid() && val.len()) { + value(key) = val.c_str(); } + ++m_fieldIt; return OxError(0); } -template -void OrganicClawWriter::setTypeInfo(const char*, int) { +Json::Value &OrganicClawWriter::value(const char *key) { + if (m_json.isArray()) { + return m_json[m_fieldIt]; + } else { + return m_json[key]; + } } -template class OrganicClawWriter; -template class OrganicClawWriter; - } diff --git a/deps/ox/src/ox/oc/write.hpp b/deps/ox/src/ox/oc/write.hpp index bda8b339..fa1cef29 100644 --- a/deps/ox/src/ox/oc/write.hpp +++ b/deps/ox/src/ox/oc/write.hpp @@ -17,101 +17,125 @@ namespace ox { -template class OrganicClawWriter { - friend OrganicClawWriter; - friend OrganicClawWriter; + template friend ValErr writeOC(T *val); protected: Json::Value m_json; + Json::ArrayIndex m_fieldIt = 0; + int m_unionIdx = -1; public: - OrganicClawWriter() = default; + OrganicClawWriter(int unionIdx = -1); - OrganicClawWriter(Json::Value json); + OrganicClawWriter(Json::Value json, int unionIdx = -1); - Error field(Key, int8_t *val); - Error field(Key, int16_t *val); - Error field(Key, int32_t *val); - Error field(Key, int64_t *val); + [[nodiscard]] Error field(const char*, int8_t *val); + [[nodiscard]] Error field(const char*, int16_t *val); + [[nodiscard]] Error field(const char*, int32_t *val); + [[nodiscard]] Error field(const char*, int64_t *val); - Error field(Key, uint8_t *val); - Error field(Key, uint16_t *val); - Error field(Key, uint32_t *val); - Error field(Key, uint64_t *val); + [[nodiscard]] Error field(const char*, uint8_t *val); + [[nodiscard]] Error field(const char*, uint16_t *val); + [[nodiscard]] Error field(const char*, uint32_t *val); + [[nodiscard]] Error field(const char*, uint64_t *val); - Error field(Key, bool *val); + [[nodiscard]] Error field(const char*, bool *val); template - Error field(Key, T *val, std::size_t len); + [[nodiscard]] Error field(const char*, T *val, std::size_t len); + + template + [[nodiscard]] Error field(const char*, UnionView val); template - Error field(Key, ox::Vector *val); + [[nodiscard]] Error field(const char*, ox::Vector *val); template - Error field(Key, ox::BString *val); + [[nodiscard]] Error field(const char*, ox::BString *val); - Error field(Key, ox::String val); + [[nodiscard]] Error field(const char*, ox::String val); - Error field(Key, SerStr val); + [[nodiscard]] Error field(const char*, SerStr val); template - Error field(Key, T *val); + [[nodiscard]] Error field(const char*, T *val); - void setTypeInfo(const char *name, int fields); + template + constexpr void setTypeInfo(const char* = T::TypeName, int = T::Fields) { + } static constexpr auto opType() { return OpType::Write; } + private: + constexpr bool targetValid() noexcept { + return static_cast(m_fieldIt) == m_unionIdx || m_unionIdx == -1; + } + + Json::Value &value(const char *key); + }; -template template -Error OrganicClawWriter::field(Key key, T *val, std::size_t len) { - OrganicClawWriter w; - for (std::size_t i = 0; i < len; ++i) { - oxReturnError(w.field(i, &val[i])); +Error OrganicClawWriter::field(const char *key, T *val, std::size_t len) { + if (targetValid()) { + OrganicClawWriter w(Json::Value(Json::arrayValue)); + for (std::size_t i = 0; i < len; ++i) { + oxReturnError(w.field("", &val[i])); + } + value(key) = w.m_json; } - m_json[key] = w.m_json; + ++m_fieldIt; return OxError(0); } -template template -Error OrganicClawWriter::field(Key key, ox::BString *val) { +Error OrganicClawWriter::field(const char *key, ox::BString *val) { return field(key, SerStr(val->data(), val->cap())); } -template template -Error OrganicClawWriter::field(Key key, T *val) { - OrganicClawWriter w; - oxReturnError(model(&w, val)); - if (!w.m_json.isNull()) { - m_json[key] = w.m_json; +Error OrganicClawWriter::field(const char *key, T *val) { + if (targetValid()) { + OrganicClawWriter w; + oxReturnError(model(&w, val)); + if (!w.m_json.isNull()) { + value(key) = w.m_json; + } } + ++m_fieldIt; + return OxError(0); +} + +template +Error OrganicClawWriter::field(const char *key, UnionView val) { + if (targetValid()) { + OrganicClawWriter w(val.idx()); + oxReturnError(model(&w, val.get())); + if (!w.m_json.isNull()) { + value(key) = w.m_json; + } + } + ++m_fieldIt; return OxError(0); } -template template -Error OrganicClawWriter::field(Key key, ox::Vector *val) { +Error OrganicClawWriter::field(const char *key, ox::Vector *val) { return field(key, val->data(), val->size()); } template ValErr writeOC(T *val) { - OrganicClawWriter writer; + OrganicClawWriter writer; oxReturnError(model(&writer, val)); Json::StreamWriterBuilder jsonBuilder; return String(Json::writeString(jsonBuilder, writer.m_json).c_str()); } -extern template class OrganicClawWriter; -extern template class OrganicClawWriter; - }