[ox/model] Fix Vector support for ModelValue system

This commit is contained in:
Gary Talent 2022-07-07 20:02:26 -05:00
parent 7d95dbaa99
commit 93e72ae938
5 changed files with 48 additions and 13 deletions

View File

@ -48,6 +48,7 @@ struct TestStruct {
ox::String String = "";
ox::BString<32> BString = "";
uint32_t List[4] = {0, 0, 0, 0};
ox::Vector<uint32_t> Vector = {1, 2, 3, 4, 5};
ox::HashMap<ox::String, int> Map;
TestStructNest EmptyStruct;
TestStructNest Struct;
@ -76,6 +77,7 @@ oxModelEnd()
template<typename T>
constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStruct> auto *obj) noexcept {
io->template setTypeInfo<TestStruct>();
oxReturnError(io->field("Vector", &obj->Vector));
oxReturnError(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int));
oxReturnError(io->field("Int1", &obj->Int1));
@ -158,6 +160,10 @@ std::map<ox::String, ox::Error(*)()> tests = {
oxAssert(testIn.List[1] == testOut.List[1], "List[1] value mismatch");
oxAssert(testIn.List[2] == testOut.List[2], "List[2] value mismatch");
oxAssert(testIn.List[3] == testOut.List[3], "List[3] value mismatch");
oxAssert(testIn.Vector[0] == testOut.Vector[0], "Vector[0] value mismatch");
oxAssert(testIn.Vector[1] == testOut.Vector[1], "Vector[1] value mismatch");
oxAssert(testIn.Vector[2] == testOut.Vector[2], "Vector[2] value mismatch");
oxAssert(testIn.Vector[3] == testOut.Vector[3], "Vector[3] value mismatch");
oxAssert(testIn.Map["asdf"] == testOut.Map["asdf"], "Map[\"asdf\"] value mismatch");
oxAssert(testIn.Map["aoeu"] == testOut.Map["aoeu"], "Map[\"aoeu\"] value mismatch");
oxAssert(testIn.EmptyStruct.Bool == testOut.EmptyStruct.Bool, "EmptyStruct.Bool value mismatch");
@ -296,7 +302,7 @@ std::map<ox::String, ox::Error(*)()> tests = {
testIn.List[1] = 2;
testIn.List[2] = 3;
testIn.List[3] = 4;
testIn.Struct.Bool = false;
testIn.Struct.Bool = true;
testIn.Struct.Int = 300;
testIn.Struct.BString = "Test String 2";
testIn.unionIdx = 1;
@ -310,6 +316,7 @@ std::map<ox::String, ox::Error(*)()> tests = {
oxAssert(ox::readMC(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["BString"].get<ox::String>() == testIn.BString.c_str(), "testOut.String 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>();
@ -320,6 +327,7 @@ std::map<ox::String, ox::Error(*)()> tests = {
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");
oxDebugf("{}", testOutStruct["BString"].get<ox::String>());
oxAssert(testOutStruct["BString"].get<ox::String>() == testIn.Struct.BString.c_str(), "testOut.Struct.BString failed");
oxAssert(testOut["unionIdx"].get<int>() == testIn.unionIdx, "testOut.unionIdx failed");
oxAssert(testOutUnion.unionIdx() == testIn.unionIdx, "testOut.Union idx wrong");

View File

@ -45,16 +45,18 @@ struct DescriptorField {
String fieldName;
int subscriptLevels = 0;
String typeName; // gives reference to type for lookup if type is null
int typeVersion = 0;
bool list = false;
constexpr DescriptorField() noexcept = default;
constexpr DescriptorField(const DescriptorType *pType, String pFieldName,
int pSubscriptLevels, String pTypeName) noexcept:
int pSubscriptLevels, String pTypeName, int pTypeVersion) noexcept:
type(pType),
fieldName(std::move(pFieldName)),
subscriptLevels(pSubscriptLevels),
typeName(std::move(pTypeName)) {
typeName(std::move(pTypeName)),
typeVersion(pTypeVersion) {
}
constexpr DescriptorField(const DescriptorField &other) noexcept:

View File

@ -150,7 +150,7 @@ constexpr Error TypeDescWriter::field(const char *name, const T *val, std::size_
constexpr typename remove_pointer<decltype(val)>::type *p = nullptr;
const auto t = type(p);
oxAssert(t != nullptr, "field(const char *name, T *val, std::size_t): Type not found or generated");
m_type->fieldList.emplace_back(t, name, detail::indirectionLevels_v<T> + 1, t->typeName);
m_type->fieldList.emplace_back(t, name, detail::indirectionLevels_v<T> + 1, t->typeName, t->typeVersion);
return OxError(0);
}
return OxError(1);
@ -159,10 +159,14 @@ constexpr Error TypeDescWriter::field(const char *name, const T *val, std::size_
template<typename T>
constexpr Error TypeDescWriter::field(const char *name, T val) noexcept {
if (m_type) {
const auto t = type(val);
oxAssert(t != nullptr, "field(const char *name, T val): Type not found or generated");
m_type->fieldList.emplace_back(t, name, 0, t->typeName);
return OxError(0);
if constexpr(isVector_v<typename ox::remove_pointer<T>::type> || isArray_v<typename ox::remove_pointer<T>::type>) {
return field(name, val->data(), val->size());
} else {
const auto t = type(val);
oxAssert(t != nullptr, "field(const char *name, T val): Type not found or generated");
m_type->fieldList.emplace_back(t, name, 0, t->typeName, t->typeVersion);
return OxError(0);
}
}
return OxError(1);
}
@ -175,7 +179,7 @@ constexpr Error TypeDescWriter::field(const char *name, const T *val) noexcept {
} else {
const auto t = type(val);
oxAssert(t != nullptr, "field(const char *name, T *val): Type not found or generated");
m_type->fieldList.emplace_back(t, name, 0, t->typeName);
m_type->fieldList.emplace_back(t, name, 0, t->typeName, t->typeVersion);
return OxError(0);
}
}
@ -309,6 +313,22 @@ constexpr const DescriptorType *TypeDescWriter::getType(const String &tn, int ty
}
}
template<typename T>
constexpr Result<DescriptorType*> buildTypeDef(TypeStore *typeStore) noexcept {
TypeDescWriter writer(typeStore);
ModelHandlerInterface handler(&writer);
if (std::is_constant_evaluated()) {
std::allocator<T> a;
T *t = a.allocate(1);
oxReturnError(model(&handler, t));
a.deallocate(t, 1);
} else {
T *t = reinterpret_cast<T*>(ox_alloca(sizeof(T)));
oxReturnError(model(&handler, t));
}
return writer.definition();
}
template<typename T>
constexpr Result<DescriptorType*> buildTypeDef(TypeStore *typeStore, T *val) noexcept {
TypeDescWriter writer(typeStore);

View File

@ -69,6 +69,8 @@ constexpr bool isVector(const QVector<T>*) noexcept {
template<typename T>
constexpr bool isVector_v = isVector(static_cast<const T*>(nullptr));
static_assert(isVector_v<ox::Vector<unsigned int, 0ul>>);
template<typename T>
constexpr bool isArray_v = false;

View File

@ -32,14 +32,14 @@ class TypeStore {
constexpr virtual ~TypeStore() noexcept = default;
constexpr Result<DescriptorType*> get(const auto &name, int typeVersion) const noexcept {
constexpr Result<const DescriptorType*> get(const auto &name, int typeVersion) const noexcept {
const auto typeId = buildTypeId(name, typeVersion);
oxRequire(out, m_cache.at(typeId));
return out->get();
}
template<typename T>
constexpr Result<DescriptorType*> get() const noexcept {
constexpr Result<const DescriptorType*> get() const noexcept {
constexpr auto typeName = requireModelTypeName<T>();
constexpr auto typeVersion = requireModelTypeVersion<T>();
const auto typeId = buildTypeId(typeName, typeVersion);
@ -64,12 +64,15 @@ class TypeStore {
return getInit(name);
}
constexpr Result<DescriptorType*> getLoad(const auto &typeName, auto typeVersion) noexcept {
constexpr Result<const DescriptorType*> getLoad(const auto &typeName, auto typeVersion) noexcept {
const auto typeId = buildTypeId(typeName, typeVersion);
auto [val, err] = m_cache.at(typeId);
if (err) {
if (!std::is_constant_evaluated()) {
oxRequireM(dt, loadDescriptor(typeName, typeVersion));
for (auto &f : dt->fieldList) {
oxReturnError(this->getLoad(f.typeName, f.typeVersion).moveTo(&f.type));
}
auto &out = m_cache[typeId];
out = std::move(dt);
return out.get();
@ -81,7 +84,7 @@ class TypeStore {
}
template<typename T>
constexpr Result<DescriptorType*> getLoad() noexcept {
constexpr Result<const DescriptorType*> getLoad() noexcept {
constexpr auto typeName = requireModelTypeName<T>();
constexpr auto typeVersion = requireModelTypeVersion<T>();
return getLoad(typeName, typeVersion);