Home | History | Annotate | Download | only in common
      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.
     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
     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 
    356 JSONValue::JSONValue()
    357     : mType(TYPE_NULL) {
    358 }
    359 
    360 JSONValue::JSONValue(const JSONValue &other)
    361     : mType(TYPE_NULL) {
    362     *this = other;
    363 }
    364 
    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 
    388 JSONValue::~JSONValue() {
    389     unset();
    390 }
    391 
    392 JSONValue::FieldType JSONValue::type() const {
    393     return mType;
    394 }
    395 
    396 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 
    405 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 
    426 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 
    435 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 
    444 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 
    453 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 
    462 void JSONValue::setInt32(int32_t value) {
    463     unset();
    464 
    465     mValue.mInt32 = value;
    466     mType = TYPE_INT32;
    467 }
    468 
    469 void JSONValue::setFloat(float value) {
    470     unset();
    471 
    472     mValue.mFloat = value;
    473     mType = TYPE_FLOAT;
    474 }
    475 
    476 void JSONValue::setString(const AString &value) {
    477     unset();
    478 
    479     mValue.mString = new AString(value);
    480     mType = TYPE_STRING;
    481 }
    482 
    483 void JSONValue::setBoolean(bool value) {
    484     unset();
    485 
    486     mValue.mBoolean = value;
    487     mType = TYPE_BOOLEAN;
    488 }
    489 
    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 
    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 
    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 
    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 
    563 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
    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 
    651 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 
    664 JSONObject::JSONObject() {}
    665 JSONObject::~JSONObject() {}
    666 
    667 bool JSONObject::isObject() const {
    668     return true;
    669 }
    670 
    671 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 
    682 void JSONObject::setValue(const char *key, const JSONValue &value) {
    683     mValues.add(AString(key), value);
    684 }
    685 
    686 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 
    712 JSONArray::JSONArray() {}
    713 
    714 JSONArray::~JSONArray() {}
    715 
    716 bool JSONArray::isObject() const {
    717     return false;
    718 }
    719 
    720 size_t JSONArray::size() const {
    721     return mValues.size();
    722 }
    723 
    724 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 
    734 void JSONArray::addValue(const JSONValue &value) {
    735     mValues.push_back(value);
    736 }
    737 
    738 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