From cb3189b43290cb5bdf3b699f0cda1b6b6a5b871b Mon Sep 17 00:00:00 2001 From: Andreas Stöckel Date: Sun, 28 Dec 2014 12:46:10 +0100 Subject: implemented and tested creation with parent type --- src/core/model/Typesystem.cpp | 41 +++++++++++++++++++++++++++++------ src/core/model/Typesystem.hpp | 10 +++++++++ test/core/model/TypesystemTest.cpp | 44 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+), 6 deletions(-) diff --git a/src/core/model/Typesystem.cpp b/src/core/model/Typesystem.cpp index 561692a..812d85c 100644 --- a/src/core/model/Typesystem.cpp +++ b/src/core/model/Typesystem.cpp @@ -313,30 +313,50 @@ bool StructType::doBuild(Variant &data, Logger &logger) const return buildFromArrayOrMap(data, logger, false); } -Rooted StructType::createValidated( - Manager &mgr, std::string name, Handle system, - Handle parent, NodeVector attributes, Logger &logger) +Rooted StructType::createValidated(Manager &mgr, std::string name, + Handle system, + Handle parent, + NodeVector attributes, + Logger &logger) { // Check the attributes for validity and uniqueness std::map attributeNames; + NodeVector collectedAttributes; + + // Copy the attributes from the parent structure + if (parent != nullptr) { + attributeNames = parent->attributeNames; + collectedAttributes = parent->attributes; + } + + // Check the attributes for validity and uniqueness for (size_t idx = 0; idx < attributes.size(); idx++) { // Check for valid attribute names const std::string &attrName = attributes[idx]->getName(); if (!Utils::isIdentifier(name)) { - logger.error(std::string("Invalid attribute name \"") + name + + logger.error(std::string("Invalid attribute name \"") + attrName + std::string("\"")); } // Check for uniqueness auto res = attributeNames.emplace(attrName, idx); if (!res.second) { - logger.error(std::string("Attribute with name \"") + name + + logger.error(std::string("Attribute with name \"") + attrName + std::string("\" defined multiple times")); + if (parent != nullptr && parent->indexOf(attrName) >= 0) { + logger.note(std::string("Attribute \"") + attrName + + std::string("\" was defined in parent class \"") + + parent->getName() + std::string("\"")); + } } + + // Store the attribute in the complete attribute list + collectedAttributes.push_back(attributes[idx]); } // Call the private constructor - return new StructType(mgr, name, system, parent, attributes, attributeNames); + return new StructType(mgr, name, system, parent, collectedAttributes, + attributeNames); } Variant StructType::create() const @@ -369,6 +389,15 @@ Variant StructType::cast(Variant &data, Logger &logger) const return buildFromArrayOrMap(data, logger, true); } +ssize_t StructType::indexOf(const std::string &name) const +{ + size_t res; + if (resolveIdentifierKey(name, res)) { + return res; + } + return -1; +} + /* Class ArrayType */ bool ArrayType::doBuild(Variant &data, Logger &logger) const diff --git a/src/core/model/Typesystem.hpp b/src/core/model/Typesystem.hpp index 7eedc67..c279b5d 100644 --- a/src/core/model/Typesystem.hpp +++ b/src/core/model/Typesystem.hpp @@ -617,6 +617,16 @@ public: * struct type has no parent. */ Rooted getParent() const { return parent; } + + /** + * Returns the index of the given attribute in a data array representing + * the StructType. + * + * @param name is the name of the attribute for which the index is + * requested. + * @return the index or -1 if the attribute does not exist. + */ + ssize_t indexOf(const std::string &name) const; }; /** diff --git a/test/core/model/TypesystemTest.cpp b/test/core/model/TypesystemTest.cpp index 4a37707..f995222 100644 --- a/test/core/model/TypesystemTest.cpp +++ b/test/core/model/TypesystemTest.cpp @@ -397,6 +397,21 @@ static Rooted createStructType(Manager &mgr, Logger &logger) return structType; } +static Rooted createStructTypeWithParent(Handle parent, + Manager &mgr, + Logger &logger) +{ + Rooted stringType{new StringType(mgr, nullptr)}; + Rooted intType{new IntType(mgr, nullptr)}; + Rooted structType{StructType::createValidated( + mgr, "struct", nullptr, parent, + NodeVector{new Attribute{mgr, "aa", stringType, "value1"}, + new Attribute{mgr, "bc", intType, 42}, + new Attribute{mgr, "cd", parent}}, + logger)}; + return structType; +} + TEST(StructType, rtti) { Logger logger; @@ -428,6 +443,35 @@ TEST(StructType, creation) ASSERT_EQ(0, arr[3].asInt()); } +TEST(StructType, creationWithParent) +{ + Logger logger; + Manager mgr; + Rooted structType = createStructType(mgr, logger); + Rooted structWithParentType = + createStructTypeWithParent(structType, mgr, logger); + + Variant val = structWithParentType->create(); + ASSERT_TRUE(val.isArray()); + ASSERT_EQ(7U, val.asArray().size()); + + const auto &arr = val.asArray(); + ASSERT_TRUE(arr[0].isString()); + ASSERT_TRUE(arr[1].isString()); + ASSERT_TRUE(arr[2].isInt()); + ASSERT_TRUE(arr[3].isInt()); + ASSERT_TRUE(arr[4].isString()); + ASSERT_TRUE(arr[5].isInt()); + ASSERT_TRUE(arr[6].isArray()); + + ASSERT_EQ("attr1default", arr[0].asString()); + ASSERT_EQ("", arr[1].asString()); + ASSERT_EQ(3, arr[2].asInt()); + ASSERT_EQ(0, arr[3].asInt()); + ASSERT_EQ("value1", arr[4].asString()); + ASSERT_EQ(42, arr[5].asInt()); +} + /* Class ArrayType */ TEST(ArrayType, rtti) -- cgit v1.2.3