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 ObjectFastOperator::SetPropertyByValue<true>( 382 thread_, result.GetTaggedValue(), keyHandle.GetTaggedValue(), value); 383 GetNextNonSpaceChar(); 384 if (*current_ == ',') { 385 current_++; 386 } else if (*current_ == '}') { 387 if (inObjorArr || current_ == range_) { 388 return result.GetTaggedValue(); 389 } else { 390 THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected Object in JSON", JSTaggedValue::Exception()); 391 } 392 } 393 } 394 THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected Object in JSON", JSTaggedValue::Exception()); 395 } 396 SkipEndWhiteSpace()397 void SkipEndWhiteSpace() 398 { 399 while (current_ != end_) { 400 if (*end_ == ' ' || *end_ == '\r' || *end_ == '\n' || *end_ == '\t') { 401 end_--; 402 } else { 403 break; 404 } 405 } 406 } 407 SkipStartWhiteSpace()408 void SkipStartWhiteSpace() 409 { 410 while (current_ != end_) { 411 if (*current_ == ' ' || *current_ == '\r' || *current_ == '\n' || *current_ == '\t') { 412 current_++; 413 } else { 414 break; 415 } 416 } 417 } 418 GetNextNonSpaceChar()419 void GetNextNonSpaceChar() 420 { 421 current_++; 422 SkipStartWhiteSpace(); 423 } 424 ParseToken()425 Tokens ParseToken() 426 { 427 switch (*current_) { 428 case '{': 429 return Tokens::OBJECT; 430 case '[': 431 return Tokens::ARRAY; 432 case '"': 433 return Tokens::STRING; 434 case '0': 435 case '1': 436 case '2': 437 case '3': 438 case '4': 439 case '5': 440 case '6': 441 case '7': 442 case '8': 443 case '9': 444 case '-': 445 return Tokens::NUMBER; 446 case 't': 447 return Tokens::LITERAL_TRUE; 448 case 'f': 449 return Tokens::LITERAL_FALSE; 450 case 'n': 451 return Tokens::LITERAL_NULL; 452 default: 453 return Tokens::TOKEN_ILLEGAL; 454 } 455 } 456 ParseLiteral(CString str,Tokens literalToken)457 JSTaggedValue ParseLiteral(CString str, Tokens literalToken) 458 { 459 ASSERT((str.size() - 1) <= static_cast<size_t>(UINT32_MAX)); 460 uint32_t strLen = str.size() - 1; 461 uint32_t remainingLength = range_ - current_; 462 if (UNLIKELY(remainingLength < strLen)) { 463 THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected Text in JSON", JSTaggedValue::Exception()); 464 } 465 466 bool isMatch = MatchText(str, strLen); 467 if (LIKELY(isMatch)) { 468 switch (literalToken) { 469 case Tokens::LITERAL_TRUE: 470 return JSTaggedValue::True(); 471 case Tokens::LITERAL_FALSE: 472 return JSTaggedValue::False(); 473 case Tokens::LITERAL_NULL: 474 return JSTaggedValue::Null(); 475 default: 476 UNREACHABLE(); 477 } 478 } 479 THROW_SYNTAX_ERROR_AND_RETURN(thread_, "Unexpected Text in JSON", JSTaggedValue::Exception()); 480 } 481 MatchText(CString str,uint32_t matchLen)482 bool MatchText(CString str, uint32_t matchLen) 483 { 484 const char *text = str.c_str(); 485 uint32_t pos = 1; 486 while (pos <= matchLen) { 487 if (current_[pos] != text[pos]) { 488 return false; 489 } 490 pos++; 491 } 492 current_ += matchLen; 493 return true; 494 } 495 ReadNumberRange(bool & isFast)496 bool ReadNumberRange(bool &isFast) 497 { 498 Text current = current_; 499 if (*current == '0') { 500 isFast = false; 501 current++; 502 } else if (*current == '-') { 503 current++; 504 if (*current == '0') { 505 isFast = false; 506 current++; 507 } 508 } 509 510 while (current != range_) { 511 if (IsNumberCharacter(*current)) { 512 current++; 513 continue; 514 } else if (IsNumberSignalCharacter(*current)) { 515 isFast = false; 516 current++; 517 continue; 518 } 519 Text end = current; 520 while (current != range_) { 521 if (*current == ' ' || *current == '\r' || *current == '\n' || *current == '\t') { 522 current++; 523 } else if (*current == ',' || *current == ']' || *current == '}') { 524 end_ = end - 1; 525 return true; 526 } else { 527 return false; 528 } 529 } 530 if (*current == ']' || *current == '}') { 531 end_ = end - 1; 532 return true; 533 } 534 return false; 535 } 536 end_ = range_ - 1; 537 return true; 538 } 539 IsNumberCharacter(T ch)540 bool IsNumberCharacter(T ch) 541 { 542 if (ch >= '0' && ch <= '9') { 543 return true; 544 } 545 return false; 546 } 547 IsNumberSignalCharacter(T ch)548 bool IsNumberSignalCharacter(T ch) 549 { 550 return ch == '.' || ch == 'e' || ch == 'E' || ch == '+' || ch == '-'; 551 } 552 IsExponentNumber()553 bool IsExponentNumber() 554 { 555 if (IsNumberCharacter(*current_)) { 556 return true; 557 } else if (*current_ == '-' || *current_ == '+') { 558 if (current_ == end_) { 559 return false; 560 } 561 current_++; 562 if (IsNumberCharacter(*current_)) { 563 return true; 564 } 565 } 566 return false; 567 } 568 IsDecimalsLegal(bool & hasExponent)569 bool IsDecimalsLegal(bool &hasExponent) 570 { 571 if (current_ == end_ && !IsNumberCharacter(*++current_)) { 572 return false; 573 } 574 575 while (current_ != end_) { 576 current_++; 577 if (IsNumberCharacter(*current_)) { 578 continue; 579 } else if (*current_ == 'e' || *current_ == 'E') { 580 if (hasExponent || current_ == end_) { 581 return false; 582 } 583 current_++; 584 if (!IsExponentNumber()) { 585 return false; 586 } 587 hasExponent = true; 588 } else { 589 return false; 590 } 591 } 592 return true; 593 } 594 IsExponentLegal(bool & hasExponent)595 bool IsExponentLegal(bool &hasExponent) 596 { 597 if (hasExponent || current_ == end_) { 598 return false; 599 } 600 current_++; 601 if (!IsExponentNumber()) { 602 return false; 603 } 604 while (current_ != end_) { 605 if (!IsNumberCharacter(*current_)) { 606 return false; 607 } 608 current_++; 609 } 610 return true; 611 } 612 ReadStringRange(bool & isFast,bool & isAscii)613 bool ReadStringRange(bool &isFast, bool &isAscii) 614 { 615 T c = 0; 616 Text current = current_; 617 618 while (current != range_) { 619 c = *current; 620 if (c == '"') { 621 end_ = current; 622 return true; 623 } else if (UNLIKELY(c == '\\')) { 624 current++; 625 isFast = false; 626 } 627 if (!IsLegalAsciiCharacter(c, isAscii)) { 628 return false; 629 } 630 current++; 631 } 632 return false; 633 } 634 ReadAsciiStringRange(bool & isFast)635 bool ReadAsciiStringRange(bool &isFast) 636 { 637 T c = 0; 638 Text current = current_; 639 640 while (current != range_) { 641 c = *current; 642 if (c == '"') { 643 end_ = current; 644 return true; 645 } else if (UNLIKELY(c == '\\')) { 646 current++; 647 isFast = false; 648 } else if (UNLIKELY(c < CODE_SPACE)) { 649 return false; 650 } 651 current++; 652 } 653 return false; 654 } 655 IsFastParseString(bool & isFast,bool & isAscii)656 bool IsFastParseString(bool &isFast, bool &isAscii) 657 { 658 Text current = current_; 659 while (current != end_) { 660 if (!IsLegalAsciiCharacter(*current, isAscii)) { 661 return false; 662 } 663 if (*current == '\\') { 664 isFast = false; 665 } 666 current++; 667 } 668 return true; 669 } 670 IsFastParseAsciiString(bool & isFast)671 bool IsFastParseAsciiString(bool &isFast) 672 { 673 Text current = current_; 674 while (current != end_) { 675 if (*current < CODE_SPACE) { 676 return false; 677 } else if (*current == '\\') { 678 isFast = false; 679 } 680 current++; 681 } 682 return true; 683 } 684 ConvertStringUnicode(CVector<uint16_t> & vec)685 bool ConvertStringUnicode(CVector<uint16_t> &vec) 686 { 687 uint32_t remainingLength = end_ - current_; 688 if (remainingLength < UNICODE_DIGIT_LENGTH) { 689 return false; 690 } 691 uint16_t res = 0; 692 uint32_t exponent = UNICODE_DIGIT_LENGTH; 693 for (uint32_t pos = 0; pos < UNICODE_DIGIT_LENGTH; pos++) { 694 current_++; 695 exponent--; 696 if (*current_ >= '0' && *current_ <= '9') { 697 res += (*current_ - '0') * pow(NUMBER_SIXTEEN, exponent); 698 } else if (*current_ >= 'a' && *current_ <= 'f') { 699 res += (*current_ - 'a' + NUMBER_TEN) * pow(NUMBER_SIXTEEN, exponent); 700 } else if (*current_ >= 'A' && *current_ <= 'F') { 701 res += (*current_ - 'A' + NUMBER_TEN) * pow(NUMBER_SIXTEEN, exponent); 702 } else { 703 return false; 704 } 705 } 706 707 vec.emplace_back(res); 708 709 if (*(current_ + 1) == '\\' && *(current_ + 2) == 'u') { // 2: next two chars 710 current_ += 2; // 2: point moves backwards by two digits 711 return ConvertStringUnicode(vec); 712 } 713 return true; 714 } 715 CheckZeroBeginNumber(bool & hasExponent)716 bool CheckZeroBeginNumber(bool &hasExponent) 717 { 718 if (current_++ != end_) { 719 if (*current_ == '.') { 720 if (!IsDecimalsLegal(hasExponent)) { 721 return false; 722 } 723 } else if (*current_ == 'e' || *current_ == 'E') { 724 if (!IsExponentLegal(hasExponent)) { 725 return false; 726 } 727 } else { 728 return false; 729 } 730 } 731 return true; 732 } 733 CheckNonZeroBeginNumber(bool & hasExponent)734 bool CheckNonZeroBeginNumber(bool &hasExponent) 735 { 736 while (current_ != end_) { 737 current_++; 738 if (IsNumberCharacter(*current_)) { 739 continue; 740 } else if (*current_ == '.') { 741 if (!IsDecimalsLegal(hasExponent)) { 742 return false; 743 } 744 } else if (*current_ == 'e' || *current_ == 'E') { 745 if (!IsExponentLegal(hasExponent)) { 746 return false; 747 } 748 } else { 749 return false; 750 } 751 } 752 return true; 753 } 754 IsLegalAsciiCharacter(T c,bool & isAscii)755 bool IsLegalAsciiCharacter(T c, bool &isAscii) 756 { 757 if (c <= ASCII_END) { 758 if (c >= CODE_SPACE) { 759 return true; 760 } 761 return false; 762 } 763 isAscii = false; 764 return true; 765 } 766 767 bool isAsciiString_ {false}; 768 Text end_ {nullptr}; 769 Text current_ {nullptr}; 770 Text range_ {nullptr}; 771 JSThread *thread_ {nullptr}; 772 ObjectFactory *factory_ {nullptr}; 773 GlobalEnv *env_ {nullptr}; 774 }; 775 776 class Internalize { 777 public: 778 static JSHandle<JSTaggedValue> InternalizeJsonProperty(JSThread *thread, const JSHandle<JSObject> &holder, 779 const JSHandle<JSTaggedValue> &name, 780 const JSHandle<JSTaggedValue> &receiver); 781 private: 782 static bool RecurseAndApply(JSThread *thread, const JSHandle<JSObject> &holder, const JSHandle<JSTaggedValue> &name, 783 const JSHandle<JSTaggedValue> &receiver); 784 }; 785 } // namespace panda::ecmascript::base 786 787 #endif // ECMASCRIPT_BASE_JSON_PARSE_INL_H 788