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