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