acme
Foundational cross-platform layer of the ca2 framework
Loading...
Searching...
No Matches
unicode_impl.h
1// Refactored by camilo on 2022-11-04 05:43 <3ThomasBorregaardSorensen!!
2#pragma once
3
4
5inline ::i32 get_utf8_char_length(const_char_pointer psz)
6{
7
8 ::i32 len = utf8_unicode_length(*psz);
9 if (len == 0) return 0;
10 if (*psz++ == 0)
11 {
12 return -1;
13 }
14 if (len == 1) return 1;
15 if (*psz++ == 0)
16 {
17 return -1;
18 }
19 if (len == 2) return 2;
20 if (*psz++ == 0)
21 {
22 return -1;
23 }
24 if (len == 3) return 3;
25 if (*psz++ == 0)
26 {
27 return -1;
28 }
29 if (len == 4) return 4;
30 if (*psz++ == 0)
31 {
32 return -1;
33 }
34 if (len == 5) return 5;
35 if (*psz++ == 0)
36 {
37 return -1;
38 }
39 if (len == 6) return 6;
40
41 {
42 return -1;
43 }
44 return -1;
45}
46
47
48
49
50//inline ::i32 unicode_index(const_char_pointer &input, character_count * psrclen)
51//{
52//
53// if (*input == 0)
54// {
55//
56// return 0;
57//
58// }
59//
60// if (*psrclen < 1)
61// {
62//
63// return -1;
64//
65// }
66//
67// ::wd32_character ::u32;
68//
69// character_count used_len = ansi_to_wd32_char(&::u32, input, *psrclen);
70//
71// if (used_len < 0)
72// {
73//
74// return -1;
75//
76// }
77//
78// input += used_len;
79//
80// *psrclen -= used_len;
81//
82// return ::u32;
83//
84//}
85//
86//
87//inline ::i32 unicode_index(const ::wd16_character *& input, character_count * psrclen)
88//{
89//
90// if (*input == 0)
91// {
92//
93// return 0;
94//
95// }
96//
97// if (*psrclen < 1)
98// {
99//
100// return -1;
101//
102// }
103//
104// ::i32 i = *input;
105//
106// ::wd32_character ::u32;
107//
108// character_count used_len = wd16_to_wd32_char(&::u32, input, *psrclen);
109//
110// input += used_len;
111//
112// *psrclen -= used_len;
113//
114// return i;
115//
116//}
117
118
119inline ::i32 unicode_index_length(const ::wd32_character *& input, character_count * psrclen)
120{
121
122 if (*input == 0)
123 {
124
125 return 0;
126
127 }
128
129 if (*psrclen < 1)
130 {
131
132 return -1;
133
134 }
135
136 ::i32 i = *input;
137
138 input++;
139
140 (*psrclen)--;
141
142 return i;
143
144}
145
146
147inline ::i32 unicode_index_length(const_char_pointer pszUtf8, ::i32 & len)
148{
149
150 if (is_empty(pszUtf8))
151 {
152
153 len = 0;
154
155 return 0;
156
157 }
158
159 ::i32 ch = 0;
160
161 ::u8 c;
162
163 len = 0;
164
165 ::i8 extraBytesToRead = utf8_e(*pszUtf8);
166
167 switch (extraBytesToRead)
168 {
169 case 5:
170 ch += c = pszUtf8[len++]; ch <<= 6;
171 if (c == '\0') { return -1; }
172 case 4:
173 ch += c = pszUtf8[len++]; ch <<= 6;
174 if (c == '\0') { return -1; }
175 case 3:
176 ch += c = pszUtf8[len++]; ch <<= 6;
177 if (c == '\0') { return -1; }
178 case 2:
179 ch += c = pszUtf8[len++]; ch <<= 6;
180 if (c == '\0') { return -1; }
181 case 1:
182 ch += c = pszUtf8[len++]; ch <<= 6;
183 if (c == '\0') { return -1; }
184 case 0:
185 ch += c = pszUtf8[len++];
186 if (c == '\0') { return -1; }
187 }
188
189 ch -= utf8_o(extraBytesToRead);
190
191 return ch;
192
193}
194
195
196inline ::i32 consume_unicode_index(const_char_pointer &pszUtf8)
197{
198
199 ::i32 len = 0;
200
201 auto i = unicode_index_length(pszUtf8, len);
202
203 if(i < 0)
204 {
205
206 throw_parsing_exception("end of string or not valid character to parse");
207
208 }
209
210 pszUtf8 += len;
211
212 return i;
213
214}
215
216
217inline ::i32 unicode_index_length(const ::wd16_character * input, ::i32 & len)
218{
219
220 if (input[0] == 0)
221 {
222
223 len = 0;
224
225 return 0;
226
227 }
228
229 if (utf16_is_2nd_surrogate(input[0]))
230 {
231
232 len = -1;
233
234 return -1;
235
236 }
237 else if (utf16_is_1st_surrogate(input[0]))
238 {
239
240 if (utf16_is_2nd_surrogate(input[1]))
241 {
242
243 len = 2;
244
245 return utf16_surrogate_to_utf32(input[0], input[1]);
246
247 }
248 else
249 {
250
251 len = -1;
252
253 return -1;
254
255 }
256
257 }
258 else
259 {
260
261 len = 1;
262
263 return input[0];
264
265 }
266
267}
268
269
270inline bool is_legal_unicode_index(::i32 iUnicodeIndex)
271{
272
273 return iUnicodeIndex >= 0 && iUnicodeIndex < 65536 ? true : false;
274
275 //return ca >= ((::u64) 0xffffffffu) ? false : true;
276
277}
278
279
280inline ::i32 unicode_to_lower_case(::i32 i)
281{
282 if (!is_legal_unicode_index(i))
283 return -1;
284 ::u32 c1 = CHAR_PROP(i);
285 if (CHAR_CATEGORY(c1) == CHAR_CATEGORY_Ll) return (::wd32_character)i;
286 if (CHAR_CATEGORY(c1) == CHAR_CATEGORY_Lt) return (::wd32_character)(i + 1);
287 return ::wd32_character(i - (c1 >> 16));
288}
289
290
291inline ::i32 unicode_to_upper_case(::i32 i)
292{
293 if (!is_legal_unicode_index(i))
294 return -1;
295 ::u32 c1 = CHAR_PROP(i);
296 if (CHAR_CATEGORY(c1) == CHAR_CATEGORY_Lu) return ::wd32_character(i);
297 if (CHAR_CATEGORY(c1) == CHAR_CATEGORY_Lt) return ::wd32_character(i - 1);
298 return ::wd32_character(i - (c1 >> 16));
299}
300
301
302//template < prototype_character CHARACTER >
303//inline const CHARACTER * string_scan(const ::range < CHARACTER > & block, const ::range < CHARACTER > & blockCharacters) noexcept
304//{
305//
306// const CHARACTER * psz;
307//
308// if (_string_scan_prefix(scopedstr, block, blockCharacters))
309// {
310//
311// return psz;
312//
313// }
314//
315// return _string_scan(block, blockCharacters);
316//
317//}
318
319
320//inline const_char_pointer _string_scan(const array_range < ::ansi_character > & block, const array_range < ::ansi_character > & blockCharacters) noexcept
321//{
322//
323// return ansi_scan(block, blockCharacters);
324//
325//}
326//
327//
328//inline const ::wd16_character * _string_scan(const ::array_range < ::wd16_character > & block, const ::array_range < ::wd16_character > & blockCharacters) noexcept
329//{
330//
331// return wd16_scan(block, blockCharacters);
332//
333//}
334
335
336inline const ::wd32_character * wd32_find_first_character_in(const ::const_wd32_range & block, const ::const_wd32_range & blockCharacters)
337{
338
339 //if (block.is_null_terminated() && blockCharacters.is_null_terminated())
340 //{
341
342 // return wd32_pbrk((::wd32_character *)block.data(), blockCharacters.data());
343
344 //}
345 //else
346 //{
347
348 return block.find_first_character_in(blockCharacters, ::comparison::comparison < ::wd32_character >());
349
350// }
351
352}
353
354
355inline ::i32 unicode_to_title_case(::i32 i)
356{
357 if (!is_legal_unicode_index(i))
358 return -1;
359 ::u32 c1 = CHAR_PROP(i);
360 if (TITLE_CASE(c1)) // titlecase exists
361 {
362 if (CHAR_CATEGORY(c1) == CHAR_CATEGORY_Lu) return ::wd32_character(i + 1);
363 if (CHAR_CATEGORY(c1) == CHAR_CATEGORY_Ll) return ::wd32_character(i - 1);
364 return ::wd32_character(i);
365 }
366 else // has no titlecase form
367 if (CHAR_CATEGORY(c1) == CHAR_CATEGORY_Ll)
368 return ::wd32_character(i - (c1 >> 16));
369 return ::wd32_character(i);
370}
371
372
373inline ::i32 unicode_to_numeric_value(::i32 i, ::f32 * f)
374{
375 if (!is_legal_unicode_index(i))
376 return false;
377 ::u32 c1 = CHAR_PROP(i);
378 if (!NUMBER(c1)) return false;
379 *f = CHAR_PROP2(i);
380 return true;
381}
382
383
384inline bool unicode_is_lower_case(::i32 i)
385{
386 if (!is_legal_unicode_index(i))
387 return false;
388 return CHAR_CATEGORY(CHAR_PROP(i)) == CHAR_CATEGORY_Ll;
389}
390
391
392inline bool unicode_is_upper_case(::i32 i)
393{
394 if (!is_legal_unicode_index(i))
395 return false;
396 return CHAR_CATEGORY(CHAR_PROP(i)) == CHAR_CATEGORY_Lu;
397}
398
399
400inline bool unicode_is_title_case(::i32 i)
401{
402 if (!is_legal_unicode_index(i))
403 return false;
404 return CHAR_CATEGORY(CHAR_PROP(i)) == CHAR_CATEGORY_Lt;
405}
406
407
408inline bool unicode_is_letter(::i32 i)
409{
410 if (!is_legal_unicode_index(i))
411 return false;
412 ::u32 c1 = CHAR_CATEGORY(CHAR_PROP(i));
413 return ((((1 << CHAR_CATEGORY_Lu) |
414 (1 << CHAR_CATEGORY_Ll) |
415 (1 << CHAR_CATEGORY_Lt) |
416 (1 << CHAR_CATEGORY_Lm) |
417 (1 << CHAR_CATEGORY_Lo)
418 ) >> c1) & 1) != 0;
419}
420
421
422inline bool unicode_is_letter_or_digit(::i32 i)
423{
424 if (!is_legal_unicode_index(i))
425 return false;
426 ::u32 c1 = CHAR_CATEGORY(CHAR_PROP(i));
427 return ((((1 << CHAR_CATEGORY_Lu) |
428 (1 << CHAR_CATEGORY_Ll) |
429 (1 << CHAR_CATEGORY_Lt) |
430 (1 << CHAR_CATEGORY_Lm) |
431 (1 << CHAR_CATEGORY_Lo) |
432 (1 << CHAR_CATEGORY_Nd)
433 ) >> c1) & 1) != 0;
434}
435
436
437inline bool unicode_is_digit(::i32 i)
438{
439
440 if (!is_legal_unicode_index(i))
441 return false;
442
443 return CHAR_CATEGORY(CHAR_PROP(i)) == CHAR_CATEGORY_Nd;
444
445}
446
447
448inline bool unicode_is_assigned(::i32 i)
449{
450 if (!is_legal_unicode_index(i))
451 return false;
452 return CHAR_CATEGORY(CHAR_PROP(i)) != CHAR_CATEGORY_Cn;
453}
454
455
456inline bool unicode_is_space_char(::i32 i)
457{
458 if (!is_legal_unicode_index(i))
459 return false;
460 return ((((1 << CHAR_CATEGORY_Zs) |
461 (1 << CHAR_CATEGORY_Zl) |
462 (1 << CHAR_CATEGORY_Zp)
463 ) >> CHAR_CATEGORY(CHAR_PROP(i))) & 1) != 0;
464}
465
466
467inline bool unicode_is_whitespace(::i32 i)
468{
469 if (!is_legal_unicode_index(i))
470 return false;
471 return (i == 0x20)
472 ||
473 ((i <= 0x0020) &&
474 (((((1 << 0x0009) |
475 (1 << 0x000A) |
476 (1 << 0x000C) |
477 (1 << 0x000D)) >> i) & 1) != 0))
478 ||
479 (((((1 << CHAR_CATEGORY_Zs) |
480 (1 << CHAR_CATEGORY_Zl) |
481 (1 << CHAR_CATEGORY_Zp)
482 ) >> CHAR_CATEGORY(CHAR_PROP(i))) & 1) != 0);
483}
484
485
486inline bool unicode_is_number(::i32 i)
487{
488 if (!is_legal_unicode_index(i))
489 return false;
490 return NUMBER(CHAR_PROP(i)) != 0;
491}
492
493
494inline ECharCategory unicode_get_category(::i32 i)
495{
496 if (!is_legal_unicode_index(i))
497 return CHAR_CATEGORY_LAST;
498 return ECharCategory(CHAR_CATEGORY(CHAR_PROP(i)));
499}
500
501
502inline ::i32 unicode_get_combining_class(::i32 i)
503{
504 if (!is_legal_unicode_index(i))
505 return false;
506 return COMBINING_CLASS(CHAR_PROP(i));
507}
508
509
510inline bool unicode_is_mirrored(::i32 i)
511{
512
513 if (!is_legal_unicode_index(i))
514 return false;
515
516 return MIRRORED(CHAR_PROP(i)) != 0;
517
518}
519
520
521inline ::i32 unicode_size_of_tables()
522{
523
524 return sizeof(arr_idxCharInfo) + sizeof(arr_CharInfo) + sizeof(arr_idxCharInfo2) + sizeof(arr_CharInfo2);
525
526}
527
528
529template < typename CHARACTER, typename CHARACTER_COUNT >
530[[nodiscard]] inline CHARACTER * unicode_next(CHARACTER *psz, CHARACTER_COUNT *piRemaining)
531 requires(sizeof(CHARACTER) == 1)
532{
533
534 if (*psz == '\0')
535 {
536
537 return psz;
538
539 }
540
541 ::i8 len = 1 + trailingBytesForUTF8(*psz);
542
543 if (len == 0) return psz;
544
545 if(piRemaining && len > *piRemaining)
546 {
547
548 throw_encoding_exception("no remaining characters for decoding utf8 encoded string (0)");
549
550 return nullptr;
551
552 }
553
554 if (*psz++ == 0)
555 {
556
557 throw_encoding_exception("premature end of utf8 encoded string (1)");
558
559 return nullptr;
560
561 }
562
563 if (len == 1)
564 {
565
566 if(piRemaining)
567 {
568
569 *piRemaining -= 1;
570
571 }
572
573 return psz;
574
575 }
576
577 if (*psz++ == 0)
578 {
579
580 throw_encoding_exception("premature end of utf8 encoded string (2)");
581
582 return nullptr;
583
584 }
585
586 if (len == 2)
587 {
588
589 if(piRemaining)
590 {
591
592 *piRemaining -= 2;
593
594 }
595
596 return psz;
597
598 }
599
600 if (*psz++ == 0)
601 {
602
603 throw_encoding_exception("premature end of utf8 encoded string (3)");
604
605 return nullptr;
606
607 }
608
609 if (len == 3)
610 {
611
612 if(piRemaining)
613 {
614
615 *piRemaining -= 3;
616
617 }
618
619 return psz;
620
621 }
622
623 if (*psz++ == 0)
624 {
625
626 throw_encoding_exception("premature end of utf8 encoded string (4)");
627
628 return nullptr;
629
630 }
631
632 if (len == 4)
633 {
634
635 if(piRemaining)
636 {
637
638 *piRemaining -= 4;
639
640 }
641
642 return psz;
643
644 }
645
646 if (*psz++ == 0)
647 {
648
649 throw_encoding_exception("premature end of utf8 encoded string (5)");
650
651 return nullptr;
652
653 }
654
655 if (len == 5)
656 {
657
658 if(piRemaining)
659 {
660
661 *piRemaining -= 5;
662
663 }
664
665 return psz;
666
667 }
668
669 if (*psz++ == 0)
670 {
671
672 throw_encoding_exception("premature end of utf8 encoded string (6)");
673
674 return nullptr;
675
676 }
677
678 if (len == 6)
679 {
680
681 if(piRemaining)
682 {
683
684 *piRemaining -= 6;
685
686 }
687
688 return psz;
689
690 }
691
692 throw_encoding_exception("premature end of utf8 encoded string (7)");
693
694 return nullptr;
695
696}
697
698
699// inline const_char_pointer unicode_next(const_char_pointer psz, ::i32 * piError)
700// {
701
702// if (psz == nullptr)
703// {
704
705// return nullptr;
706
707// }
708
709// if (*psz == '\0')
710// {
711
712// return psz;
713
714// }
715
716// *piError = 0;
717
718// ::i8 len = 1 + trailingBytesForUTF8(*psz);
719
720// if (len == 0) return psz;
721
722// if (*psz++ == 0)
723// {
724
725// *piError = 1;
726
727// return nullptr;
728
729// }
730
731// if (len == 1) return psz;
732
733// if (*psz++ == 0)
734// {
735
736// *piError = 2;
737
738// return nullptr;
739
740// }
741
742// if (len == 2) return psz;
743
744// if (*psz++ == 0)
745// {
746
747// *piError = 3;
748
749// return nullptr;
750
751// }
752
753// if (len == 3) return psz;
754
755// if (*psz++ == 0)
756// {
757
758// *piError = 4;
759
760// return nullptr;
761
762// }
763
764// if (len == 4) return psz;
765
766// if (*psz++ == 0)
767// {
768
769// *piError = 5;
770
771// return nullptr;
772
773// }
774
775// if (len == 5) return psz;
776
777// if (*psz++ == 0)
778// {
779
780// *piError = 6;
781
782// return nullptr;
783
784// }
785
786// if (len == 6) return psz;
787
788// *piError = 7;
789
790// return nullptr;
791
792// }
793
794
795template < typename CHARACTER, typename CHARACTER_COUNT >
796inline CHARACTER * unicode_next(CHARACTER *psz, CHARACTER_COUNT *piRemaining)
797 requires(sizeof(CHARACTER) == 2)
798{
799
800 if (*psz == '\0')
801 {
802
803 return psz;
804
805 }
806
807 if(piRemaining && *piRemaining < 1)
808 {
809
810 throw_encoding_exception("no remaining characters for decoding wd16 encoded string (0)");
811
812 }
813
814 const ::wd16_character uc = *psz++;
815
816 if (!utf16_is_surrogate(uc))
817 {
818
819 if(piRemaining)
820 {
821
822 (*piRemaining)--;
823
824 }
825
826 }
827 else
828 {
829
830 if (utf16_is_1st_surrogate(uc) && utf16_is_2nd_surrogate(*psz))
831 {
832
833 if(piRemaining)
834 {
835
836 if(*piRemaining < 2)
837 {
838
839 throw_encoding_exception("no remaining characters for decoding wd16 encoded string (1)");
840
841 }
842
843 *piRemaining -= 2;
844
845 }
846
847 psz++;
848
849 }
850 else
851 {
852
853 throw_encoding_exception("expected surrogate got bad wd16 surrogate (2)");
854
855 }
856
857 }
858
859 return psz;
860
861}
862
863
864template < typename CHARACTER, typename CHARACTER_COUNT >
865inline CHARACTER *unicode_next(CHARACTER *psz, CHARACTER_COUNT *piRemaining)
866 requires(sizeof(CHARACTER) == 4)
867{
868
869 if (*psz == '\0')
870 {
871
872 return psz;
873
874 }
875
876 if(piRemaining && *piRemaining < 1)
877 {
878
879 throw_encoding_exception("no remaining characters for decoding wd32 encoded string (0)");
880
881 }
882
883 return psz + 1;
884
885}
886
887
888template < typename CHARACTER >
889inline CHARACTER * unicode_prior(CHARACTER *psz, const non_const < CHARACTER > * pszBegin)
890 requires(sizeof(CHARACTER) == 1)
891{
892
893 if (psz <= pszBegin)
894 {
895
896 throw_encoding_exception("bad argument for prior decoding utf8 encoded string (A)");
897
898 return nullptr;
899
900 }
901
902 if ((*(psz - 1) & 0x80) == 0x00)
903 {
904
905 if ((psz - 1) < pszBegin)
906 {
907
908 throw_encoding_exception("no preceding characters for prior decoding utf8 encoded string (0)");
909
910 return nullptr;
911
912 }
913
914 if(*(psz - 1) == '\0')
915 {
916
917 throw_encoding_exception("first preceding character is nil for prior decoding utf8 encoded string (0)");
918
919 return nullptr;
920
921 }
922
923 return psz - 1;
924
925 }
926 else if ((*(psz - 2) & 0xE0) == 0xC0)
927 {
928
929 if ((psz - 2) < pszBegin)
930 {
931
932 throw_encoding_exception("not enough preceding characters for prior decoding utf8 encoded string (1)");
933
934 return nullptr;
935
936 }
937
938 if(*(psz - 1) == '\0')
939 {
940
941 throw_encoding_exception("first preceding character is nil for prior decoding utf8 encoded string (1)");
942
943 return nullptr;
944
945 }
946 else if(*(psz - 2) == '\0')
947 {
948
949 throw_encoding_exception("second preceding character is nil for prior decoding utf8 encoded string (1)");
950
951 return nullptr;
952
953 }
954
955 return psz - 2;
956
957 }
958 else if ((*(psz - 3) & 0xF0) == 0xE0)
959 {
960
961 if ((psz - 3) < pszBegin)
962 {
963
964 throw_encoding_exception("not enough preceding characters for prior decoding utf8 encoded string (2)");
965
966 return nullptr;
967
968 }
969
970 if(*(psz - 1) == '\0')
971 {
972
973 throw_encoding_exception("first preceding character is nil for prior decoding utf8 encoded string (2)");
974
975 return nullptr;
976
977 }
978 else if(*(psz - 2) == '\0')
979 {
980
981 throw_encoding_exception("second preceding character is nil for prior decoding utf8 encoded string (2)");
982
983 return nullptr;
984
985 }
986 else if(*(psz - 3) == '\0')
987 {
988
989 throw_encoding_exception("third preceding character is nil for prior decoding utf8 encoded string (2)");
990
991 return nullptr;
992
993 }
994
995 return psz - 3;
996
997 }
998 else if ((*(psz - 4) & 0xF8) == 0xF0)
999 {
1000
1001 if ((psz - 4) < pszBegin)
1002 {
1003
1004 throw_encoding_exception("not enough preceding characters for prior decoding utf8 encoded string (3)");
1005
1006 return nullptr;
1007
1008 }
1009
1010 if(*(psz - 1) == '\0')
1011 {
1012
1013 throw_encoding_exception("first preceding character is nil for prior decoding utf8 encoded string (3)");
1014
1015 return nullptr;
1016
1017 }
1018 else if(*(psz - 2) == '\0')
1019 {
1020
1021 throw_encoding_exception("second preceding character is nil for prior decoding utf8 encoded string (3)");
1022
1023 return nullptr;
1024
1025 }
1026 else if(*(psz - 3) == '\0')
1027 {
1028
1029 throw_encoding_exception("third preceding character is nil for prior decoding utf8 encoded string (3)");
1030
1031 return nullptr;
1032
1033 }
1034 else if(*(psz - 4) == '\0')
1035 {
1036
1037 throw_encoding_exception("fourth preceding character is nil for prior decoding utf8 encoded string (3)");
1038
1039 return nullptr;
1040
1041 }
1042
1043 return psz - 4;
1044
1045 }
1046 else if ((*(psz - 5) & 0xFC) == 0xF8)
1047 {
1048
1049 if ((psz - 5) < pszBegin)
1050 {
1051
1052 throw_encoding_exception("not enough preceding characters for prior decoding utf8 encoded string (4)");
1053
1054 return nullptr;
1055
1056 }
1057
1058 if(*(psz - 1) == '\0')
1059 {
1060
1061 throw_encoding_exception("first preceding character is nil for prior decoding utf8 encoded string (4)");
1062
1063 return nullptr;
1064
1065 }
1066 else if(*(psz - 2) == '\0')
1067 {
1068
1069 throw_encoding_exception("second preceding character is nil for prior decoding utf8 encoded string (4)");
1070
1071 return nullptr;
1072
1073 }
1074 else if(*(psz - 3) == '\0')
1075 {
1076
1077 throw_encoding_exception("third preceding character is nil for prior decoding utf8 encoded string (4)");
1078
1079 return nullptr;
1080
1081 }
1082 else if(*(psz - 4) == '\0')
1083 {
1084
1085 throw_encoding_exception("fourth preceding character is nil for prior decoding utf8 encoded string (4)");
1086
1087 return nullptr;
1088
1089 }
1090 else if(*(psz - 5) == '\0')
1091 {
1092
1093 throw_encoding_exception("fifth preceding character is nil for prior decoding utf8 encoded string (4)");
1094
1095 return nullptr;
1096
1097 }
1098
1099 return psz - 5;
1100
1101 }
1102 else if ((*(psz - 6) & 0xFE) == 0xFC)
1103 {
1104
1105 if ((psz - 6) < pszBegin)
1106 {
1107
1108 throw_encoding_exception("not enough preceding characters for prior decoding utf8 encoded string (5)");
1109
1110 return nullptr;
1111
1112 }
1113
1114 if(*(psz - 1) == '\0')
1115 {
1116
1117 throw_encoding_exception("first preceding character is nil for prior decoding utf8 encoded string (5)");
1118
1119 return nullptr;
1120
1121 }
1122 else if(*(psz - 2) == '\0')
1123 {
1124
1125 throw_encoding_exception("second preceding character is nil for prior decoding utf8 encoded string (5)");
1126
1127 return nullptr;
1128
1129 }
1130 else if(*(psz - 3) == '\0')
1131 {
1132
1133 throw_encoding_exception("third preceding character is nil for prior decoding utf8 encoded string (5)");
1134
1135 return nullptr;
1136
1137 }
1138 else if(*(psz - 4) == '\0')
1139 {
1140
1141 throw_encoding_exception("fourth preceding character is nil for prior decoding utf8 encoded string (5)");
1142
1143 return nullptr;
1144
1145 }
1146 else if(*(psz - 5) == '\0')
1147 {
1148
1149 throw_encoding_exception("fifth preceding character is nil for prior decoding utf8 encoded string (5)");
1150
1151 return nullptr;
1152
1153 }
1154 else if(*(psz - 6) == '\0')
1155 {
1156
1157 throw_encoding_exception("sixth preceding character is nil for prior decoding utf8 encoded string (5)");
1158
1159 return nullptr;
1160
1161 }
1162
1163 return psz - 6;
1164
1165 }
1166
1167 throw_encoding_exception("bad utf8 encoding (6)");
1168
1169 return nullptr;
1170
1171}
1172
1173
1174template < typename CHARACTER >
1175inline CHARACTER * unicode_prior(CHARACTER *psz, const non_const < CHARACTER > * pszBegin)
1176 requires(sizeof(CHARACTER) == 2)
1177{
1178
1179 if (psz <= pszBegin)
1180 {
1181
1182 throw_encoding_exception("no preceding characters for prior decoding wd16 encoded string (0)");
1183
1184 return nullptr;
1185
1186 }
1187
1188 if (utf16_is_2nd_surrogate(*(psz - 1)))
1189 {
1190
1191 if (psz - 2 <= pszBegin)
1192 {
1193
1194 throw_encoding_exception("no preceding characters for prior decoding wd16 encoded string (1)");
1195
1196 return nullptr;
1197
1198 }
1199
1200 if(!utf16_is_1st_surrogate(*(psz - 1)))
1201 {
1202
1203 throw_encoding_exception("bad surrogate for prior decoding wd16 encoded string (1)");
1204
1205 return nullptr;
1206
1207 }
1208
1209 return psz - 2;
1210
1211 }
1212
1213 return psz - 1;
1214
1215}
1216
1217
1218template < typename CHARACTER >
1219inline CHARACTER * unicode_prior(CHARACTER *psz, const non_const < CHARACTER > * pszBegin)
1220 requires(sizeof(CHARACTER) == 4)
1221{
1222
1223 if (psz <= pszBegin)
1224 {
1225
1226 return nullptr;
1227
1228 }
1229
1230 return psz - 1;
1231
1232}
1233
1234
1235//inline ::i32 unicode_index(const_char_pointer &pszUtf8)
1236//{
1237//
1238// if (*pszUtf8 == '\0')
1239// {
1240//
1241// return 0;
1242//
1243// }
1244//
1245// ::i32 ch = 0;
1246//
1247// ::u8 c;
1248//
1249// ::i8 extraBytesToRead = utf8_e(*pszUtf8);
1250//
1251// switch (extraBytesToRead)
1252// {
1253// case 5:
1254// ch += c = *pszUtf8++; ch <<= 6;
1255// if (c == '\0') { return -1; }
1256// case 4:
1257// ch += c = *pszUtf8++; ch <<= 6;
1258// if (c == '\0') { return -1; }
1259// case 3:
1260// ch += c = *pszUtf8++; ch <<= 6;
1261// if (c == '\0') { return -1; }
1262// case 2:
1263// ch += c = *pszUtf8++; ch <<= 6;
1264// if (c == '\0') { return -1; }
1265// case 1:
1266// ch += c = *pszUtf8++; ch <<= 6;
1267// if (c == '\0') { return -1; }
1268// case 0:
1269// ch += c = *pszUtf8++;
1270// if (c == '\0') { return -1; }
1271// }
1272//
1273// ch -= utf8_o(extraBytesToRead);
1274//
1275// return ch;
1276//
1277//}
1278//
1279//
1280//inline ::i32 unicode_index(const ::wd16_character *& input)
1281//{
1282//
1283// if (input[0] == 0)
1284// {
1285//
1286// return 0;
1287//
1288// }
1289//
1290// if (utf16_is_2nd_surrogate(input[0]))
1291// {
1292//
1293// return -1;
1294//
1295// }
1296// else if (utf16_is_1st_surrogate(input[0]))
1297// {
1298//
1299// if (utf16_is_2nd_surrogate(input[1]))
1300// {
1301//
1302// auto iUnicode = utf16_surrogate_to_utf32(input[0], input[1]);
1303//
1304// input += 2;
1305//
1306// return iUnicode;
1307//
1308// }
1309// else
1310// {
1311//
1312// return -1;
1313//
1314// }
1315//
1316// }
1317// else
1318// {
1319//
1320// auto iUnicode = input[0];
1321//
1322// input++;
1323//
1324// return iUnicode;
1325//
1326// }
1327//
1328//}
1329
1330
1331inline ::i32 ansichar_unicode_len(::wd32_character i)
1332{
1333 if (i < 0)
1334 {
1335 return -1;
1336 }
1337 else if (i < 0x0080)
1338 {
1339 return 1;
1340 }
1341 else if (i < 0x0800)
1342 {
1343 return 2;
1344 }
1345 else
1346 {
1347 return 3;
1348 }
1349}
1350
1351
1352
1353
1354
1355template < typename TYPE1, typename TYPE2 >
1356inline ::std::strong_ordering compare(const TYPE1 & str1, const TYPE2 & str2)
1357{
1358
1359 return string_compare(str1, str2);
1360
1361}
1362
1363
1364template < typename TYPE1, typename TYPE2 >
1365inline ::std::strong_ordering case_insensitive_order(const TYPE1 & str1, const TYPE2 & str2)
1366{
1367
1368 return case_insensitive_string_compare(str1, str2) <=> 0;
1369
1370}
1371
1372
1373
1374
1375template < typename TYPE1, typename TYPE2 >
1376inline TYPE1 equals_get(const TYPE1 & str1, const TYPE2 & str2, const TYPE1 & strOnEqual, const TYPE1 & strOnDifferent)
1377{
1378
1379 return equals(str1, str2) ? strOnEqual : strOnDifferent;
1380
1381}
1382
1383
1384template < typename TYPE1, typename TYPE2 >
1385inline TYPE1 equals_ci_get(const TYPE1 & str1, const TYPE2 & str2, const TYPE1 & strOnEqual, const TYPE1 & strOnDifferent)
1386{
1387
1388 return case_insensitive_equals(str1, str2) ? strOnEqual : strOnDifferent;
1389
1390}
1391
1392
1393//template < typename TYPE_CHAR >
1394//inline bool string_begins(const TYPE_CHAR * psz, character_count len, const TYPE_CHAR * pszPrefix, character_count lenPrefix)
1395//{
1396//
1397// if (lenPrefix > len)
1398// {
1399//
1400// return false;
1401//
1402// }
1403//
1404// return string_count_compare(psz, pszPrefix, lenPrefix) == 0;
1405//
1406//}
1407
1408
1409
1410//template < typename TYPE_CHAR >
1411//inline bool string_ends(const TYPE_CHAR * psz, character_count len, const TYPE_CHAR * pszSuffix, character_count lenSuffix)
1412//{
1413//
1414// auto offset = len - lenSuffix;
1415//
1416// if (offset < 0)
1417// {
1418//
1419// return false;
1420//
1421// }
1422//
1423// auto pszCompare = psz + offset;
1424//
1425// return string_count_compare(scopedstrCompare, pszSuffix, lenSuffix) == 0;
1426//
1427//}
1428
1429
1430//template < typename TYPE_CHAR >
1431//inline bool case_insensitive_string_begins(const TYPE_CHAR * psz, character_count len, const TYPE_CHAR * pszPrefix, character_count lenPrefix)
1432//{
1433//
1434// if (lenPrefix > len)
1435// {
1436//
1437// return false;
1438//
1439// }
1440//
1441// return case_insensitive_string_count_compare(scopedstr, pszPrefix, lenPrefix) == 0;
1442//
1443//}
1444
1445
1446//template < typename TYPE_CHAR >
1447//inline bool case_insensitive_string_ends(const TYPE_CHAR * psz, character_count len, const TYPE_CHAR * pszSuffix, character_count lenSuffix)
1448//{
1449//
1450// auto offset = len - lenSuffix;
1451//
1452// if (offset < 0)
1453// {
1454//
1455// return false;
1456//
1457// }
1458//
1459// auto pszCompare = psz + offset;
1460//
1461// return case_insensitive_string_count_compare(scopedstrCompare, pszSuffix, lenSuffix) == 0;
1462//
1463//}
1464
1465
1466template < typename CHAR_TYPE >
1467bool string_eat_before(string_base < CHAR_TYPE > & strBefore, const string_base < CHAR_TYPE > & strSeparator, string_base < CHAR_TYPE > & str, bool bEatEverythingIfNotFound)
1468{
1469
1470 ASSERT(&str != &strBefore);
1471
1472 if (&str == &strBefore)
1473 {
1474
1475 return false;
1476
1477 }
1478
1479 auto pFind = str.find(strSeparator);
1480
1481 if (::is_null(pFind))
1482 {
1483
1484 if (bEatEverythingIfNotFound)
1485 {
1486
1487 strBefore = str;
1488
1489 str.empty();
1490
1491 }
1492
1493 return false;
1494
1495 }
1496
1497 strBefore = str(0, pFind);
1498
1499 str = str(pFind + strSeparator.length());
1500
1501 return true;
1502
1503}
1504
1505
1506template < typename CHAR_TYPE >
1507bool string_eat_before_let_separator(string_base < CHAR_TYPE > & strBefore, const string_base < CHAR_TYPE > & strSeparator, string_base < CHAR_TYPE > & str, bool bEatEverythingIfNotFound)
1508{
1509
1510 ASSERT(&str != &strBefore);
1511
1512 if (&str == &strBefore)
1513 {
1514
1515 return false;
1516
1517 }
1518
1519 auto pFind = str.find(strSeparator);
1520
1521 if (::is_null(pFind))
1522 {
1523
1524 if (bEatEverythingIfNotFound)
1525 {
1526
1527 strBefore = str;
1528
1529 str = strSeparator;
1530
1531 }
1532
1533 return false;
1534
1535 }
1536
1537 strBefore = str(0, pFind);
1538
1539 str = str(pFind);
1540
1541 return true;
1542
1543}
1544
1545
1546
1547
1548
1549inline ::i32 unicode_len(const_char_pointer pszUtf8)
1550{
1551
1552 ::i32 len;
1553
1554 if (unicode_index_length(pszUtf8, len) < 0)
1555 {
1556
1557 return -1;
1558
1559 }
1560
1561 return len;
1562
1563}
1564
1565
1566template < typename CHAR_STRING >
1567inline bool is_trimmed_string_empty(CHAR_STRING p)
1568{
1569
1570 if (::is_null(p))
1571 {
1572
1573 return true;
1574
1575 }
1576
1577 while (*p)
1578 {
1579
1580 if (!unicode_is_whitespace(p))
1581 {
1582
1583 return false;
1584
1585 }
1586
1587 p = unicode_next(p);
1588
1589 }
1590
1591 return true;
1592
1593}
1594
1595
Definition block.h:46