diff options
Diffstat (limited to 'src/core/model')
| -rw-r--r-- | src/core/model/Typesystem.cpp | 101 | ||||
| -rw-r--r-- | src/core/model/Typesystem.hpp | 79 | 
2 files changed, 133 insertions, 47 deletions
diff --git a/src/core/model/Typesystem.cpp b/src/core/model/Typesystem.cpp index 7dd5613..bd5e615 100644 --- a/src/core/model/Typesystem.cpp +++ b/src/core/model/Typesystem.cpp @@ -67,10 +67,7 @@ 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::doCheckIsa(Handle<const Type> type) const { return false; }  bool Type::checkIsa(Handle<const Type> type) const  { @@ -114,6 +111,11 @@ bool StringType::doBuild(Variant &data, Logger &logger,  /* Class EnumType */ +EnumType::EnumType(Manager &mgr, std::string name, Handle<Typesystem> system) +    : Type(mgr, std::move(name), system, false), nextOrdinalValue(0) +{ +} +  bool EnumType::doBuild(Variant &data, Logger &logger,                         const MagicCallback &magicCallback) const  { @@ -136,41 +138,74 @@ bool EnumType::doBuild(Variant &data, Logger &logger,  		// Throw an execption if the given string value is not found  		if (it == values.end()) {  			throw LoggableException(std::string("Unknown enum constant: \"") + -			                            name + std::string("\""), +			                            name + +			                            std::string("\", expected one of ") + +			                            Utils::join(names(), ", ", "{", "}"),  			                        data);  		}  		data = it->second;  		return true;  	} -	throw LoggableException{"Expected integer or identifier", data}; + +	// Throw an exception, list possible enum types +	throw LoggableException{ +	    std::string( +	        "Expected integer or one of the following enum constants: ") + +	        Utils::join(names(), ", ", "{", "}"), +	    data};  } -Rooted<EnumType> EnumType::createValidated( -    Manager &mgr, std::string name, Handle<Typesystem> system, -    const std::vector<std::string> &values, Logger &logger) +bool EnumType::doValidate(Logger &logger) const  { -	// Map used to store the unique values of the enum -	std::map<std::string, Ordinal> unique_values; - -	// The given vector may not be empty +	bool ok = true;  	if (values.empty()) { -		logger.error("Enumeration constants may not be empty."); +		logger.error("Enum type must have at least one entry", *this); +		ok = false;  	} +	return ok & validateName(logger); +} -	// Iterate over the input vector, check the constant names for validity and -	// uniqueness and insert them into the internal values map -	for (size_t i = 0; i < values.size(); i++) { -		if (!Utils::isIdentifier(values[i])) { -			logger.error(std::string("\"") + values[i] + -			             "\" is no valid identifier."); -		} +void EnumType::addEntry(const std::string &entry, Logger &logger) +{ +	if (!Utils::isIdentifier(entry)) { +		logger.error(std::string("\"") + entry + +		             "\" is not a valid identifier."); +		return; +	} -		if (!(unique_values.insert(std::make_pair(values[i], i))).second) { -			logger.error(std::string("The value ") + values[i] + -			             " was duplicated."); -		} +	if (!values.emplace(entry, nextOrdinalValue).second) { +		logger.error(std::string("The enumeration entry ") + entry + +		             std::string(" was duplicated")); +		return;  	} -	return new EnumType{mgr, name, system, unique_values}; +	nextOrdinalValue++; +} + +void EnumType::addEntries(const std::vector<std::string> &entries, +                          Logger &logger) +{ +	for (const std::string &entry : entries) { +		addEntry(entry, logger); +	} +} + +Rooted<EnumType> EnumType::createValidated( +    Manager &mgr, std::string name, Handle<Typesystem> system, +    const std::vector<std::string> &entries, Logger &logger) +{ +	Rooted<EnumType> type = new EnumType{mgr, name, system}; +	type->addEntries(entries, logger); +	return type; +} + +std::vector<std::string> EnumType::names() const +{ +	std::vector<std::string> res; +	res.reserve(values.size()); +	for (const auto &v : values) { +		res.emplace_back(v.first); +	} +	return res;  }  std::string EnumType::nameOf(Ordinal i) const @@ -390,12 +425,15 @@ bool StructType::buildFromMap(Variant &data, Logger &logger,  			ok = false;  			logger.error(std::string("Invalid attribute key \"") + key +  			                 std::string("\""), -			             value); +			             data);  		}  	}  	// Copy the built array to the result and insert missing default values +	// TODO: Nicer way of assigning a new variant value and keeping location? +	SourceLocation loc = data.getLocation();  	data = arr; +	data.setLocation(loc);  	return insertDefaults(data, set, logger) && ok;  } @@ -470,7 +508,6 @@ bool StructType::doCheckIsa(Handle<const Type> type) const  	return false;  } -  Rooted<StructType> StructType::createValidated(      Manager &mgr, std::string name, Handle<Typesystem> system,      Handle<StructType> parentStructure, const NodeVector<Attribute> &attributes, @@ -625,7 +662,6 @@ bool ArrayType::doCheckIsa(Handle<const Type> type) const  	return t1->checkIsa(t2);  } -  /* Class UnknownType */  bool UnknownType::doBuild(Variant &, Logger &, const MagicCallback &) const @@ -706,6 +742,13 @@ Rooted<StructType> Typesystem::createStructType(const std::string &name)  	return structType;  } +Rooted<EnumType> Typesystem::createEnumType(const std::string &name) +{ +	Rooted<EnumType> enumType{new EnumType(getManager(), name, this)}; +	addType(enumType); +	return enumType; +} +  Rooted<Constant> Typesystem::createConstant(const std::string &name,                                              Variant value)  { diff --git a/src/core/model/Typesystem.hpp b/src/core/model/Typesystem.hpp index 7581626..8e3a3bc 100644 --- a/src/core/model/Typesystem.hpp +++ b/src/core/model/Typesystem.hpp @@ -371,26 +371,16 @@ public:  private:  	/** -	 * Map containing the enumeration type values and the associated integer -	 * representation. +	 * Value holding the next ordinal value that is to be used when adding a new +	 * type.  	 */ -	const std::map<std::string, Ordinal> values; +	Ordinal nextOrdinalValue;  	/** -	 * Private constructor of the EnumType class used to create a new EnumType -	 * instance from a previously created name to value map. The parameters are -	 * not checked for validity. -	 * -	 * @param mgr is the underlying Manager instance. -	 * @param name is the name of the EnumType instance. Should be a valid -	 * identifier. -	 * @param values is a vector containing the enumeration type constants. +	 * Map containing the enumeration type values and the associated integer +	 * representation.  	 */ -	EnumType(Manager &mgr, std::string name, Handle<Typesystem> system, -	         std::map<std::string, Ordinal> values) -	    : Type(mgr, std::move(name), system, false), values(std::move(values)) -	{ -	} +	std::map<std::string, Ordinal> values;  protected:  	/** @@ -405,22 +395,61 @@ protected:  	bool doBuild(Variant &data, Logger &logger,  	             const MagicCallback &magicCallback) const override; +	/** +	 * Returns true if the internal value list is non-empty. +	 * +	 * @param logger is the logger instance to which validation errors are +	 * logged. +	 */ +	bool doValidate(Logger &logger) const override; +  public:  	/** +	 * Constructor of the EnumType class. +	 * +	 * @param mgr is the underlying Manager instance. +	 * @param name is the name of the EnumType instance. Should be a valid +	 * identifier. +	 * @param system is the parent typesystem. +	 */ +	EnumType(Manager &mgr, std::string name, Handle<Typesystem> system); + +	/** +	 * Adds a new entry to the enum. The enum element is validated, errors +	 * are logged in the given logger instance. +	 * +	 * @param entry is the name of the enum element that should be added. +	 * @param logger is the logger instance that should be used to write error +	 * messages. +	 */ +	void addEntry(const std::string &entry, Logger &logger); + +	/** +	 * Adds a new entry to the enum. The enum element is validated, errors +	 * are logged in the given logger instance. +	 * +	 * @param entires is a list containing the enum elements that should be +	 * added. +	 * @param logger is the logger instance that should be used to write error +	 * messages. +	 */ +	void addEntries(const std::vector<std::string> &entries, Logger &logger); + +	/**  	 * Creates a new enum instance and validates the incomming value vector.  	 *  	 * @param mgr is the underlying Manager instance.  	 * @param name is the name of the EnumType instance. Should be a valid  	 * identifier.  	 * @param system is a reference to the parent Typesystem instance. -	 * @param values is a vector containing the enumeration type constants. +	 * @param entries is a vector containing the enumeration type constants.  	 * The constants are checked for validity (must be a valid identifier) and  	 * uniqueness (each value must exist exactly once).  	 * @param logger is the Logger instance into which errors should be written.  	 */  	static Rooted<EnumType> createValidated(  	    Manager &mgr, std::string name, Handle<Typesystem> system, -	    const std::vector<std::string> &values, Logger &logger); +	    const std::vector<std::string> &entries, Logger &logger);  	/**  	 * Creates a Variant containing a valid representation of a variable of this @@ -432,6 +461,11 @@ public:  	Variant create() const override { return Variant{0}; }  	/** +	 * Returns the names of all enum entries. +	 */ +	std::vector<std::string> names() const; + +	/**  	 * Returns the name of the given ordinal number. Throws a LoggableException  	 * if the ordinal number is out of range.  	 */ @@ -1135,6 +1169,15 @@ public:  	Rooted<StructType> createStructType(const std::string &name);  	/** +	 * Creates a new EnumType instance with the given name. Adds the new +	 * EnumType as member to the typesystem. +	 * +	 * @param name is the name of the structure that should be created. +	 * @return the new EnumType instance. +	 */ +	Rooted<EnumType> createEnumType(const std::string &name); + +	/**  	 * Creates a new Constant instance with the given name. Adds the new  	 * Constant as member to the typesystem.  	 *  | 
