1 /*
2 * Copyright (C) 2015 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 "JSONObject.h"
22
23 #include <ctype.h>
24 #include <math.h>
25 #include <media/stagefright/foundation/ADebug.h>
26 #include <media/stagefright/foundation/AString.h>
27 #include <media/stagefright/MediaErrors.h>
28
29 namespace android {
30
31 // Returns ERROR_MALFORMED if the value overflows a signed int, returns
32 // 0 otherwise.
33 // This method will assert if it is asked to parse a character which is not
34 // a digit.
parseInt32(const char * data,size_t numDigits,int32_t * out)35 static ssize_t parseInt32(const char *data, size_t numDigits, int32_t *out) {
36 int32_t x = 0;
37 for (size_t i = 0; i < numDigits; ++i) {
38 int32_t old_x = x;
39 x *= 10;
40 x += data[i] - '0';
41
42 CHECK(isdigit(data[i]));
43
44 if (x < old_x) {
45 // We've overflowed.
46 return ERROR_MALFORMED;
47 }
48 }
49
50 *out = x;
51 return 0;
52 }
53
54 // static
Parse(const char * data,size_t size,JSONValue * out)55 ssize_t JSONValue::Parse(const char *data, size_t size, JSONValue *out) {
56 size_t offset = 0;
57 while (offset < size && isspace(data[offset])) {
58 ++offset;
59 }
60
61 if (offset == size) {
62 return ERROR_MALFORMED;
63 }
64
65 if (data[offset] == '[') {
66 sp<JSONArray> array = new JSONArray;
67 ++offset;
68
69 for (;;) {
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 break;
81 }
82
83 JSONValue val;
84 ssize_t n = Parse(&data[offset], size - offset, &val);
85
86 if (n < 0) {
87 return n;
88 }
89
90 array->addValue(val);
91
92 offset += n;
93
94 while (offset < size && isspace(data[offset])) {
95 ++offset;
96 }
97
98 if (offset == size) {
99 return ERROR_MALFORMED;
100 }
101
102 if (data[offset] == ',') {
103 ++offset;
104 } else if (data[offset] != ']') {
105 return ERROR_MALFORMED;
106 }
107 };
108
109 out->setArray(array);
110
111 return offset;
112 } else if (data[offset] == '{') {
113 sp<JSONObject> obj = new JSONObject;
114 ++offset;
115
116 for (;;) {
117 while (offset < size && isspace(data[offset])) {
118 ++offset;
119 }
120
121 if (offset == size) {
122 return ERROR_MALFORMED;
123 }
124
125 if (data[offset] == '}') {
126 ++offset;
127 break;
128 }
129
130 JSONValue key;
131 ssize_t n = Parse(&data[offset], size - offset, &key);
132
133 if (n < 0) {
134 return n;
135 }
136
137 if (key.type() != TYPE_STRING) {
138 return ERROR_MALFORMED;
139 }
140
141 offset += n;
142
143 while (offset < size && isspace(data[offset])) {
144 ++offset;
145 }
146
147 if (offset == size || data[offset] != ':') {
148 return ERROR_MALFORMED;
149 }
150
151 ++offset;
152
153 JSONValue val;
154 n = Parse(&data[offset], size - offset, &val);
155
156 if (n < 0) {
157 return n;
158 }
159
160 AString keyVal;
161 CHECK(key.getString(&keyVal));
162
163 obj->setValue(keyVal.c_str(), val);
164
165 offset += n;
166
167 while (offset < size && isspace(data[offset])) {
168 ++offset;
169 }
170
171 if (offset == size) {
172 return ERROR_MALFORMED;
173 }
174
175 if (data[offset] == ',') {
176 ++offset;
177 } else if (data[offset] != '}') {
178 return ERROR_MALFORMED;
179 }
180 };
181
182 out->setObject(obj);
183
184 return offset;
185 } else if (data[offset] == '"') {
186 ++offset;
187
188 AString s;
189 bool escaped = false;
190 while (offset < size) {
191 if (escaped) {
192 char c;
193 switch (data[offset]) {
194 case '\"':
195 case '\\':
196 case '/':
197 c = data[offset];
198 break;
199 case 'b':
200 c = '\x08';
201 break;
202 case 'f':
203 c = '\x0c';
204 break;
205 case 'n':
206 c = '\x0a';
207 break;
208 case 'r':
209 c = '\x0d';
210 break;
211 case 't':
212 c = '\x09';
213 break;
214 default:
215 return ERROR_MALFORMED;
216 }
217
218 s.append(c);
219 ++offset;
220
221 escaped = false;
222 } else if (data[offset] == '\\') {
223 escaped = true;
224 } else if (data[offset] == '"') {
225 break;
226 }
227
228 s.append(data[offset++]);
229 }
230
231 if (offset == size) {
232 return ERROR_MALFORMED;
233 }
234
235 ++offset;
236 out->setString(s);
237
238 return offset;
239 } else if (isdigit(data[offset]) || data[offset] == '-') {
240 bool negate = false;
241 if (data[offset] == '-') {
242 negate = true;
243 ++offset;
244
245 if (offset == size) {
246 return ERROR_MALFORMED;
247 }
248 }
249
250 size_t firstDigitOffset = offset;
251 while (offset < size && isdigit(data[offset])) {
252 ++offset;
253 }
254
255 size_t numDigits = offset - firstDigitOffset;
256 if (numDigits > 1 && data[firstDigitOffset] == '0') {
257 // No leading zeros.
258 return ERROR_MALFORMED;
259 }
260
261 size_t firstFracDigitOffset = 0;
262 size_t numFracDigits = 0;
263
264 if (offset < size && data[offset] == '.') {
265 ++offset;
266
267 firstFracDigitOffset = offset;
268 while (offset < size && isdigit(data[offset])) {
269 ++offset;
270 }
271
272 numFracDigits = offset - firstFracDigitOffset;
273 if (numFracDigits == 0) {
274 return ERROR_MALFORMED;
275 }
276 }
277
278 bool negateExponent = false;
279 size_t firstExpDigitOffset = 0;
280 size_t numExpDigits = 0;
281
282 if (offset < size && (data[offset] == 'e' || data[offset] == 'E')) {
283 ++offset;
284
285 if (offset == size) {
286 return ERROR_MALFORMED;
287 }
288
289 if (data[offset] == '+' || data[offset] == '-') {
290 if (data[offset] == '-') {
291 negateExponent = true;
292 }
293
294 ++offset;
295 }
296
297 firstExpDigitOffset = offset;
298 while (offset < size && isdigit(data[offset])) {
299 ++offset;
300 }
301
302 numExpDigits = offset - firstExpDigitOffset;
303 if (numExpDigits == 0) {
304 return ERROR_MALFORMED;
305 }
306 }
307
308 if (numFracDigits == 0 && numExpDigits == 0) {
309 int32_t x;
310 if (parseInt32(&data[firstDigitOffset], numDigits, &x) != 0) {
311 return ERROR_MALFORMED;
312 }
313
314 out->setInt32(negate ? -x : x);
315 } else {
316 int32_t mantissa;
317 if (parseInt32(&data[firstDigitOffset], numDigits, &mantissa) != 0) {
318 return ERROR_MALFORMED;
319 }
320
321 int32_t fraction;
322 if (parseInt32(&data[firstFracDigitOffset], numFracDigits, &fraction) != 0) {
323 return ERROR_MALFORMED;
324 }
325
326 int32_t exponent;
327 if (parseInt32(&data[firstExpDigitOffset], numExpDigits, &exponent) != 0) {
328 return ERROR_MALFORMED;
329 }
330
331 if (negateExponent) {
332 exponent = -exponent;
333 }
334
335 float x = (float)mantissa;
336 x += (float)fraction * powf(10.0f, exponent - (int32_t)numFracDigits);
337
338 out->setFloat(negate ? -x : x);
339 }
340
341 return offset;
342 } else if (offset + 4 <= size && !strncmp("null", &data[offset], 4)) {
343 out->unset();
344 return offset + 4;
345 } else if (offset + 4 <= size && !strncmp("true", &data[offset], 4)) {
346 out->setBoolean(true);
347 return offset + 4;
348 } else if (offset + 5 <= size && !strncmp("false", &data[offset], 5)) {
349 out->setBoolean(false);
350 return offset + 5;
351 }
352
353 return ERROR_MALFORMED;
354 }
355
JSONValue()356 JSONValue::JSONValue()
357 : mType(TYPE_NULL) {
358 }
359
JSONValue(const JSONValue & other)360 JSONValue::JSONValue(const JSONValue &other)
361 : mType(TYPE_NULL) {
362 *this = other;
363 }
364
operator =(const JSONValue & other)365 JSONValue &JSONValue::operator=(const JSONValue &other) {
366 if (&other != this) {
367 unset();
368 mType = other.mType;
369 mValue = other.mValue;
370
371 switch (mType) {
372 case TYPE_STRING:
373 mValue.mString = new AString(*other.mValue.mString);
374 break;
375 case TYPE_OBJECT:
376 case TYPE_ARRAY:
377 mValue.mObjectOrArray->incStrong(this /* id */);
378 break;
379
380 default:
381 break;
382 }
383 }
384
385 return *this;
386 }
387
~JSONValue()388 JSONValue::~JSONValue() {
389 unset();
390 }
391
type() const392 JSONValue::FieldType JSONValue::type() const {
393 return mType;
394 }
395
getInt32(int32_t * value) const396 bool JSONValue::getInt32(int32_t *value) const {
397 if (mType != TYPE_INT32) {
398 return false;
399 }
400
401 *value = mValue.mInt32;
402 return true;
403 }
404
getFloat(float * value) const405 bool JSONValue::getFloat(float *value) const {
406 switch (mType) {
407 case TYPE_INT32:
408 {
409 *value = mValue.mInt32;
410 break;
411 }
412
413 case TYPE_FLOAT:
414 {
415 *value = mValue.mFloat;
416 break;
417 }
418
419 default:
420 return false;
421 }
422
423 return true;
424 }
425
getString(AString * value) const426 bool JSONValue::getString(AString *value) const {
427 if (mType != TYPE_STRING) {
428 return false;
429 }
430
431 *value = *mValue.mString;
432 return true;
433 }
434
getBoolean(bool * value) const435 bool JSONValue::getBoolean(bool *value) const {
436 if (mType != TYPE_BOOLEAN) {
437 return false;
438 }
439
440 *value = mValue.mBoolean;
441 return true;
442 }
443
getObject(sp<JSONObject> * value) const444 bool JSONValue::getObject(sp<JSONObject> *value) const {
445 if (mType != TYPE_OBJECT) {
446 return false;
447 }
448
449 *value = static_cast<JSONObject *>(mValue.mObjectOrArray);
450 return true;
451 }
452
getArray(sp<JSONArray> * value) const453 bool JSONValue::getArray(sp<JSONArray> *value) const {
454 if (mType != TYPE_ARRAY) {
455 return false;
456 }
457
458 *value = static_cast<JSONArray *>(mValue.mObjectOrArray);
459 return true;
460 }
461
setInt32(int32_t value)462 void JSONValue::setInt32(int32_t value) {
463 unset();
464
465 mValue.mInt32 = value;
466 mType = TYPE_INT32;
467 }
468
setFloat(float value)469 void JSONValue::setFloat(float value) {
470 unset();
471
472 mValue.mFloat = value;
473 mType = TYPE_FLOAT;
474 }
475
setString(const AString & value)476 void JSONValue::setString(const AString &value) {
477 unset();
478
479 mValue.mString = new AString(value);
480 mType = TYPE_STRING;
481 }
482
setBoolean(bool value)483 void JSONValue::setBoolean(bool value) {
484 unset();
485
486 mValue.mBoolean = value;
487 mType = TYPE_BOOLEAN;
488 }
489
setObject(const sp<JSONObject> & obj)490 void JSONValue::setObject(const sp<JSONObject> &obj) {
491 unset();
492
493 mValue.mObjectOrArray = obj.get();
494 mValue.mObjectOrArray->incStrong(this /* id */);
495
496 mType = TYPE_OBJECT;
497 }
498
setArray(const sp<JSONArray> & array)499 void JSONValue::setArray(const sp<JSONArray> &array) {
500 unset();
501
502 mValue.mObjectOrArray = array.get();
503 mValue.mObjectOrArray->incStrong(this /* id */);
504
505 mType = TYPE_ARRAY;
506 }
507
unset()508 void JSONValue::unset() {
509 switch (mType) {
510 case TYPE_STRING:
511 delete mValue.mString;
512 break;
513 case TYPE_OBJECT:
514 case TYPE_ARRAY:
515 mValue.mObjectOrArray->decStrong(this /* id */);
516 break;
517
518 default:
519 break;
520 }
521
522 mType = TYPE_NULL;
523 }
524
EscapeString(const char * in,size_t inSize,AString * out)525 static void EscapeString(const char *in, size_t inSize, AString *out) {
526 CHECK(in != out->c_str());
527 out->clear();
528
529 for (size_t i = 0; i < inSize; ++i) {
530 char c = in[i];
531 switch (c) {
532 case '\"':
533 out->append("\\\"");
534 break;
535 case '\\':
536 out->append("\\\\");
537 break;
538 case '/':
539 out->append("\\/");
540 break;
541 case '\x08':
542 out->append("\\b");
543 break;
544 case '\x0c':
545 out->append("\\f");
546 break;
547 case '\x0a':
548 out->append("\\n");
549 break;
550 case '\x0d':
551 out->append("\\r");
552 break;
553 case '\x09':
554 out->append("\\t");
555 break;
556 default:
557 out->append(c);
558 break;
559 }
560 }
561 }
562
toString(size_t depth,bool indentFirstLine) const563 AString JSONValue::toString(size_t depth, bool indentFirstLine) const {
564 static const char kIndent[] = " ";
565
566 AString out;
567
568 switch (mType) {
569 case TYPE_STRING:
570 {
571 AString escaped;
572 EscapeString(
573 mValue.mString->c_str(), mValue.mString->size(), &escaped);
574
575 out.append("\"");
576 out.append(escaped);
577 out.append("\"");
578 break;
579 }
580
581 case TYPE_INT32:
582 {
583 out = AStringPrintf("%d", mValue.mInt32);
584 break;
585 }
586
587 case TYPE_FLOAT:
588 {
589 out = AStringPrintf("%f", mValue.mFloat);
590 break;
591 }
592
593 case TYPE_BOOLEAN:
594 {
595 out = mValue.mBoolean ? "true" : "false";
596 break;
597 }
598
599 case TYPE_NULL:
600 {
601 out = "null";
602 break;
603 }
604
605 case TYPE_OBJECT:
606 case TYPE_ARRAY:
607 {
608 out = (mType == TYPE_OBJECT) ? "{\n" : "[\n";
609 out.append(mValue.mObjectOrArray->internalToString(depth + 1));
610 out.append("\n");
611 out.append(kIndent, 2 * depth);
612 out.append(mType == TYPE_OBJECT ? "}" : "]");
613 break;
614 }
615
616 default:
617 TRESPASS();
618 }
619
620 if (indentFirstLine) {
621 out.insert(kIndent, 2 * depth, 0);
622 }
623
624 return out;
625 }
626
627 ////////////////////////////////////////////////////////////////////////////////
628
629 // static
Parse(const char * data,size_t size)630 sp<JSONCompound> JSONCompound::Parse(const char *data, size_t size) {
631 JSONValue value;
632 ssize_t result = JSONValue::Parse(data, size, &value);
633
634 if (result < 0) {
635 return NULL;
636 }
637
638 sp<JSONObject> obj;
639 if (value.getObject(&obj)) {
640 return obj;
641 }
642
643 sp<JSONArray> array;
644 if (value.getArray(&array)) {
645 return array;
646 }
647
648 return NULL;
649 }
650
toString(size_t depth,bool indentFirstLine) const651 AString JSONCompound::toString(size_t depth, bool indentFirstLine) const {
652 JSONValue val;
653 if (isObject()) {
654 val.setObject((JSONObject *)this);
655 } else {
656 val.setArray((JSONArray *)this);
657 }
658
659 return val.toString(depth, indentFirstLine);
660 }
661
662 ////////////////////////////////////////////////////////////////////////////////
663
JSONObject()664 JSONObject::JSONObject() {}
~JSONObject()665 JSONObject::~JSONObject() {}
666
isObject() const667 bool JSONObject::isObject() const {
668 return true;
669 }
670
getValue(const char * key,JSONValue * value) const671 bool JSONObject::getValue(const char *key, JSONValue *value) const {
672 ssize_t index = mValues.indexOfKey(key);
673 if (index < 0) {
674 return false;
675 }
676
677 *value = mValues.valueAt(index);
678
679 return true;
680 }
681
setValue(const char * key,const JSONValue & value)682 void JSONObject::setValue(const char *key, const JSONValue &value) {
683 mValues.add(AString(key), value);
684 }
685
internalToString(size_t depth) const686 AString JSONObject::internalToString(size_t depth) const {
687 static const char kIndent[] = " ";
688
689 AString out;
690 for (size_t i = 0; i < mValues.size(); ++i) {
691 AString key = mValues.keyAt(i);
692 AString escapedKey;
693 EscapeString(key.c_str(), key.size(), &escapedKey);
694
695 out.append(kIndent, 2 * depth);
696 out.append("\"");
697 out.append(escapedKey);
698 out.append("\": ");
699
700 out.append(mValues.valueAt(i).toString(depth + 1, false));
701
702 if (i + 1 < mValues.size()) {
703 out.append(",\n");
704 }
705 }
706
707 return out;
708 }
709
710 ////////////////////////////////////////////////////////////////////////////////
711
JSONArray()712 JSONArray::JSONArray() {}
713
~JSONArray()714 JSONArray::~JSONArray() {}
715
isObject() const716 bool JSONArray::isObject() const {
717 return false;
718 }
719
size() const720 size_t JSONArray::size() const {
721 return mValues.size();
722 }
723
getValue(size_t key,JSONValue * value) const724 bool JSONArray::getValue(size_t key, JSONValue *value) const {
725 if (key >= mValues.size()) {
726 return false;
727 }
728
729 *value = mValues.itemAt(key);
730
731 return true;
732 }
733
addValue(const JSONValue & value)734 void JSONArray::addValue(const JSONValue &value) {
735 mValues.push_back(value);
736 }
737
internalToString(size_t depth) const738 AString JSONArray::internalToString(size_t depth) const {
739 AString out;
740 for (size_t i = 0; i < mValues.size(); ++i) {
741 out.append(mValues.itemAt(i).toString(depth));
742
743 if (i + 1 < mValues.size()) {
744 out.append(",\n");
745 }
746 }
747
748 return out;
749 }
750
751 ////////////////////////////////////////////////////////////////////////////////
752
753 } // namespace android
754
755