5inline ::i32 get_utf8_char_length(const_char_pointer psz)
8 ::i32 len = utf8_unicode_length(*psz);
9 if (len == 0)
return 0;
14 if (len == 1)
return 1;
19 if (len == 2)
return 2;
24 if (len == 3)
return 3;
29 if (len == 4)
return 4;
34 if (len == 5)
return 5;
39 if (len == 6)
return 6;
119inline ::i32 unicode_index_length(const ::wd32_character *& input, character_count * psrclen)
147inline ::i32 unicode_index_length(const_char_pointer pszUtf8, ::i32 & len)
150 if (is_empty(pszUtf8))
165 ::i8 extraBytesToRead = utf8_e(*pszUtf8);
167 switch (extraBytesToRead)
170 ch += c = pszUtf8[len++]; ch <<= 6;
171 if (c ==
'\0') {
return -1; }
173 ch += c = pszUtf8[len++]; ch <<= 6;
174 if (c ==
'\0') {
return -1; }
176 ch += c = pszUtf8[len++]; ch <<= 6;
177 if (c ==
'\0') {
return -1; }
179 ch += c = pszUtf8[len++]; ch <<= 6;
180 if (c ==
'\0') {
return -1; }
182 ch += c = pszUtf8[len++]; ch <<= 6;
183 if (c ==
'\0') {
return -1; }
185 ch += c = pszUtf8[len++];
186 if (c ==
'\0') {
return -1; }
189 ch -= utf8_o(extraBytesToRead);
196inline ::i32 consume_unicode_index(const_char_pointer &pszUtf8)
201 auto i = unicode_index_length(pszUtf8, len);
206 throw_parsing_exception(
"end of string or not valid character to parse");
217inline ::i32 unicode_index_length(const ::wd16_character * input, ::i32 & len)
229 if (utf16_is_2nd_surrogate(input[0]))
237 else if (utf16_is_1st_surrogate(input[0]))
240 if (utf16_is_2nd_surrogate(input[1]))
245 return utf16_surrogate_to_utf32(input[0], input[1]);
270inline bool is_legal_unicode_index(::i32 iUnicodeIndex)
273 return iUnicodeIndex >= 0 && iUnicodeIndex < 65536 ? true :
false;
280inline ::i32 unicode_to_lower_case(::i32 i)
282 if (!is_legal_unicode_index(i))
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));
291inline ::i32 unicode_to_upper_case(::i32 i)
293 if (!is_legal_unicode_index(i))
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));
336inline const ::wd32_character * wd32_find_first_character_in(const ::const_wd32_range &
block, const ::const_wd32_range & blockCharacters)
348 return block.find_first_character_in(blockCharacters, ::comparison::comparison < ::wd32_character >());
355inline ::i32 unicode_to_title_case(::i32 i)
357 if (!is_legal_unicode_index(i))
359 ::u32 c1 = CHAR_PROP(i);
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);
367 if (CHAR_CATEGORY(c1) == CHAR_CATEGORY_Ll)
368 return ::wd32_character(i - (c1 >> 16));
369 return ::wd32_character(i);
373inline ::i32 unicode_to_numeric_value(::i32 i, ::f32 * f)
375 if (!is_legal_unicode_index(i))
377 ::u32 c1 = CHAR_PROP(i);
378 if (!NUMBER(c1))
return false;
384inline bool unicode_is_lower_case(::i32 i)
386 if (!is_legal_unicode_index(i))
388 return CHAR_CATEGORY(CHAR_PROP(i)) == CHAR_CATEGORY_Ll;
392inline bool unicode_is_upper_case(::i32 i)
394 if (!is_legal_unicode_index(i))
396 return CHAR_CATEGORY(CHAR_PROP(i)) == CHAR_CATEGORY_Lu;
400inline bool unicode_is_title_case(::i32 i)
402 if (!is_legal_unicode_index(i))
404 return CHAR_CATEGORY(CHAR_PROP(i)) == CHAR_CATEGORY_Lt;
408inline bool unicode_is_letter(::i32 i)
410 if (!is_legal_unicode_index(i))
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)
422inline bool unicode_is_letter_or_digit(::i32 i)
424 if (!is_legal_unicode_index(i))
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)
437inline bool unicode_is_digit(::i32 i)
440 if (!is_legal_unicode_index(i))
443 return CHAR_CATEGORY(CHAR_PROP(i)) == CHAR_CATEGORY_Nd;
448inline bool unicode_is_assigned(::i32 i)
450 if (!is_legal_unicode_index(i))
452 return CHAR_CATEGORY(CHAR_PROP(i)) != CHAR_CATEGORY_Cn;
456inline bool unicode_is_space_char(::i32 i)
458 if (!is_legal_unicode_index(i))
460 return ((((1 << CHAR_CATEGORY_Zs) |
461 (1 << CHAR_CATEGORY_Zl) |
462 (1 << CHAR_CATEGORY_Zp)
463 ) >> CHAR_CATEGORY(CHAR_PROP(i))) & 1) != 0;
467inline bool unicode_is_whitespace(::i32 i)
469 if (!is_legal_unicode_index(i))
477 (1 << 0x000D)) >> i) & 1) != 0))
479 (((((1 << CHAR_CATEGORY_Zs) |
480 (1 << CHAR_CATEGORY_Zl) |
481 (1 << CHAR_CATEGORY_Zp)
482 ) >> CHAR_CATEGORY(CHAR_PROP(i))) & 1) != 0);
486inline bool unicode_is_number(::i32 i)
488 if (!is_legal_unicode_index(i))
490 return NUMBER(CHAR_PROP(i)) != 0;
494inline ECharCategory unicode_get_category(::i32 i)
496 if (!is_legal_unicode_index(i))
497 return CHAR_CATEGORY_LAST;
498 return ECharCategory(CHAR_CATEGORY(CHAR_PROP(i)));
502inline ::i32 unicode_get_combining_class(::i32 i)
504 if (!is_legal_unicode_index(i))
506 return COMBINING_CLASS(CHAR_PROP(i));
510inline bool unicode_is_mirrored(::i32 i)
513 if (!is_legal_unicode_index(i))
516 return MIRRORED(CHAR_PROP(i)) != 0;
521inline ::i32 unicode_size_of_tables()
524 return sizeof(arr_idxCharInfo) +
sizeof(arr_CharInfo) +
sizeof(arr_idxCharInfo2) +
sizeof(arr_CharInfo2);
529template <
typename CHARACTER,
typename CHARACTER_COUNT >
530[[nodiscard]]
inline CHARACTER * unicode_next(
CHARACTER *psz, CHARACTER_COUNT *piRemaining)
541 ::i8 len = 1 + trailingBytesForUTF8(*psz);
543 if (len == 0)
return psz;
545 if(piRemaining && len > *piRemaining)
548 throw_encoding_exception(
"no remaining characters for decoding utf8 encoded string (0)");
557 throw_encoding_exception(
"premature end of utf8 encoded string (1)");
580 throw_encoding_exception(
"premature end of utf8 encoded string (2)");
603 throw_encoding_exception(
"premature end of utf8 encoded string (3)");
626 throw_encoding_exception(
"premature end of utf8 encoded string (4)");
649 throw_encoding_exception(
"premature end of utf8 encoded string (5)");
672 throw_encoding_exception(
"premature end of utf8 encoded string (6)");
692 throw_encoding_exception(
"premature end of utf8 encoded string (7)");
795template <
typename CHARACTER,
typename CHARACTER_COUNT >
807 if(piRemaining && *piRemaining < 1)
810 throw_encoding_exception(
"no remaining characters for decoding wd16 encoded string (0)");
814 const ::wd16_character uc = *psz++;
816 if (!utf16_is_surrogate(uc))
830 if (utf16_is_1st_surrogate(uc) && utf16_is_2nd_surrogate(*psz))
839 throw_encoding_exception(
"no remaining characters for decoding wd16 encoded string (1)");
853 throw_encoding_exception(
"expected surrogate got bad wd16 surrogate (2)");
864template <
typename CHARACTER,
typename CHARACTER_COUNT >
876 if(piRemaining && *piRemaining < 1)
879 throw_encoding_exception(
"no remaining characters for decoding wd32 encoded string (0)");
888template <
typename CHARACTER >
889inline CHARACTER * unicode_prior(
CHARACTER *psz,
const non_const < CHARACTER > * pszBegin)
896 throw_encoding_exception(
"bad argument for prior decoding utf8 encoded string (A)");
902 if ((*(psz - 1) & 0x80) == 0x00)
905 if ((psz - 1) < pszBegin)
908 throw_encoding_exception(
"no preceding characters for prior decoding utf8 encoded string (0)");
914 if(*(psz - 1) ==
'\0')
917 throw_encoding_exception(
"first preceding character is nil for prior decoding utf8 encoded string (0)");
926 else if ((*(psz - 2) & 0xE0) == 0xC0)
929 if ((psz - 2) < pszBegin)
932 throw_encoding_exception(
"not enough preceding characters for prior decoding utf8 encoded string (1)");
938 if(*(psz - 1) ==
'\0')
941 throw_encoding_exception(
"first preceding character is nil for prior decoding utf8 encoded string (1)");
946 else if(*(psz - 2) ==
'\0')
949 throw_encoding_exception(
"second preceding character is nil for prior decoding utf8 encoded string (1)");
958 else if ((*(psz - 3) & 0xF0) == 0xE0)
961 if ((psz - 3) < pszBegin)
964 throw_encoding_exception(
"not enough preceding characters for prior decoding utf8 encoded string (2)");
970 if(*(psz - 1) ==
'\0')
973 throw_encoding_exception(
"first preceding character is nil for prior decoding utf8 encoded string (2)");
978 else if(*(psz - 2) ==
'\0')
981 throw_encoding_exception(
"second preceding character is nil for prior decoding utf8 encoded string (2)");
986 else if(*(psz - 3) ==
'\0')
989 throw_encoding_exception(
"third preceding character is nil for prior decoding utf8 encoded string (2)");
998 else if ((*(psz - 4) & 0xF8) == 0xF0)
1001 if ((psz - 4) < pszBegin)
1004 throw_encoding_exception(
"not enough preceding characters for prior decoding utf8 encoded string (3)");
1010 if(*(psz - 1) ==
'\0')
1013 throw_encoding_exception(
"first preceding character is nil for prior decoding utf8 encoded string (3)");
1018 else if(*(psz - 2) ==
'\0')
1021 throw_encoding_exception(
"second preceding character is nil for prior decoding utf8 encoded string (3)");
1026 else if(*(psz - 3) ==
'\0')
1029 throw_encoding_exception(
"third preceding character is nil for prior decoding utf8 encoded string (3)");
1034 else if(*(psz - 4) ==
'\0')
1037 throw_encoding_exception(
"fourth preceding character is nil for prior decoding utf8 encoded string (3)");
1046 else if ((*(psz - 5) & 0xFC) == 0xF8)
1049 if ((psz - 5) < pszBegin)
1052 throw_encoding_exception(
"not enough preceding characters for prior decoding utf8 encoded string (4)");
1058 if(*(psz - 1) ==
'\0')
1061 throw_encoding_exception(
"first preceding character is nil for prior decoding utf8 encoded string (4)");
1066 else if(*(psz - 2) ==
'\0')
1069 throw_encoding_exception(
"second preceding character is nil for prior decoding utf8 encoded string (4)");
1074 else if(*(psz - 3) ==
'\0')
1077 throw_encoding_exception(
"third preceding character is nil for prior decoding utf8 encoded string (4)");
1082 else if(*(psz - 4) ==
'\0')
1085 throw_encoding_exception(
"fourth preceding character is nil for prior decoding utf8 encoded string (4)");
1090 else if(*(psz - 5) ==
'\0')
1093 throw_encoding_exception(
"fifth preceding character is nil for prior decoding utf8 encoded string (4)");
1102 else if ((*(psz - 6) & 0xFE) == 0xFC)
1105 if ((psz - 6) < pszBegin)
1108 throw_encoding_exception(
"not enough preceding characters for prior decoding utf8 encoded string (5)");
1114 if(*(psz - 1) ==
'\0')
1117 throw_encoding_exception(
"first preceding character is nil for prior decoding utf8 encoded string (5)");
1122 else if(*(psz - 2) ==
'\0')
1125 throw_encoding_exception(
"second preceding character is nil for prior decoding utf8 encoded string (5)");
1130 else if(*(psz - 3) ==
'\0')
1133 throw_encoding_exception(
"third preceding character is nil for prior decoding utf8 encoded string (5)");
1138 else if(*(psz - 4) ==
'\0')
1141 throw_encoding_exception(
"fourth preceding character is nil for prior decoding utf8 encoded string (5)");
1146 else if(*(psz - 5) ==
'\0')
1149 throw_encoding_exception(
"fifth preceding character is nil for prior decoding utf8 encoded string (5)");
1154 else if(*(psz - 6) ==
'\0')
1157 throw_encoding_exception(
"sixth preceding character is nil for prior decoding utf8 encoded string (5)");
1167 throw_encoding_exception(
"bad utf8 encoding (6)");
1174template <
typename CHARACTER >
1175inline CHARACTER * unicode_prior(
CHARACTER *psz,
const non_const < CHARACTER > * pszBegin)
1179 if (psz <= pszBegin)
1182 throw_encoding_exception(
"no preceding characters for prior decoding wd16 encoded string (0)");
1188 if (utf16_is_2nd_surrogate(*(psz - 1)))
1191 if (psz - 2 <= pszBegin)
1194 throw_encoding_exception(
"no preceding characters for prior decoding wd16 encoded string (1)");
1200 if(!utf16_is_1st_surrogate(*(psz - 1)))
1203 throw_encoding_exception(
"bad surrogate for prior decoding wd16 encoded string (1)");
1218template <
typename CHARACTER >
1219inline CHARACTER * unicode_prior(
CHARACTER *psz,
const non_const < CHARACTER > * pszBegin)
1223 if (psz <= pszBegin)
1331inline ::i32 ansichar_unicode_len(::wd32_character i)
1337 else if (i < 0x0080)
1341 else if (i < 0x0800)
1355template <
typename TYPE1,
typename TYPE2 >
1356inline ::std::strong_ordering compare(
const TYPE1 & str1,
const TYPE2 & str2)
1359 return string_compare(str1, str2);
1364template <
typename TYPE1,
typename TYPE2 >
1365inline ::std::strong_ordering case_insensitive_order(
const TYPE1 & str1,
const TYPE2 & str2)
1368 return case_insensitive_string_compare(str1, str2) <=> 0;
1375template <
typename TYPE1,
typename TYPE2 >
1376inline TYPE1 equals_get(
const TYPE1 & str1,
const TYPE2 & str2,
const TYPE1 & strOnEqual,
const TYPE1 & strOnDifferent)
1379 return equals(str1, str2) ? strOnEqual : strOnDifferent;
1384template <
typename TYPE1,
typename TYPE2 >
1385inline TYPE1 equals_ci_get(
const TYPE1 & str1,
const TYPE2 & str2,
const TYPE1 & strOnEqual,
const TYPE1 & strOnDifferent)
1388 return case_insensitive_equals(str1, str2) ? strOnEqual : strOnDifferent;
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)
1470 ASSERT(&str != &strBefore);
1472 if (&str == &strBefore)
1479 auto pFind = str.find(strSeparator);
1481 if (::is_null(pFind))
1484 if (bEatEverythingIfNotFound)
1497 strBefore = str(0, pFind);
1499 str = str(pFind + strSeparator.length());
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)
1510 ASSERT(&str != &strBefore);
1512 if (&str == &strBefore)
1519 auto pFind = str.find(strSeparator);
1521 if (::is_null(pFind))
1524 if (bEatEverythingIfNotFound)
1537 strBefore = str(0, pFind);
1549inline ::i32 unicode_len(const_char_pointer pszUtf8)
1554 if (unicode_index_length(pszUtf8, len) < 0)
1566template <
typename CHAR_STRING >
1567inline bool is_trimmed_string_empty(CHAR_STRING p)
1580 if (!unicode_is_whitespace(p))
1587 p = unicode_next(p);