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 #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.
     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
     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 
    352 JSONValue::JSONValue()
    353     : mType(TYPE_NULL) {
    354 }
    355 
    356 JSONValue::JSONValue(const JSONValue &other)
    357     : mType(TYPE_NULL) {
    358     *this = other;
    359 }
    360 
    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 
    384 JSONValue::~JSONValue() {
    385     unset();
    386 }
    387 
    388 JSONValue::FieldType JSONValue::type() const {
    389     return mType;
    390 }
    391 
    392 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 
    401 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 
    422 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 
    431 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 
    440 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 
    449 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 
    458 void JSONValue::setInt32(int32_t value) {
    459     unset();
    460 
    461     mValue.mInt32 = value;
    462     mType = TYPE_INT32;
    463 }
    464 
    465 void JSONValue::setFloat(float value) {
    466     unset();
    467 
    468     mValue.mFloat = value;
    469     mType = TYPE_FLOAT;
    470 }
    471 
    472 void JSONValue::setString(const AString &value) {
    473     unset();
    474 
    475     mValue.mString = new AString(value);
    476     mType = TYPE_STRING;
    477 }
    478 
    479 void JSONValue::setBoolean(bool value) {
    480     unset();
    481 
    482     mValue.mBoolean = value;
    483     mType = TYPE_BOOLEAN;
    484 }
    485 
    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 
    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 
    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 
    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 
    559 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
    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 
    647 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 
    660 JSONObject::JSONObject() {}
    661 JSONObject::~JSONObject() {}
    662 
    663 bool JSONObject::isObject() const {
    664     return true;
    665 }
    666 
    667 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 
    678 void JSONObject::setValue(const char *key, const JSONValue &value) {
    679     mValues.add(AString(key), value);
    680 }
    681 
    682 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 
    708 JSONArray::JSONArray() {}
    709 
    710 JSONArray::~JSONArray() {}
    711 
    712 bool JSONArray::isObject() const {
    713     return false;
    714 }
    715 
    716 size_t JSONArray::size() const {
    717     return mValues.size();
    718 }
    719 
    720 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 
    730 void JSONArray::addValue(const JSONValue &value) {
    731     mValues.push_back(value);
    732 }
    733 
    734 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