Coverage Report

Created: 2026-01-17 06:21

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
6.09k
    const char *input, size_t length) const noexcept {
90
6.09k
  return scalar::base64::maximal_binary_length_from_base64(input, length);
91
6.09k
}
92
93
simdutf_warn_unused size_t implementation::maximal_binary_length_from_base64(
94
3.39k
    const char16_t *input, size_t length) const noexcept {
95
3.39k
  return scalar::base64::maximal_binary_length_from_base64(input, length);
96
3.39k
}
97
simdutf_warn_unused size_t implementation::base64_length_from_binary(
98
3.34k
    size_t length, base64_options options) const noexcept {
99
3.34k
  return scalar::base64::base64_length_from_binary(length, options);
100
3.34k
}
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
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
1
          last_chunk_handling_options::loose) const noexcept override {
752
1
    return set_best()->base64_to_binary_details(input, length, output, options,
753
1
                                                last_chunk_handling_options);
754
1
  }
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
1
      : implementation("best_supported_detector",
783
1
                       "Detects the best supported implementation and sets it",
784
1
                       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
3
get_available_implementation_pointers() {
797
3
  static const std::initializer_list<const implementation *>
798
3
      available_implementation_pointers{
799
3
#if SIMDUTF_IMPLEMENTATION_ICELAKE
800
3
          get_icelake_singleton(),
801
3
#endif
802
3
#if SIMDUTF_IMPLEMENTATION_HASWELL
803
3
          get_haswell_singleton(),
804
3
#endif
805
3
#if SIMDUTF_IMPLEMENTATION_WESTMERE
806
3
          get_westmere_singleton(),
807
3
#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
3
#if SIMDUTF_IMPLEMENTATION_FALLBACK
824
3
          get_fallback_singleton(),
825
3
#endif
826
3
      }; // available_implementation_pointers
827
3
  return available_implementation_pointers;
828
3
}
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
1
available_implementation_list::detect_best_supported() const noexcept {
1350
  // They are prelisted in priority order, so we just go down the list
1351
1
  uint32_t supported_instruction_sets =
1352
1
      internal::detect_supported_architectures();
1353
1
  for (const implementation *impl :
1354
2
       internal::get_available_implementation_pointers()) {
1355
2
    uint32_t required_instruction_sets = impl->required_instruction_sets();
1356
2
    if ((supported_instruction_sets & required_instruction_sets) ==
1357
2
        required_instruction_sets) {
1358
1
      return impl;
1359
1
    }
1360
2
  }
1361
0
  return get_unsupported_singleton(); // this should never happen?
1362
1
}
1363
1364
const implementation *
1365
1
detect_best_supported_implementation_on_first_use::set_best() const noexcept {
1366
1
  SIMDUTF_PUSH_DISABLE_WARNINGS
1367
  SIMDUTF_DISABLE_DEPRECATED_WARNING // Disable CRT_SECURE warning on MSVC:
1368
                                     // manually verified this is safe
1369
1
      char *force_implementation_name = getenv("SIMDUTF_FORCE_IMPLEMENTATION");
1370
1
  SIMDUTF_POP_DISABLE_WARNINGS
1371
1372
1
  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
1
  return get_active_implementation() =
1383
1
             get_available_implementations().detect_best_supported();
1384
1
}
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
2
get_available_implementations() {
1393
2
  static const internal::available_implementation_list
1394
2
      available_implementations{};
1395
2
  return available_implementations;
1396
2
}
1397
1398
/**
1399
 * The active implementation.
1400
 */
1401
SIMDUTF_DLLIMPORTEXPORT internal::atomic_ptr<const implementation> &
1402
876
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
876
  static const internal::detect_best_supported_implementation_on_first_use
1410
876
      detect_best_supported_implementation_on_first_use_singleton;
1411
876
  static internal::atomic_ptr<const implementation> active_implementation{
1412
876
      &detect_best_supported_implementation_on_first_use_singleton};
1413
876
  return active_implementation;
1414
876
#endif
1415
876
}
1416
1417
#if SIMDUTF_SINGLE_IMPLEMENTATION
1418
const implementation *get_default_implementation() {
1419
  return internal::get_single_implementation();
1420
}
1421
#else
1422
0
internal::atomic_ptr<const implementation> &get_default_implementation() {
1423
0
  return get_active_implementation();
1424
0
}
1425
#endif
1426
#define SIMDUTF_GET_CURRENT_IMPLEMENTATION
1427
1428
#if SIMDUTF_FEATURE_UTF8
1429
0
simdutf_warn_unused bool validate_utf8(const char *buf, size_t len) noexcept {
1430
0
  return get_default_implementation()->validate_utf8(buf, len);
1431
0
}
1432
simdutf_warn_unused result validate_utf8_with_errors(const char *buf,
1433
0
                                                     size_t len) noexcept {
1434
0
  return get_default_implementation()->validate_utf8_with_errors(buf, len);
1435
0
}
1436
#endif // SIMDUTF_FEATURE_UTF8
1437
1438
#if SIMDUTF_FEATURE_ASCII
1439
0
simdutf_warn_unused bool validate_ascii(const char *buf, size_t len) noexcept {
1440
0
  return get_default_implementation()->validate_ascii(buf, len);
1441
0
}
1442
simdutf_warn_unused result validate_ascii_with_errors(const char *buf,
1443
0
                                                      size_t len) noexcept {
1444
0
  return get_default_implementation()->validate_ascii_with_errors(buf, len);
1445
0
}
1446
#endif // SIMDUTF_FEATURE_ASCII
1447
1448
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_ASCII
1449
simdutf_warn_unused bool validate_utf16le_as_ascii(const char16_t *buf,
1450
0
                                                   size_t len) noexcept {
1451
0
  return get_default_implementation()->validate_utf16le_as_ascii(buf, len);
1452
0
}
1453
simdutf_warn_unused bool validate_utf16be_as_ascii(const char16_t *buf,
1454
0
                                                   size_t len) noexcept {
1455
0
  return get_default_implementation()->validate_utf16be_as_ascii(buf, len);
1456
0
}
1457
simdutf_warn_unused bool validate_utf16_as_ascii(const char16_t *input,
1458
0
                                                 size_t length) noexcept {
1459
  #if SIMDUTF_IS_BIG_ENDIAN
1460
  return validate_utf16be_as_ascii(input, length);
1461
  #else
1462
0
  return validate_utf16le_as_ascii(input, length);
1463
0
  #endif
1464
0
}
1465
#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_ASCII
1466
1467
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1468
simdutf_warn_unused size_t convert_utf8_to_utf16(
1469
0
    const char *input, size_t length, char16_t *utf16_output) noexcept {
1470
  #if SIMDUTF_IS_BIG_ENDIAN
1471
  return convert_utf8_to_utf16be(input, length, utf16_output);
1472
  #else
1473
0
  return convert_utf8_to_utf16le(input, length, utf16_output);
1474
0
  #endif
1475
0
}
1476
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1477
1478
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
1479
simdutf_warn_unused size_t convert_latin1_to_utf8(const char *buf, size_t len,
1480
0
                                                  char *utf8_output) noexcept {
1481
0
  return get_default_implementation()->convert_latin1_to_utf8(buf, len,
1482
0
                                                              utf8_output);
1483
0
}
1484
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
1485
1486
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
1487
simdutf_warn_unused size_t convert_latin1_to_utf16le(
1488
0
    const char *buf, size_t len, char16_t *utf16_output) noexcept {
1489
0
  return get_default_implementation()->convert_latin1_to_utf16le(buf, len,
1490
0
                                                                 utf16_output);
1491
0
}
1492
simdutf_warn_unused size_t convert_latin1_to_utf16be(
1493
0
    const char *buf, size_t len, char16_t *utf16_output) noexcept {
1494
0
  return get_default_implementation()->convert_latin1_to_utf16be(buf, len,
1495
0
                                                                 utf16_output);
1496
0
}
1497
#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
1498
1499
#if SIMDUTF_FEATURE_UTF32 && SIMDUTF_FEATURE_LATIN1
1500
simdutf_warn_unused size_t convert_latin1_to_utf32(
1501
0
    const char *buf, size_t len, char32_t *latin1_output) noexcept {
1502
0
  return get_default_implementation()->convert_latin1_to_utf32(buf, len,
1503
0
                                                               latin1_output);
1504
0
}
1505
// moved to the header file
1506
// simdutf_warn_unused size_t latin1_length_from_utf32(size_t length) noexcept
1507
// simdutf_warn_unused size_t utf32_length_from_latin1(size_t length) noexcept
1508
#endif // SIMDUTF_FEATURE_UTF32 && SIMDUTF_FEATURE_LATIN1
1509
1510
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
1511
simdutf_warn_unused size_t convert_utf8_to_latin1(
1512
0
    const char *buf, size_t len, char *latin1_output) noexcept {
1513
0
  return get_default_implementation()->convert_utf8_to_latin1(buf, len,
1514
0
                                                              latin1_output);
1515
0
}
1516
simdutf_warn_unused result convert_utf8_to_latin1_with_errors(
1517
0
    const char *buf, size_t len, char *latin1_output) noexcept {
1518
0
  return get_default_implementation()->convert_utf8_to_latin1_with_errors(
1519
0
      buf, len, latin1_output);
1520
0
}
1521
simdutf_warn_unused size_t convert_valid_utf8_to_latin1(
1522
0
    const char *buf, size_t len, char *latin1_output) noexcept {
1523
0
  return get_default_implementation()->convert_valid_utf8_to_latin1(
1524
0
      buf, len, latin1_output);
1525
0
}
1526
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
1527
1528
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1529
simdutf_warn_unused size_t convert_utf8_to_utf16le(
1530
0
    const char *input, size_t length, char16_t *utf16_output) noexcept {
1531
0
  return get_default_implementation()->convert_utf8_to_utf16le(input, length,
1532
0
                                                               utf16_output);
1533
0
}
1534
simdutf_warn_unused size_t convert_utf8_to_utf16be(
1535
0
    const char *input, size_t length, char16_t *utf16_output) noexcept {
1536
0
  return get_default_implementation()->convert_utf8_to_utf16be(input, length,
1537
0
                                                               utf16_output);
1538
0
}
1539
simdutf_warn_unused result convert_utf8_to_utf16_with_errors(
1540
0
    const char *input, size_t length, char16_t *utf16_output) noexcept {
1541
  #if SIMDUTF_IS_BIG_ENDIAN
1542
  return convert_utf8_to_utf16be_with_errors(input, length, utf16_output);
1543
  #else
1544
0
  return convert_utf8_to_utf16le_with_errors(input, length, utf16_output);
1545
0
  #endif
1546
0
}
1547
simdutf_warn_unused result convert_utf8_to_utf16le_with_errors(
1548
0
    const char *input, size_t length, char16_t *utf16_output) noexcept {
1549
0
  return get_default_implementation()->convert_utf8_to_utf16le_with_errors(
1550
0
      input, length, utf16_output);
1551
0
}
1552
simdutf_warn_unused result convert_utf8_to_utf16be_with_errors(
1553
0
    const char *input, size_t length, char16_t *utf16_output) noexcept {
1554
0
  return get_default_implementation()->convert_utf8_to_utf16be_with_errors(
1555
0
      input, length, utf16_output);
1556
0
}
1557
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1558
1559
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
1560
simdutf_warn_unused size_t convert_utf8_to_utf32(
1561
0
    const char *input, size_t length, char32_t *utf32_output) noexcept {
1562
0
  return get_default_implementation()->convert_utf8_to_utf32(input, length,
1563
0
                                                             utf32_output);
1564
0
}
1565
simdutf_warn_unused result convert_utf8_to_utf32_with_errors(
1566
0
    const char *input, size_t length, char32_t *utf32_output) noexcept {
1567
0
  return get_default_implementation()->convert_utf8_to_utf32_with_errors(
1568
0
      input, length, utf32_output);
1569
0
}
1570
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
1571
1572
#if SIMDUTF_FEATURE_UTF16
1573
simdutf_warn_unused bool validate_utf16(const char16_t *buf,
1574
0
                                        size_t len) noexcept {
1575
  #if SIMDUTF_IS_BIG_ENDIAN
1576
  return validate_utf16be(buf, len);
1577
  #else
1578
0
  return validate_utf16le(buf, len);
1579
0
  #endif
1580
0
}
1581
void to_well_formed_utf16be(const char16_t *input, size_t len,
1582
0
                            char16_t *output) noexcept {
1583
0
  return get_default_implementation()->to_well_formed_utf16be(input, len,
1584
0
                                                              output);
1585
0
}
1586
void to_well_formed_utf16le(const char16_t *input, size_t len,
1587
0
                            char16_t *output) noexcept {
1588
0
  return get_default_implementation()->to_well_formed_utf16le(input, len,
1589
0
                                                              output);
1590
0
}
1591
void to_well_formed_utf16(const char16_t *input, size_t len,
1592
0
                          char16_t *output) noexcept {
1593
  #if SIMDUTF_IS_BIG_ENDIAN
1594
  to_well_formed_utf16be(input, len, output);
1595
  #else
1596
0
  to_well_formed_utf16le(input, len, output);
1597
0
  #endif
1598
0
}
1599
#endif // SIMDUTF_FEATURE_UTF16
1600
1601
#if SIMDUTF_FEATURE_UTF16 || SIMDUTF_FEATURE_DETECT_ENCODING
1602
simdutf_warn_unused bool validate_utf16le(const char16_t *buf,
1603
0
                                          size_t len) noexcept {
1604
0
  return get_default_implementation()->validate_utf16le(buf, len);
1605
0
}
1606
#endif // SIMDUTF_FEATURE_UTF16 || SIMDUTF_FEATURE_DETECT_ENCODING
1607
1608
#if SIMDUTF_FEATURE_BASE64
1609
  #if SIMDUTF_ATOMIC_REF
1610
template <typename char_type>
1611
simdutf_warn_unused result atomic_base64_to_binary_safe_impl(
1612
    const char_type *input, size_t length, char *output, size_t &outlen,
1613
    base64_options options,
1614
    last_chunk_handling_options last_chunk_handling_options,
1615
0
    bool decode_up_to_bad_char) noexcept {
1616
0
    #if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
1617
  // We use a smaller buffer during fuzzing to more easily detect bugs.
1618
0
  constexpr size_t buffer_size = 128;
1619
    #else
1620
  // Arbitrary block sizes: 4KB for input.
1621
  constexpr size_t buffer_size = 4096;
1622
    #endif
1623
0
  std::array<char, buffer_size> temp_buffer;
1624
0
  const char_type *const input_init = input;
1625
0
  size_t actual_out = 0;
1626
0
  bool last_chunk = false;
1627
0
  const size_t length_init = length;
1628
0
  result r;
1629
0
  while (!last_chunk) {
1630
0
    last_chunk |= (temp_buffer.size() >= outlen - actual_out);
1631
0
    size_t temp_outlen = (std::min)(temp_buffer.size(), outlen - actual_out);
1632
0
    r = base64_to_binary_safe(input, length, temp_buffer.data(), temp_outlen,
1633
0
                              options, last_chunk_handling_options,
1634
0
                              decode_up_to_bad_char);
1635
    // We processed r.count characters of input.
1636
    // We wrote temp_outlen bytes to temp_buffer.
1637
    // If there is no ignorable characters,
1638
    // we should expect that values/4.0*3 == temp_outlen,
1639
    // except maybe at the tail end of the string.
1640
1641
    //
1642
    // We are assuming that when r.error == error_code::OUTPUT_BUFFER_TOO_SMALL,
1643
    // we truncate the results so that a number of base64 characters divisible
1644
    // by four is processed.
1645
    //
1646
1647
    //
1648
    // We wrote temp_outlen bytes to temp_buffer.
1649
    // We need to copy them to output.
1650
    // Copy with relaxed atomic operations to the output
1651
0
    simdutf_log_assert(temp_outlen <= outlen - actual_out,
1652
0
                       "Output buffer is too small");
1653
0
    simdutf_log_assert(temp_outlen <= temp_buffer.size(),
1654
0
                       "Output buffer is too small");
1655
1656
0
    simdutf::scalar::memcpy_atomic_write(output + actual_out,
1657
0
                                         temp_buffer.data(), temp_outlen);
1658
0
    actual_out += temp_outlen;
1659
0
    length -= r.count;
1660
0
    input += r.count;
1661
1662
0
    if (r.error != error_code::OUTPUT_BUFFER_TOO_SMALL) {
1663
0
      break;
1664
0
    }
1665
0
  }
1666
0
  if (size_t(input - input_init) != length_init) {
1667
    // We did not process all input characters. In such case, we
1668
    // should not end with an ignorable character. See
1669
    // https://tc39.es/proposal-arraybuffer-base64/spec/#sec-frombase64
1670
0
    while (input > input_init && base64_ignorable(*(input - 1), options)) {
1671
0
      --input;
1672
0
    }
1673
0
  }
1674
0
  outlen = actual_out;
1675
0
  return {r.error, size_t(input - input_init)};
1676
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)
1677
1678
simdutf_warn_unused result atomic_base64_to_binary_safe(
1679
    const char *input, size_t length, char *output, size_t &outlen,
1680
    base64_options options,
1681
    last_chunk_handling_options last_chunk_handling_options,
1682
0
    bool decode_up_to_bad_char) noexcept {
1683
0
  return atomic_base64_to_binary_safe_impl<char>(
1684
0
      input, length, output, outlen, options, last_chunk_handling_options,
1685
0
      decode_up_to_bad_char);
1686
0
}
1687
simdutf_warn_unused result atomic_base64_to_binary_safe(
1688
    const char16_t *input, size_t length, char *output, size_t &outlen,
1689
    base64_options options,
1690
    last_chunk_handling_options last_chunk_handling_options,
1691
0
    bool decode_up_to_bad_char) noexcept {
1692
0
  return atomic_base64_to_binary_safe_impl<char16_t>(
1693
0
      input, length, output, outlen, options, last_chunk_handling_options,
1694
0
      decode_up_to_bad_char);
1695
0
}
1696
  #endif // SIMDUTF_ATOMIC_REF
1697
1698
#endif // SIMDUTF_FEATURE_BASE64
1699
1700
#if SIMDUTF_FEATURE_UTF16
1701
simdutf_warn_unused bool validate_utf16be(const char16_t *buf,
1702
0
                                          size_t len) noexcept {
1703
0
  return get_default_implementation()->validate_utf16be(buf, len);
1704
0
}
1705
simdutf_warn_unused result validate_utf16_with_errors(const char16_t *buf,
1706
0
                                                      size_t len) noexcept {
1707
  #if SIMDUTF_IS_BIG_ENDIAN
1708
  return validate_utf16be_with_errors(buf, len);
1709
  #else
1710
0
  return validate_utf16le_with_errors(buf, len);
1711
0
  #endif
1712
0
}
1713
simdutf_warn_unused result validate_utf16le_with_errors(const char16_t *buf,
1714
0
                                                        size_t len) noexcept {
1715
0
  return get_default_implementation()->validate_utf16le_with_errors(buf, len);
1716
0
}
1717
simdutf_warn_unused result validate_utf16be_with_errors(const char16_t *buf,
1718
0
                                                        size_t len) noexcept {
1719
0
  return get_default_implementation()->validate_utf16be_with_errors(buf, len);
1720
0
}
1721
#endif // SIMDUTF_FEATURE_UTF16
1722
1723
#if SIMDUTF_FEATURE_UTF32
1724
simdutf_warn_unused bool validate_utf32(const char32_t *buf,
1725
0
                                        size_t len) noexcept {
1726
0
  return get_default_implementation()->validate_utf32(buf, len);
1727
0
}
1728
simdutf_warn_unused result validate_utf32_with_errors(const char32_t *buf,
1729
0
                                                      size_t len) noexcept {
1730
0
  return get_default_implementation()->validate_utf32_with_errors(buf, len);
1731
0
}
1732
#endif // SIMDUTF_FEATURE_UTF32
1733
1734
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1735
simdutf_warn_unused size_t convert_valid_utf8_to_utf16(
1736
0
    const char *input, size_t length, char16_t *utf16_buffer) noexcept {
1737
  #if SIMDUTF_IS_BIG_ENDIAN
1738
  return convert_valid_utf8_to_utf16be(input, length, utf16_buffer);
1739
  #else
1740
0
  return convert_valid_utf8_to_utf16le(input, length, utf16_buffer);
1741
0
  #endif
1742
0
}
1743
simdutf_warn_unused size_t convert_valid_utf8_to_utf16le(
1744
0
    const char *input, size_t length, char16_t *utf16_buffer) noexcept {
1745
0
  return get_default_implementation()->convert_valid_utf8_to_utf16le(
1746
0
      input, length, utf16_buffer);
1747
0
}
1748
simdutf_warn_unused size_t convert_valid_utf8_to_utf16be(
1749
0
    const char *input, size_t length, char16_t *utf16_buffer) noexcept {
1750
0
  return get_default_implementation()->convert_valid_utf8_to_utf16be(
1751
0
      input, length, utf16_buffer);
1752
0
}
1753
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1754
1755
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
1756
simdutf_warn_unused size_t convert_valid_utf8_to_utf32(
1757
0
    const char *input, size_t length, char32_t *utf32_buffer) noexcept {
1758
0
  return get_default_implementation()->convert_valid_utf8_to_utf32(
1759
0
      input, length, utf32_buffer);
1760
0
}
1761
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
1762
1763
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1764
simdutf_warn_unused size_t convert_utf16_to_utf8(const char16_t *buf,
1765
                                                 size_t len,
1766
0
                                                 char *utf8_buffer) noexcept {
1767
  #if SIMDUTF_IS_BIG_ENDIAN
1768
  return convert_utf16be_to_utf8(buf, len, utf8_buffer);
1769
  #else
1770
0
  return convert_utf16le_to_utf8(buf, len, utf8_buffer);
1771
0
  #endif
1772
0
}
1773
1774
simdutf_warn_unused size_t
1775
convert_utf16_to_utf8_safe(const char16_t *buf, size_t len, char *utf8_output,
1776
0
                           size_t utf8_len) noexcept {
1777
0
  const auto start{utf8_output};
1778
  // We might be able to go faster by first scanning the input buffer to
1779
  // determine how many char16_t characters we can read without exceeding the
1780
  // utf8_len. This is a one-pass algorithm that has the benefit of not
1781
  // requiring a first pass to determine the length.
1782
0
  while (true) {
1783
    // The worst case for convert_utf16_to_utf8 is when you go from 1 char16_t
1784
    // to 3 characters of UTF-8. So we can read at most utf8_len / 3 char16_t
1785
    // characters.
1786
0
    auto read_len = std::min(len, utf8_len / 3);
1787
0
    if (read_len <= 16) {
1788
0
      break;
1789
0
    }
1790
0
    if (read_len < len) {
1791
      //  If we have a high surrogate at the end of the buffer, we need to
1792
      //  either read one more char16_t or backtrack.
1793
0
      if (scalar::utf16::high_surrogate(buf[read_len - 1])) {
1794
0
        read_len--;
1795
0
      }
1796
0
    }
1797
0
    if (read_len == 0) {
1798
      // If we cannot read anything, we are done.
1799
0
      break;
1800
0
    }
1801
0
    const auto write_len =
1802
0
        simdutf::convert_utf16_to_utf8(buf, read_len, utf8_output);
1803
0
    if (write_len == 0) {
1804
      // There was an error in the conversion, we cannot continue.
1805
0
      return 0; // indicating failure
1806
0
    }
1807
1808
0
    utf8_output += write_len;
1809
0
    utf8_len -= write_len;
1810
0
    buf += read_len;
1811
0
    len -= read_len;
1812
0
  }
1813
  #if SIMDUTF_IS_BIG_ENDIAN
1814
  full_result r =
1815
      scalar::utf16_to_utf8::convert_with_errors<endianness::BIG, true>(
1816
          buf, len, utf8_output, utf8_len);
1817
  #else
1818
0
  full_result r =
1819
0
      scalar::utf16_to_utf8::convert_with_errors<endianness::LITTLE, true>(
1820
0
          buf, len, utf8_output, utf8_len);
1821
0
  #endif
1822
0
  if (r.error != error_code::SUCCESS &&
1823
0
      r.error != error_code::OUTPUT_BUFFER_TOO_SMALL) {
1824
    // If there was an error, we return 0 to indicate failure.
1825
0
    return 0; // indicating failure
1826
0
  }
1827
0
  return r.output_count + (utf8_output - start);
1828
0
}
1829
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1830
1831
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
1832
simdutf_warn_unused size_t convert_utf16_to_latin1(
1833
0
    const char16_t *buf, size_t len, char *latin1_buffer) noexcept {
1834
  #if SIMDUTF_IS_BIG_ENDIAN
1835
  return convert_utf16be_to_latin1(buf, len, latin1_buffer);
1836
  #else
1837
0
  return convert_utf16le_to_latin1(buf, len, latin1_buffer);
1838
0
  #endif
1839
0
}
1840
simdutf_warn_unused size_t convert_latin1_to_utf16(
1841
0
    const char *buf, size_t len, char16_t *utf16_output) noexcept {
1842
  #if SIMDUTF_IS_BIG_ENDIAN
1843
  return convert_latin1_to_utf16be(buf, len, utf16_output);
1844
  #else
1845
0
  return convert_latin1_to_utf16le(buf, len, utf16_output);
1846
0
  #endif
1847
0
}
1848
simdutf_warn_unused size_t convert_utf16be_to_latin1(
1849
0
    const char16_t *buf, size_t len, char *latin1_buffer) noexcept {
1850
0
  return get_default_implementation()->convert_utf16be_to_latin1(buf, len,
1851
0
                                                                 latin1_buffer);
1852
0
}
1853
simdutf_warn_unused size_t convert_utf16le_to_latin1(
1854
0
    const char16_t *buf, size_t len, char *latin1_buffer) noexcept {
1855
0
  return get_default_implementation()->convert_utf16le_to_latin1(buf, len,
1856
0
                                                                 latin1_buffer);
1857
0
}
1858
simdutf_warn_unused size_t convert_valid_utf16be_to_latin1(
1859
0
    const char16_t *buf, size_t len, char *latin1_buffer) noexcept {
1860
0
  return get_default_implementation()->convert_valid_utf16be_to_latin1(
1861
0
      buf, len, latin1_buffer);
1862
0
}
1863
simdutf_warn_unused size_t convert_valid_utf16le_to_latin1(
1864
0
    const char16_t *buf, size_t len, char *latin1_buffer) noexcept {
1865
0
  return get_default_implementation()->convert_valid_utf16le_to_latin1(
1866
0
      buf, len, latin1_buffer);
1867
0
}
1868
simdutf_warn_unused result convert_utf16le_to_latin1_with_errors(
1869
0
    const char16_t *buf, size_t len, char *latin1_buffer) noexcept {
1870
0
  return get_default_implementation()->convert_utf16le_to_latin1_with_errors(
1871
0
      buf, len, latin1_buffer);
1872
0
}
1873
simdutf_warn_unused result convert_utf16be_to_latin1_with_errors(
1874
0
    const char16_t *buf, size_t len, char *latin1_buffer) noexcept {
1875
0
  return get_default_implementation()->convert_utf16be_to_latin1_with_errors(
1876
0
      buf, len, latin1_buffer);
1877
0
}
1878
// moved to header file
1879
// simdutf_warn_unused size_t latin1_length_from_utf16(size_t length) noexcept
1880
// simdutf_warn_unused size_t utf16_length_from_latin1(size_t length) noexcept
1881
#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
1882
1883
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1884
simdutf_warn_unused size_t convert_utf16le_to_utf8(const char16_t *buf,
1885
                                                   size_t len,
1886
0
                                                   char *utf8_buffer) noexcept {
1887
0
  return get_default_implementation()->convert_utf16le_to_utf8(buf, len,
1888
0
                                                               utf8_buffer);
1889
0
}
1890
simdutf_warn_unused size_t convert_utf16be_to_utf8(const char16_t *buf,
1891
                                                   size_t len,
1892
0
                                                   char *utf8_buffer) noexcept {
1893
0
  return get_default_implementation()->convert_utf16be_to_utf8(buf, len,
1894
0
                                                               utf8_buffer);
1895
0
}
1896
simdutf_warn_unused result convert_utf16_to_utf8_with_errors(
1897
0
    const char16_t *buf, size_t len, char *utf8_buffer) noexcept {
1898
  #if SIMDUTF_IS_BIG_ENDIAN
1899
  return convert_utf16be_to_utf8_with_errors(buf, len, utf8_buffer);
1900
  #else
1901
0
  return convert_utf16le_to_utf8_with_errors(buf, len, utf8_buffer);
1902
0
  #endif
1903
0
}
1904
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1905
1906
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
1907
simdutf_warn_unused result convert_utf16_to_latin1_with_errors(
1908
0
    const char16_t *buf, size_t len, char *latin1_buffer) noexcept {
1909
  #if SIMDUTF_IS_BIG_ENDIAN
1910
  return convert_utf16be_to_latin1_with_errors(buf, len, latin1_buffer);
1911
  #else
1912
0
  return convert_utf16le_to_latin1_with_errors(buf, len, latin1_buffer);
1913
0
  #endif
1914
0
}
1915
#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
1916
1917
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1918
simdutf_warn_unused result convert_utf16le_to_utf8_with_errors(
1919
0
    const char16_t *buf, size_t len, char *utf8_buffer) noexcept {
1920
0
  return get_default_implementation()->convert_utf16le_to_utf8_with_errors(
1921
0
      buf, len, utf8_buffer);
1922
0
}
1923
simdutf_warn_unused result convert_utf16be_to_utf8_with_errors(
1924
0
    const char16_t *buf, size_t len, char *utf8_buffer) noexcept {
1925
0
  return get_default_implementation()->convert_utf16be_to_utf8_with_errors(
1926
0
      buf, len, utf8_buffer);
1927
0
}
1928
simdutf_warn_unused size_t convert_valid_utf16_to_utf8(
1929
0
    const char16_t *buf, size_t len, char *utf8_buffer) noexcept {
1930
  #if SIMDUTF_IS_BIG_ENDIAN
1931
  return convert_valid_utf16be_to_utf8(buf, len, utf8_buffer);
1932
  #else
1933
0
  return convert_valid_utf16le_to_utf8(buf, len, utf8_buffer);
1934
0
  #endif
1935
0
}
1936
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1937
1938
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
1939
simdutf_warn_unused size_t convert_valid_utf16_to_latin1(
1940
0
    const char16_t *buf, size_t len, char *latin1_buffer) noexcept {
1941
  #if SIMDUTF_IS_BIG_ENDIAN
1942
  return convert_valid_utf16be_to_latin1(buf, len, latin1_buffer);
1943
  #else
1944
0
  return convert_valid_utf16le_to_latin1(buf, len, latin1_buffer);
1945
0
  #endif
1946
0
}
1947
#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_LATIN1
1948
1949
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1950
simdutf_warn_unused size_t convert_valid_utf16le_to_utf8(
1951
0
    const char16_t *buf, size_t len, char *utf8_buffer) noexcept {
1952
0
  return get_default_implementation()->convert_valid_utf16le_to_utf8(
1953
0
      buf, len, utf8_buffer);
1954
0
}
1955
simdutf_warn_unused size_t convert_valid_utf16be_to_utf8(
1956
0
    const char16_t *buf, size_t len, char *utf8_buffer) noexcept {
1957
0
  return get_default_implementation()->convert_valid_utf16be_to_utf8(
1958
0
      buf, len, utf8_buffer);
1959
0
}
1960
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
1961
1962
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
1963
simdutf_warn_unused size_t convert_utf32_to_utf8(const char32_t *buf,
1964
                                                 size_t len,
1965
0
                                                 char *utf8_buffer) noexcept {
1966
0
  return get_default_implementation()->convert_utf32_to_utf8(buf, len,
1967
0
                                                             utf8_buffer);
1968
0
}
1969
simdutf_warn_unused result convert_utf32_to_utf8_with_errors(
1970
0
    const char32_t *buf, size_t len, char *utf8_buffer) noexcept {
1971
0
  return get_default_implementation()->convert_utf32_to_utf8_with_errors(
1972
0
      buf, len, utf8_buffer);
1973
0
}
1974
simdutf_warn_unused size_t convert_valid_utf32_to_utf8(
1975
0
    const char32_t *buf, size_t len, char *utf8_buffer) noexcept {
1976
0
  return get_default_implementation()->convert_valid_utf32_to_utf8(buf, len,
1977
0
                                                                   utf8_buffer);
1978
0
}
1979
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
1980
1981
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
1982
simdutf_warn_unused size_t convert_utf32_to_utf16(
1983
0
    const char32_t *buf, size_t len, char16_t *utf16_buffer) noexcept {
1984
  #if SIMDUTF_IS_BIG_ENDIAN
1985
  return convert_utf32_to_utf16be(buf, len, utf16_buffer);
1986
  #else
1987
0
  return convert_utf32_to_utf16le(buf, len, utf16_buffer);
1988
0
  #endif
1989
0
}
1990
#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
1991
1992
#if SIMDUTF_FEATURE_UTF32 && SIMDUTF_FEATURE_LATIN1
1993
simdutf_warn_unused size_t convert_utf32_to_latin1(
1994
0
    const char32_t *input, size_t length, char *latin1_output) noexcept {
1995
0
  return get_default_implementation()->convert_utf32_to_latin1(input, length,
1996
0
                                                               latin1_output);
1997
0
}
1998
simdutf_warn_unused result convert_utf32_to_latin1_with_errors(
1999
0
    const char32_t *input, size_t length, char *latin1_buffer) noexcept {
2000
0
  return get_default_implementation()->convert_utf32_to_latin1_with_errors(
2001
0
      input, length, latin1_buffer);
2002
0
}
2003
simdutf_warn_unused size_t convert_valid_utf32_to_latin1(
2004
0
    const char32_t *input, size_t length, char *latin1_buffer) noexcept {
2005
0
  return get_default_implementation()->convert_valid_utf32_to_latin1(
2006
0
      input, length, latin1_buffer);
2007
0
}
2008
#endif // SIMDUTF_FEATURE_UTF32 && SIMDUTF_FEATURE_LATIN1
2009
2010
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
2011
simdutf_warn_unused size_t convert_utf32_to_utf16le(
2012
0
    const char32_t *buf, size_t len, char16_t *utf16_buffer) noexcept {
2013
0
  return get_default_implementation()->convert_utf32_to_utf16le(buf, len,
2014
0
                                                                utf16_buffer);
2015
0
}
2016
simdutf_warn_unused size_t convert_utf32_to_utf16be(
2017
0
    const char32_t *buf, size_t len, char16_t *utf16_buffer) noexcept {
2018
0
  return get_default_implementation()->convert_utf32_to_utf16be(buf, len,
2019
0
                                                                utf16_buffer);
2020
0
}
2021
simdutf_warn_unused result convert_utf32_to_utf16_with_errors(
2022
0
    const char32_t *buf, size_t len, char16_t *utf16_buffer) noexcept {
2023
  #if SIMDUTF_IS_BIG_ENDIAN
2024
  return convert_utf32_to_utf16be_with_errors(buf, len, utf16_buffer);
2025
  #else
2026
0
  return convert_utf32_to_utf16le_with_errors(buf, len, utf16_buffer);
2027
0
  #endif
2028
0
}
2029
simdutf_warn_unused result convert_utf32_to_utf16le_with_errors(
2030
0
    const char32_t *buf, size_t len, char16_t *utf16_buffer) noexcept {
2031
0
  return get_default_implementation()->convert_utf32_to_utf16le_with_errors(
2032
0
      buf, len, utf16_buffer);
2033
0
}
2034
simdutf_warn_unused result convert_utf32_to_utf16be_with_errors(
2035
0
    const char32_t *buf, size_t len, char16_t *utf16_buffer) noexcept {
2036
0
  return get_default_implementation()->convert_utf32_to_utf16be_with_errors(
2037
0
      buf, len, utf16_buffer);
2038
0
}
2039
simdutf_warn_unused size_t convert_valid_utf32_to_utf16(
2040
0
    const char32_t *buf, size_t len, char16_t *utf16_buffer) noexcept {
2041
  #if SIMDUTF_IS_BIG_ENDIAN
2042
  return convert_valid_utf32_to_utf16be(buf, len, utf16_buffer);
2043
  #else
2044
0
  return convert_valid_utf32_to_utf16le(buf, len, utf16_buffer);
2045
0
  #endif
2046
0
}
2047
simdutf_warn_unused size_t convert_valid_utf32_to_utf16le(
2048
0
    const char32_t *buf, size_t len, char16_t *utf16_buffer) noexcept {
2049
0
  return get_default_implementation()->convert_valid_utf32_to_utf16le(
2050
0
      buf, len, utf16_buffer);
2051
0
}
2052
simdutf_warn_unused size_t convert_valid_utf32_to_utf16be(
2053
0
    const char32_t *buf, size_t len, char16_t *utf16_buffer) noexcept {
2054
0
  return get_default_implementation()->convert_valid_utf32_to_utf16be(
2055
0
      buf, len, utf16_buffer);
2056
0
}
2057
simdutf_warn_unused size_t convert_utf16_to_utf32(
2058
0
    const char16_t *buf, size_t len, char32_t *utf32_buffer) noexcept {
2059
  #if SIMDUTF_IS_BIG_ENDIAN
2060
  return convert_utf16be_to_utf32(buf, len, utf32_buffer);
2061
  #else
2062
0
  return convert_utf16le_to_utf32(buf, len, utf32_buffer);
2063
0
  #endif
2064
0
}
2065
simdutf_warn_unused size_t convert_utf16le_to_utf32(
2066
0
    const char16_t *buf, size_t len, char32_t *utf32_buffer) noexcept {
2067
0
  return get_default_implementation()->convert_utf16le_to_utf32(buf, len,
2068
0
                                                                utf32_buffer);
2069
0
}
2070
simdutf_warn_unused size_t convert_utf16be_to_utf32(
2071
0
    const char16_t *buf, size_t len, char32_t *utf32_buffer) noexcept {
2072
0
  return get_default_implementation()->convert_utf16be_to_utf32(buf, len,
2073
0
                                                                utf32_buffer);
2074
0
}
2075
simdutf_warn_unused result convert_utf16_to_utf32_with_errors(
2076
0
    const char16_t *buf, size_t len, char32_t *utf32_buffer) noexcept {
2077
  #if SIMDUTF_IS_BIG_ENDIAN
2078
  return convert_utf16be_to_utf32_with_errors(buf, len, utf32_buffer);
2079
  #else
2080
0
  return convert_utf16le_to_utf32_with_errors(buf, len, utf32_buffer);
2081
0
  #endif
2082
0
}
2083
simdutf_warn_unused result convert_utf16le_to_utf32_with_errors(
2084
0
    const char16_t *buf, size_t len, char32_t *utf32_buffer) noexcept {
2085
0
  return get_default_implementation()->convert_utf16le_to_utf32_with_errors(
2086
0
      buf, len, utf32_buffer);
2087
0
}
2088
simdutf_warn_unused result convert_utf16be_to_utf32_with_errors(
2089
0
    const char16_t *buf, size_t len, char32_t *utf32_buffer) noexcept {
2090
0
  return get_default_implementation()->convert_utf16be_to_utf32_with_errors(
2091
0
      buf, len, utf32_buffer);
2092
0
}
2093
simdutf_warn_unused size_t convert_valid_utf16_to_utf32(
2094
0
    const char16_t *buf, size_t len, char32_t *utf32_buffer) noexcept {
2095
  #if SIMDUTF_IS_BIG_ENDIAN
2096
  return convert_valid_utf16be_to_utf32(buf, len, utf32_buffer);
2097
  #else
2098
0
  return convert_valid_utf16le_to_utf32(buf, len, utf32_buffer);
2099
0
  #endif
2100
0
}
2101
simdutf_warn_unused size_t convert_valid_utf16le_to_utf32(
2102
0
    const char16_t *buf, size_t len, char32_t *utf32_buffer) noexcept {
2103
0
  return get_default_implementation()->convert_valid_utf16le_to_utf32(
2104
0
      buf, len, utf32_buffer);
2105
0
}
2106
simdutf_warn_unused size_t convert_valid_utf16be_to_utf32(
2107
0
    const char16_t *buf, size_t len, char32_t *utf32_buffer) noexcept {
2108
0
  return get_default_implementation()->convert_valid_utf16be_to_utf32(
2109
0
      buf, len, utf32_buffer);
2110
0
}
2111
#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
2112
2113
#if SIMDUTF_FEATURE_UTF16
2114
void change_endianness_utf16(const char16_t *input, size_t length,
2115
0
                             char16_t *output) noexcept {
2116
0
  get_default_implementation()->change_endianness_utf16(input, length, output);
2117
0
}
2118
simdutf_warn_unused size_t count_utf16(const char16_t *input,
2119
0
                                       size_t length) noexcept {
2120
  #if SIMDUTF_IS_BIG_ENDIAN
2121
  return count_utf16be(input, length);
2122
  #else
2123
0
  return count_utf16le(input, length);
2124
0
  #endif
2125
0
}
2126
simdutf_warn_unused size_t count_utf16le(const char16_t *input,
2127
0
                                         size_t length) noexcept {
2128
0
  return get_default_implementation()->count_utf16le(input, length);
2129
0
}
2130
simdutf_warn_unused size_t count_utf16be(const char16_t *input,
2131
0
                                         size_t length) noexcept {
2132
0
  return get_default_implementation()->count_utf16be(input, length);
2133
0
}
2134
#endif // SIMDUTF_FEATURE_UTF16
2135
2136
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
2137
simdutf_warn_unused size_t count_utf8(const char *input,
2138
0
                                      size_t length) noexcept {
2139
0
  return get_default_implementation()->count_utf8(input, length);
2140
0
}
2141
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
2142
2143
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
2144
simdutf_warn_unused size_t latin1_length_from_utf8(const char *buf,
2145
0
                                                   size_t len) noexcept {
2146
0
  return get_default_implementation()->latin1_length_from_utf8(buf, len);
2147
0
}
2148
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
2149
2150
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
2151
simdutf_warn_unused size_t utf8_length_from_latin1(const char *buf,
2152
0
                                                   size_t len) noexcept {
2153
0
  return get_default_implementation()->utf8_length_from_latin1(buf, len);
2154
0
}
2155
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
2156
2157
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
2158
simdutf_warn_unused size_t utf8_length_from_utf16(const char16_t *input,
2159
0
                                                  size_t length) noexcept {
2160
  #if SIMDUTF_IS_BIG_ENDIAN
2161
  return utf8_length_from_utf16be(input, length);
2162
  #else
2163
0
  return utf8_length_from_utf16le(input, length);
2164
0
  #endif
2165
0
}
2166
simdutf_warn_unused result utf8_length_from_utf16_with_replacement(
2167
0
    const char16_t *input, size_t length) noexcept {
2168
  #if SIMDUTF_IS_BIG_ENDIAN
2169
  return utf8_length_from_utf16be_with_replacement(input, length);
2170
  #else
2171
0
  return utf8_length_from_utf16le_with_replacement(input, length);
2172
0
  #endif
2173
0
}
2174
simdutf_warn_unused size_t utf8_length_from_utf16le(const char16_t *input,
2175
0
                                                    size_t length) noexcept {
2176
0
  return get_default_implementation()->utf8_length_from_utf16le(input, length);
2177
0
}
2178
simdutf_warn_unused size_t utf8_length_from_utf16be(const char16_t *input,
2179
0
                                                    size_t length) noexcept {
2180
0
  return get_default_implementation()->utf8_length_from_utf16be(input, length);
2181
0
}
2182
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
2183
2184
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
2185
simdutf_warn_unused size_t utf32_length_from_utf16(const char16_t *input,
2186
0
                                                   size_t length) noexcept {
2187
  #if SIMDUTF_IS_BIG_ENDIAN
2188
  return utf32_length_from_utf16be(input, length);
2189
  #else
2190
0
  return utf32_length_from_utf16le(input, length);
2191
0
  #endif
2192
0
}
2193
simdutf_warn_unused size_t utf32_length_from_utf16le(const char16_t *input,
2194
0
                                                     size_t length) noexcept {
2195
0
  return get_default_implementation()->utf32_length_from_utf16le(input, length);
2196
0
}
2197
simdutf_warn_unused size_t utf32_length_from_utf16be(const char16_t *input,
2198
0
                                                     size_t length) noexcept {
2199
0
  return get_default_implementation()->utf32_length_from_utf16be(input, length);
2200
0
}
2201
#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
2202
2203
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
2204
simdutf_warn_unused size_t utf16_length_from_utf8(const char *input,
2205
0
                                                  size_t length) noexcept {
2206
0
  return get_default_implementation()->utf16_length_from_utf8(input, length);
2207
0
}
2208
simdutf_warn_unused result utf8_length_from_utf16le_with_replacement(
2209
0
    const char16_t *input, size_t length) noexcept {
2210
0
  return get_default_implementation()
2211
0
      ->utf8_length_from_utf16le_with_replacement(input, length);
2212
0
}
2213
2214
simdutf_warn_unused result utf8_length_from_utf16be_with_replacement(
2215
0
    const char16_t *input, size_t length) noexcept {
2216
0
  return get_default_implementation()
2217
0
      ->utf8_length_from_utf16be_with_replacement(input, length);
2218
0
}
2219
2220
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF16
2221
2222
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
2223
simdutf_warn_unused size_t utf8_length_from_utf32(const char32_t *input,
2224
0
                                                  size_t length) noexcept {
2225
0
  return get_default_implementation()->utf8_length_from_utf32(input, length);
2226
0
}
2227
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
2228
2229
#if SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
2230
simdutf_warn_unused size_t utf16_length_from_utf32(const char32_t *input,
2231
0
                                                   size_t length) noexcept {
2232
0
  return get_default_implementation()->utf16_length_from_utf32(input, length);
2233
0
}
2234
#endif // SIMDUTF_FEATURE_UTF16 && SIMDUTF_FEATURE_UTF32
2235
2236
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
2237
simdutf_warn_unused size_t utf32_length_from_utf8(const char *input,
2238
0
                                                  size_t length) noexcept {
2239
0
  return get_default_implementation()->utf32_length_from_utf8(input, length);
2240
0
}
2241
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_UTF32
2242
2243
#if SIMDUTF_FEATURE_BASE64
2244
2245
// this has been moved to implementation.h
2246
// simdutf_warn_unused size_t
2247
// base64_length_from_binary(size_t length, base64_options option) noexcept;
2248
2249
// this has been moved to implementation.h
2250
// simdutf_warn_unused size_t base64_length_from_binary_with_lines(
2251
//     size_t length, base64_options options, size_t line_length) noexcept;
2252
// }
2253
2254
simdutf_warn_unused const char *detail::find(const char *start, const char *end,
2255
0
                                             char character) noexcept {
2256
0
  return get_default_implementation()->find(start, end, character);
2257
0
}
2258
simdutf_warn_unused const char16_t *detail::find(const char16_t *start,
2259
                                                 const char16_t *end,
2260
0
                                                 char16_t character) noexcept {
2261
0
  return get_default_implementation()->find(start, end, character);
2262
0
}
2263
2264
simdutf_warn_unused size_t
2265
0
maximal_binary_length_from_base64(const char *input, size_t length) noexcept {
2266
0
  return get_default_implementation()->maximal_binary_length_from_base64(
2267
0
      input, length);
2268
0
}
2269
2270
simdutf_warn_unused result base64_to_binary(
2271
    const char *input, size_t length, char *output, base64_options options,
2272
0
    last_chunk_handling_options last_chunk_handling_options) noexcept {
2273
0
  return get_default_implementation()->base64_to_binary(
2274
0
      input, length, output, options, last_chunk_handling_options);
2275
0
}
2276
2277
simdutf_warn_unused size_t maximal_binary_length_from_base64(
2278
0
    const char16_t *input, size_t length) noexcept {
2279
0
  return get_default_implementation()->maximal_binary_length_from_base64(
2280
0
      input, length);
2281
0
}
2282
2283
simdutf_warn_unused result base64_to_binary(
2284
    const char16_t *input, size_t length, char *output, base64_options options,
2285
0
    last_chunk_handling_options last_chunk_handling_options) noexcept {
2286
0
  return get_default_implementation()->base64_to_binary(
2287
0
      input, length, output, options, last_chunk_handling_options);
2288
0
}
2289
2290
// moved to implementation.h
2291
// simdutf_warn_unused bool base64_ignorable(char input,
2292
//                                           base64_options options) noexcept
2293
// simdutf_warn_unused bool base64_ignorable(char16_t input,
2294
//                                           base64_options options) noexcept
2295
// simdutf_warn_unused bool base64_valid(char input,
2296
//                                       base64_options options) noexcept
2297
// simdutf_warn_unused bool base64_valid(char16_t input,
2298
//                                       base64_options options) noexcept
2299
// simdutf_warn_unused bool
2300
// base64_valid_or_padding(char input, base64_options options) noexcept
2301
// simdutf_warn_unused bool
2302
// base64_valid_or_padding(char16_t input, base64_options options) noexcept
2303
2304
// base64_to_binary_safe_impl is moved to
2305
// include/simdutf/base64_implementation.h
2306
2307
  #if SIMDUTF_ATOMIC_REF
2308
size_t atomic_binary_to_base64(const char *input, size_t length, char *output,
2309
0
                               base64_options options) noexcept {
2310
0
  size_t retval = 0;
2311
0
    #if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
2312
  // We use a smaller buffer during fuzzing to more easily detect bugs.
2313
0
  constexpr size_t input_block_size = 128 * 3;
2314
    #else
2315
  // Arbitrary block sizes: 3KB for input which produces 4KB in output.
2316
  constexpr size_t input_block_size = 1024 * 3;
2317
    #endif
2318
0
  std::array<char, input_block_size> inbuf;
2319
0
  for (size_t i = 0; i < length; i += input_block_size) {
2320
0
    const size_t current_block_size = std::min(input_block_size, length - i);
2321
0
    simdutf::scalar::memcpy_atomic_read(inbuf.data(), input + i,
2322
0
                                        current_block_size);
2323
0
    const size_t written = binary_to_base64(inbuf.data(), current_block_size,
2324
0
                                            output + retval, options);
2325
0
    retval += written;
2326
0
  }
2327
0
  return retval;
2328
0
}
2329
  #endif // SIMDUTF_ATOMIC_REF
2330
2331
#endif // SIMDUTF_FEATURE_BASE64
2332
2333
#if SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
2334
simdutf_warn_unused size_t convert_latin1_to_utf8_safe(
2335
0
    const char *buf, size_t len, char *utf8_output, size_t utf8_len) noexcept {
2336
0
  const auto start{utf8_output};
2337
2338
0
  while (true) {
2339
    // convert_latin1_to_utf8 will never write more than input length * 2
2340
0
    auto read_len = std::min(len, utf8_len >> 1);
2341
0
    if (read_len <= 16) {
2342
0
      break;
2343
0
    }
2344
2345
0
    const auto write_len =
2346
0
        simdutf::convert_latin1_to_utf8(buf, read_len, utf8_output);
2347
2348
0
    utf8_output += write_len;
2349
0
    utf8_len -= write_len;
2350
0
    buf += read_len;
2351
0
    len -= read_len;
2352
0
  }
2353
2354
0
  utf8_output +=
2355
0
      scalar::latin1_to_utf8::convert_safe(buf, len, utf8_output, utf8_len);
2356
2357
0
  return utf8_output - start;
2358
0
}
2359
#endif // SIMDUTF_FEATURE_UTF8 && SIMDUTF_FEATURE_LATIN1
2360
2361
#if SIMDUTF_FEATURE_BASE64
2362
simdutf_warn_unused result
2363
base64_to_binary_safe(const char *input, size_t length, char *output,
2364
                      size_t &outlen, base64_options options,
2365
                      last_chunk_handling_options last_chunk_handling_options,
2366
370
                      bool decode_up_to_bad_char) noexcept {
2367
370
  return base64_to_binary_safe_impl<char>(input, length, output, outlen,
2368
370
                                          options, last_chunk_handling_options,
2369
370
                                          decode_up_to_bad_char);
2370
370
}
2371
simdutf_warn_unused result
2372
base64_to_binary_safe(const char16_t *input, size_t length, char *output,
2373
                      size_t &outlen, base64_options options,
2374
                      last_chunk_handling_options last_chunk_handling_options,
2375
505
                      bool decode_up_to_bad_char) noexcept {
2376
505
  return base64_to_binary_safe_impl<char16_t>(
2377
505
      input, length, output, outlen, options, last_chunk_handling_options,
2378
505
      decode_up_to_bad_char);
2379
505
}
2380
2381
size_t binary_to_base64(const char *input, size_t length, char *output,
2382
0
                        base64_options options) noexcept {
2383
0
  return get_default_implementation()->binary_to_base64(input, length, output,
2384
0
                                                        options);
2385
0
}
2386
2387
size_t binary_to_base64_with_lines(const char *input, size_t length,
2388
                                   char *output, size_t line_length,
2389
0
                                   base64_options options) noexcept {
2390
0
  return get_default_implementation()->binary_to_base64_with_lines(
2391
0
      input, length, output, line_length, options);
2392
0
}
2393
#endif // SIMDUTF_FEATURE_BASE64
2394
2395
#if SIMDUTF_FEATURE_DETECT_ENCODING
2396
simdutf_warn_unused simdutf::encoding_type
2397
0
autodetect_encoding(const char *buf, size_t length) noexcept {
2398
0
  return get_default_implementation()->autodetect_encoding(buf, length);
2399
0
}
2400
2401
simdutf_warn_unused int detect_encodings(const char *buf,
2402
0
                                         size_t length) noexcept {
2403
0
  return get_default_implementation()->detect_encodings(buf, length);
2404
0
}
2405
#endif // SIMDUTF_FEATURE_DETECT_ENCODING
2406
2407
0
const implementation *builtin_implementation() {
2408
0
  static const implementation *builtin_impl =
2409
0
      get_available_implementations()[SIMDUTF_STRINGIFY(
2410
0
          SIMDUTF_BUILTIN_IMPLEMENTATION)];
2411
0
  return builtin_impl;
2412
0
}
2413
2414
#if SIMDUTF_FEATURE_UTF8
2415
0
simdutf_warn_unused size_t trim_partial_utf8(const char *input, size_t length) {
2416
0
  return scalar::utf8::trim_partial_utf8(input, length);
2417
0
}
2418
#endif // SIMDUTF_FEATURE_UTF8
2419
2420
#if SIMDUTF_FEATURE_UTF16
2421
simdutf_warn_unused size_t trim_partial_utf16be(const char16_t *input,
2422
0
                                                size_t length) {
2423
0
  return scalar::utf16::trim_partial_utf16<BIG>(input, length);
2424
0
}
2425
2426
simdutf_warn_unused size_t trim_partial_utf16le(const char16_t *input,
2427
0
                                                size_t length) {
2428
0
  return scalar::utf16::trim_partial_utf16<LITTLE>(input, length);
2429
0
}
2430
2431
simdutf_warn_unused size_t trim_partial_utf16(const char16_t *input,
2432
0
                                              size_t length) {
2433
  #if SIMDUTF_IS_BIG_ENDIAN
2434
  return trim_partial_utf16be(input, length);
2435
  #else
2436
0
  return trim_partial_utf16le(input, length);
2437
0
  #endif
2438
0
}
2439
#endif // SIMDUTF_FEATURE_UTF16
2440
2441
} // namespace simdutf