separate comparisons and expressions
This commit is contained in:
65
include/llmr/style/filter_comparison.hpp
Normal file
65
include/llmr/style/filter_comparison.hpp
Normal file
@@ -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
|
||||
23
include/llmr/style/filter_comparison_private.hpp
Normal file
23
include/llmr/style/filter_comparison_private.hpp
Normal file
@@ -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
|
||||
@@ -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;
|
||||
|
||||
@@ -2,22 +2,10 @@
|
||||
#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) {
|
||||
|
||||
@@ -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>
|
||||
|
||||
143
src/style/filter_comparison.cpp
Normal file
143
src/style/filter_comparison.cpp
Normal file
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
@@ -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",
|
||||
],
|
||||
}
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user