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