1 | #pragma once |
2 | |
3 | #include <mbgl/style/expression/collator.hpp> |
4 | #include <mbgl/style/expression/type.hpp> |
5 | #include <mbgl/style/position.hpp> |
6 | #include <mbgl/style/types.hpp> |
7 | #include <mbgl/util/color.hpp> |
8 | #include <mbgl/util/enum.hpp> |
9 | #include <mbgl/util/feature.hpp> |
10 | #include <mbgl/util/variant.hpp> |
11 | |
12 | #include <array> |
13 | #include <vector> |
14 | |
15 | namespace mbgl { |
16 | namespace style { |
17 | namespace expression { |
18 | |
19 | struct Value; |
20 | |
21 | using ValueBase = variant< |
22 | NullValue, |
23 | bool, |
24 | double, |
25 | std::string, |
26 | Color, |
27 | Collator, |
28 | mapbox::util::recursive_wrapper<std::vector<Value>>, |
29 | mapbox::util::recursive_wrapper<std::unordered_map<std::string, Value>>>; |
30 | struct Value : ValueBase { |
31 | using ValueBase::ValueBase; |
32 | |
33 | // Javascript's Number.MAX_SAFE_INTEGER |
34 | static uint64_t maxSafeInteger() { return 9007199254740991ULL; } |
35 | |
36 | static bool isSafeInteger(uint64_t x) { return x <= maxSafeInteger(); }; |
37 | static bool isSafeInteger(int64_t x) { |
38 | return static_cast<uint64_t>(x > 0 ? x : -x) <= maxSafeInteger(); |
39 | } |
40 | static bool isSafeInteger(double x) { |
41 | return static_cast<uint64_t>(x > 0 ? x : -x) <= maxSafeInteger(); |
42 | } |
43 | |
44 | }; |
45 | |
46 | constexpr NullValue Null = NullValue(); |
47 | |
48 | type::Type typeOf(const Value& value); |
49 | std::string stringify(const Value& value); |
50 | |
51 | /* |
52 | Returns a Type object representing the expression type that corresponds to |
53 | the value type T. (Specialized for primitives and specific array types in |
54 | the .cpp.) |
55 | */ |
56 | template <typename T> |
57 | type::Type valueTypeToExpressionType(); |
58 | |
59 | /* |
60 | Conversions between style value types and expression::Value |
61 | */ |
62 | |
63 | template <class T, class Enable = void> |
64 | struct ValueConverter { |
65 | static Value toExpressionValue(const T& value) { |
66 | return Value(value); |
67 | } |
68 | |
69 | static optional<T> fromExpressionValue(const Value& value) { |
70 | return value.template is<T>() ? value.template get<T>() : optional<T>(); |
71 | } |
72 | }; |
73 | |
74 | template <> |
75 | struct ValueConverter<Value> { |
76 | static type::Type expressionType() { return type::Value; } |
77 | static Value toExpressionValue(const Value& value) { return value; } |
78 | static optional<Value> fromExpressionValue(const Value& value) { return value; } |
79 | }; |
80 | |
81 | template <> |
82 | struct ValueConverter<mbgl::Value> { |
83 | static Value toExpressionValue(const mbgl::Value& value); |
84 | static mbgl::Value fromExpressionValue(const Value& value); |
85 | }; |
86 | |
87 | template <> |
88 | struct ValueConverter<float> { |
89 | static type::Type expressionType() { return type::Number; } |
90 | static Value toExpressionValue(const float value); |
91 | static optional<float> fromExpressionValue(const Value& value); |
92 | }; |
93 | |
94 | template <typename T, std::size_t N> |
95 | struct ValueConverter<std::array<T, N>> { |
96 | static type::Type expressionType() { |
97 | return type::Array(valueTypeToExpressionType<T>(), N); |
98 | } |
99 | static Value toExpressionValue(const std::array<T, N>& value); |
100 | static optional<std::array<T, N>> fromExpressionValue(const Value& value); |
101 | }; |
102 | |
103 | template <typename T> |
104 | struct ValueConverter<std::vector<T>> { |
105 | static type::Type expressionType() { |
106 | return type::Array(valueTypeToExpressionType<T>()); |
107 | } |
108 | static Value toExpressionValue(const std::vector<T>& value); |
109 | static optional<std::vector<T>> fromExpressionValue(const Value& value); |
110 | }; |
111 | |
112 | template <> |
113 | struct ValueConverter<Position> { |
114 | static type::Type expressionType() { return type::Array(type::Number, 3); } |
115 | static Value toExpressionValue(const mbgl::style::Position& value); |
116 | static optional<Position> fromExpressionValue(const Value& v); |
117 | }; |
118 | |
119 | template <typename T> |
120 | struct ValueConverter<T, std::enable_if_t< std::is_enum<T>::value >> { |
121 | static type::Type expressionType() { return type::String; } |
122 | static Value toExpressionValue(const T& value); |
123 | static optional<T> fromExpressionValue(const Value& value); |
124 | }; |
125 | |
126 | template <typename T> |
127 | Value toExpressionValue(const T& value) { |
128 | return ValueConverter<T>::toExpressionValue(value); |
129 | } |
130 | |
131 | template <typename T> |
132 | optional<T> fromExpressionValue(const Value& value) { |
133 | return ValueConverter<T>::fromExpressionValue(value); |
134 | } |
135 | |
136 | template <typename T> |
137 | std::vector<optional<T>> fromExpressionValues(const std::vector<optional<Value>>& values) { |
138 | std::vector<optional<T>> result; |
139 | for (const auto& value : values) { |
140 | result.push_back(value ? fromExpressionValue<T>(*value) : nullopt); |
141 | } |
142 | return result; |
143 | } |
144 | |
145 | } // namespace expression |
146 | } // namespace style |
147 | } // namespace mbgl |
148 | |