[core] make style/conversion.hpp implementation private

This commit is contained in:
Konstantin Käfer
2018-08-17 15:38:47 -07:00
parent 9df9f5fe20
commit 112bbc7ab2
92 changed files with 617 additions and 432 deletions

View File

@@ -1,9 +1,9 @@
#include <benchmark/benchmark.h>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/json.hpp>
#include <mbgl/style/conversion/function.hpp>
#include <mbgl/style/conversion/property_value.hpp>
#include <mbgl/style/conversion_impl.hpp>
using namespace mbgl;
using namespace mbgl::style;

View File

@@ -2,10 +2,10 @@
#include <mbgl/benchmark/stub_geometry_tile_feature.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/json.hpp>
#include <mbgl/style/conversion/function.hpp>
#include <mbgl/style/conversion/property_value.hpp>
#include <mbgl/style/conversion_impl.hpp>
using namespace mbgl;
using namespace mbgl::style;

View File

@@ -2,9 +2,9 @@
#include <mbgl/benchmark/stub_geometry_tile_feature.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/json.hpp>
#include <mbgl/style/conversion/property_value.hpp>
#include <mbgl/style/conversion_impl.hpp>
using namespace mbgl;
using namespace mbgl::style;

View File

@@ -1,9 +1,9 @@
#include <benchmark/benchmark.h>
#include <mbgl/style/filter.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/json.hpp>
#include <mbgl/style/conversion/filter.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/benchmark/stub_geometry_tile_feature.hpp>

View File

@@ -363,6 +363,7 @@ set(MBGL_CORE_FILES
# style
include/mbgl/style/color_ramp_property_value.hpp
include/mbgl/style/conversion.hpp
include/mbgl/style/conversion_impl.hpp
include/mbgl/style/filter.hpp
include/mbgl/style/image.hpp
include/mbgl/style/layer.hpp
@@ -437,6 +438,7 @@ set(MBGL_CORE_FILES
src/mbgl/style/conversion/layer.cpp
src/mbgl/style/conversion/light.cpp
src/mbgl/style/conversion/position.cpp
src/mbgl/style/conversion/property_value.cpp
src/mbgl/style/conversion/source.cpp
src/mbgl/style/conversion/stringify.hpp
src/mbgl/style/conversion/tileset.cpp

View File

@@ -1,306 +1,26 @@
#pragma once
#include <mbgl/util/optional.hpp>
#include <mbgl/util/feature.hpp>
#include <mbgl/util/geojson.hpp>
#include <string>
namespace mbgl {
namespace style {
namespace conversion {
/*
The `conversion` namespace defines conversions from JSON structures conforming to the schema defined by
the Mapbox Style Specification, to the various C++ types that form the C++ model of that domain:
* `std::unique_ptr<Source>`
* `std::unique_ptr<Layer>`
* `Filter`
* `PropertyValue<T>`
A single template function serves as the public interface:
template <class T>
optional<T> convert(const Convertible& input, Error& error);
Where `T` is one of the above types. If the conversion fails, the result is empty, and the
error parameter includes diagnostic text suitable for presentation to a library user. Otherwise,
a filled optional is returned.
`Convertible` is a type that encapsulates a special form of polymorphism over various underlying types that
can serve as input to the conversion algorithm. For instance, on macOS, we need to support
conversion from both RapidJSON types, and a JSON structure represented with `NSArray`/`NSDictionary`/etc.
On Qt, we need to support conversion from RapidJSON types and QVariant.
We don't want to use traditional forms of polymorphism to accomplish this:
* Compile time polymorphism using a template parameter for the actual value type leads to
excessive code bloat and long compile times.
* Runtime polymorphism using virtual methods requires extra heap allocation and ubiquitous
use of std::unique_ptr, unsuitable for this performance-sensitive code.
Therefore, we're using a custom implementation of runtime polymorphism where we manually create and
dispatch through a table of function pointers (vtable), while keeping the storage for any of the possible
underlying types inline on the stack, using `std::aligned_storage`.
For a given underlying type T, an explicit specialization of `ConversionTraits<T>` must be provided. This
specialization must provide the following static methods:
* `isUndefined(v)` -- returns a boolean indication whether `v` is undefined or a JSON null
* `isArray(v)` -- returns a boolean indicating whether `v` represents a JSON array
* `arrayLength(v)` -- called only if `isArray(v)`; returns a size_t length
* `arrayMember(v)` -- called only if `isArray(v)`; returns `V` or `V&`
* `isObject(v)` -- returns a boolean indicating whether `v` represents a JSON object
* `objectMember(v, name)` -- called only if `isObject(v)`; `name` is `const char *`; return value:
* is true when evaluated in a boolean context iff the named member exists
* is convertable to a `V` or `V&` when dereferenced
* `eachMember(v, [] (const std::string&, const V&) -> optional<Error> {...})` -- called
only if `isObject(v)`; calls the provided lambda once for each key and value of the object;
short-circuits if any call returns an `Error`
* `toBool(v)` -- returns `optional<bool>`, absence indicating `v` is not a JSON boolean
* `toNumber(v)` -- returns `optional<float>`, absence indicating `v` is not a JSON number
* `toDouble(v)` -- returns `optional<double>`, absence indicating `v` is not a JSON number
* `toString(v)` -- returns `optional<std::string>`, absence indicating `v` is not a JSON string
* `toValue(v)` -- returns `optional<Value>`, a variant type, for generic conversion,
absence indicating `v` is not a boolean, number, or string. Numbers should be converted to
unsigned integer, signed integer, or floating point, in descending preference.
In addition, the type T must be move-constructable. And finally, `Convertible::Storage`, a typedef for
`std::aligned_storage_t`, must be large enough to satisfy the memory requirements for any of the
possible underlying types. (A static assert will fail if this is not the case.)
`Convertible` itself is movable, but not copyable. A moved-from `Convertible` is in an invalid state;
you must not do anything with it except let it go out of scope.
*/
// This is a forward-declaration only header intended to minimize dependencies and to improve
// compilation speed. In order to specialize implementations and get access to the actual
// implementation, include <mbgl/style/conversion_impl.hpp>.
struct Error { std::string message; };
template <typename T>
class ConversionTraits;
class Convertible {
public:
template <typename T>
Convertible(T&& value) : vtable(vtableForType<std::decay_t<T>>()) {
static_assert(sizeof(Storage) >= sizeof(std::decay_t<T>), "Storage must be large enough to hold value type");
new (static_cast<void*>(&storage)) std::decay_t<T>(std::forward<T>(value));
}
Convertible(Convertible&& v)
: vtable(v.vtable)
{
if (vtable) {
vtable->move(std::move(v.storage), this->storage);
}
}
~Convertible() {
if (vtable) {
vtable->destroy(storage);
}
}
Convertible& operator=(Convertible&& v) {
if (vtable) {
vtable->destroy(storage);
}
vtable = v.vtable;
if (vtable) {
vtable->move(std::move(v.storage), this->storage);
}
v.vtable = nullptr;
return *this;
}
Convertible() = delete;
Convertible(const Convertible&) = delete;
Convertible& operator=(const Convertible&) = delete;
friend inline bool isUndefined(const Convertible& v) {
assert(v.vtable);
return v.vtable->isUndefined(v.storage);
}
friend inline bool isArray(const Convertible& v) {
assert(v.vtable);
return v.vtable->isArray(v.storage);
}
friend inline std::size_t arrayLength(const Convertible& v) {
assert(v.vtable);
return v.vtable->arrayLength(v.storage);
}
friend inline Convertible arrayMember(const Convertible& v, std::size_t i) {
assert(v.vtable);
return v.vtable->arrayMember(v.storage, i);
}
friend inline bool isObject(const Convertible& v) {
assert(v.vtable);
return v.vtable->isObject(v.storage);
}
friend inline optional<Convertible> objectMember(const Convertible& v, const char * name) {
assert(v.vtable);
return v.vtable->objectMember(v.storage, name);
}
friend inline optional<Error> eachMember(const Convertible& v, const std::function<optional<Error> (const std::string&, const Convertible&)>& fn) {
assert(v.vtable);
return v.vtable->eachMember(v.storage, fn);
}
friend inline optional<bool> toBool(const Convertible& v) {
assert(v.vtable);
return v.vtable->toBool(v.storage);
}
friend inline optional<float> toNumber(const Convertible& v) {
assert(v.vtable);
return v.vtable->toNumber(v.storage);
}
friend inline optional<double> toDouble(const Convertible& v) {
assert(v.vtable);
return v.vtable->toDouble(v.storage);
}
friend inline optional<std::string> toString(const Convertible& v) {
assert(v.vtable);
return v.vtable->toString(v.storage);
}
friend inline optional<Value> toValue(const Convertible& v) {
assert(v.vtable);
return v.vtable->toValue(v.storage);
}
friend inline optional<GeoJSON> toGeoJSON(const Convertible& v, Error& error) {
assert(v.vtable);
return v.vtable->toGeoJSON(v.storage, error);
}
private:
#if __ANDROID__
// Android: JSValue* or mbgl::android::Value
using Storage = std::aligned_storage_t<32, 8>;
#elif __QT__
// Qt: JSValue* or QVariant
using Storage = std::aligned_storage_t<32, 8>;
#else
// Node: JSValue* or v8::Local<v8::Value>
// iOS/macOS: JSValue* or id
using Storage = std::aligned_storage_t<8, 8>;
#endif
struct VTable {
void (*move) (Storage&& src, Storage& dest);
void (*destroy) (Storage&);
bool (*isUndefined) (const Storage&);
bool (*isArray) (const Storage&);
std::size_t (*arrayLength) (const Storage&);
Convertible (*arrayMember) (const Storage&, std::size_t);
bool (*isObject) (const Storage&);
optional<Convertible> (*objectMember) (const Storage&, const char *);
optional<Error> (*eachMember) (const Storage&, const std::function<optional<Error> (const std::string&, const Convertible&)>&);
optional<bool> (*toBool) (const Storage&);
optional<float> (*toNumber) (const Storage&);
optional<double> (*toDouble) (const Storage&);
optional<std::string> (*toString) (const Storage&);
optional<Value> (*toValue) (const Storage&);
// https://github.com/mapbox/mapbox-gl-native/issues/5623
optional<GeoJSON> (*toGeoJSON) (const Storage&, Error&);
};
// Extracted this function from the table below to work around a GCC bug with differing
// visibility settings for capturing lambdas: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80947
template <typename T>
static auto vtableEachMember(const Storage& s, const std::function<optional<Error>(const std::string&, const Convertible&)>& fn) {
return ConversionTraits<T>::eachMember(reinterpret_cast<const T&>(s), [&](const std::string& k, T&& v) {
return fn(k, Convertible(std::move(v)));
});
}
template <typename T>
static VTable* vtableForType() {
using Traits = ConversionTraits<T>;
static VTable vtable = {
[] (Storage&& src, Storage& dest) {
auto srcValue = reinterpret_cast<T&&>(src);
new (static_cast<void*>(&dest)) T(std::move(srcValue));
srcValue.~T();
},
[] (Storage& s) {
reinterpret_cast<T&>(s).~T();
},
[] (const Storage& s) {
return Traits::isUndefined(reinterpret_cast<const T&>(s));
},
[] (const Storage& s) {
return Traits::isArray(reinterpret_cast<const T&>(s));
},
[] (const Storage& s) {
return Traits::arrayLength(reinterpret_cast<const T&>(s));
},
[] (const Storage& s, std::size_t i) {
return Convertible(Traits::arrayMember(reinterpret_cast<const T&>(s), i));
},
[] (const Storage& s) {
return Traits::isObject(reinterpret_cast<const T&>(s));
},
[] (const Storage& s, const char * key) {
optional<T> member = Traits::objectMember(reinterpret_cast<const T&>(s), key);
if (member) {
return optional<Convertible>(Convertible(std::move(*member)));
} else {
return optional<Convertible>();
}
},
vtableEachMember<T>,
[] (const Storage& s) {
return Traits::toBool(reinterpret_cast<const T&>(s));
},
[] (const Storage& s) {
return Traits::toNumber(reinterpret_cast<const T&>(s));
},
[] (const Storage& s) {
return Traits::toDouble(reinterpret_cast<const T&>(s));
},
[] (const Storage& s) {
return Traits::toString(reinterpret_cast<const T&>(s));
},
[] (const Storage& s) {
return Traits::toValue(reinterpret_cast<const T&>(s));
},
[] (const Storage& s, Error& err) {
return Traits::toGeoJSON(reinterpret_cast<const T&>(s), err);
}
};
return &vtable;
}
VTable* vtable;
Storage storage;
};
class Convertible;
template <class T, class Enable = void>
struct Converter;
template <class T, class...Args>
optional<T> convert(const Convertible& value, Error& error, Args&&...args) {
return Converter<T>()(value, error, std::forward<Args>(args)...);
}
} // namespace conversion
} // namespace style
} // namespace mbgl

View File

@@ -1,6 +1,7 @@
#pragma once
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/types.hpp>
#include <mbgl/util/color.hpp>
#include <mbgl/util/enum.hpp>
#include <mbgl/util/string.hpp>
@@ -30,21 +31,7 @@ struct Converter<std::string> {
template <class T>
struct Converter<T, typename std::enable_if_t<std::is_enum<T>::value>> {
optional<T> operator()(const Convertible& value, Error& error) const {
optional<std::string> string = toString(value);
if (!string) {
error.message = "value must be a string";
return nullopt;
}
const auto result = Enum<T>::toEnum(*string);
if (!result) {
error.message = "value must be a valid enumeration value";
return nullopt;
}
return *result;
}
optional<T> operator()(const Convertible& value, Error& error) const;
};
template <>
@@ -54,23 +41,7 @@ struct Converter<Color> {
template <size_t N>
struct Converter<std::array<float, N>> {
optional<std::array<float, N>> operator()(const Convertible& value, Error& error) const {
if (!isArray(value) || arrayLength(value) != N) {
error.message = "value must be an array of " + util::toString(N) + " numbers";
return nullopt;
}
std::array<float, N> result;
for (size_t i = 0; i < N; i++) {
optional<float> n = toNumber(arrayMember(value, i));
if (!n) {
error.message = "value must be an array of " + util::toString(N) + " numbers";
return nullopt;
}
result[i] = *n;
}
return result;
}
optional<std::array<float, N>> operator()(const Convertible& value, Error& error) const;
};
template <>

View File

@@ -2,6 +2,7 @@
#include <mbgl/style/conversion.hpp>
#include <mbgl/util/geo.hpp>
#include <mbgl/util/optional.hpp>
namespace mbgl {
namespace style {

View File

@@ -2,6 +2,7 @@
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/sources/custom_geometry_source.hpp>
#include <mbgl/util/optional.hpp>
namespace mbgl {
namespace style {

View File

@@ -2,6 +2,7 @@
#include <mbgl/style/filter.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/util/optional.hpp>
namespace mbgl {
namespace style {

View File

@@ -1,8 +1,8 @@
#pragma once
#include <mbgl/style/property_expression.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/constant.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/expression/expression.hpp>
#include <mbgl/style/expression/value.hpp>
@@ -16,25 +16,7 @@ std::unique_ptr<expression::Expression> convertTokenStringToExpression(const std
optional<std::unique_ptr<expression::Expression>> convertFunctionToExpression(expression::type::Type, const Convertible&, Error&, bool convertTokens);
template <class T>
optional<PropertyExpression<T>> convertFunctionToExpression(const Convertible& value, Error& error, bool convertTokens) {
auto expression = convertFunctionToExpression(expression::valueTypeToExpressionType<T>(), value, error, convertTokens);
if (!expression) {
return nullopt;
}
optional<T> defaultValue;
auto defaultValueValue = objectMember(value, "default");
if (defaultValueValue) {
defaultValue = convert<T>(*defaultValueValue, error);
if (!defaultValue) {
error.message = R"(wrong type for "default": )" + error.message;
return nullopt;
}
}
return PropertyExpression<T>(std::move(*expression), defaultValue);
}
optional<PropertyExpression<T>> convertFunctionToExpression(const Convertible& value, Error& error, bool convertTokens);
} // namespace conversion
} // namespace style

View File

@@ -1,7 +1,8 @@
#pragma once
#include <mbgl/style/conversion.hpp>
#include <mbgl/util/geojson.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/util/optional.hpp>
namespace mbgl {
namespace style {

View File

@@ -1,7 +1,8 @@
#pragma once
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/sources/geojson_source.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/util/optional.hpp>
namespace mbgl {
namespace style {

View File

@@ -2,6 +2,7 @@
#include <mbgl/style/layer.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/util/optional.hpp>
#include <memory>

View File

@@ -2,6 +2,7 @@
#include <mbgl/style/light.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/util/optional.hpp>
namespace mbgl {
namespace style {

View File

@@ -1,7 +1,8 @@
#pragma once
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/position.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/util/optional.hpp>
namespace mbgl {
namespace style {

View File

@@ -1,9 +1,9 @@
#pragma once
#include <mbgl/style/property_value.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/constant.hpp>
#include <mbgl/style/conversion/function.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/expression/value.hpp>
#include <mbgl/style/expression/is_constant.hpp>
#include <mbgl/style/expression/is_expression.hpp>
@@ -16,53 +16,7 @@ namespace conversion {
template <class T>
struct Converter<PropertyValue<T>> {
optional<PropertyValue<T>> operator()(const Convertible& value, Error& error, bool allowDataExpressions, bool convertTokens) const {
using namespace mbgl::style::expression;
if (isUndefined(value)) {
return PropertyValue<T>();
}
optional<PropertyExpression<T>> expression;
if (isExpression(value)) {
ParsingContext ctx(valueTypeToExpressionType<T>());
ParseResult parsed = ctx.parseLayerPropertyExpression(value);
if (!parsed) {
error.message = ctx.getCombinedErrors();
return nullopt;
}
expression = PropertyExpression<T>(std::move(*parsed));
} else if (isObject(value)) {
expression = convertFunctionToExpression<T>(value, error, convertTokens);
} else {
optional<T> constant = convert<T>(value, error);
if (!constant) {
return nullopt;
}
return convertTokens ? maybeConvertTokens(*constant) : PropertyValue<T>(*constant);
}
if (!expression) {
return nullopt;
} else if (!allowDataExpressions && !(*expression).isFeatureConstant()) {
error.message = "data expressions not supported";
return nullopt;
} else if (!(*expression).isFeatureConstant() || !(*expression).isZoomConstant()) {
return { std::move(*expression) };
} else if ((*expression).getExpression().getKind() == Kind::Literal) {
optional<T> constant = fromExpressionValue<T>(
static_cast<const Literal&>((*expression).getExpression()).getValue());
if (!constant) {
return nullopt;
}
return PropertyValue<T>(*constant);
} else {
assert(false);
error.message = "expected a literal expression";
return nullopt;
}
}
optional<PropertyValue<T>> operator()(const Convertible& value, Error& error, bool allowDataExpressions, bool convertTokens) const;
template <class S>
PropertyValue<T> maybeConvertTokens(const S& t) const {

View File

@@ -1,7 +1,8 @@
#pragma once
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/source.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/util/optional.hpp>
#include <memory>

View File

@@ -2,6 +2,7 @@
#include <mbgl/util/tileset.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/util/optional.hpp>
namespace mbgl {
namespace style {

View File

@@ -2,6 +2,7 @@
#include <mbgl/style/transition_options.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/util/optional.hpp>
namespace mbgl {
namespace style {

View File

@@ -0,0 +1,302 @@
#pragma once
#include <mbgl/style/conversion.hpp>
#include <mbgl/util/optional.hpp>
#include <mbgl/util/feature.hpp>
#include <mbgl/util/geojson.hpp>
#include <string>
namespace mbgl {
namespace style {
namespace conversion {
/*
The `conversion` namespace defines conversions from JSON structures conforming to the schema defined by
the Mapbox Style Specification, to the various C++ types that form the C++ model of that domain:
* `std::unique_ptr<Source>`
* `std::unique_ptr<Layer>`
* `Filter`
* `PropertyValue<T>`
A single template function serves as the public interface:
template <class T>
optional<T> convert(const Convertible& input, Error& error);
Where `T` is one of the above types. If the conversion fails, the result is empty, and the
error parameter includes diagnostic text suitable for presentation to a library user. Otherwise,
a filled optional is returned.
`Convertible` is a type that encapsulates a special form of polymorphism over various underlying types that
can serve as input to the conversion algorithm. For instance, on macOS, we need to support
conversion from both RapidJSON types, and a JSON structure represented with `NSArray`/`NSDictionary`/etc.
On Qt, we need to support conversion from RapidJSON types and QVariant.
We don't want to use traditional forms of polymorphism to accomplish this:
* Compile time polymorphism using a template parameter for the actual value type leads to
excessive code bloat and long compile times.
* Runtime polymorphism using virtual methods requires extra heap allocation and ubiquitous
use of std::unique_ptr, unsuitable for this performance-sensitive code.
Therefore, we're using a custom implementation of runtime polymorphism where we manually create and
dispatch through a table of function pointers (vtable), while keeping the storage for any of the possible
underlying types inline on the stack, using `std::aligned_storage`.
For a given underlying type T, an explicit specialization of `ConversionTraits<T>` must be provided. This
specialization must provide the following static methods:
* `isUndefined(v)` -- returns a boolean indication whether `v` is undefined or a JSON null
* `isArray(v)` -- returns a boolean indicating whether `v` represents a JSON array
* `arrayLength(v)` -- called only if `isArray(v)`; returns a size_t length
* `arrayMember(v)` -- called only if `isArray(v)`; returns `V` or `V&`
* `isObject(v)` -- returns a boolean indicating whether `v` represents a JSON object
* `objectMember(v, name)` -- called only if `isObject(v)`; `name` is `const char *`; return value:
* is true when evaluated in a boolean context iff the named member exists
* is convertable to a `V` or `V&` when dereferenced
* `eachMember(v, [] (const std::string&, const V&) -> optional<Error> {...})` -- called
only if `isObject(v)`; calls the provided lambda once for each key and value of the object;
short-circuits if any call returns an `Error`
* `toBool(v)` -- returns `optional<bool>`, absence indicating `v` is not a JSON boolean
* `toNumber(v)` -- returns `optional<float>`, absence indicating `v` is not a JSON number
* `toDouble(v)` -- returns `optional<double>`, absence indicating `v` is not a JSON number
* `toString(v)` -- returns `optional<std::string>`, absence indicating `v` is not a JSON string
* `toValue(v)` -- returns `optional<Value>`, a variant type, for generic conversion,
absence indicating `v` is not a boolean, number, or string. Numbers should be converted to
unsigned integer, signed integer, or floating point, in descending preference.
In addition, the type T must be move-constructable. And finally, `Convertible::Storage`, a typedef for
`std::aligned_storage_t`, must be large enough to satisfy the memory requirements for any of the
possible underlying types. (A static assert will fail if this is not the case.)
`Convertible` itself is movable, but not copyable. A moved-from `Convertible` is in an invalid state;
you must not do anything with it except let it go out of scope.
*/
template <typename T>
class ConversionTraits;
class Convertible {
public:
template <typename T>
Convertible(T&& value) : vtable(vtableForType<std::decay_t<T>>()) {
static_assert(sizeof(Storage) >= sizeof(std::decay_t<T>), "Storage must be large enough to hold value type");
new (static_cast<void*>(&storage)) std::decay_t<T>(std::forward<T>(value));
}
Convertible(Convertible&& v)
: vtable(v.vtable)
{
if (vtable) {
vtable->move(std::move(v.storage), this->storage);
}
}
~Convertible() {
if (vtable) {
vtable->destroy(storage);
}
}
Convertible& operator=(Convertible&& v) {
if (vtable) {
vtable->destroy(storage);
}
vtable = v.vtable;
if (vtable) {
vtable->move(std::move(v.storage), this->storage);
}
v.vtable = nullptr;
return *this;
}
Convertible() = delete;
Convertible(const Convertible&) = delete;
Convertible& operator=(const Convertible&) = delete;
friend inline bool isUndefined(const Convertible& v) {
assert(v.vtable);
return v.vtable->isUndefined(v.storage);
}
friend inline bool isArray(const Convertible& v) {
assert(v.vtable);
return v.vtable->isArray(v.storage);
}
friend inline std::size_t arrayLength(const Convertible& v) {
assert(v.vtable);
return v.vtable->arrayLength(v.storage);
}
friend inline Convertible arrayMember(const Convertible& v, std::size_t i) {
assert(v.vtable);
return v.vtable->arrayMember(v.storage, i);
}
friend inline bool isObject(const Convertible& v) {
assert(v.vtable);
return v.vtable->isObject(v.storage);
}
friend inline optional<Convertible> objectMember(const Convertible& v, const char * name) {
assert(v.vtable);
return v.vtable->objectMember(v.storage, name);
}
friend inline optional<Error> eachMember(const Convertible& v, const std::function<optional<Error> (const std::string&, const Convertible&)>& fn) {
assert(v.vtable);
return v.vtable->eachMember(v.storage, fn);
}
friend inline optional<bool> toBool(const Convertible& v) {
assert(v.vtable);
return v.vtable->toBool(v.storage);
}
friend inline optional<float> toNumber(const Convertible& v) {
assert(v.vtable);
return v.vtable->toNumber(v.storage);
}
friend inline optional<double> toDouble(const Convertible& v) {
assert(v.vtable);
return v.vtable->toDouble(v.storage);
}
friend inline optional<std::string> toString(const Convertible& v) {
assert(v.vtable);
return v.vtable->toString(v.storage);
}
friend inline optional<Value> toValue(const Convertible& v) {
assert(v.vtable);
return v.vtable->toValue(v.storage);
}
friend inline optional<GeoJSON> toGeoJSON(const Convertible& v, Error& error) {
assert(v.vtable);
return v.vtable->toGeoJSON(v.storage, error);
}
private:
#if __ANDROID__
// Android: JSValue* or mbgl::android::Value
using Storage = std::aligned_storage_t<32, 8>;
#elif __QT__
// Qt: JSValue* or QVariant
using Storage = std::aligned_storage_t<32, 8>;
#else
// Node: JSValue* or v8::Local<v8::Value>
// iOS/macOS: JSValue* or id
using Storage = std::aligned_storage_t<8, 8>;
#endif
struct VTable {
void (*move) (Storage&& src, Storage& dest);
void (*destroy) (Storage&);
bool (*isUndefined) (const Storage&);
bool (*isArray) (const Storage&);
std::size_t (*arrayLength) (const Storage&);
Convertible (*arrayMember) (const Storage&, std::size_t);
bool (*isObject) (const Storage&);
optional<Convertible> (*objectMember) (const Storage&, const char *);
optional<Error> (*eachMember) (const Storage&, const std::function<optional<Error> (const std::string&, const Convertible&)>&);
optional<bool> (*toBool) (const Storage&);
optional<float> (*toNumber) (const Storage&);
optional<double> (*toDouble) (const Storage&);
optional<std::string> (*toString) (const Storage&);
optional<Value> (*toValue) (const Storage&);
// https://github.com/mapbox/mapbox-gl-native/issues/5623
optional<GeoJSON> (*toGeoJSON) (const Storage&, Error&);
};
// Extracted this function from the table below to work around a GCC bug with differing
// visibility settings for capturing lambdas: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80947
template <typename T>
static auto vtableEachMember(const Storage& s, const std::function<optional<Error>(const std::string&, const Convertible&)>& fn) {
return ConversionTraits<T>::eachMember(reinterpret_cast<const T&>(s), [&](const std::string& k, T&& v) {
return fn(k, Convertible(std::move(v)));
});
}
template <typename T>
static VTable* vtableForType() {
using Traits = ConversionTraits<T>;
static VTable vtable = {
[] (Storage&& src, Storage& dest) {
auto srcValue = reinterpret_cast<T&&>(src);
new (static_cast<void*>(&dest)) T(std::move(srcValue));
srcValue.~T();
},
[] (Storage& s) {
reinterpret_cast<T&>(s).~T();
},
[] (const Storage& s) {
return Traits::isUndefined(reinterpret_cast<const T&>(s));
},
[] (const Storage& s) {
return Traits::isArray(reinterpret_cast<const T&>(s));
},
[] (const Storage& s) {
return Traits::arrayLength(reinterpret_cast<const T&>(s));
},
[] (const Storage& s, std::size_t i) {
return Convertible(Traits::arrayMember(reinterpret_cast<const T&>(s), i));
},
[] (const Storage& s) {
return Traits::isObject(reinterpret_cast<const T&>(s));
},
[] (const Storage& s, const char * key) {
optional<T> member = Traits::objectMember(reinterpret_cast<const T&>(s), key);
if (member) {
return optional<Convertible>(Convertible(std::move(*member)));
} else {
return optional<Convertible>();
}
},
vtableEachMember<T>,
[] (const Storage& s) {
return Traits::toBool(reinterpret_cast<const T&>(s));
},
[] (const Storage& s) {
return Traits::toNumber(reinterpret_cast<const T&>(s));
},
[] (const Storage& s) {
return Traits::toDouble(reinterpret_cast<const T&>(s));
},
[] (const Storage& s) {
return Traits::toString(reinterpret_cast<const T&>(s));
},
[] (const Storage& s) {
return Traits::toValue(reinterpret_cast<const T&>(s));
},
[] (const Storage& s, Error& err) {
return Traits::toGeoJSON(reinterpret_cast<const T&>(s), err);
}
};
return &vtable;
}
VTable* vtable;
Storage storage;
};
template <class T, class...Args>
optional<T> convert(const Convertible& value, Error& error, Args&&...args) {
return Converter<T>()(value, error, std::forward<Args>(args)...);
}
} // namespace conversion
} // namespace style
} // namespace mbgl

View File

@@ -1,8 +1,8 @@
#pragma once
#include <mbgl/style/expression/expression.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/expression/parsing_context.hpp>
#include <mbgl/style/conversion.hpp>
#include <memory>
#include <vector>

View File

@@ -1,8 +1,8 @@
#pragma once
#include <mbgl/style/expression/expression.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/expression/parsing_context.hpp>
#include <mbgl/style/conversion.hpp>
#include <memory>
#include <vector>

View File

@@ -1,8 +1,8 @@
#pragma once
#include <mbgl/style/expression/expression.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/expression/parsing_context.hpp>
#include <mbgl/style/conversion.hpp>
#include <memory>
#include <map>

View File

@@ -1,10 +1,10 @@
#pragma once
#include <mbgl/style/expression/expression.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/expression/parsing_context.hpp>
#include <mbgl/style/expression/type.hpp>
#include <mbgl/style/expression/value.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/util/optional.hpp>
#include <memory>

View File

@@ -7,6 +7,7 @@
#include <iterator>
#include <map>
#include <unordered_map>
#include <string>
#include <vector>
#include <memory>

View File

@@ -3,6 +3,7 @@
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/util/peer.hpp>
#include <mbgl/util/immutable.hpp>
#include <mbgl/util/optional.hpp>
#include <mbgl/style/layer_type.hpp>
#include <mbgl/style/types.hpp>
#include <mbgl/style/conversion.hpp>

View File

@@ -345,6 +345,11 @@ add_library(example-custom-layer SHARED
platform/android/src/example_custom_layer.cpp
)
target_link_libraries(example-custom-layer
PRIVATE mbgl-core
target_include_directories(example-custom-layer
PRIVATE include
)
target_link_libraries(example-custom-layer
PRIVATE -llog
PRIVATE -lGLESv2
)

View File

@@ -30,8 +30,8 @@
// Java -> C++ conversion
#include "style/android_conversion.hpp"
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/filter.hpp>
#include <mbgl/style/conversion_impl.hpp>
// C++ -> Java conversion
#include "conversion/conversion.hpp"

View File

@@ -5,8 +5,8 @@
#include <mbgl/util/feature.hpp>
#include <mbgl/util/logging.hpp>
#include <mbgl/util/optional.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/geojson.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <jni/jni.hpp>

View File

@@ -1,8 +1,8 @@
#pragma once
#include "../android_conversion.hpp"
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/filter.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <jni/jni.hpp>

View File

@@ -1,8 +1,8 @@
#pragma once
#include <mapbox/geojson.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/geojson.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <jni/jni.hpp>
namespace mbgl {

View File

@@ -4,8 +4,8 @@
#include <mbgl/util/variant.hpp>
#include <mbgl/util/tileset.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/tileset.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <jni/jni.hpp>

View File

@@ -18,10 +18,10 @@
#include <mbgl/util/logging.hpp>
// Java -> C++ conversion
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/filter.hpp>
#include <mbgl/style/conversion/layer.hpp>
#include <mbgl/style/conversion/source.hpp>
#include <mbgl/style/conversion_impl.hpp>
// C++ -> Java conversion
#include "../conversion/property_value.hpp"

View File

@@ -5,9 +5,9 @@
// Java -> C++ conversion
#include "../android_conversion.hpp"
#include "../conversion/filter.hpp"
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/geojson.hpp>
#include <mbgl/style/conversion/geojson_options.hpp>
#include <mbgl/style/conversion_impl.hpp>
// C++ -> Java conversion
#include "../../conversion/conversion.hpp"

View File

@@ -5,7 +5,7 @@
// C++ -> Java conversion
#include "../../conversion/conversion.hpp"
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/premultiply.hpp>
#include "../../bitmap.hpp"

View File

@@ -7,8 +7,8 @@
#include <mbgl/util/logging.hpp>
// Java -> C++ conversion
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/source.hpp>
#include <mbgl/style/conversion_impl.hpp>
// C++ -> Java conversion
#include "../conversion/property_value.hpp"

View File

@@ -1,4 +1,4 @@
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion_impl.hpp>
NS_ASSUME_NONNULL_BEGIN

View File

@@ -8,8 +8,8 @@
#include <mbgl/util/optional.hpp>
#include <mbgl/util/feature.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/geojson.hpp>
#include <mbgl/style/conversion_impl.hpp>
namespace mbgl {
namespace style {

View File

@@ -1,6 +1,6 @@
#pragma once
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/style/expression/expression.hpp>
#include <exception>
#include <memory>

View File

@@ -13,11 +13,11 @@
#include <mbgl/math/log2.hpp>
#include <mbgl/math/minmax.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/layer.hpp>
#include <mbgl/style/conversion/source.hpp>
#include <mbgl/style/conversion/filter.hpp>
#include <mbgl/style/conversion/geojson.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/style/filter.hpp>
#include <mbgl/style/layers/custom_layer.hpp>
#include <mbgl/style/layers/background_layer.hpp>

View File

@@ -1,7 +1,7 @@
#pragma once
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/geojson.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/optional.hpp>
#include <QVariant>

View File

@@ -1,6 +1,6 @@
#include <mbgl/style/conversion/color_ramp_property_value.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/constant.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/style/expression/value.hpp>
#include <mbgl/style/expression/is_constant.hpp>
#include <mbgl/style/expression/is_expression.hpp>

View File

@@ -1,4 +1,5 @@
#include <mbgl/style/conversion/constant.hpp>
#include <mbgl/style/conversion_impl.hpp>
namespace mbgl {
namespace style {
@@ -31,6 +32,38 @@ optional<std::string> Converter<std::string>::operator()(const Convertible& valu
return *converted;
}
template <class T>
optional<T> Converter<T, typename std::enable_if_t<std::is_enum<T>::value>>::operator()(const Convertible& value, Error& error) const {
optional<std::string> string = toString(value);
if (!string) {
error.message = "value must be a string";
return nullopt;
}
const auto result = Enum<T>::toEnum(*string);
if (!result) {
error.message = "value must be a valid enumeration value";
return nullopt;
}
return *result;
}
template optional<AlignmentType> Converter<AlignmentType>::operator()(const Convertible&, Error&) const;
template optional<CirclePitchScaleType> Converter<CirclePitchScaleType>::operator()(const Convertible&, Error&) const;
template optional<HillshadeIlluminationAnchorType> Converter<HillshadeIlluminationAnchorType>::operator()(const Convertible&, Error&) const;
template optional<IconTextFitType> Converter<IconTextFitType>::operator()(const Convertible&, Error&) const;
template optional<LightAnchorType> Converter<LightAnchorType>::operator()(const Convertible&, Error&) const;
template optional<LineCapType> Converter<LineCapType>::operator()(const Convertible&, Error&) const;
template optional<LineJoinType> Converter<LineJoinType>::operator()(const Convertible&, Error&) const;
template optional<RasterResamplingType> Converter<RasterResamplingType>::operator()(const Convertible&, Error&) const;
template optional<SymbolAnchorType> Converter<SymbolAnchorType>::operator()(const Convertible&, Error&) const;
template optional<SymbolPlacementType> Converter<SymbolPlacementType>::operator()(const Convertible&, Error&) const;
template optional<TextJustifyType> Converter<TextJustifyType>::operator()(const Convertible&, Error&) const;
template optional<TextTransformType> Converter<TextTransformType>::operator()(const Convertible&, Error&) const;
template optional<TranslateAnchorType> Converter<TranslateAnchorType>::operator()(const Convertible&, Error&) const;
template optional<VisibilityType> Converter<VisibilityType>::operator()(const Convertible&, Error&) const;
optional<Color> Converter<Color>::operator()(const Convertible& value, Error& error) const {
optional<std::string> string = toString(value);
if (!string) {
@@ -47,6 +80,29 @@ optional<Color> Converter<Color>::operator()(const Convertible& value, Error& er
return *color;
}
template <size_t N>
optional<std::array<float, N>> Converter<std::array<float, N>>::operator()(const Convertible& value, Error& error) const {
if (!isArray(value) || arrayLength(value) != N) {
error.message = "value must be an array of " + util::toString(N) + " numbers";
return nullopt;
}
std::array<float, N> result;
for (size_t i = 0; i < N; i++) {
optional<float> n = toNumber(arrayMember(value, i));
if (!n) {
error.message = "value must be an array of " + util::toString(N) + " numbers";
return nullopt;
}
result[i] = *n;
}
return result;
}
template optional<std::array<float, 2>> Converter<std::array<float, 2>>::operator()(const Convertible&, Error&) const;
template optional<std::array<float, 3>> Converter<std::array<float, 3>>::operator()(const Convertible&, Error&) const;
template optional<std::array<float, 4>> Converter<std::array<float, 4>>::operator()(const Convertible&, Error&) const;
optional<std::vector<float>> Converter<std::vector<float>>::operator()(const Convertible& value, Error& error) const {
if (!isArray(value)) {
error.message = "value must be an array";

View File

@@ -1,4 +1,5 @@
#include <mbgl/style/conversion/coordinate.hpp>
#include <mbgl/style/conversion_impl.hpp>
namespace mbgl {
namespace style {

View File

@@ -1,4 +1,5 @@
#include <mbgl/style/conversion/custom_geometry_source_options.hpp>
#include <mbgl/style/conversion_impl.hpp>
namespace mbgl {
namespace style {

View File

@@ -1,10 +1,11 @@
#include <mbgl/style/conversion/filter.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/style/expression/literal.hpp>
#include <mbgl/util/geometry.hpp>
#include <mbgl/style/expression/expression.hpp>
#include <mbgl/style/expression/type.hpp>
#include <mbgl/style/expression/compound_expression.hpp>
#include <mbgl/style/expression/boolean_operator.hpp>
#include <mbgl/util/geometry.hpp>
namespace mbgl {
namespace style {

View File

@@ -1,4 +1,6 @@
#include <mbgl/style/conversion/function.hpp>
#include <mbgl/style/conversion/position.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/style/expression/dsl.hpp>
#include <mbgl/style/expression/step.hpp>
#include <mbgl/style/expression/interpolate.hpp>
@@ -70,6 +72,72 @@ std::unique_ptr<Expression> convertTokenStringToExpression(const std::string& so
}
}
template <class T>
optional<PropertyExpression<T>> convertFunctionToExpression(const Convertible& value, Error& error, bool convertTokens) {
auto expression = convertFunctionToExpression(expression::valueTypeToExpressionType<T>(), value, error, convertTokens);
if (!expression) {
return nullopt;
}
optional<T> defaultValue;
auto defaultValueValue = objectMember(value, "default");
if (defaultValueValue) {
defaultValue = convert<T>(*defaultValueValue, error);
if (!defaultValue) {
error.message = R"(wrong type for "default": )" + error.message;
return nullopt;
}
}
return PropertyExpression<T>(std::move(*expression), defaultValue);
}
template optional<PropertyExpression<AlignmentType>>
convertFunctionToExpression<AlignmentType>(const Convertible&, Error&, bool);
template optional<PropertyExpression<bool>>
convertFunctionToExpression<bool>(const Convertible&, Error&, bool);
template optional<PropertyExpression<CirclePitchScaleType>>
convertFunctionToExpression<CirclePitchScaleType>(const Convertible&, Error&, bool);
template optional<PropertyExpression<float>>
convertFunctionToExpression<float>(const Convertible&, Error&, bool);
template optional<PropertyExpression<HillshadeIlluminationAnchorType>>
convertFunctionToExpression<HillshadeIlluminationAnchorType>(const Convertible&, Error&, bool);
template optional<PropertyExpression<IconTextFitType>>
convertFunctionToExpression<IconTextFitType>(const Convertible&, Error&, bool);
template optional<PropertyExpression<LightAnchorType>>
convertFunctionToExpression<LightAnchorType>(const Convertible&, Error&, bool);
template optional<PropertyExpression<LineCapType>>
convertFunctionToExpression<LineCapType>(const Convertible&, Error&, bool);
template optional<PropertyExpression<LineJoinType>>
convertFunctionToExpression<LineJoinType>(const Convertible&, Error&, bool);
template optional<PropertyExpression<Color>>
convertFunctionToExpression<Color>(const Convertible&, Error&, bool);
template optional<PropertyExpression<Position>>
convertFunctionToExpression<Position>(const Convertible&, Error&, bool);
template optional<PropertyExpression<RasterResamplingType>>
convertFunctionToExpression<RasterResamplingType>(const Convertible&, Error&, bool);
template optional<PropertyExpression<std::array<float, 2>>>
convertFunctionToExpression<std::array<float, 2>>(const Convertible&, Error&, bool);
template optional<PropertyExpression<std::array<float, 4>>>
convertFunctionToExpression<std::array<float, 4>>(const Convertible&, Error&, bool);
template optional<PropertyExpression<std::string>>
convertFunctionToExpression<std::string>(const Convertible&, Error&, bool);
template optional<PropertyExpression<std::vector<float>>>
convertFunctionToExpression<std::vector<float>>(const Convertible&, Error&, bool);
template optional<PropertyExpression<std::vector<std::string>>>
convertFunctionToExpression<std::vector<std::string>>(const Convertible&, Error&, bool);
template optional<PropertyExpression<SymbolAnchorType>>
convertFunctionToExpression<SymbolAnchorType>(const Convertible&, Error&, bool);
template optional<PropertyExpression<SymbolPlacementType>>
convertFunctionToExpression<SymbolPlacementType>(const Convertible&, Error&, bool);
template optional<PropertyExpression<TextJustifyType>>
convertFunctionToExpression<TextJustifyType>(const Convertible&, Error&, bool);
template optional<PropertyExpression<TextTransformType>>
convertFunctionToExpression<TextTransformType>(const Convertible&, Error&, bool);
template optional<PropertyExpression<TranslateAnchorType>>
convertFunctionToExpression<TranslateAnchorType>(const Convertible&, Error&, bool);
// Ad-hoc Converters for double and int64_t. We should replace float with double wholesale,
// and promote the int64_t Converter to general use (and it should check that the input is
// an integer).

View File

@@ -1,5 +1,6 @@
#include <mbgl/style/conversion/geojson.hpp>
#include <mbgl/style/conversion/json.hpp>
#include <mbgl/style/conversion_impl.hpp>
namespace mbgl {
namespace style {

View File

@@ -1,4 +1,5 @@
#include <mbgl/style/conversion/geojson_options.hpp>
#include <mbgl/style/conversion_impl.hpp>
namespace mbgl {
namespace style {

View File

@@ -1,4 +1,5 @@
#include <mbgl/style/conversion/get_json_type.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/feature.hpp>
namespace mbgl {

View File

@@ -1,6 +1,6 @@
#pragma once
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/style/rapidjson_conversion.hpp>
#include <string>

View File

@@ -1,6 +1,7 @@
#include <mbgl/style/conversion/layer.hpp>
#include <mbgl/style/conversion/constant.hpp>
#include <mbgl/style/conversion/filter.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/style/layers/background_layer.hpp>
#include <mbgl/style/layers/circle_layer.hpp>
#include <mbgl/style/layers/fill_layer.hpp>

View File

@@ -2,6 +2,7 @@
#include <mbgl/style/conversion/position.hpp>
#include <mbgl/style/conversion/property_value.hpp>
#include <mbgl/style/conversion/transition_options.hpp>
#include <mbgl/style/conversion_impl.hpp>
namespace mbgl {
namespace style {

View File

@@ -1,5 +1,6 @@
#include <mbgl/style/conversion/position.hpp>
#include <mbgl/style/conversion/constant.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <array>

View File

@@ -0,0 +1,83 @@
#include <mbgl/style/conversion/property_value.hpp>
#include <mbgl/style/conversion/position.hpp>
#include <mbgl/style/conversion_impl.hpp>
namespace mbgl {
namespace style {
namespace conversion {
template <class T>
optional<PropertyValue<T>> Converter<PropertyValue<T>>::operator()(const Convertible& value, Error& error, bool allowDataExpressions, bool convertTokens) const {
using namespace mbgl::style::expression;
if (isUndefined(value)) {
return PropertyValue<T>();
}
optional<PropertyExpression<T>> expression;
if (isExpression(value)) {
ParsingContext ctx(valueTypeToExpressionType<T>());
ParseResult parsed = ctx.parseLayerPropertyExpression(value);
if (!parsed) {
error.message = ctx.getCombinedErrors();
return nullopt;
}
expression = PropertyExpression<T>(std::move(*parsed));
} else if (isObject(value)) {
expression = convertFunctionToExpression<T>(value, error, convertTokens);
} else {
optional<T> constant = convert<T>(value, error);
if (!constant) {
return nullopt;
}
return convertTokens ? maybeConvertTokens(*constant) : PropertyValue<T>(*constant);
}
if (!expression) {
return nullopt;
} else if (!allowDataExpressions && !(*expression).isFeatureConstant()) {
error.message = "data expressions not supported";
return nullopt;
} else if (!(*expression).isFeatureConstant() || !(*expression).isZoomConstant()) {
return { std::move(*expression) };
} else if ((*expression).getExpression().getKind() == Kind::Literal) {
optional<T> constant = fromExpressionValue<T>(
static_cast<const Literal&>((*expression).getExpression()).getValue());
if (!constant) {
return nullopt;
}
return PropertyValue<T>(*constant);
} else {
assert(false);
error.message = "expected a literal expression";
return nullopt;
}
}
template optional<PropertyValue<bool>> Converter<PropertyValue<bool>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
template optional<PropertyValue<float>> Converter<PropertyValue<float>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
template optional<PropertyValue<std::array<float, 2>>> Converter<PropertyValue<std::array<float, 2>>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
template optional<PropertyValue<std::array<float, 4>>> Converter<PropertyValue<std::array<float, 4>>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
template optional<PropertyValue<std::vector<float>>> Converter<PropertyValue<std::vector<float>>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
template optional<PropertyValue<Color>> Converter<PropertyValue<Color>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
template optional<PropertyValue<std::string>> Converter<PropertyValue<std::string>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
template optional<PropertyValue<std::vector<std::string>>> Converter<PropertyValue<std::vector<std::string>>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
template optional<PropertyValue<AlignmentType>> Converter<PropertyValue<AlignmentType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
template optional<PropertyValue<CirclePitchScaleType>> Converter<PropertyValue<CirclePitchScaleType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
template optional<PropertyValue<HillshadeIlluminationAnchorType>> Converter<PropertyValue<HillshadeIlluminationAnchorType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
template optional<PropertyValue<IconTextFitType>> Converter<PropertyValue<IconTextFitType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
template optional<PropertyValue<LightAnchorType>> Converter<PropertyValue<LightAnchorType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
template optional<PropertyValue<LineCapType>> Converter<PropertyValue<LineCapType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
template optional<PropertyValue<LineJoinType>> Converter<PropertyValue<LineJoinType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
template optional<PropertyValue<Position>> Converter<PropertyValue<Position>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
template optional<PropertyValue<RasterResamplingType>> Converter<PropertyValue<RasterResamplingType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
template optional<PropertyValue<SymbolAnchorType>> Converter<PropertyValue<SymbolAnchorType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
template optional<PropertyValue<SymbolPlacementType>> Converter<PropertyValue<SymbolPlacementType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
template optional<PropertyValue<TextJustifyType>> Converter<PropertyValue<TextJustifyType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
template optional<PropertyValue<TextTransformType>> Converter<PropertyValue<TextTransformType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
template optional<PropertyValue<TranslateAnchorType>> Converter<PropertyValue<TranslateAnchorType>>::operator()(conversion::Convertible const&, conversion::Error&, bool, bool) const;
} // namespace conversion
} // namespace style
} // namespace mbgl

View File

@@ -3,6 +3,7 @@
#include <mbgl/style/conversion/geojson.hpp>
#include <mbgl/style/conversion/geojson_options.hpp>
#include <mbgl/style/conversion/tileset.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/style/sources/geojson_source.hpp>
#include <mbgl/style/sources/raster_source.hpp>
#include <mbgl/style/sources/raster_dem_source.hpp>

View File

@@ -1,4 +1,5 @@
#include <mbgl/style/conversion/tileset.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/geo.hpp>
#include <mbgl/math/clamp.hpp>

View File

@@ -1,4 +1,5 @@
#include <mbgl/style/conversion/transition_options.hpp>
#include <mbgl/style/conversion_impl.hpp>
namespace mbgl {
namespace style {

View File

@@ -1,5 +1,6 @@
#include <mbgl/style/expression/array_assertion.hpp>
#include <mbgl/style/expression/check_subtype.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/string.hpp>
namespace mbgl {

View File

@@ -1,5 +1,6 @@
#include <mbgl/style/expression/assertion.hpp>
#include <mbgl/style/expression/check_subtype.hpp>
#include <mbgl/style/conversion_impl.hpp>
namespace mbgl {
namespace style {

View File

@@ -1,4 +1,5 @@
#include <mbgl/style/expression/at.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/string.hpp>

View File

@@ -1,4 +1,5 @@
#include <mbgl/style/expression/boolean_operator.hpp>
#include <mbgl/style/conversion_impl.hpp>
namespace mbgl {
namespace style {

View File

@@ -1,4 +1,5 @@
#include <mbgl/style/expression/case.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/string.hpp>
namespace mbgl {

View File

@@ -1,5 +1,6 @@
#include <mbgl/style/expression/coalesce.hpp>
#include <mbgl/style/expression/check_subtype.hpp>
#include <mbgl/style/conversion_impl.hpp>
namespace mbgl {
namespace style {

View File

@@ -1,6 +1,7 @@
#include <mbgl/style/expression/coercion.hpp>
#include <mbgl/style/expression/check_subtype.hpp>
#include <mbgl/style/expression/util.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/string.hpp>
namespace mbgl {

View File

@@ -1,6 +1,7 @@
#include <mbgl/style/expression/collator.hpp>
#include <mbgl/style/expression/collator_expression.hpp>
#include <mbgl/style/expression/literal.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/string.hpp>
namespace mbgl {

View File

@@ -1,6 +1,7 @@
#include <mbgl/style/expression/collator.hpp>
#include <mbgl/style/expression/comparison.hpp>
#include <mbgl/style/expression/dsl.hpp>
#include <mbgl/style/conversion_impl.hpp>
namespace mbgl {
namespace style {

View File

@@ -3,6 +3,7 @@
#include <mbgl/style/expression/compound_expression.hpp>
#include <mbgl/style/expression/check_subtype.hpp>
#include <mbgl/style/expression/util.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/math/log2.hpp>
#include <mbgl/util/i18n.hpp>

View File

@@ -1,4 +1,5 @@
#include <mbgl/style/expression/interpolate.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/string.hpp>
namespace mbgl {

View File

@@ -1,8 +1,7 @@
#include <mbgl/style/expression/is_expression.hpp>
#include <mbgl/style/expression/compound_expression.hpp>
#include <mbgl/style/expression/parsing_context.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <unordered_set>

View File

@@ -1,4 +1,5 @@
#include <mbgl/style/expression/length.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/string.hpp>
namespace mbgl {

View File

@@ -1,5 +1,6 @@
#include <mbgl/style/expression/let.hpp>
#include <mbgl/style/conversion/get_json_type.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/string.hpp>
namespace mbgl {

View File

@@ -1,4 +1,5 @@
#include <mbgl/style/expression/literal.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/string.hpp>
namespace mbgl {

View File

@@ -1,6 +1,7 @@
#include <mbgl/style/expression/match.hpp>
#include <mbgl/style/expression/check_subtype.hpp>
#include <mbgl/style/expression/parsing_context.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/string.hpp>
namespace mbgl {

View File

@@ -24,6 +24,7 @@
#include <mbgl/style/expression/find_zoom_curve.hpp>
#include <mbgl/style/conversion/get_json_type.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/string.hpp>

View File

@@ -1,5 +1,6 @@
#include <mbgl/style/expression/step.hpp>
#include <mbgl/style/expression/get_covering_stops.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/string.hpp>
#include <cmath>

View File

@@ -2,6 +2,7 @@
#include <mbgl/style/layer_impl.hpp>
#include <mbgl/style/layer_observer.hpp>
#include <mbgl/style/conversion/constant.hpp>
#include <mbgl/style/conversion_impl.hpp>
namespace mbgl {
namespace style {

View File

@@ -3,12 +3,12 @@
#include <mbgl/style/layers/background_layer.hpp>
#include <mbgl/style/layers/background_layer_impl.hpp>
#include <mbgl/style/layer_observer.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/color_ramp_property_value.hpp>
#include <mbgl/style/conversion/constant.hpp>
#include <mbgl/style/conversion/property_value.hpp>
#include <mbgl/style/conversion/transition_options.hpp>
#include <mbgl/style/conversion/json.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/fnv_hash.hpp>
namespace mbgl {

View File

@@ -3,12 +3,12 @@
#include <mbgl/style/layers/circle_layer.hpp>
#include <mbgl/style/layers/circle_layer_impl.hpp>
#include <mbgl/style/layer_observer.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/color_ramp_property_value.hpp>
#include <mbgl/style/conversion/constant.hpp>
#include <mbgl/style/conversion/property_value.hpp>
#include <mbgl/style/conversion/transition_options.hpp>
#include <mbgl/style/conversion/json.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/fnv_hash.hpp>
namespace mbgl {

View File

@@ -3,12 +3,12 @@
#include <mbgl/style/layers/fill_extrusion_layer.hpp>
#include <mbgl/style/layers/fill_extrusion_layer_impl.hpp>
#include <mbgl/style/layer_observer.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/color_ramp_property_value.hpp>
#include <mbgl/style/conversion/constant.hpp>
#include <mbgl/style/conversion/property_value.hpp>
#include <mbgl/style/conversion/transition_options.hpp>
#include <mbgl/style/conversion/json.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/fnv_hash.hpp>
namespace mbgl {

View File

@@ -3,12 +3,12 @@
#include <mbgl/style/layers/fill_layer.hpp>
#include <mbgl/style/layers/fill_layer_impl.hpp>
#include <mbgl/style/layer_observer.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/color_ramp_property_value.hpp>
#include <mbgl/style/conversion/constant.hpp>
#include <mbgl/style/conversion/property_value.hpp>
#include <mbgl/style/conversion/transition_options.hpp>
#include <mbgl/style/conversion/json.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/fnv_hash.hpp>
namespace mbgl {

View File

@@ -3,12 +3,12 @@
#include <mbgl/style/layers/heatmap_layer.hpp>
#include <mbgl/style/layers/heatmap_layer_impl.hpp>
#include <mbgl/style/layer_observer.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/color_ramp_property_value.hpp>
#include <mbgl/style/conversion/constant.hpp>
#include <mbgl/style/conversion/property_value.hpp>
#include <mbgl/style/conversion/transition_options.hpp>
#include <mbgl/style/conversion/json.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/fnv_hash.hpp>
namespace mbgl {

View File

@@ -3,12 +3,12 @@
#include <mbgl/style/layers/hillshade_layer.hpp>
#include <mbgl/style/layers/hillshade_layer_impl.hpp>
#include <mbgl/style/layer_observer.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/color_ramp_property_value.hpp>
#include <mbgl/style/conversion/constant.hpp>
#include <mbgl/style/conversion/property_value.hpp>
#include <mbgl/style/conversion/transition_options.hpp>
#include <mbgl/style/conversion/json.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/fnv_hash.hpp>
namespace mbgl {

View File

@@ -8,12 +8,12 @@
#include <mbgl/style/layers/<%- type.replace('-', '_') %>_layer.hpp>
#include <mbgl/style/layers/<%- type.replace('-', '_') %>_layer_impl.hpp>
#include <mbgl/style/layer_observer.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/color_ramp_property_value.hpp>
#include <mbgl/style/conversion/constant.hpp>
#include <mbgl/style/conversion/property_value.hpp>
#include <mbgl/style/conversion/transition_options.hpp>
#include <mbgl/style/conversion/json.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/fnv_hash.hpp>
namespace mbgl {

View File

@@ -3,12 +3,12 @@
#include <mbgl/style/layers/line_layer.hpp>
#include <mbgl/style/layers/line_layer_impl.hpp>
#include <mbgl/style/layer_observer.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/color_ramp_property_value.hpp>
#include <mbgl/style/conversion/constant.hpp>
#include <mbgl/style/conversion/property_value.hpp>
#include <mbgl/style/conversion/transition_options.hpp>
#include <mbgl/style/conversion/json.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/fnv_hash.hpp>
namespace mbgl {

View File

@@ -3,12 +3,12 @@
#include <mbgl/style/layers/raster_layer.hpp>
#include <mbgl/style/layers/raster_layer_impl.hpp>
#include <mbgl/style/layer_observer.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/color_ramp_property_value.hpp>
#include <mbgl/style/conversion/constant.hpp>
#include <mbgl/style/conversion/property_value.hpp>
#include <mbgl/style/conversion/transition_options.hpp>
#include <mbgl/style/conversion/json.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/fnv_hash.hpp>
namespace mbgl {

View File

@@ -3,12 +3,12 @@
#include <mbgl/style/layers/symbol_layer.hpp>
#include <mbgl/style/layers/symbol_layer_impl.hpp>
#include <mbgl/style/layer_observer.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/color_ramp_property_value.hpp>
#include <mbgl/style/conversion/constant.hpp>
#include <mbgl/style/conversion/property_value.hpp>
#include <mbgl/style/conversion/transition_options.hpp>
#include <mbgl/style/conversion/json.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/fnv_hash.hpp>
namespace mbgl {

View File

@@ -1,12 +1,12 @@
#include <mbgl/style/parser.hpp>
#include <mbgl/style/layer_impl.hpp>
#include <mbgl/style/rapidjson_conversion.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/coordinate.hpp>
#include <mbgl/style/conversion/source.hpp>
#include <mbgl/style/conversion/layer.hpp>
#include <mbgl/style/conversion/light.hpp>
#include <mbgl/style/conversion/transition_options.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/logging.hpp>
#include <mbgl/util/string.hpp>

View File

@@ -1,7 +1,7 @@
#pragma once
#include <mbgl/util/rapidjson.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mapbox/geojson.hpp>
#include <mapbox/geojson/rapidjson.hpp>

View File

@@ -1,9 +1,9 @@
#include <mbgl/test/util.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/json.hpp>
#include <mbgl/style/conversion/constant.hpp>
#include <mbgl/style/conversion/light.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/style/position.hpp>
#include <mbgl/util/color.hpp>
#include <mbgl/util/chrono.hpp>

View File

@@ -1,6 +1,6 @@
#include <mbgl/test/util.hpp>
#include <mbgl/util/io.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/util/rapidjson.hpp>
#include <mbgl/style/rapidjson_conversion.hpp>
#include <mbgl/style/expression/is_expression.hpp>