• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2024 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 #include "ecmascript/base/json_helper.h"
17 #include "ecmascript/base/utf_helper.h"
18 
19 #include <algorithm>
20 #include <iomanip>
21 #include <sstream>
22 
23 namespace panda::ecmascript::base {
24 constexpr unsigned char CODE_SPACE = 0x20;
25 constexpr int FOUR_HEX = 4;
26 constexpr char ZERO_FIRST = static_cast<char>(0xc0); // \u0000 => c0 80
27 constexpr char ALONE_SURROGATE_3B_FIRST = static_cast<char>(0xed);
28 constexpr char ALONE_SURROGATE_3B_SECOND_START = static_cast<char>(0xa0);
29 constexpr char ALONE_SURROGATE_3B_SECOND_END = static_cast<char>(0xbf);
30 constexpr char ALONE_SURROGATE_3B_THIRD_START = static_cast<char>(0x80);
31 constexpr char ALONE_SURROGATE_3B_THIRD_END = static_cast<char>(0xbf);
32 
IsFastValueToQuotedString(const char * value)33 bool JsonHelper::IsFastValueToQuotedString(const char *value)
34 {
35     if (strpbrk(value, "\"\\\b\f\n\r\t") != nullptr) {
36         return false;
37     }
38     while (*value != '\0') {
39         if ((*value > 0 && *value < CODE_SPACE) || *value == ZERO_FIRST || *value == ALONE_SURROGATE_3B_FIRST) {
40             return false;
41         }
42         value++;
43     }
44     return true;
45 }
46 
ValueToQuotedString(CString str)47 CString JsonHelper::ValueToQuotedString(CString str)
48 {
49     CString product;
50     const char *value = str.c_str();
51     // fast mode
52     bool isFast = IsFastValueToQuotedString(value);
53     if (isFast) {
54         product += "\"";
55         product += str;
56         product += "\"";
57         return product;
58     }
59     // 1. Let product be code unit 0x0022 (QUOTATION MARK).
60     product += "\"";
61     // 2. For each code unit C in value
62     for (const char *c = value; *c != 0; ++c) {
63         switch (*c) {
64             /*
65              * a. If C is 0x0022 (QUOTATION MARK) or 0x005C (REVERSE SOLIDUS), then
66              * i. Let product be the concatenation of product and code unit 0x005C (REVERSE SOLIDUS).
67              * ii. Let product be the concatenation of product and C.
68              */
69             case '\"':
70                 product += "\\\"";
71                 break;
72             case '\\':
73                 product += "\\\\";
74                 break;
75             /*
76              * b. Else if C is 0x0008 (BACKSPACE), 0x000C (FORM FEED), 0x000A (LINE FEED), 0x000D (CARRIAGE RETURN),
77              * or 0x000B (LINE TABULATION), then
78              * i. Let product be the concatenation of product and code unit 0x005C (REVERSE SOLIDUS).
79              * ii. Let abbrev be the String value corresponding to the value of C as follows:
80              * BACKSPACE "b"
81              * FORM FEED (FF) "f"
82              * LINE FEED (LF) "n"
83              * CARRIAGE RETURN (CR) "r"
84              * LINE TABULATION "t"
85              * iii. Let product be the concatenation of product and abbrev.
86              */
87             case '\b':
88                 product += "\\b";
89                 break;
90             case '\f':
91                 product += "\\f";
92                 break;
93             case '\n':
94                 product += "\\n";
95                 break;
96             case '\r':
97                 product += "\\r";
98                 break;
99             case '\t':
100                 product += "\\t";
101                 break;
102             case ZERO_FIRST:
103                 product += "\\u0000";
104                 ++c;
105                 break;
106             case ALONE_SURROGATE_3B_FIRST:
107                 if (*(c + 1) && *(c + 1) >= ALONE_SURROGATE_3B_SECOND_START &&
108                     *(c + 1) <= ALONE_SURROGATE_3B_SECOND_END &&
109                     *(c + 2) >= ALONE_SURROGATE_3B_THIRD_START && // 2 : The third character after c
110                     *(c + 2) <= ALONE_SURROGATE_3B_THIRD_END) {   // 2 : The third character after c
111                     auto unicodeRes = utf_helper::ConvertUtf8ToUnicodeChar((uint8_t *)c, 3);
112                     std::ostringstream oss;
113                     oss << "\\u" << std::hex << std::setfill('0') << std::setw(FOUR_HEX) <<
114                         static_cast<int>(unicodeRes.first);
115                     product += oss.str();
116                     c += 2; // 2 : Skip 2 characters
117                     break;
118                 }
119                 [[fallthrough]];
120             default:
121                 // c. Else if C has a code unit value less than 0x0020 (SPACE), then
122                 if (*c > 0 && *c < CODE_SPACE) {
123                     /*
124                      * i. Let product be the concatenation of product and code unit 0x005C (REVERSE SOLIDUS).
125                      * ii. Let product be the concatenation of product and "u".
126                      * iii. Let hex be the string result of converting the numeric code unit value of C to a String of
127                      * four hexadecimal digits. Alphabetic hexadecimal digits are presented as lowercase Latin letters.
128                      * iv. Let product be the concatenation of product and hex.
129                      */
130                     std::ostringstream oss;
131                     oss << "\\u" << std::hex << std::setfill('0') << std::setw(FOUR_HEX) << static_cast<int>(*c);
132                     product += oss.str();
133                 } else {
134                     // Else,
135                     // i. Let product be the concatenation of product and C.
136                     product += *c;
137                 }
138         }
139     }
140     // 3. Let product be the concatenation of product and code unit 0x0022 (QUOTATION MARK).
141     product += "\"";
142     // Return product.
143     return product;
144 }
145 } // namespace panda::ecmascript::base