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