blob: db658edb3befa1292e2694f30c66a8feec4b4c52 [file] [log] [blame]
Jorge E. Moreiraa18ff1a2019-12-17 18:20:56 -08001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "JSONObject"
19#include <utils/Log.h>
20
21#include <media/stagefright/foundation/JSONObject.h>
22
23#include <ctype.h>
24#include <media/stagefright/Utils.h>
25#include <media/stagefright/foundation/ADebug.h>
26#include <media/stagefright/MediaErrors.h>
27
28namespace android {
29
30// static
31ssize_t JSONValue::Parse(const char *data, size_t size, JSONValue *out) {
32 size_t offset = 0;
33 while (offset < size && isspace(data[offset])) {
34 ++offset;
35 }
36
37 if (offset == size) {
38 return ERROR_MALFORMED;
39 }
40
41 if (data[offset] == '[') {
42 sp<JSONArray> array = new JSONArray;
43 ++offset;
44
45 for (;;) {
46 while (offset < size && isspace(data[offset])) {
47 ++offset;
48 }
49
50 if (offset == size) {
51 return ERROR_MALFORMED;
52 }
53
54 if (data[offset] == ']') {
55 ++offset;
56 break;
57 }
58
59 JSONValue val;
60 ssize_t n = Parse(&data[offset], size - offset, &val);
61
62 if (n < 0) {
63 return n;
64 }
65
66 array->addValue(val);
67
68 offset += n;
69
70 while (offset < size && isspace(data[offset])) {
71 ++offset;
72 }
73
74 if (offset == size) {
75 return ERROR_MALFORMED;
76 }
77
78 if (data[offset] == ',') {
79 ++offset;
80 } else if (data[offset] != ']') {
81 return ERROR_MALFORMED;
82 }
83 };
84
85 out->setArray(array);
86
87 return offset;
88 } else if (data[offset] == '{') {
89 sp<JSONObject> obj = new JSONObject;
90 ++offset;
91
92 for (;;) {
93 while (offset < size && isspace(data[offset])) {
94 ++offset;
95 }
96
97 if (offset == size) {
98 return ERROR_MALFORMED;
99 }
100
101 if (data[offset] == '}') {
102 ++offset;
103 break;
104 }
105
106 JSONValue key;
107 ssize_t n = Parse(&data[offset], size - offset, &key);
108
109 if (n < 0) {
110 return n;
111 }
112
113 if (key.type() != TYPE_STRING) {
114 return ERROR_MALFORMED;
115 }
116
117 offset += n;
118
119 while (offset < size && isspace(data[offset])) {
120 ++offset;
121 }
122
123 if (offset == size || data[offset] != ':') {
124 return ERROR_MALFORMED;
125 }
126
127 ++offset;
128
129 JSONValue val;
130 n = Parse(&data[offset], size - offset, &val);
131
132 if (n < 0) {
133 return n;
134 }
135
136 std::string keyVal;
137 CHECK(key.getString(&keyVal));
138
139 obj->setValue(keyVal.c_str(), val);
140
141 offset += n;
142
143 while (offset < size && isspace(data[offset])) {
144 ++offset;
145 }
146
147 if (offset == size) {
148 return ERROR_MALFORMED;
149 }
150
151 if (data[offset] == ',') {
152 ++offset;
153 } else if (data[offset] != '}') {
154 return ERROR_MALFORMED;
155 }
156 };
157
158 out->setObject(obj);
159
160 return offset;
161 } else if (data[offset] == '"') {
162 ++offset;
163
164 std::string s;
165 bool escaped = false;
166 while (offset < size) {
167 if (escaped) {
168 char c;
169 switch (data[offset]) {
170 case '\"':
171 case '\\':
172 case '/':
173 c = data[offset];
174 break;
175 case 'b':
176 c = '\x08';
177 break;
178 case 'f':
179 c = '\x0c';
180 break;
181 case 'n':
182 c = '\x0a';
183 break;
184 case 'r':
185 c = '\x0d';
186 break;
187 case 't':
188 c = '\x09';
189 break;
190 default:
191 return ERROR_MALFORMED;
192 }
193
194 s.append(1, c);
195 ++offset;
196
197 escaped = false;
198 continue;
199 } else if (data[offset] == '\\') {
200 escaped = true;
201 ++offset;
202 continue;
203 } else if (data[offset] == '"') {
204 break;
205 }
206
207 s.append(1, data[offset++]);
208 }
209
210 if (offset == size) {
211 return ERROR_MALFORMED;
212 }
213
214 ++offset;
215 out->setString(s);
216
217 return offset;
218 } else if (isdigit(data[offset]) || data[offset] == '-') {
219 bool negate = false;
220 if (data[offset] == '-') {
221 negate = true;
222 ++offset;
223
224 if (offset == size) {
225 return ERROR_MALFORMED;
226 }
227 }
228
229 size_t firstDigitOffset = offset;
230 while (offset < size && isdigit(data[offset])) {
231 ++offset;
232 }
233
234 size_t numDigits = offset - firstDigitOffset;
235 if (numDigits > 1 && data[firstDigitOffset] == '0') {
236 // No leading zeros.
237 return ERROR_MALFORMED;
238 }
239
240 size_t firstFracDigitOffset = 0;
241 size_t numFracDigits = 0;
242
243 if (offset < size && data[offset] == '.') {
244 ++offset;
245
246 firstFracDigitOffset = offset;
247 while (offset < size && isdigit(data[offset])) {
248 ++offset;
249 }
250
251 numFracDigits = offset - firstFracDigitOffset;
252 if (numFracDigits == 0) {
253 return ERROR_MALFORMED;
254 }
255 }
256
257 bool negateExponent = false;
258 size_t firstExpDigitOffset = 0;
259 size_t numExpDigits = 0;
260
261 if (offset < size && (data[offset] == 'e' || data[offset] == 'E')) {
262 ++offset;
263
264 if (offset == size) {
265 return ERROR_MALFORMED;
266 }
267
268 if (data[offset] == '+' || data[offset] == '-') {
269 if (data[offset] == '-') {
270 negateExponent = true;
271 }
272
273 ++offset;
274 }
275
276 firstExpDigitOffset = offset;
277 while (offset < size && isdigit(data[offset])) {
278 ++offset;
279 }
280
281 numExpDigits = offset - firstExpDigitOffset;
282 if (numExpDigits == 0) {
283 return ERROR_MALFORMED;
284 }
285 }
286
287 CHECK_EQ(numFracDigits, 0u);
288 CHECK_EQ(numExpDigits, 0u);
289
290 int32_t x = 0;
291 for (size_t i = 0; i < numDigits; ++i) {
292 x *= 10;
293 x += data[firstDigitOffset + i] - '0';
294
295 CHECK_GE(x, 0);
296 }
297
298 if (negate) {
299 x = -x;
300 }
301
302 out->setInt32(x);
303
304 return offset;
305 } else if (offset + 4 <= size && !strncmp("null", &data[offset], 4)) {
306 out->unset();
307 return offset + 4;
308 } else if (offset + 4 <= size && !strncmp("true", &data[offset], 4)) {
309 out->setBoolean(true);
310 return offset + 4;
311 } else if (offset + 5 <= size && !strncmp("false", &data[offset], 5)) {
312 out->setBoolean(false);
313 return offset + 5;
314 }
315
316 return ERROR_MALFORMED;
317}
318
319JSONValue::JSONValue()
320 : mType(TYPE_NULL) {
321}
322
323JSONValue::JSONValue(const JSONValue &other)
324 : mType(TYPE_NULL) {
325 *this = other;
326}
327
328JSONValue &JSONValue::operator=(const JSONValue &other) {
329 if (&other != this) {
330 unset();
331 mType = other.mType;
332 mValue = other.mValue;
333
334 switch (mType) {
335 case TYPE_STRING:
336 mValue.mString = new std::string(*other.mValue.mString);
337 break;
338 case TYPE_OBJECT:
339 case TYPE_ARRAY:
340 mValue.mObjectOrArray->incStrong(this);
341 break;
342
343 default:
344 break;
345 }
346 }
347
348 return *this;
349}
350
351JSONValue::~JSONValue() {
352 unset();
353}
354
355JSONValue::FieldType JSONValue::type() const {
356 return mType;
357}
358
359bool JSONValue::getInt32(int32_t *value) const {
360 if (mType != TYPE_NUMBER) {
361 return false;
362 }
363
364 *value = mValue.mInt32;
365 return true;
366}
367
368bool JSONValue::getString(std::string *value) const {
369 if (mType != TYPE_STRING) {
370 return false;
371 }
372
373 *value = *mValue.mString;
374 return true;
375}
376
377bool JSONValue::getBoolean(bool *value) const {
378 if (mType != TYPE_BOOLEAN) {
379 return false;
380 }
381
382 *value = mValue.mBoolean;
383 return true;
384}
385
386bool JSONValue::getObject(sp<JSONObject> *value) const {
387 if (mType != TYPE_OBJECT) {
388 return false;
389 }
390
391 *value = static_cast<JSONObject *>(mValue.mObjectOrArray);
392 return true;
393}
394
395bool JSONValue::getArray(sp<JSONArray> *value) const {
396 if (mType != TYPE_ARRAY) {
397 return false;
398 }
399
400 *value = static_cast<JSONArray *>(mValue.mObjectOrArray);
401 return true;
402}
403
404void JSONValue::setInt32(int32_t value) {
405 unset();
406
407 mValue.mInt32 = value;
408 mType = TYPE_NUMBER;
409}
410
411void JSONValue::setString(std::string_view value) {
412 unset();
413
414 mValue.mString = new std::string(value);
415 mType = TYPE_STRING;
416}
417
418void JSONValue::setBoolean(bool value) {
419 unset();
420
421 mValue.mBoolean = value;
422 mType = TYPE_BOOLEAN;
423}
424
425void JSONValue::setObject(const sp<JSONObject> &obj) {
426 unset();
427
428 mValue.mObjectOrArray = obj.get();
429 mValue.mObjectOrArray->incStrong(this);
430
431 mType = TYPE_OBJECT;
432}
433
434void JSONValue::setArray(const sp<JSONArray> &array) {
435 unset();
436
437 mValue.mObjectOrArray = array.get();
438 mValue.mObjectOrArray->incStrong(this);
439
440 mType = TYPE_ARRAY;
441}
442
443void JSONValue::unset() {
444 switch (mType) {
445 case TYPE_STRING:
446 delete mValue.mString;
447 break;
448 case TYPE_OBJECT:
449 case TYPE_ARRAY:
450 mValue.mObjectOrArray->decStrong(this);
451 break;
452
453 default:
454 break;
455 }
456
457 mType = TYPE_NULL;
458}
459
460static void EscapeString(const char *in, size_t inSize, std::string *out) {
461 CHECK(in != out->c_str());
462 out->clear();
463
464 for (size_t i = 0; i < inSize; ++i) {
465 char c = in[i];
466 switch (c) {
467 case '\"':
468 out->append("\\\"");
469 break;
470 case '\\':
471 out->append("\\\\");
472 break;
473 case '/':
474 out->append("\\/");
475 break;
476 case '\x08':
477 out->append("\\b");
478 break;
479 case '\x0c':
480 out->append("\\f");
481 break;
482 case '\x0a':
483 out->append("\\n");
484 break;
485 case '\x0d':
486 out->append("\\r");
487 break;
488 case '\x09':
489 out->append("\\t");
490 break;
491 default:
492 out->append(1, c);
493 break;
494 }
495 }
496}
497
498std::string JSONValue::toString(size_t depth, bool indentFirstLine) const {
499 static const char kIndent[] = " ";
500
501 std::string out;
502
503 switch (mType) {
504 case TYPE_STRING:
505 {
506 std::string escaped;
507 EscapeString(
508 mValue.mString->c_str(), mValue.mString->size(), &escaped);
509
510 out.append("\"");
511 out.append(escaped);
512 out.append("\"");
513 break;
514 }
515
516 case TYPE_NUMBER:
517 {
518 out = StringPrintf("%d", mValue.mInt32);
519 break;
520 }
521
522 case TYPE_BOOLEAN:
523 {
524 out = mValue.mBoolean ? "true" : "false";
525 break;
526 }
527
528 case TYPE_NULL:
529 {
530 out = "null";
531 break;
532 }
533
534 case TYPE_OBJECT:
535 case TYPE_ARRAY:
536 {
537 out = (mType == TYPE_OBJECT) ? "{\n" : "[\n";
538 out.append(mValue.mObjectOrArray->internalToString(depth + 1, true));
539 out.append("\n");
540 out.append(kIndent, 2 * depth);
541 out.append(mType == TYPE_OBJECT ? "}" : "]");
542 break;
543 }
544
545 default:
546 TRESPASS();
547 }
548
549 if (indentFirstLine) {
550 out.insert(0, kIndent, 2 * depth);
551 }
552
553 return out;
554}
555
556////////////////////////////////////////////////////////////////////////////////
557
558// static
559sp<JSONCompound> JSONCompound::Parse(const char *data, size_t size) {
560 JSONValue value;
561 ssize_t result = JSONValue::Parse(data, size, &value);
562
563 if (result < 0) {
564 return NULL;
565 }
566
567 sp<JSONObject> obj;
568 if (value.getObject(&obj)) {
569 return obj;
570 }
571
572 sp<JSONArray> array;
573 if (value.getArray(&array)) {
574 return array;
575 }
576
577 return NULL;
578}
579
580std::string JSONCompound::toString(size_t depth, bool indentFirstLine) const {
581 JSONValue val;
582 if (isObject()) {
583 val.setObject((JSONObject *)this);
584 } else {
585 val.setArray((JSONArray *)this);
586 }
587
588 return val.toString(depth, indentFirstLine);
589}
590
591////////////////////////////////////////////////////////////////////////////////
592
593JSONObject::JSONObject() {}
594JSONObject::~JSONObject() {}
595
596bool JSONObject::isObject() const {
597 return true;
598}
599
600bool JSONObject::getValue(const char *key, JSONValue *value) const {
601 auto it = mValues.find(key);
602
603 if (it == mValues.end()) {
604 return false;
605 }
606
607 *value = it->second;
608
609 return true;
610}
611
612void JSONObject::setValue(const char *key, const JSONValue &value) {
613 mValues[std::string(key)] = value;
614}
615
616void JSONObject::remove(const char *key) {
617 mValues.erase(key);
618}
619
620std::string JSONObject::internalToString(
621 size_t depth, bool /* indentFirstLine */) const {
622 static const char kIndent[] = " ";
623
624 std::string out;
625 for (auto it = mValues.begin(); it != mValues.end();) {
626 const std::string &key = it->first;
627 std::string escapedKey;
628 EscapeString(key.c_str(), key.size(), &escapedKey);
629
630 out.append(kIndent, 2 * depth);
631 out.append("\"");
632 out.append(escapedKey);
633 out.append("\": ");
634
635 out.append(it->second.toString(depth + 1, false));
636
637 ++it;
638 if (it != mValues.end()) {
639 out.append(",\n");
640 }
641 }
642
643 return out;
644}
645
646////////////////////////////////////////////////////////////////////////////////
647
648JSONArray::JSONArray() {}
649
650JSONArray::~JSONArray() {}
651
652bool JSONArray::isObject() const {
653 return false;
654}
655
656size_t JSONArray::size() const {
657 return mValues.size();
658}
659
660bool JSONArray::getValue(size_t key, JSONValue *value) const {
661 if (key >= mValues.size()) {
662 return false;
663 }
664
665 *value = mValues[key];
666
667 return true;
668}
669
670void JSONArray::addValue(const JSONValue &value) {
671 mValues.push_back(value);
672}
673
674std::string JSONArray::internalToString(
675 size_t depth, bool /* indentFirstLine */) const {
676 std::string out;
677 for (size_t i = 0; i < mValues.size(); ++i) {
678 out.append(mValues[i].toString(depth));
679
680 if (i + 1 < mValues.size()) {
681 out.append(",\n");
682 }
683 }
684
685 return out;
686}
687
688////////////////////////////////////////////////////////////////////////////////
689
690} // namespace android
691