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