summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/RangeSet.hpp40
-rw-r--r--src/core/common/Number.hpp2
-rw-r--r--src/core/common/Variant.hpp2
-rw-r--r--src/core/common/VariantConverter.cpp80
-rw-r--r--src/core/common/VariantReader.cpp6
-rw-r--r--src/core/common/VariantWriter.cpp1
6 files changed, 114 insertions, 17 deletions
diff --git a/src/core/RangeSet.hpp b/src/core/RangeSet.hpp
index b196dec..fc0070f 100644
--- a/src/core/RangeSet.hpp
+++ b/src/core/RangeSet.hpp
@@ -128,7 +128,7 @@ struct Range {
/**
* Calculates the union of the two ranges -- note that this operation is
- * only valid if the ranges overlapp. Use the RangeSet class if you cannot
+ * only valid if the ranges overlap. Use the RangeSet class if you cannot
* guarantee that.
*/
Range<T> merge(const Range<T> &r) const
@@ -137,6 +137,44 @@ struct Range {
}
/**
+ * Returns true if and only if this Range only accepts a single element.
+ *
+ * @return true if and only if this Range only accepts a single element.
+ */
+ bool isPrimitive() const { return start == end; }
+ /**
+ * Returns true if and only if this Range [a,b] meets the criteria:
+ * * a > lower limit of the type range (a > negative infinity)
+ * * a < b
+ * * b < upper limit of the type range (b < infinity)
+ *
+ * @return true if and only if this Range is compact as defined above.
+ */
+ bool isCompact() const
+ {
+ return start > std::numeric_limits<T>::min() && start < end &&
+ end < std::numeric_limits<T>::max();
+ }
+
+ /**
+ * Returns true if and only if the lower limit of this Range is equal to the
+ * type minimum (negative infinity).
+ *
+ * @return true if and only if this Range is open at the lower end in the
+ * sense defined above.
+ */
+ bool isOpenLow() const { return start == std::numeric_limits<T>::min(); }
+
+ /**
+ * Returns true if and only if the upper limit of this Range is equal to the
+ * type maximum (positive infinity).
+ *
+ * @return true if and only if this Range is open at the upper end in the
+ * sense defined above.
+ */
+ bool isOpenHigh() const { return end == std::numeric_limits<T>::max(); }
+
+ /**
* Returns a range that represents the spans the complete set defined by the
* given type T.
*/
diff --git a/src/core/common/Number.hpp b/src/core/common/Number.hpp
index 23db42e..5417c28 100644
--- a/src/core/common/Number.hpp
+++ b/src/core/common/Number.hpp
@@ -45,7 +45,7 @@ class Logger;
class Number {
private:
/**
- * Reprsents the part of the number: Base value a, nominator n, exponent e.
+ * Represents the part of the number: Base value a, nominator n, exponent e.
*/
enum class Part { A, N, E };
diff --git a/src/core/common/Variant.hpp b/src/core/common/Variant.hpp
index f623b6b..fc4faf5 100644
--- a/src/core/common/Variant.hpp
+++ b/src/core/common/Variant.hpp
@@ -726,7 +726,7 @@ public:
/**
* Returns a reference to the cardinality value. Performs no type
- *conversion.
+ * conversion.
* Throws an exception if the underlying type is not a cardinality.
*
* @return the cardinality value as reference.
diff --git a/src/core/common/VariantConverter.cpp b/src/core/common/VariantConverter.cpp
index 65d2039..03eb2e8 100644
--- a/src/core/common/VariantConverter.cpp
+++ b/src/core/common/VariantConverter.cpp
@@ -111,8 +111,7 @@ bool VariantConverter::toInt(Variant &var, Logger &logger, Mode mode)
case VariantType::STRING:
case VariantType::MAGIC: {
Number n;
- n.parse(var.asString(), logger);
- if (n.isInt()) {
+ if (n.parse(var.asString(), logger) && n.isInt()) {
var = (Variant::intType)n.intValue();
return true;
}
@@ -122,13 +121,25 @@ bool VariantConverter::toInt(Variant &var, Logger &logger, Mode mode)
try {
// JavaScript behaviour when converting arrays to doubles
const Variant::arrayType &a = var.asArray();
- var = (a.size() == 1) ? a[0].toInt() : 0.0;
- return true;
+ if (a.size() == 1) {
+ var = a[0].toInt();
+ return true;
+ }
}
catch (LoggableException ex) {
logger.log(ex);
+ break;
}
}
+ case VariantType::CARDINALITY: {
+ const Variant::cardinalityType &card = var.asCardinality();
+ if (card.getRanges().size() == 1 &&
+ card.getRanges().begin()->isPrimitive()) {
+ var = (Variant::intType)card.getRanges().begin()->start;
+ return true;
+ }
+ break;
+ }
default:
break;
}
@@ -168,9 +179,11 @@ bool VariantConverter::toDouble(Variant &var, Logger &logger, Mode mode)
case VariantType::STRING:
case VariantType::MAGIC: {
Number n;
- n.parse(var.asString(), logger);
- var = (Variant::doubleType)n.doubleValue();
- return true;
+ if (n.parse(var.asString(), logger)) {
+ var = (Variant::doubleType)n.doubleValue();
+ return true;
+ }
+ break;
}
case VariantType::ARRAY: {
try {
@@ -181,8 +194,18 @@ bool VariantConverter::toDouble(Variant &var, Logger &logger, Mode mode)
}
catch (LoggableException ex) {
logger.log(ex);
+ break;
}
}
+ case VariantType::CARDINALITY: {
+ const Variant::cardinalityType &card = var.asCardinality();
+ if (card.getRanges().size() == 1 &&
+ card.getRanges().begin()->isPrimitive()) {
+ var = (Variant::doubleType)card.getRanges().begin()->start;
+ return true;
+ }
+ break;
+ }
default:
break;
}
@@ -233,6 +256,40 @@ bool VariantConverter::toString(Variant &var, Logger &logger, Mode mode)
// Perform lossy conversions
if (mode == Mode::ALL) {
switch (type) {
+ case VariantType::CARDINALITY: {
+ // Print cardinality syntax
+ Variant::cardinalityType card = var.asCardinality();
+ std::stringstream ss;
+ ss << "<cardinality {";
+ bool first = true;
+ for (Variant::rangeType r : card.getRanges()) {
+ if (first) {
+ first = false;
+ } else {
+ ss << ", ";
+ }
+ if (r.isPrimitive()) {
+ ss << std::to_string(r.start);
+ } else if (r.isCompact()) {
+ ss << std::to_string(r.start) << "-"
+ << std::to_string(r.end);
+ } else if (r.isOpenLow()) {
+ if (r.isOpenHigh()) {
+ // if it is open at both ends, we set a Kleene Star
+ ss << "*";
+ } else {
+ ss << "<" << std::to_string(r.end + 1);
+ }
+ } else {
+ // because r is not compact and not open low, it must be
+ // open high.
+ ss << ">" << std::to_string(r.start - 1);
+ }
+ }
+ ss << "}>";
+ var = ss.str().c_str();
+ return true;
+ }
case VariantType::ARRAY:
case VariantType::MAP: {
std::stringstream ss;
@@ -343,7 +400,7 @@ bool VariantConverter::toCardinality(Variant &var, Logger &logger, Mode mode)
"A value smaller 0 can not be converted to a cardinality!");
return false;
}
- card.merge({(unsigned int) value});
+ card.merge({(unsigned int)value});
return true;
}
@@ -373,7 +430,7 @@ bool VariantConverter::toCardinality(Variant &var, Logger &logger, Mode mode)
"cardinality!");
return false;
}
- card.merge({(unsigned int) value});
+ card.merge({(unsigned int)value});
return true;
}
case VariantType::ARRAY: {
@@ -416,14 +473,15 @@ bool VariantConverter::toCardinality(Variant &var, Logger &logger, Mode mode)
std::to_string(end) + " of the Range.");
return false;
}
- card.merge({(unsigned int) start, (unsigned int) end});
+ card.merge({(unsigned int)start, (unsigned int)end});
it++;
}
return true;
}
case VariantType::STRING: {
var.setCardinality(Variant::cardinalityType{});
-// Variant::cardinalityType &card = var.asCardinality();
+ // Variant::cardinalityType &card =
+ // var.asCardinality();
// TODO: Implement!
return false;
}
diff --git a/src/core/common/VariantReader.cpp b/src/core/common/VariantReader.cpp
index 6bc6df8..bbceac5 100644
--- a/src/core/common/VariantReader.cpp
+++ b/src/core/common/VariantReader.cpp
@@ -610,11 +610,11 @@ std::pair<bool, Variant::cardinalityType> VariantReader::parseCardinality(
Variant::cardinalityType{});
}
if (c == '<') {
- card.merge(
- Variant::rangeType{0, (unsigned int)n.intValue()});
+ card.merge(Variant::rangeType{
+ 0, (unsigned int)n.intValue() - 1});
} else {
card.merge(Variant::rangeType::typeRangeFrom(
- (unsigned int)n.intValue()));
+ (unsigned int)n.intValue() + 1));
}
break;
}
diff --git a/src/core/common/VariantWriter.cpp b/src/core/common/VariantWriter.cpp
index fc23359..427ac5d 100644
--- a/src/core/common/VariantWriter.cpp
+++ b/src/core/common/VariantWriter.cpp
@@ -114,6 +114,7 @@ static void writeJsonInternal(const Variant &var, std::ostream &stream,
case VariantType::DOUBLE:
case VariantType::FUNCTION:
case VariantType::OBJECT:
+ case VariantType::CARDINALITY:
stream << var.toString();
return;
case VariantType::STRING: