summaryrefslogtreecommitdiff
path: root/src/mbgl
diff options
context:
space:
mode:
authorJohn Firebaugh <john.firebaugh@gmail.com>2016-04-28 16:33:09 -0700
committerJohn Firebaugh <john.firebaugh@gmail.com>2016-04-28 16:33:09 -0700
commitda78422c5c37b2150eefeb399658903e45bf05d9 (patch)
tree1a7219a082c02de4f9f4d1274abb289090989826 /src/mbgl
parent10528091db0baaad4b528555498d43236e32ccce (diff)
downloadqtlocation-mapboxgl-da78422c5c37b2150eefeb399658903e45bf05d9.tar.gz
[core] Prepare Filter for public API (#4900)
Diffstat (limited to 'src/mbgl')
-rw-r--r--src/mbgl/renderer/symbol_bucket.cpp23
-rw-r--r--src/mbgl/renderer/symbol_bucket.hpp5
-rw-r--r--src/mbgl/style/filter.hpp91
-rw-r--r--src/mbgl/style/filter_evaluator.hpp138
-rw-r--r--src/mbgl/style/filter_expression.cpp128
-rw-r--r--src/mbgl/style/filter_expression.hpp124
-rw-r--r--src/mbgl/style/filter_expression_private.hpp119
-rw-r--r--src/mbgl/style/style_bucket_parameters.cpp7
-rw-r--r--src/mbgl/style/style_bucket_parameters.hpp4
-rw-r--r--src/mbgl/style/style_layer.hpp4
-rw-r--r--src/mbgl/style/style_parser.cpp146
-rw-r--r--src/mbgl/style/style_parser.hpp3
-rw-r--r--src/mbgl/style/value.cpp33
-rw-r--r--src/mbgl/style/value.hpp20
-rw-r--r--src/mbgl/style/value_comparison.hpp109
-rw-r--r--src/mbgl/tile/geometry_tile.cpp4
-rw-r--r--src/mbgl/tile/geometry_tile.hpp2
-rw-r--r--src/mbgl/util/value.hpp9
18 files changed, 415 insertions, 554 deletions
diff --git a/src/mbgl/renderer/symbol_bucket.cpp b/src/mbgl/renderer/symbol_bucket.cpp
index cdb30bf222..c6d49101fc 100644
--- a/src/mbgl/renderer/symbol_bucket.cpp
+++ b/src/mbgl/renderer/symbol_bucket.cpp
@@ -1,4 +1,5 @@
#include <mbgl/renderer/symbol_bucket.hpp>
+#include <mbgl/style/filter_evaluator.hpp>
#include <mbgl/layer/symbol_layer.hpp>
#include <mbgl/tile/geometry_tile.hpp>
#include <mbgl/sprite/sprite_image.hpp>
@@ -26,6 +27,7 @@
#include <mbgl/util/std.hpp>
#include <mbgl/util/get_geometries.hpp>
#include <mbgl/util/constants.hpp>
+#include <mbgl/util/string.hpp>
namespace mbgl {
@@ -99,8 +101,7 @@ bool SymbolBucket::needsClipping() const {
return mode == MapMode::Still;
}
-void SymbolBucket::parseFeatures(const GeometryTileLayer& layer,
- const FilterExpression& filter) {
+void SymbolBucket::parseFeatures(const GeometryTileLayer& layer, const Filter& filter) {
const bool has_text = !layout.textField.value.empty() && !layout.textFont.value.empty();
const bool has_icon = !layout.iconImage.value.empty();
@@ -113,15 +114,27 @@ void SymbolBucket::parseFeatures(const GeometryTileLayer& layer,
for (GLsizei i = 0; i < featureCount; i++) {
auto feature = layer.getFeature(i);
- GeometryTileFeatureExtractor extractor(*feature);
- if (!evaluate(filter, extractor))
+ FilterEvaluator<GeometryTileFeatureExtractor> evaluator(*feature);
+ if (!Filter::visit(filter, evaluator))
continue;
SymbolFeature ft;
auto getValue = [&feature](const std::string& key) -> std::string {
auto value = feature->getValue(key);
- return value ? toString(*value) : std::string();
+ if (!value)
+ return std::string();
+ if (value->is<std::string>())
+ return value->get<std::string>();
+ if (value->is<bool>())
+ return value->get<bool>() ? "true" : "false";
+ if (value->is<int64_t>())
+ return util::toString(value->get<int64_t>());
+ if (value->is<uint64_t>())
+ return util::toString(value->get<uint64_t>());
+ if (value->is<double>())
+ return util::toString(value->get<double>());
+ return "null";
};
if (has_text) {
diff --git a/src/mbgl/renderer/symbol_bucket.hpp b/src/mbgl/renderer/symbol_bucket.hpp
index 243ae99de9..1b37a1e005 100644
--- a/src/mbgl/renderer/symbol_bucket.hpp
+++ b/src/mbgl/renderer/symbol_bucket.hpp
@@ -13,7 +13,7 @@
#include <mbgl/text/collision_feature.hpp>
#include <mbgl/text/shaping.hpp>
#include <mbgl/text/quads.hpp>
-#include <mbgl/style/filter_expression.hpp>
+#include <mbgl/style/filter.hpp>
#include <mbgl/layer/symbol_layer.hpp>
#include <memory>
@@ -88,8 +88,7 @@ public:
void drawIcons(IconShader&, gl::GLObjectStore&);
void drawCollisionBoxes(CollisionBoxShader&, gl::GLObjectStore&);
- void parseFeatures(const GeometryTileLayer&,
- const FilterExpression&);
+ void parseFeatures(const GeometryTileLayer&, const Filter&);
bool needsDependencies(GlyphStore&, SpriteStore&);
void placeFeatures(CollisionTile&) override;
diff --git a/src/mbgl/style/filter.hpp b/src/mbgl/style/filter.hpp
new file mode 100644
index 0000000000..85878543f8
--- /dev/null
+++ b/src/mbgl/style/filter.hpp
@@ -0,0 +1,91 @@
+#pragma once
+
+#include <mbgl/util/variant.hpp>
+#include <mbgl/util/value.hpp>
+
+#include <string>
+#include <vector>
+
+namespace mbgl {
+
+typedef variant<
+ class NullFilter,
+ class EqualsFilter,
+ class NotEqualsFilter,
+ class LessThanFilter,
+ class LessThanEqualsFilter,
+ class GreaterThanFilter,
+ class GreaterThanEqualsFilter,
+ class InFilter,
+ class NotInFilter,
+ class AnyFilter,
+ class AllFilter,
+ class NoneFilter
+ > Filter;
+
+class NullFilter {};
+
+class EqualsFilter {
+public:
+ std::string key;
+ Value value;
+};
+
+class NotEqualsFilter {
+public:
+ std::string key;
+ Value value;
+};
+
+class LessThanFilter {
+public:
+ std::string key;
+ Value value;
+};
+
+class LessThanEqualsFilter {
+public:
+ std::string key;
+ Value value;
+};
+
+class GreaterThanFilter {
+public:
+ std::string key;
+ Value value;
+};
+
+class GreaterThanEqualsFilter {
+public:
+ std::string key;
+ Value value;
+};
+
+class InFilter {
+public:
+ std::string key;
+ std::vector<Value> values;
+};
+
+class NotInFilter {
+public:
+ std::string key;
+ std::vector<Value> values;
+};
+
+class AnyFilter {
+public:
+ std::vector<Filter> filters;
+};
+
+class AllFilter {
+public:
+ std::vector<Filter> filters;
+};
+
+class NoneFilter {
+public:
+ std::vector<Filter> filters;
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/style/filter_evaluator.hpp b/src/mbgl/style/filter_evaluator.hpp
new file mode 100644
index 0000000000..27402ac211
--- /dev/null
+++ b/src/mbgl/style/filter_evaluator.hpp
@@ -0,0 +1,138 @@
+#pragma once
+
+#include <mbgl/style/filter.hpp>
+#include <mbgl/util/optional.hpp>
+
+#include <type_traits>
+
+namespace mbgl {
+
+template <class Extractor>
+class FilterEvaluator {
+public:
+ FilterEvaluator(const Extractor& extractor_)
+ : extractor(extractor_) {}
+
+ bool operator()(const NullFilter&) const {
+ return true;
+ }
+
+ bool operator()(const EqualsFilter& filter) const {
+ optional<Value> actual = extractor.getValue(filter.key);
+ return actual && equal(*actual, filter.value);
+ }
+
+ bool operator()(const NotEqualsFilter& filter) const {
+ optional<Value> actual = extractor.getValue(filter.key);
+ return !actual || !equal(*actual, filter.value);
+ }
+
+ bool operator()(const LessThanFilter& filter) const {
+ optional<Value> actual = extractor.getValue(filter.key);
+ return actual && compare(*actual, filter.value, [] (const auto& lhs_, const auto& rhs_) { return lhs_ < rhs_; });
+ }
+
+ bool operator()(const LessThanEqualsFilter& filter) const {
+ optional<Value> actual = extractor.getValue(filter.key);
+ return actual && compare(*actual, filter.value, [] (const auto& lhs_, const auto& rhs_) { return lhs_ <= rhs_; });
+ }
+
+ bool operator()(const GreaterThanFilter& filter) const {
+ optional<Value> actual = extractor.getValue(filter.key);
+ return actual && compare(*actual, filter.value, [] (const auto& lhs_, const auto& rhs_) { return lhs_ > rhs_; });
+ }
+
+ bool operator()(const GreaterThanEqualsFilter& filter) const {
+ optional<Value> actual = extractor.getValue(filter.key);
+ return actual && compare(*actual, filter.value, [] (const auto& lhs_, const auto& rhs_) { return lhs_ >= rhs_; });
+ }
+
+ bool operator()(const InFilter& filter) const {
+ optional<Value> actual = extractor.getValue(filter.key);
+ if (!actual)
+ return false;
+ for (const auto& v: filter.values) {
+ if (equal(*actual, v)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool operator()(const NotInFilter& filter) const {
+ optional<Value> actual = extractor.getValue(filter.key);
+ if (!actual)
+ return true;
+ for (const auto& v: filter.values) {
+ if (equal(*actual, v)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ bool operator()(const AnyFilter& filter) const {
+ for (const auto& f: filter.filters) {
+ if (Filter::visit(f, *this)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool operator()(const AllFilter& filter) const {
+ for (const auto& f: filter.filters) {
+ if (!Filter::visit(f, *this)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ bool operator()(const NoneFilter& filter) const {
+ for (const auto& f: filter.filters) {
+ if (Filter::visit(f, *this)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+private:
+ 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;
+ }
+ };
+
+ template <class Op>
+ bool compare(const Value& lhs, const Value& rhs, const Op& op) const {
+ return Value::binary_visit(lhs, rhs, Comparator<Op> { op });
+ }
+
+ bool equal(const Value& lhs, const Value& rhs) const {
+ return compare(lhs, rhs, [] (const auto& lhs_, const auto& rhs_) { return lhs_ == rhs_; });
+ }
+
+ const Extractor& extractor;
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/style/filter_expression.cpp b/src/mbgl/style/filter_expression.cpp
deleted file mode 100644
index 660c978f0d..0000000000
--- a/src/mbgl/style/filter_expression.cpp
+++ /dev/null
@@ -1,128 +0,0 @@
-#include <mbgl/style/filter_expression.hpp>
-#include <mbgl/tile/geometry_tile.hpp>
-#include <mbgl/platform/log.hpp>
-
-namespace mbgl {
-
-Value parseFeatureType(const Value& value) {
- 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));
- } else {
- Log::Warning(Event::ParseStyle, "value for $type filter must be Point, LineString, or Polygon");
- return Value(uint64_t(FeatureType::Unknown));
- }
-}
-
-template <class Expression>
-FilterExpression parseBinaryFilter(const JSValue& value) {
- FilterExpression empty;
-
- if (value.Size() < 3) {
- Log::Warning(Event::ParseStyle, "filter expression must have 3 elements");
- return empty;
- }
-
- if (!value[1u].IsString()) {
- Log::Warning(Event::ParseStyle, "filter expression key must be a string");
- return empty;
- }
-
- Expression expression;
- expression.key = { value[1u].GetString(), value[1u].GetStringLength() };
- expression.value = parseValue(value[2u]);
-
- if (expression.key == "$type") {
- expression.value = parseFeatureType(expression.value);
- }
-
- return expression;
-}
-
-template <class Expression>
-FilterExpression parseSetFilter(const JSValue& value) {
- FilterExpression empty;
-
- if (value.Size() < 2) {
- Log::Warning(Event::ParseStyle, "filter expression must at least 2 elements");
- return empty;
- }
-
- if (!value[1u].IsString()) {
- Log::Warning(Event::ParseStyle, "filter expression key must be a string");
- return empty;
- }
-
- Expression expression;
- expression.key = { value[1u].GetString(), value[1u].GetStringLength() };
- for (rapidjson::SizeType i = 2; i < value.Size(); ++i) {
- Value parsedValue = parseValue(value[i]);
- if (expression.key == "$type") {
- parsedValue = parseFeatureType(parsedValue);
- }
- expression.values.push_back(parsedValue);
- }
- return expression;
-}
-
-template <class Expression>
-FilterExpression parseCompoundFilter(const JSValue& value) {
- Expression expression;
- for (rapidjson::SizeType i = 1; i < value.Size(); ++i) {
- expression.expressions.push_back(parseFilterExpression(value[i]));
- }
- return expression;
-}
-
-FilterExpression parseFilterExpression(const JSValue& value) {
- FilterExpression empty;
-
- if (!value.IsArray()) {
- Log::Warning(Event::ParseStyle, "filter expression must be an array");
- return empty;
- }
-
- if (value.Size() < 1) {
- Log::Warning(Event::ParseStyle, "filter expression must have at least 1 element");
- return empty;
- }
-
- if (!value[0u].IsString()) {
- Log::Warning(Event::ParseStyle, "filter operator must be a string");
- return empty;
- }
-
- std::string op = { value[0u].GetString(), value[0u].GetStringLength() };
-
- if (op == "==") {
- return parseBinaryFilter<EqualsExpression>(value);
- } else if (op == "!=") {
- return parseBinaryFilter<NotEqualsExpression>(value);
- } else if (op == ">") {
- return parseBinaryFilter<GreaterThanExpression>(value);
- } else if (op == ">=") {
- return parseBinaryFilter<GreaterThanEqualsExpression>(value);
- } else if (op == "<") {
- return parseBinaryFilter<LessThanExpression>(value);
- } else if (op == "<=") {
- return parseBinaryFilter<LessThanEqualsExpression>(value);
- } else if (op == "in") {
- return parseSetFilter<InExpression>(value);
- } else if (op == "!in") {
- return parseSetFilter<NotInExpression>(value);
- } else if (op == "all") {
- return parseCompoundFilter<AllExpression>(value);
- } else if (op == "any") {
- return parseCompoundFilter<AnyExpression>(value);
- } else if (op == "none") {
- return parseCompoundFilter<NoneExpression>(value);
- } else {
- Log::Warning(Event::ParseStyle, "filter operator must be one of \"==\", \"!=\", \">\", \">=\", \"<\", \"<=\", \"in\", \"!in\", \"all\", \"any\", \"none\"");
- return empty;
- }
-}
-
-} // namespace mbgl
diff --git a/src/mbgl/style/filter_expression.hpp b/src/mbgl/style/filter_expression.hpp
deleted file mode 100644
index 1fa26a69f4..0000000000
--- a/src/mbgl/style/filter_expression.hpp
+++ /dev/null
@@ -1,124 +0,0 @@
-#ifndef MBGL_STYLE_FILTER_EXPRESSION
-#define MBGL_STYLE_FILTER_EXPRESSION
-
-#include <mbgl/style/value.hpp>
-#include <mbgl/util/rapidjson.hpp>
-
-#include <string>
-#include <vector>
-
-namespace mbgl {
-
-typedef variant<
- struct NullExpression,
- struct EqualsExpression,
- struct NotEqualsExpression,
- struct LessThanExpression,
- struct LessThanEqualsExpression,
- struct GreaterThanExpression,
- struct GreaterThanEqualsExpression,
- struct InExpression,
- struct NotInExpression,
- struct AnyExpression,
- struct AllExpression,
- struct NoneExpression
- > FilterExpression;
-
-FilterExpression parseFilterExpression(const JSValue&);
-
-template <class Extractor>
-bool evaluate(const FilterExpression&, const Extractor&);
-
-struct NullExpression {
- template <class Extractor>
- bool evaluate(const Extractor&) const { return true; }
-};
-
-struct EqualsExpression {
- std::string key;
- Value value;
-
- template <class Extractor>
- bool evaluate(const Extractor&) const;
-};
-
-struct NotEqualsExpression {
- std::string key;
- Value value;
-
- template <class Extractor>
- bool evaluate(const Extractor&) const;
-};
-
-struct LessThanExpression {
- std::string key;
- Value value;
-
- template <class Extractor>
- bool evaluate(const Extractor&) const;
-};
-
-struct LessThanEqualsExpression {
- std::string key;
- Value value;
-
- template <class Extractor>
- bool evaluate(const Extractor&) const;
-};
-
-struct GreaterThanExpression {
- std::string key;
- Value value;
-
- template <class Extractor>
- bool evaluate(const Extractor&) const;
-};
-
-struct GreaterThanEqualsExpression {
- std::string key;
- Value value;
-
- template <class Extractor>
- bool evaluate(const Extractor&) const;
-};
-
-struct InExpression {
- std::string key;
- std::vector<Value> values;
-
- template <class Extractor>
- bool evaluate(const Extractor&) const;
-};
-
-struct NotInExpression {
- std::string key;
- std::vector<Value> values;
-
- template <class Extractor>
- bool evaluate(const Extractor&) const;
-};
-
-struct AnyExpression {
- std::vector<FilterExpression> expressions;
-
- template <class Extractor>
- bool evaluate(const Extractor&) const;
-};
-
-struct AllExpression {
- std::vector<FilterExpression> expressions;
-
- template <class Extractor>
- bool evaluate(const Extractor&) const;
-};
-
-struct NoneExpression {
- std::vector<FilterExpression> expressions;
-
- template <class Extractor>
- bool evaluate(const Extractor&) const;
-};
-
-} // namespace mbgl
-
-#endif
diff --git a/src/mbgl/style/filter_expression_private.hpp b/src/mbgl/style/filter_expression_private.hpp
deleted file mode 100644
index bbc72526d2..0000000000
--- a/src/mbgl/style/filter_expression_private.hpp
+++ /dev/null
@@ -1,119 +0,0 @@
-#include <mbgl/util/optional.hpp>
-
-#include <mbgl/style/value_comparison.hpp>
-
-namespace mbgl {
-
-template <class Extractor>
-struct Evaluator : public mapbox::util::static_visitor<bool>
-{
- const Extractor& extractor;
-
- Evaluator(const Extractor& extractor_)
- : extractor(extractor_) {}
-
- template <class E>
- bool operator()(const E& e) const { return e.evaluate(extractor); }
-};
-
-template <class Extractor>
-bool evaluate(const FilterExpression& expression, const Extractor& extractor) {
- return mapbox::util::apply_visitor(Evaluator<Extractor>(extractor), expression);
-};
-
-template <class Extractor>
-bool EqualsExpression::evaluate(const Extractor& extractor) const {
- optional<Value> actual = extractor.getValue(key);
- return actual && util::relaxed_equal(*actual, value);
-}
-
-template <class Extractor>
-bool NotEqualsExpression::evaluate(const Extractor& extractor) const {
- optional<Value> actual = extractor.getValue(key);
- return !actual || util::relaxed_not_equal(*actual, value);
-}
-
-template <class Extractor>
-bool LessThanExpression::evaluate(const Extractor& extractor) const {
- optional<Value> actual = extractor.getValue(key);
- return actual && util::relaxed_less(*actual, value);
-}
-
-template <class Extractor>
-bool LessThanEqualsExpression::evaluate(const Extractor& extractor) const {
- optional<Value> actual = extractor.getValue(key);
- return actual && util::relaxed_less_equal(*actual, value);
-}
-
-template <class Extractor>
-bool GreaterThanExpression::evaluate(const Extractor& extractor) const {
- optional<Value> actual = extractor.getValue(key);
- return actual && util::relaxed_greater(*actual, value);
-}
-
-template <class Extractor>
-bool GreaterThanEqualsExpression::evaluate(const Extractor& extractor) const {
- optional<Value> actual = extractor.getValue(key);
- return actual && util::relaxed_greater_equal(*actual, value);
-}
-
-template <class Extractor>
-bool InExpression::evaluate(const Extractor& extractor) const {
- optional<Value> actual = extractor.getValue(key);
- if (!actual)
- return false;
- for (const auto& v: values) {
- if (util::relaxed_equal(*actual, v)) {
- return true;
- }
- }
- return false;
-}
-
-template <class Extractor>
-bool NotInExpression::evaluate(const Extractor& extractor) const {
- optional<Value> actual = extractor.getValue(key);
- if (!actual)
- return true;
- for (const auto& v: values) {
- if (util::relaxed_equal(*actual, v)) {
- return false;
- }
- }
- return true;
-}
-
-template <class Extractor>
-bool AnyExpression::evaluate(const Extractor& extractor) const {
- Evaluator<Extractor> evaluator(extractor);
- for (const auto& e: expressions) {
- if (mapbox::util::apply_visitor(evaluator, e)) {
- return true;
- }
- }
- return false;
-}
-
-template <class Extractor>
-bool AllExpression::evaluate(const Extractor& extractor) const {
- Evaluator<Extractor> evaluator(extractor);
- for (const auto& e: expressions) {
- if (!mapbox::util::apply_visitor(evaluator, e)) {
- return false;
- }
- }
- return true;
-}
-
-template <class Extractor>
-bool NoneExpression::evaluate(const Extractor& extractor) const {
- Evaluator<Extractor> evaluator(extractor);
- for (const auto& e: expressions) {
- if (mapbox::util::apply_visitor(evaluator, e)) {
- return false;
- }
- }
- return true;
-}
-
-} // namespace mbgl
diff --git a/src/mbgl/style/style_bucket_parameters.cpp b/src/mbgl/style/style_bucket_parameters.cpp
index 7bde1fd80e..8591dd430c 100644
--- a/src/mbgl/style/style_bucket_parameters.cpp
+++ b/src/mbgl/style/style_bucket_parameters.cpp
@@ -1,15 +1,16 @@
#include <mbgl/style/style_bucket_parameters.hpp>
+#include <mbgl/style/filter_evaluator.hpp>
#include <mbgl/tile/geometry_tile.hpp>
namespace mbgl {
-void StyleBucketParameters::eachFilteredFeature(const FilterExpression& filter,
+void StyleBucketParameters::eachFilteredFeature(const Filter& filter,
std::function<void (const GeometryTileFeature&)> function) {
for (std::size_t i = 0; !cancelled() && i < layer.featureCount(); i++) {
auto feature = layer.getFeature(i);
- GeometryTileFeatureExtractor extractor(*feature);
- if (!evaluate(filter, extractor))
+ FilterEvaluator<GeometryTileFeatureExtractor> evaluator(*feature);
+ if (!Filter::visit(filter, evaluator))
continue;
function(*feature);
diff --git a/src/mbgl/style/style_bucket_parameters.hpp b/src/mbgl/style/style_bucket_parameters.hpp
index 134850066d..c77980f37c 100644
--- a/src/mbgl/style/style_bucket_parameters.hpp
+++ b/src/mbgl/style/style_bucket_parameters.hpp
@@ -2,7 +2,7 @@
#define STYLE_BUCKET_PARAMETERS
#include <mbgl/map/mode.hpp>
-#include <mbgl/style/filter_expression.hpp>
+#include <mbgl/style/filter.hpp>
#include <mbgl/tile/tile_data.hpp>
#include <functional>
@@ -42,7 +42,7 @@ public:
return state == TileData::State::obsolete;
}
- void eachFilteredFeature(const FilterExpression&, std::function<void (const GeometryTileFeature&)>);
+ void eachFilteredFeature(const Filter&, std::function<void (const GeometryTileFeature&)>);
const TileID& tileID;
const GeometryTileLayer& layer;
diff --git a/src/mbgl/style/style_layer.hpp b/src/mbgl/style/style_layer.hpp
index fa09ee2e82..9313138587 100644
--- a/src/mbgl/style/style_layer.hpp
+++ b/src/mbgl/style/style_layer.hpp
@@ -2,7 +2,7 @@
#define MBGL_STYLE_STYLE_LAYER
#include <mbgl/style/types.hpp>
-#include <mbgl/style/filter_expression.hpp>
+#include <mbgl/style/filter.hpp>
#include <mbgl/renderer/render_pass.hpp>
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/util/rapidjson.hpp>
@@ -65,7 +65,7 @@ public:
std::string ref;
std::string source;
std::string sourceLayer;
- FilterExpression filter;
+ Filter filter;
float minZoom = -std::numeric_limits<float>::infinity();
float maxZoom = std::numeric_limits<float>::infinity();
VisibilityType visibility = VisibilityType::Visible;
diff --git a/src/mbgl/style/style_parser.cpp b/src/mbgl/style/style_parser.cpp
index d99339b84a..27edf15f97 100644
--- a/src/mbgl/style/style_parser.cpp
+++ b/src/mbgl/style/style_parser.cpp
@@ -11,6 +11,7 @@
#include <mapbox/geojsonvt.hpp>
#include <mapbox/geojsonvt/convert.hpp>
+#include <mbgl/tile/geometry_tile.hpp>
#include <mbgl/util/mapbox.hpp>
#include <rapidjson/document.h>
@@ -451,7 +452,7 @@ void StyleParser::parseLayer(const std::string& id, const JSValue& value, std::u
}
if (value.HasMember("filter")) {
- layer->filter = parseFilterExpression(value["filter"]);
+ layer->filter = parseFilter(value["filter"]);
}
if (value.HasMember("minzoom")) {
@@ -497,6 +498,149 @@ void StyleParser::parseVisibility(StyleLayer& layer, const JSValue& value) {
layer.visibility = VisibilityTypeClass({ value["visibility"].GetString(), value["visibility"].GetStringLength() });
}
+Value parseFeatureType(const Value& value) {
+ 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));
+ } else {
+ Log::Warning(Event::ParseStyle, "value for $type filter must be Point, LineString, or Polygon");
+ return Value(uint64_t(FeatureType::Unknown));
+ }
+}
+
+Value parseValue(const JSValue& value) {
+ switch (value.GetType()) {
+ case rapidjson::kNullType:
+ case rapidjson::kFalseType:
+ return false;
+
+ case rapidjson::kTrueType:
+ return true;
+
+ case rapidjson::kStringType:
+ return std::string { value.GetString(), value.GetStringLength() };
+
+ case rapidjson::kNumberType:
+ if (value.IsUint64()) return value.GetUint64();
+ if (value.IsInt64()) return value.GetInt64();
+ return value.GetDouble();
+
+ default:
+ return false;
+ }
+}
+
+template <class Expression>
+Filter parseBinaryFilter(const JSValue& value) {
+ Filter empty;
+
+ if (value.Size() < 3) {
+ Log::Warning(Event::ParseStyle, "filter expression must have 3 elements");
+ return empty;
+ }
+
+ if (!value[1u].IsString()) {
+ Log::Warning(Event::ParseStyle, "filter expression key must be a string");
+ return empty;
+ }
+
+ Expression expression;
+ expression.key = { value[1u].GetString(), value[1u].GetStringLength() };
+ expression.value = parseValue(value[2u]);
+
+ if (expression.key == "$type") {
+ expression.value = parseFeatureType(expression.value);
+ }
+
+ return expression;
+}
+
+template <class Expression>
+Filter parseSetFilter(const JSValue& value) {
+ Filter empty;
+
+ if (value.Size() < 2) {
+ Log::Warning(Event::ParseStyle, "filter expression must at least 2 elements");
+ return empty;
+ }
+
+ if (!value[1u].IsString()) {
+ Log::Warning(Event::ParseStyle, "filter expression key must be a string");
+ return empty;
+ }
+
+ Expression expression;
+ expression.key = { value[1u].GetString(), value[1u].GetStringLength() };
+ for (rapidjson::SizeType i = 2; i < value.Size(); ++i) {
+ Value parsedValue = parseValue(value[i]);
+ if (expression.key == "$type") {
+ parsedValue = parseFeatureType(parsedValue);
+ }
+ expression.values.push_back(parsedValue);
+ }
+ return expression;
+}
+
+template <class Expression>
+Filter parseCompoundFilter(const JSValue& value) {
+ Expression expression;
+ for (rapidjson::SizeType i = 1; i < value.Size(); ++i) {
+ expression.filters.push_back(parseFilter(value[i]));
+ }
+ return expression;
+}
+
+Filter parseFilter(const JSValue& value) {
+ Filter empty;
+
+ if (!value.IsArray()) {
+ Log::Warning(Event::ParseStyle, "filter expression must be an array");
+ return empty;
+ }
+
+ if (value.Size() < 1) {
+ Log::Warning(Event::ParseStyle, "filter expression must have at least 1 element");
+ return empty;
+ }
+
+ if (!value[0u].IsString()) {
+ Log::Warning(Event::ParseStyle, "filter operator must be a string");
+ return empty;
+ }
+
+ std::string op = { value[0u].GetString(), value[0u].GetStringLength() };
+
+ if (op == "==") {
+ return parseBinaryFilter<EqualsFilter>(value);
+ } else if (op == "!=") {
+ return parseBinaryFilter<NotEqualsFilter>(value);
+ } else if (op == ">") {
+ return parseBinaryFilter<GreaterThanFilter>(value);
+ } else if (op == ">=") {
+ return parseBinaryFilter<GreaterThanEqualsFilter>(value);
+ } else if (op == "<") {
+ return parseBinaryFilter<LessThanFilter>(value);
+ } else if (op == "<=") {
+ return parseBinaryFilter<LessThanEqualsFilter>(value);
+ } else if (op == "in") {
+ return parseSetFilter<InFilter>(value);
+ } else if (op == "!in") {
+ return parseSetFilter<NotInFilter>(value);
+ } else if (op == "all") {
+ return parseCompoundFilter<AllFilter>(value);
+ } else if (op == "any") {
+ return parseCompoundFilter<AnyFilter>(value);
+ } else if (op == "none") {
+ return parseCompoundFilter<NoneFilter>(value);
+ } else {
+ Log::Warning(Event::ParseStyle, "filter operator must be one of \"==\", \"!=\", \">\", \">=\", \"<\", \"<=\", \"in\", \"!in\", \"all\", \"any\", \"none\"");
+ return empty;
+ }
+}
+
std::vector<FontStack> StyleParser::fontStacks() const {
std::set<FontStack> result;
diff --git a/src/mbgl/style/style_parser.hpp b/src/mbgl/style/style_parser.hpp
index 4cc4e2f2cb..2c1feac15a 100644
--- a/src/mbgl/style/style_parser.hpp
+++ b/src/mbgl/style/style_parser.hpp
@@ -4,6 +4,7 @@
#include <mbgl/style/types.hpp>
#include <mbgl/style/style_layer.hpp>
#include <mbgl/source/source.hpp>
+#include <mbgl/style/filter.hpp>
#include <mbgl/util/rapidjson.hpp>
#include <vector>
@@ -17,6 +18,8 @@ namespace mbgl {
class StyleLayer;
class Source;
+Filter parseFilter(const JSValue&);
+
class StyleParser {
public:
~StyleParser();
diff --git a/src/mbgl/style/value.cpp b/src/mbgl/style/value.cpp
deleted file mode 100644
index a0fa99edf3..0000000000
--- a/src/mbgl/style/value.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-#include <mbgl/style/value.hpp>
-#include <mbgl/util/string.hpp>
-
-std::string mbgl::toString(const mbgl::Value& value) {
- if (value.is<std::string>()) return value.get<std::string>();
- else if (value.is<bool>()) return value.get<bool>() ? "true" : "false";
- else if (value.is<int64_t>()) return util::toString(value.get<int64_t>());
- else if (value.is<uint64_t>()) return util::toString(value.get<uint64_t>());
- else if (value.is<double>()) return util::toString(value.get<double>());
- else return "null";
-}
-
-mbgl::Value mbgl::parseValue(const JSValue& value) {
- switch (value.GetType()) {
- case rapidjson::kNullType:
- case rapidjson::kFalseType:
- return false;
-
- case rapidjson::kTrueType:
- return true;
-
- case rapidjson::kStringType:
- return std::string { value.GetString(), value.GetStringLength() };
-
- case rapidjson::kNumberType:
- if (value.IsUint64()) return value.GetUint64();
- if (value.IsInt64()) return value.GetInt64();
- return value.GetDouble();
-
- default:
- return false;
- }
-}
diff --git a/src/mbgl/style/value.hpp b/src/mbgl/style/value.hpp
deleted file mode 100644
index 869ddd6668..0000000000
--- a/src/mbgl/style/value.hpp
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef MBGL_STYLE_VALUE
-#define MBGL_STYLE_VALUE
-
-#include <mbgl/util/variant.hpp>
-#include <mbgl/util/rapidjson.hpp>
-
-#include <cstdlib>
-#include <cerrno>
-
-namespace mbgl {
-
-typedef variant<bool, int64_t, uint64_t, double, std::string> Value;
-
-std::string toString(const Value &value);
-
-Value parseValue(const JSValue&);
-
-} // namespace mbgl
-
-#endif
diff --git a/src/mbgl/style/value_comparison.hpp b/src/mbgl/style/value_comparison.hpp
deleted file mode 100644
index 9f6ae3a0de..0000000000
--- a/src/mbgl/style/value_comparison.hpp
+++ /dev/null
@@ -1,109 +0,0 @@
-#ifndef MBGL_STYLE_VALUE_COMPARISON
-#define MBGL_STYLE_VALUE_COMPARISON
-
-#include <mbgl/style/value.hpp>
-#include <cstdlib>
-#include <cerrno>
-
-namespace mbgl {
-
-namespace util {
-
-namespace detail {
-
-template <typename Operator>
-struct relaxed_operator_visitor {
- typedef bool result_type;
-
- template <typename T0, typename T1>
- inline bool operator()(T0, T1) const { return false; }
-
- template <typename T>
- inline bool operator()(T lhs, T rhs) const { return Operator()(lhs, rhs); }
-
- inline bool operator()(int64_t lhs, uint64_t rhs) const {
- return Operator()(double(lhs), double(rhs));
- }
-
- inline bool operator()(int64_t lhs, double rhs) const {
- return Operator()(double(lhs), rhs);
- }
-
- inline bool operator()(uint64_t lhs, int64_t rhs) const {
- return Operator()(double(lhs), double(rhs));
- }
-
- inline bool operator()(uint64_t lhs, double rhs) const {
- return Operator()(double(lhs), rhs);
- }
-
- inline bool operator()(double lhs, uint64_t rhs) const {
- return Operator()(lhs, double(rhs));
- }
-
- inline bool operator()(double lhs, int64_t rhs) const {
- return Operator()(lhs, double(rhs));
- }
-};
-
-struct relaxed_equal_operator {
- template <typename T0, typename T1>
- inline bool operator()(T0 lhs, T1 rhs) const { return lhs == rhs; }
-};
-
-struct relaxed_not_equal_operator {
- template <typename T0, typename T1>
- inline bool operator()(T0 lhs, T1 rhs) const { return lhs != rhs; }
-};
-
-struct relaxed_greater_operator {
- template <typename T0, typename T1>
- inline bool operator()(T0 lhs, T1 rhs) const { return lhs > rhs; }
-};
-
-struct relaxed_greater_equal_operator {
- template <typename T0, typename T1>
- inline bool operator()(T0 lhs, T1 rhs) const { return lhs >= rhs; }
-};
-
-struct relaxed_less_operator {
- template <typename T0, typename T1>
- inline bool operator()(T0 lhs, T1 rhs) const { return lhs < rhs; }
-};
-
-struct relaxed_less_equal_operator {
- template <typename T0, typename T1>
- inline bool operator()(T0 lhs, T1 rhs) const { return lhs <= rhs; }
-};
-
-} // end namespace detail
-
-inline bool relaxed_equal(Value const &lhs, Value const &rhs) {
- return apply_visitor(detail::relaxed_operator_visitor<detail::relaxed_equal_operator>(), lhs, rhs);
-}
-
-inline bool relaxed_not_equal(Value const &lhs, Value const &rhs) {
- return apply_visitor(detail::relaxed_operator_visitor<detail::relaxed_not_equal_operator>(), lhs, rhs);
-}
-
-inline bool relaxed_greater(Value const &lhs, Value const &rhs) {
- return apply_visitor(detail::relaxed_operator_visitor<detail::relaxed_greater_operator>(), lhs, rhs);
-}
-
-inline bool relaxed_greater_equal(Value const &lhs, Value const &rhs) {
- return apply_visitor(detail::relaxed_operator_visitor<detail::relaxed_greater_equal_operator>(), lhs, rhs);
-}
-
-inline bool relaxed_less(Value const &lhs, Value const &rhs) {
- return apply_visitor(detail::relaxed_operator_visitor<detail::relaxed_less_operator>(), lhs, rhs);
-}
-
-inline bool relaxed_less_equal(Value const &lhs, Value const &rhs) {
- return apply_visitor(detail::relaxed_operator_visitor<detail::relaxed_less_equal_operator>(), lhs, rhs);
-}
-
-} // namespace util
-
-} // namespace mbgl
-
-#endif
diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp
index fa41481d4d..e3c7437a9c 100644
--- a/src/mbgl/tile/geometry_tile.cpp
+++ b/src/mbgl/tile/geometry_tile.cpp
@@ -1,6 +1,4 @@
#include <mbgl/tile/geometry_tile.hpp>
-#include <mbgl/style/filter_expression.hpp>
-#include <mbgl/style/filter_expression_private.hpp>
namespace mbgl {
@@ -12,6 +10,4 @@ optional<Value> GeometryTileFeatureExtractor::getValue(const std::string& key) c
return feature.getValue(key);
}
-template bool evaluate(const FilterExpression&, const GeometryTileFeatureExtractor&);
-
} // namespace mbgl
diff --git a/src/mbgl/tile/geometry_tile.hpp b/src/mbgl/tile/geometry_tile.hpp
index d6e073e203..71077d03ac 100644
--- a/src/mbgl/tile/geometry_tile.hpp
+++ b/src/mbgl/tile/geometry_tile.hpp
@@ -1,7 +1,7 @@
#ifndef MBGL_MAP_GEOMETRY_TILE
#define MBGL_MAP_GEOMETRY_TILE
-#include <mbgl/style/value.hpp>
+#include <mbgl/util/value.hpp>
#include <mbgl/util/chrono.hpp>
#include <mbgl/util/ptr.hpp>
#include <mbgl/util/vec.hpp>
diff --git a/src/mbgl/util/value.hpp b/src/mbgl/util/value.hpp
new file mode 100644
index 0000000000..78507c7f25
--- /dev/null
+++ b/src/mbgl/util/value.hpp
@@ -0,0 +1,9 @@
+#pragma once
+
+#include <mbgl/util/variant.hpp>
+
+namespace mbgl {
+
+typedef variant<bool, int64_t, uint64_t, double, std::string> Value;
+
+} // namespace mbgl