[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::String String = "";
ox::BString<32> BString = ""; ox::BString<32> BString = "";
uint32_t List[4] = {0, 0, 0, 0}; uint32_t List[4] = {0, 0, 0, 0};
ox::Vector<uint32_t> Vector = {1, 2, 3, 4, 5};
ox::HashMap<ox::String, int> Map; ox::HashMap<ox::String, int> Map;
TestStructNest EmptyStruct; TestStructNest EmptyStruct;
TestStructNest Struct; TestStructNest Struct;
@ -76,6 +77,7 @@ oxModelEnd()
template<typename T> template<typename T>
constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStruct> auto *obj) noexcept { constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStruct> auto *obj) noexcept {
io->template setTypeInfo<TestStruct>(); io->template setTypeInfo<TestStruct>();
oxReturnError(io->field("Vector", &obj->Vector));
oxReturnError(io->field("Bool", &obj->Bool)); oxReturnError(io->field("Bool", &obj->Bool));
oxReturnError(io->field("Int", &obj->Int)); oxReturnError(io->field("Int", &obj->Int));
oxReturnError(io->field("Int1", &obj->Int1)); 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[1] == testOut.List[1], "List[1] value mismatch");
oxAssert(testIn.List[2] == testOut.List[2], "List[2] 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.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["asdf"] == testOut.Map["asdf"], "Map[\"asdf\"] value mismatch");
oxAssert(testIn.Map["aoeu"] == testOut.Map["aoeu"], "Map[\"aoeu\"] value mismatch"); oxAssert(testIn.Map["aoeu"] == testOut.Map["aoeu"], "Map[\"aoeu\"] value mismatch");
oxAssert(testIn.EmptyStruct.Bool == testOut.EmptyStruct.Bool, "EmptyStruct.Bool 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[1] = 2;
testIn.List[2] = 3; testIn.List[2] = 3;
testIn.List[3] = 4; testIn.List[3] = 4;
testIn.Struct.Bool = false; testIn.Struct.Bool = true;
testIn.Struct.Int = 300; testIn.Struct.Int = 300;
testIn.Struct.BString = "Test String 2"; testIn.Struct.BString = "Test String 2";
testIn.unionIdx = 1; 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(ox::readMC(dataBuff.data(), dataBuff.size(), &testOut), "Data read failed");
oxAssert(testOut["Int"].get<int>() == testIn.Int, "testOut.Int failed"); oxAssert(testOut["Int"].get<int>() == testIn.Int, "testOut.Int failed");
oxAssert(testOut["Bool"].get<bool>() == testIn.Bool, "testOut.Bool 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"); oxAssert(testOut["String"].get<ox::String>() == testIn.String, "testOut.String failed");
auto &testOutStruct = testOut["Struct"].get<ox::ModelObject>(); auto &testOutStruct = testOut["Struct"].get<ox::ModelObject>();
auto &testOutUnion = testOut["Union"].get<ox::ModelUnion>(); 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.typeName() == TestStructNest::TypeName, "ModelObject TypeName failed");
oxAssert(testOutStruct.typeVersion() == TestStructNest::TypeVersion, "ModelObject TypeVersion failed"); oxAssert(testOutStruct.typeVersion() == TestStructNest::TypeVersion, "ModelObject TypeVersion failed");
oxAssert(testOutStruct["Bool"].get<bool>() == testIn.Struct.Bool, "testOut.Struct.Bool 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(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(testOut["unionIdx"].get<int>() == testIn.unionIdx, "testOut.unionIdx failed");
oxAssert(testOutUnion.unionIdx() == testIn.unionIdx, "testOut.Union idx wrong"); oxAssert(testOutUnion.unionIdx() == testIn.unionIdx, "testOut.Union idx wrong");

View File

@ -45,16 +45,18 @@ struct DescriptorField {
String fieldName; String fieldName;
int subscriptLevels = 0; int subscriptLevels = 0;
String typeName; // gives reference to type for lookup if type is null String typeName; // gives reference to type for lookup if type is null
int typeVersion = 0;
bool list = false; bool list = false;
constexpr DescriptorField() noexcept = default; constexpr DescriptorField() noexcept = default;
constexpr DescriptorField(const DescriptorType *pType, String pFieldName, constexpr DescriptorField(const DescriptorType *pType, String pFieldName,
int pSubscriptLevels, String pTypeName) noexcept: int pSubscriptLevels, String pTypeName, int pTypeVersion) noexcept:
type(pType), type(pType),
fieldName(std::move(pFieldName)), fieldName(std::move(pFieldName)),
subscriptLevels(pSubscriptLevels), subscriptLevels(pSubscriptLevels),
typeName(std::move(pTypeName)) { typeName(std::move(pTypeName)),
typeVersion(pTypeVersion) {
} }
constexpr DescriptorField(const DescriptorField &other) noexcept: 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; constexpr typename remove_pointer<decltype(val)>::type *p = nullptr;
const auto t = type(p); const auto t = type(p);
oxAssert(t != nullptr, "field(const char *name, T *val, std::size_t): Type not found or generated"); 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(0);
} }
return OxError(1); return OxError(1);
@ -159,10 +159,14 @@ constexpr Error TypeDescWriter::field(const char *name, const T *val, std::size_
template<typename T> template<typename T>
constexpr Error TypeDescWriter::field(const char *name, T val) noexcept { constexpr Error TypeDescWriter::field(const char *name, T val) noexcept {
if (m_type) { if (m_type) {
const auto t = type(val); if constexpr(isVector_v<typename ox::remove_pointer<T>::type> || isArray_v<typename ox::remove_pointer<T>::type>) {
oxAssert(t != nullptr, "field(const char *name, T val): Type not found or generated"); return field(name, val->data(), val->size());
m_type->fieldList.emplace_back(t, name, 0, t->typeName); } else {
return OxError(0); 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); return OxError(1);
} }
@ -175,7 +179,7 @@ constexpr Error TypeDescWriter::field(const char *name, const T *val) noexcept {
} else { } else {
const auto t = type(val); const auto t = type(val);
oxAssert(t != nullptr, "field(const char *name, T *val): Type not found or generated"); 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); 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> template<typename T>
constexpr Result<DescriptorType*> buildTypeDef(TypeStore *typeStore, T *val) noexcept { constexpr Result<DescriptorType*> buildTypeDef(TypeStore *typeStore, T *val) noexcept {
TypeDescWriter writer(typeStore); TypeDescWriter writer(typeStore);

View File

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

View File

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