diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/core/model/Typesystem.cpp | 47 | ||||
-rw-r--r-- | src/core/model/Typesystem.hpp | 43 |
2 files changed, 76 insertions, 14 deletions
diff --git a/src/core/model/Typesystem.cpp b/src/core/model/Typesystem.cpp index 2899e03..c2ab363 100644 --- a/src/core/model/Typesystem.cpp +++ b/src/core/model/Typesystem.cpp @@ -94,34 +94,48 @@ bool BoolType::doBuild(Variant &var, Logger &logger) const bool EnumType::doBuild(Variant &var, Logger &logger) const { + // If the variant is an int, check whether the value is in range if (var.isInt()) { int i = var.asInt(); if (i < 0 || i >= (int)values.size()) { throw LoggableException("Value is out of range."); } - } else if (var.isMagic()) { + return true; + } + + // If the given variant is a magic value it may be an enumeration constant. + // Set the variant to the numeric value + if (var.isMagic()) { // Fetch the given constant name and look it up in the value map const std::string &name = var.asMagic(); auto it = values.find(name); - // Throw an execption + // 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("\"")); } var = it->second; + return true; } - return true; + throw LoggableException{"Expected integer or identifier"}; } -EnumType EnumType::createValidated(Manager &mgr, std::string name, +Rooted<EnumType> EnumType::createValidated(Manager &mgr, std::string name, Handle<Typesystem> system, const std::vector<std::string> &values, Logger &logger) { // Map used to store the unique values of the enum - std::map<std::string, Variant::intType> unique_values; + std::map<std::string, Ordinal> unique_values; + // The given vector may not be empty + if (values.empty()) { + logger.error("Enumeration constants may not be empty."); + } + + // 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(values[i] + " is no valid identifier."); @@ -132,7 +146,28 @@ EnumType EnumType::createValidated(Manager &mgr, std::string name, " was duplicated."); } } - return std::move(EnumType(mgr, name, system, unique_values)); + return new EnumType{mgr, name, system, unique_values}; +} + +std::string EnumType::nameOf(Ordinal i) const +{ + if (i >= 0 && i < (int)values.size()) { + for (const auto &v : values) { + if (v.second == i) { + return v.first; + } + } + } + throw LoggableException("Ordinal value out of range."); +} + +EnumType::Ordinal EnumType::valueOf(const std::string &name) const +{ + auto it = values.find(name); + if (it != values.end()) { + return it->second; + } + throw LoggableException(std::string("Unknown enum constant: ") + name); } /* Class ArrayType */ diff --git a/src/core/model/Typesystem.hpp b/src/core/model/Typesystem.hpp index 3511354..8562546 100644 --- a/src/core/model/Typesystem.hpp +++ b/src/core/model/Typesystem.hpp @@ -279,12 +279,15 @@ public: * The EnumType class represents a user defined enumeration type. */ class EnumType : public Type { +public: + using Ordinal = Variant::intType; + private: /** * Map containing the enumeration type values and the associated integer * representation. */ - const std::map<std::string, Variant::intType> values; + const std::map<std::string, Ordinal> values; protected: /** @@ -303,24 +306,47 @@ protected: * instance from a previously created name to value map. */ EnumType(Manager &mgr, std::string name, Handle<Typesystem> system, - std::map<std::string, Variant::intType> values) + std::map<std::string, Ordinal> values) : Type(mgr, std::move(name), system, false), values(std::move(values)) { } public: /** - * TODO: DOC + * 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 values 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 EnumType createValidated(Manager &mgr, std::string name, - Handle<Typesystem> system, - const std::vector<std::string> &values, - Logger &logger); + static Rooted<EnumType> createValidated( + Manager &mgr, std::string name, Handle<Typesystem> system, + const std::vector<std::string> &values, Logger &logger); /** - * TODO: DOC + * Creates a Variant containing a valid representation of a variable of this + * EnumType instance. The variant will point at the first enumeration + * constant. + * + * @return a variant pointing at the first enumeration constant. */ Variant create() const override { return Variant{0}; } + + /** + * Returns the name of the given ordinal number. Throws a LoggableException + * if the ordinal number is out of range. + */ + std::string nameOf(Ordinal i) const; + + /** + * Returns the ordinal numer associated with the given enumeration constant + * name. Throws a LoggableException if the string does not exist. + */ + Ordinal valueOf(const std::string &name) const; }; /** @@ -350,6 +376,7 @@ public: * @param mgr is the Manager instance to be used for the Node. * @param type holds a reference to the type descriptor holding the type * of the attribute. + * @param name is the name of the Attribute. Should be a valid identifier. * @param defaultValue is the default value of the attribute * @param optional should be set to true if the if the default value should * be used. |