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