diff options
Diffstat (limited to 'src/mbgl/style/expression/value.cpp')
-rw-r--r-- | src/mbgl/style/expression/value.cpp | 222 |
1 files changed, 188 insertions, 34 deletions
diff --git a/src/mbgl/style/expression/value.cpp b/src/mbgl/style/expression/value.cpp index 4e670ec5dd..324fc06f17 100644 --- a/src/mbgl/style/expression/value.cpp +++ b/src/mbgl/style/expression/value.cpp @@ -4,38 +4,6 @@ namespace mbgl { namespace style { namespace expression { -struct ConvertValue { -// null_value_t, bool, uint64_t, int64_t, double, std::string, -// mapbox::util::recursive_wrapper<std::vector<value>>, -// mapbox::util::recursive_wrapper<std::unordered_map<std::string, value>> - Value operator()(const std::vector<mbgl::Value>& v) { - std::vector<Value> result; - for(const auto& item : v) { - result.emplace_back(convertValue(item)); - } - return result; - } - - Value operator()(const std::unordered_map<std::string, mbgl::Value>& v) { - std::unordered_map<std::string, Value> result; - for(const auto& entry : v) { - result.emplace(entry.first, convertValue(entry.second)); - } - return result; - } - - Value operator()(const std::string& s) { return s; } - Value operator()(const bool& b) { return b; } - Value operator()(const mbgl::NullValue) { return Null; } - - template <typename T> - Value operator()(const T& v) { return *numericValue<float>(v); } -}; - -Value convertValue(const mbgl::Value& value) { - return mbgl::Value::visit(value, ConvertValue()); -} - type::Type typeOf(const Value& value) { return value.match( [&](bool) -> type::Type { return type::Boolean; }, @@ -92,6 +60,165 @@ std::string stringify(const Value& value) { ); } + +template <class T, class Enable = void> +struct Converter { + 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 Converter<mbgl::Value> { + static Value toExpressionValue(const mbgl::Value& value) { + return mbgl::Value::visit(value, Converter<mbgl::Value>()); + } + + + // Double duty as a variant visitor for mbgl::Value: + Value operator()(const std::vector<mbgl::Value>& v) { + std::vector<Value> result; + for(const auto& item : v) { + result.emplace_back(toExpressionValue(item)); + } + return result; + } + + Value operator()(const std::unordered_map<std::string, mbgl::Value>& v) { + std::unordered_map<std::string, Value> result; + 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 mbgl::NullValue) { return Null; } + + template <typename T> + Value operator()(const T& v) { return *numericValue<float>(v); } +}; + +template <typename T, std::size_t N> +struct Converter<std::array<T, N>> { + static Value toExpressionValue(const std::array<T, N>& value) { + std::vector<Value> result; + std::copy_n(value.begin(), N, result.begin()); + return result; + } + + static optional<std::array<T, N>> fromExpressionValue(const Value& v) { + return v.match( + [&] (const std::vector<Value>& v) -> optional<std::array<T, N>> { + if (v.size() != N) return optional<std::array<T, N>>(); + std::array<T, N> result; + auto it = result.begin(); + for(const auto& item : v) { + if (!item.template is<T>()) { + return optional<std::array<T, N>>(); + } + *it = item.template get<T>(); + it = std::next(it); + } + return result; + }, + [&] (const auto&) { return optional<std::array<T, N>>(); } + ); + } + + static type::Type expressionType() { + return type::Array(valueTypeToExpressionType<T>(), N); + } +}; + +template <typename T> +struct Converter<std::vector<T>> { + static Value toExpressionValue(const std::vector<T>& value) { + std::vector<Value> v; + std::copy(value.begin(), value.end(), v.begin()); + return v; + } + + static optional<std::vector<T>> fromExpressionValue(const Value& v) { + return v.match( + [&] (const std::vector<Value>& v) -> optional<std::vector<T>> { + std::vector<T> result; + for(const auto& item : v) { + if (!item.template is<T>()) { + return optional<std::vector<T>>(); + } + result.push_back(item.template get<T>()); + } + return result; + }, + [&] (const auto&) { return optional<std::vector<T>>(); } + ); + } + + static type::Type expressionType() { + return type::Array(valueTypeToExpressionType<T>()); + } +}; + +template <> +struct Converter<Position> { + static Value toExpressionValue(const mbgl::style::Position& value) { + return Converter<std::array<float, 3>>::toExpressionValue(value.getSpherical()); + } + + static optional<Position> fromExpressionValue(const Value& v) { + auto pos = Converter<std::array<float, 3>>::fromExpressionValue(v); + return pos ? optional<Position>(Position(*pos)) : optional<Position>(); + } + + static type::Type expressionType() { + return type::Array(type::Number, 3); + } +}; + +template <typename T> +struct Converter<T, std::enable_if_t< std::is_enum<T>::value >> { + static Value toExpressionValue(const T& value) { + return std::string(Enum<T>::toString(value)); + } + + static optional<T> fromExpressionValue(const Value& v) { + return v.match( + [&] (const std::string& v) { return Enum<T>::toEnum(v); }, + [&] (const auto&) { return optional<T>(); } + ); + } + + static type::Type expressionType() { + return type::String; + } +}; + +Value toExpressionValue(const Value& v) { + return v; +} + +template <typename T, typename Enable> +Value toExpressionValue(const T& value) { + return Converter<T>::toExpressionValue(value); +} + +template <typename T> +std::enable_if_t< !std::is_convertible<T, Value>::value, +optional<T>> fromExpressionValue(const Value& v) +{ + return Converter<T>::fromExpressionValue(v); +} + +template <typename T> +type::Type valueTypeToExpressionType() { + return Converter<T>::expressionType(); +} + template <> type::Type valueTypeToExpressionType<Value>() { return type::Value; } template <> type::Type valueTypeToExpressionType<NullValue>() { return type::Null; } template <> type::Type valueTypeToExpressionType<bool>() { return type::Boolean; } @@ -99,10 +226,37 @@ template <> type::Type valueTypeToExpressionType<float>() { return type::Number; template <> type::Type valueTypeToExpressionType<std::string>() { return type::String; } template <> type::Type valueTypeToExpressionType<mbgl::Color>() { return type::Color; } template <> type::Type valueTypeToExpressionType<std::unordered_map<std::string, Value>>() { return type::Object; } -template <> type::Type valueTypeToExpressionType<std::array<float, 2>>() { return type::Array(type::Number, 2); } -template <> type::Type valueTypeToExpressionType<std::array<float, 4>>() { return type::Array(type::Number, 4); } template <> type::Type valueTypeToExpressionType<std::vector<Value>>() { return type::Array(type::Value); } + +template Value toExpressionValue(const mbgl::Value&); + +// instantiate templates fromExpressionValue<T>, toExpressionValue<T>, and valueTypeToExpressionType<T> +template <typename T> +struct instantiate { + void noop(const T& t) { + fromExpressionValue<T>(toExpressionValue(t)); + valueTypeToExpressionType<T>(); + } +}; + +template struct instantiate<std::array<float, 2>>; +template struct instantiate<std::array<float, 4>>; +template struct instantiate<std::vector<float>>; +template struct instantiate<std::vector<std::string>>; +template struct instantiate<AlignmentType>; +template struct instantiate<CirclePitchScaleType>; +template struct instantiate<IconTextFitType>; +template struct instantiate<LineCapType>; +template struct instantiate<LineJoinType>; +template struct instantiate<SymbolPlacementType>; +template struct instantiate<TextAnchorType>; +template struct instantiate<TextJustifyType>; +template struct instantiate<TextTransformType>; +template struct instantiate<TranslateAnchorType>; +template struct instantiate<LightAnchorType>; +template struct instantiate<Position>; + } // namespace expression } // namespace style } // namespace mbgl |