summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorBenjamin Paassen <bpaassen@techfak.uni-bielefeld.de>2015-02-16 11:57:16 +0100
committerBenjamin Paassen <bpaassen@techfak.uni-bielefeld.de>2015-02-16 11:57:16 +0100
commit9556bd8ac1374daf01700e18e4a025c02b5d3857 (patch)
tree06ae86031eb13892e1606d5ffdad4e267abe77bd /src/core
parent3cca090a650d2e8268977b57aa0dfdb0fb2cae85 (diff)
parent33a70e7dc2624a674094169dbd234959d5433d81 (diff)
Merge branch 'master' of somweyr.de:ousia
Diffstat (limited to 'src/core')
-rw-r--r--src/core/common/Argument.cpp51
-rw-r--r--src/core/common/Argument.hpp11
-rw-r--r--src/core/common/VariantConverter.cpp46
-rw-r--r--src/core/common/VariantReader.cpp24
-rw-r--r--src/core/parser/stack/Stack.cpp5
5 files changed, 91 insertions, 46 deletions
diff --git a/src/core/common/Argument.cpp b/src/core/common/Argument.cpp
index b10fad3..ee129a3 100644
--- a/src/core/common/Argument.cpp
+++ b/src/core/common/Argument.cpp
@@ -54,7 +54,8 @@ Argument Argument::Any(std::string name)
Argument Argument::Any(std::string name, Variant defaultValue)
{
- return Argument{name, &RttiTypes::None, &RttiTypes::None, defaultValue, true};
+ return Argument{name, &RttiTypes::None, &RttiTypes::None, defaultValue,
+ true};
}
Argument Argument::Bool(std::string name)
@@ -95,7 +96,8 @@ Argument Argument::String(std::string name)
Argument Argument::String(std::string name,
const Variant::stringType &defaultValue)
{
- return Argument{name, &RttiTypes::String, Variant::fromString(defaultValue)};
+ return Argument{name, &RttiTypes::String,
+ Variant::fromString(defaultValue)};
}
Argument Argument::Object(std::string name, const Rtti *type)
@@ -158,7 +160,8 @@ Argument Argument::Map(std::string name, const Variant::mapType &defaultValue)
Argument Argument::Map(std::string name, const Rtti *innerType)
{
- return Argument(std::move(name), &RttiTypes::Map, innerType, nullptr, false);
+ return Argument(std::move(name), &RttiTypes::Map, innerType, nullptr,
+ false);
}
Argument Argument::Map(std::string name, const Rtti *innerType,
@@ -276,7 +279,7 @@ bool Arguments::validateArray(Variant::arrayType &arr, Logger &logger) const
}
bool Arguments::validateMap(Variant::mapType &map, Logger &logger,
- bool ignoreUnknown) const
+ bool ignoreUnknown, bool allowNumericIndices) const
{
// Abort if no arguments were explicitly given -- everything is valid
if (!valid) {
@@ -289,28 +292,60 @@ bool Arguments::validateMap(Variant::mapType &map, Logger &logger,
const size_t N = arguments.size();
std::vector<bool> set(N);
bool ok = true;
+ std::unordered_map<std::string, std::string> keyReplacements;
// Iterate over the map entries and search for the corresponding argument
for (auto &e : map) {
// Check whether an argument with the name of the current entry exists
- auto it = names.find(e.first);
+ const std::string &key = e.first;
+ auto it = names.find(key);
+ ssize_t idx = -1;
if (it != names.end()) {
// Fetch the corresponding index in the "arguments" array
- size_t idx = it->second;
+ idx = it->second;
+ } else if (!key.empty() && key[0] == '#' && allowNumericIndices) {
+ // Read the numeric index
+ try {
+ size_t i = stoul(key.substr(1));
+ if (i >= 0 && i < arguments.size()) {
+ idx = i;
+ keyReplacements.emplace(key, arguments[i].getName());
+ } else {
+ ok = false;
+ }
+ }
+ catch (std::exception ex) {
+ logger.error(
+ std::string("Invalid key \"") + key + std::string("\""),
+ e.second);
+ ok = false;
+ }
+ }
+
+ // If the key could be resolved to an index, validate the argument
+ if (idx >= 0) {
set[idx] = arguments[idx].validate(e.second, logger);
ok = ok && set[idx];
} else {
if (ignoreUnknown) {
logger.note(std::string("Ignoring argument \"") + e.first +
- std::string("\""), e.second);
+ std::string("\""),
+ e.second);
} else {
logger.error(std::string("Unknown argument \"") + e.first +
- std::string("\""), e.second);
+ std::string("\""),
+ e.second);
ok = false;
}
}
}
+ // Execute all the key replacements
+ for (const auto &replacement : keyReplacements) {
+ map[replacement.second] = std::move(map[replacement.first]);
+ map.erase(replacement.first);
+ }
+
// Insert all unset arguments
for (size_t a = 0; a < N; a++) {
if (!set[a]) {
diff --git a/src/core/common/Argument.hpp b/src/core/common/Argument.hpp
index 679b4a5..39b3bb6 100644
--- a/src/core/common/Argument.hpp
+++ b/src/core/common/Argument.hpp
@@ -61,13 +61,13 @@ private:
/**
* Type that should be returned by the Variant rttiType function.
*/
- Rtti const* type;
+ Rtti const *type;
/**
* Describes the inner type of the variant -- e.g. the type of the elements
* inside an array. Normally set to RttiTypes::None.
*/
- Rtti const* innerType;
+ Rtti const *innerType;
/**
* Default value. Note that a value of nullptr does not indicate that no
@@ -421,7 +421,7 @@ public:
* @return the default value that was given in the constructor (may be
* nullptr) and nullptr if no default value was given.
*/
- const Variant& getDefaultValue() const;
+ const Variant &getDefaultValue() const;
/**
* Returns true if a default value was set in the constructor.
@@ -502,10 +502,13 @@ public:
* @param ignoreUnknown if set to true, unknown map entries are ignored
* (a note is issued). This behaviour can be usefull if forward
* compatibility must be achieved (such as for XML based formats).
+ * @param allowNumericIndices if set to true, allows numeric indices in the
+ * input map (such as "#1").
* @return true if the operation was successful, false if an error occured.
*/
bool validateMap(Variant::mapType &map, Logger &logger,
- bool ignoreUnknown = false) const;
+ bool ignoreUnknown = false,
+ bool allowNumericIndices = false) const;
};
}
diff --git a/src/core/common/VariantConverter.cpp b/src/core/common/VariantConverter.cpp
index 271fe75..a9ca467 100644
--- a/src/core/common/VariantConverter.cpp
+++ b/src/core/common/VariantConverter.cpp
@@ -81,7 +81,7 @@ bool VariantConverter::toBool(Variant &var, Logger &logger, Mode mode)
}
// No conversion possible, assign default value and log error
- logger.error(msgUnexpectedType(var, VariantType::BOOL));
+ logger.error(msgUnexpectedType(var, VariantType::BOOL), var);
var = false;
return false;
}
@@ -129,7 +129,7 @@ bool VariantConverter::toInt(Variant &var, Logger &logger, Mode mode)
}
}
catch (LoggableException ex) {
- logger.log(ex);
+ logger.log(ex, var);
break;
}
}
@@ -148,7 +148,7 @@ bool VariantConverter::toInt(Variant &var, Logger &logger, Mode mode)
}
// No conversion possible, assign default value and log error
- logger.error(msgUnexpectedType(var, VariantType::INT));
+ logger.error(msgUnexpectedType(var, VariantType::INT), var);
var = 0;
return false;
}
@@ -195,7 +195,7 @@ bool VariantConverter::toDouble(Variant &var, Logger &logger, Mode mode)
return true;
}
catch (LoggableException ex) {
- logger.log(ex);
+ logger.log(ex, var);
break;
}
}
@@ -214,7 +214,7 @@ bool VariantConverter::toDouble(Variant &var, Logger &logger, Mode mode)
}
// No conversion possible, assign default value and log error
- logger.error(msgUnexpectedType(var, VariantType::DOUBLE));
+ logger.error(msgUnexpectedType(var, VariantType::DOUBLE), var);
var = 0.0;
return false;
}
@@ -225,22 +225,22 @@ bool VariantConverter::toString(Variant &var, Logger &logger, Mode mode)
const VariantType type = var.getType();
switch (type) {
case VariantType::NULLPTR:
- logger.warning(msgImplicitConversion(type, VariantType::STRING));
+ logger.warning(msgImplicitConversion(type, VariantType::STRING), var);
var = "null";
return true;
case VariantType::BOOL:
- logger.warning(msgImplicitConversion(type, VariantType::STRING));
+ logger.warning(msgImplicitConversion(type, VariantType::STRING), var);
var = var.asBool() ? "true" : "false";
return true;
case VariantType::INT: {
- logger.warning(msgImplicitConversion(type, VariantType::STRING));
+ logger.warning(msgImplicitConversion(type, VariantType::STRING), var);
std::stringstream ss;
ss << var.asInt();
var = ss.str().c_str();
return true;
}
case VariantType::DOUBLE: {
- logger.warning(msgImplicitConversion(type, VariantType::STRING));
+ logger.warning(msgImplicitConversion(type, VariantType::STRING), var);
std::stringstream ss;
ss << var.asDouble();
var = ss.str().c_str();
@@ -325,7 +325,7 @@ bool VariantConverter::toString(Variant &var, Logger &logger, Mode mode)
}
// No conversion possible, assign default value and log error
- logger.error(msgUnexpectedType(var, VariantType::STRING));
+ logger.error(msgUnexpectedType(var, VariantType::STRING), var);
var = "";
return false;
}
@@ -357,7 +357,7 @@ bool VariantConverter::toArray(Variant &var, const Rtti *innerType,
}
// No conversion possible, assign the default value and log an error
- logger.error(msgUnexpectedType(var, VariantType::ARRAY));
+ logger.error(msgUnexpectedType(var, VariantType::ARRAY), var);
var.setArray(Variant::arrayType{});
return false;
}
@@ -384,7 +384,7 @@ bool VariantConverter::toMap(Variant &var, const Rtti *innerType,
}
// No conversion possible, assign the default value and log an error
- logger.error(msgUnexpectedType(var, VariantType::MAP));
+ logger.error(msgUnexpectedType(var, VariantType::MAP), var);
var.setMap(Variant::mapType{});
return false;
}
@@ -401,7 +401,7 @@ bool VariantConverter::toCardinality(Variant &var, Logger &logger, Mode mode)
Variant::cardinalityType &card = var.asCardinality();
if (value < 0) {
logger.error(
- "A value smaller 0 can not be converted to a cardinality!");
+ "A value smaller 0 can not be converted to a cardinality!", var);
return false;
}
card.merge({(unsigned int)value});
@@ -432,7 +432,7 @@ bool VariantConverter::toCardinality(Variant &var, Logger &logger, Mode mode)
if (value < 0) {
logger.error(
"A value smaller 0 can not be converted to a "
- "cardinality!");
+ "cardinality!", var);
return false;
}
card.merge({(unsigned int)value});
@@ -448,14 +448,14 @@ bool VariantConverter::toCardinality(Variant &var, Logger &logger, Mode mode)
if (!startVar.isInt()) {
logger.error(
"A non-integer can not be interpreted as the start "
- "of a range");
+ "of a range", startVar);
return false;
}
int start = startVar.asInt();
if (start < 0) {
logger.error(
"A value smaller 0 can not be converted to a "
- "cardinality!");
+ "cardinality!", startVar);
return false;
}
it++;
@@ -466,7 +466,7 @@ bool VariantConverter::toCardinality(Variant &var, Logger &logger, Mode mode)
if (!endVar.isInt()) {
logger.error(
"A non-integer can not be interpreted as the end "
- "of a range");
+ "of a range", endVar);
return false;
}
int end = endVar.asInt();
@@ -475,7 +475,7 @@ bool VariantConverter::toCardinality(Variant &var, Logger &logger, Mode mode)
std::string("The supposed start value ") +
std::to_string(start) +
" was bigger than the supposed end value " +
- std::to_string(end) + " of the Range.");
+ std::to_string(end) + " of the Range.", endVar);
return false;
}
card.merge({(unsigned int)start, (unsigned int)end});
@@ -500,7 +500,7 @@ bool VariantConverter::toCardinality(Variant &var, Logger &logger, Mode mode)
}
// No conversion possible, assign the default value and log an error
- logger.error(msgUnexpectedType(var, VariantType::CARDINALITY));
+ logger.error(msgUnexpectedType(var, VariantType::CARDINALITY), var);
var.setCardinality(Variant::cardinalityType{});
return false;
}
@@ -512,7 +512,7 @@ bool VariantConverter::toFunction(Variant &var, Logger &logger)
}
// No conversion possible, assign the default value and log an error
- logger.error(msgUnexpectedType(var, VariantType::FUNCTION));
+ logger.error(msgUnexpectedType(var, VariantType::FUNCTION), var);
var.setFunction(std::shared_ptr<Function>{new FunctionStub()});
return false;
}
@@ -527,7 +527,7 @@ bool VariantConverter::convert(Variant &var, const Rtti *type,
} else if (type == &RttiTypes::Nullptr) {
// Make sure the variant is set to null
if (!var.isNull()) {
- logger.error(msgUnexpectedType(var, VariantType::NULLPTR));
+ logger.error(msgUnexpectedType(var, VariantType::NULLPTR), var);
var.setNull();
return false;
}
@@ -553,7 +553,7 @@ bool VariantConverter::convert(Variant &var, const Rtti *type,
// If none of the above primitive types is requested, we were
// obviously asked for a managed object.
if (!var.isObject()) {
- logger.error(msgUnexpectedType(var, VariantType::OBJECT));
+ logger.error(msgUnexpectedType(var, VariantType::OBJECT), var);
var.setObject(nullptr);
return false;
}
@@ -561,7 +561,7 @@ bool VariantConverter::convert(Variant &var, const Rtti *type,
// Make sure the object type is correct
if (!var.getRtti()->isa(type)) {
logger.error(std::string("Expected object of type ") + type->name +
- " but got object of type " + var.getRtti()->name);
+ " but got object of type " + var.getRtti()->name, var);
var.setObject(nullptr);
return false;
}
diff --git a/src/core/common/VariantReader.cpp b/src/core/common/VariantReader.cpp
index fb93ad0..601d086 100644
--- a/src/core/common/VariantReader.cpp
+++ b/src/core/common/VariantReader.cpp
@@ -848,17 +848,23 @@ std::pair<bool, Variant> VariantReader::parseGenericToken(
std::pair<bool, Variant> VariantReader::parseGenericString(
const std::string &str, Logger &logger, SourceId sourceId, size_t offs)
{
- CharReader reader{str, sourceId, offs};
- LoggerFork loggerFork = logger.fork();
+ // If the given string is empty, just return it as a string (there is no
+ // other type for which something empty would be valid)
+ // TODO: How to integrate this into parseGenericToken?
+ if (!str.empty()) {
+ CharReader reader{str, sourceId, offs};
+ LoggerFork loggerFork = logger.fork();
- // Try to parse a single token
- std::pair<bool, Variant> res =
- parseGenericToken(reader, loggerFork, std::unordered_set<char>{}, true);
+ // Try to parse a single token
+ std::pair<bool, Variant> res = parseGenericToken(
+ reader, loggerFork, std::unordered_set<char>{}, true);
- // If the string was actually consisted of a single token, return that token
- if (reader.atEnd()) {
- loggerFork.commit();
- return res;
+ // If the string was actually consisted of a single token, return that
+ // token
+ if (reader.atEnd()) {
+ loggerFork.commit();
+ return res;
+ }
}
// Otherwise return the given string as a string, set the location of the
diff --git a/src/core/parser/stack/Stack.cpp b/src/core/parser/stack/Stack.cpp
index 905edb4..b98cddb 100644
--- a/src/core/parser/stack/Stack.cpp
+++ b/src/core/parser/stack/Stack.cpp
@@ -361,9 +361,10 @@ void Stack::command(const Variant &name, const Variant::mapType &args)
info.valid = false;
if (validStack) {
// Canonicalize the arguments (if this has not already been done),
- // allow additional arguments
+ // allow additional arguments and numeric indices
Variant::mapType canonicalArgs = args;
- targetState->arguments.validateMap(canonicalArgs, loggerFork, true);
+ targetState->arguments.validateMap(canonicalArgs, loggerFork, true,
+ true);
handler->setLogger(loggerFork);
try {