#include #include #include #include namespace mbgl { namespace style { namespace expression { type::Type typeOf(const Value& value) { return value.match( [&](bool) -> type::Type { return type::Boolean; }, [&](double) -> type::Type { return type::Number; }, [&](const std::string&) -> type::Type { return type::String; }, [&](const Color&) -> type::Type { return type::Color; }, [&](const Collator&) -> type::Type { return type::Collator; }, [&](const Formatted&) -> type::Type { return type::Formatted; }, [&](const NullValue&) -> type::Type { return type::Null; }, [&](const std::unordered_map&) -> type::Type { return type::Object; }, [&](const std::vector& arr) -> type::Type { optional itemType; for (const auto& item : arr) { const type::Type t = typeOf(item); if (!itemType) { itemType = {t}; } else if (*itemType == t) { continue; } else { itemType = {type::Value}; break; } } return type::Array(itemType.value_or(type::Value), arr.size()); } ); } std::string toString(const Value& value) { return value.match( [](const NullValue&) { return std::string(); }, [](const Color& c) { return c.stringify(); }, // avoid quoting [](const Formatted& f) { return f.toString(); }, [](const std::string& s) { return s; }, // avoid quoting [](const auto& v_) { return stringify(v_); } ); } void writeJSON(rapidjson::Writer& writer, const Value& value) { value.match( [&] (const NullValue&) { writer.Null(); }, [&] (bool b) { writer.Bool(b); }, [&] (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 Color& c) { writer.String(c.stringify()); }, [&] (const Collator&) { // Collators are excluded from constant folding and there's no Literal parser // for them so there shouldn't be any way to serialize this value. assert(false); }, [&] (const Formatted& f) { // `stringify` in turns calls ValueConverter::fromExpressionValue below // Serialization strategy for Formatted objects is to return the constant // expression that would generate them. mbgl::style::conversion::stringify(writer, f); }, [&] (const std::vector& arr) { writer.StartArray(); for(const auto& item : arr) { writeJSON(writer, item); } writer.EndArray(); }, [&] (const std::unordered_map& obj) { writer.StartObject(); for(const auto& entry : obj) { writer.Key(entry.first.c_str()); writeJSON(writer, entry.second); } writer.EndObject(); } ); } std::string stringify(const Value& value) { rapidjson::StringBuffer buffer; rapidjson::Writer writer(buffer); writeJSON(writer, value); return buffer.GetString(); } struct FromMBGLValue { Value operator()(const std::vector& v) { std::vector result; result.reserve(v.size()); for(const auto& item : v) { result.emplace_back(toExpressionValue(item)); } return result; } Value operator()(const std::unordered_map& v) { std::unordered_map result; result.reserve(v.size()); for(const auto& entry : v) { result.emplace(entry.first, toExpressionValue(entry.second)); } return result; } Value operator()(const std::string& s) { return s; } Value operator()(const bool b) { return b; } Value operator()(const NullValue) { return Null; } Value operator()(const double v) { return v; } Value operator()(const uint64_t& v) { return static_cast(v); } Value operator()(const int64_t& v) { return static_cast(v); } }; Value ValueConverter::toExpressionValue(const mbgl::Value& value) { return mbgl::Value::visit(value, FromMBGLValue()); } mbgl::Value ValueConverter::fromExpressionValue(const Value& value) { return value.match( [&](const Color& color)->mbgl::Value { std::array array = color.toArray(); return std::vector{ std::string("rgba"), array[0], array[1], array[2], array[3], }; }, [&](const Collator&)->mbgl::Value { // fromExpressionValue can't be used for Collator values, // because they have no meaningful representation as an mbgl::Value assert(false); return mbgl::Value(); }, [&](const Formatted& formatted)->mbgl::Value { // Serialization strategy for Formatted objects is to return the constant // expression that would generate them. std::vector serialized; static std::string formatOperator("format"); serialized.emplace_back(formatOperator); for (const auto& section : formatted.sections) { serialized.emplace_back(section.text); std::unordered_map options; if (section.fontScale) { options.emplace("font-scale", *section.fontScale); } if (section.fontStack) { std::vector fontStack; for (const auto& font : *section.fontStack) { fontStack.emplace_back(font); } options.emplace("text-font", std::vector{ std::string("literal"), fontStack }); } if (section.textColor) { options.emplace("text-color", fromExpressionValue(*section.textColor)); } serialized.emplace_back(options); } return serialized; }, [&](const std::vector& values)->mbgl::Value { std::vector converted; converted.reserve(values.size()); for (const Value& v : values) { converted.emplace_back(fromExpressionValue(v)); } return converted; }, [&](const std::unordered_map& values)->mbgl::Value { std::unordered_map converted; converted.reserve(values.size()); for(const auto& entry : values) { converted.emplace(entry.first, fromExpressionValue(entry.second)); } return converted; }, [&](const auto& a)->mbgl::Value { return a; } ); } Value ValueConverter::toExpressionValue(const float value) { return static_cast(value); } optional ValueConverter::fromExpressionValue(const Value& value) { return value.template is() ? static_cast(value.template get()) : optional(); } template std::vector toArrayValue(const Container& value) { std::vector result; result.reserve(value.size()); for (const T& item : value) { result.push_back(ValueConverter::toExpressionValue(item)); } return result; } template Value ValueConverter>::toExpressionValue(const std::array& value) { return toArrayValue(value); } template optional> ValueConverter>::fromExpressionValue(const Value& value) { return value.match( [&] (const std::vector& v) -> optional> { if (v.size() != N) return optional>(); std::array result; auto it = result.begin(); for(const Value& item : v) { optional convertedItem = ValueConverter::fromExpressionValue(item); if (!convertedItem) { return optional>(); } *it = *convertedItem; it = std::next(it); } return result; }, [&] (const auto&) { return optional>(); } ); } template Value ValueConverter>::toExpressionValue(const std::vector& value) { return toArrayValue(value); } template optional> ValueConverter>::fromExpressionValue(const Value& value) { return value.match( [&] (const std::vector& v) -> optional> { std::vector result; result.reserve(v.size()); for(const Value& item : v) { optional convertedItem = ValueConverter::fromExpressionValue(item); if (!convertedItem) { return optional>(); } result.push_back(*convertedItem); } return result; }, [&] (const auto&) { return optional>(); } ); } Value ValueConverter::toExpressionValue(const mbgl::style::Position& value) { return ValueConverter>::toExpressionValue(value.getSpherical()); } optional ValueConverter::fromExpressionValue(const Value& v) { auto pos = ValueConverter>::fromExpressionValue(v); return pos ? optional(Position(*pos)) : optional(); } Value ValueConverter::toExpressionValue(const mbgl::style::RadialOffsetType& value) { return ValueConverter>::toExpressionValue(value); } optional ValueConverter::fromExpressionValue(const Value& v) { if (auto val = ValueConverter>::fromExpressionValue(v)) { RadialOffsetType result(std::move(*val)); return result; } if (auto val = ValueConverter::fromExpressionValue(v)) { RadialOffsetType result(2, *val); return result; } return nullopt; } template Value ValueConverter::value >>::toExpressionValue(const T& value) { return std::string(Enum::toString(value)); } template optional ValueConverter::value >>::fromExpressionValue(const Value& value) { return value.match( [&] (const std::string& v) { return Enum::toEnum(v); }, [&] (const auto&) { return optional(); } ); } template type::Type valueTypeToExpressionType() { return ValueConverter::expressionType(); } template <> type::Type valueTypeToExpressionType() { return type::Value; } template <> type::Type valueTypeToExpressionType() { return type::Null; } template <> type::Type valueTypeToExpressionType() { return type::Boolean; } template <> type::Type valueTypeToExpressionType() { return type::Number; } template <> type::Type valueTypeToExpressionType() { return type::String; } template <> type::Type valueTypeToExpressionType() { return type::Color; } template <> type::Type valueTypeToExpressionType() { return type::Collator; } template <> type::Type valueTypeToExpressionType() { return type::Formatted; } template <> type::Type valueTypeToExpressionType>() { return type::Object; } template <> type::Type valueTypeToExpressionType>() { return type::Array(type::Value); } // used only for the special (and private) "error" expression template <> type::Type valueTypeToExpressionType() { return type::Error; } // for to_rgba expression template type::Type valueTypeToExpressionType>(); template struct ValueConverter>; // layout/paint property types template type::Type valueTypeToExpressionType(); template type::Type valueTypeToExpressionType(); template type::Type valueTypeToExpressionType>(); template struct ValueConverter>; template type::Type valueTypeToExpressionType>(); template struct ValueConverter>; template type::Type valueTypeToExpressionType>(); template struct ValueConverter>; template type::Type valueTypeToExpressionType>(); template struct ValueConverter>; template type::Type valueTypeToExpressionType>(); template struct ValueConverter>; template type::Type valueTypeToExpressionType(); template struct ValueConverter; template type::Type valueTypeToExpressionType(); template struct ValueConverter; template type::Type valueTypeToExpressionType(); template struct ValueConverter; template type::Type valueTypeToExpressionType(); template struct ValueConverter; template type::Type valueTypeToExpressionType(); template struct ValueConverter; template type::Type valueTypeToExpressionType(); template struct ValueConverter; template type::Type valueTypeToExpressionType(); template struct ValueConverter; template type::Type valueTypeToExpressionType(); template struct ValueConverter; template type::Type valueTypeToExpressionType(); template struct ValueConverter; template type::Type valueTypeToExpressionType(); template struct ValueConverter; template type::Type valueTypeToExpressionType(); template struct ValueConverter; template type::Type valueTypeToExpressionType(); template struct ValueConverter; template type::Type valueTypeToExpressionType(); template struct ValueConverter; template type::Type valueTypeToExpressionType(); template struct ValueConverter; template<> type::Type valueTypeToExpressionType() { return valueTypeToExpressionType>(); } } // namespace expression } // namespace style } // namespace mbgl