separate comparisons and expressions

This commit is contained in:
Konstantin Käfer
2014-07-16 18:26:05 -07:00
parent a1d7da71c6
commit 4d1d2c5d5d
9 changed files with 240 additions and 207 deletions

View 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

View 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

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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>

View 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;
}

View File

@@ -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;
}

View File

@@ -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>

View File

@@ -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",
],
}
]