12template <
class BytePtr>
13simdutf_constexpr23 simdutf_warn_unused
bool validate(BytePtr data,
14 size_t len)
noexcept {
16 std::is_same<
typename std::decay<
decltype(*data)>::type, uint8_t>::value,
17 "dereferencing the data pointer must result in a uint8_t");
19 uint32_t code_point = 0;
22#if SIMDUTF_CPLUSPLUS23
27 if (next_pos <= len) {
30 std::memcpy(&v1, data + pos,
sizeof(uint64_t));
32 std::memcpy(&v2, data + pos +
sizeof(uint64_t),
sizeof(uint64_t));
34 if ((v & 0x8080808080808080) == 0) {
41 unsigned char byte = data[pos];
43 while (
byte < 0b10000000) {
50 if ((
byte & 0b11100000) == 0b11000000) {
55 if ((data[pos + 1] & 0b11000000) != 0b10000000) {
59 code_point = (
byte & 0b00011111) << 6 | (data[pos + 1] & 0b00111111);
60 if (code_point < 0x80) {
63 }
else if ((
byte & 0b11110000) == 0b11100000) {
68 if ((data[pos + 1] & 0b11000000) != 0b10000000) {
71 if ((data[pos + 2] & 0b11000000) != 0b10000000) {
75 code_point = (
byte & 0b00001111) << 12 |
76 (data[pos + 1] & 0b00111111) << 6 |
77 (data[pos + 2] & 0b00111111);
78 if ((code_point < 0x800) ||
79 (0xd7ff < code_point && code_point < 0xe000)) {
82 }
else if ((
byte & 0b11111000) == 0b11110000) {
87 if ((data[pos + 1] & 0b11000000) != 0b10000000) {
90 if ((data[pos + 2] & 0b11000000) != 0b10000000) {
93 if ((data[pos + 3] & 0b11000000) != 0b10000000) {
98 (
byte & 0b00000111) << 18 | (data[pos + 1] & 0b00111111) << 12 |
99 (data[pos + 2] & 0b00111111) << 6 | (data[pos + 3] & 0b00111111);
100 if (code_point <= 0xffff || 0x10ffff < code_point) {
112simdutf_really_inline simdutf_warn_unused
bool validate(
const char *buf,
113 size_t len)
noexcept {
114 return validate(
reinterpret_cast<const uint8_t *
>(buf), len);
117template <
class BytePtr>
118simdutf_constexpr23 simdutf_warn_unused result
119validate_with_errors(BytePtr data,
size_t len)
noexcept {
121 std::is_same<
typename std::decay<
decltype(*data)>::type, uint8_t>::value,
122 "dereferencing the data pointer must result in a uint8_t");
124 uint32_t code_point = 0;
127 size_t next_pos = pos + 16;
131 std::memcpy(&v1, data + pos,
sizeof(uint64_t));
133 std::memcpy(&v2, data + pos +
sizeof(uint64_t),
sizeof(uint64_t));
135 if ((v & 0x8080808080808080) == 0) {
140 unsigned char byte = data[pos];
142 while (
byte < 0b10000000) {
144 return result(error_code::SUCCESS, len);
149 if ((
byte & 0b11100000) == 0b11000000) {
151 if (next_pos > len) {
152 return result(error_code::TOO_SHORT, pos);
154 if ((data[pos + 1] & 0b11000000) != 0b10000000) {
155 return result(error_code::TOO_SHORT, pos);
158 code_point = (
byte & 0b00011111) << 6 | (data[pos + 1] & 0b00111111);
159 if (code_point < 0x80) {
160 return result(error_code::OVERLONG, pos);
162 }
else if ((
byte & 0b11110000) == 0b11100000) {
164 if (next_pos > len) {
165 return result(error_code::TOO_SHORT, pos);
167 if ((data[pos + 1] & 0b11000000) != 0b10000000) {
168 return result(error_code::TOO_SHORT, pos);
170 if ((data[pos + 2] & 0b11000000) != 0b10000000) {
171 return result(error_code::TOO_SHORT, pos);
174 code_point = (
byte & 0b00001111) << 12 |
175 (data[pos + 1] & 0b00111111) << 6 |
176 (data[pos + 2] & 0b00111111);
177 if (code_point < 0x800) {
178 return result(error_code::OVERLONG, pos);
180 if (0xd7ff < code_point && code_point < 0xe000) {
181 return result(error_code::SURROGATE, pos);
183 }
else if ((
byte & 0b11111000) == 0b11110000) {
185 if (next_pos > len) {
186 return result(error_code::TOO_SHORT, pos);
188 if ((data[pos + 1] & 0b11000000) != 0b10000000) {
189 return result(error_code::TOO_SHORT, pos);
191 if ((data[pos + 2] & 0b11000000) != 0b10000000) {
192 return result(error_code::TOO_SHORT, pos);
194 if ((data[pos + 3] & 0b11000000) != 0b10000000) {
195 return result(error_code::TOO_SHORT, pos);
199 (
byte & 0b00000111) << 18 | (data[pos + 1] & 0b00111111) << 12 |
200 (data[pos + 2] & 0b00111111) << 6 | (data[pos + 3] & 0b00111111);
201 if (code_point <= 0xffff) {
202 return result(error_code::OVERLONG, pos);
204 if (0x10ffff < code_point) {
205 return result(error_code::TOO_LARGE, pos);
209 if ((
byte & 0b11000000) == 0b10000000) {
210 return result(error_code::TOO_LONG, pos);
212 return result(error_code::HEADER_BITS, pos);
217 return result(error_code::SUCCESS, len);
220simdutf_really_inline simdutf_warn_unused result
221validate_with_errors(
const char *buf,
size_t len)
noexcept {
222 return validate_with_errors(
reinterpret_cast<const uint8_t *
>(buf), len);
231inline simdutf_warn_unused result rewind_and_validate_with_errors(
232 const char *start,
const char *buf,
size_t len)
noexcept {
234 if ((*start & 0b11000000) == 0b10000000) {
235 return result(error_code::TOO_LONG, 0);
239 for (
int i = 0; i < 5; i++) {
240 unsigned char byte = *buf;
241 if ((
byte & 0b11000000) != 0b10000000) {
249 result res = validate_with_errors(buf, len + extra_len);
250 res.count -= extra_len;
254template <
typename InputPtr>
255#if SIMDUTF_CPLUSPLUS20
256 requires simdutf::detail::indexes_into_byte_like<InputPtr>
258simdutf_constexpr23
size_t count_code_points(InputPtr data,
size_t len) {
260 for (
size_t i = 0; i < len; i++) {
263 if (int8_t(data[i]) > -65) {
270template <
typename InputPtr>
271#if SIMDUTF_CPLUSPLUS20
272 requires simdutf::detail::indexes_into_byte_like<InputPtr>
276 for (
size_t i = 0; i < len; i++) {
277 if (int8_t(data[i]) > -65) {
280 if (uint8_t(data[i]) >= 240) {
287template <
typename InputPtr>
288#if SIMDUTF_CPLUSPLUS20
289 requires simdutf::detail::indexes_into_byte_like<InputPtr>
291simdutf_warn_unused simdutf_constexpr23
size_t
296 if (uint8_t(input[length - 1]) >= 0xc0) {
299 if (uint8_t(input[length - 2]) >= 0xe0) {
304 if (uint8_t(input[length - 1]) >= 0xc0) {
312 if (uint8_t(input[length - 1]) >= 0xc0) {
315 if (uint8_t(input[length - 2]) >= 0xe0) {
318 if (uint8_t(input[length - 3]) >= 0xf0) {
helpers placed in namespace detail are not a part of the public API
simdutf_warn_unused size_t utf16_length_from_utf8(const char *input, size_t length) noexcept
Compute the number of 2-byte code units that this UTF-8 string would require in UTF-16LE format.
simdutf_warn_unused size_t trim_partial_utf8(const char *input, size_t length)
Given a valid UTF-8 string having a possibly truncated last character, this function checks the end o...