[core] Implement has/!has filters (#4952)

This commit is contained in:
John Firebaugh
2016-05-05 14:30:37 -07:00
parent a66901ed07
commit 59a7fbf8e4
4 changed files with 67 additions and 2 deletions

View File

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

View File

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

View File

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

View File

@@ -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\"]"),
{{}}));
}