diff options
author | John Firebaugh <john.firebaugh@gmail.com> | 2014-10-28 11:17:03 -0400 |
---|---|---|
committer | John Firebaugh <john.firebaugh@gmail.com> | 2014-11-04 12:26:14 -0800 |
commit | c151f12997d2560353cf7692d033fb123440a8b0 (patch) | |
tree | e24248df2899059caea190fd5c48331c5ac30786 /include/mbgl/style | |
parent | f25cf706891edd2db63b0ea34918cc87bb631c20 (diff) | |
download | qtlocation-mapboxgl-c151f12997d2560353cf7692d033fb123440a8b0.tar.gz |
Implement v6 filters
Diffstat (limited to 'include/mbgl/style')
-rw-r--r-- | include/mbgl/style/filter_comparison.hpp | 65 | ||||
-rw-r--r-- | include/mbgl/style/filter_comparison_private.hpp | 23 | ||||
-rw-r--r-- | include/mbgl/style/filter_expression.hpp | 139 | ||||
-rw-r--r-- | include/mbgl/style/filter_expression_private.hpp | 161 | ||||
-rw-r--r-- | include/mbgl/style/style_parser.hpp | 4 | ||||
-rw-r--r-- | include/mbgl/style/value.hpp | 2 | ||||
-rw-r--r-- | include/mbgl/style/value_comparison.hpp | 36 |
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 { |