• 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             // 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