| 343 | } |
| 344 | |
| 345 | bool WriteString(const Ch* str, SizeType length) { |
| 346 | static const typename TargetEncoding::Ch hexDigits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; |
| 347 | static const char escape[256] = { |
| 348 | #define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 |
| 349 | //0 1 2 3 4 5 6 7 8 9 A B C D E F |
| 350 | 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', // 00 |
| 351 | 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', // 10 |
| 352 | 0, 0, '"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20 |
| 353 | Z16, Z16, // 30~4F |
| 354 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0, // 50 |
| 355 | Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16 // 60~FF |
| 356 | #undef Z16 |
| 357 | }; |
| 358 | |
| 359 | if (TargetEncoding::supportUnicode) |
| 360 | PutReserve(*os_, 2 + length * 6); // "\uxxxx..." |
| 361 | else |
| 362 | PutReserve(*os_, 2 + length * 12); // "\uxxxx\uyyyy..." |
| 363 | |
| 364 | PutUnsafe(*os_, '\"'); |
| 365 | GenericStringStream<SourceEncoding> is(str); |
| 366 | while (ScanWriteUnescapedString(is, length)) { |
| 367 | const Ch c = is.Peek(); |
| 368 | if (!TargetEncoding::supportUnicode && static_cast<unsigned>(c) >= 0x80) { |
| 369 | // Unicode escaping |
| 370 | unsigned codepoint; |
| 371 | if (RAPIDJSON_UNLIKELY(!SourceEncoding::Decode(is, &codepoint))) |
| 372 | return false; |
| 373 | PutUnsafe(*os_, '\\'); |
| 374 | PutUnsafe(*os_, 'u'); |
| 375 | if (codepoint <= 0xD7FF || (codepoint >= 0xE000 && codepoint <= 0xFFFF)) { |
| 376 | PutUnsafe(*os_, hexDigits[(codepoint >> 12) & 15]); |
| 377 | PutUnsafe(*os_, hexDigits[(codepoint >> 8) & 15]); |
| 378 | PutUnsafe(*os_, hexDigits[(codepoint >> 4) & 15]); |
| 379 | PutUnsafe(*os_, hexDigits[(codepoint ) & 15]); |
| 380 | } |
| 381 | else { |
| 382 | RAPIDJSON_ASSERT(codepoint >= 0x010000 && codepoint <= 0x10FFFF); |
| 383 | // Surrogate pair |
| 384 | unsigned s = codepoint - 0x010000; |
| 385 | unsigned lead = (s >> 10) + 0xD800; |
| 386 | unsigned trail = (s & 0x3FF) + 0xDC00; |
| 387 | PutUnsafe(*os_, hexDigits[(lead >> 12) & 15]); |
| 388 | PutUnsafe(*os_, hexDigits[(lead >> 8) & 15]); |
| 389 | PutUnsafe(*os_, hexDigits[(lead >> 4) & 15]); |
| 390 | PutUnsafe(*os_, hexDigits[(lead ) & 15]); |
| 391 | PutUnsafe(*os_, '\\'); |
| 392 | PutUnsafe(*os_, 'u'); |
| 393 | PutUnsafe(*os_, hexDigits[(trail >> 12) & 15]); |
| 394 | PutUnsafe(*os_, hexDigits[(trail >> 8) & 15]); |
| 395 | PutUnsafe(*os_, hexDigits[(trail >> 4) & 15]); |
| 396 | PutUnsafe(*os_, hexDigits[(trail ) & 15]); |
| 397 | } |
| 398 | } |
| 399 | else if ((sizeof(Ch) == 1 || static_cast<unsigned>(c) < 256) && RAPIDJSON_UNLIKELY(escape[static_cast<unsigned char>(c)])) { |
| 400 | is.Take(); |
| 401 | PutUnsafe(*os_, '\\'); |
| 402 | PutUnsafe(*os_, static_cast<typename TargetEncoding::Ch>(escape[static_cast<unsigned char>(c)])); |