simdutf 9.3.3
Unicode at GB/s.
Loading...
Searching...
No Matches
implementation.h
1#ifndef SIMDUTF_IMPLEMENTATION_H
2#define SIMDUTF_IMPLEMENTATION_H
3#if !defined(SIMDUTF_NO_THREADS)
4 #include <atomic>
5#endif
6#ifdef SIMDUTF_INTERNAL_TESTS
7 #include <vector>
8#endif
9#include "simdutf/common_defs.h"
10#include "simdutf/compiler_check.h"
11#include "simdutf/encoding_types.h"
12#include "simdutf/error.h"
13#include "simdutf/internal/isadetection.h"
14
15#include <string_view>
16#if SIMDUTF_SPAN
17 #include <concepts>
18 #include <type_traits>
19 #include <span>
20 #include <tuple>
21 #include <utility> // for std::unreachable
22#endif
23// The following defines are conditionally enabled/disabled during amalgamation.
24// By default all features are enabled, regular code shouldn't check them. Only
25// when user code really relies of a selected subset, it's good to verify these
26// flags, like:
27//
28// #if !SIMDUTF_FEATURE_UTF16
29// # error("Please amalgamate simdutf with UTF-16 support")
30// #endif
31//
32#ifndef SIMDUTF_FEATURE_DETECT_ENCODING
33 #define SIMDUTF_FEATURE_DETECT_ENCODING 1
34#endif
35#ifndef SIMDUTF_FEATURE_ASCII
36 #define SIMDUTF_FEATURE_ASCII 1
37#endif
38#ifndef SIMDUTF_FEATURE_LATIN1
39 #define SIMDUTF_FEATURE_LATIN1 1
40#endif
41#ifndef SIMDUTF_FEATURE_UTF8
42 #define SIMDUTF_FEATURE_UTF8 1
43#endif
44#ifndef SIMDUTF_FEATURE_UTF16
45 #define SIMDUTF_FEATURE_UTF16 1
46#endif
47#ifndef SIMDUTF_FEATURE_UTF32
48 #define SIMDUTF_FEATURE_UTF32 1
49#endif
50#ifndef SIMDUTF_FEATURE_BASE64
51 #define SIMDUTF_FEATURE_BASE64 1
52#endif
53
54/// helpers placed in namespace detail are not a part of the public API
55namespace simdutf {
56namespace detail {
57namespace {
58// this is to avoid including <algorithm> just for min
59constexpr std::size_t min(std::size_t a, std::size_t b) {
60 return a < b ? a : b;
61}
62template <typename T, typename U>
63constexpr std::size_t min(const T &a, const U &b) = delete;
64} // namespace
65} // namespace detail
66} // namespace simdutf
67
68#if SIMDUTF_CPLUSPLUS23
69 #include <simdutf/constexpr_ptr.h>
70#endif
71
72#if SIMDUTF_SPAN
73/// helpers placed in namespace detail are not a part of the public API
74namespace simdutf {
75namespace detail {
76/**
77 * matches a byte, in the many ways C++ allows. note that these
78 * are all distinct types.
79 */
80template <typename T>
81concept byte_like = std::is_same_v<T, std::byte> || //
82 std::is_same_v<T, char> || //
83 std::is_same_v<T, signed char> || //
84 std::is_same_v<T, unsigned char> || //
85 std::is_same_v<T, char8_t>;
86
87template <typename T>
88concept is_byte_like = byte_like<std::remove_cvref_t<T>>;
89
90template <typename T>
91concept is_pointer = std::is_pointer_v<T>;
92
93/**
94 * matches anything that behaves like std::span and points to character-like
95 * data such as: std::byte, char, unsigned char, signed char, std::int8_t,
96 * std::uint8_t
97 */
98template <typename T>
99concept input_span_of_byte_like = requires(const T &t) {
100 { t.size() } noexcept -> std::convertible_to<std::size_t>;
101 { t.data() } noexcept -> is_pointer;
102 { *t.data() } noexcept -> is_byte_like;
103};
104
105template <typename T>
106concept is_mutable = !std::is_const_v<std::remove_reference_t<T>>;
107
108/**
109 * like span_of_byte_like, but for an output span (intended to be written to)
110 */
111template <typename T>
112concept output_span_of_byte_like = requires(T &t) {
113 { t.size() } noexcept -> std::convertible_to<std::size_t>;
114 { t.data() } noexcept -> is_pointer;
115 { *t.data() } noexcept -> is_byte_like;
116 { *t.data() } noexcept -> is_mutable;
117};
118
119 #if SIMDUTF_CPLUSPLUS23
120// Give the scalar base64 code a char copy of a non-char span (constexpr only).
121template <typename F> constexpr auto with_char_input(const auto &input, F &&f) {
122 using T = std::remove_cvref_t<decltype(*input.data())>;
123 if constexpr (std::is_same_v<T, char>) {
124 return f(input.data());
125 } else {
126 char *copy = new char[input.size()];
127 for (std::size_t i = 0; i < input.size(); i++) {
128 copy[i] = static_cast<char>(input.data()[i]);
129 }
130 auto r = f(static_cast<const char *>(copy));
131 delete[] copy;
132 return r;
133 }
134}
135
136// Copy back only the written(r) bytes, leaving the rest of the output alone.
137template <typename F, typename W>
138constexpr auto with_char_output(auto &&output, F &&f, W &&written) {
139 using T = std::remove_cvref_t<decltype(*output.data())>;
140 if constexpr (std::is_same_v<T, char>) {
141 return f(output.data());
142 } else {
143 char *copy = new char[output.size()];
144 auto r = f(copy);
145 const std::size_t n = written(r);
146 for (std::size_t i = 0; i < n; i++) {
147 output.data()[i] = static_cast<T>(copy[i]);
148 }
149 delete[] copy;
150 return r;
151 }
152}
153 #endif // SIMDUTF_CPLUSPLUS23
154
155/**
156 * a pointer like object, when indexed, results in a byte like result.
157 * valid examples: char*, const char*, std::array<char,10>
158 * invalid examples: int*, std::array<int,10>
159 */
160template <class InputPtr>
161concept indexes_into_byte_like = requires(InputPtr p) {
162 { std::decay_t<decltype(p[0])>{} } -> simdutf::detail::byte_like;
163};
164template <class InputPtr>
165concept indexes_into_utf16 = requires(InputPtr p) {
166 { std::decay_t<decltype(p[0])>{} } -> std::same_as<char16_t>;
167};
168template <class InputPtr>
169concept indexes_into_utf32 = requires(InputPtr p) {
170 { std::decay_t<decltype(p[0])>{} } -> std::same_as<char32_t>;
171};
172
173template <class InputPtr>
174concept index_assignable_from_char = requires(InputPtr p, char s) {
175 { p[0] = s };
176};
177
178/**
179 * a pointer like object that results in a uint32_t when indexed.
180 * valid examples: uint32_t*
181 */
182template <class InputPtr>
183concept indexes_into_uint32 = requires(InputPtr p) {
184 { std::decay_t<decltype(p[0])>{} } -> std::same_as<std::uint32_t>;
185};
186} // namespace detail
187} // namespace simdutf
188#endif // SIMDUTF_SPAN
189
190// these includes are needed for constexpr support. they are
191// not part of the public api.
192#include <simdutf/scalar/swap_bytes.h>
193#include <simdutf/scalar/ascii.h>
194#include <simdutf/scalar/atomic_util.h>
195#include <simdutf/scalar/latin1.h>
196#include <simdutf/scalar/latin1_to_utf16/latin1_to_utf16.h>
197#include <simdutf/scalar/latin1_to_utf32/latin1_to_utf32.h>
198#include <simdutf/scalar/latin1_to_utf8/latin1_to_utf8.h>
199#include <simdutf/scalar/utf16.h>
200#include <simdutf/scalar/utf16_to_latin1/utf16_to_latin1.h>
201#include <simdutf/scalar/utf16_to_latin1/valid_utf16_to_latin1.h>
202#include <simdutf/scalar/utf16_to_utf32/utf16_to_utf32.h>
203#include <simdutf/scalar/utf16_to_utf32/valid_utf16_to_utf32.h>
204#include <simdutf/scalar/utf16_to_utf8/utf16_to_utf8.h>
205#include <simdutf/scalar/utf16_to_utf8/valid_utf16_to_utf8.h>
206#include <simdutf/scalar/utf32.h>
207#include <simdutf/scalar/utf32_to_latin1/utf32_to_latin1.h>
208#include <simdutf/scalar/utf32_to_latin1/valid_utf32_to_latin1.h>
209#include <simdutf/scalar/utf32_to_utf16/utf32_to_utf16.h>
210#include <simdutf/scalar/utf32_to_utf16/valid_utf32_to_utf16.h>
211#include <simdutf/scalar/utf32_to_utf8/utf32_to_utf8.h>
212#include <simdutf/scalar/utf32_to_utf8/valid_utf32_to_utf8.h>
213#include <simdutf/scalar/utf8.h>
214#include <simdutf/scalar/utf8_to_latin1/utf8_to_latin1.h>
215#include <simdutf/scalar/utf8_to_latin1/valid_utf8_to_latin1.h>
216#include <simdutf/scalar/utf8_to_utf16/utf8_to_utf16.h>
217#include <simdutf/scalar/utf8_to_utf16/utf8_to_utf16_with_replacement.h>
218#include <simdutf/scalar/utf8_to_utf16/valid_utf8_to_utf16.h>
219#include <simdutf/scalar/utf8_to_utf32/utf8_to_utf32.h>
220#include <simdutf/scalar/utf8_to_utf32/valid_utf8_to_utf32.h>
221
222namespace simdutf {
223
224constexpr size_t default_line_length =
225 76; ///< default line length for base64 encoding with lines
226
227#if SIMDUTF_FEATURE_DETECT_ENCODING
228/**
229 * Autodetect the encoding of the input, a single encoding is recommended.
230 * E.g., the function might return simdutf::encoding_type::UTF8,
231 * simdutf::encoding_type::UTF16_LE, simdutf::encoding_type::UTF16_BE, or
232 * simdutf::encoding_type::UTF32_LE.
233 *
234 * @param input the string to analyze.
235 * @param length the length of the string in bytes.
236 * @return the detected encoding type
237 */
238simdutf_warn_unused simdutf::encoding_type
239autodetect_encoding(const char *input, size_t length) noexcept;
240simdutf_really_inline simdutf_warn_unused simdutf::encoding_type
241autodetect_encoding(const uint8_t *input, size_t length) noexcept {
242 return autodetect_encoding(reinterpret_cast<const char *>(input), length);
243}
244 #if SIMDUTF_SPAN
245/**
246 * Autodetect the encoding of the input, a single encoding is recommended.
247 * E.g., the function might return simdutf::encoding_type::UTF8,
248 * simdutf::encoding_type::UTF16_LE, simdutf::encoding_type::UTF16_BE, or
249 * simdutf::encoding_type::UTF32_LE.
250 *
251 * @param input the string to analyze. can be a anything span-like that has a
252 * data() and size() that points to character data: std::string,
253 * std::string_view, std::vector<char>, std::span<const std::byte> etc.
254 * @return the detected encoding type
255 */
256simdutf_really_inline simdutf_warn_unused simdutf::encoding_type
258 const detail::input_span_of_byte_like auto &input) noexcept {
259 return autodetect_encoding(reinterpret_cast<const char *>(input.data()),
260 input.size());
261}
262 #endif // SIMDUTF_SPAN
263
264/**
265 * Autodetect the possible encodings of the input in one pass.
266 * E.g., if the input might be UTF-16LE or UTF-8, this function returns
267 * the value (simdutf::encoding_type::UTF8 | simdutf::encoding_type::UTF16_LE).
268 *
269 * Overridden by each implementation.
270 *
271 * @param input the string to analyze.
272 * @param length the length of the string in bytes.
273 * @return the detected encoding type
274 */
275simdutf_warn_unused int detect_encodings(const char *input,
276 size_t length) noexcept;
277simdutf_really_inline simdutf_warn_unused int
278detect_encodings(const uint8_t *input, size_t length) noexcept {
279 return detect_encodings(reinterpret_cast<const char *>(input), length);
280}
281 #if SIMDUTF_SPAN
282simdutf_really_inline simdutf_warn_unused int
283detect_encodings(const detail::input_span_of_byte_like auto &input) noexcept {
284 return detect_encodings(reinterpret_cast<const char *>(input.data()),
285 input.size());
286}
287 #endif // SIMDUTF_SPAN
288#endif // SIMDUTF_FEATURE_DETECT_ENCODING
289
290#if SIMDUTF_FEATURE_UTF8 || SIMDUTF_FEATURE_DETECT_ENCODING
291/**
292 * Validate the UTF-8 string. This function may be best when you expect
293 * the input to be almost always valid. Otherwise, consider using
294 * validate_utf8_with_errors.
295 *
296 * Overridden by each implementation.
297 *
298 * @param buf the UTF-8 string to validate.
299 * @param len the length of the string in bytes.
300 * @return true if and only if the string is valid UTF-8.
301 */
302simdutf_warn_unused bool validate_utf8(const char *buf, size_t len) noexcept;
303 #if SIMDUTF_SPAN
304simdutf_constexpr23 simdutf_really_inline simdutf_warn_unused bool
305validate_utf8(const detail::input_span_of_byte_like auto &input) noexcept {
306 #if SIMDUTF_CPLUSPLUS23
307 if consteval {
308 return scalar::utf8::validate(
309 detail::constexpr_cast_ptr<uint8_t>(input.data()), input.size());
310 } else
311 #endif
312 {
313 return validate_utf8(reinterpret_cast<const char *>(input.data()),
314 input.size());
315 }
316}
317 #endif // SIMDUTF_SPAN
318#endif // SIMDUTF_FEATURE_UTF8 || SIMDUTF_FEATURE_DETECT_ENCODING
319
320#if SIMDUTF_FEATURE_UTF8
321/**
322 * Validate the UTF-8 string and stop on error.
323 *
324 * Overridden by each implementation.
325 *
326 * @param buf the UTF-8 string to validate.
327 * @param len the length of the string in bytes.
328 * @return a result pair struct (of type simdutf::result containing the two
329 * fields error and count) with an error code and either position of the error
330 * (in the input in code units) if any, or the number of code units validated if
331 * successful.
332 */
333simdutf_warn_unused result validate_utf8_with_errors(const char *buf,
334 size_t len) noexcept;
335 #if SIMDUTF_SPAN
336simdutf_really_inline simdutf_constexpr23 simdutf_warn_unused result
338 const detail::input_span_of_byte_like auto &input) noexcept {
339 #if SIMDUTF_CPLUSPLUS23
340 if consteval {
341 return scalar::utf8::validate_with_errors(
342 detail::constexpr_cast_ptr<uint8_t>(input.data()), input.size());
343 } else
344 #endif
345 {
347 reinterpret_cast<const char *>(input.data()), input.size());
348 }
349}
350 #endif // SIMDUTF_SPAN
351#endif // SIMDUTF_FEATURE_UTF8
352
353#if SIMDUTF_FEATURE_UTF8
354/**
355 * Validate the UTF-8 string and stop on error, while counting the number of
356 * continuation bytes and of four-byte sequences in the valid prefix.
357 *
358 * Overridden by each implementation.
359 *
360 * These two counts are enough to derive, without a second pass over the input,
361 * both the number of code points (input_count - continuation_count) and the
362 * number of UTF-16 code units (input_count - continuation_count +
363 * four_byte_count) of the valid prefix. The utf32_length() and utf16_length()
364 * helpers return them.
365 *
366 * @param buf the UTF-8 string to validate.
367 * @param len the length of the string in bytes.
368 * @return a utf8_result struct with an error code, the number of bytes in the
369 * valid prefix (input_count), and the counts of continuation bytes and of
370 * four-byte sequences within it.
371 */
372simdutf_warn_unused utf8_result validate_utf8_with_counts(const char *buf,
373 size_t len) noexcept;
374 #if SIMDUTF_SPAN
375simdutf_really_inline simdutf_constexpr23 simdutf_warn_unused utf8_result
377 const detail::input_span_of_byte_like auto &input) noexcept {
378 #if SIMDUTF_CPLUSPLUS23
379 if consteval {
380 return scalar::utf8::validate_with_counts(
381 detail::constexpr_cast_ptr<uint8_t>(input.data()), input.size());
382 } else
383 #endif
384 {
386 reinterpret_cast<const char *>(input.data()), input.size());
387 }
388}
389 #endif // SIMDUTF_SPAN
390#endif // SIMDUTF_FEATURE_UTF8
391
392#if SIMDUTF_FEATURE_ASCII
393/**
394 * Validate the ASCII string.
395 *
396 * Overridden by each implementation.
397 *
398 * @param buf the ASCII string to validate.
399 * @param len the length of the string in bytes.
400 * @return true if and only if the string is valid ASCII.
401 */
402simdutf_warn_unused bool validate_ascii(const char *buf, size_t len) noexcept;
403 #if SIMDUTF_SPAN
404simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 bool
405validate_ascii(const detail::input_span_of_byte_like auto &input) noexcept {
406 #if SIMDUTF_CPLUSPLUS23
407 if consteval {
408 return scalar::ascii::validate(
409 detail::constexpr_cast_ptr<std::uint8_t>(input.data()), input.size());
410 } else
411 #endif
412 {
413 return validate_ascii(reinterpret_cast<const char *>(input.data()),
414 input.size());
415 }
416}
417 #endif // SIMDUTF_SPAN
418
419/**
420 * Validate the ASCII string and stop on error. It might be faster than
421 * validate_utf8 when an error is expected to occur early.
422 *
423 * Overridden by each implementation.
424 *
425 * @param buf the ASCII string to validate.
426 * @param len the length of the string in bytes.
427 * @return a result pair struct (of type simdutf::result containing the two
428 * fields error and count) with an error code and either position of the error
429 * (in the input in code units) if any, or the number of code units validated if
430 * successful.
431 */
432simdutf_warn_unused result validate_ascii_with_errors(const char *buf,
433 size_t len) noexcept;
434 #if SIMDUTF_SPAN
435simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
437 const detail::input_span_of_byte_like auto &input) noexcept {
438 #if SIMDUTF_CPLUSPLUS23
439 if consteval {
440 return scalar::ascii::validate_with_errors(
441 detail::constexpr_cast_ptr<std::uint8_t>(input.data()), input.size());
442 } else
443 #endif
444 {
446 reinterpret_cast<const char *>(input.data()), input.size());
447 }
448}
449 #endif // SIMDUTF_SPAN
450#endif // SIMDUTF_FEATURE_ASCII
451
452#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_ASCII
453/**
454 * Validate the ASCII string as a UTF-16 sequence.
455 * An UTF-16 sequence is considered an ASCII sequence
456 * if it could be converted to an ASCII string losslessly.
457 *
458 * Overridden by each implementation.
459 *
460 * @param buf the UTF-16 string to validate.
461 * @param len the length of the string in bytes.
462 * @return true if and only if the string is valid ASCII.
463 */
464simdutf_warn_unused bool validate_utf16_as_ascii(const char16_t *buf,
465 size_t len) noexcept;
466 #if SIMDUTF_SPAN
467simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 bool
468validate_utf16_as_ascii(std::span<const char16_t> input) noexcept {
469 #if SIMDUTF_CPLUSPLUS23
470 if consteval {
471 return scalar::utf16::validate_as_ascii<endianness::NATIVE>(input.data(),
472 input.size());
473 } else
474 #endif
475 {
476 return validate_utf16_as_ascii(input.data(), input.size());
477 }
478}
479 #endif // SIMDUTF_SPAN
480
481/**
482 * Validate the ASCII string as a UTF-16BE sequence.
483 * An UTF-16 sequence is considered an ASCII sequence
484 * if it could be converted to an ASCII string losslessly.
485 *
486 * Overridden by each implementation.
487 *
488 * @param buf the UTF-16BE string to validate.
489 * @param len the length of the string in bytes.
490 * @return true if and only if the string is valid ASCII.
491 */
492simdutf_warn_unused bool validate_utf16be_as_ascii(const char16_t *buf,
493 size_t len) noexcept;
494 #if SIMDUTF_SPAN
495simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 bool
496validate_utf16be_as_ascii(std::span<const char16_t> input) noexcept {
497 #if SIMDUTF_CPLUSPLUS23
498 if consteval {
499 return scalar::utf16::validate_as_ascii<endianness::BIG>(input.data(),
500 input.size());
501 } else
502 #endif
503 {
504 return validate_utf16be_as_ascii(input.data(), input.size());
505 }
506}
507 #endif // SIMDUTF_SPAN
508
509/**
510 * Validate the ASCII string as a UTF-16LE sequence.
511 * An UTF-16 sequence is considered an ASCII sequence
512 * if it could be converted to an ASCII string losslessly.
513 *
514 * Overridden by each implementation.
515 *
516 * @param buf the UTF-16LE string to validate.
517 * @param len the length of the string in bytes.
518 * @return true if and only if the string is valid ASCII.
519 */
520simdutf_warn_unused bool validate_utf16le_as_ascii(const char16_t *buf,
521 size_t len) noexcept;
522 #if SIMDUTF_SPAN
523simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 bool
524validate_utf16le_as_ascii(std::span<const char16_t> input) noexcept {
525 #if SIMDUTF_CPLUSPLUS23
526 if consteval {
527 return scalar::utf16::validate_as_ascii<endianness::LITTLE>(input.data(),
528 input.size());
529 } else
530 #endif
531 {
532 return validate_utf16le_as_ascii(input.data(), input.size());
533 }
534}
535 #endif // SIMDUTF_SPAN
536#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_ASCII
537
538#if SIMDUTF_FEATURE_UTF16
539/**
540 * Using native endianness; Validate the UTF-16 string.
541 * This function may be best when you expect the input to be almost always
542 * valid. Otherwise, consider using validate_utf16_with_errors.
543 *
544 * Overridden by each implementation.
545 *
546 * This function is not BOM-aware.
547 *
548 * @param buf the UTF-16 string to validate.
549 * @param len the length of the string in number of 2-byte code units
550 * (char16_t).
551 * @return true if and only if the string is valid UTF-16.
552 */
553simdutf_warn_unused bool validate_utf16(const char16_t *buf,
554 size_t len) noexcept;
555 #if SIMDUTF_SPAN
556simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 bool
557validate_utf16(std::span<const char16_t> input) noexcept {
558 #if SIMDUTF_CPLUSPLUS23
559 if consteval {
560 return scalar::utf16::validate<endianness::NATIVE>(input.data(),
561 input.size());
562 } else
563 #endif
564 {
565 return validate_utf16(input.data(), input.size());
566 }
567}
568 #endif // SIMDUTF_SPAN
569#endif // SIMDUTF_FEATURE_UTF16
570
571#if SIMDUTF_FEATURE_UTF16 || SIMDUTF_FEATURE_DETECT_ENCODING
572/**
573 * Validate the UTF-16LE string. This function may be best when you expect
574 * the input to be almost always valid. Otherwise, consider using
575 * validate_utf16le_with_errors.
576 *
577 * Overridden by each implementation.
578 *
579 * This function is not BOM-aware.
580 *
581 * @param buf the UTF-16LE string to validate.
582 * @param len the length of the string in number of 2-byte code units
583 * (char16_t).
584 * @return true if and only if the string is valid UTF-16LE.
585 */
586simdutf_warn_unused bool validate_utf16le(const char16_t *buf,
587 size_t len) noexcept;
588 #if SIMDUTF_SPAN
589simdutf_really_inline simdutf_constexpr23 simdutf_warn_unused bool
590validate_utf16le(std::span<const char16_t> input) noexcept {
591 #if SIMDUTF_CPLUSPLUS23
592 if consteval {
593 return scalar::utf16::validate<endianness::LITTLE>(input.data(),
594 input.size());
595 } else
596 #endif
597 {
598 return validate_utf16le(input.data(), input.size());
599 }
600}
601 #endif // SIMDUTF_SPAN
602#endif // SIMDUTF_FEATURE_UTF16 || SIMDUTF_FEATURE_DETECT_ENCODING
603
604#if SIMDUTF_FEATURE_UTF16
605/**
606 * Validate the UTF-16BE string. This function may be best when you expect
607 * the input to be almost always valid. Otherwise, consider using
608 * validate_utf16be_with_errors.
609 *
610 * Overridden by each implementation.
611 *
612 * This function is not BOM-aware.
613 *
614 * @param buf the UTF-16BE string to validate.
615 * @param len the length of the string in number of 2-byte code units
616 * (char16_t).
617 * @return true if and only if the string is valid UTF-16BE.
618 */
619simdutf_warn_unused bool validate_utf16be(const char16_t *buf,
620 size_t len) noexcept;
621 #if SIMDUTF_SPAN
622simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 bool
623validate_utf16be(std::span<const char16_t> input) noexcept {
624 #if SIMDUTF_CPLUSPLUS23
625 if consteval {
626 return scalar::utf16::validate<endianness::BIG>(input.data(), input.size());
627 } else
628 #endif
629 {
630 return validate_utf16be(input.data(), input.size());
631 }
632}
633 #endif // SIMDUTF_SPAN
634
635/**
636 * Using native endianness; Validate the UTF-16 string and stop on error.
637 * It might be faster than validate_utf16 when an error is expected to occur
638 * early.
639 *
640 * Overridden by each implementation.
641 *
642 * This function is not BOM-aware.
643 *
644 * @param buf the UTF-16 string to validate.
645 * @param len the length of the string in number of 2-byte code units
646 * (char16_t).
647 * @return a result pair struct (of type simdutf::result containing the two
648 * fields error and count) with an error code and either position of the error
649 * (in the input in code units) if any, or the number of code units validated if
650 * successful.
651 */
652simdutf_warn_unused result validate_utf16_with_errors(const char16_t *buf,
653 size_t len) noexcept;
654 #if SIMDUTF_SPAN
655simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
656validate_utf16_with_errors(std::span<const char16_t> input) noexcept {
657 #if SIMDUTF_CPLUSPLUS23
658 if consteval {
659 return scalar::utf16::validate_with_errors<endianness::NATIVE>(
660 input.data(), input.size());
661 } else
662 #endif
663 {
664 return validate_utf16_with_errors(input.data(), input.size());
665 }
666}
667 #endif // SIMDUTF_SPAN
668
669/**
670 * Validate the UTF-16LE string and stop on error. It might be faster than
671 * validate_utf16le when an error is expected to occur early.
672 *
673 * Overridden by each implementation.
674 *
675 * This function is not BOM-aware.
676 *
677 * @param buf the UTF-16LE string to validate.
678 * @param len the length of the string in number of 2-byte code units
679 * (char16_t).
680 * @return a result pair struct (of type simdutf::result containing the two
681 * fields error and count) with an error code and either position of the error
682 * (in the input in code units) if any, or the number of code units validated if
683 * successful.
684 */
685simdutf_warn_unused result validate_utf16le_with_errors(const char16_t *buf,
686 size_t len) noexcept;
687 #if SIMDUTF_SPAN
688simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
689validate_utf16le_with_errors(std::span<const char16_t> input) noexcept {
690 #if SIMDUTF_CPLUSPLUS23
691 if consteval {
692 return scalar::utf16::validate_with_errors<endianness::LITTLE>(
693 input.data(), input.size());
694 } else
695 #endif
696 {
697 return validate_utf16le_with_errors(input.data(), input.size());
698 }
699}
700 #endif // SIMDUTF_SPAN
701
702/**
703 * Validate the UTF-16BE string and stop on error. It might be faster than
704 * validate_utf16be when an error is expected to occur early.
705 *
706 * Overridden by each implementation.
707 *
708 * This function is not BOM-aware.
709 *
710 * @param buf the UTF-16BE string to validate.
711 * @param len the length of the string in number of 2-byte code units
712 * (char16_t).
713 * @return a result pair struct (of type simdutf::result containing the two
714 * fields error and count) with an error code and either position of the error
715 * (in the input in code units) if any, or the number of code units validated if
716 * successful.
717 */
718simdutf_warn_unused result validate_utf16be_with_errors(const char16_t *buf,
719 size_t len) noexcept;
720 #if SIMDUTF_SPAN
721simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
722validate_utf16be_with_errors(std::span<const char16_t> input) noexcept {
723 #if SIMDUTF_CPLUSPLUS23
724 if consteval {
725 return scalar::utf16::validate_with_errors<endianness::BIG>(input.data(),
726 input.size());
727 } else
728 #endif
729 {
730 return validate_utf16be_with_errors(input.data(), input.size());
731 }
732}
733 #endif // SIMDUTF_SPAN
734
735/**
736 * Fixes an ill-formed UTF-16LE string by replacing mismatched surrogates with
737 * the Unicode replacement character U+FFFD. If input and output points to
738 * different memory areas, the procedure copies string, and it's expected that
739 * output memory is at least as big as the input. It's also possible to set
740 * input equal output, that makes replacements an in-place operation.
741 *
742 * @param input the UTF-16LE string to correct.
743 * @param len the length of the string in number of 2-byte code units
744 * (char16_t).
745 * @param output the output buffer.
746 */
747void to_well_formed_utf16le(const char16_t *input, size_t len,
748 char16_t *output) noexcept;
749 #if SIMDUTF_SPAN
750simdutf_really_inline simdutf_constexpr23 void
751to_well_formed_utf16le(std::span<const char16_t> input,
752 std::span<char16_t> output) noexcept {
753 #if SIMDUTF_CPLUSPLUS23
754 if consteval {
755 scalar::utf16::to_well_formed_utf16<endianness::LITTLE>(
756 input.data(), input.size(), output.data());
757 } else
758 #endif
759 {
760 to_well_formed_utf16le(input.data(), input.size(), output.data());
761 }
762}
763 #endif // SIMDUTF_SPAN
764
765/**
766 * Fixes an ill-formed UTF-16BE string by replacing mismatched surrogates with
767 * the Unicode replacement character U+FFFD. If input and output points to
768 * different memory areas, the procedure copies string, and it's expected that
769 * output memory is at least as big as the input. It's also possible to set
770 * input equal output, that makes replacements an in-place operation.
771 *
772 * @param input the UTF-16BE string to correct.
773 * @param len the length of the string in number of 2-byte code units
774 * (char16_t).
775 * @param output the output buffer.
776 */
777void to_well_formed_utf16be(const char16_t *input, size_t len,
778 char16_t *output) noexcept;
779 #if SIMDUTF_SPAN
780simdutf_really_inline simdutf_constexpr23 void
781to_well_formed_utf16be(std::span<const char16_t> input,
782 std::span<char16_t> output) noexcept {
783 #if SIMDUTF_CPLUSPLUS23
784 if consteval {
785 scalar::utf16::to_well_formed_utf16<endianness::BIG>(
786 input.data(), input.size(), output.data());
787 } else
788 #endif
789 {
790 to_well_formed_utf16be(input.data(), input.size(), output.data());
791 }
792}
793 #endif // SIMDUTF_SPAN
794
795/**
796 * Fixes an ill-formed UTF-16 string by replacing mismatched surrogates with the
797 * Unicode replacement character U+FFFD. If input and output points to different
798 * memory areas, the procedure copies string, and it's expected that output
799 * memory is at least as big as the input. It's also possible to set input equal
800 * output, that makes replacements an in-place operation.
801 *
802 * @param input the UTF-16 string to correct.
803 * @param len the length of the string in number of 2-byte code units
804 * (char16_t).
805 * @param output the output buffer.
806 */
807void to_well_formed_utf16(const char16_t *input, size_t len,
808 char16_t *output) noexcept;
809 #if SIMDUTF_SPAN
810simdutf_really_inline simdutf_constexpr23 void
811to_well_formed_utf16(std::span<const char16_t> input,
812 std::span<char16_t> output) noexcept {
813 #if SIMDUTF_CPLUSPLUS23
814 if consteval {
815 scalar::utf16::to_well_formed_utf16<endianness::NATIVE>(
816 input.data(), input.size(), output.data());
817 } else
818 #endif
819 {
820 to_well_formed_utf16(input.data(), input.size(), output.data());
821 }
822}
823 #endif // SIMDUTF_SPAN
824
825#endif // SIMDUTF_FEATURE_UTF16
826
827#if SIMDUTF_FEATURE_UTF32 || SIMDUTF_FEATURE_DETECT_ENCODING
828/**
829 * Validate the UTF-32 string. This function may be best when you expect
830 * the input to be almost always valid. Otherwise, consider using
831 * validate_utf32_with_errors.
832 *
833 * Overridden by each implementation.
834 *
835 * This function is not BOM-aware.
836 *
837 * @param buf the UTF-32 string to validate.
838 * @param len the length of the string in number of 4-byte code units
839 * (char32_t).
840 * @return true if and only if the string is valid UTF-32.
841 */
842simdutf_warn_unused bool validate_utf32(const char32_t *buf,
843 size_t len) noexcept;
844 #if SIMDUTF_SPAN
845simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 bool
846validate_utf32(std::span<const char32_t> input) noexcept {
847 #if SIMDUTF_CPLUSPLUS23
848 if consteval {
849 return scalar::utf32::validate(
850 detail::constexpr_cast_ptr<std::uint32_t>(input.data()), input.size());
851 } else
852 #endif
853 {
854 return validate_utf32(input.data(), input.size());
855 }
856}
857 #endif // SIMDUTF_SPAN
858#endif // SIMDUTF_FEATURE_UTF32 || SIMDUTF_FEATURE_DETECT_ENCODING
859
860#if SIMDUTF_FEATURE_UTF32
861/**
862 * Validate the UTF-32 string and stop on error. It might be faster than
863 * validate_utf32 when an error is expected to occur early.
864 *
865 * Overridden by each implementation.
866 *
867 * This function is not BOM-aware.
868 *
869 * @param buf the UTF-32 string to validate.
870 * @param len the length of the string in number of 4-byte code units
871 * (char32_t).
872 * @return a result pair struct (of type simdutf::result containing the two
873 * fields error and count) with an error code and either position of the error
874 * (in the input in code units) if any, or the number of code units validated if
875 * successful.
876 */
877simdutf_warn_unused result validate_utf32_with_errors(const char32_t *buf,
878 size_t len) noexcept;
879 #if SIMDUTF_SPAN
880simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
881validate_utf32_with_errors(std::span<const char32_t> input) noexcept {
882 #if SIMDUTF_CPLUSPLUS23
883 if consteval {
884 return scalar::utf32::validate_with_errors(
885 detail::constexpr_cast_ptr<std::uint32_t>(input.data()), input.size());
886 } else
887 #endif
888 {
889 return validate_utf32_with_errors(input.data(), input.size());
890 }
891}
892 #endif // SIMDUTF_SPAN
893#endif // SIMDUTF_FEATURE_UTF32
894
895#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
896/**
897 * Convert Latin1 string into UTF-8 string.
898 *
899 * This function is suitable to work with inputs from untrusted sources.
900 *
901 * @param input the Latin1 string to convert
902 * @param length the length of the string in bytes
903 * @param utf8_output the pointer to buffer that can hold conversion result
904 * @return the number of written char; 0 if conversion is not possible
905 */
906simdutf_warn_unused size_t convert_latin1_to_utf8(const char *input,
907 size_t length,
908 char *utf8_output) noexcept;
909 #if SIMDUTF_SPAN
910simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
912 const detail::input_span_of_byte_like auto &latin1_input,
913 detail::output_span_of_byte_like auto &&utf8_output) noexcept {
914 #if SIMDUTF_CPLUSPLUS23
915 if consteval {
916 return scalar::latin1_to_utf8::convert(
917 detail::constexpr_cast_ptr<char>(latin1_input.data()),
918 latin1_input.size(),
919 detail::constexpr_cast_writeptr<char>(utf8_output.data()));
920 } else
921 #endif
922 {
924 reinterpret_cast<const char *>(latin1_input.data()),
925 latin1_input.size(), reinterpret_cast<char *>(utf8_output.data()));
926 }
927}
928 #endif // SIMDUTF_SPAN
929
930/**
931 * Convert Latin1 string into UTF-8 string with output limit.
932 *
933 * This function is suitable to work with inputs from untrusted sources.
934 *
935 * We write as many characters as possible.
936 *
937 * Using convert_latin1_to_utf8_safe instead of convert_latin1_to_utf8 comes
938 * with a significant penalty in some cases, being up to four times slower,
939 * especially on short inputs. If you have allocated the output buffer so that
940 * it contains utf8_length_from_latin1(input, length) bytes, then prefer
941 * convert_latin1_to_utf8.
942 *
943 * @param input the Latin1 string to convert
944 * @param length the length of the string in bytes
945 * @param utf8_output the pointer to buffer that can hold conversion result
946 * @param utf8_len the maximum output length
947 * @return the number of written char; 0 if conversion is not possible
948 */
949simdutf_warn_unused size_t
950convert_latin1_to_utf8_safe(const char *input, size_t length, char *utf8_output,
951 size_t utf8_len) noexcept;
952 #if SIMDUTF_SPAN
953simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
955 const detail::input_span_of_byte_like auto &input,
956 detail::output_span_of_byte_like auto &&utf8_output) noexcept {
957 // implementation note: outputspan is a forwarding ref to avoid copying
958 // and allow both lvalues and rvalues. std::span can be copied without
959 // problems, but std::vector should not, and this function should accept
960 // both. it will allow using an owning rvalue ref (example: passing a
961 // temporary std::string) as output, but the user will quickly find out
962 // that he has no way of getting the data out of the object in that case.
963 #if SIMDUTF_CPLUSPLUS23
964 if consteval {
965 return scalar::latin1_to_utf8::convert_safe_constexpr(
966 input.data(), input.size(), utf8_output.data(), utf8_output.size());
967 } else
968 #endif
969 {
971 reinterpret_cast<const char *>(input.data()), input.size(),
972 reinterpret_cast<char *>(utf8_output.data()), utf8_output.size());
973 }
974}
975 #endif // SIMDUTF_SPAN
976
977/**
978 * Convert a Latin1 string into a size-limited UTF-8 buffer and report how much
979 * input was consumed and output was written.
980 *
981 * We write as many complete characters as possible. The returned error is
982 * SUCCESS if all input was consumed, or OUTPUT_BUFFER_TOO_SMALL otherwise.
983 *
984 * @param input the Latin1 string to convert
985 * @param length the length of the string in bytes
986 * @param utf8_output the pointer to the output buffer
987 * @param utf8_len the maximum output length
988 * @return a full_result with error, input_count and output_count
989 */
991 const char *input, size_t length, char *utf8_output,
992 size_t utf8_len) noexcept;
993 #if SIMDUTF_SPAN
994simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 full_result
996 const detail::input_span_of_byte_like auto &input,
997 detail::output_span_of_byte_like auto &&utf8_output) noexcept {
998 #if SIMDUTF_CPLUSPLUS23
999 if consteval {
1000 return scalar::latin1_to_utf8::convert_safe_with_details_constexpr(
1001 input.data(), input.size(), utf8_output.data(), utf8_output.size());
1002 } else
1003 #endif
1004 {
1006 reinterpret_cast<const char *>(input.data()), input.size(),
1007 reinterpret_cast<char *>(utf8_output.data()), utf8_output.size());
1008 }
1009}
1010 #endif // SIMDUTF_SPAN
1011#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
1012
1013#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
1014/**
1015 * Convert possibly Latin1 string into UTF-16LE string.
1016 *
1017 * This function is suitable to work with inputs from untrusted sources.
1018 *
1019 * @param input the Latin1 string to convert
1020 * @param length the length of the string in bytes
1021 * @param utf16_output the pointer to buffer that can hold conversion result
1022 * @return the number of written char16_t; 0 if conversion is not possible
1023 */
1024simdutf_warn_unused size_t convert_latin1_to_utf16le(
1025 const char *input, size_t length, char16_t *utf16_output) noexcept;
1026 #if SIMDUTF_SPAN
1027simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
1029 const detail::input_span_of_byte_like auto &latin1_input,
1030 std::span<char16_t> utf16_output) noexcept {
1031 #if SIMDUTF_CPLUSPLUS23
1032 if consteval {
1033 return scalar::latin1_to_utf16::convert<endianness::LITTLE>(
1034 latin1_input.data(), latin1_input.size(), utf16_output.data());
1035 } else
1036 #endif
1037 {
1039 reinterpret_cast<const char *>(latin1_input.data()),
1040 latin1_input.size(), utf16_output.data());
1041 }
1042}
1043 #endif // SIMDUTF_SPAN
1044
1045/**
1046 * Convert Latin1 string into UTF-16BE string.
1047 *
1048 * This function is suitable to work with inputs from untrusted sources.
1049 *
1050 * @param input the Latin1 string to convert
1051 * @param length the length of the string in bytes
1052 * @param utf16_output the pointer to buffer that can hold conversion result
1053 * @return the number of written char16_t; 0 if conversion is not possible
1054 */
1055simdutf_warn_unused size_t convert_latin1_to_utf16be(
1056 const char *input, size_t length, char16_t *utf16_output) noexcept;
1057 #if SIMDUTF_SPAN
1058simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
1059convert_latin1_to_utf16be(const detail::input_span_of_byte_like auto &input,
1060 std::span<char16_t> output) noexcept {
1061 #if SIMDUTF_CPLUSPLUS23
1062 if consteval {
1063 return scalar::latin1_to_utf16::convert<endianness::BIG>(
1064 input.data(), input.size(), output.data());
1065 } else
1066 #endif
1067 {
1069 reinterpret_cast<const char *>(input.data()), input.size(),
1070 output.data());
1071 }
1072}
1073 #endif // SIMDUTF_SPAN
1074/**
1075 * Compute the number of bytes that this UTF-16 string would require in Latin1
1076 * format.
1077 *
1078 * @param length the length of the string in Latin1 code units (char)
1079 * @return the length of the string in Latin1 code units (char) required to
1080 * encode the UTF-16 string as Latin1
1081 */
1082simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
1083latin1_length_from_utf16(size_t length) noexcept {
1084 return length;
1085}
1086
1087/**
1088 * Compute the number of code units that this Latin1 string would require in
1089 * UTF-16 format.
1090 *
1091 * @param length the length of the string in Latin1 code units (char)
1092 * @return the length of the string in 2-byte code units (char16_t) required to
1093 * encode the Latin1 string as UTF-16
1094 */
1095simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
1096utf16_length_from_latin1(size_t length) noexcept {
1097 return length;
1098}
1099#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
1100
1101#if SIMDUTF_FEATURE_UTF32 && SIMDUTF_FEATURE_LATIN1
1102/**
1103 * Convert Latin1 string into UTF-32 string.
1104 *
1105 * This function is suitable to work with inputs from untrusted sources.
1106 *
1107 * @param input the Latin1 string to convert
1108 * @param length the length of the string in bytes
1109 * @param utf32_buffer the pointer to buffer that can hold conversion result
1110 * @return the number of written char32_t; 0 if conversion is not possible
1111 */
1112simdutf_warn_unused size_t convert_latin1_to_utf32(
1113 const char *input, size_t length, char32_t *utf32_buffer) noexcept;
1114 #if SIMDUTF_SPAN
1115simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
1117 const detail::input_span_of_byte_like auto &latin1_input,
1118 std::span<char32_t> utf32_output) noexcept {
1119 #if SIMDUTF_CPLUSPLUS23
1120 if consteval {
1121 return scalar::latin1_to_utf32::convert(
1122 latin1_input.data(), latin1_input.size(), utf32_output.data());
1123 } else
1124 #endif
1125 {
1127 reinterpret_cast<const char *>(latin1_input.data()),
1128 latin1_input.size(), utf32_output.data());
1129 }
1130}
1131 #endif // SIMDUTF_SPAN
1132#endif // SIMDUTF_FEATURE_UTF32 && SIMDUTF_FEATURE_LATIN1
1133
1134#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
1135/**
1136 * Convert possibly broken UTF-8 string into latin1 string.
1137 *
1138 * During the conversion also validation of the input string is done.
1139 * This function is suitable to work with inputs from untrusted sources.
1140 *
1141 * @param input the UTF-8 string to convert
1142 * @param length the length of the string in bytes
1143 * @param latin1_output the pointer to buffer that can hold conversion result
1144 * @return the number of written char; 0 if the input was not valid UTF-8 string
1145 * or if it cannot be represented as Latin1
1146 */
1147simdutf_warn_unused size_t convert_utf8_to_latin1(const char *input,
1148 size_t length,
1149 char *latin1_output) noexcept;
1150 #if SIMDUTF_SPAN
1151simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
1153 const detail::input_span_of_byte_like auto &input,
1154 detail::output_span_of_byte_like auto &&output) noexcept {
1155 #if SIMDUTF_CPLUSPLUS23
1156 if consteval {
1157 return scalar::utf8_to_latin1::convert(input.data(), input.size(),
1158 output.data());
1159 } else
1160 #endif
1161 {
1162 return convert_utf8_to_latin1(reinterpret_cast<const char *>(input.data()),
1163 input.size(),
1164 reinterpret_cast<char *>(output.data()));
1165 }
1166}
1167 #endif // SIMDUTF_SPAN
1168#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
1169
1170#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1171/**
1172 * Using native endianness, convert possibly broken UTF-8 string into a UTF-16
1173 * string.
1174 *
1175 * During the conversion also validation of the input string is done.
1176 * This function is suitable to work with inputs from untrusted sources.
1177 *
1178 * @param input the UTF-8 string to convert
1179 * @param length the length of the string in bytes
1180 * @param utf16_output the pointer to buffer that can hold conversion result
1181 * @return the number of written char16_t; 0 if the input was not valid UTF-8
1182 * string
1183 */
1184simdutf_warn_unused size_t convert_utf8_to_utf16(
1185 const char *input, size_t length, char16_t *utf16_output) noexcept;
1186 #if SIMDUTF_SPAN
1187simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
1188convert_utf8_to_utf16(const detail::input_span_of_byte_like auto &input,
1189 std::span<char16_t> output) noexcept {
1190 #if SIMDUTF_CPLUSPLUS23
1191 if consteval {
1192 return scalar::utf8_to_utf16::convert<endianness::NATIVE>(
1193 input.data(), input.size(), output.data());
1194 } else
1195 #endif
1196 {
1197 return convert_utf8_to_utf16(reinterpret_cast<const char *>(input.data()),
1198 input.size(), output.data());
1199 }
1200}
1201 #endif // SIMDUTF_SPAN
1202
1203/**
1204 * Compute the number of bytes that this UTF-16LE string would require in UTF-8
1205 * format even when the UTF-16LE content contains mismatched surrogates
1206 * that have to be replaced by the replacement character (0xFFFD).
1207 *
1208 * @param input the UTF-16LE string to convert
1209 * @param length the length of the string in 2-byte code units (char16_t)
1210 * @return a result pair struct (of type simdutf::result containing the two
1211 * fields error and count) where the count is the number of bytes required to
1212 * encode the UTF-16LE string as UTF-8, and the error code is either SUCCESS or
1213 * SURROGATE. The count is correct regardless of the error field.
1214 * When SURROGATE is returned, it does not indicate an error in the case of this
1215 * function: it indicates that at least one surrogate has been encountered: the
1216 * surrogates may be matched or not (thus this function does not validate). If
1217 * the returned error code is SUCCESS, then the input contains no surrogate, is
1218 * in the Basic Multilingual Plane, and is necessarily valid.
1219 */
1221 const char16_t *input, size_t length) noexcept;
1222 #if SIMDUTF_SPAN
1223simdutf_really_inline simdutf_constexpr23 simdutf_warn_unused result
1225 std::span<const char16_t> valid_utf16_input) noexcept {
1226 #if SIMDUTF_CPLUSPLUS23
1227 if consteval {
1228 return scalar::utf16::utf8_length_from_utf16_with_replacement<
1229 endianness::LITTLE>(valid_utf16_input.data(), valid_utf16_input.size());
1230 } else
1231 #endif
1232 {
1233 return utf8_length_from_utf16le_with_replacement(valid_utf16_input.data(),
1234 valid_utf16_input.size());
1235 }
1236}
1237 #endif // SIMDUTF_SPAN
1238
1239/**
1240 * Compute the number of bytes that this UTF-16BE string would require in UTF-8
1241 * format even when the UTF-16BE content contains mismatched surrogates
1242 * that have to be replaced by the replacement character (0xFFFD).
1243 *
1244 * @param input the UTF-16BE string to convert
1245 * @param length the length of the string in 2-byte code units (char16_t)
1246 * @return a result pair struct (of type simdutf::result containing the two
1247 * fields error and count) where the count is the number of bytes required to
1248 * encode the UTF-16BE string as UTF-8, and the error code is either SUCCESS or
1249 * SURROGATE. The count is correct regardless of the error field.
1250 * When SURROGATE is returned, it does not indicate an error in the case of this
1251 * function: it indicates that at least one surrogate has been encountered: the
1252 * surrogates may be matched or not (thus this function does not validate). If
1253 * the returned error code is SUCCESS, then the input contains no surrogate, is
1254 * in the Basic Multilingual Plane, and is necessarily valid.
1255 */
1257 const char16_t *input, size_t length) noexcept;
1258 #if SIMDUTF_SPAN
1259simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
1261 std::span<const char16_t> valid_utf16_input) noexcept {
1262 #if SIMDUTF_CPLUSPLUS23
1263 if consteval {
1264 return scalar::utf16::utf8_length_from_utf16_with_replacement<
1265 endianness::BIG>(valid_utf16_input.data(), valid_utf16_input.size());
1266 } else
1267 #endif
1268 {
1269 return utf8_length_from_utf16be_with_replacement(valid_utf16_input.data(),
1270 valid_utf16_input.size());
1271 }
1272}
1273 #endif // SIMDUTF_SPAN
1274
1275#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1276
1277#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
1278/**
1279 * Using native endianness, convert a Latin1 string into a UTF-16 string.
1280 *
1281 * @param input the Latin1 string to convert
1282 * @param length the length of the string in bytes
1283 * @param utf16_output the pointer to buffer that can hold conversion result
1284 * @return the number of written char16_t.
1285 */
1286simdutf_warn_unused size_t convert_latin1_to_utf16(
1287 const char *input, size_t length, char16_t *utf16_output) noexcept;
1288 #if SIMDUTF_SPAN
1289simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
1290convert_latin1_to_utf16(const detail::input_span_of_byte_like auto &input,
1291 std::span<char16_t> output) noexcept {
1292 #if SIMDUTF_CPLUSPLUS23
1293 if consteval {
1294 return scalar::latin1_to_utf16::convert<endianness::NATIVE>(
1295 input.data(), input.size(), output.data());
1296 } else
1297 #endif
1298 {
1299 return convert_latin1_to_utf16(reinterpret_cast<const char *>(input.data()),
1300 input.size(), output.data());
1301 }
1302}
1303 #endif // SIMDUTF_SPAN
1304#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
1305
1306#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1307/**
1308 * Convert possibly broken UTF-8 string into UTF-16LE string.
1309 *
1310 * During the conversion also validation of the input string is done.
1311 * This function is suitable to work with inputs from untrusted sources.
1312 *
1313 * @param input the UTF-8 string to convert
1314 * @param length the length of the string in bytes
1315 * @param utf16_output the pointer to buffer that can hold conversion result
1316 * @return the number of written char16_t; 0 if the input was not valid UTF-8
1317 * string
1318 */
1319simdutf_warn_unused size_t convert_utf8_to_utf16le(
1320 const char *input, size_t length, char16_t *utf16_output) noexcept;
1321 #if SIMDUTF_SPAN
1322simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
1323convert_utf8_to_utf16le(const detail::input_span_of_byte_like auto &utf8_input,
1324 std::span<char16_t> utf16_output) noexcept {
1325 #if SIMDUTF_CPLUSPLUS23
1326 if consteval {
1327 return scalar::utf8_to_utf16::convert<endianness::LITTLE>(
1328 utf8_input.data(), utf8_input.size(), utf16_output.data());
1329 } else
1330 #endif
1331 {
1333 reinterpret_cast<const char *>(utf8_input.data()), utf8_input.size(),
1334 utf16_output.data());
1335 }
1336}
1337 #endif // SIMDUTF_SPAN
1338
1339/**
1340 * Convert possibly broken UTF-8 string into UTF-16BE string.
1341 *
1342 * During the conversion also validation of the input string is done.
1343 * This function is suitable to work with inputs from untrusted sources.
1344 *
1345 * @param input the UTF-8 string to convert
1346 * @param length the length of the string in bytes
1347 * @param utf16_output the pointer to buffer that can hold conversion result
1348 * @return the number of written char16_t; 0 if the input was not valid UTF-8
1349 * string
1350 */
1351simdutf_warn_unused size_t convert_utf8_to_utf16be(
1352 const char *input, size_t length, char16_t *utf16_output) noexcept;
1353 #if SIMDUTF_SPAN
1354simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
1355convert_utf8_to_utf16be(const detail::input_span_of_byte_like auto &utf8_input,
1356 std::span<char16_t> utf16_output) noexcept {
1357
1358 #if SIMDUTF_CPLUSPLUS23
1359 if consteval {
1360 return scalar::utf8_to_utf16::convert<endianness::BIG>(
1361 utf8_input.data(), utf8_input.size(), utf16_output.data());
1362 } else
1363 #endif
1364 {
1366 reinterpret_cast<const char *>(utf8_input.data()), utf8_input.size(),
1367 utf16_output.data());
1368 }
1369}
1370 #endif // SIMDUTF_SPAN
1371#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1372
1373#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
1374/**
1375 * Convert possibly broken UTF-8 string into latin1 string with errors.
1376 * If the string cannot be represented as Latin1, an error
1377 * code is returned.
1378 *
1379 * During the conversion also validation of the input string is done.
1380 * This function is suitable to work with inputs from untrusted sources.
1381 *
1382 * @param input the UTF-8 string to convert
1383 * @param length the length of the string in bytes
1384 * @param latin1_output the pointer to buffer that can hold conversion result
1385 * @return a result pair struct (of type simdutf::result containing the two
1386 * fields error and count) with an error code and either position of the error
1387 * (in the input in code units) if any, or the number of code units validated if
1388 * successful.
1389 */
1391 const char *input, size_t length, char *latin1_output) noexcept;
1392 #if SIMDUTF_SPAN
1393simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
1395 const detail::input_span_of_byte_like auto &utf8_input,
1396 detail::output_span_of_byte_like auto &&latin1_output) noexcept {
1397 #if SIMDUTF_CPLUSPLUS23
1398 if consteval {
1399 return scalar::utf8_to_latin1::convert_with_errors(
1400 utf8_input.data(), utf8_input.size(), latin1_output.data());
1401 } else
1402 #endif
1403 {
1405 reinterpret_cast<const char *>(utf8_input.data()), utf8_input.size(),
1406 reinterpret_cast<char *>(latin1_output.data()));
1407 }
1408}
1409 #endif // SIMDUTF_SPAN
1410#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
1411
1412#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1413/**
1414 * Using native endianness, convert possibly broken UTF-8 string into UTF-16
1415 * string and stop on error.
1416 *
1417 * During the conversion also validation of the input string is done.
1418 * This function is suitable to work with inputs from untrusted sources.
1419 *
1420 * @param input the UTF-8 string to convert
1421 * @param length the length of the string in bytes
1422 * @param utf16_output the pointer to buffer that can hold conversion result
1423 * @return a result pair struct (of type simdutf::result containing the two
1424 * fields error and count) with an error code and either position of the error
1425 * (in the input in code units) if any, or the number of char16_t written if
1426 * successful.
1427 */
1429 const char *input, size_t length, char16_t *utf16_output) noexcept;
1430 #if SIMDUTF_SPAN
1431simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
1433 const detail::input_span_of_byte_like auto &utf8_input,
1434 std::span<char16_t> utf16_output) noexcept {
1435 #if SIMDUTF_CPLUSPLUS23
1436 if consteval {
1437 return scalar::utf8_to_utf16::convert_with_errors<endianness::NATIVE>(
1438 utf8_input.data(), utf8_input.size(), utf16_output.data());
1439 } else
1440 #endif
1441 {
1443 reinterpret_cast<const char *>(utf8_input.data()), utf8_input.size(),
1444 utf16_output.data());
1445 }
1446}
1447 #endif // SIMDUTF_SPAN
1448
1449/**
1450 * Convert possibly broken UTF-8 string into UTF-16LE string and stop on error.
1451 *
1452 * During the conversion also validation of the input string is done.
1453 * This function is suitable to work with inputs from untrusted sources.
1454 *
1455 * @param input the UTF-8 string to convert
1456 * @param length the length of the string in bytes
1457 * @param utf16_output the pointer to buffer that can hold conversion result
1458 * @return a result pair struct (of type simdutf::result containing the two
1459 * fields error and count) with an error code and either position of the error
1460 * (in the input in code units) if any, or the number of char16_t written if
1461 * successful.
1462 */
1464 const char *input, size_t length, char16_t *utf16_output) noexcept;
1465 #if SIMDUTF_SPAN
1466simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
1468 const detail::input_span_of_byte_like auto &utf8_input,
1469 std::span<char16_t> utf16_output) noexcept {
1470 #if SIMDUTF_CPLUSPLUS23
1471 if consteval {
1472 return scalar::utf8_to_utf16::convert_with_errors<endianness::LITTLE>(
1473 utf8_input.data(), utf8_input.size(), utf16_output.data());
1474 } else
1475 #endif
1476 {
1478 reinterpret_cast<const char *>(utf8_input.data()), utf8_input.size(),
1479 utf16_output.data());
1480 }
1481}
1482 #endif // SIMDUTF_SPAN
1483
1484/**
1485 * Convert possibly broken UTF-8 string into UTF-16BE string and stop on error.
1486 *
1487 * During the conversion also validation of the input string is done.
1488 * This function is suitable to work with inputs from untrusted sources.
1489 *
1490 * @param input the UTF-8 string to convert
1491 * @param length the length of the string in bytes
1492 * @param utf16_output the pointer to buffer that can hold conversion result
1493 * @return a result pair struct (of type simdutf::result containing the two
1494 * fields error and count) with an error code and either position of the error
1495 * (in the input in code units) if any, or the number of char16_t written if
1496 * successful.
1497 */
1499 const char *input, size_t length, char16_t *utf16_output) noexcept;
1500 #if SIMDUTF_SPAN
1501simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
1503 const detail::input_span_of_byte_like auto &utf8_input,
1504 std::span<char16_t> utf16_output) noexcept {
1505 #if SIMDUTF_CPLUSPLUS23
1506 if consteval {
1507 return scalar::utf8_to_utf16::convert_with_errors<endianness::BIG>(
1508 utf8_input.data(), utf8_input.size(), utf16_output.data());
1509 } else
1510 #endif
1511 {
1513 reinterpret_cast<const char *>(utf8_input.data()), utf8_input.size(),
1514 utf16_output.data());
1515 }
1516}
1517 #endif // SIMDUTF_SPAN
1518
1519/**
1520 * Convert a possibly ill-formed UTF-8 string into a UTF-16 string (native
1521 * endianness), replacing each ill-formed subsequence with U+FFFD.
1522 *
1523 * Substitution follows Unicode maximal subparts (the WHATWG rule): each
1524 * maximal subpart of an ill-formed sequence becomes one U+FFFD code unit.
1525 * The function always succeeds. The output buffer must hold
1526 * utf16_length_from_utf8_with_replacement(...).count char16_t. A buffer of
1527 * `length` char16_t is always large enough. Pass that result to the overload
1528 * that takes it, so the recorded error locations are not discovered again.
1529 *
1530 * This function is not BOM-aware.
1531 *
1532 * @param input the UTF-8 string to convert
1533 * @param length the length of the string in bytes
1534 * @param utf16_output the pointer to buffer that can hold the conversion
1535 * result
1536 * @return the number of written char16_t
1537 */
1539 const char *input, size_t length, char16_t *utf16_output) noexcept;
1540 #if SIMDUTF_SPAN
1541simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
1543 const detail::input_span_of_byte_like auto &utf8_input,
1544 std::span<char16_t> utf16_output) noexcept {
1545 #if SIMDUTF_CPLUSPLUS23
1546 if consteval {
1547 return scalar::utf8_to_utf16::convert_with_replacement<endianness::NATIVE>(
1548 utf8_input.data(), utf8_input.size(), utf16_output.data());
1549 } else
1550 #endif
1551 {
1553 reinterpret_cast<const char *>(utf8_input.data()), utf8_input.size(),
1554 utf16_output.data());
1555 }
1556}
1557 #endif // SIMDUTF_SPAN
1558
1559/**
1560 * Convert a possibly ill-formed UTF-8 string into a UTF-16 string (native
1561 * endianness), replacing each ill-formed subsequence with U+FFFD, using error
1562 * locations already computed for this same input.
1563 *
1564 * locations must be the value returned by
1565 * utf16_length_from_utf8_with_replacement for these bytes. When
1566 * locations.more_errors is false, every ill-formed subsequence is in
1567 * locations.error_offset and the gaps are valid UTF-8. When it is true, the
1568 * input has further ill-formed subsequences, and the tail past the stored
1569 * locations is scanned during conversion. The function always succeeds.
1570 *
1571 * @param input the UTF-8 string to convert
1572 * @param length the length of the string in bytes
1573 * @param utf16_output the pointer to buffer that can hold the conversion
1574 * result
1575 * @param locations result of utf16_length_from_utf8_with_replacement
1576 * @return the number of written char16_t, equal to locations.count when
1577 * locations describes this input
1578 */
1580 const char *input, size_t length, char16_t *utf16_output,
1581 const utf8_to_utf16_result &locations) noexcept;
1582 #if SIMDUTF_SPAN
1583simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
1585 const detail::input_span_of_byte_like auto &utf8_input,
1586 std::span<char16_t> utf16_output,
1587 const utf8_to_utf16_result &locations) noexcept {
1588 #if SIMDUTF_CPLUSPLUS23
1589 if consteval {
1590 (void)locations;
1591 return scalar::utf8_to_utf16::convert_with_replacement<endianness::NATIVE>(
1592 utf8_input.data(), utf8_input.size(), utf16_output.data());
1593 } else
1594 #endif
1595 {
1597 reinterpret_cast<const char *>(utf8_input.data()), utf8_input.size(),
1598 utf16_output.data(), locations);
1599 }
1600}
1601 #endif // SIMDUTF_SPAN
1602
1603/**
1604 * Convert a possibly ill-formed UTF-8 string into a UTF-16LE string, replacing
1605 * each ill-formed subsequence with U+FFFD.
1606 *
1607 * Substitution follows Unicode maximal subparts (the WHATWG rule): each
1608 * maximal subpart of an ill-formed sequence becomes one U+FFFD code unit.
1609 * The function always succeeds. The output buffer must hold
1610 * utf16_length_from_utf8_with_replacement(...).count char16_t. A buffer of
1611 * `length` char16_t is always large enough. Pass that result to the overload
1612 * that takes it, so the recorded error locations are not discovered again.
1613 *
1614 * This function is not BOM-aware.
1615 *
1616 * @param input the UTF-8 string to convert
1617 * @param length the length of the string in bytes
1618 * @param utf16_output the pointer to buffer that can hold the conversion
1619 * result
1620 * @return the number of written char16_t
1621 */
1623 const char *input, size_t length, char16_t *utf16_output) noexcept;
1624 #if SIMDUTF_SPAN
1625simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
1627 const detail::input_span_of_byte_like auto &utf8_input,
1628 std::span<char16_t> utf16_output) noexcept {
1629 #if SIMDUTF_CPLUSPLUS23
1630 if consteval {
1631 return scalar::utf8_to_utf16::convert_with_replacement<endianness::LITTLE>(
1632 utf8_input.data(), utf8_input.size(), utf16_output.data());
1633 } else
1634 #endif
1635 {
1637 reinterpret_cast<const char *>(utf8_input.data()), utf8_input.size(),
1638 utf16_output.data());
1639 }
1640}
1641 #endif // SIMDUTF_SPAN
1642
1643/**
1644 * Convert a possibly ill-formed UTF-8 string into a UTF-16LE string, using
1645 * error locations already computed for this same input. See
1646 * convert_utf8_to_utf16_with_replacement.
1647 *
1648 * @param input the UTF-8 string to convert
1649 * @param length the length of the string in bytes
1650 * @param utf16_output the pointer to buffer that can hold the conversion
1651 * result
1652 * @param locations result of utf16_length_from_utf8_with_replacement
1653 * @return the number of written char16_t
1654 */
1656 const char *input, size_t length, char16_t *utf16_output,
1657 const utf8_to_utf16_result &locations) noexcept;
1658 #if SIMDUTF_SPAN
1659simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
1661 const detail::input_span_of_byte_like auto &utf8_input,
1662 std::span<char16_t> utf16_output,
1663 const utf8_to_utf16_result &locations) noexcept {
1664 #if SIMDUTF_CPLUSPLUS23
1665 if consteval {
1666 (void)locations;
1667 return scalar::utf8_to_utf16::convert_with_replacement<endianness::LITTLE>(
1668 utf8_input.data(), utf8_input.size(), utf16_output.data());
1669 } else
1670 #endif
1671 {
1673 reinterpret_cast<const char *>(utf8_input.data()), utf8_input.size(),
1674 utf16_output.data(), locations);
1675 }
1676}
1677 #endif // SIMDUTF_SPAN
1678
1679/**
1680 * Convert a possibly ill-formed UTF-8 string into a UTF-16BE string, replacing
1681 * each ill-formed subsequence with U+FFFD.
1682 *
1683 * Substitution follows Unicode maximal subparts (the WHATWG rule): each
1684 * maximal subpart of an ill-formed sequence becomes one U+FFFD code unit.
1685 * The function always succeeds. The output buffer must hold
1686 * utf16_length_from_utf8_with_replacement(...).count char16_t. A buffer of
1687 * `length` char16_t is always large enough. Pass that result to the overload
1688 * that takes it, so the recorded error locations are not discovered again.
1689 *
1690 * This function is not BOM-aware.
1691 *
1692 * @param input the UTF-8 string to convert
1693 * @param length the length of the string in bytes
1694 * @param utf16_output the pointer to buffer that can hold the conversion
1695 * result
1696 * @return the number of written char16_t
1697 */
1699 const char *input, size_t length, char16_t *utf16_output) noexcept;
1700 #if SIMDUTF_SPAN
1701simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
1703 const detail::input_span_of_byte_like auto &utf8_input,
1704 std::span<char16_t> utf16_output) noexcept {
1705 #if SIMDUTF_CPLUSPLUS23
1706 if consteval {
1707 return scalar::utf8_to_utf16::convert_with_replacement<endianness::BIG>(
1708 utf8_input.data(), utf8_input.size(), utf16_output.data());
1709 } else
1710 #endif
1711 {
1713 reinterpret_cast<const char *>(utf8_input.data()), utf8_input.size(),
1714 utf16_output.data());
1715 }
1716}
1717 #endif // SIMDUTF_SPAN
1718
1719/**
1720 * Convert a possibly ill-formed UTF-8 string into a UTF-16BE string, using
1721 * error locations already computed for this same input. See
1722 * convert_utf8_to_utf16_with_replacement.
1723 *
1724 * @param input the UTF-8 string to convert
1725 * @param length the length of the string in bytes
1726 * @param utf16_output the pointer to buffer that can hold the conversion
1727 * result
1728 * @param locations result of utf16_length_from_utf8_with_replacement
1729 * @return the number of written char16_t
1730 */
1732 const char *input, size_t length, char16_t *utf16_output,
1733 const utf8_to_utf16_result &locations) noexcept;
1734 #if SIMDUTF_SPAN
1735simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
1737 const detail::input_span_of_byte_like auto &utf8_input,
1738 std::span<char16_t> utf16_output,
1739 const utf8_to_utf16_result &locations) noexcept {
1740 #if SIMDUTF_CPLUSPLUS23
1741 if consteval {
1742 (void)locations;
1743 return scalar::utf8_to_utf16::convert_with_replacement<endianness::BIG>(
1744 utf8_input.data(), utf8_input.size(), utf16_output.data());
1745 } else
1746 #endif
1747 {
1749 reinterpret_cast<const char *>(utf8_input.data()), utf8_input.size(),
1750 utf16_output.data(), locations);
1751 }
1752}
1753 #endif // SIMDUTF_SPAN
1754#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1755
1756#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
1757/**
1758 * Convert possibly broken UTF-8 string into UTF-32 string.
1759 *
1760 * During the conversion also validation of the input string is done.
1761 * This function is suitable to work with inputs from untrusted sources.
1762 *
1763 * @param input the UTF-8 string to convert
1764 * @param length the length of the string in bytes
1765 * @param utf32_output the pointer to buffer that can hold conversion result
1766 * @return the number of written char32_t; 0 if the input was not valid UTF-8
1767 * string
1768 */
1769simdutf_warn_unused size_t convert_utf8_to_utf32(
1770 const char *input, size_t length, char32_t *utf32_output) noexcept;
1771 #if SIMDUTF_SPAN
1772simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
1773convert_utf8_to_utf32(const detail::input_span_of_byte_like auto &utf8_input,
1774 std::span<char32_t> utf32_output) noexcept {
1775 #if SIMDUTF_CPLUSPLUS23
1776 if consteval {
1777 return scalar::utf8_to_utf32::convert(utf8_input.data(), utf8_input.size(),
1778 utf32_output.data());
1779 } else
1780 #endif
1781 {
1782 return convert_utf8_to_utf32(
1783 reinterpret_cast<const char *>(utf8_input.data()), utf8_input.size(),
1784 utf32_output.data());
1785 }
1786}
1787 #endif // SIMDUTF_SPAN
1788
1789/**
1790 * Convert possibly broken UTF-8 string into UTF-32 string and stop on error.
1791 *
1792 * During the conversion also validation of the input string is done.
1793 * This function is suitable to work with inputs from untrusted sources.
1794 *
1795 * @param input the UTF-8 string to convert
1796 * @param length the length of the string in bytes
1797 * @param utf32_output the pointer to buffer that can hold conversion result
1798 * @return a result pair struct (of type simdutf::result containing the two
1799 * fields error and count) with an error code and either position of the error
1800 * (in the input in code units) if any, or the number of char32_t written if
1801 * successful.
1802 */
1804 const char *input, size_t length, char32_t *utf32_output) noexcept;
1805 #if SIMDUTF_SPAN
1806simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
1808 const detail::input_span_of_byte_like auto &utf8_input,
1809 std::span<char32_t> utf32_output) noexcept {
1810 #if SIMDUTF_CPLUSPLUS23
1811 if consteval {
1812 return scalar::utf8_to_utf32::convert_with_errors(
1813 utf8_input.data(), utf8_input.size(), utf32_output.data());
1814 } else
1815 #endif
1816 {
1818 reinterpret_cast<const char *>(utf8_input.data()), utf8_input.size(),
1819 utf32_output.data());
1820 }
1821}
1822 #endif // SIMDUTF_SPAN
1823#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
1824
1825#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
1826/**
1827 * Convert valid UTF-8 string into latin1 string.
1828 *
1829 * This function assumes that the input string is valid UTF-8 and that it can be
1830 * represented as Latin1. If you violate this assumption, the result is
1831 * implementation defined and may include system-dependent behavior such as
1832 * crashes.
1833 *
1834 * This function is for expert users only and not part of our public API. Use
1835 * convert_utf8_to_latin1 instead. The function may be removed from the library
1836 * in the future.
1837 *
1838 * This function is not BOM-aware.
1839 *
1840 * @param input the UTF-8 string to convert
1841 * @param length the length of the string in bytes
1842 * @param latin1_output the pointer to buffer that can hold conversion result
1843 * @return the number of written char; 0 if the input was not valid UTF-8 string
1844 */
1845simdutf_warn_unused size_t convert_valid_utf8_to_latin1(
1846 const char *input, size_t length, char *latin1_output) noexcept;
1847 #if SIMDUTF_SPAN
1848simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
1850 const detail::input_span_of_byte_like auto &valid_utf8_input,
1851 detail::output_span_of_byte_like auto &&latin1_output) noexcept {
1852 #if SIMDUTF_CPLUSPLUS23
1853 if consteval {
1854 return scalar::utf8_to_latin1::convert_valid(
1855 valid_utf8_input.data(), valid_utf8_input.size(), latin1_output.data());
1856 } else
1857 #endif
1858 {
1860 reinterpret_cast<const char *>(valid_utf8_input.data()),
1861 valid_utf8_input.size(), latin1_output.data());
1862 }
1863}
1864 #endif // SIMDUTF_SPAN
1865#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
1866
1867#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1868/**
1869 * Using native endianness, convert valid UTF-8 string into a UTF-16 string.
1870 *
1871 * This function assumes that the input string is valid UTF-8.
1872 *
1873 * @param input the UTF-8 string to convert
1874 * @param length the length of the string in bytes
1875 * @param utf16_buffer the pointer to buffer that can hold conversion result
1876 * @return the number of written char16_t
1877 */
1878simdutf_warn_unused size_t convert_valid_utf8_to_utf16(
1879 const char *input, size_t length, char16_t *utf16_buffer) noexcept;
1880 #if SIMDUTF_SPAN
1881simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
1883 const detail::input_span_of_byte_like auto &valid_utf8_input,
1884 std::span<char16_t> utf16_output) noexcept {
1885 #if SIMDUTF_CPLUSPLUS23
1886 if consteval {
1887 return scalar::utf8_to_utf16::convert_valid<endianness::NATIVE>(
1888 valid_utf8_input.data(), valid_utf8_input.size(), utf16_output.data());
1889 } else
1890 #endif
1891 {
1893 reinterpret_cast<const char *>(valid_utf8_input.data()),
1894 valid_utf8_input.size(), utf16_output.data());
1895 }
1896}
1897 #endif // SIMDUTF_SPAN
1898
1899/**
1900 * Convert valid UTF-8 string into UTF-16LE string.
1901 *
1902 * This function assumes that the input string is valid UTF-8.
1903 *
1904 * @param input the UTF-8 string to convert
1905 * @param length the length of the string in bytes
1906 * @param utf16_buffer the pointer to buffer that can hold conversion result
1907 * @return the number of written char16_t
1908 */
1909simdutf_warn_unused size_t convert_valid_utf8_to_utf16le(
1910 const char *input, size_t length, char16_t *utf16_buffer) noexcept;
1911 #if SIMDUTF_SPAN
1912simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
1914 const detail::input_span_of_byte_like auto &valid_utf8_input,
1915 std::span<char16_t> utf16_output) noexcept {
1916
1917 #if SIMDUTF_CPLUSPLUS23
1918 if consteval {
1919 return scalar::utf8_to_utf16::convert_valid<endianness::LITTLE>(
1920 valid_utf8_input.data(), valid_utf8_input.size(), utf16_output.data());
1921 } else
1922 #endif
1923 {
1925 reinterpret_cast<const char *>(valid_utf8_input.data()),
1926 valid_utf8_input.size(), utf16_output.data());
1927 }
1928}
1929 #endif // SIMDUTF_SPAN
1930
1931/**
1932 * Convert valid UTF-8 string into UTF-16BE string.
1933 *
1934 * This function assumes that the input string is valid UTF-8.
1935 *
1936 * @param input the UTF-8 string to convert
1937 * @param length the length of the string in bytes
1938 * @param utf16_buffer the pointer to buffer that can hold conversion result
1939 * @return the number of written char16_t
1940 */
1941simdutf_warn_unused size_t convert_valid_utf8_to_utf16be(
1942 const char *input, size_t length, char16_t *utf16_buffer) noexcept;
1943 #if SIMDUTF_SPAN
1944simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
1946 const detail::input_span_of_byte_like auto &valid_utf8_input,
1947 std::span<char16_t> utf16_output) noexcept {
1948 #if SIMDUTF_CPLUSPLUS23
1949 if consteval {
1950 return scalar::utf8_to_utf16::convert_valid<endianness::BIG>(
1951 valid_utf8_input.data(), valid_utf8_input.size(), utf16_output.data());
1952 } else
1953 #endif
1954 {
1956 reinterpret_cast<const char *>(valid_utf8_input.data()),
1957 valid_utf8_input.size(), utf16_output.data());
1958 }
1959}
1960 #endif // SIMDUTF_SPAN
1961#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1962
1963#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
1964/**
1965 * Convert valid UTF-8 string into UTF-32 string.
1966 *
1967 * This function assumes that the input string is valid UTF-8.
1968 *
1969 * @param input the UTF-8 string to convert
1970 * @param length the length of the string in bytes
1971 * @param utf32_buffer the pointer to buffer that can hold conversion result
1972 * @return the number of written char32_t
1973 */
1974simdutf_warn_unused size_t convert_valid_utf8_to_utf32(
1975 const char *input, size_t length, char32_t *utf32_buffer) noexcept;
1976 #if SIMDUTF_SPAN
1977simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
1979 const detail::input_span_of_byte_like auto &valid_utf8_input,
1980 std::span<char32_t> utf32_output) noexcept {
1981 #if SIMDUTF_CPLUSPLUS23
1982 if consteval {
1983 return scalar::utf8_to_utf32::convert_valid(
1984 valid_utf8_input.data(), valid_utf8_input.size(), utf32_output.data());
1985 } else
1986 #endif
1987 {
1989 reinterpret_cast<const char *>(valid_utf8_input.data()),
1990 valid_utf8_input.size(), utf32_output.data());
1991 }
1992}
1993 #endif // SIMDUTF_SPAN
1994#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
1995
1996#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
1997/**
1998 * Return the number of bytes that this Latin1 string would require in UTF-8
1999 * format.
2000 *
2001 * @param input the Latin1 string to convert
2002 * @param length the length of the string bytes
2003 * @return the number of bytes required to encode the Latin1 string as UTF-8
2004 */
2005simdutf_warn_unused size_t utf8_length_from_latin1(const char *input,
2006 size_t length) noexcept;
2007 #if SIMDUTF_SPAN
2008simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
2010 const detail::input_span_of_byte_like auto &latin1_input) noexcept {
2011 #if SIMDUTF_CPLUSPLUS23
2012 if consteval {
2013 return scalar::latin1_to_utf8::utf8_length_from_latin1(latin1_input.data(),
2014 latin1_input.size());
2015 } else
2016 #endif
2017 {
2019 reinterpret_cast<const char *>(latin1_input.data()),
2020 latin1_input.size());
2021 }
2022}
2023 #endif // SIMDUTF_SPAN
2024
2025/**
2026 * Compute the number of bytes that this UTF-8 string would require in Latin1
2027 * format.
2028 *
2029 * This function does not validate the input. It is acceptable to pass invalid
2030 * UTF-8 strings but in such cases the result is implementation defined.
2031 *
2032 * This function is not BOM-aware.
2033 *
2034 * @param input the UTF-8 string to convert
2035 * @param length the length of the string in byte
2036 * @return the number of bytes required to encode the UTF-8 string as Latin1
2037 */
2038simdutf_warn_unused size_t latin1_length_from_utf8(const char *input,
2039 size_t length) noexcept;
2040 #if SIMDUTF_SPAN
2041simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
2043 const detail::input_span_of_byte_like auto &valid_utf8_input) noexcept {
2044 #if SIMDUTF_CPLUSPLUS23
2045 if consteval {
2046 return scalar::utf8::count_code_points(valid_utf8_input.data(),
2047 valid_utf8_input.size());
2048 } else
2049 #endif
2050 {
2052 reinterpret_cast<const char *>(valid_utf8_input.data()),
2053 valid_utf8_input.size());
2054 }
2055}
2056 #endif // SIMDUTF_SPAN
2057#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
2058
2059#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
2060/**
2061 * Compute the number of 2-byte code units that this UTF-8 string would require
2062 * in UTF-16LE format.
2063 *
2064 * This function does not validate the input. It is acceptable to pass invalid
2065 * UTF-8 strings but in such cases the result is implementation defined.
2066 *
2067 * This function is not BOM-aware.
2068 *
2069 * @param input the UTF-8 string to process
2070 * @param length the length of the string in bytes
2071 * @return the number of char16_t code units required to encode the UTF-8 string
2072 * as UTF-16LE
2073 */
2074simdutf_warn_unused size_t utf16_length_from_utf8(const char *input,
2075 size_t length) noexcept;
2076 #if SIMDUTF_SPAN
2077simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
2079 const detail::input_span_of_byte_like auto &valid_utf8_input) noexcept {
2080 #if SIMDUTF_CPLUSPLUS23
2081 if consteval {
2082 return scalar::utf8::utf16_length_from_utf8(valid_utf8_input.data(),
2083 valid_utf8_input.size());
2084 } else
2085 #endif
2086 {
2088 reinterpret_cast<const char *>(valid_utf8_input.data()),
2089 valid_utf8_input.size());
2090 }
2091}
2092 #endif // SIMDUTF_SPAN
2093
2094/**
2095 * Compute the number of char16_t that this UTF-8 string requires in UTF-16
2096 * when ill-formed subsequences are replaced by U+FFFD, and record where those
2097 * subsequences are.
2098 *
2099 * Substitution follows Unicode maximal subparts (the WHATWG rule): each
2100 * maximal subpart becomes one U+FFFD. count is always the number of char16_t
2101 * that convert_utf8_to_utf16_with_replacement writes, and it is at most
2102 * `length`. The count does not depend on endianness.
2103 *
2104 * error is SUCCESS when the input is valid UTF-8. Otherwise it is the error
2105 * code of the first ill-formed sequence (HEADER_BITS, TOO_SHORT, TOO_LONG,
2106 * OVERLONG, TOO_LARGE, or SURROGATE). count stays correct either way.
2107 *
2108 * error_offset holds the first error_count byte indexes, at most
2109 * utf8_to_utf16_result::max_errors (16), counting from the start of input.
2110 * more_errors is true when the input has further ill-formed subsequences.
2111 * Pass the whole result to convert_utf8_to_utf16_with_replacement on these
2112 * same bytes. A complete list (more_errors false) lets that conversion skip a
2113 * second scan.
2114 *
2115 * When the input is known to be valid, utf16_length_from_utf8 is the faster
2116 * length function: it only counts, whereas this one validates.
2117 *
2118 * This function is not BOM-aware.
2119 *
2120 * @param input the UTF-8 string to process
2121 * @param length the length of the string in bytes
2122 * @return a utf8_to_utf16_result
2123 */
2124simdutf_warn_unused utf8_to_utf16_result
2126 size_t length) noexcept;
2127 #if SIMDUTF_SPAN
2128simdutf_really_inline
2129 simdutf_warn_unused simdutf_constexpr23 utf8_to_utf16_result
2131 const detail::input_span_of_byte_like auto &utf8_input) noexcept {
2132 #if SIMDUTF_CPLUSPLUS23
2133 if consteval {
2134 return scalar::utf8_to_utf16::utf16_length_from_utf8_with_replacement(
2135 utf8_input.data(), utf8_input.size());
2136 } else
2137 #endif
2138 {
2140 reinterpret_cast<const char *>(utf8_input.data()), utf8_input.size());
2141 }
2142}
2143 #endif // SIMDUTF_SPAN
2144#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
2145
2146#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
2147/**
2148 * Compute the number of 4-byte code units that this UTF-8 string would require
2149 * in UTF-32 format.
2150 *
2151 * This function is equivalent to count_utf8
2152 *
2153 * This function does not validate the input. It is acceptable to pass invalid
2154 * UTF-8 strings but in such cases the result is implementation defined.
2155 *
2156 * This function is not BOM-aware.
2157 *
2158 * @param input the UTF-8 string to process
2159 * @param length the length of the string in bytes
2160 * @return the number of char32_t code units required to encode the UTF-8 string
2161 * as UTF-32
2162 */
2163simdutf_warn_unused size_t utf32_length_from_utf8(const char *input,
2164 size_t length) noexcept;
2165 #if SIMDUTF_SPAN
2166simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
2168 const detail::input_span_of_byte_like auto &valid_utf8_input) noexcept {
2169
2170 #if SIMDUTF_CPLUSPLUS23
2171 if consteval {
2172 return scalar::utf8::count_code_points(valid_utf8_input.data(),
2173 valid_utf8_input.size());
2174 } else
2175 #endif
2176 {
2178 reinterpret_cast<const char *>(valid_utf8_input.data()),
2179 valid_utf8_input.size());
2180 }
2181}
2182 #endif // SIMDUTF_SPAN
2183#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
2184
2185#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
2186/**
2187 * Using native endianness, convert possibly broken UTF-16 string into UTF-8
2188 * string.
2189 *
2190 * During the conversion also validation of the input string is done.
2191 * This function is suitable to work with inputs from untrusted sources.
2192 *
2193 * This function is not BOM-aware.
2194 *
2195 * @param input the UTF-16 string to convert
2196 * @param length the length of the string in 2-byte code units (char16_t)
2197 * @param utf8_buffer the pointer to buffer that can hold conversion result
2198 * @return number of written code units; 0 if input is not a valid UTF-16LE
2199 * string
2200 */
2201simdutf_warn_unused size_t convert_utf16_to_utf8(const char16_t *input,
2202 size_t length,
2203 char *utf8_buffer) noexcept;
2204 #if SIMDUTF_SPAN
2205simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
2207 std::span<const char16_t> utf16_input,
2208 detail::output_span_of_byte_like auto &&utf8_output) noexcept {
2209 #if SIMDUTF_CPLUSPLUS23
2210 if consteval {
2211 return scalar::utf16_to_utf8::convert<endianness::NATIVE>(
2212 utf16_input.data(), utf16_input.size(), utf8_output.data());
2213 } else
2214 #endif
2215 {
2216 return convert_utf16_to_utf8(utf16_input.data(), utf16_input.size(),
2217 reinterpret_cast<char *>(utf8_output.data()));
2218 }
2219}
2220 #endif // SIMDUTF_SPAN
2221
2222/**
2223 * Using native endianness, convert possibly broken UTF-16 string into UTF-8
2224 * string with output limit.
2225 *
2226 * We write as many characters as possible into the output buffer,
2227 *
2228 * During the conversion also validation of the input string is done.
2229 * This function is suitable to work with inputs from untrusted sources.
2230 *
2231 * This function is not BOM-aware.
2232 *
2233 * Using convert_utf16_to_utf8_safe instead of convert_utf16_to_utf8 comes with
2234 * a significant penalty in some cases, being up to three times slower,
2235 * especially on short inputs. If you have allocated the output buffer so that
2236 * it contains utf8_length_from_utf16(input, length) bytes, then prefer
2237 * convert_utf16_to_utf8.
2238 *
2239 * @param input the UTF-16 string to convert
2240 * @param length the length of the string in 16-bit code units (char16_t)
2241 * @param utf8_output the pointer to buffer that can hold conversion result
2242 * @param utf8_len the maximum output length
2243 * @return the number of written char; 0 if conversion is not possible
2244 */
2245simdutf_warn_unused size_t convert_utf16_to_utf8_safe(const char16_t *input,
2246 size_t length,
2247 char *utf8_output,
2248 size_t utf8_len) noexcept;
2249 #if SIMDUTF_SPAN
2250simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
2252 std::span<const char16_t> utf16_input,
2253 detail::output_span_of_byte_like auto &&utf8_output) noexcept {
2254 // implementation note: outputspan is a forwarding ref to avoid copying
2255 // and allow both lvalues and rvalues. std::span can be copied without
2256 // problems, but std::vector should not, and this function should accept
2257 // both. it will allow using an owning rvalue ref (example: passing a
2258 // temporary std::string) as output, but the user will quickly find out
2259 // that he has no way of getting the data out of the object in that case.
2260 #if SIMDUTF_CPLUSPLUS23
2261 if consteval {
2262 const full_result r =
2263 scalar::utf16_to_utf8::convert_with_errors<endianness::NATIVE, true>(
2264 utf16_input.data(), utf16_input.size(), utf8_output.data(),
2265 utf8_output.size());
2266 if (r.error != error_code::SUCCESS &&
2267 r.error != error_code::OUTPUT_BUFFER_TOO_SMALL) {
2268 return 0;
2269 }
2270 return r.output_count;
2271 } else
2272 #endif
2273 {
2275 utf16_input.data(), utf16_input.size(),
2276 reinterpret_cast<char *>(utf8_output.data()), utf8_output.size());
2277 }
2278}
2279 #endif // SIMDUTF_SPAN
2280
2281/**
2282 * Convert a possibly broken UTF-16 string into a size-limited UTF-8 buffer and
2283 * report how much input was consumed and output was written.
2284 *
2285 * We write as many complete characters as possible while validating the input.
2286 * The returned error is SUCCESS if all input was consumed,
2287 * OUTPUT_BUFFER_TOO_SMALL if the next character does not fit, or SURROGATE if
2288 * an unpaired surrogate was found.
2289 *
2290 * @param input the UTF-16 string to convert
2291 * @param length the length in 16-bit code units
2292 * @param utf8_output the pointer to the output buffer
2293 * @param utf8_len the maximum output length
2294 * @return a full_result with error, input_count and output_count
2295 */
2297 const char16_t *input, size_t length, char *utf8_output,
2298 size_t utf8_len) noexcept;
2299 #if SIMDUTF_SPAN
2300simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 full_result
2302 std::span<const char16_t> utf16_input,
2303 detail::output_span_of_byte_like auto &&utf8_output) noexcept {
2304 #if SIMDUTF_CPLUSPLUS23
2305 if consteval {
2306 if (utf16_input.empty()) {
2307 return full_result(error_code::SUCCESS, 0, 0);
2308 }
2309 return scalar::utf16_to_utf8::convert_with_errors<endianness::NATIVE, true>(
2310 utf16_input.data(), utf16_input.size(), utf8_output.data(),
2311 utf8_output.size());
2312 } else
2313 #endif
2314 {
2316 utf16_input.data(), utf16_input.size(),
2317 reinterpret_cast<char *>(utf8_output.data()), utf8_output.size());
2318 }
2319}
2320 #endif // SIMDUTF_SPAN
2321#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
2322
2323#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
2324/**
2325 * Using native endianness, convert possibly broken UTF-16 string into Latin1
2326 * string.
2327 *
2328 * During the conversion also validation of the input string is done.
2329 * This function is suitable to work with inputs from untrusted sources.
2330 *
2331 * This function is not BOM-aware.
2332 *
2333 * @param input the UTF-16 string to convert
2334 * @param length the length of the string in 2-byte code units (char16_t)
2335 * @param latin1_buffer the pointer to buffer that can hold conversion result
2336 * @return number of written code units; 0 if input is not a valid UTF-16 string
2337 * or if it cannot be represented as Latin1
2338 */
2339simdutf_warn_unused size_t convert_utf16_to_latin1(
2340 const char16_t *input, size_t length, char *latin1_buffer) noexcept;
2341 #if SIMDUTF_SPAN
2342simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
2344 std::span<const char16_t> utf16_input,
2345 detail::output_span_of_byte_like auto &&latin1_output) noexcept {
2346 #if SIMDUTF_CPLUSPLUS23
2347 if consteval {
2348 return scalar::utf16_to_latin1::convert<endianness::NATIVE>(
2349 utf16_input.data(), utf16_input.size(), latin1_output.data());
2350 } else
2351 #endif
2352 {
2354 utf16_input.data(), utf16_input.size(),
2355 reinterpret_cast<char *>(latin1_output.data()));
2356 }
2357}
2358 #endif // SIMDUTF_SPAN
2359
2360/**
2361 * Convert possibly broken UTF-16LE string into Latin1 string.
2362 * If the string cannot be represented as Latin1, an error
2363 * is returned.
2364 *
2365 * During the conversion also validation of the input string is done.
2366 * This function is suitable to work with inputs from untrusted sources.
2367 *
2368 * This function is not BOM-aware.
2369 *
2370 * @param input the UTF-16LE string to convert
2371 * @param length the length of the string in 2-byte code units (char16_t)
2372 * @param latin1_buffer the pointer to buffer that can hold conversion result
2373 * @return number of written code units; 0 if input is not a valid UTF-16LE
2374 * string or if it cannot be represented as Latin1
2375 */
2376simdutf_warn_unused size_t convert_utf16le_to_latin1(
2377 const char16_t *input, size_t length, char *latin1_buffer) noexcept;
2378 #if SIMDUTF_SPAN
2379simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
2381 std::span<const char16_t> utf16_input,
2382 detail::output_span_of_byte_like auto &&latin1_output) noexcept {
2383 #if SIMDUTF_CPLUSPLUS23
2384 if consteval {
2385 return scalar::utf16_to_latin1::convert<endianness::LITTLE>(
2386 utf16_input.data(), utf16_input.size(), latin1_output.data());
2387 } else
2388 #endif
2389 {
2391 utf16_input.data(), utf16_input.size(),
2392 reinterpret_cast<char *>(latin1_output.data()));
2393 }
2394}
2395 #endif // SIMDUTF_SPAN
2396
2397/**
2398 * Convert possibly broken UTF-16BE string into Latin1 string.
2399 *
2400 * During the conversion also validation of the input string is done.
2401 * This function is suitable to work with inputs from untrusted sources.
2402 *
2403 * This function is not BOM-aware.
2404 *
2405 * @param input the UTF-16BE string to convert
2406 * @param length the length of the string in 2-byte code units (char16_t)
2407 * @param latin1_buffer the pointer to buffer that can hold conversion result
2408 * @return number of written code units; 0 if input is not a valid UTF-16BE
2409 * string or if it cannot be represented as Latin1
2410 */
2411simdutf_warn_unused size_t convert_utf16be_to_latin1(
2412 const char16_t *input, size_t length, char *latin1_buffer) noexcept;
2413 #if SIMDUTF_SPAN
2414simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
2416 std::span<const char16_t> utf16_input,
2417 detail::output_span_of_byte_like auto &&latin1_output) noexcept {
2418 #if SIMDUTF_CPLUSPLUS23
2419 if consteval {
2420 return scalar::utf16_to_latin1::convert<endianness::BIG>(
2421 utf16_input.data(), utf16_input.size(), latin1_output.data());
2422 } else
2423 #endif
2424 {
2426 utf16_input.data(), utf16_input.size(),
2427 reinterpret_cast<char *>(latin1_output.data()));
2428 }
2429}
2430 #endif // SIMDUTF_SPAN
2431#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
2432
2433#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
2434/**
2435 * Convert possibly broken UTF-16LE string into UTF-8 string.
2436 *
2437 * During the conversion also validation of the input string is done.
2438 * This function is suitable to work with inputs from untrusted sources.
2439 *
2440 * This function is not BOM-aware.
2441 *
2442 * @param input the UTF-16LE string to convert
2443 * @param length the length of the string in 2-byte code units (char16_t)
2444 * @param utf8_buffer the pointer to buffer that can hold conversion result
2445 * @return number of written code units; 0 if input is not a valid UTF-16LE
2446 * string
2447 */
2448simdutf_warn_unused size_t convert_utf16le_to_utf8(const char16_t *input,
2449 size_t length,
2450 char *utf8_buffer) noexcept;
2451 #if SIMDUTF_SPAN
2452simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
2454 std::span<const char16_t> utf16_input,
2455 detail::output_span_of_byte_like auto &&utf8_output) noexcept {
2456 #if SIMDUTF_CPLUSPLUS23
2457 if consteval {
2458 return scalar::utf16_to_utf8::convert<endianness::LITTLE>(
2459 utf16_input.data(), utf16_input.size(), utf8_output.data());
2460 } else
2461 #endif
2462 {
2464 utf16_input.data(), utf16_input.size(),
2465 reinterpret_cast<char *>(utf8_output.data()));
2466 }
2467}
2468 #endif // SIMDUTF_SPAN
2469
2470/**
2471 * Convert possibly broken UTF-16BE string into UTF-8 string.
2472 *
2473 * During the conversion also validation of the input string is done.
2474 * This function is suitable to work with inputs from untrusted sources.
2475 *
2476 * This function is not BOM-aware.
2477 *
2478 * @param input the UTF-16BE string to convert
2479 * @param length the length of the string in 2-byte code units (char16_t)
2480 * @param utf8_buffer the pointer to buffer that can hold conversion result
2481 * @return number of written code units; 0 if input is not a valid UTF-16LE
2482 * string
2483 */
2484simdutf_warn_unused size_t convert_utf16be_to_utf8(const char16_t *input,
2485 size_t length,
2486 char *utf8_buffer) noexcept;
2487 #if SIMDUTF_SPAN
2488simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
2490 std::span<const char16_t> utf16_input,
2491 detail::output_span_of_byte_like auto &&utf8_output) noexcept {
2492 #if SIMDUTF_CPLUSPLUS23
2493 if consteval {
2494 return scalar::utf16_to_utf8::convert<endianness::BIG>(
2495 utf16_input.data(), utf16_input.size(), utf8_output.data());
2496 } else
2497 #endif
2498 {
2500 utf16_input.data(), utf16_input.size(),
2501 reinterpret_cast<char *>(utf8_output.data()));
2502 }
2503}
2504 #endif // SIMDUTF_SPAN
2505#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
2506
2507#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
2508/**
2509 * Using native endianness, convert possibly broken UTF-16 string into Latin1
2510 * string.
2511 *
2512 * During the conversion also validation of the input string is done.
2513 * This function is suitable to work with inputs from untrusted sources.
2514 * This function is not BOM-aware.
2515 *
2516 * @param input the UTF-16 string to convert
2517 * @param length the length of the string in 2-byte code units (char16_t)
2518 * @param latin1_buffer the pointer to buffer that can hold conversion result
2519 * @return a result pair struct (of type simdutf::result containing the two
2520 * fields error and count) with an error code and either position of the error
2521 * (in the input in code units) if any, or the number of char written if
2522 * successful.
2523 */
2525 const char16_t *input, size_t length, char *latin1_buffer) noexcept;
2526 #if SIMDUTF_SPAN
2527simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
2529 std::span<const char16_t> utf16_input,
2530 detail::output_span_of_byte_like auto &&latin1_output) noexcept {
2531 #if SIMDUTF_CPLUSPLUS23
2532 if consteval {
2533 return scalar::utf16_to_latin1::convert_with_errors<endianness::NATIVE>(
2534 utf16_input.data(), utf16_input.size(), latin1_output.data());
2535 } else
2536 #endif
2537 {
2539 utf16_input.data(), utf16_input.size(),
2540 reinterpret_cast<char *>(latin1_output.data()));
2541 }
2542}
2543 #endif // SIMDUTF_SPAN
2544
2545/**
2546 * Convert possibly broken UTF-16LE string into Latin1 string.
2547 *
2548 * During the conversion also validation of the input string is done.
2549 * This function is suitable to work with inputs from untrusted sources.
2550 * This function is not BOM-aware.
2551 *
2552 * @param input the UTF-16LE string to convert
2553 * @param length the length of the string in 2-byte code units (char16_t)
2554 * @param latin1_buffer the pointer to buffer that can hold conversion result
2555 * @return a result pair struct (of type simdutf::result containing the two
2556 * fields error and count) with an error code and either position of the error
2557 * (in the input in code units) if any, or the number of char written if
2558 * successful.
2559 */
2561 const char16_t *input, size_t length, char *latin1_buffer) noexcept;
2562 #if SIMDUTF_SPAN
2563simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
2565 std::span<const char16_t> utf16_input,
2566 detail::output_span_of_byte_like auto &&latin1_output) noexcept {
2567 #if SIMDUTF_CPLUSPLUS23
2568 if consteval {
2569 return scalar::utf16_to_latin1::convert_with_errors<endianness::LITTLE>(
2570 utf16_input.data(), utf16_input.size(), latin1_output.data());
2571 } else
2572 #endif
2573 {
2575 utf16_input.data(), utf16_input.size(),
2576 reinterpret_cast<char *>(latin1_output.data()));
2577 }
2578}
2579 #endif // SIMDUTF_SPAN
2580
2581/**
2582 * Convert possibly broken UTF-16BE string into Latin1 string.
2583 * If the string cannot be represented as Latin1, an error
2584 * is returned.
2585 *
2586 * During the conversion also validation of the input string is done.
2587 * This function is suitable to work with inputs from untrusted sources.
2588 * This function is not BOM-aware.
2589 *
2590 * @param input the UTF-16BE string to convert
2591 * @param length the length of the string in 2-byte code units (char16_t)
2592 * @param latin1_buffer the pointer to buffer that can hold conversion result
2593 * @return a result pair struct (of type simdutf::result containing the two
2594 * fields error and count) with an error code and either position of the error
2595 * (in the input in code units) if any, or the number of char written if
2596 * successful.
2597 */
2599 const char16_t *input, size_t length, char *latin1_buffer) noexcept;
2600 #if SIMDUTF_SPAN
2601simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
2603 std::span<const char16_t> utf16_input,
2604 detail::output_span_of_byte_like auto &&latin1_output) noexcept {
2605 #if SIMDUTF_CPLUSPLUS23
2606 if consteval {
2607 return scalar::utf16_to_latin1::convert_with_errors<endianness::BIG>(
2608 utf16_input.data(), utf16_input.size(), latin1_output.data());
2609 } else
2610 #endif
2611 {
2613 utf16_input.data(), utf16_input.size(),
2614 reinterpret_cast<char *>(latin1_output.data()));
2615 }
2616}
2617 #endif // SIMDUTF_SPAN
2618#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
2619
2620#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
2621/**
2622 * Using native endianness, convert possibly broken UTF-16 string into UTF-8
2623 * string and stop on error.
2624 *
2625 * During the conversion also validation of the input string is done.
2626 * This function is suitable to work with inputs from untrusted sources.
2627 *
2628 * This function is not BOM-aware.
2629 *
2630 * @param input the UTF-16 string to convert
2631 * @param length the length of the string in 2-byte code units (char16_t)
2632 * @param utf8_buffer the pointer to buffer that can hold conversion result
2633 * @return a result pair struct (of type simdutf::result containing the two
2634 * fields error and count) with an error code and either position of the error
2635 * (in the input in code units) if any, or the number of char written if
2636 * successful.
2637 */
2639 const char16_t *input, size_t length, char *utf8_buffer) noexcept;
2640 #if SIMDUTF_SPAN
2641simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
2643 std::span<const char16_t> utf16_input,
2644 detail::output_span_of_byte_like auto &&utf8_output) noexcept {
2645 #if SIMDUTF_CPLUSPLUS23
2646 if consteval {
2647 return scalar::utf16_to_utf8::convert_with_errors<endianness::NATIVE>(
2648 utf16_input.data(), utf16_input.size(), utf8_output.data());
2649 } else
2650 #endif
2651 {
2653 utf16_input.data(), utf16_input.size(),
2654 reinterpret_cast<char *>(utf8_output.data()));
2655 }
2656}
2657 #endif // SIMDUTF_SPAN
2658
2659/**
2660 * Convert possibly broken UTF-16LE string into UTF-8 string and stop on error.
2661 *
2662 * During the conversion also validation of the input string is done.
2663 * This function is suitable to work with inputs from untrusted sources.
2664 *
2665 * This function is not BOM-aware.
2666 *
2667 * @param input the UTF-16LE string to convert
2668 * @param length the length of the string in 2-byte code units (char16_t)
2669 * @param utf8_buffer the pointer to buffer that can hold conversion result
2670 * @return a result pair struct (of type simdutf::result containing the two
2671 * fields error and count) with an error code and either position of the error
2672 * (in the input in code units) if any, or the number of char written if
2673 * successful.
2674 */
2676 const char16_t *input, size_t length, char *utf8_buffer) noexcept;
2677 #if SIMDUTF_SPAN
2678simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
2680 std::span<const char16_t> utf16_input,
2681 detail::output_span_of_byte_like auto &&utf8_output) noexcept {
2682 #if SIMDUTF_CPLUSPLUS23
2683 if consteval {
2684 return scalar::utf16_to_utf8::convert_with_errors<endianness::LITTLE>(
2685 utf16_input.data(), utf16_input.size(), utf8_output.data());
2686 } else
2687 #endif
2688 {
2690 utf16_input.data(), utf16_input.size(),
2691 reinterpret_cast<char *>(utf8_output.data()));
2692 }
2693}
2694 #endif // SIMDUTF_SPAN
2695
2696/**
2697 * Convert possibly broken UTF-16BE string into UTF-8 string and stop on error.
2698 *
2699 * During the conversion also validation of the input string is done.
2700 * This function is suitable to work with inputs from untrusted sources.
2701 *
2702 * This function is not BOM-aware.
2703 *
2704 * @param input the UTF-16BE string to convert
2705 * @param length the length of the string in 2-byte code units (char16_t)
2706 * @param utf8_buffer the pointer to buffer that can hold conversion result
2707 * @return a result pair struct (of type simdutf::result containing the two
2708 * fields error and count) with an error code and either position of the error
2709 * (in the input in code units) if any, or the number of char written if
2710 * successful.
2711 */
2713 const char16_t *input, size_t length, char *utf8_buffer) noexcept;
2714 #if SIMDUTF_SPAN
2715simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
2717 std::span<const char16_t> utf16_input,
2718 detail::output_span_of_byte_like auto &&utf8_output) noexcept {
2719 #if SIMDUTF_CPLUSPLUS23
2720 if consteval {
2721 return scalar::utf16_to_utf8::convert_with_errors<endianness::BIG>(
2722 utf16_input.data(), utf16_input.size(), utf8_output.data());
2723 } else
2724 #endif
2725 {
2727 utf16_input.data(), utf16_input.size(),
2728 reinterpret_cast<char *>(utf8_output.data()));
2729 }
2730}
2731 #endif // SIMDUTF_SPAN
2732
2733/**
2734 * Convert possibly broken UTF-16LE string into UTF-8 string, replacing
2735 * unpaired surrogates with the Unicode replacement character U+FFFD.
2736 *
2737 * This function always succeeds: unpaired surrogates are replaced with
2738 * U+FFFD (3 bytes in UTF-8: 0xEF 0xBF 0xBD).
2739 *
2740 * This function is not BOM-aware.
2741 *
2742 * @param input the UTF-16LE string to convert
2743 * @param length the length of the string in 2-byte code units (char16_t)
2744 * @param utf8_buffer the pointer to buffer that can hold conversion result
2745 * @return number of written code units
2746 */
2748 const char16_t *input, size_t length, char *utf8_buffer) noexcept;
2749 #if SIMDUTF_SPAN
2750simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
2752 std::span<const char16_t> utf16_input,
2753 detail::output_span_of_byte_like auto &&utf8_output) noexcept {
2754 #if SIMDUTF_CPLUSPLUS23
2755 if consteval {
2756 return scalar::utf16_to_utf8::convert_with_replacement<endianness::LITTLE>(
2757 utf16_input.data(), utf16_input.size(), utf8_output.data());
2758 } else
2759 #endif
2760 {
2762 utf16_input.data(), utf16_input.size(),
2763 reinterpret_cast<char *>(utf8_output.data()));
2764 }
2765}
2766 #endif // SIMDUTF_SPAN
2767
2768/**
2769 * Convert possibly broken UTF-16BE string into UTF-8 string, replacing
2770 * unpaired surrogates with the Unicode replacement character U+FFFD.
2771 *
2772 * This function always succeeds: unpaired surrogates are replaced with
2773 * U+FFFD (3 bytes in UTF-8: 0xEF 0xBF 0xBD).
2774 *
2775 * This function is not BOM-aware.
2776 *
2777 * @param input the UTF-16BE string to convert
2778 * @param length the length of the string in 2-byte code units (char16_t)
2779 * @param utf8_buffer the pointer to buffer that can hold conversion result
2780 * @return number of written code units
2781 */
2783 const char16_t *input, size_t length, char *utf8_buffer) noexcept;
2784 #if SIMDUTF_SPAN
2785simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
2787 std::span<const char16_t> utf16_input,
2788 detail::output_span_of_byte_like auto &&utf8_output) noexcept {
2789 #if SIMDUTF_CPLUSPLUS23
2790 if consteval {
2791 return scalar::utf16_to_utf8::convert_with_replacement<endianness::BIG>(
2792 utf16_input.data(), utf16_input.size(), utf8_output.data());
2793 } else
2794 #endif
2795 {
2797 utf16_input.data(), utf16_input.size(),
2798 reinterpret_cast<char *>(utf8_output.data()));
2799 }
2800}
2801 #endif // SIMDUTF_SPAN
2802
2803/**
2804 * Convert possibly broken UTF-16 string (native endianness) into UTF-8 string,
2805 * replacing unpaired surrogates with the Unicode replacement character U+FFFD.
2806 *
2807 * This function always succeeds: unpaired surrogates are replaced with
2808 * U+FFFD (3 bytes in UTF-8: 0xEF 0xBF 0xBD).
2809 *
2810 * This function is not BOM-aware.
2811 *
2812 * @param input the UTF-16 string to convert
2813 * @param length the length of the string in 2-byte code units (char16_t)
2814 * @param utf8_buffer the pointer to buffer that can hold conversion result
2815 * @return number of written code units
2816 */
2818 const char16_t *input, size_t length, char *utf8_buffer) noexcept;
2819 #if SIMDUTF_SPAN
2820simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
2822 std::span<const char16_t> utf16_input,
2823 detail::output_span_of_byte_like auto &&utf8_output) noexcept {
2824 #if SIMDUTF_CPLUSPLUS23
2825 if consteval {
2826 return scalar::utf16_to_utf8::convert_with_replacement<endianness::NATIVE>(
2827 utf16_input.data(), utf16_input.size(), utf8_output.data());
2828 } else
2829 #endif
2830 {
2832 utf16_input.data(), utf16_input.size(),
2833 reinterpret_cast<char *>(utf8_output.data()));
2834 }
2835}
2836 #endif // SIMDUTF_SPAN
2837
2838/**
2839 * Convert a possibly broken UTF-16 string into a size-limited UTF-8 buffer,
2840 * replacing unpaired surrogates with U+FFFD and reporting how much input was
2841 * consumed and output was written.
2842 *
2843 * We write as many complete characters as possible. The returned error is
2844 * SUCCESS if all input was consumed, or OUTPUT_BUFFER_TOO_SMALL if the next
2845 * character or replacement does not fit.
2846 *
2847 * @param input the UTF-16 string to convert
2848 * @param length the length in 16-bit code units
2849 * @param utf8_output the pointer to the output buffer
2850 * @param utf8_len the maximum output length
2851 * @return a full_result with error, input_count and output_count
2852 */
2854 const char16_t *input, size_t length, char *utf8_output,
2855 size_t utf8_len) noexcept;
2856 #if SIMDUTF_SPAN
2857simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 full_result
2859 std::span<const char16_t> utf16_input,
2860 detail::output_span_of_byte_like auto &&utf8_output) noexcept {
2861 #if SIMDUTF_CPLUSPLUS23
2862 if consteval {
2863 return scalar::utf16_to_utf8::convert_with_replacement_safe<
2864 endianness::NATIVE>(utf16_input.data(), utf16_input.size(),
2865 utf8_output.data(), utf8_output.size());
2866 } else
2867 #endif
2868 {
2870 utf16_input.data(), utf16_input.size(),
2871 reinterpret_cast<char *>(utf8_output.data()), utf8_output.size());
2872 }
2873}
2874 #endif // SIMDUTF_SPAN
2875#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
2876
2877#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
2878/**
2879 * Using native endianness, convert valid UTF-16 string into UTF-8 string.
2880 *
2881 * This function assumes that the input string is valid UTF-16.
2882 *
2883 * This function is not BOM-aware.
2884 *
2885 * @param input the UTF-16 string to convert
2886 * @param length the length of the string in 2-byte code units (char16_t)
2887 * @param utf8_buffer the pointer to a buffer that can hold the conversion
2888 * result
2889 * @return number of written code units; 0 if conversion is not possible
2890 */
2891simdutf_warn_unused size_t convert_valid_utf16_to_utf8(
2892 const char16_t *input, size_t length, char *utf8_buffer) noexcept;
2893 #if SIMDUTF_SPAN
2894simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
2896 std::span<const char16_t> valid_utf16_input,
2897 detail::output_span_of_byte_like auto &&utf8_output) noexcept {
2898 #if SIMDUTF_CPLUSPLUS23
2899 if consteval {
2900 return scalar::utf16_to_utf8::convert_valid<endianness::NATIVE>(
2901 valid_utf16_input.data(), valid_utf16_input.size(), utf8_output.data());
2902 } else
2903 #endif
2904 {
2906 valid_utf16_input.data(), valid_utf16_input.size(),
2907 reinterpret_cast<char *>(utf8_output.data()));
2908 }
2909}
2910 #endif // SIMDUTF_SPAN
2911#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
2912
2913#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
2914/**
2915 * Using native endianness, convert UTF-16 string into Latin1 string.
2916 *
2917 * This function assumes that the input string is valid UTF-16 and that it can
2918 * be represented as Latin1. If you violate this assumption, the result is
2919 * implementation defined and may include system-dependent behavior such as
2920 * crashes.
2921 *
2922 * This function is for expert users only and not part of our public API. Use
2923 * convert_utf16_to_latin1 instead. The function may be removed from the library
2924 * in the future.
2925 *
2926 * This function is not BOM-aware.
2927 *
2928 * @param input the UTF-16 string to convert
2929 * @param length the length of the string in 2-byte code units (char16_t)
2930 * @param latin1_buffer the pointer to buffer that can hold conversion result
2931 * @return number of written code units; 0 if conversion is not possible
2932 */
2933simdutf_warn_unused size_t convert_valid_utf16_to_latin1(
2934 const char16_t *input, size_t length, char *latin1_buffer) noexcept;
2935 #if SIMDUTF_SPAN
2936simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
2938 std::span<const char16_t> valid_utf16_input,
2939 detail::output_span_of_byte_like auto &&latin1_output) noexcept {
2940 #if SIMDUTF_CPLUSPLUS23
2941 if consteval {
2942 return scalar::utf16_to_latin1::convert_valid_impl<endianness::NATIVE>(
2943 detail::constexpr_cast_ptr<uint16_t>(valid_utf16_input.data()),
2944 valid_utf16_input.size(),
2945 detail::constexpr_cast_writeptr<char>(latin1_output.data()));
2946 } else
2947 #endif
2948 {
2950 valid_utf16_input.data(), valid_utf16_input.size(),
2951 reinterpret_cast<char *>(latin1_output.data()));
2952 }
2953}
2954 #endif // SIMDUTF_SPAN
2955
2956/**
2957 * Convert valid UTF-16LE string into Latin1 string.
2958 *
2959 * This function assumes that the input string is valid UTF-16LE and that it can
2960 * be represented as Latin1. If you violate this assumption, the result is
2961 * implementation defined and may include system-dependent behavior such as
2962 * crashes.
2963 *
2964 * This function is for expert users only and not part of our public API. Use
2965 * convert_utf16le_to_latin1 instead. The function may be removed from the
2966 * library in the future.
2967 *
2968 * This function is not BOM-aware.
2969 *
2970 * @param input the UTF-16LE string to convert
2971 * @param length the length of the string in 2-byte code units (char16_t)
2972 * @param latin1_buffer the pointer to buffer that can hold conversion result
2973 * @return number of written code units; 0 if conversion is not possible
2974 */
2975simdutf_warn_unused size_t convert_valid_utf16le_to_latin1(
2976 const char16_t *input, size_t length, char *latin1_buffer) noexcept;
2977 #if SIMDUTF_SPAN
2978simdutf_really_inline simdutf_constexpr23 simdutf_warn_unused size_t
2980 std::span<const char16_t> valid_utf16_input,
2981 detail::output_span_of_byte_like auto &&latin1_output) noexcept {
2982 #if SIMDUTF_CPLUSPLUS23
2983 if consteval {
2984 return scalar::utf16_to_latin1::convert_valid_impl<endianness::LITTLE>(
2985 detail::constexpr_cast_ptr<uint16_t>(valid_utf16_input.data()),
2986 valid_utf16_input.size(),
2987 detail::constexpr_cast_writeptr<char>(latin1_output.data()));
2988 } else
2989 #endif
2990 {
2992 valid_utf16_input.data(), valid_utf16_input.size(),
2993 reinterpret_cast<char *>(latin1_output.data()));
2994 }
2995}
2996 #endif // SIMDUTF_SPAN
2997
2998/**
2999 * Convert valid UTF-16BE string into Latin1 string.
3000 *
3001 * This function assumes that the input string is valid UTF-16BE and that it can
3002 * be represented as Latin1. If you violate this assumption, the result is
3003 * implementation defined and may include system-dependent behavior such as
3004 * crashes.
3005 *
3006 * This function is for expert users only and not part of our public API. Use
3007 * convert_utf16be_to_latin1 instead. The function may be removed from the
3008 * library in the future.
3009 *
3010 * This function is not BOM-aware.
3011 *
3012 * @param input the UTF-16BE string to convert
3013 * @param length the length of the string in 2-byte code units (char16_t)
3014 * @param latin1_buffer the pointer to buffer that can hold conversion result
3015 * @return number of written code units; 0 if conversion is not possible
3016 */
3017simdutf_warn_unused size_t convert_valid_utf16be_to_latin1(
3018 const char16_t *input, size_t length, char *latin1_buffer) noexcept;
3019 #if SIMDUTF_SPAN
3020simdutf_really_inline simdutf_constexpr23 simdutf_warn_unused size_t
3022 std::span<const char16_t> valid_utf16_input,
3023 detail::output_span_of_byte_like auto &&latin1_output) noexcept {
3024 #if SIMDUTF_CPLUSPLUS23
3025 if consteval {
3026 return scalar::utf16_to_latin1::convert_valid_impl<endianness::BIG>(
3027 detail::constexpr_cast_ptr<uint16_t>(valid_utf16_input.data()),
3028 valid_utf16_input.size(),
3029 detail::constexpr_cast_writeptr<char>(latin1_output.data()));
3030 } else
3031 #endif
3032 {
3034 valid_utf16_input.data(), valid_utf16_input.size(),
3035 reinterpret_cast<char *>(latin1_output.data()));
3036 }
3037}
3038 #endif // SIMDUTF_SPAN
3039#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
3040
3041#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
3042/**
3043 * Convert valid UTF-16LE string into UTF-8 string.
3044 *
3045 * This function assumes that the input string is valid UTF-16LE
3046 *
3047 * This function is not BOM-aware.
3048 *
3049 * @param input the UTF-16LE string to convert
3050 * @param length the length of the string in 2-byte code units (char16_t)
3051 * @param utf8_buffer the pointer to a buffer that can hold the conversion
3052 * result
3053 * @return number of written code units; 0 if conversion is not possible
3054 */
3055simdutf_warn_unused size_t convert_valid_utf16le_to_utf8(
3056 const char16_t *input, size_t length, char *utf8_buffer) noexcept;
3057 #if SIMDUTF_SPAN
3058simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
3060 std::span<const char16_t> valid_utf16_input,
3061 detail::output_span_of_byte_like auto &&utf8_output) noexcept {
3062 #if SIMDUTF_CPLUSPLUS23
3063 if consteval {
3064 return scalar::utf16_to_utf8::convert_valid<endianness::NATIVE>(
3065 valid_utf16_input.data(), valid_utf16_input.size(), utf8_output.data());
3066 } else
3067 #endif
3068 {
3070 valid_utf16_input.data(), valid_utf16_input.size(),
3071 reinterpret_cast<char *>(utf8_output.data()));
3072 }
3073}
3074 #endif // SIMDUTF_SPAN
3075
3076/**
3077 * Convert valid UTF-16BE string into UTF-8 string.
3078 *
3079 * This function assumes that the input string is valid UTF-16BE.
3080 *
3081 * This function is not BOM-aware.
3082 *
3083 * @param input the UTF-16BE string to convert
3084 * @param length the length of the string in 2-byte code units (char16_t)
3085 * @param utf8_buffer the pointer to a buffer that can hold the conversion
3086 * result
3087 * @return number of written code units; 0 if conversion is not possible
3088 */
3089simdutf_warn_unused size_t convert_valid_utf16be_to_utf8(
3090 const char16_t *input, size_t length, char *utf8_buffer) noexcept;
3091 #if SIMDUTF_SPAN
3092simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
3094 std::span<const char16_t> valid_utf16_input,
3095 detail::output_span_of_byte_like auto &&utf8_output) noexcept {
3096 #if SIMDUTF_CPLUSPLUS23
3097 if consteval {
3098 return scalar::utf16_to_utf8::convert_valid<endianness::BIG>(
3099 valid_utf16_input.data(), valid_utf16_input.size(), utf8_output.data());
3100 } else
3101 #endif
3102 {
3104 valid_utf16_input.data(), valid_utf16_input.size(),
3105 reinterpret_cast<char *>(utf8_output.data()));
3106 }
3107}
3108 #endif // SIMDUTF_SPAN
3109#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
3110
3111#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
3112/**
3113 * Using native endianness, convert possibly broken UTF-16 string into UTF-32
3114 * string.
3115 *
3116 * During the conversion also validation of the input string is done.
3117 * This function is suitable to work with inputs from untrusted sources.
3118 *
3119 * This function is not BOM-aware.
3120 *
3121 * @param input the UTF-16 string to convert
3122 * @param length the length of the string in 2-byte code units (char16_t)
3123 * @param utf32_buffer the pointer to buffer that can hold conversion result
3124 * @return number of written code units; 0 if input is not a valid UTF-16LE
3125 * string
3126 */
3127simdutf_warn_unused size_t convert_utf16_to_utf32(
3128 const char16_t *input, size_t length, char32_t *utf32_buffer) noexcept;
3129 #if SIMDUTF_SPAN
3130simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
3131convert_utf16_to_utf32(std::span<const char16_t> utf16_input,
3132 std::span<char32_t> utf32_output) noexcept {
3133
3134 #if SIMDUTF_CPLUSPLUS23
3135 if consteval {
3136 return scalar::utf16_to_utf32::convert<endianness::NATIVE>(
3137 utf16_input.data(), utf16_input.size(), utf32_output.data());
3138 } else
3139 #endif
3140 {
3141 return convert_utf16_to_utf32(utf16_input.data(), utf16_input.size(),
3142 utf32_output.data());
3143 }
3144}
3145 #endif // SIMDUTF_SPAN
3146
3147/**
3148 * Convert possibly broken UTF-16LE string into UTF-32 string.
3149 *
3150 * During the conversion also validation of the input string is done.
3151 * This function is suitable to work with inputs from untrusted sources.
3152 *
3153 * This function is not BOM-aware.
3154 *
3155 * @param input the UTF-16LE string to convert
3156 * @param length the length of the string in 2-byte code units (char16_t)
3157 * @param utf32_buffer the pointer to buffer that can hold conversion result
3158 * @return number of written code units; 0 if input is not a valid UTF-16LE
3159 * string
3160 */
3161simdutf_warn_unused size_t convert_utf16le_to_utf32(
3162 const char16_t *input, size_t length, char32_t *utf32_buffer) noexcept;
3163 #if SIMDUTF_SPAN
3164simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
3165convert_utf16le_to_utf32(std::span<const char16_t> utf16_input,
3166 std::span<char32_t> utf32_output) noexcept {
3167 #if SIMDUTF_CPLUSPLUS23
3168 if consteval {
3169 return scalar::utf16_to_utf32::convert<endianness::LITTLE>(
3170 utf16_input.data(), utf16_input.size(), utf32_output.data());
3171 } else
3172 #endif
3173 {
3174 return convert_utf16le_to_utf32(utf16_input.data(), utf16_input.size(),
3175 utf32_output.data());
3176 }
3177}
3178 #endif // SIMDUTF_SPAN
3179
3180/**
3181 * Convert possibly broken UTF-16BE string into UTF-32 string.
3182 *
3183 * During the conversion also validation of the input string is done.
3184 * This function is suitable to work with inputs from untrusted sources.
3185 *
3186 * This function is not BOM-aware.
3187 *
3188 * @param input the UTF-16BE string to convert
3189 * @param length the length of the string in 2-byte code units (char16_t)
3190 * @param utf32_buffer the pointer to buffer that can hold conversion result
3191 * @return number of written code units; 0 if input is not a valid UTF-16LE
3192 * string
3193 */
3194simdutf_warn_unused size_t convert_utf16be_to_utf32(
3195 const char16_t *input, size_t length, char32_t *utf32_buffer) noexcept;
3196 #if SIMDUTF_SPAN
3197simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
3198convert_utf16be_to_utf32(std::span<const char16_t> utf16_input,
3199 std::span<char32_t> utf32_output) noexcept {
3200 #if SIMDUTF_CPLUSPLUS23
3201 if consteval {
3202 return scalar::utf16_to_utf32::convert<endianness::BIG>(
3203 utf16_input.data(), utf16_input.size(), utf32_output.data());
3204 } else
3205 #endif
3206 {
3207 return convert_utf16be_to_utf32(utf16_input.data(), utf16_input.size(),
3208 utf32_output.data());
3209 }
3210}
3211 #endif // SIMDUTF_SPAN
3212
3213/**
3214 * Using native endianness, convert possibly broken UTF-16 string into
3215 * UTF-32 string and stop on error.
3216 *
3217 * During the conversion also validation of the input string is done.
3218 * This function is suitable to work with inputs from untrusted sources.
3219 *
3220 * This function is not BOM-aware.
3221 *
3222 * @param input the UTF-16 string to convert
3223 * @param length the length of the string in 2-byte code units (char16_t)
3224 * @param utf32_buffer the pointer to buffer that can hold conversion result
3225 * @return a result pair struct (of type simdutf::result containing the two
3226 * fields error and count) with an error code and either position of the error
3227 * (in the input in code units) if any, or the number of char32_t written if
3228 * successful.
3229 */
3231 const char16_t *input, size_t length, char32_t *utf32_buffer) noexcept;
3232 #if SIMDUTF_SPAN
3233simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
3234convert_utf16_to_utf32_with_errors(std::span<const char16_t> utf16_input,
3235 std::span<char32_t> utf32_output) noexcept {
3236 #if SIMDUTF_CPLUSPLUS23
3237 if consteval {
3238 return scalar::utf16_to_utf32::convert_with_errors<endianness::NATIVE>(
3239 utf16_input.data(), utf16_input.size(), utf32_output.data());
3240 } else
3241 #endif
3242 {
3244 utf16_input.data(), utf16_input.size(), utf32_output.data());
3245 }
3246}
3247 #endif // SIMDUTF_SPAN
3248
3249/**
3250 * Convert possibly broken UTF-16LE string into UTF-32 string and stop on error.
3251 *
3252 * During the conversion also validation of the input string is done.
3253 * This function is suitable to work with inputs from untrusted sources.
3254 *
3255 * This function is not BOM-aware.
3256 *
3257 * @param input the UTF-16LE string to convert
3258 * @param length the length of the string in 2-byte code units (char16_t)
3259 * @param utf32_buffer the pointer to buffer that can hold conversion result
3260 * @return a result pair struct (of type simdutf::result containing the two
3261 * fields error and count) with an error code and either position of the error
3262 * (in the input in code units) if any, or the number of char32_t written if
3263 * successful.
3264 */
3266 const char16_t *input, size_t length, char32_t *utf32_buffer) noexcept;
3267 #if SIMDUTF_SPAN
3268simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
3270 std::span<const char16_t> utf16_input,
3271 std::span<char32_t> utf32_output) noexcept {
3272 #if SIMDUTF_CPLUSPLUS23
3273 if consteval {
3274 return scalar::utf16_to_utf32::convert_with_errors<endianness::LITTLE>(
3275 utf16_input.data(), utf16_input.size(), utf32_output.data());
3276 } else
3277 #endif
3278 {
3280 utf16_input.data(), utf16_input.size(), utf32_output.data());
3281 }
3282}
3283 #endif // SIMDUTF_SPAN
3284
3285/**
3286 * Convert possibly broken UTF-16BE string into UTF-32 string and stop on error.
3287 *
3288 * During the conversion also validation of the input string is done.
3289 * This function is suitable to work with inputs from untrusted sources.
3290 *
3291 * This function is not BOM-aware.
3292 *
3293 * @param input the UTF-16BE string to convert
3294 * @param length the length of the string in 2-byte code units (char16_t)
3295 * @param utf32_buffer the pointer to buffer that can hold conversion result
3296 * @return a result pair struct (of type simdutf::result containing the two
3297 * fields error and count) with an error code and either position of the error
3298 * (in the input in code units) if any, or the number of char32_t written if
3299 * successful.
3300 */
3302 const char16_t *input, size_t length, char32_t *utf32_buffer) noexcept;
3303 #if SIMDUTF_SPAN
3304simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
3306 std::span<const char16_t> utf16_input,
3307 std::span<char32_t> utf32_output) noexcept {
3308 #if SIMDUTF_CPLUSPLUS23
3309 if consteval {
3310 return scalar::utf16_to_utf32::convert_with_errors<endianness::BIG>(
3311 utf16_input.data(), utf16_input.size(), utf32_output.data());
3312 } else
3313 #endif
3314 {
3316 utf16_input.data(), utf16_input.size(), utf32_output.data());
3317 }
3318}
3319 #endif // SIMDUTF_SPAN
3320
3321/**
3322 * Using native endianness, convert valid UTF-16 string into UTF-32 string.
3323 *
3324 * This function assumes that the input string is valid UTF-16 (native
3325 * endianness).
3326 *
3327 * This function is not BOM-aware.
3328 *
3329 * @param input the UTF-16 string to convert
3330 * @param length the length of the string in 2-byte code units (char16_t)
3331 * @param utf32_buffer the pointer to a buffer that can hold the conversion
3332 * result
3333 * @return number of written code units; 0 if conversion is not possible
3334 */
3335simdutf_warn_unused size_t convert_valid_utf16_to_utf32(
3336 const char16_t *input, size_t length, char32_t *utf32_buffer) noexcept;
3337 #if SIMDUTF_SPAN
3338simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
3339convert_valid_utf16_to_utf32(std::span<const char16_t> valid_utf16_input,
3340 std::span<char32_t> utf32_output) noexcept {
3341 #if SIMDUTF_CPLUSPLUS23
3342 if consteval {
3343 return scalar::utf16_to_utf32::convert_valid<endianness::NATIVE>(
3344 valid_utf16_input.data(), valid_utf16_input.size(),
3345 utf32_output.data());
3346 } else
3347 #endif
3348 {
3349 return convert_valid_utf16_to_utf32(valid_utf16_input.data(),
3350 valid_utf16_input.size(),
3351 utf32_output.data());
3352 }
3353}
3354 #endif // SIMDUTF_SPAN
3355
3356/**
3357 * Convert valid UTF-16LE string into UTF-32 string.
3358 *
3359 * This function assumes that the input string is valid UTF-16LE.
3360 *
3361 * This function is not BOM-aware.
3362 *
3363 * @param input the UTF-16LE string to convert
3364 * @param length the length of the string in 2-byte code units (char16_t)
3365 * @param utf32_buffer the pointer to a buffer that can hold the conversion
3366 * result
3367 * @return number of written code units; 0 if conversion is not possible
3368 */
3369simdutf_warn_unused size_t convert_valid_utf16le_to_utf32(
3370 const char16_t *input, size_t length, char32_t *utf32_buffer) noexcept;
3371 #if SIMDUTF_SPAN
3372simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
3373convert_valid_utf16le_to_utf32(std::span<const char16_t> valid_utf16_input,
3374 std::span<char32_t> utf32_output) noexcept {
3375 #if SIMDUTF_CPLUSPLUS23
3376 if consteval {
3377 return scalar::utf16_to_utf32::convert_valid<endianness::LITTLE>(
3378 valid_utf16_input.data(), valid_utf16_input.size(),
3379 utf32_output.data());
3380 } else
3381 #endif
3382 {
3383 return convert_valid_utf16le_to_utf32(valid_utf16_input.data(),
3384 valid_utf16_input.size(),
3385 utf32_output.data());
3386 }
3387}
3388 #endif // SIMDUTF_SPAN
3389
3390/**
3391 * Convert valid UTF-16BE string into UTF-32 string.
3392 *
3393 * This function assumes that the input string is valid UTF-16LE.
3394 *
3395 * This function is not BOM-aware.
3396 *
3397 * @param input the UTF-16BE string to convert
3398 * @param length the length of the string in 2-byte code units (char16_t)
3399 * @param utf32_buffer the pointer to a buffer that can hold the conversion
3400 * result
3401 * @return number of written code units; 0 if conversion is not possible
3402 */
3403simdutf_warn_unused size_t convert_valid_utf16be_to_utf32(
3404 const char16_t *input, size_t length, char32_t *utf32_buffer) noexcept;
3405 #if SIMDUTF_SPAN
3406simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
3407convert_valid_utf16be_to_utf32(std::span<const char16_t> valid_utf16_input,
3408 std::span<char32_t> utf32_output) noexcept {
3409 #if SIMDUTF_CPLUSPLUS23
3410 if consteval {
3411 return scalar::utf16_to_utf32::convert_valid<endianness::BIG>(
3412 valid_utf16_input.data(), valid_utf16_input.size(),
3413 utf32_output.data());
3414 } else
3415 #endif
3416 {
3417 return convert_valid_utf16be_to_utf32(valid_utf16_input.data(),
3418 valid_utf16_input.size(),
3419 utf32_output.data());
3420 }
3421}
3422 #endif // SIMDUTF_SPAN
3423#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
3424
3425#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
3426/**
3427 * Using native endianness; Compute the number of bytes that this UTF-16
3428 * string would require in UTF-8 format.
3429 *
3430 * This function does not validate the input. It is acceptable to pass invalid
3431 * UTF-16 strings but in such cases the result is implementation defined.
3432 *
3433 * @param input the UTF-16 string to convert
3434 * @param length the length of the string in 2-byte code units (char16_t)
3435 * @return the number of bytes required to encode the UTF-16LE string as UTF-8
3436 */
3437simdutf_warn_unused size_t utf8_length_from_utf16(const char16_t *input,
3438 size_t length) noexcept;
3439 #if SIMDUTF_SPAN
3440simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
3441utf8_length_from_utf16(std::span<const char16_t> valid_utf16_input) noexcept {
3442 #if SIMDUTF_CPLUSPLUS23
3443 if consteval {
3444 return scalar::utf16::utf8_length_from_utf16<endianness::NATIVE>(
3445 valid_utf16_input.data(), valid_utf16_input.size());
3446 } else
3447 #endif
3448 {
3449 return utf8_length_from_utf16(valid_utf16_input.data(),
3450 valid_utf16_input.size());
3451 }
3452}
3453 #endif // SIMDUTF_SPAN
3454
3455/**
3456 * Using native endianness; compute the number of bytes that this UTF-16
3457 * string would require in UTF-8 format even when the UTF-16LE content contains
3458 * mismatched surrogates that have to be replaced by the replacement character
3459 * (0xFFFD).
3460 *
3461 * @param input the UTF-16 string to convert
3462 * @param length the length of the string in 2-byte code units (char16_t)
3463 * @return a result pair struct (of type simdutf::result containing the two
3464 * fields error and count) where the count is the number of bytes required to
3465 * encode the UTF-16 string as UTF-8, and the error code is either SUCCESS or
3466 * SURROGATE. The count is correct regardless of the error field.
3467 * When SURROGATE is returned, it does not indicate an error in the case of this
3468 * function: it indicates that at least one surrogate has been encountered: the
3469 * surrogates may be matched or not (thus this function does not validate). If
3470 * the returned error code is SUCCESS, then the input contains no surrogate, is
3471 * in the Basic Multilingual Plane, and is necessarily valid.
3472 */
3474 const char16_t *input, size_t length) noexcept;
3475 #if SIMDUTF_SPAN
3476simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
3478 std::span<const char16_t> valid_utf16_input) noexcept {
3479 #if SIMDUTF_CPLUSPLUS23
3480 if consteval {
3481 return scalar::utf16::utf8_length_from_utf16_with_replacement<
3482 endianness::NATIVE>(valid_utf16_input.data(), valid_utf16_input.size());
3483 } else
3484 #endif
3485 {
3486 return utf8_length_from_utf16_with_replacement(valid_utf16_input.data(),
3487 valid_utf16_input.size());
3488 }
3489}
3490 #endif // SIMDUTF_SPAN
3491
3492/**
3493 * Compute the number of bytes that this UTF-16LE string would require in UTF-8
3494 * format.
3495 *
3496 * This function does not validate the input. It is acceptable to pass invalid
3497 * UTF-16 strings but in such cases the result is implementation defined.
3498 *
3499 * @param input the UTF-16LE string to convert
3500 * @param length the length of the string in 2-byte code units (char16_t)
3501 * @return the number of bytes required to encode the UTF-16LE string as UTF-8
3502 */
3503simdutf_warn_unused size_t utf8_length_from_utf16le(const char16_t *input,
3504 size_t length) noexcept;
3505 #if SIMDUTF_SPAN
3506simdutf_really_inline simdutf_constexpr23 simdutf_warn_unused size_t
3507utf8_length_from_utf16le(std::span<const char16_t> valid_utf16_input) noexcept {
3508 #if SIMDUTF_CPLUSPLUS23
3509 if consteval {
3510 return scalar::utf16::utf8_length_from_utf16<endianness::LITTLE>(
3511 valid_utf16_input.data(), valid_utf16_input.size());
3512 } else
3513 #endif
3514 {
3515 return utf8_length_from_utf16le(valid_utf16_input.data(),
3516 valid_utf16_input.size());
3517 }
3518}
3519 #endif // SIMDUTF_SPAN
3520
3521/**
3522 * Compute the number of bytes that this UTF-16BE string would require in UTF-8
3523 * format.
3524 *
3525 * This function does not validate the input. It is acceptable to pass invalid
3526 * UTF-16 strings but in such cases the result is implementation defined.
3527 *
3528 * @param input the UTF-16BE string to convert
3529 * @param length the length of the string in 2-byte code units (char16_t)
3530 * @return the number of bytes required to encode the UTF-16BE string as UTF-8
3531 */
3532simdutf_warn_unused size_t utf8_length_from_utf16be(const char16_t *input,
3533 size_t length) noexcept;
3534 #if SIMDUTF_SPAN
3535simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
3536utf8_length_from_utf16be(std::span<const char16_t> valid_utf16_input) noexcept {
3537 #if SIMDUTF_CPLUSPLUS23
3538 if consteval {
3539 return scalar::utf16::utf8_length_from_utf16<endianness::BIG>(
3540 valid_utf16_input.data(), valid_utf16_input.size());
3541 } else
3542 #endif
3543 {
3544 return utf8_length_from_utf16be(valid_utf16_input.data(),
3545 valid_utf16_input.size());
3546 }
3547}
3548 #endif // SIMDUTF_SPAN
3549#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
3550
3551#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
3552/**
3553 * Convert possibly broken UTF-32 string into UTF-8 string.
3554 *
3555 * During the conversion also validation of the input string is done.
3556 * This function is suitable to work with inputs from untrusted sources.
3557 *
3558 * This function is not BOM-aware.
3559 *
3560 * @param input the UTF-32 string to convert
3561 * @param length the length of the string in 4-byte code units (char32_t)
3562 * @param utf8_buffer the pointer to buffer that can hold conversion result
3563 * @return number of written code units; 0 if input is not a valid UTF-32 string
3564 */
3565simdutf_warn_unused size_t convert_utf32_to_utf8(const char32_t *input,
3566 size_t length,
3567 char *utf8_buffer) noexcept;
3568 #if SIMDUTF_SPAN
3569simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
3571 std::span<const char32_t> utf32_input,
3572 detail::output_span_of_byte_like auto &&utf8_output) noexcept {
3573 #if SIMDUTF_CPLUSPLUS23
3574 if consteval {
3575 return scalar::utf32_to_utf8::convert(
3576 utf32_input.data(), utf32_input.size(), utf8_output.data());
3577 } else
3578 #endif
3579 {
3580 return convert_utf32_to_utf8(utf32_input.data(), utf32_input.size(),
3581 reinterpret_cast<char *>(utf8_output.data()));
3582 }
3583}
3584 #endif // SIMDUTF_SPAN
3585
3586/**
3587 * Convert possibly broken UTF-32 string into UTF-8 string and stop on error.
3588 *
3589 * During the conversion also validation of the input string is done.
3590 * This function is suitable to work with inputs from untrusted sources.
3591 *
3592 * This function is not BOM-aware.
3593 *
3594 * @param input the UTF-32 string to convert
3595 * @param length the length of the string in 4-byte code units (char32_t)
3596 * @param utf8_buffer the pointer to buffer that can hold conversion result
3597 * @return a result pair struct (of type simdutf::result containing the two
3598 * fields error and count) with an error code and either position of the error
3599 * (in the input in code units) if any, or the number of char written if
3600 * successful.
3601 */
3603 const char32_t *input, size_t length, char *utf8_buffer) noexcept;
3604 #if SIMDUTF_SPAN
3605simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
3607 std::span<const char32_t> utf32_input,
3608 detail::output_span_of_byte_like auto &&utf8_output) noexcept {
3609 #if SIMDUTF_CPLUSPLUS23
3610 if consteval {
3611 return scalar::utf32_to_utf8::convert_with_errors(
3612 utf32_input.data(), utf32_input.size(), utf8_output.data());
3613 } else
3614 #endif
3615 {
3617 utf32_input.data(), utf32_input.size(),
3618 reinterpret_cast<char *>(utf8_output.data()));
3619 }
3620}
3621 #endif // SIMDUTF_SPAN
3622
3623/**
3624 * Convert valid UTF-32 string into UTF-8 string.
3625 *
3626 * This function assumes that the input string is valid UTF-32.
3627 *
3628 * This function is not BOM-aware.
3629 *
3630 * @param input the UTF-32 string to convert
3631 * @param length the length of the string in 4-byte code units (char32_t)
3632 * @param utf8_buffer the pointer to a buffer that can hold the conversion
3633 * result
3634 * @return number of written code units; 0 if conversion is not possible
3635 */
3636simdutf_warn_unused size_t convert_valid_utf32_to_utf8(
3637 const char32_t *input, size_t length, char *utf8_buffer) noexcept;
3638 #if SIMDUTF_SPAN
3639simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
3641 std::span<const char32_t> valid_utf32_input,
3642 detail::output_span_of_byte_like auto &&utf8_output) noexcept {
3643 #if SIMDUTF_CPLUSPLUS23
3644 if consteval {
3645 return scalar::utf32_to_utf8::convert_valid(
3646 valid_utf32_input.data(), valid_utf32_input.size(), utf8_output.data());
3647 } else
3648 #endif
3649 {
3651 valid_utf32_input.data(), valid_utf32_input.size(),
3652 reinterpret_cast<char *>(utf8_output.data()));
3653 }
3654}
3655 #endif // SIMDUTF_SPAN
3656#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
3657
3658#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
3659/**
3660 * Using native endianness, convert possibly broken UTF-32 string into a UTF-16
3661 * string.
3662 *
3663 * During the conversion also validation of the input string is done.
3664 * This function is suitable to work with inputs from untrusted sources.
3665 *
3666 * This function is not BOM-aware.
3667 *
3668 * @param input the UTF-32 string to convert
3669 * @param length the length of the string in 4-byte code units (char32_t)
3670 * @param utf16_buffer the pointer to buffer that can hold conversion result
3671 * @return number of written code units; 0 if input is not a valid UTF-32 string
3672 */
3673simdutf_warn_unused size_t convert_utf32_to_utf16(
3674 const char32_t *input, size_t length, char16_t *utf16_buffer) noexcept;
3675 #if SIMDUTF_SPAN
3676simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
3677convert_utf32_to_utf16(std::span<const char32_t> utf32_input,
3678 std::span<char16_t> utf16_output) noexcept {
3679 #if SIMDUTF_CPLUSPLUS23
3680 if consteval {
3681 return scalar::utf32_to_utf16::convert<endianness::NATIVE>(
3682 utf32_input.data(), utf32_input.size(), utf16_output.data());
3683 } else
3684 #endif
3685 {
3686 return convert_utf32_to_utf16(utf32_input.data(), utf32_input.size(),
3687 utf16_output.data());
3688 }
3689}
3690 #endif // SIMDUTF_SPAN
3691
3692/**
3693 * Convert possibly broken UTF-32 string into UTF-16LE string.
3694 *
3695 * During the conversion also validation of the input string is done.
3696 * This function is suitable to work with inputs from untrusted sources.
3697 *
3698 * This function is not BOM-aware.
3699 *
3700 * @param input the UTF-32 string to convert
3701 * @param length the length of the string in 4-byte code units (char32_t)
3702 * @param utf16_buffer the pointer to buffer that can hold conversion result
3703 * @return number of written code units; 0 if input is not a valid UTF-32 string
3704 */
3705simdutf_warn_unused size_t convert_utf32_to_utf16le(
3706 const char32_t *input, size_t length, char16_t *utf16_buffer) noexcept;
3707 #if SIMDUTF_SPAN
3708simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
3709convert_utf32_to_utf16le(std::span<const char32_t> utf32_input,
3710 std::span<char16_t> utf16_output) noexcept {
3711 #if SIMDUTF_CPLUSPLUS23
3712 if consteval {
3713 return scalar::utf32_to_utf16::convert<endianness::LITTLE>(
3714 utf32_input.data(), utf32_input.size(), utf16_output.data());
3715 } else
3716 #endif
3717 {
3718 return convert_utf32_to_utf16le(utf32_input.data(), utf32_input.size(),
3719 utf16_output.data());
3720 }
3721}
3722 #endif // SIMDUTF_SPAN
3723#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
3724
3725#if SIMDUTF_FEATURE_UTF32 && SIMDUTF_FEATURE_LATIN1
3726/**
3727 * Convert possibly broken UTF-32 string into Latin1 string.
3728 *
3729 * During the conversion also validation of the input string is done.
3730 * This function is suitable to work with inputs from untrusted sources.
3731 *
3732 * This function is not BOM-aware.
3733 *
3734 * @param input the UTF-32 string to convert
3735 * @param length the length of the string in 4-byte code units (char32_t)
3736 * @param latin1_buffer the pointer to buffer that can hold conversion result
3737 * @return number of written code units; 0 if input is not a valid UTF-32 string
3738 * or if it cannot be represented as Latin1
3739 */
3740simdutf_warn_unused size_t convert_utf32_to_latin1(
3741 const char32_t *input, size_t length, char *latin1_buffer) noexcept;
3742 #if SIMDUTF_SPAN
3743simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
3745 std::span<const char32_t> utf32_input,
3746 detail::output_span_of_byte_like auto &&latin1_output) noexcept {
3747 #if SIMDUTF_CPLUSPLUS23
3748 if consteval {
3749 return scalar::utf32_to_latin1::convert(
3750 utf32_input.data(), utf32_input.size(), latin1_output.data());
3751 } else
3752 #endif
3753 {
3755 utf32_input.data(), utf32_input.size(),
3756 reinterpret_cast<char *>(latin1_output.data()));
3757 }
3758}
3759 #endif // SIMDUTF_SPAN
3760
3761/**
3762 * Convert possibly broken UTF-32 string into Latin1 string and stop on error.
3763 * If the string cannot be represented as Latin1, an error is returned.
3764 *
3765 * During the conversion also validation of the input string is done.
3766 * This function is suitable to work with inputs from untrusted sources.
3767 *
3768 * This function is not BOM-aware.
3769 *
3770 * @param input the UTF-32 string to convert
3771 * @param length the length of the string in 4-byte code units (char32_t)
3772 * @param latin1_buffer the pointer to buffer that can hold conversion result
3773 * @return a result pair struct (of type simdutf::result containing the two
3774 * fields error and count) with an error code and either position of the error
3775 * (in the input in code units) if any, or the number of char written if
3776 * successful.
3777 */
3779 const char32_t *input, size_t length, char *latin1_buffer) noexcept;
3780 #if SIMDUTF_SPAN
3781simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
3783 std::span<const char32_t> utf32_input,
3784 detail::output_span_of_byte_like auto &&latin1_output) noexcept {
3785 #if SIMDUTF_CPLUSPLUS23
3786 if consteval {
3787 return scalar::utf32_to_latin1::convert_with_errors(
3788 utf32_input.data(), utf32_input.size(), latin1_output.data());
3789 } else
3790 #endif
3791 {
3793 utf32_input.data(), utf32_input.size(),
3794 reinterpret_cast<char *>(latin1_output.data()));
3795 }
3796}
3797 #endif // SIMDUTF_SPAN
3798
3799/**
3800 * Convert valid UTF-32 string into Latin1 string.
3801 *
3802 * This function assumes that the input string is valid UTF-32 and that it can
3803 * be represented as Latin1. If you violate this assumption, the result is
3804 * implementation defined and may include system-dependent behavior such as
3805 * crashes.
3806 *
3807 * This function is for expert users only and not part of our public API. Use
3808 * convert_utf32_to_latin1 instead. The function may be removed from the library
3809 * in the future.
3810 *
3811 * This function is not BOM-aware.
3812 *
3813 * @param input the UTF-32 string to convert
3814 * @param length the length of the string in 4-byte code units (char32_t)
3815 * @param latin1_buffer the pointer to a buffer that can hold the conversion
3816 * result
3817 * @return number of written code units; 0 if conversion is not possible
3818 */
3819simdutf_warn_unused size_t convert_valid_utf32_to_latin1(
3820 const char32_t *input, size_t length, char *latin1_buffer) noexcept;
3821 #if SIMDUTF_SPAN
3822simdutf_really_inline simdutf_constexpr23 simdutf_warn_unused size_t
3824 std::span<const char32_t> valid_utf32_input,
3825 detail::output_span_of_byte_like auto &&latin1_output) noexcept {
3826 #if SIMDUTF_CPLUSPLUS23
3827 if consteval {
3828 return scalar::utf32_to_latin1::convert_valid(
3829 detail::constexpr_cast_ptr<uint32_t>(valid_utf32_input.data()),
3830 valid_utf32_input.size(),
3831 detail::constexpr_cast_writeptr<char>(latin1_output.data()));
3832 }
3833 #endif
3834 {
3836 valid_utf32_input.data(), valid_utf32_input.size(),
3837 reinterpret_cast<char *>(latin1_output.data()));
3838 }
3839}
3840 #endif // SIMDUTF_SPAN
3841
3842/**
3843 * Compute the number of bytes that this UTF-32 string would require in Latin1
3844 * format.
3845 *
3846 * This function does not validate the input. It is acceptable to pass invalid
3847 * UTF-32 strings but in such cases the result is implementation defined.
3848 *
3849 * This function is not BOM-aware.
3850 *
3851 * @param length the length of the string in 4-byte code units (char32_t)
3852 * @return the number of bytes required to encode the UTF-32 string as Latin1
3853 */
3854simdutf_warn_unused simdutf_really_inline simdutf_constexpr23 size_t
3855latin1_length_from_utf32(size_t length) noexcept {
3856 return length;
3857}
3858
3859/**
3860 * Compute the number of bytes that this Latin1 string would require in UTF-32
3861 * format.
3862 *
3863 * @param length the length of the string in Latin1 code units (char)
3864 * @return the length of the string in 4-byte code units (char32_t) required to
3865 * encode the Latin1 string as UTF-32
3866 */
3867simdutf_warn_unused simdutf_really_inline simdutf_constexpr23 size_t
3868utf32_length_from_latin1(size_t length) noexcept {
3869 return length;
3870}
3871#endif // SIMDUTF_FEATURE_UTF32 && SIMDUTF_FEATURE_LATIN1
3872
3873#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
3874/**
3875 * Convert possibly broken UTF-32 string into UTF-16BE string.
3876 *
3877 * During the conversion also validation of the input string is done.
3878 * This function is suitable to work with inputs from untrusted sources.
3879 *
3880 * This function is not BOM-aware.
3881 *
3882 * @param input the UTF-32 string to convert
3883 * @param length the length of the string in 4-byte code units (char32_t)
3884 * @param utf16_buffer the pointer to buffer that can hold conversion result
3885 * @return number of written code units; 0 if input is not a valid UTF-32 string
3886 */
3887simdutf_warn_unused size_t convert_utf32_to_utf16be(
3888 const char32_t *input, size_t length, char16_t *utf16_buffer) noexcept;
3889 #if SIMDUTF_SPAN
3890simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
3891convert_utf32_to_utf16be(std::span<const char32_t> utf32_input,
3892 std::span<char16_t> utf16_output) noexcept {
3893 #if SIMDUTF_CPLUSPLUS23
3894 if consteval {
3895 return scalar::utf32_to_utf16::convert<endianness::BIG>(
3896 utf32_input.data(), utf32_input.size(), utf16_output.data());
3897 } else
3898 #endif
3899 {
3900 return convert_utf32_to_utf16be(utf32_input.data(), utf32_input.size(),
3901 utf16_output.data());
3902 }
3903}
3904 #endif // SIMDUTF_SPAN
3905
3906/**
3907 * Using native endianness, convert possibly broken UTF-32 string into UTF-16
3908 * string and stop on error.
3909 *
3910 * During the conversion also validation of the input string is done.
3911 * This function is suitable to work with inputs from untrusted sources.
3912 *
3913 * This function is not BOM-aware.
3914 *
3915 * @param input the UTF-32 string to convert
3916 * @param length the length of the string in 4-byte code units (char32_t)
3917 * @param utf16_buffer the pointer to buffer that can hold conversion result
3918 * @return a result pair struct (of type simdutf::result containing the two
3919 * fields error and count) with an error code and either position of the error
3920 * (in the input in code units) if any, or the number of char16_t written if
3921 * successful.
3922 */
3924 const char32_t *input, size_t length, char16_t *utf16_buffer) noexcept;
3925 #if SIMDUTF_SPAN
3926simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
3927convert_utf32_to_utf16_with_errors(std::span<const char32_t> utf32_input,
3928 std::span<char16_t> utf16_output) noexcept {
3929 #if SIMDUTF_CPLUSPLUS23
3930 if consteval {
3931 return scalar::utf32_to_utf16::convert_with_errors<endianness::NATIVE>(
3932 utf32_input.data(), utf32_input.size(), utf16_output.data());
3933 } else
3934 #endif
3935 {
3937 utf32_input.data(), utf32_input.size(), utf16_output.data());
3938 }
3939}
3940 #endif // SIMDUTF_SPAN
3941
3942/**
3943 * Convert possibly broken UTF-32 string into UTF-16LE string and stop on error.
3944 *
3945 * During the conversion also validation of the input string is done.
3946 * This function is suitable to work with inputs from untrusted sources.
3947 *
3948 * This function is not BOM-aware.
3949 *
3950 * @param input the UTF-32 string to convert
3951 * @param length the length of the string in 4-byte code units (char32_t)
3952 * @param utf16_buffer the pointer to buffer that can hold conversion result
3953 * @return a result pair struct (of type simdutf::result containing the two
3954 * fields error and count) with an error code and either position of the error
3955 * (in the input in code units) if any, or the number of char16_t written if
3956 * successful.
3957 */
3959 const char32_t *input, size_t length, char16_t *utf16_buffer) noexcept;
3960 #if SIMDUTF_SPAN
3961simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
3963 std::span<const char32_t> utf32_input,
3964 std::span<char16_t> utf16_output) noexcept {
3965 #if SIMDUTF_CPLUSPLUS23
3966 if consteval {
3967 return scalar::utf32_to_utf16::convert_with_errors<endianness::LITTLE>(
3968 utf32_input.data(), utf32_input.size(), utf16_output.data());
3969 } else
3970 #endif
3971 {
3973 utf32_input.data(), utf32_input.size(), utf16_output.data());
3974 }
3975}
3976 #endif // SIMDUTF_SPAN
3977
3978/**
3979 * Convert possibly broken UTF-32 string into UTF-16BE string and stop on error.
3980 *
3981 * During the conversion also validation of the input string is done.
3982 * This function is suitable to work with inputs from untrusted sources.
3983 *
3984 * This function is not BOM-aware.
3985 *
3986 * @param input the UTF-32 string to convert
3987 * @param length the length of the string in 4-byte code units (char32_t)
3988 * @param utf16_buffer the pointer to buffer that can hold conversion result
3989 * @return a result pair struct (of type simdutf::result containing the two
3990 * fields error and count) with an error code and either position of the error
3991 * (in the input in code units) if any, or the number of char16_t written if
3992 * successful.
3993 */
3995 const char32_t *input, size_t length, char16_t *utf16_buffer) noexcept;
3996 #if SIMDUTF_SPAN
3997simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
3999 std::span<const char32_t> utf32_input,
4000 std::span<char16_t> utf16_output) noexcept {
4001 #if SIMDUTF_CPLUSPLUS23
4002 if consteval {
4003 return scalar::utf32_to_utf16::convert_with_errors<endianness::BIG>(
4004 utf32_input.data(), utf32_input.size(), utf16_output.data());
4005 } else
4006 #endif
4007 {
4009 utf32_input.data(), utf32_input.size(), utf16_output.data());
4010 }
4011}
4012 #endif // SIMDUTF_SPAN
4013
4014/**
4015 * Using native endianness, convert valid UTF-32 string into a UTF-16 string.
4016 *
4017 * This function assumes that the input string is valid UTF-32.
4018 *
4019 * This function is not BOM-aware.
4020 *
4021 * @param input the UTF-32 string to convert
4022 * @param length the length of the string in 4-byte code units (char32_t)
4023 * @param utf16_buffer the pointer to a buffer that can hold the conversion
4024 * result
4025 * @return number of written code units; 0 if conversion is not possible
4026 */
4027simdutf_warn_unused size_t convert_valid_utf32_to_utf16(
4028 const char32_t *input, size_t length, char16_t *utf16_buffer) noexcept;
4029 #if SIMDUTF_SPAN
4030simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
4031convert_valid_utf32_to_utf16(std::span<const char32_t> valid_utf32_input,
4032 std::span<char16_t> utf16_output) noexcept {
4033
4034 #if SIMDUTF_CPLUSPLUS23
4035 if consteval {
4036 return scalar::utf32_to_utf16::convert_valid<endianness::NATIVE>(
4037 valid_utf32_input.data(), valid_utf32_input.size(),
4038 utf16_output.data());
4039 } else
4040 #endif
4041 {
4042 return convert_valid_utf32_to_utf16(valid_utf32_input.data(),
4043 valid_utf32_input.size(),
4044 utf16_output.data());
4045 }
4046}
4047 #endif // SIMDUTF_SPAN
4048
4049/**
4050 * Convert valid UTF-32 string into UTF-16LE string.
4051 *
4052 * This function assumes that the input string is valid UTF-32.
4053 *
4054 * This function is not BOM-aware.
4055 *
4056 * @param input the UTF-32 string to convert
4057 * @param length the length of the string in 4-byte code units (char32_t)
4058 * @param utf16_buffer the pointer to a buffer that can hold the conversion
4059 * result
4060 * @return number of written code units; 0 if conversion is not possible
4061 */
4062simdutf_warn_unused size_t convert_valid_utf32_to_utf16le(
4063 const char32_t *input, size_t length, char16_t *utf16_buffer) noexcept;
4064 #if SIMDUTF_SPAN
4065simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
4066convert_valid_utf32_to_utf16le(std::span<const char32_t> valid_utf32_input,
4067 std::span<char16_t> utf16_output) noexcept {
4068 #if SIMDUTF_CPLUSPLUS23
4069 if consteval {
4070 return scalar::utf32_to_utf16::convert_valid<endianness::LITTLE>(
4071 valid_utf32_input.data(), valid_utf32_input.size(),
4072 utf16_output.data());
4073 } else
4074 #endif
4075 {
4076 return convert_valid_utf32_to_utf16le(valid_utf32_input.data(),
4077 valid_utf32_input.size(),
4078 utf16_output.data());
4079 }
4080}
4081 #endif // SIMDUTF_SPAN
4082
4083/**
4084 * Convert valid UTF-32 string into UTF-16BE string.
4085 *
4086 * This function assumes that the input string is valid UTF-32.
4087 *
4088 * This function is not BOM-aware.
4089 *
4090 * @param input the UTF-32 string to convert
4091 * @param length the length of the string in 4-byte code units (char32_t)
4092 * @param utf16_buffer the pointer to a buffer that can hold the conversion
4093 * result
4094 * @return number of written code units; 0 if conversion is not possible
4095 */
4096simdutf_warn_unused size_t convert_valid_utf32_to_utf16be(
4097 const char32_t *input, size_t length, char16_t *utf16_buffer) noexcept;
4098 #if SIMDUTF_SPAN
4099simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
4100convert_valid_utf32_to_utf16be(std::span<const char32_t> valid_utf32_input,
4101 std::span<char16_t> utf16_output) noexcept {
4102 #if SIMDUTF_CPLUSPLUS23
4103 if consteval {
4104 return scalar::utf32_to_utf16::convert_valid<endianness::BIG>(
4105 valid_utf32_input.data(), valid_utf32_input.size(),
4106 utf16_output.data());
4107 } else
4108 #endif
4109 {
4110 return convert_valid_utf32_to_utf16be(valid_utf32_input.data(),
4111 valid_utf32_input.size(),
4112 utf16_output.data());
4113 }
4114}
4115 #endif // SIMDUTF_SPAN
4116#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
4117
4118#if SIMDUTF_FEATURE_UTF16
4119/**
4120 * Change the endianness of the input. Can be used to go from UTF-16LE to
4121 * UTF-16BE or from UTF-16BE to UTF-16LE.
4122 *
4123 * This function does not validate the input.
4124 *
4125 * This function is not BOM-aware.
4126 *
4127 * @param input the UTF-16 string to process
4128 * @param length the length of the string in 2-byte code units (char16_t)
4129 * @param output the pointer to a buffer that can hold the conversion
4130 * result
4131 */
4132void change_endianness_utf16(const char16_t *input, size_t length,
4133 char16_t *output) noexcept;
4134 #if SIMDUTF_SPAN
4135simdutf_really_inline simdutf_constexpr23 void
4136change_endianness_utf16(std::span<const char16_t> utf16_input,
4137 std::span<char16_t> utf16_output) noexcept {
4138 #if SIMDUTF_CPLUSPLUS23
4139 if consteval {
4140 return scalar::utf16::change_endianness_utf16(
4141 utf16_input.data(), utf16_input.size(), utf16_output.data());
4142 } else
4143 #endif
4144 {
4145 return change_endianness_utf16(utf16_input.data(), utf16_input.size(),
4146 utf16_output.data());
4147 }
4148}
4149 #endif // SIMDUTF_SPAN
4150#endif // SIMDUTF_FEATURE_UTF16
4151
4152#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
4153/**
4154 * Compute the number of bytes that this UTF-32 string would require in UTF-8
4155 * format.
4156 *
4157 * This function does not validate the input. It is acceptable to pass invalid
4158 * UTF-32 strings but in such cases the result is implementation defined.
4159 *
4160 * @param input the UTF-32 string to convert
4161 * @param length the length of the string in 4-byte code units (char32_t)
4162 * @return the number of bytes required to encode the UTF-32 string as UTF-8
4163 */
4164simdutf_warn_unused size_t utf8_length_from_utf32(const char32_t *input,
4165 size_t length) noexcept;
4166 #if SIMDUTF_SPAN
4167simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
4168utf8_length_from_utf32(std::span<const char32_t> valid_utf32_input) noexcept {
4169 #if SIMDUTF_CPLUSPLUS23
4170 if consteval {
4171 return scalar::utf32::utf8_length_from_utf32(valid_utf32_input.data(),
4172 valid_utf32_input.size());
4173 } else
4174 #endif
4175 {
4176 return utf8_length_from_utf32(valid_utf32_input.data(),
4177 valid_utf32_input.size());
4178 }
4179}
4180 #endif // SIMDUTF_SPAN
4181#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
4182
4183#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
4184/**
4185 * Compute the number of two-byte code units that this UTF-32 string would
4186 * require in UTF-16 format.
4187 *
4188 * This function does not validate the input. It is acceptable to pass invalid
4189 * UTF-32 strings but in such cases the result is implementation defined.
4190 *
4191 * @param input the UTF-32 string to convert
4192 * @param length the length of the string in 4-byte code units (char32_t)
4193 * @return the number of bytes required to encode the UTF-32 string as UTF-16
4194 */
4195simdutf_warn_unused size_t utf16_length_from_utf32(const char32_t *input,
4196 size_t length) noexcept;
4197 #if SIMDUTF_SPAN
4198simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
4199utf16_length_from_utf32(std::span<const char32_t> valid_utf32_input) noexcept {
4200 #if SIMDUTF_CPLUSPLUS23
4201 if consteval {
4202 return scalar::utf32::utf16_length_from_utf32(valid_utf32_input.data(),
4203 valid_utf32_input.size());
4204 } else
4205 #endif
4206 {
4207 return utf16_length_from_utf32(valid_utf32_input.data(),
4208 valid_utf32_input.size());
4209 }
4210}
4211 #endif // SIMDUTF_SPAN
4212
4213/**
4214 * Using native endianness; Compute the number of bytes that this UTF-16
4215 * string would require in UTF-32 format.
4216 *
4217 * This function is equivalent to count_utf16.
4218 *
4219 * This function does not validate the input. It is acceptable to pass invalid
4220 * UTF-16 strings but in such cases the result is implementation defined.
4221 *
4222 * This function is not BOM-aware.
4223 *
4224 * @param input the UTF-16 string to convert
4225 * @param length the length of the string in 2-byte code units (char16_t)
4226 * @return the number of bytes required to encode the UTF-16LE string as UTF-32
4227 */
4228simdutf_warn_unused size_t utf32_length_from_utf16(const char16_t *input,
4229 size_t length) noexcept;
4230 #if SIMDUTF_SPAN
4231simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
4232utf32_length_from_utf16(std::span<const char16_t> valid_utf16_input) noexcept {
4233 #if SIMDUTF_CPLUSPLUS23
4234 if consteval {
4235 return scalar::utf16::utf32_length_from_utf16<endianness::NATIVE>(
4236 valid_utf16_input.data(), valid_utf16_input.size());
4237 } else
4238 #endif
4239 {
4240 return utf32_length_from_utf16(valid_utf16_input.data(),
4241 valid_utf16_input.size());
4242 }
4243}
4244 #endif // SIMDUTF_SPAN
4245
4246/**
4247 * Compute the number of bytes that this UTF-16LE string would require in UTF-32
4248 * format.
4249 *
4250 * This function is equivalent to count_utf16le.
4251 *
4252 * This function does not validate the input. It is acceptable to pass invalid
4253 * UTF-16 strings but in such cases the result is implementation defined.
4254 *
4255 * This function is not BOM-aware.
4256 *
4257 * @param input the UTF-16LE string to convert
4258 * @param length the length of the string in 2-byte code units (char16_t)
4259 * @return the number of bytes required to encode the UTF-16LE string as UTF-32
4260 */
4261simdutf_warn_unused size_t utf32_length_from_utf16le(const char16_t *input,
4262 size_t length) noexcept;
4263 #if SIMDUTF_SPAN
4264simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
4266 std::span<const char16_t> valid_utf16_input) noexcept {
4267 #if SIMDUTF_CPLUSPLUS23
4268 if consteval {
4269 return scalar::utf16::utf32_length_from_utf16<endianness::LITTLE>(
4270 valid_utf16_input.data(), valid_utf16_input.size());
4271 } else
4272 #endif
4273 {
4274 return utf32_length_from_utf16le(valid_utf16_input.data(),
4275 valid_utf16_input.size());
4276 }
4277}
4278 #endif // SIMDUTF_SPAN
4279
4280/**
4281 * Compute the number of bytes that this UTF-16BE string would require in UTF-32
4282 * format.
4283 *
4284 * This function is equivalent to count_utf16be.
4285 *
4286 * This function does not validate the input. It is acceptable to pass invalid
4287 * UTF-16 strings but in such cases the result is implementation defined.
4288 *
4289 * This function is not BOM-aware.
4290 *
4291 * @param input the UTF-16BE string to convert
4292 * @param length the length of the string in 2-byte code units (char16_t)
4293 * @return the number of bytes required to encode the UTF-16BE string as UTF-32
4294 */
4295simdutf_warn_unused size_t utf32_length_from_utf16be(const char16_t *input,
4296 size_t length) noexcept;
4297 #if SIMDUTF_SPAN
4298simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
4300 std::span<const char16_t> valid_utf16_input) noexcept {
4301 #if SIMDUTF_CPLUSPLUS23
4302 if consteval {
4303 return scalar::utf16::utf32_length_from_utf16<endianness::BIG>(
4304 valid_utf16_input.data(), valid_utf16_input.size());
4305 } else
4306 #endif
4307 {
4308 return utf32_length_from_utf16be(valid_utf16_input.data(),
4309 valid_utf16_input.size());
4310 }
4311}
4312 #endif // SIMDUTF_SPAN
4313#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
4314
4315#if SIMDUTF_FEATURE_UTF16
4316/**
4317 * Count the number of code points (characters) in the string assuming that
4318 * it is valid.
4319 *
4320 * This function assumes that the input string is valid UTF-16 (native
4321 * endianness). It is acceptable to pass invalid UTF-16 strings but in such
4322 * cases the result is implementation defined.
4323 *
4324 * This function is not BOM-aware.
4325 *
4326 * @param input the UTF-16 string to process
4327 * @param length the length of the string in 2-byte code units (char16_t)
4328 * @return number of code points
4329 */
4330simdutf_warn_unused size_t count_utf16(const char16_t *input,
4331 size_t length) noexcept;
4332 #if SIMDUTF_SPAN
4333simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
4334count_utf16(std::span<const char16_t> valid_utf16_input) noexcept {
4335 #if SIMDUTF_CPLUSPLUS23
4336 if consteval {
4337 return scalar::utf16::count_code_points<endianness::NATIVE>(
4338 valid_utf16_input.data(), valid_utf16_input.size());
4339 } else
4340 #endif
4341 {
4342 return count_utf16(valid_utf16_input.data(), valid_utf16_input.size());
4343 }
4344}
4345 #endif // SIMDUTF_SPAN
4346
4347/**
4348 * Count the number of code points (characters) in the string assuming that
4349 * it is valid.
4350 *
4351 * This function assumes that the input string is valid UTF-16LE.
4352 * It is acceptable to pass invalid UTF-16 strings but in such cases
4353 * the result is implementation defined.
4354 *
4355 * This function is not BOM-aware.
4356 *
4357 * @param input the UTF-16LE string to process
4358 * @param length the length of the string in 2-byte code units (char16_t)
4359 * @return number of code points
4360 */
4361simdutf_warn_unused size_t count_utf16le(const char16_t *input,
4362 size_t length) noexcept;
4363 #if SIMDUTF_SPAN
4364simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
4365count_utf16le(std::span<const char16_t> valid_utf16_input) noexcept {
4366 #if SIMDUTF_CPLUSPLUS23
4367 if consteval {
4368 return scalar::utf16::count_code_points<endianness::LITTLE>(
4369 valid_utf16_input.data(), valid_utf16_input.size());
4370 } else
4371 #endif
4372 {
4373 return count_utf16le(valid_utf16_input.data(), valid_utf16_input.size());
4374 }
4375}
4376 #endif // SIMDUTF_SPAN
4377
4378/**
4379 * Count the number of code points (characters) in the string assuming that
4380 * it is valid.
4381 *
4382 * This function assumes that the input string is valid UTF-16BE.
4383 * It is acceptable to pass invalid UTF-16 strings but in such cases
4384 * the result is implementation defined.
4385 *
4386 * This function is not BOM-aware.
4387 *
4388 * @param input the UTF-16BE string to process
4389 * @param length the length of the string in 2-byte code units (char16_t)
4390 * @return number of code points
4391 */
4392simdutf_warn_unused size_t count_utf16be(const char16_t *input,
4393 size_t length) noexcept;
4394 #if SIMDUTF_SPAN
4395simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
4396count_utf16be(std::span<const char16_t> valid_utf16_input) noexcept {
4397 #if SIMDUTF_CPLUSPLUS23
4398 if consteval {
4399 return scalar::utf16::count_code_points<endianness::BIG>(
4400 valid_utf16_input.data(), valid_utf16_input.size());
4401 } else
4402 #endif
4403 {
4404 return count_utf16be(valid_utf16_input.data(), valid_utf16_input.size());
4405 }
4406}
4407 #endif // SIMDUTF_SPAN
4408#endif // SIMDUTF_FEATURE_UTF16
4409
4410#if SIMDUTF_FEATURE_UTF8
4411/**
4412 * Count the number of code points (characters) in the string assuming that
4413 * it is valid.
4414 *
4415 * This function assumes that the input string is valid UTF-8.
4416 * It is acceptable to pass invalid UTF-8 strings but in such cases
4417 * the result is implementation defined.
4418 *
4419 * @param input the UTF-8 string to process
4420 * @param length the length of the string in bytes
4421 * @return number of code points
4422 */
4423simdutf_warn_unused size_t count_utf8(const char *input,
4424 size_t length) noexcept;
4425 #if SIMDUTF_SPAN
4426simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t count_utf8(
4427 const detail::input_span_of_byte_like auto &valid_utf8_input) noexcept {
4428 #if SIMDUTF_CPLUSPLUS23
4429 if consteval {
4430 return scalar::utf8::count_code_points(valid_utf8_input.data(),
4431 valid_utf8_input.size());
4432 } else
4433 #endif
4434 {
4435 return count_utf8(reinterpret_cast<const char *>(valid_utf8_input.data()),
4436 valid_utf8_input.size());
4437 }
4438}
4439 #endif // SIMDUTF_SPAN
4440
4441/**
4442 * Given a valid UTF-8 string having a possibly truncated last character,
4443 * this function checks the end of string. If the last character is truncated
4444 * (or partial), then it returns a shorter length (shorter by 1 to 3 bytes) so
4445 * that the short UTF-8 strings only contain complete characters. If there is no
4446 * truncated character, the original length is returned.
4447 *
4448 * This function assumes that the input string is valid UTF-8, but possibly
4449 * truncated.
4450 *
4451 * @param input the UTF-8 string to process
4452 * @param length the length of the string in bytes
4453 * @return the length of the string in bytes, possibly shorter by 1 to 3 bytes
4454 */
4455simdutf_warn_unused size_t trim_partial_utf8(const char *input, size_t length);
4456 #if SIMDUTF_SPAN
4457simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
4459 const detail::input_span_of_byte_like auto &valid_utf8_input) noexcept {
4460 #if SIMDUTF_CPLUSPLUS23
4461 if consteval {
4462 return scalar::utf8::trim_partial_utf8(valid_utf8_input.data(),
4463 valid_utf8_input.size());
4464 } else
4465 #endif
4466 {
4467 return trim_partial_utf8(
4468 reinterpret_cast<const char *>(valid_utf8_input.data()),
4469 valid_utf8_input.size());
4470 }
4471}
4472 #endif // SIMDUTF_SPAN
4473#endif // SIMDUTF_FEATURE_UTF8
4474
4475#if SIMDUTF_FEATURE_UTF16
4476/**
4477 * Given a valid UTF-16BE string having a possibly truncated last character,
4478 * this function checks the end of string. If the last character is truncated
4479 * (or partial), then it returns a shorter length (shorter by 1 unit) so that
4480 * the short UTF-16BE strings only contain complete characters. If there is no
4481 * truncated character, the original length is returned.
4482 *
4483 * This function assumes that the input string is valid UTF-16BE, but possibly
4484 * truncated.
4485 *
4486 * @param input the UTF-16BE string to process
4487 * @param length the length of the string in bytes
4488 * @return the length of the string in bytes, possibly shorter by 1 unit
4489 */
4490simdutf_warn_unused size_t trim_partial_utf16be(const char16_t *input,
4491 size_t length);
4492 #if SIMDUTF_SPAN
4493simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
4494trim_partial_utf16be(std::span<const char16_t> valid_utf16_input) noexcept {
4495 #if SIMDUTF_CPLUSPLUS23
4496 if consteval {
4497 return scalar::utf16::trim_partial_utf16<endianness::BIG>(
4498 valid_utf16_input.data(), valid_utf16_input.size());
4499 } else
4500 #endif
4501 {
4502 return trim_partial_utf16be(valid_utf16_input.data(),
4503 valid_utf16_input.size());
4504 }
4505}
4506 #endif // SIMDUTF_SPAN
4507
4508/**
4509 * Given a valid UTF-16LE string having a possibly truncated last character,
4510 * this function checks the end of string. If the last character is truncated
4511 * (or partial), then it returns a shorter length (shorter by 1 unit) so that
4512 * the short UTF-16LE strings only contain complete characters. If there is no
4513 * truncated character, the original length is returned.
4514 *
4515 * This function assumes that the input string is valid UTF-16LE, but possibly
4516 * truncated.
4517 *
4518 * @param input the UTF-16LE string to process
4519 * @param length the length of the string in bytes
4520 * @return the length of the string in unit, possibly shorter by 1 unit
4521 */
4522simdutf_warn_unused size_t trim_partial_utf16le(const char16_t *input,
4523 size_t length);
4524 #if SIMDUTF_SPAN
4525simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
4526trim_partial_utf16le(std::span<const char16_t> valid_utf16_input) noexcept {
4527 #if SIMDUTF_CPLUSPLUS23
4528 if consteval {
4529 return scalar::utf16::trim_partial_utf16<endianness::LITTLE>(
4530 valid_utf16_input.data(), valid_utf16_input.size());
4531 } else
4532 #endif
4533 {
4534 return trim_partial_utf16le(valid_utf16_input.data(),
4535 valid_utf16_input.size());
4536 }
4537}
4538 #endif // SIMDUTF_SPAN
4539
4540/**
4541 * Given a valid UTF-16 string having a possibly truncated last character,
4542 * this function checks the end of string. If the last character is truncated
4543 * (or partial), then it returns a shorter length (shorter by 1 unit) so that
4544 * the short UTF-16 strings only contain complete characters. If there is no
4545 * truncated character, the original length is returned.
4546 *
4547 * This function assumes that the input string is valid UTF-16, but possibly
4548 * truncated. We use the native endianness.
4549 *
4550 * @param input the UTF-16 string to process
4551 * @param length the length of the string in bytes
4552 * @return the length of the string in unit, possibly shorter by 1 unit
4553 */
4554simdutf_warn_unused size_t trim_partial_utf16(const char16_t *input,
4555 size_t length);
4556 #if SIMDUTF_SPAN
4557simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
4558trim_partial_utf16(std::span<const char16_t> valid_utf16_input) noexcept {
4559 #if SIMDUTF_CPLUSPLUS23
4560 if consteval {
4561 return scalar::utf16::trim_partial_utf16<endianness::NATIVE>(
4562 valid_utf16_input.data(), valid_utf16_input.size());
4563 } else
4564 #endif
4565 {
4566 return trim_partial_utf16(valid_utf16_input.data(),
4567 valid_utf16_input.size());
4568 }
4569}
4570 #endif // SIMDUTF_SPAN
4571#endif // SIMDUTF_FEATURE_UTF16
4572
4573#if SIMDUTF_FEATURE_BASE64 || SIMDUTF_FEATURE_UTF16 || \
4574 SIMDUTF_FEATURE_DETECT_ENCODING
4575 #ifndef SIMDUTF_NEED_TRAILING_ZEROES
4576 #define SIMDUTF_NEED_TRAILING_ZEROES 1
4577 #endif
4578#endif // SIMDUTF_FEATURE_BASE64 || SIMDUTF_FEATURE_UTF16 ||
4579 // SIMDUTF_FEATURE_DETECT_ENCODING
4580
4581#if SIMDUTF_FEATURE_BASE64
4582// base64_options are used to specify the base64 encoding options.
4583// ASCII spaces are ' ', '\t', '\n', '\r', '\f'
4584// garbage characters are characters that are not part of the base64 alphabet
4585// nor ASCII spaces.
4586constexpr uint64_t base64_reverse_padding =
4587 2; /* modifier for base64_default and base64_url */
4588enum base64_options : uint64_t {
4589 base64_default = 0, /* standard base64 format (with padding) */
4590 base64_url = 1, /* base64url format (no padding) */
4591 base64_default_no_padding =
4592 base64_default |
4593 base64_reverse_padding, /* standard base64 format without padding */
4594 base64_url_with_padding =
4595 base64_url | base64_reverse_padding, /* base64url with padding */
4596 base64_default_accept_garbage =
4597 4, /* standard base64 format accepting garbage characters, the input stops
4598 with the first '=' if any */
4599 base64_url_accept_garbage =
4600 5, /* base64url format accepting garbage characters, the input stops with
4601 the first '=' if any */
4602 base64_default_or_url =
4603 8, /* standard/base64url hybrid format (only meaningful for decoding!) */
4604 base64_default_or_url_accept_garbage =
4605 12, /* standard/base64url hybrid format accepting garbage characters
4606 (only meaningful for decoding!), the input stops with the first '='
4607 if any */
4608};
4609
4610// last_chunk_handling_options are used to specify the handling of the last
4611// chunk in base64 decoding.
4612// https://tc39.es/proposal-arraybuffer-base64/spec/#sec-frombase64
4613enum last_chunk_handling_options : uint64_t {
4614 loose = 0, /* standard base64 format, decode partial final chunk */
4615 strict = 1, /* error when the last chunk is partial, 2 or 3 chars, and
4616 unpadded, or non-zero bit padding */
4617 stop_before_partial =
4618 2, /* if the last chunk is partial, ignore it (no error) */
4619 only_full_chunks =
4620 3 /* only decode full blocks (4 base64 characters, no padding) */
4621};
4622
4623inline simdutf_constexpr23 bool
4624is_partial(last_chunk_handling_options options) {
4625 return (options == stop_before_partial) || (options == only_full_chunks);
4626}
4627
4628namespace detail {
4629simdutf_warn_unused const char *find(const char *start, const char *end,
4630 char character) noexcept;
4631simdutf_warn_unused const char16_t *
4632find(const char16_t *start, const char16_t *end, char16_t character) noexcept;
4633} // namespace detail
4634
4635/**
4636 * Find the first occurrence of a character in a string. If the character is
4637 * not found, return a pointer to the end of the string.
4638 * @param start the start of the string
4639 * @param end the end of the string
4640 * @param character the character to find
4641 * @return a pointer to the first occurrence of the character in the string,
4642 * or a pointer to the end of the string if the character is not found.
4643 *
4644 */
4645simdutf_warn_unused simdutf_really_inline simdutf_constexpr23 const char *
4646find(const char *start, const char *end, char character) noexcept {
4647 #if SIMDUTF_CPLUSPLUS23
4648 if consteval {
4649 for (; start != end; ++start)
4650 if (*start == character)
4651 return start;
4652 return end;
4653 } else
4654 #endif
4655 {
4656 return detail::find(start, end, character);
4657 }
4658}
4659simdutf_warn_unused simdutf_really_inline simdutf_constexpr23 const char16_t *
4660find(const char16_t *start, const char16_t *end, char16_t character) noexcept {
4661 // implementation note: this is repeated instead of a template, to ensure
4662 // the api is still a function and compiles without concepts
4663 #if SIMDUTF_CPLUSPLUS23
4664 if consteval {
4665 for (; start != end; ++start)
4666 if (*start == character)
4667 return start;
4668 return end;
4669 } else
4670 #endif
4671 {
4672 return detail::find(start, end, character);
4673 }
4674}
4675}
4676 // We include base64_tables once.
4677 #include <simdutf/base64_tables.h>
4678 #include <simdutf/scalar/base64.h>
4679
4680namespace simdutf {
4681
4682inline std::string_view to_string(base64_options options) {
4683 switch (options) {
4684 case base64_default:
4685 return "base64_default";
4686 case base64_url:
4687 return "base64_url";
4688 case base64_reverse_padding:
4689 return "base64_reverse_padding";
4690 case base64_url_with_padding:
4691 return "base64_url_with_padding";
4692 case base64_default_accept_garbage:
4693 return "base64_default_accept_garbage";
4694 case base64_url_accept_garbage:
4695 return "base64_url_accept_garbage";
4696 case base64_default_or_url:
4697 return "base64_default_or_url";
4698 case base64_default_or_url_accept_garbage:
4699 return "base64_default_or_url_accept_garbage";
4700 }
4701 return "<unknown>";
4702}
4703
4704inline std::string_view to_string(last_chunk_handling_options options) {
4705 switch (options) {
4706 case loose:
4707 return "loose";
4708 case strict:
4709 return "strict";
4710 case stop_before_partial:
4711 return "stop_before_partial";
4712 case only_full_chunks:
4713 return "only_full_chunks";
4714 }
4715 return "<unknown>";
4716}
4717
4718/**
4719 * Provide the maximal binary length in bytes given the base64 input.
4720 * As long as the input does not contain ignorable characters (e.g., ASCII
4721 * spaces or linefeed characters), the result is exact. In particular, the
4722 * function checks for padding characters.
4723 *
4724 * The function is fast (constant time). It checks up to two characters at
4725 * the end of the string. The input is not otherwise validated or read.
4726 *
4727 * @param input the base64 input to process
4728 * @param length the length of the base64 input in bytes
4729 * @return maximum number of binary bytes
4730 */
4731simdutf_warn_unused size_t
4732maximal_binary_length_from_base64(const char *input, size_t length) noexcept;
4733 #if SIMDUTF_SPAN
4734simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
4736 const detail::input_span_of_byte_like auto &input) noexcept {
4737 #if SIMDUTF_CPLUSPLUS23
4738 if consteval {
4739 return scalar::base64::maximal_binary_length_from_base64(
4740 detail::constexpr_cast_ptr<uint8_t>(input.data()), input.size());
4741 } else
4742 #endif
4743 {
4745 reinterpret_cast<const char *>(input.data()), input.size());
4746 }
4747}
4748 #endif // SIMDUTF_SPAN
4749
4750/**
4751 * Provide the maximal binary length in bytes given the base64 input.
4752 * As long as the input does not contain ignorable characters (e.g., ASCII
4753 * spaces or linefeed characters), the result is exact. In particular, the
4754 * function checks for padding characters.
4755 *
4756 * The function is fast (constant time). It checks up to two characters at
4757 * the end of the string. The input is not otherwise validated or read.
4758 *
4759 * @param input the base64 input to process, in ASCII stored as 16-bit
4760 * units
4761 * @param length the length of the base64 input in 16-bit units
4762 * @return maximal number of binary bytes
4763 */
4764simdutf_warn_unused size_t maximal_binary_length_from_base64(
4765 const char16_t *input, size_t length) noexcept;
4766 #if SIMDUTF_SPAN
4767simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
4768maximal_binary_length_from_base64(std::span<const char16_t> input) noexcept {
4769 #if SIMDUTF_CPLUSPLUS23
4770 if consteval {
4771 return scalar::base64::maximal_binary_length_from_base64(input.data(),
4772 input.size());
4773 } else
4774 #endif
4775 {
4776 return maximal_binary_length_from_base64(input.data(), input.size());
4777 }
4778}
4779 #endif // SIMDUTF_SPAN
4780
4781/**
4782 * Compute the binary length from a base64 input.
4783 * This function is useful for base64 inputs that may contain ASCII whitespaces
4784 * (such as line breaks). For such inputs, the result is exact, and for any
4785 * inputs the result can be used to size the output buffer passed to
4786 * `base64_to_binary`.
4787 *
4788 * The function ignores whitespace and does not require padding characters
4789 * ('=').
4790 *
4791 * @param input the base64 input to process
4792 * @param length the length of the base64 input in bytes
4793 * @return number of binary bytes
4794 */
4795simdutf_warn_unused size_t binary_length_from_base64(const char *input,
4796 size_t length) noexcept;
4797 #if SIMDUTF_SPAN
4798simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
4800 const detail::input_span_of_byte_like auto &input) noexcept {
4801 #if SIMDUTF_CPLUSPLUS23
4802 if consteval {
4803 return detail::with_char_input(input, [&](auto in) {
4804 return scalar::base64::binary_length_from_base64(in, input.size());
4805 });
4806 } else
4807 #endif
4808 {
4810 reinterpret_cast<const char *>(input.data()), input.size());
4811 }
4812}
4813 #endif // SIMDUTF_SPAN
4814
4815/**
4816 * Compute the binary length from a base64 input.
4817 * This function is useful for base64 inputs that may contain ASCII whitespaces
4818 * (such as line breaks). For such inputs, the result is exact, and for any
4819 * inputs the result can be used to size the output buffer passed to
4820 * `base64_to_binary`.
4821 *
4822 * The function ignores whitespace and does not require padding characters
4823 * ('=').
4824 *
4825 * @param input the base64 input to process, in ASCII stored as 16-bit
4826 * units
4827 * @param length the length of the base64 input in 16-bit units
4828 * @return number of binary bytes
4829 */
4830simdutf_warn_unused size_t binary_length_from_base64(const char16_t *input,
4831 size_t length) noexcept;
4832 #if SIMDUTF_SPAN
4833simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
4834binary_length_from_base64(std::span<const char16_t> input) noexcept {
4835 #if SIMDUTF_CPLUSPLUS23
4836 if consteval {
4837 return scalar::base64::binary_length_from_base64(input.data(),
4838 input.size());
4839 } else
4840 #endif
4841 {
4842 return binary_length_from_base64(input.data(), input.size());
4843 }
4844}
4845 #endif // SIMDUTF_SPAN
4846
4847/**
4848 * Convert a base64 input to a binary output.
4849 *
4850 * This function follows the WHATWG forgiving-base64 format, which means that it
4851 * will ignore any ASCII spaces in the input. You may provide a padded input
4852 * (with one or two equal signs at the end) or an unpadded input (without any
4853 * equal signs at the end).
4854 *
4855 * See https://infra.spec.whatwg.org/#forgiving-base64-decode
4856 *
4857 * This function will fail in case of invalid input. When last_chunk_options =
4858 * loose, there are two possible reasons for failure: the input contains a
4859 * number of base64 characters that when divided by 4, leaves a single remainder
4860 * character (BASE64_INPUT_REMAINDER), or the input contains a character that is
4861 * not a valid base64 character (INVALID_BASE64_CHARACTER).
4862 *
4863 * When the error is INVALID_BASE64_CHARACTER, r.count contains the index in the
4864 * input where the invalid character was found. When the error is
4865 * BASE64_INPUT_REMAINDER, then r.count contains the number of bytes decoded.
4866 *
4867 * The default option (simdutf::base64_default) expects the characters `+` and
4868 * `/` as part of its alphabet. The URL option (simdutf::base64_url) expects the
4869 * characters `-` and `_` as part of its alphabet.
4870 *
4871 * The padding (`=`) is validated if present. There may be at most two padding
4872 * characters at the end of the input. If there are any padding characters, the
4873 * total number of characters (excluding spaces but including padding
4874 * characters) must be divisible by four.
4875 *
4876 * You should call this function with a buffer that is at least
4877 * maximal_binary_length_from_base64(input, length) bytes long. If you fail to
4878 * provide that much space, the function may cause a buffer overflow.
4879 *
4880 * Advanced users may want to tailor how the last chunk is handled. By default,
4881 * we use a loose (forgiving) approach but we also support a strict approach
4882 * as well as a stop_before_partial approach, as per the following proposal:
4883 *
4884 * https://tc39.es/proposal-arraybuffer-base64/spec/#sec-frombase64
4885 *
4886 * @param input the base64 string to process
4887 * @param length the length of the string in bytes
4888 * @param output the pointer to a buffer that can hold the conversion
4889 * result (should be at least maximal_binary_length_from_base64(input, length)
4890 * bytes long).
4891 * @param options the base64 options to use, usually base64_default or
4892 * base64_url, and base64_default by default.
4893 * @param last_chunk_options the last chunk handling options,
4894 * last_chunk_handling_options::loose by default
4895 * but can also be last_chunk_handling_options::strict or
4896 * last_chunk_handling_options::stop_before_partial.
4897 * @return a result pair struct (of type simdutf::result containing the two
4898 * fields error and count) with an error code and either position of the error
4899 * (in the input in bytes) if any, or the number of bytes written if successful.
4900 */
4901simdutf_warn_unused result base64_to_binary(
4902 const char *input, size_t length, char *output,
4903 base64_options options = base64_default,
4904 last_chunk_handling_options last_chunk_options = loose) noexcept;
4905 #if SIMDUTF_SPAN
4906simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
4908 const detail::input_span_of_byte_like auto &input,
4909 detail::output_span_of_byte_like auto &&binary_output,
4910 base64_options options = base64_default,
4911 last_chunk_handling_options last_chunk_options = loose) noexcept {
4912 #if SIMDUTF_CPLUSPLUS23
4913 if consteval {
4914 return detail::with_char_input(input, [&](auto in) {
4915 return detail::with_char_output(
4916 binary_output,
4917 [&](char *out) {
4918 return scalar::base64::base64_to_binary_details_impl(
4919 in, input.size(), out, options, last_chunk_options);
4920 },
4921 [](const full_result &r) { return r.output_count; });
4922 });
4923 } else
4924 #endif
4925 {
4926 return base64_to_binary(reinterpret_cast<const char *>(input.data()),
4927 input.size(),
4928 reinterpret_cast<char *>(binary_output.data()),
4929 options, last_chunk_options);
4930 }
4931}
4932 #endif // SIMDUTF_SPAN
4933
4934/**
4935 * Provide the base64 length in bytes given the length of a binary input.
4936 *
4937 * @param length the length of the input in bytes
4938 * @param options the base64 options to use (default: base64_default)
4939 * @return number of base64 bytes
4940 */
4941inline simdutf_warn_unused simdutf_constexpr23 size_t base64_length_from_binary(
4942 size_t length, base64_options options = base64_default) noexcept {
4943 return scalar::base64::base64_length_from_binary(length, options);
4944}
4945
4946/**
4947 * Provide the base64 length in bytes given the length of a binary input,
4948 * taking into account line breaks.
4949 *
4950 * @param length the length of the input in bytes
4951 * @param options the base64 options to use (default: base64_default)
4952 * @param line_length the length of lines, must be at least 4 (otherwise it is
4953 * interpreted as 4),
4954 * @return number of base64 bytes
4955 */
4956inline simdutf_warn_unused simdutf_constexpr23 size_t
4958 size_t length, base64_options options = base64_default,
4959 size_t line_length = default_line_length) noexcept {
4960 return scalar::base64::base64_length_from_binary_with_lines(length, options,
4961 line_length);
4962}
4963
4964/**
4965 * Convert a binary input to a base64 output.
4966 *
4967 * The default option (simdutf::base64_default) uses the characters `+` and `/`
4968 * as part of its alphabet. Further, it adds padding (`=`) at the end of the
4969 * output to ensure that the output length is a multiple of four.
4970 *
4971 * The URL option (simdutf::base64_url) uses the characters `-` and `_` as part
4972 * of its alphabet. No padding is added at the end of the output.
4973 *
4974 * This function always succeeds.
4975 *
4976 * @param input the binary to process
4977 * @param length the length of the input in bytes
4978 * @param output the pointer to a buffer that can hold the conversion
4979 * result (should be at least base64_length_from_binary(length) bytes long)
4980 * @param options the base64 options to use, can be base64_default or
4981 * base64_url, is base64_default by default.
4982 * @return number of written bytes, will be equal to
4983 * base64_length_from_binary(length, options)
4984 */
4985size_t binary_to_base64(const char *input, size_t length, char *output,
4986 base64_options options = base64_default) noexcept;
4987 #if SIMDUTF_SPAN
4988simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
4989binary_to_base64(const detail::input_span_of_byte_like auto &input,
4990 detail::output_span_of_byte_like auto &&binary_output,
4991 base64_options options = base64_default) noexcept {
4992 #if SIMDUTF_CPLUSPLUS23
4993 if consteval {
4994 return detail::with_char_input(input, [&](const char *in) {
4995 return detail::with_char_output(
4996 binary_output,
4997 [&](char *out) {
4998 return scalar::base64::tail_encode_base64(out, in, input.size(),
4999 options);
5000 },
5001 [](std::size_t n) { return n; });
5002 });
5003 } else
5004 #endif
5005 {
5006 return binary_to_base64(
5007 reinterpret_cast<const char *>(input.data()), input.size(),
5008 reinterpret_cast<char *>(binary_output.data()), options);
5009 }
5010}
5011 #endif // SIMDUTF_SPAN
5012
5013/**
5014 * Convert a binary input to a base64 output with line breaks.
5015 *
5016 * The default option (simdutf::base64_default) uses the characters `+` and `/`
5017 * as part of its alphabet. Further, it adds padding (`=`) at the end of the
5018 * output to ensure that the output length is a multiple of four.
5019 *
5020 * The URL option (simdutf::base64_url) uses the characters `-` and `_` as part
5021 * of its alphabet. No padding is added at the end of the output.
5022 *
5023 * This function always succeeds.
5024 *
5025 * @param input the binary to process
5026 * @param length the length of the input in bytes
5027 * @param output the pointer to a buffer that can hold the conversion
5028 * result (should be at least base64_length_from_binary_with_lines(length,
5029 * options, line_length) bytes long)
5030 * @param line_length the length of lines, must be at least 4 (otherwise it is
5031 * interpreted as 4),
5032 * @param options the base64 options to use, can be base64_default or
5033 * base64_url, is base64_default by default.
5034 * @return number of written bytes, will be equal to
5035 * base64_length_from_binary_with_lines(length, options)
5036 */
5037size_t
5038binary_to_base64_with_lines(const char *input, size_t length, char *output,
5039 size_t line_length = simdutf::default_line_length,
5040 base64_options options = base64_default) noexcept;
5041 #if SIMDUTF_SPAN
5042simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t
5044 const detail::input_span_of_byte_like auto &input,
5045 detail::output_span_of_byte_like auto &&binary_output,
5046 size_t line_length = simdutf::default_line_length,
5047 base64_options options = base64_default) noexcept {
5048 #if SIMDUTF_CPLUSPLUS23
5049 if consteval {
5050 return detail::with_char_input(input, [&](const char *in) {
5051 return detail::with_char_output(
5052 binary_output,
5053 [&](char *out) {
5054 return scalar::base64::tail_encode_base64_impl<true>(
5055 out, in, input.size(), options, line_length);
5056 },
5057 [](std::size_t n) { return n; });
5058 });
5059 } else
5060 #endif
5061 {
5063 reinterpret_cast<const char *>(input.data()), input.size(),
5064 reinterpret_cast<char *>(binary_output.data()), line_length, options);
5065 }
5066}
5067 #endif // SIMDUTF_SPAN
5068
5069 #if SIMDUTF_ATOMIC_REF
5070/**
5071 * Convert a binary input to a base64 output, using atomic accesses.
5072 * This function comes with a potentially significant performance
5073 * penalty, but it may be useful in some cases where the input
5074 * buffers are shared between threads, to avoid undefined
5075 * behavior in case of data races.
5076 *
5077 * The function is for advanced users. Its main use case is when
5078 * to silence sanitizer warnings. We have no documented use case
5079 * where this function is actually necessary in terms of practical correctness.
5080 *
5081 * This function is only available when simdutf is compiled with
5082 * C++20 support and __cpp_lib_atomic_ref >= 201806L. You may check
5083 * the availability of this function by checking the macro
5084 * SIMDUTF_ATOMIC_REF.
5085 *
5086 * The default option (simdutf::base64_default) uses the characters `+` and `/`
5087 * as part of its alphabet. Further, it adds padding (`=`) at the end of the
5088 * output to ensure that the output length is a multiple of four.
5089 *
5090 * The URL option (simdutf::base64_url) uses the characters `-` and `_` as part
5091 * of its alphabet. No padding is added at the end of the output.
5092 *
5093 * This function always succeeds.
5094 *
5095 * This function is considered experimental. It is not tested by default
5096 * (see the CMake option SIMDUTF_ATOMIC_BASE64_TESTS) nor is it fuzz tested.
5097 * It is not documented in the public API documentation (README). It is
5098 * offered on a best effort basis. We rely on the community for further
5099 * testing and feedback.
5100 *
5101 * @brief atomic_binary_to_base64
5102 * @param input the binary to process
5103 * @param length the length of the input in bytes
5104 * @param output the pointer to a buffer that can hold the conversion
5105 * result (should be at least base64_length_from_binary(length) bytes long)
5106 * @param options the base64 options to use, can be base64_default or
5107 * base64_url, is base64_default by default.
5108 * @return number of written bytes, will be equal to
5109 * base64_length_from_binary(length, options)
5110 */
5111size_t
5112atomic_binary_to_base64(const char *input, size_t length, char *output,
5113 base64_options options = base64_default) noexcept;
5114 #if SIMDUTF_SPAN
5115simdutf_really_inline simdutf_warn_unused size_t
5116atomic_binary_to_base64(const detail::input_span_of_byte_like auto &input,
5117 detail::output_span_of_byte_like auto &&binary_output,
5118 base64_options options = base64_default) noexcept {
5119 return atomic_binary_to_base64(
5120 reinterpret_cast<const char *>(input.data()), input.size(),
5121 reinterpret_cast<char *>(binary_output.data()), options);
5122}
5123 #endif // SIMDUTF_SPAN
5124 #endif // SIMDUTF_ATOMIC_REF
5125
5126/**
5127 * Convert a base64 input to a binary output.
5128 *
5129 * This function follows the WHATWG forgiving-base64 format, which means that it
5130 * will ignore any ASCII spaces in the input. You may provide a padded input
5131 * (with one or two equal signs at the end) or an unpadded input (without any
5132 * equal signs at the end).
5133 *
5134 * See https://infra.spec.whatwg.org/#forgiving-base64-decode
5135 *
5136 * This function will fail in case of invalid input. When last_chunk_options =
5137 * loose, there are two possible reasons for failure: the input contains a
5138 * number of base64 characters that when divided by 4, leaves a single remainder
5139 * character (BASE64_INPUT_REMAINDER), or the input contains a character that is
5140 * not a valid base64 character (INVALID_BASE64_CHARACTER).
5141 *
5142 * When the error is INVALID_BASE64_CHARACTER, r.count contains the index in the
5143 * input where the invalid character was found. When the error is
5144 * BASE64_INPUT_REMAINDER, then r.count contains the number of bytes decoded.
5145 *
5146 * The default option (simdutf::base64_default) expects the characters `+` and
5147 * `/` as part of its alphabet. The URL option (simdutf::base64_url) expects the
5148 * characters `-` and `_` as part of its alphabet.
5149 *
5150 * The padding (`=`) is validated if present. There may be at most two padding
5151 * characters at the end of the input. If there are any padding characters, the
5152 * total number of characters (excluding spaces but including padding
5153 * characters) must be divisible by four.
5154 *
5155 * You should call this function with a buffer that is at least
5156 * maximal_binary_length_from_base64(input, length) bytes long. If you fail
5157 * to provide that much space, the function may cause a buffer overflow.
5158 *
5159 * Advanced users may want to tailor how the last chunk is handled. By default,
5160 * we use a loose (forgiving) approach but we also support a strict approach
5161 * as well as a stop_before_partial approach, as per the following proposal:
5162 *
5163 * https://tc39.es/proposal-arraybuffer-base64/spec/#sec-frombase64
5164 *
5165 * @param input the base64 string to process, in ASCII stored as 16-bit
5166 * units
5167 * @param length the length of the string in 16-bit units
5168 * @param output the pointer to a buffer that can hold the conversion
5169 * result (should be at least maximal_binary_length_from_base64(input, length)
5170 * bytes long).
5171 * @param options the base64 options to use, can be base64_default or
5172 * base64_url, is base64_default by default.
5173 * @param last_chunk_options the last chunk handling options,
5174 * last_chunk_handling_options::loose by default
5175 * but can also be last_chunk_handling_options::strict or
5176 * last_chunk_handling_options::stop_before_partial.
5177 * @return a result pair struct (of type simdutf::result containing the two
5178 * fields error and count) with an error code and position of the
5179 * INVALID_BASE64_CHARACTER error (in the input in units) if any, or the number
5180 * of bytes written if successful.
5181 */
5182simdutf_warn_unused result
5183base64_to_binary(const char16_t *input, size_t length, char *output,
5184 base64_options options = base64_default,
5185 last_chunk_handling_options last_chunk_options =
5186 last_chunk_handling_options::loose) noexcept;
5187 #if SIMDUTF_SPAN
5188simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 result
5190 std::span<const char16_t> input,
5191 detail::output_span_of_byte_like auto &&binary_output,
5192 base64_options options = base64_default,
5193 last_chunk_handling_options last_chunk_options = loose) noexcept {
5194 #if SIMDUTF_CPLUSPLUS23
5195 if consteval {
5196 return detail::with_char_output(
5197 binary_output,
5198 [&](auto out) {
5199 return scalar::base64::base64_to_binary_details_impl(
5200 input.data(), input.size(), out, options, last_chunk_options);
5201 },
5202 [](const full_result &r) { return r.output_count; });
5203 } else
5204 #endif
5205 {
5206 return base64_to_binary(input.data(), input.size(),
5207 reinterpret_cast<char *>(binary_output.data()),
5208 options, last_chunk_options);
5209 }
5210}
5211 #endif // SIMDUTF_SPAN
5212
5213/**
5214 * Convert a base64 input to a binary output while returning more details
5215 * than base64_to_binary.
5216 *
5217 * This function follows the WHATWG forgiving-base64 format, which means that it
5218 * will ignore any ASCII spaces in the input. You may provide a padded input
5219 * (with one or two equal signs at the end) or an unpadded input (without any
5220 * equal signs at the end).
5221 *
5222 * See https://infra.spec.whatwg.org/#forgiving-base64-decode
5223 *
5224 * Unlike base64_to_binary, this function returns a full_result with both
5225 * input_count and output_count, so you always know how much input was consumed
5226 * and how much output was written. There are three cases where the input may
5227 * not be fully consumed:
5228 *
5229 * 1. stop_before_partial: When last_chunk_options is set to
5230 * stop_before_partial, any incomplete 4-character group at the end of the
5231 * input is left unconsumed. This is useful for streaming/chunked decoding
5232 * where you can carry over the unconsumed input to the next chunk.
5233 *
5234 * 2. INVALID_BASE64_CHARACTER: The input contains a character that is not a
5235 * valid base64 character. In this case, input_count indicates where the
5236 * invalid character was found.
5237 *
5238 * 3. BASE64_INPUT_REMAINDER: When last_chunk_options is loose, the input
5239 * contains a number of base64 characters that, when divided by 4, leaves
5240 * a single remainder character (which cannot encode any bytes).
5241 *
5242 * You should call this function with a buffer that is at least
5243 * maximal_binary_length_from_base64(input, length) bytes long. If you fail to
5244 * provide that much space, the function may cause a buffer overflow.
5245 *
5246 * @param input the base64 string to process
5247 * @param length the length of the string in bytes
5248 * @param output the pointer to a buffer that can hold the conversion
5249 * result (should be at least maximal_binary_length_from_base64(input, length)
5250 * bytes long).
5251 * @param options the base64 options to use, can be base64_default or
5252 * base64_url, is base64_default by default.
5253 * @param last_chunk_options the last chunk handling options,
5254 * last_chunk_handling_options::loose by default
5255 * but can also be last_chunk_handling_options::strict or
5256 * last_chunk_handling_options::stop_before_partial.
5257 * @return a full_result struct (of type simdutf::full_result containing the
5258 * three fields error, input_count and output_count).
5259 */
5260simdutf_warn_unused full_result
5261base64_to_binary_details(const char *input, size_t length, char *output,
5262 base64_options options = base64_default,
5263 last_chunk_handling_options last_chunk_options =
5264 last_chunk_handling_options::loose) noexcept;
5265 #if SIMDUTF_SPAN
5266simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 full_result
5268 const detail::input_span_of_byte_like auto &input,
5269 detail::output_span_of_byte_like auto &&binary_output,
5270 base64_options options = base64_default,
5271 last_chunk_handling_options last_chunk_options = loose) noexcept {
5272 #if SIMDUTF_CPLUSPLUS23
5273 if consteval {
5274 return detail::with_char_input(input, [&](auto in) {
5275 return detail::with_char_output(
5276 binary_output,
5277 [&](char *out) {
5278 return scalar::base64::base64_to_binary_details_impl(
5279 in, input.size(), out, options, last_chunk_options);
5280 },
5281 [](const full_result &r) { return r.output_count; });
5282 });
5283 } else
5284 #endif
5285 {
5287 reinterpret_cast<const char *>(input.data()), input.size(),
5288 reinterpret_cast<char *>(binary_output.data()), options,
5289 last_chunk_options);
5290 }
5291}
5292 #endif // SIMDUTF_SPAN
5293
5294/**
5295 * Convert a base64 input to a binary output while returning more details
5296 * than base64_to_binary.
5297 *
5298 * This function follows the WHATWG forgiving-base64 format, which means that it
5299 * will ignore any ASCII spaces in the input. You may provide a padded input
5300 * (with one or two equal signs at the end) or an unpadded input (without any
5301 * equal signs at the end).
5302 *
5303 * See https://infra.spec.whatwg.org/#forgiving-base64-decode
5304 *
5305 * Unlike base64_to_binary, this function returns a full_result with both
5306 * input_count and output_count, so you always know how much input was consumed
5307 * and how much output was written. There are three cases where the input may
5308 * not be fully consumed:
5309 *
5310 * 1. stop_before_partial: When last_chunk_options is set to
5311 * stop_before_partial, any incomplete 4-character group at the end of the
5312 * input is left unconsumed. This is useful for streaming/chunked decoding
5313 * where you can carry over the unconsumed input to the next chunk.
5314 *
5315 * 2. INVALID_BASE64_CHARACTER: The input contains a character that is not a
5316 * valid base64 character. In this case, input_count indicates where the
5317 * invalid character was found.
5318 *
5319 * 3. BASE64_INPUT_REMAINDER: When last_chunk_options is loose, the input
5320 * contains a number of base64 characters that, when divided by 4, leaves
5321 * a single remainder character (which cannot encode any bytes).
5322 *
5323 * You should call this function with a buffer that is at least
5324 * maximal_binary_length_from_base64(input, length) bytes long. If you fail to
5325 * provide that much space, the function may cause a buffer overflow.
5326 *
5327 * @param input the base64 string to process, in ASCII stored as 16-bit
5328 * units
5329 * @param length the length of the string in 16-bit units
5330 * @param output the pointer to a buffer that can hold the conversion
5331 * result (should be at least maximal_binary_length_from_base64(input, length)
5332 * bytes long).
5333 * @param options the base64 options to use, can be base64_default or
5334 * base64_url, is base64_default by default.
5335 * @param last_chunk_options the last chunk handling options,
5336 * last_chunk_handling_options::loose by default
5337 * but can also be last_chunk_handling_options::strict or
5338 * last_chunk_handling_options::stop_before_partial.
5339 * @return a full_result struct (of type simdutf::full_result containing the
5340 * three fields error, input_count and output_count).
5341 */
5342simdutf_warn_unused full_result
5343base64_to_binary_details(const char16_t *input, size_t length, char *output,
5344 base64_options options = base64_default,
5345 last_chunk_handling_options last_chunk_options =
5346 last_chunk_handling_options::loose) noexcept;
5347 #if SIMDUTF_SPAN
5348simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 full_result
5350 std::span<const char16_t> input,
5351 detail::output_span_of_byte_like auto &&binary_output,
5352 base64_options options = base64_default,
5353 last_chunk_handling_options last_chunk_options = loose) noexcept {
5354 #if SIMDUTF_CPLUSPLUS23
5355 if consteval {
5356 return detail::with_char_output(
5357 binary_output,
5358 [&](auto out) {
5359 return scalar::base64::base64_to_binary_details_impl(
5360 input.data(), input.size(), out, options, last_chunk_options);
5361 },
5362 [](const full_result &r) { return r.output_count; });
5363 } else
5364 #endif
5365 {
5367 input.data(), input.size(),
5368 reinterpret_cast<char *>(binary_output.data()), options,
5369 last_chunk_options);
5370 }
5371}
5372 #endif // SIMDUTF_SPAN
5373
5374/**
5375 * Check if a character is an ignorable base64 character.
5376 * Checking a large input, character by character, is not computationally
5377 * efficient.
5378 *
5379 * @param input the character to check
5380 * @param options the base64 options to use, is base64_default by default.
5381 * @return true if the character is an ignorable base64 character, false
5382 * otherwise.
5383 */
5384simdutf_warn_unused simdutf_really_inline simdutf_constexpr23 bool
5385base64_ignorable(char input, base64_options options = base64_default) noexcept {
5386 return scalar::base64::is_ignorable(input, options);
5387}
5388simdutf_warn_unused simdutf_really_inline simdutf_constexpr23 bool
5389base64_ignorable(char16_t input,
5390 base64_options options = base64_default) noexcept {
5391 return scalar::base64::is_ignorable(input, options);
5392}
5393
5394/**
5395 * Check if a character is a valid base64 character.
5396 * Checking a large input, character by character, is not computationally
5397 * efficient.
5398 * Note that padding characters are not considered valid base64 characters in
5399 * this context, nor are spaces.
5400 *
5401 * @param input the character to check
5402 * @param options the base64 options to use, is base64_default by default.
5403 * @return true if the character is a base64 character, false otherwise.
5404 */
5405simdutf_warn_unused simdutf_really_inline simdutf_constexpr23 bool
5406base64_valid(char input, base64_options options = base64_default) noexcept {
5407 return scalar::base64::is_base64(input, options);
5408}
5409simdutf_warn_unused simdutf_really_inline simdutf_constexpr23 bool
5410base64_valid(char16_t input, base64_options options = base64_default) noexcept {
5411 return scalar::base64::is_base64(input, options);
5412}
5413
5414/**
5415 * Check if a character is a valid base64 character or the padding character
5416 * ('='). Checking a large input, character by character, is not computationally
5417 * efficient.
5418 *
5419 * @param input the character to check
5420 * @param options the base64 options to use, is base64_default by default.
5421 * @return true if the character is a base64 character, false otherwise.
5422 */
5423simdutf_warn_unused simdutf_really_inline simdutf_constexpr23 bool
5425 base64_options options = base64_default) noexcept {
5426 return scalar::base64::is_base64_or_padding(input, options);
5427}
5428simdutf_warn_unused simdutf_really_inline simdutf_constexpr23 bool
5429base64_valid_or_padding(char16_t input,
5430 base64_options options = base64_default) noexcept {
5431 return scalar::base64::is_base64_or_padding(input, options);
5432}
5433
5434/**
5435 * Convert a base64 input to a binary output.
5436 *
5437 * This function follows the WHATWG forgiving-base64 format, which means that it
5438 * will ignore any ASCII spaces in the input. You may provide a padded input
5439 * (with one or two equal signs at the end) or an unpadded input (without any
5440 * equal signs at the end).
5441 *
5442 * See https://infra.spec.whatwg.org/#forgiving-base64-decode
5443 *
5444 * This function will fail in case of invalid input. When last_chunk_options =
5445 * loose, there are three possible reasons for failure: the input contains a
5446 * number of base64 characters that when divided by 4, leaves a single remainder
5447 * character (BASE64_INPUT_REMAINDER), the input contains a character that is
5448 * not a valid base64 character (INVALID_BASE64_CHARACTER), or the output buffer
5449 * is too small (OUTPUT_BUFFER_TOO_SMALL).
5450 *
5451 * When OUTPUT_BUFFER_TOO_SMALL, we return both the number of bytes written
5452 * and the number of units processed, see description of the parameters and
5453 * returned value.
5454 *
5455 * When the error is INVALID_BASE64_CHARACTER, r.count contains the index in the
5456 * input where the invalid character was found. When the error is
5457 * BASE64_INPUT_REMAINDER, then r.count contains the number of bytes decoded.
5458 *
5459 * The default option (simdutf::base64_default) expects the characters `+` and
5460 * `/` as part of its alphabet. The URL option (simdutf::base64_url) expects the
5461 * characters `-` and `_` as part of its alphabet.
5462 *
5463 * The padding (`=`) is validated if present. There may be at most two padding
5464 * characters at the end of the input. If there are any padding characters, the
5465 * total number of characters (excluding spaces but including padding
5466 * characters) must be divisible by four.
5467 *
5468 * The INVALID_BASE64_CHARACTER cases are considered fatal and you are expected
5469 * to discard the output unless the parameter decode_up_to_bad_char is set to
5470 * true. In that case, the function will decode up to the first invalid
5471 * character. Extra padding characters ('=') are considered invalid characters.
5472 *
5473 * Advanced users may want to tailor how the last chunk is handled. By default,
5474 * we use a loose (forgiving) approach but we also support a strict approach
5475 * as well as a stop_before_partial approach, as per the following proposal:
5476 *
5477 * https://tc39.es/proposal-arraybuffer-base64/spec/#sec-frombase64
5478 *
5479 * The base64_to_binary_safe function has negligible overhead compared with
5480 * base64_to_binary in the absence of ignorable characters; however, on short
5481 * inputs containing ignorable characters, it can be up to three times slower.
5482 *
5483 * @param input the base64 string to process, in ASCII stored as 8-bit
5484 * or 16-bit units
5485 * @param length the length of the string in 8-bit or 16-bit units.
5486 * @param output the pointer to a buffer that can hold the conversion
5487 * result.
5488 * @param outlen the number of bytes that can be written in the output
5489 * buffer. Upon return, it is modified to reflect how many bytes were written.
5490 * @param options the base64 options to use, can be base64_default or
5491 * base64_url, is base64_default by default.
5492 * @param last_chunk_options the last chunk handling options,
5493 * last_chunk_handling_options::loose by default
5494 * but can also be last_chunk_handling_options::strict or
5495 * last_chunk_handling_options::stop_before_partial.
5496 * @param decode_up_to_bad_char if true, the function will decode up to the
5497 * first invalid character. By default (false), it is assumed that the output
5498 * buffer is to be discarded. When there are multiple errors in the input,
5499 * using decode_up_to_bad_char might trigger a different error.
5500 * @return a result pair struct (of type simdutf::result containing the two
5501 * fields error and count) with an error code and position of the
5502 * INVALID_BASE64_CHARACTER error (in the input in units) if any, or the number
5503 * of units processed if successful.
5504 */
5505simdutf_warn_unused result
5506base64_to_binary_safe(const char *input, size_t length, char *output,
5507 size_t &outlen, base64_options options = base64_default,
5508 last_chunk_handling_options last_chunk_options =
5509 last_chunk_handling_options::loose,
5510 bool decode_up_to_bad_char = false) noexcept;
5511// the span overload has moved to the bottom of the file
5512
5513simdutf_warn_unused result
5514base64_to_binary_safe(const char16_t *input, size_t length, char *output,
5515 size_t &outlen, base64_options options = base64_default,
5516 last_chunk_handling_options last_chunk_options =
5517 last_chunk_handling_options::loose,
5518 bool decode_up_to_bad_char = false) noexcept;
5519 // span overload moved to bottom of file
5520
5521 #if SIMDUTF_ATOMIC_REF
5522/**
5523 * Convert a base64 input to a binary output with a size limit and using atomic
5524 * operations.
5525 *
5526 * Like `base64_to_binary_safe` but using atomic operations, this function is
5527 * thread-safe for concurrent memory access, allowing the output
5528 * buffers to be shared between threads without undefined behavior in case of
5529 * data races.
5530 *
5531 * This function comes with a potentially significant performance penalty, but
5532 * is useful when thread safety is needed during base64 decoding.
5533 *
5534 * This function is only available when simdutf is compiled with
5535 * C++20 support and __cpp_lib_atomic_ref >= 201806L. You may check
5536 * the availability of this function by checking the macro
5537 * SIMDUTF_ATOMIC_REF.
5538 *
5539 * This function is considered experimental. It is not tested by default
5540 * (see the CMake option SIMDUTF_ATOMIC_BASE64_TESTS) nor is it fuzz tested.
5541 * It is not documented in the public API documentation (README). It is
5542 * offered on a best effort basis. We rely on the community for further
5543 * testing and feedback.
5544 *
5545 * @param input the base64 input to decode
5546 * @param length the length of the input in bytes
5547 * @param output the pointer to buffer that can hold the conversion
5548 * result
5549 * @param outlen the number of bytes that can be written in the output
5550 * buffer. Upon return, it is modified to reflect how many bytes were written.
5551 * @param options the base64 options to use (default, url, etc.)
5552 * @param last_chunk_options the last chunk handling options (loose, strict,
5553 * stop_before_partial)
5554 * @param decode_up_to_bad_char if true, the function will decode up to the
5555 * first invalid character. By default (false), it is assumed that the output
5556 * buffer is to be discarded. When there are multiple errors in the input,
5557 * using decode_up_to_bad_char might trigger a different error.
5558 * @return a result struct with an error code and count indicating error
5559 * position or success
5560 */
5561simdutf_warn_unused result atomic_base64_to_binary_safe(
5562 const char *input, size_t length, char *output, size_t &outlen,
5563 base64_options options = base64_default,
5564 last_chunk_handling_options last_chunk_options =
5565 last_chunk_handling_options::loose,
5566 bool decode_up_to_bad_char = false) noexcept;
5567simdutf_warn_unused result atomic_base64_to_binary_safe(
5568 const char16_t *input, size_t length, char *output, size_t &outlen,
5569 base64_options options = base64_default,
5570 last_chunk_handling_options last_chunk_options = loose,
5571 bool decode_up_to_bad_char = false) noexcept;
5572 #if SIMDUTF_SPAN
5573/**
5574 * @brief span overload
5575 * @return a tuple of result and outlen
5576 */
5577simdutf_really_inline simdutf_warn_unused std::tuple<result, std::size_t>
5578atomic_base64_to_binary_safe(
5579 const detail::input_span_of_byte_like auto &binary_input,
5580 detail::output_span_of_byte_like auto &&output,
5581 base64_options options = base64_default,
5582 last_chunk_handling_options last_chunk_options =
5583 last_chunk_handling_options::loose,
5584 bool decode_up_to_bad_char = false) noexcept {
5585 size_t outlen = output.size();
5586 auto ret = atomic_base64_to_binary_safe(
5587 reinterpret_cast<const char *>(binary_input.data()), binary_input.size(),
5588 reinterpret_cast<char *>(output.data()), outlen, options,
5589 last_chunk_options, decode_up_to_bad_char);
5590 return {ret, outlen};
5591}
5592/**
5593 * @brief span overload
5594 * @return a tuple of result and outlen
5595 */
5596simdutf_warn_unused std::tuple<result, std::size_t>
5597atomic_base64_to_binary_safe(
5598 std::span<const char16_t> base64_input,
5599 detail::output_span_of_byte_like auto &&binary_output,
5600 base64_options options = base64_default,
5601 last_chunk_handling_options last_chunk_options = loose,
5602 bool decode_up_to_bad_char = false) noexcept {
5603 size_t outlen = binary_output.size();
5604 auto ret = atomic_base64_to_binary_safe(
5605 base64_input.data(), base64_input.size(),
5606 reinterpret_cast<char *>(binary_output.data()), outlen, options,
5607 last_chunk_options, decode_up_to_bad_char);
5608 return {ret, outlen};
5609}
5610 #endif // SIMDUTF_SPAN
5611 #endif // SIMDUTF_ATOMIC_REF
5612
5613#endif // SIMDUTF_FEATURE_BASE64
5614
5615/**
5616 * An implementation of simdutf for a particular CPU architecture.
5617 *
5618 * Also used to maintain the currently active implementation. The active
5619 * implementation is automatically initialized on first use to the most advanced
5620 * implementation supported by the host.
5621 */
5622class implementation {
5623public:
5624 /**
5625 * The name of this implementation.
5626 *
5627 * const implementation *impl = simdutf::active_implementation;
5628 * cout << "simdutf is optimized for " << impl->name() << "(" <<
5629 * impl->description() << ")" << endl;
5630 *
5631 * @return the name of the implementation, e.g. "haswell", "westmere", "arm64"
5632 */
5633 virtual std::string_view name() const noexcept { return _name; }
5634
5635 /**
5636 * The description of this implementation.
5637 *
5638 * const implementation *impl = simdutf::active_implementation;
5639 * cout << "simdutf is optimized for " << impl->name() << "(" <<
5640 * impl->description() << ")" << endl;
5641 *
5642 * @return the name of the implementation, e.g. "haswell", "westmere", "arm64"
5643 */
5644 virtual std::string_view description() const noexcept { return _description; }
5645
5646 /**
5647 * The instruction sets this implementation is compiled against
5648 * and the current CPU match. This function may poll the current CPU/system
5649 * and should therefore not be called too often if performance is a concern.
5650 *
5651 *
5652 * @return true if the implementation can be safely used on the current system
5653 * (determined at runtime)
5654 */
5656
5657#if SIMDUTF_FEATURE_DETECT_ENCODING
5658 /**
5659 * This function will try to detect the encoding
5660 * @param input the string to identify
5661 * @param length the length of the string in bytes.
5662 * @return the encoding type detected
5663 */
5664 virtual encoding_type autodetect_encoding(const char *input,
5665 size_t length) const noexcept;
5666
5667 /**
5668 * This function will try to detect the possible encodings in one pass
5669 * @param input the string to identify
5670 * @param length the length of the string in bytes.
5671 * @return the encoding type detected
5672 */
5673 virtual int detect_encodings(const char *input,
5674 size_t length) const noexcept = 0;
5675#endif // SIMDUTF_FEATURE_DETECT_ENCODING
5676
5677 /**
5678 * @private For internal implementation use
5679 *
5680 * The instruction sets this implementation is compiled against.
5681 *
5682 * @return a mask of all required `internal::instruction_set::` values
5683 */
5684 virtual uint32_t required_instruction_sets() const {
5685 return _required_instruction_sets;
5686 }
5687
5688#if SIMDUTF_FEATURE_UTF8 || SIMDUTF_FEATURE_DETECT_ENCODING
5689 /**
5690 * Validate the UTF-8 string.
5691 *
5692 * Overridden by each implementation.
5693 *
5694 * @param buf the UTF-8 string to validate.
5695 * @param len the length of the string in bytes.
5696 * @return true if and only if the string is valid UTF-8.
5697 */
5698 simdutf_warn_unused virtual bool validate_utf8(const char *buf,
5699 size_t len) const noexcept = 0;
5700#endif // SIMDUTF_FEATURE_UTF8 || SIMDUTF_FEATURE_DETECT_ENCODING
5701
5702#if SIMDUTF_FEATURE_UTF8
5703 /**
5704 * Validate the UTF-8 string and stop on errors.
5705 *
5706 * Overridden by each implementation.
5707 *
5708 * @param buf the UTF-8 string to validate.
5709 * @param len the length of the string in bytes.
5710 * @return a result pair struct (of type simdutf::result containing the two
5711 * fields error and count) with an error code and either position of the error
5712 * (in the input in code units) if any, or the number of code units validated
5713 * if successful.
5714 */
5715 simdutf_warn_unused virtual result
5716 validate_utf8_with_errors(const char *buf, size_t len) const noexcept = 0;
5717 /**
5718 * Finds the pointer to the first byte of invalid utf8 while counting
5719 continuation bytes and four-byte sequences.
5720
5721 * @param buf the UTF-8 string to validate.
5722 * @param len the length of the string in bytes.
5723 * @return a utf8_result struct. It contains the length of the valid utf8
5724 segment, the error code and the count of continuation bytes and four-byte
5725 sequences.
5726 *
5727 * Returns a utf8_result
5728 */
5729 virtual simdutf_warn_unused utf8_result
5730 validate_utf8_with_counts(const char *buf, size_t len) const noexcept = 0;
5731
5732#endif // SIMDUTF_FEATURE_UTF8
5733
5734#if SIMDUTF_FEATURE_ASCII
5735 /**
5736 * Validate the ASCII string.
5737 *
5738 * Overridden by each implementation.
5739 *
5740 * @param buf the ASCII string to validate.
5741 * @param len the length of the string in bytes.
5742 * @return true if and only if the string is valid ASCII.
5743 */
5744 simdutf_warn_unused virtual bool
5745 validate_ascii(const char *buf, size_t len) const noexcept = 0;
5746
5747 /**
5748 * Validate the ASCII string and stop on error.
5749 *
5750 * Overridden by each implementation.
5751 *
5752 * @param buf the ASCII string to validate.
5753 * @param len the length of the string in bytes.
5754 * @return a result pair struct (of type simdutf::result containing the two
5755 * fields error and count) with an error code and either position of the error
5756 * (in the input in code units) if any, or the number of code units validated
5757 * if successful.
5758 */
5759 simdutf_warn_unused virtual result
5760 validate_ascii_with_errors(const char *buf, size_t len) const noexcept = 0;
5761
5762#endif // SIMDUTF_FEATURE_ASCII
5763
5764#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_ASCII
5765 /**
5766 * Validate the ASCII string as a UTF-16BE sequence.
5767 * An UTF-16 sequence is considered an ASCII sequence
5768 * if it could be converted to an ASCII string losslessly.
5769 *
5770 * Overridden by each implementation.
5771 *
5772 * @param buf the UTF-16BE string to validate.
5773 * @param len the length of the string in bytes.
5774 * @return true if and only if the string is valid ASCII.
5775 */
5776 simdutf_warn_unused virtual bool
5777 validate_utf16be_as_ascii(const char16_t *buf, size_t len) const noexcept = 0;
5778
5779 /**
5780 * Validate the ASCII string as a UTF-16LE sequence.
5781 * An UTF-16 sequence is considered an ASCII sequence
5782 * if it could be converted to an ASCII string losslessly.
5783 *
5784 * Overridden by each implementation.
5785 *
5786 * @param buf the UTF-16LE string to validate.
5787 * @param len the length of the string in bytes.
5788 * @return true if and only if the string is valid ASCII.
5789 */
5790 simdutf_warn_unused virtual bool
5791 validate_utf16le_as_ascii(const char16_t *buf, size_t len) const noexcept = 0;
5792#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_ASCII
5793
5794#if SIMDUTF_FEATURE_UTF16 || SIMDUTF_FEATURE_DETECT_ENCODING
5795 /**
5796 * Validate the UTF-16LE string.This function may be best when you expect
5797 * the input to be almost always valid. Otherwise, consider using
5798 * validate_utf16le_with_errors.
5799 *
5800 * Overridden by each implementation.
5801 *
5802 * This function is not BOM-aware.
5803 *
5804 * @param buf the UTF-16LE string to validate.
5805 * @param len the length of the string in number of 2-byte code units
5806 * (char16_t).
5807 * @return true if and only if the string is valid UTF-16LE.
5808 */
5809 simdutf_warn_unused virtual bool
5810 validate_utf16le(const char16_t *buf, size_t len) const noexcept = 0;
5811#endif // SIMDUTF_FEATURE_UTF16 || SIMDUTF_FEATURE_DETECT_ENCODING
5812
5813#if SIMDUTF_FEATURE_UTF16
5814 /**
5815 * Validate the UTF-16BE string. This function may be best when you expect
5816 * the input to be almost always valid. Otherwise, consider using
5817 * validate_utf16be_with_errors.
5818 *
5819 * Overridden by each implementation.
5820 *
5821 * This function is not BOM-aware.
5822 *
5823 * @param buf the UTF-16BE string to validate.
5824 * @param len the length of the string in number of 2-byte code units
5825 * (char16_t).
5826 * @return true if and only if the string is valid UTF-16BE.
5827 */
5828 simdutf_warn_unused virtual bool
5829 validate_utf16be(const char16_t *buf, size_t len) const noexcept = 0;
5830
5831 /**
5832 * Validate the UTF-16LE string and stop on error. It might be faster than
5833 * validate_utf16le when an error is expected to occur early.
5834 *
5835 * Overridden by each implementation.
5836 *
5837 * This function is not BOM-aware.
5838 *
5839 * @param buf the UTF-16LE string to validate.
5840 * @param len the length of the string in number of 2-byte code units
5841 * (char16_t).
5842 * @return a result pair struct (of type simdutf::result containing the two
5843 * fields error and count) with an error code and either position of the error
5844 * (in the input in code units) if any, or the number of code units validated
5845 * if successful.
5846 */
5847 simdutf_warn_unused virtual result
5848 validate_utf16le_with_errors(const char16_t *buf,
5849 size_t len) const noexcept = 0;
5850
5851 /**
5852 * Validate the UTF-16BE string and stop on error. It might be faster than
5853 * validate_utf16be when an error is expected to occur early.
5854 *
5855 * Overridden by each implementation.
5856 *
5857 * This function is not BOM-aware.
5858 *
5859 * @param buf the UTF-16BE string to validate.
5860 * @param len the length of the string in number of 2-byte code units
5861 * (char16_t).
5862 * @return a result pair struct (of type simdutf::result containing the two
5863 * fields error and count) with an error code and either position of the error
5864 * (in the input in code units) if any, or the number of code units validated
5865 * if successful.
5866 */
5867 simdutf_warn_unused virtual result
5868 validate_utf16be_with_errors(const char16_t *buf,
5869 size_t len) const noexcept = 0;
5870 /**
5871 * Copies the UTF-16LE string while replacing mismatched surrogates with the
5872 * Unicode replacement character U+FFFD. We allow the input and output to be
5873 * the same buffer so that the correction is done in-place.
5874 *
5875 * Overridden by each implementation.
5876 *
5877 * @param input the UTF-16LE string to correct.
5878 * @param len the length of the string in number of 2-byte code units
5879 * (char16_t).
5880 * @param output the output buffer.
5881 */
5882 virtual void to_well_formed_utf16le(const char16_t *input, size_t len,
5883 char16_t *output) const noexcept = 0;
5884 /**
5885 * Copies the UTF-16BE string while replacing mismatched surrogates with the
5886 * Unicode replacement character U+FFFD. We allow the input and output to be
5887 * the same buffer so that the correction is done in-place.
5888 *
5889 * Overridden by each implementation.
5890 *
5891 * @param input the UTF-16BE string to correct.
5892 * @param len the length of the string in number of 2-byte code units
5893 * (char16_t).
5894 * @param output the output buffer.
5895 */
5896 virtual void to_well_formed_utf16be(const char16_t *input, size_t len,
5897 char16_t *output) const noexcept = 0;
5898#endif // SIMDUTF_FEATURE_UTF16
5899
5900#if SIMDUTF_FEATURE_UTF32 || SIMDUTF_FEATURE_DETECT_ENCODING
5901 /**
5902 * Validate the UTF-32 string.
5903 *
5904 * Overridden by each implementation.
5905 *
5906 * This function is not BOM-aware.
5907 *
5908 * @param buf the UTF-32 string to validate.
5909 * @param len the length of the string in number of 4-byte code units
5910 * (char32_t).
5911 * @return true if and only if the string is valid UTF-32.
5912 */
5913 simdutf_warn_unused virtual bool
5914 validate_utf32(const char32_t *buf, size_t len) const noexcept = 0;
5915#endif // SIMDUTF_FEATURE_UTF32 || SIMDUTF_FEATURE_DETECT_ENCODING
5916
5917#if SIMDUTF_FEATURE_UTF32
5918 /**
5919 * Validate the UTF-32 string and stop on error.
5920 *
5921 * Overridden by each implementation.
5922 *
5923 * This function is not BOM-aware.
5924 *
5925 * @param buf the UTF-32 string to validate.
5926 * @param len the length of the string in number of 4-byte code units
5927 * (char32_t).
5928 * @return a result pair struct (of type simdutf::result containing the two
5929 * fields error and count) with an error code and either position of the error
5930 * (in the input in code units) if any, or the number of code units validated
5931 * if successful.
5932 */
5933 simdutf_warn_unused virtual result
5934 validate_utf32_with_errors(const char32_t *buf,
5935 size_t len) const noexcept = 0;
5936#endif // SIMDUTF_FEATURE_UTF32
5937
5938#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
5939 /**
5940 * Convert Latin1 string into UTF-8 string.
5941 *
5942 * This function is suitable to work with inputs from untrusted sources.
5943 *
5944 * @param input the Latin1 string to convert
5945 * @param length the length of the string in bytes
5946 * @param utf8_output the pointer to buffer that can hold conversion result
5947 * @return the number of written char; 0 if conversion is not possible
5948 */
5949 simdutf_warn_unused virtual size_t
5950 convert_latin1_to_utf8(const char *input, size_t length,
5951 char *utf8_output) const noexcept = 0;
5952#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
5953
5954#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
5955 /**
5956 * Convert possibly Latin1 string into UTF-16LE string.
5957 *
5958 * This function is suitable to work with inputs from untrusted sources.
5959 *
5960 * @param input the Latin1 string to convert
5961 * @param length the length of the string in bytes
5962 * @param utf16_output the pointer to buffer that can hold conversion result
5963 * @return the number of written char16_t; 0 if conversion is not possible
5964 */
5965 simdutf_warn_unused virtual size_t
5966 convert_latin1_to_utf16le(const char *input, size_t length,
5967 char16_t *utf16_output) const noexcept = 0;
5968
5969 /**
5970 * Convert Latin1 string into UTF-16BE string.
5971 *
5972 * This function is suitable to work with inputs from untrusted sources.
5973 *
5974 * @param input the Latin1 string to convert
5975 * @param length the length of the string in bytes
5976 * @param utf16_output the pointer to buffer that can hold conversion result
5977 * @return the number of written char16_t; 0 if conversion is not possible
5978 */
5979 simdutf_warn_unused virtual size_t
5980 convert_latin1_to_utf16be(const char *input, size_t length,
5981 char16_t *utf16_output) const noexcept = 0;
5982#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
5983
5984#if SIMDUTF_FEATURE_UTF32 && SIMDUTF_FEATURE_LATIN1
5985 /**
5986 * Convert Latin1 string into UTF-32 string.
5987 *
5988 * This function is suitable to work with inputs from untrusted sources.
5989 *
5990 * @param input the Latin1 string to convert
5991 * @param length the length of the string in bytes
5992 * @param utf32_buffer the pointer to buffer that can hold conversion result
5993 * @return the number of written char32_t; 0 if conversion is not possible
5994 */
5995 simdutf_warn_unused virtual size_t
5996 convert_latin1_to_utf32(const char *input, size_t length,
5997 char32_t *utf32_buffer) const noexcept = 0;
5998#endif // SIMDUTF_FEATURE_UTF32 && SIMDUTF_FEATURE_LATIN1
5999
6000#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
6001 /**
6002 * Convert possibly broken UTF-8 string into latin1 string.
6003 *
6004 * During the conversion also validation of the input string is done.
6005 * This function is suitable to work with inputs from untrusted sources.
6006 *
6007 * @param input the UTF-8 string to convert
6008 * @param length the length of the string in bytes
6009 * @param latin1_output the pointer to buffer that can hold conversion result
6010 * @return the number of written char; 0 if the input was not valid UTF-8
6011 * string or if it cannot be represented as Latin1
6012 */
6013 simdutf_warn_unused virtual size_t
6014 convert_utf8_to_latin1(const char *input, size_t length,
6015 char *latin1_output) const noexcept = 0;
6016
6017 /**
6018 * Convert possibly broken UTF-8 string into latin1 string with errors.
6019 * If the string cannot be represented as Latin1, an error
6020 * code is returned.
6021 *
6022 * During the conversion also validation of the input string is done.
6023 * This function is suitable to work with inputs from untrusted sources.
6024 *
6025 * @param input the UTF-8 string to convert
6026 * @param length the length of the string in bytes
6027 * @param latin1_output the pointer to buffer that can hold conversion result
6028 * @return a result pair struct (of type simdutf::result containing the two
6029 * fields error and count) with an error code and either position of the error
6030 * (in the input in code units) if any, or the number of code units validated
6031 * if successful.
6032 */
6033 simdutf_warn_unused virtual result
6034 convert_utf8_to_latin1_with_errors(const char *input, size_t length,
6035 char *latin1_output) const noexcept = 0;
6036
6037 /**
6038 * Convert valid UTF-8 string into latin1 string.
6039 *
6040 * This function assumes that the input string is valid UTF-8 and that it can
6041 * be represented as Latin1. If you violate this assumption, the result is
6042 * implementation defined and may include system-dependent behavior such as
6043 * crashes.
6044 *
6045 * This function is for expert users only and not part of our public API. Use
6046 * convert_utf8_to_latin1 instead.
6047 *
6048 * This function is not BOM-aware.
6049 *
6050 * @param input the UTF-8 string to convert
6051 * @param length the length of the string in bytes
6052 * @param latin1_output the pointer to buffer that can hold conversion result
6053 * @return the number of written char; 0 if the input was not valid UTF-8
6054 * string
6055 */
6056 simdutf_warn_unused virtual size_t
6057 convert_valid_utf8_to_latin1(const char *input, size_t length,
6058 char *latin1_output) const noexcept = 0;
6059#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
6060
6061#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
6062 /**
6063 * Convert possibly broken UTF-8 string into UTF-16LE string.
6064 *
6065 * During the conversion also validation of the input string is done.
6066 * This function is suitable to work with inputs from untrusted sources.
6067 *
6068 * @param input the UTF-8 string to convert
6069 * @param length the length of the string in bytes
6070 * @param utf16_output the pointer to buffer that can hold conversion result
6071 * @return the number of written char16_t; 0 if the input was not valid UTF-8
6072 * string
6073 */
6074 simdutf_warn_unused virtual size_t
6075 convert_utf8_to_utf16le(const char *input, size_t length,
6076 char16_t *utf16_output) const noexcept = 0;
6077
6078 /**
6079 * Convert possibly broken UTF-8 string into UTF-16BE string.
6080 *
6081 * During the conversion also validation of the input string is done.
6082 * This function is suitable to work with inputs from untrusted sources.
6083 *
6084 * @param input the UTF-8 string to convert
6085 * @param length the length of the string in bytes
6086 * @param utf16_output the pointer to buffer that can hold conversion result
6087 * @return the number of written char16_t; 0 if the input was not valid UTF-8
6088 * string
6089 */
6090 simdutf_warn_unused virtual size_t
6091 convert_utf8_to_utf16be(const char *input, size_t length,
6092 char16_t *utf16_output) const noexcept = 0;
6093
6094 /**
6095 * Convert possibly broken UTF-8 string into UTF-16LE string and stop on
6096 * error.
6097 *
6098 * During the conversion also validation of the input string is done.
6099 * This function is suitable to work with inputs from untrusted sources.
6100 *
6101 * @param input the UTF-8 string to convert
6102 * @param length the length of the string in bytes
6103 * @param utf16_output the pointer to buffer that can hold conversion result
6104 * @return a result pair struct (of type simdutf::result containing the two
6105 * fields error and count) with an error code and either position of the error
6106 * (in the input in code units) if any, or the number of code units validated
6107 * if successful.
6108 */
6109 simdutf_warn_unused virtual result convert_utf8_to_utf16le_with_errors(
6110 const char *input, size_t length,
6111 char16_t *utf16_output) const noexcept = 0;
6112
6113 /**
6114 * Convert possibly broken UTF-8 string into UTF-16BE string and stop on
6115 * error.
6116 *
6117 * During the conversion also validation of the input string is done.
6118 * This function is suitable to work with inputs from untrusted sources.
6119 *
6120 * @param input the UTF-8 string to convert
6121 * @param length the length of the string in bytes
6122 * @param utf16_output the pointer to buffer that can hold conversion result
6123 * @return a result pair struct (of type simdutf::result containing the two
6124 * fields error and count) with an error code and either position of the error
6125 * (in the input in code units) if any, or the number of code units validated
6126 * if successful.
6127 */
6128 simdutf_warn_unused virtual result convert_utf8_to_utf16be_with_errors(
6129 const char *input, size_t length,
6130 char16_t *utf16_output) const noexcept = 0;
6131 /**
6132 * Compute the number of bytes that this UTF-16LE string would require in
6133 * UTF-8 format even when the UTF-16LE content contains mismatched
6134 * surrogates that have to be replaced by the replacement character (0xFFFD).
6135 *
6136 * @param input the UTF-16LE string to convert
6137 * @param length the length of the string in 2-byte code units
6138 * (char16_t)
6139 * @return a result pair struct (of type simdutf::result containing the two
6140 * fields error and count) where the count is the number of bytes required to
6141 * encode the UTF-16LE string as UTF-8, and the error code is either SUCCESS
6142 * or SURROGATE. The count is correct regardless of the error field.
6143 * When SURROGATE is returned, it does not indicate an error in the case of
6144 * this function: it indicates that at least one surrogate has been
6145 * encountered: the surrogates may be matched or not (thus this function does
6146 * not validate). If the returned error code is SUCCESS, then the input
6147 * contains no surrogate, is in the Basic Multilingual Plane, and is
6148 * necessarily valid.
6149 */
6151 const char16_t *input, size_t length) const noexcept = 0;
6152
6153 /**
6154 * Compute the number of bytes that this UTF-16BE string would require in
6155 * UTF-8 format even when the UTF-16BE content contains mismatched
6156 * surrogates that have to be replaced by the replacement character (0xFFFD).
6157 *
6158 * @param input the UTF-16BE string to convert
6159 * @param length the length of the string in 2-byte code units
6160 * (char16_t)
6161 * @return a result pair struct (of type simdutf::result containing the two
6162 * fields error and count) where the count is the number of bytes required to
6163 * encode the UTF-16BE string as UTF-8, and the error code is either SUCCESS
6164 * or SURROGATE. The count is correct regardless of the error field.
6165 * When SURROGATE is returned, it does not indicate an error in the case of
6166 * this function: it indicates that at least one surrogate has been
6167 * encountered: the surrogates may be matched or not (thus this function does
6168 * not validate). If the returned error code is SUCCESS, then the input
6169 * contains no surrogate, is in the Basic Multilingual Plane, and is
6170 * necessarily valid.
6171 */
6173 const char16_t *input, size_t length) const noexcept = 0;
6174
6175#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
6176
6177#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
6178 /**
6179 * Convert possibly broken UTF-8 string into UTF-32 string.
6180 *
6181 * During the conversion also validation of the input string is done.
6182 * This function is suitable to work with inputs from untrusted sources.
6183 *
6184 * @param input the UTF-8 string to convert
6185 * @param length the length of the string in bytes
6186 * @param utf32_output the pointer to buffer that can hold conversion result
6187 * @return the number of written char16_t; 0 if the input was not valid UTF-8
6188 * string
6189 */
6190 simdutf_warn_unused virtual size_t
6191 convert_utf8_to_utf32(const char *input, size_t length,
6192 char32_t *utf32_output) const noexcept = 0;
6193
6194 /**
6195 * Convert possibly broken UTF-8 string into UTF-32 string and stop on error.
6196 *
6197 * During the conversion also validation of the input string is done.
6198 * This function is suitable to work with inputs from untrusted sources.
6199 *
6200 * @param input the UTF-8 string to convert
6201 * @param length the length of the string in bytes
6202 * @param utf32_output the pointer to buffer that can hold conversion result
6203 * @return a result pair struct (of type simdutf::result containing the two
6204 * fields error and count) with an error code and either position of the error
6205 * (in the input in code units) if any, or the number of char32_t written if
6206 * successful.
6207 */
6208 simdutf_warn_unused virtual result
6209 convert_utf8_to_utf32_with_errors(const char *input, size_t length,
6210 char32_t *utf32_output) const noexcept = 0;
6211#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
6212
6213#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
6214 /**
6215 * Convert valid UTF-8 string into UTF-16LE string.
6216 *
6217 * This function assumes that the input string is valid UTF-8.
6218 *
6219 * @param input the UTF-8 string to convert
6220 * @param length the length of the string in bytes
6221 * @param utf16_buffer the pointer to buffer that can hold conversion result
6222 * @return the number of written char16_t
6223 */
6224 simdutf_warn_unused virtual size_t
6225 convert_valid_utf8_to_utf16le(const char *input, size_t length,
6226 char16_t *utf16_buffer) const noexcept = 0;
6227
6228 /**
6229 * Convert valid UTF-8 string into UTF-16BE string.
6230 *
6231 * This function assumes that the input string is valid UTF-8.
6232 *
6233 * @param input the UTF-8 string to convert
6234 * @param length the length of the string in bytes
6235 * @param utf16_buffer the pointer to buffer that can hold conversion result
6236 * @return the number of written char16_t
6237 */
6238 simdutf_warn_unused virtual size_t
6239 convert_valid_utf8_to_utf16be(const char *input, size_t length,
6240 char16_t *utf16_buffer) const noexcept = 0;
6241#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
6242
6243#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
6244 /**
6245 * Convert valid UTF-8 string into UTF-32 string.
6246 *
6247 * This function assumes that the input string is valid UTF-8.
6248 *
6249 * @param input the UTF-8 string to convert
6250 * @param length the length of the string in bytes
6251 * @param utf32_buffer the pointer to buffer that can hold conversion result
6252 * @return the number of written char32_t
6253 */
6254 simdutf_warn_unused virtual size_t
6255 convert_valid_utf8_to_utf32(const char *input, size_t length,
6256 char32_t *utf32_buffer) const noexcept = 0;
6257#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
6258
6259#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
6260 /**
6261 * Compute the number of 2-byte code units that this UTF-8 string would
6262 * require in UTF-16LE format.
6263 *
6264 * This function does not validate the input. It is acceptable to pass invalid
6265 * UTF-8 strings but in such cases the result is implementation defined.
6266 *
6267 * @param input the UTF-8 string to process
6268 * @param length the length of the string in bytes
6269 * @return the number of char16_t code units required to encode the UTF-8
6270 * string as UTF-16LE
6271 */
6272 simdutf_warn_unused virtual size_t
6273 utf16_length_from_utf8(const char *input, size_t length) const noexcept = 0;
6274#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
6275
6276#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
6277 /**
6278 * Compute the number of 4-byte code units that this UTF-8 string would
6279 * require in UTF-32 format.
6280 *
6281 * This function is equivalent to count_utf8. It is acceptable to pass invalid
6282 * UTF-8 strings but in such cases the result is implementation defined.
6283 *
6284 * This function does not validate the input.
6285 *
6286 * @param input the UTF-8 string to process
6287 * @param length the length of the string in bytes
6288 * @return the number of char32_t code units required to encode the UTF-8
6289 * string as UTF-32
6290 */
6291 simdutf_warn_unused virtual size_t
6292 utf32_length_from_utf8(const char *input, size_t length) const noexcept = 0;
6293#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
6294
6295#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
6296 /**
6297 * Convert possibly broken UTF-16LE string into Latin1 string.
6298 *
6299 * During the conversion also validation of the input string is done.
6300 * This function is suitable to work with inputs from untrusted sources.
6301 *
6302 * This function is not BOM-aware.
6303 *
6304 * @param input the UTF-16LE string to convert
6305 * @param length the length of the string in 2-byte code units
6306 * (char16_t)
6307 * @param latin1_buffer the pointer to buffer that can hold conversion
6308 * result
6309 * @return number of written code units; 0 if input is not a valid UTF-16LE
6310 * string or if it cannot be represented as Latin1
6311 */
6312 simdutf_warn_unused virtual size_t
6313 convert_utf16le_to_latin1(const char16_t *input, size_t length,
6314 char *latin1_buffer) const noexcept = 0;
6315
6316 /**
6317 * Convert possibly broken UTF-16BE string into Latin1 string.
6318 *
6319 * During the conversion also validation of the input string is done.
6320 * This function is suitable to work with inputs from untrusted sources.
6321 *
6322 * This function is not BOM-aware.
6323 *
6324 * @param input the UTF-16BE string to convert
6325 * @param length the length of the string in 2-byte code units
6326 * (char16_t)
6327 * @param latin1_buffer the pointer to buffer that can hold conversion
6328 * result
6329 * @return number of written code units; 0 if input is not a valid UTF-16BE
6330 * string or if it cannot be represented as Latin1
6331 */
6332 simdutf_warn_unused virtual size_t
6333 convert_utf16be_to_latin1(const char16_t *input, size_t length,
6334 char *latin1_buffer) const noexcept = 0;
6335
6336 /**
6337 * Convert possibly broken UTF-16LE string into Latin1 string.
6338 * If the string cannot be represented as Latin1, an error
6339 * is returned.
6340 *
6341 * During the conversion also validation of the input string is done.
6342 * This function is suitable to work with inputs from untrusted sources.
6343 * This function is not BOM-aware.
6344 *
6345 * @param input the UTF-16LE string to convert
6346 * @param length the length of the string in 2-byte code units
6347 * (char16_t)
6348 * @param latin1_buffer the pointer to buffer that can hold conversion
6349 * result
6350 * @return a result pair struct (of type simdutf::result containing the two
6351 * fields error and count) with an error code and either position of the error
6352 * (in the input in code units) if any, or the number of char written if
6353 * successful.
6354 */
6355 simdutf_warn_unused virtual result
6356 convert_utf16le_to_latin1_with_errors(const char16_t *input, size_t length,
6357 char *latin1_buffer) const noexcept = 0;
6358
6359 /**
6360 * Convert possibly broken UTF-16BE string into Latin1 string.
6361 * If the string cannot be represented as Latin1, an error
6362 * is returned.
6363 *
6364 * During the conversion also validation of the input string is done.
6365 * This function is suitable to work with inputs from untrusted sources.
6366 * This function is not BOM-aware.
6367 *
6368 * @param input the UTF-16BE string to convert
6369 * @param length the length of the string in 2-byte code units
6370 * (char16_t)
6371 * @param latin1_buffer the pointer to buffer that can hold conversion
6372 * result
6373 * @return a result pair struct (of type simdutf::result containing the two
6374 * fields error and count) with an error code and either position of the error
6375 * (in the input in code units) if any, or the number of char written if
6376 * successful.
6377 */
6378 simdutf_warn_unused virtual result
6379 convert_utf16be_to_latin1_with_errors(const char16_t *input, size_t length,
6380 char *latin1_buffer) const noexcept = 0;
6381
6382 /**
6383 * Convert valid UTF-16LE string into Latin1 string.
6384 *
6385 * This function assumes that the input string is valid UTF-L16LE and that it
6386 * can be represented as Latin1. If you violate this assumption, the result is
6387 * implementation defined and may include system-dependent behavior such as
6388 * crashes.
6389 *
6390 * This function is for expert users only and not part of our public API. Use
6391 * convert_utf16le_to_latin1 instead.
6392 *
6393 * This function is not BOM-aware.
6394 *
6395 * @param input the UTF-16LE string to convert
6396 * @param length the length of the string in 2-byte code units
6397 * (char16_t)
6398 * @param latin1_buffer the pointer to buffer that can hold conversion
6399 * result
6400 * @return number of written code units; 0 if conversion is not possible
6401 */
6402 simdutf_warn_unused virtual size_t
6403 convert_valid_utf16le_to_latin1(const char16_t *input, size_t length,
6404 char *latin1_buffer) const noexcept = 0;
6405
6406 /**
6407 * Convert valid UTF-16BE string into Latin1 string.
6408 *
6409 * This function assumes that the input string is valid UTF16-BE and that it
6410 * can be represented as Latin1. If you violate this assumption, the result is
6411 * implementation defined and may include system-dependent behavior such as
6412 * crashes.
6413 *
6414 * This function is for expert users only and not part of our public API. Use
6415 * convert_utf16be_to_latin1 instead.
6416 *
6417 * This function is not BOM-aware.
6418 *
6419 * @param input the UTF-16BE string to convert
6420 * @param length the length of the string in 2-byte code units
6421 * (char16_t)
6422 * @param latin1_buffer the pointer to buffer that can hold conversion
6423 * result
6424 * @return number of written code units; 0 if conversion is not possible
6425 */
6426 simdutf_warn_unused virtual size_t
6427 convert_valid_utf16be_to_latin1(const char16_t *input, size_t length,
6428 char *latin1_buffer) const noexcept = 0;
6429#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
6430
6431#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
6432 /**
6433 * Convert possibly broken UTF-16LE string into UTF-8 string.
6434 *
6435 * During the conversion also validation of the input string is done.
6436 * This function is suitable to work with inputs from untrusted sources.
6437 *
6438 * This function is not BOM-aware.
6439 *
6440 * @param input the UTF-16LE string to convert
6441 * @param length the length of the string in 2-byte code units
6442 * (char16_t)
6443 * @param utf8_buffer the pointer to buffer that can hold conversion result
6444 * @return number of written code units; 0 if input is not a valid UTF-16LE
6445 * string
6446 */
6447 simdutf_warn_unused virtual size_t
6448 convert_utf16le_to_utf8(const char16_t *input, size_t length,
6449 char *utf8_buffer) const noexcept = 0;
6450
6451 /**
6452 * Convert possibly broken UTF-16BE string into UTF-8 string.
6453 *
6454 * During the conversion also validation of the input string is done.
6455 * This function is suitable to work with inputs from untrusted sources.
6456 *
6457 * This function is not BOM-aware.
6458 *
6459 * @param input the UTF-16BE string to convert
6460 * @param length the length of the string in 2-byte code units
6461 * (char16_t)
6462 * @param utf8_buffer the pointer to buffer that can hold conversion result
6463 * @return number of written code units; 0 if input is not a valid UTF-16BE
6464 * string
6465 */
6466 simdutf_warn_unused virtual size_t
6467 convert_utf16be_to_utf8(const char16_t *input, size_t length,
6468 char *utf8_buffer) const noexcept = 0;
6469
6470 /**
6471 * Convert possibly broken UTF-16LE string into UTF-8 string and stop on
6472 * error.
6473 *
6474 * During the conversion also validation of the input string is done.
6475 * This function is suitable to work with inputs from untrusted sources.
6476 *
6477 * This function is not BOM-aware.
6478 *
6479 * @param input the UTF-16LE string to convert
6480 * @param length the length of the string in 2-byte code units
6481 * (char16_t)
6482 * @param utf8_buffer the pointer to buffer that can hold conversion result
6483 * @return a result pair struct (of type simdutf::result containing the two
6484 * fields error and count) with an error code and either position of the error
6485 * (in the input in code units) if any, or the number of char written if
6486 * successful.
6487 */
6488 simdutf_warn_unused virtual result
6489 convert_utf16le_to_utf8_with_errors(const char16_t *input, size_t length,
6490 char *utf8_buffer) const noexcept = 0;
6491
6492 /**
6493 * Convert possibly broken UTF-16BE string into UTF-8 string and stop on
6494 * error.
6495 *
6496 * During the conversion also validation of the input string is done.
6497 * This function is suitable to work with inputs from untrusted sources.
6498 *
6499 * This function is not BOM-aware.
6500 *
6501 * @param input the UTF-16BE string to convert
6502 * @param length the length of the string in 2-byte code units
6503 * (char16_t)
6504 * @param utf8_buffer the pointer to buffer that can hold conversion result
6505 * @return a result pair struct (of type simdutf::result containing the two
6506 * fields error and count) with an error code and either position of the error
6507 * (in the input in code units) if any, or the number of char written if
6508 * successful.
6509 */
6510 simdutf_warn_unused virtual result
6511 convert_utf16be_to_utf8_with_errors(const char16_t *input, size_t length,
6512 char *utf8_buffer) const noexcept = 0;
6513
6514 /**
6515 * Convert possibly broken UTF-16LE string into UTF-8 string, replacing
6516 * unpaired surrogates with the Unicode replacement character U+FFFD.
6517 *
6518 * This function always succeeds: unpaired surrogates are replaced with
6519 * U+FFFD (3 bytes in UTF-8: 0xEF 0xBF 0xBD).
6520 *
6521 * This function is not BOM-aware.
6522 *
6523 * @param input the UTF-16LE string to convert
6524 * @param length the length of the string in 2-byte code units
6525 * (char16_t)
6526 * @param utf8_buffer the pointer to buffer that can hold conversion result
6527 * @return number of written code units
6528 */
6529 simdutf_warn_unused virtual size_t convert_utf16le_to_utf8_with_replacement(
6530 const char16_t *input, size_t length,
6531 char *utf8_buffer) const noexcept = 0;
6532
6533 /**
6534 * Convert possibly broken UTF-16BE string into UTF-8 string, replacing
6535 * unpaired surrogates with the Unicode replacement character U+FFFD.
6536 *
6537 * This function always succeeds: unpaired surrogates are replaced with
6538 * U+FFFD (3 bytes in UTF-8: 0xEF 0xBF 0xBD).
6539 *
6540 * This function is not BOM-aware.
6541 *
6542 * @param input the UTF-16BE string to convert
6543 * @param length the length of the string in 2-byte code units
6544 * (char16_t)
6545 * @param utf8_buffer the pointer to buffer that can hold conversion result
6546 * @return number of written code units
6547 */
6548 simdutf_warn_unused virtual size_t convert_utf16be_to_utf8_with_replacement(
6549 const char16_t *input, size_t length,
6550 char *utf8_buffer) const noexcept = 0;
6551
6552 /**
6553 * Convert valid UTF-16LE string into UTF-8 string.
6554 *
6555 * This function assumes that the input string is valid UTF-16LE.
6556 *
6557 * This function is not BOM-aware.
6558 *
6559 * @param input the UTF-16LE string to convert
6560 * @param length the length of the string in 2-byte code units
6561 * (char16_t)
6562 * @param utf8_buffer the pointer to a buffer that can hold the conversion
6563 * result
6564 * @return number of written code units; 0 if conversion is not possible
6565 */
6566 simdutf_warn_unused virtual size_t
6567 convert_valid_utf16le_to_utf8(const char16_t *input, size_t length,
6568 char *utf8_buffer) const noexcept = 0;
6569
6570 /**
6571 * Convert valid UTF-16BE string into UTF-8 string.
6572 *
6573 * This function assumes that the input string is valid UTF-16BE.
6574 *
6575 * This function is not BOM-aware.
6576 *
6577 * @param input the UTF-16BE string to convert
6578 * @param length the length of the string in 2-byte code units
6579 * (char16_t)
6580 * @param utf8_buffer the pointer to a buffer that can hold the conversion
6581 * result
6582 * @return number of written code units; 0 if conversion is not possible
6583 */
6584 simdutf_warn_unused virtual size_t
6585 convert_valid_utf16be_to_utf8(const char16_t *input, size_t length,
6586 char *utf8_buffer) const noexcept = 0;
6587#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
6588
6589#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
6590 /**
6591 * Convert possibly broken UTF-16LE string into UTF-32 string.
6592 *
6593 * During the conversion also validation of the input string is done.
6594 * This function is suitable to work with inputs from untrusted sources.
6595 *
6596 * This function is not BOM-aware.
6597 *
6598 * @param input the UTF-16LE string to convert
6599 * @param length the length of the string in 2-byte code units
6600 * (char16_t)
6601 * @param utf32_buffer the pointer to buffer that can hold conversion result
6602 * @return number of written code units; 0 if input is not a valid UTF-16LE
6603 * string
6604 */
6605 simdutf_warn_unused virtual size_t
6606 convert_utf16le_to_utf32(const char16_t *input, size_t length,
6607 char32_t *utf32_buffer) const noexcept = 0;
6608
6609 /**
6610 * Convert possibly broken UTF-16BE string into UTF-32 string.
6611 *
6612 * During the conversion also validation of the input string is done.
6613 * This function is suitable to work with inputs from untrusted sources.
6614 *
6615 * This function is not BOM-aware.
6616 *
6617 * @param input the UTF-16BE string to convert
6618 * @param length the length of the string in 2-byte code units
6619 * (char16_t)
6620 * @param utf32_buffer the pointer to buffer that can hold conversion result
6621 * @return number of written code units; 0 if input is not a valid UTF-16BE
6622 * string
6623 */
6624 simdutf_warn_unused virtual size_t
6625 convert_utf16be_to_utf32(const char16_t *input, size_t length,
6626 char32_t *utf32_buffer) const noexcept = 0;
6627
6628 /**
6629 * Convert possibly broken UTF-16LE string into UTF-32 string and stop on
6630 * error.
6631 *
6632 * During the conversion also validation of the input string is done.
6633 * This function is suitable to work with inputs from untrusted sources.
6634 *
6635 * This function is not BOM-aware.
6636 *
6637 * @param input the UTF-16LE string to convert
6638 * @param length the length of the string in 2-byte code units
6639 * (char16_t)
6640 * @param utf32_buffer the pointer to buffer that can hold conversion result
6641 * @return a result pair struct (of type simdutf::result containing the two
6642 * fields error and count) with an error code and either position of the error
6643 * (in the input in code units) if any, or the number of char32_t written if
6644 * successful.
6645 */
6647 const char16_t *input, size_t length,
6648 char32_t *utf32_buffer) const noexcept = 0;
6649
6650 /**
6651 * Convert possibly broken UTF-16BE string into UTF-32 string and stop on
6652 * error.
6653 *
6654 * During the conversion also validation of the input string is done.
6655 * This function is suitable to work with inputs from untrusted sources.
6656 *
6657 * This function is not BOM-aware.
6658 *
6659 * @param input the UTF-16BE string to convert
6660 * @param length the length of the string in 2-byte code units
6661 * (char16_t)
6662 * @param utf32_buffer the pointer to buffer that can hold conversion result
6663 * @return a result pair struct (of type simdutf::result containing the two
6664 * fields error and count) with an error code and either position of the error
6665 * (in the input in code units) if any, or the number of char32_t written if
6666 * successful.
6667 */
6669 const char16_t *input, size_t length,
6670 char32_t *utf32_buffer) const noexcept = 0;
6671
6672 /**
6673 * Convert valid UTF-16LE string into UTF-32 string.
6674 *
6675 * This function assumes that the input string is valid UTF-16LE.
6676 *
6677 * This function is not BOM-aware.
6678 *
6679 * @param input the UTF-16LE string to convert
6680 * @param length the length of the string in 2-byte code units
6681 * (char16_t)
6682 * @param utf32_buffer the pointer to a buffer that can hold the conversion
6683 * result
6684 * @return number of written code units; 0 if conversion is not possible
6685 */
6686 simdutf_warn_unused virtual size_t
6687 convert_valid_utf16le_to_utf32(const char16_t *input, size_t length,
6688 char32_t *utf32_buffer) const noexcept = 0;
6689
6690 /**
6691 * Convert valid UTF-16LE string into UTF-32BE string.
6692 *
6693 * This function assumes that the input string is valid UTF-16BE.
6694 *
6695 * This function is not BOM-aware.
6696 *
6697 * @param input the UTF-16BE string to convert
6698 * @param length the length of the string in 2-byte code units
6699 * (char16_t)
6700 * @param utf32_buffer the pointer to a buffer that can hold the conversion
6701 * result
6702 * @return number of written code units; 0 if conversion is not possible
6703 */
6704 simdutf_warn_unused virtual size_t
6705 convert_valid_utf16be_to_utf32(const char16_t *input, size_t length,
6706 char32_t *utf32_buffer) const noexcept = 0;
6707#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
6708
6709#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
6710 /**
6711 * Compute the number of bytes that this UTF-16LE string would require in
6712 * UTF-8 format.
6713 *
6714 * This function does not validate the input. It is acceptable to pass invalid
6715 * UTF-16 strings but in such cases the result is implementation defined.
6716 *
6717 * This function is not BOM-aware.
6718 *
6719 * @param input the UTF-16LE string to convert
6720 * @param length the length of the string in 2-byte code units
6721 * (char16_t)
6722 * @return the number of bytes required to encode the UTF-16LE string as UTF-8
6723 */
6724 simdutf_warn_unused virtual size_t
6725 utf8_length_from_utf16le(const char16_t *input,
6726 size_t length) const noexcept = 0;
6727
6728 /**
6729 * Compute the number of bytes that this UTF-16BE string would require in
6730 * UTF-8 format.
6731 *
6732 * This function does not validate the input. It is acceptable to pass invalid
6733 * UTF-16 strings but in such cases the result is implementation defined.
6734 *
6735 * This function is not BOM-aware.
6736 *
6737 * @param input the UTF-16BE string to convert
6738 * @param length the length of the string in 2-byte code units
6739 * (char16_t)
6740 * @return the number of bytes required to encode the UTF-16BE string as UTF-8
6741 */
6742 simdutf_warn_unused virtual size_t
6743 utf8_length_from_utf16be(const char16_t *input,
6744 size_t length) const noexcept = 0;
6745#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
6746
6747#if SIMDUTF_FEATURE_UTF32 && SIMDUTF_FEATURE_LATIN1
6748 /**
6749 * Convert possibly broken UTF-32 string into Latin1 string.
6750 *
6751 * During the conversion also validation of the input string is done.
6752 * This function is suitable to work with inputs from untrusted sources.
6753 *
6754 * This function is not BOM-aware.
6755 *
6756 * @param input the UTF-32 string to convert
6757 * @param length the length of the string in 4-byte code units
6758 * (char32_t)
6759 * @param latin1_buffer the pointer to buffer that can hold conversion
6760 * result
6761 * @return number of written code units; 0 if input is not a valid UTF-32
6762 * string
6763 */
6764 simdutf_warn_unused virtual size_t
6765 convert_utf32_to_latin1(const char32_t *input, size_t length,
6766 char *latin1_buffer) const noexcept = 0;
6767#endif // SIMDUTF_FEATURE_UTF32 && SIMDUTF_FEATURE_LATIN1
6768
6769#if SIMDUTF_FEATURE_UTF32 && SIMDUTF_FEATURE_LATIN1
6770 /**
6771 * Convert possibly broken UTF-32 string into Latin1 string and stop on error.
6772 * If the string cannot be represented as Latin1, an error is returned.
6773 *
6774 * During the conversion also validation of the input string is done.
6775 * This function is suitable to work with inputs from untrusted sources.
6776 *
6777 * This function is not BOM-aware.
6778 *
6779 * @param input the UTF-32 string to convert
6780 * @param length the length of the string in 4-byte code units
6781 * (char32_t)
6782 * @param latin1_buffer the pointer to buffer that can hold conversion
6783 * result
6784 * @return a result pair struct (of type simdutf::result containing the two
6785 * fields error and count) with an error code and either position of the error
6786 * (in the input in code units) if any, or the number of char written if
6787 * successful.
6788 */
6789 simdutf_warn_unused virtual result
6790 convert_utf32_to_latin1_with_errors(const char32_t *input, size_t length,
6791 char *latin1_buffer) const noexcept = 0;
6792
6793 /**
6794 * Convert valid UTF-32 string into Latin1 string.
6795 *
6796 * This function assumes that the input string is valid UTF-32 and can be
6797 * represented as Latin1. If you violate this assumption, the result is
6798 * implementation defined and may include system-dependent behavior such as
6799 * crashes.
6800 *
6801 * This function is for expert users only and not part of our public API. Use
6802 * convert_utf32_to_latin1 instead.
6803 *
6804 * This function is not BOM-aware.
6805 *
6806 * @param input the UTF-32 string to convert
6807 * @param length the length of the string in 4-byte code units
6808 * (char32_t)
6809 * @param latin1_buffer the pointer to a buffer that can hold the conversion
6810 * result
6811 * @return number of written code units; 0 if conversion is not possible
6812 */
6813 simdutf_warn_unused virtual size_t
6814 convert_valid_utf32_to_latin1(const char32_t *input, size_t length,
6815 char *latin1_buffer) const noexcept = 0;
6816#endif // SIMDUTF_FEATURE_UTF32 && SIMDUTF_FEATURE_LATIN1
6817
6818#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
6819 /**
6820 * Convert possibly broken UTF-32 string into UTF-8 string.
6821 *
6822 * During the conversion also validation of the input string is done.
6823 * This function is suitable to work with inputs from untrusted sources.
6824 *
6825 * This function is not BOM-aware.
6826 *
6827 * @param input the UTF-32 string to convert
6828 * @param length the length of the string in 4-byte code units
6829 * (char32_t)
6830 * @param utf8_buffer the pointer to buffer that can hold conversion result
6831 * @return number of written code units; 0 if input is not a valid UTF-32
6832 * string
6833 */
6834 simdutf_warn_unused virtual size_t
6835 convert_utf32_to_utf8(const char32_t *input, size_t length,
6836 char *utf8_buffer) const noexcept = 0;
6837
6838 /**
6839 * Convert possibly broken UTF-32 string into UTF-8 string and stop on error.
6840 *
6841 * During the conversion also validation of the input string is done.
6842 * This function is suitable to work with inputs from untrusted sources.
6843 *
6844 * This function is not BOM-aware.
6845 *
6846 * @param input the UTF-32 string to convert
6847 * @param length the length of the string in 4-byte code units
6848 * (char32_t)
6849 * @param utf8_buffer the pointer to buffer that can hold conversion result
6850 * @return a result pair struct (of type simdutf::result containing the two
6851 * fields error and count) with an error code and either position of the error
6852 * (in the input in code units) if any, or the number of char written if
6853 * successful.
6854 */
6855 simdutf_warn_unused virtual result
6856 convert_utf32_to_utf8_with_errors(const char32_t *input, size_t length,
6857 char *utf8_buffer) const noexcept = 0;
6858
6859 /**
6860 * Convert valid UTF-32 string into UTF-8 string.
6861 *
6862 * This function assumes that the input string is valid UTF-32.
6863 *
6864 * This function is not BOM-aware.
6865 *
6866 * @param input the UTF-32 string to convert
6867 * @param length the length of the string in 4-byte code units
6868 * (char32_t)
6869 * @param utf8_buffer the pointer to a buffer that can hold the conversion
6870 * result
6871 * @return number of written code units; 0 if conversion is not possible
6872 */
6873 simdutf_warn_unused virtual size_t
6874 convert_valid_utf32_to_utf8(const char32_t *input, size_t length,
6875 char *utf8_buffer) const noexcept = 0;
6876#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
6877
6878#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
6879 /**
6880 * Return the number of bytes that this UTF-16 string would require in Latin1
6881 * format.
6882 *
6883 *
6884 * @param length the length of the string in 2-byte code units
6885 * (char16_t)
6886 * @return the number of bytes required to encode the UTF-16 string as Latin1
6887 */
6888 simdutf_warn_unused virtual size_t
6889 utf16_length_from_latin1(size_t length) const noexcept {
6890 return length;
6891 }
6892#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
6893
6894#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
6895 /**
6896 * Convert possibly broken UTF-32 string into UTF-16LE string.
6897 *
6898 * During the conversion also validation of the input string is done.
6899 * This function is suitable to work with inputs from untrusted sources.
6900 *
6901 * This function is not BOM-aware.
6902 *
6903 * @param input the UTF-32 string to convert
6904 * @param length the length of the string in 4-byte code units
6905 * (char32_t)
6906 * @param utf16_buffer the pointer to buffer that can hold conversion result
6907 * @return number of written code units; 0 if input is not a valid UTF-32
6908 * string
6909 */
6910 simdutf_warn_unused virtual size_t
6911 convert_utf32_to_utf16le(const char32_t *input, size_t length,
6912 char16_t *utf16_buffer) const noexcept = 0;
6913
6914 /**
6915 * Convert possibly broken UTF-32 string into UTF-16BE string.
6916 *
6917 * During the conversion also validation of the input string is done.
6918 * This function is suitable to work with inputs from untrusted sources.
6919 *
6920 * This function is not BOM-aware.
6921 *
6922 * @param input the UTF-32 string to convert
6923 * @param length the length of the string in 4-byte code units
6924 * (char32_t)
6925 * @param utf16_buffer the pointer to buffer that can hold conversion result
6926 * @return number of written code units; 0 if input is not a valid UTF-32
6927 * string
6928 */
6929 simdutf_warn_unused virtual size_t
6930 convert_utf32_to_utf16be(const char32_t *input, size_t length,
6931 char16_t *utf16_buffer) const noexcept = 0;
6932
6933 /**
6934 * Convert possibly broken UTF-32 string into UTF-16LE string and stop on
6935 * error.
6936 *
6937 * During the conversion also validation of the input string is done.
6938 * This function is suitable to work with inputs from untrusted sources.
6939 *
6940 * This function is not BOM-aware.
6941 *
6942 * @param input the UTF-32 string to convert
6943 * @param length the length of the string in 4-byte code units
6944 * (char32_t)
6945 * @param utf16_buffer the pointer to buffer that can hold conversion result
6946 * @return a result pair struct (of type simdutf::result containing the two
6947 * fields error and count) with an error code and either position of the error
6948 * (in the input in code units) if any, or the number of char16_t written if
6949 * successful.
6950 */
6952 const char32_t *input, size_t length,
6953 char16_t *utf16_buffer) const noexcept = 0;
6954
6955 /**
6956 * Convert possibly broken UTF-32 string into UTF-16BE string and stop on
6957 * error.
6958 *
6959 * During the conversion also validation of the input string is done.
6960 * This function is suitable to work with inputs from untrusted sources.
6961 *
6962 * This function is not BOM-aware.
6963 *
6964 * @param input the UTF-32 string to convert
6965 * @param length the length of the string in 4-byte code units
6966 * (char32_t)
6967 * @param utf16_buffer the pointer to buffer that can hold conversion result
6968 * @return a result pair struct (of type simdutf::result containing the two
6969 * fields error and count) with an error code and either position of the error
6970 * (in the input in code units) if any, or the number of char16_t written if
6971 * successful.
6972 */
6974 const char32_t *input, size_t length,
6975 char16_t *utf16_buffer) const noexcept = 0;
6976
6977 /**
6978 * Convert valid UTF-32 string into UTF-16LE string.
6979 *
6980 * This function assumes that the input string is valid UTF-32.
6981 *
6982 * This function is not BOM-aware.
6983 *
6984 * @param input the UTF-32 string to convert
6985 * @param length the length of the string in 4-byte code units
6986 * (char32_t)
6987 * @param utf16_buffer the pointer to a buffer that can hold the conversion
6988 * result
6989 * @return number of written code units; 0 if conversion is not possible
6990 */
6991 simdutf_warn_unused virtual size_t
6992 convert_valid_utf32_to_utf16le(const char32_t *input, size_t length,
6993 char16_t *utf16_buffer) const noexcept = 0;
6994
6995 /**
6996 * Convert valid UTF-32 string into UTF-16BE string.
6997 *
6998 * This function assumes that the input string is valid UTF-32.
6999 *
7000 * This function is not BOM-aware.
7001 *
7002 * @param input the UTF-32 string to convert
7003 * @param length the length of the string in 4-byte code units
7004 * (char32_t)
7005 * @param utf16_buffer the pointer to a buffer that can hold the conversion
7006 * result
7007 * @return number of written code units; 0 if conversion is not possible
7008 */
7009 simdutf_warn_unused virtual size_t
7010 convert_valid_utf32_to_utf16be(const char32_t *input, size_t length,
7011 char16_t *utf16_buffer) const noexcept = 0;
7012#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
7013
7014#if SIMDUTF_FEATURE_UTF16
7015 /**
7016 * Change the endianness of the input. Can be used to go from UTF-16LE to
7017 * UTF-16BE or from UTF-16BE to UTF-16LE.
7018 *
7019 * This function does not validate the input.
7020 *
7021 * This function is not BOM-aware.
7022 *
7023 * @param input the UTF-16 string to process
7024 * @param length the length of the string in 2-byte code units
7025 * (char16_t)
7026 * @param output the pointer to a buffer that can hold the conversion
7027 * result
7028 */
7029 virtual void change_endianness_utf16(const char16_t *input, size_t length,
7030 char16_t *output) const noexcept = 0;
7031#endif // SIMDUTF_FEATURE_UTF16
7032
7033#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
7034 /**
7035 * Return the number of bytes that this Latin1 string would require in UTF-8
7036 * format.
7037 *
7038 * @param input the Latin1 string to convert
7039 * @param length the length of the string bytes
7040 * @return the number of bytes required to encode the Latin1 string as UTF-8
7041 */
7042 simdutf_warn_unused virtual size_t
7043 utf8_length_from_latin1(const char *input, size_t length) const noexcept = 0;
7044#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
7045
7046#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
7047 /**
7048 * Compute the number of bytes that this UTF-32 string would require in UTF-8
7049 * format.
7050 *
7051 * This function does not validate the input. It is acceptable to pass invalid
7052 * UTF-32 strings but in such cases the result is implementation defined.
7053 *
7054 * @param input the UTF-32 string to convert
7055 * @param length the length of the string in 4-byte code units
7056 * (char32_t)
7057 * @return the number of bytes required to encode the UTF-32 string as UTF-8
7058 */
7059 simdutf_warn_unused virtual size_t
7060 utf8_length_from_utf32(const char32_t *input,
7061 size_t length) const noexcept = 0;
7062#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
7063
7064#if SIMDUTF_FEATURE_UTF32 && SIMDUTF_FEATURE_LATIN1
7065 /**
7066 * Compute the number of bytes that this UTF-32 string would require in Latin1
7067 * format.
7068 *
7069 * This function does not validate the input. It is acceptable to pass invalid
7070 * UTF-32 strings but in such cases the result is implementation defined.
7071 *
7072 * @param length the length of the string in 4-byte code units
7073 * (char32_t)
7074 * @return the number of bytes required to encode the UTF-32 string as Latin1
7075 */
7076 simdutf_warn_unused virtual size_t
7077 latin1_length_from_utf32(size_t length) const noexcept {
7078 return length;
7079 }
7080#endif // SIMDUTF_FEATURE_UTF32 && SIMDUTF_FEATURE_LATIN1
7081
7082#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
7083 /**
7084 * Compute the number of bytes that this UTF-8 string would require in Latin1
7085 * format.
7086 *
7087 * This function does not validate the input. It is acceptable to pass invalid
7088 * UTF-8 strings but in such cases the result is implementation defined.
7089 *
7090 * @param input the UTF-8 string to convert
7091 * @param length the length of the string in byte
7092 * @return the number of bytes required to encode the UTF-8 string as Latin1
7093 */
7094 simdutf_warn_unused virtual size_t
7095 latin1_length_from_utf8(const char *input, size_t length) const noexcept = 0;
7096#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
7097
7098#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
7099 /**
7100 * Compute the number of bytes that this UTF-16LE/BE string would require in
7101 * Latin1 format.
7102 *
7103 * This function does not validate the input. It is acceptable to pass invalid
7104 * UTF-16 strings but in such cases the result is implementation defined.
7105 *
7106 * This function is not BOM-aware.
7107 *
7108 * @param length the length of the string in 2-byte code units
7109 * (char16_t)
7110 * @return the number of bytes required to encode the UTF-16LE string as
7111 * Latin1
7112 */
7113 simdutf_warn_unused virtual size_t
7114 latin1_length_from_utf16(size_t length) const noexcept {
7115 return length;
7116 }
7117#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
7118
7119#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
7120 /**
7121 * Compute the number of two-byte code units that this UTF-32 string would
7122 * require in UTF-16 format.
7123 *
7124 * This function does not validate the input. It is acceptable to pass invalid
7125 * UTF-32 strings but in such cases the result is implementation defined.
7126 *
7127 * @param input the UTF-32 string to convert
7128 * @param length the length of the string in 4-byte code units
7129 * (char32_t)
7130 * @return the number of bytes required to encode the UTF-32 string as UTF-16
7131 */
7132 simdutf_warn_unused virtual size_t
7133 utf16_length_from_utf32(const char32_t *input,
7134 size_t length) const noexcept = 0;
7135#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
7136
7137#if SIMDUTF_FEATURE_UTF32 && SIMDUTF_FEATURE_LATIN1
7138 /**
7139 * Return the number of bytes that this UTF-32 string would require in Latin1
7140 * format.
7141 *
7142 * @param length the length of the string in 4-byte code units
7143 * (char32_t)
7144 * @return the number of bytes required to encode the UTF-32 string as Latin1
7145 */
7146 simdutf_warn_unused virtual size_t
7147 utf32_length_from_latin1(size_t length) const noexcept {
7148 return length;
7149 }
7150#endif // SIMDUTF_FEATURE_UTF32 && SIMDUTF_FEATURE_LATIN1
7151
7152#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
7153 /**
7154 * Compute the number of bytes that this UTF-16LE string would require in
7155 * UTF-32 format.
7156 *
7157 * This function is equivalent to count_utf16le.
7158 *
7159 * This function does not validate the input. It is acceptable to pass invalid
7160 * UTF-16 strings but in such cases the result is implementation defined.
7161 *
7162 * This function is not BOM-aware.
7163 *
7164 * @param input the UTF-16LE string to convert
7165 * @param length the length of the string in 2-byte code units
7166 * (char16_t)
7167 * @return the number of bytes required to encode the UTF-16LE string as
7168 * UTF-32
7169 */
7170 simdutf_warn_unused virtual size_t
7171 utf32_length_from_utf16le(const char16_t *input,
7172 size_t length) const noexcept = 0;
7173
7174 /**
7175 * Compute the number of bytes that this UTF-16BE string would require in
7176 * UTF-32 format.
7177 *
7178 * This function is equivalent to count_utf16be.
7179 *
7180 * This function does not validate the input. It is acceptable to pass invalid
7181 * UTF-16 strings but in such cases the result is implementation defined.
7182 *
7183 * This function is not BOM-aware.
7184 *
7185 * @param input the UTF-16BE string to convert
7186 * @param length the length of the string in 2-byte code units
7187 * (char16_t)
7188 * @return the number of bytes required to encode the UTF-16BE string as
7189 * UTF-32
7190 */
7191 simdutf_warn_unused virtual size_t
7192 utf32_length_from_utf16be(const char16_t *input,
7193 size_t length) const noexcept = 0;
7194#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
7195
7196#if SIMDUTF_FEATURE_UTF16
7197 /**
7198 * Count the number of code points (characters) in the string assuming that
7199 * it is valid.
7200 *
7201 * This function assumes that the input string is valid UTF-16LE.
7202 * It is acceptable to pass invalid UTF-16 strings but in such cases
7203 * the result is implementation defined.
7204 *
7205 * This function is not BOM-aware.
7206 *
7207 * @param input the UTF-16LE string to process
7208 * @param length the length of the string in 2-byte code units
7209 * (char16_t)
7210 * @return number of code points
7211 */
7212 simdutf_warn_unused virtual size_t
7213 count_utf16le(const char16_t *input, size_t length) const noexcept = 0;
7214
7215 /**
7216 * Count the number of code points (characters) in the string assuming that
7217 * it is valid.
7218 *
7219 * This function assumes that the input string is valid UTF-16BE.
7220 * It is acceptable to pass invalid UTF-16 strings but in such cases
7221 * the result is implementation defined.
7222 *
7223 * This function is not BOM-aware.
7224 *
7225 * @param input the UTF-16BE string to process
7226 * @param length the length of the string in 2-byte code units
7227 * (char16_t)
7228 * @return number of code points
7229 */
7230 simdutf_warn_unused virtual size_t
7231 count_utf16be(const char16_t *input, size_t length) const noexcept = 0;
7232#endif // SIMDUTF_FEATURE_UTF16
7233
7234#if SIMDUTF_FEATURE_UTF8
7235 /**
7236 * Count the number of code points (characters) in the string assuming that
7237 * it is valid.
7238 *
7239 * This function assumes that the input string is valid UTF-8.
7240 * It is acceptable to pass invalid UTF-8 strings but in such cases
7241 * the result is implementation defined.
7242 *
7243 * @param input the UTF-8 string to process
7244 * @param length the length of the string in bytes
7245 * @return number of code points
7246 */
7247 simdutf_warn_unused virtual size_t
7248 count_utf8(const char *input, size_t length) const noexcept = 0;
7249#endif // SIMDUTF_FEATURE_UTF8
7250
7251#if SIMDUTF_FEATURE_BASE64
7252 /**
7253 * Provide the maximal binary length in bytes given the base64 input.
7254 * As long as the input does not contain ignorable characters (e.g., ASCII
7255 * spaces or linefeed characters), the result is exact. In particular, the
7256 * function checks for padding characters.
7257 *
7258 * The function is fast (constant time). It checks up to two characters at
7259 * the end of the string. The input is not otherwise validated or read..
7260 *
7261 * @param input the base64 input to process
7262 * @param length the length of the base64 input in bytes
7263 * @return maximal number of binary bytes
7264 */
7265 simdutf_warn_unused size_t maximal_binary_length_from_base64(
7266 const char *input, size_t length) const noexcept;
7267
7268 /**
7269 * Provide the maximal binary length in bytes given the base64 input.
7270 * As long as the input does not contain ignorable characters (e.g., ASCII
7271 * spaces or linefeed characters), the result is exact. In particular, the
7272 * function checks for padding characters.
7273 *
7274 * The function is fast (constant time). It checks up to two characters at
7275 * the end of the string. The input is not otherwise validated or read.
7276 *
7277 * @param input the base64 input to process, in ASCII stored as 16-bit
7278 * units
7279 * @param length the length of the base64 input in 16-bit units
7280 * @return maximal number of binary bytes
7281 */
7282 simdutf_warn_unused size_t maximal_binary_length_from_base64(
7283 const char16_t *input, size_t length) const noexcept;
7284
7285 /**
7286 * Compute the binary length from a base64 input with ASCII spaces.
7287 * This function is useful for well-formed base64 inputs that may contain
7288 * ASCII spaces (such as line breaks). For such inputs, the result is exact.
7289 *
7290 * The function counts non-whitespace characters (ASCII value > 0x20) and
7291 * subtracts padding characters ('=') found at the end.
7292 *
7293 * @param input the base64 input to process
7294 * @param length the length of the base64 input in bytes
7295 * @return number of binary bytes
7296 */
7297 simdutf_warn_unused virtual size_t
7298 binary_length_from_base64(const char *input, size_t length) const noexcept;
7299
7300 /**
7301 * Compute the binary length from a base64 input with ASCII spaces.
7302 * This function is useful for well-formed base64 inputs that may contain
7303 * ASCII spaces (such as line breaks). For such inputs, the result is exact.
7304 *
7305 * The function counts non-whitespace characters (ASCII value > 0x20) and
7306 * subtracts padding characters ('=') found at the end.
7307 *
7308 * @param input the base64 input to process, in ASCII stored as 16-bit
7309 * units
7310 * @param length the length of the base64 input in 16-bit units
7311 * @return number of binary bytes
7312 */
7313 simdutf_warn_unused virtual size_t
7314 binary_length_from_base64(const char16_t *input,
7315 size_t length) const noexcept;
7316
7317 /**
7318 * Convert a base64 input to a binary output.
7319 *
7320 * This function follows the WHATWG forgiving-base64 format, which means that
7321 * it will ignore any ASCII spaces in the input. You may provide a padded
7322 * input (with one or two equal signs at the end) or an unpadded input
7323 * (without any equal signs at the end).
7324 *
7325 * See https://infra.spec.whatwg.org/#forgiving-base64-decode
7326 *
7327 * This function will fail in case of invalid input. When last_chunk_options =
7328 * loose, there are two possible reasons for failure: the input contains a
7329 * number of base64 characters that when divided by 4, leaves a single
7330 * remainder character (BASE64_INPUT_REMAINDER), or the input contains a
7331 * character that is not a valid base64 character (INVALID_BASE64_CHARACTER).
7332 *
7333 * You should call this function with a buffer that is at least
7334 * maximal_binary_length_from_base64(input, length) bytes long. If you fail to
7335 * provide that much space, the function may cause a buffer overflow.
7336 *
7337 * @param input the base64 string to process
7338 * @param length the length of the string in bytes
7339 * @param output the pointer to a buffer that can hold the conversion
7340 * result (should be at least maximal_binary_length_from_base64(input, length)
7341 * bytes long).
7342 * @param options the base64 options to use, can be base64_default or
7343 * base64_url, is base64_default by default.
7344 * @param last_chunk_options the handling of the last chunk (default: loose)
7345 * @return a result pair struct (of type simdutf::result containing the two
7346 * fields error and count) with an error code and either position of the error
7347 * (in the input in bytes) if any, or the number of bytes written if
7348 * successful.
7349 */
7350 simdutf_warn_unused virtual result
7351 base64_to_binary(const char *input, size_t length, char *output,
7352 base64_options options = base64_default,
7353 last_chunk_handling_options last_chunk_options =
7354 last_chunk_handling_options::loose) const noexcept = 0;
7355
7356 /**
7357 * Convert a base64 input to a binary output while returning more details
7358 * than base64_to_binary.
7359 *
7360 * This function follows the WHATWG forgiving-base64 format, which means that
7361 * it will ignore any ASCII spaces in the input. You may provide a padded
7362 * input (with one or two equal signs at the end) or an unpadded input
7363 * (without any equal signs at the end).
7364 *
7365 * See https://infra.spec.whatwg.org/#forgiving-base64-decode
7366 *
7367 * This function will fail in case of invalid input. When last_chunk_options =
7368 * loose, there are two possible reasons for failure: the input contains a
7369 * number of base64 characters that when divided by 4, leaves a single
7370 * remainder character (BASE64_INPUT_REMAINDER), or the input contains a
7371 * character that is not a valid base64 character (INVALID_BASE64_CHARACTER).
7372 *
7373 * You should call this function with a buffer that is at least
7374 * maximal_binary_length_from_base64(input, length) bytes long. If you fail to
7375 * provide that much space, the function may cause a buffer overflow.
7376 *
7377 * @param input the base64 string to process
7378 * @param length the length of the string in bytes
7379 * @param output the pointer to a buffer that can hold the conversion
7380 * result (should be at least maximal_binary_length_from_base64(input, length)
7381 * bytes long).
7382 * @param options the base64 options to use, can be base64_default or
7383 * base64_url, is base64_default by default.
7384 * @param last_chunk_options the handling of the last chunk (default: loose)
7385 * @return a full_result pair struct (of type simdutf::result containing the
7386 * three fields error, input_count and output_count).
7387 */
7388 simdutf_warn_unused virtual full_result base64_to_binary_details(
7389 const char *input, size_t length, char *output,
7390 base64_options options = base64_default,
7391 last_chunk_handling_options last_chunk_options =
7392 last_chunk_handling_options::loose) const noexcept = 0;
7393
7394 /**
7395 * Convert a base64 input to a binary output.
7396 *
7397 * This function follows the WHATWG forgiving-base64 format, which means that
7398 * it will ignore any ASCII spaces in the input. You may provide a padded
7399 * input (with one or two equal signs at the end) or an unpadded input
7400 * (without any equal signs at the end).
7401 *
7402 * See https://infra.spec.whatwg.org/#forgiving-base64-decode
7403 *
7404 * This function will fail in case of invalid input. When last_chunk_options =
7405 * loose, there are two possible reasons for failure: the input contains a
7406 * number of base64 characters that when divided by 4, leaves a single
7407 * remainder character (BASE64_INPUT_REMAINDER), or the input contains a
7408 * character that is not a valid base64 character (INVALID_BASE64_CHARACTER).
7409 *
7410 * You should call this function with a buffer that is at least
7411 * maximal_binary_length_from_base64(input, length) bytes long. If you
7412 * fail to provide that much space, the function may cause a buffer overflow.
7413 *
7414 * @param input the base64 string to process, in ASCII stored as
7415 * 16-bit units
7416 * @param length the length of the string in 16-bit units
7417 * @param output the pointer to a buffer that can hold the conversion
7418 * result (should be at least maximal_binary_length_from_base64(input, length)
7419 * bytes long).
7420 * @param options the base64 options to use, can be base64_default or
7421 * base64_url, is base64_default by default.
7422 * @param last_chunk_options the handling of the last chunk (default: loose)
7423 * @return a result pair struct (of type simdutf::result containing the two
7424 * fields error and count) with an error code and position of the
7425 * INVALID_BASE64_CHARACTER error (in the input in units) if any, or the
7426 * number of bytes written if successful.
7427 */
7428 simdutf_warn_unused virtual result
7429 base64_to_binary(const char16_t *input, size_t length, char *output,
7430 base64_options options = base64_default,
7431 last_chunk_handling_options last_chunk_options =
7432 last_chunk_handling_options::loose) const noexcept = 0;
7433
7434 /**
7435 * Convert a base64 input to a binary output while returning more details
7436 * than base64_to_binary.
7437 *
7438 * This function follows the WHATWG forgiving-base64 format, which means that
7439 * it will ignore any ASCII spaces in the input. You may provide a padded
7440 * input (with one or two equal signs at the end) or an unpadded input
7441 * (without any equal signs at the end).
7442 *
7443 * See https://infra.spec.whatwg.org/#forgiving-base64-decode
7444 *
7445 * This function will fail in case of invalid input. When last_chunk_options =
7446 * loose, there are two possible reasons for failure: the input contains a
7447 * number of base64 characters that when divided by 4, leaves a single
7448 * remainder character (BASE64_INPUT_REMAINDER), or the input contains a
7449 * character that is not a valid base64 character (INVALID_BASE64_CHARACTER).
7450 *
7451 * You should call this function with a buffer that is at least
7452 * maximal_binary_length_from_base64(input, length) bytes long. If you fail to
7453 * provide that much space, the function may cause a buffer overflow.
7454 *
7455 * @param input the base64 string to process
7456 * @param length the length of the string in bytes
7457 * @param output the pointer to a buffer that can hold the conversion
7458 * result (should be at least maximal_binary_length_from_base64(input, length)
7459 * bytes long).
7460 * @param options the base64 options to use, can be base64_default or
7461 * base64_url, is base64_default by default.
7462 * @param last_chunk_options the handling of the last chunk (default: loose)
7463 * @return a full_result pair struct (of type simdutf::result containing the
7464 * three fields error, input_count and output_count).
7465 */
7466 simdutf_warn_unused virtual full_result base64_to_binary_details(
7467 const char16_t *input, size_t length, char *output,
7468 base64_options options = base64_default,
7469 last_chunk_handling_options last_chunk_options =
7470 last_chunk_handling_options::loose) const noexcept = 0;
7471
7472 /**
7473 * Provide the base64 length in bytes given the length of a binary input.
7474 *
7475 * @param length the length of the input in bytes
7476 * @param options the base64 options to use, can be base64_default or
7477 * base64_url, is base64_default by default.
7478 * @return number of base64 bytes
7479 */
7480 simdutf_warn_unused size_t base64_length_from_binary(
7481 size_t length, base64_options options = base64_default) const noexcept;
7482
7483 /**
7484 * Convert a binary input to a base64 output.
7485 *
7486 * The default option (simdutf::base64_default) uses the characters `+` and
7487 * `/` as part of its alphabet. Further, it adds padding (`=`) at the end of
7488 * the output to ensure that the output length is a multiple of four.
7489 *
7490 * The URL option (simdutf::base64_url) uses the characters `-` and `_` as
7491 * part of its alphabet. No padding is added at the end of the output.
7492 *
7493 * This function always succeeds.
7494 *
7495 * @param input the binary to process
7496 * @param length the length of the input in bytes
7497 * @param output the pointer to a buffer that can hold the conversion
7498 * result (should be at least base64_length_from_binary(length) bytes long)
7499 * @param options the base64 options to use, can be base64_default or
7500 * base64_url, is base64_default by default.
7501 * @return number of written bytes, will be equal to
7502 * base64_length_from_binary(length, options)
7503 */
7504 virtual size_t
7505 binary_to_base64(const char *input, size_t length, char *output,
7506 base64_options options = base64_default) const noexcept = 0;
7507
7508 /**
7509 * Convert a binary input to a base64 output with lines of given length.
7510 * Lines are separated by a single linefeed character.
7511 *
7512 * The default option (simdutf::base64_default) uses the characters `+` and
7513 * `/` as part of its alphabet. Further, it adds padding (`=`) at the end of
7514 * the output to ensure that the output length is a multiple of four.
7515 *
7516 * The URL option (simdutf::base64_url) uses the characters `-` and `_` as
7517 * part of its alphabet. No padding is added at the end of the output.
7518 *
7519 * This function always succeeds.
7520 *
7521 * @param input the binary to process
7522 * @param length the length of the input in bytes
7523 * @param output the pointer to a buffer that can hold the conversion
7524 * result (should be at least base64_length_from_binary_with_lines(length,
7525 * options, line_length) bytes long)
7526 * @param line_length the length of each line, values smaller than 4 are
7527 * interpreted as 4
7528 * @param options the base64 options to use, can be base64_default or
7529 * base64_url, is base64_default by default.
7530 * @return number of written bytes, will be equal to
7531 * base64_length_from_binary_with_lines(length, options, line_length)
7532 */
7534 const char *input, size_t length, char *output,
7535 size_t line_length = simdutf::default_line_length,
7536 base64_options options = base64_default) const noexcept = 0;
7537
7538 /**
7539 * Find the first occurrence of a character in a string. If the character is
7540 * not found, return a pointer to the end of the string.
7541 * @param start the start of the string
7542 * @param end the end of the string
7543 * @param character the character to find
7544 * @return a pointer to the first occurrence of the character in the string,
7545 * or a pointer to the end of the string if the character is not found.
7546 *
7547 */
7548 virtual const char *find(const char *start, const char *end,
7549 char character) const noexcept = 0;
7550 virtual const char16_t *find(const char16_t *start, const char16_t *end,
7551 char16_t character) const noexcept = 0;
7552#endif // SIMDUTF_FEATURE_BASE64
7553
7554#ifdef SIMDUTF_INTERNAL_TESTS
7555 // This method is exported only in developer mode, its purpose
7556 // is to expose some internal test procedures from the given
7557 // implementation and then use them through our standard test
7558 // framework.
7559 //
7560 // Regular users should not use it, the tests of the public
7561 // API are enough.
7562
7563 struct TestProcedure {
7564 // display name
7565 std::string_view name;
7566
7567 // procedure should return whether given test pass or not
7568 void (*procedure)(const implementation &);
7569 };
7570
7571 virtual std::vector<TestProcedure> internal_tests() const;
7572#endif
7573
7574protected:
7575 /** @private Construct an implementation with the given name and description.
7576 * For subclasses.
7577 * @param name the name of this implementation
7578 * @param description a description of this implementation
7579 * @param required_instruction_sets the instruction sets this implementation
7580 * requires
7581 */
7582 simdutf_really_inline implementation(const char *name,
7583 const char *description,
7584 uint32_t required_instruction_sets)
7585 : _name(name), _description(description),
7586 _required_instruction_sets(required_instruction_sets) {}
7587
7588protected:
7589 ~implementation() = default;
7590
7591private:
7592 /**
7593 * The name of this implementation.
7594 */
7595 const char *_name;
7596
7597 /**
7598 * The description of this implementation.
7599 */
7600 const char *_description;
7601
7602 /**
7603 * Instruction sets required for this implementation.
7604 */
7605 const uint32_t _required_instruction_sets;
7606};
7607
7608/** @private */
7609namespace internal {
7610
7611/**
7612 * The list of available implementations compiled into simdutf.
7613 */
7614class available_implementation_list {
7615public:
7616 /** Get the list of available implementations compiled into simdutf */
7617 simdutf_really_inline available_implementation_list() {}
7618 /** Number of implementations */
7619 size_t size() const noexcept;
7620 /** STL const begin() iterator */
7621 const implementation *const *begin() const noexcept;
7622 /** STL const end() iterator */
7623 const implementation *const *end() const noexcept;
7624
7625 /**
7626 * Get the implementation with the given name.
7627 *
7628 * Case sensitive.
7629 *
7630 * const implementation *impl =
7631 * simdutf::available_implementations["westmere"]; if (!impl) { exit(1); } if
7632 * (!imp->supported_by_runtime_system()) { exit(1); }
7633 * simdutf::active_implementation = impl;
7634 *
7635 * @param name the implementation to find, e.g. "westmere", "haswell", "arm64"
7636 * @return the implementation, or nullptr if the parse failed.
7637 */
7638 const implementation *operator[](std::string_view name) const noexcept {
7639 for (const implementation *impl : *this) {
7640 if (impl->name() == name) {
7641 return impl;
7642 }
7643 }
7644 return nullptr;
7645 }
7646
7647 /**
7648 * Detect the most advanced implementation supported by the current host.
7649 *
7650 * This is used to initialize the implementation on startup.
7651 *
7652 * const implementation *impl =
7653 * simdutf::available_implementation::detect_best_supported();
7654 * simdutf::active_implementation = impl;
7655 *
7656 * @return the most advanced supported implementation for the current host, or
7657 * an implementation that returns UNSUPPORTED_ARCHITECTURE if there is no
7658 * supported implementation. Will never return nullptr.
7659 */
7660 const implementation *detect_best_supported() const noexcept;
7661};
7662
7663template <typename T> class atomic_ptr {
7664public:
7665 atomic_ptr(T *_ptr) : ptr{_ptr} {}
7666
7667#if defined(SIMDUTF_NO_THREADS)
7668 operator const T *() const { return ptr; }
7669 const T &operator*() const { return *ptr; }
7670 const T *operator->() const { return ptr; }
7671
7672 operator T *() { return ptr; }
7673 T &operator*() { return *ptr; }
7674 T *operator->() { return ptr; }
7675 atomic_ptr &operator=(T *_ptr) {
7676 ptr = _ptr;
7677 return *this;
7678 }
7679
7680#else
7681 operator const T *() const { return ptr.load(); }
7682 const T &operator*() const { return *ptr; }
7683 const T *operator->() const { return ptr.load(); }
7684
7685 operator T *() { return ptr.load(); }
7686 T &operator*() { return *ptr; }
7687 T *operator->() { return ptr.load(); }
7688 atomic_ptr &operator=(T *_ptr) {
7689 ptr = _ptr;
7690 return *this;
7691 }
7692
7693#endif
7694
7695private:
7696#if defined(SIMDUTF_NO_THREADS)
7697 T *ptr;
7698#else
7699 std::atomic<T *> ptr;
7700#endif
7701};
7702
7703class detect_best_supported_implementation_on_first_use;
7704
7705} // namespace internal
7706
7707/**
7708 * The list of available implementations compiled into simdutf.
7709 */
7710extern SIMDUTF_DLLIMPORTEXPORT const internal::available_implementation_list &
7712
7713/**
7714 * The active implementation.
7715 *
7716 * Automatically initialized on first use to the most advanced implementation
7717 * supported by this hardware.
7718 */
7719extern SIMDUTF_DLLIMPORTEXPORT internal::atomic_ptr<const implementation> &
7721
7722} // namespace simdutf
7723
7724#if SIMDUTF_FEATURE_BASE64
7725 // this header is not part of the public api
7726 #include <simdutf/base64_implementation.h>
7727
7728namespace simdutf {
7729 #if SIMDUTF_SPAN
7730/**
7731 * @brief span overload
7732 * @return a tuple of result and outlen
7733 */
7734simdutf_really_inline
7735 simdutf_constexpr23 simdutf_warn_unused std::tuple<result, std::size_t>
7737 const detail::input_span_of_byte_like auto &input,
7738 detail::output_span_of_byte_like auto &&binary_output,
7739 base64_options options = base64_default,
7740 last_chunk_handling_options last_chunk_options = loose,
7741 bool decode_up_to_bad_char = false) noexcept {
7742 size_t outlen = binary_output.size();
7743 #if SIMDUTF_CPLUSPLUS23
7744 if consteval {
7745 auto r = detail::with_char_input(input, [&](auto in) {
7746 return detail::with_char_output(
7747 binary_output,
7748 [&](char *out) {
7749 return base64_to_binary_safe_impl(in, input.size(), out, outlen,
7750 options, last_chunk_options,
7751 decode_up_to_bad_char);
7752 },
7753 [&](const auto &) { return outlen; });
7754 });
7755 return {r, outlen};
7756 } else
7757 #endif
7758 {
7759 auto r = base64_to_binary_safe_impl<char>(
7760 reinterpret_cast<const char *>(input.data()), input.size(),
7761 reinterpret_cast<char *>(binary_output.data()), outlen, options,
7762 last_chunk_options, decode_up_to_bad_char);
7763 return {r, outlen};
7764 }
7765}
7766
7767 #if SIMDUTF_SPAN
7768/**
7769 * @brief span overload
7770 * @return a tuple of result and outlen
7771 */
7772simdutf_really_inline
7773 simdutf_warn_unused simdutf_constexpr23 std::tuple<result, std::size_t>
7775 std::span<const char16_t> input,
7776 detail::output_span_of_byte_like auto &&binary_output,
7777 base64_options options = base64_default,
7778 last_chunk_handling_options last_chunk_options = loose,
7779 bool decode_up_to_bad_char = false) noexcept {
7780 size_t outlen = binary_output.size();
7781 #if SIMDUTF_CPLUSPLUS23
7782 if consteval {
7783 auto r = detail::with_char_output(
7784 binary_output,
7785 [&](auto out) {
7786 return base64_to_binary_safe_impl(input.data(), input.size(), out,
7787 outlen, options, last_chunk_options,
7788 decode_up_to_bad_char);
7789 },
7790 [&](const auto &) { return outlen; });
7791 return {r, outlen};
7792 } else
7793 #endif
7794 {
7795 auto r = base64_to_binary_safe(
7796 input.data(), input.size(),
7797 reinterpret_cast<char *>(binary_output.data()), outlen, options,
7798 last_chunk_options, decode_up_to_bad_char);
7799 return {r, outlen};
7800 }
7801}
7802 #endif // SIMDUTF_SPAN
7803
7804 #endif // SIMDUTF_SPAN
7805} // namespace simdutf
7806
7807#endif // SIMDUTF_FEATURE_BASE64
7808
7809#if SIMDUTF_CPLUSPLUS23 && SIMDUTF_FEATURE_BASE64
7810
7811namespace simdutf {
7812namespace literals {
7813
7814namespace detail {
7815
7816// the detail namespace is not part of the public api
7817
7818template <std::size_t N> struct base64_literal_helper {
7819 std::array<char, N - 1> storage{};
7820 static constexpr std::size_t size() noexcept { return N - 1; }
7821 consteval base64_literal_helper(const char (&str)[N]) {
7822 for (std::size_t i = 0; i < size(); i++) {
7823 storage[i] = str[i];
7824 }
7825 }
7826};
7827
7828template <std::size_t InputLen> struct base64_decode_result {
7829 static constexpr std::size_t max_out = (InputLen + 3) / 4 * 3;
7830 std::array<char, max_out> buffer{};
7831 std::size_t output_count{};
7832};
7833
7834template <std::size_t InputLen>
7835consteval auto base64_decode_literal(const char *str) {
7836 base64_decode_result<InputLen> result{};
7837 auto r = scalar::base64::base64_to_binary_details_impl(
7838 str, InputLen, result.buffer.data(), base64_default, loose);
7839 if (r.error != error_code::SUCCESS) {
7840 #if __cpp_lib_unreachable >= 202202L
7841 std::unreachable(); // invalid base64 input in _base64 literal
7842 #else
7843 // workaround for older stdlib
7844 throw "invalid base64 input in _base64 literal";
7845 #endif
7846 }
7847 result.output_count = r.output_count;
7848 return result;
7849}
7850
7851template <base64_literal_helper a> consteval auto base64_make_array() {
7852 constexpr auto decoded = base64_decode_literal<a.size()>(a.storage.data());
7853 std::array<char, decoded.output_count> ret{};
7854 for (std::size_t i = 0; i < decoded.output_count; i++) {
7855 ret[i] = decoded.buffer[i];
7856 }
7857 return ret;
7858}
7859
7860} // namespace detail
7861
7862/**
7863 * User-defined literal for compile-time base64 decoding.
7864 *
7865 * Usage:
7866 * using namespace simdutf::literals;
7867 * constexpr auto decoded = "SGVsbG8gV29ybGQh"_base64;
7868 * // decoded is a std::array<char, 12> containing "Hello World!"
7869 *
7870 * The input must be valid base64. Whitepace is allowed and ignored.
7871 * A compilation error occurs if the input is invalid.
7872 */
7873template <detail::base64_literal_helper a> consteval auto operator""_base64() {
7874 return detail::base64_make_array<a>();
7875}
7876
7877} // namespace literals
7878} // namespace simdutf
7879
7880#endif // SIMDUTF_CPLUSPLUS23 && SIMDUTF_FEATURE_BASE64
7881
7882#endif // SIMDUTF_IMPLEMENTATION_H
An implementation of simdutf for a particular CPU architecture.
virtual simdutf_warn_unused size_t convert_valid_utf32_to_latin1(const char32_t *input, size_t length, char *latin1_buffer) const noexcept=0
Convert valid UTF-32 string into Latin1 string.
virtual simdutf_warn_unused size_t binary_length_from_base64(const char *input, size_t length) const noexcept
Compute the binary length from a base64 input with ASCII spaces.
virtual const char * find(const char *start, const char *end, char character) const noexcept=0
Find the first occurrence of a character in a string.
virtual simdutf_warn_unused size_t convert_valid_utf8_to_utf16le(const char *input, size_t length, char16_t *utf16_buffer) const noexcept=0
Convert valid UTF-8 string into UTF-16LE string.
virtual simdutf_warn_unused size_t latin1_length_from_utf16(size_t length) const noexcept
Compute the number of bytes that this UTF-16LE/BE string would require in Latin1 format.
virtual simdutf_warn_unused size_t convert_utf16le_to_utf8_with_replacement(const char16_t *input, size_t length, char *utf8_buffer) const noexcept=0
Convert possibly broken UTF-16LE string into UTF-8 string, replacing unpaired surrogates with the Uni...
virtual simdutf_warn_unused size_t binary_length_from_base64(const char16_t *input, size_t length) const noexcept
Compute the binary length from a base64 input with ASCII spaces.
virtual simdutf_warn_unused size_t utf32_length_from_utf16be(const char16_t *input, size_t length) const noexcept=0
Compute the number of bytes that this UTF-16BE string would require in UTF-32 format.
virtual simdutf_warn_unused size_t convert_utf8_to_utf16be(const char *input, size_t length, char16_t *utf16_output) const noexcept=0
Convert possibly broken UTF-8 string into UTF-16BE string.
virtual simdutf_warn_unused size_t convert_utf16le_to_utf32(const char16_t *input, size_t length, char32_t *utf32_buffer) const noexcept=0
Convert possibly broken UTF-16LE string into UTF-32 string.
virtual simdutf_warn_unused size_t convert_valid_utf16be_to_utf32(const char16_t *input, size_t length, char32_t *utf32_buffer) const noexcept=0
Convert valid UTF-16LE string into UTF-32BE string.
virtual std::string_view name() const noexcept
The name of this implementation.
virtual simdutf_warn_unused size_t convert_valid_utf16be_to_utf8(const char16_t *input, size_t length, char *utf8_buffer) const noexcept=0
Convert valid UTF-16BE string into UTF-8 string.
virtual simdutf_warn_unused size_t convert_latin1_to_utf16le(const char *input, size_t length, char16_t *utf16_output) const noexcept=0
Convert possibly Latin1 string into UTF-16LE string.
virtual simdutf_warn_unused bool validate_utf16be(const char16_t *buf, size_t len) const noexcept=0
Validate the UTF-16BE string.
virtual simdutf_warn_unused result convert_utf16be_to_latin1_with_errors(const char16_t *input, size_t length, char *latin1_buffer) const noexcept=0
Convert possibly broken UTF-16BE string into Latin1 string.
virtual simdutf_warn_unused full_result base64_to_binary_details(const char *input, size_t length, char *output, base64_options options=base64_default, last_chunk_handling_options last_chunk_options=last_chunk_handling_options::loose) const noexcept=0
Convert a base64 input to a binary output while returning more details than base64_to_binary.
virtual simdutf_warn_unused size_t convert_valid_utf16le_to_utf32(const char16_t *input, size_t length, char32_t *utf32_buffer) const noexcept=0
Convert valid UTF-16LE string into UTF-32 string.
virtual simdutf_warn_unused size_t latin1_length_from_utf8(const char *input, size_t length) const noexcept=0
Compute the number of bytes that this UTF-8 string would require in Latin1 format.
virtual simdutf_warn_unused result convert_utf32_to_latin1_with_errors(const char32_t *input, size_t length, char *latin1_buffer) const noexcept=0
Convert possibly broken UTF-32 string into Latin1 string and stop on error.
virtual simdutf_warn_unused size_t utf8_length_from_utf32(const char32_t *input, size_t length) const noexcept=0
Compute the number of bytes that this UTF-32 string would require in UTF-8 format.
virtual simdutf_warn_unused size_t convert_latin1_to_utf16be(const char *input, size_t length, char16_t *utf16_output) const noexcept=0
Convert Latin1 string into UTF-16BE string.
virtual simdutf_warn_unused size_t latin1_length_from_utf32(size_t length) const noexcept
Compute the number of bytes that this UTF-32 string would require in Latin1 format.
virtual simdutf_warn_unused full_result base64_to_binary_details(const char16_t *input, size_t length, char *output, base64_options options=base64_default, last_chunk_handling_options last_chunk_options=last_chunk_handling_options::loose) const noexcept=0
Convert a base64 input to a binary output while returning more details than base64_to_binary.
virtual simdutf_warn_unused size_t convert_utf32_to_utf16le(const char32_t *input, size_t length, char16_t *utf16_buffer) const noexcept=0
Convert possibly broken UTF-32 string into UTF-16LE string.
virtual simdutf_warn_unused size_t utf16_length_from_utf32(const char32_t *input, size_t length) const noexcept=0
Compute the number of two-byte code units that this UTF-32 string would require in UTF-16 format.
virtual simdutf_warn_unused size_t count_utf8(const char *input, size_t length) const noexcept=0
Count the number of code points (characters) in the string assuming that it is valid.
virtual simdutf_warn_unused size_t convert_valid_utf32_to_utf16be(const char32_t *input, size_t length, char16_t *utf16_buffer) const noexcept=0
Convert valid UTF-32 string into UTF-16BE string.
virtual simdutf_warn_unused size_t utf32_length_from_utf8(const char *input, size_t length) const noexcept=0
Compute the number of 4-byte code units that this UTF-8 string would require in UTF-32 format.
virtual simdutf_warn_unused size_t convert_valid_utf16le_to_utf8(const char16_t *input, size_t length, char *utf8_buffer) const noexcept=0
Convert valid UTF-16LE string into UTF-8 string.
virtual void to_well_formed_utf16le(const char16_t *input, size_t len, char16_t *output) const noexcept=0
Copies the UTF-16LE string while replacing mismatched surrogates with the Unicode replacement charact...
virtual simdutf_warn_unused result convert_utf32_to_utf16be_with_errors(const char32_t *input, size_t length, char16_t *utf16_buffer) const noexcept=0
Convert possibly broken UTF-32 string into UTF-16BE string and stop on error.
virtual simdutf_warn_unused result validate_utf8_with_errors(const char *buf, size_t len) const noexcept=0
Validate the UTF-8 string and stop on errors.
virtual simdutf_warn_unused size_t utf8_length_from_utf16le(const char16_t *input, size_t length) const noexcept=0
Compute the number of bytes that this UTF-16LE string would require in UTF-8 format.
virtual size_t binary_to_base64_with_lines(const char *input, size_t length, char *output, size_t line_length=simdutf::default_line_length, base64_options options=base64_default) const noexcept=0
Convert a binary input to a base64 output with lines of given length.
virtual simdutf_warn_unused size_t convert_utf16be_to_utf8(const char16_t *input, size_t length, char *utf8_buffer) const noexcept=0
Convert possibly broken UTF-16BE string into UTF-8 string.
virtual simdutf_warn_unused size_t convert_utf8_to_utf16le(const char *input, size_t length, char16_t *utf16_output) const noexcept=0
Convert possibly broken UTF-8 string into UTF-16LE string.
virtual simdutf_warn_unused result convert_utf16le_to_latin1_with_errors(const char16_t *input, size_t length, char *latin1_buffer) const noexcept=0
Convert possibly broken UTF-16LE string into Latin1 string.
virtual simdutf_warn_unused result utf8_length_from_utf16le_with_replacement(const char16_t *input, size_t length) const noexcept=0
Compute the number of bytes that this UTF-16LE string would require in UTF-8 format even when the UTF...
virtual simdutf_warn_unused result validate_utf16le_with_errors(const char16_t *buf, size_t len) const noexcept=0
Validate the UTF-16LE string and stop on error.
virtual simdutf_warn_unused result convert_utf16be_to_utf8_with_errors(const char16_t *input, size_t length, char *utf8_buffer) const noexcept=0
Convert possibly broken UTF-16BE string into UTF-8 string and stop on error.
virtual size_t binary_to_base64(const char *input, size_t length, char *output, base64_options options=base64_default) const noexcept=0
Convert a binary input to a base64 output.
virtual simdutf_warn_unused result utf8_length_from_utf16be_with_replacement(const char16_t *input, size_t length) const noexcept=0
Compute the number of bytes that this UTF-16BE string would require in UTF-8 format even when the UTF...
virtual simdutf_warn_unused size_t convert_latin1_to_utf32(const char *input, size_t length, char32_t *utf32_buffer) const noexcept=0
Convert Latin1 string into UTF-32 string.
virtual simdutf_warn_unused result convert_utf8_to_utf32_with_errors(const char *input, size_t length, char32_t *utf32_output) const noexcept=0
Convert possibly broken UTF-8 string into UTF-32 string and stop on error.
virtual simdutf_warn_unused size_t convert_valid_utf32_to_utf8(const char32_t *input, size_t length, char *utf8_buffer) const noexcept=0
Convert valid UTF-32 string into UTF-8 string.
virtual simdutf_warn_unused size_t utf32_length_from_latin1(size_t length) const noexcept
Return the number of bytes that this UTF-32 string would require in Latin1 format.
virtual std::string_view description() const noexcept
The description of this implementation.
virtual simdutf_warn_unused bool validate_utf16le(const char16_t *buf, size_t len) const noexcept=0
Validate the UTF-16LE string.This function may be best when you expect the input to be almost always ...
virtual simdutf_warn_unused result convert_utf8_to_utf16le_with_errors(const char *input, size_t length, char16_t *utf16_output) const noexcept=0
Convert possibly broken UTF-8 string into UTF-16LE string and stop on error.
virtual simdutf_warn_unused size_t count_utf16le(const char16_t *input, size_t length) const noexcept=0
Count the number of code points (characters) in the string assuming that it is valid.
virtual simdutf_warn_unused size_t convert_utf16be_to_utf32(const char16_t *input, size_t length, char32_t *utf32_buffer) const noexcept=0
Convert possibly broken UTF-16BE string into UTF-32 string.
virtual simdutf_warn_unused size_t convert_valid_utf16le_to_latin1(const char16_t *input, size_t length, char *latin1_buffer) const noexcept=0
Convert valid UTF-16LE string into Latin1 string.
virtual simdutf_warn_unused size_t convert_utf32_to_latin1(const char32_t *input, size_t length, char *latin1_buffer) const noexcept=0
Convert possibly broken UTF-32 string into Latin1 string.
virtual simdutf_warn_unused size_t convert_valid_utf16be_to_latin1(const char16_t *input, size_t length, char *latin1_buffer) const noexcept=0
Convert valid UTF-16BE string into Latin1 string.
bool supported_by_runtime_system() const
The instruction sets this implementation is compiled against and the current CPU match.
virtual simdutf_warn_unused size_t convert_valid_utf8_to_utf32(const char *input, size_t length, char32_t *utf32_buffer) const noexcept=0
Convert valid UTF-8 string into UTF-32 string.
virtual simdutf_warn_unused size_t convert_utf16le_to_latin1(const char16_t *input, size_t length, char *latin1_buffer) const noexcept=0
Convert possibly broken UTF-16LE string into Latin1 string.
virtual simdutf_warn_unused result validate_utf16be_with_errors(const char16_t *buf, size_t len) const noexcept=0
Validate the UTF-16BE string and stop on error.
virtual simdutf_warn_unused result convert_utf16le_to_utf8_with_errors(const char16_t *input, size_t length, char *utf8_buffer) const noexcept=0
Convert possibly broken UTF-16LE string into UTF-8 string and stop on error.
virtual simdutf_warn_unused result convert_utf16be_to_utf32_with_errors(const char16_t *input, size_t length, char32_t *utf32_buffer) const noexcept=0
Convert possibly broken UTF-16BE string into UTF-32 string and stop on error.
virtual simdutf_warn_unused result base64_to_binary(const char *input, size_t length, char *output, base64_options options=base64_default, last_chunk_handling_options last_chunk_options=last_chunk_handling_options::loose) const noexcept=0
Convert a base64 input to a binary output.
virtual simdutf_warn_unused bool validate_utf16be_as_ascii(const char16_t *buf, size_t len) const noexcept=0
Validate the ASCII string as a UTF-16BE sequence.
virtual simdutf_warn_unused size_t convert_utf32_to_utf16be(const char32_t *input, size_t length, char16_t *utf16_buffer) const noexcept=0
Convert possibly broken UTF-32 string into UTF-16BE string.
virtual simdutf_warn_unused result validate_utf32_with_errors(const char32_t *buf, size_t len) const noexcept=0
Validate the UTF-32 string and stop on error.
virtual simdutf_warn_unused size_t utf32_length_from_utf16le(const char16_t *input, size_t length) const noexcept=0
Compute the number of bytes that this UTF-16LE string would require in UTF-32 format.
virtual void change_endianness_utf16(const char16_t *input, size_t length, char16_t *output) const noexcept=0
Change the endianness of the input.
virtual simdutf_warn_unused size_t convert_valid_utf8_to_utf16be(const char *input, size_t length, char16_t *utf16_buffer) const noexcept=0
Convert valid UTF-8 string into UTF-16BE string.
virtual simdutf_warn_unused size_t convert_valid_utf8_to_latin1(const char *input, size_t length, char *latin1_output) const noexcept=0
Convert valid UTF-8 string into latin1 string.
simdutf_warn_unused size_t maximal_binary_length_from_base64(const char *input, size_t length) const noexcept
Provide the maximal binary length in bytes given the base64 input.
virtual simdutf_warn_unused size_t convert_valid_utf32_to_utf16le(const char32_t *input, size_t length, char16_t *utf16_buffer) const noexcept=0
Convert valid UTF-32 string into UTF-16LE string.
virtual simdutf_warn_unused result validate_ascii_with_errors(const char *buf, size_t len) const noexcept=0
Validate the ASCII string and stop on error.
virtual simdutf_warn_unused bool validate_utf8(const char *buf, size_t len) const noexcept=0
Validate the UTF-8 string.
virtual simdutf_warn_unused size_t convert_utf8_to_utf32(const char *input, size_t length, char32_t *utf32_output) const noexcept=0
Convert possibly broken UTF-8 string into UTF-32 string.
simdutf_warn_unused size_t maximal_binary_length_from_base64(const char16_t *input, size_t length) const noexcept
Provide the maximal binary length in bytes given the base64 input.
virtual simdutf_warn_unused bool validate_utf32(const char32_t *buf, size_t len) const noexcept=0
Validate the UTF-32 string.
virtual simdutf_warn_unused result convert_utf16le_to_utf32_with_errors(const char16_t *input, size_t length, char32_t *utf32_buffer) const noexcept=0
Convert possibly broken UTF-16LE string into UTF-32 string and stop on error.
virtual simdutf_warn_unused size_t convert_utf16be_to_utf8_with_replacement(const char16_t *input, size_t length, char *utf8_buffer) const noexcept=0
Convert possibly broken UTF-16BE string into UTF-8 string, replacing unpaired surrogates with the Uni...
virtual simdutf_warn_unused size_t convert_utf16le_to_utf8(const char16_t *input, size_t length, char *utf8_buffer) const noexcept=0
Convert possibly broken UTF-16LE string into UTF-8 string.
virtual simdutf_warn_unused size_t utf8_length_from_utf16be(const char16_t *input, size_t length) const noexcept=0
Compute the number of bytes that this UTF-16BE string would require in UTF-8 format.
virtual simdutf_warn_unused size_t convert_utf32_to_utf8(const char32_t *input, size_t length, char *utf8_buffer) const noexcept=0
Convert possibly broken UTF-32 string into UTF-8 string.
virtual simdutf_warn_unused size_t convert_utf16be_to_latin1(const char16_t *input, size_t length, char *latin1_buffer) const noexcept=0
Convert possibly broken UTF-16BE string into Latin1 string.
virtual simdutf_warn_unused size_t convert_utf8_to_latin1(const char *input, size_t length, char *latin1_output) const noexcept=0
Convert possibly broken UTF-8 string into latin1 string.
virtual simdutf_warn_unused result base64_to_binary(const char16_t *input, size_t length, char *output, base64_options options=base64_default, last_chunk_handling_options last_chunk_options=last_chunk_handling_options::loose) const noexcept=0
Convert a base64 input to a binary output.
simdutf_warn_unused size_t base64_length_from_binary(size_t length, base64_options options=base64_default) const noexcept
Provide the base64 length in bytes given the length of a binary input.
virtual int detect_encodings(const char *input, size_t length) const noexcept=0
This function will try to detect the possible encodings in one pass.
virtual simdutf_warn_unused size_t count_utf16be(const char16_t *input, size_t length) const noexcept=0
Count the number of code points (characters) in the string assuming that it is valid.
virtual simdutf_warn_unused result convert_utf32_to_utf8_with_errors(const char32_t *input, size_t length, char *utf8_buffer) const noexcept=0
Convert possibly broken UTF-32 string into UTF-8 string and stop on error.
virtual simdutf_warn_unused bool validate_utf16le_as_ascii(const char16_t *buf, size_t len) const noexcept=0
Validate the ASCII string as a UTF-16LE sequence.
virtual void to_well_formed_utf16be(const char16_t *input, size_t len, char16_t *output) const noexcept=0
Copies the UTF-16BE string while replacing mismatched surrogates with the Unicode replacement charact...
virtual simdutf_warn_unused bool validate_ascii(const char *buf, size_t len) const noexcept=0
Validate the ASCII string.
virtual simdutf_warn_unused size_t utf16_length_from_utf8(const char *input, size_t length) const noexcept=0
Compute the number of 2-byte code units that this UTF-8 string would require in UTF-16LE format.
virtual simdutf_warn_unused result convert_utf8_to_utf16be_with_errors(const char *input, size_t length, char16_t *utf16_output) const noexcept=0
Convert possibly broken UTF-8 string into UTF-16BE string and stop on error.
virtual simdutf_warn_unused result convert_utf8_to_latin1_with_errors(const char *input, size_t length, char *latin1_output) const noexcept=0
Convert possibly broken UTF-8 string into latin1 string with errors.
virtual simdutf_warn_unused size_t utf16_length_from_latin1(size_t length) const noexcept
Return the number of bytes that this UTF-16 string would require in Latin1 format.
virtual simdutf_warn_unused result convert_utf32_to_utf16le_with_errors(const char32_t *input, size_t length, char16_t *utf16_buffer) const noexcept=0
Convert possibly broken UTF-32 string into UTF-16LE string and stop on error.
virtual simdutf_warn_unused size_t convert_latin1_to_utf8(const char *input, size_t length, char *utf8_output) const noexcept=0
Convert Latin1 string into UTF-8 string.
virtual simdutf_warn_unused utf8_result validate_utf8_with_counts(const char *buf, size_t len) const noexcept=0
Finds the pointer to the first byte of invalid utf8 while counting continuation bytes and four-byte s...
virtual encoding_type autodetect_encoding(const char *input, size_t length) const noexcept
This function will try to detect the encoding.
virtual simdutf_warn_unused size_t utf8_length_from_latin1(const char *input, size_t length) const noexcept=0
Return the number of bytes that this Latin1 string would require in UTF-8 format.
helpers placed in namespace detail are not a part of the public API
simdutf_warn_unused simdutf_really_inline simdutf_constexpr23 size_t utf32_length_from_latin1(size_t length) noexcept
Compute the number of bytes that this Latin1 string would require in UTF-32 format.
simdutf_warn_unused size_t convert_utf16_to_latin1(const char16_t *input, size_t length, char *latin1_buffer) noexcept
Using native endianness, convert possibly broken UTF-16 string into Latin1 string.
simdutf_warn_unused size_t convert_valid_utf16_to_utf8(const char16_t *input, size_t length, char *utf8_buffer) noexcept
Using native endianness, convert valid UTF-16 string into UTF-8 string.
simdutf_warn_unused bool validate_utf16be(const char16_t *buf, size_t len) noexcept
Validate the UTF-16BE string.
simdutf_warn_unused size_t convert_valid_utf16_to_latin1(const char16_t *input, size_t length, char *latin1_buffer) noexcept
Using native endianness, convert UTF-16 string into Latin1 string.
simdutf_warn_unused size_t convert_valid_utf16le_to_utf8(const char16_t *input, size_t length, char *utf8_buffer) noexcept
Convert valid UTF-16LE string into UTF-8 string.
simdutf_warn_unused simdutf_constexpr23 size_t base64_length_from_binary(size_t length, base64_options options=base64_default) noexcept
Provide the base64 length in bytes given the length of a binary input.
simdutf_warn_unused simdutf_really_inline simdutf_constexpr23 bool base64_ignorable(char input, base64_options options=base64_default) noexcept
Check if a character is an ignorable base64 character.
simdutf_warn_unused size_t convert_utf8_to_utf16_with_replacement(const char *input, size_t length, char16_t *utf16_output) noexcept
Convert a possibly ill-formed UTF-8 string into a UTF-16 string (native endianness),...
simdutf_warn_unused bool validate_utf16_as_ascii(const char16_t *buf, size_t len) noexcept
Validate the ASCII string as a UTF-16 sequence.
simdutf_warn_unused bool validate_utf16le(const char16_t *buf, size_t len) noexcept
Validate the UTF-16LE string.
simdutf_warn_unused size_t utf8_length_from_utf32(const char32_t *input, size_t length) noexcept
Compute the number of bytes that this UTF-32 string would require in UTF-8 format.
simdutf_warn_unused simdutf_really_inline simdutf_constexpr23 const char * find(const char *start, const char *end, char character) noexcept
Find the first occurrence of a character in a string.
simdutf_warn_unused result base64_to_binary_safe(const char *input, size_t length, char *output, size_t &outlen, base64_options options=base64_default, last_chunk_handling_options last_chunk_options=last_chunk_handling_options::loose, bool decode_up_to_bad_char=false) noexcept
Convert a base64 input to a binary output.
simdutf_warn_unused size_t convert_utf16be_to_utf8_with_replacement(const char16_t *input, size_t length, char *utf8_buffer) noexcept
Convert possibly broken UTF-16BE string into UTF-8 string, replacing unpaired surrogates with the Uni...
simdutf_warn_unused size_t convert_utf8_to_utf32(const char *input, size_t length, char32_t *utf32_output) noexcept
Convert possibly broken UTF-8 string into UTF-32 string.
simdutf_warn_unused size_t convert_valid_utf16le_to_utf32(const char16_t *input, size_t length, char32_t *utf32_buffer) noexcept
Convert valid UTF-16LE string into UTF-32 string.
simdutf_warn_unused size_t utf32_length_from_utf16le(const char16_t *input, size_t length) noexcept
Compute the number of bytes that this UTF-16LE string would require in UTF-32 format.
constexpr size_t default_line_length
default line length for base64 encoding with lines
size_t binary_to_base64(const char *input, size_t length, char *output, base64_options options=base64_default) noexcept
Convert a binary input to a base64 output.
simdutf_warn_unused result base64_to_binary(const char *input, size_t length, char *output, base64_options options=base64_default, last_chunk_handling_options last_chunk_options=loose) noexcept
Convert a base64 input to a binary output.
SIMDUTF_DLLIMPORTEXPORT internal::atomic_ptr< const implementation > & get_active_implementation()
The active implementation.
simdutf_warn_unused size_t convert_utf16be_to_latin1(const char16_t *input, size_t length, char *latin1_buffer) noexcept
Convert possibly broken UTF-16BE string into Latin1 string.
simdutf_warn_unused size_t convert_utf16le_to_utf8(const char16_t *input, size_t length, char *utf8_buffer) noexcept
Convert possibly broken UTF-16LE string into UTF-8 string.
simdutf_warn_unused bool validate_utf16le_as_ascii(const char16_t *buf, size_t len) noexcept
Validate the ASCII string as a UTF-16LE sequence.
simdutf_warn_unused size_t convert_valid_utf8_to_latin1(const char *input, size_t length, char *latin1_output) noexcept
Convert valid UTF-8 string into latin1 string.
simdutf_warn_unused size_t convert_utf8_to_utf16le(const char *input, size_t length, char16_t *utf16_output) noexcept
Convert possibly broken UTF-8 string into UTF-16LE string.
simdutf_warn_unused size_t convert_valid_utf16be_to_utf8(const char16_t *input, size_t length, char *utf8_buffer) noexcept
Convert valid UTF-16BE string into UTF-8 string.
simdutf_warn_unused full_result convert_latin1_to_utf8_safe_with_details(const char *input, size_t length, char *utf8_output, size_t utf8_len) noexcept
Convert a Latin1 string into a size-limited UTF-8 buffer and report how much input was consumed and o...
simdutf_warn_unused size_t convert_latin1_to_utf32(const char *input, size_t length, char32_t *utf32_buffer) noexcept
Convert Latin1 string into UTF-32 string.
simdutf_warn_unused size_t convert_utf16_to_utf8(const char16_t *input, size_t length, char *utf8_buffer) noexcept
Using native endianness, convert possibly broken UTF-16 string into UTF-8 string.
simdutf_warn_unused size_t convert_utf16le_to_utf32(const char16_t *input, size_t length, char32_t *utf32_buffer) noexcept
Convert possibly broken UTF-16LE string into UTF-32 string.
simdutf_warn_unused result convert_utf16be_to_utf8_with_errors(const char16_t *input, size_t length, char *utf8_buffer) noexcept
Convert possibly broken UTF-16BE string into UTF-8 string and stop on error.
simdutf_warn_unused size_t convert_valid_utf8_to_utf32(const char *input, size_t length, char32_t *utf32_buffer) noexcept
Convert valid UTF-8 string into UTF-32 string.
simdutf_warn_unused result convert_utf32_to_utf8_with_errors(const char32_t *input, size_t length, char *utf8_buffer) noexcept
Convert possibly broken UTF-32 string into UTF-8 string and stop on error.
simdutf_warn_unused size_t convert_utf8_to_utf16le_with_replacement(const char *input, size_t length, char16_t *utf16_output) noexcept
Convert a possibly ill-formed UTF-8 string into a UTF-16LE string, replacing each ill-formed subseque...
simdutf_warn_unused result validate_utf16be_with_errors(const char16_t *buf, size_t len) noexcept
Validate the UTF-16BE string and stop on error.
simdutf_warn_unused size_t convert_utf16_to_utf8_with_replacement(const char16_t *input, size_t length, char *utf8_buffer) noexcept
Convert possibly broken UTF-16 string (native endianness) into UTF-8 string, replacing unpaired surro...
SIMDUTF_DLLIMPORTEXPORT const internal::available_implementation_list & get_available_implementations()
The list of available implementations compiled into simdutf.
simdutf_warn_unused size_t convert_utf32_to_utf16le(const char32_t *input, size_t length, char16_t *utf16_buffer) noexcept
Convert possibly broken UTF-32 string into UTF-16LE string.
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t utf16_length_from_latin1(size_t length) noexcept
Compute the number of code units that this Latin1 string would require in UTF-16 format.
simdutf_warn_unused simdutf_really_inline simdutf_constexpr23 bool base64_valid_or_padding(char input, base64_options options=base64_default) noexcept
Check if a character is a valid base64 character or the padding character ('=').
void change_endianness_utf16(const char16_t *input, size_t length, char16_t *output) noexcept
Change the endianness of the input.
simdutf_warn_unused result utf8_length_from_utf16_with_replacement(const char16_t *input, size_t length) noexcept
Using native endianness; compute the number of bytes that this UTF-16 string would require in UTF-8 f...
simdutf_warn_unused full_result convert_utf16_to_utf8_with_replacement_safe(const char16_t *input, size_t length, char *utf8_output, size_t utf8_len) noexcept
Convert a possibly broken UTF-16 string into a size-limited UTF-8 buffer, replacing unpaired surrogat...
simdutf_warn_unused result utf8_length_from_utf16le_with_replacement(const char16_t *input, size_t length) noexcept
Compute the number of bytes that this UTF-16LE string would require in UTF-8 format even when the UTF...
simdutf_warn_unused full_result base64_to_binary_details(const char *input, size_t length, char *output, base64_options options=base64_default, last_chunk_handling_options last_chunk_options=last_chunk_handling_options::loose) noexcept
Convert a base64 input to a binary output while returning more details than base64_to_binary.
simdutf_warn_unused size_t convert_utf16be_to_utf32(const char16_t *input, size_t length, char32_t *utf32_buffer) noexcept
Convert possibly broken UTF-16BE string into UTF-32 string.
simdutf_warn_unused size_t utf8_length_from_latin1(const char *input, size_t length) noexcept
Return the number of bytes that this Latin1 string would require in UTF-8 format.
simdutf_warn_unused result convert_utf8_to_utf16le_with_errors(const char *input, size_t length, char16_t *utf16_output) noexcept
Convert possibly broken UTF-8 string into UTF-16LE string and stop on error.
simdutf_warn_unused size_t count_utf16be(const char16_t *input, size_t length) noexcept
Count the number of code points (characters) in the string assuming that it is valid.
simdutf_warn_unused bool validate_utf8(const char *buf, size_t len) noexcept
Validate the UTF-8 string.
simdutf_warn_unused bool validate_utf16(const char16_t *buf, size_t len) noexcept
Using native endianness; Validate the UTF-16 string.
simdutf_warn_unused result convert_utf16be_to_utf32_with_errors(const char16_t *input, size_t length, char32_t *utf32_buffer) noexcept
Convert possibly broken UTF-16BE string into UTF-32 string and stop on error.
simdutf_warn_unused size_t utf8_length_from_utf16le(const char16_t *input, size_t length) noexcept
Compute the number of bytes that this UTF-16LE string would require in UTF-8 format.
simdutf_warn_unused size_t count_utf8(const char *input, size_t length) noexcept
Count the number of code points (characters) in the string assuming that it is valid.
simdutf_warn_unused bool validate_utf32(const char32_t *buf, size_t len) noexcept
Validate the UTF-32 string.
simdutf_warn_unused result convert_utf16le_to_utf8_with_errors(const char16_t *input, size_t length, char *utf8_buffer) noexcept
Convert possibly broken UTF-16LE string into UTF-8 string and stop on error.
simdutf_warn_unused result utf8_length_from_utf16be_with_replacement(const char16_t *input, size_t length) noexcept
Compute the number of bytes that this UTF-16BE string would require in UTF-8 format even when the UTF...
simdutf_warn_unused size_t convert_valid_utf8_to_utf16be(const char *input, size_t length, char16_t *utf16_buffer) noexcept
Convert valid UTF-8 string into UTF-16BE string.
simdutf_warn_unused utf8_to_utf16_result utf16_length_from_utf8_with_replacement(const char *input, size_t length) noexcept
Compute the number of char16_t that this UTF-8 string requires in UTF-16 when ill-formed subsequences...
simdutf_warn_unused size_t utf8_length_from_utf16be(const char16_t *input, size_t length) noexcept
Compute the number of bytes that this UTF-16BE string would require in UTF-8 format.
simdutf_warn_unused utf8_result validate_utf8_with_counts(const char *buf, size_t len) noexcept
Validate the UTF-8 string and stop on error, while counting the number of continuation bytes and of f...
simdutf_warn_unused result convert_utf32_to_utf16_with_errors(const char32_t *input, size_t length, char16_t *utf16_buffer) noexcept
Using native endianness, convert possibly broken UTF-32 string into UTF-16 string and stop on error.
simdutf_warn_unused size_t trim_partial_utf16(const char16_t *input, size_t length)
Given a valid UTF-16 string having a possibly truncated last character, this function checks the end ...
simdutf_warn_unused result convert_utf32_to_latin1_with_errors(const char32_t *input, size_t length, char *latin1_buffer) noexcept
Convert possibly broken UTF-32 string into Latin1 string and stop on error.
simdutf_warn_unused size_t convert_valid_utf32_to_utf16le(const char32_t *input, size_t length, char16_t *utf16_buffer) noexcept
Convert valid UTF-32 string into UTF-16LE string.
simdutf_warn_unused size_t convert_valid_utf16le_to_latin1(const char16_t *input, size_t length, char *latin1_buffer) noexcept
Convert valid UTF-16LE string into Latin1 string.
simdutf_warn_unused size_t convert_valid_utf8_to_utf16(const char *input, size_t length, char16_t *utf16_buffer) noexcept
Using native endianness, convert valid UTF-8 string into a UTF-16 string.
simdutf_warn_unused size_t count_utf16(const char16_t *input, size_t length) noexcept
Count the number of code points (characters) in the string assuming that it is valid.
simdutf_warn_unused result convert_utf32_to_utf16le_with_errors(const char32_t *input, size_t length, char16_t *utf16_buffer) noexcept
Convert possibly broken UTF-32 string into UTF-16LE string and stop on error.
simdutf_warn_unused size_t convert_latin1_to_utf8(const char *input, size_t length, char *utf8_output) noexcept
Convert Latin1 string into UTF-8 string.
simdutf_warn_unused result convert_utf16_to_utf8_with_errors(const char16_t *input, size_t length, char *utf8_buffer) noexcept
Using native endianness, convert possibly broken UTF-16 string into UTF-8 string and stop on error.
simdutf_warn_unused size_t convert_utf16le_to_utf8_with_replacement(const char16_t *input, size_t length, char *utf8_buffer) noexcept
Convert possibly broken UTF-16LE string into UTF-8 string, replacing unpaired surrogates with the Uni...
simdutf_warn_unused size_t maximal_binary_length_from_base64(const char *input, size_t length) noexcept
Provide the maximal binary length in bytes given the base64 input.
simdutf_warn_unused result convert_utf8_to_utf16_with_errors(const char *input, size_t length, char16_t *utf16_output) noexcept
Using native endianness, convert possibly broken UTF-8 string into UTF-16 string and stop on error.
simdutf_warn_unused bool validate_utf16be_as_ascii(const char16_t *buf, size_t len) noexcept
Validate the ASCII string as a UTF-16BE sequence.
simdutf_warn_unused result convert_utf8_to_utf16be_with_errors(const char *input, size_t length, char16_t *utf16_output) noexcept
Convert possibly broken UTF-8 string into UTF-16BE string and stop on error.
simdutf_really_inline simdutf_warn_unused simdutf_constexpr23 size_t latin1_length_from_utf16(size_t length) noexcept
Compute the number of bytes that this UTF-16 string would require in Latin1 format.
simdutf_warn_unused result convert_utf16le_to_latin1_with_errors(const char16_t *input, size_t length, char *latin1_buffer) noexcept
Convert possibly broken UTF-16LE string into Latin1 string.
simdutf_warn_unused result convert_utf16_to_utf32_with_errors(const char16_t *input, size_t length, char32_t *utf32_buffer) noexcept
Using native endianness, convert possibly broken UTF-16 string into UTF-32 string and stop on error.
simdutf_warn_unused result convert_utf8_to_latin1_with_errors(const char *input, size_t length, char *latin1_output) noexcept
Convert possibly broken UTF-8 string into latin1 string with errors.
simdutf_warn_unused size_t utf32_length_from_utf8(const char *input, size_t length) noexcept
Compute the number of 4-byte code units that this UTF-8 string would require in UTF-32 format.
simdutf_warn_unused result validate_utf8_with_errors(const char *buf, size_t len) noexcept
Validate the UTF-8 string and stop on error.
simdutf_warn_unused size_t latin1_length_from_utf8(const char *input, size_t length) noexcept
Compute the number of bytes that this UTF-8 string would require in Latin1 format.
simdutf_warn_unused size_t convert_utf16be_to_utf8(const char16_t *input, size_t length, char *utf8_buffer) noexcept
Convert possibly broken UTF-16BE string into UTF-8 string.
simdutf_warn_unused size_t convert_valid_utf32_to_utf16(const char32_t *input, size_t length, char16_t *utf16_buffer) noexcept
Using native endianness, convert valid UTF-32 string into a UTF-16 string.
simdutf_warn_unused size_t utf32_length_from_utf16be(const char16_t *input, size_t length) noexcept
Compute the number of bytes that this UTF-16BE string would require in UTF-32 format.
simdutf_warn_unused size_t convert_latin1_to_utf16be(const char *input, size_t length, char16_t *utf16_output) noexcept
Convert Latin1 string into UTF-16BE string.
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 convert_utf8_to_latin1(const char *input, size_t length, char *latin1_output) noexcept
Convert possibly broken UTF-8 string into latin1 string.
simdutf_warn_unused size_t convert_valid_utf16be_to_latin1(const char16_t *input, size_t length, char *latin1_buffer) noexcept
Convert valid UTF-16BE string into Latin1 string.
void to_well_formed_utf16le(const char16_t *input, size_t len, char16_t *output) noexcept
Fixes an ill-formed UTF-16LE string by replacing mismatched surrogates with the Unicode replacement c...
simdutf_warn_unused simdutf_really_inline simdutf_constexpr23 size_t latin1_length_from_utf32(size_t length) noexcept
Compute the number of bytes that this UTF-32 string would require in Latin1 format.
simdutf_warn_unused size_t convert_utf16_to_utf32(const char16_t *input, size_t length, char32_t *utf32_buffer) noexcept
Using native endianness, convert possibly broken UTF-16 string into UTF-32 string.
simdutf_warn_unused size_t trim_partial_utf16le(const char16_t *input, size_t length)
Given a valid UTF-16LE string having a possibly truncated last character, this function checks the en...
simdutf_warn_unused size_t count_utf16le(const char16_t *input, size_t length) noexcept
Count the number of code points (characters) in the string assuming that it is valid.
simdutf_warn_unused result validate_utf16_with_errors(const char16_t *buf, size_t len) noexcept
Using native endianness; Validate the UTF-16 string and stop on error.
simdutf_warn_unused result convert_utf8_to_utf32_with_errors(const char *input, size_t length, char32_t *utf32_output) noexcept
Convert possibly broken UTF-8 string into UTF-32 string and stop on error.
void to_well_formed_utf16be(const char16_t *input, size_t len, char16_t *output) noexcept
Fixes an ill-formed UTF-16BE string by replacing mismatched surrogates with the Unicode replacement c...
simdutf_warn_unused result validate_utf16le_with_errors(const char16_t *buf, size_t len) noexcept
Validate the UTF-16LE string and stop on error.
simdutf_warn_unused size_t convert_valid_utf16_to_utf32(const char16_t *input, size_t length, char32_t *utf32_buffer) noexcept
Using native endianness, convert valid UTF-16 string into UTF-32 string.
simdutf_warn_unused full_result convert_utf16_to_utf8_safe_with_details(const char16_t *input, size_t length, char *utf8_output, size_t utf8_len) noexcept
Convert a possibly broken UTF-16 string into a size-limited UTF-8 buffer and report how much input wa...
simdutf_warn_unused result convert_utf16_to_latin1_with_errors(const char16_t *input, size_t length, char *latin1_buffer) noexcept
Using native endianness, convert possibly broken UTF-16 string into Latin1 string.
simdutf_warn_unused size_t convert_utf16le_to_latin1(const char16_t *input, size_t length, char *latin1_buffer) noexcept
Convert possibly broken UTF-16LE string into Latin1 string.
simdutf_warn_unused size_t convert_valid_utf32_to_latin1(const char32_t *input, size_t length, char *latin1_buffer) noexcept
Convert valid UTF-32 string into Latin1 string.
simdutf_warn_unused size_t binary_length_from_base64(const char *input, size_t length) noexcept
Compute the binary length from a base64 input.
simdutf_warn_unused int detect_encodings(const char *input, size_t length) noexcept
Autodetect the possible encodings of the input in one pass.
simdutf_warn_unused size_t convert_utf8_to_utf16be_with_replacement(const char *input, size_t length, char16_t *utf16_output) noexcept
Convert a possibly ill-formed UTF-8 string into a UTF-16BE string, replacing each ill-formed subseque...
simdutf_warn_unused size_t convert_valid_utf32_to_utf8(const char32_t *input, size_t length, char *utf8_buffer) noexcept
Convert valid UTF-32 string into UTF-8 string.
size_t binary_to_base64_with_lines(const char *input, size_t length, char *output, size_t line_length=simdutf::default_line_length, base64_options options=base64_default) noexcept
Convert a binary input to a base64 output with line breaks.
simdutf_warn_unused result convert_utf16be_to_latin1_with_errors(const char16_t *input, size_t length, char *latin1_buffer) noexcept
Convert possibly broken UTF-16BE string into Latin1 string.
simdutf_warn_unused simdutf_constexpr23 size_t base64_length_from_binary_with_lines(size_t length, base64_options options=base64_default, size_t line_length=default_line_length) noexcept
Provide the base64 length in bytes given the length of a binary input, taking into account line break...
simdutf_warn_unused size_t trim_partial_utf16be(const char16_t *input, size_t length)
Given a valid UTF-16BE string having a possibly truncated last character, this function checks the en...
simdutf_warn_unused size_t convert_utf32_to_utf16(const char32_t *input, size_t length, char16_t *utf16_buffer) noexcept
Using native endianness, convert possibly broken UTF-32 string into a UTF-16 string.
simdutf_warn_unused result validate_utf32_with_errors(const char32_t *buf, size_t len) noexcept
Validate the UTF-32 string and stop on error.
simdutf_warn_unused size_t convert_valid_utf8_to_utf16le(const char *input, size_t length, char16_t *utf16_buffer) noexcept
Convert valid UTF-8 string into UTF-16LE string.
simdutf_warn_unused size_t convert_latin1_to_utf8_safe(const char *input, size_t length, char *utf8_output, size_t utf8_len) noexcept
Convert Latin1 string into UTF-8 string with output limit.
simdutf_warn_unused size_t convert_utf8_to_utf16be(const char *input, size_t length, char16_t *utf16_output) noexcept
Convert possibly broken UTF-8 string into UTF-16BE string.
simdutf_warn_unused simdutf_really_inline simdutf_constexpr23 bool base64_valid(char input, base64_options options=base64_default) noexcept
Check if a character is a valid base64 character.
simdutf_warn_unused size_t convert_utf16_to_utf8_safe(const char16_t *input, size_t length, char *utf8_output, size_t utf8_len) noexcept
Using native endianness, convert possibly broken UTF-16 string into UTF-8 string with output limit.
simdutf_warn_unused result convert_utf32_to_utf16be_with_errors(const char32_t *input, size_t length, char16_t *utf16_buffer) noexcept
Convert possibly broken UTF-32 string into UTF-16BE string and stop on error.
simdutf_warn_unused size_t convert_utf32_to_utf8(const char32_t *input, size_t length, char *utf8_buffer) noexcept
Convert possibly broken UTF-32 string into UTF-8 string.
simdutf_warn_unused size_t utf32_length_from_utf16(const char16_t *input, size_t length) noexcept
Using native endianness; Compute the number of bytes that this UTF-16 string would require in UTF-32 ...
simdutf_warn_unused size_t convert_valid_utf16be_to_utf32(const char16_t *input, size_t length, char32_t *utf32_buffer) noexcept
Convert valid UTF-16BE string into UTF-32 string.
simdutf_warn_unused size_t convert_valid_utf32_to_utf16be(const char32_t *input, size_t length, char16_t *utf16_buffer) noexcept
Convert valid UTF-32 string into UTF-16BE string.
simdutf_warn_unused result convert_utf16le_to_utf32_with_errors(const char16_t *input, size_t length, char32_t *utf32_buffer) noexcept
Convert possibly broken UTF-16LE string into UTF-32 string and stop on error.
simdutf_warn_unused result validate_ascii_with_errors(const char *buf, size_t len) noexcept
Validate the ASCII string and stop on error.
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...
simdutf_warn_unused size_t convert_latin1_to_utf16le(const char *input, size_t length, char16_t *utf16_output) noexcept
Convert possibly Latin1 string into UTF-16LE string.
simdutf_warn_unused size_t convert_utf8_to_utf16(const char *input, size_t length, char16_t *utf16_output) noexcept
Using native endianness, convert possibly broken UTF-8 string into a UTF-16 string.
simdutf_warn_unused size_t convert_latin1_to_utf16(const char *input, size_t length, char16_t *utf16_output) noexcept
Using native endianness, convert a Latin1 string into a UTF-16 string.
simdutf_warn_unused bool validate_ascii(const char *buf, size_t len) noexcept
Validate the ASCII string.
simdutf_warn_unused size_t convert_utf32_to_latin1(const char32_t *input, size_t length, char *latin1_buffer) noexcept
Convert possibly broken UTF-32 string into Latin1 string.
simdutf_warn_unused size_t utf8_length_from_utf16(const char16_t *input, size_t length) noexcept
Using native endianness; Compute the number of bytes that this UTF-16 string would require in UTF-8 f...
void to_well_formed_utf16(const char16_t *input, size_t len, char16_t *output) noexcept
Fixes an ill-formed UTF-16 string by replacing mismatched surrogates with the Unicode replacement cha...
simdutf_warn_unused size_t convert_utf32_to_utf16be(const char32_t *input, size_t length, char16_t *utf16_buffer) noexcept
Convert possibly broken UTF-32 string into UTF-16BE string.
simdutf_warn_unused simdutf::encoding_type autodetect_encoding(const char *input, size_t length) noexcept
Autodetect the encoding of the input, a single encoding is recommended.
simdutf_warn_unused size_t utf16_length_from_utf32(const char32_t *input, size_t length) noexcept
Compute the number of two-byte code units that this UTF-32 string would require in UTF-16 format.