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