summaryrefslogtreecommitdiff
path: root/include/mbgl/style/conversion
diff options
context:
space:
mode:
authorJohn Firebaugh <john.firebaugh@gmail.com>2017-02-09 16:18:57 -0600
committerMinh Nguyễn <mxn@1ec5.org>2017-02-09 14:18:57 -0800
commita1a639120d7662cb68f0ba5770e4f42cc9415069 (patch)
treefc92f9c1f0422da0bda7d35a0a6e446626c5b06d /include/mbgl/style/conversion
parent272dc3f6a91ee1f0734c6642d610366f4396ec93 (diff)
downloadqtlocation-mapboxgl-a1a639120d7662cb68f0ba5770e4f42cc9415069.tar.gz
[core] Introduce dedicated filter types for $type and $id special cases (#7971)
* [core] Introduce dedicated filter types for $type and $id special cases * [ios, macos] Special-case $id, $type in predicates Also support $id ≟ nil.
Diffstat (limited to 'include/mbgl/style/conversion')
-rw-r--r--include/mbgl/style/conversion/filter.hpp144
1 files changed, 118 insertions, 26 deletions
diff --git a/include/mbgl/style/conversion/filter.hpp b/include/mbgl/style/conversion/filter.hpp
index 3ab91e5bbc..2c4eeb4ac7 100644
--- a/include/mbgl/style/conversion/filter.hpp
+++ b/include/mbgl/style/conversion/filter.hpp
@@ -27,9 +27,9 @@ public:
}
if (*op == "==") {
- return convertBinaryFilter<EqualsFilter>(value);
+ return convertEqualityFilter<EqualsFilter, TypeEqualsFilter, IdentifierEqualsFilter>(value);
} else if (*op == "!=") {
- return convertBinaryFilter<NotEqualsFilter>(value);
+ return convertEqualityFilter<NotEqualsFilter, TypeNotEqualsFilter, IdentifierNotEqualsFilter>(value);
} else if (*op == ">") {
return convertBinaryFilter<GreaterThanFilter>(value);
} else if (*op == ">=") {
@@ -39,9 +39,9 @@ public:
} else if (*op == "<=") {
return convertBinaryFilter<LessThanEqualsFilter>(value);
} else if (*op == "in") {
- return convertSetFilter<InFilter>(value);
+ return convertSetFilter<InFilter, TypeInFilter, IdentifierInFilter>(value);
} else if (*op == "!in") {
- return convertSetFilter<NotInFilter>(value);
+ return convertSetFilter<NotInFilter, TypeNotInFilter, IdentifierNotInFilter>(value);
} else if (*op == "all") {
return convertCompoundFilter<AllFilter>(value);
} else if (*op == "any") {
@@ -49,32 +49,57 @@ public:
} else if (*op == "none") {
return convertCompoundFilter<NoneFilter>(value);
} else if (*op == "has") {
- return convertUnaryFilter<HasFilter>(value);
+ return convertUnaryFilter<HasFilter, HasIdentifierFilter>(value);
} else if (*op == "!has") {
- return convertUnaryFilter<NotHasFilter>(value);
+ return convertUnaryFilter<NotHasFilter, NotHasIdentifierFilter>(value);
}
return Error { "filter operator must be one of \"==\", \"!=\", \">\", \">=\", \"<\", \"<=\", \"in\", \"!in\", \"all\", \"any\", \"none\", \"has\", or \"!has\"" };
}
private:
- Result<Value> normalizeValue(const std::string& key, const optional<Value>& value) const {
+ Result<Value> normalizeValue(const optional<Value>& value) const {
if (!value) {
return Error { "filter expression value must be a boolean, number, or string" };
- } else if (key != "$type") {
+ } else {
return *value;
- } else if (*value == std::string("Point")) {
- return Value(uint64_t(FeatureType::Point));
- } else if (*value == std::string("LineString")) {
- return Value(uint64_t(FeatureType::LineString));
- } else if (*value == std::string("Polygon")) {
- return Value(uint64_t(FeatureType::Polygon));
+ }
+ }
+
+ template <class V>
+ Result<FeatureType> toFeatureType(const V& value) const {
+ optional<std::string> type = toString(value);
+ if (!type) {
+ return Error { "value for $type filter must be a string" };
+ } else if (*type == "Point") {
+ return FeatureType::Point;
+ } else if (*type == "LineString") {
+ return FeatureType::LineString;
+ } else if (*type == "Polygon") {
+ return FeatureType::Polygon;
} else {
return Error { "value for $type filter must be Point, LineString, or Polygon" };
}
}
- template <class FilterType, class V>
+ template <class V>
+ Result<FeatureIdentifier> toFeatureIdentifier(const V& value) const {
+ optional<Value> identifier = toValue(value);
+ if (!identifier) {
+ return Error { "filter expression value must be a boolean, number, or string" };
+ } else {
+ return (*identifier).match(
+ [] (uint64_t t) -> Result<FeatureIdentifier> { return t; },
+ [] ( int64_t t) -> Result<FeatureIdentifier> { return t; },
+ [] ( double t) -> Result<FeatureIdentifier> { return t; },
+ [] (const std::string& t) -> Result<FeatureIdentifier> { return t; },
+ [] (const auto&) -> Result<FeatureIdentifier> {
+ return Error { "filter expression value must be a boolean, number, or string" };
+ });
+ }
+ }
+
+ template <class FilterType, class IdentifierFilterType, class V>
Result<Filter> convertUnaryFilter(const V& value) const {
if (arrayLength(value) < 2) {
return Error { "filter expression must have 2 elements" };
@@ -85,7 +110,48 @@ private:
return Error { "filter expression key must be a string" };
}
- return FilterType { *key };
+ if (*key == "$id") {
+ return IdentifierFilterType {};
+ } else {
+ return FilterType { *key };
+ }
+ }
+
+ template <class FilterType, class TypeFilterType, class IdentifierFilterType, class V>
+ Result<Filter> convertEqualityFilter(const V& value) const {
+ if (arrayLength(value) < 3) {
+ return Error { "filter expression must have 3 elements" };
+ }
+
+ optional<std::string> key = toString(arrayMember(value, 1));
+ if (!key) {
+ return Error { "filter expression key must be a string" };
+ }
+
+ if (*key == "$type") {
+ Result<FeatureType> filterValue = toFeatureType(arrayMember(value, 2));
+ if (!filterValue) {
+ return filterValue.error();
+ }
+
+ return TypeFilterType { *filterValue };
+
+ } else if (*key == "$id") {
+ Result<FeatureIdentifier> filterValue = toFeatureIdentifier(arrayMember(value, 2));
+ if (!filterValue) {
+ return filterValue.error();
+ }
+
+ return IdentifierFilterType { *filterValue };
+
+ } else {
+ Result<Value> filterValue = normalizeValue(toValue(arrayMember(value, 2)));
+ if (!filterValue) {
+ return filterValue.error();
+ }
+
+ return FilterType { *key, *filterValue };
+ }
}
template <class FilterType, class V>
@@ -99,7 +165,7 @@ private:
return Error { "filter expression key must be a string" };
}
- Result<Value> filterValue = normalizeValue(*key, toValue(arrayMember(value, 2)));
+ Result<Value> filterValue = normalizeValue(toValue(arrayMember(value, 2)));
if (!filterValue) {
return filterValue.error();
}
@@ -107,7 +173,7 @@ private:
return FilterType { *key, *filterValue };
}
- template <class FilterType, class V>
+ template <class FilterType, class TypeFilterType, class IdentifierFilterType, class V>
Result<Filter> convertSetFilter(const V& value) const {
if (arrayLength(value) < 2) {
return Error { "filter expression must at least 2 elements" };
@@ -118,16 +184,42 @@ private:
return Error { "filter expression key must be a string" };
}
- std::vector<Value> values;
- for (std::size_t i = 2; i < arrayLength(value); ++i) {
- Result<Value> filterValue = normalizeValue(*key, toValue(arrayMember(value, i)));
- if (!filterValue) {
- return filterValue.error();
+ if (*key == "$type") {
+ std::vector<FeatureType> values;
+ for (std::size_t i = 2; i < arrayLength(value); ++i) {
+ Result<FeatureType> filterValue = toFeatureType(arrayMember(value, i));
+ if (!filterValue) {
+ return filterValue.error();
+ }
+ values.push_back(*filterValue);
}
- values.push_back(*filterValue);
- }
- return FilterType { *key, std::move(values) };
+ return TypeFilterType { std::move(values) };
+
+ } else if (*key == "$id") {
+ std::vector<FeatureIdentifier> values;
+ for (std::size_t i = 2; i < arrayLength(value); ++i) {
+ Result<FeatureIdentifier> filterValue = toFeatureIdentifier(arrayMember(value, i));
+ if (!filterValue) {
+ return filterValue.error();
+ }
+ values.push_back(*filterValue);
+ }
+
+ return IdentifierFilterType { std::move(values) };
+
+ } else {
+ std::vector<Value> values;
+ for (std::size_t i = 2; i < arrayLength(value); ++i) {
+ Result<Value> filterValue = normalizeValue(toValue(arrayMember(value, i)));
+ if (!filterValue) {
+ return filterValue.error();
+ }
+ values.push_back(*filterValue);
+ }
+
+ return FilterType { *key, std::move(values) };
+ }
}
template <class FilterType, class V>