diff options
author | Andreas Stöckel <astoecke@techfak.uni-bielefeld.de> | 2015-01-30 03:09:37 +0100 |
---|---|---|
committer | Andreas Stöckel <astoecke@techfak.uni-bielefeld.de> | 2015-01-30 03:09:37 +0100 |
commit | c4da68ba28e742810d05d35f0a26ef1d9b8c5b6c (patch) | |
tree | e506de597542f2a48fc025b13b4765a791339fb9 /src/core/model | |
parent | 90b2e9507e9d720452792b863b422221fe96d948 (diff) |
stuff
Diffstat (limited to 'src/core/model')
-rw-r--r-- | src/core/model/Typesystem.cpp | 107 | ||||
-rw-r--r-- | src/core/model/Typesystem.hpp | 116 |
2 files changed, 140 insertions, 83 deletions
diff --git a/src/core/model/Typesystem.cpp b/src/core/model/Typesystem.cpp index 8a50492..591dcbe 100644 --- a/src/core/model/Typesystem.cpp +++ b/src/core/model/Typesystem.cpp @@ -24,12 +24,28 @@ namespace ousia { +/* Static helper functions */ + +static void NullMagicCallback(Variant &, bool, ManagedUid) {} + /* Class Type */ -bool Type::build(Variant &data, Logger &logger) const +bool Type::build(Variant &data, Logger &logger, + const MagicCallback &magicCallback) const { + // If the given variant is marked as "magic", try to resolve the real value + if (data.isMagic()) { + Variant strData = Variant::fromString(data.asString()); + Logger nullLogger; + bool valid = isValid(strData, nullLogger); + magicCallback(data, valid, + getUid()); + build(strData, nullLogger); + return true; // Just return true for now + } + try { - return doBuild(data, logger); + return doBuild(data, logger, magicCallback); } catch (LoggableException ex) { logger.log(ex); @@ -38,37 +54,47 @@ bool Type::build(Variant &data, Logger &logger) const } } +bool Type::build(Variant &data, Logger &logger) const +{ + return build(data, logger, NullMagicCallback); +} + /* Class BoolType */ -bool BoolType::doBuild(Variant &data, Logger &logger) const +bool BoolType::doBuild(Variant &data, Logger &logger, + const MagicCallback &magicCallback) const { return VariantConverter::toBool(data, logger); } /* Class IntType */ -bool IntType::doBuild(Variant &data, Logger &logger) const +bool IntType::doBuild(Variant &data, Logger &logger, + const MagicCallback &magicCallback) const { return VariantConverter::toInt(data, logger); } /* Class DoubleType */ -bool DoubleType::doBuild(Variant &data, Logger &logger) const +bool DoubleType::doBuild(Variant &data, Logger &logger, + const MagicCallback &magicCallback) const { return VariantConverter::toDouble(data, logger); } /* Class StringType */ -bool StringType::doBuild(Variant &data, Logger &logger) const +bool StringType::doBuild(Variant &data, Logger &logger, + const MagicCallback &magicCallback) const { return VariantConverter::toString(data, logger); } /* Class EnumType */ -bool EnumType::doBuild(Variant &data, Logger &logger) const +bool EnumType::doBuild(Variant &data, Logger &logger, + const MagicCallback &magicCallback) const { // If the variant is an int, check whether the value is in range if (data.isInt()) { @@ -152,7 +178,7 @@ Attribute::Attribute(Manager &mgr, std::string name, Handle<Type> type, Variant defaultValue, bool optional) : Node(mgr, std::move(name)), type(acquire(type)), - rawDefaultValue(defaultValue), + defaultValue(std::move(defaultValue)), optional(optional) { ExceptionLogger logger; @@ -173,7 +199,6 @@ Attribute::Attribute(Manager &mgr, std::string name, Variant defaultValue, void Attribute::initialize(Logger &logger) { if (optional) { - defaultValue = rawDefaultValue; type->build(defaultValue, logger); } } @@ -187,7 +212,6 @@ void Attribute::setDefaultValue(const Variant &defaultValue, Logger &logger) { invalidate(); - rawDefaultValue = defaultValue; optional = true; initialize(logger); } @@ -196,7 +220,6 @@ void Attribute::removeDefaultValue() { invalidate(); - rawDefaultValue = nullptr; defaultValue = nullptr; optional = false; } @@ -264,7 +287,9 @@ bool StructType::insertDefaults(Variant &data, const std::vector<bool> &set, return ok; } -bool StructType::buildFromArray(Variant &data, Logger &logger, bool trim) const +bool StructType::buildFromArray(Variant &data, Logger &logger, + const MagicCallback &magicCallback, + bool trim) const { bool ok = true; Variant::arrayType &arr = data.asArray(); @@ -286,14 +311,16 @@ bool StructType::buildFromArray(Variant &data, Logger &logger, bool trim) const // 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); + set[a] = attributes[a]->getType()->build(arr[a], logger, magicCallback); ok = ok && set[a]; } return insertDefaults(data, set, logger) && ok; } -bool StructType::buildFromMap(Variant &data, Logger &logger, bool trim) const +bool StructType::buildFromMap(Variant &data, Logger &logger, + const MagicCallback &magicCallback, + bool trim) const { bool ok = true; const Variant::mapType &map = data.asMap(); @@ -323,7 +350,8 @@ bool StructType::buildFromMap(Variant &data, Logger &logger, bool trim) const // Convert the value to the type of the attribute arr[idx] = value; - set[idx] = attributes[idx]->getType()->build(arr[idx], logger); + set[idx] = attributes[idx]->getType()->build(arr[idx], logger, + magicCallback); } else if (!trim) { ok = false; logger.error(std::string("Invalid attribute key \"") + key + @@ -337,13 +365,14 @@ bool StructType::buildFromMap(Variant &data, Logger &logger, bool trim) const } bool StructType::buildFromArrayOrMap(Variant &data, Logger &logger, + const MagicCallback &magicCallback, bool trim) const { if (data.isArray()) { - return buildFromArray(data, logger, trim); + return buildFromArray(data, logger, magicCallback, trim); } if (data.isMap()) { - return buildFromMap(data, logger, trim); + return buildFromMap(data, logger, magicCallback, trim); } throw LoggableException( std::string( @@ -375,9 +404,10 @@ void StructType::initialize(Logger &logger) } } -bool StructType::doBuild(Variant &data, Logger &logger) const +bool StructType::doBuild(Variant &data, Logger &logger, + const MagicCallback &magicCallback) const { - return buildFromArrayOrMap(data, logger, false); + return buildFromArrayOrMap(data, logger, magicCallback, false); } bool StructType::doValidate(Logger &logger) const @@ -491,7 +521,7 @@ bool StructType::derivedFrom(Handle<StructType> other) const bool StructType::cast(Variant &data, Logger &logger) const { - return buildFromArrayOrMap(data, logger, true); + return buildFromArrayOrMap(data, logger, NullMagicCallback, true); } ssize_t StructType::indexOf(const std::string &name) const @@ -510,7 +540,8 @@ bool StructType::hasAttribute(const std::string &name) const /* Class ArrayType */ -bool ArrayType::doBuild(Variant &data, Logger &logger) const +bool ArrayType::doBuild(Variant &data, Logger &logger, + const MagicCallback &magicCallback) const { if (!data.isArray()) { throw LoggableException(std::string("Expected array, but got ") + @@ -518,23 +549,32 @@ bool ArrayType::doBuild(Variant &data, Logger &logger) const } bool res = true; for (auto &v : data.asArray()) { - if (!innerType->build(v, logger)) { + if (!innerType->build(v, logger, magicCallback)) { res = false; } } return res; } +/* Class UnknownType */ + +bool UnknownType::doBuild(Variant &, Logger &, const MagicCallback &) const +{ + return true; +} + +UnknownType::UnknownType(Manager &mgr) : Type(mgr, "unknown", nullptr, false) {} + +Variant UnknownType::create() const { return Variant{nullptr}; } + /* Class Constant */ Constant::Constant(Manager &mgr, std::string name, Handle<Typesystem> system, Handle<Type> type, Variant value) - : Node(mgr, std::move(name), system), - type(acquire(type)), - rawValue(std::move(value)) + : Node(mgr, std::move(name), system), type(acquire(type)), value(value) { ExceptionLogger logger; - initialize(logger); + this->type->build(this->value, logger); } Constant::Constant(Manager &mgr, std::string name, Handle<Typesystem> system, @@ -543,27 +583,20 @@ Constant::Constant(Manager &mgr, std::string name, Handle<Typesystem> system, { } -void Constant::initialize(Logger &logger) -{ - value = rawValue; - type->build(value, logger); -} - Rooted<Type> Constant::getType() const { return type; } void Constant::setType(Handle<Type> type, Logger &logger) { this->type = acquire(type); - initialize(logger); + this->type->build(this->value, logger); } -const Variant &Constant::getValue() const { return value; } +Variant &Constant::getValue() { return value; } void Constant::setValue(Variant value, Logger &logger) { - this->rawValue = value; this->value = std::move(value); - initialize(logger); + this->type->build(this->value, logger); } /* Class Typesystem */ @@ -571,7 +604,7 @@ void Constant::setValue(Variant value, Logger &logger) void Typesystem::doResolve(ResolutionState &state) { continueResolveComposita(constants, constants.getIndex(), state); - continueResolveComposita(types, constants.getIndex(), state); + continueResolveComposita(types, types.getIndex(), state); continueResolveReferences(typesystems, state); } diff --git a/src/core/model/Typesystem.hpp b/src/core/model/Typesystem.hpp index 5b1254a..d88a7e9 100644 --- a/src/core/model/Typesystem.hpp +++ b/src/core/model/Typesystem.hpp @@ -29,6 +29,7 @@ #ifndef _OUSIA_MODEL_TYPESYSTEM_HPP_ #define _OUSIA_MODEL_TYPESYSTEM_HPP_ +#include <functional> #include <map> #include <vector> @@ -55,6 +56,21 @@ class SystemTypesystem; * definitions. */ class Type : public Node { +public: + /** + * 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. + * @param isValid is set to true if the magic value does not necessarily + * have to be looked up, in this case no error message has to be generated + * if the lookup for a constant fails. + * @param type is the managed uid of the underlying Type for which the magic + * value should be looked up. + */ + using MagicCallback = std::function<void(Variant &data, bool isValid, ManagedUid Type)>; + protected: /** * Protected constructor to be called by the classes derived from the Type @@ -82,9 +98,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" + * functions. * @return true if the conversion was successful, false otherwise. */ - virtual bool doBuild(Variant &data, Logger &logger) const = 0; + virtual bool doBuild(Variant &data, Logger &logger, + const MagicCallback &magicCallback) const = 0; public: /** @@ -109,6 +128,22 @@ 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 + * 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; + + /** + * Validates and completes the given variant which was read from a + * user-supplied source. + * + * @param data is a variant containing the data that should be checked and + * -- 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. * @return true if the conversion was successful, false otherwise. */ bool build(Variant &data, Logger &logger) const; @@ -154,7 +189,8 @@ protected: * @param logger is the Logger instance into which errors should be written. * @return true if the conversion was successful, false otherwise. */ - bool doBuild(Variant &data, Logger &logger) const override; + bool doBuild(Variant &data, Logger &logger, + const MagicCallback &magicCallback) const override; public: /** @@ -192,7 +228,8 @@ protected: * @param logger is the Logger instance into which errors should be written. * @return true if the conversion was successful, false otherwise. */ - bool doBuild(Variant &data, Logger &logger) const override; + bool doBuild(Variant &data, Logger &logger, + const MagicCallback &magicCallback) const override; public: /** @@ -230,7 +267,8 @@ protected: * @param logger is the Logger instance into which errors should be written. * @return true if the conversion was successful, false otherwise. */ - bool doBuild(Variant &data, Logger &logger) const override; + bool doBuild(Variant &data, Logger &logger, + const MagicCallback &magicCallback) const override; public: /** @@ -268,7 +306,8 @@ protected: * @param logger is the Logger instance into which errors should be written. * @return true if the conversion was successful, false otherwise. */ - bool doBuild(Variant &data, Logger &logger) const override; + bool doBuild(Variant &data, Logger &logger, + const MagicCallback &magicCallback) const override; public: /** @@ -332,7 +371,8 @@ protected: * @param logger is the Logger instance into which errors should be written. * @return true if the conversion was successful, false otherwise. */ - bool doBuild(Variant &data, Logger &logger) const override; + bool doBuild(Variant &data, Logger &logger, + const MagicCallback &magicCallback) const override; public: /** @@ -384,12 +424,6 @@ private: Owned<Type> type; /** - * Initial default value passed to the constructor of the Attribute class - * that has not been passed through the "build" method of the type. - */ - Variant rawDefaultValue; - - /** * Default value of the attribute. */ Variant defaultValue; @@ -400,11 +434,7 @@ private: bool optional; /** - * Reinitializes the default value from the raw default value with the - * current type. - * - * @param logger is the logger instance to which errors while building the - * default value should be passed. + * Function used to parse the Attribute default value with the current type. */ void initialize(Logger &logger); @@ -473,7 +503,7 @@ public: * @return the default value of the attribute. If no default value has been * given a null variant is returned (the opposite does not hold). */ - Variant getDefaultValue() const { return defaultValue; } + Variant& getDefaultValue() { return defaultValue; } /** * Removes any default value from the attribute, making this attribute @@ -589,7 +619,8 @@ private: * of attributes (as needed when casting from a derived type). * @return true if the operation is successful, false otherwise. */ - bool buildFromArray(Variant &data, Logger &logger, bool trim) const; + bool buildFromArray(Variant &data, Logger &logger, + const MagicCallback &magicCallback, bool trim) const; /** * Checks a map and its entries for validity and if possible updates its @@ -601,7 +632,8 @@ private: * when casting from a derived type. * @return true if the operation is successful, false otherwise. */ - bool buildFromMap(Variant &data, Logger &logger, bool trim) const; + bool buildFromMap(Variant &data, Logger &logger, + const MagicCallback &magicCallback, bool trim) const; /** * Checks a map or an array for validity and if possible updates its content @@ -613,7 +645,9 @@ private: * when casting from a derived type. * @return true if the operation is successful, false otherwise. */ - bool buildFromArrayOrMap(Variant &data, Logger &logger, bool trim) const; + bool buildFromArrayOrMap(Variant &data, Logger &logger, + const MagicCallback &magicCallback, + bool trim) const; /** * Rebuilds the internal index and attribute list depending on the parent @@ -645,7 +679,8 @@ protected: * @param logger is the Logger instance into which errors should be written. * @return true if the conversion was successful, false otherwise. */ - bool doBuild(Variant &data, Logger &logger) const override; + bool doBuild(Variant &data, Logger &logger, + const MagicCallback &magicCallback) const override; /** * Checks the struct descriptor for being valid. @@ -819,17 +854,18 @@ protected: * @param logger is the Logger instance into which errors should be written. * @return true if the conversion was successful, false otherwise. */ - bool doBuild(Variant &data, Logger &logger) const override; + bool doBuild(Variant &data, Logger &logger, + const MagicCallback &magicCallback) const override; public: /** * Constructor of the ArrayType class. * - * @param mgr is the Manager instance to be used for the Node. * @param innerType is the type of the elements stored in the array. */ - ArrayType(Manager &mgr, Handle<Type> innerType) - : Type(mgr, "", innerType->getTypesystem(), false), + ArrayType(Handle<Type> innerType) + : Type(innerType->getManager(), innerType->getName() + "[]", + innerType->getTypesystem(), false), innerType(acquire(innerType)) { } @@ -869,7 +905,7 @@ protected: * * @return always true. */ - bool doBuild(Variant &, Logger &) const override { return true; } + bool doBuild(Variant &, Logger &, const MagicCallback &) const override; public: /** @@ -878,14 +914,14 @@ public: * * @param mgr is the Manager instance to be used for the Node. */ - UnknownType(Manager &mgr) : Type(mgr, "unknown", nullptr, false) {} + UnknownType(Manager &mgr); /** * Returns a nullptr variant. * * @return a Variant instance with nullptr value. */ - Variant create() const override { return Variant{nullptr}; } + Variant create() const override; }; /** @@ -900,23 +936,10 @@ private: Owned<Type> type; /** - * Value of the value before a proper type was set. - */ - Variant rawValue; - - /** * Actual value of the constant. */ Variant value; - /** - * Reinitializes the value from the raw value with the current type. - * - * @param logger is the logger instance to which errors while building the - * value should be passed. - */ - void initialize(Logger &logger); - public: /** * Constructor of the Constant node. @@ -952,9 +975,10 @@ public: Rooted<Type> getType() const; /** - * Sets the type of the constant to the given type. This will cause the raw - * value of the variant to be reparsed and any error to be logged in the - * given logger. + * Sets the type of the constant to the given type. This will cause the + * value of the variant to be built with the given type and any error to be + * logged in the given logger. Note: This operation is possibly lossy and + * will destroy values if the current variant value doesn't match the type. * * @param type is the new type of the constant. * @param logger is the logger instance to which errors that occur during @@ -968,7 +992,7 @@ public: * * @return a const reference to the actual value of the constant. */ - const Variant &getValue() const; + Variant &getValue(); /** * Sets the value of the constant. The value will be passed to the "build" |