#pragma once #include #include #include #include #include #include #include #include #include #include #include namespace mbgl { namespace style { namespace conversion { template void stringify(Writer& writer, NullValue) { writer.Null(); } template void stringify(Writer& writer, bool v) { writer.Bool(v); } template void stringify(Writer& writer, uint64_t v) { writer.Uint64(v); } template void stringify(Writer& writer, int64_t v) { writer.Int64(v); } template void stringify(Writer& writer, double v) { writer.Double(v); } template void stringify(Writer& writer, const std::string& v) { writer.String(v); } template ::value>> void stringify(Writer& writer, const T& v) { writer.String(Enum::toString(v)); } template void stringify(Writer& writer, const Color& v) { writer.String(v.stringify()); } template void stringify(Writer& writer, const std::array& v) { writer.StartArray(); writer.Double(v[0]); writer.Double(v[1]); writer.EndArray(); } template void stringify(Writer& writer, const std::array& v) { writer.StartArray(); writer.Double(v[0]); writer.Double(v[1]); writer.Double(v[2]); writer.Double(v[3]); writer.EndArray(); } template void stringify(Writer&, const Value&); template void stringify(Writer& writer, const std::vector& v) { writer.StartArray(); for (const auto& e : v) { stringify(writer, e); } writer.EndArray(); } template void stringify(Writer& writer, const std::unordered_map& m) { writer.StartObject(); for (const auto& p : m) { writer.Key(p.first.data(), static_cast(p.first.size())); stringify(writer, p.second); } writer.EndObject(); } template void stringify(Writer& writer, const Value& v) { Value::visit(v, [&] (const auto& v_) { stringify(writer, v_); }); } template void stringify(Writer& writer, FeatureType type) { switch (type) { case FeatureType::Unknown: writer.String("Unknown"); break; case FeatureType::Point: writer.String("Point"); break; case FeatureType::LineString: writer.String("LineString"); break; case FeatureType::Polygon: writer.String("Polygon"); break; } } template void stringify(Writer& writer, const FeatureIdentifier& id) { FeatureIdentifier::visit(id, [&] (const auto& id_) { stringify(writer, id_); }); } template class StringifyFilter { public: Writer& writer; void operator()(const NullFilter&) { writer.Null(); } void operator()(const EqualsFilter& f) { stringifyBinaryFilter(f, "=="); } void operator()(const NotEqualsFilter& f) { stringifyBinaryFilter(f, "!="); } void operator()(const LessThanFilter& f) { stringifyBinaryFilter(f, "<"); } void operator()(const LessThanEqualsFilter& f) { stringifyBinaryFilter(f, "<="); } void operator()(const GreaterThanFilter& f) { stringifyBinaryFilter(f, ">"); } void operator()(const GreaterThanEqualsFilter& f) { stringifyBinaryFilter(f, ">="); } void operator()(const InFilter& f) { stringifySetFilter(f, "in"); } void operator()(const NotInFilter& f) { stringifySetFilter(f, "!in"); } void operator()(const AllFilter& f) { stringifyCompoundFilter(f, "all"); } void operator()(const AnyFilter& f) { stringifyCompoundFilter(f, "any"); } void operator()(const NoneFilter& f) { stringifyCompoundFilter(f, "none"); } void operator()(const HasFilter& f) { stringifyUnaryFilter("has", f.key); } void operator()(const NotHasFilter& f) { stringifyUnaryFilter("!has", f.key); } void operator()(const TypeEqualsFilter& f) { stringifyBinaryFilter(f, "==", "$type"); } void operator()(const TypeNotEqualsFilter& f) { stringifyBinaryFilter(f, "!=", "$type"); } void operator()(const TypeInFilter& f) { stringifySetFilter(f, "in", "$type"); } void operator()(const TypeNotInFilter& f) { stringifySetFilter(f, "!in", "$type"); } void operator()(const IdentifierEqualsFilter& f) { stringifyBinaryFilter(f, "==", "$id"); } void operator()(const IdentifierNotEqualsFilter& f) { stringifyBinaryFilter(f, "!=", "$id"); } void operator()(const IdentifierInFilter& f) { stringifySetFilter(f, "in", "$id"); } void operator()(const IdentifierNotInFilter& f) { stringifySetFilter(f, "!in", "$id"); } void operator()(const HasIdentifierFilter&) { stringifyUnaryFilter("has", "$id"); } void operator()(const NotHasIdentifierFilter&) { stringifyUnaryFilter("!has", "$id"); } void operator()(const ExpressionFilter& filter) { stringify(writer, filter.expression->serialize()); } private: template void stringifyBinaryFilter(const F& f, const char * op) { stringifyBinaryFilter(f, op, f.key); } template void stringifyBinaryFilter(const F& f, const char * op, const std::string& key) { writer.StartArray(); writer.String(op); writer.String(key); stringify(writer, f.value); writer.EndArray(); } template void stringifySetFilter(const F& f, const char * op) { stringifySetFilter(f, op, f.key); } template void stringifySetFilter(const F& f, const char * op, const std::string& key) { writer.StartArray(); writer.String(op); writer.String(key); for (const auto& value : f.values) { stringify(writer, value); } writer.EndArray(); } template void stringifyCompoundFilter(const F& f, const char * op) { writer.StartArray(); writer.String(op); for (const auto& filter : f.filters) { Filter::visit(filter, *this); } writer.EndArray(); } void stringifyUnaryFilter(const char * op, const std::string& key) { writer.StartArray(); writer.String(op); writer.String(key); writer.EndArray(); } }; template void stringify(Writer& writer, const Filter& f) { Filter::visit(f, StringifyFilter { writer }); } template void stringify(Writer& writer, const Undefined&) { assert(false); // Should be omitted entirely instead. writer.Null(); } template void stringify(Writer& writer, const CameraFunction& fn) { stringify(writer, fn.getExpression().serialize()); } template void stringify(Writer& writer, const SourceFunction& fn) { stringify(writer, fn.getExpression().serialize()); } template void stringify(Writer& writer, const CompositeFunction& fn) { stringify(writer, fn.getExpression().serialize()); } template void stringify(Writer& writer, const PropertyValue& v) { v.evaluate([&] (const auto& v_) { stringify(writer, v_); }); } template void stringify(Writer& writer, const PropertyValue& value) { if (!value.isUndefined()) { writer.Key(Property::key); stringify(writer, value); } } template void stringify(Writer& writer, const DataDrivenPropertyValue& v) { v.evaluate([&] (const auto& v_) { stringify(writer, v_); }); } template void stringify(Writer& writer, const DataDrivenPropertyValue& value) { if (!value.isUndefined()) { writer.Key(Property::key); stringify(writer, value); } } } // namespace conversion } // namespace style } // namespace mbgl