From 21f5a34b758cf584e3e667fee61031311b668473 Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Thu, 28 Feb 2019 23:11:27 -0600 Subject: [PATCH] [ox/mc] Fix build issues encountered when using MetalClawDefWriter --- deps/ox/src/ox/mc/CMakeLists.txt | 5 ++- deps/ox/src/ox/mc/deftypes.hpp | 24 +++++----- deps/ox/src/ox/mc/defwriter.cpp | 64 +++++++++++++++++--------- deps/ox/src/ox/mc/defwriter.hpp | 77 ++++++++++---------------------- deps/ox/src/ox/mc/mc.hpp | 1 + deps/ox/src/ox/mc/test/tests.cpp | 57 +++++++++++------------ deps/ox/src/ox/mc/types.hpp | 7 +++ 7 files changed, 120 insertions(+), 115 deletions(-) diff --git a/deps/ox/src/ox/mc/CMakeLists.txt b/deps/ox/src/ox/mc/CMakeLists.txt index 3b7c13a6..dbf996b3 100644 --- a/deps/ox/src/ox/mc/CMakeLists.txt +++ b/deps/ox/src/ox/mc/CMakeLists.txt @@ -1,5 +1,7 @@ add_library( OxMetalClaw + defread.cpp + deftypes.cpp defwriter.cpp presencemask.cpp read.cpp @@ -20,6 +22,7 @@ set_property( install( FILES + defread.hpp deftypes.hpp defwriter.hpp err.hpp @@ -27,7 +30,7 @@ install( presencemask.hpp read.hpp types.hpp - walker.cpp + walker.hpp write.hpp DESTINATION include/ox/mc diff --git a/deps/ox/src/ox/mc/deftypes.hpp b/deps/ox/src/ox/mc/deftypes.hpp index be7ecb17..cfe5084c 100644 --- a/deps/ox/src/ox/mc/deftypes.hpp +++ b/deps/ox/src/ox/mc/deftypes.hpp @@ -15,6 +15,8 @@ namespace ox::mc { using String = BString<100>; +using FieldName = String; +using TypeName = String; enum class PrimitiveType: uint8_t { UnsignedInteger = 0, @@ -25,8 +27,6 @@ enum class PrimitiveType: uint8_t { Struct = 5, }; -using FieldName = String; - struct Field { // order of fields matters @@ -36,28 +36,29 @@ struct Field { int subscriptLevels = 0; // do not serialize the following - String typeName; // gives reference to type for lookup if type is null - bool serializeType = false; + TypeName typeName; // gives reference to type for lookup if type is null + bool ownsType = false; + + ~Field(); }; using FieldList = Vector; -using TypeName = String; struct Type { TypeName typeName; PrimitiveType primitiveType; // fieldList only applies to structs - Vector fieldList; + FieldList fieldList; // - number of bytes for integer and float types // - number of fields for structs and lists int64_t length = 0; Type() = default; - Type(String tn, PrimitiveType t, int b): typeName(tn), primitiveType(t), length(b) { + Type(TypeName tn, PrimitiveType t, int b): typeName(tn), primitiveType(t), length(b) { } - Type(String tn, PrimitiveType t, FieldList fl): typeName(tn), primitiveType(t), fieldList(fl) { + Type(TypeName tn, PrimitiveType t, FieldList fl): typeName(tn), primitiveType(t), fieldList(fl) { } }; @@ -77,7 +78,7 @@ template int ioOpWrite(T *io, Field *field) { int32_t err = 0; io->setTypeInfo("ox::mc::Field", 4); - if (field->serializeType) { + if (field->ownsType) { err |= io->op("typeName", ""); err |= io->op("type", field->type); } else { @@ -93,18 +94,21 @@ int ioOpWrite(T *io, Field *field) { template int ioOpRead(T *io, Field *field) { int32_t err = 0; + auto &typeStore = io->typeStore(); io->setTypeInfo("ox::mc::Field", 4); err |= io->op("typeName", &field->typeName); if (field->typeName == "") { - field->serializeType = true; + field->ownsType = true; if (field->type == nullptr) { field->type = new Type; } err |= io->op("type", field->type); + typeStore[field->type->typeName] = field->type; } else { // should be empty, so discard Type 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 diff --git a/deps/ox/src/ox/mc/defwriter.cpp b/deps/ox/src/ox/mc/defwriter.cpp index a9698292..593b3824 100644 --- a/deps/ox/src/ox/mc/defwriter.cpp +++ b/deps/ox/src/ox/mc/defwriter.cpp @@ -12,6 +12,27 @@ 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[][])"); + + MetalClawDefWriter::MetalClawDefWriter(mc::TypeStore *typeStore) { if (!typeStore) { m_typeStoreOwnerRef = new mc::TypeStore; @@ -21,86 +42,87 @@ MetalClawDefWriter::MetalClawDefWriter(mc::TypeStore *typeStore) { } MetalClawDefWriter::~MetalClawDefWriter() { + // does not own it's elements delete m_typeStoreOwnerRef; } -constexpr mc::Type *MetalClawDefWriter::type(int8_t*, bool *alreadyExisted) { +mc::Type *MetalClawDefWriter::type(int8_t*, bool *alreadyExisted) { constexpr auto TypeName = "B:int8_t"; constexpr auto PT = mc::PrimitiveType::SignedInteger; constexpr auto Bytes = 8; - return getPrimitive(TypeName, PT, Bytes, alreadyExisted); + return getType(TypeName, PT, Bytes, alreadyExisted); } -constexpr mc::Type *MetalClawDefWriter::type(int16_t*, bool *alreadyExisted) { +mc::Type *MetalClawDefWriter::type(int16_t*, bool *alreadyExisted) { constexpr auto TypeName = "B:int16_t"; constexpr auto PT = mc::PrimitiveType::SignedInteger; constexpr auto Bytes = 16; - return getPrimitive(TypeName, PT, Bytes, alreadyExisted); + return getType(TypeName, PT, Bytes, alreadyExisted); } -constexpr mc::Type *MetalClawDefWriter::type(int32_t*, bool *alreadyExisted) { +mc::Type *MetalClawDefWriter::type(int32_t*, bool *alreadyExisted) { constexpr auto TypeName = "B:int32_t"; constexpr auto PT = mc::PrimitiveType::SignedInteger; constexpr auto Bytes = 32; - return getPrimitive(TypeName, PT, Bytes, alreadyExisted); + return getType(TypeName, PT, Bytes, alreadyExisted); } -constexpr mc::Type *MetalClawDefWriter::type(int64_t*, bool *alreadyExisted) { +mc::Type *MetalClawDefWriter::type(int64_t*, bool *alreadyExisted) { constexpr auto TypeName = "B:int64_t"; constexpr auto PT = mc::PrimitiveType::SignedInteger; constexpr auto Bytes = 64; - return getPrimitive(TypeName, PT, Bytes, alreadyExisted); + return getType(TypeName, PT, Bytes, alreadyExisted); } -constexpr mc::Type *MetalClawDefWriter::type(uint8_t*, bool *alreadyExisted) { +mc::Type *MetalClawDefWriter::type(uint8_t*, bool *alreadyExisted) { constexpr auto TypeName = "B:uint8_t"; constexpr auto PT = mc::PrimitiveType::UnsignedInteger; constexpr auto Bytes = 8; - return getPrimitive(TypeName, PT, Bytes, alreadyExisted); + return getType(TypeName, PT, Bytes, alreadyExisted); } -constexpr mc::Type *MetalClawDefWriter::type(uint16_t*, bool *alreadyExisted) { +mc::Type *MetalClawDefWriter::type(uint16_t*, bool *alreadyExisted) { constexpr auto TypeName = "B:uint16_t"; constexpr auto PT = mc::PrimitiveType::UnsignedInteger; constexpr auto Bytes = 16; - return getPrimitive(TypeName, PT, Bytes, alreadyExisted); + return getType(TypeName, PT, Bytes, alreadyExisted); } -constexpr mc::Type *MetalClawDefWriter::type(uint32_t*, bool *alreadyExisted) { +mc::Type *MetalClawDefWriter::type(uint32_t*, bool *alreadyExisted) { constexpr auto TypeName = "B:uint32_t"; constexpr auto PT = mc::PrimitiveType::UnsignedInteger; constexpr auto Bytes = 32; - return getPrimitive(TypeName, PT, Bytes, alreadyExisted); + return getType(TypeName, PT, Bytes, alreadyExisted); } -constexpr mc::Type *MetalClawDefWriter::type(uint64_t*, bool *alreadyExisted) { +mc::Type *MetalClawDefWriter::type(uint64_t*, bool *alreadyExisted) { constexpr auto TypeName = "B:uint64_t"; constexpr auto PT = mc::PrimitiveType::UnsignedInteger; constexpr auto Bytes = 64; - return getPrimitive(TypeName, PT, Bytes, alreadyExisted); + return getType(TypeName, PT, Bytes, alreadyExisted); } mc::Type *MetalClawDefWriter::type(McStr, bool *alreadyExisted) { constexpr auto TypeName = "B:string"; constexpr auto PT = mc::PrimitiveType::String; - return getPrimitive(TypeName, PT, 0, alreadyExisted); + return getType(TypeName, PT, 0, alreadyExisted); } -constexpr mc::Type *MetalClawDefWriter::type(bool*, bool *alreadyExisted) { +mc::Type *MetalClawDefWriter::type(bool*, bool *alreadyExisted) { constexpr auto TypeName = "B:bool"; constexpr auto PT = mc::PrimitiveType::Bool; constexpr auto Bytes = 0; - return getPrimitive(TypeName, PT, Bytes, alreadyExisted); + return getType(TypeName, PT, Bytes, alreadyExisted); } -constexpr void MetalClawDefWriter::setTypeInfo(const char *name, int) { +void MetalClawDefWriter::setTypeInfo(const char *name, int) { m_typeAlreayExisted = m_typeStore->contains(name); m_type = &m_typeStore->at(name); m_type->typeName = name; m_type->primitiveType = mc::PrimitiveType::Struct; } -constexpr mc::Type *MetalClawDefWriter::getPrimitive(mc::String tn, mc::PrimitiveType pt, int b, bool *alreadyExisted) { +mc::Type *MetalClawDefWriter::getType(mc::TypeName tn, mc::PrimitiveType pt, int b, bool *alreadyExisted) { if (m_typeStore->contains(tn)) { *alreadyExisted = true; return &m_typeStore->at(tn); diff --git a/deps/ox/src/ox/mc/defwriter.hpp b/deps/ox/src/ox/mc/defwriter.hpp index 45682a1b..16f131a8 100644 --- a/deps/ox/src/ox/mc/defwriter.hpp +++ b/deps/ox/src/ox/mc/defwriter.hpp @@ -32,26 +32,6 @@ static constexpr int indirectionLevels(T *t) { return 1 + indirectionLevels(*t); } -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[][])"); - class MetalClawDefWriter { private: @@ -72,42 +52,38 @@ class MetalClawDefWriter { template ox::Error op(const char *name, ox::Vector *val); - template - ox::Error op(const char *name, ox::BString *val); - template - constexpr ox::Error op(const char *name, T *val); + ox::Error op(const char *name, T *val); - constexpr void setTypeInfo(const char *name, int fields); + void setTypeInfo(const char *name, int fields); + + [[nodiscard]] mc::Type *definition() noexcept { + return m_type; + } static constexpr OpType opType() { return OpType::WriteDefinition; } private: - constexpr mc::Type *type(int8_t *val, bool *alreadyExisted); - constexpr mc::Type *type(int16_t *val, bool *alreadyExisted); - constexpr mc::Type *type(int32_t *val, bool *alreadyExisted); - constexpr mc::Type *type(int64_t *val, bool *alreadyExisted); + mc::Type *type(int8_t *val, bool *alreadyExisted); + mc::Type *type(int16_t *val, bool *alreadyExisted); + mc::Type *type(int32_t *val, bool *alreadyExisted); + mc::Type *type(int64_t *val, bool *alreadyExisted); - constexpr mc::Type *type(uint8_t *val, bool *alreadyExisted); - constexpr mc::Type *type(uint16_t *val, bool *alreadyExisted); - constexpr mc::Type *type(uint32_t *val, bool *alreadyExisted); - constexpr mc::Type *type(uint64_t *val, bool *alreadyExisted); + mc::Type *type(uint8_t *val, bool *alreadyExisted); + mc::Type *type(uint16_t *val, bool *alreadyExisted); + mc::Type *type(uint32_t *val, bool *alreadyExisted); + mc::Type *type(uint64_t *val, bool *alreadyExisted); - constexpr mc::Type *type(bool *val, bool *alreadyExisted); - - constexpr mc::Type *type(const char *val, bool *alreadyExisted); + mc::Type *type(bool *val, bool *alreadyExisted); mc::Type *type(McStr val, bool *alreadyExisted); - template - constexpr mc::Type *type(ox::BString *val, bool *alreadyExisted); - template mc::Type *type(T *val, bool *alreadyExisted); - constexpr mc::Type *getPrimitive(mc::String tn, mc::PrimitiveType t, int b, bool *alreadyExisted); + mc::Type *getType(mc::TypeName tn, mc::PrimitiveType t, int b, bool *alreadyExisted); }; // array handler @@ -117,7 +93,7 @@ ox::Error MetalClawDefWriter::op(const char *name, T *val, std::size_t) { constexpr typename RemoveIndirection::type *p = nullptr; bool alreadyExisted = false; const auto t = type(p, &alreadyExisted); - m_type->fieldList.push_back(mc::Field{t, name, subscriptLevels(val), !alreadyExisted}); + m_type->fieldList.push_back(mc::Field{t, name, indirectionLevels(val), alreadyExisted ? t->typeName : "", !alreadyExisted}); return OxError(0); } return OxError(1); @@ -128,17 +104,12 @@ ox::Error MetalClawDefWriter::op(const char *name, ox::Vector *val) { return op(name, val->data(), val->size()); } -template -ox::Error MetalClawDefWriter::op(const char *name, ox::BString *val) { - return op(name, val->c_str()); -} - template -constexpr ox::Error MetalClawDefWriter::op(const char *name, T *val) { +ox::Error MetalClawDefWriter::op(const char *name, T *val) { if (m_type) { bool alreadyExisted = false; const auto t = type(val, &alreadyExisted); - m_type->fieldList.push_back(mc::Field{t, name, 0, !alreadyExisted}); + m_type->fieldList.push_back(mc::Field{t, name, 0, alreadyExisted ? t->typeName : "", !alreadyExisted}); return OxError(0); } return OxError(1); @@ -152,11 +123,11 @@ mc::Type *MetalClawDefWriter::type(T *val, bool *alreadyExisted) { return dw.m_type; } -template -constexpr mc::Type *MetalClawDefWriter::type(ox::BString*, bool *alreadyExisted) { - constexpr auto TypeName = "B:string"; - constexpr auto PT = mc::PrimitiveType::String; - return getPrimitive(TypeName, PT, 0, alreadyExisted); +template +[[nodiscard]] ValErr writeMCDef(T *val) { + MetalClawDefWriter writer; + ox::Error err = ioOp(&writer, val); + return {writer.definition(), err}; } } diff --git a/deps/ox/src/ox/mc/mc.hpp b/deps/ox/src/ox/mc/mc.hpp index 7b24c350..31e6e89c 100644 --- a/deps/ox/src/ox/mc/mc.hpp +++ b/deps/ox/src/ox/mc/mc.hpp @@ -8,6 +8,7 @@ #pragma once +#include "defread.hpp" #include "deftypes.hpp" #include "defwriter.hpp" #include "read.hpp" diff --git a/deps/ox/src/ox/mc/test/tests.cpp b/deps/ox/src/ox/mc/test/tests.cpp index e5b563a4..e8c079ab 100644 --- a/deps/ox/src/ox/mc/test/tests.cpp +++ b/deps/ox/src/ox/mc/test/tests.cpp @@ -6,21 +6,16 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include #include #include -#include #include #include #include -using namespace std; -using namespace ox; - struct TestStructNest { bool Bool = false; uint32_t Int = 0; - BString<32> String = ""; + ox::BString<32> String = ""; }; struct TestStruct { @@ -34,7 +29,7 @@ struct TestStruct { int32_t Int6 = 0; int32_t Int7 = 0; int32_t Int8 = 0; - BString<32> String = ""; + ox::BString<32> String = ""; uint32_t List[4] = {0, 0, 0 , 0}; TestStructNest EmptyStruct; TestStructNest Struct; @@ -43,7 +38,7 @@ struct TestStruct { template int ioOp(T *io, TestStructNest *obj) { int32_t err = 0; - io->setTypeInfo("common::TestStructNest", 3); + io->setTypeInfo("TestStructNest", 3); err |= io->op("Bool", &obj->Bool); err |= io->op("Int", &obj->Int); err |= io->op("String", &obj->String); @@ -53,7 +48,7 @@ int ioOp(T *io, TestStructNest *obj) { template int ioOp(T *io, TestStruct *obj) { int err = 0; - io->setTypeInfo("common::TestStruct", 14); + io->setTypeInfo("TestStruct", 14); err |= io->op("Bool", &obj->Bool); err |= io->op("Int", &obj->Int); err |= io->op("Int1", &obj->Int1); @@ -71,31 +66,29 @@ int ioOp(T *io, TestStruct *obj) { return err; } -map tests = { +std::map tests = { { { "MetalClawWriter", - [](string) { + [] { // This test doesn't confirm much, but it does show that the writer // doesn't segfault - size_t buffLen = 1024; - auto buff = new uint8_t[buffLen]; - int err = 0; + constexpr size_t buffLen = 1024; + uint8_t buff[buffLen]; + ox::Error err = 0; TestStruct ts; - err |= writeMC(buff, buffLen, &ts); - - delete []buff; + err |= ox::writeMC(buff, buffLen, &ts); return err; } }, { "MetalClawReader", - [](string) { - int err = 0; - size_t buffLen = 1024; - auto buff = new uint8_t[buffLen]; + [] { + ox::Error err = 0; + constexpr size_t buffLen = 1024; + uint8_t buff[buffLen]; TestStruct testIn, testOut; testIn.Bool = true; @@ -109,8 +102,8 @@ map tests = { testIn.Struct.Int = 300; testIn.Struct.String = "Test String 2"; - err |= writeMC(buff, buffLen, &testIn); - err |= readMC(buff, buffLen, &testOut); + err |= ox::writeMC(buff, buffLen, &testIn); + err |= ox::readMC(buff, buffLen, &testOut); err |= !(testIn.Bool == testOut.Bool); err |= !(testIn.Int == testOut.Int); @@ -134,24 +127,28 @@ map tests = { err |= !(testIn.Struct.String == testOut.Struct.String); err |= !(testIn.Struct.Bool == testOut.Struct.Bool); - delete []buff; + auto def = ox::writeMCDef(&testIn); + err |= def.error; return err; } }, + { + "MetalClawDef", + [] { + ox::Error err = 0; + return err; + } + }, } }; int main(int argc, const char **args) { int retval = -1; - if (argc > 1) { + if (argc > 0) { auto testName = args[1]; - string testArg = ""; - if (args[2]) { - testArg = args[2]; - } if (tests.find(testName) != tests.end()) { - retval = tests[testName](testArg); + retval = tests[testName](); } } return retval; diff --git a/deps/ox/src/ox/mc/types.hpp b/deps/ox/src/ox/mc/types.hpp index 2848c2bb..c5e9d5f0 100644 --- a/deps/ox/src/ox/mc/types.hpp +++ b/deps/ox/src/ox/mc/types.hpp @@ -8,6 +8,7 @@ #pragma once +#include #include #include @@ -28,6 +29,12 @@ class McStr { m_cap = -1; } + template + constexpr McStr(BString *str) noexcept { + m_str = const_cast(str->data()); + m_cap = -1; + } + constexpr McStr(char *str, int cap) noexcept { m_str = str; m_cap = cap;