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