diff options
Diffstat (limited to 'include/mbgl/style/expression/value.hpp')
-rw-r--r-- | include/mbgl/style/expression/value.hpp | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/include/mbgl/style/expression/value.hpp b/include/mbgl/style/expression/value.hpp new file mode 100644 index 0000000000..8baa9d2dba --- /dev/null +++ b/include/mbgl/style/expression/value.hpp @@ -0,0 +1,153 @@ +#pragma once + +#include <mbgl/style/expression/type.hpp> +#include <mbgl/style/position.hpp> +#include <mbgl/style/types.hpp> +#include <mbgl/util/color.hpp> +#include <mbgl/util/enum.hpp> +#include <mbgl/util/feature.hpp> +#include <mbgl/util/variant.hpp> + +#include <array> +#include <vector> + +namespace mbgl { +namespace style { +namespace expression { + +struct Value; + +using ValueBase = variant< + NullValue, + bool, + double, + std::string, + Color, + mapbox::util::recursive_wrapper<std::vector<Value>>, + mapbox::util::recursive_wrapper<std::unordered_map<std::string, Value>>>; +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<uint64_t>(x > 0 ? x : -x) <= maxSafeInteger(); + } + static bool isSafeInteger(double x) { + return static_cast<uint64_t>(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 <typename T> +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 <typename T> +std::enable_if_t<std::is_same<T, Value>::value, +optional<T>> fromExpressionValue(const Value& v) +{ + return optional<T>(v); +} + +// T = member type of Value +template <typename T> +std::enable_if_t< std::is_convertible<T, Value>::value && !std::is_same<T, Value>::value, +optional<T>> fromExpressionValue(const Value& v) +{ + return v.template is<T>() ? v.template get<T>() : optional<T>(); +} + +// real conversions +template <typename T, typename Enable = std::enable_if_t< !std::is_convertible<T, Value>::value >> +Value toExpressionValue(const T& value); + +template <typename T> +std::enable_if_t< !std::is_convertible<T, Value>::value, +optional<T>> fromExpressionValue(const Value& v); + + + +template <class T, class Enable = void> +struct ValueConverter { + using ExpressionType = T; + + static Value toExpressionValue(const T& value) { + return Value(value); + } + static optional<T> fromExpressionValue(const Value& value) { + return value.template is<T>() ? value.template get<T>() : optional<T>(); + } +}; + +template <> +struct ValueConverter<float> { + using ExpressionType = double; + static type::Type expressionType() { return type::Number; } + static Value toExpressionValue(const float value); + static optional<float> fromExpressionValue(const Value& value); +}; + +template<> +struct ValueConverter<mbgl::Value> { + static Value toExpressionValue(const mbgl::Value& value); +}; + +template <typename T, std::size_t N> +struct ValueConverter<std::array<T, N>> { + using ExpressionType = std::vector<Value>; + static type::Type expressionType() { + return type::Array(valueTypeToExpressionType<T>(), N); + } + static Value toExpressionValue(const std::array<T, N>& value); + static optional<std::array<T, N>> fromExpressionValue(const Value& value); +}; + +template <typename T> +struct ValueConverter<std::vector<T>> { + using ExpressionType = std::vector<Value>; + static type::Type expressionType() { + return type::Array(valueTypeToExpressionType<T>()); + } + static Value toExpressionValue(const std::vector<T>& value); + static optional<std::vector<T>> fromExpressionValue(const Value& value); +}; + +template <> +struct ValueConverter<Position> { + using ExpressionType = std::vector<Value>; + static type::Type expressionType() { return type::Array(type::Number, 3); } + static Value toExpressionValue(const mbgl::style::Position& value); + static optional<Position> fromExpressionValue(const Value& v); +}; + +template <typename T> +struct ValueConverter<T, std::enable_if_t< std::is_enum<T>::value >> { + using ExpressionType = std::string; + static type::Type expressionType() { return type::String; } + static Value toExpressionValue(const T& value); + static optional<T> fromExpressionValue(const Value& value); +}; + +} // namespace expression +} // namespace style +} // namespace mbgl |