summaryrefslogtreecommitdiff
path: root/include/mbgl/style
diff options
context:
space:
mode:
authorJohn Firebaugh <john.firebaugh@gmail.com>2014-10-28 11:17:03 -0400
committerJohn Firebaugh <john.firebaugh@gmail.com>2014-11-04 12:26:14 -0800
commitc151f12997d2560353cf7692d033fb123440a8b0 (patch)
treee24248df2899059caea190fd5c48331c5ac30786 /include/mbgl/style
parentf25cf706891edd2db63b0ea34918cc87bb631c20 (diff)
downloadqtlocation-mapboxgl-c151f12997d2560353cf7692d033fb123440a8b0.tar.gz
Implement v6 filters
Diffstat (limited to 'include/mbgl/style')
-rw-r--r--include/mbgl/style/filter_comparison.hpp65
-rw-r--r--include/mbgl/style/filter_comparison_private.hpp23
-rw-r--r--include/mbgl/style/filter_expression.hpp139
-rw-r--r--include/mbgl/style/filter_expression_private.hpp161
-rw-r--r--include/mbgl/style/style_parser.hpp4
-rw-r--r--include/mbgl/style/value.hpp2
-rw-r--r--include/mbgl/style/value_comparison.hpp36
7 files changed, 227 insertions, 203 deletions
diff --git a/include/mbgl/style/filter_comparison.hpp b/include/mbgl/style/filter_comparison.hpp
deleted file mode 100644
index 1b0a9b5486..0000000000
--- a/include/mbgl/style/filter_comparison.hpp
+++ /dev/null
@@ -1,65 +0,0 @@
-#ifndef MBGL_STYLE_FILTER_COMPARISON
-#define MBGL_STYLE_FILTER_COMPARISON
-
-#include <mbgl/style/value.hpp>
-
-#include <vector>
-#include <string>
-#include <iosfwd>
-
-namespace mbgl {
-
-class FilterComparison {
-public:
- enum class Operator : uint8_t {
- Equal,
- NotEqual,
- Greater,
- GreaterEqual,
- Less,
- LessEqual,
- In,
- NotIn
- };
-
- class Instance {
- public:
- Instance(Operator op_, std::vector<Value> &&values_)
- : op(op_), values(values_) {}
-
- bool compare(const std::vector<Value> &property_values) const;
-
- private:
- Operator op = Operator::Equal;
- std::vector<Value> values;
-
- friend std::ostream& operator <<(std::ostream &, const Instance &);
- };
-
-public:
- FilterComparison(const std::string &field_) : field(field_) {};
-
- const std::string &getField() const;
- template <typename Extractor> inline bool compare(const Extractor &extractor) const;
-
- template <typename ...Args>
- inline void add(Args&& ...args) {
- instances.emplace_back(::std::forward<Args>(args)...);
- }
-
-private:
- std::string field;
- std::vector<Instance> instances;
-
- friend std::ostream& operator <<(std::ostream &, const FilterComparison &);
-};
-
-std::ostream& operator <<(std::ostream &s, const FilterComparison &comparison);
-std::ostream& operator <<(std::ostream &s, const FilterComparison::Instance &instance);
-
-
-FilterComparison::Operator parseFilterComparisonOperator(const std::string &op);
-
-}
-
-#endif
diff --git a/include/mbgl/style/filter_comparison_private.hpp b/include/mbgl/style/filter_comparison_private.hpp
deleted file mode 100644
index 6486832424..0000000000
--- a/include/mbgl/style/filter_comparison_private.hpp
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef MBGL_STYLE_FILTER_COMPARISON_PRIVATE
-#define MBGL_STYLE_FILTER_COMPARISON_PRIVATE
-
-#include "filter_comparison.hpp"
-
-namespace mbgl {
-
-template <typename Extractor>
-inline bool FilterComparison::compare(const Extractor &extractor) const {
- const std::vector<Value> values = extractor.getValues(field);
-
- // All instances are ANDed together.
- for (const Instance &instance : instances) {
- if (!instance.compare(values)) {
- return false;
- }
- }
- return true;
-}
-
-}
-
-#endif
diff --git a/include/mbgl/style/filter_expression.hpp b/include/mbgl/style/filter_expression.hpp
index 915d3931d1..8c6f447770 100644
--- a/include/mbgl/style/filter_expression.hpp
+++ b/include/mbgl/style/filter_expression.hpp
@@ -1,54 +1,125 @@
#ifndef MBGL_STYLE_FILTER_EXPRESSION
#define MBGL_STYLE_FILTER_EXPRESSION
-#include <mbgl/style/filter_comparison.hpp>
-#include <mbgl/util/recursive_wrapper.hpp>
+#include <mbgl/style/value.hpp>
-#include <iosfwd>
+#include <rapidjson/document.h>
+
+#include <string>
+#include <vector>
namespace mbgl {
-class FilterExpression {
-public:
- typedef mapbox::util::recursive_wrapper<FilterExpression> Wrapper;
+typedef mapbox::util::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 rapidjson::Value&);
+
+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;
- enum class Operator : uint8_t {
- And,
- Or,
- Xor,
- Nor
- };
+ template <class Extractor>
+ bool evaluate(const Extractor&) const;
+};
- enum class GeometryType : uint8_t {
- Any,
- Point,
- LineString,
- Polygon
- };
+struct NotEqualsExpression {
+ std::string key;
+ Value value;
-public:
- FilterExpression() = default;
- FilterExpression(Operator op_) : op(op_) {};
+ template <class Extractor>
+ bool evaluate(const Extractor&) const;
+};
- bool empty() const;
+struct LessThanExpression {
+ std::string key;
+ Value value;
- template <typename Extractor> bool compare(const Extractor &extractor) const;
- void add(const FilterComparison &comparison);
- void add(const FilterExpression &expression);
- void setGeometryType(GeometryType g);
+ 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;
+};
-private:
- Operator op = Operator::And;
- GeometryType type = GeometryType::Any;
- std::vector<FilterComparison> comparisons;
- std::vector<FilterExpression::Wrapper> expressions;
+struct GreaterThanEqualsExpression {
+ std::string key;
+ Value value;
- friend std::ostream& operator <<(std::ostream &, const FilterExpression &);
+ template <class Extractor>
+ bool evaluate(const Extractor&) const;
};
-std::ostream& operator <<(std::ostream &s, const FilterExpression &expression);
+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;
+};
-FilterExpression::GeometryType parseGeometryType(const std::string &geometry);
}
#endif
diff --git a/include/mbgl/style/filter_expression_private.hpp b/include/mbgl/style/filter_expression_private.hpp
index 9379d250ba..381f8f617c 100644
--- a/include/mbgl/style/filter_expression_private.hpp
+++ b/include/mbgl/style/filter_expression_private.hpp
@@ -1,75 +1,118 @@
-#ifndef MBGL_STYLE_FILTER_EXPRESSION_PRIVATE
-#define MBGL_STYLE_FILTER_EXPRESSION_PRIVATE
-
-#include "filter_expression.hpp"
-#include "filter_comparison_private.hpp"
+#include <mbgl/util/optional.hpp>
+#include <mbgl/style/value_comparison.hpp>
namespace mbgl {
-template <typename Extractor>
-bool FilterExpression::compare(const Extractor &extractor) const {
- if (type != GeometryType::Any && extractor.getType() != type && extractor.getType() != GeometryType::Any) {
+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 {
+ mapbox::util::optional<Value> actual = extractor.getValue(key);
+ return actual && util::relaxed_equal(*actual, value);
+}
+
+template <class Extractor>
+bool NotEqualsExpression::evaluate(const Extractor& extractor) const {
+ mapbox::util::optional<Value> actual = extractor.getValue(key);
+ return !actual || util::relaxed_not_equal(*actual, value);
+}
+
+template <class Extractor>
+bool LessThanExpression::evaluate(const Extractor& extractor) const {
+ mapbox::util::optional<Value> actual = extractor.getValue(key);
+ return actual && util::relaxed_less(*actual, value);
+}
+
+template <class Extractor>
+bool LessThanEqualsExpression::evaluate(const Extractor& extractor) const {
+ mapbox::util::optional<Value> actual = extractor.getValue(key);
+ return actual && util::relaxed_less_equal(*actual, value);
+}
+
+template <class Extractor>
+bool GreaterThanExpression::evaluate(const Extractor& extractor) const {
+ mapbox::util::optional<Value> actual = extractor.getValue(key);
+ return actual && util::relaxed_greater(*actual, value);
+}
+
+template <class Extractor>
+bool GreaterThanEqualsExpression::evaluate(const Extractor& extractor) const {
+ mapbox::util::optional<Value> actual = extractor.getValue(key);
+ return actual && util::relaxed_greater_equal(*actual, value);
+}
+
+template <class Extractor>
+bool InExpression::evaluate(const Extractor& extractor) const {
+ mapbox::util::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;
+}
- switch (op) {
- case Operator::And:
- for (const FilterComparison &comparison : comparisons) {
- if (!comparison.compare(extractor)) {
- return false;
- }
- }
- for (const FilterExpression &expression: expressions) {
- if (!expression.compare(extractor)) {
- return false;
- }
- }
+template <class Extractor>
+bool NotInExpression::evaluate(const Extractor& extractor) const {
+ mapbox::util::optional<Value> actual = extractor.getValue(key);
+ if (!actual)
return true;
- case Operator::Or:
- for (const FilterComparison &comparison : comparisons) {
- if (comparison.compare(extractor)) {
- return true;
- }
+ for (const auto& v: values) {
+ if (util::relaxed_equal(*actual, v)) {
+ return false;
}
- for (const FilterExpression &expression: expressions) {
- if (expression.compare(extractor)) {
- return true;
- }
- }
- return false;
- case Operator::Xor: {
- int count = 0;
- for (const FilterComparison &comparison : comparisons) {
- count += comparison.compare(extractor);
- if (count > 1) {
- return false;
- }
- }
- for (const FilterExpression &expression: expressions) {
- count += expression.compare(extractor);
- if (count > 1) {
- return false;
- }
- }
- return count == 1;
}
- case Operator::Nor:
- for (const FilterComparison &comparison : comparisons) {
- if (comparison.compare(extractor)) {
- 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;
}
- for (const FilterExpression &expression: expressions) {
- if (expression.compare(extractor)) {
- return false;
- }
+ }
+ 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;
- default:
- return true;
}
+ 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;
}
-#endif
+}
diff --git a/include/mbgl/style/style_parser.hpp b/include/mbgl/style/style_parser.hpp
index fc253bb1dd..a1c57cf2df 100644
--- a/include/mbgl/style/style_parser.hpp
+++ b/include/mbgl/style/style_parser.hpp
@@ -85,11 +85,7 @@ private:
template <typename T>
T parseFunctionArgument(JSVal value);
-
- FilterExpression parseFilter(JSVal, FilterExpression::Operator op);
FilterExpression parseFilter(JSVal);
- Value parseValue(JSVal value);
- std::vector<Value> parseValues(JSVal values);
private:
std::unordered_map<std::string, const rapidjson::Value *> constants;
diff --git a/include/mbgl/style/value.hpp b/include/mbgl/style/value.hpp
index b981f1db9c..87d6f4cda3 100644
--- a/include/mbgl/style/value.hpp
+++ b/include/mbgl/style/value.hpp
@@ -3,6 +3,7 @@
#include <mbgl/util/variant.hpp>
#include <mbgl/util/pbf.hpp>
+#include <rapidjson/document.h>
#include <cstdlib>
#include <cerrno>
@@ -14,6 +15,7 @@ typedef mapbox::util::variant<bool, int64_t, uint64_t, double, std::string> Valu
std::string toString(const Value &value);
Value parseValue(pbf data);
+Value parseValue(const rapidjson::Value&);
namespace util {
inline bool parseNumericString(const std::string &str, double &result) {
diff --git a/include/mbgl/style/value_comparison.hpp b/include/mbgl/style/value_comparison.hpp
index 41c1d44123..98e29afa7c 100644
--- a/include/mbgl/style/value_comparison.hpp
+++ b/include/mbgl/style/value_comparison.hpp
@@ -15,35 +15,35 @@ template <typename Operator>
struct relaxed_operator_visitor {
typedef bool result_type;
- inline bool operator()(bool lhs, bool rhs) const { return Operator()(lhs, rhs); }
-
- template <typename T, class = typename std::enable_if<std::is_arithmetic<T>::value>::type>
- inline bool operator()(bool lhs, T rhs) const { return Operator()(T(lhs), rhs); }
+ template <typename T0, typename T1>
+ inline bool operator()(T0, T1) const { return false; }
- template <typename T, class = typename std::enable_if<std::is_arithmetic<T>::value>::type>
- inline bool operator()(T lhs, bool rhs) const { return Operator()(lhs, T(rhs)); }
+ 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 lhs < 0 ? false : Operator()(uint64_t(lhs), rhs);
+ 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 rhs < 0 ? false : Operator()(lhs, uint64_t(rhs));
+ return Operator()(double(lhs), double(rhs));
}
- template <typename T, class = typename std::enable_if<std::is_arithmetic<T>::value>::type>
- inline bool operator()(const std::string &lhs, T rhs) const {
- double value;
- return parseNumericString(lhs, value) ? Operator()(value, double(rhs)) : false;
+ inline bool operator()(uint64_t lhs, double rhs) const {
+ return Operator()(double(lhs), rhs);
}
- template <typename T, class = typename std::enable_if<std::is_arithmetic<T>::value>::type>
- inline bool operator()(T lhs, const std::string &rhs) const {
- double value;
- return parseNumericString(rhs, value) ? Operator()(double(lhs), value) : false;
+ inline bool operator()(double lhs, uint64_t rhs) const {
+ return Operator()(lhs, double(rhs));
}
- template <typename T0, typename T1>
- inline bool operator()(T0 lhs, T1 rhs) const { return Operator()(lhs, rhs); }
+ inline bool operator()(double lhs, int64_t rhs) const {
+ return Operator()(lhs, double(rhs));
+ }
};
struct relaxed_equal_operator {