[ox] Overhaul serialization/model system and add ModelValue/ModelObject/ModelUnion variant system

This commit is contained in:
2022-06-21 21:43:49 -05:00
parent bc391b45fc
commit ca64f95be3
47 changed files with 2696 additions and 973 deletions

View File

@@ -3,10 +3,11 @@
*
* 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/.
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#include <ox/std/bit.hpp>
#include <utility>
#include "read.hpp"
@@ -18,7 +19,7 @@ OrganicClawReader::OrganicClawReader(const uint8_t *buff, std::size_t buffSize)
Json::CharReaderBuilder parserBuilder;
auto parser = std::unique_ptr<Json::CharReader>(parserBuilder.newCharReader());
if (!parser->parse(json, json + jsonLen, &m_json, nullptr)) {
throw OxError(1, "Could not parse JSON");
throw OxException(1, "Could not parse JSON");
}
}
@@ -26,12 +27,12 @@ OrganicClawReader::OrganicClawReader(const char *json, std::size_t jsonLen) {
Json::CharReaderBuilder parserBuilder;
auto parser = std::unique_ptr<Json::CharReader>(parserBuilder.newCharReader());
if (!parser->parse(json, json + jsonLen, &m_json, nullptr)) {
throw OxError(1, "Could not parse JSON");
throw OxException(1, "Could not parse JSON");
}
}
OrganicClawReader::OrganicClawReader(const Json::Value &json, int unionIdx) noexcept:
m_json(json),
OrganicClawReader::OrganicClawReader(Json::Value json, int unionIdx) noexcept:
m_json(std::move(json)),
m_unionIdx(unionIdx) {
}
@@ -208,6 +209,87 @@ Error OrganicClawReader::field(const char *key, SerStr val) noexcept {
return err;
}
Error OrganicClawReader::fieldCString(const char *key, char *val, std::size_t buffLen) noexcept {
auto err = OxError(0);
const char *begin = nullptr, *end = nullptr;
const auto &jv = value(key);
if (targetValid()) {
if (jv.empty()) {
auto data = val;
if (data) {
data[0] = 0;
}
} else if (jv.isString()) {
jv.getString(&begin, &end);
const auto strSize = static_cast<std::size_t>(end - begin);
auto data = val;
if (strSize >= buffLen) {
err = OxError(2, "String size exceeds capacity of destination");
} else {
ox_memcpy(data, begin, static_cast<std::size_t>(strSize));
data[strSize] = 0;
}
} else {
err = OxError(1, "Type mismatch");
}
}
++m_fieldIt;
return err;
}
Error OrganicClawReader::fieldCString(const char *key, char **val) noexcept {
auto err = OxError(0);
const char *begin = nullptr, *end = nullptr;
const auto &jv = value(key);
auto &data = *val;
if (targetValid()) {
if (jv.empty()) {
if (data) {
data[0] = 0;
}
} else if (jv.isString()) {
jv.getString(&begin, &end);
const auto strSize = static_cast<std::size_t>(end - begin);
safeDelete(*val);
*val = new char[strSize + 1];
ox_memcpy(data, begin, static_cast<std::size_t>(strSize));
data[strSize] = 0;
} else {
err = OxError(1, "Type mismatch");
}
}
++m_fieldIt;
return err;
}
Error OrganicClawReader::fieldCString(const char *key, char **val, std::size_t buffLen) noexcept {
auto err = OxError(0);
const char *begin = nullptr, *end = nullptr;
const auto &jv = value(key);
if (targetValid()) {
if (jv.empty()) {
auto data = val;
if (data) {
data[0] = 0;
}
} else if (jv.isString()) {
jv.getString(&begin, &end);
const auto strSize = static_cast<std::size_t>(end - begin);
auto data = val;
if (strSize >= buffLen) {
safeDelete(*val);
*val = new char[strSize + 1];
}
ox_memcpy(data, begin, static_cast<std::size_t>(strSize));
data[strSize] = 0;
} else {
err = OxError(1, "Type mismatch");
}
}
++m_fieldIt;
return err;
}
Result<std::size_t> OrganicClawReader::arrayLength(const char *key, bool) noexcept {
const auto &jv = value(key);
if (jv.empty()) {
@@ -234,13 +316,25 @@ std::size_t OrganicClawReader::stringLength(const char *key) noexcept {
}
OrganicClawReader OrganicClawReader::child(const char *key, int unionIdx) noexcept {
return OrganicClawReader(m_json[key], unionIdx);
return OrganicClawReader(value(key), unionIdx);
}
bool OrganicClawReader::fieldPresent(const char *key) noexcept {
return !m_json[key].empty();
}
int OrganicClawReader::whichFieldPresent(const char *name, const ModelUnion &u) const noexcept {
const auto &obj = m_json[name];
if (!obj.isObject()) {
return -1;
}
const auto &keys = obj.getMemberNames();
if (keys.size() != 1) {
return -1;
}
return u.getKeyIdx(keys.front().c_str());
}
Json::Value &OrganicClawReader::value(const char *key) noexcept {
if (m_json.isArray()) {
return m_json[m_fieldIt];
@@ -249,7 +343,7 @@ Json::Value &OrganicClawReader::value(const char *key) noexcept {
}
}
bool OrganicClawReader::targetValid() noexcept {
bool OrganicClawReader::targetValid() const noexcept {
return static_cast<int>(m_fieldIt) == m_unionIdx || m_unionIdx == -1;
}

View File

@@ -3,7 +3,7 @@
*
* 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/.
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#pragma once
@@ -11,6 +11,7 @@
#include <json/json.h>
#include <ox/model/fieldcounter.hpp>
#include <ox/model/modelhandleradaptor.hpp>
#include <ox/model/optype.hpp>
#include <ox/model/typenamecatcher.hpp>
#include <ox/model/types.hpp>
@@ -37,7 +38,7 @@ class OrganicClawReader {
OrganicClawReader(const char *json, std::size_t buffSize);
explicit OrganicClawReader(const Json::Value &json, int unionIdx = -1) noexcept;
explicit OrganicClawReader(Json::Value json, int unionIdx = -1) noexcept;
Error field(const char *key, int8_t *val) noexcept;
Error field(const char *key, int16_t *val) noexcept;
@@ -61,8 +62,8 @@ class OrganicClawReader {
template<typename T>
Error field(const char *key, T *val) noexcept;
template<typename U>
Error field(const char *key, UnionView<U> val) noexcept;
template<typename U, bool force = false>
Error field(const char *key, UnionView<U, force> val) noexcept;
template<std::size_t L>
Error field(const char *key, BasicString<L> *val) noexcept;
@@ -72,6 +73,12 @@ class OrganicClawReader {
Error field(const char *key, SerStr val) noexcept;
Error fieldCString(const char *key, char *val, std::size_t buffLen) noexcept;
Error fieldCString(const char *key, char **val) noexcept;
Error fieldCString(const char *key, char **val, std::size_t buffLen) noexcept;
/**
* Reads an array length from the current location in the buffer.
* @param pass indicates that the parsing should iterate past the array length
@@ -109,16 +116,23 @@ class OrganicClawReader {
// compatibility stub
constexpr void nextField() noexcept {}
[[nodiscard]]
bool fieldPresent(const char *key) noexcept;
[[nodiscard]]
int whichFieldPresent(const char *name, const ModelUnion &u) const noexcept;
[[nodiscard]]
static constexpr auto opType() noexcept {
return OpType::Read;
}
private:
[[nodiscard]]
Json::Value &value(const char *key) noexcept;
bool targetValid() noexcept;
[[nodiscard]]
bool targetValid() const noexcept;
};
@@ -134,7 +148,8 @@ Error OrganicClawReader::field(const char *key, T *val) noexcept {
const auto &jv = value(key);
if (jv.empty() || jv.isObject()) {
auto reader = child(key);
return model(&reader, val);
ModelHandlerInterface handler(&reader);
return model(&handler, val);
} else {
err = OxError(1, "Type mismatch");
}
@@ -143,14 +158,15 @@ Error OrganicClawReader::field(const char *key, T *val) noexcept {
return err;
}
template<typename U>
Error OrganicClawReader::field(const char *key, UnionView<U> val) noexcept {
template<typename U, bool force>
Error OrganicClawReader::field(const char *key, UnionView<U, force> val) noexcept {
auto err = OxError(0);
if (targetValid()) {
const auto &jv = value(key);
if (jv.empty() || jv.isObject()) {
auto reader = child(key, val.idx());
err = model(&reader, val.get());
ModelHandlerInterface handler(&reader);
err = model(&handler, val.get());
} else {
err = OxError(1, "Type mismatch");
}
@@ -185,13 +201,17 @@ Error OrganicClawReader::field(const char *key, BString<L> *val) noexcept {
template<typename T>
Error OrganicClawReader::field(const char *key, T *val, std::size_t valLen) noexcept {
const auto &srcVal = value(key);
if (!srcVal.isNull() && !srcVal.isArray()) {
return OxError(1, "Type mismatch");
}
auto srcSize = srcVal.size();
if (srcSize > valLen) {
return OxError(1);
}
OrganicClawReader r(srcVal);
ModelHandlerInterface handler{&r};
for (decltype(srcSize) i = 0; i < srcSize; ++i) {
oxReturnError(r.field("", &val[i]));
oxReturnError(handler.field("", &val[i]));
}
return OxError(0);
}
@@ -199,28 +219,32 @@ Error OrganicClawReader::field(const char *key, T *val, std::size_t valLen) noex
template<typename T>
Error OrganicClawReader::field(const char *key, HashMap<String, T> *val) noexcept {
const auto &srcVal = value(key);
if (!srcVal.isObject()) {
return OxError(1, "Type mismatch");
}
auto keys = srcVal.getMemberNames();
auto srcSize = srcVal.size();
OrganicClawReader r(srcVal);
ModelHandlerInterface handler{&r};
for (decltype(srcSize) i = 0; i < srcSize; ++i) {
const auto k = keys[i].c_str();
oxReturnError(r.field(k, &val->operator[](k)));
oxReturnError(handler.field(k, &val->operator[](k)));
}
return OxError(0);
}
template<typename T>
Error readOC(const char *json, std::size_t jsonSize, T *val) noexcept {
Error readOC(const char *buff, std::size_t buffSize, auto *val) noexcept {
// OrganicClawReader constructor can throw, but readOC should return its errors.
try {
Json::Value doc;
Json::CharReaderBuilder parserBuilder;
auto parser = std::unique_ptr<Json::CharReader>(parserBuilder.newCharReader());
if (!parser->parse(json, json + jsonSize, &doc, nullptr)) {
auto parser = UniquePtr<Json::CharReader>(parserBuilder.newCharReader());
if (!parser->parse(buff, buff + buffSize, &doc, nullptr)) {
return OxError(1, "Could not parse JSON");
}
OrganicClawReader reader(json, jsonSize);
return model(&reader, val);
OrganicClawReader reader(buff, buffSize);
ModelHandlerInterface handler(&reader);
return model(&handler, val);
} catch (const Error &err) {
return err;
} catch (...) {

View File

@@ -10,4 +10,5 @@ target_link_libraries(
add_test("[ox/oc] OcTest Writer" OcTest OrganicClawWriter)
add_test("[ox/oc] OcTest Reader" OcTest OrganicClawReader)
add_test("[ox/oc] OcTest OrganicClawModelValue" OcTest OrganicClawModelValue)
add_test("[ox/oc] OcTest OrganicClawDef" OcTest OrganicClawDef)

View File

@@ -3,7 +3,7 @@
*
* 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/.
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#undef NDEBUG
@@ -19,7 +19,7 @@ union TestUnion {
static constexpr auto TypeVersion = 1;
bool Bool;
uint32_t Int = 5;
char String[32];
char *String;
};
struct TestStructNest {
@@ -43,8 +43,9 @@ struct TestStruct {
int32_t Int6 = 0;
int32_t Int7 = 0;
int32_t Int8 = 0;
int unionIdx = 1;
TestUnion Union;
ox::BString<32> String = "";
ox::String String = "";
uint32_t List[4] = {0, 0, 0, 0};
ox::HashMap<ox::String, int> Map;
TestStructNest EmptyStruct;
@@ -55,23 +56,24 @@ struct TestStruct {
TestStruct(TestStruct &&other) noexcept;
constexpr ~TestStruct() noexcept {
if (unionIdx == 2) {
ox::safeDelete(Union.String);
}
}
constexpr TestStruct &operator=(TestStruct&&) noexcept;
};
template<typename T>
constexpr ox::Error model(T *io, TestUnion *obj) noexcept {
constexpr ox::Error model(auto *io, ox::CommonPtrWith<TestUnion> auto *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->fieldCString("String", &obj->String));
return OxError(0);
}
template<typename T>
constexpr ox::Error model(T *io, TestStructNest *obj) noexcept {
constexpr ox::Error model(auto *io, ox::CommonPtrWith<TestStructNest> auto *obj) noexcept {
io->template setTypeInfo<TestStructNest>();
oxReturnError(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int));
@@ -79,8 +81,7 @@ constexpr ox::Error model(T *io, TestStructNest *obj) noexcept {
return OxError(0);
}
template<typename T>
constexpr ox::Error model(T *io, TestStruct *obj) noexcept {
constexpr ox::Error model(auto *io, ox::CommonPtrWith<TestStruct> auto *obj) noexcept {
io->template setTypeInfo<TestStruct>();
oxReturnError(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int));
@@ -92,7 +93,12 @@ constexpr ox::Error model(T *io, TestStruct *obj) noexcept {
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("unionIdx", &obj->unionIdx));
if (ox_strcmp(io->opType(), ox::OpType::Reflect) == 0) {
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, 0}));
} else {
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, obj->unionIdx}));
}
oxReturnError(io->field("String", &obj->String));
oxReturnError(io->field("List", obj->List, 4));
oxReturnError(io->field("Map", &obj->Map));
@@ -173,6 +179,57 @@ const std::map<std::string_view, ox::Error(*)()> tests = {
return OxError(0);
}
},
{
"OrganicClawModelValue",
[] {
ox::Buffer dataBuff;
TestStruct testIn;
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.unionIdx = 1;
testIn.Union.Int = 93;
oxAssert(ox::writeOC(&testIn).moveTo(&dataBuff), "Data generation failed");
ox::TypeStore typeStore;
auto type = ox::buildTypeDef(&typeStore, &testIn);
oxAssert(type.error, "Descriptor write failed");
ox::ModelObject testOut;
oxReturnError(testOut.setType(type.value));
oxAssert(ox::readOC(dataBuff.data(), dataBuff.size(), &testOut), "Data read failed");
oxAssert(testOut["Int"].get<int>() == testIn.Int, "testOut.Int failed");
oxAssert(testOut["Bool"].get<bool>() == testIn.Bool, "testOut.Bool failed");
oxAssert(testOut["String"].get<ox::String>() == testIn.String, "testOut.String failed");
auto &testOutStruct = testOut["Struct"].get<ox::ModelObject>();
auto &testOutUnion = testOut["Union"].get<ox::ModelUnion>();
auto &testOutList = testOut["List"].get<ox::ModelValueVector>();
auto testOutStructCopy = testOut["Struct"].get<ox::ModelObject>();
auto testOutUnionCopy = testOut["Union"].get<ox::ModelUnion>();
auto testOutListCopy = testOut["List"].get<ox::ModelValueVector>();
oxAssert(testOutStruct.typeName() == TestStructNest::TypeName, "ModelObject TypeName failed");
oxAssert(testOutStruct.typeVersion() == TestStructNest::TypeVersion, "ModelObject TypeVersion failed");
oxAssert(testOutStruct["Bool"].get<bool>() == testIn.Struct.Bool, "testOut.Struct.Bool failed");
oxAssert(testOutStruct["String"].get<ox::String>() == testIn.Struct.String.c_str(), "testOut.Struct.String failed");
oxAssert(testOut["unionIdx"].get<int>() == testIn.unionIdx, "testOut.unionIdx failed");
oxAssert(testOutUnion.unionIdx() == testIn.unionIdx, "testOut.Union idx wrong");
oxAssert(testOutUnion["Int"].get<uint32_t>() == testIn.Union.Int, "testOut.Union.Int failed");
oxAssert(testOutList[0].get<uint32_t>() == testIn.List[0], "testOut.List[0] failed");
oxAssert(testOutList[1].get<uint32_t>() == testIn.List[1], "testOut.Struct.List[1] failed");
oxAssert(testOutStructCopy["Bool"].get<bool>() == testIn.Struct.Bool, "testOut.Struct.Bool (copy) failed");
oxAssert(testOutStructCopy["String"].get<ox::String>() == testIn.Struct.String.c_str(), "testOut.Struct.String (copy) failed");
oxAssert(testOutListCopy[0].get<uint32_t>() == testIn.List[0], "testOut.Struct.List[0] (copy) failed");
oxAssert(testOutListCopy[1].get<uint32_t>() == testIn.List[1], "testOut.Struct.List[1] (copy) failed");
return OxError(0);
}
},
{
"OrganicClawDef",
[] {

View File

@@ -3,7 +3,7 @@
*
* 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/.
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#include "write.hpp"
@@ -18,87 +18,6 @@ OrganicClawWriter::OrganicClawWriter(Json::Value json, int unionIdx) noexcept:
m_unionIdx(unionIdx) {
}
Error OrganicClawWriter::field(const char *key, int8_t *val) noexcept {
if (*val) {
value(key) = *val;
}
++m_fieldIt;
return OxError(0);
}
Error OrganicClawWriter::field(const char *key, int16_t *val) noexcept {
if (*val) {
value(key) = *val;
}
++m_fieldIt;
return OxError(0);
}
Error OrganicClawWriter::field(const char *key, int32_t *val) noexcept {
if (*val) {
value(key) = *val;
}
++m_fieldIt;
return OxError(0);
}
Error OrganicClawWriter::field(const char *key, int64_t *val) noexcept {
if (*val) {
value(key) = *val;
}
++m_fieldIt;
return OxError(0);
}
Error OrganicClawWriter::field(const char *key, uint8_t *val) noexcept {
if (*val) {
value(key) = *val;
}
++m_fieldIt;
return OxError(0);
}
Error OrganicClawWriter::field(const char *key, uint16_t *val) noexcept {
if (targetValid() && *val) {
value(key) = *val;
}
++m_fieldIt;
return OxError(0);
}
Error OrganicClawWriter::field(const char *key, uint32_t *val) noexcept {
if (targetValid() && *val) {
value(key) = *val;
}
++m_fieldIt;
return OxError(0);
}
Error OrganicClawWriter::field(const char *key, uint64_t *val) noexcept {
if (targetValid() && *val) {
value(key) = *val;
}
++m_fieldIt;
return OxError(0);
}
Error OrganicClawWriter::field(const char *key, bool *val) noexcept {
if (targetValid() && *val) {
value(key) = *val;
}
++m_fieldIt;
return OxError(0);
}
Error OrganicClawWriter::field(const char *key, String *val) noexcept {
if (targetValid() && val->len()) {
value(key) = val->c_str();
}
++m_fieldIt;
return OxError(0);
}
Error OrganicClawWriter::field(const char *key, SerStr val) noexcept {
if (targetValid() && val.len()) {
value(key) = val.c_str();
@@ -107,6 +26,26 @@ Error OrganicClawWriter::field(const char *key, SerStr val) noexcept {
return OxError(0);
}
Error OrganicClawWriter::fieldCString(const char *key, const char **val, int len) noexcept {
if (targetValid() && len) {
value(key) = *val;
}
++m_fieldIt;
return OxError(0);
}
Error OrganicClawWriter::fieldCString(const char *key, char **val, int len) noexcept {
return fieldCString(key, const_cast<const char**>(val), len);
}
Error OrganicClawWriter::fieldCString(const char *key, const char **val) noexcept {
return fieldCString(key, const_cast<const char**>(val), {});
}
Error OrganicClawWriter::fieldCString(const char *key, char **val) noexcept {
return fieldCString(key, const_cast<const char**>(val), {});
}
Json::Value &OrganicClawWriter::value(const char *key) noexcept {
if (m_json.isArray()) {
return m_json[m_fieldIt];

View File

@@ -3,7 +3,7 @@
*
* 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/.
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#pragma once
@@ -11,6 +11,7 @@
#include <json/json.h>
#include <ox/model/fieldcounter.hpp>
#include <ox/model/modelhandleradaptor.hpp>
#include <ox/model/optype.hpp>
#include <ox/model/types.hpp>
#include <ox/model/typenamecatcher.hpp>
@@ -22,8 +23,7 @@ namespace ox {
class OrganicClawWriter {
template<typename T>
friend Result<Buffer> writeOC(T *val) noexcept;
friend Result<Buffer> writeOC(auto *val) noexcept;
protected:
Json::Value m_json;
@@ -35,36 +35,140 @@ class OrganicClawWriter {
explicit OrganicClawWriter(Json::Value json, int unionIdx = -1) noexcept;
Error field(const char*, int8_t *val) noexcept;
Error field(const char*, int16_t *val) noexcept;
Error field(const char*, int32_t *val) noexcept;
Error field(const char*, int64_t *val) noexcept;
Error field(const char *key, CommonPtrWith<int8_t> auto *val) noexcept {
if (*val) {
value(key) = *val;
}
++m_fieldIt;
return OxError(0);
}
Error field(const char*, uint8_t *val) noexcept;
Error field(const char*, uint16_t *val) noexcept;
Error field(const char*, uint32_t *val) noexcept;
Error field(const char*, uint64_t *val) noexcept;
Error field(const char *key, CommonPtrWith<int16_t> auto *val) noexcept {
if (*val) {
value(key) = *val;
}
++m_fieldIt;
return OxError(0);
}
Error field(const char*, bool *val) noexcept;
Error field(const char *key, CommonPtrWith<int32_t> auto *val) noexcept {
if (*val) {
value(key) = *val;
}
++m_fieldIt;
return OxError(0);
}
Error field(const char *key, CommonPtrWith<int64_t> auto *val) noexcept {
if (*val) {
value(key) = *val;
}
++m_fieldIt;
return OxError(0);
}
Error field(const char *key, CommonPtrWith<uint8_t> auto *val) noexcept {
if (*val) {
value(key) = *val;
}
++m_fieldIt;
return OxError(0);
}
Error field(const char *key, CommonPtrWith<uint16_t> auto *val) noexcept {
if (targetValid() && *val) {
value(key) = *val;
}
++m_fieldIt;
return OxError(0);
}
Error field(const char *key, CommonPtrWith<uint32_t> auto *val) noexcept {
if (targetValid() && *val) {
value(key) = *val;
}
++m_fieldIt;
return OxError(0);
}
Error field(const char *key, CommonPtrWith<uint64_t> auto *val) noexcept {
if (targetValid() && *val) {
value(key) = *val;
}
++m_fieldIt;
return OxError(0);
}
Error field(const char *key, CommonPtrWith<bool> auto *val) noexcept {
if (targetValid() && *val) {
value(key) = *val;
}
++m_fieldIt;
return OxError(0);
}
template<typename T>
Error field(const char*, T *val, std::size_t len) noexcept;
template<typename U>
Error field(const char*, UnionView<U> val) noexcept;
template<typename U, bool force = true>
Error field(const char*, UnionView<U, force> val) noexcept;
template<typename T>
Error field(const char*, HashMap<String, T> *val) noexcept;
Error field(const char *key, const HashMap<String, T> *val) noexcept {
if (targetValid()) {
const auto &keys = val->keys();
OrganicClawWriter w;
ModelHandlerInterface handler{&w};
for (std::size_t i = 0; i < keys.size(); ++i) {
const auto k = keys[i].c_str();
oxReturnError(handler.field(k, val->at(k).value));
}
value(key) = w.m_json;
}
++m_fieldIt;
return OxError(0);
}
template<typename T>
Error field(const char *key, HashMap<String, T> *val) noexcept {
return field(key, const_cast<const HashMap<String, T>*>(val));
}
template<std::size_t L>
Error field(const char*, BString<L> *val) noexcept;
Error field(const char *key, const BString<L> *val) noexcept {
return field(key, SerStr(val->data(), val->cap()));
}
Error field(const char*, String *val) noexcept;
template<std::size_t L>
Error field(const char *key, BString<L> *val) noexcept {
return field(key, SerStr(val->data(), val->cap()));
}
template<std::size_t L>
Error field(const char *key, const BasicString<L> *val) noexcept {
if (targetValid() && val->len()) {
value(key) = val->c_str();
}
++m_fieldIt;
return OxError(0);
}
template<std::size_t L>
Error field(const char *key, BasicString<L> *val) noexcept {
return field(key, const_cast<const BasicString<L>*>(val));
}
Error field(const char*, SerStr val) noexcept;
Error fieldCString(const char*, const char **val, int len) noexcept;
Error fieldCString(const char *name, char **val, int len) noexcept;
Error fieldCString(const char *name, const char **val) noexcept;
Error fieldCString(const char *name, char **val) noexcept;
template<typename T>
Error field(const char*, T *val) noexcept;
@@ -91,8 +195,9 @@ template<typename T>
Error OrganicClawWriter::field(const char *key, T *val, std::size_t len) noexcept {
if (targetValid() && len) {
OrganicClawWriter w((Json::Value(Json::arrayValue)));
ModelHandlerInterface handler{&w};
for (std::size_t i = 0; i < len; ++i) {
oxReturnError(w.field("", &val[i]));
oxReturnError(handler.field("", &val[i]));
}
value(key) = w.m_json;
}
@@ -100,18 +205,14 @@ Error OrganicClawWriter::field(const char *key, T *val, std::size_t len) noexcep
return OxError(0);
}
template<std::size_t L>
Error OrganicClawWriter::field(const char *key, BString<L> *val) noexcept {
return field(key, SerStr(val->data(), val->cap()));
}
template<typename T>
Error OrganicClawWriter::field(const char *key, T *val) noexcept {
if constexpr(isVector_v<T>) {
return field(key, val->data(), val->size());
} else if (val && targetValid()) {
OrganicClawWriter w;
oxReturnError(model(&w, val));
ModelHandlerInterface handler{&w};
oxReturnError(model(&handler, val));
if (!w.m_json.isNull()) {
value(key) = w.m_json;
}
@@ -120,11 +221,12 @@ Error OrganicClawWriter::field(const char *key, T *val) noexcept {
return OxError(0);
}
template<typename U>
Error OrganicClawWriter::field(const char *key, UnionView<U> val) noexcept {
template<typename U, bool force>
Error OrganicClawWriter::field(const char *key, UnionView<U, force> val) noexcept {
if (targetValid()) {
OrganicClawWriter w(val.idx());
oxReturnError(model(&w, val.get()));
ModelHandlerInterface handler{&w};
oxReturnError(model(&handler, val.get()));
if (!w.m_json.isNull()) {
value(key) = w.m_json;
}
@@ -133,25 +235,10 @@ Error OrganicClawWriter::field(const char *key, UnionView<U> val) noexcept {
return OxError(0);
}
template<typename T>
Error OrganicClawWriter::field(const char *key, HashMap<String, T> *val) noexcept {
if (targetValid()) {
const auto &keys = val->keys();
OrganicClawWriter w;
for (std::size_t i = 0; i < keys.size(); ++i) {
const auto k = keys[i].c_str();
oxReturnError(w.field(k, &val->operator[](k)));
}
value(key) = w.m_json;
}
++m_fieldIt;
return OxError(0);
}
template<typename T>
Result<Buffer> writeOC(T *val) noexcept {
Result<Buffer> writeOC(auto *val) noexcept {
OrganicClawWriter writer;
oxReturnError(model(&writer, val));
ModelHandlerInterface handler(&writer);
oxReturnError(model(&handler, val));
Json::StreamWriterBuilder jsonBuilder;
const auto str = Json::writeString(jsonBuilder, writer.m_json);
Buffer buff(str.size() + 1);