From 3803f1238f061a4cc962e67630c3bbbbae01eae5 Mon Sep 17 00:00:00 2001 From: Andreas Stöckel Date: Wed, 15 Apr 2015 00:37:39 +0200 Subject: Replace Typesystem "MagicCallback" by a more generic one. --- src/core/model/Typesystem.cpp | 88 +++++++++++++++++++------------ src/core/model/Typesystem.hpp | 74 +++++++------------------- src/core/parser/ParserScope.cpp | 53 +++++-------------- src/core/parser/ParserScope.hpp | 32 ++++------- src/core/parser/stack/DocumentHandler.cpp | 4 +- 5 files changed, 99 insertions(+), 152 deletions(-) (limited to 'src/core') diff --git a/src/core/model/Typesystem.cpp b/src/core/model/Typesystem.cpp index 17d81dd..cf980d6 100644 --- a/src/core/model/Typesystem.cpp +++ b/src/core/model/Typesystem.cpp @@ -27,34 +27,55 @@ namespace ousia { /* Static helper functions */ -static Type::MagicCallbackResult NullMagicCallback(Variant &, const Type *) +static bool NullResolveCallback(bool, const Rtti *, + const std::vector &, + ResolutionResultCallback) { - return Type::MagicCallbackResult::NOT_FOUND; + return false; } /* Class Type */ bool Type::build(Variant &data, Logger &logger, - const MagicCallback &magicCallback) const + const ResolveCallback &resolveCallback) const { // If the given variant is marked as "magic", try to resolve the real value if (data.isMagic()) { - switch (magicCallback(data, this)) { - case MagicCallbackResult::NOT_FOUND: - break; - case MagicCallbackResult::FOUND_INVALID: { - // The magic callback has probably already issued an error - // message -- do not print more errors + Rooted constant; + if (resolveCallback( + false, &RttiTypes::Constant, Utils::split(data.asMagic(), '.'), + [&constant](Handle resolved, Handle owner, + Logger &logger) mutable { + // Copy the resolution result out of this function + constant = resolved.cast(); + })) { + // Check whether the inner type of the constant is correct + Rooted constantType = constant->getType(); + if (!constantType->checkIsa(this)) { + logger.error( + std::string("Expected value of type \"") + this->getName() + + std::string("\" but found constant \"") + + constant->getName() + std::string("\" of type \"") + + constantType->getName() + "\" instead.", + data); + logger.note("Constant was defined here:", *constant); + + // The resolution was successful, but the received value has the + // wrong type. The code above has already issued an error + // message -- do not print more errors. Logger nullLogger; return build(data, nullLogger); } - case MagicCallbackResult::FOUND_VALID: - return true; + + // A valid constant was found, copy the data to the variant and + // abort + data = constant->getValue(); + return true; } } try { - return doBuild(data, logger, magicCallback); + return doBuild(data, logger, resolveCallback); } catch (LoggableException ex) { logger.log(ex, data); @@ -65,7 +86,7 @@ bool Type::build(Variant &data, Logger &logger, bool Type::build(Variant &data, Logger &logger) const { - return build(data, logger, NullMagicCallback); + return build(data, logger, NullResolveCallback); } bool Type::doCheckIsa(Handle type) const { return false; } @@ -81,7 +102,7 @@ bool Type::checkIsa(Handle type) const /* Class BoolType */ bool BoolType::doBuild(Variant &data, Logger &logger, - const MagicCallback &magicCallback) const + const ResolveCallback &resolveCallback) const { return VariantConverter::toBool(data, logger); } @@ -89,7 +110,7 @@ bool BoolType::doBuild(Variant &data, Logger &logger, /* Class IntType */ bool IntType::doBuild(Variant &data, Logger &logger, - const MagicCallback &magicCallback) const + const ResolveCallback &resolveCallback) const { return VariantConverter::toInt(data, logger); } @@ -97,7 +118,7 @@ bool IntType::doBuild(Variant &data, Logger &logger, /* Class DoubleType */ bool DoubleType::doBuild(Variant &data, Logger &logger, - const MagicCallback &magicCallback) const + const ResolveCallback &resolveCallback) const { return VariantConverter::toDouble(data, logger); } @@ -105,7 +126,7 @@ bool DoubleType::doBuild(Variant &data, Logger &logger, /* Class StringType */ bool StringType::doBuild(Variant &data, Logger &logger, - const MagicCallback &magicCallback) const + const ResolveCallback &resolveCallback) const { return VariantConverter::toString(data, logger); } @@ -113,7 +134,7 @@ bool StringType::doBuild(Variant &data, Logger &logger, /* Class CardinalityType */ bool CardinalityType::doBuild(Variant &data, Logger &logger, - const MagicCallback &magicCallback) const + const ResolveCallback &resolveCallback) const { return VariantConverter::toCardinality(data, logger); } @@ -126,7 +147,7 @@ EnumType::EnumType(Manager &mgr, std::string name, Handle system) } bool EnumType::doBuild(Variant &data, Logger &logger, - const MagicCallback &magicCallback) const + const ResolveCallback &resolveCallback) const { // If the variant is an int, check whether the value is in range if (data.isInt()) { @@ -363,7 +384,7 @@ bool StructType::insertDefaults(Variant &data, const std::vector &set, } bool StructType::buildFromArray(Variant &data, Logger &logger, - const MagicCallback &magicCallback, + const ResolveCallback &resolveCallback, bool trim) const { bool ok = true; @@ -388,7 +409,8 @@ bool StructType::buildFromArray(Variant &data, Logger &logger, // Make sure the given attributes have to correct type const size_t len = std::min(n, N); for (size_t a = 0; a < len; a++) { - set[a] = attributes[a]->getType()->build(arr[a], logger, magicCallback); + set[a] = + attributes[a]->getType()->build(arr[a], logger, resolveCallback); ok = ok && set[a]; } @@ -396,7 +418,7 @@ bool StructType::buildFromArray(Variant &data, Logger &logger, } bool StructType::buildFromMap(Variant &data, Logger &logger, - const MagicCallback &magicCallback, + const ResolveCallback &resolveCallback, bool trim) const { bool ok = true; @@ -429,7 +451,7 @@ bool StructType::buildFromMap(Variant &data, Logger &logger, // Convert the value to the type of the attribute arr[idx] = value; set[idx] = attributes[idx]->getType()->build(arr[idx], logger, - magicCallback); + resolveCallback); } else if (!trim) { ok = false; logger.error(std::string("Invalid attribute key \"") + key + @@ -447,14 +469,14 @@ bool StructType::buildFromMap(Variant &data, Logger &logger, } bool StructType::buildFromArrayOrMap(Variant &data, Logger &logger, - const MagicCallback &magicCallback, + const ResolveCallback &resolveCallback, bool trim) const { if (data.isArray()) { - return buildFromArray(data, logger, magicCallback, trim); + return buildFromArray(data, logger, resolveCallback, trim); } if (data.isMap()) { - return buildFromMap(data, logger, magicCallback, trim); + return buildFromMap(data, logger, resolveCallback, trim); } throw LoggableException( std::string( @@ -488,9 +510,9 @@ void StructType::initialize(Logger &logger) } bool StructType::doBuild(Variant &data, Logger &logger, - const MagicCallback &magicCallback) const + const ResolveCallback &resolveCallback) const { - return buildFromArrayOrMap(data, logger, magicCallback, false); + return buildFromArrayOrMap(data, logger, resolveCallback, false); } bool StructType::doValidate(Logger &logger) const @@ -616,7 +638,7 @@ bool StructType::derivedFrom(Handle other) const bool StructType::cast(Variant &data, Logger &logger) const { - return buildFromArrayOrMap(data, logger, NullMagicCallback, true); + return buildFromArrayOrMap(data, logger, NullResolveCallback, true); } NodeVector StructType::getOwnAttributes() const @@ -650,7 +672,7 @@ ReferenceType::ReferenceType(Manager &mgr, const std::string &name, } bool ReferenceType::doBuild(Variant &data, Logger &logger, - const MagicCallback &magicCallback) const + const ResolveCallback &resolveCallback) const { // Null references are valid references if (data.isNull()) { @@ -693,7 +715,7 @@ void ReferenceType::setDescriptor(Handle descriptor) /* Class ArrayType */ bool ArrayType::doBuild(Variant &data, Logger &logger, - const MagicCallback &magicCallback) const + const ResolveCallback &resolveCallback) const { if (!data.isArray()) { throw LoggableException( @@ -701,7 +723,7 @@ bool ArrayType::doBuild(Variant &data, Logger &logger, } bool res = true; for (auto &v : data.asArray()) { - if (!innerType->build(v, logger, magicCallback)) { + if (!innerType->build(v, logger, resolveCallback)) { res = false; } } @@ -730,7 +752,7 @@ bool ArrayType::doCheckIsa(Handle type) const /* Class UnknownType */ -bool UnknownType::doBuild(Variant &, Logger &, const MagicCallback &) const +bool UnknownType::doBuild(Variant &, Logger &, const ResolveCallback &) const { return true; } diff --git a/src/core/model/Typesystem.hpp b/src/core/model/Typesystem.hpp index 3d869d9..dc4526e 100644 --- a/src/core/model/Typesystem.hpp +++ b/src/core/model/Typesystem.hpp @@ -39,6 +39,7 @@ #include "Node.hpp" #include "RootNode.hpp" +#include "ResolutionCallbacks.hpp" namespace ousia { @@ -59,45 +60,6 @@ class Descriptor; * definitions. */ class Type : public Node { -public: - /** - * Enum describing the result of the MagicCallback. - */ - enum class MagicCallbackResult { - /** - * A magic value with the given name could not be resolved. - */ - NOT_FOUND, - - /** - * A magic value with the given name could be resolved, but is of the - * wrong type. - */ - FOUND_INVALID, - - /** - * A magic value with the given name could be resolved and is of the - * correct type. - */ - FOUND_VALID - }; - - /** - * Callback function called when a variant with "magic" value is reached. - * This callback allows to transform these magic values into something else. - * This mechanism is used to resolve constants. - * - * @param data is the magic value that should be looked up and the variant - * to which the value of the looked up constant should be written. - * @param type is a const pointer at the type. TODO: Replace this with a - * "ConstHandle". - * @return a MagicCallbackResult describing whether the magic value could - * not be resolved, could be resolved but is of the wrong type or could be - * resolved and is of the correct type. - */ - using MagicCallback = - std::function; - protected: /** * Protected constructor to be called by the classes derived from the Type @@ -125,12 +87,12 @@ protected: * -- if possible and necessary -- converted to a variant adhering to the * internal representation used by the Type class. * @param logger is the Logger instance into which errors should be written. - * @param magicCallback is a callback that should be called to other "build" + * @param resolveCallback is a callback that should be called to other "build" * functions. * @return true if the conversion was successful, false otherwise. */ virtual bool doBuild(Variant &data, Logger &logger, - const MagicCallback &magicCallback) const = 0; + const ResolveCallback &resolveCallback) const = 0; /** * May be overriden to check whether an instance of this type logically is @@ -167,12 +129,12 @@ public: * internal representation used by the Type class. * @param logger is the Logger instance into which errors should be * written. - * @param magicCallback is the callback function to be called whenever + * @param resolveCallback is the callback function to be called whenever * a variant with "magic" value is reached. * @return true if the conversion was successful, false otherwise. */ bool build(Variant &data, Logger &logger, - const MagicCallback &magicCallback) const; + const ResolveCallback &resolveCallback) const; /** * Validates and completes the given variant which was read from a @@ -241,7 +203,7 @@ protected: * @return true if the conversion was successful, false otherwise. */ bool doBuild(Variant &data, Logger &logger, - const MagicCallback &magicCallback) const override; + const ResolveCallback &resolveCallback) const override; public: /** @@ -280,7 +242,7 @@ protected: * @return true if the conversion was successful, false otherwise. */ bool doBuild(Variant &data, Logger &logger, - const MagicCallback &magicCallback) const override; + const ResolveCallback &resolveCallback) const override; public: /** @@ -319,7 +281,7 @@ protected: * @return true if the conversion was successful, false otherwise. */ bool doBuild(Variant &data, Logger &logger, - const MagicCallback &magicCallback) const override; + const ResolveCallback &resolveCallback) const override; public: /** @@ -358,7 +320,7 @@ protected: * @return true if the conversion was successful, false otherwise. */ bool doBuild(Variant &data, Logger &logger, - const MagicCallback &magicCallback) const override; + const ResolveCallback &resolveCallback) const override; public: /** @@ -396,7 +358,7 @@ protected: * @return true if the conversion was successful, false otherwise. */ bool doBuild(Variant &data, Logger &logger, - const MagicCallback &magicCallback) const override; + const ResolveCallback &resolveCallback) const override; public: /** @@ -452,7 +414,7 @@ protected: * @return true if the conversion was successful, false otherwise. */ bool doBuild(Variant &data, Logger &logger, - const MagicCallback &magicCallback) const override; + const ResolveCallback &resolveCallback) const override; /** * Returns true if the internal value list is non-empty. @@ -751,7 +713,7 @@ private: * @return true if the operation is successful, false otherwise. */ bool buildFromArray(Variant &data, Logger &logger, - const MagicCallback &magicCallback, bool trim) const; + const ResolveCallback &resolveCallback, bool trim) const; /** * Checks a map and its entries for validity and if possible updates its @@ -764,7 +726,7 @@ private: * @return true if the operation is successful, false otherwise. */ bool buildFromMap(Variant &data, Logger &logger, - const MagicCallback &magicCallback, bool trim) const; + const ResolveCallback &resolveCallback, bool trim) const; /** * Checks a map or an array for validity and if possible updates its content @@ -777,7 +739,7 @@ private: * @return true if the operation is successful, false otherwise. */ bool buildFromArrayOrMap(Variant &data, Logger &logger, - const MagicCallback &magicCallback, + const ResolveCallback &resolveCallback, bool trim) const; /** @@ -811,7 +773,7 @@ protected: * @return true if the conversion was successful, false otherwise. */ bool doBuild(Variant &data, Logger &logger, - const MagicCallback &magicCallback) const override; + const ResolveCallback &resolveCallback) const override; /** * Checks the struct descriptor for being valid. @@ -1004,7 +966,7 @@ protected: * @return true if the conversion was successful, false otherwise. */ bool doBuild(Variant &data, Logger &logger, - const MagicCallback &magicCallback) const override; + const ResolveCallback &resolveCallback) const override; /** * Returns true if this type is equivalent to another given ReferenceType, @@ -1074,7 +1036,7 @@ protected: * @return true if the conversion was successful, false otherwise. */ bool doBuild(Variant &data, Logger &logger, - const MagicCallback &magicCallback) const override; + const ResolveCallback &resolveCallback) const override; /** * Returns true if this type is equivalent to another given ArrayType. @@ -1134,7 +1096,7 @@ protected: * * @return always true. */ - bool doBuild(Variant &, Logger &, const MagicCallback &) const override; + bool doBuild(Variant &, Logger &, const ResolveCallback &) const override; public: /** diff --git a/src/core/parser/ParserScope.cpp b/src/core/parser/ParserScope.cpp index ed35839..5e4b37f 100644 --- a/src/core/parser/ParserScope.cpp +++ b/src/core/parser/ParserScope.cpp @@ -409,45 +409,20 @@ bool ParserScope::resolveType(const std::string &name, Handle owner, return resolveType(Utils::split(name, '.'), owner, logger, resultCallback); } -bool ParserScope::resolveValue(Variant &data, Handle type, Logger &logger) +bool ParserScope::resolveValue(Variant &data, Handle owner, + Handle type, Logger &logger) { - return type->build( - data, logger, - [&](Variant &innerData, - const Type *innerType) mutable -> Type::MagicCallbackResult { - // Try to resolve the node - Rooted constant = - ParserScopeBase::resolve(&RttiTypes::Constant, - Utils::split(innerData.asMagic(), '.'), - logger).cast(); - - // Abort if nothing was found - if (constant == nullptr) { - return Type::MagicCallbackResult::NOT_FOUND; - } - - // Check whether the inner type of the constant is correct - Type::MagicCallbackResult res = - Type::MagicCallbackResult::FOUND_VALID; - Rooted constantType = constant->getType(); - if (!constantType->checkIsa(innerType)) { - logger.error(std::string("Expected value of type \"") + - innerType->getName() + - std::string("\" but found constant \"") + - constant->getName() + - std::string("\" of type \"") + - constantType->getName() + "\" instead.", - innerData); - logger.note("Constant was defined here:", *constant); - res = Type::MagicCallbackResult::FOUND_INVALID; - } - - // Set the data to the value of the constant (even if an error - // happend -- probably the type was not that wrong -- who knows?) - innerData = constant->getValue(); - - return res; - }); + return type->build(data, logger, + [&](bool async, const Rtti *rttiType, + const std::vector &path, + ResolutionResultCallback resultCallback) mutable { + if (!async) { + Rooted resolved = ParserScopeBase::resolve(rttiType, path, logger); + resultCallback(resolved, owner, logger); + return resolved != nullptr; + } + return resolve(rttiType, path, type, logger, resultCallback); + }); } bool ParserScope::resolveTypeWithValue(const std::vector &path, @@ -465,7 +440,7 @@ bool ParserScope::resolveTypeWithValue(const std::vector &path, [=](Handle resolved, Handle owner, Logger &logger) mutable { if (resolved != nullptr) { Rooted type = resolved.cast(); - scope.resolveValue(*valuePtr, type, logger); + scope.resolveValue(*valuePtr, owner, type, logger); } // Call the result callback with the type diff --git a/src/core/parser/ParserScope.hpp b/src/core/parser/ParserScope.hpp index 85b5d8b..eec4751 100644 --- a/src/core/parser/ParserScope.hpp +++ b/src/core/parser/ParserScope.hpp @@ -28,6 +28,7 @@ #include #include #include +#include /** * @file ParserScope.hpp @@ -47,23 +48,6 @@ class ParserScope; class Type; class Variant; -/** - * Callback function type used for creating a dummy object while no correct - * object is available for resolution. - */ -using ResolutionImposterCallback = std::function()>; - -/** - * Callback function type called whenever the result of a resolution is - * available. - * - * @param resolved is the new, resolved node. - * @param owner is the node that was passed as "owner". - * @param logger is the logger to which errors should be logged. - */ -using ResolutionResultCallback = std::function< - void(Handle resolved, Handle owner, Logger &logger)>; - /** * Base class for the ParserScope, does not contain the mechanisms for deferred * lookup, only maintains the stack of nodes. @@ -288,14 +272,14 @@ enum class ParserFlag { POST_HEAD, /** - * Set to the boolean value "true" if explicit fields may no longer be - * defined inside a structure element. - */ + * Set to the boolean value "true" if explicit fields may no longer be + * defined inside a structure element. + */ POST_EXPLICIT_FIELDS, /** - * Set to true if all user defined tokens have been registered. - */ + * Set to true if all user defined tokens have been registered. + */ POST_USER_DEFINED_TOKEN_REGISTRATION }; @@ -716,12 +700,14 @@ public: * @param data is a reference at a variant that may contain magic values * (even in inner structures). The data will be passed to the "build" * function of the given type. + * @param owner is the node for which the resolution takes place. * @param type is the Typesystem type the data should be interpreted with. * @param logger is the logger instance into which resolution problems * should be logged. * @return true if the value was successfully built. */ - bool resolveValue(Variant &data, Handle type, Logger &logger); + bool resolveValue(Variant &data, Handle owner, Handle type, + Logger &logger); /** * Resolves a type and makes sure the corresponding value is of the correct diff --git a/src/core/parser/stack/DocumentHandler.cpp b/src/core/parser/stack/DocumentHandler.cpp index 7564fad..2228f11 100644 --- a/src/core/parser/stack/DocumentHandler.cpp +++ b/src/core/parser/stack/DocumentHandler.cpp @@ -768,7 +768,9 @@ bool DocumentChildHandler::convertData(Handle field, } // Now try to resolve the value for the primitive type - return valid && scope().resolveValue(data, type, logger); + return valid && + scope().resolveValue(data, field->getParent().cast(), type, + logger); } bool DocumentChildHandler::data() -- cgit v1.2.3