1 /* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef ECMASCRIPT_BASE_JSON_PARSE_INL_H 17 #define ECMASCRIPT_BASE_JSON_PARSE_INL_H 18 19 #include "ecmascript/base/json_parser.h" 20 #include "ecmascript/base/builtins_base.h" 21 #include "ecmascript/base/number_helper.h" 22 #include "ecmascript/base/string_helper.h" 23 #include "ecmascript/base/utf_helper.h" 24 #include "ecmascript/ecma_string-inl.h" 25 #include "ecmascript/ecma_string.h" 26 #include "ecmascript/js_array.h" 27 #include "ecmascript/js_function.h" 28 #include "ecmascript/js_handle.h" 29 #include "ecmascript/global_env.h" 30 #include "ecmascript/js_tagged_value.h" 31 #include "ecmascript/object_factory.h" 32 #include "ecmascript/object_fast_operator-inl.h" 33 34 namespace panda::ecmascript::base { 35 constexpr unsigned int UNICODE_DIGIT_LENGTH = 4; 36 constexpr unsigned int NUMBER_TEN = 10; 37 constexpr unsigned int NUMBER_SIXTEEN = 16; 38 39 constexpr unsigned char CODE_SPACE = 0x20; 40 constexpr unsigned char ASCII_END = 0X7F; 41 enum class Tokens : uint8_t { 42 // six structural tokens 43 OBJECT = 0, 44 ARRAY, 45 NUMBER, 46 STRING, 47 LITERAL_TRUE, 48 LITERAL_FALSE, 49 LITERAL_NULL, 50 TOKEN_ILLEGAL, 51 }; 52 53 template<typename T> 54 class JsonParser { 55 public: 56 using Text = const T *; 57 explicit JsonParser() = default; JsonParser(JSThread * thread)58 explicit JsonParser(JSThread *thread) : thread_(thread) {} 59 ~JsonParser() = default; 60 NO_COPY_SEMANTIC(JsonParser); 61 NO_MOVE_SEMANTIC(JsonParser); Parse(Text begin,Text end)62 JSHandle<JSTaggedValue> Parse(Text begin, Text end) 63 { 64 end_ = (end == begin) ? end : end - 1; 65 current_ = begin; 66 67 auto vm = thread_->GetEcmaVM(); 68 factory_ = vm->GetFactory(); 69 env_ = *vm->GetGlobalEnv(); 70 71 SkipEndWhiteSpace(); 72 range_ = end_; 73 JSTaggedValue result = ParseJSONText<false>(); 74 return JSHandle<JSTaggedValue>(thread_, result); 75 } 76 ParseUtf8(EcmaString * str)77 JSHandle<JSTaggedValue> ParseUtf8(EcmaString *str) 78 { 79 ASSERT(str != nullptr); 80 isAsciiString_ = true; 81 uint32_t len = EcmaStringAccessor(str).GetLength(); 82 ASSERT(len != UINT32_MAX); 83 CVector<T> buf(len + 1); // 1 means add '\0' in the end of buf 84 EcmaStringAccessor(str).WriteToFlatUtf8(buf.data(), len + 1); 85 Text begin = buf.data(); 86 return Parse(begin, begin + len); 87 } 88 ParseUtf16(EcmaString * str)89 JSHandle<JSTaggedValue> ParseUtf16(EcmaString *str) 90 { 91 ASSERT(str != nullptr); 92 uint32_t len = EcmaStringAccessor(str).GetLength(); 93 CVector<T> buf(len); 94 EcmaStringAccessor(str).WriteToFlatUtf16(buf.data(), len); 95 Text begin = buf.data(); 96 return Parse(begin, begin + len); 97 } 98 99 private: 100 template<bool inObjorArr = false> ParseJSONText()101 JSTaggedValue ParseJSONText() 102 { 103 SkipStartWhiteSpace(); 104 Tokens token = ParseToken(); 105 switch (token) { 106 case Tokens::OBJECT: 107 return ParseObject<inObjorArr>(); 108 case Tokens::ARRAY: 109 return ParseArray<inObjorArr>(); 110 case Tokens::LITERAL_TRUE: 111 return ParseLiteral("true", Tokens::LITERAL_TRUE); 112 case Tokens::LITERAL_FALSE: 113 return ParseLiteral("false", Tokens::LITERAL_FALSE); 114 case Tokens::LITERAL_NULL: 115 return ParseLiteral("null", Tokens::LITERAL_NULL); 116 case Tokens::NUMBER: 117 return ParseNumber<inObjorArr>(); 118 case Tokens::STRING: 119 return ParseString<inObjorArr>(); 120 default: 121 THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected Text in JSON", JSTaggedValue::Exception()); 122 } 123 } 124 125 template<bool inObjOrArr = false> ParseNumber()126 JSTaggedValue ParseNumber() 127 { 128 if (inObjOrArr) { 129 bool isFast = true; 130 bool isNumber = ReadNumberRange(isFast); 131 if (!isNumber) { 132 THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected Number in JSON", JSTaggedValue::Exception()); 133 } 134 if (isFast) { 135 std::string strNum(current_, end_ + 1); 136 current_ = end_; 137 double v = std::stod(strNum); 138 return JSTaggedValue::TryCastDoubleToInt32(v); 139 } 140 } 141 142 Text current = current_; 143 bool hasExponent = false; 144 if (*current_ == '-') { 145 if (UNLIKELY(current_++ == end_)) { 146 THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected Number in JSON", JSTaggedValue::Exception()); 147 } 148 } 149 if (*current_ == '0') { 150 if (!CheckZeroBeginNumber(hasExponent)) { 151 THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected Number in JSON", JSTaggedValue::Exception()); 152 } 153 } else if (*current_ >= '1' && *current_ <= '9') { 154 if (!CheckNonZeroBeginNumber(hasExponent)) { 155 THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected Number in JSON", JSTaggedValue::Exception()); 156 } 157 } else { 158 THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected Number in JSON", JSTaggedValue::Exception()); 159 } 160 161 std::string strNum(current, end_ + 1); 162 current_ = end_; 163 double v = std::stod(strNum); 164 return JSTaggedValue::TryCastDoubleToInt32(v); 165 } 166 ReadJsonStringRange(bool & isFastString,bool & isAscii)167 bool ReadJsonStringRange(bool &isFastString, bool &isAscii) 168 { 169 current_++; 170 if (isAsciiString_) { 171 return ReadAsciiStringRange(isFastString); 172 } 173 return ReadStringRange(isFastString, isAscii); 174 } 175 IsFastParseJsonString(bool & isFastString,bool & isAscii)176 bool IsFastParseJsonString(bool &isFastString, bool &isAscii) 177 { 178 current_++; 179 if (isAsciiString_) { 180 return IsFastParseAsciiString(isFastString); 181 } 182 return IsFastParseString(isFastString, isAscii); 183 } 184 ParseBackslash(CString & res)185 bool ParseBackslash(CString &res) 186 { 187 if (current_ == end_) { 188 return false; 189 } 190 current_++; 191 switch (*current_) { 192 case '\"': 193 res += "\""; 194 break; 195 case '\\': 196 res += "\\"; 197 break; 198 case '/': 199 res += "/"; 200 break; 201 case 'b': 202 res += "\b"; 203 break; 204 case 'f': 205 res += "\f"; 206 break; 207 case 'n': 208 res += "\n"; 209 break; 210 case 'r': 211 res += "\r"; 212 break; 213 case 't': 214 res += "\t"; 215 break; 216 case 'u': { 217 CVector<uint16_t> vec; 218 if (UNLIKELY(!ConvertStringUnicode(vec))) { 219 return false; 220 } 221 std::u16string u16Str; 222 u16Str.assign(vec.begin(), vec.end()); 223 res += base::StringHelper::U16stringToString(u16Str); 224 break; 225 } 226 default: 227 return false; 228 } 229 return true; 230 } 231 SlowParseString()232 JSTaggedValue SlowParseString() 233 { 234 end_--; 235 CString res; 236 while (current_ <= end_) { 237 if (*current_ == '\\') { 238 bool isLegalChar = ParseBackslash(res); 239 if (!isLegalChar) { 240 THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected string in JSON", JSTaggedValue::Exception()); 241 } 242 current_++; 243 } else if (UNLIKELY(*current_ > ASCII_END)) { 244 if (UNLIKELY(*current_ > utf_helper::DECODE_LEAD_LOW && *current_ < utf_helper::DECODE_LEAD_HIGH && 245 *(current_ + 1) > utf_helper::DECODE_TRAIL_LOW && 246 *(current_ + 1) < utf_helper::DECODE_TRAIL_HIGH)) { 247 std::u16string str(current_, current_ + 2); // 2 means twice as many bytes as normal u16string 248 res += ConvertToString(StringHelper::U16stringToString(str)); 249 current_ += 2; // 2 means twice as many bytes as normal u16string 250 } else { 251 std::u16string str(current_, current_ + 1); 252 res += ConvertToString(StringHelper::U16stringToString(str)); 253 current_++; 254 } 255 } else { 256 res += *current_; 257 current_++; 258 } 259 } 260 ASSERT(res.length() <= static_cast<size_t>(UINT32_MAX)); 261 return factory_->NewFromUtf8Literal(reinterpret_cast<const uint8_t *>(res.c_str()), res.length()) 262 .GetTaggedValue(); 263 } 264 265 template<bool inObjorArr = false> ParseString()266 JSTaggedValue ParseString() 267 { 268 bool isFastString = true; 269 bool isAscii = true; 270 bool isLegal = true; 271 if (inObjorArr) { 272 isLegal = ReadJsonStringRange(isFastString, isAscii); 273 if (!isLegal) { 274 THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected end Text in JSON", JSTaggedValue::Exception()); 275 } 276 if (isFastString) { 277 if (isAscii) { 278 CString value(current_, end_); 279 current_ = end_; 280 ASSERT(value.length() <= static_cast<size_t>(UINT32_MAX)); 281 return factory_->NewFromUtf8LiteralCompress( 282 reinterpret_cast<const uint8_t *>(value.c_str()), value.length()).GetTaggedValue(); 283 } 284 std::u16string value(current_, end_); 285 current_ = end_; 286 ASSERT(value.length() <= static_cast<size_t>(UINT32_MAX)); 287 return factory_->NewFromUtf16LiteralNotCompress( 288 reinterpret_cast<const uint16_t *>(value.c_str()), value.length()).GetTaggedValue(); 289 } 290 } else { 291 if (*end_ != '"' || current_ == end_) { 292 THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected end Text in JSON", JSTaggedValue::Exception()); 293 } 294 isLegal = IsFastParseJsonString(isFastString, isAscii); 295 if (!isLegal) { 296 THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected end Text in JSON", JSTaggedValue::Exception()); 297 } 298 if (LIKELY(isFastString)) { 299 if (isAscii) { 300 CString value(current_, end_); 301 ASSERT(value.length() <= static_cast<size_t>(UINT32_MAX)); 302 return factory_->NewFromUtf8LiteralCompress( 303 reinterpret_cast<const uint8_t *>(value.c_str()), value.length()).GetTaggedValue(); 304 } 305 std::u16string value(current_, end_); 306 ASSERT(value.length() <= static_cast<size_t>(UINT32_MAX)); 307 return factory_->NewFromUtf16LiteralNotCompress( 308 reinterpret_cast<const uint16_t *>(value.c_str()), value.length()).GetTaggedValue(); 309 } 310 } 311 return SlowParseString(); 312 } 313 314 template<bool inObjorArr = false> ParseArray()315 JSTaggedValue ParseArray() 316 { 317 if (UNLIKELY(*range_ != ']' && !inObjorArr)) { 318 THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected Array in JSON", JSTaggedValue::Exception()); 319 } 320 321 current_++; 322 SkipStartWhiteSpace(); 323 JSHandle<JSArray> arr = factory_->NewJSArray(); 324 if (*current_ == ']') { 325 return arr.GetTaggedValue(); 326 } 327 328 JSTaggedValue value; 329 uint32_t index = 0; 330 while (current_ <= range_) { 331 value = ParseJSONText<true>(); 332 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread_); 333 ObjectFastOperator::SetPropertyByIndex<true>(thread_, arr.GetTaggedValue(), index++, value); 334 GetNextNonSpaceChar(); 335 if (*current_ == ',') { 336 current_++; 337 } else if (*current_ == ']') { 338 if (inObjorArr || current_ == range_) { 339 return arr.GetTaggedValue(); 340 } else { 341 THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected Array in JSON", JSTaggedValue::Exception()); 342 } 343 } 344 } 345 THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected Array in JSON", JSTaggedValue::Exception()); 346 } 347 348 template<bool inObjorArr = false> ParseObject()349 JSTaggedValue ParseObject() 350 { 351 if (UNLIKELY(*range_ != '}' && !inObjorArr)) { 352 THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected Object in JSON", JSTaggedValue::Exception()); 353 } 354 355 JSHandle<JSFunction> proto(env_->GetObjectFunction()); 356 JSHandle<JSObject> result = factory_->NewJSObjectByConstructor(proto); 357 current_++; 358 if (*current_ == '}') { 359 return result.GetTaggedValue(); 360 } 361 362 JSMutableHandle<JSTaggedValue> keyHandle(thread_, JSTaggedValue::Undefined()); 363 JSTaggedValue value; 364 while (current_ <= range_) { 365 SkipStartWhiteSpace(); 366 if (*current_ == '"') { 367 keyHandle.Update(ParseString<true>()); 368 } else { 369 if (*current_ == '}' && (inObjorArr || current_ == range_)) { 370 return result.GetTaggedValue(); 371 } 372 THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected Object in JSON", JSTaggedValue::Exception()); 373 } 374 GetNextNonSpaceChar(); 375 if (*current_ == ':') { 376 current_++; 377 } else { 378 THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected Object in JSON", JSTaggedValue::Exception()); 379 } 380 value = ParseJSONText<true>(); 381 // fast path 382 JSTaggedValue res = ObjectFastOperator::SetPropertyByValue<true>(thread_, result.GetTaggedValue(), 383 keyHandle.GetTaggedValue(), value); 384 if (res.IsHole()) { 385 // slow path 386 JSTaggedValue::SetProperty(thread_, JSHandle<JSTaggedValue>(result), keyHandle, 387 JSHandle<JSTaggedValue>(thread_, value), true); 388 } 389 GetNextNonSpaceChar(); 390 if (*current_ == ',') { 391 current_++; 392 } else if (*current_ == '}') { 393 if (inObjorArr || current_ == range_) { 394 return result.GetTaggedValue(); 395 } else { 396 THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected Object in JSON", JSTaggedValue::Exception()); 397 } 398 } 399 } 400 THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected Object in JSON", JSTaggedValue::Exception()); 401 } 402 SkipEndWhiteSpace()403 void SkipEndWhiteSpace() 404 { 405 while (current_ != end_) { 406 if (*end_ == ' ' || *end_ == '\r' || *end_ == '\n' || *end_ == '\t') { 407 end_--; 408 } else { 409 break; 410 } 411 } 412 } 413 SkipStartWhiteSpace()414 void SkipStartWhiteSpace() 415 { 416 while (current_ != end_) { 417 if (*current_ == ' ' || *current_ == '\r' || *current_ == '\n' || *current_ == '\t') { 418 current_++; 419 } else { 420 break; 421 } 422 } 423 } 424 GetNextNonSpaceChar()425 void GetNextNonSpaceChar() 426 { 427 current_++; 428 SkipStartWhiteSpace(); 429 } 430 ParseToken()431 Tokens ParseToken() 432 { 433 switch (*current_) { 434 case '{': 435 return Tokens::OBJECT; 436 case '[': 437 return Tokens::ARRAY; 438 case '"': 439 return Tokens::STRING; 440 case '0': 441 case '1': 442 case '2': 443 case '3': 444 case '4': 445 case '5': 446 case '6': 447 case '7': 448 case '8': 449 case '9': 450 case '-': 451 return Tokens::NUMBER; 452 case 't': 453 return Tokens::LITERAL_TRUE; 454 case 'f': 455 return Tokens::LITERAL_FALSE; 456 case 'n': 457 return Tokens::LITERAL_NULL; 458 default: 459 return Tokens::TOKEN_ILLEGAL; 460 } 461 } 462 ParseLiteral(CString str,Tokens literalToken)463 JSTaggedValue ParseLiteral(CString str, Tokens literalToken) 464 { 465 ASSERT((str.size() - 1) <= static_cast<size_t>(UINT32_MAX)); 466 uint32_t strLen = str.size() - 1; 467 uint32_t remainingLength = range_ - current_; 468 if (UNLIKELY(remainingLength < strLen)) { 469 THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected Text in JSON", JSTaggedValue::Exception()); 470 } 471 472 bool isMatch = MatchText(str, strLen); 473 if (LIKELY(isMatch)) { 474 switch (literalToken) { 475 case Tokens::LITERAL_TRUE: 476 return JSTaggedValue::True(); 477 case Tokens::LITERAL_FALSE: 478 return JSTaggedValue::False(); 479 case Tokens::LITERAL_NULL: 480 return JSTaggedValue::Null(); 481 default: 482 UNREACHABLE(); 483 } 484 } 485 THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected Text in JSON", JSTaggedValue::Exception()); 486 } 487 MatchText(CString str,uint32_t matchLen)488 bool MatchText(CString str, uint32_t matchLen) 489 { 490 const char *text = str.c_str(); 491 uint32_t pos = 1; 492 while (pos <= matchLen) { 493 if (current_[pos] != text[pos]) { 494 return false; 495 } 496 pos++; 497 } 498 current_ += matchLen; 499 return true; 500 } 501 ReadNumberRange(bool & isFast)502 bool ReadNumberRange(bool &isFast) 503 { 504 Text current = current_; 505 if (*current == '0') { 506 isFast = false; 507 current++; 508 } else if (*current == '-') { 509 current++; 510 if (*current == '0') { 511 isFast = false; 512 current++; 513 } 514 } 515 516 while (current != range_) { 517 if (IsNumberCharacter(*current)) { 518 current++; 519 continue; 520 } else if (IsNumberSignalCharacter(*current)) { 521 isFast = false; 522 current++; 523 continue; 524 } 525 Text end = current; 526 while (current != range_) { 527 if (*current == ' ' || *current == '\r' || *current == '\n' || *current == '\t') { 528 current++; 529 } else if (*current == ',' || *current == ']' || *current == '}') { 530 end_ = end - 1; 531 return true; 532 } else { 533 return false; 534 } 535 } 536 if (*current == ']' || *current == '}') { 537 end_ = end - 1; 538 return true; 539 } 540 return false; 541 } 542 end_ = range_ - 1; 543 return true; 544 } 545 IsNumberCharacter(T ch)546 bool IsNumberCharacter(T ch) 547 { 548 if (ch >= '0' && ch <= '9') { 549 return true; 550 } 551 return false; 552 } 553 IsNumberSignalCharacter(T ch)554 bool IsNumberSignalCharacter(T ch) 555 { 556 return ch == '.' || ch == 'e' || ch == 'E' || ch == '+' || ch == '-'; 557 } 558 IsExponentNumber()559 bool IsExponentNumber() 560 { 561 if (IsNumberCharacter(*current_)) { 562 return true; 563 } else if (*current_ == '-' || *current_ == '+') { 564 if (current_ == end_) { 565 return false; 566 } 567 current_++; 568 if (IsNumberCharacter(*current_)) { 569 return true; 570 } 571 } 572 return false; 573 } 574 IsDecimalsLegal(bool & hasExponent)575 bool IsDecimalsLegal(bool &hasExponent) 576 { 577 if (current_ == end_ && !IsNumberCharacter(*++current_)) { 578 return false; 579 } 580 581 while (current_ != end_) { 582 current_++; 583 if (IsNumberCharacter(*current_)) { 584 continue; 585 } else if (*current_ == 'e' || *current_ == 'E') { 586 if (hasExponent || current_ == end_) { 587 return false; 588 } 589 current_++; 590 if (!IsExponentNumber()) { 591 return false; 592 } 593 hasExponent = true; 594 } else { 595 return false; 596 } 597 } 598 return true; 599 } 600 IsExponentLegal(bool & hasExponent)601 bool IsExponentLegal(bool &hasExponent) 602 { 603 if (hasExponent || current_ == end_) { 604 return false; 605 } 606 current_++; 607 if (!IsExponentNumber()) { 608 return false; 609 } 610 while (current_ != end_) { 611 if (!IsNumberCharacter(*current_)) { 612 return false; 613 } 614 current_++; 615 } 616 return true; 617 } 618 ReadStringRange(bool & isFast,bool & isAscii)619 bool ReadStringRange(bool &isFast, bool &isAscii) 620 { 621 T c = 0; 622 Text current = current_; 623 624 while (current != range_) { 625 c = *current; 626 if (c == '"') { 627 end_ = current; 628 return true; 629 } else if (UNLIKELY(c == '\\')) { 630 current++; 631 isFast = false; 632 } 633 if (!IsLegalAsciiCharacter(c, isAscii)) { 634 return false; 635 } 636 current++; 637 } 638 return false; 639 } 640 ReadAsciiStringRange(bool & isFast)641 bool ReadAsciiStringRange(bool &isFast) 642 { 643 T c = 0; 644 Text current = current_; 645 646 while (current != range_) { 647 c = *current; 648 if (c == '"') { 649 end_ = current; 650 return true; 651 } else if (UNLIKELY(c == '\\')) { 652 current++; 653 isFast = false; 654 } else if (UNLIKELY(c < CODE_SPACE)) { 655 return false; 656 } 657 current++; 658 } 659 return false; 660 } 661 IsFastParseString(bool & isFast,bool & isAscii)662 bool IsFastParseString(bool &isFast, bool &isAscii) 663 { 664 Text current = current_; 665 while (current != end_) { 666 if (!IsLegalAsciiCharacter(*current, isAscii)) { 667 return false; 668 } 669 if (*current == '\\') { 670 isFast = false; 671 } 672 current++; 673 } 674 return true; 675 } 676 IsFastParseAsciiString(bool & isFast)677 bool IsFastParseAsciiString(bool &isFast) 678 { 679 Text current = current_; 680 while (current != end_) { 681 if (*current < CODE_SPACE) { 682 return false; 683 } else if (*current == '\\') { 684 isFast = false; 685 } 686 current++; 687 } 688 return true; 689 } 690 ConvertStringUnicode(CVector<uint16_t> & vec)691 bool ConvertStringUnicode(CVector<uint16_t> &vec) 692 { 693 uint32_t remainingLength = end_ - current_; 694 if (remainingLength < UNICODE_DIGIT_LENGTH) { 695 return false; 696 } 697 uint16_t res = 0; 698 uint32_t exponent = UNICODE_DIGIT_LENGTH; 699 for (uint32_t pos = 0; pos < UNICODE_DIGIT_LENGTH; pos++) { 700 current_++; 701 exponent--; 702 if (*current_ >= '0' && *current_ <= '9') { 703 res += (*current_ - '0') * pow(NUMBER_SIXTEEN, exponent); 704 } else if (*current_ >= 'a' && *current_ <= 'f') { 705 res += (*current_ - 'a' + NUMBER_TEN) * pow(NUMBER_SIXTEEN, exponent); 706 } else if (*current_ >= 'A' && *current_ <= 'F') { 707 res += (*current_ - 'A' + NUMBER_TEN) * pow(NUMBER_SIXTEEN, exponent); 708 } else { 709 return false; 710 } 711 } 712 713 vec.emplace_back(res); 714 715 if (*(current_ + 1) == '\\' && *(current_ + 2) == 'u') { // 2: next two chars 716 current_ += 2; // 2: point moves backwards by two digits 717 return ConvertStringUnicode(vec); 718 } 719 return true; 720 } 721 CheckZeroBeginNumber(bool & hasExponent)722 bool CheckZeroBeginNumber(bool &hasExponent) 723 { 724 if (current_++ != end_) { 725 if (*current_ == '.') { 726 if (!IsDecimalsLegal(hasExponent)) { 727 return false; 728 } 729 } else if (*current_ == 'e' || *current_ == 'E') { 730 if (!IsExponentLegal(hasExponent)) { 731 return false; 732 } 733 } else { 734 return false; 735 } 736 } 737 return true; 738 } 739 CheckNonZeroBeginNumber(bool & hasExponent)740 bool CheckNonZeroBeginNumber(bool &hasExponent) 741 { 742 while (current_ != end_) { 743 current_++; 744 if (IsNumberCharacter(*current_)) { 745 continue; 746 } else if (*current_ == '.') { 747 if (!IsDecimalsLegal(hasExponent)) { 748 return false; 749 } 750 } else if (*current_ == 'e' || *current_ == 'E') { 751 if (!IsExponentLegal(hasExponent)) { 752 return false; 753 } 754 } else { 755 return false; 756 } 757 } 758 return true; 759 } 760 IsLegalAsciiCharacter(T c,bool & isAscii)761 bool IsLegalAsciiCharacter(T c, bool &isAscii) 762 { 763 if (c <= ASCII_END) { 764 if (c >= CODE_SPACE) { 765 return true; 766 } 767 return false; 768 } 769 isAscii = false; 770 return true; 771 } 772 773 bool isAsciiString_ {false}; 774 Text end_ {nullptr}; 775 Text current_ {nullptr}; 776 Text range_ {nullptr}; 777 JSThread *thread_ {nullptr}; 778 ObjectFactory *factory_ {nullptr}; 779 GlobalEnv *env_ {nullptr}; 780 }; 781 782 class Internalize { 783 public: 784 static JSHandle<JSTaggedValue> InternalizeJsonProperty(JSThread *thread, const JSHandle<JSObject> &holder, 785 const JSHandle<JSTaggedValue> &name, 786 const JSHandle<JSTaggedValue> &receiver); 787 private: 788 static bool RecurseAndApply(JSThread *thread, const JSHandle<JSObject> &holder, const JSHandle<JSTaggedValue> &name, 789 const JSHandle<JSTaggedValue> &receiver); 790 }; 791 } // namespace panda::ecmascript::base 792 793 #endif // ECMASCRIPT_BASE_JSON_PARSE_INL_H 794