diff options
-rw-r--r-- | src/core/model/Typesystem.cpp | 47 | ||||
-rw-r--r-- | src/core/model/Typesystem.hpp | 48 | ||||
-rw-r--r-- | test/core/model/TypesystemTest.cpp | 69 |
3 files changed, 164 insertions, 0 deletions
diff --git a/src/core/model/Typesystem.cpp b/src/core/model/Typesystem.cpp index 7af3e54..7dd5613 100644 --- a/src/core/model/Typesystem.cpp +++ b/src/core/model/Typesystem.cpp @@ -67,6 +67,19 @@ bool Type::build(Variant &data, Logger &logger) const return build(data, logger, NullMagicCallback); } +bool Type::doCheckIsa(Handle<const Type> type) const +{ + return false; +} + +bool Type::checkIsa(Handle<const Type> type) const +{ + if (type.get() == this) { + return true; + } + return doCheckIsa(type); +} + /* Class BoolType */ bool BoolType::doBuild(Variant &data, Logger &logger, @@ -445,6 +458,19 @@ bool StructType::doValidate(Logger &logger) const continueValidationCheckDuplicates(attributes, logger); } +bool StructType::doCheckIsa(Handle<const Type> type) const +{ + Handle<StructType> parent = parentStructure; + while (parent != nullptr) { + if (parent == type) { + return true; + } + parent = parent->parentStructure; + } + return false; +} + + Rooted<StructType> StructType::createValidated( Manager &mgr, std::string name, Handle<Typesystem> system, Handle<StructType> parentStructure, const NodeVector<Attribute> &attributes, @@ -579,6 +605,27 @@ bool ArrayType::doBuild(Variant &data, Logger &logger, return res; } +bool ArrayType::doCheckIsa(Handle<const Type> type) const +{ + Handle<const Type> t1{this}; + Handle<const Type> t2{type}; + + // Unwrap the array types until only the innermost type is left + while (t1->isa(RttiTypes::ArrayType) && t2->isa(RttiTypes::ArrayType)) { + t1 = t1.cast<const ArrayType>()->innerType; + t2 = t2.cast<const ArrayType>()->innerType; + } + + // Abort if only one of the to types is an array type + if (t1->isa(RttiTypes::ArrayType) || t2->isa(RttiTypes::ArrayType)) { + return false; + } + + // Run the isa test on the inntermost type + return t1->checkIsa(t2); +} + + /* Class UnknownType */ bool UnknownType::doBuild(Variant &, Logger &, const MagicCallback &) const diff --git a/src/core/model/Typesystem.hpp b/src/core/model/Typesystem.hpp index b14ff62..7581626 100644 --- a/src/core/model/Typesystem.hpp +++ b/src/core/model/Typesystem.hpp @@ -108,6 +108,18 @@ protected: virtual bool doBuild(Variant &data, Logger &logger, const MagicCallback &magicCallback) const = 0; + /** + * May be overriden to check whether an instance of this type logically is + * an instance of the given type. Default implementation always returns + * false. + * + * @param type is the type that should be checked for the "isa" + * relationship. + * @return true if an instance of this type also is an instance of the given + * type, false otherwise. + */ + virtual bool doCheckIsa(Handle<const Type> type) const; + public: /** * Set to true, if this type descriptor is a primitive type. @@ -123,6 +135,10 @@ public: virtual Variant create() const = 0; /** + * Pure virtual function + */ + + /** * Validates and completes the given variant which was read from a * user-supplied source. * @@ -166,6 +182,18 @@ public: } /** + * May be overriden to check whether an instance of this type logically is + * an instance of the given type. This always evaluates to true if the given + * type points at this type descriptor. + * + * @param type is the type that should be checked for the "isa" + * relationship. + * @return true if an instance of this type also is an instance of the given + * type, false otherwise. + */ + bool checkIsa(Handle<const Type> type) const; + + /** * Returns the underlying Typesystem instance. * * @return a Rooted reference pointing at the underlying typesystem @@ -700,6 +728,16 @@ protected: */ bool doValidate(Logger &logger) const override; + /** + * Returns true if this type has the given type as parent (directly or + * indirectly). + * + * @param type is the type that should be checked for the "isa" + * relationship. + * @return true if the given type is a parent of this type, false otherwise. + */ + bool doCheckIsa(Handle<const Type> type) const override; + public: /** * Constructor of the StructType class, creates a new instance @@ -867,6 +905,16 @@ protected: bool doBuild(Variant &data, Logger &logger, const MagicCallback &magicCallback) const override; + /** + * Returns true if this type is equivalent to another given ArrayType. + * + * @param type is the type that should be checked for the "isa" + * relationship. + * @return true if the given type is equivalent to this type, false + * otherwise. + */ + bool doCheckIsa(Handle<const Type> type) const override; + public: /** * Constructor of the ArrayType class. diff --git a/test/core/model/TypesystemTest.cpp b/test/core/model/TypesystemTest.cpp index 9a40db7..2a2c81e 100644 --- a/test/core/model/TypesystemTest.cpp +++ b/test/core/model/TypesystemTest.cpp @@ -674,6 +674,19 @@ TEST(StructType, cast) ASSERT_EQ(0, arr[3].asInt()); } +TEST(StructType, isa) +{ + Manager mgr; + Rooted<StructType> s1 = createStructType(mgr, logger); + Rooted<StructType> s2 = createStructTypeWithParent(s1, mgr, logger); + + ASSERT_TRUE(s1->checkIsa(s1)); + ASSERT_FALSE(s1->checkIsa(s2)); + + ASSERT_TRUE(s2->checkIsa(s1)); + ASSERT_TRUE(s2->checkIsa(s2)); +} + TEST(StructType, indexOf) { Manager mgr; @@ -804,6 +817,62 @@ TEST(ArrayType, creation) ASSERT_TRUE(val.asArray().empty()); } +TEST(ArrayType, isa) +{ + Manager mgr; + Rooted<StringType> stringType{new StringType(mgr, nullptr)}; + Rooted<IntType> intType{new IntType(mgr, nullptr)}; + + Rooted<ArrayType> a1{new ArrayType(stringType)}; + Rooted<ArrayType> a2{new ArrayType(stringType)}; + Rooted<ArrayType> a3{new ArrayType(intType)}; + Rooted<ArrayType> a4{new ArrayType(a1)}; + Rooted<ArrayType> a5{new ArrayType(a2)}; + Rooted<ArrayType> a6{new ArrayType(a3)}; + + ASSERT_TRUE(a1->checkIsa(a1)); + ASSERT_TRUE(a1->checkIsa(a2)); + ASSERT_FALSE(a1->checkIsa(a3)); + ASSERT_FALSE(a1->checkIsa(a4)); + ASSERT_FALSE(a1->checkIsa(a5)); + ASSERT_FALSE(a1->checkIsa(a6)); + + ASSERT_TRUE(a2->checkIsa(a1)); + ASSERT_TRUE(a2->checkIsa(a2)); + ASSERT_FALSE(a2->checkIsa(a3)); + ASSERT_FALSE(a2->checkIsa(a4)); + ASSERT_FALSE(a2->checkIsa(a5)); + ASSERT_FALSE(a2->checkIsa(a6)); + + ASSERT_FALSE(a3->checkIsa(a1)); + ASSERT_FALSE(a3->checkIsa(a2)); + ASSERT_TRUE(a3->checkIsa(a3)); + ASSERT_FALSE(a3->checkIsa(a4)); + ASSERT_FALSE(a3->checkIsa(a5)); + ASSERT_FALSE(a3->checkIsa(a6)); + + ASSERT_FALSE(a4->checkIsa(a1)); + ASSERT_FALSE(a4->checkIsa(a2)); + ASSERT_FALSE(a4->checkIsa(a3)); + ASSERT_TRUE(a4->checkIsa(a4)); + ASSERT_TRUE(a4->checkIsa(a5)); + ASSERT_FALSE(a4->checkIsa(a6)); + + ASSERT_FALSE(a5->checkIsa(a1)); + ASSERT_FALSE(a5->checkIsa(a2)); + ASSERT_FALSE(a5->checkIsa(a3)); + ASSERT_TRUE(a5->checkIsa(a4)); + ASSERT_TRUE(a5->checkIsa(a5)); + ASSERT_FALSE(a5->checkIsa(a6)); + + ASSERT_FALSE(a6->checkIsa(a1)); + ASSERT_FALSE(a6->checkIsa(a2)); + ASSERT_FALSE(a6->checkIsa(a3)); + ASSERT_FALSE(a6->checkIsa(a4)); + ASSERT_FALSE(a6->checkIsa(a5)); + ASSERT_TRUE(a6->checkIsa(a6)); +} + TEST(ArrayType, conversion) { Manager mgr; |