diff options
-rw-r--r-- | include/llmr/style/filter_comparison.hpp | 65 | ||||
-rw-r--r-- | include/llmr/style/filter_comparison_private.hpp | 23 | ||||
-rw-r--r-- | include/llmr/style/filter_expression.hpp | 56 | ||||
-rw-r--r-- | include/llmr/style/filter_expression_private.hpp | 14 | ||||
-rw-r--r-- | src/map/vector_tile.cpp | 2 | ||||
-rw-r--r-- | src/style/filter_comparison.cpp | 143 | ||||
-rw-r--r-- | src/style/filter_expression.cpp | 134 | ||||
-rw-r--r-- | test/comparison.cpp (renamed from test/expressions.cpp) | 2 | ||||
-rw-r--r-- | test/test.gyp | 8 |
9 files changed, 240 insertions, 207 deletions
diff --git a/include/llmr/style/filter_comparison.hpp b/include/llmr/style/filter_comparison.hpp new file mode 100644 index 0000000000..0e7a929e1c --- /dev/null +++ b/include/llmr/style/filter_comparison.hpp @@ -0,0 +1,65 @@ +#ifndef LLMR_STYLE_FILTER_COMPARISON +#define LLMR_STYLE_FILTER_COMPARISON + +#include <llmr/style/value.hpp> + +#include <vector> +#include <string> +#include <iosfwd> + +namespace llmr { + +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/llmr/style/filter_comparison_private.hpp b/include/llmr/style/filter_comparison_private.hpp new file mode 100644 index 0000000000..d778097730 --- /dev/null +++ b/include/llmr/style/filter_comparison_private.hpp @@ -0,0 +1,23 @@ +#ifndef LLMR_STYLE_FILTER_COMPARISON_PRIVATE +#define LLMR_STYLE_FILTER_COMPARISON_PRIVATE + +#include "filter_comparison.hpp" + +namespace llmr { + +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/llmr/style/filter_expression.hpp b/include/llmr/style/filter_expression.hpp index 97ba8c9719..db67aa43a1 100644 --- a/include/llmr/style/filter_expression.hpp +++ b/include/llmr/style/filter_expression.hpp @@ -1,67 +1,13 @@ #ifndef LLMR_STYLE_FILTER_EXPRESSION #define LLMR_STYLE_FILTER_EXPRESSION -#include <llmr/style/value.hpp> +#include <llmr/style/filter_comparison.hpp> #include <llmr/util/recursive_wrapper.hpp> -#include <vector> -#include <string> #include <iosfwd> namespace llmr { -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); - - class FilterExpression { public: typedef util::recursive_wrapper<FilterExpression> Wrapper; diff --git a/include/llmr/style/filter_expression_private.hpp b/include/llmr/style/filter_expression_private.hpp index c21fcac085..91c434e6ff 100644 --- a/include/llmr/style/filter_expression_private.hpp +++ b/include/llmr/style/filter_expression_private.hpp @@ -2,23 +2,11 @@ #define LLMR_STYLE_FILTER_EXPRESSION_PRIVATE #include "filter_expression.hpp" +#include "filter_comparison_private.hpp" namespace llmr { 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; -} - -template <typename Extractor> bool FilterExpression::compare(const Extractor &extractor) const { if (type != GeometryType::Any && extractor.getType() != type && extractor.getType() != GeometryType::Any) { return false; diff --git a/src/map/vector_tile.cpp b/src/map/vector_tile.cpp index 86844c5d61..393a72c14b 100644 --- a/src/map/vector_tile.cpp +++ b/src/map/vector_tile.cpp @@ -1,4 +1,6 @@ #include <llmr/map/vector_tile.hpp> +#include <llmr/style/filter_expression_private.hpp> +#include <llmr/style/filter_comparison_private.hpp> #include <algorithm> #include <iostream> diff --git a/src/style/filter_comparison.cpp b/src/style/filter_comparison.cpp new file mode 100644 index 0000000000..c3971cdc0b --- /dev/null +++ b/src/style/filter_comparison.cpp @@ -0,0 +1,143 @@ +#include <llmr/map/vector_tile.hpp> +#include <llmr/style/filter_comparison_private.hpp> + +#include <llmr/style/value_comparison.hpp> + +#include <ostream> + +namespace llmr { + + +inline bool includes(const Value &property_value, const std::vector<Value> &filter_values) { + for (const Value &filter_value : filter_values) { + if (util::relaxed_equal(property_value, filter_value)) { + return true; + } + } + return false; +} + +template <typename Comparer> +inline bool compare(const Value &property_value, const std::vector<Value> &filter_values, const Comparer &comparer) { + for (const Value &filter_value : filter_values) { + if (!comparer(property_value, filter_value)) { + return false; + } + } + return true; +} + +template <typename Comparer> +inline bool all(const std::vector<Value> &property_values, const std::vector<Value> &filter_values, const Comparer &comparer) { + for (const Value &property_value : property_values) { + if (!compare(property_value, filter_values, comparer)) { + return false; + } + } + return true; +} + + +inline bool set_equal(const std::vector<Value> &property_values, const std::vector<Value> &filter_values) { + for (const Value &property_value : property_values) { + if (!includes(property_value, filter_values)) { + return false; + } + } + if (property_values.size() == filter_values.size()) { + // Optimization: When the count is the same, the set is guaranteed to be identical. + return true; + } + // Otherwise, check again for identical reverse-mapped values. + for (const Value &filter_value : filter_values) { + if (!includes(filter_value, property_values)) { + return false; + } + } + return true; +} + + +bool FilterComparison::Instance::compare(const std::vector<Value> &property_values) const { + switch (op) { + case Operator::Equal: + return set_equal(property_values, values); + case Operator::NotEqual: + return !set_equal(property_values, values); + case Operator::In: + for (const Value &property_value : property_values) { + if (includes(property_value, values)) { + return true; + } + } + return false; + case Operator::NotIn: + for (const Value &property_value : property_values) { + if (!includes(property_value, values)) { + return true; + } + } + return false; + case Operator::Greater: + return all(property_values, values, util::relaxed_greater); + case Operator::GreaterEqual: + return all(property_values, values, util::relaxed_greater_equal); + case Operator::Less: + return all(property_values, values, util::relaxed_less); + case Operator::LessEqual: + return all(property_values, values, util::relaxed_less_equal); + default: + return false; + } +} + + +const std::string &FilterComparison::getField() const { + return field; +} + +std::ostream& operator <<(std::ostream &s, const FilterComparison &comparison) { + s << "comparison" << std::endl; + for (const FilterComparison::Instance &instance : comparison.instances) { + s << " - " << comparison.field << " " << instance << std::endl; + } + return s; +} + + +std::ostream& operator <<(std::ostream &s, const FilterComparison::Instance &instance) { + switch (instance.op) { + case FilterComparison::Operator::Equal: s << "=="; break; + case FilterComparison::Operator::NotEqual: s << "!="; break; + case FilterComparison::Operator::Greater: s << ">"; break; + case FilterComparison::Operator::GreaterEqual: s << ">="; break; + case FilterComparison::Operator::Less: s << "<"; break; + case FilterComparison::Operator::LessEqual: s << "<="; break; + case FilterComparison::Operator::In: s << "in"; break; + case FilterComparison::Operator::NotIn: s << "!in"; break; + } + + s << " [ "; + for (const Value &value : instance.values) { + s << toString(value) << " "; + } + s << "]"; + return s; +} + + +FilterComparison::Operator parseFilterComparisonOperator(const std::string &op) { + if (op == "==") return FilterComparison::Operator::Equal; + if (op == "!=") return FilterComparison::Operator::NotEqual; + if (op == ">") return FilterComparison::Operator::Greater; + if (op == ">=") return FilterComparison::Operator::GreaterEqual; + if (op == "<") return FilterComparison::Operator::Less; + if (op == "<=") return FilterComparison::Operator::LessEqual; + if (op == "in") return FilterComparison::Operator::In; + if (op == "!in") return FilterComparison::Operator::NotIn; + return FilterComparison::Operator::Equal; +} + +template bool FilterComparison::compare(const VectorTileTagExtractor &extractor) const; + +} diff --git a/src/style/filter_expression.cpp b/src/style/filter_expression.cpp index aaa898b41a..4246422786 100644 --- a/src/style/filter_expression.cpp +++ b/src/style/filter_expression.cpp @@ -7,138 +7,6 @@ namespace llmr { - -inline bool includes(const Value &property_value, const std::vector<Value> &filter_values) { - for (const Value &filter_value : filter_values) { - if (util::relaxed_equal(property_value, filter_value)) { - return true; - } - } - return false; -} - -template <typename Comparer> -inline bool compare(const Value &property_value, const std::vector<Value> &filter_values, const Comparer &comparer) { - for (const Value &filter_value : filter_values) { - if (!comparer(property_value, filter_value)) { - return false; - } - } - return true; -} - -template <typename Comparer> -inline bool all(const std::vector<Value> &property_values, const std::vector<Value> &filter_values, const Comparer &comparer) { - for (const Value &property_value : property_values) { - if (!compare(property_value, filter_values, comparer)) { - return false; - } - } - return true; -} - - -inline bool set_equal(const std::vector<Value> &property_values, const std::vector<Value> &filter_values) { - for (const Value &property_value : property_values) { - if (!includes(property_value, filter_values)) { - return false; - } - } - if (property_values.size() == filter_values.size()) { - // Optimization: When the count is the same, the set is guaranteed to be identical. - return true; - } - // Otherwise, check again for identical reverse-mapped values. - for (const Value &filter_value : filter_values) { - if (!includes(filter_value, property_values)) { - return false; - } - } - return true; -} - - -bool FilterComparison::Instance::compare(const std::vector<Value> &property_values) const { - switch (op) { - case Operator::Equal: - return set_equal(property_values, values); - case Operator::NotEqual: - return !set_equal(property_values, values); - case Operator::In: - for (const Value &property_value : property_values) { - if (includes(property_value, values)) { - return true; - } - } - return false; - case Operator::NotIn: - for (const Value &property_value : property_values) { - if (!includes(property_value, values)) { - return true; - } - } - return false; - case Operator::Greater: - return all(property_values, values, util::relaxed_greater); - case Operator::GreaterEqual: - return all(property_values, values, util::relaxed_greater_equal); - case Operator::Less: - return all(property_values, values, util::relaxed_less); - case Operator::LessEqual: - return all(property_values, values, util::relaxed_less_equal); - default: - return false; - } -} - - -const std::string &FilterComparison::getField() const { - return field; -} - -std::ostream& operator <<(std::ostream &s, const FilterComparison &comparison) { - s << "comparison" << std::endl; - for (const FilterComparison::Instance &instance : comparison.instances) { - s << " - " << comparison.field << " " << instance << std::endl; - } - return s; -} - - -std::ostream& operator <<(std::ostream &s, const FilterComparison::Instance &instance) { - switch (instance.op) { - case FilterComparison::Operator::Equal: s << "=="; break; - case FilterComparison::Operator::NotEqual: s << "!="; break; - case FilterComparison::Operator::Greater: s << ">"; break; - case FilterComparison::Operator::GreaterEqual: s << ">="; break; - case FilterComparison::Operator::Less: s << "<"; break; - case FilterComparison::Operator::LessEqual: s << "<="; break; - case FilterComparison::Operator::In: s << "in"; break; - case FilterComparison::Operator::NotIn: s << "!in"; break; - } - - s << " [ "; - for (const Value &value : instance.values) { - s << toString(value) << " "; - } - s << "]"; - return s; -} - - -FilterComparison::Operator parseFilterComparisonOperator(const std::string &op) { - if (op == "==") return FilterComparison::Operator::Equal; - if (op == "!=") return FilterComparison::Operator::NotEqual; - if (op == ">") return FilterComparison::Operator::Greater; - if (op == ">=") return FilterComparison::Operator::GreaterEqual; - if (op == "<") return FilterComparison::Operator::Less; - if (op == "<=") return FilterComparison::Operator::LessEqual; - if (op == "in") return FilterComparison::Operator::In; - if (op == "!in") return FilterComparison::Operator::NotIn; - return FilterComparison::Operator::Equal; -} - - std::ostream& operator <<(std::ostream &s, FilterExpression::Operator op) { switch (op) { case FilterExpression::Operator::And: s << "AND"; break; @@ -193,8 +61,6 @@ std::ostream& operator <<(std::ostream &s, const FilterExpression &expression) { return s; } -// Explicit instantiation -template bool FilterComparison::compare(const VectorTileTagExtractor &extractor) const; template bool FilterExpression::compare(const VectorTileTagExtractor &extractor) const; } diff --git a/test/expressions.cpp b/test/comparison.cpp index de398fe7dc..44a1cc1bdd 100644 --- a/test/expressions.cpp +++ b/test/comparison.cpp @@ -1,7 +1,7 @@ #include <iostream> #include "gtest/gtest.h" -#include <llmr/style/filter_expression.hpp> +#include <llmr/style/filter_comparison_private.hpp> #include <llmr/style/filter_expression_private.hpp> #include <map> diff --git a/test/test.gyp b/test/test.gyp index 0f065a5beb..7e52de9e6a 100644 --- a/test/test.gyp +++ b/test/test.gyp @@ -123,15 +123,15 @@ ] }, { - "target_name": "expressions", - "product_name": "test_expressions", + "target_name": "comparisons", + "product_name": "test_comparisons", "type": "executable", "libraries": [ "-lpthread", ], "sources": [ "./main.cpp", - "./expressions.cpp", + "./comparisons.cpp", ], "dependencies": [ "../deps/gtest/gtest.gyp:gtest", @@ -204,7 +204,7 @@ "tile", "functions", "headless", - "expressions", + "comparisons", ], } ] |