diff options
author | John Firebaugh <john.firebaugh@gmail.com> | 2017-02-09 16:18:57 -0600 |
---|---|---|
committer | Minh Nguyễn <mxn@1ec5.org> | 2017-02-09 14:18:57 -0800 |
commit | a1a639120d7662cb68f0ba5770e4f42cc9415069 (patch) | |
tree | fc92f9c1f0422da0bda7d35a0a6e446626c5b06d /include/mbgl/style/conversion/filter.hpp | |
parent | 272dc3f6a91ee1f0734c6642d610366f4396ec93 (diff) | |
download | qtlocation-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/filter.hpp')
-rw-r--r-- | include/mbgl/style/conversion/filter.hpp | 144 |
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> |