Serene Runtime 1.0.0
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 127 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 319 of file utf8.h.

320 {
321 utf8_int32_t src1_lwr_cp = 0, src2_lwr_cp = 0, src1_upr_cp = 0,
322 src2_upr_cp = 0, src1_orig_cp = 0, src2_orig_cp = 0;
323
324 for (;;) {
325 src1 = utf8codepoint(src1, &src1_orig_cp);
326 src2 = utf8codepoint(src2, &src2_orig_cp);
327
328 /* lower the srcs if required */
329 src1_lwr_cp = utf8lwrcodepoint(src1_orig_cp);
330 src2_lwr_cp = utf8lwrcodepoint(src2_orig_cp);
331
332 /* lower the srcs if required */
333 src1_upr_cp = utf8uprcodepoint(src1_orig_cp);
334 src2_upr_cp = utf8uprcodepoint(src2_orig_cp);
335
336 /* check if the lowered codepoints match */
337 if ((0 == src1_orig_cp) && (0 == src2_orig_cp)) {
338 return 0;
339 } else if ((src1_lwr_cp == src2_lwr_cp) || (src1_upr_cp == src2_upr_cp)) {
340 continue;
341 }
342
343 /* if they don't match, then we return the difference between the characters
344 */
345 return src1_lwr_cp - src2_lwr_cp;
346 }
347}
utf8_constexpr14 utf8_int32_t utf8uprcodepoint(utf8_int32_t cp)
Definition utf8.h:1511
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:1209
utf8_constexpr14 utf8_int32_t utf8lwrcodepoint(utf8_int32_t cp)
Definition utf8.h:1348
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 994 of file utf8.h.

995 {
996 /* if needle has no utf8 codepoints before the null terminating
997 * byte then return haystack */
998 if ('\0' == *needle) {
999 return (utf8_int8_t *)haystack;
1000 }
1001
1002 for (;;) {
1003 const utf8_int8_t *maybeMatch = haystack;
1004 const utf8_int8_t *n = needle;
1005 utf8_int32_t h_cp = 0, n_cp = 0;
1006
1007 /* Get the next code point and track it */
1008 const utf8_int8_t *nextH = haystack = utf8codepoint(haystack, &h_cp);
1009 n = utf8codepoint(n, &n_cp);
1010
1011 while ((0 != h_cp) && (0 != n_cp)) {
1012 h_cp = utf8lwrcodepoint(h_cp);
1013 n_cp = utf8lwrcodepoint(n_cp);
1014
1015 /* if we find a mismatch, bail out! */
1016 if (h_cp != n_cp) {
1017 break;
1018 }
1019
1020 haystack = utf8codepoint(haystack, &h_cp);
1021 n = utf8codepoint(n, &n_cp);
1022 }
1023
1024 if (0 == n_cp) {
1025 /* we found the whole utf8 string for needle in haystack at
1026 * maybeMatch, so return it */
1027 return (utf8_int8_t *)maybeMatch;
1028 }
1029
1030 if (0 == h_cp) {
1031 /* no match */
1032 return utf8_null;
1033 }
1034
1035 /* Roll back to the next code point in the haystack to test */
1036 haystack = nextH;
1037 }
1038}
int n
Definition acutest.h:538
#define utf8_null
Definition utf8.h:110
char utf8_int8_t
Definition utf8.h:127
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 349 of file utf8.h.

350 {
351 utf8_int8_t *d = dst;
352 /* find the null terminating byte in dst */
353 while ('\0' != *d) {
354 d++;
355 }
356
357 /* overwriting the null terminating byte in dst, append src byte-by-byte */
358 while ('\0' != *src) {
359 *d++ = *src++;
360 }
361
362 /* write out a new null terminating byte into dst */
363 *d = '\0';
364
365 return dst;
366}

◆ utf8catcodepoint()

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

Definition at line 1262 of file utf8.h.

1262 {
1263 if (0 == ((utf8_int32_t)0xffffff80 & chr)) {
1264 /* 1-byte/7-bit ascii
1265 * (0b0xxxxxxx) */
1266 if (n < 1) {
1267 return utf8_null;
1268 }
1269 str[0] = (utf8_int8_t)chr;
1270 str += 1;
1271 } else if (0 == ((utf8_int32_t)0xfffff800 & chr)) {
1272 /* 2-byte/11-bit utf8 code point
1273 * (0b110xxxxx 0b10xxxxxx) */
1274 if (n < 2) {
1275 return utf8_null;
1276 }
1277 str[0] = (utf8_int8_t)(0xc0 | (utf8_int8_t)((chr >> 6) & 0x1f));
1278 str[1] = (utf8_int8_t)(0x80 | (utf8_int8_t)(chr & 0x3f));
1279 str += 2;
1280 } else if (0 == ((utf8_int32_t)0xffff0000 & chr)) {
1281 /* 3-byte/16-bit utf8 code point
1282 * (0b1110xxxx 0b10xxxxxx 0b10xxxxxx) */
1283 if (n < 3) {
1284 return utf8_null;
1285 }
1286 str[0] = (utf8_int8_t)(0xe0 | (utf8_int8_t)((chr >> 12) & 0x0f));
1287 str[1] = (utf8_int8_t)(0x80 | (utf8_int8_t)((chr >> 6) & 0x3f));
1288 str[2] = (utf8_int8_t)(0x80 | (utf8_int8_t)(chr & 0x3f));
1289 str += 3;
1290 } else { /* if (0 == ((int)0xffe00000 & chr)) { */
1291 /* 4-byte/21-bit utf8 code point
1292 * (0b11110xxx 0b10xxxxxx 0b10xxxxxx 0b10xxxxxx) */
1293 if (n < 4) {
1294 return utf8_null;
1295 }
1296 str[0] = (utf8_int8_t)(0xf0 | (utf8_int8_t)((chr >> 18) & 0x07));
1297 str[1] = (utf8_int8_t)(0x80 | (utf8_int8_t)((chr >> 12) & 0x3f));
1298 str[2] = (utf8_int8_t)(0x80 | (utf8_int8_t)((chr >> 6) & 0x3f));
1299 str[3] = (utf8_int8_t)(0x80 | (utf8_int8_t)(chr & 0x3f));
1300 str += 4;
1301 }
1302
1303 return str;
1304}
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 368 of file utf8.h.

369 {
370 utf8_int8_t c[5] = {'\0', '\0', '\0', '\0', '\0'};
371
372 if (0 == chr) {
373 /* being asked to return position of null terminating byte, so
374 * just run s to the end, and return! */
375 while ('\0' != *src) {
376 src++;
377 }
378 return (utf8_int8_t *)src;
379 } else if (0 == ((utf8_int32_t)0xffffff80 & chr)) {
380 /* 1-byte/7-bit ascii
381 * (0b0xxxxxxx) */
382 c[0] = (utf8_int8_t)chr;
383 } else if (0 == ((utf8_int32_t)0xfffff800 & chr)) {
384 /* 2-byte/11-bit utf8 code point
385 * (0b110xxxxx 0b10xxxxxx) */
386 c[0] = (utf8_int8_t)(0xc0 | (utf8_int8_t)(chr >> 6));
387 c[1] = (utf8_int8_t)(0x80 | (utf8_int8_t)(chr & 0x3f));
388 } else if (0 == ((utf8_int32_t)0xffff0000 & chr)) {
389 /* 3-byte/16-bit utf8 code point
390 * (0b1110xxxx 0b10xxxxxx 0b10xxxxxx) */
391 c[0] = (utf8_int8_t)(0xe0 | (utf8_int8_t)(chr >> 12));
392 c[1] = (utf8_int8_t)(0x80 | (utf8_int8_t)((chr >> 6) & 0x3f));
393 c[2] = (utf8_int8_t)(0x80 | (utf8_int8_t)(chr & 0x3f));
394 } else { /* if (0 == ((int)0xffe00000 & chr)) { */
395 /* 4-byte/21-bit utf8 code point
396 * (0b11110xxx 0b10xxxxxx 0b10xxxxxx 0b10xxxxxx) */
397 c[0] = (utf8_int8_t)(0xf0 | (utf8_int8_t)(chr >> 18));
398 c[1] = (utf8_int8_t)(0x80 | (utf8_int8_t)((chr >> 12) & 0x3f));
399 c[2] = (utf8_int8_t)(0x80 | (utf8_int8_t)((chr >> 6) & 0x3f));
400 c[3] = (utf8_int8_t)(0x80 | (utf8_int8_t)(chr & 0x3f));
401 }
402
403 /* we've made c into a 2 utf8 codepoint string, one for the chr we are
404 * seeking, another for the null terminating byte. Now use utf8str to
405 * search */
406 return utf8str(src, c);
407}
utf8_constexpr14 utf8_nonnull utf8_pure utf8_int8_t * utf8str(const utf8_int8_t *haystack, const utf8_int8_t *needle)
Definition utf8.h:959
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 409 of file utf8.h.

410 {
411 while (('\0' != *src1) || ('\0' != *src2)) {
412 if (*src1 < *src2) {
413 return -1;
414 } else if (*src1 > *src2) {
415 return 1;
416 }
417
418 src1++;
419 src2++;
420 }
421
422 /* both utf8 strings matched */
423 return 0;
424}

◆ 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 1209 of file utf8.h.

1210 {
1211 if (0xf0 == (0xf8 & str[0])) {
1212 /* 4 byte utf8 codepoint */
1213 *out_codepoint = ((0x07 & str[0]) << 18) | ((0x3f & str[1]) << 12) |
1214 ((0x3f & str[2]) << 6) | (0x3f & str[3]);
1215 str += 4;
1216 } else if (0xe0 == (0xf0 & str[0])) {
1217 /* 3 byte utf8 codepoint */
1218 *out_codepoint =
1219 ((0x0f & str[0]) << 12) | ((0x3f & str[1]) << 6) | (0x3f & str[2]);
1220 str += 3;
1221 } else if (0xc0 == (0xe0 & str[0])) {
1222 /* 2 byte utf8 codepoint */
1223 *out_codepoint = ((0x1f & str[0]) << 6) | (0x3f & str[1]);
1224 str += 2;
1225 } else {
1226 /* 1 byte utf8 codepoint otherwise */
1227 *out_codepoint = str[0];
1228 str += 1;
1229 }
1230
1231 return (utf8_int8_t *)str;
1232}
Here is the caller graph for this function:

◆ utf8codepointcalcsize()

utf8_constexpr14_impl size_t utf8codepointcalcsize ( const utf8_int8_t * str)

Definition at line 1234 of file utf8.h.

1234 {
1235 if (0xf0 == (0xf8 & str[0])) {
1236 /* 4 byte utf8 codepoint */
1237 return 4;
1238 } else if (0xe0 == (0xf0 & str[0])) {
1239 /* 3 byte utf8 codepoint */
1240 return 3;
1241 } else if (0xc0 == (0xe0 & str[0])) {
1242 /* 2 byte utf8 codepoint */
1243 return 2;
1244 }
1245
1246 /* 1 byte utf8 codepoint otherwise */
1247 return 1;
1248}
Here is the caller graph for this function:

◆ utf8codepointsize()

utf8_constexpr14_impl size_t utf8codepointsize ( utf8_int32_t chr)

Definition at line 1250 of file utf8.h.

1250 {
1251 if (0 == ((utf8_int32_t)0xffffff80 & chr)) {
1252 return 1;
1253 } else if (0 == ((utf8_int32_t)0xfffff800 & chr)) {
1254 return 2;
1255 } else if (0 == ((utf8_int32_t)0xffff0000 & chr)) {
1256 return 3;
1257 } else { /* if (0 == ((int)0xffe00000 & chr)) { */
1258 return 4;
1259 }
1260}
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 429 of file utf8.h.

430 {
431 utf8_int8_t *d = dst;
432
433 /* overwriting anything previously in dst, write byte-by-byte
434 * from src */
435 while ('\0' != *src) {
436 *d++ = *src++;
437 }
438
439 /* append null terminating byte */
440 *d = '\0';
441
442 return dst;
443}

◆ utf8cspn()

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

Definition at line 445 of file utf8.h.

446 {
447 size_t chars = 0;
448
449 while ('\0' != *src) {
450 const utf8_int8_t *r = reject;
451 size_t offset = 0;
452
453 while ('\0' != *r) {
454 /* checking that if *r is the start of a utf8 codepoint
455 * (it is not 0b10xxxxxx) and we have successfully matched
456 * a previous character (0 < offset) - we found a match */
457 if ((0x80 != (0xc0 & *r)) && (0 < offset)) {
458 return chars;
459 } else {
460 if (*r == src[offset]) {
461 /* part of a utf8 codepoint matched, so move our checking
462 * onwards to the next byte */
463 offset++;
464 r++;
465 } else {
466 /* r could be in the middle of an unmatching utf8 code point,
467 * so we need to march it on to the next character beginning, */
468
469 do {
470 r++;
471 } while (0x80 == (0xc0 & *r));
472
473 /* reset offset too as we found a mismatch */
474 offset = 0;
475 }
476 }
477 }
478
479 /* found a match at the end of *r, so didn't get a chance to test it */
480 if (0 < offset) {
481 return chars;
482 }
483
484 /* the current utf8 codepoint in src did not match reject, but src
485 * could have been partway through a utf8 codepoint, so we need to
486 * march it onto the next utf8 codepoint starting byte */
487 do {
488 src++;
489 } while ((0x80 == (0xc0 & *src)));
490 chars++;
491 }
492
493 return chars;
494}

◆ utf8dup()

utf8_int8_t * utf8dup ( const utf8_int8_t * src)

Definition at line 496 of file utf8.h.

496 {
497 return utf8dup_ex(src, utf8_null, utf8_null);
498}
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:500
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 500 of file utf8.h.

502 {
504
505 /* figure out how many bytes (including the terminator) we need to copy first
506 */
507 size_t bytes = utf8size(src);
508
509 if (alloc_func_ptr) {
510 n = alloc_func_ptr(user_data, bytes);
511 } else {
512#if !defined(UTF8_NO_STD_MALLOC)
513 n = (utf8_int8_t *)malloc(bytes);
514#else
515 return utf8_null;
516#endif
517 }
518
519 if (utf8_null == n) {
520 /* out of memory so we bail */
521 return utf8_null;
522 } else {
523 bytes = 0;
524
525 /* copy src byte-by-byte into our new utf8 string */
526 while ('\0' != src[bytes]) {
527 n[bytes] = src[bytes];
528 bytes++;
529 }
530
531 /* append null terminating byte */
532 n[bytes] = '\0';
533 return n;
534 }
535}
utf8_constexpr14 utf8_nonnull utf8_pure size_t utf8size(const utf8_int8_t *str)
Definition utf8.h:889
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 1306 of file utf8.h.

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

◆ utf8isupper()

utf8_constexpr14_impl int utf8isupper ( utf8_int32_t chr)

Definition at line 1310 of file utf8.h.

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

◆ utf8len()

utf8_constexpr14_impl size_t utf8len ( const utf8_int8_t * str)

Definition at line 539 of file utf8.h.

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

◆ utf8lwr()

void utf8lwr ( utf8_int8_t *utf8_restrict str)

Definition at line 1314 of file utf8.h.

1314 {
1315 utf8_int32_t cp = 0;
1316 utf8_int8_t *pn = utf8codepoint(str, &cp);
1317
1318 while (cp != 0) {
1319 const utf8_int32_t lwr_cp = utf8lwrcodepoint(cp);
1320 const size_t size = utf8codepointsize(lwr_cp);
1321
1322 if (lwr_cp != cp) {
1323 utf8catcodepoint(str, lwr_cp, size);
1324 }
1325
1326 str = pn;
1327 pn = utf8codepoint(str, &cp);
1328 }
1329}
utf8_nonnull utf8_weak utf8_int8_t * utf8catcodepoint(utf8_int8_t *str, utf8_int32_t chr, size_t n)
Definition utf8.h:1262
utf8_constexpr14 size_t utf8codepointsize(utf8_int32_t chr)
Definition utf8.h:1250
Here is the call graph for this function:

◆ utf8lwrcodepoint()

Definition at line 1348 of file utf8.h.

1348 {
1349 if (((0x0041 <= cp) && (0x005a >= cp)) ||
1350 ((0x00c0 <= cp) && (0x00d6 >= cp)) ||
1351 ((0x00d8 <= cp) && (0x00de >= cp)) ||
1352 ((0x0391 <= cp) && (0x03a1 >= cp)) ||
1353 ((0x03a3 <= cp) && (0x03ab >= cp)) ||
1354 ((0x0410 <= cp) && (0x042f >= cp))) {
1355 cp += 32;
1356 } else if ((0x0400 <= cp) && (0x040f >= cp)) {
1357 cp += 80;
1358 } else if (((0x0100 <= cp) && (0x012f >= cp)) ||
1359 ((0x0132 <= cp) && (0x0137 >= cp)) ||
1360 ((0x014a <= cp) && (0x0177 >= cp)) ||
1361 ((0x0182 <= cp) && (0x0185 >= cp)) ||
1362 ((0x01a0 <= cp) && (0x01a5 >= cp)) ||
1363 ((0x01de <= cp) && (0x01ef >= cp)) ||
1364 ((0x01f8 <= cp) && (0x021f >= cp)) ||
1365 ((0x0222 <= cp) && (0x0233 >= cp)) ||
1366 ((0x0246 <= cp) && (0x024f >= cp)) ||
1367 ((0x03d8 <= cp) && (0x03ef >= cp)) ||
1368 ((0x0460 <= cp) && (0x0481 >= cp)) ||
1369 ((0x048a <= cp) && (0x04ff >= cp))) {
1370 cp |= 0x1;
1371 } else if (((0x0139 <= cp) && (0x0148 >= cp)) ||
1372 ((0x0179 <= cp) && (0x017e >= cp)) ||
1373 ((0x01af <= cp) && (0x01b0 >= cp)) ||
1374 ((0x01b3 <= cp) && (0x01b6 >= cp)) ||
1375 ((0x01cd <= cp) && (0x01dc >= cp))) {
1376 cp += 1;
1377 cp &= ~0x1;
1378 } else {
1379 switch (cp) {
1380 default:
1381 break;
1382 case 0x0178:
1383 cp = 0x00ff;
1384 break;
1385 case 0x0243:
1386 cp = 0x0180;
1387 break;
1388 case 0x018e:
1389 cp = 0x01dd;
1390 break;
1391 case 0x023d:
1392 cp = 0x019a;
1393 break;
1394 case 0x0220:
1395 cp = 0x019e;
1396 break;
1397 case 0x01b7:
1398 cp = 0x0292;
1399 break;
1400 case 0x01c4:
1401 cp = 0x01c6;
1402 break;
1403 case 0x01c7:
1404 cp = 0x01c9;
1405 break;
1406 case 0x01ca:
1407 cp = 0x01cc;
1408 break;
1409 case 0x01f1:
1410 cp = 0x01f3;
1411 break;
1412 case 0x01f7:
1413 cp = 0x01bf;
1414 break;
1415 case 0x0187:
1416 cp = 0x0188;
1417 break;
1418 case 0x018b:
1419 cp = 0x018c;
1420 break;
1421 case 0x0191:
1422 cp = 0x0192;
1423 break;
1424 case 0x0198:
1425 cp = 0x0199;
1426 break;
1427 case 0x01a7:
1428 cp = 0x01a8;
1429 break;
1430 case 0x01ac:
1431 cp = 0x01ad;
1432 break;
1433 case 0x01b8:
1434 cp = 0x01b9;
1435 break;
1436 case 0x01bc:
1437 cp = 0x01bd;
1438 break;
1439 case 0x01f4:
1440 cp = 0x01f5;
1441 break;
1442 case 0x023b:
1443 cp = 0x023c;
1444 break;
1445 case 0x0241:
1446 cp = 0x0242;
1447 break;
1448 case 0x03fd:
1449 cp = 0x037b;
1450 break;
1451 case 0x03fe:
1452 cp = 0x037c;
1453 break;
1454 case 0x03ff:
1455 cp = 0x037d;
1456 break;
1457 case 0x037f:
1458 cp = 0x03f3;
1459 break;
1460 case 0x0386:
1461 cp = 0x03ac;
1462 break;
1463 case 0x0388:
1464 cp = 0x03ad;
1465 break;
1466 case 0x0389:
1467 cp = 0x03ae;
1468 break;
1469 case 0x038a:
1470 cp = 0x03af;
1471 break;
1472 case 0x038c:
1473 cp = 0x03cc;
1474 break;
1475 case 0x038e:
1476 cp = 0x03cd;
1477 break;
1478 case 0x038f:
1479 cp = 0x03ce;
1480 break;
1481 case 0x0370:
1482 cp = 0x0371;
1483 break;
1484 case 0x0372:
1485 cp = 0x0373;
1486 break;
1487 case 0x0376:
1488 cp = 0x0377;
1489 break;
1490 case 0x03f4:
1491 cp = 0x03b8;
1492 break;
1493 case 0x03cf:
1494 cp = 0x03d7;
1495 break;
1496 case 0x03f9:
1497 cp = 0x03f2;
1498 break;
1499 case 0x03f7:
1500 cp = 0x03f8;
1501 break;
1502 case 0x03fa:
1503 cp = 0x03fb;
1504 break;
1505 }
1506 }
1507
1508 return cp;
1509}
Here is the caller graph for this function:

◆ utf8makevalid()

int utf8makevalid ( utf8_int8_t * str,
const utf8_int32_t replacement )

Definition at line 1143 of file utf8.h.

1143 {
1144 utf8_int8_t *read = str;
1145 utf8_int8_t *write = read;
1146 const utf8_int8_t r = (utf8_int8_t)replacement;
1147 utf8_int32_t codepoint = 0;
1148
1149 if (replacement > 0x7f) {
1150 return -1;
1151 }
1152
1153 while ('\0' != *read) {
1154 if (0xf0 == (0xf8 & *read)) {
1155 /* ensure each of the 3 following bytes in this 4-byte
1156 * utf8 codepoint began with 0b10xxxxxx */
1157 if ((0x80 != (0xc0 & read[1])) || (0x80 != (0xc0 & read[2])) ||
1158 (0x80 != (0xc0 & read[3]))) {
1159 *write++ = r;
1160 read++;
1161 continue;
1162 }
1163
1164 /* 4-byte utf8 code point (began with 0b11110xxx) */
1165 read = utf8codepoint(read, &codepoint);
1166 write = utf8catcodepoint(write, codepoint, 4);
1167 } else if (0xe0 == (0xf0 & *read)) {
1168 /* ensure each of the 2 following bytes in this 3-byte
1169 * utf8 codepoint began with 0b10xxxxxx */
1170 if ((0x80 != (0xc0 & read[1])) || (0x80 != (0xc0 & read[2]))) {
1171 *write++ = r;
1172 read++;
1173 continue;
1174 }
1175
1176 /* 3-byte utf8 code point (began with 0b1110xxxx) */
1177 read = utf8codepoint(read, &codepoint);
1178 write = utf8catcodepoint(write, codepoint, 3);
1179 } else if (0xc0 == (0xe0 & *read)) {
1180 /* ensure the 1 following byte in this 2-byte
1181 * utf8 codepoint began with 0b10xxxxxx */
1182 if (0x80 != (0xc0 & read[1])) {
1183 *write++ = r;
1184 read++;
1185 continue;
1186 }
1187
1188 /* 2-byte utf8 code point (began with 0b110xxxxx) */
1189 read = utf8codepoint(read, &codepoint);
1190 write = utf8catcodepoint(write, codepoint, 2);
1191 } else if (0x00 == (0x80 & *read)) {
1192 /* 1-byte ascii (began with 0b0xxxxxxx) */
1193 read = utf8codepoint(read, &codepoint);
1194 write = utf8catcodepoint(write, codepoint, 1);
1195 } else {
1196 /* if we got here then we've got a dangling continuation (0b10xxxxxx) */
1197 *write++ = r;
1198 read++;
1199 continue;
1200 }
1201 }
1202
1203 *write = '\0';
1204
1205 return 0;
1206}
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 573 of file utf8.h.

574 {
575 utf8_int32_t src1_lwr_cp = 0, src2_lwr_cp = 0, src1_upr_cp = 0,
576 src2_upr_cp = 0, src1_orig_cp = 0, src2_orig_cp = 0;
577
578 do {
579 const utf8_int8_t *const s1 = src1;
580 const utf8_int8_t *const s2 = src2;
581
582 /* first check that we have enough bytes left in n to contain an entire
583 * codepoint */
584 if (0 == n) {
585 return 0;
586 }
587
588 if ((1 == n) && ((0xc0 == (0xe0 & *s1)) || (0xc0 == (0xe0 & *s2)))) {
589 const utf8_int32_t c1 = (0xe0 & *s1);
590 const utf8_int32_t c2 = (0xe0 & *s2);
591
592 if (c1 != c2) {
593 return c1 - c2;
594 } else {
595 return 0;
596 }
597 }
598
599 if ((2 >= n) && ((0xe0 == (0xf0 & *s1)) || (0xe0 == (0xf0 & *s2)))) {
600 const utf8_int32_t c1 = (0xf0 & *s1);
601 const utf8_int32_t c2 = (0xf0 & *s2);
602
603 if (c1 != c2) {
604 return c1 - c2;
605 } else {
606 return 0;
607 }
608 }
609
610 if ((3 >= n) && ((0xf0 == (0xf8 & *s1)) || (0xf0 == (0xf8 & *s2)))) {
611 const utf8_int32_t c1 = (0xf8 & *s1);
612 const utf8_int32_t c2 = (0xf8 & *s2);
613
614 if (c1 != c2) {
615 return c1 - c2;
616 } else {
617 return 0;
618 }
619 }
620
621 src1 = utf8codepoint(src1, &src1_orig_cp);
622 src2 = utf8codepoint(src2, &src2_orig_cp);
623 n -= utf8codepointsize(src1_orig_cp);
624
625 src1_lwr_cp = utf8lwrcodepoint(src1_orig_cp);
626 src2_lwr_cp = utf8lwrcodepoint(src2_orig_cp);
627
628 src1_upr_cp = utf8uprcodepoint(src1_orig_cp);
629 src2_upr_cp = utf8uprcodepoint(src2_orig_cp);
630
631 /* check if the lowered codepoints match */
632 if ((0 == src1_orig_cp) && (0 == src2_orig_cp)) {
633 return 0;
634 } else if ((src1_lwr_cp == src2_lwr_cp) || (src1_upr_cp == src2_upr_cp)) {
635 continue;
636 }
637
638 /* if they don't match, then we return the difference between the characters
639 */
640 return src1_lwr_cp - src2_lwr_cp;
641 } while (0 < n);
642
643 /* both utf8 strings matched */
644 return 0;
645}
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 647 of file utf8.h.

648 {
649 utf8_int8_t *d = dst;
650
651 /* find the null terminating byte in dst */
652 while ('\0' != *d) {
653 d++;
654 }
655
656 /* overwriting the null terminating byte in dst, append src byte-by-byte
657 * stopping if we run out of space */
658 while (('\0' != *src) && (0 != n--)) {
659 *d++ = *src++;
660 }
661
662 /* write out a new null terminating byte into dst */
663 *d = '\0';
664
665 return dst;
666}

◆ utf8ncmp()

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

Definition at line 668 of file utf8.h.

669 {
670 while ((0 != n--) && (('\0' != *src1) || ('\0' != *src2))) {
671 if (*src1 < *src2) {
672 return -1;
673 } else if (*src1 > *src2) {
674 return 1;
675 }
676
677 src1++;
678 src2++;
679 }
680
681 /* both utf8 strings matched */
682 return 0;
683}

◆ utf8ncpy()

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

Definition at line 685 of file utf8.h.

686 {
687 utf8_int8_t *d = dst;
688 size_t index = 0, check_index = 0;
689
690 if (n == 0) {
691 return dst;
692 }
693
694 /* overwriting anything previously in dst, write byte-by-byte
695 * from src */
696 for (index = 0; index < n; index++) {
697 d[index] = src[index];
698 if ('\0' == src[index]) {
699 break;
700 }
701 }
702
703 for (check_index = index - 1;
704 check_index > 0 && 0x80 == (0xc0 & d[check_index]); check_index--) {
705 /* just moving the index */
706 }
707
708 if (check_index < index &&
709 ((index - check_index) < utf8codepointcalcsize(&d[check_index]) ||
710 (index - check_index) == n)) {
711 index = check_index;
712 }
713
714 /* append null terminating byte */
715 for (; index < n; index++) {
716 d[index] = 0;
717 }
718
719 return dst;
720}
utf8_constexpr14 utf8_nonnull size_t utf8codepointcalcsize(const utf8_int8_t *str)
Definition utf8.h:1234
Here is the call graph for this function:

◆ utf8ndup()

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

Definition at line 722 of file utf8.h.

722 {
723 return utf8ndup_ex(src, n, utf8_null, utf8_null);
724}
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:726
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 726 of file utf8.h.

728 {
730 size_t bytes = 0;
731
732 /* Find the end of the string or stop when n is reached */
733 while ('\0' != src[bytes] && bytes < n) {
734 bytes++;
735 }
736
737 /* In case bytes is actually less than n, we need to set it
738 * to be used later in the copy byte by byte. */
739 n = bytes;
740
741 if (alloc_func_ptr) {
742 c = alloc_func_ptr(user_data, bytes + 1);
743 } else {
744#if !defined(UTF8_NO_STD_MALLOC)
745 c = (utf8_int8_t *)malloc(bytes + 1);
746#else
747 c = utf8_null;
748#endif
749 }
750
751 if (utf8_null == c) {
752 /* out of memory so we bail */
753 return utf8_null;
754 }
755
756 bytes = 0;
757
758 /* copy src byte-by-byte into our new utf8 string */
759 while ('\0' != src[bytes] && bytes < n) {
760 c[bytes] = src[bytes];
761 bytes++;
762 }
763
764 /* append null terminating byte */
765 c[bytes] = '\0';
766 return c;
767}
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 543 of file utf8.h.

543 {
544 const utf8_int8_t *t = str;
545 size_t length = 0;
546
547 while ((size_t)(str - t) < n && '\0' != *str) {
548 if (0xf0 == (0xf8 & *str)) {
549 /* 4-byte utf8 code point (began with 0b11110xxx) */
550 str += 4;
551 } else if (0xe0 == (0xf0 & *str)) {
552 /* 3-byte utf8 code point (began with 0b1110xxxx) */
553 str += 3;
554 } else if (0xc0 == (0xe0 & *str)) {
555 /* 2-byte utf8 code point (began with 0b110xxxxx) */
556 str += 2;
557 } else { /* if (0x00 == (0x80 & *s)) { */
558 /* 1-byte ascii (began with 0b0xxxxxxx) */
559 str += 1;
560 }
561
562 /* no matter the bytes we marched s forward by, it was
563 * only 1 utf8 codepoint */
564 length++;
565 }
566
567 if ((size_t)(str - t) > n) {
568 length--;
569 }
570 return length;
571}
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 897 of file utf8.h.

897 {
898 size_t size = 0;
899 while (size < n && '\0' != str[size]) {
900 size++;
901 }
902 return size;
903}
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 1044 of file utf8.h.

1045 {
1046 const utf8_int8_t *t = str;
1047 size_t consumed = 0;
1048
1049 while ((void)(consumed = (size_t)(str - t)), consumed < n && '\0' != *str) {
1050 const size_t remaining = n - consumed;
1051
1052 if (0xf0 == (0xf8 & *str)) {
1053 /* ensure that there's 4 bytes or more remaining */
1054 if (remaining < 4) {
1055 return (utf8_int8_t *)str;
1056 }
1057
1058 /* ensure each of the 3 following bytes in this 4-byte
1059 * utf8 codepoint began with 0b10xxxxxx */
1060 if ((0x80 != (0xc0 & str[1])) || (0x80 != (0xc0 & str[2])) ||
1061 (0x80 != (0xc0 & str[3]))) {
1062 return (utf8_int8_t *)str;
1063 }
1064
1065 /* ensure that our utf8 codepoint ended after 4 bytes */
1066 if ((remaining != 4) && (0x80 == (0xc0 & str[4]))) {
1067 return (utf8_int8_t *)str;
1068 }
1069
1070 /* ensure that the top 5 bits of this 4-byte utf8
1071 * codepoint were not 0, as then we could have used
1072 * one of the smaller encodings */
1073 if ((0 == (0x07 & str[0])) && (0 == (0x30 & str[1]))) {
1074 return (utf8_int8_t *)str;
1075 }
1076
1077 /* 4-byte utf8 code point (began with 0b11110xxx) */
1078 str += 4;
1079 } else if (0xe0 == (0xf0 & *str)) {
1080 /* ensure that there's 3 bytes or more remaining */
1081 if (remaining < 3) {
1082 return (utf8_int8_t *)str;
1083 }
1084
1085 /* ensure each of the 2 following bytes in this 3-byte
1086 * utf8 codepoint began with 0b10xxxxxx */
1087 if ((0x80 != (0xc0 & str[1])) || (0x80 != (0xc0 & str[2]))) {
1088 return (utf8_int8_t *)str;
1089 }
1090
1091 /* ensure that our utf8 codepoint ended after 3 bytes */
1092 if ((remaining != 3) && (0x80 == (0xc0 & str[3]))) {
1093 return (utf8_int8_t *)str;
1094 }
1095
1096 /* ensure that the top 5 bits of this 3-byte utf8
1097 * codepoint were not 0, as then we could have used
1098 * one of the smaller encodings */
1099 if ((0 == (0x0f & str[0])) && (0 == (0x20 & str[1]))) {
1100 return (utf8_int8_t *)str;
1101 }
1102
1103 /* 3-byte utf8 code point (began with 0b1110xxxx) */
1104 str += 3;
1105 } else if (0xc0 == (0xe0 & *str)) {
1106 /* ensure that there's 2 bytes or more remaining */
1107 if (remaining < 2) {
1108 return (utf8_int8_t *)str;
1109 }
1110
1111 /* ensure the 1 following byte in this 2-byte
1112 * utf8 codepoint began with 0b10xxxxxx */
1113 if (0x80 != (0xc0 & str[1])) {
1114 return (utf8_int8_t *)str;
1115 }
1116
1117 /* ensure that our utf8 codepoint ended after 2 bytes */
1118 if ((remaining != 2) && (0x80 == (0xc0 & str[2]))) {
1119 return (utf8_int8_t *)str;
1120 }
1121
1122 /* ensure that the top 4 bits of this 2-byte utf8
1123 * codepoint were not 0, as then we could have used
1124 * one of the smaller encodings */
1125 if (0 == (0x1e & str[0])) {
1126 return (utf8_int8_t *)str;
1127 }
1128
1129 /* 2-byte utf8 code point (began with 0b110xxxxx) */
1130 str += 2;
1131 } else if (0x00 == (0x80 & *str)) {
1132 /* 1-byte ascii (began with 0b0xxxxxxx) */
1133 str += 1;
1134 } else {
1135 /* we have an invalid 0b1xxxxxxx utf8 code point entry */
1136 return (utf8_int8_t *)str;
1137 }
1138 }
1139
1140 return utf8_null;
1141}
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 841 of file utf8.h.

842 {
843 while ('\0' != *str) {
844 const utf8_int8_t *a = accept;
845 size_t offset = 0;
846
847 while ('\0' != *a) {
848 /* checking that if *a is the start of a utf8 codepoint
849 * (it is not 0b10xxxxxx) and we have successfully matched
850 * a previous character (0 < offset) - we found a match */
851 if ((0x80 != (0xc0 & *a)) && (0 < offset)) {
852 return (utf8_int8_t *)str;
853 } else {
854 if (*a == str[offset]) {
855 /* part of a utf8 codepoint matched, so move our checking
856 * onwards to the next byte */
857 offset++;
858 a++;
859 } else {
860 /* r could be in the middle of an unmatching utf8 code point,
861 * so we need to march it on to the next character beginning, */
862
863 do {
864 a++;
865 } while (0x80 == (0xc0 & *a));
866
867 /* reset offset too as we found a mismatch */
868 offset = 0;
869 }
870 }
871 }
872
873 /* we found a match on the last utf8 codepoint */
874 if (0 < offset) {
875 return (utf8_int8_t *)str;
876 }
877
878 /* the current utf8 codepoint in src did not match accept, but src
879 * could have been partway through a utf8 codepoint, so we need to
880 * march it onto the next utf8 codepoint starting byte */
881 do {
882 str++;
883 } while ((0x80 == (0xc0 & *str)));
884 }
885
886 return utf8_null;
887}

◆ utf8rchr()

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

Definition at line 769 of file utf8.h.

769 {
770
771 utf8_int8_t *match = utf8_null;
772 utf8_int8_t c[5] = {'\0', '\0', '\0', '\0', '\0'};
773
774 if (0 == chr) {
775 /* being asked to return position of null terminating byte, so
776 * just run s to the end, and return! */
777 while ('\0' != *src) {
778 src++;
779 }
780 return (utf8_int8_t *)src;
781 } else if (0 == ((int)0xffffff80 & chr)) {
782 /* 1-byte/7-bit ascii
783 * (0b0xxxxxxx) */
784 c[0] = (utf8_int8_t)chr;
785 } else if (0 == ((int)0xfffff800 & chr)) {
786 /* 2-byte/11-bit utf8 code point
787 * (0b110xxxxx 0b10xxxxxx) */
788 c[0] = (utf8_int8_t)(0xc0 | (utf8_int8_t)(chr >> 6));
789 c[1] = (utf8_int8_t)(0x80 | (utf8_int8_t)(chr & 0x3f));
790 } else if (0 == ((int)0xffff0000 & chr)) {
791 /* 3-byte/16-bit utf8 code point
792 * (0b1110xxxx 0b10xxxxxx 0b10xxxxxx) */
793 c[0] = (utf8_int8_t)(0xe0 | (utf8_int8_t)(chr >> 12));
794 c[1] = (utf8_int8_t)(0x80 | (utf8_int8_t)((chr >> 6) & 0x3f));
795 c[2] = (utf8_int8_t)(0x80 | (utf8_int8_t)(chr & 0x3f));
796 } else { /* if (0 == ((int)0xffe00000 & chr)) { */
797 /* 4-byte/21-bit utf8 code point
798 * (0b11110xxx 0b10xxxxxx 0b10xxxxxx 0b10xxxxxx) */
799 c[0] = (utf8_int8_t)(0xf0 | (utf8_int8_t)(chr >> 18));
800 c[1] = (utf8_int8_t)(0x80 | (utf8_int8_t)((chr >> 12) & 0x3f));
801 c[2] = (utf8_int8_t)(0x80 | (utf8_int8_t)((chr >> 6) & 0x3f));
802 c[3] = (utf8_int8_t)(0x80 | (utf8_int8_t)(chr & 0x3f));
803 }
804
805 /* we've created a 2 utf8 codepoint string in c that is
806 * the utf8 character asked for by chr, and a null
807 * terminating byte */
808
809 while ('\0' != *src) {
810 size_t offset = 0;
811
812 while ((src[offset] == c[offset]) && ('\0' != src[offset])) {
813 offset++;
814 }
815
816 if ('\0' == c[offset]) {
817 /* we found a matching utf8 code point */
818 match = (utf8_int8_t *)src;
819 src += offset;
820
821 if ('\0' == *src) {
822 break;
823 }
824 } else {
825 src += offset;
826
827 /* need to march s along to next utf8 codepoint start
828 * (the next byte that doesn't match 0b10xxxxxx) */
829 if ('\0' != *src) {
830 do {
831 src++;
832 } while (0x80 == (0xc0 & *src));
833 }
834 }
835 }
836
837 /* return the last match we found (or 0 if no match was found) */
838 return match;
839}

◆ 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 1675 of file utf8.h.

1676 {
1677 const utf8_int8_t *s = (const utf8_int8_t *)str;
1678
1679 if (0xf0 == (0xf8 & s[0])) {
1680 /* 4 byte utf8 codepoint */
1681 *out_codepoint = ((0x07 & s[0]) << 18) | ((0x3f & s[1]) << 12) |
1682 ((0x3f & s[2]) << 6) | (0x3f & s[3]);
1683 } else if (0xe0 == (0xf0 & s[0])) {
1684 /* 3 byte utf8 codepoint */
1685 *out_codepoint =
1686 ((0x0f & s[0]) << 12) | ((0x3f & s[1]) << 6) | (0x3f & s[2]);
1687 } else if (0xc0 == (0xe0 & s[0])) {
1688 /* 2 byte utf8 codepoint */
1689 *out_codepoint = ((0x1f & s[0]) << 6) | (0x3f & s[1]);
1690 } else {
1691 /* 1 byte utf8 codepoint otherwise */
1692 *out_codepoint = s[0];
1693 }
1694
1695 do {
1696 s--;
1697 } while ((0 != (0x80 & s[0])) && (0x80 == (0xc0 & s[0])));
1698
1699 return (utf8_int8_t *)s;
1700}

◆ utf8size()

utf8_constexpr14_impl size_t utf8size ( const utf8_int8_t * str)

Definition at line 889 of file utf8.h.

889 {
890 return utf8size_lazy(str) + 1;
891}
utf8_constexpr14 utf8_nonnull utf8_pure size_t utf8size_lazy(const utf8_int8_t *str)
Definition utf8.h:893
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 893 of file utf8.h.

893 {
894 return utf8nsize_lazy(str, SIZE_MAX);
895}
utf8_constexpr14 utf8_nonnull utf8_pure size_t utf8nsize_lazy(const utf8_int8_t *str, size_t n)
Definition utf8.h:897
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 905 of file utf8.h.

906 {
907 size_t chars = 0;
908
909 while ('\0' != *src) {
910 const utf8_int8_t *a = accept;
911 size_t offset = 0;
912
913 while ('\0' != *a) {
914 /* checking that if *r is the start of a utf8 codepoint
915 * (it is not 0b10xxxxxx) and we have successfully matched
916 * a previous character (0 < offset) - we found a match */
917 if ((0x80 != (0xc0 & *a)) && (0 < offset)) {
918 /* found a match, so increment the number of utf8 codepoints
919 * that have matched and stop checking whether any other utf8
920 * codepoints in a match */
921 chars++;
922 src += offset;
923 offset = 0;
924 break;
925 } else {
926 if (*a == src[offset]) {
927 offset++;
928 a++;
929 } else {
930 /* a could be in the middle of an unmatching utf8 codepoint,
931 * so we need to march it on to the next character beginning, */
932 do {
933 a++;
934 } while (0x80 == (0xc0 & *a));
935
936 /* reset offset too as we found a mismatch */
937 offset = 0;
938 }
939 }
940 }
941
942 /* found a match at the end of *a, so didn't get a chance to test it */
943 if (0 < offset) {
944 chars++;
945 src += offset;
946 continue;
947 }
948
949 /* if a got to its terminating null byte, then we didn't find a match.
950 * Return the current number of matched utf8 codepoints */
951 if ('\0' == *a) {
952 return chars;
953 }
954 }
955
956 return chars;
957}

◆ utf8str()

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

Definition at line 959 of file utf8.h.

960 {
961 utf8_int32_t throwaway_codepoint = 0;
962
963 /* if needle has no utf8 codepoints before the null terminating
964 * byte then return haystack */
965 if ('\0' == *needle) {
966 return (utf8_int8_t *)haystack;
967 }
968
969 while ('\0' != *haystack) {
970 const utf8_int8_t *maybeMatch = haystack;
971 const utf8_int8_t *n = needle;
972
973 while (*haystack == *n && (*haystack != '\0' && *n != '\0')) {
974 n++;
975 haystack++;
976 }
977
978 if ('\0' == *n) {
979 /* we found the whole utf8 string for needle in haystack at
980 * maybeMatch, so return it */
981 return (utf8_int8_t *)maybeMatch;
982 } else {
983 /* h could be in the middle of an unmatching utf8 codepoint,
984 * so we need to march it on to the next character beginning
985 * starting from the current character */
986 haystack = utf8codepoint(maybeMatch, &throwaway_codepoint);
987 }
988 }
989
990 /* no match */
991 return utf8_null;
992}
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 1331 of file utf8.h.

1331 {
1332 utf8_int32_t cp = 0;
1333 utf8_int8_t *pn = utf8codepoint(str, &cp);
1334
1335 while (cp != 0) {
1336 const utf8_int32_t lwr_cp = utf8uprcodepoint(cp);
1337 const size_t size = utf8codepointsize(lwr_cp);
1338
1339 if (lwr_cp != cp) {
1340 utf8catcodepoint(str, lwr_cp, size);
1341 }
1342
1343 str = pn;
1344 pn = utf8codepoint(str, &cp);
1345 }
1346}
Here is the call graph for this function:

◆ utf8uprcodepoint()

Definition at line 1511 of file utf8.h.

1511 {
1512 if (((0x0061 <= cp) && (0x007a >= cp)) ||
1513 ((0x00e0 <= cp) && (0x00f6 >= cp)) ||
1514 ((0x00f8 <= cp) && (0x00fe >= cp)) ||
1515 ((0x03b1 <= cp) && (0x03c1 >= cp)) ||
1516 ((0x03c3 <= cp) && (0x03cb >= cp)) ||
1517 ((0x0430 <= cp) && (0x044f >= cp))) {
1518 cp -= 32;
1519 } else if ((0x0450 <= cp) && (0x045f >= cp)) {
1520 cp -= 80;
1521 } else if (((0x0100 <= cp) && (0x012f >= cp)) ||
1522 ((0x0132 <= cp) && (0x0137 >= cp)) ||
1523 ((0x014a <= cp) && (0x0177 >= cp)) ||
1524 ((0x0182 <= cp) && (0x0185 >= cp)) ||
1525 ((0x01a0 <= cp) && (0x01a5 >= cp)) ||
1526 ((0x01de <= cp) && (0x01ef >= cp)) ||
1527 ((0x01f8 <= cp) && (0x021f >= cp)) ||
1528 ((0x0222 <= cp) && (0x0233 >= cp)) ||
1529 ((0x0246 <= cp) && (0x024f >= cp)) ||
1530 ((0x03d8 <= cp) && (0x03ef >= cp)) ||
1531 ((0x0460 <= cp) && (0x0481 >= cp)) ||
1532 ((0x048a <= cp) && (0x04ff >= cp))) {
1533 cp &= ~0x1;
1534 } else if (((0x0139 <= cp) && (0x0148 >= cp)) ||
1535 ((0x0179 <= cp) && (0x017e >= cp)) ||
1536 ((0x01af <= cp) && (0x01b0 >= cp)) ||
1537 ((0x01b3 <= cp) && (0x01b6 >= cp)) ||
1538 ((0x01cd <= cp) && (0x01dc >= cp))) {
1539 cp -= 1;
1540 cp |= 0x1;
1541 } else {
1542 switch (cp) {
1543 default:
1544 break;
1545 case 0x00ff:
1546 cp = 0x0178;
1547 break;
1548 case 0x0180:
1549 cp = 0x0243;
1550 break;
1551 case 0x01dd:
1552 cp = 0x018e;
1553 break;
1554 case 0x019a:
1555 cp = 0x023d;
1556 break;
1557 case 0x019e:
1558 cp = 0x0220;
1559 break;
1560 case 0x0292:
1561 cp = 0x01b7;
1562 break;
1563 case 0x01c6:
1564 cp = 0x01c4;
1565 break;
1566 case 0x01c9:
1567 cp = 0x01c7;
1568 break;
1569 case 0x01cc:
1570 cp = 0x01ca;
1571 break;
1572 case 0x01f3:
1573 cp = 0x01f1;
1574 break;
1575 case 0x01bf:
1576 cp = 0x01f7;
1577 break;
1578 case 0x0188:
1579 cp = 0x0187;
1580 break;
1581 case 0x018c:
1582 cp = 0x018b;
1583 break;
1584 case 0x0192:
1585 cp = 0x0191;
1586 break;
1587 case 0x0199:
1588 cp = 0x0198;
1589 break;
1590 case 0x01a8:
1591 cp = 0x01a7;
1592 break;
1593 case 0x01ad:
1594 cp = 0x01ac;
1595 break;
1596 case 0x01b9:
1597 cp = 0x01b8;
1598 break;
1599 case 0x01bd:
1600 cp = 0x01bc;
1601 break;
1602 case 0x01f5:
1603 cp = 0x01f4;
1604 break;
1605 case 0x023c:
1606 cp = 0x023b;
1607 break;
1608 case 0x0242:
1609 cp = 0x0241;
1610 break;
1611 case 0x037b:
1612 cp = 0x03fd;
1613 break;
1614 case 0x037c:
1615 cp = 0x03fe;
1616 break;
1617 case 0x037d:
1618 cp = 0x03ff;
1619 break;
1620 case 0x03f3:
1621 cp = 0x037f;
1622 break;
1623 case 0x03ac:
1624 cp = 0x0386;
1625 break;
1626 case 0x03ad:
1627 cp = 0x0388;
1628 break;
1629 case 0x03ae:
1630 cp = 0x0389;
1631 break;
1632 case 0x03af:
1633 cp = 0x038a;
1634 break;
1635 case 0x03cc:
1636 cp = 0x038c;
1637 break;
1638 case 0x03cd:
1639 cp = 0x038e;
1640 break;
1641 case 0x03ce:
1642 cp = 0x038f;
1643 break;
1644 case 0x0371:
1645 cp = 0x0370;
1646 break;
1647 case 0x0373:
1648 cp = 0x0372;
1649 break;
1650 case 0x0377:
1651 cp = 0x0376;
1652 break;
1653 case 0x03d1:
1654 cp = 0x0398;
1655 break;
1656 case 0x03d7:
1657 cp = 0x03cf;
1658 break;
1659 case 0x03f2:
1660 cp = 0x03f9;
1661 break;
1662 case 0x03f8:
1663 cp = 0x03f7;
1664 break;
1665 case 0x03fb:
1666 cp = 0x03fa;
1667 break;
1668 }
1669 }
1670
1671 return cp;
1672}
Here is the caller graph for this function:

◆ utf8valid()

utf8_constexpr14_impl utf8_int8_t * utf8valid ( const utf8_int8_t * str)

Definition at line 1040 of file utf8.h.

1040 {
1041 return utf8nvalid(str, SIZE_MAX);
1042}
utf8_constexpr14 utf8_nonnull utf8_pure utf8_int8_t * utf8nvalid(const utf8_int8_t *str, size_t n)
Definition utf8.h:1044
Here is the call graph for this function: