| 845 | template <typename Traits, typename opt_swap = opt_false> struct utf_decoder |
| 846 | { |
| 847 | static inline typename Traits::value_type decode_utf8_block(const uint8_t* data, size_t size, typename Traits::value_type result) |
| 848 | { |
| 849 | const uint8_t utf8_byte_mask = 0x3f; |
| 850 | |
| 851 | while (size) |
| 852 | { |
| 853 | uint8_t lead = *data; |
| 854 | |
| 855 | // 0xxxxxxx -> U+0000..U+007F |
| 856 | if (lead < 0x80) |
| 857 | { |
| 858 | result = Traits::low(result, lead); |
| 859 | data += 1; |
| 860 | size -= 1; |
| 861 | |
| 862 | // process aligned single-byte (ascii) blocks |
| 863 | if ((reinterpret_cast<uintptr_t>(data) & 3) == 0) |
| 864 | { |
| 865 | // round-trip through void* to silence 'cast increases required alignment of target type' warnings |
| 866 | while (size >= 4 && (*static_cast<const uint32_t*>(static_cast<const void*>(data)) & 0x80808080) == 0) |
| 867 | { |
| 868 | result = Traits::low(result, data[0]); |
| 869 | result = Traits::low(result, data[1]); |
| 870 | result = Traits::low(result, data[2]); |
| 871 | result = Traits::low(result, data[3]); |
| 872 | data += 4; |
| 873 | size -= 4; |
| 874 | } |
| 875 | } |
| 876 | } |
| 877 | // 110xxxxx -> U+0080..U+07FF |
| 878 | else if (static_cast<unsigned int>(lead - 0xC0) < 0x20 && size >= 2 && (data[1] & 0xc0) == 0x80) |
| 879 | { |
| 880 | result = Traits::low(result, ((lead & ~0xC0) << 6) | (data[1] & utf8_byte_mask)); |
| 881 | data += 2; |
| 882 | size -= 2; |
| 883 | } |
| 884 | // 1110xxxx -> U+0800-U+FFFF |
| 885 | else if (static_cast<unsigned int>(lead - 0xE0) < 0x10 && size >= 3 && (data[1] & 0xc0) == 0x80 && (data[2] & 0xc0) == 0x80) |
| 886 | { |
| 887 | result = Traits::low(result, ((lead & ~0xE0) << 12) | ((data[1] & utf8_byte_mask) << 6) | (data[2] & utf8_byte_mask)); |
| 888 | data += 3; |
| 889 | size -= 3; |
| 890 | } |
| 891 | // 11110xxx -> U+10000..U+10FFFF |
| 892 | else if (static_cast<unsigned int>(lead - 0xF0) < 0x08 && size >= 4 && (data[1] & 0xc0) == 0x80 && (data[2] & 0xc0) == 0x80 && (data[3] & 0xc0) == 0x80) |
| 893 | { |
| 894 | result = Traits::high(result, ((lead & ~0xF0) << 18) | ((data[1] & utf8_byte_mask) << 12) | ((data[2] & utf8_byte_mask) << 6) | (data[3] & utf8_byte_mask)); |
| 895 | data += 4; |
| 896 | size -= 4; |
| 897 | } |
| 898 | // 10xxxxxx or 11111xxx -> invalid |
| 899 | else |
| 900 | { |
| 901 | data += 1; |
| 902 | size -= 1; |
| 903 | } |
| 904 | } |
nothing calls this directly
no outgoing calls
no test coverage detected