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