summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/common/VariantConverter.cpp27
-rw-r--r--src/core/common/VariantConverter.hpp19
-rw-r--r--src/core/common/VariantReader.cpp20
3 files changed, 39 insertions, 27 deletions
diff --git a/src/core/common/VariantConverter.cpp b/src/core/common/VariantConverter.cpp
index 03eb2e8..ff7c5a1 100644
--- a/src/core/common/VariantConverter.cpp
+++ b/src/core/common/VariantConverter.cpp
@@ -22,12 +22,14 @@
#include <string>
#include <sstream>
+#include "CharReader.hpp"
#include "Function.hpp"
#include "Logger.hpp"
#include "Number.hpp"
#include "Rtti.hpp"
#include "Variant.hpp"
#include "VariantConverter.hpp"
+#include "VariantReader.hpp"
#include "VariantWriter.hpp"
namespace ousia {
@@ -389,9 +391,11 @@ bool VariantConverter::toMap(Variant &var, const Rtti &innerType,
bool VariantConverter::toCardinality(Variant &var, Logger &logger, Mode mode)
{
+ if (var.isCardinality()) {
+ return true;
+ }
// Perform safe conversions (all these operations are considered "lossless")
- const VariantType type = var.getType();
- if (type == VariantType::INT) {
+ if (var.isInt()) {
int value = var.asInt();
var.setCardinality(Variant::cardinalityType{});
Variant::cardinalityType &card = var.asCardinality();
@@ -406,6 +410,7 @@ bool VariantConverter::toCardinality(Variant &var, Logger &logger, Mode mode)
// Perform lossy conversions
if (mode == Mode::ALL) {
+ const VariantType type = var.getType();
switch (type) {
case VariantType::NULLPTR:
var.setCardinality(Variant::cardinalityType{});
@@ -465,11 +470,11 @@ bool VariantConverter::toCardinality(Variant &var, Logger &logger, Mode mode)
return false;
}
int end = endVar.asInt();
- if (end <= start) {
+ if (end < start) {
logger.error(
std::string("The supposed start value ") +
std::to_string(start) +
- " was bigger or equal to the supposed end value " +
+ " was bigger than the supposed end value " +
std::to_string(end) + " of the Range.");
return false;
}
@@ -479,11 +484,15 @@ bool VariantConverter::toCardinality(Variant &var, Logger &logger, Mode mode)
return true;
}
case VariantType::STRING: {
- var.setCardinality(Variant::cardinalityType{});
- // Variant::cardinalityType &card =
- // var.asCardinality();
- // TODO: Implement!
- return false;
+ CharReader reader{var.asString().c_str()};
+ auto res = VariantReader::parseCardinality(reader, logger);
+ if (res.first) {
+ var.setCardinality(res.second);
+ return true;
+ } else {
+ var.setCardinality(Variant::cardinalityType{});
+ return false;
+ }
}
default:
break;
diff --git a/src/core/common/VariantConverter.hpp b/src/core/common/VariantConverter.hpp
index 7e317a2..92cc40a 100644
--- a/src/core/common/VariantConverter.hpp
+++ b/src/core/common/VariantConverter.hpp
@@ -84,10 +84,10 @@ public:
* to Mode::SAFE, only integers can be converted to integers. For all other
* types the conversion fails. If "mode" is set to Mode::ALL, booleans are
* converted to 0, 1, nullptr is converted to 0, doubles are truncated,
- * strings are parsed and truncated, arrays with one element are converted
- * to an integer. Conversion fails for objects, functions, maps and arrays
- * with zero or more than one entry. If the conversion fails, 0 is returned
- * as default value.
+ * strings are parsed and truncated, arrays and cardinalities with one
+ * element are converted to an integer. Conversion fails for objects,
+ * functions, maps and arrays with zero or more than one entry. If the
+ * conversion fails, 0 is returned as default value.
*
* @param var is instance of the Variant class that should be converted to
* the requested type.
@@ -105,7 +105,8 @@ public:
* to Mode::SAFE, only integers and doubles can be converted to doubles. For
* all other types the conversion fails. If "mode" is set to Mode::ALL,
* booleans are converted to 0.0, 1.0, nullptr is converted to 0.0, strings
- * are parsed, arrays with one element are converted to a double.
+ * are parsed, arrays and cardinalities with one element are converted to a
+ * double.
* Conversion fails for objects, functions, maps and arrays with zero or
* more than one entry. If the conversion fails, 0.0 is returned as default
* value.
@@ -125,10 +126,10 @@ public:
* Converts the given variant to a string. If the "mode" parameter is set
* to Mode::SAFE, all primitive types can be converted to strings. For
* all other types the conversion fails. If "mode" is set to Mode::ALL,
- * maps and arrays are converted to a JSON representation, objects and
- * functions are converted to an informative string containing their pointer
- * and type. If the conversion fails, an empty string is returned as default
- * value.
+ * maps and arrays are converted to a JSON representation, cardinalities
+ * to their parsing syntax and objects and functions are converted to an
+ * informative string containing their pointer and type. If the conversion
+ * fails, an empty string is returned as default value.
*
* @param var is instance of the Variant class that should be converted to
* the requested type.
diff --git a/src/core/common/VariantReader.cpp b/src/core/common/VariantReader.cpp
index bbceac5..7320973 100644
--- a/src/core/common/VariantReader.cpp
+++ b/src/core/common/VariantReader.cpp
@@ -518,7 +518,7 @@ std::pair<bool, Variant::mapType> VariantReader::parseObject(CharReader &reader,
return std::make_pair(res.first, res.second.asMap());
}
-static const std::unordered_set<char> cardDelims{' ', ',', '}'};
+static const std::unordered_set<char> cardDelims{' ', ',', '}', '-'};
std::pair<bool, Variant::cardinalityType> VariantReader::parseCardinality(
CharReader &reader, Logger &logger)
@@ -533,6 +533,7 @@ std::pair<bool, Variant::cardinalityType> VariantReader::parseCardinality(
Variant::cardinalityType card{};
+ reader.consumePeek();
reader.consumeWhitespace();
// which should in turn be followed by ranges.
@@ -541,14 +542,15 @@ std::pair<bool, Variant::cardinalityType> VariantReader::parseCardinality(
// in case of a numeric character we want to read an integer.
reader.resetPeek();
Number n;
- n.parse(reader, logger, cardDelims);
- if (!n.isInt() || n.intValue() < 0) {
+ if (!n.parse(reader, logger, cardDelims) || !n.isInt() ||
+ n.intValue() < 0) {
return error(reader, logger, "Invalid number for cardinality!",
Variant::cardinalityType{});
}
unsigned int start = (unsigned int)n.intValue();
// if we have that we might either find a } or , making this a
// range or a - leading us to expect another integer.
+ reader.consumePeek();
reader.consumeWhitespace();
if (!reader.peek(c)) {
error(reader, logger, ERR_UNEXPECTED_END,
@@ -560,16 +562,16 @@ std::pair<bool, Variant::cardinalityType> VariantReader::parseCardinality(
reader.resetPeek();
break;
case '-': {
- reader.consumePeek();
// get another integer.
+ reader.consumePeek();
reader.consumeWhitespace();
if (!reader.peek(c)) {
error(reader, logger, ERR_UNEXPECTED_END,
Variant::cardinalityType{});
}
Number n2;
- n2.parse(reader, logger, cardDelims);
- if (!n2.isInt() || n2.intValue() < 0) {
+ if (!n2.parse(reader, logger, cardDelims) || !n2.isInt() ||
+ n2.intValue() < 0) {
return error(reader, logger,
"Invalid number for cardinality!",
Variant::cardinalityType{});
@@ -583,9 +585,6 @@ std::pair<bool, Variant::cardinalityType> VariantReader::parseCardinality(
return unexpected(reader, logger, "}, , or -", c,
Variant::cardinalityType{});
}
- if (c == '{' || c == ',') {
- reader.resetPeek();
- }
} else {
switch (c) {
case '*':
@@ -596,6 +595,7 @@ std::pair<bool, Variant::cardinalityType> VariantReader::parseCardinality(
case '<':
case '>': {
// in case of an open range we expect a number.
+ reader.consumePeek();
reader.consumeWhitespace();
Number n;
if (!n.parse(reader, logger, cardDelims)) {
@@ -625,6 +625,7 @@ std::pair<bool, Variant::cardinalityType> VariantReader::parseCardinality(
}
}
// after we have parsed a range, read all whitespaces.
+ reader.consumePeek();
reader.consumeWhitespace();
// ... and check if we are at the end.
if (!reader.read(c)) {
@@ -635,6 +636,7 @@ std::pair<bool, Variant::cardinalityType> VariantReader::parseCardinality(
case '}':
return std::make_pair(true, card);
case ',':
+ reader.consumePeek();
reader.consumeWhitespace();
break;