simdutf 9.3.3
Unicode at GB/s.
Loading...
Searching...
No Matches
simdutf_c.h
1/***
2 * simdutf_c.h.h - C API for simdutf
3 * This is currently experimental.
4 * We are committed to keeping the C API, but there might be mistakes in our
5 * implementation. Please report any issues you find.
6 */
7
8#ifndef SIMDUTF_C_H
9#define SIMDUTF_C_H
10
11#include <stddef.h>
12#include <stdbool.h>
13#include <stdint.h>
14
15#ifdef __has_include
16 #if __has_include(<uchar.h>)
17 #include <uchar.h>
18 #else // __has_include(<uchar.h>)
19 #define char16_t uint16_t
20 #define char32_t uint32_t
21 #endif // __has_include(<uchar.h>)
22#else // __has_include(<uchar.h>)
23 #define char16_t uint16_t
24 #define char32_t uint32_t
25#endif // __has_include
26
27#ifdef __cplusplus
28extern "C" {
29#endif
30
31/* C-friendly subset of simdutf errors */
32typedef enum simdutf_error_code {
33 SIMDUTF_ERROR_SUCCESS = 0,
34 SIMDUTF_ERROR_HEADER_BITS,
35 SIMDUTF_ERROR_TOO_SHORT,
36 SIMDUTF_ERROR_TOO_LONG,
37 SIMDUTF_ERROR_OVERLONG,
38 SIMDUTF_ERROR_TOO_LARGE,
39 SIMDUTF_ERROR_SURROGATE,
40 SIMDUTF_ERROR_INVALID_BASE64_CHARACTER,
41 SIMDUTF_ERROR_BASE64_INPUT_REMAINDER,
42 SIMDUTF_ERROR_BASE64_EXTRA_BITS,
43 SIMDUTF_ERROR_OUTPUT_BUFFER_TOO_SMALL,
44 SIMDUTF_ERROR_OTHER
45} simdutf_error_code;
46
47typedef struct simdutf_result {
48 simdutf_error_code error;
49 size_t count; /* position of error or number of code units validated */
51
52typedef struct simdutf_full_result {
53 simdutf_error_code error;
54 size_t input_count; /* number of input units consumed */
55 size_t output_count; /* number of output bytes written */
57
58typedef struct simdutf_utf8_result {
59 simdutf_error_code error;
60 size_t input_count; /* number of bytes in the valid prefix */
61 size_t continuation_count; /* continuation bytes within the valid prefix */
62 size_t four_byte_count; /* four-byte sequences within the valid prefix */
64
65/* Byte indexes of the first ill-formed UTF-8 subsequences, for conversion to
66 UTF-16 with U+FFFD. error_offset[i] is an index into the same input passed
67 to simdutf_utf16_length_from_utf8_with_replacement. count is always the full
68 number of char16_t. more_errors is true when the input has ill-formed
69 subsequences past the stored ones. */
70#define SIMDUTF_UTF8_TO_UTF16_MAX_ERRORS 16
72 simdutf_error_code error;
73 size_t count;
74 size_t error_count;
75 bool more_errors;
76 size_t error_offset[SIMDUTF_UTF8_TO_UTF16_MAX_ERRORS];
78
79typedef enum simdutf_encoding_type {
80 SIMDUTF_ENCODING_UNSPECIFIED = 0,
81 SIMDUTF_ENCODING_UTF8 = 1,
82 SIMDUTF_ENCODING_UTF16_LE = 2,
83 SIMDUTF_ENCODING_UTF16_BE = 4,
84 SIMDUTF_ENCODING_UTF32_LE = 8,
85 SIMDUTF_ENCODING_UTF32_BE = 16
86} simdutf_encoding_type;
87
88/* Validate UTF-8: returns true iff input is valid UTF-8 */
89bool simdutf_validate_utf8(const char *buf, size_t len);
90
91/* Validate UTF-8 with detailed result */
92simdutf_result simdutf_validate_utf8_with_errors(const char *buf, size_t len);
93
94/* Validate UTF-8, stopping on error, while counting the continuation bytes and
95 the four-byte sequences of the valid prefix. These two counts give both the
96 number of code points (input_count - continuation_count) and the number of
97 UTF-16 code units (input_count - continuation_count + four_byte_count) of
98 the valid prefix, without a second pass over the input. */
99simdutf_utf8_result simdutf_validate_utf8_with_counts(const char *buf,
100 size_t len);
101
102/* Number of UTF-16 code units the valid prefix described by r transcodes to,
103 i.e. r.input_count - r.continuation_count + r.four_byte_count. */
104size_t simdutf_utf8_result_utf16_length(simdutf_utf8_result r);
105
106/* Number of code points in the valid prefix described by r, which is also the
107 number of UTF-32 code units, i.e. r.input_count - r.continuation_count. */
108size_t simdutf_utf8_result_utf32_length(simdutf_utf8_result r);
109
110/* Encoding detection */
111simdutf_encoding_type simdutf_autodetect_encoding(const char *input,
112 size_t length);
113int simdutf_detect_encodings(const char *input, size_t length);
114
115/* ASCII validation */
116bool simdutf_validate_ascii(const char *buf, size_t len);
117simdutf_result simdutf_validate_ascii_with_errors(const char *buf, size_t len);
118
119/* UTF-16 ASCII checks */
120bool simdutf_validate_utf16_as_ascii(const char16_t *buf, size_t len);
121bool simdutf_validate_utf16be_as_ascii(const char16_t *buf, size_t len);
122bool simdutf_validate_utf16le_as_ascii(const char16_t *buf, size_t len);
123
124/* UTF-16/UTF-8/UTF-32 validation (native/endian-specific) */
125bool simdutf_validate_utf16(const char16_t *buf, size_t len);
126bool simdutf_validate_utf16le(const char16_t *buf, size_t len);
127bool simdutf_validate_utf16be(const char16_t *buf, size_t len);
128simdutf_result simdutf_validate_utf16_with_errors(const char16_t *buf,
129 size_t len);
130simdutf_result simdutf_validate_utf16le_with_errors(const char16_t *buf,
131 size_t len);
132simdutf_result simdutf_validate_utf16be_with_errors(const char16_t *buf,
133 size_t len);
134
135bool simdutf_validate_utf32(const char32_t *buf, size_t len);
136simdutf_result simdutf_validate_utf32_with_errors(const char32_t *buf,
137 size_t len);
138
139/* to_well_formed UTF-16 helpers */
140void simdutf_to_well_formed_utf16le(const char16_t *input, size_t len,
141 char16_t *output);
142void simdutf_to_well_formed_utf16be(const char16_t *input, size_t len,
143 char16_t *output);
144void simdutf_to_well_formed_utf16(const char16_t *input, size_t len,
145 char16_t *output);
146
147/* Counting */
148size_t simdutf_count_utf16(const char16_t *input, size_t length);
149size_t simdutf_count_utf16le(const char16_t *input, size_t length);
150size_t simdutf_count_utf16be(const char16_t *input, size_t length);
151size_t simdutf_count_utf8(const char *input, size_t length);
152
153/* Length estimators */
154size_t simdutf_utf8_length_from_latin1(const char *input, size_t length);
155size_t simdutf_latin1_length_from_utf8(const char *input, size_t length);
156size_t simdutf_latin1_length_from_utf16(size_t length);
157size_t simdutf_latin1_length_from_utf32(size_t length);
158size_t simdutf_utf16_length_from_utf8(const char *input, size_t length);
159/* UTF-16 length of a possibly ill-formed UTF-8 string, plus the byte index of
160 up to SIMDUTF_UTF8_TO_UTF16_MAX_ERRORS ill-formed subsequences. count is
161 always the number of char16_t, at most `length`. error is SIMDUTF_SUCCESS
162 when the input is valid, otherwise the first UTF-8 error. Endian-independent.
163 Pass the result to simdutf_convert_utf8_to_utf16_with_replacement_with_result
164 (or the le/be variant) on the same bytes. */
166simdutf_utf16_length_from_utf8_with_replacement(const char *input,
167 size_t length);
168size_t simdutf_utf32_length_from_utf8(const char *input, size_t length);
169size_t simdutf_utf8_length_from_utf16(const char16_t *input, size_t length);
170size_t simdutf_utf8_length_from_utf32(const char32_t *input, size_t length);
172simdutf_utf8_length_from_utf16_with_replacement(const char16_t *input,
173 size_t length);
174size_t simdutf_utf8_length_from_utf16le(const char16_t *input, size_t length);
175size_t simdutf_utf8_length_from_utf16be(const char16_t *input, size_t length);
177simdutf_utf8_length_from_utf16le_with_replacement(const char16_t *input,
178 size_t length);
180simdutf_utf8_length_from_utf16be_with_replacement(const char16_t *input,
181 size_t length);
182
183/* Conversions: latin1 <-> utf8, utf8 <-> utf16/utf32, utf16 <-> utf8, etc. */
184size_t simdutf_convert_latin1_to_utf8(const char *input, size_t length,
185 char *output);
186size_t simdutf_convert_latin1_to_utf8_safe(const char *input, size_t length,
187 char *output, size_t utf8_len);
188simdutf_full_result simdutf_convert_latin1_to_utf8_safe_with_details(
189 const char *input, size_t length, char *output, size_t utf8_len);
190size_t simdutf_convert_latin1_to_utf16le(const char *input, size_t length,
191 char16_t *output);
192size_t simdutf_convert_latin1_to_utf16be(const char *input, size_t length,
193 char16_t *output);
194size_t simdutf_convert_latin1_to_utf16(const char *input, size_t length,
195 char16_t *output);
196size_t simdutf_convert_latin1_to_utf32(const char *input, size_t length,
197 char32_t *output);
198
199size_t simdutf_convert_utf8_to_latin1(const char *input, size_t length,
200 char *output);
201size_t simdutf_convert_utf8_to_utf16le(const char *input, size_t length,
202 char16_t *output);
203size_t simdutf_convert_utf8_to_utf16be(const char *input, size_t length,
204 char16_t *output);
205size_t simdutf_convert_utf8_to_utf16(const char *input, size_t length,
206 char16_t *output);
207/* Convert possibly ill-formed UTF-8 to UTF-16, replacing each maximal
208 ill-formed subsequence with U+FFFD. These always succeed and return the
209 number of char16_t written. Size the output with
210 simdutf_utf16_length_from_utf8_with_replacement. `length` char16_t is
211 always enough. */
212size_t simdutf_convert_utf8_to_utf16_with_replacement(const char *input,
213 size_t length,
214 char16_t *output);
215size_t simdutf_convert_utf8_to_utf16le_with_replacement(const char *input,
216 size_t length,
217 char16_t *output);
218size_t simdutf_convert_utf8_to_utf16be_with_replacement(const char *input,
219 size_t length,
220 char16_t *output);
221/* Same conversions, using locations from
222 simdutf_utf16_length_from_utf8_with_replacement on this input. locations
223 must not be null. */
224size_t simdutf_convert_utf8_to_utf16_with_replacement_with_result(
225 const char *input, size_t length, char16_t *output,
226 const simdutf_utf8_to_utf16_result *locations);
227size_t simdutf_convert_utf8_to_utf16le_with_replacement_with_result(
228 const char *input, size_t length, char16_t *output,
229 const simdutf_utf8_to_utf16_result *locations);
230size_t simdutf_convert_utf8_to_utf16be_with_replacement_with_result(
231 const char *input, size_t length, char16_t *output,
232 const simdutf_utf8_to_utf16_result *locations);
233
234size_t simdutf_convert_utf8_to_utf32(const char *input, size_t length,
235 char32_t *output);
236simdutf_result simdutf_convert_utf8_to_latin1_with_errors(const char *input,
237 size_t length,
238 char *output);
239simdutf_result simdutf_convert_utf8_to_utf16_with_errors(const char *input,
240 size_t length,
241 char16_t *output);
242simdutf_result simdutf_convert_utf8_to_utf16le_with_errors(const char *input,
243 size_t length,
244 char16_t *output);
245simdutf_result simdutf_convert_utf8_to_utf16be_with_errors(const char *input,
246 size_t length,
247 char16_t *output);
248simdutf_result simdutf_convert_utf8_to_utf32_with_errors(const char *input,
249 size_t length,
250 char32_t *output);
251
252/* Conversions assuming valid input */
253size_t simdutf_convert_valid_utf8_to_latin1(const char *input, size_t length,
254 char *output);
255size_t simdutf_convert_valid_utf8_to_utf16le(const char *input, size_t length,
256 char16_t *output);
257size_t simdutf_convert_valid_utf8_to_utf16be(const char *input, size_t length,
258 char16_t *output);
259size_t simdutf_convert_valid_utf8_to_utf32(const char *input, size_t length,
260 char32_t *output);
261
262/* UTF-16 -> UTF-8 and related conversions */
263size_t simdutf_convert_utf16_to_utf8(const char16_t *input, size_t length,
264 char *output);
265size_t simdutf_convert_utf16le_to_utf8(const char16_t *input, size_t length,
266 char *output);
267size_t simdutf_convert_utf16be_to_utf8(const char16_t *input, size_t length,
268 char *output);
269size_t simdutf_convert_utf16_to_utf8_safe(const char16_t *input, size_t length,
270 char *output, size_t utf8_len);
271simdutf_full_result simdutf_convert_utf16_to_utf8_safe_with_details(
272 const char16_t *input, size_t length, char *output, size_t utf8_len);
273size_t simdutf_convert_utf16_to_latin1(const char16_t *input, size_t length,
274 char *output);
275size_t simdutf_convert_utf16le_to_latin1(const char16_t *input, size_t length,
276 char *output);
277size_t simdutf_convert_utf16be_to_latin1(const char16_t *input, size_t length,
278 char *output);
280simdutf_convert_utf16_to_latin1_with_errors(const char16_t *input,
281 size_t length, char *output);
283simdutf_convert_utf16le_to_latin1_with_errors(const char16_t *input,
284 size_t length, char *output);
286simdutf_convert_utf16be_to_latin1_with_errors(const char16_t *input,
287 size_t length, char *output);
288
289simdutf_result simdutf_convert_utf16_to_utf8_with_errors(const char16_t *input,
290 size_t length,
291 char *output);
293simdutf_convert_utf16le_to_utf8_with_errors(const char16_t *input,
294 size_t length, char *output);
296simdutf_convert_utf16be_to_utf8_with_errors(const char16_t *input,
297 size_t length, char *output);
298
299/* Convert possibly broken UTF-16 to UTF-8, replacing each unpaired surrogate
300 with U+FFFD (EF BF BD). These always succeed and return the number of bytes
301 written. Size the output buffer with the matching
302 simdutf_utf8_length_from_utf16*_with_replacement function. */
303size_t simdutf_convert_utf16_to_utf8_with_replacement(const char16_t *input,
304 size_t length,
305 char *output);
306simdutf_full_result simdutf_convert_utf16_to_utf8_with_replacement_safe(
307 const char16_t *input, size_t length, char *output, size_t utf8_len);
308size_t simdutf_convert_utf16le_to_utf8_with_replacement(const char16_t *input,
309 size_t length,
310 char *output);
311size_t simdutf_convert_utf16be_to_utf8_with_replacement(const char16_t *input,
312 size_t length,
313 char *output);
314
315size_t simdutf_convert_valid_utf16_to_utf8(const char16_t *input, size_t length,
316 char *output);
317size_t simdutf_convert_valid_utf16_to_latin1(const char16_t *input,
318 size_t length, char *output);
319size_t simdutf_convert_valid_utf16le_to_latin1(const char16_t *input,
320 size_t length, char *output);
321size_t simdutf_convert_valid_utf16be_to_latin1(const char16_t *input,
322 size_t length, char *output);
323
324size_t simdutf_convert_valid_utf16le_to_utf8(const char16_t *input,
325 size_t length, char *output);
326size_t simdutf_convert_valid_utf16be_to_utf8(const char16_t *input,
327 size_t length, char *output);
328
329/* UTF-16 <-> UTF-32 conversions */
330size_t simdutf_convert_utf16_to_utf32(const char16_t *input, size_t length,
331 char32_t *output);
332size_t simdutf_convert_utf16le_to_utf32(const char16_t *input, size_t length,
333 char32_t *output);
334size_t simdutf_convert_utf16be_to_utf32(const char16_t *input, size_t length,
335 char32_t *output);
336simdutf_result simdutf_convert_utf16_to_utf32_with_errors(const char16_t *input,
337 size_t length,
338 char32_t *output);
340simdutf_convert_utf16le_to_utf32_with_errors(const char16_t *input,
341 size_t length, char32_t *output);
343simdutf_convert_utf16be_to_utf32_with_errors(const char16_t *input,
344 size_t length, char32_t *output);
345
346/* Valid UTF-16 conversions */
347size_t simdutf_convert_valid_utf16_to_utf32(const char16_t *input,
348 size_t length, char32_t *output);
349size_t simdutf_convert_valid_utf16le_to_utf32(const char16_t *input,
350 size_t length, char32_t *output);
351size_t simdutf_convert_valid_utf16be_to_utf32(const char16_t *input,
352 size_t length, char32_t *output);
353
354/* UTF-32 -> ... conversions */
355size_t simdutf_convert_utf32_to_utf8(const char32_t *input, size_t length,
356 char *output);
357simdutf_result simdutf_convert_utf32_to_utf8_with_errors(const char32_t *input,
358 size_t length,
359 char *output);
360size_t simdutf_convert_valid_utf32_to_utf8(const char32_t *input, size_t length,
361 char *output);
362
363size_t simdutf_convert_utf32_to_utf16(const char32_t *input, size_t length,
364 char16_t *output);
365size_t simdutf_convert_utf32_to_utf16le(const char32_t *input, size_t length,
366 char16_t *output);
367size_t simdutf_convert_utf32_to_utf16be(const char32_t *input, size_t length,
368 char16_t *output);
370simdutf_convert_utf32_to_latin1_with_errors(const char32_t *input,
371 size_t length, char *output);
372
373/* --- Find helpers --- */
374const char *simdutf_find(const char *start, const char *end, char character);
375const char16_t *simdutf_find_utf16(const char16_t *start, const char16_t *end,
376 char16_t character);
377
378/* --- Base64 enums and helpers --- */
379typedef enum simdutf_base64_options {
380 SIMDUTF_BASE64_DEFAULT = 0,
381 SIMDUTF_BASE64_URL = 1,
382 SIMDUTF_BASE64_DEFAULT_NO_PADDING = 2,
383 SIMDUTF_BASE64_URL_WITH_PADDING = 3,
384 SIMDUTF_BASE64_DEFAULT_ACCEPT_GARBAGE = 4,
385 SIMDUTF_BASE64_URL_ACCEPT_GARBAGE = 5,
386 SIMDUTF_BASE64_DEFAULT_OR_URL = 8,
387 SIMDUTF_BASE64_DEFAULT_OR_URL_ACCEPT_GARBAGE = 12
388} simdutf_base64_options;
389
390typedef enum simdutf_last_chunk_handling_options {
391 SIMDUTF_LAST_CHUNK_LOOSE = 0,
392 SIMDUTF_LAST_CHUNK_STRICT = 1,
393 SIMDUTF_LAST_CHUNK_STOP_BEFORE_PARTIAL = 2,
394 SIMDUTF_LAST_CHUNK_ONLY_FULL_CHUNKS = 3
395} simdutf_last_chunk_handling_options;
396
397/* maximal binary length estimators */
398size_t simdutf_maximal_binary_length_from_base64(const char *input,
399 size_t length);
400size_t simdutf_maximal_binary_length_from_base64_utf16(const char16_t *input,
401 size_t length);
402
403/* base64 decoding/encoding */
404simdutf_result simdutf_base64_to_binary(
405 const char *input, size_t length, char *output,
406 simdutf_base64_options options,
407 simdutf_last_chunk_handling_options last_chunk_options);
408simdutf_result simdutf_base64_to_binary_utf16(
409 const char16_t *input, size_t length, char *output,
410 simdutf_base64_options options,
411 simdutf_last_chunk_handling_options last_chunk_options);
412
413size_t simdutf_base64_length_from_binary(size_t length,
414 simdutf_base64_options options);
415size_t simdutf_base64_length_from_binary_with_lines(
416 size_t length, simdutf_base64_options options, size_t line_length);
417
418size_t simdutf_binary_to_base64(const char *input, size_t length, char *output,
419 simdutf_base64_options options);
420size_t simdutf_binary_to_base64_with_lines(const char *input, size_t length,
421 char *output, size_t line_length,
422 simdutf_base64_options options);
423
424/* safe decoding that provides an in/out outlen parameter */
425simdutf_result simdutf_base64_to_binary_safe(
426 const char *input, size_t length, char *output, size_t *outlen,
427 simdutf_base64_options options,
428 simdutf_last_chunk_handling_options last_chunk_options,
429 bool decode_up_to_bad_char);
430simdutf_result simdutf_base64_to_binary_safe_utf16(
431 const char16_t *input, size_t length, char *output, size_t *outlen,
432 simdutf_base64_options options,
433 simdutf_last_chunk_handling_options last_chunk_options,
434 bool decode_up_to_bad_char);
435
436/* detailed decoding returning input_count and output_count */
437simdutf_full_result simdutf_base64_to_binary_details(
438 const char *input, size_t length, char *output,
439 simdutf_base64_options options,
440 simdutf_last_chunk_handling_options last_chunk_options);
441simdutf_full_result simdutf_base64_to_binary_details_utf16(
442 const char16_t *input, size_t length, char *output,
443 simdutf_base64_options options,
444 simdutf_last_chunk_handling_options last_chunk_options);
445
446/* single-character base64 validation */
447bool simdutf_base64_valid(char input, simdutf_base64_options options);
448bool simdutf_base64_valid_utf16(char16_t input, simdutf_base64_options options);
449
450#ifdef __cplusplus
451} /* extern "C" */
452#endif
453
454#endif /* SIMDUTF_C_H */