1 /*
2  *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "webrtc/base/json.h"
12 
13 #include <errno.h>
14 #include <limits.h>
15 #include <stdlib.h>
16 
17 #include <sstream>
18 
19 namespace rtc {
20 
GetStringFromJson(const Json::Value & in,std::string * out)21 bool GetStringFromJson(const Json::Value& in, std::string* out) {
22   if (!in.isString()) {
23     std::ostringstream s;
24     if (in.isBool()) {
25       s << std::boolalpha << in.asBool();
26     } else if (in.isInt()) {
27       s << in.asInt();
28     } else if (in.isUInt()) {
29       s << in.asUInt();
30     } else if (in.isDouble()) {
31       s << in.asDouble();
32     } else {
33       return false;
34     }
35     *out = s.str();
36   } else {
37     *out = in.asString();
38   }
39   return true;
40 }
41 
GetIntFromJson(const Json::Value & in,int * out)42 bool GetIntFromJson(const Json::Value& in, int* out) {
43   bool ret;
44   if (!in.isString()) {
45     ret = in.isConvertibleTo(Json::intValue);
46     if (ret) {
47       *out = in.asInt();
48     }
49   } else {
50     long val;  // NOLINT
51     const char* c_str = in.asCString();
52     char* end_ptr;
53     errno = 0;
54     val = strtol(c_str, &end_ptr, 10);  // NOLINT
55     ret = (end_ptr != c_str && *end_ptr == '\0' && !errno &&
56            val >= INT_MIN && val <= INT_MAX);
57     *out = val;
58   }
59   return ret;
60 }
61 
GetUIntFromJson(const Json::Value & in,unsigned int * out)62 bool GetUIntFromJson(const Json::Value& in, unsigned int* out) {
63   bool ret;
64   if (!in.isString()) {
65     ret = in.isConvertibleTo(Json::uintValue);
66     if (ret) {
67       *out = in.asUInt();
68     }
69   } else {
70     unsigned long val;  // NOLINT
71     const char* c_str = in.asCString();
72     char* end_ptr;
73     errno = 0;
74     val = strtoul(c_str, &end_ptr, 10);  // NOLINT
75     ret = (end_ptr != c_str && *end_ptr == '\0' && !errno &&
76            val <= UINT_MAX);
77     *out = val;
78   }
79   return ret;
80 }
81 
GetBoolFromJson(const Json::Value & in,bool * out)82 bool GetBoolFromJson(const Json::Value& in, bool* out) {
83   bool ret;
84   if (!in.isString()) {
85     ret = in.isConvertibleTo(Json::booleanValue);
86     if (ret) {
87       *out = in.asBool();
88     }
89   } else {
90     if (in.asString() == "true") {
91       *out = true;
92       ret = true;
93     } else if (in.asString() == "false") {
94       *out = false;
95       ret = true;
96     } else {
97       ret = false;
98     }
99   }
100   return ret;
101 }
102 
GetDoubleFromJson(const Json::Value & in,double * out)103 bool GetDoubleFromJson(const Json::Value& in, double* out) {
104   bool ret;
105   if (!in.isString()) {
106     ret = in.isConvertibleTo(Json::realValue);
107     if (ret) {
108       *out = in.asDouble();
109     }
110   } else {
111     double val;
112     const char* c_str = in.asCString();
113     char* end_ptr;
114     errno = 0;
115     val = strtod(c_str, &end_ptr);
116     ret = (end_ptr != c_str && *end_ptr == '\0' && !errno);
117     *out = val;
118   }
119   return ret;
120 }
121 
122 namespace {
123 template<typename T>
JsonArrayToVector(const Json::Value & value,bool (* getter)(const Json::Value & in,T * out),std::vector<T> * vec)124 bool JsonArrayToVector(const Json::Value& value,
125                        bool (*getter)(const Json::Value& in, T* out),
126                        std::vector<T> *vec) {
127   vec->clear();
128   if (!value.isArray()) {
129     return false;
130   }
131 
132   for (Json::Value::ArrayIndex i = 0; i < value.size(); ++i) {
133     T val;
134     if (!getter(value[i], &val)) {
135       return false;
136     }
137     vec->push_back(val);
138   }
139 
140   return true;
141 }
142 // Trivial getter helper
GetValueFromJson(const Json::Value & in,Json::Value * out)143 bool GetValueFromJson(const Json::Value& in, Json::Value* out) {
144   *out = in;
145   return true;
146 }
147 }  // unnamed namespace
148 
JsonArrayToValueVector(const Json::Value & in,std::vector<Json::Value> * out)149 bool JsonArrayToValueVector(const Json::Value& in,
150                             std::vector<Json::Value>* out) {
151   return JsonArrayToVector(in, GetValueFromJson, out);
152 }
153 
JsonArrayToIntVector(const Json::Value & in,std::vector<int> * out)154 bool JsonArrayToIntVector(const Json::Value& in,
155                           std::vector<int>* out) {
156   return JsonArrayToVector(in, GetIntFromJson, out);
157 }
158 
JsonArrayToUIntVector(const Json::Value & in,std::vector<unsigned int> * out)159 bool JsonArrayToUIntVector(const Json::Value& in,
160                            std::vector<unsigned int>* out) {
161   return JsonArrayToVector(in, GetUIntFromJson, out);
162 }
163 
JsonArrayToStringVector(const Json::Value & in,std::vector<std::string> * out)164 bool JsonArrayToStringVector(const Json::Value& in,
165                              std::vector<std::string>* out) {
166   return JsonArrayToVector(in, GetStringFromJson, out);
167 }
168 
JsonArrayToBoolVector(const Json::Value & in,std::vector<bool> * out)169 bool JsonArrayToBoolVector(const Json::Value& in,
170                            std::vector<bool>* out) {
171   return JsonArrayToVector(in, GetBoolFromJson, out);
172 }
173 
JsonArrayToDoubleVector(const Json::Value & in,std::vector<double> * out)174 bool JsonArrayToDoubleVector(const Json::Value& in,
175                              std::vector<double>* out) {
176   return JsonArrayToVector(in, GetDoubleFromJson, out);
177 }
178 
179 namespace {
180 template<typename T>
VectorToJsonArray(const std::vector<T> & vec)181 Json::Value VectorToJsonArray(const std::vector<T>& vec) {
182   Json::Value result(Json::arrayValue);
183   for (size_t i = 0; i < vec.size(); ++i) {
184     result.append(Json::Value(vec[i]));
185   }
186   return result;
187 }
188 }  // unnamed namespace
189 
ValueVectorToJsonArray(const std::vector<Json::Value> & in)190 Json::Value ValueVectorToJsonArray(const std::vector<Json::Value>& in) {
191   return VectorToJsonArray(in);
192 }
193 
IntVectorToJsonArray(const std::vector<int> & in)194 Json::Value IntVectorToJsonArray(const std::vector<int>& in) {
195   return VectorToJsonArray(in);
196 }
197 
UIntVectorToJsonArray(const std::vector<unsigned int> & in)198 Json::Value UIntVectorToJsonArray(const std::vector<unsigned int>& in) {
199   return VectorToJsonArray(in);
200 }
201 
StringVectorToJsonArray(const std::vector<std::string> & in)202 Json::Value StringVectorToJsonArray(const std::vector<std::string>& in) {
203   return VectorToJsonArray(in);
204 }
205 
BoolVectorToJsonArray(const std::vector<bool> & in)206 Json::Value BoolVectorToJsonArray(const std::vector<bool>& in) {
207   return VectorToJsonArray(in);
208 }
209 
DoubleVectorToJsonArray(const std::vector<double> & in)210 Json::Value DoubleVectorToJsonArray(const std::vector<double>& in) {
211   return VectorToJsonArray(in);
212 }
213 
GetValueFromJsonArray(const Json::Value & in,size_t n,Json::Value * out)214 bool GetValueFromJsonArray(const Json::Value& in, size_t n,
215                            Json::Value* out) {
216   if (!in.isArray() || !in.isValidIndex(static_cast<int>(n))) {
217     return false;
218   }
219 
220   *out = in[static_cast<Json::Value::ArrayIndex>(n)];
221   return true;
222 }
223 
GetIntFromJsonArray(const Json::Value & in,size_t n,int * out)224 bool GetIntFromJsonArray(const Json::Value& in, size_t n,
225                          int* out) {
226   Json::Value x;
227   return GetValueFromJsonArray(in, n, &x) && GetIntFromJson(x, out);
228 }
229 
GetUIntFromJsonArray(const Json::Value & in,size_t n,unsigned int * out)230 bool GetUIntFromJsonArray(const Json::Value& in, size_t n,
231                           unsigned int* out)  {
232   Json::Value x;
233   return GetValueFromJsonArray(in, n, &x) && GetUIntFromJson(x, out);
234 }
235 
GetStringFromJsonArray(const Json::Value & in,size_t n,std::string * out)236 bool GetStringFromJsonArray(const Json::Value& in, size_t n,
237                             std::string* out) {
238   Json::Value x;
239   return GetValueFromJsonArray(in, n, &x) && GetStringFromJson(x, out);
240 }
241 
GetBoolFromJsonArray(const Json::Value & in,size_t n,bool * out)242 bool GetBoolFromJsonArray(const Json::Value& in, size_t n,
243                           bool* out) {
244   Json::Value x;
245   return GetValueFromJsonArray(in, n, &x) && GetBoolFromJson(x, out);
246 }
247 
GetDoubleFromJsonArray(const Json::Value & in,size_t n,double * out)248 bool GetDoubleFromJsonArray(const Json::Value& in, size_t n,
249                             double* out) {
250   Json::Value x;
251   return GetValueFromJsonArray(in, n, &x) && GetDoubleFromJson(x, out);
252 }
253 
GetValueFromJsonObject(const Json::Value & in,const std::string & k,Json::Value * out)254 bool GetValueFromJsonObject(const Json::Value& in, const std::string& k,
255                             Json::Value* out) {
256   if (!in.isObject() || !in.isMember(k)) {
257     return false;
258   }
259 
260   *out = in[k];
261   return true;
262 }
263 
GetIntFromJsonObject(const Json::Value & in,const std::string & k,int * out)264 bool GetIntFromJsonObject(const Json::Value& in, const std::string& k,
265                           int* out) {
266   Json::Value x;
267   return GetValueFromJsonObject(in, k, &x) && GetIntFromJson(x, out);
268 }
269 
GetUIntFromJsonObject(const Json::Value & in,const std::string & k,unsigned int * out)270 bool GetUIntFromJsonObject(const Json::Value& in, const std::string& k,
271                            unsigned int* out)  {
272   Json::Value x;
273   return GetValueFromJsonObject(in, k, &x) && GetUIntFromJson(x, out);
274 }
275 
GetStringFromJsonObject(const Json::Value & in,const std::string & k,std::string * out)276 bool GetStringFromJsonObject(const Json::Value& in, const std::string& k,
277                              std::string* out)  {
278   Json::Value x;
279   return GetValueFromJsonObject(in, k, &x) && GetStringFromJson(x, out);
280 }
281 
GetBoolFromJsonObject(const Json::Value & in,const std::string & k,bool * out)282 bool GetBoolFromJsonObject(const Json::Value& in, const std::string& k,
283                            bool* out) {
284   Json::Value x;
285   return GetValueFromJsonObject(in, k, &x) && GetBoolFromJson(x, out);
286 }
287 
GetDoubleFromJsonObject(const Json::Value & in,const std::string & k,double * out)288 bool GetDoubleFromJsonObject(const Json::Value& in, const std::string& k,
289                              double* out) {
290   Json::Value x;
291   return GetValueFromJsonObject(in, k, &x) && GetDoubleFromJson(x, out);
292 }
293 
JsonValueToString(const Json::Value & json)294 std::string JsonValueToString(const Json::Value& json) {
295   Json::FastWriter w;
296   std::string value = w.write(json);
297   return value.substr(0, value.size() - 1);  // trim trailing newline
298 }
299 
300 }  // namespace rtc
301