1 #pragma once
2
3 #include <mbgl/util/rapidjson.hpp>
4 #include <mbgl/style/conversion.hpp>
5
6 #include <mapbox/geojson.hpp>
7 #include <mapbox/geojson/rapidjson.hpp>
8
9 namespace mbgl {
10 namespace style {
11 namespace conversion {
12
13 template <>
14 class ConversionTraits<const JSValue*> {
15 public:
isUndefined(const JSValue * value)16 static bool isUndefined(const JSValue* value) {
17 return value->IsNull();
18 }
19
isArray(const JSValue * value)20 static bool isArray(const JSValue* value) {
21 return value->IsArray();
22 }
23
arrayLength(const JSValue * value)24 static std::size_t arrayLength(const JSValue* value) {
25 return value->Size();
26 }
27
arrayMember(const JSValue * value,std::size_t i)28 static const JSValue* arrayMember(const JSValue* value, std::size_t i) {
29 return &(*value)[rapidjson::SizeType(i)];
30 }
31
isObject(const JSValue * value)32 static bool isObject(const JSValue* value) {
33 return value->IsObject();
34 }
35
objectMember(const JSValue * value,const char * name)36 static optional<const JSValue*> objectMember(const JSValue* value, const char * name) {
37 if (!value->HasMember(name)) {
38 return optional<const JSValue*>();
39 }
40 const JSValue* const& member = &(*value)[name];
41 return {member};
42 }
43
44 template <class Fn>
eachMember(const JSValue * value,Fn && fn)45 static optional<Error> eachMember(const JSValue* value, Fn&& fn) {
46 assert(value->IsObject());
47 for (const auto& property : value->GetObject()) {
48 optional<Error> result =
49 fn({ property.name.GetString(), property.name.GetStringLength() }, &property.value);
50 if (result) {
51 return result;
52 }
53 }
54 return {};
55 }
56
toBool(const JSValue * value)57 static optional<bool> toBool(const JSValue* value) {
58 if (!value->IsBool()) {
59 return {};
60 }
61 return value->GetBool();
62 }
63
toNumber(const JSValue * value)64 static optional<float> toNumber(const JSValue* value) {
65 if (!value->IsNumber()) {
66 return {};
67 }
68 return value->GetDouble();
69 }
70
toDouble(const JSValue * value)71 static optional<double> toDouble(const JSValue* value) {
72 if (!value->IsNumber()) {
73 return {};
74 }
75 return value->GetDouble();
76 }
77
toString(const JSValue * value)78 static optional<std::string> toString(const JSValue* value) {
79 if (!value->IsString()) {
80 return {};
81 }
82 return {{ value->GetString(), value->GetStringLength() }};
83 }
84
toValue(const JSValue * value)85 static optional<Value> toValue(const JSValue* value) {
86 switch (value->GetType()) {
87 case rapidjson::kNullType:
88 case rapidjson::kFalseType:
89 return { false };
90
91 case rapidjson::kTrueType:
92 return { true };
93
94 case rapidjson::kStringType:
95 return { std::string { value->GetString(), value->GetStringLength() } };
96
97 case rapidjson::kNumberType:
98 if (value->IsUint64()) return { value->GetUint64() };
99 if (value->IsInt64()) return { value->GetInt64() };
100 return { value->GetDouble() };
101
102 default:
103 return {};
104 }
105 }
106
toGeoJSON(const JSValue * value,Error & error)107 static optional<GeoJSON> toGeoJSON(const JSValue* value, Error& error) {
108 try {
109 return mapbox::geojson::convert(*value);
110 } catch (const std::exception& ex) {
111 error = { ex.what() };
112 return {};
113 }
114 }
115 };
116
117 template <class T, class...Args>
convert(const JSValue & value,Error & error,Args &&...args)118 optional<T> convert(const JSValue& value, Error& error, Args&&...args) {
119 return convert<T>(Convertible(&value), error, std::forward<Args>(args)...);
120 }
121
122 } // namespace conversion
123 } // namespace style
124 } // namespace mbgl
125
126