Files
MapLibreParticleLab/include/mbgl/style/expression/value.hpp
2017-11-08 12:34:02 -05:00

154 lines
4.4 KiB
C++

#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