20 typedef wchar_t utf16_t;
22 typedef char16_t utf16_t;
30 inline bool is_high_surrogate(_In_ utf16_t chr)
32 return 0xd800 < chr && chr < 0xdc00;
40 inline bool is_low_surrogate(_In_ utf16_t chr)
42 return 0xdc00 < chr && chr < 0xe000;
50 inline bool is_surrogate_pair(_In_reads_(2)
const utf16_t* str)
52 return is_high_surrogate(str[0]) && is_low_surrogate(str[1]);
60 inline char32_t surrogate_pair_to_ucs4(_In_reads_(2)
const utf16_t* str)
62 assert(is_surrogate_pair(str));
64 ((
char32_t)(str[0] - 0xd800) << 10) +
65 (char32_t)(str[1] - 0xdc00) +
74 inline void ucs4_to_surrogate_pair(_Out_writes_(2) utf16_t* str, _In_
char32_t chr)
76 assert(chr >= 0x10000);
78 str[0] = 0xd800 + (char32_t)((chr >> 10) & 0x3ff);
79 str[1] = 0xdc00 + (char32_t)(chr & 0x3ff);
87 inline bool iscombining(_In_
char32_t chr)
90 0x0300 <= chr && chr < 0x0370 ||
91 0x1dc0 <= chr && chr < 0x1e00 ||
92 0x20d0 <= chr && chr < 0x2100 ||
93 0xfe20 <= chr && chr < 0xfe30;
102 inline size_t islbreak(_In_ T chr)
104 return chr ==
'\n' || chr ==
'\r';
114 inline size_t islbreak(_In_reads_or_z_(count)
const T* chr, _In_
size_t count)
116 if (count >= 2 && (chr[0] ==
'\r' && chr[1] ==
'\n' || chr[0] ==
'\n' && chr[1] ==
'\r'))
118 if (count > 1 && (chr[0] ==
'\n' || chr[0] ==
'\r'))
129 inline size_t glyphlen(_In_reads_or_z_(count)
const wchar_t* glyph,
size_t count)
133 size_t i = count < 2 || !is_surrogate_pair(glyph) ? 1 : 2;
137 for (; i < count && iscombining(glyph[i]); ++i);
151 inline size_t strlen(_In_z_
const T* str)
155 for (i = 0; str[i]; ++i);
168 inline size_t strnlen(_In_z_
const T* str, _In_
size_t count)
172 for (i = 0; i < count && str[i]; ++i);
186 inline const T* strnchr(
187 _In_reads_or_z_(count)
const T* str,
191 assert(str || !count);
192 for (
size_t i = 0; i < count && str[i]; ++i)
193 if (str[i] == chr)
return str + i;
207 inline const T* strnichr(
208 _In_reads_or_z_(count)
const T* str,
211 _In_
const std::locale& locale)
213 assert(str || !count);
214 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
215 chr = ctype.tolower(chr);
216 for (
size_t i = 0; i < count && str[i]; ++i)
217 if (ctype.tolower(str[i]) == chr)
return str + i;
231 template <
class T1,
class T2>
233 _In_reads_or_z_(count1)
const T1* str1, _In_
size_t count1,
234 _In_reads_or_z_(count2)
const T2* str2, _In_
size_t count2)
236 assert(str1 || !count1);
237 assert(str2 || !count2);
238 size_t i; T1 a; T2 b;
239 for (i = 0; i < count1 && i < count2 && ((a = str1[i]) | (b = str2[i])); ++i) {
240 if (a > b)
return +1;
241 if (a < b)
return -1;
243 if (i < count1 && str1[i])
return +1;
244 if (i < count2 && str2[i])
return -1;
258 template <
class T1,
class T2>
260 _In_reads_or_z_(count1)
const T1* str1, _In_
size_t count1,
261 _In_reads_or_z_(count2)
const T2* str2, _In_
size_t count2,
262 _In_
const std::locale& locale)
264 assert(str1 || !count1);
265 assert(str2 || !count2);
266 size_t i; T1 a; T2 b;
267 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
268 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
269 for (i = 0; i < count1 && i < count2 && ((a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i]))); i++) {
270 if (a > b)
return +1;
271 if (a < b)
return -1;
273 if (i < count1 && str1[i])
return +1;
274 if (i < count2 && str2[i])
return -1;
287 template <
class T1,
class T2>
289 _In_reads_or_z_(count)
const T1* str,
290 _In_z_
const T2* sample,
293 assert(str || !count);
295 for (
size_t offset = 0;; ++offset) {
296 for (
size_t i = offset, j = 0;; ++i, ++j) {
299 if (i >= count || !str[i])
301 if (str[i] != sample[j])
316 template <
class T1,
class T2>
317 inline const T1* strnistr(
318 _In_reads_or_z_(count)
const T1* str,
319 _In_z_
const T2* sample,
321 _In_
const std::locale& locale)
323 assert(str || !count);
325 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
326 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
327 for (
size_t offset = 0;; ++offset) {
328 for (
size_t i = offset, j = 0;; ++i, ++j) {
331 if (i >= count || !str[i])
333 if (ctype1.tolower(str[i]) != ctype2.tolower(sample[j]))
349 inline size_t crlf2nl(_Out_writes_z_(strlen(src)) T* dst, _In_z_
const T* src)
354 for (i = j = 0; src[j];) {
355 if (src[j] !=
'\r' || src[j + 1] !=
'\n')
367 template <
class T,
class T_bin>
368 inline T_bin strtoint(
369 _In_reads_or_z_(count)
const T* str, _In_
size_t count,
370 _Out_opt_
size_t* end,
372 _Out_ uint8_t& flags)
374 assert(str || !count);
375 assert(radix == 0 || 2 <= radix && radix <= 36);
378 T_bin value = 0, digit,
380 max_ui_pre1, max_ui_pre2;
386 if (i >= count || !str[i])
goto error;
387 if (!isspace(str[i]))
break;
394 if (i >= count || !str[i])
goto error;
396 else if (str[i] ==
'-') {
399 if (i >= count || !str[i])
goto error;
404 if (str[i] ==
'0' && i + 1 < count && (str[i + 1] ==
'x' || str[i + 1] ==
'X')) {
406 if (i >= count || !str[i])
goto error;
413 if (i >= count || !str[i])
goto error;
414 if (str[i] ==
'x' || str[i] ==
'X') {
417 if (i >= count || !str[i])
goto error;
427 max_ui_pre1 = max_ui / (T_bin)radix;
428 max_ui_pre2 = max_ui % (T_bin)radix;
430 if (
'0' <= str[i] && str[i] <=
'9')
431 digit = (T_bin)str[i] -
'0';
432 else if (
'A' <= str[i] && str[i] <=
'Z')
433 digit = (T_bin)str[i] -
'A' +
'\x0a';
434 else if (
'a' <= str[i] && str[i] <=
'z')
435 digit = (T_bin)str[i] -
'a' +
'\x0a';
438 if (digit >= (T_bin)radix)
441 if (value < max_ui_pre1 ||
442 value == max_ui_pre1 && digit <= max_ui_pre2)
443 value = value * (T_bin)radix + digit;
450 if (i >= count || !str[i])
470 template <
class T,
class T_bin>
472 _In_reads_or_z_(count)
const T* str, _In_
size_t count,
473 _Out_opt_
size_t* end,
479 switch (
sizeof(T_bin)) {
481 value = (T_bin)strtoint<T, uint8_t>(str, count, end, radix, flags);
482 if ((flags & 0x01) && (value & 0x80)) {
486 return (flags & 0x02) ?
487 (flags & 0x01) ? (T_bin)0x80 : (T_bin)0x7f :
488 (flags & 0x01) ? -value : value;
491 value = (T_bin)strtoint<T, T_U2>(str, count, end, radix, flags);
492 if ((flags & 0x01) && (value & 0x8000)) {
496 return (flags & 0x02) ?
497 (flags & 0x01) ? (T_bin)0x8000 : (T_bin)0x7fff :
498 (flags & 0x01) ? -value : value;
501 value = (T_bin)strtoint<T, uint32_t>(str, count, end, radix, flags);
502 if ((flags & 0x01) && (value & 0x80000000)) {
506 return (flags & 0x02) ?
507 (flags & 0x01) ? (T_bin)0x80000000 : (T_bin)0x7fffffff :
508 (flags & 0x01) ? -value : value;
511 value = (T_bin)strtoint<T, uint64_t>(str, count, end, radix, flags);
512 if ((flags & 0x01) && (value & 0x8000000000000000)) {
516 return (flags & 0x02) ?
517 (flags & 0x01) ? (T_bin)0x8000000000000000 : (T_bin)0x7fffffffffffffff :
518 (flags & 0x01) ? -value : value;
521 throw std::invalid_argument(
"Unsupported bit length");
535 template <
class T,
class T_bin>
536 inline T_bin strtouint(
537 _In_reads_or_z_(count)
const T* str,
539 _Out_opt_
size_t* end,
545 switch (
sizeof(T_bin)) {
546 case 1: value = (T_bin)strtoint<T, uint8_t>(str, count, end, radix, flags);
break;
547 case 2: value = (T_bin)strtoint<T, uint16_t>(str, count, end, radix, flags);
break;
548 case 4: value = (T_bin)strtoint<T, uint32_t>(str, count, end, radix, flags);
break;
549 case 8: value = (T_bin)strtoint<T, uint64_t>(str, count, end, radix, flags);
break;
550 default:
throw std::invalid_argument(
"Unsupported bit length");
553 return (flags & 0x02) ?
554 (flags & 0x01) ? (T_bin)0 : (T_bin)-1 :
555 (flags & 0x01) ? ~value : value;
569 inline int32_t strto32(
570 _In_reads_or_z_(count)
const T* str, _In_
size_t count,
571 _Out_opt_
size_t* end,
574 return strtoint<T, int32_t>(str, count, end, radix);
588 inline int64_t strto64(
589 _In_reads_or_z_(count)
const T* str, _In_
size_t count,
590 _Out_opt_
size_t* end,
593 return strtoint<T, int64_t>(str, count, end, radix);
608 inline intptr_t strtoi(
609 _In_reads_or_z_(count)
const T* str, _In_
size_t count,
610 _Out_opt_
size_t* end,
613#if defined(_WIN64) || defined(__LP64__)
614 return (intptr_t)strto64(str, count, end, radix);
616 return (intptr_t)strto32(str, count, end, radix);
631 inline uint32_t strtou32(
632 _In_reads_or_z_(count)
const T* str, _In_
size_t count,
633 _Out_opt_
size_t* end,
636 return strtouint<T, uint32_t>(str, count, end, radix);
650 inline uint64_t strtou64(
651 _In_reads_or_z_(count)
const T* str, _In_
size_t count,
652 _Out_opt_
size_t* end,
655 return strtouint<T, uint64_t>(str, count, end, radix);
670 inline size_t strtoui(
671 _In_reads_or_z_(count)
const T* str, _In_
size_t count,
672 _Out_opt_
size_t* end,
675#if defined(_WIN64) || defined(__LP64__)
676 return (
size_t)strtou64(str, count, end, radix);
678 return (
size_t)strtou32(str, count, end, radix);