VR-Forces 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
DT_DLL_VRVCORE double length(const makVrv::DtCoordinateSystem &, const std::vector< DtVector > &vertices)
Returns the total distance of a segmented line defined by the provided vector of vertices. Coordinates are in local database coordinates. The coordinate system is used to convert between the local database coordinates and geocentric. All distance is in 2D – the Z value is ignored.
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 Oct 23 22:29:17 EDT 2025 from SVN revision 280951
Copyright © 2005-2024 MAK Technologies. All Rights Reserved (www.mak.com)