| 2565 | } |
| 2566 | |
| 2567 | std::string parse_unicode(std::string::iterator& it, |
| 2568 | const std::string::iterator& end) |
| 2569 | { |
| 2570 | bool large = *it++ == 'U'; |
| 2571 | auto codepoint = parse_hex(it, end, large ? 0x10000000 : 0x1000); |
| 2572 | |
| 2573 | if ((codepoint > 0xd7ff && codepoint < 0xe000) || codepoint > 0x10ffff) |
| 2574 | { |
| 2575 | throw_parse_exception( |
| 2576 | "Unicode escape sequence is not a Unicode scalar value"); |
| 2577 | } |
| 2578 | |
| 2579 | std::string result; |
| 2580 | // See Table 3-6 of the Unicode standard |
| 2581 | if (codepoint <= 0x7f) |
| 2582 | { |
| 2583 | // 1-byte codepoints: 00000000 0xxxxxxx |
| 2584 | // repr: 0xxxxxxx |
| 2585 | result += static_cast<char>(codepoint & 0x7f); |
| 2586 | } |
| 2587 | else if (codepoint <= 0x7ff) |
| 2588 | { |
| 2589 | // 2-byte codepoints: 00000yyy yyxxxxxx |
| 2590 | // repr: 110yyyyy 10xxxxxx |
| 2591 | // |
| 2592 | // 0x1f = 00011111 |
| 2593 | // 0xc0 = 11000000 |
| 2594 | // |
| 2595 | result += static_cast<char>(0xc0 | ((codepoint >> 6) & 0x1f)); |
| 2596 | // |
| 2597 | // 0x80 = 10000000 |
| 2598 | // 0x3f = 00111111 |
| 2599 | // |
| 2600 | result += static_cast<char>(0x80 | (codepoint & 0x3f)); |
| 2601 | } |
| 2602 | else if (codepoint <= 0xffff) |
| 2603 | { |
| 2604 | // 3-byte codepoints: zzzzyyyy yyxxxxxx |
| 2605 | // repr: 1110zzzz 10yyyyyy 10xxxxxx |
| 2606 | // |
| 2607 | // 0xe0 = 11100000 |
| 2608 | // 0x0f = 00001111 |
| 2609 | // |
| 2610 | result += static_cast<char>(0xe0 | ((codepoint >> 12) & 0x0f)); |
| 2611 | result += static_cast<char>(0x80 | ((codepoint >> 6) & 0x1f)); |
| 2612 | result += static_cast<char>(0x80 | (codepoint & 0x3f)); |
| 2613 | } |
| 2614 | else |
| 2615 | { |
| 2616 | // 4-byte codepoints: 000uuuuu zzzzyyyy yyxxxxxx |
| 2617 | // repr: 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx |
| 2618 | // |
| 2619 | // 0xf0 = 11110000 |
| 2620 | // 0x07 = 00000111 |
| 2621 | // |
| 2622 | result += static_cast<char>(0xf0 | ((codepoint >> 18) & 0x07)); |
| 2623 | result += static_cast<char>(0x80 | ((codepoint >> 12) & 0x3f)); |
| 2624 | result += static_cast<char>(0x80 | ((codepoint >> 6) & 0x3f)); |
no test coverage detected