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