[core] Implement has/!has filters (#4952)
This commit is contained in:
@@ -20,7 +20,9 @@ typedef variant<
|
||||
class NotInFilter,
|
||||
class AnyFilter,
|
||||
class AllFilter,
|
||||
class NoneFilter
|
||||
class NoneFilter,
|
||||
class HasFilter,
|
||||
class NotHasFilter
|
||||
> Filter;
|
||||
|
||||
class NullFilter {};
|
||||
@@ -88,4 +90,14 @@ public:
|
||||
std::vector<Filter> filters;
|
||||
};
|
||||
|
||||
class HasFilter {
|
||||
public:
|
||||
std::string key;
|
||||
};
|
||||
|
||||
class NotHasFilter {
|
||||
public:
|
||||
std::string key;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -97,6 +97,14 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator()(const HasFilter& filter) const {
|
||||
return bool(getValue(filter.key));
|
||||
}
|
||||
|
||||
bool operator()(const NotHasFilter& filter) const {
|
||||
return !getValue(filter.key);
|
||||
}
|
||||
|
||||
private:
|
||||
optional<Value> getValue(const std::string& key) const {
|
||||
return key == "$type"
|
||||
|
||||
@@ -533,6 +533,25 @@ Value parseValue(const JSValue& value) {
|
||||
}
|
||||
}
|
||||
|
||||
template <class Expression>
|
||||
Filter parseUnaryFilter(const JSValue& value) {
|
||||
Filter empty;
|
||||
|
||||
if (value.Size() < 2) {
|
||||
Log::Warning(Event::ParseStyle, "filter expression must have 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() };
|
||||
return expression;
|
||||
}
|
||||
|
||||
template <class Expression>
|
||||
Filter parseBinaryFilter(const JSValue& value) {
|
||||
Filter empty;
|
||||
@@ -635,8 +654,12 @@ Filter parseFilter(const JSValue& value) {
|
||||
return parseCompoundFilter<AnyFilter>(value);
|
||||
} else if (op == "none") {
|
||||
return parseCompoundFilter<NoneFilter>(value);
|
||||
} else if (op == "has") {
|
||||
return parseUnaryFilter<HasFilter>(value);
|
||||
} else if (op == "!has") {
|
||||
return parseUnaryFilter<NotHasFilter>(value);
|
||||
} else {
|
||||
Log::Warning(Event::ParseStyle, "filter operator must be one of \"==\", \"!=\", \">\", \">=\", \"<\", \"<=\", \"in\", \"!in\", \"all\", \"any\", \"none\"");
|
||||
Log::Warning(Event::ParseStyle, "filter operator must be one of \"==\", \"!=\", \">\", \">=\", \"<\", \"<=\", \"in\", \"!in\", \"all\", \"any\", \"none\", \"has\", or \"!has\"");
|
||||
return empty;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,3 +114,25 @@ TEST(Filter, None) {
|
||||
ASSERT_FALSE(evaluate(parse("[\"none\", [\"==\", \"foo\", 0], [\"==\", \"foo\", 1]]"),
|
||||
{{ std::string("foo"), int64_t(1) }}));
|
||||
}
|
||||
|
||||
TEST(Filter, Has) {
|
||||
ASSERT_TRUE(evaluate(parse("[\"has\", \"foo\"]"),
|
||||
{{ std::string("foo"), int64_t(1) }}));
|
||||
ASSERT_TRUE(evaluate(parse("[\"has\", \"foo\"]"),
|
||||
{{ std::string("foo"), int64_t(0) }}));
|
||||
ASSERT_TRUE(evaluate(parse("[\"has\", \"foo\"]"),
|
||||
{{ std::string("foo"), false }}));
|
||||
ASSERT_FALSE(evaluate(parse("[\"has\", \"foo\"]"),
|
||||
{{}}));
|
||||
}
|
||||
|
||||
TEST(Filter, NotHas) {
|
||||
ASSERT_FALSE(evaluate(parse("[\"!has\", \"foo\"]"),
|
||||
{{ std::string("foo"), int64_t(1) }}));
|
||||
ASSERT_FALSE(evaluate(parse("[\"!has\", \"foo\"]"),
|
||||
{{ std::string("foo"), int64_t(0) }}));
|
||||
ASSERT_FALSE(evaluate(parse("[\"!has\", \"foo\"]"),
|
||||
{{ std::string("foo"), false }}));
|
||||
ASSERT_TRUE(evaluate(parse("[\"!has\", \"foo\"]"),
|
||||
{{}}));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user