Coverage Report

Created: 2026-02-09 07:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/simdutf/src/implementation.cpp
Line
Count
Source
1
#include "simdutf.h"
2
#include <initializer_list>
3
#include <climits>
4
#include <type_traits>
5
#if SIMDUTF_ATOMIC_REF
6
  #include <array>
7
  #include "simdutf/scalar/atomic_util.h"
8
#endif
9
10
static_assert(sizeof(uint8_t) == sizeof(char),
11
              "simdutf requires that uint8_t be a char");
12
static_assert(sizeof(uint16_t) == sizeof(char16_t),
13
              "simdutf requires that char16_t be 16 bits");
14
static_assert(sizeof(uint32_t) == sizeof(char32_t),
15
              "simdutf requires that char32_t be 32 bits");
16
// next line is redundant, but it is kept to catch defective systems.
17
static_assert(CHAR_BIT == 8, "simdutf requires 8-bit bytes");
18
19
// Useful for debugging purposes
20
namespace simdutf {
21
namespace {
22
23
template <typename T> std::string toBinaryString(T b) {
24
  std::string binary = "";
25
  T mask = T(1) << (sizeof(T) * CHAR_BIT - 1);
26
  while (mask > 0) {
27
    binary += ((b & mask) == 0) ? '0' : '1';
28
    mask >>= 1;
29
  }
30
  return binary;
31
}
32
} // namespace
33
} // namespace simdutf
34
35
namespace simdutf {
36
8
bool implementation::supported_by_runtime_system() const {
37
8
  uint32_t required_instruction_sets = this->required_instruction_sets();
38
8
  uint32_t supported_instruction_sets =
39
8
      internal::detect_supported_architectures();
40
8
  return ((supported_instruction_sets & required_instruction_sets) ==
41
8
          required_instruction_sets);
42
8
}
43
44
#if SIMDUTF_FEATURE_DETECT_ENCODING
45
simdutf_warn_unused encoding_type implementation::autodetect_encoding(
46
0
    const char *input, size_t length) const noexcept {
47
  // If there is a BOM, then we trust it.
48
0
  auto bom_encoding = simdutf::BOM::check_bom(input, length);
49
0
  if (bom_encoding != encoding_type::unspecified) {
50
0
    return bom_encoding;
51
0
  }
52
  // UTF8 is common, it includes ASCII, and is commonly represented
53
  // without a BOM, so if it fits, go with that. Note that it is still
54
  // possible to get it wrong, we are only 'guessing'. If some has UTF-16
55
  // data without a BOM, it could pass as UTF-8.
56
  //
57
  // An interesting twist might be to check for UTF-16 ASCII first (every
58
  // other byte is zero).
59
0
  if (validate_utf8(input, length)) {
60
0
    return encoding_type::UTF8;
61
0
  }
62
  // The next most common encoding that might appear without BOM is probably
63
  // UTF-16LE, so try that next.
64
0
  if ((length % 2) == 0) {
65
    // important: we need to divide by two
66
0
    if (validate_utf16le(reinterpret_cast<const char16_t *>(input),
67
0
                         length / 2)) {
68
0
      return encoding_type::UTF16_LE;
69
0
    }
70
0
  }
71
0
  if ((length % 4) == 0) {
72
0
    if (validate_utf32(reinterpret_cast<const char32_t *>(input), length / 4)) {
73
0
      return encoding_type::UTF32_LE;
74
0
    }
75
0
  }
76
0
  return encoding_type::unspecified;
77
0
}
78
79
  #ifdef SIMDUTF_INTERNAL_TESTS
80
std::vector<implementation::TestProcedure>
81
implementation::internal_tests() const {
82
  return {};
83
}
84
  #endif
85
#endif // SIMDUTF_FEATURE_DETECT_ENCODING
86
87
#if SIMDUTF_FEATURE_BASE64
88
simdutf_warn_unused size_t implementation::maximal_binary_length_from_base64(
89
0
    const char *input, size_t length) const noexcept {
90
0
  return scalar::base64::maximal_binary_length_from_base64(input, length);
91
0
}
92
93
simdutf_warn_unused size_t implementation::maximal_binary_length_from_base64(
94
0
    const char16_t *input, size_t length) const noexcept {
95
0
  return scalar::base64::maximal_binary_length_from_base64(input, length);
96
0
}
97
simdutf_warn_unused size_t implementation::base64_length_from_binary(
98
0
    size_t length, base64_options options) const noexcept {
99
0
  return scalar::base64::base64_length_from_binary(length, options);
100
0
}
101
#endif // SIMDUTF_FEATURE_BASE64
102
103
namespace internal {
104
// When there is a single implementation, we should not pay a price
105
// for dispatching to the best implementation. We should just use the
106
// one we have. This is a compile-time check.
107
#define SIMDUTF_SINGLE_IMPLEMENTATION                                          \
108
  (SIMDUTF_IMPLEMENTATION_ICELAKE + SIMDUTF_IMPLEMENTATION_HASWELL +           \
109
       SIMDUTF_IMPLEMENTATION_WESTMERE + SIMDUTF_IMPLEMENTATION_ARM64 +        \
110
       SIMDUTF_IMPLEMENTATION_PPC64 + SIMDUTF_IMPLEMENTATION_LSX +             \
111
       SIMDUTF_IMPLEMENTATION_LASX + SIMDUTF_IMPLEMENTATION_FALLBACK ==        \
112
   1)
113
114
// Static array of known implementations. We are hoping these get baked into the
115
// executable without requiring a static initializer.
116
117
#if SIMDUTF_IMPLEMENTATION_ICELAKE
118
1
static const icelake::implementation *get_icelake_singleton() {
119
1
  static const icelake::implementation icelake_singleton{};
120
1
  return &icelake_singleton;
121
1
}
122
#endif
123
#if SIMDUTF_IMPLEMENTATION_HASWELL
124
1
static const haswell::implementation *get_haswell_singleton() {
125
1
  static const haswell::implementation haswell_singleton{};
126
1
  return &haswell_singleton;
127
1
}
128
#endif
129
#if SIMDUTF_IMPLEMENTATION_WESTMERE
130
1
static const westmere::implementation *get_westmere_singleton() {
131
1
  static const westmere::implementation westmere_singleton{};
132
1
  return &westmere_singleton;
133
1
}
134
#endif
135
#if SIMDUTF_IMPLEMENTATION_ARM64
136
static const arm64::implementation *get_arm64_singleton() {
137
  static const arm64::implementation arm64_singleton{};
138
  return &arm64_singleton;
139
}
140
#endif
141
#if SIMDUTF_IMPLEMENTATION_PPC64
142
static const ppc64::implementation *get_ppc64_singleton() {
143
  static const ppc64::implementation ppc64_singleton{};
144
  return &ppc64_singleton;
145
}
146
#endif
147
#if SIMDUTF_IMPLEMENTATION_RVV
148
static const rvv::implementation *get_rvv_singleton() {
149
  static const rvv::implementation rvv_singleton{};
150
  return &rvv_singleton;
151
}
152
#endif
153
#if SIMDUTF_IMPLEMENTATION_LASX
154
static const lasx::implementation *get_lasx_singleton() {
155
  static const lasx::implementation lasx_singleton{};
156
  return &lasx_singleton;
157
}
158
#endif
159
#if SIMDUTF_IMPLEMENTATION_LSX
160
static const lsx::implementation *get_lsx_singleton() {
161
  static const lsx::implementation lsx_singleton{};
162
  return &lsx_singleton;
163
}
164
#endif
165
#if SIMDUTF_IMPLEMENTATION_FALLBACK
166
1
static const fallback::implementation *get_fallback_singleton() {
167
1
  static const fallback::implementation fallback_singleton{};
168
1
  return &fallback_singleton;
169
1
}
170
#endif
171
172
#if SIMDUTF_SINGLE_IMPLEMENTATION
173
simdutf_really_inline static const implementation *get_single_implementation() {
174
  return
175
  #if SIMDUTF_IMPLEMENTATION_ICELAKE
176
      get_icelake_singleton();
177
  #endif
178
  #if SIMDUTF_IMPLEMENTATION_HASWELL
179
  get_haswell_singleton();
180
  #endif
181
  #if SIMDUTF_IMPLEMENTATION_WESTMERE
182
  get_westmere_singleton();
183
  #endif
184
  #if SIMDUTF_IMPLEMENTATION_ARM64
185
  get_arm64_singleton();
186
  #endif
187
  #if SIMDUTF_IMPLEMENTATION_PPC64
188
  get_ppc64_singleton();
189
  #endif
190
  #if SIMDUTF_IMPLEMENTATION_LASX
191
  get_lasx_singleton();
192
  #endif
193
  #if SIMDUTF_IMPLEMENTATION_LSX
194
  get_lsx_singleton();
195
  #endif
196
  #if SIMDUTF_IMPLEMENTATION_FALLBACK
197
  get_fallback_singleton();
198
  #endif
199
}
200
#endif
201
202
/**
203
 * @private Detects best supported implementation on first use, and sets it
204
 */
205
class detect_best_supported_implementation_on_first_use final
206
    : public implementation {
207
public:
208
0
  std::string name() const noexcept final { return set_best()->name(); }
209
0
  std::string description() const noexcept final {
210
0
    return set_best()->description();
211
0
  }
212
0
  uint32_t required_instruction_sets() const noexcept final {
213
0
    return set_best()->required_instruction_sets();
214
0
  }
215
216
#if SIMDUTF_FEATURE_DETECT_ENCODING
217
  simdutf_warn_unused int
218
0
  detect_encodings(const char *input, size_t length) const noexcept override {
219
0
    return set_best()->detect_encodings(input, length);
220
0
  }
221
#endif // SIMDUTF_FEATURE_DETECT_ENCODING
222
223
#if SIMDUTF_FEATURE_UTF8 || SIMDUTF_FEATURE_DETECT_ENCODING
224
  simdutf_warn_unused bool
225
0
  validate_utf8(const char *buf, size_t len) const noexcept final override {
226
0
    return set_best()->validate_utf8(buf, len);
227
0
  }
228
#endif // SIMDUTF_FEATURE_UTF8 || SIMDUTF_FEATURE_DETECT_ENCODING
229
230
#if SIMDUTF_FEATURE_UTF8
231
  simdutf_warn_unused result validate_utf8_with_errors(
232
0
      const char *buf, size_t len) const noexcept final override {
233
0
    return set_best()->validate_utf8_with_errors(buf, len);
234
0
  }
235
#endif // SIMDUTF_FEATURE_UTF8
236
237
#if SIMDUTF_FEATURE_ASCII
238
  simdutf_warn_unused bool
239
0
  validate_ascii(const char *buf, size_t len) const noexcept final override {
240
0
    return set_best()->validate_ascii(buf, len);
241
0
  }
242
  simdutf_warn_unused result validate_ascii_with_errors(
243
0
      const char *buf, size_t len) const noexcept final override {
244
0
    return set_best()->validate_ascii_with_errors(buf, len);
245
0
  }
246
#endif // SIMDUTF_FEATURE_ASCII
247
248
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_ASCII
249
  simdutf_warn_unused bool
250
  validate_utf16le_as_ascii(const char16_t *buf,
251
0
                            size_t len) const noexcept final override {
252
0
    return set_best()->validate_utf16le_as_ascii(buf, len);
253
0
  }
254
  simdutf_warn_unused bool
255
  validate_utf16be_as_ascii(const char16_t *buf,
256
0
                            size_t len) const noexcept final override {
257
0
    return set_best()->validate_utf16be_as_ascii(buf, len);
258
0
  }
259
#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_ASCII
260
261
#if SIMDUTF_FEATURE_UTF16 || SIMDUTF_FEATURE_DETECT_ENCODING
262
  simdutf_warn_unused bool
263
  validate_utf16le(const char16_t *buf,
264
0
                   size_t len) const noexcept final override {
265
0
    return set_best()->validate_utf16le(buf, len);
266
0
  }
267
#endif // SIMDUTF_FEATURE_UTF16 || SIMDUTF_FEATURE_DETECT_ENCODING
268
269
#if SIMDUTF_FEATURE_UTF16
270
  simdutf_warn_unused bool
271
  validate_utf16be(const char16_t *buf,
272
0
                   size_t len) const noexcept final override {
273
0
    return set_best()->validate_utf16be(buf, len);
274
0
  }
275
276
  simdutf_warn_unused result validate_utf16le_with_errors(
277
0
      const char16_t *buf, size_t len) const noexcept final override {
278
0
    return set_best()->validate_utf16le_with_errors(buf, len);
279
0
  }
280
281
  simdutf_warn_unused result validate_utf16be_with_errors(
282
0
      const char16_t *buf, size_t len) const noexcept final override {
283
0
    return set_best()->validate_utf16be_with_errors(buf, len);
284
0
  }
285
  void to_well_formed_utf16be(const char16_t *input, size_t len,
286
0
                              char16_t *output) const noexcept final override {
287
0
    return set_best()->to_well_formed_utf16be(input, len, output);
288
0
  }
289
  void to_well_formed_utf16le(const char16_t *input, size_t len,
290
0
                              char16_t *output) const noexcept final override {
291
0
    return set_best()->to_well_formed_utf16le(input, len, output);
292
0
  }
293
#endif // SIMDUTF_FEATURE_UTF16
294
295
#if SIMDUTF_FEATURE_UTF32 || SIMDUTF_FEATURE_DETECT_ENCODING
296
  simdutf_warn_unused bool
297
  validate_utf32(const char32_t *buf,
298
0
                 size_t len) const noexcept final override {
299
0
    return set_best()->validate_utf32(buf, len);
300
0
  }
301
#endif // SIMDUTF_FEATURE_UTF32 || SIMDUTF_FEATURE_DETECT_ENCODING
302
303
#if SIMDUTF_FEATURE_UTF32
304
  simdutf_warn_unused result validate_utf32_with_errors(
305
0
      const char32_t *buf, size_t len) const noexcept final override {
306
0
    return set_best()->validate_utf32_with_errors(buf, len);
307
0
  }
308
#endif // SIMDUTF_FEATURE_UTF32
309
310
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
311
  simdutf_warn_unused size_t
312
  convert_latin1_to_utf8(const char *buf, size_t len,
313
0
                         char *utf8_output) const noexcept final override {
314
0
    return set_best()->convert_latin1_to_utf8(buf, len, utf8_output);
315
0
  }
316
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
317
318
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
319
  simdutf_warn_unused size_t convert_latin1_to_utf16le(
320
      const char *buf, size_t len,
321
0
      char16_t *utf16_output) const noexcept final override {
322
0
    return set_best()->convert_latin1_to_utf16le(buf, len, utf16_output);
323
0
  }
324
325
  simdutf_warn_unused size_t convert_latin1_to_utf16be(
326
      const char *buf, size_t len,
327
0
      char16_t *utf16_output) const noexcept final override {
328
0
    return set_best()->convert_latin1_to_utf16be(buf, len, utf16_output);
329
0
  }
330
#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
331
332
#if SIMDUTF_FEATURE_UTF32 && SIMDUTF_FEATURE_LATIN1
333
  simdutf_warn_unused size_t convert_latin1_to_utf32(
334
      const char *buf, size_t len,
335
0
      char32_t *latin1_output) const noexcept final override {
336
0
    return set_best()->convert_latin1_to_utf32(buf, len, latin1_output);
337
0
  }
338
#endif // SIMDUTF_FEATURE_UTF32 && SIMDUTF_FEATURE_LATIN1
339
340
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
341
  simdutf_warn_unused size_t
342
  convert_utf8_to_latin1(const char *buf, size_t len,
343
0
                         char *latin1_output) const noexcept final override {
344
0
    return set_best()->convert_utf8_to_latin1(buf, len, latin1_output);
345
0
  }
346
347
  simdutf_warn_unused result convert_utf8_to_latin1_with_errors(
348
      const char *buf, size_t len,
349
0
      char *latin1_output) const noexcept final override {
350
0
    return set_best()->convert_utf8_to_latin1_with_errors(buf, len,
351
0
                                                          latin1_output);
352
0
  }
353
354
  simdutf_warn_unused size_t convert_valid_utf8_to_latin1(
355
      const char *buf, size_t len,
356
0
      char *latin1_output) const noexcept final override {
357
0
    return set_best()->convert_valid_utf8_to_latin1(buf, len, latin1_output);
358
0
  }
359
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
360
361
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
362
  simdutf_warn_unused size_t convert_utf8_to_utf16le(
363
      const char *buf, size_t len,
364
0
      char16_t *utf16_output) const noexcept final override {
365
0
    return set_best()->convert_utf8_to_utf16le(buf, len, utf16_output);
366
0
  }
367
368
  simdutf_warn_unused size_t convert_utf8_to_utf16be(
369
      const char *buf, size_t len,
370
0
      char16_t *utf16_output) const noexcept final override {
371
0
    return set_best()->convert_utf8_to_utf16be(buf, len, utf16_output);
372
0
  }
373
374
  simdutf_warn_unused result convert_utf8_to_utf16le_with_errors(
375
      const char *buf, size_t len,
376
0
      char16_t *utf16_output) const noexcept final override {
377
0
    return set_best()->convert_utf8_to_utf16le_with_errors(buf, len,
378
0
                                                           utf16_output);
379
0
  }
380
381
  simdutf_warn_unused result convert_utf8_to_utf16be_with_errors(
382
      const char *buf, size_t len,
383
0
      char16_t *utf16_output) const noexcept final override {
384
0
    return set_best()->convert_utf8_to_utf16be_with_errors(buf, len,
385
0
                                                           utf16_output);
386
0
  }
387
388
  simdutf_warn_unused size_t convert_valid_utf8_to_utf16le(
389
      const char *buf, size_t len,
390
0
      char16_t *utf16_output) const noexcept final override {
391
0
    return set_best()->convert_valid_utf8_to_utf16le(buf, len, utf16_output);
392
0
  }
393
394
  simdutf_warn_unused size_t convert_valid_utf8_to_utf16be(
395
      const char *buf, size_t len,
396
0
      char16_t *utf16_output) const noexcept final override {
397
0
    return set_best()->convert_valid_utf8_to_utf16be(buf, len, utf16_output);
398
0
  }
399
  simdutf_warn_unused result utf8_length_from_utf16le_with_replacement(
400
0
      const char16_t *input, size_t length) const noexcept final override {
401
0
    return set_best()->utf8_length_from_utf16le_with_replacement(input, length);
402
0
  }
403
404
  simdutf_warn_unused result utf8_length_from_utf16be_with_replacement(
405
0
      const char16_t *input, size_t length) const noexcept final override {
406
0
    return set_best()->utf8_length_from_utf16be_with_replacement(input, length);
407
0
  }
408
409
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
410
411
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
412
  simdutf_warn_unused size_t
413
  convert_utf8_to_utf32(const char *buf, size_t len,
414
0
                        char32_t *utf32_output) const noexcept final override {
415
0
    return set_best()->convert_utf8_to_utf32(buf, len, utf32_output);
416
0
  }
417
418
  simdutf_warn_unused result convert_utf8_to_utf32_with_errors(
419
      const char *buf, size_t len,
420
0
      char32_t *utf32_output) const noexcept final override {
421
0
    return set_best()->convert_utf8_to_utf32_with_errors(buf, len,
422
0
                                                         utf32_output);
423
0
  }
424
425
  simdutf_warn_unused size_t convert_valid_utf8_to_utf32(
426
      const char *buf, size_t len,
427
0
      char32_t *utf32_output) const noexcept final override {
428
0
    return set_best()->convert_valid_utf8_to_utf32(buf, len, utf32_output);
429
0
  }
430
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
431
432
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
433
  simdutf_warn_unused size_t
434
  convert_utf16le_to_latin1(const char16_t *buf, size_t len,
435
0
                            char *latin1_output) const noexcept final override {
436
0
    return set_best()->convert_utf16le_to_latin1(buf, len, latin1_output);
437
0
  }
438
439
  simdutf_warn_unused size_t
440
  convert_utf16be_to_latin1(const char16_t *buf, size_t len,
441
0
                            char *latin1_output) const noexcept final override {
442
0
    return set_best()->convert_utf16be_to_latin1(buf, len, latin1_output);
443
0
  }
444
445
  simdutf_warn_unused result convert_utf16le_to_latin1_with_errors(
446
      const char16_t *buf, size_t len,
447
0
      char *latin1_output) const noexcept final override {
448
0
    return set_best()->convert_utf16le_to_latin1_with_errors(buf, len,
449
0
                                                             latin1_output);
450
0
  }
451
452
  simdutf_warn_unused result convert_utf16be_to_latin1_with_errors(
453
      const char16_t *buf, size_t len,
454
0
      char *latin1_output) const noexcept final override {
455
0
    return set_best()->convert_utf16be_to_latin1_with_errors(buf, len,
456
0
                                                             latin1_output);
457
0
  }
458
459
  simdutf_warn_unused size_t convert_valid_utf16le_to_latin1(
460
      const char16_t *buf, size_t len,
461
0
      char *latin1_output) const noexcept final override {
462
0
    return set_best()->convert_valid_utf16le_to_latin1(buf, len, latin1_output);
463
0
  }
464
465
  simdutf_warn_unused size_t convert_valid_utf16be_to_latin1(
466
      const char16_t *buf, size_t len,
467
0
      char *latin1_output) const noexcept final override {
468
0
    return set_best()->convert_valid_utf16be_to_latin1(buf, len, latin1_output);
469
0
  }
470
#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
471
472
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
473
  simdutf_warn_unused size_t
474
  convert_utf16le_to_utf8(const char16_t *buf, size_t len,
475
0
                          char *utf8_output) const noexcept final override {
476
0
    return set_best()->convert_utf16le_to_utf8(buf, len, utf8_output);
477
0
  }
478
479
  simdutf_warn_unused size_t
480
  convert_utf16be_to_utf8(const char16_t *buf, size_t len,
481
0
                          char *utf8_output) const noexcept final override {
482
0
    return set_best()->convert_utf16be_to_utf8(buf, len, utf8_output);
483
0
  }
484
485
  simdutf_warn_unused result convert_utf16le_to_utf8_with_errors(
486
      const char16_t *buf, size_t len,
487
0
      char *utf8_output) const noexcept final override {
488
0
    return set_best()->convert_utf16le_to_utf8_with_errors(buf, len,
489
0
                                                           utf8_output);
490
0
  }
491
492
  simdutf_warn_unused result convert_utf16be_to_utf8_with_errors(
493
      const char16_t *buf, size_t len,
494
0
      char *utf8_output) const noexcept final override {
495
0
    return set_best()->convert_utf16be_to_utf8_with_errors(buf, len,
496
0
                                                           utf8_output);
497
0
  }
498
499
  simdutf_warn_unused size_t convert_valid_utf16le_to_utf8(
500
      const char16_t *buf, size_t len,
501
0
      char *utf8_output) const noexcept final override {
502
0
    return set_best()->convert_valid_utf16le_to_utf8(buf, len, utf8_output);
503
0
  }
504
505
  simdutf_warn_unused size_t convert_valid_utf16be_to_utf8(
506
      const char16_t *buf, size_t len,
507
0
      char *utf8_output) const noexcept final override {
508
0
    return set_best()->convert_valid_utf16be_to_utf8(buf, len, utf8_output);
509
0
  }
510
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
511
512
#if SIMDUTF_FEATURE_UTF32 && SIMDUTF_FEATURE_LATIN1
513
  simdutf_warn_unused size_t
514
  convert_utf32_to_latin1(const char32_t *buf, size_t len,
515
0
                          char *latin1_output) const noexcept final override {
516
0
    return set_best()->convert_utf32_to_latin1(buf, len, latin1_output);
517
0
  }
518
519
  simdutf_warn_unused result convert_utf32_to_latin1_with_errors(
520
      const char32_t *buf, size_t len,
521
0
      char *latin1_output) const noexcept final override {
522
0
    return set_best()->convert_utf32_to_latin1_with_errors(buf, len,
523
0
                                                           latin1_output);
524
0
  }
525
526
  simdutf_warn_unused size_t convert_valid_utf32_to_latin1(
527
      const char32_t *buf, size_t len,
528
0
      char *latin1_output) const noexcept final override {
529
0
    return set_best()->convert_utf32_to_latin1(buf, len, latin1_output);
530
0
  }
531
#endif // SIMDUTF_FEATURE_UTF32 && SIMDUTF_FEATURE_LATIN1
532
533
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
534
  simdutf_warn_unused size_t
535
  convert_utf32_to_utf8(const char32_t *buf, size_t len,
536
0
                        char *utf8_output) const noexcept final override {
537
0
    return set_best()->convert_utf32_to_utf8(buf, len, utf8_output);
538
0
  }
539
540
  simdutf_warn_unused result convert_utf32_to_utf8_with_errors(
541
      const char32_t *buf, size_t len,
542
0
      char *utf8_output) const noexcept final override {
543
0
    return set_best()->convert_utf32_to_utf8_with_errors(buf, len, utf8_output);
544
0
  }
545
546
  simdutf_warn_unused size_t
547
  convert_valid_utf32_to_utf8(const char32_t *buf, size_t len,
548
0
                              char *utf8_output) const noexcept final override {
549
0
    return set_best()->convert_valid_utf32_to_utf8(buf, len, utf8_output);
550
0
  }
551
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
552
553
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
554
  simdutf_warn_unused size_t convert_utf32_to_utf16le(
555
      const char32_t *buf, size_t len,
556
0
      char16_t *utf16_output) const noexcept final override {
557
0
    return set_best()->convert_utf32_to_utf16le(buf, len, utf16_output);
558
0
  }
559
560
  simdutf_warn_unused size_t convert_utf32_to_utf16be(
561
      const char32_t *buf, size_t len,
562
0
      char16_t *utf16_output) const noexcept final override {
563
0
    return set_best()->convert_utf32_to_utf16be(buf, len, utf16_output);
564
0
  }
565
566
  simdutf_warn_unused result convert_utf32_to_utf16le_with_errors(
567
      const char32_t *buf, size_t len,
568
0
      char16_t *utf16_output) const noexcept final override {
569
0
    return set_best()->convert_utf32_to_utf16le_with_errors(buf, len,
570
0
                                                            utf16_output);
571
0
  }
572
573
  simdutf_warn_unused result convert_utf32_to_utf16be_with_errors(
574
      const char32_t *buf, size_t len,
575
0
      char16_t *utf16_output) const noexcept final override {
576
0
    return set_best()->convert_utf32_to_utf16be_with_errors(buf, len,
577
0
                                                            utf16_output);
578
0
  }
579
580
  simdutf_warn_unused size_t convert_valid_utf32_to_utf16le(
581
      const char32_t *buf, size_t len,
582
0
      char16_t *utf16_output) const noexcept final override {
583
0
    return set_best()->convert_valid_utf32_to_utf16le(buf, len, utf16_output);
584
0
  }
585
586
  simdutf_warn_unused size_t convert_valid_utf32_to_utf16be(
587
      const char32_t *buf, size_t len,
588
0
      char16_t *utf16_output) const noexcept final override {
589
0
    return set_best()->convert_valid_utf32_to_utf16be(buf, len, utf16_output);
590
0
  }
591
592
  simdutf_warn_unused size_t convert_utf16le_to_utf32(
593
      const char16_t *buf, size_t len,
594
0
      char32_t *utf32_output) const noexcept final override {
595
0
    return set_best()->convert_utf16le_to_utf32(buf, len, utf32_output);
596
0
  }
597
598
  simdutf_warn_unused size_t convert_utf16be_to_utf32(
599
      const char16_t *buf, size_t len,
600
0
      char32_t *utf32_output) const noexcept final override {
601
0
    return set_best()->convert_utf16be_to_utf32(buf, len, utf32_output);
602
0
  }
603
604
  simdutf_warn_unused result convert_utf16le_to_utf32_with_errors(
605
      const char16_t *buf, size_t len,
606
0
      char32_t *utf32_output) const noexcept final override {
607
0
    return set_best()->convert_utf16le_to_utf32_with_errors(buf, len,
608
0
                                                            utf32_output);
609
0
  }
610
611
  simdutf_warn_unused result convert_utf16be_to_utf32_with_errors(
612
      const char16_t *buf, size_t len,
613
0
      char32_t *utf32_output) const noexcept final override {
614
0
    return set_best()->convert_utf16be_to_utf32_with_errors(buf, len,
615
0
                                                            utf32_output);
616
0
  }
617
618
  simdutf_warn_unused size_t convert_valid_utf16le_to_utf32(
619
      const char16_t *buf, size_t len,
620
0
      char32_t *utf32_output) const noexcept final override {
621
0
    return set_best()->convert_valid_utf16le_to_utf32(buf, len, utf32_output);
622
0
  }
623
624
  simdutf_warn_unused size_t convert_valid_utf16be_to_utf32(
625
      const char16_t *buf, size_t len,
626
0
      char32_t *utf32_output) const noexcept final override {
627
0
    return set_best()->convert_valid_utf16be_to_utf32(buf, len, utf32_output);
628
0
  }
629
#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
630
631
#if SIMDUTF_FEATURE_UTF16
632
  void change_endianness_utf16(const char16_t *buf, size_t len,
633
0
                               char16_t *output) const noexcept final override {
634
0
    set_best()->change_endianness_utf16(buf, len, output);
635
0
  }
636
637
  simdutf_warn_unused size_t
638
0
  count_utf16le(const char16_t *buf, size_t len) const noexcept final override {
639
0
    return set_best()->count_utf16le(buf, len);
640
0
  }
641
642
  simdutf_warn_unused size_t
643
0
  count_utf16be(const char16_t *buf, size_t len) const noexcept final override {
644
0
    return set_best()->count_utf16be(buf, len);
645
0
  }
646
#endif // SIMDUTF_FEATURE_UTF16
647
648
#if SIMDUTF_FEATURE_UTF8
649
  simdutf_warn_unused size_t
650
0
  count_utf8(const char *buf, size_t len) const noexcept final override {
651
0
    return set_best()->count_utf8(buf, len);
652
0
  }
653
#endif // SIMDUTF_FEATURE_UTF8
654
655
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
656
  simdutf_warn_unused size_t
657
0
  latin1_length_from_utf8(const char *buf, size_t len) const noexcept override {
658
0
    return set_best()->latin1_length_from_utf8(buf, len);
659
0
  }
660
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
661
662
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
663
  simdutf_warn_unused size_t
664
0
  utf8_length_from_latin1(const char *buf, size_t len) const noexcept override {
665
0
    return set_best()->utf8_length_from_latin1(buf, len);
666
0
  }
667
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
668
669
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
670
  simdutf_warn_unused size_t utf8_length_from_utf16le(
671
0
      const char16_t *buf, size_t len) const noexcept override {
672
0
    return set_best()->utf8_length_from_utf16le(buf, len);
673
0
  }
674
675
  simdutf_warn_unused size_t utf8_length_from_utf16be(
676
0
      const char16_t *buf, size_t len) const noexcept override {
677
0
    return set_best()->utf8_length_from_utf16be(buf, len);
678
0
  }
679
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
680
681
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
682
  simdutf_warn_unused size_t utf32_length_from_utf16le(
683
0
      const char16_t *buf, size_t len) const noexcept override {
684
0
    return set_best()->utf32_length_from_utf16le(buf, len);
685
0
  }
686
687
  simdutf_warn_unused size_t utf32_length_from_utf16be(
688
0
      const char16_t *buf, size_t len) const noexcept override {
689
0
    return set_best()->utf32_length_from_utf16be(buf, len);
690
0
  }
691
#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
692
693
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
694
  simdutf_warn_unused size_t
695
0
  utf16_length_from_utf8(const char *buf, size_t len) const noexcept override {
696
0
    return set_best()->utf16_length_from_utf8(buf, len);
697
0
  }
698
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
699
700
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
701
  simdutf_warn_unused size_t utf8_length_from_utf32(
702
0
      const char32_t *buf, size_t len) const noexcept override {
703
0
    return set_best()->utf8_length_from_utf32(buf, len);
704
0
  }
705
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
706
707
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
708
  simdutf_warn_unused size_t utf16_length_from_utf32(
709
0
      const char32_t *buf, size_t len) const noexcept override {
710
0
    return set_best()->utf16_length_from_utf32(buf, len);
711
0
  }
712
#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
713
714
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
715
  simdutf_warn_unused size_t
716
0
  utf32_length_from_utf8(const char *buf, size_t len) const noexcept override {
717
0
    return set_best()->utf32_length_from_utf8(buf, len);
718
0
  }
719
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
720
721
#if SIMDUTF_FEATURE_BASE64
722
  simdutf_warn_unused result base64_to_binary(
723
      const char *input, size_t length, char *output, base64_options options,
724
      last_chunk_handling_options last_chunk_handling_options =
725
0
          last_chunk_handling_options::loose) const noexcept override {
726
0
    return set_best()->base64_to_binary(input, length, output, options,
727
0
                                        last_chunk_handling_options);
728
0
  }
729
730
  simdutf_warn_unused full_result base64_to_binary_details(
731
      const char *input, size_t length, char *output, base64_options options,
732
      last_chunk_handling_options last_chunk_handling_options =
733
0
          last_chunk_handling_options::loose) const noexcept override {
734
0
    return set_best()->base64_to_binary_details(input, length, output, options,
735
0
                                                last_chunk_handling_options);
736
0
  }
737
738
  simdutf_warn_unused result base64_to_binary(
739
      const char16_t *input, size_t length, char *output,
740
      base64_options options,
741
      last_chunk_handling_options last_chunk_handling_options =
742
0
          last_chunk_handling_options::loose) const noexcept override {
743
0
    return set_best()->base64_to_binary(input, length, output, options,
744
0
                                        last_chunk_handling_options);
745
0
  }
746
747
  simdutf_warn_unused full_result base64_to_binary_details(
748
      const char16_t *input, size_t length, char *output,
749
      base64_options options,
750
      last_chunk_handling_options last_chunk_handling_options =
751
0
          last_chunk_handling_options::loose) const noexcept override {
752
0
    return set_best()->base64_to_binary_details(input, length, output, options,
753
0
                                                last_chunk_handling_options);
754
0
  }
755
756
  size_t binary_to_base64(const char *input, size_t length, char *output,
757
0
                          base64_options options) const noexcept override {
758
0
    return set_best()->binary_to_base64(input, length, output, options);
759
0
  }
760
761
  size_t
762
  binary_to_base64_with_lines(const char *input, size_t length, char *output,
763
                              size_t line_length,
764
0
                              base64_options options) const noexcept override {
765
0
    return set_best()->binary_to_base64_with_lines(input, length, output,
766
0
                                                   line_length, options);
767
0
  }
768
769
  const char *find(const char *start, const char *end,
770
0
                   char character) const noexcept override {
771
0
    return set_best()->find(start, end, character);
772
0
  }
773
774
  const char16_t *find(const char16_t *start, const char16_t *end,
775
0
                       char16_t character) const noexcept override {
776
0
    return set_best()->find(start, end, character);
777
0
  }
778
#endif // SIMDUTF_FEATURE_BASE64
779
780
  simdutf_really_inline
781
  detect_best_supported_implementation_on_first_use() noexcept
782
0
      : implementation("best_supported_detector",
783
0
                       "Detects the best supported implementation and sets it",
784
0
                       0) {}
785
786
private:
787
  const implementation *set_best() const noexcept;
788
};
789
790
static_assert(std::is_trivially_destructible<
791
                  detect_best_supported_implementation_on_first_use>::value,
792
              "detect_best_supported_implementation_on_first_use should be "
793
              "trivially destructible");
794
795
static const std::initializer_list<const implementation *> &
796
2
get_available_implementation_pointers() {
797
2
  static const std::initializer_list<const implementation *>
798
2
      available_implementation_pointers{
799
2
#if SIMDUTF_IMPLEMENTATION_ICELAKE
800
2
          get_icelake_singleton(),
801
2
#endif
802
2
#if SIMDUTF_IMPLEMENTATION_HASWELL
803
2
          get_haswell_singleton(),
804
2
#endif
805
2
#if SIMDUTF_IMPLEMENTATION_WESTMERE
806
2
          get_westmere_singleton(),
807
2
#endif
808
#if SIMDUTF_IMPLEMENTATION_ARM64
809
          get_arm64_singleton(),
810
#endif
811
#if SIMDUTF_IMPLEMENTATION_PPC64
812
          get_ppc64_singleton(),
813
#endif
814
#if SIMDUTF_IMPLEMENTATION_RVV
815
          get_rvv_singleton(),
816
#endif
817
#if SIMDUTF_IMPLEMENTATION_LASX
818
          get_lasx_singleton(),
819
#endif
820
#if SIMDUTF_IMPLEMENTATION_LSX
821
          get_lsx_singleton(),
822
#endif
823
2
#if SIMDUTF_IMPLEMENTATION_FALLBACK
824
2
          get_fallback_singleton(),
825
2
#endif
826
2
      }; // available_implementation_pointers
827
2
  return available_implementation_pointers;
828
2
}
829
830
// So we can return UNSUPPORTED_ARCHITECTURE from the parser when there is no
831
// support
832
class unsupported_implementation final : public implementation {
833
public:
834
#if SIMDUTF_FEATURE_DETECT_ENCODING
835
  simdutf_warn_unused int detect_encodings(const char *,
836
0
                                           size_t) const noexcept override {
837
0
    return encoding_type::unspecified;
838
0
  }
839
#endif // SIMDUTF_FEATURE_DETECT_ENCODING
840
841
#if SIMDUTF_FEATURE_UTF8 || SIMDUTF_FEATURE_DETECT_ENCODING
842
  simdutf_warn_unused bool validate_utf8(const char *,
843
0
                                         size_t) const noexcept final override {
844
0
    return false; // Just refuse to validate. Given that we have a fallback
845
                  // implementation
846
    // it seems unlikely that unsupported_implementation will ever be used. If
847
    // it is used, then it will flag all strings as invalid. The alternative is
848
    // to return an error_code from which the user has to figure out whether the
849
    // string is valid UTF-8... which seems like a lot of work just to handle
850
    // the very unlikely case that we have an unsupported implementation. And,
851
    // when it does happen (that we have an unsupported implementation), what
852
    // are the chances that the programmer has a fallback? Given that *we*
853
    // provide the fallback, it implies that the programmer would need a
854
    // fallback for our fallback.
855
0
  }
856
#endif // SIMDUTF_FEATURE_UTF8 || SIMDUTF_FEATURE_DETECT_ENCODING
857
858
#if SIMDUTF_FEATURE_UTF8
859
  simdutf_warn_unused result validate_utf8_with_errors(
860
0
      const char *, size_t) const noexcept final override {
861
0
    return result(error_code::OTHER, 0);
862
0
  }
863
#endif // SIMDUTF_FEATURE_UTF8
864
865
#if SIMDUTF_FEATURE_ASCII
866
  simdutf_warn_unused bool
867
0
  validate_ascii(const char *, size_t) const noexcept final override {
868
0
    return false;
869
0
  }
870
871
  simdutf_warn_unused result validate_ascii_with_errors(
872
0
      const char *, size_t) const noexcept final override {
873
0
    return result(error_code::OTHER, 0);
874
0
  }
875
#endif // SIMDUTF_FEATURE_ASCII
876
877
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_ASCII
878
  simdutf_warn_unused bool
879
  validate_utf16le_as_ascii(const char16_t *,
880
0
                            size_t) const noexcept final override {
881
0
    return false;
882
0
  }
883
884
  simdutf_warn_unused bool
885
  validate_utf16be_as_ascii(const char16_t *,
886
0
                            size_t) const noexcept final override {
887
0
    return false;
888
0
  }
889
#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_ASCII
890
891
#if SIMDUTF_FEATURE_UTF16 || SIMDUTF_FEATURE_DETECT_ENCODING
892
  simdutf_warn_unused bool
893
0
  validate_utf16le(const char16_t *, size_t) const noexcept final override {
894
0
    return false;
895
0
  }
896
#endif // SIMDUTF_FEATURE_UTF16 || SIMDUTF_FEATURE_DETECT_ENCODING
897
898
#if SIMDUTF_FEATURE_UTF16
899
  simdutf_warn_unused bool
900
0
  validate_utf16be(const char16_t *, size_t) const noexcept final override {
901
0
    return false;
902
0
  }
903
904
  simdutf_warn_unused result validate_utf16le_with_errors(
905
0
      const char16_t *, size_t) const noexcept final override {
906
0
    return result(error_code::OTHER, 0);
907
0
  }
908
909
  simdutf_warn_unused result validate_utf16be_with_errors(
910
0
      const char16_t *, size_t) const noexcept final override {
911
0
    return result(error_code::OTHER, 0);
912
0
  }
913
  void to_well_formed_utf16be(const char16_t *, size_t,
914
0
                              char16_t *) const noexcept final override {}
915
  void to_well_formed_utf16le(const char16_t *, size_t,
916
0
                              char16_t *) const noexcept final override {}
917
#endif // SIMDUTF_FEATURE_UTF16
918
919
#if SIMDUTF_FEATURE_UTF32 || SIMDUTF_FEATURE_DETECT_ENCODING
920
  simdutf_warn_unused bool
921
0
  validate_utf32(const char32_t *, size_t) const noexcept final override {
922
0
    return false;
923
0
  }
924
#endif // SIMDUTF_FEATURE_UTF32 || SIMDUTF_FEATURE_DETECT_ENCODING
925
926
#if SIMDUTF_FEATURE_UTF32
927
  simdutf_warn_unused result validate_utf32_with_errors(
928
0
      const char32_t *, size_t) const noexcept final override {
929
0
    return result(error_code::OTHER, 0);
930
0
  }
931
#endif // SIMDUTF_FEATURE_UTF32
932
933
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
934
  simdutf_warn_unused size_t convert_latin1_to_utf8(
935
0
      const char *, size_t, char *) const noexcept final override {
936
0
    return 0;
937
0
  }
938
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
939
940
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
941
  simdutf_warn_unused size_t convert_latin1_to_utf16le(
942
0
      const char *, size_t, char16_t *) const noexcept final override {
943
0
    return 0;
944
0
  }
945
946
  simdutf_warn_unused size_t convert_latin1_to_utf16be(
947
0
      const char *, size_t, char16_t *) const noexcept final override {
948
0
    return 0;
949
0
  }
950
#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
951
952
#if SIMDUTF_FEATURE_UTF32 && SIMDUTF_FEATURE_LATIN1
953
  simdutf_warn_unused size_t convert_latin1_to_utf32(
954
0
      const char *, size_t, char32_t *) const noexcept final override {
955
0
    return 0;
956
0
  }
957
#endif // SIMDUTF_FEATURE_UTF32 && SIMDUTF_FEATURE_LATIN1
958
959
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
960
  simdutf_warn_unused size_t convert_utf8_to_latin1(
961
0
      const char *, size_t, char *) const noexcept final override {
962
0
    return 0;
963
0
  }
964
965
  simdutf_warn_unused result convert_utf8_to_latin1_with_errors(
966
0
      const char *, size_t, char *) const noexcept final override {
967
0
    return result(error_code::OTHER, 0);
968
0
  }
969
970
  simdutf_warn_unused size_t convert_valid_utf8_to_latin1(
971
0
      const char *, size_t, char *) const noexcept final override {
972
0
    return 0;
973
0
  }
974
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
975
976
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
977
  simdutf_warn_unused size_t convert_utf8_to_utf16le(
978
0
      const char *, size_t, char16_t *) const noexcept final override {
979
0
    return 0;
980
0
  }
981
982
  simdutf_warn_unused size_t convert_utf8_to_utf16be(
983
0
      const char *, size_t, char16_t *) const noexcept final override {
984
0
    return 0;
985
0
  }
986
987
  simdutf_warn_unused result convert_utf8_to_utf16le_with_errors(
988
0
      const char *, size_t, char16_t *) const noexcept final override {
989
0
    return result(error_code::OTHER, 0);
990
0
  }
991
992
  simdutf_warn_unused result convert_utf8_to_utf16be_with_errors(
993
0
      const char *, size_t, char16_t *) const noexcept final override {
994
0
    return result(error_code::OTHER, 0);
995
0
  }
996
997
  simdutf_warn_unused size_t convert_valid_utf8_to_utf16le(
998
0
      const char *, size_t, char16_t *) const noexcept final override {
999
0
    return 0;
1000
0
  }
1001
1002
  simdutf_warn_unused size_t convert_valid_utf8_to_utf16be(
1003
0
      const char *, size_t, char16_t *) const noexcept final override {
1004
0
    return 0;
1005
0
  }
1006
  simdutf_warn_unused result utf8_length_from_utf16le_with_replacement(
1007
0
      const char16_t *, size_t) const noexcept final override {
1008
0
    return {OTHER, 0}; // Not supported
1009
0
  }
1010
1011
  simdutf_warn_unused result utf8_length_from_utf16be_with_replacement(
1012
0
      const char16_t *, size_t) const noexcept final override {
1013
0
    return {OTHER, 0}; // Not supported
1014
0
  }
1015
1016
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1017
1018
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
1019
  simdutf_warn_unused size_t convert_utf8_to_utf32(
1020
0
      const char *, size_t, char32_t *) const noexcept final override {
1021
0
    return 0;
1022
0
  }
1023
1024
  simdutf_warn_unused result convert_utf8_to_utf32_with_errors(
1025
0
      const char *, size_t, char32_t *) const noexcept final override {
1026
0
    return result(error_code::OTHER, 0);
1027
0
  }
1028
1029
  simdutf_warn_unused size_t convert_valid_utf8_to_utf32(
1030
0
      const char *, size_t, char32_t *) const noexcept final override {
1031
0
    return 0;
1032
0
  }
1033
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
1034
1035
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
1036
  simdutf_warn_unused size_t convert_utf16le_to_latin1(
1037
0
      const char16_t *, size_t, char *) const noexcept final override {
1038
0
    return 0;
1039
0
  }
1040
1041
  simdutf_warn_unused size_t convert_utf16be_to_latin1(
1042
0
      const char16_t *, size_t, char *) const noexcept final override {
1043
0
    return 0;
1044
0
  }
1045
1046
  simdutf_warn_unused result convert_utf16le_to_latin1_with_errors(
1047
0
      const char16_t *, size_t, char *) const noexcept final override {
1048
0
    return result(error_code::OTHER, 0);
1049
0
  }
1050
1051
  simdutf_warn_unused result convert_utf16be_to_latin1_with_errors(
1052
0
      const char16_t *, size_t, char *) const noexcept final override {
1053
0
    return result(error_code::OTHER, 0);
1054
0
  }
1055
1056
  simdutf_warn_unused size_t convert_valid_utf16le_to_latin1(
1057
0
      const char16_t *, size_t, char *) const noexcept final override {
1058
0
    return 0;
1059
0
  }
1060
1061
  simdutf_warn_unused size_t convert_valid_utf16be_to_latin1(
1062
0
      const char16_t *, size_t, char *) const noexcept final override {
1063
0
    return 0;
1064
0
  }
1065
#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
1066
1067
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1068
  simdutf_warn_unused size_t convert_utf16le_to_utf8(
1069
0
      const char16_t *, size_t, char *) const noexcept final override {
1070
0
    return 0;
1071
0
  }
1072
1073
  simdutf_warn_unused size_t convert_utf16be_to_utf8(
1074
0
      const char16_t *, size_t, char *) const noexcept final override {
1075
0
    return 0;
1076
0
  }
1077
1078
  simdutf_warn_unused result convert_utf16le_to_utf8_with_errors(
1079
0
      const char16_t *, size_t, char *) const noexcept final override {
1080
0
    return result(error_code::OTHER, 0);
1081
0
  }
1082
1083
  simdutf_warn_unused result convert_utf16be_to_utf8_with_errors(
1084
0
      const char16_t *, size_t, char *) const noexcept final override {
1085
0
    return result(error_code::OTHER, 0);
1086
0
  }
1087
1088
  simdutf_warn_unused size_t convert_valid_utf16le_to_utf8(
1089
0
      const char16_t *, size_t, char *) const noexcept final override {
1090
0
    return 0;
1091
0
  }
1092
1093
  simdutf_warn_unused size_t convert_valid_utf16be_to_utf8(
1094
0
      const char16_t *, size_t, char *) const noexcept final override {
1095
0
    return 0;
1096
0
  }
1097
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1098
1099
#if SIMDUTF_FEATURE_UTF32 && SIMDUTF_FEATURE_LATIN1
1100
  simdutf_warn_unused size_t convert_utf32_to_latin1(
1101
0
      const char32_t *, size_t, char *) const noexcept final override {
1102
0
    return 0;
1103
0
  }
1104
1105
  simdutf_warn_unused result convert_utf32_to_latin1_with_errors(
1106
0
      const char32_t *, size_t, char *) const noexcept final override {
1107
0
    return result(error_code::OTHER, 0);
1108
0
  }
1109
1110
  simdutf_warn_unused size_t convert_valid_utf32_to_latin1(
1111
0
      const char32_t *, size_t, char *) const noexcept final override {
1112
0
    return 0;
1113
0
  }
1114
#endif // SIMDUTF_FEATURE_UTF32 && SIMDUTF_FEATURE_LATIN1
1115
1116
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
1117
  simdutf_warn_unused size_t convert_utf32_to_utf8(
1118
0
      const char32_t *, size_t, char *) const noexcept final override {
1119
0
    return 0;
1120
0
  }
1121
1122
  simdutf_warn_unused result convert_utf32_to_utf8_with_errors(
1123
0
      const char32_t *, size_t, char *) const noexcept final override {
1124
0
    return result(error_code::OTHER, 0);
1125
0
  }
1126
1127
  simdutf_warn_unused size_t convert_valid_utf32_to_utf8(
1128
0
      const char32_t *, size_t, char *) const noexcept final override {
1129
0
    return 0;
1130
0
  }
1131
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
1132
1133
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
1134
  simdutf_warn_unused size_t convert_utf32_to_utf16le(
1135
0
      const char32_t *, size_t, char16_t *) const noexcept final override {
1136
0
    return 0;
1137
0
  }
1138
1139
  simdutf_warn_unused size_t convert_utf32_to_utf16be(
1140
0
      const char32_t *, size_t, char16_t *) const noexcept final override {
1141
0
    return 0;
1142
0
  }
1143
1144
  simdutf_warn_unused result convert_utf32_to_utf16le_with_errors(
1145
0
      const char32_t *, size_t, char16_t *) const noexcept final override {
1146
0
    return result(error_code::OTHER, 0);
1147
0
  }
1148
1149
  simdutf_warn_unused result convert_utf32_to_utf16be_with_errors(
1150
0
      const char32_t *, size_t, char16_t *) const noexcept final override {
1151
0
    return result(error_code::OTHER, 0);
1152
0
  }
1153
1154
  simdutf_warn_unused size_t convert_valid_utf32_to_utf16le(
1155
0
      const char32_t *, size_t, char16_t *) const noexcept final override {
1156
0
    return 0;
1157
0
  }
1158
1159
  simdutf_warn_unused size_t convert_valid_utf32_to_utf16be(
1160
0
      const char32_t *, size_t, char16_t *) const noexcept final override {
1161
0
    return 0;
1162
0
  }
1163
1164
  simdutf_warn_unused size_t convert_utf16le_to_utf32(
1165
0
      const char16_t *, size_t, char32_t *) const noexcept final override {
1166
0
    return 0;
1167
0
  }
1168
1169
  simdutf_warn_unused size_t convert_utf16be_to_utf32(
1170
0
      const char16_t *, size_t, char32_t *) const noexcept final override {
1171
0
    return 0;
1172
0
  }
1173
1174
  simdutf_warn_unused result convert_utf16le_to_utf32_with_errors(
1175
0
      const char16_t *, size_t, char32_t *) const noexcept final override {
1176
0
    return result(error_code::OTHER, 0);
1177
0
  }
1178
1179
  simdutf_warn_unused result convert_utf16be_to_utf32_with_errors(
1180
0
      const char16_t *, size_t, char32_t *) const noexcept final override {
1181
0
    return result(error_code::OTHER, 0);
1182
0
  }
1183
1184
  simdutf_warn_unused size_t convert_valid_utf16le_to_utf32(
1185
0
      const char16_t *, size_t, char32_t *) const noexcept final override {
1186
0
    return 0;
1187
0
  }
1188
1189
  simdutf_warn_unused size_t convert_valid_utf16be_to_utf32(
1190
0
      const char16_t *, size_t, char32_t *) const noexcept final override {
1191
0
    return 0;
1192
0
  }
1193
#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
1194
1195
#if SIMDUTF_FEATURE_UTF16
1196
  void change_endianness_utf16(const char16_t *, size_t,
1197
0
                               char16_t *) const noexcept final override {}
1198
1199
  simdutf_warn_unused size_t
1200
0
  count_utf16le(const char16_t *, size_t) const noexcept final override {
1201
0
    return 0;
1202
0
  }
1203
1204
  simdutf_warn_unused size_t
1205
0
  count_utf16be(const char16_t *, size_t) const noexcept final override {
1206
0
    return 0;
1207
0
  }
1208
#endif // SIMDUTF_FEATURE_UTF16
1209
1210
#if SIMDUTF_FEATURE_UTF8
1211
  simdutf_warn_unused size_t count_utf8(const char *,
1212
0
                                        size_t) const noexcept final override {
1213
0
    return 0;
1214
0
  }
1215
#endif // SIMDUTF_FEATURE_UTF8
1216
1217
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
1218
  simdutf_warn_unused size_t
1219
0
  latin1_length_from_utf8(const char *, size_t) const noexcept override {
1220
0
    return 0;
1221
0
  }
1222
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
1223
1224
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
1225
  simdutf_warn_unused size_t
1226
0
  utf8_length_from_latin1(const char *, size_t) const noexcept override {
1227
0
    return 0;
1228
0
  }
1229
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
1230
1231
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1232
  simdutf_warn_unused size_t
1233
0
  utf8_length_from_utf16le(const char16_t *, size_t) const noexcept override {
1234
0
    return 0;
1235
0
  }
1236
1237
  simdutf_warn_unused size_t
1238
0
  utf8_length_from_utf16be(const char16_t *, size_t) const noexcept override {
1239
0
    return 0;
1240
0
  }
1241
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1242
1243
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
1244
  simdutf_warn_unused size_t
1245
0
  utf32_length_from_utf16le(const char16_t *, size_t) const noexcept override {
1246
0
    return 0;
1247
0
  }
1248
1249
  simdutf_warn_unused size_t
1250
0
  utf32_length_from_utf16be(const char16_t *, size_t) const noexcept override {
1251
0
    return 0;
1252
0
  }
1253
#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
1254
1255
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1256
  simdutf_warn_unused size_t
1257
0
  utf16_length_from_utf8(const char *, size_t) const noexcept override {
1258
0
    return 0;
1259
0
  }
1260
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1261
1262
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
1263
  simdutf_warn_unused size_t
1264
0
  utf8_length_from_utf32(const char32_t *, size_t) const noexcept override {
1265
0
    return 0;
1266
0
  }
1267
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
1268
1269
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
1270
  simdutf_warn_unused size_t
1271
0
  utf16_length_from_utf32(const char32_t *, size_t) const noexcept override {
1272
0
    return 0;
1273
0
  }
1274
#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
1275
1276
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
1277
  simdutf_warn_unused size_t
1278
0
  utf32_length_from_utf8(const char *, size_t) const noexcept override {
1279
0
    return 0;
1280
0
  }
1281
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
1282
1283
#if SIMDUTF_FEATURE_BASE64
1284
  simdutf_warn_unused result
1285
  base64_to_binary(const char *, size_t, char *, base64_options,
1286
0
                   last_chunk_handling_options) const noexcept override {
1287
0
    return result(error_code::OTHER, 0);
1288
0
  }
1289
1290
  simdutf_warn_unused full_result base64_to_binary_details(
1291
      const char *, size_t, char *, base64_options,
1292
0
      last_chunk_handling_options) const noexcept override {
1293
0
    return full_result(error_code::OTHER, 0, 0);
1294
0
  }
1295
1296
  simdutf_warn_unused result
1297
  base64_to_binary(const char16_t *, size_t, char *, base64_options,
1298
0
                   last_chunk_handling_options) const noexcept override {
1299
0
    return result(error_code::OTHER, 0);
1300
0
  }
1301
1302
  simdutf_warn_unused full_result base64_to_binary_details(
1303
      const char16_t *, size_t, char *, base64_options,
1304
0
      last_chunk_handling_options) const noexcept override {
1305
0
    return full_result(error_code::OTHER, 0, 0);
1306
0
  }
1307
1308
  size_t binary_to_base64(const char *, size_t, char *,
1309
0
                          base64_options) const noexcept override {
1310
0
    return 0;
1311
0
  }
1312
  size_t binary_to_base64_with_lines(const char *, size_t, char *, size_t,
1313
0
                                     base64_options) const noexcept override {
1314
0
    return 0;
1315
0
  }
1316
0
  const char *find(const char *, const char *, char) const noexcept override {
1317
0
    return nullptr;
1318
0
  }
1319
  const char16_t *find(const char16_t *, const char16_t *,
1320
0
                       char16_t) const noexcept override {
1321
0
    return nullptr;
1322
0
  }
1323
#endif // SIMDUTF_FEATURE_BASE64
1324
1325
  unsupported_implementation()
1326
0
      : implementation("unsupported",
1327
0
                       "Unsupported CPU (no detected SIMD instructions)", 0) {}
1328
};
1329
1330
0
const unsupported_implementation *get_unsupported_singleton() {
1331
0
  static const unsupported_implementation unsupported_singleton{};
1332
0
  return &unsupported_singleton;
1333
0
}
1334
static_assert(std::is_trivially_destructible<unsupported_implementation>::value,
1335
              "unsupported_singleton should be trivially destructible");
1336
1337
0
size_t available_implementation_list::size() const noexcept {
1338
0
  return internal::get_available_implementation_pointers().size();
1339
0
}
1340
const implementation *const *
1341
1
available_implementation_list::begin() const noexcept {
1342
1
  return internal::get_available_implementation_pointers().begin();
1343
1
}
1344
const implementation *const *
1345
1
available_implementation_list::end() const noexcept {
1346
1
  return internal::get_available_implementation_pointers().end();
1347
1
}
1348
const implementation *
1349
0
available_implementation_list::detect_best_supported() const noexcept {
1350
  // They are prelisted in priority order, so we just go down the list
1351
0
  uint32_t supported_instruction_sets =
1352
0
      internal::detect_supported_architectures();
1353
0
  for (const implementation *impl :
1354
0
       internal::get_available_implementation_pointers()) {
1355
0
    uint32_t required_instruction_sets = impl->required_instruction_sets();
1356
0
    if ((supported_instruction_sets & required_instruction_sets) ==
1357
0
        required_instruction_sets) {
1358
0
      return impl;
1359
0
    }
1360
0
  }
1361
0
  return get_unsupported_singleton(); // this should never happen?
1362
0
}
1363
1364
const implementation *
1365
0
detect_best_supported_implementation_on_first_use::set_best() const noexcept {
1366
0
  SIMDUTF_PUSH_DISABLE_WARNINGS
1367
  SIMDUTF_DISABLE_DEPRECATED_WARNING // Disable CRT_SECURE warning on MSVC:
1368
                                     // manually verified this is safe
1369
0
      char *force_implementation_name = getenv("SIMDUTF_FORCE_IMPLEMENTATION");
1370
0
  SIMDUTF_POP_DISABLE_WARNINGS
1371
1372
0
  if (force_implementation_name) {
1373
0
    auto force_implementation =
1374
0
        get_available_implementations()[force_implementation_name];
1375
0
    if (force_implementation) {
1376
0
      return get_active_implementation() = force_implementation;
1377
0
    } else {
1378
      // Note: abort() and stderr usage within the library is forbidden.
1379
0
      return get_active_implementation() = get_unsupported_singleton();
1380
0
    }
1381
0
  }
1382
0
  return get_active_implementation() =
1383
0
             get_available_implementations().detect_best_supported();
1384
0
}
1385
1386
} // namespace internal
1387
1388
/**
1389
 * The list of available implementations compiled into simdutf.
1390
 */
1391
SIMDUTF_DLLIMPORTEXPORT const internal::available_implementation_list &
1392
1
get_available_implementations() {
1393
1
  static const internal::available_implementation_list
1394
1
      available_implementations{};
1395
1
  return available_implementations;
1396
1
}
1397
1398
/**
1399
 * The active implementation.
1400
 */
1401
SIMDUTF_DLLIMPORTEXPORT internal::atomic_ptr<const implementation> &
1402
0
get_active_implementation() {
1403
#if SIMDUTF_SINGLE_IMPLEMENTATION
1404
  // skip runtime detection
1405
  static internal::atomic_ptr<const implementation> active_implementation{
1406
      internal::get_single_implementation()};
1407
  return active_implementation;
1408
#else
1409
0
  static const internal::detect_best_supported_implementation_on_first_use
1410
0
      detect_best_supported_implementation_on_first_use_singleton;
1411
0
  static internal::atomic_ptr<const implementation> active_implementation{
1412
0
      &detect_best_supported_implementation_on_first_use_singleton};
1413
0
  return active_implementation;
1414
0
#endif
1415
0
}
1416
1417
#if SIMDUTF_SINGLE_IMPLEMENTATION
1418
simdutf_really_inline const implementation *get_default_implementation() {
1419
  return internal::get_single_implementation();
1420
}
1421
#else
1422
simdutf_really_inline internal::atomic_ptr<const implementation> &
1423
0
get_default_implementation() {
1424
0
  return get_active_implementation();
1425
0
}
1426
#endif
1427
#define SIMDUTF_GET_CURRENT_IMPLEMENTATION
1428
1429
#if SIMDUTF_FEATURE_UTF8
1430
0
simdutf_warn_unused bool validate_utf8(const char *buf, size_t len) noexcept {
1431
0
  return get_default_implementation()->validate_utf8(buf, len);
1432
0
}
1433
simdutf_warn_unused result validate_utf8_with_errors(const char *buf,
1434
0
                                                     size_t len) noexcept {
1435
0
  return get_default_implementation()->validate_utf8_with_errors(buf, len);
1436
0
}
1437
#endif // SIMDUTF_FEATURE_UTF8
1438
1439
#if SIMDUTF_FEATURE_ASCII
1440
0
simdutf_warn_unused bool validate_ascii(const char *buf, size_t len) noexcept {
1441
0
  return get_default_implementation()->validate_ascii(buf, len);
1442
0
}
1443
simdutf_warn_unused result validate_ascii_with_errors(const char *buf,
1444
0
                                                      size_t len) noexcept {
1445
0
  return get_default_implementation()->validate_ascii_with_errors(buf, len);
1446
0
}
1447
#endif // SIMDUTF_FEATURE_ASCII
1448
1449
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_ASCII
1450
simdutf_warn_unused bool validate_utf16le_as_ascii(const char16_t *buf,
1451
0
                                                   size_t len) noexcept {
1452
0
  return get_default_implementation()->validate_utf16le_as_ascii(buf, len);
1453
0
}
1454
simdutf_warn_unused bool validate_utf16be_as_ascii(const char16_t *buf,
1455
0
                                                   size_t len) noexcept {
1456
0
  return get_default_implementation()->validate_utf16be_as_ascii(buf, len);
1457
0
}
1458
simdutf_warn_unused bool validate_utf16_as_ascii(const char16_t *input,
1459
0
                                                 size_t length) noexcept {
1460
  #if SIMDUTF_IS_BIG_ENDIAN
1461
  return validate_utf16be_as_ascii(input, length);
1462
  #else
1463
0
  return validate_utf16le_as_ascii(input, length);
1464
0
  #endif
1465
0
}
1466
#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_ASCII
1467
1468
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1469
simdutf_warn_unused size_t convert_utf8_to_utf16(
1470
0
    const char *input, size_t length, char16_t *utf16_output) noexcept {
1471
  #if SIMDUTF_IS_BIG_ENDIAN
1472
  return convert_utf8_to_utf16be(input, length, utf16_output);
1473
  #else
1474
0
  return convert_utf8_to_utf16le(input, length, utf16_output);
1475
0
  #endif
1476
0
}
1477
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1478
1479
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
1480
simdutf_warn_unused size_t convert_latin1_to_utf8(const char *buf, size_t len,
1481
0
                                                  char *utf8_output) noexcept {
1482
0
  return get_default_implementation()->convert_latin1_to_utf8(buf, len,
1483
0
                                                              utf8_output);
1484
0
}
1485
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
1486
1487
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
1488
simdutf_warn_unused size_t convert_latin1_to_utf16le(
1489
0
    const char *buf, size_t len, char16_t *utf16_output) noexcept {
1490
0
  return get_default_implementation()->convert_latin1_to_utf16le(buf, len,
1491
0
                                                                 utf16_output);
1492
0
}
1493
simdutf_warn_unused size_t convert_latin1_to_utf16be(
1494
0
    const char *buf, size_t len, char16_t *utf16_output) noexcept {
1495
0
  return get_default_implementation()->convert_latin1_to_utf16be(buf, len,
1496
0
                                                                 utf16_output);
1497
0
}
1498
#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
1499
1500
#if SIMDUTF_FEATURE_UTF32 && SIMDUTF_FEATURE_LATIN1
1501
simdutf_warn_unused size_t convert_latin1_to_utf32(
1502
0
    const char *buf, size_t len, char32_t *latin1_output) noexcept {
1503
0
  return get_default_implementation()->convert_latin1_to_utf32(buf, len,
1504
0
                                                               latin1_output);
1505
0
}
1506
// moved to the header file
1507
// simdutf_warn_unused size_t latin1_length_from_utf32(size_t length) noexcept
1508
// simdutf_warn_unused size_t utf32_length_from_latin1(size_t length) noexcept
1509
#endif // SIMDUTF_FEATURE_UTF32 && SIMDUTF_FEATURE_LATIN1
1510
1511
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
1512
simdutf_warn_unused size_t convert_utf8_to_latin1(
1513
0
    const char *buf, size_t len, char *latin1_output) noexcept {
1514
0
  return get_default_implementation()->convert_utf8_to_latin1(buf, len,
1515
0
                                                              latin1_output);
1516
0
}
1517
simdutf_warn_unused result convert_utf8_to_latin1_with_errors(
1518
0
    const char *buf, size_t len, char *latin1_output) noexcept {
1519
0
  return get_default_implementation()->convert_utf8_to_latin1_with_errors(
1520
0
      buf, len, latin1_output);
1521
0
}
1522
simdutf_warn_unused size_t convert_valid_utf8_to_latin1(
1523
0
    const char *buf, size_t len, char *latin1_output) noexcept {
1524
0
  return get_default_implementation()->convert_valid_utf8_to_latin1(
1525
0
      buf, len, latin1_output);
1526
0
}
1527
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
1528
1529
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1530
simdutf_warn_unused size_t convert_utf8_to_utf16le(
1531
0
    const char *input, size_t length, char16_t *utf16_output) noexcept {
1532
0
  return get_default_implementation()->convert_utf8_to_utf16le(input, length,
1533
0
                                                               utf16_output);
1534
0
}
1535
simdutf_warn_unused size_t convert_utf8_to_utf16be(
1536
0
    const char *input, size_t length, char16_t *utf16_output) noexcept {
1537
0
  return get_default_implementation()->convert_utf8_to_utf16be(input, length,
1538
0
                                                               utf16_output);
1539
0
}
1540
simdutf_warn_unused result convert_utf8_to_utf16_with_errors(
1541
0
    const char *input, size_t length, char16_t *utf16_output) noexcept {
1542
  #if SIMDUTF_IS_BIG_ENDIAN
1543
  return convert_utf8_to_utf16be_with_errors(input, length, utf16_output);
1544
  #else
1545
0
  return convert_utf8_to_utf16le_with_errors(input, length, utf16_output);
1546
0
  #endif
1547
0
}
1548
simdutf_warn_unused result convert_utf8_to_utf16le_with_errors(
1549
0
    const char *input, size_t length, char16_t *utf16_output) noexcept {
1550
0
  return get_default_implementation()->convert_utf8_to_utf16le_with_errors(
1551
0
      input, length, utf16_output);
1552
0
}
1553
simdutf_warn_unused result convert_utf8_to_utf16be_with_errors(
1554
0
    const char *input, size_t length, char16_t *utf16_output) noexcept {
1555
0
  return get_default_implementation()->convert_utf8_to_utf16be_with_errors(
1556
0
      input, length, utf16_output);
1557
0
}
1558
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1559
1560
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
1561
simdutf_warn_unused size_t convert_utf8_to_utf32(
1562
0
    const char *input, size_t length, char32_t *utf32_output) noexcept {
1563
0
  return get_default_implementation()->convert_utf8_to_utf32(input, length,
1564
0
                                                             utf32_output);
1565
0
}
1566
simdutf_warn_unused result convert_utf8_to_utf32_with_errors(
1567
0
    const char *input, size_t length, char32_t *utf32_output) noexcept {
1568
0
  return get_default_implementation()->convert_utf8_to_utf32_with_errors(
1569
0
      input, length, utf32_output);
1570
0
}
1571
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
1572
1573
#if SIMDUTF_FEATURE_UTF16
1574
simdutf_warn_unused bool validate_utf16(const char16_t *buf,
1575
0
                                        size_t len) noexcept {
1576
  #if SIMDUTF_IS_BIG_ENDIAN
1577
  return validate_utf16be(buf, len);
1578
  #else
1579
0
  return validate_utf16le(buf, len);
1580
0
  #endif
1581
0
}
1582
void to_well_formed_utf16be(const char16_t *input, size_t len,
1583
0
                            char16_t *output) noexcept {
1584
0
  return get_default_implementation()->to_well_formed_utf16be(input, len,
1585
0
                                                              output);
1586
0
}
1587
void to_well_formed_utf16le(const char16_t *input, size_t len,
1588
0
                            char16_t *output) noexcept {
1589
0
  return get_default_implementation()->to_well_formed_utf16le(input, len,
1590
0
                                                              output);
1591
0
}
1592
void to_well_formed_utf16(const char16_t *input, size_t len,
1593
0
                          char16_t *output) noexcept {
1594
  #if SIMDUTF_IS_BIG_ENDIAN
1595
  to_well_formed_utf16be(input, len, output);
1596
  #else
1597
0
  to_well_formed_utf16le(input, len, output);
1598
0
  #endif
1599
0
}
1600
#endif // SIMDUTF_FEATURE_UTF16
1601
1602
#if SIMDUTF_FEATURE_UTF16 || SIMDUTF_FEATURE_DETECT_ENCODING
1603
simdutf_warn_unused bool validate_utf16le(const char16_t *buf,
1604
0
                                          size_t len) noexcept {
1605
0
  return get_default_implementation()->validate_utf16le(buf, len);
1606
0
}
1607
#endif // SIMDUTF_FEATURE_UTF16 || SIMDUTF_FEATURE_DETECT_ENCODING
1608
1609
#if SIMDUTF_FEATURE_BASE64
1610
  #if SIMDUTF_ATOMIC_REF
1611
template <typename char_type>
1612
simdutf_warn_unused result atomic_base64_to_binary_safe_impl(
1613
    const char_type *input, size_t length, char *output, size_t &outlen,
1614
    base64_options options,
1615
    last_chunk_handling_options last_chunk_handling_options,
1616
0
    bool decode_up_to_bad_char) noexcept {
1617
0
    #if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
1618
  // We use a smaller buffer during fuzzing to more easily detect bugs.
1619
0
  constexpr size_t buffer_size = 128;
1620
    #else
1621
  // Arbitrary block sizes: 4KB for input.
1622
  constexpr size_t buffer_size = 4096;
1623
    #endif
1624
0
  std::array<char, buffer_size> temp_buffer;
1625
0
  const char_type *const input_init = input;
1626
0
  size_t actual_out = 0;
1627
0
  bool last_chunk = false;
1628
0
  const size_t length_init = length;
1629
0
  result r;
1630
0
  while (!last_chunk) {
1631
0
    last_chunk |= (temp_buffer.size() >= outlen - actual_out);
1632
0
    size_t temp_outlen = (std::min)(temp_buffer.size(), outlen - actual_out);
1633
0
    r = base64_to_binary_safe(input, length, temp_buffer.data(), temp_outlen,
1634
0
                              options, last_chunk_handling_options,
1635
0
                              decode_up_to_bad_char);
1636
    // We processed r.count characters of input.
1637
    // We wrote temp_outlen bytes to temp_buffer.
1638
    // If there is no ignorable characters,
1639
    // we should expect that values/4.0*3 == temp_outlen,
1640
    // except maybe at the tail end of the string.
1641
1642
    //
1643
    // We are assuming that when r.error == error_code::OUTPUT_BUFFER_TOO_SMALL,
1644
    // we truncate the results so that a number of base64 characters divisible
1645
    // by four is processed.
1646
    //
1647
1648
    //
1649
    // We wrote temp_outlen bytes to temp_buffer.
1650
    // We need to copy them to output.
1651
    // Copy with relaxed atomic operations to the output
1652
0
    simdutf_log_assert(temp_outlen <= outlen - actual_out,
1653
0
                       "Output buffer is too small");
1654
0
    simdutf_log_assert(temp_outlen <= temp_buffer.size(),
1655
0
                       "Output buffer is too small");
1656
1657
0
    simdutf::scalar::memcpy_atomic_write(output + actual_out,
1658
0
                                         temp_buffer.data(), temp_outlen);
1659
0
    actual_out += temp_outlen;
1660
0
    length -= r.count;
1661
0
    input += r.count;
1662
1663
0
    if (r.error != error_code::OUTPUT_BUFFER_TOO_SMALL) {
1664
0
      break;
1665
0
    }
1666
0
  }
1667
0
  if (size_t(input - input_init) != length_init) {
1668
    // We did not process all input characters. In such case, we
1669
    // should not end with an ignorable character. See
1670
    // https://tc39.es/proposal-arraybuffer-base64/spec/#sec-frombase64
1671
0
    while (input > input_init && base64_ignorable(*(input - 1), options)) {
1672
0
      --input;
1673
0
    }
1674
0
  }
1675
0
  outlen = actual_out;
1676
0
  return {r.error, size_t(input - input_init)};
1677
0
}
Unexecuted instantiation: simdutf::result simdutf::atomic_base64_to_binary_safe_impl<char>(char const*, unsigned long, char*, unsigned long&, simdutf::base64_options, simdutf::last_chunk_handling_options, bool)
Unexecuted instantiation: simdutf::result simdutf::atomic_base64_to_binary_safe_impl<char16_t>(char16_t const*, unsigned long, char*, unsigned long&, simdutf::base64_options, simdutf::last_chunk_handling_options, bool)
1678
1679
simdutf_warn_unused result atomic_base64_to_binary_safe(
1680
    const char *input, size_t length, char *output, size_t &outlen,
1681
    base64_options options,
1682
    last_chunk_handling_options last_chunk_handling_options,
1683
0
    bool decode_up_to_bad_char) noexcept {
1684
0
  return atomic_base64_to_binary_safe_impl<char>(
1685
0
      input, length, output, outlen, options, last_chunk_handling_options,
1686
0
      decode_up_to_bad_char);
1687
0
}
1688
simdutf_warn_unused result atomic_base64_to_binary_safe(
1689
    const char16_t *input, size_t length, char *output, size_t &outlen,
1690
    base64_options options,
1691
    last_chunk_handling_options last_chunk_handling_options,
1692
0
    bool decode_up_to_bad_char) noexcept {
1693
0
  return atomic_base64_to_binary_safe_impl<char16_t>(
1694
0
      input, length, output, outlen, options, last_chunk_handling_options,
1695
0
      decode_up_to_bad_char);
1696
0
}
1697
  #endif // SIMDUTF_ATOMIC_REF
1698
1699
#endif // SIMDUTF_FEATURE_BASE64
1700
1701
#if SIMDUTF_FEATURE_UTF16
1702
simdutf_warn_unused bool validate_utf16be(const char16_t *buf,
1703
0
                                          size_t len) noexcept {
1704
0
  return get_default_implementation()->validate_utf16be(buf, len);
1705
0
}
1706
simdutf_warn_unused result validate_utf16_with_errors(const char16_t *buf,
1707
0
                                                      size_t len) noexcept {
1708
  #if SIMDUTF_IS_BIG_ENDIAN
1709
  return validate_utf16be_with_errors(buf, len);
1710
  #else
1711
0
  return validate_utf16le_with_errors(buf, len);
1712
0
  #endif
1713
0
}
1714
simdutf_warn_unused result validate_utf16le_with_errors(const char16_t *buf,
1715
0
                                                        size_t len) noexcept {
1716
0
  return get_default_implementation()->validate_utf16le_with_errors(buf, len);
1717
0
}
1718
simdutf_warn_unused result validate_utf16be_with_errors(const char16_t *buf,
1719
0
                                                        size_t len) noexcept {
1720
0
  return get_default_implementation()->validate_utf16be_with_errors(buf, len);
1721
0
}
1722
#endif // SIMDUTF_FEATURE_UTF16
1723
1724
#if SIMDUTF_FEATURE_UTF32
1725
simdutf_warn_unused bool validate_utf32(const char32_t *buf,
1726
0
                                        size_t len) noexcept {
1727
0
  return get_default_implementation()->validate_utf32(buf, len);
1728
0
}
1729
simdutf_warn_unused result validate_utf32_with_errors(const char32_t *buf,
1730
0
                                                      size_t len) noexcept {
1731
0
  return get_default_implementation()->validate_utf32_with_errors(buf, len);
1732
0
}
1733
#endif // SIMDUTF_FEATURE_UTF32
1734
1735
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1736
simdutf_warn_unused size_t convert_valid_utf8_to_utf16(
1737
0
    const char *input, size_t length, char16_t *utf16_buffer) noexcept {
1738
  #if SIMDUTF_IS_BIG_ENDIAN
1739
  return convert_valid_utf8_to_utf16be(input, length, utf16_buffer);
1740
  #else
1741
0
  return convert_valid_utf8_to_utf16le(input, length, utf16_buffer);
1742
0
  #endif
1743
0
}
1744
simdutf_warn_unused size_t convert_valid_utf8_to_utf16le(
1745
0
    const char *input, size_t length, char16_t *utf16_buffer) noexcept {
1746
0
  return get_default_implementation()->convert_valid_utf8_to_utf16le(
1747
0
      input, length, utf16_buffer);
1748
0
}
1749
simdutf_warn_unused size_t convert_valid_utf8_to_utf16be(
1750
0
    const char *input, size_t length, char16_t *utf16_buffer) noexcept {
1751
0
  return get_default_implementation()->convert_valid_utf8_to_utf16be(
1752
0
      input, length, utf16_buffer);
1753
0
}
1754
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1755
1756
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
1757
simdutf_warn_unused size_t convert_valid_utf8_to_utf32(
1758
0
    const char *input, size_t length, char32_t *utf32_buffer) noexcept {
1759
0
  return get_default_implementation()->convert_valid_utf8_to_utf32(
1760
0
      input, length, utf32_buffer);
1761
0
}
1762
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
1763
1764
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1765
simdutf_warn_unused size_t convert_utf16_to_utf8(const char16_t *buf,
1766
                                                 size_t len,
1767
0
                                                 char *utf8_buffer) noexcept {
1768
  #if SIMDUTF_IS_BIG_ENDIAN
1769
  return convert_utf16be_to_utf8(buf, len, utf8_buffer);
1770
  #else
1771
0
  return convert_utf16le_to_utf8(buf, len, utf8_buffer);
1772
0
  #endif
1773
0
}
1774
1775
simdutf_warn_unused size_t
1776
convert_utf16_to_utf8_safe(const char16_t *buf, size_t len, char *utf8_output,
1777
0
                           size_t utf8_len) noexcept {
1778
0
  const auto start{utf8_output};
1779
  // We might be able to go faster by first scanning the input buffer to
1780
  // determine how many char16_t characters we can read without exceeding the
1781
  // utf8_len. This is a one-pass algorithm that has the benefit of not
1782
  // requiring a first pass to determine the length.
1783
0
  while (true) {
1784
    // The worst case for convert_utf16_to_utf8 is when you go from 1 char16_t
1785
    // to 3 characters of UTF-8. So we can read at most utf8_len / 3 char16_t
1786
    // characters.
1787
0
    auto read_len = std::min(len, utf8_len / 3);
1788
0
    if (read_len <= 16) {
1789
0
      break;
1790
0
    }
1791
0
    if (read_len < len) {
1792
      //  If we have a high surrogate at the end of the buffer, we need to
1793
      //  either read one more char16_t or backtrack.
1794
0
      if (scalar::utf16::high_surrogate(buf[read_len - 1])) {
1795
0
        read_len--;
1796
0
      }
1797
0
    }
1798
0
    if (read_len == 0) {
1799
      // If we cannot read anything, we are done.
1800
0
      break;
1801
0
    }
1802
0
    const auto write_len =
1803
0
        simdutf::convert_utf16_to_utf8(buf, read_len, utf8_output);
1804
0
    if (write_len == 0) {
1805
      // There was an error in the conversion, we cannot continue.
1806
0
      return 0; // indicating failure
1807
0
    }
1808
1809
0
    utf8_output += write_len;
1810
0
    utf8_len -= write_len;
1811
0
    buf += read_len;
1812
0
    len -= read_len;
1813
0
  }
1814
  #if SIMDUTF_IS_BIG_ENDIAN
1815
  full_result r =
1816
      scalar::utf16_to_utf8::convert_with_errors<endianness::BIG, true>(
1817
          buf, len, utf8_output, utf8_len);
1818
  #else
1819
0
  full_result r =
1820
0
      scalar::utf16_to_utf8::convert_with_errors<endianness::LITTLE, true>(
1821
0
          buf, len, utf8_output, utf8_len);
1822
0
  #endif
1823
0
  if (r.error != error_code::SUCCESS &&
1824
0
      r.error != error_code::OUTPUT_BUFFER_TOO_SMALL) {
1825
    // If there was an error, we return 0 to indicate failure.
1826
0
    return 0; // indicating failure
1827
0
  }
1828
0
  return r.output_count + (utf8_output - start);
1829
0
}
1830
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1831
1832
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
1833
simdutf_warn_unused size_t convert_utf16_to_latin1(
1834
0
    const char16_t *buf, size_t len, char *latin1_buffer) noexcept {
1835
  #if SIMDUTF_IS_BIG_ENDIAN
1836
  return convert_utf16be_to_latin1(buf, len, latin1_buffer);
1837
  #else
1838
0
  return convert_utf16le_to_latin1(buf, len, latin1_buffer);
1839
0
  #endif
1840
0
}
1841
simdutf_warn_unused size_t convert_latin1_to_utf16(
1842
0
    const char *buf, size_t len, char16_t *utf16_output) noexcept {
1843
  #if SIMDUTF_IS_BIG_ENDIAN
1844
  return convert_latin1_to_utf16be(buf, len, utf16_output);
1845
  #else
1846
0
  return convert_latin1_to_utf16le(buf, len, utf16_output);
1847
0
  #endif
1848
0
}
1849
simdutf_warn_unused size_t convert_utf16be_to_latin1(
1850
0
    const char16_t *buf, size_t len, char *latin1_buffer) noexcept {
1851
0
  return get_default_implementation()->convert_utf16be_to_latin1(buf, len,
1852
0
                                                                 latin1_buffer);
1853
0
}
1854
simdutf_warn_unused size_t convert_utf16le_to_latin1(
1855
0
    const char16_t *buf, size_t len, char *latin1_buffer) noexcept {
1856
0
  return get_default_implementation()->convert_utf16le_to_latin1(buf, len,
1857
0
                                                                 latin1_buffer);
1858
0
}
1859
simdutf_warn_unused size_t convert_valid_utf16be_to_latin1(
1860
0
    const char16_t *buf, size_t len, char *latin1_buffer) noexcept {
1861
0
  return get_default_implementation()->convert_valid_utf16be_to_latin1(
1862
0
      buf, len, latin1_buffer);
1863
0
}
1864
simdutf_warn_unused size_t convert_valid_utf16le_to_latin1(
1865
0
    const char16_t *buf, size_t len, char *latin1_buffer) noexcept {
1866
0
  return get_default_implementation()->convert_valid_utf16le_to_latin1(
1867
0
      buf, len, latin1_buffer);
1868
0
}
1869
simdutf_warn_unused result convert_utf16le_to_latin1_with_errors(
1870
0
    const char16_t *buf, size_t len, char *latin1_buffer) noexcept {
1871
0
  return get_default_implementation()->convert_utf16le_to_latin1_with_errors(
1872
0
      buf, len, latin1_buffer);
1873
0
}
1874
simdutf_warn_unused result convert_utf16be_to_latin1_with_errors(
1875
0
    const char16_t *buf, size_t len, char *latin1_buffer) noexcept {
1876
0
  return get_default_implementation()->convert_utf16be_to_latin1_with_errors(
1877
0
      buf, len, latin1_buffer);
1878
0
}
1879
// moved to header file
1880
// simdutf_warn_unused size_t latin1_length_from_utf16(size_t length) noexcept
1881
// simdutf_warn_unused size_t utf16_length_from_latin1(size_t length) noexcept
1882
#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
1883
1884
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1885
simdutf_warn_unused size_t convert_utf16le_to_utf8(const char16_t *buf,
1886
                                                   size_t len,
1887
0
                                                   char *utf8_buffer) noexcept {
1888
0
  return get_default_implementation()->convert_utf16le_to_utf8(buf, len,
1889
0
                                                               utf8_buffer);
1890
0
}
1891
simdutf_warn_unused size_t convert_utf16be_to_utf8(const char16_t *buf,
1892
                                                   size_t len,
1893
0
                                                   char *utf8_buffer) noexcept {
1894
0
  return get_default_implementation()->convert_utf16be_to_utf8(buf, len,
1895
0
                                                               utf8_buffer);
1896
0
}
1897
simdutf_warn_unused result convert_utf16_to_utf8_with_errors(
1898
0
    const char16_t *buf, size_t len, char *utf8_buffer) noexcept {
1899
  #if SIMDUTF_IS_BIG_ENDIAN
1900
  return convert_utf16be_to_utf8_with_errors(buf, len, utf8_buffer);
1901
  #else
1902
0
  return convert_utf16le_to_utf8_with_errors(buf, len, utf8_buffer);
1903
0
  #endif
1904
0
}
1905
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1906
1907
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
1908
simdutf_warn_unused result convert_utf16_to_latin1_with_errors(
1909
0
    const char16_t *buf, size_t len, char *latin1_buffer) noexcept {
1910
  #if SIMDUTF_IS_BIG_ENDIAN
1911
  return convert_utf16be_to_latin1_with_errors(buf, len, latin1_buffer);
1912
  #else
1913
0
  return convert_utf16le_to_latin1_with_errors(buf, len, latin1_buffer);
1914
0
  #endif
1915
0
}
1916
#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
1917
1918
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1919
simdutf_warn_unused result convert_utf16le_to_utf8_with_errors(
1920
0
    const char16_t *buf, size_t len, char *utf8_buffer) noexcept {
1921
0
  return get_default_implementation()->convert_utf16le_to_utf8_with_errors(
1922
0
      buf, len, utf8_buffer);
1923
0
}
1924
simdutf_warn_unused result convert_utf16be_to_utf8_with_errors(
1925
0
    const char16_t *buf, size_t len, char *utf8_buffer) noexcept {
1926
0
  return get_default_implementation()->convert_utf16be_to_utf8_with_errors(
1927
0
      buf, len, utf8_buffer);
1928
0
}
1929
simdutf_warn_unused size_t convert_valid_utf16_to_utf8(
1930
0
    const char16_t *buf, size_t len, char *utf8_buffer) noexcept {
1931
  #if SIMDUTF_IS_BIG_ENDIAN
1932
  return convert_valid_utf16be_to_utf8(buf, len, utf8_buffer);
1933
  #else
1934
0
  return convert_valid_utf16le_to_utf8(buf, len, utf8_buffer);
1935
0
  #endif
1936
0
}
1937
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1938
1939
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
1940
simdutf_warn_unused size_t convert_valid_utf16_to_latin1(
1941
0
    const char16_t *buf, size_t len, char *latin1_buffer) noexcept {
1942
  #if SIMDUTF_IS_BIG_ENDIAN
1943
  return convert_valid_utf16be_to_latin1(buf, len, latin1_buffer);
1944
  #else
1945
0
  return convert_valid_utf16le_to_latin1(buf, len, latin1_buffer);
1946
0
  #endif
1947
0
}
1948
#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
1949
1950
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1951
simdutf_warn_unused size_t convert_valid_utf16le_to_utf8(
1952
0
    const char16_t *buf, size_t len, char *utf8_buffer) noexcept {
1953
0
  return get_default_implementation()->convert_valid_utf16le_to_utf8(
1954
0
      buf, len, utf8_buffer);
1955
0
}
1956
simdutf_warn_unused size_t convert_valid_utf16be_to_utf8(
1957
0
    const char16_t *buf, size_t len, char *utf8_buffer) noexcept {
1958
0
  return get_default_implementation()->convert_valid_utf16be_to_utf8(
1959
0
      buf, len, utf8_buffer);
1960
0
}
1961
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1962
1963
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
1964
simdutf_warn_unused size_t convert_utf32_to_utf8(const char32_t *buf,
1965
                                                 size_t len,
1966
0
                                                 char *utf8_buffer) noexcept {
1967
0
  return get_default_implementation()->convert_utf32_to_utf8(buf, len,
1968
0
                                                             utf8_buffer);
1969
0
}
1970
simdutf_warn_unused result convert_utf32_to_utf8_with_errors(
1971
0
    const char32_t *buf, size_t len, char *utf8_buffer) noexcept {
1972
0
  return get_default_implementation()->convert_utf32_to_utf8_with_errors(
1973
0
      buf, len, utf8_buffer);
1974
0
}
1975
simdutf_warn_unused size_t convert_valid_utf32_to_utf8(
1976
0
    const char32_t *buf, size_t len, char *utf8_buffer) noexcept {
1977
0
  return get_default_implementation()->convert_valid_utf32_to_utf8(buf, len,
1978
0
                                                                   utf8_buffer);
1979
0
}
1980
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
1981
1982
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
1983
simdutf_warn_unused size_t convert_utf32_to_utf16(
1984
0
    const char32_t *buf, size_t len, char16_t *utf16_buffer) noexcept {
1985
  #if SIMDUTF_IS_BIG_ENDIAN
1986
  return convert_utf32_to_utf16be(buf, len, utf16_buffer);
1987
  #else
1988
0
  return convert_utf32_to_utf16le(buf, len, utf16_buffer);
1989
0
  #endif
1990
0
}
1991
#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
1992
1993
#if SIMDUTF_FEATURE_UTF32 && SIMDUTF_FEATURE_LATIN1
1994
simdutf_warn_unused size_t convert_utf32_to_latin1(
1995
0
    const char32_t *input, size_t length, char *latin1_output) noexcept {
1996
0
  return get_default_implementation()->convert_utf32_to_latin1(input, length,
1997
0
                                                               latin1_output);
1998
0
}
1999
simdutf_warn_unused result convert_utf32_to_latin1_with_errors(
2000
0
    const char32_t *input, size_t length, char *latin1_buffer) noexcept {
2001
0
  return get_default_implementation()->convert_utf32_to_latin1_with_errors(
2002
0
      input, length, latin1_buffer);
2003
0
}
2004
simdutf_warn_unused size_t convert_valid_utf32_to_latin1(
2005
0
    const char32_t *input, size_t length, char *latin1_buffer) noexcept {
2006
0
  return get_default_implementation()->convert_valid_utf32_to_latin1(
2007
0
      input, length, latin1_buffer);
2008
0
}
2009
#endif // SIMDUTF_FEATURE_UTF32 && SIMDUTF_FEATURE_LATIN1
2010
2011
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
2012
simdutf_warn_unused size_t convert_utf32_to_utf16le(
2013
0
    const char32_t *buf, size_t len, char16_t *utf16_buffer) noexcept {
2014
0
  return get_default_implementation()->convert_utf32_to_utf16le(buf, len,
2015
0
                                                                utf16_buffer);
2016
0
}
2017
simdutf_warn_unused size_t convert_utf32_to_utf16be(
2018
0
    const char32_t *buf, size_t len, char16_t *utf16_buffer) noexcept {
2019
0
  return get_default_implementation()->convert_utf32_to_utf16be(buf, len,
2020
0
                                                                utf16_buffer);
2021
0
}
2022
simdutf_warn_unused result convert_utf32_to_utf16_with_errors(
2023
0
    const char32_t *buf, size_t len, char16_t *utf16_buffer) noexcept {
2024
  #if SIMDUTF_IS_BIG_ENDIAN
2025
  return convert_utf32_to_utf16be_with_errors(buf, len, utf16_buffer);
2026
  #else
2027
0
  return convert_utf32_to_utf16le_with_errors(buf, len, utf16_buffer);
2028
0
  #endif
2029
0
}
2030
simdutf_warn_unused result convert_utf32_to_utf16le_with_errors(
2031
0
    const char32_t *buf, size_t len, char16_t *utf16_buffer) noexcept {
2032
0
  return get_default_implementation()->convert_utf32_to_utf16le_with_errors(
2033
0
      buf, len, utf16_buffer);
2034
0
}
2035
simdutf_warn_unused result convert_utf32_to_utf16be_with_errors(
2036
0
    const char32_t *buf, size_t len, char16_t *utf16_buffer) noexcept {
2037
0
  return get_default_implementation()->convert_utf32_to_utf16be_with_errors(
2038
0
      buf, len, utf16_buffer);
2039
0
}
2040
simdutf_warn_unused size_t convert_valid_utf32_to_utf16(
2041
0
    const char32_t *buf, size_t len, char16_t *utf16_buffer) noexcept {
2042
  #if SIMDUTF_IS_BIG_ENDIAN
2043
  return convert_valid_utf32_to_utf16be(buf, len, utf16_buffer);
2044
  #else
2045
0
  return convert_valid_utf32_to_utf16le(buf, len, utf16_buffer);
2046
0
  #endif
2047
0
}
2048
simdutf_warn_unused size_t convert_valid_utf32_to_utf16le(
2049
0
    const char32_t *buf, size_t len, char16_t *utf16_buffer) noexcept {
2050
0
  return get_default_implementation()->convert_valid_utf32_to_utf16le(
2051
0
      buf, len, utf16_buffer);
2052
0
}
2053
simdutf_warn_unused size_t convert_valid_utf32_to_utf16be(
2054
0
    const char32_t *buf, size_t len, char16_t *utf16_buffer) noexcept {
2055
0
  return get_default_implementation()->convert_valid_utf32_to_utf16be(
2056
0
      buf, len, utf16_buffer);
2057
0
}
2058
simdutf_warn_unused size_t convert_utf16_to_utf32(
2059
0
    const char16_t *buf, size_t len, char32_t *utf32_buffer) noexcept {
2060
  #if SIMDUTF_IS_BIG_ENDIAN
2061
  return convert_utf16be_to_utf32(buf, len, utf32_buffer);
2062
  #else
2063
0
  return convert_utf16le_to_utf32(buf, len, utf32_buffer);
2064
0
  #endif
2065
0
}
2066
simdutf_warn_unused size_t convert_utf16le_to_utf32(
2067
0
    const char16_t *buf, size_t len, char32_t *utf32_buffer) noexcept {
2068
0
  return get_default_implementation()->convert_utf16le_to_utf32(buf, len,
2069
0
                                                                utf32_buffer);
2070
0
}
2071
simdutf_warn_unused size_t convert_utf16be_to_utf32(
2072
0
    const char16_t *buf, size_t len, char32_t *utf32_buffer) noexcept {
2073
0
  return get_default_implementation()->convert_utf16be_to_utf32(buf, len,
2074
0
                                                                utf32_buffer);
2075
0
}
2076
simdutf_warn_unused result convert_utf16_to_utf32_with_errors(
2077
0
    const char16_t *buf, size_t len, char32_t *utf32_buffer) noexcept {
2078
  #if SIMDUTF_IS_BIG_ENDIAN
2079
  return convert_utf16be_to_utf32_with_errors(buf, len, utf32_buffer);
2080
  #else
2081
0
  return convert_utf16le_to_utf32_with_errors(buf, len, utf32_buffer);
2082
0
  #endif
2083
0
}
2084
simdutf_warn_unused result convert_utf16le_to_utf32_with_errors(
2085
0
    const char16_t *buf, size_t len, char32_t *utf32_buffer) noexcept {
2086
0
  return get_default_implementation()->convert_utf16le_to_utf32_with_errors(
2087
0
      buf, len, utf32_buffer);
2088
0
}
2089
simdutf_warn_unused result convert_utf16be_to_utf32_with_errors(
2090
0
    const char16_t *buf, size_t len, char32_t *utf32_buffer) noexcept {
2091
0
  return get_default_implementation()->convert_utf16be_to_utf32_with_errors(
2092
0
      buf, len, utf32_buffer);
2093
0
}
2094
simdutf_warn_unused size_t convert_valid_utf16_to_utf32(
2095
0
    const char16_t *buf, size_t len, char32_t *utf32_buffer) noexcept {
2096
  #if SIMDUTF_IS_BIG_ENDIAN
2097
  return convert_valid_utf16be_to_utf32(buf, len, utf32_buffer);
2098
  #else
2099
0
  return convert_valid_utf16le_to_utf32(buf, len, utf32_buffer);
2100
0
  #endif
2101
0
}
2102
simdutf_warn_unused size_t convert_valid_utf16le_to_utf32(
2103
0
    const char16_t *buf, size_t len, char32_t *utf32_buffer) noexcept {
2104
0
  return get_default_implementation()->convert_valid_utf16le_to_utf32(
2105
0
      buf, len, utf32_buffer);
2106
0
}
2107
simdutf_warn_unused size_t convert_valid_utf16be_to_utf32(
2108
0
    const char16_t *buf, size_t len, char32_t *utf32_buffer) noexcept {
2109
0
  return get_default_implementation()->convert_valid_utf16be_to_utf32(
2110
0
      buf, len, utf32_buffer);
2111
0
}
2112
#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
2113
2114
#if SIMDUTF_FEATURE_UTF16
2115
void change_endianness_utf16(const char16_t *input, size_t length,
2116
0
                             char16_t *output) noexcept {
2117
0
  get_default_implementation()->change_endianness_utf16(input, length, output);
2118
0
}
2119
simdutf_warn_unused size_t count_utf16(const char16_t *input,
2120
0
                                       size_t length) noexcept {
2121
  #if SIMDUTF_IS_BIG_ENDIAN
2122
  return count_utf16be(input, length);
2123
  #else
2124
0
  return count_utf16le(input, length);
2125
0
  #endif
2126
0
}
2127
simdutf_warn_unused size_t count_utf16le(const char16_t *input,
2128
0
                                         size_t length) noexcept {
2129
0
  return get_default_implementation()->count_utf16le(input, length);
2130
0
}
2131
simdutf_warn_unused size_t count_utf16be(const char16_t *input,
2132
0
                                         size_t length) noexcept {
2133
0
  return get_default_implementation()->count_utf16be(input, length);
2134
0
}
2135
#endif // SIMDUTF_FEATURE_UTF16
2136
2137
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
2138
simdutf_warn_unused size_t count_utf8(const char *input,
2139
0
                                      size_t length) noexcept {
2140
0
  return get_default_implementation()->count_utf8(input, length);
2141
0
}
2142
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
2143
2144
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
2145
simdutf_warn_unused size_t latin1_length_from_utf8(const char *buf,
2146
0
                                                   size_t len) noexcept {
2147
0
  return get_default_implementation()->latin1_length_from_utf8(buf, len);
2148
0
}
2149
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
2150
2151
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
2152
simdutf_warn_unused size_t utf8_length_from_latin1(const char *buf,
2153
0
                                                   size_t len) noexcept {
2154
0
  return get_default_implementation()->utf8_length_from_latin1(buf, len);
2155
0
}
2156
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
2157
2158
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
2159
simdutf_warn_unused size_t utf8_length_from_utf16(const char16_t *input,
2160
0
                                                  size_t length) noexcept {
2161
  #if SIMDUTF_IS_BIG_ENDIAN
2162
  return utf8_length_from_utf16be(input, length);
2163
  #else
2164
0
  return utf8_length_from_utf16le(input, length);
2165
0
  #endif
2166
0
}
2167
simdutf_warn_unused result utf8_length_from_utf16_with_replacement(
2168
0
    const char16_t *input, size_t length) noexcept {
2169
  #if SIMDUTF_IS_BIG_ENDIAN
2170
  return utf8_length_from_utf16be_with_replacement(input, length);
2171
  #else
2172
0
  return utf8_length_from_utf16le_with_replacement(input, length);
2173
0
  #endif
2174
0
}
2175
simdutf_warn_unused size_t utf8_length_from_utf16le(const char16_t *input,
2176
0
                                                    size_t length) noexcept {
2177
0
  return get_default_implementation()->utf8_length_from_utf16le(input, length);
2178
0
}
2179
simdutf_warn_unused size_t utf8_length_from_utf16be(const char16_t *input,
2180
0
                                                    size_t length) noexcept {
2181
0
  return get_default_implementation()->utf8_length_from_utf16be(input, length);
2182
0
}
2183
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
2184
2185
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
2186
simdutf_warn_unused size_t utf32_length_from_utf16(const char16_t *input,
2187
0
                                                   size_t length) noexcept {
2188
  #if SIMDUTF_IS_BIG_ENDIAN
2189
  return utf32_length_from_utf16be(input, length);
2190
  #else
2191
0
  return utf32_length_from_utf16le(input, length);
2192
0
  #endif
2193
0
}
2194
simdutf_warn_unused size_t utf32_length_from_utf16le(const char16_t *input,
2195
0
                                                     size_t length) noexcept {
2196
0
  return get_default_implementation()->utf32_length_from_utf16le(input, length);
2197
0
}
2198
simdutf_warn_unused size_t utf32_length_from_utf16be(const char16_t *input,
2199
0
                                                     size_t length) noexcept {
2200
0
  return get_default_implementation()->utf32_length_from_utf16be(input, length);
2201
0
}
2202
#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
2203
2204
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
2205
simdutf_warn_unused size_t utf16_length_from_utf8(const char *input,
2206
0
                                                  size_t length) noexcept {
2207
0
  return get_default_implementation()->utf16_length_from_utf8(input, length);
2208
0
}
2209
simdutf_warn_unused result utf8_length_from_utf16le_with_replacement(
2210
0
    const char16_t *input, size_t length) noexcept {
2211
0
  return get_default_implementation()
2212
0
      ->utf8_length_from_utf16le_with_replacement(input, length);
2213
0
}
2214
2215
simdutf_warn_unused result utf8_length_from_utf16be_with_replacement(
2216
0
    const char16_t *input, size_t length) noexcept {
2217
0
  return get_default_implementation()
2218
0
      ->utf8_length_from_utf16be_with_replacement(input, length);
2219
0
}
2220
2221
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
2222
2223
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
2224
simdutf_warn_unused size_t utf8_length_from_utf32(const char32_t *input,
2225
0
                                                  size_t length) noexcept {
2226
0
  return get_default_implementation()->utf8_length_from_utf32(input, length);
2227
0
}
2228
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
2229
2230
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
2231
simdutf_warn_unused size_t utf16_length_from_utf32(const char32_t *input,
2232
0
                                                   size_t length) noexcept {
2233
0
  return get_default_implementation()->utf16_length_from_utf32(input, length);
2234
0
}
2235
#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
2236
2237
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
2238
simdutf_warn_unused size_t utf32_length_from_utf8(const char *input,
2239
0
                                                  size_t length) noexcept {
2240
0
  return get_default_implementation()->utf32_length_from_utf8(input, length);
2241
0
}
2242
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
2243
2244
#if SIMDUTF_FEATURE_BASE64
2245
2246
// this has been moved to implementation.h
2247
// simdutf_warn_unused size_t
2248
// base64_length_from_binary(size_t length, base64_options option) noexcept;
2249
2250
// this has been moved to implementation.h
2251
// simdutf_warn_unused size_t base64_length_from_binary_with_lines(
2252
//     size_t length, base64_options options, size_t line_length) noexcept;
2253
// }
2254
2255
simdutf_warn_unused const char *detail::find(const char *start, const char *end,
2256
0
                                             char character) noexcept {
2257
0
  return get_default_implementation()->find(start, end, character);
2258
0
}
2259
simdutf_warn_unused const char16_t *detail::find(const char16_t *start,
2260
                                                 const char16_t *end,
2261
0
                                                 char16_t character) noexcept {
2262
0
  return get_default_implementation()->find(start, end, character);
2263
0
}
2264
2265
simdutf_warn_unused size_t
2266
0
maximal_binary_length_from_base64(const char *input, size_t length) noexcept {
2267
0
  return get_default_implementation()->maximal_binary_length_from_base64(
2268
0
      input, length);
2269
0
}
2270
2271
simdutf_warn_unused result base64_to_binary(
2272
    const char *input, size_t length, char *output, base64_options options,
2273
0
    last_chunk_handling_options last_chunk_handling_options) noexcept {
2274
0
  return get_default_implementation()->base64_to_binary(
2275
0
      input, length, output, options, last_chunk_handling_options);
2276
0
}
2277
2278
simdutf_warn_unused size_t maximal_binary_length_from_base64(
2279
0
    const char16_t *input, size_t length) noexcept {
2280
0
  return get_default_implementation()->maximal_binary_length_from_base64(
2281
0
      input, length);
2282
0
}
2283
2284
simdutf_warn_unused result base64_to_binary(
2285
    const char16_t *input, size_t length, char *output, base64_options options,
2286
0
    last_chunk_handling_options last_chunk_handling_options) noexcept {
2287
0
  return get_default_implementation()->base64_to_binary(
2288
0
      input, length, output, options, last_chunk_handling_options);
2289
0
}
2290
2291
// moved to implementation.h
2292
// simdutf_warn_unused bool base64_ignorable(char input,
2293
//                                           base64_options options) noexcept
2294
// simdutf_warn_unused bool base64_ignorable(char16_t input,
2295
//                                           base64_options options) noexcept
2296
// simdutf_warn_unused bool base64_valid(char input,
2297
//                                       base64_options options) noexcept
2298
// simdutf_warn_unused bool base64_valid(char16_t input,
2299
//                                       base64_options options) noexcept
2300
// simdutf_warn_unused bool
2301
// base64_valid_or_padding(char input, base64_options options) noexcept
2302
// simdutf_warn_unused bool
2303
// base64_valid_or_padding(char16_t input, base64_options options) noexcept
2304
2305
// base64_to_binary_safe_impl is moved to
2306
// include/simdutf/base64_implementation.h
2307
2308
  #if SIMDUTF_ATOMIC_REF
2309
size_t atomic_binary_to_base64(const char *input, size_t length, char *output,
2310
0
                               base64_options options) noexcept {
2311
0
  size_t retval = 0;
2312
0
    #if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
2313
  // We use a smaller buffer during fuzzing to more easily detect bugs.
2314
0
  constexpr size_t input_block_size = 128 * 3;
2315
    #else
2316
  // Arbitrary block sizes: 3KB for input which produces 4KB in output.
2317
  constexpr size_t input_block_size = 1024 * 3;
2318
    #endif
2319
0
  std::array<char, input_block_size> inbuf;
2320
0
  for (size_t i = 0; i < length; i += input_block_size) {
2321
0
    const size_t current_block_size = std::min(input_block_size, length - i);
2322
0
    simdutf::scalar::memcpy_atomic_read(inbuf.data(), input + i,
2323
0
                                        current_block_size);
2324
0
    const size_t written = binary_to_base64(inbuf.data(), current_block_size,
2325
0
                                            output + retval, options);
2326
0
    retval += written;
2327
0
  }
2328
0
  return retval;
2329
0
}
2330
  #endif // SIMDUTF_ATOMIC_REF
2331
2332
#endif // SIMDUTF_FEATURE_BASE64
2333
2334
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
2335
simdutf_warn_unused size_t convert_latin1_to_utf8_safe(
2336
0
    const char *buf, size_t len, char *utf8_output, size_t utf8_len) noexcept {
2337
0
  const auto start{utf8_output};
2338
2339
0
  while (true) {
2340
    // convert_latin1_to_utf8 will never write more than input length * 2
2341
0
    auto read_len = std::min(len, utf8_len >> 1);
2342
0
    if (read_len <= 16) {
2343
0
      break;
2344
0
    }
2345
2346
0
    const auto write_len =
2347
0
        simdutf::convert_latin1_to_utf8(buf, read_len, utf8_output);
2348
2349
0
    utf8_output += write_len;
2350
0
    utf8_len -= write_len;
2351
0
    buf += read_len;
2352
0
    len -= read_len;
2353
0
  }
2354
2355
0
  utf8_output +=
2356
0
      scalar::latin1_to_utf8::convert_safe(buf, len, utf8_output, utf8_len);
2357
2358
0
  return utf8_output - start;
2359
0
}
2360
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
2361
2362
#if SIMDUTF_FEATURE_BASE64
2363
simdutf_warn_unused result
2364
base64_to_binary_safe(const char *input, size_t length, char *output,
2365
                      size_t &outlen, base64_options options,
2366
                      last_chunk_handling_options last_chunk_handling_options,
2367
0
                      bool decode_up_to_bad_char) noexcept {
2368
0
  return base64_to_binary_safe_impl<char>(input, length, output, outlen,
2369
0
                                          options, last_chunk_handling_options,
2370
0
                                          decode_up_to_bad_char);
2371
0
}
2372
simdutf_warn_unused result
2373
base64_to_binary_safe(const char16_t *input, size_t length, char *output,
2374
                      size_t &outlen, base64_options options,
2375
                      last_chunk_handling_options last_chunk_handling_options,
2376
0
                      bool decode_up_to_bad_char) noexcept {
2377
0
  return base64_to_binary_safe_impl<char16_t>(
2378
0
      input, length, output, outlen, options, last_chunk_handling_options,
2379
0
      decode_up_to_bad_char);
2380
0
}
2381
2382
size_t binary_to_base64(const char *input, size_t length, char *output,
2383
0
                        base64_options options) noexcept {
2384
0
  return get_default_implementation()->binary_to_base64(input, length, output,
2385
0
                                                        options);
2386
0
}
2387
2388
size_t binary_to_base64_with_lines(const char *input, size_t length,
2389
                                   char *output, size_t line_length,
2390
0
                                   base64_options options) noexcept {
2391
0
  return get_default_implementation()->binary_to_base64_with_lines(
2392
0
      input, length, output, line_length, options);
2393
0
}
2394
#endif // SIMDUTF_FEATURE_BASE64
2395
2396
#if SIMDUTF_FEATURE_DETECT_ENCODING
2397
simdutf_warn_unused simdutf::encoding_type
2398
0
autodetect_encoding(const char *buf, size_t length) noexcept {
2399
0
  return get_default_implementation()->autodetect_encoding(buf, length);
2400
0
}
2401
2402
simdutf_warn_unused int detect_encodings(const char *buf,
2403
0
                                         size_t length) noexcept {
2404
0
  return get_default_implementation()->detect_encodings(buf, length);
2405
0
}
2406
#endif // SIMDUTF_FEATURE_DETECT_ENCODING
2407
2408
0
const implementation *builtin_implementation() {
2409
0
  static const implementation *builtin_impl =
2410
0
      get_available_implementations()[SIMDUTF_STRINGIFY(
2411
0
          SIMDUTF_BUILTIN_IMPLEMENTATION)];
2412
0
  return builtin_impl;
2413
0
}
2414
2415
#if SIMDUTF_FEATURE_UTF8
2416
0
simdutf_warn_unused size_t trim_partial_utf8(const char *input, size_t length) {
2417
0
  return scalar::utf8::trim_partial_utf8(input, length);
2418
0
}
2419
#endif // SIMDUTF_FEATURE_UTF8
2420
2421
#if SIMDUTF_FEATURE_UTF16
2422
simdutf_warn_unused size_t trim_partial_utf16be(const char16_t *input,
2423
0
                                                size_t length) {
2424
0
  return scalar::utf16::trim_partial_utf16<BIG>(input, length);
2425
0
}
2426
2427
simdutf_warn_unused size_t trim_partial_utf16le(const char16_t *input,
2428
0
                                                size_t length) {
2429
0
  return scalar::utf16::trim_partial_utf16<LITTLE>(input, length);
2430
0
}
2431
2432
simdutf_warn_unused size_t trim_partial_utf16(const char16_t *input,
2433
0
                                              size_t length) {
2434
  #if SIMDUTF_IS_BIG_ENDIAN
2435
  return trim_partial_utf16be(input, length);
2436
  #else
2437
0
  return trim_partial_utf16le(input, length);
2438
0
  #endif
2439
0
}
2440
#endif // SIMDUTF_FEATURE_UTF16
2441
2442
} // namespace simdutf