VR-Forces 5.0.3 Developer's Guide
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
utf8.h
Go to the documentation of this file.
1 // This is free and unencumbered software released into the public domain.
2 //
3 // Anyone is free to copy, modify, publish, use, compile, sell, or
4 // distribute this software, either in source code form or as a compiled
5 // binary, for any purpose, commercial or non-commercial, and by any
6 // means.
7 //
8 // In jurisdictions that recognize copyright laws, the author or authors
9 // of this software dedicate any and all copyright interest in the
10 // software to the public domain. We make this dedication for the benefit
11 // of the public at large and to the detriment of our heirs and
12 // successors. We intend this dedication to be an overt act of
13 // relinquishment in perpetuity of all present and future rights to this
14 // software under copyright law.
15 //
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 // OTHER DEALINGS IN THE SOFTWARE.
23 //
24 // For more information, please refer to <http://unlicense.org/>
25 
26 #ifndef SHEREDOM_UTF8_H_INCLUDED
27 #define SHEREDOM_UTF8_H_INCLUDED
28 
29 #if defined(_MSC_VER)
30 #pragma warning(push)
31 
32 // disable 'bytes padding added after construct' warning
33 #pragma warning(disable : 4820)
34 #endif
35 
36 #include <stddef.h>
37 #include <stdlib.h>
38 
39 #if defined(_MSC_VER)
40 #pragma warning(pop)
41 #endif
42 
43 #if defined(_MSC_VER)
44 #define int32_t __int32
45 #define uint32_t __uint32
46 #else
47 #include <stdint.h>
48 #endif
49 
50 #if defined(__clang__)
51 #pragma clang diagnostic push
52 #pragma clang diagnostic ignored "-Wold-style-cast"
53 #pragma clang diagnostic ignored "-Wcast-qual"
54 #endif
55 
56 #ifdef __cplusplus
57 extern "C" {
58 #endif
59 
60 #if defined(__clang__) || defined(__GNUC__)
61 #define utf8_nonnull __attribute__((nonnull))
62 #define utf8_pure __attribute__((pure))
63 #define utf8_restrict __restrict__
64 #define utf8_weak __attribute__((weak))
65 #elif defined(_MSC_VER)
66 #define utf8_nonnull
67 #define utf8_pure
68 #define utf8_restrict __restrict
69 #define utf8_weak __inline
70 #else
71 #error Non clang, non gcc, non MSVC compiler found!
72 #endif
73 
74  // While ignoring the case of ASCII characters, return less
75  // than 0, 0, greater than 0 if src1 < src2, src1 == src2,
76  // src1 > src2 respectively.
77  utf8_nonnull utf8_pure utf8_weak int utf8casecmp(const void *src1,
78  const void *src2);
79 
80  // Append the utf8 string src onto the utf8 string dst.
81  utf8_nonnull utf8_weak void *utf8cat(void *utf8_restrict dst,
82  const void *utf8_restrict src);
83 
84  // Find the first match of the utf8 codepoint chr in the utf8 string src.
85  utf8_nonnull utf8_pure utf8_weak void *utf8chr(const void *src, int32_t chr);
86 
87  // Return less than 0, 0, greater than 0 if src1 < src2,
88  // src1 == src2, src1 > src2 respectively.
89  utf8_nonnull utf8_pure utf8_weak int utf8cmp(const void *src1,
90  const void *src2);
91 
92  // Copy the utf8 string src onto the memory allocated in dst.
93  utf8_nonnull utf8_weak void *utf8cpy(void *utf8_restrict dst,
94  const void *utf8_restrict src);
95 
96  // Number of utf8 codepoints in the utf8 string src that consists entirely
97  // of utf8 codepoints not from the utf8 string reject.
98  utf8_nonnull utf8_pure utf8_weak size_t utf8cspn(const void *src,
99  const void *reject);
100 
101  // Duplicate the utf8 string src by getting its size, malloc'ing a new buffer
102  // copying over the data, and returning that. Or 0 if malloc failed.
103  utf8_nonnull utf8_weak void *utf8dup(const void *src);
104 
105  // Number of utf8 codepoints in the utf8 string str,
106  // excluding the null terminating byte.
107  utf8_nonnull utf8_pure utf8_weak size_t utf8len(const void *str);
108 
109  // While ignoring the case of ASCII characters, return less
110  // than 0, 0, greater than 0 if src1 < src2, src1 == src2,
111  // src1 > src2 respectively. Checking at most n
112  // bytes of each utf8 string.
113  utf8_nonnull utf8_pure utf8_weak int utf8ncasecmp(const void *src1,
114  const void *src2, size_t n);
115 
116  // Append the utf8 string src onto the utf8 string dst,
117  // writing at most n+1 bytes. Can produce an invalid utf8
118  // string if n falls partway through a utf8 codepoint.
119  utf8_nonnull utf8_weak void *utf8ncat(void *utf8_restrict dst,
120  const void *utf8_restrict src, size_t n);
121 
122  // Return less than 0, 0, greater than 0 if src1 < src2,
123  // src1 == src2, src1 > src2 respectively. Checking at most n
124  // bytes of each utf8 string.
125  utf8_nonnull utf8_pure utf8_weak int utf8ncmp(const void *src1,
126  const void *src2, size_t n);
127 
128  // Copy the utf8 string src onto the memory allocated in dst.
129  // Copies at most n bytes. If there is no terminating null byte in
130  // the first n bytes of src, the string placed into dst will not be
131  // null-terminated. If the size (in bytes) of src is less than n,
132  // extra null terminating bytes are appended to dst such that at
133  // total of n bytes are written. Can produce an invalid utf8
134  // string if n falls partway through a utf8 codepoint.
135  utf8_nonnull utf8_weak void *utf8ncpy(void *utf8_restrict dst,
136  const void *utf8_restrict src, size_t n);
137 
138  // Locates the first occurence in the utf8 string str of any byte in the
139  // utf8 string accept, or 0 if no match was found.
140  utf8_nonnull utf8_pure utf8_weak void *utf8pbrk(const void *str,
141  const void *accept);
142 
143  // Find the last match of the utf8 codepoint chr in the utf8 string src.
144  utf8_nonnull utf8_pure utf8_weak void *utf8rchr(const void *src, int chr);
145 
146  // Number of bytes in the utf8 string str,
147  // including the null terminating byte.
148  utf8_nonnull utf8_pure utf8_weak size_t utf8size(const void *str);
149 
150  // Number of utf8 codepoints in the utf8 string src that consists entirely
151  // of utf8 codepoints from the utf8 string accept.
152  utf8_nonnull utf8_pure utf8_weak size_t utf8spn(const void *src,
153  const void *accept);
154 
155  // The position of the utf8 string needle in the utf8 string haystack.
156  utf8_nonnull utf8_pure utf8_weak void *utf8str(const void *haystack,
157  const void *needle);
158 
159  // The position of the utf8 string needle in the utf8 string haystack, case
160  // instensitive.
161  utf8_nonnull utf8_pure utf8_weak void *utf8casestr(const void *haystack,
162  const void *needle);
163 
164  // Return 0 on success, or the position of the invalid
165  // utf8 codepoint on failure.
166  utf8_nonnull utf8_pure utf8_weak void *utf8valid(const void *str);
167 
168  // Sets out_codepoint to the next utf8 codepoint in str, and returns the address
169  // of the utf8 codepoint after the current one in str.
170  utf8_nonnull utf8_weak void *utf8codepoint(const void *utf8_restrict str,
171  int32_t *utf8_restrict out_codepoint);
172 
173  // Returns the size of the given codepoint in bytes.
174  utf8_weak size_t utf8codepointsize(int32_t chr);
175 
176  // Write a codepoint to the given string, and return the address to the next place
177  // after the written codepoint. Pass how many bytes left in the buffer to n. If there
178  // is not enough space for the codepoint, this function returns null.
179  utf8_nonnull utf8_weak void *utf8catcodepoint(void *utf8_restrict str, int32_t chr, size_t n);
180 
181  // Returns 1 if the given character is lowercase, or 0 if it is not.
182  utf8_weak int utf8islower(int32_t chr);
183 
184  // Returns 1 if the given character is uppercase, or 0 if it is not.
185  utf8_weak int utf8isupper(int32_t chr);
186 
187  // Transform the given string into all lowercase codepoints.
188  utf8_nonnull utf8_weak void utf8lwr(void *utf8_restrict str);
189 
190  // Transform the given string into all uppercase codepoints.
191  utf8_nonnull utf8_weak void utf8upr(void *utf8_restrict str);
192 
193 #undef utf8_weak
194 #undef utf8_pure
195 #undef utf8_nonnull
196 
197  int utf8casecmp(const void *src1, const void *src2) {
198  const unsigned char *s1 = (const unsigned char *)src1;
199  const unsigned char *s2 = (const unsigned char *)src2;
200 
201  while (('\0' != *s1) || ('\0' != *s2)) {
202  unsigned char a = *s1;
203  unsigned char b = *s2;
204 
205  if (('A' <= a) && ('Z' >= a)) {
206  a |= 0x20; // make a lowercase
207  }
208 
209  if (('A' <= b) && ('Z' >= b)) {
210  b |= 0x20; // make b lowercase
211  }
212 
213  if (a < b) {
214  return -1;
215  } else if (a > b) {
216  return 1;
217  }
218 
219  s1++;
220  s2++;
221  }
222 
223  // both utf8 strings matched
224  return 0;
225  }
226 
227  void *utf8cat(void *utf8_restrict dst, const void *utf8_restrict src) {
228  char *d = (char *)dst;
229  const char *s = (const char *)src;
230 
231  // find the null terminating byte in dst
232  while ('\0' != *d) {
233  d++;
234  }
235 
236  // overwriting the null terminating byte in dst, append src byte-by-byte
237  while ('\0' != *s) {
238  *d++ = *s++;
239  }
240 
241  // write out a new null terminating byte into dst
242  *d = '\0';
243 
244  return dst;
245  }
246 
247  void *utf8chr(const void *src, int32_t chr) {
248  char c[5] = {'\0', '\0', '\0', '\0', '\0'};
249 
250  if (0 == chr) {
251  // being asked to return position of null terminating byte, so
252  // just run s to the end, and return!
253  const char *s = (const char *)src;
254  while ('\0' != *s) {
255  s++;
256  }
257  return (void *)s;
258  } else if (0 == ((int32_t)0xffffff80 & chr)) {
259  // 1-byte/7-bit ascii
260  // (0b0xxxxxxx)
261  c[0] = (char)chr;
262  } else if (0 == ((int32_t)0xfffff800 & chr)) {
263  // 2-byte/11-bit utf8 code point
264  // (0b110xxxxx 0b10xxxxxx)
265  c[0] = 0xc0 | (char)(chr >> 6);
266  c[1] = 0x80 | (char)(chr & 0x3f);
267  } else if (0 == ((int32_t)0xffff0000 & chr)) {
268  // 3-byte/16-bit utf8 code point
269  // (0b1110xxxx 0b10xxxxxx 0b10xxxxxx)
270  c[0] = 0xe0 | (char)(chr >> 12);
271  c[1] = 0x80 | (char)((chr >> 6) & 0x3f);
272  c[2] = 0x80 | (char)(chr & 0x3f);
273  } else { // if (0 == ((int)0xffe00000 & chr)) {
274  // 4-byte/21-bit utf8 code point
275  // (0b11110xxx 0b10xxxxxx 0b10xxxxxx 0b10xxxxxx)
276  c[0] = 0xf0 | (char)(chr >> 18);
277  c[1] = 0x80 | (char)((chr >> 12) & 0x3f);
278  c[2] = 0x80 | (char)((chr >> 6) & 0x3f);
279  c[3] = 0x80 | (char)(chr & 0x3f);
280  }
281 
282  // we've made c into a 2 utf8 codepoint string, one for the chr we are
283  // seeking, another for the null terminating byte. Now use utf8str to
284  // search
285  return utf8str(src, c);
286  }
287 
288  int utf8cmp(const void *src1, const void *src2) {
289  const unsigned char *s1 = (const unsigned char *)src1;
290  const unsigned char *s2 = (const unsigned char *)src2;
291 
292  while (('\0' != *s1) || ('\0' != *s2)) {
293  if (*s1 < *s2) {
294  return -1;
295  } else if (*s1 > *s2) {
296  return 1;
297  }
298 
299  s1++;
300  s2++;
301  }
302 
303  // both utf8 strings matched
304  return 0;
305  }
306 
307  int utf8coll(const void *src1, const void *src2);
308 
309  void *utf8cpy(void *utf8_restrict dst, const void *utf8_restrict src) {
310  char *d = (char *)dst;
311  const char *s = (const char *)src;
312 
313  // overwriting anything previously in dst, write byte-by-byte
314  // from src
315  while ('\0' != *s) {
316  *d++ = *s++;
317  }
318 
319  // append null terminating byte
320  *d = '\0';
321 
322  return dst;
323  }
324 
325  size_t utf8cspn(const void *src, const void *reject) {
326  const char *s = (const char *)src;
327  size_t chars = 0;
328 
329  while ('\0' != *s) {
330  const char *r = (const char *)reject;
331  size_t offset = 0;
332 
333  while ('\0' != *r) {
334  // checking that if *r is the start of a utf8 codepoint
335  // (it is not 0b10xxxxxx) and we have successfully matched
336  // a previous character (0 < offset) - we found a match
337  if ((0x80 != (0xc0 & *r)) && (0 < offset)) {
338  return chars;
339  } else {
340  if (*r == s[offset]) {
341  // part of a utf8 codepoint matched, so move our checking
342  // onwards to the next byte
343  offset++;
344  r++;
345  } else {
346  // r could be in the middle of an unmatching utf8 code point,
347  // so we need to march it on to the next character beginning,
348 
349  do {
350  r++;
351  } while (0x80 == (0xc0 & *r));
352 
353  // reset offset too as we found a mismatch
354  offset = 0;
355  }
356  }
357  }
358 
359  // the current utf8 codepoint in src did not match reject, but src
360  // could have been partway through a utf8 codepoint, so we need to
361  // march it onto the next utf8 codepoint starting byte
362  do {
363  s++;
364  } while ((0x80 == (0xc0 & *s)));
365  chars++;
366  }
367 
368  return chars;
369  }
370 
371  size_t utf8size(const void *str);
372 
373  void *utf8dup(const void *src) {
374  const char *s = (const char *)src;
375  char *n = 0;
376 
377  // figure out how many bytes (including the terminator) we need to copy first
378  size_t bytes = utf8size(src);
379 
380  n = (char *)malloc(bytes);
381 
382  if (0 == n) {
383  // out of memory so we bail
384  return 0;
385  } else {
386  bytes = 0;
387 
388  // copy src byte-by-byte into our new utf8 string
389  while ('\0' != s[bytes]) {
390  n[bytes] = s[bytes];
391  bytes++;
392  }
393 
394  // append null terminating byte
395  n[bytes] = '\0';
396  return n;
397  }
398  }
399 
400  void *utf8fry(const void *str);
401 
402  size_t utf8len(const void *str) {
403  const unsigned char *s = (const unsigned char *)str;
404  size_t length = 0;
405 
406  while ('\0' != *s) {
407  if (0xf0 == (0xf8 & *s)) {
408  // 4-byte utf8 code point (began with 0b11110xxx)
409  s += 4;
410  } else if (0xe0 == (0xf0 & *s)) {
411  // 3-byte utf8 code point (began with 0b1110xxxx)
412  s += 3;
413  } else if (0xc0 == (0xe0 & *s)) {
414  // 2-byte utf8 code point (began with 0b110xxxxx)
415  s += 2;
416  } else { // if (0x00 == (0x80 & *s)) {
417  // 1-byte ascii (began with 0b0xxxxxxx)
418  s += 1;
419  }
420 
421  // no matter the bytes we marched s forward by, it was
422  // only 1 utf8 codepoint
423  length++;
424  }
425 
426  return length;
427  }
428 
429  int utf8ncasecmp(const void *src1, const void *src2, size_t n) {
430  const unsigned char *s1 = (const unsigned char *)src1;
431  const unsigned char *s2 = (const unsigned char *)src2;
432 
433  while ((('\0' != *s1) || ('\0' != *s2)) && (0 != n--)) {
434  unsigned char a = *s1;
435  unsigned char b = *s2;
436 
437  if (('A' <= a) && ('Z' >= a)) {
438  a |= 0x20; // make a lowercase
439  }
440 
441  if (('A' <= b) && ('Z' >= b)) {
442  b |= 0x20; // make b lowercase
443  }
444 
445  if (a < b) {
446  return -1;
447  } else if (a > b) {
448  return 1;
449  }
450 
451  s1++;
452  s2++;
453  }
454 
455  // both utf8 strings matched
456  return 0;
457  }
458 
459  void *utf8ncat(void *utf8_restrict dst, const void *utf8_restrict src,
460  size_t n) {
461  char *d = (char *)dst;
462  const char *s = (const char *)src;
463 
464  // find the null terminating byte in dst
465  while ('\0' != *d) {
466  d++;
467  }
468 
469  // overwriting the null terminating byte in dst, append src byte-by-byte
470  // stopping if we run out of space
471  do {
472  *d++ = *s++;
473  } while (('\0' != *s) && (0 != --n));
474 
475  // write out a new null terminating byte into dst
476  *d = '\0';
477 
478  return dst;
479  }
480 
481  int utf8ncmp(const void *src1, const void *src2, size_t n) {
482  const unsigned char *s1 = (const unsigned char *)src1;
483  const unsigned char *s2 = (const unsigned char *)src2;
484 
485  while ((('\0' != *s1) || ('\0' != *s2)) && (0 != n--)) {
486  if (*s1 < *s2) {
487  return -1;
488  } else if (*s1 > *s2) {
489  return 1;
490  }
491 
492  s1++;
493  s2++;
494  }
495 
496  // both utf8 strings matched
497  return 0;
498  }
499 
500  void *utf8ncpy(void *utf8_restrict dst, const void *utf8_restrict src,
501  size_t n) {
502  char *d = (char *)dst;
503  const char *s = (const char *)src;
504 
505  // overwriting anything previously in dst, write byte-by-byte
506  // from src
507  do {
508  *d++ = *s++;
509  } while (('\0' != *s) && (0 != --n));
510 
511  // append null terminating byte
512  while (0 != n) {
513  *d++ = '\0';
514  n--;
515  }
516 
517  return dst;
518  }
519 
520  void *utf8rchr(const void *src, int chr) {
521  const char *s = (const char *)src;
522  const char *match = 0;
523  char c[5] = {'\0', '\0', '\0', '\0', '\0'};
524 
525  if (0 == chr) {
526  // being asked to return position of null terminating byte, so
527  // just run s to the end, and return!
528  while ('\0' != *s) {
529  s++;
530  }
531  return (void *)s;
532  } else if (0 == ((int)0xffffff80 & chr)) {
533  // 1-byte/7-bit ascii
534  // (0b0xxxxxxx)
535  c[0] = (char)chr;
536  } else if (0 == ((int)0xfffff800 & chr)) {
537  // 2-byte/11-bit utf8 code point
538  // (0b110xxxxx 0b10xxxxxx)
539  c[0] = 0xc0 | (char)(chr >> 6);
540  c[1] = 0x80 | (char)(chr & 0x3f);
541  } else if (0 == ((int)0xffff0000 & chr)) {
542  // 3-byte/16-bit utf8 code point
543  // (0b1110xxxx 0b10xxxxxx 0b10xxxxxx)
544  c[0] = 0xe0 | (char)(chr >> 12);
545  c[1] = 0x80 | (char)((chr >> 6) & 0x3f);
546  c[2] = 0x80 | (char)(chr & 0x3f);
547  } else { // if (0 == ((int)0xffe00000 & chr)) {
548  // 4-byte/21-bit utf8 code point
549  // (0b11110xxx 0b10xxxxxx 0b10xxxxxx 0b10xxxxxx)
550  c[0] = 0xf0 | (char)(chr >> 18);
551  c[1] = 0x80 | (char)((chr >> 12) & 0x3f);
552  c[2] = 0x80 | (char)((chr >> 6) & 0x3f);
553  c[3] = 0x80 | (char)(chr & 0x3f);
554  }
555 
556  // we've created a 2 utf8 codepoint string in c that is
557  // the utf8 character asked for by chr, and a null
558  // terminating byte
559 
560  while ('\0' != *s) {
561  size_t offset = 0;
562 
563  while (s[offset] == c[offset]) {
564  offset++;
565  }
566 
567  if ('\0' == c[offset]) {
568  // we found a matching utf8 code point
569  match = s;
570  s += offset;
571  } else {
572  s += offset;
573 
574  // need to march s along to next utf8 codepoint start
575  // (the next byte that doesn't match 0b10xxxxxx)
576  if ('\0' != *s) {
577  do {
578  s++;
579  } while (0x80 == (0xc0 & *s));
580  }
581  }
582  }
583 
584  // return the last match we found (or 0 if no match was found)
585  return (void *)match;
586  }
587 
588  void *utf8pbrk(const void *str, const void *accept) {
589  const char *s = (const char *)str;
590 
591  while ('\0' != *s) {
592  const char *a = (const char *)accept;
593  size_t offset = 0;
594 
595  while ('\0' != *a) {
596  // checking that if *a is the start of a utf8 codepoint
597  // (it is not 0b10xxxxxx) and we have successfully matched
598  // a previous character (0 < offset) - we found a match
599  if ((0x80 != (0xc0 & *a)) && (0 < offset)) {
600  return (void *)s;
601  } else {
602  if (*a == s[offset]) {
603  // part of a utf8 codepoint matched, so move our checking
604  // onwards to the next byte
605  offset++;
606  a++;
607  } else {
608  // r could be in the middle of an unmatching utf8 code point,
609  // so we need to march it on to the next character beginning,
610 
611  do {
612  a++;
613  } while (0x80 == (0xc0 & *a));
614 
615  // reset offset too as we found a mismatch
616  offset = 0;
617  }
618  }
619  }
620 
621  // we found a match on the last utf8 codepoint
622  if (0 < offset) {
623  return (void *)s;
624  }
625 
626  // the current utf8 codepoint in src did not match accept, but src
627  // could have been partway through a utf8 codepoint, so we need to
628  // march it onto the next utf8 codepoint starting byte
629  do {
630  s++;
631  } while ((0x80 == (0xc0 & *s)));
632  }
633 
634  return 0;
635  }
636 
637  size_t utf8size(const void *str) {
638  const char *s = (const char *)str;
639  size_t size = 0;
640  while ('\0' != s[size]) {
641  size++;
642  }
643 
644  // we are including the null terminating byte in the size calculation
645  size++;
646  return size;
647  }
648 
649  size_t utf8spn(const void *src, const void *accept) {
650  const char *s = (const char *)src;
651  size_t chars = 0;
652 
653  while ('\0' != *s) {
654  const char *a = (const char *)accept;
655  size_t offset = 0;
656 
657  while ('\0' != *a) {
658  // checking that if *r is the start of a utf8 codepoint
659  // (it is not 0b10xxxxxx) and we have successfully matched
660  // a previous character (0 < offset) - we found a match
661  if ((0x80 != (0xc0 & *a)) && (0 < offset)) {
662  // found a match, so increment the number of utf8 codepoints
663  // that have matched and stop checking whether any other utf8
664  // codepoints in a match
665  chars++;
666  s += offset;
667  break;
668  } else {
669  if (*a == s[offset]) {
670  offset++;
671  a++;
672  } else {
673  // a could be in the middle of an unmatching utf8 codepoint,
674  // so we need to march it on to the next character beginning,
675  do {
676  a++;
677  } while (0x80 == (0xc0 & *a));
678 
679  // reset offset too as we found a mismatch
680  offset = 0;
681  }
682  }
683  }
684 
685  // if a got to its terminating null byte, then we didn't find a match.
686  // Return the current number of matched utf8 codepoints
687  if ('\0' == *a) {
688  return chars;
689  }
690  }
691 
692  return chars;
693  }
694 
695  void *utf8str(const void *haystack, const void *needle) {
696  const char *h = (const char *)haystack;
697 
698  // if needle has no utf8 codepoints before the null terminating
699  // byte then return haystack
700  if ('\0' == *((const char *)needle)) {
701  return (void *)haystack;
702  }
703 
704  while ('\0' != *h) {
705  const char *maybeMatch = h;
706  const char *n = (const char *)needle;
707 
708  while (*h == *n && (*h != '\0' && *n != '\0')) {
709  n++;
710  h++;
711  }
712 
713  if ('\0' == *n) {
714  // we found the whole utf8 string for needle in haystack at
715  // maybeMatch, so return it
716  return (void *)maybeMatch;
717  } else {
718  // h could be in the middle of an unmatching utf8 codepoint,
719  // so we need to march it on to the next character beginning,
720  if ('\0' != *h) {
721  do {
722  h++;
723  } while (0x80 == (0xc0 & *h));
724  }
725  }
726  }
727 
728  // no match
729  return 0;
730  }
731 
732  void *utf8casestr(const void *haystack, const void *needle) {
733  const char *h = (const char *)haystack;
734 
735  // if needle has no utf8 codepoints before the null terminating
736  // byte then return haystack
737  if ('\0' == *((const char *)needle)) {
738  return (void *)haystack;
739  }
740 
741  while ('\0' != *h) {
742  const char *maybeMatch = h;
743  const char *n = (const char *)needle;
744 
745  for (;;) {
746  char a = *h;
747  char b = *n;
748  // not entirely correct, but good enough
749  if (('A' <= a) && ('Z' >= a)) {
750  a |= 0x20; // make a lowercase
751  }
752 
753  if (('A' <= b) && ('Z' >= b)) {
754  b |= 0x20; // make b lowercase
755  }
756 
757  // if we find a mismatch, bail out!
758  if (a != b) {
759  break;
760  }
761 
762  n++;
763  h++;
764  }
765 
766  if ('\0' == *n) {
767  // we found the whole utf8 string for needle in haystack at
768  // maybeMatch, so return it
769  return (void *)maybeMatch;
770  } else {
771  // h could be in the middle of an unmatching utf8 codepoint,
772  // so we need to march it on to the next character beginning,
773  if ('\0' != *h) {
774  do {
775  h++;
776  } while (0x80 == (0xc0 & *h));
777  }
778  }
779  }
780 
781  // no match
782  return 0;
783  }
784 
785  void *utf8valid(const void *str) {
786  const char *s = (const char *)str;
787 
788  while ('\0' != *s) {
789  if (0xf0 == (0xf8 & *s)) {
790  // ensure each of the 3 following bytes in this 4-byte
791  // utf8 codepoint began with 0b10xxxxxx
792  if ((0x80 != (0xc0 & s[1])) || (0x80 != (0xc0 & s[2])) ||
793  (0x80 != (0xc0 & s[3]))) {
794  return (void *)s;
795  }
796 
797  // ensure that our utf8 codepoint ended after 4 bytes
798  if (0x80 == (0xc0 & s[4])) {
799  return (void *)s;
800  }
801 
802  // ensure that the top 5 bits of this 4-byte utf8
803  // codepoint were not 0, as then we could have used
804  // one of the smaller encodings
805  if ((0 == (0x07 & s[0])) && (0 == (0x30 & s[1]))) {
806  return (void *)s;
807  }
808 
809  // 4-byte utf8 code point (began with 0b11110xxx)
810  s += 4;
811  } else if (0xe0 == (0xf0 & *s)) {
812  // ensure each of the 2 following bytes in this 3-byte
813  // utf8 codepoint began with 0b10xxxxxx
814  if ((0x80 != (0xc0 & s[1])) || (0x80 != (0xc0 & s[2]))) {
815  return (void *)s;
816  }
817 
818  // ensure that our utf8 codepoint ended after 3 bytes
819  if (0x80 == (0xc0 & s[3])) {
820  return (void *)s;
821  }
822 
823  // ensure that the top 5 bits of this 3-byte utf8
824  // codepoint were not 0, as then we could have used
825  // one of the smaller encodings
826  if ((0 == (0x0f & s[0])) && (0 == (0x20 & s[1]))) {
827  return (void *)s;
828  }
829 
830  // 3-byte utf8 code point (began with 0b1110xxxx)
831  s += 3;
832  } else if (0xc0 == (0xe0 & *s)) {
833  // ensure the 1 following byte in this 2-byte
834  // utf8 codepoint began with 0b10xxxxxx
835  if (0x80 != (0xc0 & s[1])) {
836  return (void *)s;
837  }
838 
839  // ensure that our utf8 codepoint ended after 2 bytes
840  if (0x80 == (0xc0 & s[2])) {
841  return (void *)s;
842  }
843 
844  // ensure that the top 4 bits of this 2-byte utf8
845  // codepoint were not 0, as then we could have used
846  // one of the smaller encodings
847  if (0 == (0x1e & s[0])) {
848  return (void *)s;
849  }
850 
851  // 2-byte utf8 code point (began with 0b110xxxxx)
852  s += 2;
853  } else if (0x00 == (0x80 & *s)) {
854  // 1-byte ascii (began with 0b0xxxxxxx)
855  s += 1;
856  } else {
857  // we have an invalid 0b1xxxxxxx utf8 code point entry
858  return (void *)s;
859  }
860  }
861 
862  return 0;
863  }
864 
865  void *utf8codepoint(const void *utf8_restrict str,
866  int32_t *utf8_restrict out_codepoint) {
867  const char *s = (const char *)str;
868 
869  if (0xf0 == (0xf8 & s[0])) {
870  // 4 byte utf8 codepoint
871  *out_codepoint = ((0x07 & s[0]) << 18) | ((0x3f & s[1]) << 12) |
872  ((0x3f & s[2]) << 6) | (0x3f & s[3]);
873  s += 4;
874  } else if (0xe0 == (0xf0 & s[0])) {
875  // 3 byte utf8 codepoint
876  *out_codepoint =
877  ((0x0f & s[0]) << 12) | ((0x3f & s[1]) << 6) | (0x3f & s[2]);
878  s += 3;
879  } else if (0xc0 == (0xe0 & s[0])) {
880  // 2 byte utf8 codepoint
881  *out_codepoint = ((0x1f & s[0]) << 6) | (0x3f & s[1]);
882  s += 2;
883  } else {
884  // 1 byte utf8 codepoint otherwise
885  *out_codepoint = s[0];
886  s += 1;
887  }
888 
889  return (void *)s;
890  }
891 
892  size_t utf8codepointsize(int32_t chr) {
893  if (0 == ((int32_t)0xffffff80 & chr)) {
894  return 1;
895  } else if (0 == ((int32_t)0xfffff800 & chr)) {
896  return 2;
897  } else if (0 == ((int32_t)0xffff0000 & chr)) {
898  return 3;
899  } else { // if (0 == ((int)0xffe00000 & chr)) {
900  return 4;
901  }
902  }
903 
904  void *utf8catcodepoint(void *utf8_restrict str, int32_t chr, size_t n) {
905  char *s = (char *)str;
906 
907  if (0 == ((int32_t)0xffffff80 & chr)) {
908  // 1-byte/7-bit ascii
909  // (0b0xxxxxxx)
910  if (n < 1) {
911  return 0;
912  }
913  s[0] = (char)chr;
914  s += 1;
915  } else if (0 == ((int32_t)0xfffff800 & chr)) {
916  // 2-byte/11-bit utf8 code point
917  // (0b110xxxxx 0b10xxxxxx)
918  if (n < 2) {
919  return 0;
920  }
921  s[0] = 0xc0 | (char)(chr >> 6);
922  s[1] = 0x80 | (char)(chr & 0x3f);
923  s += 2;
924  } else if (0 == ((int32_t)0xffff0000 & chr)) {
925  // 3-byte/16-bit utf8 code point
926  // (0b1110xxxx 0b10xxxxxx 0b10xxxxxx)
927  if (n < 3) {
928  return 0;
929  }
930  s[0] = 0xe0 | (char)(chr >> 12);
931  s[1] = 0x80 | (char)((chr >> 6) & 0x3f);
932  s[2] = 0x80 | (char)(chr & 0x3f);
933  s += 3;
934  } else { // if (0 == ((int)0xffe00000 & chr)) {
935  // 4-byte/21-bit utf8 code point
936  // (0b11110xxx 0b10xxxxxx 0b10xxxxxx 0b10xxxxxx)
937  if (n < 4) {
938  return 0;
939  }
940  s[0] = 0xf0 | (char)(chr >> 18);
941  s[1] = 0x80 | (char)((chr >> 12) & 0x3f);
942  s[2] = 0x80 | (char)((chr >> 6) & 0x3f);
943  s[3] = 0x80 | (char)(chr & 0x3f);
944  s += 4;
945  }
946 
947  return s;
948  }
949 
950  int utf8islower(int32_t chr)
951  {
952  if (('A' <= chr) && ('Z' >= chr)) {
953  return 0;
954  }
955  // Because we're not all-inclusive, assume everything else is lowercase
956  return 1;
957  }
958 
959  int utf8isupper(int32_t chr)
960  {
961  if (('A' <= chr) && ('Z' >= chr)) {
962  return 1;
963  }
964  return 0;
965  }
966 
967  void utf8lwr(void *utf8_restrict str)
968  {
969  void *p, *pn;
970  int cp;
971 
972  p = (char *)str;
973  pn = utf8codepoint(p, &cp);
974 
975  while (cp != 0) {
976  if (('A' <= cp) && ('Z' >= cp)) {
977  cp |= 0x20;
978  utf8catcodepoint(p, cp, 1);
979  }
980  p = pn;
981  pn = utf8codepoint(p, &cp);
982  }
983  }
984 
985  void utf8upr(void *utf8_restrict str)
986  {
987  void *p, *pn;
988  int cp;
989 
990  p = (char *)str;
991  pn = utf8codepoint(p, &cp);
992 
993  while (cp != 0) {
994  if (('a' <= cp) && ('z' >= cp)) {
995  cp &= ~0x20;
996  utf8catcodepoint(p, cp, 1);
997  }
998  p = pn;
999  pn = utf8codepoint(p, &cp);
1000  }
1001  }
1002 
1003 #undef utf8_restrict
1004 
1005 #ifdef __cplusplus
1006 } // extern "C"
1007 #endif
1008 
1009 #if defined(__clang__)
1010 #pragma clang diagnostic pop
1011 #endif
1012 
1013 #endif // SHEREDOM_UTF8_H_INCLUDED
utf8_nonnull utf8_pure utf8_weak int utf8casecmp(const void *src1, const void *src2)
Definition: utf8.h:197
utf8_nonnull utf8_pure utf8_weak void * utf8valid(const void *str)
Definition: utf8.h:785
utf8_nonnull utf8_weak void * utf8cpy(void *utf8_restrict dst, const void *utf8_restrict src)
Definition: utf8.h:309
utf8_nonnull utf8_weak void * utf8catcodepoint(void *utf8_restrict str, int32_t chr, size_t n)
Definition: utf8.h:904
voidpf void uLong size
Definition: ioapi.h:39
utf8_nonnull utf8_pure utf8_weak int utf8ncmp(const void *src1, const void *src2, size_t n)
Definition: utf8.h:481
char * dst
Definition: lz4.h:464
utf8_nonnull utf8_pure utf8_weak void * utf8rchr(const void *src, int chr)
Definition: utf8.h:520
utf8_nonnull utf8_pure utf8_weak void * utf8str(const void *haystack, const void *needle)
Definition: utf8.h:695
utf8_weak int utf8islower(int32_t chr)
Definition: utf8.h:950
utf8_nonnull utf8_pure utf8_weak void * utf8pbrk(const void *str, const void *accept)
Definition: utf8.h:588
utf8_nonnull utf8_pure utf8_weak void * utf8chr(const void *src, int32_t chr)
Definition: utf8.h:247
void * utf8fry(const void *str)
utf8_nonnull utf8_weak void utf8upr(void *utf8_restrict str)
Definition: utf8.h:985
utf8_nonnull utf8_pure utf8_weak int utf8ncasecmp(const void *src1, const void *src2, size_t n)
Definition: utf8.h:429
utf8_nonnull utf8_weak void * utf8ncpy(void *utf8_restrict dst, const void *utf8_restrict src, size_t n)
Definition: utf8.h:500
utf8_weak size_t utf8codepointsize(int32_t chr)
Definition: utf8.h:892
utf8_nonnull utf8_weak void * utf8cat(void *utf8_restrict dst, const void *utf8_restrict src)
Definition: utf8.h:227
utf8_nonnull utf8_pure utf8_weak size_t utf8cspn(const void *src, const void *reject)
Definition: utf8.h:325
utf8_nonnull utf8_weak void * utf8codepoint(const void *utf8_restrict str, int32_t *utf8_restrict out_codepoint)
Definition: utf8.h:865
utf8_nonnull utf8_pure utf8_weak void * utf8casestr(const void *haystack, const void *needle)
Definition: utf8.h:732
utf8_nonnull utf8_pure utf8_weak size_t utf8spn(const void *src, const void *accept)
Definition: utf8.h:649
utf8_nonnull utf8_weak void * utf8ncat(void *utf8_restrict dst, const void *utf8_restrict src, size_t n)
Definition: utf8.h:459
utf8_nonnull utf8_pure utf8_weak size_t utf8len(const void *str)
Definition: utf8.h:402
utf8_nonnull utf8_pure utf8_weak size_t utf8size(const void *str)
Definition: utf8.h:637
utf8_weak int utf8isupper(int32_t chr)
Definition: utf8.h:959
voidpf uLong offset
Definition: ioapi.h:42
int utf8coll(const void *src1, const void *src2)
utf8_nonnull utf8_weak void utf8lwr(void *utf8_restrict str)
Definition: utf8.h:967
utf8_nonnull utf8_weak void * utf8dup(const void *src)
Definition: utf8.h:373
utf8_nonnull utf8_pure utf8_weak int utf8cmp(const void *src1, const void *src2)
Definition: utf8.h:288

Document ID: Generated on Thu Jun 1 17:58:13 EDT 2023 from SVN revision 255404
Copyright © 2005-2021 MAK Technologies. All Rights Reserved (www.mak.com)