| 1672 | typedef uint8_t type; |
| 1673 | |
| 1674 | template <typename Traits> static inline typename Traits::value_type process(const uint8_t* data, size_t size, typename Traits::value_type result, Traits) |
| 1675 | { |
| 1676 | const uint8_t utf8_byte_mask = 0x3f; |
| 1677 | |
| 1678 | while (size) |
| 1679 | { |
| 1680 | uint8_t lead = *data; |
| 1681 | |
| 1682 | // 0xxxxxxx -> U+0000..U+007F |
| 1683 | if (lead < 0x80) |
| 1684 | { |
| 1685 | result = Traits::low(result, lead); |
| 1686 | data += 1; |
| 1687 | size -= 1; |
| 1688 | |
| 1689 | // process aligned single-byte (ascii) blocks |
| 1690 | if ((reinterpret_cast<uintptr_t>(data) & 3) == 0) |
| 1691 | { |
| 1692 | // round-trip through void* to silence 'cast increases required alignment of target type' warnings |
| 1693 | while (size >= 4 && (*static_cast<const uint32_t*>(static_cast<const void*>(data)) & 0x80808080) == 0) |
| 1694 | { |
| 1695 | result = Traits::low(result, data[0]); |
| 1696 | result = Traits::low(result, data[1]); |
| 1697 | result = Traits::low(result, data[2]); |
| 1698 | result = Traits::low(result, data[3]); |
| 1699 | data += 4; |
| 1700 | size -= 4; |
| 1701 | } |
| 1702 | } |
| 1703 | } |
| 1704 | // 110xxxxx -> U+0080..U+07FF |
| 1705 | else if (static_cast<unsigned int>(lead - 0xC0) < 0x20 && size >= 2 && (data[1] & 0xc0) == 0x80) |
| 1706 | { |
| 1707 | result = Traits::low(result, ((lead & ~0xC0) << 6) | (data[1] & utf8_byte_mask)); |
| 1708 | data += 2; |
| 1709 | size -= 2; |
| 1710 | } |
| 1711 | // 1110xxxx -> U+0800-U+FFFF |
| 1712 | else if (static_cast<unsigned int>(lead - 0xE0) < 0x10 && size >= 3 && (data[1] & 0xc0) == 0x80 && (data[2] & 0xc0) == 0x80) |
| 1713 | { |
| 1714 | result = Traits::low(result, ((lead & ~0xE0) << 12) | ((data[1] & utf8_byte_mask) << 6) | (data[2] & utf8_byte_mask)); |
| 1715 | data += 3; |
| 1716 | size -= 3; |
| 1717 | } |
| 1718 | // 11110xxx -> U+10000..U+10FFFF |
| 1719 | else if (static_cast<unsigned int>(lead - 0xF0) < 0x08 && size >= 4 && (data[1] & 0xc0) == 0x80 && (data[2] & 0xc0) == 0x80 && (data[3] & 0xc0) == 0x80) |
| 1720 | { |
| 1721 | result = Traits::high(result, ((lead & ~0xF0) << 18) | ((data[1] & utf8_byte_mask) << 12) | ((data[2] & utf8_byte_mask) << 6) | (data[3] & utf8_byte_mask)); |
| 1722 | data += 4; |
| 1723 | size -= 4; |
| 1724 | } |
| 1725 | // 10xxxxxx or 11111xxx -> invalid |
| 1726 | else |
| 1727 | { |
| 1728 | data += 1; |
| 1729 | size -= 1; |
| 1730 | } |
| 1731 | } |
no outgoing calls
no test coverage detected