Implement v6 filters
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
#include <mbgl/style/value.hpp>
|
||||
#include <mbgl/text/glyph.hpp>
|
||||
#include <mbgl/util/pbf.hpp>
|
||||
#include <mbgl/util/optional.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <iosfwd>
|
||||
@@ -44,14 +45,14 @@ public:
|
||||
VectorTileTagExtractor(const VectorTileLayer &layer);
|
||||
|
||||
void setTags(const pbf &pbf);
|
||||
std::vector<Value> getValues(const std::string &key) const;
|
||||
void setType(FilterExpression::GeometryType type);
|
||||
FilterExpression::GeometryType getType() const;
|
||||
mapbox::util::optional<Value> getValue(const std::string &key) const;
|
||||
void setType(FeatureType type);
|
||||
FeatureType getType() const;
|
||||
|
||||
private:
|
||||
const VectorTileLayer &layer_;
|
||||
pbf tags_;
|
||||
FilterExpression::GeometryType type_ = FilterExpression::GeometryType::Any;
|
||||
FeatureType type_ = FeatureType::Unknown;
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
enum class Operator : uint8_t {
|
||||
And,
|
||||
Or,
|
||||
Xor,
|
||||
Nor
|
||||
};
|
||||
FilterExpression parseFilterExpression(const rapidjson::Value&);
|
||||
|
||||
enum class GeometryType : uint8_t {
|
||||
Any,
|
||||
Point,
|
||||
LineString,
|
||||
Polygon
|
||||
};
|
||||
template <class Extractor>
|
||||
bool evaluate(const FilterExpression&, const Extractor&);
|
||||
|
||||
public:
|
||||
FilterExpression() = default;
|
||||
FilterExpression(Operator op_) : op(op_) {};
|
||||
|
||||
bool empty() const;
|
||||
|
||||
template <typename Extractor> bool compare(const Extractor &extractor) const;
|
||||
void add(const FilterComparison &comparison);
|
||||
void add(const FilterExpression &expression);
|
||||
void setGeometryType(GeometryType g);
|
||||
|
||||
private:
|
||||
Operator op = Operator::And;
|
||||
GeometryType type = GeometryType::Any;
|
||||
std::vector<FilterComparison> comparisons;
|
||||
std::vector<FilterExpression::Wrapper> expressions;
|
||||
|
||||
friend std::ostream& operator <<(std::ostream &, const FilterExpression &);
|
||||
struct NullExpression {
|
||||
template <class Extractor>
|
||||
bool evaluate(const Extractor&) const { return true; }
|
||||
};
|
||||
|
||||
std::ostream& operator <<(std::ostream &s, const FilterExpression &expression);
|
||||
struct EqualsExpression {
|
||||
std::string key;
|
||||
Value value;
|
||||
|
||||
template <class Extractor>
|
||||
bool evaluate(const Extractor&) const;
|
||||
};
|
||||
|
||||
struct NotEqualsExpression {
|
||||
std::string key;
|
||||
Value value;
|
||||
|
||||
template <class Extractor>
|
||||
bool evaluate(const Extractor&) const;
|
||||
};
|
||||
|
||||
struct LessThanExpression {
|
||||
std::string key;
|
||||
Value value;
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
struct GreaterThanEqualsExpression {
|
||||
std::string key;
|
||||
Value value;
|
||||
|
||||
template <class Extractor>
|
||||
bool evaluate(const Extractor&) const;
|
||||
};
|
||||
|
||||
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
|
||||
|
||||
@@ -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) {
|
||||
return false;
|
||||
}
|
||||
template <class Extractor>
|
||||
struct Evaluator : public mapbox::util::static_visitor<bool>
|
||||
{
|
||||
const Extractor& extractor;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
case Operator::Or:
|
||||
for (const FilterComparison &comparison : comparisons) {
|
||||
if (comparison.compare(extractor)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (const FilterExpression &expression: expressions) {
|
||||
if (expression.compare(extractor)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
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;
|
||||
case Operator::Xor: {
|
||||
int count = 0;
|
||||
for (const FilterComparison &comparison : comparisons) {
|
||||
count += comparison.compare(extractor);
|
||||
if (count > 1) {
|
||||
return false;
|
||||
}
|
||||
for (const auto& v: values) {
|
||||
if (util::relaxed_equal(*actual, v)) {
|
||||
return true;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
for (const FilterExpression &expression: expressions) {
|
||||
if (expression.compare(extractor)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class Extractor>
|
||||
bool NotInExpression::evaluate(const Extractor& extractor) const {
|
||||
mapbox::util::optional<Value> actual = extractor.getValue(key);
|
||||
if (!actual)
|
||||
return true;
|
||||
for (const auto& v: values) {
|
||||
if (util::relaxed_equal(*actual, v)) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 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()(bool lhs, T rhs) const { return Operator()(T(lhs), rhs); }
|
||||
|
||||
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 {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include <mbgl/map/vector_tile.hpp>
|
||||
#include <mbgl/style/filter_expression_private.hpp>
|
||||
#include <mbgl/style/filter_comparison_private.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
@@ -123,81 +122,6 @@ FilteredVectorTileLayer::iterator::iterator(const FilteredVectorTileLayer& paren
|
||||
operator++();
|
||||
}
|
||||
|
||||
//bool FilteredVectorTileLayer::iterator::matchesFilterExpression(const FilterExpression &filterExpression, const pbf &tags_pbf) {
|
||||
// if (filterExpression.empty()) {
|
||||
// return true;
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// if (filterExpression.is<util::recursive_wrapper<PropertyFilter>>()) {
|
||||
// return matchesFilter(filterExpression.get<util::recursive_wrapper<PropertyFilter>>().get(), tags_pbf);
|
||||
// } else if (filterExpression.is<util::recursive_wrapper<PropertyExpression>>()) {
|
||||
// return matchesExpression(filterExpression.get<util::recursive_wrapper<PropertyExpression>>().get(), tags_pbf);
|
||||
// } else if (filterExpression.is<std::true_type>()) {
|
||||
// return true;
|
||||
// } else {
|
||||
// return false;
|
||||
// }
|
||||
// return true;
|
||||
//}
|
||||
|
||||
//
|
||||
//bool FilteredVectorTileLayer::iterator::matchesFilter(const PropertyFilter &filter, const pbf &const_tags_pbf) {
|
||||
// auto field_it = parent.layer.key_index.find(filter.field);
|
||||
// if (field_it != parent.layer.key_index.end()) {
|
||||
// const uint32_t filter_key = field_it->second;
|
||||
//
|
||||
// // Now loop through all the key/value pair tags.
|
||||
// // tags are packed varints. They should have an even length.
|
||||
// pbf tags_pbf = const_tags_pbf;
|
||||
// while (tags_pbf) {
|
||||
// uint32_t tag_key = tags_pbf.varint();
|
||||
// if (!tags_pbf) {
|
||||
// // This should not happen; otherwise the vector tile
|
||||
// // is invalid.
|
||||
// throw std::runtime_error("uneven number of feature tag ids");
|
||||
// }
|
||||
// uint32_t tag_val = tags_pbf.varint();
|
||||
//
|
||||
// if (tag_key == filter_key) {
|
||||
// if (parent.layer.values.size() > tag_val) {
|
||||
// const Value &value = parent.layer.values[tag_val];
|
||||
// return filter.compare(value);
|
||||
// } else {
|
||||
// throw std::runtime_error("feature references out of range value");
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // The feature doesn't contain the field that we're looking to compare.
|
||||
// // Depending on the filter, this may still be okay.
|
||||
// return filter.isMissingFieldOkay();
|
||||
//}
|
||||
//
|
||||
//bool FilteredVectorTileLayer::iterator::matchesExpression(const PropertyExpression &expression, const pbf &tags_pbf) {
|
||||
// if (expression.op == ExpressionOperator::Or) {
|
||||
// for (const PropertyFilterExpression &filterExpression : expression.operands) {
|
||||
// if (matchesFilterExpression(filterExpression, tags_pbf)) {
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
// return false;
|
||||
// } else if (expression.op == ExpressionOperator::And) {
|
||||
// for (const PropertyFilterExpression &filterExpression : expression.operands) {
|
||||
// if (!matchesFilterExpression(filterExpression, tags_pbf)) {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// return true;
|
||||
// } else {
|
||||
// return false;
|
||||
// }
|
||||
//}
|
||||
//
|
||||
|
||||
VectorTileTagExtractor::VectorTileTagExtractor(const VectorTileLayer &layer) : layer_(layer) {}
|
||||
|
||||
|
||||
@@ -205,8 +129,12 @@ void VectorTileTagExtractor::setTags(const pbf &pbf) {
|
||||
tags_ = pbf;
|
||||
}
|
||||
|
||||
std::vector<Value> VectorTileTagExtractor::getValues(const std::string &key) const {
|
||||
std::vector<Value> values;
|
||||
mapbox::util::optional<Value> VectorTileTagExtractor::getValue(const std::string &key) const {
|
||||
if (key == "$type") {
|
||||
return Value(uint64_t(type_));
|
||||
}
|
||||
|
||||
mapbox::util::optional<Value> value;
|
||||
|
||||
auto field_it = layer_.key_index.find(key);
|
||||
if (field_it != layer_.key_index.end()) {
|
||||
@@ -221,14 +149,14 @@ std::vector<Value> VectorTileTagExtractor::getValues(const std::string &key) con
|
||||
if (!tags_pbf) {
|
||||
// This should not happen; otherwise the vector tile is invalid.
|
||||
fprintf(stderr, "[WARNING] uneven number of feature tag ids\n");
|
||||
return values;
|
||||
return value;
|
||||
}
|
||||
// Note: We need to run this command in all cases, even if the keys don't match.
|
||||
tag_val = tags_pbf.varint();
|
||||
|
||||
if (tag_key == filter_key) {
|
||||
if (layer_.values.size() > tag_val) {
|
||||
values.emplace_back(layer_.values[tag_val]);
|
||||
value = layer_.values[tag_val];
|
||||
} else {
|
||||
fprintf(stderr, "[WARNING] feature references out of range value\n");
|
||||
break;
|
||||
@@ -237,16 +165,14 @@ std::vector<Value> VectorTileTagExtractor::getValues(const std::string &key) con
|
||||
}
|
||||
}
|
||||
|
||||
return values;
|
||||
return value;
|
||||
}
|
||||
|
||||
void VectorTileTagExtractor::setType(FilterExpression::GeometryType type) {
|
||||
void VectorTileTagExtractor::setType(FeatureType type) {
|
||||
type_ = type;
|
||||
}
|
||||
|
||||
FilterExpression::GeometryType VectorTileTagExtractor::getType() const {
|
||||
return type_;
|
||||
}
|
||||
template bool mbgl::evaluate(const FilterExpression&, const VectorTileTagExtractor&);
|
||||
|
||||
void FilteredVectorTileLayer::iterator::operator++() {
|
||||
valid = false;
|
||||
@@ -256,36 +182,21 @@ void FilteredVectorTileLayer::iterator::operator++() {
|
||||
while (data.next(2)) { // feature
|
||||
feature = data.message();
|
||||
pbf feature_pbf = feature;
|
||||
bool matched = false;
|
||||
|
||||
// Treat the absence of any expression filters as a match.
|
||||
if (expression.empty()) {
|
||||
matched = true;
|
||||
}
|
||||
VectorTileTagExtractor extractor(parent.layer);
|
||||
|
||||
if (!matched) {
|
||||
VectorTileTagExtractor extractor(parent.layer);
|
||||
|
||||
// Retrieve the basic information
|
||||
while (feature_pbf.next()) {
|
||||
if (feature_pbf.tag == 2) { // tags
|
||||
extractor.setTags(feature_pbf.message());
|
||||
} else if (feature_pbf.tag == 3) { // geometry type
|
||||
switch (FeatureType(feature_pbf.varint())) {
|
||||
case FeatureType::Point: extractor.setType(FilterExpression::GeometryType::Point); break;
|
||||
case FeatureType::LineString: extractor.setType(FilterExpression::GeometryType::LineString); break;
|
||||
case FeatureType::Polygon: extractor.setType(FilterExpression::GeometryType::Polygon); break;
|
||||
default: break;
|
||||
}
|
||||
} else {
|
||||
feature_pbf.skip();
|
||||
}
|
||||
// Retrieve the basic information
|
||||
while (feature_pbf.next()) {
|
||||
if (feature_pbf.tag == 2) { // tags
|
||||
extractor.setTags(feature_pbf.message());
|
||||
} else if (feature_pbf.tag == 3) { // geometry type
|
||||
extractor.setType(FeatureType(feature_pbf.varint()));
|
||||
} else {
|
||||
feature_pbf.skip();
|
||||
}
|
||||
|
||||
matched = expression.compare(extractor);
|
||||
}
|
||||
|
||||
if (matched) {
|
||||
if (evaluate(expression, extractor)) {
|
||||
valid = true;
|
||||
return; // data loop
|
||||
} else {
|
||||
|
||||
@@ -1,143 +0,0 @@
|
||||
#include <mbgl/map/vector_tile.hpp>
|
||||
#include <mbgl/style/filter_comparison_private.hpp>
|
||||
|
||||
#include <mbgl/style/value_comparison.hpp>
|
||||
|
||||
#include <ostream>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
@@ -1,66 +1,123 @@
|
||||
#include <mbgl/style/filter_expression_private.hpp>
|
||||
#include <mbgl/map/vector_tile.hpp>
|
||||
|
||||
#include <mbgl/style/value_comparison.hpp>
|
||||
|
||||
#include <ostream>
|
||||
#include <mbgl/platform/log.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
std::ostream& operator <<(std::ostream &s, FilterExpression::Operator op) {
|
||||
switch (op) {
|
||||
case FilterExpression::Operator::And: s << "AND"; break;
|
||||
case FilterExpression::Operator::Or: s << "OR"; break;
|
||||
case FilterExpression::Operator::Xor: s << "XOR"; break;
|
||||
case FilterExpression::Operator::Nor: s << "NOR"; break;
|
||||
Value parseFeatureType(const Value& value) {
|
||||
if (value == std::string("Point")) {
|
||||
return Value(uint64_t(FeatureType::Point));
|
||||
} else if (value == std::string("LineString")) {
|
||||
return Value(uint64_t(FeatureType::LineString));
|
||||
} else if (value == std::string("Polygon")) {
|
||||
return Value(uint64_t(FeatureType::Polygon));
|
||||
} else {
|
||||
Log::Warning(Event::ParseStyle, "value for $type filter must be Point, LineString, or Polygon");
|
||||
return Value(uint64_t(FeatureType::Unknown));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
template <class Expression>
|
||||
FilterExpression parseBinaryFilter(const rapidjson::Value& value) {
|
||||
FilterExpression empty;
|
||||
|
||||
std::ostream& operator <<(std::ostream &s, FilterExpression::GeometryType type) {
|
||||
switch (type) {
|
||||
case FilterExpression::GeometryType::Point: s << "Point"; break;
|
||||
case FilterExpression::GeometryType::LineString: s << "LineString"; break;
|
||||
case FilterExpression::GeometryType::Polygon: s << "Polygon"; break;
|
||||
case FilterExpression::GeometryType::Any: s << "<Any>"; break;
|
||||
if (value.Size() < 3) {
|
||||
Log::Warning(Event::ParseStyle, "filter expression must have 3 elements");
|
||||
return empty;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
bool FilterExpression::empty() const {
|
||||
return type == GeometryType::Any && comparisons.empty() && expressions.empty();
|
||||
}
|
||||
|
||||
void FilterExpression::add(const FilterComparison &comparison) {
|
||||
comparisons.emplace_back(comparison);
|
||||
}
|
||||
|
||||
void FilterExpression::add(const FilterExpression &expression) {
|
||||
expressions.emplace_back(expression);
|
||||
}
|
||||
|
||||
void FilterExpression::setGeometryType(GeometryType g) {
|
||||
type = g;
|
||||
}
|
||||
|
||||
FilterExpression::GeometryType parseGeometryType(const std::string &geometry) {
|
||||
if (geometry == "Point") return FilterExpression::GeometryType::Point;
|
||||
if (geometry == "LineString") return FilterExpression::GeometryType::LineString;
|
||||
if (geometry == "Polygon") return FilterExpression::GeometryType::Polygon;
|
||||
return FilterExpression::GeometryType::Any;
|
||||
}
|
||||
|
||||
std::ostream& operator <<(std::ostream &s, const FilterExpression &expression) {
|
||||
s << "expression " << expression.op << std::endl;
|
||||
s << " - $type = " << expression.type << std::endl;
|
||||
for (const FilterComparison &comparison : expression.comparisons) {
|
||||
s << comparison;
|
||||
if (!value[1u].IsString()) {
|
||||
Log::Warning(Event::ParseStyle, "filter expression key must be a string");
|
||||
return empty;
|
||||
}
|
||||
s << "end expression" << std::endl;
|
||||
return s;
|
||||
|
||||
Expression expression;
|
||||
expression.key = { value[1u].GetString(), value[1u].GetStringLength() };
|
||||
expression.value = parseValue(value[2u]);
|
||||
|
||||
if (expression.key == "$type") {
|
||||
expression.value = parseFeatureType(expression.value);
|
||||
}
|
||||
|
||||
return expression;
|
||||
}
|
||||
|
||||
template bool FilterExpression::compare(const VectorTileTagExtractor &extractor) const;
|
||||
template <class Expression>
|
||||
FilterExpression parseSetFilter(const rapidjson::Value& value) {
|
||||
FilterExpression empty;
|
||||
|
||||
if (value.Size() < 2) {
|
||||
Log::Warning(Event::ParseStyle, "filter expression must at least 2 elements");
|
||||
return empty;
|
||||
}
|
||||
|
||||
if (!value[1u].IsString()) {
|
||||
Log::Warning(Event::ParseStyle, "filter expression key must be a string");
|
||||
return empty;
|
||||
}
|
||||
|
||||
Expression expression;
|
||||
expression.key = { value[1u].GetString(), value[1u].GetStringLength() };
|
||||
for (rapidjson::SizeType i = 2; i < value.Size(); ++i) {
|
||||
expression.values.push_back(parseValue(value[i]));
|
||||
}
|
||||
return expression;
|
||||
}
|
||||
|
||||
template <class Expression>
|
||||
FilterExpression parseCompoundFilter(const rapidjson::Value& value) {
|
||||
Expression expression;
|
||||
for (rapidjson::SizeType i = 1; i < value.Size(); ++i) {
|
||||
expression.expressions.push_back(parseFilterExpression(value[i]));
|
||||
}
|
||||
return expression;
|
||||
}
|
||||
|
||||
FilterExpression parseFilterExpression(const rapidjson::Value& value) {
|
||||
FilterExpression empty;
|
||||
|
||||
if (!value.IsArray()) {
|
||||
Log::Warning(Event::ParseStyle, "filter expression must be an array");
|
||||
return empty;
|
||||
}
|
||||
|
||||
if (value.Size() < 1) {
|
||||
Log::Warning(Event::ParseStyle, "filter expression must have at least 1 element");
|
||||
return empty;
|
||||
}
|
||||
|
||||
if (!value[0u].IsString()) {
|
||||
Log::Warning(Event::ParseStyle, "filter operator must be a string");
|
||||
return empty;
|
||||
}
|
||||
|
||||
std::string op = { value[0u].GetString(), value[0u].GetStringLength() };
|
||||
|
||||
if (op == "==") {
|
||||
return parseBinaryFilter<EqualsExpression>(value);
|
||||
} else if (op == "!=") {
|
||||
return parseBinaryFilter<NotEqualsExpression>(value);
|
||||
} else if (op == ">") {
|
||||
return parseBinaryFilter<GreaterThanExpression>(value);
|
||||
} else if (op == ">=") {
|
||||
return parseBinaryFilter<GreaterThanEqualsExpression>(value);
|
||||
} else if (op == "<") {
|
||||
return parseBinaryFilter<LessThanExpression>(value);
|
||||
} else if (op == "<=") {
|
||||
return parseBinaryFilter<LessThanEqualsExpression>(value);
|
||||
} else if (op == "in") {
|
||||
return parseSetFilter<InExpression>(value);
|
||||
} else if (op == "!in") {
|
||||
return parseSetFilter<NotInExpression>(value);
|
||||
} else if (op == "all") {
|
||||
return parseCompoundFilter<AllExpression>(value);
|
||||
} else if (op == "any") {
|
||||
return parseCompoundFilter<AnyExpression>(value);
|
||||
} else if (op == "none") {
|
||||
return parseCompoundFilter<NoneExpression>(value);
|
||||
} else {
|
||||
Log::Warning(Event::ParseStyle, "filter operator must be one of \"==\", \"!=\", \">\", \">=\", \"<\", \"<=\", \"in\", \"!in\", \"all\", \"any\", \"none\"");
|
||||
return empty;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -711,7 +711,7 @@ void StyleParser::parseBucket(JSVal value, util::ptr<StyleLayer> &layer) {
|
||||
|
||||
if (value.HasMember("filter")) {
|
||||
JSVal value_filter = replaceConstant(value["filter"]);
|
||||
layer->bucket->filter = parseFilter(value_filter);
|
||||
layer->bucket->filter = parseFilterExpression(value_filter);
|
||||
}
|
||||
|
||||
if (value.HasMember("render")) {
|
||||
@@ -738,93 +738,6 @@ void StyleParser::parseBucket(JSVal value, util::ptr<StyleLayer> &layer) {
|
||||
}
|
||||
}
|
||||
|
||||
FilterExpression StyleParser::parseFilter(JSVal value) {
|
||||
return parseFilter(value, value.IsArray() ? FilterExpression::Operator::Or : FilterExpression::Operator::And);
|
||||
}
|
||||
|
||||
FilterExpression StyleParser::parseFilter(JSVal value, FilterExpression::Operator op) {
|
||||
FilterExpression expression(op);
|
||||
if (value.IsObject()) {
|
||||
rapidjson::Value::ConstMemberIterator itr = value.MemberBegin();
|
||||
for (; itr != value.MemberEnd(); ++itr) {
|
||||
const std::string name { itr->name.GetString(), itr->name.GetStringLength() };
|
||||
if (name == "&") {
|
||||
expression.add(parseFilter(replaceConstant(itr->value), FilterExpression::Operator::And));
|
||||
} else if (name == "|") {
|
||||
expression.add(parseFilter(replaceConstant(itr->value), FilterExpression::Operator::Or));
|
||||
} else if (name == "^") {
|
||||
expression.add(parseFilter(replaceConstant(itr->value), FilterExpression::Operator::Xor));
|
||||
} else if (name == "!") {
|
||||
expression.add(parseFilter(replaceConstant(itr->value), FilterExpression::Operator::Nor));
|
||||
} else if (name == "$type") {
|
||||
JSVal type = replaceConstant(itr->value);
|
||||
if (type.IsString()) {
|
||||
expression.setGeometryType(parseGeometryType({ type.GetString(), type.GetStringLength() }));
|
||||
}
|
||||
} else {
|
||||
FilterComparison comparison(name);
|
||||
JSVal filterValue = replaceConstant(itr->value);
|
||||
if (filterValue.IsObject()) {
|
||||
rapidjson::Value::ConstMemberIterator filter_itr = filterValue.MemberBegin();
|
||||
for (; filter_itr != filterValue.MemberEnd(); ++filter_itr) {
|
||||
comparison.add(
|
||||
parseFilterComparisonOperator({ filter_itr->name.GetString(), filter_itr->name.GetStringLength() }),
|
||||
parseValues(replaceConstant(filter_itr->value))
|
||||
);
|
||||
}
|
||||
} else if (filterValue.IsArray()) {
|
||||
comparison.add(FilterComparison::Operator::In, parseValues(filterValue));
|
||||
} else {
|
||||
comparison.add(FilterComparison::Operator::Equal, std::vector<Value>({ parseValue(filterValue) }));
|
||||
}
|
||||
expression.add(comparison);
|
||||
}
|
||||
}
|
||||
} else if (value.IsArray()) {
|
||||
for (rapidjson::SizeType i = 0; i < value.Size(); i++) {
|
||||
expression.add(parseFilter(replaceConstant(value[i])));
|
||||
}
|
||||
} else {
|
||||
Log::Warning(Event::ParseStyle, "expression must be either an array or an object");
|
||||
}
|
||||
|
||||
return expression;
|
||||
}
|
||||
|
||||
Value StyleParser::parseValue(JSVal value) {
|
||||
switch (value.GetType()) {
|
||||
case rapidjson::kNullType:
|
||||
case rapidjson::kFalseType:
|
||||
return false;
|
||||
|
||||
case rapidjson::kTrueType:
|
||||
return true;
|
||||
|
||||
case rapidjson::kStringType:
|
||||
return std::string { value.GetString(), value.GetStringLength() };
|
||||
|
||||
case rapidjson::kNumberType:
|
||||
if (value.IsUint64()) return value.GetUint64();
|
||||
if (value.IsInt64()) return value.GetInt64();
|
||||
return value.GetDouble();
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Value> StyleParser::parseValues(JSVal value) {
|
||||
std::vector<Value> values;
|
||||
if (value.IsArray()) {
|
||||
for (rapidjson::SizeType i = 0; i < value.Size(); i++) {
|
||||
values.emplace_back(parseValue(replaceConstant(value[i])));
|
||||
}
|
||||
} else {
|
||||
values.emplace_back(parseValue(value));
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
void StyleParser::parseRender(JSVal value, util::ptr<StyleLayer> &layer) {
|
||||
if (!value.IsObject()) {
|
||||
Log::Warning(Event::ParseStyle, "render property of layer '%s' must be an object", layer->id.c_str());
|
||||
|
||||
@@ -42,3 +42,25 @@ std::string mbgl::toString(const mbgl::Value& value) {
|
||||
else if (value.is<double>()) return boost::lexical_cast<std::string>(value.get<double>());
|
||||
else return "null";
|
||||
}
|
||||
|
||||
mbgl::Value mbgl::parseValue(const rapidjson::Value& value) {
|
||||
switch (value.GetType()) {
|
||||
case rapidjson::kNullType:
|
||||
case rapidjson::kFalseType:
|
||||
return false;
|
||||
|
||||
case rapidjson::kTrueType:
|
||||
return true;
|
||||
|
||||
case rapidjson::kStringType:
|
||||
return std::string { value.GetString(), value.GetStringLength() };
|
||||
|
||||
case rapidjson::kNumberType:
|
||||
if (value.IsUint64()) return value.GetUint64();
|
||||
if (value.IsInt64()) return value.GetInt64();
|
||||
return value.GetDouble();
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,306 +1,103 @@
|
||||
#include <iostream>
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <mbgl/style/filter_comparison_private.hpp>
|
||||
#include <mbgl/map/vector_tile.hpp>
|
||||
#include <mbgl/style/filter_expression.hpp>
|
||||
#include <mbgl/style/filter_expression_private.hpp>
|
||||
|
||||
#include <map>
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
typedef std::multimap<std::string, mbgl::Value> Properties;
|
||||
|
||||
class MockExtractor {
|
||||
class Extractor {
|
||||
public:
|
||||
inline MockExtractor(const std::multimap<std::string, mbgl::Value> &values_) : values(values_) {}
|
||||
inline MockExtractor() {}
|
||||
inline Extractor(const Properties& properties_, FeatureType type_)
|
||||
: properties(properties_)
|
||||
, type(type_)
|
||||
{}
|
||||
|
||||
inline std::vector<mbgl::Value> getValues(const std::string &key) const {
|
||||
std::vector<mbgl::Value> result;
|
||||
// Find all values with the requested key.
|
||||
const auto ret = values.equal_range(key);
|
||||
for (auto it = ret.first; it != ret.second; it++) {
|
||||
// Append the newly found value to the forward list.
|
||||
result.emplace_back(it->second);
|
||||
}
|
||||
return result;
|
||||
mapbox::util::optional<Value> getValue(const std::string &key) const {
|
||||
if (key == "$type")
|
||||
return Value(uint64_t(type));
|
||||
auto it = properties.find(key);
|
||||
if (it == properties.end())
|
||||
return mapbox::util::optional<Value>();
|
||||
return it->second;
|
||||
}
|
||||
|
||||
FeatureType getType() const {
|
||||
return type;
|
||||
}
|
||||
|
||||
private:
|
||||
const std::multimap<std::string, mbgl::Value> values;
|
||||
const Properties properties;
|
||||
FeatureType type;
|
||||
};
|
||||
|
||||
|
||||
TEST(FilterComparison, EqualsSingleStringValue) {
|
||||
using namespace mbgl;
|
||||
|
||||
FilterComparison comparison("test");
|
||||
comparison.add(FilterComparison::Operator::Equal, std::vector<Value> { std::string("bar") });
|
||||
// comparison is { "test": { "==": "bar" } }
|
||||
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("bar") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("bar") }, { "test", std::string("bar") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("bar") }, { "test", std::string("booz") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "other", std::string("bar") }, { "test", std::string("bar") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "other", std::string("bar") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor()));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("barst") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", int64_t(-18932) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", uint64_t(18932) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", double(32.8) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", bool(false) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", bool(true) }})));
|
||||
FilterExpression parse(const char * expression) {
|
||||
rapidjson::Document doc;
|
||||
doc.Parse<0>(expression);
|
||||
return parseFilterExpression(doc);
|
||||
}
|
||||
|
||||
|
||||
TEST(FilterComparison, EqualsSingleDoubleValue) {
|
||||
using namespace mbgl;
|
||||
|
||||
FilterComparison comparison("test");
|
||||
comparison.add(FilterComparison::Operator::Equal, std::vector<Value> { double(32.8) });
|
||||
// comparison is { "test": { "==": 32.8 } }
|
||||
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", double(32.8) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("32.8") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "other", std::string("bar") }, { "test", double(32.8) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", double(32.8) }, { "test", std::string("booz") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "other", double(32.8) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor()));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", double(32.9) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", int64_t(-18932) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", uint64_t(18932) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", bool(false) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", bool(true) }})));
|
||||
bool evaluate(const FilterExpression& expression, const Properties& properties, FeatureType type = FeatureType::Unknown) {
|
||||
return mbgl::evaluate(expression, Extractor(properties, type));
|
||||
}
|
||||
|
||||
TEST(FilterComparison, EqualsSingleUintValue) {
|
||||
using namespace mbgl;
|
||||
TEST(FilterComparison, EqualsString) {
|
||||
FilterExpression f = parse("[\"==\", \"foo\", \"bar\"]");
|
||||
ASSERT_TRUE(evaluate(f, {{ "foo", std::string("bar") }}));
|
||||
ASSERT_FALSE(evaluate(f, {{ "foo", std::string("baz") }}));
|
||||
};
|
||||
|
||||
FilterComparison comparison("test");
|
||||
comparison.add(FilterComparison::Operator::Equal, std::vector<Value> { uint64_t(42) });
|
||||
// comparison is { "test": { "==": 42 } }
|
||||
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", uint64_t(42) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", double(42) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", int64_t(42) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("42") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "other", std::string("bar") }, { "test", uint64_t(42) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", uint64_t(42) }, { "test", std::string("booz") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "other", uint64_t(42) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor()));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", double(43) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", int64_t(-18932) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", uint64_t(18932) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", bool(false) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", bool(true) }})));
|
||||
TEST(FilterComparison, EqualsNumber) {
|
||||
FilterExpression f = parse("[\"==\", \"foo\", 0]");
|
||||
ASSERT_TRUE(evaluate(f, {{ "foo", int64_t(0) }}));
|
||||
ASSERT_TRUE(evaluate(f, {{ "foo", uint64_t(0) }}));
|
||||
ASSERT_TRUE(evaluate(f, {{ "foo", double(0) }}));
|
||||
ASSERT_FALSE(evaluate(f, {{ "foo", int64_t(1) }}));
|
||||
ASSERT_FALSE(evaluate(f, {{ "foo", uint64_t(1) }}));
|
||||
ASSERT_FALSE(evaluate(f, {{ "foo", double(1) }}));
|
||||
ASSERT_FALSE(evaluate(f, {{ "foo", std::string("0") }}));
|
||||
ASSERT_FALSE(evaluate(f, {{ "foo", false }}));
|
||||
ASSERT_FALSE(evaluate(f, {{ "foo", true }}));
|
||||
ASSERT_FALSE(evaluate(f, {{}}));
|
||||
}
|
||||
|
||||
TEST(FilterComparison, EqualsSingleIntValue) {
|
||||
using namespace mbgl;
|
||||
|
||||
FilterComparison comparison("test");
|
||||
comparison.add(FilterComparison::Operator::Equal, std::vector<Value> { int64_t(-42) });
|
||||
// comparison is { "test": { "==": -42 } }
|
||||
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", int64_t(-42) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", double(-42) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("-42") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "other", std::string("bar") }, { "test", int64_t(-42) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", int64_t(-42) }, { "test", std::string("booz") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "other", int64_t(-42) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor()));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", int64_t(-43) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", double(-43) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", uint64_t(-42) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", bool(false) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", bool(true) }})));
|
||||
TEST(FilterComparison, EqualsType) {
|
||||
FilterExpression f = parse("[\"==\", \"$type\", \"LineString\"]");
|
||||
ASSERT_FALSE(evaluate(f, {{}}, FeatureType::Point));
|
||||
ASSERT_TRUE(evaluate(f, {{}}, FeatureType::LineString));
|
||||
}
|
||||
|
||||
TEST(FilterComparison, EqualsSingleBoolValue) {
|
||||
using namespace mbgl;
|
||||
|
||||
FilterComparison comparison("test");
|
||||
comparison.add(FilterComparison::Operator::Equal, std::vector<Value> { bool(true) });
|
||||
// comparison is { "test": { "==": true } }
|
||||
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", bool(true) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", int64_t(1) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", uint64_t(1) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", double(1) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("1") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "other", std::string("bar") }, { "test", bool(true) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", bool(true) }, { "test", std::string("booz") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "other", bool(true) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor()));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", bool(false) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", int64_t(-18932) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", uint64_t(18932) }})));
|
||||
TEST(FilterComparison, Any) {
|
||||
ASSERT_FALSE(evaluate(parse("[\"any\"]"), {{}}));
|
||||
ASSERT_TRUE(evaluate(parse("[\"any\", [\"==\", \"foo\", 1]]"),
|
||||
{{ std::string("foo"), int64_t(1) }}));
|
||||
ASSERT_FALSE(evaluate(parse("[\"any\", [\"==\", \"foo\", 0]]"),
|
||||
{{ std::string("foo"), int64_t(1) }}));
|
||||
ASSERT_TRUE(evaluate(parse("[\"any\", [\"==\", \"foo\", 0], [\"==\", \"foo\", 1]]"),
|
||||
{{ std::string("foo"), int64_t(1) }}));
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST(FilterComparison, EqualsMultipleStringValues) {
|
||||
using namespace mbgl;
|
||||
|
||||
FilterComparison comparison("test");
|
||||
comparison.add(FilterComparison::Operator::Equal, std::vector<Value> { std::string("bar"), std::string("baz") });
|
||||
// comparison is { "test": { "==": ["bar", "baz"]̇ } }
|
||||
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("bar") }, { "test", std::string("baz") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("baz") }, { "test", std::string("bar") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("bar") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("baz") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("bar") }, { "test", std::string("baz") }, { "test", std::string("boo") }})));
|
||||
TEST(FilterComparison, All) {
|
||||
ASSERT_TRUE(evaluate(parse("[\"all\"]"), {{}}));
|
||||
ASSERT_TRUE(evaluate(parse("[\"all\", [\"==\", \"foo\", 1]]"),
|
||||
{{ std::string("foo"), int64_t(1) }}));
|
||||
ASSERT_FALSE(evaluate(parse("[\"all\", [\"==\", \"foo\", 0]]"),
|
||||
{{ std::string("foo"), int64_t(1) }}));
|
||||
ASSERT_FALSE(evaluate(parse("[\"all\", [\"==\", \"foo\", 0], [\"==\", \"foo\", 1]]"),
|
||||
{{ std::string("foo"), int64_t(1) }}));
|
||||
}
|
||||
|
||||
TEST(FilterComparison, EqualsMultipleIdenticalStringValues) {
|
||||
using namespace mbgl;
|
||||
|
||||
FilterComparison comparison("test");
|
||||
comparison.add(FilterComparison::Operator::Equal, std::vector<Value> { std::string("bar"), std::string("bar") });
|
||||
// comparison is { "test": { "==": ["bar", "bar"]̇ } }
|
||||
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("bar") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("bar") }, { "test", std::string("bar") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("baz") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("bar") }, { "test", std::string("baz") }})));
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST(FilterComparison, NotEqualsSingleStringValue) {
|
||||
using namespace mbgl;
|
||||
|
||||
FilterComparison comparison("test");
|
||||
comparison.add(FilterComparison::Operator::NotEqual, std::vector<Value> { std::string("bar") });
|
||||
// comparison is { "test": { "!=": "bar" } }
|
||||
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("bar") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("bar") }, { "test", std::string("bar") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "other", std::string("bar") }, { "test", std::string("bar") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("bar") }, { "test", std::string("booz") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "other", std::string("bar") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor()));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("barst") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", int64_t(-18932) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", uint64_t(18932) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", double(32.8) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", bool(false) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", bool(true) }})));
|
||||
}
|
||||
|
||||
|
||||
TEST(FilterComparison, NotEqualsSingleDoubleValue) {
|
||||
using namespace mbgl;
|
||||
|
||||
FilterComparison comparison("test");
|
||||
comparison.add(FilterComparison::Operator::NotEqual, std::vector<Value> { double(32.8) });
|
||||
// comparison is { "test": { "!=": 32.8 } }
|
||||
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", double(32.8) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("32.8") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "other", std::string("bar") }, { "test", double(32.8) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", double(32.8) }, { "test", std::string("booz") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "other", double(32.8) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor()));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", double(32.9) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", int64_t(-18932) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", uint64_t(18932) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", bool(false) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", bool(true) }})));
|
||||
}
|
||||
|
||||
TEST(FilterComparison, NotEqualsSingleUintValue) {
|
||||
using namespace mbgl;
|
||||
|
||||
FilterComparison comparison("test");
|
||||
comparison.add(FilterComparison::Operator::NotEqual, std::vector<Value> { uint64_t(42) });
|
||||
// comparison is { "test": { "!=": 42 } }
|
||||
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", uint64_t(42) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", double(42) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", int64_t(42) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("42") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "other", std::string("bar") }, { "test", uint64_t(42) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", uint64_t(42) }, { "test", std::string("booz") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "other", uint64_t(42) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor()));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", double(43) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", int64_t(-18932) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", uint64_t(18932) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", bool(false) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", bool(true) }})));
|
||||
}
|
||||
|
||||
|
||||
TEST(FilterComparison, NotEqualsSingleIntValue) {
|
||||
using namespace mbgl;
|
||||
|
||||
FilterComparison comparison("test");
|
||||
comparison.add(FilterComparison::Operator::NotEqual, std::vector<Value> { int64_t(-42) });
|
||||
// comparison is { "test": { "!=": -42 } }
|
||||
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", int64_t(-42) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", double(-42) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("-42") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "other", std::string("bar") }, { "test", int64_t(-42) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", int64_t(-42) }, { "test", std::string("booz") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "other", int64_t(-42) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor()));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", int64_t(-43) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", double(-43) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", uint64_t(-42) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", bool(false) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", bool(true) }})));
|
||||
}
|
||||
|
||||
|
||||
TEST(FilterComparison, NotEqualsSingleBoolValue) {
|
||||
using namespace mbgl;
|
||||
|
||||
FilterComparison comparison("test");
|
||||
comparison.add(FilterComparison::Operator::NotEqual, std::vector<Value> { bool(true) });
|
||||
// comparison is { "test": { "!=": true } }
|
||||
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", bool(true) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", int64_t(1) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", uint64_t(1) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", double(1) }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("1") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "other", std::string("bar") }, { "test", bool(true) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", bool(true) }, { "test", std::string("booz") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "other", bool(true) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor()));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", bool(false) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", int64_t(-18932) }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", uint64_t(18932) }})));
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST(FilterComparison, NotEqualsMultipleStringValues) {
|
||||
using namespace mbgl;
|
||||
|
||||
FilterComparison comparison("test");
|
||||
comparison.add(FilterComparison::Operator::NotEqual, std::vector<Value> { std::string("bar"), std::string("baz") });
|
||||
// comparison is { "test": { "!=": ["bar", "baz"]̇ } }
|
||||
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("bar") }, { "test", std::string("baz") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("baz") }, { "test", std::string("bar") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("bar") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("baz") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("bar") }, { "test", std::string("baz") }, { "test", std::string("boo") }})));
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST(FilterComparison, NotEqualsMultipleIdenticalStringValues) {
|
||||
using namespace mbgl;
|
||||
|
||||
FilterComparison comparison("test");
|
||||
comparison.add(FilterComparison::Operator::NotEqual, std::vector<Value> { std::string("bar"), std::string("bar") });
|
||||
// comparison is { "test": { "!=": ["bar", "bar"]̇ } }
|
||||
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("bar") }})));
|
||||
ASSERT_FALSE(comparison.compare(MockExtractor({{ "test", std::string("bar") }, { "test", std::string("bar") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("baz") }})));
|
||||
ASSERT_TRUE(comparison.compare(MockExtractor({{ "test", std::string("bar") }, { "test", std::string("baz") }})));
|
||||
TEST(FilterComparison, None) {
|
||||
ASSERT_TRUE(evaluate(parse("[\"none\"]"), {{}}));
|
||||
ASSERT_FALSE(evaluate(parse("[\"none\", [\"==\", \"foo\", 1]]"),
|
||||
{{ std::string("foo"), int64_t(1) }}));
|
||||
ASSERT_TRUE(evaluate(parse("[\"none\", [\"==\", \"foo\", 0]]"),
|
||||
{{ std::string("foo"), int64_t(1) }}));
|
||||
ASSERT_FALSE(evaluate(parse("[\"none\", [\"==\", \"foo\", 0], [\"==\", \"foo\", 1]]"),
|
||||
{{ std::string("foo"), int64_t(1) }}));
|
||||
}
|
||||
|
||||
345
test/variant.cpp
345
test/variant.cpp
@@ -17,110 +17,26 @@ TEST(Variant, toString) {
|
||||
EXPECT_EQ("false", toString( false ));
|
||||
}
|
||||
|
||||
|
||||
TEST(Variant, RelaxedEqualityStringToBool) {
|
||||
// 1-ish values are true
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string("1"), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string("1.0"), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string(" 1"), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string(" 0x1"), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string(" 0X1"), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string(" 1.0"), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string(" 1 "), bool(true)));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(true), std::string("1")));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(true), std::string("1.0")));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(true), std::string(" 1")));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(true), std::string(" 0x1")));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(true), std::string(" 0X1")));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(true), std::string(" 1.0")));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(true), std::string(" 1 ")));
|
||||
|
||||
// 0-ish values are false
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string("0"), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string("0.0"), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string(" 0"), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string(" 0x0"), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string(" 0X0"), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string(" 0.0"), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string(" 0 "), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string(""), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string(" "), bool(false)));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(false), std::string("0")));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(false), std::string("0.0")));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(false), std::string(" 0")));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(false), std::string(" 0x0")));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(false), std::string(" 0X0")));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(false), std::string(" 0.0")));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(false), std::string(" 0 ")));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(false), std::string("")));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(false), std::string(" ")));
|
||||
|
||||
|
||||
// other string values are neither true nor false
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string(" 1.0 g"), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string("foo"), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string("true"), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string("false"), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string(" inf "), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string(" inFINITY "), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string(" nan "), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string(" NAN "), bool(true)));
|
||||
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(true), std::string(" 1.0 g")));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(true), std::string("foo")));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(true), std::string("true")));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(true), std::string("false")));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(true), std::string(" inf ")));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(true), std::string(" inFINITY ")));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(true), std::string(" nan ")));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(true), std::string(" NAN ")));
|
||||
|
||||
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string(" 1.0 g"), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string("foo"), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string("true"), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string("false"), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string(" inf "), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string(" inFINITY "), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string(" nan "), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string(" NAN "), bool(false)));
|
||||
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), std::string(" 1.0 g")));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), std::string("foo")));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), std::string("true")));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), std::string("false")));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), std::string(" inf ")));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), std::string(" inFINITY ")));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), std::string(" nan ")));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), std::string(" NAN ")));
|
||||
}
|
||||
|
||||
TEST(Variant, RelaxedEquality) {
|
||||
// Compare to bool
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(false), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(false), int64_t(0)));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(false), uint64_t(0)));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(false), double(0)));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(false), std::string("0")));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(false), std::string("")));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(true), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(true), int64_t(1)));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(true), uint64_t(1)));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(true), double(1)));
|
||||
EXPECT_TRUE(util::relaxed_equal(bool(true), std::string("1")));
|
||||
|
||||
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), int64_t(0)));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), uint64_t(0)));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), double(0)));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), std::string("0")));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), std::string("")));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), int64_t(386)));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), int64_t(-7042)));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), uint64_t(386)));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), double(3.145)));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), std::string("386")));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(false), std::string("test")));
|
||||
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(true), int64_t(1)));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(true), uint64_t(1)));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(true), double(1)));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(true), std::string("1")));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(true), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(true), int64_t(386)));
|
||||
EXPECT_FALSE(util::relaxed_equal(bool(true), int64_t(-7042)));
|
||||
@@ -135,10 +51,9 @@ TEST(Variant, RelaxedEquality) {
|
||||
EXPECT_TRUE(util::relaxed_equal(int64_t(-7042), int64_t(-7042)));
|
||||
EXPECT_TRUE(util::relaxed_equal(int64_t(386), uint64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_equal(int64_t(386), double(386)));
|
||||
EXPECT_TRUE(util::relaxed_equal(int64_t(386), std::string("386")));
|
||||
EXPECT_TRUE(util::relaxed_equal(int64_t(1), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_equal(int64_t(0), bool(false)));
|
||||
|
||||
EXPECT_FALSE(util::relaxed_equal(int64_t(386), std::string("386")));
|
||||
EXPECT_FALSE(util::relaxed_equal(int64_t(1), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_equal(int64_t(0), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_equal(int64_t(386), int64_t(387)));
|
||||
EXPECT_FALSE(util::relaxed_equal(int64_t(-7042), int64_t(-7043)));
|
||||
EXPECT_FALSE(util::relaxed_equal(int64_t(386), uint64_t(387)));
|
||||
@@ -151,16 +66,14 @@ TEST(Variant, RelaxedEquality) {
|
||||
EXPECT_FALSE(util::relaxed_equal(int64_t(1), std::string("false")));
|
||||
EXPECT_FALSE(util::relaxed_equal(int64_t(0), std::string("true")));
|
||||
|
||||
|
||||
// Compare to uint64_t
|
||||
EXPECT_TRUE(util::relaxed_equal(uint64_t(386), int64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_equal(uint64_t(386), uint64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_equal(uint64_t(0), uint64_t(0)));
|
||||
EXPECT_TRUE(util::relaxed_equal(uint64_t(386), double(386)));
|
||||
EXPECT_TRUE(util::relaxed_equal(uint64_t(386), std::string("386")));
|
||||
EXPECT_TRUE(util::relaxed_equal(uint64_t(1), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_equal(uint64_t(0), bool(false)));
|
||||
|
||||
EXPECT_FALSE(util::relaxed_equal(uint64_t(386), std::string("386")));
|
||||
EXPECT_FALSE(util::relaxed_equal(uint64_t(1), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_equal(uint64_t(0), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_equal(uint64_t(386), int64_t(387)));
|
||||
EXPECT_FALSE(util::relaxed_equal(uint64_t(386), uint64_t(387)));
|
||||
EXPECT_FALSE(util::relaxed_equal(uint64_t(0), uint64_t(1)));
|
||||
@@ -173,17 +86,15 @@ TEST(Variant, RelaxedEquality) {
|
||||
EXPECT_FALSE(util::relaxed_equal(uint64_t(1), std::string("false")));
|
||||
EXPECT_FALSE(util::relaxed_equal(uint64_t(0), std::string("true")));
|
||||
|
||||
|
||||
// Compare to double
|
||||
EXPECT_TRUE(util::relaxed_equal(double(3.159385), double(3.159385)));
|
||||
EXPECT_TRUE(util::relaxed_equal(double(386), int64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_equal(double(386), uint64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_equal(double(0), uint64_t(0)));
|
||||
EXPECT_TRUE(util::relaxed_equal(double(386), double(386)));
|
||||
EXPECT_TRUE(util::relaxed_equal(double(386), std::string("386")));
|
||||
EXPECT_TRUE(util::relaxed_equal(double(1), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_equal(double(0), bool(false)));
|
||||
|
||||
EXPECT_FALSE(util::relaxed_equal(double(386), std::string("386")));
|
||||
EXPECT_FALSE(util::relaxed_equal(double(1), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_equal(double(0), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_equal(double(3.159385), double(3.159383)));
|
||||
EXPECT_FALSE(util::relaxed_equal(double(386), int64_t(387)));
|
||||
EXPECT_FALSE(util::relaxed_equal(double(386), uint64_t(387)));
|
||||
@@ -205,16 +116,14 @@ TEST(Variant, RelaxedEquality) {
|
||||
EXPECT_FALSE(util::relaxed_equal(double(0), std::string("true")));
|
||||
EXPECT_FALSE(util::relaxed_equal(double(0), std::string("TRUE")));
|
||||
|
||||
|
||||
// Compare to string
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string("lord"), std::string("lord")));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string("386"), int64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string("-386"), int64_t(-386)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string("386"), uint64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string("386.36"), double(386.36)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string(""), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_equal(std::string("1"), bool(true)));
|
||||
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string("386"), int64_t(386)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string("-386"), int64_t(-386)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string("386"), uint64_t(386)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string("386.36"), double(386.36)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string(""), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string("1"), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string("lord"), std::string("baron")));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string("386"), int64_t(387)));
|
||||
EXPECT_FALSE(util::relaxed_equal(std::string("-386"), int64_t(-387)));
|
||||
@@ -239,46 +148,46 @@ TEST(Variant, RelaxedEquality) {
|
||||
|
||||
TEST(Variant, RelaxedGreater) {
|
||||
EXPECT_TRUE(util::relaxed_greater(std::string("387"), std::string("386")));
|
||||
EXPECT_TRUE(util::relaxed_greater(uint64_t(387), std::string("386")));
|
||||
EXPECT_TRUE(util::relaxed_greater(int64_t(387), std::string("386")));
|
||||
EXPECT_TRUE(util::relaxed_greater(double(387), std::string("386")));
|
||||
EXPECT_TRUE(util::relaxed_greater(bool(true), std::string("0")));
|
||||
EXPECT_FALSE(util::relaxed_greater(uint64_t(387), std::string("386")));
|
||||
EXPECT_FALSE(util::relaxed_greater(int64_t(387), std::string("386")));
|
||||
EXPECT_FALSE(util::relaxed_greater(double(387), std::string("386")));
|
||||
EXPECT_FALSE(util::relaxed_greater(bool(true), std::string("0")));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_greater(std::string("387"), uint64_t(386)));
|
||||
EXPECT_FALSE(util::relaxed_greater(std::string("387"), uint64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_greater(uint64_t(387), uint64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_greater(int64_t(387), uint64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_greater(double(387), uint64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_greater(bool(true), uint64_t(0)));
|
||||
EXPECT_FALSE(util::relaxed_greater(bool(true), uint64_t(0)));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_greater(std::string("387"), int64_t(386)));
|
||||
EXPECT_FALSE(util::relaxed_greater(std::string("387"), int64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_greater(uint64_t(387), int64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_greater(int64_t(387), int64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_greater(double(387), int64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_greater(bool(true), int64_t(0)));
|
||||
EXPECT_FALSE(util::relaxed_greater(bool(true), int64_t(0)));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_greater(std::string("387"), double(386.7)));
|
||||
EXPECT_FALSE(util::relaxed_greater(std::string("387"), double(386.7)));
|
||||
EXPECT_TRUE(util::relaxed_greater(uint64_t(387), double(386.7)));
|
||||
EXPECT_TRUE(util::relaxed_greater(int64_t(387), double(386.7)));
|
||||
EXPECT_TRUE(util::relaxed_greater(double(387), double(386.7)));
|
||||
EXPECT_TRUE(util::relaxed_greater(bool(true), double(0)));
|
||||
EXPECT_FALSE(util::relaxed_greater(bool(true), double(0)));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_greater(std::string("387"), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_greater(std::string("387"), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_greater(uint64_t(387), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_greater(int64_t(387), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_greater(double(387), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_greater(double(387), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_greater(uint64_t(387), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_greater(int64_t(387), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_greater(double(387), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_greater(double(387), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_greater(std::string("387"), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_greater(std::string("387"), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_greater(uint64_t(387), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_greater(int64_t(387), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_greater(double(387), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_greater(double(387), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_greater(uint64_t(387), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_greater(int64_t(387), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_greater(double(387), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_greater(double(387), bool(true)));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_greater(bool(true), double(0)));
|
||||
EXPECT_TRUE(util::relaxed_greater(bool(true), double(0.5)));
|
||||
EXPECT_TRUE(util::relaxed_greater(bool(true), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_greater(bool(true), int64_t(0)));
|
||||
EXPECT_TRUE(util::relaxed_greater(bool(true), uint64_t(0)));
|
||||
EXPECT_FALSE(util::relaxed_greater(bool(true), double(0)));
|
||||
EXPECT_FALSE(util::relaxed_greater(bool(true), double(0.5)));
|
||||
EXPECT_TRUE(util::relaxed_greater(bool(true), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_greater(bool(true), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_greater(bool(true), int64_t(0)));
|
||||
EXPECT_FALSE(util::relaxed_greater(bool(true), uint64_t(0)));
|
||||
|
||||
|
||||
|
||||
@@ -315,52 +224,52 @@ TEST(Variant, RelaxedGreater) {
|
||||
TEST(Variant, RelaxedGreaterEqual) {
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), std::string("386")));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), std::string("387")));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), std::string("386")));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), std::string("387")));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), std::string("386")));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), std::string("387")));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(double(387), std::string("386")));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(double(387), std::string("387")));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(bool(true), std::string("0")));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(uint64_t(387), std::string("386")));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(uint64_t(387), std::string("387")));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(int64_t(387), std::string("386")));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(int64_t(387), std::string("387")));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(double(387), std::string("386")));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(double(387), std::string("387")));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(bool(true), std::string("0")));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), uint64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), uint64_t(387)));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(std::string("387"), uint64_t(386)));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(std::string("387"), uint64_t(387)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), uint64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), uint64_t(387)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), uint64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), uint64_t(387)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(double(387), uint64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(double(387), uint64_t(387)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(bool(true), uint64_t(0)));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(bool(true), uint64_t(0)));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), int64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), int64_t(387)));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(std::string("387"), int64_t(386)));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(std::string("387"), int64_t(387)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), int64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), int64_t(387)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), int64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), int64_t(387)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(double(387), int64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(double(387), int64_t(387)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(bool(true), int64_t(0)));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(bool(true), int64_t(0)));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), double(386.7)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), double(387)));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(std::string("387"), double(386.7)));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(std::string("387"), double(387)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), double(386.7)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), double(387)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), double(386.7)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), double(387)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(double(387), double(386.7)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(double(387), double(387)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(bool(true), double(0)));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(bool(true), double(0)));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(std::string("387"), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(uint64_t(387), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(int64_t(387), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(double(387), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(double(387), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(std::string("387"), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(std::string("387"), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(uint64_t(387), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(uint64_t(387), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(int64_t(387), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(int64_t(387), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(double(387), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_greater_equal(double(387), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(bool(true), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_greater_equal(bool(true), bool(true)));
|
||||
|
||||
@@ -391,43 +300,43 @@ TEST(Variant, RelaxedGreaterEqual) {
|
||||
|
||||
TEST(Variant, RelaxedLess) {
|
||||
EXPECT_TRUE(util::relaxed_less(std::string("387"), std::string("388")));
|
||||
EXPECT_TRUE(util::relaxed_less(uint64_t(387), std::string("388")));
|
||||
EXPECT_TRUE(util::relaxed_less(int64_t(387), std::string("388")));
|
||||
EXPECT_TRUE(util::relaxed_less(double(387), std::string("388")));
|
||||
EXPECT_TRUE(util::relaxed_less(bool(false), std::string("388")));
|
||||
EXPECT_TRUE(util::relaxed_less(bool(false), std::string("1")));
|
||||
EXPECT_FALSE(util::relaxed_less(uint64_t(387), std::string("388")));
|
||||
EXPECT_FALSE(util::relaxed_less(int64_t(387), std::string("388")));
|
||||
EXPECT_FALSE(util::relaxed_less(double(387), std::string("388")));
|
||||
EXPECT_FALSE(util::relaxed_less(bool(false), std::string("388")));
|
||||
EXPECT_FALSE(util::relaxed_less(bool(false), std::string("1")));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_less(std::string("387"), uint64_t(388)));
|
||||
EXPECT_FALSE(util::relaxed_less(std::string("387"), uint64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less(uint64_t(387), uint64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less(int64_t(387), uint64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less(double(387), uint64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less(bool(false), uint64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less(bool(false), uint64_t(1)));
|
||||
EXPECT_FALSE(util::relaxed_less(bool(false), uint64_t(388)));
|
||||
EXPECT_FALSE(util::relaxed_less(bool(false), uint64_t(1)));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_less(std::string("387"), int64_t(388)));
|
||||
EXPECT_FALSE(util::relaxed_less(std::string("387"), int64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less(uint64_t(387), int64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less(int64_t(387), int64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less(double(387), int64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less(bool(false), int64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less(bool(false), int64_t(1)));
|
||||
EXPECT_FALSE(util::relaxed_less(bool(false), int64_t(388)));
|
||||
EXPECT_FALSE(util::relaxed_less(bool(false), int64_t(1)));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_less(std::string("387"), double(387.7)));
|
||||
EXPECT_FALSE(util::relaxed_less(std::string("387"), double(387.7)));
|
||||
EXPECT_TRUE(util::relaxed_less(uint64_t(387), double(387.7)));
|
||||
EXPECT_TRUE(util::relaxed_less(int64_t(387), double(387.7)));
|
||||
EXPECT_TRUE(util::relaxed_less(double(387), double(387.7)));
|
||||
EXPECT_TRUE(util::relaxed_less(bool(false), double(387)));
|
||||
EXPECT_TRUE(util::relaxed_less(bool(false), double(1)));
|
||||
EXPECT_FALSE(util::relaxed_less(bool(false), double(387)));
|
||||
EXPECT_FALSE(util::relaxed_less(bool(false), double(1)));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_less(std::string("0"), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_less(uint64_t(0), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_less(int64_t(0), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_less(double(0), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_less(std::string("0"), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_less(uint64_t(0), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_less(int64_t(0), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_less(double(0), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_less(bool(false), bool(true)));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_less(bool(true), std::string("386")));
|
||||
EXPECT_TRUE(util::relaxed_less(bool(true), uint64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_less(bool(true), int64_t(386)));
|
||||
EXPECT_TRUE(util::relaxed_less(bool(true), double(386)));
|
||||
EXPECT_FALSE(util::relaxed_less(bool(true), std::string("386")));
|
||||
EXPECT_FALSE(util::relaxed_less(bool(true), uint64_t(386)));
|
||||
EXPECT_FALSE(util::relaxed_less(bool(true), int64_t(386)));
|
||||
EXPECT_FALSE(util::relaxed_less(bool(true), double(386)));
|
||||
|
||||
|
||||
|
||||
@@ -464,60 +373,60 @@ TEST(Variant, RelaxedLess) {
|
||||
TEST(Variant, RelaxedLessEqual) {
|
||||
EXPECT_TRUE(util::relaxed_less_equal(std::string("387"), std::string("388")));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(std::string("387"), std::string("387")));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(uint64_t(387), std::string("388")));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(uint64_t(387), std::string("387")));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(int64_t(387), std::string("388")));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(int64_t(387), std::string("387")));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(double(387), std::string("388")));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(double(387), std::string("387")));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(bool(false), std::string("388")));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(bool(false), std::string("1")));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(bool(false), std::string("0")));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(uint64_t(387), std::string("388")));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(uint64_t(387), std::string("387")));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(int64_t(387), std::string("388")));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(int64_t(387), std::string("387")));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(double(387), std::string("388")));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(double(387), std::string("387")));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(bool(false), std::string("388")));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(bool(false), std::string("1")));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(bool(false), std::string("0")));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_less_equal(std::string("387"), uint64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(std::string("387"), uint64_t(387)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(std::string("387"), uint64_t(388)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(std::string("387"), uint64_t(387)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(uint64_t(387), uint64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(uint64_t(387), uint64_t(387)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(int64_t(387), uint64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(int64_t(387), uint64_t(387)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(double(387), uint64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(double(387), uint64_t(387)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(bool(false), uint64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(bool(false), uint64_t(1)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(bool(false), uint64_t(0)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(bool(false), uint64_t(388)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(bool(false), uint64_t(1)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(bool(false), uint64_t(0)));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_less_equal(std::string("387"), int64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(std::string("387"), int64_t(387)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(std::string("387"), int64_t(388)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(std::string("387"), int64_t(387)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(uint64_t(387), int64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(uint64_t(387), int64_t(387)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(int64_t(387), int64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(int64_t(387), int64_t(387)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(double(387), int64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(double(387), int64_t(387)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(bool(false), int64_t(388)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(bool(false), int64_t(1)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(bool(false), int64_t(0)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(bool(false), int64_t(388)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(bool(false), int64_t(1)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(bool(false), int64_t(0)));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_less_equal(std::string("387"), double(387.7)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(std::string("387"), double(387)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(std::string("387"), double(387.7)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(std::string("387"), double(387)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(uint64_t(387), double(387.7)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(uint64_t(387), double(387)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(int64_t(387), double(387.7)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(int64_t(387), double(387)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(double(387), double(387.7)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(double(387), double(387)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(bool(false), double(387)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(bool(false), double(1)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(bool(false), double(0)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(bool(false), double(387)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(bool(false), double(1)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(bool(false), double(0)));
|
||||
|
||||
EXPECT_TRUE(util::relaxed_less_equal(std::string("0"), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(std::string("0"), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(uint64_t(0), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(uint64_t(0), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(int64_t(0), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(int64_t(0), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(double(0), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(double(0), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(std::string("0"), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(std::string("0"), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(uint64_t(0), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(uint64_t(0), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(int64_t(0), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(int64_t(0), bool(false)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(double(0), bool(true)));
|
||||
EXPECT_FALSE(util::relaxed_less_equal(double(0), bool(false)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(bool(false), bool(true)));
|
||||
EXPECT_TRUE(util::relaxed_less_equal(bool(false), bool(false)));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user