diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/core/RangeSet.hpp | 40 | ||||
-rw-r--r-- | src/core/common/Number.hpp | 2 | ||||
-rw-r--r-- | src/core/common/Variant.hpp | 2 | ||||
-rw-r--r-- | src/core/common/VariantConverter.cpp | 80 | ||||
-rw-r--r-- | src/core/common/VariantReader.cpp | 6 | ||||
-rw-r--r-- | src/core/common/VariantWriter.cpp | 1 |
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: |