diff options
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"  | 
