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