• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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