From 6a1529fc7e5d9022fa95434cc90809173d9708ed Mon Sep 17 00:00:00 2001 From: Andreas Stöckel Date: Tue, 3 Feb 2015 21:42:48 +0100 Subject: Added "checkIsa" function to Type that allows to check for an isa relationship. --- src/core/model/Typesystem.cpp | 47 ++++++++++++++++++++++++++ src/core/model/Typesystem.hpp | 48 ++++++++++++++++++++++++++ test/core/model/TypesystemTest.cpp | 69 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 164 insertions(+) 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 type) const +{ + return false; +} + +bool Type::checkIsa(Handle 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 type) const +{ + Handle parent = parentStructure; + while (parent != nullptr) { + if (parent == type) { + return true; + } + parent = parent->parentStructure; + } + return false; +} + + Rooted StructType::createValidated( Manager &mgr, std::string name, Handle system, Handle parentStructure, const NodeVector &attributes, @@ -579,6 +605,27 @@ bool ArrayType::doBuild(Variant &data, Logger &logger, return res; } +bool ArrayType::doCheckIsa(Handle type) const +{ + Handle t1{this}; + Handle 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()->innerType; + t2 = t2.cast()->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 type) const; + public: /** * Set to true, if this type descriptor is a primitive type. @@ -122,6 +134,10 @@ public: */ virtual Variant create() const = 0; + /** + * Pure virtual function + */ + /** * Validates and completes the given variant which was read from a * user-supplied source. @@ -165,6 +181,18 @@ public: return build(data, logger); } + /** + * 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 type) const; + /** * Returns the underlying Typesystem instance. * @@ -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 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 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 s1 = createStructType(mgr, logger); + Rooted 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{new StringType(mgr, nullptr)}; + Rooted intType{new IntType(mgr, nullptr)}; + + Rooted a1{new ArrayType(stringType)}; + Rooted a2{new ArrayType(stringType)}; + Rooted a3{new ArrayType(intType)}; + Rooted a4{new ArrayType(a1)}; + Rooted a5{new ArrayType(a2)}; + Rooted 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; -- cgit v1.2.3