converts a UTF-16 literal to UTF-8 * A literal can be one or two sequences of the form \uXXXX */
| 646 | /* converts a UTF-16 literal to UTF-8 |
| 647 | * A literal can be one or two sequences of the form \uXXXX */ |
| 648 | static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer) |
| 649 | { |
| 650 | long unsigned int codepoint = 0; |
| 651 | unsigned int first_code = 0; |
| 652 | const unsigned char *first_sequence = input_pointer; |
| 653 | unsigned char utf8_length = 0; |
| 654 | unsigned char utf8_position = 0; |
| 655 | unsigned char sequence_length = 0; |
| 656 | unsigned char first_byte_mark = 0; |
| 657 | |
| 658 | if ((input_end - first_sequence) < 6) |
| 659 | { |
| 660 | /* input ends unexpectedly */ |
| 661 | goto fail; |
| 662 | } |
| 663 | |
| 664 | /* get the first utf16 sequence */ |
| 665 | first_code = parse_hex4(first_sequence + 2); |
| 666 | |
| 667 | /* check that the code is valid */ |
| 668 | if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) |
| 669 | { |
| 670 | goto fail; |
| 671 | } |
| 672 | |
| 673 | /* UTF16 surrogate pair */ |
| 674 | if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) |
| 675 | { |
| 676 | const unsigned char *second_sequence = first_sequence + 6; |
| 677 | unsigned int second_code = 0; |
| 678 | sequence_length = 12; /* \uXXXX\uXXXX */ |
| 679 | |
| 680 | if ((input_end - second_sequence) < 6) |
| 681 | { |
| 682 | /* input ends unexpectedly */ |
| 683 | goto fail; |
| 684 | } |
| 685 | |
| 686 | if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) |
| 687 | { |
| 688 | /* missing second half of the surrogate pair */ |
| 689 | goto fail; |
| 690 | } |
| 691 | |
| 692 | /* get the second utf16 sequence */ |
| 693 | second_code = parse_hex4(second_sequence + 2); |
| 694 | /* check that the code is valid */ |
| 695 | if ((second_code < 0xDC00) || (second_code > 0xDFFF)) |
| 696 | { |
| 697 | /* invalid second half of the surrogate pair */ |
| 698 | goto fail; |
| 699 | } |
| 700 | |
| 701 | |
| 702 | /* calculate the unicode codepoint from the surrogate pair */ |
| 703 | codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF)); |
| 704 | } |
| 705 | else |
no test coverage detected