[ox] Rename Serialization package to Model
This commit is contained in:
35
deps/ox/src/ox/model/CMakeLists.txt
vendored
Normal file
35
deps/ox/src/ox/model/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
add_library(
|
||||
OxModel
|
||||
desctypes.cpp
|
||||
descwrite.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
OxModel PUBLIC
|
||||
OxStd
|
||||
)
|
||||
|
||||
set_property(
|
||||
TARGET
|
||||
OxModel
|
||||
PROPERTY
|
||||
POSITION_INDEPENDENT_CODE ON
|
||||
)
|
||||
|
||||
install(
|
||||
FILES
|
||||
descread.hpp
|
||||
desctypes.hpp
|
||||
descwrite.hpp
|
||||
optype.hpp
|
||||
model.hpp
|
||||
types.hpp
|
||||
walk.hpp
|
||||
DESTINATION
|
||||
include/ox/model
|
||||
)
|
||||
|
||||
install(TARGETS OxModel
|
||||
LIBRARY DESTINATION lib/ox
|
||||
ARCHIVE DESTINATION lib/ox
|
||||
)
|
7
deps/ox/src/ox/model/definition-language.txt
vendored
Normal file
7
deps/ox/src/ox/model/definition-language.txt
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
<Type> : <TypeName><FieldList>
|
||||
<FieldList> : <FieldList> | <FieldList><Field>
|
||||
<Field> : <FieldType><TypeID><FieldName>
|
||||
<TypeID> : <TypeName> | <TypeName><Type>
|
||||
<TypeName> : <string>
|
||||
<FieldType> : <0: single> | <1: list>
|
||||
<FieldName> : <string>
|
42
deps/ox/src/ox/model/descread.hpp
vendored
Normal file
42
deps/ox/src/ox/model/descread.hpp
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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 "desctypes.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
template<typename ReaderBase>
|
||||
class TypeDescReader: public ReaderBase {
|
||||
private:
|
||||
TypeStore m_typeStore;
|
||||
|
||||
public:
|
||||
TypeDescReader(uint8_t *buff, std::size_t buffLen);
|
||||
|
||||
const TypeStore &typeStore() const;
|
||||
|
||||
};
|
||||
|
||||
template<typename ReaderBase>
|
||||
TypeDescReader<ReaderBase>::TypeDescReader(uint8_t *buff, std::size_t buffLen): ReaderBase(buff, buffLen) {
|
||||
}
|
||||
|
||||
template<typename ReaderBase>
|
||||
const TypeStore &TypeDescReader<ReaderBase>::typeStore() const {
|
||||
return m_typeStore;
|
||||
}
|
||||
|
||||
template<typename ReaderBase, typename T>
|
||||
int readMCDef(uint8_t *buff, std::size_t buffLen, T *val) {
|
||||
TypeDescReader<ReaderBase> reader(buff, buffLen);
|
||||
return ioOp(&reader, val);
|
||||
}
|
||||
|
||||
}
|
19
deps/ox/src/ox/model/desctypes.cpp
vendored
Normal file
19
deps/ox/src/ox/model/desctypes.cpp
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
#include "desctypes.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
DescriptorField::~DescriptorField() {
|
||||
if (ownsType) {
|
||||
delete type;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
175
deps/ox/src/ox/model/desctypes.hpp
vendored
Normal file
175
deps/ox/src/ox/model/desctypes.hpp
vendored
Normal file
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* 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 <ox/std/error.hpp>
|
||||
#include <ox/std/hashmap.hpp>
|
||||
#include <ox/std/string.hpp>
|
||||
#include <ox/std/vector.hpp>
|
||||
|
||||
namespace ox {
|
||||
|
||||
using String = BString<100>;
|
||||
using FieldName = String;
|
||||
using TypeName = String;
|
||||
|
||||
enum class PrimitiveType: uint8_t {
|
||||
UnsignedInteger = 0,
|
||||
SignedInteger = 1,
|
||||
Bool = 2,
|
||||
// Float = 3, reserved, but not implemented
|
||||
String = 4,
|
||||
Struct = 5,
|
||||
};
|
||||
|
||||
struct DescriptorField {
|
||||
// order of fields matters
|
||||
|
||||
// only serialize type name if type has already been serialized
|
||||
const struct DescriptorType *type = nullptr;
|
||||
FieldName fieldName;
|
||||
int subscriptLevels = 0;
|
||||
|
||||
// do not serialize the following
|
||||
TypeName typeName; // gives reference to type for lookup if type is null
|
||||
bool ownsType = false;
|
||||
|
||||
constexpr DescriptorField() noexcept = default;
|
||||
|
||||
/**
|
||||
* Allow for explicit copying.
|
||||
*/
|
||||
constexpr explicit DescriptorField(const DescriptorField &other) noexcept {
|
||||
type = other.type;
|
||||
fieldName = other.fieldName;
|
||||
subscriptLevels = other.subscriptLevels;
|
||||
typeName = other.typeName;
|
||||
ownsType = false; // is copy, only owns type if move
|
||||
}
|
||||
|
||||
constexpr DescriptorField(const DescriptorType *type, const FieldName &fieldName, int subscriptLevels, const TypeName &typeName, bool ownsType) noexcept {
|
||||
this->type = type;
|
||||
this->fieldName = fieldName;
|
||||
this->subscriptLevels = subscriptLevels;
|
||||
this->typeName = typeName;
|
||||
this->ownsType = ownsType;
|
||||
}
|
||||
|
||||
constexpr DescriptorField(DescriptorField &&other) noexcept {
|
||||
type = other.type;
|
||||
fieldName = other.fieldName;
|
||||
subscriptLevels = other.subscriptLevels;
|
||||
typeName = other.typeName;
|
||||
ownsType = other.ownsType;
|
||||
|
||||
other.type = {};
|
||||
other.fieldName = "";
|
||||
other.subscriptLevels = {};
|
||||
other.typeName = "";
|
||||
other.ownsType = {};
|
||||
}
|
||||
|
||||
~DescriptorField();
|
||||
|
||||
constexpr const DescriptorField &operator=(DescriptorField &&other) noexcept {
|
||||
type = other.type;
|
||||
fieldName = other.fieldName;
|
||||
subscriptLevels = other.subscriptLevels;
|
||||
typeName = other.typeName;
|
||||
ownsType = other.ownsType;
|
||||
|
||||
other.type = {};
|
||||
other.fieldName = "";
|
||||
other.subscriptLevels = {};
|
||||
other.typeName = "";
|
||||
other.ownsType = {};
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
using FieldList = Vector<DescriptorField>;
|
||||
|
||||
struct DescriptorType {
|
||||
TypeName typeName;
|
||||
PrimitiveType primitiveType;
|
||||
// fieldList only applies to structs
|
||||
FieldList fieldList;
|
||||
// - number of bytes for integer and float types
|
||||
// - number of fields for structs and lists
|
||||
int64_t length = 0;
|
||||
|
||||
DescriptorType() = default;
|
||||
|
||||
DescriptorType(TypeName tn, PrimitiveType t, int b): typeName(tn), primitiveType(t), length(b) {
|
||||
}
|
||||
|
||||
DescriptorType(TypeName tn, PrimitiveType t, FieldList fl): typeName(tn), primitiveType(t), fieldList(fl) {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
Error ioOp(T *io, DescriptorType *type) {
|
||||
Error err = 0;
|
||||
io->setTypeInfo("ox::DescriptorType", 4);
|
||||
err |= io->op("typeName", &type->typeName);
|
||||
err |= io->op("primitiveType", &type->primitiveType);
|
||||
err |= io->op("fieldList", &type->fieldList);
|
||||
err |= io->op("length", &type->length);
|
||||
return err;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Error ioOpWrite(T *io, DescriptorField *field) {
|
||||
Error err = 0;
|
||||
io->setTypeInfo("ox::DescriptorField", 4);
|
||||
if (field->ownsType) {
|
||||
err |= io->op("typeName", "");
|
||||
err |= io->op("type", field->type);
|
||||
} else {
|
||||
err |= io->op("typeName", &field->type->typeName);
|
||||
err |= io->op("type", static_cast<decltype(field->type)>(nullptr));
|
||||
}
|
||||
err |= io->op("fieldName", &field->fieldName);
|
||||
// defaultValue is unused now, but leave placeholder for backwards compatibility
|
||||
const int DefaultValue = 0;
|
||||
err |= io->op("defaultValue", &DefaultValue);
|
||||
return err;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Error ioOpRead(T *io, DescriptorField *field) {
|
||||
Error err = 0;
|
||||
auto &typeStore = io->typeStore();
|
||||
io->setTypeInfo("ox::DescriptorField", 4);
|
||||
err |= io->op("typeName", &field->typeName);
|
||||
if (field->typeName == "") {
|
||||
field->ownsType = true;
|
||||
if (field->type == nullptr) {
|
||||
field->type = new DescriptorType;
|
||||
}
|
||||
err |= io->op("type", field->type);
|
||||
typeStore[field->type->typeName] = field->type;
|
||||
} else {
|
||||
// should be empty, so discard
|
||||
DescriptorType t;
|
||||
err |= io->op("type", &t);
|
||||
field->type = typeStore[field->typeName];
|
||||
}
|
||||
err |= io->op("fieldName", &field->fieldName);
|
||||
// defaultValue is unused now, but placeholder for backwards compatibility
|
||||
err |= io->op("defaultValue", nullptr);
|
||||
return err;
|
||||
}
|
||||
|
||||
using TypeStore = ox::HashMap<String, DescriptorType*>;
|
||||
|
||||
}
|
153
deps/ox/src/ox/model/descwrite.cpp
vendored
Normal file
153
deps/ox/src/ox/model/descwrite.cpp
vendored
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright 2015 - 2019 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 <ox/std/typeinfo.hpp>
|
||||
|
||||
#include "descwrite.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
static_assert([] {
|
||||
int i = 0;
|
||||
return indirectionLevels(i) == 0;
|
||||
}(), "indirectionLevels broken: indirectionLevels(int)");
|
||||
|
||||
static_assert([] {
|
||||
int i = 0;
|
||||
return indirectionLevels(&i) == 1;
|
||||
}(), "indirectionLevels broken: indirectionLevels(int*)");
|
||||
|
||||
static_assert([] {
|
||||
int i[2] = {};
|
||||
return indirectionLevels(i) == 1;
|
||||
}(), "indirectionLevels broken: indirectionLevels(int[])");
|
||||
|
||||
static_assert([] {
|
||||
int i[2][2] = {{}};
|
||||
return indirectionLevels(i) == 2;
|
||||
}(), "indirectionLevels broken: indirectionLevels(int[][])");
|
||||
|
||||
|
||||
TypeDescWriter::TypeDescWriter(TypeStore *typeStore) {
|
||||
if (!typeStore) {
|
||||
m_typeStoreOwnerRef = new TypeStore;
|
||||
typeStore = m_typeStoreOwnerRef;
|
||||
}
|
||||
m_typeStore = typeStore;
|
||||
}
|
||||
|
||||
TypeDescWriter::~TypeDescWriter() {
|
||||
// does not own it's elements
|
||||
delete m_typeStoreOwnerRef;
|
||||
}
|
||||
|
||||
DescriptorType *TypeDescWriter::type(int8_t*, bool *alreadyExisted) {
|
||||
constexpr auto TypeName = "B:int8_t";
|
||||
constexpr auto PT = PrimitiveType::SignedInteger;
|
||||
constexpr auto Bytes = 1;
|
||||
return getType(TypeName, PT, Bytes, alreadyExisted);
|
||||
}
|
||||
|
||||
DescriptorType *TypeDescWriter::type(int16_t*, bool *alreadyExisted) {
|
||||
constexpr auto TypeName = "B:int16_t";
|
||||
constexpr auto PT = PrimitiveType::SignedInteger;
|
||||
constexpr auto Bytes = 2;
|
||||
return getType(TypeName, PT, Bytes, alreadyExisted);
|
||||
}
|
||||
|
||||
DescriptorType *TypeDescWriter::type(int32_t*, bool *alreadyExisted) {
|
||||
constexpr auto TypeName = "B:int32_t";
|
||||
constexpr auto PT = PrimitiveType::SignedInteger;
|
||||
constexpr auto Bytes = 4;
|
||||
return getType(TypeName, PT, Bytes, alreadyExisted);
|
||||
}
|
||||
|
||||
DescriptorType *TypeDescWriter::type(int64_t*, bool *alreadyExisted) {
|
||||
constexpr auto TypeName = "B:int64_t";
|
||||
constexpr auto PT = PrimitiveType::SignedInteger;
|
||||
constexpr auto Bytes = 8;
|
||||
return getType(TypeName, PT, Bytes, alreadyExisted);
|
||||
}
|
||||
|
||||
DescriptorType *TypeDescWriter::type(uint8_t*, bool *alreadyExisted) {
|
||||
constexpr auto TypeName = "B:uint8_t";
|
||||
constexpr auto PT = PrimitiveType::UnsignedInteger;
|
||||
constexpr auto Bytes = 1;
|
||||
return getType(TypeName, PT, Bytes, alreadyExisted);
|
||||
}
|
||||
|
||||
DescriptorType *TypeDescWriter::type(uint16_t*, bool *alreadyExisted) {
|
||||
constexpr auto TypeName = "B:uint16_t";
|
||||
constexpr auto PT = PrimitiveType::UnsignedInteger;
|
||||
constexpr auto Bytes = 2;
|
||||
return getType(TypeName, PT, Bytes, alreadyExisted);
|
||||
}
|
||||
|
||||
DescriptorType *TypeDescWriter::type(uint32_t*, bool *alreadyExisted) {
|
||||
constexpr auto TypeName = "B:uint32_t";
|
||||
constexpr auto PT = PrimitiveType::UnsignedInteger;
|
||||
constexpr auto Bytes = 4;
|
||||
return getType(TypeName, PT, Bytes, alreadyExisted);
|
||||
}
|
||||
|
||||
DescriptorType *TypeDescWriter::type(uint64_t*, bool *alreadyExisted) {
|
||||
constexpr auto TypeName = "B:uint64_t";
|
||||
constexpr auto PT = PrimitiveType::UnsignedInteger;
|
||||
constexpr auto Bytes = 8;
|
||||
return getType(TypeName, PT, Bytes, alreadyExisted);
|
||||
}
|
||||
|
||||
DescriptorType *TypeDescWriter::type(const char*, bool *alreadyExisted) {
|
||||
constexpr auto TypeName = "B:string";
|
||||
constexpr auto PT = PrimitiveType::String;
|
||||
return getType(TypeName, PT, 0, alreadyExisted);
|
||||
}
|
||||
|
||||
DescriptorType *TypeDescWriter::type(SerStr, bool *alreadyExisted) {
|
||||
constexpr auto TypeName = "B:string";
|
||||
constexpr auto PT = PrimitiveType::String;
|
||||
return getType(TypeName, PT, 0, alreadyExisted);
|
||||
}
|
||||
|
||||
DescriptorType *TypeDescWriter::type(bool*, bool *alreadyExisted) {
|
||||
constexpr auto TypeName = "B:bool";
|
||||
constexpr auto PT = PrimitiveType::Bool;
|
||||
constexpr auto Bytes = 0;
|
||||
return getType(TypeName, PT, Bytes, alreadyExisted);
|
||||
}
|
||||
|
||||
void TypeDescWriter::setTypeInfo(const char *name, int) {
|
||||
auto &t = m_typeStore->at(name);
|
||||
if (!t) {
|
||||
t = new DescriptorType;
|
||||
}
|
||||
m_type = t;
|
||||
m_type->typeName = name;
|
||||
m_type->primitiveType = PrimitiveType::Struct;
|
||||
}
|
||||
|
||||
DescriptorType *TypeDescWriter::getType(TypeName tn, PrimitiveType pt, int b, bool *alreadyExisted) {
|
||||
if (m_typeStore->contains(tn)) {
|
||||
*alreadyExisted = true;
|
||||
auto type = m_typeStore->at(tn);
|
||||
oxAssert(type != nullptr, "TypeDescWriter::getType returning null DescriptorType");
|
||||
return type;
|
||||
} else {
|
||||
*alreadyExisted = false;
|
||||
auto &t = m_typeStore->at(tn);
|
||||
if (!t) {
|
||||
t = new DescriptorType;
|
||||
}
|
||||
t->typeName = tn;
|
||||
t->primitiveType = pt;
|
||||
t->length = b;
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
183
deps/ox/src/ox/model/descwrite.hpp
vendored
Normal file
183
deps/ox/src/ox/model/descwrite.hpp
vendored
Normal file
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright 2015 - 2019 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 <ox/std/byteswap.hpp>
|
||||
#include <ox/std/hashmap.hpp>
|
||||
#include <ox/std/string.hpp>
|
||||
#include <ox/std/trace.hpp>
|
||||
#include <ox/std/types.hpp>
|
||||
#include <ox/std/vector.hpp>
|
||||
|
||||
#include "desctypes.hpp"
|
||||
#include "optype.hpp"
|
||||
#include "types.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
template<typename T>
|
||||
static constexpr int indirectionLevels(T) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static constexpr int indirectionLevels(T *t) {
|
||||
return 1 + indirectionLevels(*t);
|
||||
}
|
||||
|
||||
class TypeDescWriter {
|
||||
|
||||
private:
|
||||
struct NameCatcher {
|
||||
|
||||
TypeName name;
|
||||
|
||||
constexpr void setTypeInfo(const char *name, int) noexcept {
|
||||
this->name = name;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr ox::Error op(const char*, T*, std::size_t) noexcept {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr ox::Error op(const char*, T*) noexcept {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
TypeStore *m_typeStoreOwnerRef = nullptr;
|
||||
TypeStore *m_typeStore = nullptr;
|
||||
DescriptorType *m_type = nullptr;
|
||||
|
||||
public:
|
||||
explicit TypeDescWriter(TypeStore *typeStore = nullptr);
|
||||
|
||||
~TypeDescWriter();
|
||||
|
||||
template<typename T>
|
||||
ox::Error op(const char *name, T *val, std::size_t valLen);
|
||||
|
||||
template<typename T>
|
||||
ox::Error op(const char *name, ox::Vector<T> *val);
|
||||
|
||||
template<typename T>
|
||||
ox::Error op(const char *name, T *val);
|
||||
|
||||
void setTypeInfo(const char *name, int fields);
|
||||
|
||||
[[nodiscard]] DescriptorType *definition() noexcept {
|
||||
return m_type;
|
||||
}
|
||||
|
||||
static constexpr OpType opType() {
|
||||
return OpType::WriteDefinition;
|
||||
}
|
||||
|
||||
private:
|
||||
DescriptorType *type(int8_t *val, bool *alreadyExisted);
|
||||
DescriptorType *type(int16_t *val, bool *alreadyExisted);
|
||||
DescriptorType *type(int32_t *val, bool *alreadyExisted);
|
||||
DescriptorType *type(int64_t *val, bool *alreadyExisted);
|
||||
|
||||
DescriptorType *type(uint8_t *val, bool *alreadyExisted);
|
||||
DescriptorType *type(uint16_t *val, bool *alreadyExisted);
|
||||
DescriptorType *type(uint32_t *val, bool *alreadyExisted);
|
||||
DescriptorType *type(uint64_t *val, bool *alreadyExisted);
|
||||
|
||||
DescriptorType *type(bool *val, bool *alreadyExisted);
|
||||
|
||||
DescriptorType *type(const char *val, bool *alreadyExisted);
|
||||
|
||||
DescriptorType *type(SerStr val, bool *alreadyExisted);
|
||||
|
||||
template<std::size_t sz>
|
||||
DescriptorType *type(BString<sz> *val, bool *alreadyExisted);
|
||||
|
||||
template<typename T>
|
||||
DescriptorType *type(T *val, bool *alreadyExisted);
|
||||
|
||||
DescriptorType *getType(TypeName tn, PrimitiveType t, int b, bool *alreadyExisted);
|
||||
};
|
||||
|
||||
// array handler
|
||||
template<typename T>
|
||||
ox::Error TypeDescWriter::op(const char *name, T *val, std::size_t) {
|
||||
if (m_type) {
|
||||
constexpr typename ox::remove_pointer<decltype(val)>::type *p = nullptr;
|
||||
bool alreadyExisted = false;
|
||||
const auto t = type(p, &alreadyExisted);
|
||||
oxAssert(t != nullptr, "op(const char *name, T *val, std::size_t): Type not found or generated");
|
||||
if (t == nullptr) {
|
||||
type(p, &alreadyExisted);
|
||||
}
|
||||
m_type->fieldList.emplace_back(t, name, indirectionLevels(val), alreadyExisted ? t->typeName : "", !alreadyExisted);
|
||||
return OxError(0);
|
||||
}
|
||||
return OxError(1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ox::Error TypeDescWriter::op(const char *name, ox::Vector<T> *val) {
|
||||
return op(name, val->data(), val->size());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ox::Error TypeDescWriter::op(const char *name, T *val) {
|
||||
if (m_type) {
|
||||
bool alreadyExisted = false;
|
||||
const auto t = type(val, &alreadyExisted);
|
||||
oxAssert(t != nullptr, "op(const char *name, T *val): Type not found or generated");
|
||||
m_type->fieldList.emplace_back(t, name, 0, alreadyExisted ? t->typeName : "", !alreadyExisted);
|
||||
return OxError(0);
|
||||
}
|
||||
return OxError(1);
|
||||
}
|
||||
|
||||
template<std::size_t sz>
|
||||
DescriptorType *TypeDescWriter::type(BString<sz> *val, bool *alreadyExisted) {
|
||||
return type(SerStr(val), alreadyExisted);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
DescriptorType *TypeDescWriter::type(T *val, bool *alreadyExisted) {
|
||||
NameCatcher nc;
|
||||
ioOp(&nc, val);
|
||||
if (m_typeStore->contains(nc.name)) {
|
||||
*alreadyExisted = true;
|
||||
return m_typeStore->at(nc.name);
|
||||
} else {
|
||||
TypeDescWriter dw(m_typeStore);
|
||||
oxLogError(ioOp(&dw, val));
|
||||
*alreadyExisted = false;
|
||||
return dw.m_type;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]] ValErr<DescriptorType*> buildMCDef(T *val) {
|
||||
TypeDescWriter writer;
|
||||
Error err = ioOp(&writer, val);
|
||||
return {writer.definition(), err};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Error writeMCDef(uint8_t *buff, std::size_t buffLen, T *val, std::size_t *sizeOut = nullptr) {
|
||||
auto def = buildMCDef(val);
|
||||
auto err = def.error;
|
||||
if (!err) {
|
||||
err |= writeMC(buff, buffLen, def.value, sizeOut);
|
||||
}
|
||||
delete def.value;
|
||||
return err;
|
||||
}
|
||||
|
||||
}
|
15
deps/ox/src/ox/model/model.hpp
vendored
Normal file
15
deps/ox/src/ox/model/model.hpp
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright 2015 - 2019 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 "descread.hpp"
|
||||
#include "desctypes.hpp"
|
||||
#include "descwrite.hpp"
|
||||
#include "types.hpp"
|
||||
#include "walk.hpp"
|
50
deps/ox/src/ox/model/optype.hpp
vendored
Normal file
50
deps/ox/src/ox/model/optype.hpp
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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 <ox/std/error.hpp>
|
||||
|
||||
namespace ox {
|
||||
|
||||
enum class OpType {
|
||||
Read = 1,
|
||||
Write = 2,
|
||||
WriteDefinition = 3,
|
||||
};
|
||||
|
||||
// empty default implementations of ioOp functions
|
||||
|
||||
template<typename T, typename O>
|
||||
ox::Error ioOpRead(T*, O*) {
|
||||
return OxError(1);
|
||||
}
|
||||
|
||||
template<typename T, typename O>
|
||||
ox::Error ioOpWrite(T*, O*) {
|
||||
return OxError(1);
|
||||
}
|
||||
|
||||
template<typename T, typename O>
|
||||
ox::Error ioOpWriteDefinition(T*, O*) {
|
||||
return OxError(1);
|
||||
}
|
||||
|
||||
template<typename T, typename O>
|
||||
ox::Error ioOp(T *io, O *obj) {
|
||||
if constexpr(T::opType() == ox::OpType::Read) {
|
||||
return ioOpRead(io, obj);
|
||||
} else if constexpr(T::opType() == ox::OpType::Write) {
|
||||
return ioOpWrite(io, obj);
|
||||
} else if constexpr(T::opType() == ox::OpType::WriteDefinition) {
|
||||
return ioOpWriteDefinition(io, obj);
|
||||
}
|
||||
return OxError(1);
|
||||
}
|
||||
|
||||
}
|
58
deps/ox/src/ox/model/types.hpp
vendored
Normal file
58
deps/ox/src/ox/model/types.hpp
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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 <ox/std/string.hpp>
|
||||
#include <ox/std/strops.hpp>
|
||||
#include <ox/std/types.hpp>
|
||||
|
||||
namespace ox {
|
||||
|
||||
class SerStr {
|
||||
|
||||
protected:
|
||||
int m_cap = 0;
|
||||
char *m_str = nullptr;
|
||||
|
||||
public:
|
||||
template<std::size_t sz>
|
||||
constexpr SerStr(BString<sz> *str) noexcept {
|
||||
m_str = str->data();
|
||||
m_cap = str->cap();
|
||||
}
|
||||
|
||||
constexpr SerStr(char *str, int cap) noexcept {
|
||||
m_str = str;
|
||||
m_cap = cap;
|
||||
}
|
||||
|
||||
constexpr const char *c_str() noexcept {
|
||||
return m_str;
|
||||
}
|
||||
|
||||
constexpr char *data() noexcept {
|
||||
// do not return a non-const pointer to the const_casted m_str
|
||||
return m_str;
|
||||
}
|
||||
|
||||
constexpr int len() noexcept {
|
||||
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;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
146
deps/ox/src/ox/model/walk.hpp
vendored
Normal file
146
deps/ox/src/ox/model/walk.hpp
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* 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 <ox/std/error.hpp>
|
||||
|
||||
#include "desctypes.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
template<typename Reader, typename T>
|
||||
class DataWalker {
|
||||
template<typename ReaderBase, typename FH>
|
||||
friend ox::Error parseField(const DescriptorField &field, ReaderBase *rdr, DataWalker<ReaderBase, FH> *walker);
|
||||
|
||||
private:
|
||||
Vector<const DescriptorType*> m_typeStack;
|
||||
T m_fieldHandler;
|
||||
Vector<FieldName> m_path;
|
||||
Vector<TypeName> m_typePath;
|
||||
|
||||
public:
|
||||
DataWalker(DescriptorType *type, T fieldHandler);
|
||||
|
||||
[[nodiscard]] const DescriptorType *type() const noexcept;
|
||||
|
||||
ox::Error read(const DescriptorField&, Reader *rdr);
|
||||
|
||||
protected:
|
||||
void pushNamePath(FieldName fn);
|
||||
|
||||
void popNamePath();
|
||||
|
||||
void pushType(const DescriptorType *type);
|
||||
|
||||
void popType();
|
||||
|
||||
};
|
||||
|
||||
template<typename Reader, typename T>
|
||||
DataWalker<Reader, T>::DataWalker(DescriptorType *type, T fieldHandler): m_fieldHandler(fieldHandler) {
|
||||
m_typeStack.push_back(type);
|
||||
}
|
||||
|
||||
template<typename Reader, typename T>
|
||||
const DescriptorType *DataWalker<Reader, T>::type() const noexcept {
|
||||
return m_typeStack.back();
|
||||
}
|
||||
|
||||
template<typename Reader, typename T>
|
||||
ox::Error DataWalker<Reader, T>::read(const DescriptorField &f, Reader *rdr) {
|
||||
// get const ref of paths
|
||||
const auto &pathCr = m_path;
|
||||
const auto &typePathCr = m_typePath;
|
||||
return m_fieldHandler(pathCr, typePathCr, f, rdr);
|
||||
}
|
||||
|
||||
template<typename Reader, typename T>
|
||||
void DataWalker<Reader, T>::pushNamePath(FieldName fn) {
|
||||
m_path.push_back(fn);
|
||||
}
|
||||
|
||||
template<typename Reader, typename T>
|
||||
void DataWalker<Reader, T>::popNamePath() {
|
||||
m_path.pop_back();
|
||||
}
|
||||
|
||||
template<typename Reader, typename T>
|
||||
void DataWalker<Reader, T>::pushType(const DescriptorType *type) {
|
||||
m_typeStack.push_back(type);
|
||||
}
|
||||
|
||||
template<typename Reader, typename T>
|
||||
void DataWalker<Reader, T>::popType() {
|
||||
m_typeStack.pop_back();
|
||||
}
|
||||
|
||||
template<typename Reader, typename FH>
|
||||
static ox::Error parseField(const DescriptorField &field, Reader *rdr, DataWalker<Reader, FH> *walker) {
|
||||
walker->pushNamePath(field.fieldName);
|
||||
if (field.subscriptLevels) {
|
||||
// add array handling
|
||||
const auto arrayLen = rdr->arrayLength(true);
|
||||
auto child = rdr->child();
|
||||
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++) {
|
||||
subscript = "[";
|
||||
subscript += i;
|
||||
subscript += "]";
|
||||
walker->pushNamePath(subscript);
|
||||
oxReturnError(parseField(f, &child, walker));
|
||||
walker->popNamePath();
|
||||
}
|
||||
rdr->nextField();
|
||||
} else {
|
||||
switch (field.type->primitiveType) {
|
||||
case PrimitiveType::UnsignedInteger:
|
||||
case PrimitiveType::SignedInteger:
|
||||
case PrimitiveType::Bool:
|
||||
case PrimitiveType::String:
|
||||
oxReturnError(walker->read(field, rdr));
|
||||
break;
|
||||
case PrimitiveType::Struct:
|
||||
if (rdr->fieldPresent()) {
|
||||
auto child = rdr->child();
|
||||
walker->pushType(field.type);
|
||||
oxReturnError(ioOp(&child, walker));
|
||||
walker->popType();
|
||||
rdr->nextField();
|
||||
} else {
|
||||
// skip and discard absent field
|
||||
int discard;
|
||||
oxReturnError(rdr->op("", &discard));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
walker->popNamePath();
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename Reader, typename FH>
|
||||
ox::Error ioOp(Reader *rdr, DataWalker<Reader, FH> *walker) {
|
||||
auto type = walker->type();
|
||||
if (!type) {
|
||||
return OxError(1);
|
||||
}
|
||||
auto typeName = type->typeName.c_str();
|
||||
auto &fields = type->fieldList;
|
||||
rdr->setTypeInfo(typeName, fields.size());
|
||||
for (std::size_t i = 0; i < fields.size(); i++) {
|
||||
oxReturnError(parseField(fields[i], rdr, walker));
|
||||
}
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user