Keep original input for filters using legacy syntax.
This commit is contained in:
@@ -11,14 +11,18 @@
|
||||
|
||||
namespace mbgl {
|
||||
namespace style {
|
||||
|
||||
|
||||
class Filter {
|
||||
public:
|
||||
optional<std::shared_ptr<const expression::Expression>> expression;
|
||||
|
||||
private:
|
||||
optional<mbgl::Value> legacyFilter;
|
||||
public:
|
||||
Filter() : expression() {}
|
||||
|
||||
Filter(expression::ParseResult _expression) : expression(std::move(*_expression)) {
|
||||
Filter(expression::ParseResult _expression, optional<mbgl::Value> _filter = {})
|
||||
: expression(std::move(*_expression)),
|
||||
legacyFilter(std::move(_filter)){
|
||||
assert(!expression || *expression != nullptr);
|
||||
}
|
||||
|
||||
@@ -35,6 +39,16 @@ public:
|
||||
friend bool operator!=(const Filter& lhs, const Filter& rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
mbgl::Value serialize() const {
|
||||
if (legacyFilter) {
|
||||
return *legacyFilter;
|
||||
}
|
||||
else if (expression) {
|
||||
return (**expression).serialize();
|
||||
}
|
||||
return NullValue();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace style
|
||||
|
||||
@@ -14,6 +14,7 @@ using namespace mbgl::style::expression;
|
||||
|
||||
static bool isExpression(const Convertible& filter);
|
||||
ParseResult convertLegacyFilter(const Convertible& values, Error& error);
|
||||
optional<mbgl::Value> serializeLegacyFilter(const Convertible& values);
|
||||
|
||||
optional<Filter> Converter<Filter>::operator()(const Convertible& value, Error& error) const {
|
||||
if (isExpression(value)) {
|
||||
@@ -31,7 +32,7 @@ optional<Filter> Converter<Filter>::operator()(const Convertible& value, Error&
|
||||
assert(error.message.size() > 0);
|
||||
return {};
|
||||
}
|
||||
return Filter(optional<std::unique_ptr<Expression>>(std::move(*expression)));
|
||||
return Filter(optional<std::unique_ptr<Expression>>(std::move(*expression)), serializeLegacyFilter(value));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,6 +219,24 @@ ParseResult convertLegacyFilter(const Convertible& values, Error& error) {
|
||||
}
|
||||
}
|
||||
|
||||
optional<mbgl::Value> serializeLegacyFilter(const Convertible& values) {
|
||||
if (isUndefined(values)) {
|
||||
return {};
|
||||
} else if (isArray(values)) {
|
||||
std::vector<mbgl::Value> result;
|
||||
for (std::size_t i = 0; i < arrayLength(values); i++) {
|
||||
auto arrayValue = serializeLegacyFilter(arrayMember(values, i));
|
||||
if (arrayValue) {
|
||||
result.push_back(*arrayValue);
|
||||
} else {
|
||||
result.push_back(NullValue());
|
||||
}
|
||||
}
|
||||
return (mbgl::Value)result;
|
||||
}
|
||||
return toValue(values);
|
||||
}
|
||||
|
||||
} // namespace conversion
|
||||
} // namespace style
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
#include <mbgl/style/filter.hpp>
|
||||
#include <mbgl/style/conversion/json.hpp>
|
||||
#include <mbgl/style/conversion/filter.hpp>
|
||||
#include <mbgl/util/rapidjson.hpp>
|
||||
|
||||
#include <rapidjson/writer.h>
|
||||
#include <rapidjson/stringbuffer.h>
|
||||
|
||||
using namespace mbgl;
|
||||
using namespace mbgl::style;
|
||||
@@ -39,6 +43,42 @@ void invalidFilter(const char * json) {
|
||||
EXPECT_NE(error.message, "");
|
||||
}
|
||||
|
||||
void writeJSON(rapidjson::Writer<rapidjson::StringBuffer>& writer, const Value& value) {
|
||||
value.match(
|
||||
[&] (const NullValue&) { writer.Null(); },
|
||||
[&] (bool b) { writer.Bool(b); },
|
||||
[&] (uint64_t t) { writer.Uint64(t); },
|
||||
[&] (int64_t t) { writer.Int64(t); },
|
||||
[&] (double f) {
|
||||
// make sure integer values are stringified without trailing ".0".
|
||||
f == std::floor(f) ? writer.Int(f) : writer.Double(f);
|
||||
},
|
||||
[&] (const std::string& s) { writer.String(s); },
|
||||
[&] (const std::vector<Value>& arr) {
|
||||
writer.StartArray();
|
||||
for(const auto& item : arr) {
|
||||
writeJSON(writer, item);
|
||||
}
|
||||
writer.EndArray();
|
||||
},
|
||||
[](const auto&) {
|
||||
});
|
||||
}
|
||||
|
||||
std::string stringifyFilter(const char * json) {
|
||||
conversion::Error error;
|
||||
optional<Filter> filter = conversion::convertJSON<Filter>(json, error);
|
||||
EXPECT_TRUE(bool(filter));
|
||||
EXPECT_EQ(error.message, "");
|
||||
|
||||
auto value = filter->serialize();
|
||||
|
||||
rapidjson::StringBuffer s;
|
||||
rapidjson::Writer<rapidjson::StringBuffer> writer(s);
|
||||
writeJSON(writer, value);
|
||||
return s.GetString();
|
||||
}
|
||||
|
||||
TEST(Filter, EqualsNull) {
|
||||
auto f = R"(["==", "foo", null])";
|
||||
ASSERT_TRUE(filter(f, {{ "foo", mapbox::geometry::null_value }}));
|
||||
@@ -181,6 +221,21 @@ TEST(Filter, LegacyProperty) {
|
||||
ASSERT_FALSE(filter("[\"==\", \"two\", 4]", {{"two", std::string("2")}}));
|
||||
}
|
||||
|
||||
TEST(Filter, Serialize) {
|
||||
std::string json = R"(["any",["==","foo",0],["==","foo",1]])";
|
||||
EXPECT_EQ(stringifyFilter(json.c_str()), std::string(json));
|
||||
|
||||
json = R"(["<=","two",2])";
|
||||
EXPECT_EQ(stringifyFilter(json.c_str()), std::string(json));
|
||||
|
||||
//Constant folding for Expression filters
|
||||
json = R"(["==",["+",1,1],2])";
|
||||
EXPECT_EQ(stringifyFilter(json.c_str()), std::string("true"));
|
||||
|
||||
json = R"(["all",["==",["get","foo"],0],["==",["get","foo"],1]])";
|
||||
EXPECT_EQ(stringifyFilter(json.c_str()), std::string(json));
|
||||
}
|
||||
|
||||
TEST(Filter, ExpressionLegacyMix) {
|
||||
conversion::Error error;
|
||||
optional<Filter> filter = conversion::convertJSON<Filter>(R"(["any", ["all", ["==", ["geometry-type"], "LineString"]], ["==", "x", 1]])", error);
|
||||
|
||||
Reference in New Issue
Block a user