[ox/oc] Add union support

This commit is contained in:
Gary Talent 2020-04-13 23:36:27 -05:00
parent d2e7528dae
commit d0f5819072
5 changed files with 351 additions and 275 deletions

View File

@ -12,8 +12,7 @@
namespace ox {
template<typename Key>
OrganicClawReader<Key>::OrganicClawReader(const uint8_t *buff, std::size_t buffSize) {
OrganicClawReader::OrganicClawReader(const uint8_t *buff, std::size_t buffSize) {
auto json = bit_cast<const char*>(buff);
auto jsonLen = ox_strnlen(json, buffSize);
Json::CharReaderBuilder parserBuilder;
@ -23,8 +22,7 @@ OrganicClawReader<Key>::OrganicClawReader(const uint8_t *buff, std::size_t buffS
}
}
template<typename Key>
OrganicClawReader<Key>::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<Json::CharReader>(parserBuilder.newCharReader());
if (!parser->parse(json, json + jsonLen, &m_json, nullptr)) {
@ -32,163 +30,182 @@ OrganicClawReader<Key>::OrganicClawReader(const char *json, std::size_t jsonLen)
}
}
template<typename Key>
OrganicClawReader<Key>::OrganicClawReader(const Json::Value &json) {
m_json = json;
OrganicClawReader::OrganicClawReader(const Json::Value &json, int unionIdx):
m_json(json),
m_unionIdx(unionIdx) {
}
template<typename Key>
Error OrganicClawReader<Key>::field(Key key, int8_t *val) {
Error OrganicClawReader::field(const char *key, int8_t *val) {
auto err = OxError(0);
if (targetValid()) {
const auto &jv = value(key);
++m_fieldIt;
if (jv.empty()) {
return OxError(0);
}
if (jv.isInt()) {
*val = 0;
} else if (jv.isInt()) {
*val = static_cast<int8_t>(jv.asInt());
return OxError(0);
} else {
err = OxError(1, "Type mismatch");
}
return OxError(1, "Type mismatch");
}
++m_fieldIt;
return err;
}
template<typename Key>
Error OrganicClawReader<Key>::field(Key key, int16_t *val) {
Error OrganicClawReader::field(const char *key, int16_t *val) {
auto err = OxError(0);
if (targetValid()) {
const auto &jv = value(key);
++m_fieldIt;
if (jv.empty()) {
return OxError(0);
}
if (jv.isInt()) {
*val = 0;
} else if (jv.isInt()) {
*val = static_cast<int16_t>(jv.asInt());
return OxError(0);
} else {
err = OxError(1, "Type mismatch");
}
return OxError(1, "Type mismatch");
}
++m_fieldIt;
return err;
}
template<typename Key>
Error OrganicClawReader<Key>::field(Key key, int32_t *val) {
Error OrganicClawReader::field(const char *key, int32_t *val) {
auto err = OxError(0);
if (targetValid()) {
const auto &jv = value(key);
++m_fieldIt;
if (jv.empty()) {
return OxError(0);
}
if (jv.isInt()) {
*val = 0;
} else if (jv.isInt()) {
*val = static_cast<int32_t>(jv.asInt());
return OxError(0);
} else {
err = OxError(1, "Type mismatch");
}
return OxError(1, "Type mismatch");
}
++m_fieldIt;
return err;
}
template<typename Key>
Error OrganicClawReader<Key>::field(Key key, int64_t *val) {
Error OrganicClawReader::field(const char *key, int64_t *val) {
auto err = OxError(0);
if (targetValid()) {
const auto &jv = value(key);
++m_fieldIt;
if (jv.empty()) {
return OxError(0);
}
if (jv.isInt() || jv.isInt64()) {
*val = 0;
} else if (jv.isInt() || jv.isInt64()) {
*val = static_cast<int64_t>(jv.asInt64());
return OxError(0);
} else {
err = OxError(1, "Type mismatch");
}
return OxError(1, "Type mismatch");
}
++m_fieldIt;
return err;
}
template<typename Key>
Error OrganicClawReader<Key>::field(Key key, uint8_t *val) {
Error OrganicClawReader::field(const char *key, uint8_t *val) {
auto err = OxError(0);
if (targetValid()) {
const auto &jv = value(key);
++m_fieldIt;
if (jv.empty()) {
return OxError(0);
}
if (jv.isUInt()) {
*val = 0;
} else if (jv.isUInt()) {
*val = static_cast<uint8_t>(jv.asUInt());
return OxError(0);
} else {
err = OxError(1, "Type mismatch");
}
return OxError(1, "Type mismatch");
}
++m_fieldIt;
return err;
}
template<typename Key>
Error OrganicClawReader<Key>::field(Key key, uint16_t *val) {
Error OrganicClawReader::field(const char *key, uint16_t *val) {
auto err = OxError(0);
if (targetValid()) {
const auto &jv = value(key);
++m_fieldIt;
if (jv.empty()) {
return OxError(0);
}
if (jv.isUInt()) {
*val = 0;
} else if (jv.isUInt()) {
*val = static_cast<uint16_t>(jv.asUInt());
return OxError(0);
} else {
err = OxError(1, "Type mismatch");
}
return OxError(1, "Type mismatch");
}
++m_fieldIt;
return err;
}
template<typename Key>
Error OrganicClawReader<Key>::field(Key key, uint32_t *val) {
Error OrganicClawReader::field(const char *key, uint32_t *val) {
auto err = OxError(0);
if (targetValid()) {
const auto &jv = value(key);
++m_fieldIt;
if (jv.empty()) {
return OxError(0);
}
if (jv.isUInt()) {
*val = 0;
} else if (jv.isUInt()) {
*val = static_cast<uint32_t>(jv.asUInt());
return OxError(0);
} else {
err = OxError(1, "Type mismatch");
}
return OxError(1, "Type mismatch");
}
++m_fieldIt;
return err;
}
template<typename Key>
Error OrganicClawReader<Key>::field(Key key, uint64_t *val) {
Error OrganicClawReader::field(const char *key, uint64_t *val) {
auto err = OxError(0);
if (targetValid()) {
const auto &jv = value(key);
++m_fieldIt;
if (jv.empty()) {
return OxError(0);
}
if (jv.isUInt() || jv.isUInt64()) {
*val = 0;
} else if (jv.isUInt() || jv.isUInt64()) {
*val = static_cast<uint64_t>(jv.asUInt64());
return OxError(0);
} else {
err = OxError(1, "Type mismatch");
}
}
return OxError(1, "Type mismatch");
}
template<typename Key>
Error OrganicClawReader<Key>::field(Key key, bool *val) {
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");
return err;
}
template<typename Key>
Error OrganicClawReader<Key>::field(Key key, SerStr val) {
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;
return err;
}
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 (targetValid()) {
if (jv.empty()) {
return OxError(0);
}
if (jv.isString()) {
val.data()[0] = 0;
} else if (jv.isString()) {
jv.getString(&begin, &end);
auto strSize = end - begin;
if (strSize >= val.cap()) {
return OxError(1, "String size exceeds capacity of destination");
}
err = OxError(1, "String size exceeds capacity of destination");
} else {
ox_memcpy(val.data(), begin, static_cast<std::size_t>(strSize));
val.data()[strSize] = 0;
return OxError(0);
}
return OxError(1, "Type mismatch");
} else {
err = OxError(1, "Type mismatch");
}
}
++m_fieldIt;
return err;
}
template<typename Key>
[[nodiscard]] ValErr<std::size_t> OrganicClawReader<Key>::arrayLength(Key key, bool) {
[[nodiscard]] ValErr<std::size_t> OrganicClawReader::arrayLength(const char *key, bool) {
const auto &jv = value(key);
++m_fieldIt;
if (jv.empty()) {
return 0;
}
@ -198,11 +215,9 @@ template<typename Key>
return OxError(1, "Type mismatch");
}
template<typename Key>
[[nodiscard]] std::size_t OrganicClawReader<Key>::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<typename Key>
return OxError(1, "Type mismatch");
}
template<typename Key>
void OrganicClawReader<Key>::setTypeInfo(const char*, int) {
OrganicClawReader OrganicClawReader::child(const char *key, int unionIdx) {
return OrganicClawReader(m_json[key], unionIdx);
}
template<typename Key>
OrganicClawReader<Key> OrganicClawReader<Key>::child(Key key) {
return OrganicClawReader<Key>(m_json[key]);
}
template<typename Key>
bool OrganicClawReader<Key>::fieldPresent(Key key) {
bool OrganicClawReader::fieldPresent(const char *key) {
return !m_json[key].empty();
}
template<typename Key>
Json::Value &OrganicClawReader<Key>::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<Key>::value(Key key) {
}
}
template class OrganicClawReader<const char*>;
template class OrganicClawReader<Json::ArrayIndex>;
bool OrganicClawReader::targetValid() noexcept {
return static_cast<int>(m_fieldIt) == m_unionIdx || m_unionIdx == -1;
}
}

View File

@ -18,12 +18,12 @@
namespace ox {
template<typename Key>
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<typename T>
[[nodiscard]] Error field(Key key, T *val, std::size_t len);
[[nodiscard]] Error field(const char *key, T *val, std::size_t len);
template<typename T>
[[nodiscard]] Error field(Key key, ox::Vector<T> *val);
[[nodiscard]] Error field(const char *key, ox::Vector<T> *val);
template<typename T>
[[nodiscard]] Error field(Key key, T *val);
[[nodiscard]] Error field(const char *key, T *val);
template<typename U>
[[nodiscard]] Error field(const char *key, UnionView<U> val);
template<std::size_t L>
[[nodiscard]] Error field(Key key, ox::BString<L> *val);
[[nodiscard]] Error field(const char *key, ox::BString<L> *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<std::size_t> arrayLength(Key key, bool pass = true);
[[nodiscard]] ValErr<std::size_t> 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<typename T = void>
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<typename Key>
template<typename T>
Error OrganicClawReader<Key>::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<typename U>
Error OrganicClawReader::field(const char *key, UnionView<U> 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<typename Key>
template<std::size_t L>
Error OrganicClawReader<Key>::field(Key name, ox::BString<L> *val) {
Error OrganicClawReader::field(const char *name, ox::BString<L> *val) {
return field(name, SerStr(val->data(), val->cap()));
}
// array handler
template<typename Key>
template<typename T>
Error OrganicClawReader<Key>::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<const char*> r(srcVal);
OrganicClawReader r(srcVal);
for (decltype(srcSize) i = 0; i < srcSize; ++i) {
oxReturnError(r.field("", &val[i]));
}
return OxError(0);
}
template<typename Key>
template<typename T>
Error OrganicClawReader<Key>::field(Key key, ox::Vector<T> *val) {
Error OrganicClawReader::field(const char *key, ox::Vector<T> *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<const char*> reader(json, jsonSize);
OrganicClawReader reader(json, jsonSize);
return model(&reader, val);
} catch (Error err) {
return err;

View File

@ -16,6 +16,14 @@
#include <ox/oc/oc.hpp>
#include <ox/std/std.hpp>
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<typename T>
ox::Error model(T *io, TestUnion *obj) {
io->template setTypeInfo<TestUnion>();
oxReturnError(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int));
oxReturnError(io->field("String", ox::SerStr(obj->String)));
return OxError(0);
}
template<typename T>
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<typename T>
@ -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<std::string, ox::Error(*)()> 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<std::string, ox::Error(*)()> 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<std::string, ox::Error(*)()> tests = {
oxAssert(ocErr, "Data generation failed");
auto type = ox::buildTypeDef(&testIn);
oxAssert(type.error, "Descriptor write failed");
ox::walkModel<ox::OrganicClawReader<const char*>>(type.value, ox::bit_cast<uint8_t*>(oc.c_str()), oc.len() + 1,
[](const ox::Vector<ox::FieldName>&, const ox::Vector<ox::TypeName>&, const ox::DescriptorField &f, ox::OrganicClawReader<const char*> *rdr) -> ox::Error {
ox::walkModel<ox::OrganicClawReader>(type.value, ox::bit_cast<uint8_t*>(oc.c_str()), oc.len() + 1,
[](const ox::Vector<ox::FieldName>&, const ox::Vector<ox::TypeName>&, 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) {

View File

@ -10,105 +10,109 @@
namespace ox {
template<typename Key>
OrganicClawWriter<Key>::OrganicClawWriter(Json::Value json) {
m_json = json;
OrganicClawWriter::OrganicClawWriter(int unionIdx): m_unionIdx(unionIdx) {
}
template<typename Key>
Error OrganicClawWriter<Key>::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<typename Key>
Error OrganicClawWriter<Key>::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<typename Key>
Error OrganicClawWriter<Key>::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<typename Key>
Error OrganicClawWriter<Key>::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<typename Key>
Error OrganicClawWriter<Key>::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<typename Key>
Error OrganicClawWriter<Key>::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<typename Key>
Error OrganicClawWriter<Key>::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<typename Key>
Error OrganicClawWriter<Key>::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<typename Key>
Error OrganicClawWriter<Key>::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<typename Key>
Error OrganicClawWriter<Key>::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<typename Key>
Error OrganicClawWriter<Key>::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<typename Key>
void OrganicClawWriter<Key>::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<const char*>;
template class OrganicClawWriter<Json::ArrayIndex>;
}

View File

@ -17,101 +17,125 @@
namespace ox {
template<typename Key>
class OrganicClawWriter {
friend OrganicClawWriter<const char*>;
friend OrganicClawWriter<Json::ArrayIndex>;
template<typename T>
friend ValErr<String> 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<typename T>
Error field(Key, T *val, std::size_t len);
[[nodiscard]] Error field(const char*, T *val, std::size_t len);
template<typename U>
[[nodiscard]] Error field(const char*, UnionView<U> val);
template<typename T>
Error field(Key, ox::Vector<T> *val);
[[nodiscard]] Error field(const char*, ox::Vector<T> *val);
template<std::size_t L>
Error field(Key, ox::BString<L> *val);
[[nodiscard]] Error field(const char*, ox::BString<L> *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<typename T>
Error field(Key, T *val);
[[nodiscard]] Error field(const char*, T *val);
void setTypeInfo(const char *name, int fields);
template<typename T = void>
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<int>(m_fieldIt) == m_unionIdx || m_unionIdx == -1;
}
Json::Value &value(const char *key);
};
template<typename Key>
template<typename T>
Error OrganicClawWriter<Key>::field(Key key, T *val, std::size_t len) {
OrganicClawWriter<Json::ArrayIndex> w;
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(i, &val[i]));
oxReturnError(w.field("", &val[i]));
}
m_json[key] = w.m_json;
value(key) = w.m_json;
}
++m_fieldIt;
return OxError(0);
}
template<typename Key>
template<std::size_t L>
Error OrganicClawWriter<Key>::field(Key key, ox::BString<L> *val) {
Error OrganicClawWriter::field(const char *key, ox::BString<L> *val) {
return field(key, SerStr(val->data(), val->cap()));
}
template<typename Key>
template<typename T>
Error OrganicClawWriter<Key>::field(Key key, T *val) {
OrganicClawWriter<const char*> w;
Error OrganicClawWriter::field(const char *key, T *val) {
if (targetValid()) {
OrganicClawWriter w;
oxReturnError(model(&w, val));
if (!w.m_json.isNull()) {
m_json[key] = w.m_json;
value(key) = w.m_json;
}
}
++m_fieldIt;
return OxError(0);
}
template<typename U>
Error OrganicClawWriter::field(const char *key, UnionView<U> 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<typename Key>
template<typename T>
Error OrganicClawWriter<Key>::field(Key key, ox::Vector<T> *val) {
Error OrganicClawWriter::field(const char *key, ox::Vector<T> *val) {
return field(key, val->data(), val->size());
}
template<typename T>
ValErr<String> writeOC(T *val) {
OrganicClawWriter<const char*> writer;
OrganicClawWriter writer;
oxReturnError(model(&writer, val));
Json::StreamWriterBuilder jsonBuilder;
return String(Json::writeString(jsonBuilder, writer.m_json).c_str());
}
extern template class OrganicClawWriter<const char*>;
extern template class OrganicClawWriter<Json::ArrayIndex>;
}