blob: 8a544a0c0d2033b368c9367e532a2a15bacb03b9 [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001/*
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
Sam Zackrissonb45bdb52018-10-02 16:25:59 +020011#include "rtc_base/strings/json.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000012
13#include <errno.h>
14#include <limits.h>
15#include <stdlib.h>
16
Steve Anton10542f22019-01-11 09:11:00 -080017#include "rtc_base/string_encode.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000018
Thiago Farinacb76b892015-04-02 09:59:15 +000019namespace rtc {
20
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000021bool GetStringFromJson(const Json::Value& in, std::string* out) {
22 if (!in.isString()) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000023 if (in.isBool()) {
Jonas Olsson941a07c2018-09-13 10:07:07 +020024 *out = rtc::ToString(in.asBool());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000025 } else if (in.isInt()) {
Jonas Olsson941a07c2018-09-13 10:07:07 +020026 *out = rtc::ToString(in.asInt());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000027 } else if (in.isUInt()) {
Jonas Olsson941a07c2018-09-13 10:07:07 +020028 *out = rtc::ToString(in.asUInt());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000029 } else if (in.isDouble()) {
Jonas Olsson941a07c2018-09-13 10:07:07 +020030 *out = rtc::ToString(in.asDouble());
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000031 } else {
32 return false;
33 }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000034 } 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
Yves Gerey665174f2018-06-19 15:03:05 +020053 ret = (end_ptr != c_str && *end_ptr == '\0' && !errno && val >= INT_MIN &&
54 val <= INT_MAX);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000055 *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
Yves Gerey665174f2018-06-19 15:03:05 +020073 ret = (end_ptr != c_str && *end_ptr == '\0' && !errno && val <= UINT_MAX);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000074 *out = val;
75 }
76 return ret;
77}
78
79bool 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
100bool 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
119namespace {
Yves Gerey665174f2018-06-19 15:03:05 +0200120template <typename T>
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000121bool JsonArrayToVector(const Json::Value& value,
122 bool (*getter)(const Json::Value& in, T* out),
Yves Gerey665174f2018-06-19 15:03:05 +0200123 std::vector<T>* vec) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000124 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
140bool GetValueFromJson(const Json::Value& in, Json::Value* out) {
141 *out = in;
142 return true;
143}
144} // unnamed namespace
145
146bool JsonArrayToValueVector(const Json::Value& in,
147 std::vector<Json::Value>* out) {
148 return JsonArrayToVector(in, GetValueFromJson, out);
149}
150
Yves Gerey665174f2018-06-19 15:03:05 +0200151bool JsonArrayToIntVector(const Json::Value& in, std::vector<int>* out) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000152 return JsonArrayToVector(in, GetIntFromJson, out);
153}
154
155bool JsonArrayToUIntVector(const Json::Value& in,
156 std::vector<unsigned int>* out) {
157 return JsonArrayToVector(in, GetUIntFromJson, out);
158}
159
160bool JsonArrayToStringVector(const Json::Value& in,
161 std::vector<std::string>* out) {
162 return JsonArrayToVector(in, GetStringFromJson, out);
163}
164
Yves Gerey665174f2018-06-19 15:03:05 +0200165bool JsonArrayToBoolVector(const Json::Value& in, std::vector<bool>* out) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000166 return JsonArrayToVector(in, GetBoolFromJson, out);
167}
168
Yves Gerey665174f2018-06-19 15:03:05 +0200169bool JsonArrayToDoubleVector(const Json::Value& in, std::vector<double>* out) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000170 return JsonArrayToVector(in, GetDoubleFromJson, out);
171}
172
173namespace {
Yves Gerey665174f2018-06-19 15:03:05 +0200174template <typename T>
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000175Json::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
184Json::Value ValueVectorToJsonArray(const std::vector<Json::Value>& in) {
185 return VectorToJsonArray(in);
186}
187
188Json::Value IntVectorToJsonArray(const std::vector<int>& in) {
189 return VectorToJsonArray(in);
190}
191
192Json::Value UIntVectorToJsonArray(const std::vector<unsigned int>& in) {
193 return VectorToJsonArray(in);
194}
195
196Json::Value StringVectorToJsonArray(const std::vector<std::string>& in) {
197 return VectorToJsonArray(in);
198}
199
200Json::Value BoolVectorToJsonArray(const std::vector<bool>& in) {
201 return VectorToJsonArray(in);
202}
203
204Json::Value DoubleVectorToJsonArray(const std::vector<double>& in) {
205 return VectorToJsonArray(in);
206}
207
Yves Gerey665174f2018-06-19 15:03:05 +0200208bool GetValueFromJsonArray(const Json::Value& in, size_t n, Json::Value* out) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000209 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
Yves Gerey665174f2018-06-19 15:03:05 +0200217bool GetIntFromJsonArray(const Json::Value& in, size_t n, int* out) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000218 Json::Value x;
219 return GetValueFromJsonArray(in, n, &x) && GetIntFromJson(x, out);
220}
221
Yves Gerey665174f2018-06-19 15:03:05 +0200222bool GetUIntFromJsonArray(const Json::Value& in, size_t n, unsigned int* out) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000223 Json::Value x;
224 return GetValueFromJsonArray(in, n, &x) && GetUIntFromJson(x, out);
225}
226
Yves Gerey665174f2018-06-19 15:03:05 +0200227bool GetStringFromJsonArray(const Json::Value& in, size_t n, std::string* out) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000228 Json::Value x;
229 return GetValueFromJsonArray(in, n, &x) && GetStringFromJson(x, out);
230}
231
Yves Gerey665174f2018-06-19 15:03:05 +0200232bool GetBoolFromJsonArray(const Json::Value& in, size_t n, bool* out) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000233 Json::Value x;
234 return GetValueFromJsonArray(in, n, &x) && GetBoolFromJson(x, out);
235}
236
Yves Gerey665174f2018-06-19 15:03:05 +0200237bool GetDoubleFromJsonArray(const Json::Value& in, size_t n, double* out) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000238 Json::Value x;
239 return GetValueFromJsonArray(in, n, &x) && GetDoubleFromJson(x, out);
240}
241
Yves Gerey665174f2018-06-19 15:03:05 +0200242bool GetValueFromJsonObject(const Json::Value& in,
243 const std::string& k,
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000244 Json::Value* out) {
245 if (!in.isObject() || !in.isMember(k)) {
246 return false;
247 }
248
249 *out = in[k];
250 return true;
251}
252
Yves Gerey665174f2018-06-19 15:03:05 +0200253bool GetIntFromJsonObject(const Json::Value& in,
254 const std::string& k,
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000255 int* out) {
256 Json::Value x;
257 return GetValueFromJsonObject(in, k, &x) && GetIntFromJson(x, out);
258}
259
Yves Gerey665174f2018-06-19 15:03:05 +0200260bool GetUIntFromJsonObject(const Json::Value& in,
261 const std::string& k,
262 unsigned int* out) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000263 Json::Value x;
264 return GetValueFromJsonObject(in, k, &x) && GetUIntFromJson(x, out);
265}
266
Yves Gerey665174f2018-06-19 15:03:05 +0200267bool GetStringFromJsonObject(const Json::Value& in,
268 const std::string& k,
269 std::string* out) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000270 Json::Value x;
271 return GetValueFromJsonObject(in, k, &x) && GetStringFromJson(x, out);
272}
273
Yves Gerey665174f2018-06-19 15:03:05 +0200274bool GetBoolFromJsonObject(const Json::Value& in,
275 const std::string& k,
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000276 bool* out) {
277 Json::Value x;
278 return GetValueFromJsonObject(in, k, &x) && GetBoolFromJson(x, out);
279}
280
Yves Gerey665174f2018-06-19 15:03:05 +0200281bool GetDoubleFromJsonObject(const Json::Value& in,
282 const std::string& k,
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000283 double* out) {
284 Json::Value x;
285 return GetValueFromJsonObject(in, k, &x) && GetDoubleFromJson(x, out);
286}
287
288std::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}
Thiago Farinacb76b892015-04-02 09:59:15 +0000293
294} // namespace rtc