summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndreas Stöckel <astoecke@techfak.uni-bielefeld.de>2014-12-24 01:27:54 +0100
committerAndreas Stöckel <andreas@somweyr.de>2014-12-24 01:27:54 +0100
commitdfc44b33d8a58d3caa3ea04acf0ce009c811b4bc (patch)
tree62ab9bbb14b396e7c463851391c5458c26fdf2dd /src
parentbc5eb58c47855e1a20f2709fa52a0f9a08603d51 (diff)
finished EnumType class, added unit tests
Diffstat (limited to 'src')
-rw-r--r--src/core/model/Typesystem.cpp47
-rw-r--r--src/core/model/Typesystem.hpp43
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.