Serene Runtime 1.0.0-dev
C runtime for the Serene programming language
Loading...
Searching...
No Matches
utf8.h File Reference
#include <stddef.h>
#include <stdlib.h>
#include <stdint.h>
Include dependency graph for utf8.h:

Go to the source code of this file.

Macros

#define UTF8_ATTRIBUTE(a)
#define utf8_null   0
#define utf8_constexpr14   utf8_weak
#define utf8_constexpr14_impl

Typedefs

typedef int32_t utf8_int32_t
typedef char utf8_int8_t

Functions

utf8_constexpr14 utf8_nonnull utf8_pure int utf8casecmp (const utf8_int8_t *src1, const utf8_int8_t *src2)
utf8_nonnull utf8_weak utf8_int8_tutf8cat (utf8_int8_t *utf8_restrict dst, const utf8_int8_t *utf8_restrict src)
utf8_constexpr14 utf8_nonnull utf8_pure utf8_int8_tutf8chr (const utf8_int8_t *src, utf8_int32_t chr)
utf8_constexpr14 utf8_nonnull utf8_pure int utf8cmp (const utf8_int8_t *src1, const utf8_int8_t *src2)
utf8_nonnull utf8_weak utf8_int8_tutf8cpy (utf8_int8_t *utf8_restrict dst, const utf8_int8_t *utf8_restrict src)
utf8_constexpr14 utf8_nonnull utf8_pure size_t utf8cspn (const utf8_int8_t *src, const utf8_int8_t *reject)
utf8_weak utf8_int8_tutf8dup (const utf8_int8_t *src)
utf8_constexpr14 utf8_nonnull utf8_pure size_t utf8len (const utf8_int8_t *str)
utf8_constexpr14 utf8_nonnull utf8_pure size_t utf8nlen (const utf8_int8_t *str, size_t n)
utf8_constexpr14 utf8_nonnull utf8_pure int utf8ncasecmp (const utf8_int8_t *src1, const utf8_int8_t *src2, size_t n)
utf8_nonnull utf8_weak utf8_int8_tutf8ncat (utf8_int8_t *utf8_restrict dst, const utf8_int8_t *utf8_restrict src, size_t n)
utf8_constexpr14 utf8_nonnull utf8_pure int utf8ncmp (const utf8_int8_t *src1, const utf8_int8_t *src2, size_t n)
utf8_nonnull utf8_weak utf8_int8_tutf8ncpy (utf8_int8_t *utf8_restrict dst, const utf8_int8_t *utf8_restrict src, size_t n)
utf8_weak utf8_int8_tutf8ndup (const utf8_int8_t *src, size_t n)
utf8_constexpr14 utf8_nonnull utf8_pure utf8_int8_tutf8pbrk (const utf8_int8_t *str, const utf8_int8_t *accept)
utf8_constexpr14 utf8_nonnull utf8_pure utf8_int8_tutf8rchr (const utf8_int8_t *src, int chr)
utf8_constexpr14 utf8_nonnull utf8_pure size_t utf8size (const utf8_int8_t *str)
utf8_constexpr14 utf8_nonnull utf8_pure size_t utf8size_lazy (const utf8_int8_t *str)
utf8_constexpr14 utf8_nonnull utf8_pure size_t utf8nsize_lazy (const utf8_int8_t *str, size_t n)
utf8_constexpr14 utf8_nonnull utf8_pure size_t utf8spn (const utf8_int8_t *src, const utf8_int8_t *accept)
utf8_constexpr14 utf8_nonnull utf8_pure utf8_int8_tutf8str (const utf8_int8_t *haystack, const utf8_int8_t *needle)
utf8_constexpr14 utf8_nonnull utf8_pure utf8_int8_tutf8casestr (const utf8_int8_t *haystack, const utf8_int8_t *needle)
utf8_constexpr14 utf8_nonnull utf8_pure utf8_int8_tutf8valid (const utf8_int8_t *str)
utf8_constexpr14 utf8_nonnull utf8_pure utf8_int8_tutf8nvalid (const utf8_int8_t *str, size_t n)
utf8_nonnull utf8_weak int utf8makevalid (utf8_int8_t *str, const utf8_int32_t replacement)
utf8_constexpr14 utf8_nonnull utf8_int8_tutf8codepoint (const utf8_int8_t *utf8_restrict str, utf8_int32_t *utf8_restrict out_codepoint)
utf8_constexpr14 utf8_nonnull size_t utf8codepointcalcsize (const utf8_int8_t *str)
utf8_constexpr14 size_t utf8codepointsize (utf8_int32_t chr)
utf8_nonnull utf8_weak utf8_int8_tutf8catcodepoint (utf8_int8_t *str, utf8_int32_t chr, size_t n)
utf8_constexpr14 int utf8islower (utf8_int32_t chr)
utf8_constexpr14 int utf8isupper (utf8_int32_t chr)
utf8_nonnull utf8_weak void utf8lwr (utf8_int8_t *utf8_restrict str)
utf8_nonnull utf8_weak void utf8upr (utf8_int8_t *utf8_restrict str)
utf8_constexpr14 utf8_int32_t utf8lwrcodepoint (utf8_int32_t cp)
utf8_constexpr14 utf8_int32_t utf8uprcodepoint (utf8_int32_t cp)
utf8_constexpr14 utf8_nonnull utf8_int8_tutf8rcodepoint (const utf8_int8_t *utf8_restrict str, utf8_int32_t *utf8_restrict out_codepoint)
utf8_weak utf8_int8_tutf8dup_ex (const utf8_int8_t *src, utf8_int8_t *(*alloc_func_ptr)(utf8_int8_t *, size_t), utf8_int8_t *user_data)
utf8_weak utf8_int8_tutf8ndup_ex (const utf8_int8_t *src, size_t n, utf8_int8_t *(*alloc_func_ptr)(utf8_int8_t *, size_t), utf8_int8_t *user_data)
utf8_constexpr14_impl int utf8coll (const utf8_int8_t *src1, const utf8_int8_t *src2)
utf8_constexpr14_impl utf8_int8_tutf8fry (const utf8_int8_t *str)

Macro Definition Documentation

◆ UTF8_ATTRIBUTE

#define UTF8_ATTRIBUTE ( a)
Value:
__attribute__((a))

Definition at line 80 of file utf8.h.

◆ utf8_constexpr14

#define utf8_constexpr14   utf8_weak

Definition at line 119 of file utf8.h.

◆ utf8_constexpr14_impl

#define utf8_constexpr14_impl

Definition at line 120 of file utf8.h.

◆ utf8_null

#define utf8_null   0

Definition at line 110 of file utf8.h.

Typedef Documentation

◆ utf8_int32_t

typedef int32_t utf8_int32_t

Definition at line 60 of file utf8.h.

◆ utf8_int8_t

typedef char utf8_int8_t

Definition at line 126 of file utf8.h.

Function Documentation

◆ utf8casecmp()

utf8_constexpr14_impl int utf8casecmp ( const utf8_int8_t * src1,
const utf8_int8_t * src2 )

Definition at line 305 of file utf8.h.

305 {
306 utf8_int32_t src1_lwr_cp = 0, src2_lwr_cp = 0, src1_upr_cp = 0, src2_upr_cp = 0, src1_orig_cp = 0,
307 src2_orig_cp = 0;
308
309 for (;;) {
310 src1 = utf8codepoint(src1, &src1_orig_cp);
311 src2 = utf8codepoint(src2, &src2_orig_cp);
312
313 /* lower the srcs if required */
314 src1_lwr_cp = utf8lwrcodepoint(src1_orig_cp);
315 src2_lwr_cp = utf8lwrcodepoint(src2_orig_cp);
316
317 /* lower the srcs if required */
318 src1_upr_cp = utf8uprcodepoint(src1_orig_cp);
319 src2_upr_cp = utf8uprcodepoint(src2_orig_cp);
320
321 /* check if the lowered codepoints match */
322 if ((0 == src1_orig_cp) && (0 == src2_orig_cp)) {
323 return 0;
324 } else if ((src1_lwr_cp == src2_lwr_cp) || (src1_upr_cp == src2_upr_cp)) {
325 continue;
326 }
327
328 /* if they don't match, then we return the difference between the characters
329 */
330 return src1_lwr_cp - src2_lwr_cp;
331 }
332}
utf8_constexpr14 utf8_int32_t utf8uprcodepoint(utf8_int32_t cp)
Definition utf8.h:1467
int32_t utf8_int32_t
Definition utf8.h:60
utf8_constexpr14 utf8_nonnull utf8_int8_t * utf8codepoint(const utf8_int8_t *utf8_restrict str, utf8_int32_t *utf8_restrict out_codepoint)
Definition utf8.h:1176
utf8_constexpr14 utf8_int32_t utf8lwrcodepoint(utf8_int32_t cp)
Definition utf8.h:1309
Here is the call graph for this function:

◆ utf8casestr()

utf8_constexpr14_impl utf8_int8_t * utf8casestr ( const utf8_int8_t * haystack,
const utf8_int8_t * needle )

Definition at line 965 of file utf8.h.

965 {
966 /* if needle has no utf8 codepoints before the null terminating
967 * byte then return haystack */
968 if ('\0' == *needle) {
969 return (utf8_int8_t *)haystack;
970 }
971
972 for (;;) {
973 const utf8_int8_t *maybeMatch = haystack;
974 const utf8_int8_t *n = needle;
975 utf8_int32_t h_cp = 0, n_cp = 0;
976
977 /* Get the next code point and track it */
978 const utf8_int8_t *nextH = haystack = utf8codepoint(haystack, &h_cp);
979 n = utf8codepoint(n, &n_cp);
980
981 while ((0 != h_cp) && (0 != n_cp)) {
982 h_cp = utf8lwrcodepoint(h_cp);
983 n_cp = utf8lwrcodepoint(n_cp);
984
985 /* if we find a mismatch, bail out! */
986 if (h_cp != n_cp) {
987 break;
988 }
989
990 haystack = utf8codepoint(haystack, &h_cp);
991 n = utf8codepoint(n, &n_cp);
992 }
993
994 if (0 == n_cp) {
995 /* we found the whole utf8 string for needle in haystack at
996 * maybeMatch, so return it */
997 return (utf8_int8_t *)maybeMatch;
998 }
999
1000 if (0 == h_cp) {
1001 /* no match */
1002 return utf8_null;
1003 }
1004
1005 /* Roll back to the next code point in the haystack to test */
1006 haystack = nextH;
1007 }
1008}
int n
Definition acutest.h:525
#define utf8_null
Definition utf8.h:110
char utf8_int8_t
Definition utf8.h:126
Here is the call graph for this function:

◆ utf8cat()

utf8_int8_t * utf8cat ( utf8_int8_t *utf8_restrict dst,
const utf8_int8_t *utf8_restrict src )

Definition at line 334 of file utf8.h.

334 {
335 utf8_int8_t *d = dst;
336 /* find the null terminating byte in dst */
337 while ('\0' != *d) {
338 d++;
339 }
340
341 /* overwriting the null terminating byte in dst, append src byte-by-byte */
342 while ('\0' != *src) {
343 *d++ = *src++;
344 }
345
346 /* write out a new null terminating byte into dst */
347 *d = '\0';
348
349 return dst;
350}

◆ utf8catcodepoint()

utf8_int8_t * utf8catcodepoint ( utf8_int8_t * str,
utf8_int32_t chr,
size_t n )

Definition at line 1227 of file utf8.h.

1227 {
1228 if (0 == ((utf8_int32_t)0xffffff80 & chr)) {
1229 /* 1-byte/7-bit ascii
1230 * (0b0xxxxxxx) */
1231 if (n < 1) {
1232 return utf8_null;
1233 }
1234 str[0] = (utf8_int8_t)chr;
1235 str += 1;
1236 } else if (0 == ((utf8_int32_t)0xfffff800 & chr)) {
1237 /* 2-byte/11-bit utf8 code point
1238 * (0b110xxxxx 0b10xxxxxx) */
1239 if (n < 2) {
1240 return utf8_null;
1241 }
1242 str[0] = (utf8_int8_t)(0xc0 | (utf8_int8_t)((chr >> 6) & 0x1f));
1243 str[1] = (utf8_int8_t)(0x80 | (utf8_int8_t)(chr & 0x3f));
1244 str += 2;
1245 } else if (0 == ((utf8_int32_t)0xffff0000 & chr)) {
1246 /* 3-byte/16-bit utf8 code point
1247 * (0b1110xxxx 0b10xxxxxx 0b10xxxxxx) */
1248 if (n < 3) {
1249 return utf8_null;
1250 }
1251 str[0] = (utf8_int8_t)(0xe0 | (utf8_int8_t)((chr >> 12) & 0x0f));
1252 str[1] = (utf8_int8_t)(0x80 | (utf8_int8_t)((chr >> 6) & 0x3f));
1253 str[2] = (utf8_int8_t)(0x80 | (utf8_int8_t)(chr & 0x3f));
1254 str += 3;
1255 } else { /* if (0 == ((int)0xffe00000 & chr)) { */
1256 /* 4-byte/21-bit utf8 code point
1257 * (0b11110xxx 0b10xxxxxx 0b10xxxxxx 0b10xxxxxx) */
1258 if (n < 4) {
1259 return utf8_null;
1260 }
1261 str[0] = (utf8_int8_t)(0xf0 | (utf8_int8_t)((chr >> 18) & 0x07));
1262 str[1] = (utf8_int8_t)(0x80 | (utf8_int8_t)((chr >> 12) & 0x3f));
1263 str[2] = (utf8_int8_t)(0x80 | (utf8_int8_t)((chr >> 6) & 0x3f));
1264 str[3] = (utf8_int8_t)(0x80 | (utf8_int8_t)(chr & 0x3f));
1265 str += 4;
1266 }
1267
1268 return str;
1269}
Here is the caller graph for this function:

◆ utf8chr()

utf8_constexpr14_impl utf8_int8_t * utf8chr ( const utf8_int8_t * src,
utf8_int32_t chr )

Definition at line 352 of file utf8.h.

352 {
353 utf8_int8_t c[5] = {'\0', '\0', '\0', '\0', '\0'};
354
355 if (0 == chr) {
356 /* being asked to return position of null terminating byte, so
357 * just run s to the end, and return! */
358 while ('\0' != *src) {
359 src++;
360 }
361 return (utf8_int8_t *)src;
362 } else if (0 == ((utf8_int32_t)0xffffff80 & chr)) {
363 /* 1-byte/7-bit ascii
364 * (0b0xxxxxxx) */
365 c[0] = (utf8_int8_t)chr;
366 } else if (0 == ((utf8_int32_t)0xfffff800 & chr)) {
367 /* 2-byte/11-bit utf8 code point
368 * (0b110xxxxx 0b10xxxxxx) */
369 c[0] = (utf8_int8_t)(0xc0 | (utf8_int8_t)(chr >> 6));
370 c[1] = (utf8_int8_t)(0x80 | (utf8_int8_t)(chr & 0x3f));
371 } else if (0 == ((utf8_int32_t)0xffff0000 & chr)) {
372 /* 3-byte/16-bit utf8 code point
373 * (0b1110xxxx 0b10xxxxxx 0b10xxxxxx) */
374 c[0] = (utf8_int8_t)(0xe0 | (utf8_int8_t)(chr >> 12));
375 c[1] = (utf8_int8_t)(0x80 | (utf8_int8_t)((chr >> 6) & 0x3f));
376 c[2] = (utf8_int8_t)(0x80 | (utf8_int8_t)(chr & 0x3f));
377 } else { /* if (0 == ((int)0xffe00000 & chr)) { */
378 /* 4-byte/21-bit utf8 code point
379 * (0b11110xxx 0b10xxxxxx 0b10xxxxxx 0b10xxxxxx) */
380 c[0] = (utf8_int8_t)(0xf0 | (utf8_int8_t)(chr >> 18));
381 c[1] = (utf8_int8_t)(0x80 | (utf8_int8_t)((chr >> 12) & 0x3f));
382 c[2] = (utf8_int8_t)(0x80 | (utf8_int8_t)((chr >> 6) & 0x3f));
383 c[3] = (utf8_int8_t)(0x80 | (utf8_int8_t)(chr & 0x3f));
384 }
385
386 /* we've made c into a 2 utf8 codepoint string, one for the chr we are
387 * seeking, another for the null terminating byte. Now use utf8str to
388 * search */
389 return utf8str(src, c);
390}
utf8_constexpr14 utf8_nonnull utf8_pure utf8_int8_t * utf8str(const utf8_int8_t *haystack, const utf8_int8_t *needle)
Definition utf8.h:930
Here is the call graph for this function:

◆ utf8cmp()

utf8_constexpr14_impl int utf8cmp ( const utf8_int8_t * src1,
const utf8_int8_t * src2 )

Definition at line 392 of file utf8.h.

392 {
393 while (('\0' != *src1) || ('\0' != *src2)) {
394 if (*src1 < *src2) {
395 return -1;
396 } else if (*src1 > *src2) {
397 return 1;
398 }
399
400 src1++;
401 src2++;
402 }
403
404 /* both utf8 strings matched */
405 return 0;
406}

◆ utf8codepoint()

utf8_constexpr14_impl utf8_int8_t * utf8codepoint ( const utf8_int8_t *utf8_restrict str,
utf8_int32_t *utf8_restrict out_codepoint )

Definition at line 1176 of file utf8.h.

1176 {
1177 if (0xf0 == (0xf8 & str[0])) {
1178 /* 4 byte utf8 codepoint */
1179 *out_codepoint =
1180 ((0x07 & str[0]) << 18) | ((0x3f & str[1]) << 12) | ((0x3f & str[2]) << 6) | (0x3f & str[3]);
1181 str += 4;
1182 } else if (0xe0 == (0xf0 & str[0])) {
1183 /* 3 byte utf8 codepoint */
1184 *out_codepoint = ((0x0f & str[0]) << 12) | ((0x3f & str[1]) << 6) | (0x3f & str[2]);
1185 str += 3;
1186 } else if (0xc0 == (0xe0 & str[0])) {
1187 /* 2 byte utf8 codepoint */
1188 *out_codepoint = ((0x1f & str[0]) << 6) | (0x3f & str[1]);
1189 str += 2;
1190 } else {
1191 /* 1 byte utf8 codepoint otherwise */
1192 *out_codepoint = str[0];
1193 str += 1;
1194 }
1195
1196 return (utf8_int8_t *)str;
1197}
Here is the caller graph for this function:

◆ utf8codepointcalcsize()

utf8_constexpr14_impl size_t utf8codepointcalcsize ( const utf8_int8_t * str)

Definition at line 1199 of file utf8.h.

1199 {
1200 if (0xf0 == (0xf8 & str[0])) {
1201 /* 4 byte utf8 codepoint */
1202 return 4;
1203 } else if (0xe0 == (0xf0 & str[0])) {
1204 /* 3 byte utf8 codepoint */
1205 return 3;
1206 } else if (0xc0 == (0xe0 & str[0])) {
1207 /* 2 byte utf8 codepoint */
1208 return 2;
1209 }
1210
1211 /* 1 byte utf8 codepoint otherwise */
1212 return 1;
1213}
Here is the caller graph for this function:

◆ utf8codepointsize()

utf8_constexpr14_impl size_t utf8codepointsize ( utf8_int32_t chr)

Definition at line 1215 of file utf8.h.

1215 {
1216 if (0 == ((utf8_int32_t)0xffffff80 & chr)) {
1217 return 1;
1218 } else if (0 == ((utf8_int32_t)0xfffff800 & chr)) {
1219 return 2;
1220 } else if (0 == ((utf8_int32_t)0xffff0000 & chr)) {
1221 return 3;
1222 } else { /* if (0 == ((int)0xffe00000 & chr)) { */
1223 return 4;
1224 }
1225}
Here is the caller graph for this function:

◆ utf8coll()

utf8_constexpr14_impl int utf8coll ( const utf8_int8_t * src1,
const utf8_int8_t * src2 )

◆ utf8cpy()

utf8_int8_t * utf8cpy ( utf8_int8_t *utf8_restrict dst,
const utf8_int8_t *utf8_restrict src )

Definition at line 410 of file utf8.h.

410 {
411 utf8_int8_t *d = dst;
412
413 /* overwriting anything previously in dst, write byte-by-byte
414 * from src */
415 while ('\0' != *src) {
416 *d++ = *src++;
417 }
418
419 /* append null terminating byte */
420 *d = '\0';
421
422 return dst;
423}

◆ utf8cspn()

utf8_constexpr14_impl size_t utf8cspn ( const utf8_int8_t * src,
const utf8_int8_t * reject )

Definition at line 425 of file utf8.h.

425 {
426 size_t chars = 0;
427
428 while ('\0' != *src) {
429 const utf8_int8_t *r = reject;
430 size_t offset = 0;
431
432 while ('\0' != *r) {
433 /* checking that if *r is the start of a utf8 codepoint
434 * (it is not 0b10xxxxxx) and we have successfully matched
435 * a previous character (0 < offset) - we found a match */
436 if ((0x80 != (0xc0 & *r)) && (0 < offset)) {
437 return chars;
438 } else {
439 if (*r == src[offset]) {
440 /* part of a utf8 codepoint matched, so move our checking
441 * onwards to the next byte */
442 offset++;
443 r++;
444 } else {
445 /* r could be in the middle of an unmatching utf8 code point,
446 * so we need to march it on to the next character beginning, */
447
448 do {
449 r++;
450 } while (0x80 == (0xc0 & *r));
451
452 /* reset offset too as we found a mismatch */
453 offset = 0;
454 }
455 }
456 }
457
458 /* found a match at the end of *r, so didn't get a chance to test it */
459 if (0 < offset) {
460 return chars;
461 }
462
463 /* the current utf8 codepoint in src did not match reject, but src
464 * could have been partway through a utf8 codepoint, so we need to
465 * march it onto the next utf8 codepoint starting byte */
466 do {
467 src++;
468 } while ((0x80 == (0xc0 & *src)));
469 chars++;
470 }
471
472 return chars;
473}

◆ utf8dup()

utf8_int8_t * utf8dup ( const utf8_int8_t * src)

Definition at line 475 of file utf8.h.

475{ return utf8dup_ex(src, utf8_null, utf8_null); }
utf8_weak utf8_int8_t * utf8dup_ex(const utf8_int8_t *src, utf8_int8_t *(*alloc_func_ptr)(utf8_int8_t *, size_t), utf8_int8_t *user_data)
Definition utf8.h:477
Here is the call graph for this function:

◆ utf8dup_ex()

utf8_int8_t * utf8dup_ex ( const utf8_int8_t * src,
utf8_int8_t *(* alloc_func_ptr )(utf8_int8_t *, size_t),
utf8_int8_t * user_data )

Definition at line 477 of file utf8.h.

480 {
482
483 /* figure out how many bytes (including the terminator) we need to copy first
484 */
485 size_t bytes = utf8size(src);
486
487 if (alloc_func_ptr) {
488 n = alloc_func_ptr(user_data, bytes);
489 } else {
490#if !defined(UTF8_NO_STD_MALLOC)
491 n = (utf8_int8_t *)malloc(bytes);
492#else
493 return utf8_null;
494#endif
495 }
496
497 if (utf8_null == n) {
498 /* out of memory so we bail */
499 return utf8_null;
500 } else {
501 bytes = 0;
502
503 /* copy src byte-by-byte into our new utf8 string */
504 while ('\0' != src[bytes]) {
505 n[bytes] = src[bytes];
506 bytes++;
507 }
508
509 /* append null terminating byte */
510 n[bytes] = '\0';
511 return n;
512 }
513}
utf8_constexpr14 utf8_nonnull utf8_pure size_t utf8size(const utf8_int8_t *str)
Definition utf8.h:863
Here is the call graph for this function:
Here is the caller graph for this function:

◆ utf8fry()

utf8_constexpr14_impl utf8_int8_t * utf8fry ( const utf8_int8_t * str)

◆ utf8islower()

utf8_constexpr14_impl int utf8islower ( utf8_int32_t chr)

Definition at line 1271 of file utf8.h.

1271{ return chr != utf8uprcodepoint(chr); }
Here is the call graph for this function:

◆ utf8isupper()

utf8_constexpr14_impl int utf8isupper ( utf8_int32_t chr)

Definition at line 1273 of file utf8.h.

1273{ return chr != utf8lwrcodepoint(chr); }
Here is the call graph for this function:

◆ utf8len()

utf8_constexpr14_impl size_t utf8len ( const utf8_int8_t * str)

Definition at line 517 of file utf8.h.

517{ return utf8nlen(str, SIZE_MAX); }
utf8_constexpr14 utf8_nonnull utf8_pure size_t utf8nlen(const utf8_int8_t *str, size_t n)
Definition utf8.h:519
Here is the call graph for this function:

◆ utf8lwr()

void utf8lwr ( utf8_int8_t *utf8_restrict str)

Definition at line 1275 of file utf8.h.

1275 {
1276 utf8_int32_t cp = 0;
1277 utf8_int8_t *pn = utf8codepoint(str, &cp);
1278
1279 while (cp != 0) {
1280 const utf8_int32_t lwr_cp = utf8lwrcodepoint(cp);
1281 const size_t size = utf8codepointsize(lwr_cp);
1282
1283 if (lwr_cp != cp) {
1284 utf8catcodepoint(str, lwr_cp, size);
1285 }
1286
1287 str = pn;
1288 pn = utf8codepoint(str, &cp);
1289 }
1290}
utf8_nonnull utf8_weak utf8_int8_t * utf8catcodepoint(utf8_int8_t *str, utf8_int32_t chr, size_t n)
Definition utf8.h:1227
utf8_constexpr14 size_t utf8codepointsize(utf8_int32_t chr)
Definition utf8.h:1215
Here is the call graph for this function:

◆ utf8lwrcodepoint()

Definition at line 1309 of file utf8.h.

1309 {
1310 if (
1311 ((0x0041 <= cp) && (0x005a >= cp)) || ((0x00c0 <= cp) && (0x00d6 >= cp)) ||
1312 ((0x00d8 <= cp) && (0x00de >= cp)) || ((0x0391 <= cp) && (0x03a1 >= cp)) ||
1313 ((0x03a3 <= cp) && (0x03ab >= cp)) || ((0x0410 <= cp) && (0x042f >= cp))
1314 ) {
1315 cp += 32;
1316 } else if ((0x0400 <= cp) && (0x040f >= cp)) {
1317 cp += 80;
1318 } else if (
1319 ((0x0100 <= cp) && (0x012f >= cp)) || ((0x0132 <= cp) && (0x0137 >= cp)) ||
1320 ((0x014a <= cp) && (0x0177 >= cp)) || ((0x0182 <= cp) && (0x0185 >= cp)) ||
1321 ((0x01a0 <= cp) && (0x01a5 >= cp)) || ((0x01de <= cp) && (0x01ef >= cp)) ||
1322 ((0x01f8 <= cp) && (0x021f >= cp)) || ((0x0222 <= cp) && (0x0233 >= cp)) ||
1323 ((0x0246 <= cp) && (0x024f >= cp)) || ((0x03d8 <= cp) && (0x03ef >= cp)) ||
1324 ((0x0460 <= cp) && (0x0481 >= cp)) || ((0x048a <= cp) && (0x04ff >= cp))
1325 ) {
1326 cp |= 0x1;
1327 } else if (
1328 ((0x0139 <= cp) && (0x0148 >= cp)) || ((0x0179 <= cp) && (0x017e >= cp)) ||
1329 ((0x01af <= cp) && (0x01b0 >= cp)) || ((0x01b3 <= cp) && (0x01b6 >= cp)) ||
1330 ((0x01cd <= cp) && (0x01dc >= cp))
1331 ) {
1332 cp += 1;
1333 cp &= ~0x1;
1334 } else {
1335 switch (cp) {
1336 default:
1337 break;
1338 case 0x0178:
1339 cp = 0x00ff;
1340 break;
1341 case 0x0243:
1342 cp = 0x0180;
1343 break;
1344 case 0x018e:
1345 cp = 0x01dd;
1346 break;
1347 case 0x023d:
1348 cp = 0x019a;
1349 break;
1350 case 0x0220:
1351 cp = 0x019e;
1352 break;
1353 case 0x01b7:
1354 cp = 0x0292;
1355 break;
1356 case 0x01c4:
1357 cp = 0x01c6;
1358 break;
1359 case 0x01c7:
1360 cp = 0x01c9;
1361 break;
1362 case 0x01ca:
1363 cp = 0x01cc;
1364 break;
1365 case 0x01f1:
1366 cp = 0x01f3;
1367 break;
1368 case 0x01f7:
1369 cp = 0x01bf;
1370 break;
1371 case 0x0187:
1372 cp = 0x0188;
1373 break;
1374 case 0x018b:
1375 cp = 0x018c;
1376 break;
1377 case 0x0191:
1378 cp = 0x0192;
1379 break;
1380 case 0x0198:
1381 cp = 0x0199;
1382 break;
1383 case 0x01a7:
1384 cp = 0x01a8;
1385 break;
1386 case 0x01ac:
1387 cp = 0x01ad;
1388 break;
1389 case 0x01b8:
1390 cp = 0x01b9;
1391 break;
1392 case 0x01bc:
1393 cp = 0x01bd;
1394 break;
1395 case 0x01f4:
1396 cp = 0x01f5;
1397 break;
1398 case 0x023b:
1399 cp = 0x023c;
1400 break;
1401 case 0x0241:
1402 cp = 0x0242;
1403 break;
1404 case 0x03fd:
1405 cp = 0x037b;
1406 break;
1407 case 0x03fe:
1408 cp = 0x037c;
1409 break;
1410 case 0x03ff:
1411 cp = 0x037d;
1412 break;
1413 case 0x037f:
1414 cp = 0x03f3;
1415 break;
1416 case 0x0386:
1417 cp = 0x03ac;
1418 break;
1419 case 0x0388:
1420 cp = 0x03ad;
1421 break;
1422 case 0x0389:
1423 cp = 0x03ae;
1424 break;
1425 case 0x038a:
1426 cp = 0x03af;
1427 break;
1428 case 0x038c:
1429 cp = 0x03cc;
1430 break;
1431 case 0x038e:
1432 cp = 0x03cd;
1433 break;
1434 case 0x038f:
1435 cp = 0x03ce;
1436 break;
1437 case 0x0370:
1438 cp = 0x0371;
1439 break;
1440 case 0x0372:
1441 cp = 0x0373;
1442 break;
1443 case 0x0376:
1444 cp = 0x0377;
1445 break;
1446 case 0x03f4:
1447 cp = 0x03b8;
1448 break;
1449 case 0x03cf:
1450 cp = 0x03d7;
1451 break;
1452 case 0x03f9:
1453 cp = 0x03f2;
1454 break;
1455 case 0x03f7:
1456 cp = 0x03f8;
1457 break;
1458 case 0x03fa:
1459 cp = 0x03fb;
1460 break;
1461 }
1462 }
1463
1464 return cp;
1465}
Here is the caller graph for this function:

◆ utf8makevalid()

int utf8makevalid ( utf8_int8_t * str,
const utf8_int32_t replacement )

Definition at line 1111 of file utf8.h.

1111 {
1112 utf8_int8_t *read = str;
1113 utf8_int8_t *write = read;
1114 const utf8_int8_t r = (utf8_int8_t)replacement;
1115 utf8_int32_t codepoint = 0;
1116
1117 if (replacement > 0x7f) {
1118 return -1;
1119 }
1120
1121 while ('\0' != *read) {
1122 if (0xf0 == (0xf8 & *read)) {
1123 /* ensure each of the 3 following bytes in this 4-byte
1124 * utf8 codepoint began with 0b10xxxxxx */
1125 if ((0x80 != (0xc0 & read[1])) || (0x80 != (0xc0 & read[2])) || (0x80 != (0xc0 & read[3]))) {
1126 *write++ = r;
1127 read++;
1128 continue;
1129 }
1130
1131 /* 4-byte utf8 code point (began with 0b11110xxx) */
1132 read = utf8codepoint(read, &codepoint);
1133 write = utf8catcodepoint(write, codepoint, 4);
1134 } else if (0xe0 == (0xf0 & *read)) {
1135 /* ensure each of the 2 following bytes in this 3-byte
1136 * utf8 codepoint began with 0b10xxxxxx */
1137 if ((0x80 != (0xc0 & read[1])) || (0x80 != (0xc0 & read[2]))) {
1138 *write++ = r;
1139 read++;
1140 continue;
1141 }
1142
1143 /* 3-byte utf8 code point (began with 0b1110xxxx) */
1144 read = utf8codepoint(read, &codepoint);
1145 write = utf8catcodepoint(write, codepoint, 3);
1146 } else if (0xc0 == (0xe0 & *read)) {
1147 /* ensure the 1 following byte in this 2-byte
1148 * utf8 codepoint began with 0b10xxxxxx */
1149 if (0x80 != (0xc0 & read[1])) {
1150 *write++ = r;
1151 read++;
1152 continue;
1153 }
1154
1155 /* 2-byte utf8 code point (began with 0b110xxxxx) */
1156 read = utf8codepoint(read, &codepoint);
1157 write = utf8catcodepoint(write, codepoint, 2);
1158 } else if (0x00 == (0x80 & *read)) {
1159 /* 1-byte ascii (began with 0b0xxxxxxx) */
1160 read = utf8codepoint(read, &codepoint);
1161 write = utf8catcodepoint(write, codepoint, 1);
1162 } else {
1163 /* if we got here then we've got a dangling continuation (0b10xxxxxx) */
1164 *write++ = r;
1165 read++;
1166 continue;
1167 }
1168 }
1169
1170 *write = '\0';
1171
1172 return 0;
1173}
Here is the call graph for this function:

◆ utf8ncasecmp()

utf8_constexpr14_impl int utf8ncasecmp ( const utf8_int8_t * src1,
const utf8_int8_t * src2,
size_t n )

Definition at line 549 of file utf8.h.

549 {
550 utf8_int32_t src1_lwr_cp = 0, src2_lwr_cp = 0, src1_upr_cp = 0, src2_upr_cp = 0, src1_orig_cp = 0,
551 src2_orig_cp = 0;
552
553 do {
554 const utf8_int8_t *const s1 = src1;
555 const utf8_int8_t *const s2 = src2;
556
557 /* first check that we have enough bytes left in n to contain an entire
558 * codepoint */
559 if (0 == n) {
560 return 0;
561 }
562
563 if ((1 == n) && ((0xc0 == (0xe0 & *s1)) || (0xc0 == (0xe0 & *s2)))) {
564 const utf8_int32_t c1 = (0xe0 & *s1);
565 const utf8_int32_t c2 = (0xe0 & *s2);
566
567 if (c1 != c2) {
568 return c1 - c2;
569 } else {
570 return 0;
571 }
572 }
573
574 if ((2 >= n) && ((0xe0 == (0xf0 & *s1)) || (0xe0 == (0xf0 & *s2)))) {
575 const utf8_int32_t c1 = (0xf0 & *s1);
576 const utf8_int32_t c2 = (0xf0 & *s2);
577
578 if (c1 != c2) {
579 return c1 - c2;
580 } else {
581 return 0;
582 }
583 }
584
585 if ((3 >= n) && ((0xf0 == (0xf8 & *s1)) || (0xf0 == (0xf8 & *s2)))) {
586 const utf8_int32_t c1 = (0xf8 & *s1);
587 const utf8_int32_t c2 = (0xf8 & *s2);
588
589 if (c1 != c2) {
590 return c1 - c2;
591 } else {
592 return 0;
593 }
594 }
595
596 src1 = utf8codepoint(src1, &src1_orig_cp);
597 src2 = utf8codepoint(src2, &src2_orig_cp);
598 n -= utf8codepointsize(src1_orig_cp);
599
600 src1_lwr_cp = utf8lwrcodepoint(src1_orig_cp);
601 src2_lwr_cp = utf8lwrcodepoint(src2_orig_cp);
602
603 src1_upr_cp = utf8uprcodepoint(src1_orig_cp);
604 src2_upr_cp = utf8uprcodepoint(src2_orig_cp);
605
606 /* check if the lowered codepoints match */
607 if ((0 == src1_orig_cp) && (0 == src2_orig_cp)) {
608 return 0;
609 } else if ((src1_lwr_cp == src2_lwr_cp) || (src1_upr_cp == src2_upr_cp)) {
610 continue;
611 }
612
613 /* if they don't match, then we return the difference between the characters
614 */
615 return src1_lwr_cp - src2_lwr_cp;
616 } while (0 < n);
617
618 /* both utf8 strings matched */
619 return 0;
620}
Here is the call graph for this function:

◆ utf8ncat()

utf8_int8_t * utf8ncat ( utf8_int8_t *utf8_restrict dst,
const utf8_int8_t *utf8_restrict src,
size_t n )

Definition at line 623 of file utf8.h.

623 {
624 utf8_int8_t *d = dst;
625
626 /* find the null terminating byte in dst */
627 while ('\0' != *d) {
628 d++;
629 }
630
631 /* overwriting the null terminating byte in dst, append src byte-by-byte
632 * stopping if we run out of space */
633 while (('\0' != *src) && (0 != n--)) {
634 *d++ = *src++;
635 }
636
637 /* write out a new null terminating byte into dst */
638 *d = '\0';
639
640 return dst;
641}

◆ utf8ncmp()

utf8_constexpr14_impl int utf8ncmp ( const utf8_int8_t * src1,
const utf8_int8_t * src2,
size_t n )

Definition at line 643 of file utf8.h.

643 {
644 while ((0 != n--) && (('\0' != *src1) || ('\0' != *src2))) {
645 if (*src1 < *src2) {
646 return -1;
647 } else if (*src1 > *src2) {
648 return 1;
649 }
650
651 src1++;
652 src2++;
653 }
654
655 /* both utf8 strings matched */
656 return 0;
657}

◆ utf8ncpy()

utf8_int8_t * utf8ncpy ( utf8_int8_t *utf8_restrict dst,
const utf8_int8_t *utf8_restrict src,
size_t n )

Definition at line 660 of file utf8.h.

660 {
661 utf8_int8_t *d = dst;
662 size_t index = 0, check_index = 0;
663
664 if (n == 0) {
665 return dst;
666 }
667
668 /* overwriting anything previously in dst, write byte-by-byte
669 * from src */
670 for (index = 0; index < n; index++) {
671 d[index] = src[index];
672 if ('\0' == src[index]) {
673 break;
674 }
675 }
676
677 for (check_index = index - 1; check_index > 0 && 0x80 == (0xc0 & d[check_index]); check_index--) {
678 /* just moving the index */
679 }
680
681 if (
682 check_index < index &&
683 ((index - check_index) < utf8codepointcalcsize(&d[check_index]) || (index - check_index) == n)
684 ) {
685 index = check_index;
686 }
687
688 /* append null terminating byte */
689 for (; index < n; index++) {
690 d[index] = 0;
691 }
692
693 return dst;
694}
utf8_constexpr14 utf8_nonnull size_t utf8codepointcalcsize(const utf8_int8_t *str)
Definition utf8.h:1199
Here is the call graph for this function:

◆ utf8ndup()

utf8_int8_t * utf8ndup ( const utf8_int8_t * src,
size_t n )

Definition at line 696 of file utf8.h.

696 {
697 return utf8ndup_ex(src, n, utf8_null, utf8_null);
698}
utf8_weak utf8_int8_t * utf8ndup_ex(const utf8_int8_t *src, size_t n, utf8_int8_t *(*alloc_func_ptr)(utf8_int8_t *, size_t), utf8_int8_t *user_data)
Definition utf8.h:700
Here is the call graph for this function:

◆ utf8ndup_ex()

utf8_int8_t * utf8ndup_ex ( const utf8_int8_t * src,
size_t n,
utf8_int8_t *(* alloc_func_ptr )(utf8_int8_t *, size_t),
utf8_int8_t * user_data )

Definition at line 700 of file utf8.h.

703 {
705 size_t bytes = 0;
706
707 /* Find the end of the string or stop when n is reached */
708 while ('\0' != src[bytes] && bytes < n) {
709 bytes++;
710 }
711
712 /* In case bytes is actually less than n, we need to set it
713 * to be used later in the copy byte by byte. */
714 n = bytes;
715
716 if (alloc_func_ptr) {
717 c = alloc_func_ptr(user_data, bytes + 1);
718 } else {
719#if !defined(UTF8_NO_STD_MALLOC)
720 c = (utf8_int8_t *)malloc(bytes + 1);
721#else
722 c = utf8_null;
723#endif
724 }
725
726 if (utf8_null == c) {
727 /* out of memory so we bail */
728 return utf8_null;
729 }
730
731 bytes = 0;
732
733 /* copy src byte-by-byte into our new utf8 string */
734 while ('\0' != src[bytes] && bytes < n) {
735 c[bytes] = src[bytes];
736 bytes++;
737 }
738
739 /* append null terminating byte */
740 c[bytes] = '\0';
741 return c;
742}
Here is the caller graph for this function:

◆ utf8nlen()

utf8_constexpr14_impl size_t utf8nlen ( const utf8_int8_t * str,
size_t n )

Definition at line 519 of file utf8.h.

519 {
520 const utf8_int8_t *t = str;
521 size_t length = 0;
522
523 while ((size_t)(str - t) < n && '\0' != *str) {
524 if (0xf0 == (0xf8 & *str)) {
525 /* 4-byte utf8 code point (began with 0b11110xxx) */
526 str += 4;
527 } else if (0xe0 == (0xf0 & *str)) {
528 /* 3-byte utf8 code point (began with 0b1110xxxx) */
529 str += 3;
530 } else if (0xc0 == (0xe0 & *str)) {
531 /* 2-byte utf8 code point (began with 0b110xxxxx) */
532 str += 2;
533 } else { /* if (0x00 == (0x80 & *s)) { */
534 /* 1-byte ascii (began with 0b0xxxxxxx) */
535 str += 1;
536 }
537
538 /* no matter the bytes we marched s forward by, it was
539 * only 1 utf8 codepoint */
540 length++;
541 }
542
543 if ((size_t)(str - t) > n) {
544 length--;
545 }
546 return length;
547}
Here is the caller graph for this function:

◆ utf8nsize_lazy()

utf8_constexpr14_impl size_t utf8nsize_lazy ( const utf8_int8_t * str,
size_t n )

Definition at line 869 of file utf8.h.

869 {
870 size_t size = 0;
871 while (size < n && '\0' != str[size]) {
872 size++;
873 }
874 return size;
875}
Here is the caller graph for this function:

◆ utf8nvalid()

utf8_constexpr14_impl utf8_int8_t * utf8nvalid ( const utf8_int8_t * str,
size_t n )

Definition at line 1014 of file utf8.h.

1014 {
1015 const utf8_int8_t *t = str;
1016 size_t consumed = 0;
1017
1018 while ((void)(consumed = (size_t)(str - t)), consumed < n && '\0' != *str) {
1019 const size_t remaining = n - consumed;
1020
1021 if (0xf0 == (0xf8 & *str)) {
1022 /* ensure that there's 4 bytes or more remaining */
1023 if (remaining < 4) {
1024 return (utf8_int8_t *)str;
1025 }
1026
1027 /* ensure each of the 3 following bytes in this 4-byte
1028 * utf8 codepoint began with 0b10xxxxxx */
1029 if ((0x80 != (0xc0 & str[1])) || (0x80 != (0xc0 & str[2])) || (0x80 != (0xc0 & str[3]))) {
1030 return (utf8_int8_t *)str;
1031 }
1032
1033 /* ensure that our utf8 codepoint ended after 4 bytes */
1034 if ((remaining != 4) && (0x80 == (0xc0 & str[4]))) {
1035 return (utf8_int8_t *)str;
1036 }
1037
1038 /* ensure that the top 5 bits of this 4-byte utf8
1039 * codepoint were not 0, as then we could have used
1040 * one of the smaller encodings */
1041 if ((0 == (0x07 & str[0])) && (0 == (0x30 & str[1]))) {
1042 return (utf8_int8_t *)str;
1043 }
1044
1045 /* 4-byte utf8 code point (began with 0b11110xxx) */
1046 str += 4;
1047 } else if (0xe0 == (0xf0 & *str)) {
1048 /* ensure that there's 3 bytes or more remaining */
1049 if (remaining < 3) {
1050 return (utf8_int8_t *)str;
1051 }
1052
1053 /* ensure each of the 2 following bytes in this 3-byte
1054 * utf8 codepoint began with 0b10xxxxxx */
1055 if ((0x80 != (0xc0 & str[1])) || (0x80 != (0xc0 & str[2]))) {
1056 return (utf8_int8_t *)str;
1057 }
1058
1059 /* ensure that our utf8 codepoint ended after 3 bytes */
1060 if ((remaining != 3) && (0x80 == (0xc0 & str[3]))) {
1061 return (utf8_int8_t *)str;
1062 }
1063
1064 /* ensure that the top 5 bits of this 3-byte utf8
1065 * codepoint were not 0, as then we could have used
1066 * one of the smaller encodings */
1067 if ((0 == (0x0f & str[0])) && (0 == (0x20 & str[1]))) {
1068 return (utf8_int8_t *)str;
1069 }
1070
1071 /* 3-byte utf8 code point (began with 0b1110xxxx) */
1072 str += 3;
1073 } else if (0xc0 == (0xe0 & *str)) {
1074 /* ensure that there's 2 bytes or more remaining */
1075 if (remaining < 2) {
1076 return (utf8_int8_t *)str;
1077 }
1078
1079 /* ensure the 1 following byte in this 2-byte
1080 * utf8 codepoint began with 0b10xxxxxx */
1081 if (0x80 != (0xc0 & str[1])) {
1082 return (utf8_int8_t *)str;
1083 }
1084
1085 /* ensure that our utf8 codepoint ended after 2 bytes */
1086 if ((remaining != 2) && (0x80 == (0xc0 & str[2]))) {
1087 return (utf8_int8_t *)str;
1088 }
1089
1090 /* ensure that the top 4 bits of this 2-byte utf8
1091 * codepoint were not 0, as then we could have used
1092 * one of the smaller encodings */
1093 if (0 == (0x1e & str[0])) {
1094 return (utf8_int8_t *)str;
1095 }
1096
1097 /* 2-byte utf8 code point (began with 0b110xxxxx) */
1098 str += 2;
1099 } else if (0x00 == (0x80 & *str)) {
1100 /* 1-byte ascii (began with 0b0xxxxxxx) */
1101 str += 1;
1102 } else {
1103 /* we have an invalid 0b1xxxxxxx utf8 code point entry */
1104 return (utf8_int8_t *)str;
1105 }
1106 }
1107
1108 return utf8_null;
1109}
Here is the caller graph for this function:

◆ utf8pbrk()

utf8_constexpr14_impl utf8_int8_t * utf8pbrk ( const utf8_int8_t * str,
const utf8_int8_t * accept )

Definition at line 816 of file utf8.h.

816 {
817 while ('\0' != *str) {
818 const utf8_int8_t *a = accept;
819 size_t offset = 0;
820
821 while ('\0' != *a) {
822 /* checking that if *a is the start of a utf8 codepoint
823 * (it is not 0b10xxxxxx) and we have successfully matched
824 * a previous character (0 < offset) - we found a match */
825 if ((0x80 != (0xc0 & *a)) && (0 < offset)) {
826 return (utf8_int8_t *)str;
827 } else {
828 if (*a == str[offset]) {
829 /* part of a utf8 codepoint matched, so move our checking
830 * onwards to the next byte */
831 offset++;
832 a++;
833 } else {
834 /* r could be in the middle of an unmatching utf8 code point,
835 * so we need to march it on to the next character beginning, */
836
837 do {
838 a++;
839 } while (0x80 == (0xc0 & *a));
840
841 /* reset offset too as we found a mismatch */
842 offset = 0;
843 }
844 }
845 }
846
847 /* we found a match on the last utf8 codepoint */
848 if (0 < offset) {
849 return (utf8_int8_t *)str;
850 }
851
852 /* the current utf8 codepoint in src did not match accept, but src
853 * could have been partway through a utf8 codepoint, so we need to
854 * march it onto the next utf8 codepoint starting byte */
855 do {
856 str++;
857 } while ((0x80 == (0xc0 & *str)));
858 }
859
860 return utf8_null;
861}

◆ utf8rchr()

utf8_constexpr14_impl utf8_int8_t * utf8rchr ( const utf8_int8_t * src,
int chr )

Definition at line 744 of file utf8.h.

744 {
745
746 utf8_int8_t *match = utf8_null;
747 utf8_int8_t c[5] = {'\0', '\0', '\0', '\0', '\0'};
748
749 if (0 == chr) {
750 /* being asked to return position of null terminating byte, so
751 * just run s to the end, and return! */
752 while ('\0' != *src) {
753 src++;
754 }
755 return (utf8_int8_t *)src;
756 } else if (0 == ((int)0xffffff80 & chr)) {
757 /* 1-byte/7-bit ascii
758 * (0b0xxxxxxx) */
759 c[0] = (utf8_int8_t)chr;
760 } else if (0 == ((int)0xfffff800 & chr)) {
761 /* 2-byte/11-bit utf8 code point
762 * (0b110xxxxx 0b10xxxxxx) */
763 c[0] = (utf8_int8_t)(0xc0 | (utf8_int8_t)(chr >> 6));
764 c[1] = (utf8_int8_t)(0x80 | (utf8_int8_t)(chr & 0x3f));
765 } else if (0 == ((int)0xffff0000 & chr)) {
766 /* 3-byte/16-bit utf8 code point
767 * (0b1110xxxx 0b10xxxxxx 0b10xxxxxx) */
768 c[0] = (utf8_int8_t)(0xe0 | (utf8_int8_t)(chr >> 12));
769 c[1] = (utf8_int8_t)(0x80 | (utf8_int8_t)((chr >> 6) & 0x3f));
770 c[2] = (utf8_int8_t)(0x80 | (utf8_int8_t)(chr & 0x3f));
771 } else { /* if (0 == ((int)0xffe00000 & chr)) { */
772 /* 4-byte/21-bit utf8 code point
773 * (0b11110xxx 0b10xxxxxx 0b10xxxxxx 0b10xxxxxx) */
774 c[0] = (utf8_int8_t)(0xf0 | (utf8_int8_t)(chr >> 18));
775 c[1] = (utf8_int8_t)(0x80 | (utf8_int8_t)((chr >> 12) & 0x3f));
776 c[2] = (utf8_int8_t)(0x80 | (utf8_int8_t)((chr >> 6) & 0x3f));
777 c[3] = (utf8_int8_t)(0x80 | (utf8_int8_t)(chr & 0x3f));
778 }
779
780 /* we've created a 2 utf8 codepoint string in c that is
781 * the utf8 character asked for by chr, and a null
782 * terminating byte */
783
784 while ('\0' != *src) {
785 size_t offset = 0;
786
787 while ((src[offset] == c[offset]) && ('\0' != src[offset])) {
788 offset++;
789 }
790
791 if ('\0' == c[offset]) {
792 /* we found a matching utf8 code point */
793 match = (utf8_int8_t *)src;
794 src += offset;
795
796 if ('\0' == *src) {
797 break;
798 }
799 } else {
800 src += offset;
801
802 /* need to march s along to next utf8 codepoint start
803 * (the next byte that doesn't match 0b10xxxxxx) */
804 if ('\0' != *src) {
805 do {
806 src++;
807 } while (0x80 == (0xc0 & *src));
808 }
809 }
810 }
811
812 /* return the last match we found (or 0 if no match was found) */
813 return match;
814}

◆ utf8rcodepoint()

utf8_constexpr14_impl utf8_int8_t * utf8rcodepoint ( const utf8_int8_t *utf8_restrict str,
utf8_int32_t *utf8_restrict out_codepoint )

Definition at line 1626 of file utf8.h.

1626 {
1627 const utf8_int8_t *s = (const utf8_int8_t *)str;
1628
1629 if (0xf0 == (0xf8 & s[0])) {
1630 /* 4 byte utf8 codepoint */
1631 *out_codepoint =
1632 ((0x07 & s[0]) << 18) | ((0x3f & s[1]) << 12) | ((0x3f & s[2]) << 6) | (0x3f & s[3]);
1633 } else if (0xe0 == (0xf0 & s[0])) {
1634 /* 3 byte utf8 codepoint */
1635 *out_codepoint = ((0x0f & s[0]) << 12) | ((0x3f & s[1]) << 6) | (0x3f & s[2]);
1636 } else if (0xc0 == (0xe0 & s[0])) {
1637 /* 2 byte utf8 codepoint */
1638 *out_codepoint = ((0x1f & s[0]) << 6) | (0x3f & s[1]);
1639 } else {
1640 /* 1 byte utf8 codepoint otherwise */
1641 *out_codepoint = s[0];
1642 }
1643
1644 do {
1645 s--;
1646 } while ((0 != (0x80 & s[0])) && (0x80 == (0xc0 & s[0])));
1647
1648 return (utf8_int8_t *)s;
1649}

◆ utf8size()

utf8_constexpr14_impl size_t utf8size ( const utf8_int8_t * str)

Definition at line 863 of file utf8.h.

863{ return utf8size_lazy(str) + 1; }
utf8_constexpr14 utf8_nonnull utf8_pure size_t utf8size_lazy(const utf8_int8_t *str)
Definition utf8.h:865
Here is the call graph for this function:
Here is the caller graph for this function:

◆ utf8size_lazy()

utf8_constexpr14_impl size_t utf8size_lazy ( const utf8_int8_t * str)

Definition at line 865 of file utf8.h.

865 {
866 return utf8nsize_lazy(str, SIZE_MAX);
867}
utf8_constexpr14 utf8_nonnull utf8_pure size_t utf8nsize_lazy(const utf8_int8_t *str, size_t n)
Definition utf8.h:869
Here is the call graph for this function:
Here is the caller graph for this function:

◆ utf8spn()

utf8_constexpr14_impl size_t utf8spn ( const utf8_int8_t * src,
const utf8_int8_t * accept )

Definition at line 877 of file utf8.h.

877 {
878 size_t chars = 0;
879
880 while ('\0' != *src) {
881 const utf8_int8_t *a = accept;
882 size_t offset = 0;
883
884 while ('\0' != *a) {
885 /* checking that if *r is the start of a utf8 codepoint
886 * (it is not 0b10xxxxxx) and we have successfully matched
887 * a previous character (0 < offset) - we found a match */
888 if ((0x80 != (0xc0 & *a)) && (0 < offset)) {
889 /* found a match, so increment the number of utf8 codepoints
890 * that have matched and stop checking whether any other utf8
891 * codepoints in a match */
892 chars++;
893 src += offset;
894 offset = 0;
895 break;
896 } else {
897 if (*a == src[offset]) {
898 offset++;
899 a++;
900 } else {
901 /* a could be in the middle of an unmatching utf8 codepoint,
902 * so we need to march it on to the next character beginning, */
903 do {
904 a++;
905 } while (0x80 == (0xc0 & *a));
906
907 /* reset offset too as we found a mismatch */
908 offset = 0;
909 }
910 }
911 }
912
913 /* found a match at the end of *a, so didn't get a chance to test it */
914 if (0 < offset) {
915 chars++;
916 src += offset;
917 continue;
918 }
919
920 /* if a got to its terminating null byte, then we didn't find a match.
921 * Return the current number of matched utf8 codepoints */
922 if ('\0' == *a) {
923 return chars;
924 }
925 }
926
927 return chars;
928}

◆ utf8str()

utf8_constexpr14_impl utf8_int8_t * utf8str ( const utf8_int8_t * haystack,
const utf8_int8_t * needle )

Definition at line 930 of file utf8.h.

930 {
931 utf8_int32_t throwaway_codepoint = 0;
932
933 /* if needle has no utf8 codepoints before the null terminating
934 * byte then return haystack */
935 if ('\0' == *needle) {
936 return (utf8_int8_t *)haystack;
937 }
938
939 while ('\0' != *haystack) {
940 const utf8_int8_t *maybeMatch = haystack;
941 const utf8_int8_t *n = needle;
942
943 while (*haystack == *n && (*haystack != '\0' && *n != '\0')) {
944 n++;
945 haystack++;
946 }
947
948 if ('\0' == *n) {
949 /* we found the whole utf8 string for needle in haystack at
950 * maybeMatch, so return it */
951 return (utf8_int8_t *)maybeMatch;
952 } else {
953 /* h could be in the middle of an unmatching utf8 codepoint,
954 * so we need to march it on to the next character beginning
955 * starting from the current character */
956 haystack = utf8codepoint(maybeMatch, &throwaway_codepoint);
957 }
958 }
959
960 /* no match */
961 return utf8_null;
962}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ utf8upr()

void utf8upr ( utf8_int8_t *utf8_restrict str)

Definition at line 1292 of file utf8.h.

1292 {
1293 utf8_int32_t cp = 0;
1294 utf8_int8_t *pn = utf8codepoint(str, &cp);
1295
1296 while (cp != 0) {
1297 const utf8_int32_t lwr_cp = utf8uprcodepoint(cp);
1298 const size_t size = utf8codepointsize(lwr_cp);
1299
1300 if (lwr_cp != cp) {
1301 utf8catcodepoint(str, lwr_cp, size);
1302 }
1303
1304 str = pn;
1305 pn = utf8codepoint(str, &cp);
1306 }
1307}
Here is the call graph for this function:

◆ utf8uprcodepoint()

Definition at line 1467 of file utf8.h.

1467 {
1468 if (
1469 ((0x0061 <= cp) && (0x007a >= cp)) || ((0x00e0 <= cp) && (0x00f6 >= cp)) ||
1470 ((0x00f8 <= cp) && (0x00fe >= cp)) || ((0x03b1 <= cp) && (0x03c1 >= cp)) ||
1471 ((0x03c3 <= cp) && (0x03cb >= cp)) || ((0x0430 <= cp) && (0x044f >= cp))
1472 ) {
1473 cp -= 32;
1474 } else if ((0x0450 <= cp) && (0x045f >= cp)) {
1475 cp -= 80;
1476 } else if (
1477 ((0x0100 <= cp) && (0x012f >= cp)) || ((0x0132 <= cp) && (0x0137 >= cp)) ||
1478 ((0x014a <= cp) && (0x0177 >= cp)) || ((0x0182 <= cp) && (0x0185 >= cp)) ||
1479 ((0x01a0 <= cp) && (0x01a5 >= cp)) || ((0x01de <= cp) && (0x01ef >= cp)) ||
1480 ((0x01f8 <= cp) && (0x021f >= cp)) || ((0x0222 <= cp) && (0x0233 >= cp)) ||
1481 ((0x0246 <= cp) && (0x024f >= cp)) || ((0x03d8 <= cp) && (0x03ef >= cp)) ||
1482 ((0x0460 <= cp) && (0x0481 >= cp)) || ((0x048a <= cp) && (0x04ff >= cp))
1483 ) {
1484 cp &= ~0x1;
1485 } else if (
1486 ((0x0139 <= cp) && (0x0148 >= cp)) || ((0x0179 <= cp) && (0x017e >= cp)) ||
1487 ((0x01af <= cp) && (0x01b0 >= cp)) || ((0x01b3 <= cp) && (0x01b6 >= cp)) ||
1488 ((0x01cd <= cp) && (0x01dc >= cp))
1489 ) {
1490 cp -= 1;
1491 cp |= 0x1;
1492 } else {
1493 switch (cp) {
1494 default:
1495 break;
1496 case 0x00ff:
1497 cp = 0x0178;
1498 break;
1499 case 0x0180:
1500 cp = 0x0243;
1501 break;
1502 case 0x01dd:
1503 cp = 0x018e;
1504 break;
1505 case 0x019a:
1506 cp = 0x023d;
1507 break;
1508 case 0x019e:
1509 cp = 0x0220;
1510 break;
1511 case 0x0292:
1512 cp = 0x01b7;
1513 break;
1514 case 0x01c6:
1515 cp = 0x01c4;
1516 break;
1517 case 0x01c9:
1518 cp = 0x01c7;
1519 break;
1520 case 0x01cc:
1521 cp = 0x01ca;
1522 break;
1523 case 0x01f3:
1524 cp = 0x01f1;
1525 break;
1526 case 0x01bf:
1527 cp = 0x01f7;
1528 break;
1529 case 0x0188:
1530 cp = 0x0187;
1531 break;
1532 case 0x018c:
1533 cp = 0x018b;
1534 break;
1535 case 0x0192:
1536 cp = 0x0191;
1537 break;
1538 case 0x0199:
1539 cp = 0x0198;
1540 break;
1541 case 0x01a8:
1542 cp = 0x01a7;
1543 break;
1544 case 0x01ad:
1545 cp = 0x01ac;
1546 break;
1547 case 0x01b9:
1548 cp = 0x01b8;
1549 break;
1550 case 0x01bd:
1551 cp = 0x01bc;
1552 break;
1553 case 0x01f5:
1554 cp = 0x01f4;
1555 break;
1556 case 0x023c:
1557 cp = 0x023b;
1558 break;
1559 case 0x0242:
1560 cp = 0x0241;
1561 break;
1562 case 0x037b:
1563 cp = 0x03fd;
1564 break;
1565 case 0x037c:
1566 cp = 0x03fe;
1567 break;
1568 case 0x037d:
1569 cp = 0x03ff;
1570 break;
1571 case 0x03f3:
1572 cp = 0x037f;
1573 break;
1574 case 0x03ac:
1575 cp = 0x0386;
1576 break;
1577 case 0x03ad:
1578 cp = 0x0388;
1579 break;
1580 case 0x03ae:
1581 cp = 0x0389;
1582 break;
1583 case 0x03af:
1584 cp = 0x038a;
1585 break;
1586 case 0x03cc:
1587 cp = 0x038c;
1588 break;
1589 case 0x03cd:
1590 cp = 0x038e;
1591 break;
1592 case 0x03ce:
1593 cp = 0x038f;
1594 break;
1595 case 0x0371:
1596 cp = 0x0370;
1597 break;
1598 case 0x0373:
1599 cp = 0x0372;
1600 break;
1601 case 0x0377:
1602 cp = 0x0376;
1603 break;
1604 case 0x03d1:
1605 cp = 0x0398;
1606 break;
1607 case 0x03d7:
1608 cp = 0x03cf;
1609 break;
1610 case 0x03f2:
1611 cp = 0x03f9;
1612 break;
1613 case 0x03f8:
1614 cp = 0x03f7;
1615 break;
1616 case 0x03fb:
1617 cp = 0x03fa;
1618 break;
1619 }
1620 }
1621
1622 return cp;
1623}
Here is the caller graph for this function:

◆ utf8valid()

utf8_constexpr14_impl utf8_int8_t * utf8valid ( const utf8_int8_t * str)

Definition at line 1010 of file utf8.h.

1010 {
1011 return utf8nvalid(str, SIZE_MAX);
1012}
utf8_constexpr14 utf8_nonnull utf8_pure utf8_int8_t * utf8nvalid(const utf8_int8_t *str, size_t n)
Definition utf8.h:1014
Here is the call graph for this function: