summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Firebaugh <john.firebaugh@gmail.com>2017-10-17 11:35:36 -0700
committerJohn Firebaugh <john.firebaugh@gmail.com>2017-10-17 14:16:16 -0700
commit84685bfe567712c4a40892079b6c9b40473ea050 (patch)
tree897333ebb7f74798a383f6704741170645d3d394
parenta0874815f8c9fd6fccd9ffd7e28f8aa8abaded19 (diff)
downloadqtlocation-mapboxgl-84685bfe567712c4a40892079b6c9b40473ea050.tar.gz
Require explicit specialization for ValueTraits
* Allows using more natural types for the trait method inputs (`const JSValue*` instead of `const JSValue* const&`) * Makes it a compile error rather than a link error if you pass the wrong type to the templated Value constructor * Allows the compiler to inline the trait methods into the vtable
-rw-r--r--cmake/core-files.cmake1
-rw-r--r--cmake/node.cmake1
-rw-r--r--include/mbgl/style/conversion.hpp16
-rw-r--r--platform/android/config.cmake1
-rw-r--r--platform/android/src/style/android_conversion.cpp106
-rw-r--r--platform/android/src/style/android_conversion.hpp98
-rw-r--r--platform/darwin/src/MGLConversion.h137
-rw-r--r--platform/darwin/src/MGLConversion.mm149
-rw-r--r--platform/ios/ios.xcodeproj/project.pbxproj6
-rw-r--r--platform/macos/macos.xcodeproj/project.pbxproj13
-rw-r--r--platform/node/src/node_conversion.cpp137
-rw-r--r--platform/node/src/node_conversion.hpp122
-rw-r--r--platform/qt/qt.cmake1
-rw-r--r--platform/qt/src/qt_conversion.cpp133
-rw-r--r--platform/qt/src/qt_conversion.hpp130
-rw-r--r--src/mbgl/style/rapidjson_conversion.cpp112
-rw-r--r--src/mbgl/style/rapidjson_conversion.hpp106
17 files changed, 591 insertions, 678 deletions
diff --git a/cmake/core-files.cmake b/cmake/core-files.cmake
index cbb0d0e625..7621283e7e 100644
--- a/cmake/core-files.cmake
+++ b/cmake/core-files.cmake
@@ -350,7 +350,6 @@ set(MBGL_CORE_FILES
src/mbgl/style/parser.cpp
src/mbgl/style/parser.hpp
src/mbgl/style/properties.hpp
- src/mbgl/style/rapidjson_conversion.cpp
src/mbgl/style/rapidjson_conversion.hpp
src/mbgl/style/source.cpp
src/mbgl/style/source_impl.cpp
diff --git a/cmake/node.cmake b/cmake/node.cmake
index 575f45020a..388a98b68f 100644
--- a/cmake/node.cmake
+++ b/cmake/node.cmake
@@ -14,7 +14,6 @@ target_sources(mbgl-node
PRIVATE platform/node/src/node_logging.hpp
PRIVATE platform/node/src/node_logging.cpp
PRIVATE platform/node/src/node_conversion.hpp
- PRIVATE platform/node/src/node_conversion.cpp
PRIVATE platform/node/src/node_map.hpp
PRIVATE platform/node/src/node_map.cpp
PRIVATE platform/node/src/node_request.hpp
diff --git a/include/mbgl/style/conversion.hpp b/include/mbgl/style/conversion.hpp
index 41034c8a33..3fe7bbe508 100644
--- a/include/mbgl/style/conversion.hpp
+++ b/include/mbgl/style/conversion.hpp
@@ -33,21 +33,7 @@ namespace conversion {
struct Error { std::string message; };
template <typename T>
-struct ValueTraits {
- static bool isUndefined(const T& value);
- static bool isArray(const T& value);
- static std::size_t arrayLength(const T& value);
- static T arrayMember(const T& value, std::size_t i);
- static bool isObject(const T& value);
- static optional<T> objectMember(const T& value, const char * name);
- static optional<Error> eachMember(const T& value, const std::function<optional<Error> (const std::string&, const T&)>& fn);
- static optional<bool> toBool(const T& value);
- static optional<float> toNumber(const T& value);
- static optional<double> toDouble(const T& value);
- static optional<std::string> toString(const T& value);
- static optional<mbgl::Value> toValue(const T& value);
- static optional<GeoJSON> toGeoJSON(const T& value, Error& error);
-};
+class ValueTraits;
class Value {
public:
diff --git a/platform/android/config.cmake b/platform/android/config.cmake
index da752e4cb8..db75b850f1 100644
--- a/platform/android/config.cmake
+++ b/platform/android/config.cmake
@@ -146,7 +146,6 @@ add_library(mbgl-android STATIC
# Style conversion Java -> C++
platform/android/src/style/android_conversion.hpp
- platform/android/src/style/android_conversion.cpp
platform/android/src/style/value.cpp
platform/android/src/style/value.hpp
platform/android/src/style/conversion/url_or_tileset.hpp
diff --git a/platform/android/src/style/android_conversion.cpp b/platform/android/src/style/android_conversion.cpp
deleted file mode 100644
index 43940c2acd..0000000000
--- a/platform/android/src/style/android_conversion.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-#include "android_conversion.hpp"
-#include <mbgl/style/conversion/geojson.hpp>
-
-
-namespace mbgl {
-namespace style {
-namespace conversion {
-
-using AndroidValue = mbgl::android::Value;
-
-template<> bool ValueTraits<AndroidValue>::isUndefined(const AndroidValue& value) {
- return value.isNull();
-}
-
-template<> bool ValueTraits<AndroidValue>::isArray(const AndroidValue& value) {
- return value.isArray();
-}
-
-template<> bool ValueTraits<AndroidValue>::isObject(const AndroidValue& value) {
- return value.isObject();
-}
-
-template<> std::size_t ValueTraits<AndroidValue>::arrayLength(const AndroidValue& value) {
- return value.getLength();;
-}
-
-template<> AndroidValue ValueTraits<AndroidValue>::arrayMember(const AndroidValue& value, std::size_t i) {
- return value.get(i);
-}
-
-template<> optional<AndroidValue> ValueTraits<AndroidValue>::objectMember(const AndroidValue& value, const char* key) {
- AndroidValue member = value.get(key);
-
- if (!member.isNull()) {
- return member;
- } else {
- return {};
- }
-}
-
-template<> optional<Error> ValueTraits<AndroidValue>::eachMember(const AndroidValue&, const std::function<optional<Error> (const std::string&, const AndroidValue&)>&) {
- // TODO
- mbgl::Log::Warning(mbgl::Event::Android, "eachMember not implemented");
- return {};
-}
-
-template<> optional<bool> ValueTraits<AndroidValue>::toBool(const AndroidValue& value) {
- if (value.isBool()) {
- return value.toBool();
- } else {
- return {};
- }
-}
-
-template<> optional<float> ValueTraits<AndroidValue>::toNumber(const AndroidValue& value) {
- if (value.isNumber()) {
- auto num = value.toFloat();
- return num;
- } else {
- return {};
- }
-}
-
-template<> optional<double> ValueTraits<AndroidValue>::toDouble(const AndroidValue& value) {
- if (value.isNumber()) {
- return value.toDouble();
- } else {
- return {};
- }
-}
-
-template<> optional<std::string> ValueTraits<AndroidValue>::toString(const AndroidValue& value) {
- if (value.isString()) {
- return value.toString();
- } else {
- return {};
- }
-}
-
-template<> optional<mbgl::Value> ValueTraits<AndroidValue>::toValue(const AndroidValue& value) {
- if (value.isNull()) {
- return {};
- } else if (value.isBool()) {
- return { value.toBool() };
- } else if (value.isString()) {
- return { value.toString() };
- } else if (value.isNumber()) {
- auto doubleVal = value.toDouble();
- return { doubleVal - (int) doubleVal > 0.0 ? doubleVal : value.toLong() };
- } else {
- return {};
- }
-}
-
-template<> optional<GeoJSON> ValueTraits<AndroidValue>::toGeoJSON(const AndroidValue &value, Error &error) {
- if(value.isNull() || !value.isString()) {
- error = { "no json data found" };
- return {};
- }
-
- return parseGeoJSON(value.toString(), error);
-}
-
-} // namespace conversion
-} // namespace style
-} // namespace mbgl
diff --git a/platform/android/src/style/android_conversion.hpp b/platform/android/src/style/android_conversion.hpp
index 3969553816..bc067fbc53 100644
--- a/platform/android/src/style/android_conversion.hpp
+++ b/platform/android/src/style/android_conversion.hpp
@@ -4,8 +4,9 @@
#include <mbgl/util/feature.hpp>
#include <mbgl/util/logging.hpp>
-#include <mbgl/style/conversion.hpp>
#include <mbgl/util/optional.hpp>
+#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/conversion/geojson.hpp>
#include <jni/jni.hpp>
@@ -13,6 +14,101 @@ namespace mbgl {
namespace style {
namespace conversion {
+template <>
+class ValueTraits<mbgl::android::Value> {
+public:
+ static bool isUndefined(const mbgl::android::Value& value) {
+ return value.isNull();
+ }
+
+ static bool isArray(const mbgl::android::Value& value) {
+ return value.isArray();
+ }
+
+ static bool isObject(const mbgl::android::Value& value) {
+ return value.isObject();
+ }
+
+ static std::size_t arrayLength(const mbgl::android::Value& value) {
+ return value.getLength();;
+ }
+
+ static mbgl::android::Value arrayMember(const mbgl::android::Value& value, std::size_t i) {
+ return value.get(i);
+ }
+
+ static optional<mbgl::android::Value> objectMember(const mbgl::android::Value& value, const char* key) {
+ mbgl::android::Value member = value.get(key);
+ if (!member.isNull()) {
+ return member;
+ } else {
+ return {};
+ }
+ }
+
+ static optional<Error> eachMember(const mbgl::android::Value&, const std::function<optional<Error> (const std::string&, const mbgl::android::Value&)>&) {
+ // TODO
+ mbgl::Log::Warning(mbgl::Event::Android, "eachMember not implemented");
+ return {};
+ }
+
+ static optional<bool> toBool(const mbgl::android::Value& value) {
+ if (value.isBool()) {
+ return value.toBool();
+ } else {
+ return {};
+ }
+ }
+
+ static optional<float> toNumber(const mbgl::android::Value& value) {
+ if (value.isNumber()) {
+ auto num = value.toFloat();
+ return num;
+ } else {
+ return {};
+ }
+ }
+
+ static optional<double> toDouble(const mbgl::android::Value& value) {
+ if (value.isNumber()) {
+ return value.toDouble();
+ } else {
+ return {};
+ }
+ }
+
+ static optional<std::string> toString(const mbgl::android::Value& value) {
+ if (value.isString()) {
+ return value.toString();
+ } else {
+ return {};
+ }
+ }
+
+ static optional<mbgl::Value> toValue(const mbgl::android::Value& value) {
+ if (value.isNull()) {
+ return {};
+ } else if (value.isBool()) {
+ return { value.toBool() };
+ } else if (value.isString()) {
+ return { value.toString() };
+ } else if (value.isNumber()) {
+ auto doubleVal = value.toDouble();
+ return { doubleVal - (int) doubleVal > 0.0 ? doubleVal : value.toLong() };
+ } else {
+ return {};
+ }
+ }
+
+ static optional<GeoJSON> toGeoJSON(const mbgl::android::Value &value, Error &error) {
+ if (value.isNull() || !value.isString()) {
+ error = { "no json data found" };
+ return {};
+ }
+ return parseGeoJSON(value.toString(), error);
+ }
+};
+
template <class T, class...Args>
optional<T> convert(const mbgl::android::Value& value, Error& error, Args&&...args) {
return convert<T>(Value(value), error, std::forward<Args>(args)...);
diff --git a/platform/darwin/src/MGLConversion.h b/platform/darwin/src/MGLConversion.h
index a354c28cd9..f5db1acfe5 100644
--- a/platform/darwin/src/MGLConversion.h
+++ b/platform/darwin/src/MGLConversion.h
@@ -6,7 +6,142 @@ namespace mbgl {
namespace style {
namespace conversion {
-Value makeValue(const id value);
+class Holder {
+public:
+ Holder(const id v) : value(v) {}
+ const id value;
+};
+
+template <>
+class ValueTraits<Holder> {
+public:
+ static bool isUndefined(const Holder& holder) {
+ const id value = holder.value;
+ return !value || value == [NSNull null];
+ }
+
+ static bool isArray(const Holder& holder) {
+ const id value = holder.value;
+ return [value isKindOfClass:[NSArray class]];
+ }
+
+ static bool isObject(const Holder& holder) {
+ const id value = holder.value;
+ return [value isKindOfClass:[NSDictionary class]];
+ }
+
+ static std::size_t arrayLength(const Holder& holder) {
+ const id value = holder.value;
+ NSCAssert([value isKindOfClass:[NSArray class]], @"Value must be an NSArray for getLength().");
+ NSArray *array = value;
+ auto length = [array count];
+ NSCAssert(length <= std::numeric_limits<size_t>::max(), @"Array length out of bounds.");
+ return length;
+ }
+
+ static Holder arrayMember(const Holder& holder, std::size_t i) {
+ const id value = holder.value;
+ NSCAssert([value isKindOfClass:[NSArray class]], @"Value must be an NSArray for get(int).");
+ NSCAssert(i < NSUIntegerMax, @"Index must be less than NSUIntegerMax");
+ return {[value objectAtIndex: i]};
+ }
+
+ static optional<Holder> objectMember(const Holder& holder, const char *key) {
+ const id value = holder.value;
+ NSCAssert([value isKindOfClass:[NSDictionary class]], @"Value must be an NSDictionary for get(string).");
+ NSObject *member = [value objectForKey: @(key)];
+ if (member && member != [NSNull null]) {
+ return {member};
+ } else {
+ return {};
+ }
+ }
+
+ static optional<Error> eachMember(const Holder& holder, const std::function<optional<Error> (const std::string&, const Holder&)>& fn) {
+ // Not implemented (unneeded for MGLStyleFunction conversion).
+ NSCAssert(NO, @"eachMember not implemented");
+ return {};
+ }
+
+ static optional<bool> toBool(const Holder& holder) {
+ const id value = holder.value;
+ if (_isBool(value)) {
+ return ((NSNumber *)value).boolValue;
+ } else {
+ return {};
+ }
+ }
+
+ static optional<float> toNumber(const Holder& holder) {
+ const id value = holder.value;
+ if (_isNumber(value)) {
+ return ((NSNumber *)value).floatValue;
+ } else {
+ return {};
+ }
+ }
+
+ static optional<double> toDouble(const Holder& holder) {
+ const id value = holder.value;
+ if (_isNumber(value)) {
+ return ((NSNumber *)value).doubleValue;
+ } else {
+ return {};
+ }
+ }
+
+ static optional<std::string> toString(const Holder& holder) {
+ const id value = holder.value;
+ if (_isString(value)) {
+ return std::string(static_cast<const char *>([value UTF8String]));
+ } else {
+ return {};
+ }
+ }
+
+ static optional<mbgl::Value> toValue(const Holder& holder) {
+ const id value = holder.value;
+ if (isUndefined(value)) {
+ return {};
+ } else if (_isBool(value)) {
+ return { *toBool(holder) };
+ } else if ( _isString(value)) {
+ return { *toString(holder) };
+ } else if (_isNumber(value)) {
+ // Need to cast to a double here as the float is otherwise considered a bool...
+ return { static_cast<double>(*toNumber(holder)) };
+ } else {
+ return {};
+ }
+ }
+
+ static optional<GeoJSON> toGeoJSON(const Holder& holder, Error& error) {
+ error = { "toGeoJSON not implemented" };
+ return {};
+ }
+
+private:
+ static bool _isBool(const id value) {
+ if (![value isKindOfClass:[NSNumber class]]) return false;
+ // char: 32-bit boolean
+ // BOOL: 64-bit boolean
+ NSNumber *number = value;
+ return ((strcmp([number objCType], @encode(char)) == 0) ||
+ (strcmp([number objCType], @encode(BOOL)) == 0));
+ }
+
+ static bool _isNumber(const id value) {
+ return [value isKindOfClass:[NSNumber class]] && !_isBool(value);
+ }
+
+ static bool _isString(const id value) {
+ return [value isKindOfClass:[NSString class]];
+ }
+};
+
+inline Value makeValue(const id value) {
+ return {Holder(value)};
+}
} // namespace conversion
} // namespace style
diff --git a/platform/darwin/src/MGLConversion.mm b/platform/darwin/src/MGLConversion.mm
deleted file mode 100644
index 890a96c34d..0000000000
--- a/platform/darwin/src/MGLConversion.mm
+++ /dev/null
@@ -1,149 +0,0 @@
-#import <Foundation/Foundation.h>
-
-#include "MGLConversion.h"
-
-NS_ASSUME_NONNULL_BEGIN
-
-namespace mbgl {
-namespace style {
-namespace conversion {
-
-class Holder {
-public:
- Holder(const id v) : value(v) {}
- const id value;
-};
-
-template<> bool ValueTraits<Holder>::isUndefined(const Holder& holder) {
- const id value = holder.value;
- return !value || value == [NSNull null];
-}
-
-template<> bool ValueTraits<Holder>::isArray(const Holder& holder) {
- const id value = holder.value;
- return [value isKindOfClass:[NSArray class]];
-}
-
-template<> bool ValueTraits<Holder>::isObject(const Holder& holder) {
- const id value = holder.value;
- return [value isKindOfClass:[NSDictionary class]];
-}
-
-template<> std::size_t ValueTraits<Holder>::arrayLength(const Holder& holder) {
- const id value = holder.value;
- NSCAssert([value isKindOfClass:[NSArray class]], @"Value must be an NSArray for getLength().");
- NSArray *array = value;
- auto length = [array count];
- NSCAssert(length <= std::numeric_limits<size_t>::max(), @"Array length out of bounds.");
- return length;
-}
-
-template<> Holder ValueTraits<Holder>::arrayMember(const Holder& holder, std::size_t i) {
- const id value = holder.value;
- NSCAssert([value isKindOfClass:[NSArray class]], @"Value must be an NSArray for get(int).");
- NSCAssert(i < NSUIntegerMax, @"Index must be less than NSUIntegerMax");
- return {[value objectAtIndex: i]};
-}
-
-template<> optional<Holder> ValueTraits<Holder>::objectMember(const Holder& holder, const char *key) {
- const id value = holder.value;
- NSCAssert([value isKindOfClass:[NSDictionary class]], @"Value must be an NSDictionary for get(string).");
- NSObject *member = [value objectForKey: @(key)];
- if (member && member != [NSNull null]) {
- return {member};
- } else {
- return {};
- }
-}
-
-template<> optional<Error> ValueTraits<Holder>::eachMember(const Holder& holder, const std::function<optional<Error> (const std::string&, const Holder&)>& fn) {
- // Not implemented (unneeded for MGLStyleFunction conversion).
- NSCAssert(NO, @"eachMember not implemented");
- return {};
-}
-
-inline bool _isBool(const id value) {
- if (![value isKindOfClass:[NSNumber class]]) return false;
- // char: 32-bit boolean
- // BOOL: 64-bit boolean
- NSNumber *number = value;
- return ((strcmp([number objCType], @encode(char)) == 0) ||
- (strcmp([number objCType], @encode(BOOL)) == 0));
-}
-
-inline bool _isNumber(const id value) {
- return [value isKindOfClass:[NSNumber class]] && !_isBool(value);
-}
-
-inline bool _isString(const id value) {
- return [value isKindOfClass:[NSString class]];
-}
-
-template<> optional<bool> ValueTraits<Holder>::toBool(const Holder& holder) {
- const id value = holder.value;
- if (_isBool(value)) {
- return ((NSNumber *)value).boolValue;
- } else {
- return {};
- }
-}
-
-template<> optional<float> ValueTraits<Holder>::toNumber(const Holder& holder) {
- const id value = holder.value;
- if (_isNumber(value)) {
- return ((NSNumber *)value).floatValue;
- } else {
- return {};
- }
-}
-
-template<> optional<double> ValueTraits<Holder>::toDouble(const Holder& holder) {
- const id value = holder.value;
- if (_isNumber(value)) {
- return ((NSNumber *)value).doubleValue;
- } else {
- return {};
- }
-}
-
-template<> optional<std::string> ValueTraits<Holder>::toString(const Holder& holder) {
- const id value = holder.value;
- if (_isString(value)) {
- return std::string(static_cast<const char *>([value UTF8String]));
- } else {
- return {};
- }
-}
-
-template<> optional<mbgl::Value> ValueTraits<Holder>::toValue(const Holder& holder) {
- const id value = holder.value;
- if (isUndefined(value)) {
- return {};
- } else if (_isBool(value)) {
- return { *toBool(holder) };
- } else if ( _isString(value)) {
- return { *toString(holder) };
- } else if (_isNumber(value)) {
- // Need to cast to a double here as the float is otherwise considered a bool...
- return { static_cast<double>(*toNumber(holder)) };
- } else {
- return {};
- }
-}
-
-template<> optional<GeoJSON> ValueTraits<Holder>::toGeoJSON(const Holder& holder, Error& error) {
- error = { "toGeoJSON not implemented" };
- return {};
-}
-
-Value makeValue(const id value) {
- return {Holder(value)};
-}
-
-
-} // namespace conversion
-} // namespace style
-} // namespace mbgl
-
-NS_ASSUME_NONNULL_END
-
diff --git a/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/ios.xcodeproj/project.pbxproj
index 63fc76b2df..a3ccc9337b 100644
--- a/platform/ios/ios.xcodeproj/project.pbxproj
+++ b/platform/ios/ios.xcodeproj/project.pbxproj
@@ -14,8 +14,6 @@
071BBB071EE77631001FB02A /* MGLImageSourceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 071BBB051EE7761A001FB02A /* MGLImageSourceTests.m */; };
1753ED421E53CE6F00A9FD90 /* MGLConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 1753ED411E53CE6F00A9FD90 /* MGLConversion.h */; };
1753ED431E53CE6F00A9FD90 /* MGLConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 1753ED411E53CE6F00A9FD90 /* MGLConversion.h */; };
- 17DBEF831F95066000E60A6B /* MGLConversion.mm in Sources */ = {isa = PBXBuildFile; fileRef = 17DBEF821F95066000E60A6B /* MGLConversion.mm */; };
- 17DBEF841F95066000E60A6B /* MGLConversion.mm in Sources */ = {isa = PBXBuildFile; fileRef = 17DBEF821F95066000E60A6B /* MGLConversion.mm */; };
1F06668A1EC64F8E001C16D7 /* MGLLight.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F0666881EC64F8E001C16D7 /* MGLLight.h */; settings = {ATTRIBUTES = (Public, ); }; };
1F06668D1EC64F8E001C16D7 /* MGLLight.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1F0666891EC64F8E001C16D7 /* MGLLight.mm */; };
1F7454921ECBB42C00021D39 /* MGLLight.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1F0666891EC64F8E001C16D7 /* MGLLight.mm */; };
@@ -574,7 +572,6 @@
071BBAFD1EE75CD4001FB02A /* MGLImageSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLImageSource.mm; sourceTree = "<group>"; };
071BBB051EE7761A001FB02A /* MGLImageSourceTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLImageSourceTests.m; path = ../../darwin/test/MGLImageSourceTests.m; sourceTree = "<group>"; };
1753ED411E53CE6F00A9FD90 /* MGLConversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLConversion.h; sourceTree = "<group>"; };
- 17DBEF821F95066000E60A6B /* MGLConversion.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLConversion.mm; sourceTree = "<group>"; };
1F0666881EC64F8E001C16D7 /* MGLLight.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLLight.h; sourceTree = "<group>"; };
1F0666891EC64F8E001C16D7 /* MGLLight.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLLight.mm; sourceTree = "<group>"; };
1F7454941ECD450D00021D39 /* MGLLight_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLLight_Private.h; sourceTree = "<group>"; };
@@ -1097,7 +1094,6 @@
35599DA21D4682B60048254D /* Styling */ = {
isa = PBXGroup;
children = (
- 17DBEF821F95066000E60A6B /* MGLConversion.mm */,
1753ED411E53CE6F00A9FD90 /* MGLConversion.h */,
35599DB81D46AD7F0048254D /* Categories */,
353933F01D3FB6BA003F57D7 /* Layers */,
@@ -2328,7 +2324,6 @@
DA8848501CBAFB9800AB86E3 /* MGLAnnotationImage.m in Sources */,
DA8848281CBAFA6200AB86E3 /* MGLShape.mm in Sources */,
DA35A2B31CCA141D00E826B2 /* MGLCompassDirectionFormatter.m in Sources */,
- 17DBEF831F95066000E60A6B /* MGLConversion.mm in Sources */,
DD0902A91DB1929D00C5BDCE /* MGLNetworkConfiguration.m in Sources */,
35D13AB91D3D15E300AFB4E0 /* MGLStyleLayer.mm in Sources */,
DA35A2CB1CCAAAD200E826B2 /* NSValue+MGLAdditions.m in Sources */,
@@ -2416,7 +2411,6 @@
DAA4E41F1CBB730400178DFB /* MGLMultiPoint.mm in Sources */,
DD0902AA1DB1929D00C5BDCE /* MGLNetworkConfiguration.m in Sources */,
DA35A2B41CCA141D00E826B2 /* MGLCompassDirectionFormatter.m in Sources */,
- 17DBEF841F95066000E60A6B /* MGLConversion.mm in Sources */,
35D13ABA1D3D15E300AFB4E0 /* MGLStyleLayer.mm in Sources */,
071BBAFF1EE7613E001FB02A /* MGLImageSource.mm in Sources */,
DA35A2CC1CCAAAD200E826B2 /* NSValue+MGLAdditions.m in Sources */,
diff --git a/platform/macos/macos.xcodeproj/project.pbxproj b/platform/macos/macos.xcodeproj/project.pbxproj
index 6f99382b02..34f8860686 100644
--- a/platform/macos/macos.xcodeproj/project.pbxproj
+++ b/platform/macos/macos.xcodeproj/project.pbxproj
@@ -73,7 +73,6 @@
40B77E451DB11BC9003DA2FE /* NSArray+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 40B77E431DB11BB0003DA2FE /* NSArray+MGLAdditions.h */; };
40B77E461DB11BCD003DA2FE /* NSArray+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 40B77E421DB11BB0003DA2FE /* NSArray+MGLAdditions.mm */; };
40E1601D1DF217D6005EA6D9 /* MGLStyleLayerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 40E1601B1DF216E6005EA6D9 /* MGLStyleLayerTests.m */; };
- 5241C2BE1F7AFFAF00DDB20E /* MGLConversion.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5241C2BD1F7AFFAF00DDB20E /* MGLConversion.mm */; };
52B5D17F1E5E26DF00BBCB48 /* libmbgl-loop-darwin.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5548BE7B1D0ACBBD005DDE81 /* libmbgl-loop-darwin.a */; };
52B5D1801E5E26DF00BBCB48 /* libmbgl-loop-darwin.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5548BE7B1D0ACBBD005DDE81 /* libmbgl-loop-darwin.a */; };
5548BE781D09E718005DDE81 /* libmbgl-core.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAE6C3451CC31D1200DB3429 /* libmbgl-core.a */; };
@@ -350,7 +349,6 @@
40B77E431DB11BB0003DA2FE /* NSArray+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSArray+MGLAdditions.h"; sourceTree = "<group>"; };
40E1601A1DF216E6005EA6D9 /* MGLStyleLayerTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLStyleLayerTests.h; sourceTree = "<group>"; };
40E1601B1DF216E6005EA6D9 /* MGLStyleLayerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLStyleLayerTests.m; sourceTree = "<group>"; };
- 5241C2BD1F7AFFAF00DDB20E /* MGLConversion.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLConversion.mm; sourceTree = "<group>"; };
52BECB091CC5A26F009CD791 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
5548BE7B1D0ACBBD005DDE81 /* libmbgl-loop-darwin.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libmbgl-loop-darwin.a"; path = "cmake/Debug/libmbgl-loop-darwin.a"; sourceTree = "<group>"; };
556660C51E1BEA0100E2C41B /* MGLFoundation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLFoundation.h; sourceTree = "<group>"; };
@@ -700,7 +698,6 @@
isa = PBXGroup;
children = (
1753ED3F1E53CE5200A9FD90 /* MGLConversion.h */,
- 5241C2BD1F7AFFAF00DDB20E /* MGLConversion.mm */,
352742791D4C235C00A1ECE6 /* Categories */,
35136D471D42295400C20EFD /* Layers */,
3527427E1D4C242B00A1ECE6 /* Sources */,
@@ -730,14 +727,6 @@
name = "Test Helpers";
sourceTree = "<group>";
};
- 5241C2BA1F7AF16100DDB20E /* Recovered References */ = {
- isa = PBXGroup;
- children = (
- 30E578141DAA7D920050F07E /* NSImage+MGLAdditions.h */,
- );
- name = "Recovered References";
- sourceTree = "<group>";
- };
DA839E891CC2E3400062CAFB = {
isa = PBXGroup;
children = (
@@ -747,7 +736,6 @@
DAE6C31E1CC308BC00DB3429 /* Frameworks */,
DAE6C3C41CC31F7800DB3429 /* Configuration */,
DA839E931CC2E3400062CAFB /* Products */,
- 5241C2BA1F7AF16100DDB20E /* Recovered References */,
);
sourceTree = "<group>";
};
@@ -1445,7 +1433,6 @@
1FCDF1431F2A4F3600A46694 /* MGLVectorSource+MGLAdditions.m in Sources */,
DD0902B21DB1AC6400C5BDCE /* MGLNetworkConfiguration.m in Sources */,
1F7454A51ECFB00300021D39 /* MGLLight.mm in Sources */,
- 5241C2BE1F7AFFAF00DDB20E /* MGLConversion.mm in Sources */,
DAE6C3B11CC31EF300DB3429 /* MGLAnnotationImage.m in Sources */,
3508EC651D749D39009B0EE4 /* NSExpression+MGLAdditions.mm in Sources */,
DACC22151CF3D3E200D220D9 /* MGLFeature.mm in Sources */,
diff --git a/platform/node/src/node_conversion.cpp b/platform/node/src/node_conversion.cpp
deleted file mode 100644
index ed082615d0..0000000000
--- a/platform/node/src/node_conversion.cpp
+++ /dev/null
@@ -1,137 +0,0 @@
-#include "node_conversion.hpp"
-#include <mbgl/style/conversion/geojson.hpp>
-
-namespace mbgl {
-namespace style {
-namespace conversion {
-
-template<> bool ValueTraits<v8::Local<v8::Value>>::isUndefined(const v8::Local<v8::Value>& value) {
- Nan::HandleScope scope;
-
- return value->IsUndefined() || value->IsNull();
-}
-
-template<> bool ValueTraits<v8::Local<v8::Value>>::isArray(const v8::Local<v8::Value>& value) {
- Nan::HandleScope scope;
-
- return value->IsArray();
-}
-
-template<> std::size_t ValueTraits<v8::Local<v8::Value>>::arrayLength(const v8::Local<v8::Value>& value) {
- Nan::HandleScope scope;
- // const_cast because v8::Local<T>::As is not marked const until node v8.0
- v8::Local<v8::Array> array = const_cast<v8::Local<v8::Value>&>(value).As<v8::Array>();
- return array->Length();
-}
-
-template<> v8::Local<v8::Value> ValueTraits<v8::Local<v8::Value>>::arrayMember(const v8::Local<v8::Value>& value, std::size_t i) {
- Nan::EscapableHandleScope scope;
- // const_cast because v8::Local<T>::As is not marked const until node v8.0
- v8::Local<v8::Array> array = const_cast<v8::Local<v8::Value>&>(value).As<v8::Array>();
- return scope.Escape(Nan::Get(array, i).ToLocalChecked());
-}
-
-template<> bool ValueTraits<v8::Local<v8::Value>>::isObject(const v8::Local<v8::Value>& value) {
- Nan::HandleScope scope;
-
- return value->IsObject() && !value->IsArray();
-}
-
-template<> optional<v8::Local<v8::Value>> ValueTraits<v8::Local<v8::Value>>::objectMember(const v8::Local<v8::Value>& value, const char * name) {
- Nan::EscapableHandleScope scope;
-
- if (!Nan::Has(Nan::To<v8::Object>(value).ToLocalChecked(), Nan::New(name).ToLocalChecked()).FromJust()) {
- return {};
- }
- Nan::MaybeLocal<v8::Value> result = Nan::Get(Nan::To<v8::Object>(value).ToLocalChecked(), Nan::New(name).ToLocalChecked());
- if (result.IsEmpty()) {
- return {};
- }
- return {scope.Escape(result.ToLocalChecked())};
-}
-
-template<> optional<Error> ValueTraits<v8::Local<v8::Value>>::eachMember(const v8::Local<v8::Value>& value, const std::function<optional<Error> (const std::string&, const v8::Local<v8::Value>&)>& fn) {
- Nan::HandleScope scope;
-
- v8::Local<v8::Array> names = Nan::GetOwnPropertyNames(Nan::To<v8::Object>(value).ToLocalChecked()).ToLocalChecked();
- for (uint32_t i = 0; i < names->Length(); ++i) {
- v8::Local<v8::Value> k = Nan::Get(names, i).ToLocalChecked();
- v8::Local<v8::Value> v = Nan::Get(Nan::To<v8::Object>(value).ToLocalChecked(), k).ToLocalChecked();
- optional<Error> result = fn(*Nan::Utf8String(k), v);
- if (result) {
- return result;
- }
- }
- return {};
-}
-
-template<> optional<bool> ValueTraits<v8::Local<v8::Value>>::toBool(const v8::Local<v8::Value>& value) {
- Nan::HandleScope scope;
-
- if (!value->IsBoolean()) {
- return {};
- }
- return value->BooleanValue();
-}
-
-template<> optional<float> ValueTraits<v8::Local<v8::Value>>::toNumber(const v8::Local<v8::Value>& value) {
- Nan::HandleScope scope;
-
- if (!value->IsNumber()) {
- return {};
- }
- return value->NumberValue();
-}
-
-template<> optional<double> ValueTraits<v8::Local<v8::Value>>::toDouble(const v8::Local<v8::Value>& value) {
- Nan::HandleScope scope;
-
- if (!value->IsNumber()) {
- return {};
- }
- return value->NumberValue();
-}
-
-template<> optional<std::string> ValueTraits<v8::Local<v8::Value>>::toString(const v8::Local<v8::Value>& value) {
- Nan::HandleScope scope;
-
- if (!value->IsString()) {
- return {};
- }
- return std::string(*Nan::Utf8String(value));
-}
-
-template<> optional<mbgl::Value> ValueTraits<v8::Local<v8::Value>>::toValue(const v8::Local<v8::Value>& value) {
-
- if (value->IsFalse()) {
- return { false };
- } else if (value->IsTrue()) {
- return { true };
- } else if (value->IsString()) {
- return { std::string(*Nan::Utf8String(value)) };
- } else if (value->IsUint32()) {
- return { std::uint64_t(value->Uint32Value()) };
- } else if (value->IsInt32()) {
- return { std::int64_t(value->Int32Value()) };
- } else if (value->IsNumber()) {
- return { value->NumberValue() };
- } else {
- return {};
- }
-}
-
-template<> optional<GeoJSON> ValueTraits<v8::Local<v8::Value>>::toGeoJSON(const v8::Local<v8::Value>& value, Error& error) {
- try {
- Nan::JSON JSON;
-
- std::string string = *Nan::Utf8String(JSON.Stringify(value->ToObject()).ToLocalChecked());
- return parseGeoJSON(string, error);
- } catch (const std::exception& ex) {
- error = { ex.what() };
- return {};
- }
-}
-
-} // namespace conversion
-} // namespace style
-} // namespace mbgl
diff --git a/platform/node/src/node_conversion.hpp b/platform/node/src/node_conversion.hpp
index 7f0a7ed39e..7db5b23642 100644
--- a/platform/node/src/node_conversion.hpp
+++ b/platform/node/src/node_conversion.hpp
@@ -9,17 +9,137 @@
#include <mbgl/util/optional.hpp>
#include <mbgl/util/feature.hpp>
#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/conversion/geojson.hpp>
namespace mbgl {
namespace style {
namespace conversion {
+template <>
+class ValueTraits<v8::Local<v8::Value>> {
+public:
+ static bool isUndefined(const v8::Local<v8::Value>& value) {
+ Nan::HandleScope scope;
+ return value->IsUndefined() || value->IsNull();
+ }
+
+ static bool isArray(const v8::Local<v8::Value>& value) {
+ Nan::HandleScope scope;
+ return value->IsArray();
+ }
+
+ static std::size_t arrayLength(const v8::Local<v8::Value>& value) {
+ Nan::HandleScope scope;
+ // const_cast because v8::Local<T>::As is not marked const until node v8.0
+ v8::Local<v8::Array> array = const_cast<v8::Local<v8::Value>&>(value).As<v8::Array>();
+ return array->Length();
+ }
+
+ static v8::Local<v8::Value> arrayMember(const v8::Local<v8::Value>& value, std::size_t i) {
+ Nan::EscapableHandleScope scope;
+ // const_cast because v8::Local<T>::As is not marked const until node v8.0
+ v8::Local<v8::Array> array = const_cast<v8::Local<v8::Value>&>(value).As<v8::Array>();
+ return scope.Escape(Nan::Get(array, i).ToLocalChecked());
+ }
+
+ static bool isObject(const v8::Local<v8::Value>& value) {
+ Nan::HandleScope scope;
+ return value->IsObject() && !value->IsArray();
+ }
+
+ static optional<v8::Local<v8::Value>> objectMember(const v8::Local<v8::Value>& value, const char * name) {
+ Nan::EscapableHandleScope scope;
+ if (!Nan::Has(Nan::To<v8::Object>(value).ToLocalChecked(), Nan::New(name).ToLocalChecked()).FromJust()) {
+ return {};
+ }
+ Nan::MaybeLocal<v8::Value> result = Nan::Get(Nan::To<v8::Object>(value).ToLocalChecked(), Nan::New(name).ToLocalChecked());
+ if (result.IsEmpty()) {
+ return {};
+ }
+ return {scope.Escape(result.ToLocalChecked())};
+ }
+
+ static optional<Error> eachMember(const v8::Local<v8::Value>& value, const std::function<optional<Error> (const std::string&, const v8::Local<v8::Value>&)>& fn) {
+ Nan::HandleScope scope;
+ v8::Local<v8::Array> names = Nan::GetOwnPropertyNames(Nan::To<v8::Object>(value).ToLocalChecked()).ToLocalChecked();
+ for (uint32_t i = 0; i < names->Length(); ++i) {
+ v8::Local<v8::Value> k = Nan::Get(names, i).ToLocalChecked();
+ v8::Local<v8::Value> v = Nan::Get(Nan::To<v8::Object>(value).ToLocalChecked(), k).ToLocalChecked();
+ optional<Error> result = fn(*Nan::Utf8String(k), v);
+ if (result) {
+ return result;
+ }
+ }
+ return {};
+ }
+
+ static optional<bool> toBool(const v8::Local<v8::Value>& value) {
+ Nan::HandleScope scope;
+ if (!value->IsBoolean()) {
+ return {};
+ }
+ return value->BooleanValue();
+ }
+
+ static optional<float> toNumber(const v8::Local<v8::Value>& value) {
+ Nan::HandleScope scope;
+ if (!value->IsNumber()) {
+ return {};
+ }
+ return value->NumberValue();
+ }
+
+ static optional<double> toDouble(const v8::Local<v8::Value>& value) {
+ Nan::HandleScope scope;
+ if (!value->IsNumber()) {
+ return {};
+ }
+ return value->NumberValue();
+ }
+
+ static optional<std::string> toString(const v8::Local<v8::Value>& value) {
+ Nan::HandleScope scope;
+ if (!value->IsString()) {
+ return {};
+ }
+ return std::string(*Nan::Utf8String(value));
+ }
+
+ static optional<mbgl::Value> toValue(const v8::Local<v8::Value>& value) {
+ if (value->IsFalse()) {
+ return { false };
+ } else if (value->IsTrue()) {
+ return { true };
+ } else if (value->IsString()) {
+ return { std::string(*Nan::Utf8String(value)) };
+ } else if (value->IsUint32()) {
+ return { std::uint64_t(value->Uint32Value()) };
+ } else if (value->IsInt32()) {
+ return { std::int64_t(value->Int32Value()) };
+ } else if (value->IsNumber()) {
+ return { value->NumberValue() };
+ } else {
+ return {};
+ }
+ }
+
+ static optional<GeoJSON> toGeoJSON(const v8::Local<v8::Value>& value, Error& error) {
+ try {
+ Nan::JSON JSON;
+ std::string string = *Nan::Utf8String(JSON.Stringify(value->ToObject()).ToLocalChecked());
+ return parseGeoJSON(string, error);
+ } catch (const std::exception& ex) {
+ error = { ex.what() };
+ return {};
+ }
+ }
+};
+
template <class T, class...Args>
optional<T> convert(const v8::Local<v8::Value>& value, Error& error, Args&&...args) {
return convert<T>(Value(value), error, std::forward<Args>(args)...);
}
-
} // namespace conversion
} // namespace style
} // namespace mbgl
diff --git a/platform/qt/qt.cmake b/platform/qt/qt.cmake
index 918e6b93cd..a7862c3936 100644
--- a/platform/qt/qt.cmake
+++ b/platform/qt/qt.cmake
@@ -60,7 +60,6 @@ set(MBGL_QT_FILESOURCE_FILES
add_library(qmapboxgl SHARED
platform/qt/include/qmapbox.hpp
platform/qt/include/qmapboxgl.hpp
- platform/qt/src/qt_conversion.cpp
platform/qt/src/qt_conversion.hpp
platform/qt/src/qt_geojson.cpp
platform/qt/src/qt_geojson.hpp
diff --git a/platform/qt/src/qt_conversion.cpp b/platform/qt/src/qt_conversion.cpp
deleted file mode 100644
index 35a6ef4fc9..0000000000
--- a/platform/qt/src/qt_conversion.cpp
+++ /dev/null
@@ -1,133 +0,0 @@
-#include <mbgl/util/feature.hpp>
-#include <mbgl/style/conversion/geojson.hpp>
-#include <QColor>
-#include <QMapbox>
-#include "qt_geojson.hpp"
-
-namespace mbgl {
-namespace style {
-namespace conversion {
-
-template<> bool ValueTraits<QVariant>::isUndefined(const QVariant& value) {
- return value.isNull() || !value.isValid();
-}
-
-template<> bool ValueTraits<QVariant>::isArray(const QVariant& value) {
- return value.canConvert(QVariant::List);
-}
-
-template<> std::size_t ValueTraits<QVariant>::arrayLength(const QVariant& value) {
- return value.toList().size();
-}
-
-template<> QVariant ValueTraits<QVariant>::arrayMember(const QVariant& value, std::size_t i) {
- return value.toList()[i];
-}
-
-template<> bool ValueTraits<QVariant>::isObject(const QVariant& value) {
- return value.canConvert(QVariant::Map)
- || value.type() == QVariant::ByteArray
-#if QT_VERSION >= 0x050000
- || QString(value.typeName()) == QStringLiteral("QMapbox::Feature");
-#else
- || QString(value.typeName()) == QString("QMapbox::Feature");
-#endif
-}
-
-template<> optional<QVariant> ValueTraits<QVariant>::objectMember(const QVariant& value, const char* key) {
- auto map = value.toMap();
- auto iter = map.constFind(key);
-
- if (iter != map.constEnd()) {
- return iter.value();
- } else {
- return {};
- }
-}
-
-using EachMemberFn = std::function<optional<Error>(const std::string&, const QVariant&)>;
-
-template<> optional<Error> ValueTraits<QVariant>::eachMember(const QVariant& value, const EachMemberFn& fn) {
- auto map = value.toMap();
- auto iter = map.constBegin();
-
- while (iter != map.constEnd()) {
- optional<Error> result = fn(iter.key().toStdString(), iter.value());
- if (result) {
- return result;
- }
-
- ++iter;
- }
-
- return {};
-}
-
-template<> optional<bool> ValueTraits<QVariant>::toBool(const QVariant& value) {
- if (value.type() == QVariant::Bool) {
- return value.toBool();
- } else {
- return {};
- }
-}
-
-template<> optional<float> ValueTraits<QVariant>::toNumber(const QVariant& value) {
- if (value.type() == QVariant::Int || value.type() == QVariant::Double) {
- return value.toFloat();
- } else {
- return {};
- }
-}
-template<> optional<double> ValueTraits<QVariant>::toDouble(const QVariant& value) {
- if (value.type() == QVariant::Int || value.type() == QVariant::Double) {
- return value.toDouble();
- } else {
- return {};
- }
-}
-
-template<> optional<std::string> ValueTraits<QVariant>::toString(const QVariant& value) {
- if (value.type() == QVariant::String) {
- return value.toString().toStdString();
- } else if (value.type() == QVariant::Color) {
- return value.value<QColor>().name().toStdString();
- } else {
- return {};
- }
-}
-
-template<> optional<mbgl::Value> ValueTraits<QVariant>::toValue(const QVariant& value) {
- if (value.type() == QVariant::Bool) {
- return { value.toBool() };
- } else if (value.type() == QVariant::String) {
- return { value.toString().toStdString() };
- } else if (value.type() == QVariant::Color) {
- return { value.value<QColor>().name().toStdString() };
- } else if (value.type() == QVariant::Int) {
- return { int64_t(value.toInt()) };
- } else if (value.canConvert(QVariant::Double)) {
- return { value.toDouble() };
- } else {
- return {};
- }
-}
-
-template <> optional<GeoJSON> ValueTraits<QVariant>::toGeoJSON(const QVariant& value, Error& error) {
-#if QT_VERSION >= 0x050000
- if (value.typeName() == QStringLiteral("QMapbox::Feature")) {
-#else
- if (value.typeName() == QString("QMapbox::Feature")) {
-#endif
- return GeoJSON { asMapboxGLFeature(value.value<QMapbox::Feature>()) };
- } else if (value.type() != QVariant::ByteArray) {
- error = { "JSON data must be in QByteArray" };
- return {};
- }
-
- QByteArray data = value.toByteArray();
- return parseGeoJSON(std::string(data.constData(), data.size()), error);
-}
-
-} // namespace conversion
-} // namespace style
-} // namespace mbgl
diff --git a/platform/qt/src/qt_conversion.hpp b/platform/qt/src/qt_conversion.hpp
index bd830f8432..3f58147ca2 100644
--- a/platform/qt/src/qt_conversion.hpp
+++ b/platform/qt/src/qt_conversion.hpp
@@ -1,13 +1,143 @@
#pragma once
#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/conversion/geojson.hpp>
#include <mbgl/util/optional.hpp>
+
#include <QVariant>
+#include <QColor>
+#include <QMapbox>
+#include "qt_geojson.hpp"
namespace mbgl {
namespace style {
namespace conversion {
+template <>
+class ValueTraits<QVariant> {
+public:
+ static bool isUndefined(const QVariant& value) {
+ return value.isNull() || !value.isValid();
+ }
+
+ static bool isArray(const QVariant& value) {
+ return value.canConvert(QVariant::List);
+ }
+
+ static std::size_t arrayLength(const QVariant& value) {
+ return value.toList().size();
+ }
+
+ static QVariant arrayMember(const QVariant& value, std::size_t i) {
+ return value.toList()[i];
+ }
+
+ static bool isObject(const QVariant& value) {
+ return value.canConvert(QVariant::Map)
+ || value.type() == QVariant::ByteArray
+ #if QT_VERSION >= 0x050000
+ || QString(value.typeName()) == QStringLiteral("QMapbox::Feature");
+ #else
+ || QString(value.typeName()) == QString("QMapbox::Feature");
+ #endif
+ }
+
+ static optional<QVariant> objectMember(const QVariant& value, const char* key) {
+ auto map = value.toMap();
+ auto iter = map.constFind(key);
+
+ if (iter != map.constEnd()) {
+ return iter.value();
+ } else {
+ return {};
+ }
+ }
+
+ using EachMemberFn = std::function<optional<Error>(const std::string&, const QVariant&)>;
+
+ static optional<Error> eachMember(const QVariant& value, const EachMemberFn& fn) {
+ auto map = value.toMap();
+ auto iter = map.constBegin();
+
+ while (iter != map.constEnd()) {
+ optional<Error> result = fn(iter.key().toStdString(), iter.value());
+ if (result) {
+ return result;
+ }
+
+ ++iter;
+ }
+
+ return {};
+ }
+
+ static optional<bool> toBool(const QVariant& value) {
+ if (value.type() == QVariant::Bool) {
+ return value.toBool();
+ } else {
+ return {};
+ }
+ }
+
+ static optional<float> toNumber(const QVariant& value) {
+ if (value.type() == QVariant::Int || value.type() == QVariant::Double) {
+ return value.toFloat();
+ } else {
+ return {};
+ }
+ }
+
+ static optional<double> toDouble(const QVariant& value) {
+ if (value.type() == QVariant::Int || value.type() == QVariant::Double) {
+ return value.toDouble();
+ } else {
+ return {};
+ }
+ }
+
+ static optional<std::string> toString(const QVariant& value) {
+ if (value.type() == QVariant::String) {
+ return value.toString().toStdString();
+ } else if (value.type() == QVariant::Color) {
+ return value.value<QColor>().name().toStdString();
+ } else {
+ return {};
+ }
+ }
+
+ static optional<mbgl::Value> toValue(const QVariant& value) {
+ if (value.type() == QVariant::Bool) {
+ return { value.toBool() };
+ } else if (value.type() == QVariant::String) {
+ return { value.toString().toStdString() };
+ } else if (value.type() == QVariant::Color) {
+ return { value.value<QColor>().name().toStdString() };
+ } else if (value.type() == QVariant::Int) {
+ return { int64_t(value.toInt()) };
+ } else if (value.canConvert(QVariant::Double)) {
+ return { value.toDouble() };
+ } else {
+ return {};
+ }
+ }
+
+ static optional<GeoJSON> toGeoJSON(const QVariant& value, Error& error) {
+ #if QT_VERSION >= 0x050000
+ if (value.typeName() == QStringLiteral("QMapbox::Feature")) {
+ #else
+ if (value.typeName() == QString("QMapbox::Feature")) {
+ #endif
+ return GeoJSON { asMapboxGLFeature(value.value<QMapbox::Feature>()) };
+ } else if (value.type() != QVariant::ByteArray) {
+ error = { "JSON data must be in QByteArray" };
+ return {};
+ }
+
+ QByteArray data = value.toByteArray();
+ return parseGeoJSON(std::string(data.constData(), data.size()), error);
+ }
+};
+
template <class T, class...Args>
optional<T> convert(const QVariant& value, Error& error, Args&&...args) {
return convert<T>(Value(value), error, std::forward<Args>(args)...);
diff --git a/src/mbgl/style/rapidjson_conversion.cpp b/src/mbgl/style/rapidjson_conversion.cpp
deleted file mode 100644
index a6162f1b77..0000000000
--- a/src/mbgl/style/rapidjson_conversion.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-#include <mbgl/style/rapidjson_conversion.hpp>
-#include <mapbox/geojson.hpp>
-#include <mapbox/geojson/rapidjson.hpp>
-
-
-namespace mbgl {
-namespace style {
-namespace conversion {
-
-template<> bool ValueTraits<const JSValue*>::isUndefined(const JSValue* const& value) {
- return value->IsNull();
-}
-
-template<> bool ValueTraits<const JSValue*>::isArray(const JSValue* const& value) {
- return value->IsArray();
-}
-
-template<> std::size_t ValueTraits<const JSValue*>::arrayLength(const JSValue* const& value) {
- return value->Size();
-}
-
-template<> const JSValue* ValueTraits<const JSValue*>::arrayMember(const JSValue* const& value, std::size_t i) {
- return &(*value)[rapidjson::SizeType(i)];
-}
-
-template<> bool ValueTraits<const JSValue*>::isObject(const JSValue* const& value) {
- return value->IsObject();
-}
-
-template<> optional<const JSValue*> ValueTraits<const JSValue*>::objectMember(const JSValue* const& value, const char * name) {
- if (!value->HasMember(name)) {
- return optional<const JSValue*>();
- }
- const JSValue* const& member = &(*value)[name];
- return {member};
-}
-
-template<> optional<Error> ValueTraits<const JSValue*>::eachMember(const JSValue* const& value, const std::function<optional<Error> (const std::string&, const JSValue* const&)>& fn) {
- assert(value->IsObject());
- for (const auto& property : value->GetObject()) {
- optional<Error> result =
- fn({ property.name.GetString(), property.name.GetStringLength() }, &property.value);
- if (result) {
- return result;
- }
- }
- return {};
-}
-
-template<> optional<bool> ValueTraits<const JSValue*>::toBool(const JSValue* const& value) {
- if (!value->IsBool()) {
- return {};
- }
- return value->GetBool();
-}
-
-template<> optional<float> ValueTraits<const JSValue*>::toNumber(const JSValue* const& value) {
- if (!value->IsNumber()) {
- return {};
- }
- return value->GetDouble();
-}
-
-template<> optional<double> ValueTraits<const JSValue*>::toDouble(const JSValue* const& value) {
- if (!value->IsNumber()) {
- return {};
- }
- return value->GetDouble();
-}
-
-template<> optional<std::string> ValueTraits<const JSValue*>::toString(const JSValue* const& value) {
- if (!value->IsString()) {
- return {};
- }
- return {{ value->GetString(), value->GetStringLength() }};
-}
-
-template<> optional<mbgl::Value> ValueTraits<const JSValue*>::toValue(const JSValue* const& value) {
- switch (value->GetType()) {
- case rapidjson::kNullType:
- case rapidjson::kFalseType:
- return { false };
-
- case rapidjson::kTrueType:
- return { true };
-
- case rapidjson::kStringType:
- return { std::string { value->GetString(), value->GetStringLength() } };
-
- case rapidjson::kNumberType:
- if (value->IsUint64()) return { value->GetUint64() };
- if (value->IsInt64()) return { value->GetInt64() };
- return { value->GetDouble() };
-
- default:
- return {};
- }
-}
-
-template<> optional<GeoJSON> ValueTraits<const JSValue*>::toGeoJSON(const JSValue* const& value, Error& error) {
- try {
- return mapbox::geojson::convert(*value);
- } catch (const std::exception& ex) {
- error = { ex.what() };
- return {};
- }
-}
-
-
-} // namespace conversion
-} // namespace style
-} // namespace mbgl
diff --git a/src/mbgl/style/rapidjson_conversion.hpp b/src/mbgl/style/rapidjson_conversion.hpp
index 082fd1c064..ae3ead24b0 100644
--- a/src/mbgl/style/rapidjson_conversion.hpp
+++ b/src/mbgl/style/rapidjson_conversion.hpp
@@ -3,10 +3,116 @@
#include <mbgl/util/rapidjson.hpp>
#include <mbgl/style/conversion.hpp>
+#include <mapbox/geojson.hpp>
+#include <mapbox/geojson/rapidjson.hpp>
+
namespace mbgl {
namespace style {
namespace conversion {
+template <>
+class ValueTraits<const JSValue*> {
+public:
+ static bool isUndefined(const JSValue* value) {
+ return value->IsNull();
+ }
+
+ static bool isArray(const JSValue* value) {
+ return value->IsArray();
+ }
+
+ static std::size_t arrayLength(const JSValue* value) {
+ return value->Size();
+ }
+
+ static const JSValue* arrayMember(const JSValue* value, std::size_t i) {
+ return &(*value)[rapidjson::SizeType(i)];
+ }
+
+ static bool isObject(const JSValue* value) {
+ return value->IsObject();
+ }
+
+ static optional<const JSValue*> objectMember(const JSValue* value, const char * name) {
+ if (!value->HasMember(name)) {
+ return optional<const JSValue*>();
+ }
+ const JSValue* const& member = &(*value)[name];
+ return {member};
+ }
+
+ static optional<Error> eachMember(const JSValue* value, const std::function<optional<Error> (const std::string&, const JSValue* const&)>& fn) {
+ assert(value->IsObject());
+ for (const auto& property : value->GetObject()) {
+ optional<Error> result =
+ fn({ property.name.GetString(), property.name.GetStringLength() }, &property.value);
+ if (result) {
+ return result;
+ }
+ }
+ return {};
+ }
+
+ static optional<bool> toBool(const JSValue* value) {
+ if (!value->IsBool()) {
+ return {};
+ }
+ return value->GetBool();
+ }
+
+ static optional<float> toNumber(const JSValue* value) {
+ if (!value->IsNumber()) {
+ return {};
+ }
+ return value->GetDouble();
+ }
+
+ static optional<double> toDouble(const JSValue* value) {
+ if (!value->IsNumber()) {
+ return {};
+ }
+ return value->GetDouble();
+ }
+
+ static optional<std::string> toString(const JSValue* value) {
+ if (!value->IsString()) {
+ return {};
+ }
+ return {{ value->GetString(), value->GetStringLength() }};
+ }
+
+ static optional<mbgl::Value> toValue(const JSValue* value) {
+ switch (value->GetType()) {
+ case rapidjson::kNullType:
+ case rapidjson::kFalseType:
+ return { false };
+
+ case rapidjson::kTrueType:
+ return { true };
+
+ case rapidjson::kStringType:
+ return { std::string { value->GetString(), value->GetStringLength() } };
+
+ case rapidjson::kNumberType:
+ if (value->IsUint64()) return { value->GetUint64() };
+ if (value->IsInt64()) return { value->GetInt64() };
+ return { value->GetDouble() };
+
+ default:
+ return {};
+ }
+ }
+
+ static optional<GeoJSON> toGeoJSON(const JSValue* value, Error& error) {
+ try {
+ return mapbox::geojson::convert(*value);
+ } catch (const std::exception& ex) {
+ error = { ex.what() };
+ return {};
+ }
+ }
+};
+
template <class T, class...Args>
optional<T> convert(const JSValue& value, Error& error, Args&&...args) {
return convert<T>(Value(&value), error, std::forward<Args>(args)...);