simdutf 9.0.0
Unicode at GB/s.
Loading...
Searching...
No Matches
valid_utf8_to_utf32.h
1#ifndef SIMDUTF_VALID_UTF8_TO_UTF32_H
2#define SIMDUTF_VALID_UTF8_TO_UTF32_H
3
4#include <cstring>
5
6namespace simdutf {
7namespace scalar {
8namespace {
9namespace utf8_to_utf32 {
10
11template <typename InputPtr>
12#if SIMDUTF_CPLUSPLUS20
13 requires simdutf::detail::indexes_into_byte_like<InputPtr>
14#endif
15simdutf_constexpr23 size_t convert_valid(InputPtr data, size_t len,
16 char32_t *utf32_output) {
17 size_t pos = 0;
18 char32_t *start{utf32_output};
19 while (pos < len) {
20#if SIMDUTF_CPLUSPLUS23
21 if !consteval
22#endif
23 {
24 // try to convert the next block of 8 ASCII bytes
25 if (pos + 8 <= len) { // if it is safe to read 8 more bytes, check that
26 // they are ascii
27 uint64_t v;
28 ::memcpy(&v, data + pos, sizeof(uint64_t));
29 if ((v & 0x8080808080808080) == 0) {
30 size_t final_pos = pos + 8;
31 while (pos < final_pos) {
32 *utf32_output++ = uint8_t(data[pos]);
33 pos++;
34 }
35 continue;
36 }
37 }
38 }
39 auto leading_byte = uint8_t(data[pos]); // leading byte
40 if (leading_byte < 0b10000000) {
41 // converting one ASCII byte !!!
42 *utf32_output++ = char32_t(leading_byte);
43 pos++;
44 } else if ((leading_byte & 0b11100000) == 0b11000000) {
45 // We have a two-byte UTF-8
46 if (pos + 1 >= len) {
47 break;
48 } // minimal bound checking
49 *utf32_output++ = char32_t(((leading_byte & 0b00011111) << 6) |
50 (uint8_t(data[pos + 1]) & 0b00111111));
51 pos += 2;
52 } else if ((leading_byte & 0b11110000) == 0b11100000) {
53 // We have a three-byte UTF-8
54 if (pos + 2 >= len) {
55 break;
56 } // minimal bound checking
57 *utf32_output++ = char32_t(((leading_byte & 0b00001111) << 12) |
58 ((uint8_t(data[pos + 1]) & 0b00111111) << 6) |
59 (uint8_t(data[pos + 2]) & 0b00111111));
60 pos += 3;
61 } else if ((leading_byte & 0b11111000) == 0b11110000) { // 0b11110000
62 // we have a 4-byte UTF-8 word.
63 if (pos + 3 >= len) {
64 break;
65 } // minimal bound checking
66 uint32_t code_word = ((leading_byte & 0b00000111) << 18) |
67 ((uint8_t(data[pos + 1]) & 0b00111111) << 12) |
68 ((uint8_t(data[pos + 2]) & 0b00111111) << 6) |
69 (uint8_t(data[pos + 3]) & 0b00111111);
70 *utf32_output++ = char32_t(code_word);
71 pos += 4;
72 } else {
73 // we may have a continuation but we do not do error checking
74 return 0;
75 }
76 }
77 return utf32_output - start;
78}
79
80} // namespace utf8_to_utf32
81} // unnamed namespace
82} // namespace scalar
83} // namespace simdutf
84
85#endif
helpers placed in namespace detail are not a part of the public API