summaryrefslogtreecommitdiff
path: root/src/mbgl/style
diff options
context:
space:
mode:
authorFabian Guerra <fabian.guerra@mapbox.com>2018-05-17 11:47:31 -0400
committerFabian Guerra <fabian.guerra@mapbox.com>2018-05-17 11:47:31 -0400
commit30376f3ce1d17522d9e64901b1bbc52906ee5267 (patch)
tree1f00d04a223a76a86e16ddebc77f56d2cff88b5b /src/mbgl/style
parent7d1e52a3255d4eecdcd37e4fb600eb76fa9333f8 (diff)
parent146057adf90e85e3edc80446f02d20e5f6cab378 (diff)
downloadqtlocation-mapboxgl-30376f3ce1d17522d9e64901b1bbc52906ee5267.tar.gz
Merge branch 'release-boba' into masterupstream/fabian-merge-release-4.0.1-master
# Conflicts: # mapbox-gl-js # platform/android/CHANGELOG.md # platform/android/MapboxGLAndroidSDK/gradle.properties # platform/android/gradle/dependencies.gradle # platform/darwin/src/MGLVectorTileSource.mm # platform/darwin/src/MGLVectorTileSource_Private.h # platform/ios/CHANGELOG.md # src/mbgl/style/expression/compound_expression.cpp
Diffstat (limited to 'src/mbgl/style')
-rw-r--r--src/mbgl/style/conversion/filter.cpp343
-rw-r--r--src/mbgl/style/conversion/stringify.hpp159
-rw-r--r--src/mbgl/style/expression/compound_expression.cpp325
-rw-r--r--src/mbgl/style/expression/literal.cpp8
-rw-r--r--src/mbgl/style/filter.cpp12
-rw-r--r--src/mbgl/style/filter_evaluator.cpp225
6 files changed, 433 insertions, 639 deletions
diff --git a/src/mbgl/style/conversion/filter.cpp b/src/mbgl/style/conversion/filter.cpp
index 3c941945fd..386d85e921 100644
--- a/src/mbgl/style/conversion/filter.cpp
+++ b/src/mbgl/style/conversion/filter.cpp
@@ -1,17 +1,39 @@
#include <mbgl/style/conversion/filter.hpp>
+#include <mbgl/style/expression/literal.hpp>
#include <mbgl/util/geometry.hpp>
#include <mbgl/style/expression/expression.hpp>
#include <mbgl/style/expression/type.hpp>
-#include <mbgl/style/expression/parsing_context.hpp>
+#include <mbgl/style/expression/compound_expression.hpp>
+#include <mbgl/style/expression/boolean_operator.hpp>
namespace mbgl {
namespace style {
namespace conversion {
-using GeometryValue = mapbox::geometry::value;
+using namespace mbgl::style::expression;
+
+static bool isExpression(const Convertible& filter);
+std::unique_ptr<Expression> convertLegacyFilter(const Convertible& values, Error& error);
+
+optional<Filter> Converter<Filter>::operator()(const Convertible& value, Error& error) const {
+ if (isExpression(value)) {
+ ParsingContext parsingContext(type::Boolean);
+ ParseResult parseResult = parsingContext.parseExpression(value);
+ if (!parseResult) {
+ error = { parsingContext.getCombinedErrors() };
+ return {};
+ } else {
+ return { Filter(std::move(parseResult)) };
+ }
+ } else {
+ std::unique_ptr<Expression> expression = convertLegacyFilter(value, error);
+ if (!expression) return {};
+ return Filter(optional<std::unique_ptr<Expression>>(std::move(expression)));
+ }
+}
// This is a port from https://github.com/mapbox/mapbox-gl-js/blob/master/src/style-spec/feature_filter/index.js
-static bool isExpressionFilter(const Convertible& filter) {
+bool isExpression(const Convertible& filter) {
if (!isArray(filter) || arrayLength(filter) == 0) {
return false;
}
@@ -20,7 +42,7 @@ static bool isExpressionFilter(const Convertible& filter) {
if (!op) {
return false;
-
+
} else if (*op == "has") {
if (arrayLength(filter) < 2) return false;
optional<std::string> operand = toString(arrayMember(filter, 1));
@@ -35,7 +57,7 @@ static bool isExpressionFilter(const Convertible& filter) {
} else if (*op == "any" || *op == "all") {
for (std::size_t i = 1; i < arrayLength(filter); i++) {
Convertible f = arrayMember(filter, i);
- if (!isExpressionFilter(f) && !toBool(f)) {
+ if (!isExpression(f) && !toBool(f)) {
return false;
}
}
@@ -46,257 +68,136 @@ static bool isExpressionFilter(const Convertible& filter) {
}
}
-static optional<GeometryValue> normalizeValue(const optional<GeometryValue>& value, Error& error) {
- if (!value) {
- error = { "filter expression value must be a boolean, number, or string" };
- return {};
- } else {
- return *value;
- }
-}
+std::unique_ptr<Expression> createExpression(std::string op, std::vector<std::unique_ptr<Expression>> args, Error& error) {
+ if (op == "any") {
+ return std::make_unique<Any>(std::move(args));
+
+ } else if (op == "all") {
+ return std::make_unique<All>(std::move(args));
-static optional<FeatureType> toFeatureType(const Convertible& value, Error& error) {
- optional<std::string> type = toString(value);
- if (!type) {
- error = { "value for $type filter must be a string" };
- return {};
- } else if (*type == "Point") {
- return FeatureType::Point;
- } else if (*type == "LineString") {
- return FeatureType::LineString;
- } else if (*type == "Polygon") {
- return FeatureType::Polygon;
} else {
- error = { "value for $type filter must be Point, LineString, or Polygon" };
- return {};
+ ParsingContext parsingContext(type::Boolean);
+ ParseResult parseResult = createCompoundExpression(op, std::move(args), parsingContext);
+ if (!parseResult) {
+ error = { parsingContext.getCombinedErrors() };
+ return {};
+ } else {
+ return std::move(*parseResult);
+ }
}
}
-static optional<FeatureIdentifier> toFeatureIdentifier(const Convertible& value, Error& error) {
- optional<GeometryValue> identifier = toValue(value);
- if (!identifier) {
- error = { "filter expression value must be a boolean, number, or string" };
- return {};
- } else {
- return (*identifier).match(
- [] (uint64_t t) -> optional<FeatureIdentifier> { return { t }; },
- [] ( int64_t t) -> optional<FeatureIdentifier> { return { t }; },
- [] ( double t) -> optional<FeatureIdentifier> { return { t }; },
- [] (const std::string& t) -> optional<FeatureIdentifier> { return { t }; },
- [&] (const auto&) -> optional<FeatureIdentifier> {
- error = { "filter expression value must be a boolean, number, or string" };
- return {};
- });
- }
+std::unique_ptr<Expression> createExpression(std::string op, std::unique_ptr<Expression> expression, Error& error) {
+ std::vector<std::unique_ptr<Expression>> args;
+ args.push_back(std::move(expression));
+ return createExpression(op, std::move(args), error);
}
-template <class FilterType, class IdentifierFilterType>
-optional<Filter> convertUnaryFilter(const Convertible& value, Error& error) {
- if (arrayLength(value) < 2) {
- error = { "filter expression must have 2 elements" };
- return {};
- }
-
- optional<std::string> key = toString(arrayMember(value, 1));
- if (!key) {
- error = { "filter expression key must be a string" };
- return {};
- }
-
- if (*key == "$id") {
- return { IdentifierFilterType {} };
+std::unique_ptr<Expression> convertLiteral(const Convertible& convertible, Error& error) {
+ ParsingContext parsingContext;
+ ParseResult parseResult = Literal::parse(convertible, parsingContext);
+ if (parseResult) {
+ return std::move(*parseResult);
} else {
- return { FilterType { *key } };
+ error = { parsingContext.getCombinedErrors() };
+ return {};
}
}
-template <class FilterType, class TypeFilterType, class IdentifierFilterType>
-optional<Filter> convertEqualityFilter(const Convertible& value, Error& error) {
- if (arrayLength(value) < 3) {
- error = { "filter expression must have 3 elements" };
- return {};
+std::vector<std::unique_ptr<Expression>> convertLiteralArray(const Convertible &input, Error& error, std::size_t startIndex = 0) {
+ std::vector<std::unique_ptr<Expression>> output;
+ for (std::size_t i = startIndex; i < arrayLength(input); i++) {
+ output.push_back(convertLiteral(arrayMember(input, i), error));
}
+ return output;
+}
- optional<std::string> key = toString(arrayMember(value, 1));
- if (!key) {
- error = { "filter expression key must be a string" };
+std::unique_ptr<Expression> convertLegacyComparisonFilter(const Convertible& values, Error& error, optional<std::string> opOverride = {}) {
+ optional<std::string> op = opOverride ? opOverride : toString(arrayMember(values, 0));
+ optional<std::string> property = toString(arrayMember(values, 1));
+
+ if (!property) {
+ error = { "filter property must be a string" };
return {};
- }
-
- if (*key == "$type") {
- optional<FeatureType> filterValue = toFeatureType(arrayMember(value, 2), error);
- if (!filterValue) {
- return {};
- }
-
- return { TypeFilterType { *filterValue } };
-
- } else if (*key == "$id") {
- optional<FeatureIdentifier> filterValue = toFeatureIdentifier(arrayMember(value, 2), error);
- if (!filterValue) {
- return {};
- }
-
- return { IdentifierFilterType { *filterValue } };
-
+ } else if (*property == "$type") {
+ return createExpression("filter-type-" + *op, convertLiteralArray(values, error, 2), error);
+ } else if (*property == "$id") {
+ return createExpression("filter-id-" + *op, convertLiteralArray(values, error, 2), error);
} else {
- optional<GeometryValue> filterValue = normalizeValue(toValue(arrayMember(value, 2)), error);
- if (!filterValue) {
- return {};
- }
-
- return { FilterType { *key, *filterValue } };
+ return createExpression("filter-" + *op, convertLiteralArray(values, error, 1), error);
}
}
-
-template <class FilterType>
-optional<Filter> convertBinaryFilter(const Convertible& value, Error& error) {
- if (arrayLength(value) < 3) {
- error = { "filter expression must have 3 elements" };
- return {};
- }
-
- optional<std::string> key = toString(arrayMember(value, 1));
- if (!key) {
- error = { "filter expression key must be a string" };
- return {};
- }
-
- optional<GeometryValue> filterValue = normalizeValue(toValue(arrayMember(value, 2)), error);
- if (!filterValue) {
+
+std::unique_ptr<Expression> convertLegacyHasFilter(const Convertible& values, Error& error) {
+ optional<std::string> property = toString(arrayMember(values, 1));
+
+ if (!property) {
+ error = { "filter property must be a string" };
return {};
+ } else if (*property == "$type") {
+ return std::make_unique<Literal>(true);
+ } else if (*property == "$id") {
+ return createExpression("filter-has-id", std::vector<std::unique_ptr<Expression>>(), error);
+ } else {
+ return createExpression("filter-has", std::make_unique<Literal>(*property), error);
}
-
- return { FilterType { *key, *filterValue } };
}
-template <class FilterType, class TypeFilterType, class IdentifierFilterType>
-optional<Filter> convertSetFilter(const Convertible& value, Error& error) {
- if (arrayLength(value) < 2) {
- error = { "filter expression must at least 2 elements" };
- return {};
- }
-
- optional<std::string> key = toString(arrayMember(value, 1));
- if (!key) {
- error = { "filter expression key must be a string" };
- return {};
- }
-
- if (*key == "$type") {
- std::vector<FeatureType> values;
- for (std::size_t i = 2; i < arrayLength(value); ++i) {
- optional<FeatureType> filterValue = toFeatureType(arrayMember(value, i), error);
- if (!filterValue) {
- return {};
- }
- values.push_back(*filterValue);
- }
-
- return { TypeFilterType { std::move(values) } };
-
- } else if (*key == "$id") {
- std::vector<FeatureIdentifier> values;
- for (std::size_t i = 2; i < arrayLength(value); ++i) {
- optional<FeatureIdentifier> filterValue = toFeatureIdentifier(arrayMember(value, i), error);
- if (!filterValue) {
- return {};
- }
- values.push_back(*filterValue);
- }
-
- return { IdentifierFilterType { std::move(values) } };
-
+std::unique_ptr<Expression> convertLegacyInFilter(const Convertible& values, Error& error) {
+ optional<std::string> property = toString(arrayMember(values, 1));
+
+ if (!property) {
+ error = { "filter property must be a string" };
+ return {};
+ } else if (arrayLength(values) == 0) {
+ return std::make_unique<Literal>(false);
+ } else if (*property == "$type") {
+ return createExpression("filter-type-in", convertLiteralArray(values, error, 2), error);
+ } else if (*property == "$id") {
+ return createExpression("filter-id-in", convertLiteralArray(values, error, 2), error);
} else {
- std::vector<GeometryValue> values;
- for (std::size_t i = 2; i < arrayLength(value); ++i) {
- optional<GeometryValue> filterValue = normalizeValue(toValue(arrayMember(value, i)), error);
- if (!filterValue) {
- return {};
- }
- values.push_back(*filterValue);
- }
-
- return { FilterType { *key, std::move(values) } };
+ return createExpression("filter-in", convertLiteralArray(values, error, 1), error);
}
}
-template <class FilterType>
-optional<Filter> convertCompoundFilter(const Convertible& value, Error& error) {
- std::vector<Filter> filters;
- for (std::size_t i = 1; i < arrayLength(value); ++i) {
- optional<Filter> element = convert<Filter>(arrayMember(value, i), error);
- if (!element) {
- return {};
- }
- filters.push_back(*element);
+std::vector<std::unique_ptr<Expression>> convertLegacyFilterArray(const Convertible &input, Error& error, std::size_t startIndex = 0) {
+ std::vector<std::unique_ptr<Expression>> output;
+ for (std::size_t i = startIndex; i < arrayLength(input); i++) {
+ output.push_back(convertLegacyFilter(arrayMember(input, i), error));
}
-
- return { FilterType { std::move(filters) } };
+ return output;
}
-optional<Filter> convertExpressionFilter(const Convertible& value, Error& error) {
- expression::ParsingContext ctx(expression::type::Boolean);
- expression::ParseResult expression = ctx.parseExpression(value);
- if (!expression) {
- error = { ctx.getCombinedErrors() };
- return {};
- }
-
- return { ExpressionFilter { std::move(*expression) } };
-}
-
-optional<Filter> Converter<Filter>::operator()(const Convertible& value, Error& error) const {
- if (isExpressionFilter(value)) {
- return convertExpressionFilter(value, error);
+std::unique_ptr<Expression> convertLegacyFilter(const Convertible& values, Error& error) {
+ if (isUndefined(values)) {
+ return std::make_unique<Literal>(true);
}
- if (!isArray(value)) {
- error = { "filter expression must be an array" };
- return {};
- }
-
- if (arrayLength(value) < 1) {
- error = { "filter expression must have at least 1 element" };
- return {};
- }
+ optional<std::string> op = toString(arrayMember(values, 0));
- optional<std::string> op = toString(arrayMember(value, 0));
if (!op) {
error = { "filter operator must be a string" };
return {};
+ } else if (arrayLength(values) <= 1) {
+ return std::make_unique<Literal>(*op != "any");
+ } else {
+ return (
+ *op == "==" ||
+ *op == "<" ||
+ *op == ">" ||
+ *op == "<=" ||
+ *op == ">=" ? convertLegacyComparisonFilter(values, error) :
+ *op == "!=" ? createExpression("!", convertLegacyComparisonFilter(values, error, {"=="}), error) :
+ *op == "any" ? createExpression("any", convertLegacyFilterArray(values, error, 1), error) :
+ *op == "all" ? createExpression("all", convertLegacyFilterArray(values, error, 1), error) :
+ *op == "none" ? createExpression("!", createExpression("any", convertLegacyFilterArray(values, error, 1), error), error) :
+ *op == "in" ? convertLegacyInFilter(values, error) :
+ *op == "!in" ? createExpression("!", convertLegacyInFilter(values, error), error) :
+ *op == "has" ? convertLegacyHasFilter(values, error) :
+ *op == "!has" ? createExpression("!", convertLegacyHasFilter(values, error), error) :
+ std::make_unique<Literal>(true)
+ );
}
-
- if (*op == "==") {
- return convertEqualityFilter<EqualsFilter, TypeEqualsFilter, IdentifierEqualsFilter>(value, error);
- } else if (*op == "!=") {
- return convertEqualityFilter<NotEqualsFilter, TypeNotEqualsFilter, IdentifierNotEqualsFilter>(value, error);
- } else if (*op == ">") {
- return convertBinaryFilter<GreaterThanFilter>(value, error);
- } else if (*op == ">=") {
- return convertBinaryFilter<GreaterThanEqualsFilter>(value, error);
- } else if (*op == "<") {
- return convertBinaryFilter<LessThanFilter>(value, error);
- } else if (*op == "<=") {
- return convertBinaryFilter<LessThanEqualsFilter>(value, error);
- } else if (*op == "in") {
- return convertSetFilter<InFilter, TypeInFilter, IdentifierInFilter>(value, error);
- } else if (*op == "!in") {
- return convertSetFilter<NotInFilter, TypeNotInFilter, IdentifierNotInFilter>(value, error);
- } else if (*op == "all") {
- return convertCompoundFilter<AllFilter>(value, error);
- } else if (*op == "any") {
- return convertCompoundFilter<AnyFilter>(value, error);
- } else if (*op == "none") {
- return convertCompoundFilter<NoneFilter>(value, error);
- } else if (*op == "has") {
- return convertUnaryFilter<HasFilter, HasIdentifierFilter>(value, error);
- } else if (*op == "!has") {
- return convertUnaryFilter<NotHasFilter, NotHasIdentifierFilter>(value, error);
- }
-
- error = { R"(filter operator must be one of "==", "!=", ">", ">=", "<", "<=", "in", "!in", "all", "any", "none", "has", or "!has")" };
- return {};
}
} // namespace conversion
diff --git a/src/mbgl/style/conversion/stringify.hpp b/src/mbgl/style/conversion/stringify.hpp
index 7b7727d7c4..74171763a0 100644
--- a/src/mbgl/style/conversion/stringify.hpp
+++ b/src/mbgl/style/conversion/stringify.hpp
@@ -126,162 +126,9 @@ void stringify(Writer& writer, const FeatureIdentifier& id) {
}
template <class Writer>
-class StringifyFilter {
-public:
- Writer& writer;
-
- void operator()(const NullFilter&) {
- writer.Null();
- }
-
- void operator()(const EqualsFilter& f) {
- stringifyBinaryFilter(f, "==");
- }
-
- void operator()(const NotEqualsFilter& f) {
- stringifyBinaryFilter(f, "!=");
- }
-
- void operator()(const LessThanFilter& f) {
- stringifyBinaryFilter(f, "<");
- }
-
- void operator()(const LessThanEqualsFilter& f) {
- stringifyBinaryFilter(f, "<=");
- }
-
- void operator()(const GreaterThanFilter& f) {
- stringifyBinaryFilter(f, ">");
- }
-
- void operator()(const GreaterThanEqualsFilter& f) {
- stringifyBinaryFilter(f, ">=");
- }
-
- void operator()(const InFilter& f) {
- stringifySetFilter(f, "in");
- }
-
- void operator()(const NotInFilter& f) {
- stringifySetFilter(f, "!in");
- }
-
- void operator()(const AllFilter& f) {
- stringifyCompoundFilter(f, "all");
- }
-
- void operator()(const AnyFilter& f) {
- stringifyCompoundFilter(f, "any");
- }
-
- void operator()(const NoneFilter& f) {
- stringifyCompoundFilter(f, "none");
- }
-
- void operator()(const HasFilter& f) {
- stringifyUnaryFilter("has", f.key);
- }
-
- void operator()(const NotHasFilter& f) {
- stringifyUnaryFilter("!has", f.key);
- }
-
- void operator()(const TypeEqualsFilter& f) {
- stringifyBinaryFilter(f, "==", "$type");
- }
-
- void operator()(const TypeNotEqualsFilter& f) {
- stringifyBinaryFilter(f, "!=", "$type");
- }
-
- void operator()(const TypeInFilter& f) {
- stringifySetFilter(f, "in", "$type");
- }
-
- void operator()(const TypeNotInFilter& f) {
- stringifySetFilter(f, "!in", "$type");
- }
-
- void operator()(const IdentifierEqualsFilter& f) {
- stringifyBinaryFilter(f, "==", "$id");
- }
-
- void operator()(const IdentifierNotEqualsFilter& f) {
- stringifyBinaryFilter(f, "!=", "$id");
- }
-
- void operator()(const IdentifierInFilter& f) {
- stringifySetFilter(f, "in", "$id");
- }
-
- void operator()(const IdentifierNotInFilter& f) {
- stringifySetFilter(f, "!in", "$id");
- }
-
- void operator()(const HasIdentifierFilter&) {
- stringifyUnaryFilter("has", "$id");
- }
-
- void operator()(const NotHasIdentifierFilter&) {
- stringifyUnaryFilter("!has", "$id");
- }
-
- void operator()(const ExpressionFilter& filter) {
- stringify(writer, filter.expression->serialize());
- }
-
-private:
- template <class F>
- void stringifyBinaryFilter(const F& f, const char * op) {
- stringifyBinaryFilter(f, op, f.key);
- }
-
- template <class F>
- void stringifyBinaryFilter(const F& f, const char * op, const std::string& key) {
- writer.StartArray();
- writer.String(op);
- writer.String(key);
- stringify(writer, f.value);
- writer.EndArray();
- }
-
- template <class F>
- void stringifySetFilter(const F& f, const char * op) {
- stringifySetFilter(f, op, f.key);
- }
-
- template <class F>
- void stringifySetFilter(const F& f, const char * op, const std::string& key) {
- writer.StartArray();
- writer.String(op);
- writer.String(key);
- for (const auto& value : f.values) {
- stringify(writer, value);
- }
- writer.EndArray();
- }
-
- template <class F>
- void stringifyCompoundFilter(const F& f, const char * op) {
- writer.StartArray();
- writer.String(op);
- for (const auto& filter : f.filters) {
- Filter::visit(filter, *this);
- }
- writer.EndArray();
- }
-
- void stringifyUnaryFilter(const char * op, const std::string& key) {
- writer.StartArray();
- writer.String(op);
- writer.String(key);
- writer.EndArray();
- }
-};
-
-template <class Writer>
-void stringify(Writer& writer, const Filter& f) {
- Filter::visit(f, StringifyFilter<Writer> { writer });
+void stringify(Writer& writer, const Filter& filter) {
+ if (!filter.expression) writer.Null();
+ else stringify(writer, (*filter.expression)->serialize());
}
template <class Writer>
diff --git a/src/mbgl/style/expression/compound_expression.cpp b/src/mbgl/style/expression/compound_expression.cpp
index bcde09e1b6..4226756fe4 100644
--- a/src/mbgl/style/expression/compound_expression.cpp
+++ b/src/mbgl/style/expression/compound_expression.cpp
@@ -19,7 +19,7 @@ namespace detail {
The Signature<Fn> structs are wrappers around an "evaluate()" function whose
purpose is to extract the necessary Type data from the evaluate function's
type. There are three key (partial) specializations:
-
+
Signature<R (Params...)>:
Wraps a simple evaluate function (const T0&, const T1&, ...) -> Result<U>
@@ -30,9 +30,9 @@ namespace detail {
Signature<R (const EvaluationContext&, Params...)>:
Wraps an evaluate function that needs to access the expression evaluation
parameters in addition to its subexpressions, i.e.,
- (const EvaluationParams& const T0&, const T1&, ...) -> Result<U>. Needed
+ (const EvaluationParams&, const T0&, const T1&, ...) -> Result<U>. Needed
for expressions like ["zoom"], ["get", key], etc.
-
+
In each of the above evaluate signatures, T0, T1, etc. are the types of
the successfully evaluated subexpressions.
*/
@@ -43,7 +43,7 @@ struct Signature;
template <class R, class... Params>
struct Signature<R (Params...)> : SignatureBase {
using Args = std::array<std::unique_ptr<Expression>, sizeof...(Params)>;
-
+
Signature(R (*evaluate_)(Params...), std::string name_) :
SignatureBase(
valueTypeToExpressionType<std::decay_t<typename R::Value>>(),
@@ -55,7 +55,7 @@ struct Signature<R (Params...)> : SignatureBase {
EvaluationResult apply(const EvaluationContext& evaluationParameters, const Args& args) const {
return applyImpl(evaluationParameters, args, std::index_sequence_for<Params...>{});
}
-
+
std::unique_ptr<Expression> makeExpression(std::vector<std::unique_ptr<Expression>> args) const override {
typename Signature::Args argsArray;
std::copy_n(std::make_move_iterator(args.begin()), sizeof...(Params), argsArray.begin());
@@ -80,7 +80,7 @@ private:
template <class R, typename T>
struct Signature<R (const Varargs<T>&)> : SignatureBase {
using Args = std::vector<std::unique_ptr<Expression>>;
-
+
Signature(R (*evaluate_)(const Varargs<T>&), std::string name_) :
SignatureBase(
valueTypeToExpressionType<std::decay_t<typename R::Value>>(),
@@ -89,11 +89,11 @@ struct Signature<R (const Varargs<T>&)> : SignatureBase {
),
evaluate(evaluate_)
{}
-
+
std::unique_ptr<Expression> makeExpression(std::vector<std::unique_ptr<Expression>> args) const override {
return std::make_unique<CompoundExpression<Signature>>(name, *this, std::move(args));
};
-
+
EvaluationResult apply(const EvaluationContext& evaluationParameters, const Args& args) const {
Varargs<T> evaluated;
evaluated.reserve(args.size());
@@ -115,7 +115,7 @@ struct Signature<R (const Varargs<T>&)> : SignatureBase {
template <class R, class... Params>
struct Signature<R (const EvaluationContext&, Params...)> : SignatureBase {
using Args = std::array<std::unique_ptr<Expression>, sizeof...(Params)>;
-
+
Signature(R (*evaluate_)(const EvaluationContext&, Params...), std::string name_) :
SignatureBase(
valueTypeToExpressionType<std::decay_t<typename R::Value>>(),
@@ -124,17 +124,17 @@ struct Signature<R (const EvaluationContext&, Params...)> : SignatureBase {
),
evaluate(evaluate_)
{}
-
+
std::unique_ptr<Expression> makeExpression(std::vector<std::unique_ptr<Expression>> args) const override {
typename Signature::Args argsArray;
std::copy_n(std::make_move_iterator(args.begin()), sizeof...(Params), argsArray.begin());
return std::make_unique<CompoundExpression<Signature>>(name, *this, std::move(argsArray));
}
-
+
EvaluationResult apply(const EvaluationContext& evaluationParameters, const Args& args) const {
return applyImpl(evaluationParameters, args, std::index_sequence_for<Params...>{});
}
-
+
private:
template <std::size_t ...I>
EvaluationResult applyImpl(const EvaluationContext& evaluationParameters, const Args& args, std::index_sequence<I...>) const {
@@ -150,6 +150,41 @@ private:
R (*evaluate)(const EvaluationContext&, Params...);
};
+
+// Evaluate function needing EvaluationContext and Varargs
+// (const EvaluationContext&, const Varargs<T>&) -> Result<U>
+template <class R, typename T>
+struct Signature<R (const EvaluationContext&, const Varargs<T>&)> : SignatureBase {
+ using Args = std::vector<std::unique_ptr<Expression>>;
+
+ Signature(R (*evaluate_)(const EvaluationContext&, const Varargs<T>&), std::string name_) :
+ SignatureBase(
+ valueTypeToExpressionType<std::decay_t<typename R::Value>>(),
+ VarargsType { valueTypeToExpressionType<T>() },
+ std::move(name_)
+ ),
+ evaluate(evaluate_)
+ {}
+
+ std::unique_ptr<Expression> makeExpression(std::vector<std::unique_ptr<Expression>> args) const override {
+ return std::make_unique<CompoundExpression<Signature>>(name, *this, std::move(args));
+ };
+
+ EvaluationResult apply(const EvaluationContext& evaluationParameters, const Args& args) const {
+ Varargs<T> evaluated;
+ evaluated.reserve(args.size());
+ for (const auto& arg : args) {
+ const EvaluationResult evaluatedArg = arg->evaluate(evaluationParameters);
+ if(!evaluatedArg) return evaluatedArg.error();
+ evaluated.push_back(*fromExpressionValue<std::decay_t<T>>(*evaluatedArg));
+ }
+ const R value = evaluate(evaluationParameters, evaluated);
+ if (!value) return value.error();
+ return *value;
+ }
+
+ R (*evaluate)(const EvaluationContext&, const Varargs<T>&);
+};
// Machinery to pull out function types from class methods, lambdas, etc.
template <class R, class... Params>
@@ -181,29 +216,104 @@ static std::unique_ptr<detail::SignatureBase> makeSignature(Fn evaluateFunction,
return std::make_unique<detail::Signature<Fn>>(evaluateFunction, std::move(name));
}
+Value featureIdAsExpressionValue(EvaluationContext params) {
+ assert(params.feature);
+ auto id = params.feature->getID();
+ if (!id) return Null;
+ return id->match([](const auto& idid) {
+ return toExpressionValue(mbgl::Value(idid));
+ });
+};
+
+optional<Value> featurePropertyAsExpressionValue(EvaluationContext params, const std::string& key) {
+ assert(params.feature);
+ auto property = params.feature->getValue(key);
+ return property ? toExpressionValue(*property) : optional<Value>();
+};
+
+optional<std::string> featureTypeAsString(FeatureType type) {
+ switch(type) {
+ case FeatureType::Point:
+ return optional<std::string>("Point");
+ case FeatureType::LineString:
+ return optional<std::string>("LineString");
+ case FeatureType::Polygon:
+ return optional<std::string>("Polygon");
+ case FeatureType::Unknown:
+ return optional<std::string>("Unknown");
+ default:
+ return {};
+ }
+};
+
+optional<double> featurePropertyAsDouble(EvaluationContext params, const std::string& key) {
+ assert(params.feature);
+ auto property = params.feature->getValue(key);
+ if (!property) return {};
+ return property->match(
+ [](double value) { return value; },
+ [](uint64_t value) { return optional<double>(static_cast<double>(value)); },
+ [](int64_t value) { return optional<double>(static_cast<double>(value)); },
+ [](auto) { return optional<double>(); }
+ );
+};
+
+optional<std::string> featurePropertyAsString(EvaluationContext params, const std::string& key) {
+ assert(params.feature);
+ auto property = params.feature->getValue(key);
+ if (!property) return {};
+ return property->match(
+ [](std::string value) { return value; },
+ [](auto) { return optional<std::string>(); }
+ );
+};
+
+optional<double> featureIdAsDouble(EvaluationContext params) {
+ assert(params.feature);
+ auto id = params.feature->getID();
+ if (!id) return optional<double>();
+ return id->match(
+ [](double value) { return value; },
+ [](uint64_t value) { return optional<double>(static_cast<double>(value)); },
+ [](int64_t value) { return optional<double>(static_cast<double>(value)); },
+ [](auto) { return optional<double>(); }
+ );
+};
+
+optional<std::string> featureIdAsString(EvaluationContext params) {
+ assert(params.feature);
+ auto id = params.feature->getID();
+ if (!id) return optional<std::string>();
+ return id->match(
+ [](std::string value) { return value; },
+ [](auto) { return optional<std::string>(); }
+ );
+};
+
std::unordered_map<std::string, CompoundExpressionRegistry::Definition> initializeDefinitions() {
std::unordered_map<std::string, CompoundExpressionRegistry::Definition> definitions;
auto define = [&](std::string name, auto fn) {
definitions[name].push_back(makeSignature(fn, name));
};
-
+
define("e", []() -> Result<double> { return 2.718281828459045; });
define("pi", []() -> Result<double> { return 3.141592653589793; });
define("ln2", []() -> Result<double> { return 0.6931471805599453; });
define("typeof", [](const Value& v) -> Result<std::string> { return toString(typeOf(v)); });
-
+
define("to-string", [](const Value& value) -> Result<std::string> {
return value.match(
+ [](const NullValue&) -> Result<std::string> { return std::string(); },
[](const Color& c) -> Result<std::string> { return c.stringify(); }, // avoid quoting
[](const std::string& s) -> Result<std::string> { return s; }, // avoid quoting
[](const auto& v) -> Result<std::string> { return stringify(v); }
);
});
-
+
define("to-boolean", [](const Value& v) -> Result<bool> {
return v.match(
- [&] (double f) { return (bool)f; },
+ [&] (double f) { return static_cast<bool>(f); },
[&] (const std::string& s) { return s.length() > 0; },
[&] (bool b) { return b; },
[&] (const NullValue&) { return false; },
@@ -213,10 +323,10 @@ std::unordered_map<std::string, CompoundExpressionRegistry::Definition> initiali
define("to-rgba", [](const Color& color) -> Result<std::array<double, 4>> {
return color.toArray();
});
-
+
define("rgba", rgba);
define("rgb", [](double r, double g, double b) { return rgba(r, g, b, 1.0f); });
-
+
define("zoom", [](const EvaluationContext& params) -> Result<double> {
if (!params.zoom) {
return EvaluationError {
@@ -225,7 +335,7 @@ std::unordered_map<std::string, CompoundExpressionRegistry::Definition> initiali
}
return *(params.zoom);
});
-
+
define("heatmap-density", [](const EvaluationContext& params) -> Result<double> {
if (!params.heatmapDensity) {
return EvaluationError {
@@ -241,7 +351,7 @@ std::unordered_map<std::string, CompoundExpressionRegistry::Definition> initiali
"Feature data is unavailable in the current evaluation context."
};
}
-
+
return params.feature->getValue(key) ? true : false;
});
define("has", [](const std::string& key, const std::unordered_map<std::string, Value>& object) -> Result<bool> {
@@ -267,7 +377,7 @@ std::unordered_map<std::string, CompoundExpressionRegistry::Definition> initiali
}
return object.at(key);
});
-
+
define("properties", [](const EvaluationContext& params) -> Result<std::unordered_map<std::string, Value>> {
if (!params.feature) {
return EvaluationError {
@@ -281,14 +391,14 @@ std::unordered_map<std::string, CompoundExpressionRegistry::Definition> initiali
}
return result;
});
-
+
define("geometry-type", [](const EvaluationContext& params) -> Result<std::string> {
if (!params.feature) {
return EvaluationError {
"Feature data is unavailable in the current evaluation context."
};
}
-
+
auto type = params.feature->getType();
if (type == FeatureType::Point) {
return "Point";
@@ -300,14 +410,14 @@ std::unordered_map<std::string, CompoundExpressionRegistry::Definition> initiali
return "Unknown";
}
});
-
+
define("id", [](const EvaluationContext& params) -> Result<Value> {
if (!params.feature) {
return EvaluationError {
"Feature data is unavailable in the current evaluation context."
};
}
-
+
auto id = params.feature->getID();
if (!id) {
return Null;
@@ -318,7 +428,7 @@ std::unordered_map<std::string, CompoundExpressionRegistry::Definition> initiali
}
);
});
-
+
define("+", [](const Varargs<double>& args) -> Result<double> {
double sum = 0.0f;
for (auto arg : args) {
@@ -348,7 +458,7 @@ std::unordered_map<std::string, CompoundExpressionRegistry::Definition> initiali
define("asin", [](double x) -> Result<double> { return asin(x); });
define("acos", [](double x) -> Result<double> { return acos(x); });
define("atan", [](double x) -> Result<double> { return atan(x); });
-
+
define("min", [](const Varargs<double>& args) -> Result<double> {
double result = std::numeric_limits<double>::infinity();
for (double arg : args) {
@@ -377,7 +487,7 @@ std::unordered_map<std::string, CompoundExpressionRegistry::Definition> initiali
define("<", [](const std::string& lhs, const std::string& rhs) -> Result<bool> { return lhs < rhs; });
define("<=", [](double lhs, double rhs) -> Result<bool> { return lhs <= rhs; });
define("<=", [](const std::string& lhs, const std::string& rhs) -> Result<bool> { return lhs <= rhs; });
-
+
define("!", [](bool e) -> Result<bool> { return !e; });
define("is-supported-script", [](const std::string& x) -> Result<bool> {
@@ -400,7 +510,130 @@ std::unordered_map<std::string, CompoundExpressionRegistry::Definition> initiali
define("error", [](const std::string& input) -> Result<type::ErrorType> {
return EvaluationError { input };
});
+
+ // Legacy Filters
+ define("filter-==", [](const EvaluationContext& params, const std::string& key, const Value &lhs) -> Result<bool> {
+ const auto rhs = featurePropertyAsExpressionValue(params, key);
+ return rhs ? lhs == *rhs : false;
+ });
+
+ define("filter-id-==", [](const EvaluationContext& params, const Value &lhs) -> Result<bool> {
+ return lhs == featureIdAsExpressionValue(params);
+ });
+
+ define("filter-type-==", [](const EvaluationContext& params, const std::string &lhs) -> Result<bool> {
+ if (!params.feature) return false;
+ return featureTypeAsString(params.feature->getType()) == lhs;
+ });
+
+ define("filter-<", [](const EvaluationContext& params, const std::string& key, double lhs) -> Result<bool> {
+ auto rhs = featurePropertyAsDouble(params, key);
+ return rhs ? rhs < lhs : false;
+ });
+
+ define("filter-<", [](const EvaluationContext& params, const std::string& key, std::string lhs) -> Result<bool> {
+ auto rhs = featurePropertyAsString(params, key);
+ return rhs ? rhs < lhs : false;
+ });
+
+ define("filter-id-<", [](const EvaluationContext& params, double lhs) -> Result<bool> {
+ auto rhs = featureIdAsDouble(params);
+ return rhs ? rhs < lhs : false;
+ });
+
+ define("filter-id-<", [](const EvaluationContext& params, std::string lhs) -> Result<bool> {
+ auto rhs = featureIdAsString(params);
+ return rhs ? rhs < lhs : false;
+ });
+
+ define("filter->", [](const EvaluationContext& params, const std::string& key, double lhs) -> Result<bool> {
+ auto rhs = featurePropertyAsDouble(params, key);
+ return rhs ? rhs > lhs : false;
+ });
+
+ define("filter->", [](const EvaluationContext& params, const std::string& key, std::string lhs) -> Result<bool> {
+ auto rhs = featurePropertyAsString(params, key);
+ return rhs ? rhs > lhs : false;
+ });
+
+ define("filter-id->", [](const EvaluationContext& params, double lhs) -> Result<bool> {
+ auto rhs = featureIdAsDouble(params);
+ return rhs ? rhs > lhs : false;
+ });
+
+ define("filter-id->", [](const EvaluationContext& params, std::string lhs) -> Result<bool> {
+ auto rhs = featureIdAsString(params);
+ return rhs ? rhs > lhs : false;
+ });
+
+ define("filter-<=", [](const EvaluationContext& params, const std::string& key, double lhs) -> Result<bool> {
+ auto rhs = featurePropertyAsDouble(params, key);
+ return rhs ? rhs <= lhs : false;
+ });
+
+ define("filter-<=", [](const EvaluationContext& params, const std::string& key, std::string lhs) -> Result<bool> {
+ auto rhs = featurePropertyAsString(params, key);
+ return rhs ? rhs <= lhs : false;
+ });
+
+ define("filter-id-<=", [](const EvaluationContext& params, double lhs) -> Result<bool> {
+ auto rhs = featureIdAsDouble(params);
+ return rhs ? rhs <= lhs : false;
+ });
+ define("filter-id-<=", [](const EvaluationContext& params, std::string lhs) -> Result<bool> {
+ auto rhs = featureIdAsString(params);
+ return rhs ? rhs <= lhs : false;
+ });
+
+ define("filter->=", [](const EvaluationContext& params, const std::string& key, double lhs) -> Result<bool> {
+ auto rhs = featurePropertyAsDouble(params, key);
+ return rhs ? rhs >= lhs : false;
+ });
+
+ define("filter->=", [](const EvaluationContext& params, const std::string& key, std::string lhs) -> Result<bool> {
+ auto rhs = featurePropertyAsString(params, key);
+ return rhs ? rhs >= lhs : false;
+ });
+
+ define("filter-id->=", [](const EvaluationContext& params, double lhs) -> Result<bool> {
+ auto rhs = featureIdAsDouble(params);
+ return rhs ? rhs >= lhs : false;
+ });
+
+ define("filter-id->=", [](const EvaluationContext& params, std::string lhs) -> Result<bool> {
+ auto rhs = featureIdAsString(params);
+ return rhs ? rhs >= lhs : false;
+ });
+
+ define("filter-has", [](const EvaluationContext& params, const std::string& key) -> Result<bool> {
+ assert(params.feature);
+ return bool(params.feature->getValue(key));
+ });
+
+ define("filter-has-id", [](const EvaluationContext& params) -> Result<bool> {
+ assert(params.feature);
+ return bool(params.feature->getID());
+ });
+
+ define("filter-type-in", [](const EvaluationContext& params, const Varargs<std::string>& types) -> Result<bool> {
+ assert(params.feature);
+ optional<std::string> type = featureTypeAsString(params.feature->getType());
+ return std::find(types.begin(), types.end(), type) != types.end();
+ });
+
+ define("filter-id-in", [](const EvaluationContext& params, const Varargs<Value>& ids) -> Result<bool> {
+ auto id = featureIdAsExpressionValue(params);
+ return std::find(ids.begin(), ids.end(), id) != ids.end();
+ });
+
+ define("filter-in", [](const EvaluationContext& params, const Varargs<Value>& varargs) -> Result<bool> {
+ if (varargs.size() < 2) return false;
+ assert(varargs[0].is<std::string>());
+ auto value = featurePropertyAsExpressionValue(params, varargs[0].get<std::string>());
+ return value ? std::find(varargs.begin() + 1, varargs.end(), *value) != varargs.end() : false;
+ });
+
return definitions;
}
@@ -419,7 +652,7 @@ ParseResult parseCompoundExpression(const std::string name, const Convertible& v
return ParseResult();
}
const CompoundExpressionRegistry::Definition& definition = it->second;
-
+
auto length = arrayLength(value);
// Check if we have a single signature with the correct number of
@@ -445,14 +678,14 @@ ParseResult parseCompoundExpression(const std::string name, const Convertible& v
args.reserve(length - 1);
for (std::size_t i = 1; i < length; i++) {
optional<type::Type> expected;
-
+
if (singleMatchingSignature) {
expected = definition[*singleMatchingSignature]->params.match(
[](const VarargsType& varargs) { return varargs.type; },
[&](const std::vector<type::Type>& params_) { return params_[i - 1]; }
);
}
-
+
auto parsed = ctx.parse(arrayMember(value, i), i, expected);
if (!parsed) {
return parsed;
@@ -479,7 +712,7 @@ ParseResult createCompoundExpression(const Definition& definition,
for (const std::unique_ptr<detail::SignatureBase>& signature : definition) {
signatureContext.clearErrors();
-
+
if (signature->params.is<std::vector<type::Type>>()) {
const std::vector<type::Type>& params = signature->params.get<std::vector<type::Type>>();
if (params.size() != args.size()) {
@@ -507,12 +740,12 @@ ParseResult createCompoundExpression(const Definition& definition,
}
}
}
-
+
if (signatureContext.getErrors().size() == 0) {
return ParseResult(signature->makeExpression(std::move(args)));
}
}
-
+
if (definition.size() == 1) {
ctx.appendErrors(std::move(signatureContext));
} else {
@@ -545,10 +778,32 @@ ParseResult createCompoundExpression(const Definition& definition,
}
ctx.error("Expected arguments of type " + signatures + ", but found (" + actualTypes + ") instead.");
}
-
+
return ParseResult();
}
+ParseResult createCompoundExpression(const std::string& name, ParsingContext& ctx) {
+ return createCompoundExpression(name, std::vector<std::unique_ptr<Expression>>(), ctx);
+}
+
+ParseResult createCompoundExpression(const std::string& name,
+ std::unique_ptr<Expression> arg1,
+ ParsingContext& ctx) {
+ std::vector<std::unique_ptr<Expression>> args;
+ args.push_back(std::move(arg1));
+ return createCompoundExpression(name, std::move(args), ctx);
+}
+
+ParseResult createCompoundExpression(const std::string& name,
+ std::unique_ptr<Expression> arg1,
+ std::unique_ptr<Expression> arg2,
+ ParsingContext& ctx) {
+ std::vector<std::unique_ptr<Expression>> args;
+ args.push_back(std::move(arg1));
+ args.push_back(std::move(arg2));
+ return createCompoundExpression(name, std::move(args), ctx);
+}
+
} // namespace expression
} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/expression/literal.cpp b/src/mbgl/style/expression/literal.cpp
index 8a63980dba..f68cfd5cf5 100644
--- a/src/mbgl/style/expression/literal.cpp
+++ b/src/mbgl/style/expression/literal.cpp
@@ -109,6 +109,14 @@ mbgl::Value Literal::serialize() const {
return *fromExpressionValue<mbgl::Value>(value);
}
}
+
+std::unique_ptr<Literal> createLiteral(const char* value) {
+ return createLiteral(std::string(value));
+}
+
+std::unique_ptr<Literal> createLiteral(Value value) {
+ return std::make_unique<Literal>(value);
+}
} // namespace expression
} // namespace style
diff --git a/src/mbgl/style/filter.cpp b/src/mbgl/style/filter.cpp
index 51aa6bcf82..2559eb4816 100644
--- a/src/mbgl/style/filter.cpp
+++ b/src/mbgl/style/filter.cpp
@@ -1,12 +1,20 @@
#include <mbgl/style/filter.hpp>
-#include <mbgl/style/filter_evaluator.hpp>
#include <mbgl/tile/geometry_tile_data.hpp>
namespace mbgl {
namespace style {
bool Filter::operator()(const expression::EvaluationContext &context) const {
- return FilterBase::visit(*this, FilterEvaluator { context });
+
+ if (!this->expression) return true;
+
+ const expression::EvaluationResult result = (*this->expression)->evaluate(context);
+ if (result) {
+ const optional<bool> typed = expression::fromExpressionValue<bool>(*result);
+ return typed ? *typed : false;
+ } else {
+ return true;
+ }
}
} // namespace style
diff --git a/src/mbgl/style/filter_evaluator.cpp b/src/mbgl/style/filter_evaluator.cpp
deleted file mode 100644
index 72022172f4..0000000000
--- a/src/mbgl/style/filter_evaluator.cpp
+++ /dev/null
@@ -1,225 +0,0 @@
-#include <mbgl/style/filter.hpp>
-#include <mbgl/style/filter_evaluator.hpp>
-#include <mbgl/tile/geometry_tile_data.hpp>
-
-namespace mbgl {
-namespace style {
-
-template <class Op>
-struct Comparator {
- const Op& op;
-
- template <class T>
- bool operator()(const T& lhs, const T& rhs) const {
- return op(lhs, rhs);
- }
-
- template <class T0, class T1>
- auto operator()(const T0& lhs, const T1& rhs) const
- -> typename std::enable_if_t<std::is_arithmetic<T0>::value && !std::is_same<T0, bool>::value &&
- std::is_arithmetic<T1>::value && !std::is_same<T1, bool>::value, bool> {
- return op(double(lhs), double(rhs));
- }
-
- template <class T0, class T1>
- auto operator()(const T0&, const T1&) const
- -> typename std::enable_if_t<!std::is_arithmetic<T0>::value || std::is_same<T0, bool>::value ||
- !std::is_arithmetic<T1>::value || std::is_same<T1, bool>::value, bool> {
- return false;
- }
-
- bool operator()(const NullValue&,
- const NullValue&) const {
- // Should be unreachable; null is not currently allowed by the style specification.
- assert(false);
- return false;
- }
-
- bool operator()(const std::vector<Value>&,
- const std::vector<Value>&) const {
- // Should be unreachable; nested values are not currently allowed by the style specification.
- assert(false);
- return false;
- }
-
- bool operator()(const PropertyMap&,
- const PropertyMap&) const {
- // Should be unreachable; nested values are not currently allowed by the style specification.
- assert(false);
- return false;
- }
-};
-
-template <class Op>
-bool compare(const Value& lhs, const Value& rhs, const Op& op) {
- return Value::binary_visit(lhs, rhs, Comparator<Op> { op });
-}
-
-bool equal(const Value& lhs, const Value& rhs) {
- return compare(lhs, rhs, [] (const auto& lhs_, const auto& rhs_) { return lhs_ == rhs_; });
-}
-
-bool FilterEvaluator::operator()(const NullFilter&) const {
- return true;
-}
-
-bool FilterEvaluator::operator()(const EqualsFilter& filter) const {
- optional<Value> actual = context.feature->getValue(filter.key);
- return actual && equal(*actual, filter.value);
-}
-
-bool FilterEvaluator::operator()(const NotEqualsFilter& filter) const {
- optional<Value> actual = context.feature->getValue(filter.key);
- return !actual || !equal(*actual, filter.value);
-}
-
-bool FilterEvaluator::operator()(const LessThanFilter& filter) const {
- optional<Value> actual = context.feature->getValue(filter.key);
- return actual && compare(*actual, filter.value, [] (const auto& lhs_, const auto& rhs_) { return lhs_ < rhs_; });
-}
-
-bool FilterEvaluator::operator()(const LessThanEqualsFilter& filter) const {
- optional<Value> actual = context.feature->getValue(filter.key);
- return actual && compare(*actual, filter.value, [] (const auto& lhs_, const auto& rhs_) { return lhs_ <= rhs_; });
-}
-
-bool FilterEvaluator::operator()(const GreaterThanFilter& filter) const {
- optional<Value> actual = context.feature->getValue(filter.key);
- return actual && compare(*actual, filter.value, [] (const auto& lhs_, const auto& rhs_) { return lhs_ > rhs_; });
-}
-
-bool FilterEvaluator::operator()(const GreaterThanEqualsFilter& filter) const {
- optional<Value> actual = context.feature->getValue(filter.key);
- return actual && compare(*actual, filter.value, [] (const auto& lhs_, const auto& rhs_) { return lhs_ >= rhs_; });
-}
-
-bool FilterEvaluator::operator()(const InFilter& filter) const {
- optional<Value> actual = context.feature->getValue(filter.key);
- if (!actual)
- return false;
- for (const auto& v: filter.values) {
- if (equal(*actual, v)) {
- return true;
- }
- }
- return false;
-}
-
-bool FilterEvaluator::operator()(const NotInFilter& filter) const {
- optional<Value> actual = context.feature->getValue(filter.key);
- if (!actual)
- return true;
- for (const auto& v: filter.values) {
- if (equal(*actual, v)) {
- return false;
- }
- }
- return true;
-}
-
-bool FilterEvaluator::operator()(const AnyFilter& filter) const {
- for (const auto& f: filter.filters) {
- if (Filter::visit(f, *this)) {
- return true;
- }
- }
- return false;
-}
-
-bool FilterEvaluator::operator()(const AllFilter& filter) const {
- for (const auto& f: filter.filters) {
- if (!Filter::visit(f, *this)) {
- return false;
- }
- }
- return true;
-}
-
-bool FilterEvaluator::operator()(const NoneFilter& filter) const {
- for (const auto& f: filter.filters) {
- if (Filter::visit(f, *this)) {
- return false;
- }
- }
- return true;
-}
-
-bool FilterEvaluator::operator()(const HasFilter& filter) const {
- return bool(context.feature->getValue(filter.key));
-}
-
-bool FilterEvaluator::operator()(const NotHasFilter& filter) const {
- return !context.feature->getValue(filter.key);
-}
-
-bool FilterEvaluator::operator()(const TypeEqualsFilter& filter) const {
- return context.feature->getType() == filter.value;
-}
-
-bool FilterEvaluator::operator()(const TypeNotEqualsFilter& filter) const {
- return context.feature->getType() != filter.value;
-}
-
-bool FilterEvaluator::operator()(const TypeInFilter& filter) const {
- for (const auto& v: filter.values) {
- if (context.feature->getType() == v) {
- return true;
- }
- }
- return false;
-}
-
-bool FilterEvaluator::operator()(const TypeNotInFilter& filter) const {
- for (const auto& v: filter.values) {
- if (context.feature->getType() == v) {
- return false;
- }
- }
- return true;
-}
-
-bool FilterEvaluator::operator()(const IdentifierEqualsFilter& filter) const {
- return context.feature->getID() == filter.value;
-}
-
-bool FilterEvaluator::operator()(const IdentifierNotEqualsFilter& filter) const {
- return context.feature->getID() != filter.value;
-}
-
-bool FilterEvaluator::operator()(const IdentifierInFilter& filter) const {
- for (const auto& v: filter.values) {
- if (context.feature->getID() == v) {
- return true;
- }
- }
- return false;
-}
-
-bool FilterEvaluator::operator()(const IdentifierNotInFilter& filter) const {
- for (const auto& v: filter.values) {
- if (context.feature->getID() == v) {
- return false;
- }
- }
- return true;
-}
-
-bool FilterEvaluator::operator()(const HasIdentifierFilter&) const {
- return bool(context.feature->getID());
-}
-
-bool FilterEvaluator::operator()(const NotHasIdentifierFilter&) const {
- return !context.feature->getID();
-}
-
-bool FilterEvaluator::operator()(const ExpressionFilter& filter) const {
- const expression::EvaluationResult result = filter.expression->evaluate(context);
- if (result) {
- const optional<bool> typed = expression::fromExpressionValue<bool>(*result);
- return typed ? *typed : false;
- }
- return false;
-}
-
-} // namespace style
-} // namespace mbgl