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