1#ifndef SIMDUTF_UTF32_TO_UTF8_H
2#define SIMDUTF_UTF32_TO_UTF8_H
9namespace utf32_to_utf8 {
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>)
16simdutf_constexpr23
size_t convert(InputPtr data,
size_t len,
17 OutputPtr utf8_output) {
19 auto start = utf8_output;
21#if SIMDUTF_CPLUSPLUS23
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]);
38 uint32_t word = data[pos];
39 if ((word & 0xFFFFFF80) == 0) {
41 *utf8_output++ = char(word);
43 }
else if ((word & 0xFFFFF800) == 0) {
46 *utf8_output++ = char((word >> 6) | 0b11000000);
47 *utf8_output++ = char((word & 0b111111) | 0b10000000);
49 }
else if ((word & 0xFFFF0000) == 0) {
52 if (word >= 0xD800 && word <= 0xDFFF) {
55 *utf8_output++ = char((word >> 12) | 0b11100000);
56 *utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
57 *utf8_output++ = char((word & 0b111111) | 0b10000000);
62 if (word > 0x10FFFF) {
65 *utf8_output++ = char((word >> 18) | 0b11110000);
66 *utf8_output++ = char(((word >> 12) & 0b111111) | 0b10000000);
67 *utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
68 *utf8_output++ = char((word & 0b111111) | 0b10000000);
72 return utf8_output - start;
75template <
typename InputPtr,
typename OutputPtr>
76#if SIMDUTF_CPLUSPLUS20
77 requires(simdutf::detail::indexes_into_utf32<InputPtr> &&
78 simdutf::detail::index_assignable_from_char<OutputPtr>)
80simdutf_constexpr23 result convert_with_errors(InputPtr data,
size_t len,
81 OutputPtr utf8_output) {
83 auto start = utf8_output;
85#if SIMDUTF_CPLUSPLUS23
92 ::memcpy(&v, data + pos,
sizeof(uint64_t));
93 if ((v & 0xFFFFFF80FFFFFF80) == 0) {
94 *utf8_output++ = char(data[pos]);
95 *utf8_output++ = char(data[pos + 1]);
102 uint32_t word = data[pos];
103 if ((word & 0xFFFFFF80) == 0) {
105 *utf8_output++ = char(word);
107 }
else if ((word & 0xFFFFF800) == 0) {
110 *utf8_output++ = char((word >> 6) | 0b11000000);
111 *utf8_output++ = char((word & 0b111111) | 0b10000000);
113 }
else if ((word & 0xFFFF0000) == 0) {
116 if (word >= 0xD800 && word <= 0xDFFF) {
117 return result(error_code::SURROGATE, pos);
119 *utf8_output++ = char((word >> 12) | 0b11100000);
120 *utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
121 *utf8_output++ = char((word & 0b111111) | 0b10000000);
126 if (word > 0x10FFFF) {
127 return result(error_code::TOO_LARGE, pos);
129 *utf8_output++ = char((word >> 18) | 0b11110000);
130 *utf8_output++ = char(((word >> 12) & 0b111111) | 0b10000000);
131 *utf8_output++ = char(((word >> 6) & 0b111111) | 0b10000000);
132 *utf8_output++ = char((word & 0b111111) | 0b10000000);
136 return result(error_code::SUCCESS, utf8_output - start);
helpers placed in namespace detail are not a part of the public API