simdutf 9.0.0
Unicode at GB/s.
Loading...
Searching...
No Matches
valid_utf32_to_utf8.h
1#ifndef SIMDUTF_VALID_UTF32_TO_UTF8_H
2#define SIMDUTF_VALID_UTF32_TO_UTF8_H
3
4#include <cstring>
5
6namespace simdutf {
7namespace scalar {
8namespace {
9namespace utf32_to_utf8 {
10
11template <typename InputPtr, typename OutputPtr>
12#if SIMDUTF_CPLUSPLUS20
13 requires(simdutf::detail::indexes_into_utf32<InputPtr> &&
14 simdutf::detail::index_assignable_from_char<OutputPtr>)
15#endif
16simdutf_constexpr23 size_t convert_valid(InputPtr data, size_t len,
17 OutputPtr utf8_output) {
18 size_t pos = 0;
19 auto start = utf8_output;
20 while (pos < len) {
21#if SIMDUTF_CPLUSPLUS23
22 if !consteval
23#endif
24 { // try to convert the next block of 2 ASCII characters
25 if (pos + 2 <= 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 & 0xFFFFFF80FFFFFF80) == 0) {
30 *utf8_output++ = char(data[pos]);
31 *utf8_output++ = char(data[pos + 1]);
32 pos += 2;
33 continue;
34 }
35 }
36 }
37
38 uint32_t word = data[pos];
39 if ((word & 0xFFFFFF80) == 0) {
40 // will generate one UTF-8 bytes
41 *utf8_output++ = char(word);
42 pos++;
43 } else if ((word & 0xFFFFF800) == 0) {
44 // will generate two UTF-8 bytes
45 // we have 0b110XXXXX 0b10XXXXXX
46 *utf8_output++ = char((word >> 6) | 0b11000000);
47 *utf8_output++ = char((word & 0b111111) | 0b10000000);
48 pos++;
49 } else if ((word & 0xFFFF0000) == 0) {
50 // will generate three UTF-8 bytes
51 // we have 0b1110XXXX 0b10XXXXXX 0b10XXXXXX
52 *utf8_output++ = char((word >> 12) | 0b11100000);
53 *utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
54 *utf8_output++ = char((word & 0b111111) | 0b10000000);
55 pos++;
56 } else {
57 // will generate four UTF-8 bytes
58 // we have 0b11110XXX 0b10XXXXXX 0b10XXXXXX 0b10XXXXXX
59 *utf8_output++ = char((word >> 18) | 0b11110000);
60 *utf8_output++ = char(((word >> 12) & 0b111111) | 0b10000000);
61 *utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
62 *utf8_output++ = char((word & 0b111111) | 0b10000000);
63 pos++;
64 }
65 }
66 return utf8_output - start;
67}
68
69} // namespace utf32_to_utf8
70} // unnamed namespace
71} // namespace scalar
72} // namespace simdutf
73
74#endif
helpers placed in namespace detail are not a part of the public API