diff options
-rw-r--r-- | include/mbgl/style/filter.hpp | 20 | ||||
-rw-r--r-- | src/mbgl/style/conversion/filter.cpp | 21 | ||||
-rw-r--r-- | test/style/filter.test.cpp | 55 |
3 files changed, 92 insertions, 4 deletions
diff --git a/include/mbgl/style/filter.hpp b/include/mbgl/style/filter.hpp index ce4015bb69..c9dc9fb1ec 100644 --- a/include/mbgl/style/filter.hpp +++ b/include/mbgl/style/filter.hpp @@ -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 diff --git a/src/mbgl/style/conversion/filter.cpp b/src/mbgl/style/conversion/filter.cpp index cd588345ef..b690c96388 100644 --- a/src/mbgl/style/conversion/filter.cpp +++ b/src/mbgl/style/conversion/filter.cpp @@ -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 diff --git a/test/style/filter.test.cpp b/test/style/filter.test.cpp index bac3801223..e04a569203 100644 --- a/test/style/filter.test.cpp +++ b/test/style/filter.test.cpp @@ -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); |