#pragma once #include #include #include #include #include #include #include #include #include namespace mbgl { namespace style { namespace expression { struct Value; using ValueBase = variant< NullValue, bool, double, std::string, Color, mapbox::util::recursive_wrapper>, mapbox::util::recursive_wrapper>>; struct Value : ValueBase { using ValueBase::ValueBase; // Javascript's Number.MAX_SAFE_INTEGER static uint64_t maxSafeInteger() { return 9007199254740991ULL; } static bool isSafeInteger(uint64_t x) { return x <= maxSafeInteger(); }; static bool isSafeInteger(int64_t x) { return static_cast(x > 0 ? x : -x) <= maxSafeInteger(); } static bool isSafeInteger(double x) { return static_cast(x > 0 ? x : -x) <= maxSafeInteger(); } }; constexpr NullValue Null = NullValue(); type::Type typeOf(const Value& value); std::string stringify(const Value& value); /* Returns a Type object representing the expression type that corresponds to the value type T. (Specialized for primitives and specific array types in the .cpp.) */ template type::Type valueTypeToExpressionType(); /* Conversions between style value types and expression::Value */ // no-op overloads Value toExpressionValue(const Value&); // T = Value (just wrap in optional) template std::enable_if_t::value, optional> fromExpressionValue(const Value& v) { return optional(v); } // T = member type of Value template std::enable_if_t< std::is_convertible::value && !std::is_same::value, optional> fromExpressionValue(const Value& v) { return v.template is() ? v.template get() : optional(); } // real conversions template ::value >> Value toExpressionValue(const T& value); template std::enable_if_t< !std::is_convertible::value, optional> fromExpressionValue(const Value& v); template struct ValueConverter { using ExpressionType = T; static Value toExpressionValue(const T& value) { return Value(value); } static optional fromExpressionValue(const Value& value) { return value.template is() ? value.template get() : optional(); } }; template <> struct ValueConverter { using ExpressionType = double; static type::Type expressionType() { return type::Number; } static Value toExpressionValue(const float value); static optional fromExpressionValue(const Value& value); }; template<> struct ValueConverter { static Value toExpressionValue(const mbgl::Value& value); static mbgl::Value fromExpressionValue(const Value& value); }; template struct ValueConverter> { using ExpressionType = std::vector; static type::Type expressionType() { return type::Array(valueTypeToExpressionType(), N); } static Value toExpressionValue(const std::array& value); static optional> fromExpressionValue(const Value& value); }; template struct ValueConverter> { using ExpressionType = std::vector; static type::Type expressionType() { return type::Array(valueTypeToExpressionType()); } static Value toExpressionValue(const std::vector& value); static optional> fromExpressionValue(const Value& value); }; template <> struct ValueConverter { using ExpressionType = std::vector; static type::Type expressionType() { return type::Array(type::Number, 3); } static Value toExpressionValue(const mbgl::style::Position& value); static optional fromExpressionValue(const Value& v); }; template struct ValueConverter::value >> { using ExpressionType = std::string; static type::Type expressionType() { return type::String; } static Value toExpressionValue(const T& value); static optional fromExpressionValue(const Value& value); }; template std::vector> fromExpressionValues(const std::vector>& values) { std::vector> result; for (const auto& value : values) { result.push_back(value ? fromExpressionValue(*value) : nullopt); } return result; } } // namespace expression } // namespace style } // namespace mbgl