31 #include <google/protobuf/util/internal/json_escaping.h>
35 #include <google/protobuf/stubs/logging.h>
36 #include <google/protobuf/stubs/common.h>
46 static const char kHex[] =
"0123456789abcdef";
54 static const char kCommonEscapes[160][7] = {
56 "\\u0000",
"\\u0001",
"\\u0002",
"\\u0003",
57 "\\u0004",
"\\u0005",
"\\u0006",
"\\u0007",
"\\b",
"\\t",
"\\n",
"\\u000b",
58 "\\f",
"\\r",
"\\u000e",
"\\u000f",
"\\u0010",
"\\u0011",
"\\u0012",
60 "\\u0014",
"\\u0015",
"\\u0016",
"\\u0017",
"\\u0018",
"\\u0019",
"\\u001a",
61 "\\u001b",
"\\u001c",
"\\u001d",
"\\u001e",
"\\u001f",
64 "",
"",
"\\\"",
"",
"",
"",
"",
"",
65 "",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
66 "",
"",
"",
"",
"\\u003c",
"",
"\\u003e",
"",
"",
"",
"",
"",
"",
"",
"",
68 "",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
69 "",
"",
"",
"",
"\\\\",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
70 "",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
71 "",
"",
"",
"",
"",
"",
"",
"\\u007f",
73 "\\u0080",
"\\u0081",
"\\u0082",
"\\u0083",
74 "\\u0084",
"\\u0085",
"\\u0086",
"\\u0087",
"\\u0088",
"\\u0089",
"\\u008a",
75 "\\u008b",
"\\u008c",
"\\u008d",
"\\u008e",
"\\u008f",
"\\u0090",
"\\u0091",
77 "\\u0094",
"\\u0095",
"\\u0096",
"\\u0097",
"\\u0098",
"\\u0099",
"\\u009a",
78 "\\u009b",
"\\u009c",
"\\u009d",
"\\u009e",
"\\u009f"};
131 int* num_left,
int* num_read) {
132 if (*num_left == 0) {
163 }
else if (*cp <= 0xbf) {
165 }
else if (*cp <= 0xdf) {
168 }
else if (*cp <= 0xef) {
171 }
else if (*cp <= 0xf7) {
182 while (*num_left > 0 &&
index <
str.size()) {
186 *cp = (*cp << 6) | (
ch & 0x3f);
187 if (ch < 0x80 || ch > 0xbf)
return false;
196 buffer[5] = kHex[cp & 0x0f];
198 buffer[4] = kHex[cp & 0x0f];
200 buffer[3] = kHex[cp & 0x0f];
202 buffer[2] = kHex[cp & 0x0f];
203 return StringPiece(
buffer, 6);
211 uint16_t high = ToHighSurrogate(cp);
213 buffer[11] = kHex[low & 0x0f];
215 buffer[10] = kHex[low & 0x0f];
217 buffer[9] = kHex[low & 0x0f];
219 buffer[8] = kHex[low & 0x0f];
221 buffer[5] = kHex[high & 0x0f];
223 buffer[4] = kHex[high & 0x0f];
225 buffer[3] = kHex[high & 0x0f];
227 buffer[2] = kHex[high & 0x0f];
229 return StringPiece(
buffer, 12);
240 if (cp < 0xa0)
return kCommonEscapes[cp];
257 if ((cp >= 0x0600 && cp <= 0x0603) ||
258 (cp >= 0x200b && cp <= 0x200f) ||
259 (cp >= 0x2028 && cp <= 0x202e) ||
260 (cp >= 0x2060 && cp <= 0x2064) ||
261 (cp >= 0x206a && cp <= 0x206f)) {
265 if (cp == 0x000e0001 ||
266 (cp >= 0x0001d173 && cp <= 0x0001d17a) ||
267 (cp >= 0x000e0020 && cp <= 0x000e007f)) {
268 return ToSurrogateHex(cp,
buffer);
271 return StringPiece();
279 StringPiece sp = EscapeCodePoint(cp,
buffer);
280 if (force_output && sp.empty()) {
281 buffer[5] = (cp & 0x3f) | 0x80;
285 sp = StringPiece(
buffer + 4, 2);
288 buffer[4] = (cp & 0x3f) | 0x80;
292 sp = StringPiece(
buffer + 3, 3);
295 buffer[3] = (cp & 0x3f) | 0x80;
296 buffer[2] = ((cp >> 6) & 0x07) | 0xf0;
297 sp = StringPiece(
buffer + 2, 4);
305 strings::ByteSink*
output) {
306 char buffer[12] =
"\\udead\\ubee";
309 while (
input->Available() > 0) {
315 bool cp_was_split = num_left > 0;
322 ok = ReadCodePoint(
str, i, &cp, &num_left, &num_read);
323 if (num_left > 0 || !
ok)
break;
324 escaped = EscapeCodePoint(cp,
buffer, cp_was_split);
325 if (!escaped.empty())
break;
328 }
while (i <
str.length());
331 if (num_read > 0)
input->Skip(num_read);
336 }
else if (num_left == 0 && !escaped.empty()) {
338 output->Append(escaped.data(), escaped.size());
349 const char* p =
input.data();
351 bool can_skip_escaping =
true;
352 for (
int i = 0;
i <
len;
i++) {
354 if (c < 0x20 || c >= 0x7F || c ==
'"' || c ==
'<' || c ==
'>' ||
356 can_skip_escaping =
false;
361 if (can_skip_escaping) {