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