30 typedef wchar_t utf16_t;
32 typedef char16_t utf16_t;
40 inline bool is_high_surrogate(_In_ utf16_t chr)
42 return 0xd800 < chr && chr < 0xdc00;
50 inline bool is_low_surrogate(_In_ utf16_t chr)
52 return 0xdc00 < chr && chr < 0xe000;
60 inline bool is_surrogate_pair(_In_reads_(2)
const utf16_t* str)
62 return is_high_surrogate(str[0]) && is_low_surrogate(str[1]);
70 inline char32_t surrogate_pair_to_ucs4(_In_reads_(2)
const utf16_t* str)
72 _Assume_(is_surrogate_pair(str));
74 ((
char32_t)(str[0] - 0xd800) << 10) +
75 (char32_t)(str[1] - 0xdc00) +
84 inline void ucs4_to_surrogate_pair(_Out_writes_(2) utf16_t* str, _In_
char32_t chr)
86 _Assume_(chr >= 0x10000);
88 str[0] = 0xd800 + (char32_t)((chr >> 10) & 0x3ff);
89 str[1] = 0xdc00 + (char32_t)(chr & 0x3ff);
97 inline bool iscombining(_In_
char32_t chr)
100 (0x0300 <= chr && chr < 0x0370) ||
101 (0x1dc0 <= chr && chr < 0x1e00) ||
102 (0x20d0 <= chr && chr < 0x2100) ||
103 (0xfe20 <= chr && chr < 0xfe30);
112 inline bool islbreak(_In_ T chr)
114 return chr ==
'\n' || chr ==
'\r';
126 inline size_t islbreak(_In_reads_or_z_opt_(count)
const T* chr, _In_
size_t count)
128 _Assume_(chr || !count);
129 if (count >= 2 && ((chr[0] ==
'\r' && chr[1] ==
'\n') || (chr[0] ==
'\n' && chr[1] ==
'\r')))
131 if (count > 1 && (chr[0] ==
'\n' || chr[0] ==
'\r'))
142 inline bool isspace(_In_ T chr)
144 return chr ==
' ' || chr ==
'\t' || chr ==
'\n' || chr ==
'\r' || chr ==
'\v' || chr ==
'\f';
153 inline bool islower(_In_ T chr)
155 return 'a' <= chr && chr <=
'z';
164 inline bool isupper(_In_ T chr)
166 return 'A' <= chr && chr <=
'Z';
175 inline bool isdigit(_In_ T chr)
177 return '0' <= chr && chr <=
'9';
186 inline bool isalpha(_In_ T chr)
188 return islower(chr) || isupper(chr);
197 inline size_t glyphlen(_In_reads_or_z_opt_(count)
const wchar_t* glyph, _In_
size_t count)
199 _Assume_(glyph || !count);
202 size_t i = count < 2 || !is_surrogate_pair(glyph) ? 1 : 2;
206 for (; i < count && iscombining(glyph[i]); ++i);
220 inline T tolower(_In_ T chr)
222 return isupper(chr) ? chr | 0x20 : chr;
233 inline T toupper(_In_ T chr)
235 return islower(chr) ? chr | ~0x20 : chr;
246 inline size_t strlen(_In_z_
const T* str)
250 for (i = 0; str[i]; ++i);
263 inline size_t strnlen(_In_reads_or_z_opt_(count)
const T* str, _In_
size_t count)
265 _Assume_(str || !count);
267 for (i = 0; i < count && str[i]; ++i);
278 template <
class T,
size_t SIZE>
279 inline size_t strnlen(_In_
const T (&str)[SIZE])
281 return strnlen(str, SIZE);
284 constexpr auto npos{
static_cast<size_t>(-1) };
295 inline size_t strchr(_In_z_
const T* str, _In_ T chr)
298 for (
size_t i = 0; str[i]; ++i)
299 if (str[i] == chr)
return i;
311 template <
class T,
class _Traits = std::
char_traits<T>,
class _Ax = std::allocator<T>>
312 inline size_t strrchr(_In_
const std::basic_string<T, _Traits, _Ax>& str, _In_ T chr)
314 return strrnchr(str.data(), str.size(), chr);
327 inline size_t strnchr(
328 _In_reads_or_z_opt_(count)
const T* str,
332 _Assume_(str || !count);
333 for (
size_t i = 0; i < count && str[i]; ++i)
334 if (str[i] == chr)
return i;
348 inline size_t strrnchr(
349 _In_reads_or_z_opt_(count)
const T* str,
353 _Assume_(str || !count);
355 for (
size_t i = 0; i < count && str[i]; ++i)
356 if (str[i] == chr) z = i;
370 _In_reads_or_z_opt_(count)
const T* str,
373 _Assume_(str || !count);
374 for (
size_t i = 0; i < count && str[i]; ++i)
375 if (!isspace(str[i]))
391 _In_reads_or_z_opt_(count)
const T* str,
393 _In_
const std::locale& locale)
395 _Assume_(str || !count);
396 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
397 for (
size_t i = 0; i < count && str[i]; ++i)
398 if (!ctype.is(ctype.space, str[i]))
413 inline size_t strnichr(
414 _In_reads_or_z_opt_(count)
const T* str,
418 _Assume_(str || !count);
420 for (
size_t i = 0; i < count && str[i]; ++i)
421 if (tolower(str[i]) == chr)
return i;
436 inline size_t strnichr(
437 _In_reads_or_z_opt_(count)
const T* str,
440 _In_
const std::locale& locale)
442 _Assume_(str || !count);
443 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
444 chr = ctype.tolower(chr);
445 for (
size_t i = 0; i < count && str[i]; ++i)
446 if (ctype.tolower(str[i]) == chr)
return i;
460 inline size_t strrnichr(
461 _In_reads_or_z_opt_(count)
const T* str,
465 _Assume_(str || !count);
468 for (
size_t i = 0; i < count && str[i]; ++i)
469 if (tolower(str[i]) == chr) z = i;
484 inline size_t strrnichr(
485 _In_reads_or_z_opt_(count)
const T* str,
488 _In_
const std::locale& locale)
490 _Assume_(str || !count);
491 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
492 chr = ctype.tolower(chr);
494 for (
size_t i = 0; i < count && str[i]; ++i)
495 if (ctype.tolower(str[i]) == chr) z = i;
507 template <
class T1,
class T2>
508 inline int strcmp(
const T1* str1,
const T2* str2)
510 _Assume_(str1 && str2);
512 for (
size_t i = 0; (a = str1[i]) | (b = str2[i]); ++i) {
513 if (a > b)
return +1;
514 if (a < b)
return -1;
529 template <
class T1,
class T2>
531 _In_reads_or_z_opt_(count1)
const T1* str1, _In_
size_t count1,
532 _In_reads_or_z_opt_(count2)
const T2* str2, _In_
size_t count2)
534 _Assume_(str1 || !count1);
535 _Assume_(str2 || !count2);
536 size_t i; T1 a; T2 b;
537 for (i = 0; i < count1 && i < count2 && ((a = str1[i]) | (b = str2[i])); ++i) {
538 if (a > b)
return +1;
539 if (a < b)
return -1;
541 if (i < count1 && str1[i])
return +1;
542 if (i < count2 && str2[i])
return -1;
555 template <
class T1,
class T2>
556 inline int strncmp(_In_reads_or_z_opt_(count)
const T1* str1, _In_reads_or_z_opt_(count)
const T2* str2, _In_
size_t count)
558 _Assume_((str1 && str2) || !count);
559 size_t i; T1 a; T2 b;
560 for (i = 0; i < count && ((a = str1[i]) | (b = str2[i])); ++i) {
561 if (a > b)
return +1;
562 if (a < b)
return -1;
564 if (i < count && str1[i])
return +1;
565 if (i < count && str2[i])
return -1;
582 _In_reads_or_z_opt_(count1)
const T* str1, _In_
size_t count1,
583 _In_reads_or_z_opt_(count2)
const T* str2, _In_
size_t count2,
584 _In_
const std::locale& locale)
586 _Assume_(str1 || !count1);
587 _Assume_(str2 || !count2);
588 auto& collate = std::use_facet<std::collate<T>>(locale);
589 return collate.compare(str1, str1 + count1, str2, str2 + count2);
600 template <
class T1,
class T2>
601 inline int stricmp(_In_z_
const T1* str1, _In_z_
const T2* str2)
605 size_t i; T1 a; T2 b;
606 for (i = 0; (a = tolower(str1[i])) | (b = tolower(str2[i])); i++) {
607 if (a > b)
return +1;
608 if (a < b)
return -1;
610 if (str1[i])
return +1;
611 if (str2[i])
return -1;
623 template <
class T1,
class _Traits1 = std::
char_traits<T1>,
class _Ax1 = std::allocator<T1>,
class T2,
class _Traits2 = std::
char_traits<T2>,
class _Ax2 = std::allocator<T2>>
625 _In_
const std::basic_string<T1, _Traits1, _Ax1>& str1,
626 _In_
const std::basic_string<T2, _Traits2, _Ax2>& str2)
628 return strnicmp(str1.data(), str1.size(), str2.data(), str2.size());
640 template <
class T1,
class T2>
641 inline int stricmp(_In_z_
const T1* str1, _In_z_
const T2* str2, _In_
const std::locale& locale)
645 size_t i; T1 a; T2 b;
646 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
647 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
648 for (i = 0; (a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i])); i++) {
649 if (a > b)
return +1;
650 if (a < b)
return -1;
652 if (str1[i])
return +1;
653 if (str2[i])
return -1;
666 template <
class T1,
class _Traits1 = std::
char_traits<T1>,
class _Ax1 = std::allocator<T1>,
class T2,
class _Traits2 = std::
char_traits<T2>,
class _Ax2 = std::allocator<T2>>
668 _In_
const std::basic_string<T1, _Traits1, _Ax1>& str1,
669 _In_
const std::basic_string<T2, _Traits2, _Ax2>& str2,
670 _In_
const std::locale& locale)
672 return strnicmp(str1.data(), str1.size(), str2.data(), str2.size(), locale);
684 template <
class T1,
class T2>
685 inline int strnicmp(_In_reads_or_z_opt_(count)
const T1* str1, _In_reads_or_z_opt_(count)
const T2* str2, _In_
size_t count)
687 _Assume_(str1 || !count);
688 _Assume_(str2 || !count);
689 size_t i; T1 a; T2 b;
690 for (i = 0; i < count && ((a = tolower(str1[i])) | (b = tolower(str2[i]))); i++) {
691 if (a > b)
return +1;
692 if (a < b)
return -1;
694 if (i < count && str1[i])
return +1;
695 if (i < count && str2[i])
return -1;
709 template <
class T1,
class T2>
710 inline int strnicmp(_In_reads_or_z_opt_(count)
const T1* str1, _In_reads_or_z_opt_(count)
const T2* str2, _In_
size_t count, _In_
const std::locale& locale)
712 _Assume_(str1 || !count);
713 _Assume_(str2 || !count);
714 size_t i; T1 a; T2 b;
715 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
716 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
717 for (i = 0; i < count && ((a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i]))); i++) {
718 if (a > b)
return +1;
719 if (a < b)
return -1;
721 if (i < count && str1[i])
return +1;
722 if (i < count && str2[i])
return -1;
736 template <
class T1,
class T2>
738 _In_reads_or_z_opt_(count1)
const T1* str1, _In_
size_t count1,
739 _In_reads_or_z_opt_(count2)
const T2* str2, _In_
size_t count2)
741 _Assume_(str1 || !count1);
742 _Assume_(str2 || !count2);
743 size_t i; T1 a; T2 b;
744 for (i = 0; i < count1 && i < count2 && ((a = tolower(str1[i])) | (b = tolower(str2[i]))); i++) {
745 if (a > b)
return +1;
746 if (a < b)
return -1;
748 if (i < count1 && str1[i])
return +1;
749 if (i < count2 && str2[i])
return -1;
764 template <
class T1,
class T2>
766 _In_reads_or_z_opt_(count1)
const T1* str1, _In_
size_t count1,
767 _In_reads_or_z_opt_(count2)
const T2* str2, _In_
size_t count2,
768 _In_
const std::locale& locale)
770 _Assume_(str1 || !count1);
771 _Assume_(str2 || !count2);
772 size_t i; T1 a; T2 b;
773 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
774 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
775 for (i = 0; i < count1 && i < count2 && ((a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i]))); i++) {
776 if (a > b)
return +1;
777 if (a < b)
return -1;
779 if (i < count1 && str1[i])
return +1;
780 if (i < count2 && str2[i])
return -1;
792 template <
class T1,
class T2>
793 inline size_t strstr(
794 _In_z_
const T1* str,
795 _In_z_
const T2* sample)
799 for (
size_t offset = 0;; ++offset) {
800 for (
size_t i = offset, j = 0;; ++i, ++j) {
805 if (str[i] != sample[j])
820 template <
class T1,
class T2>
821 inline size_t strnstr(
822 _In_reads_or_z_opt_(count)
const T1* str,
824 _In_z_
const T2* sample)
826 _Assume_(str || !count);
828 for (
size_t offset = 0;; ++offset) {
829 for (
size_t i = offset, j = 0;; ++i, ++j) {
832 if (i >= count || !str[i])
834 if (str[i] != sample[j])
848 template <
class T1,
class T2>
849 inline size_t stristr(
850 _In_z_
const T1* str,
851 _In_z_
const T2* sample)
855 for (
size_t offset = 0;; ++offset) {
856 for (
size_t i = offset, j = 0;; ++i, ++j) {
861 if (tolower(str[i]) != tolower(sample[j]))
876 template <
class T1,
class T2>
877 inline size_t stristr(
878 _In_z_
const T1* str,
879 _In_z_
const T2* sample,
880 _In_
const std::locale& locale)
884 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
885 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
886 for (
size_t offset = 0;; ++offset) {
887 for (
size_t i = offset, j = 0;; ++i, ++j) {
892 if (ctype1.tolower(str[i]) != ctype2.tolower(sample[j]))
907 template <
class T1,
class T2>
908 inline size_t strnistr(
909 _In_reads_or_z_opt_(count)
const T1* str,
911 _In_z_
const T2* sample)
913 _Assume_(str || !count);
915 for (
size_t offset = 0;; ++offset) {
916 for (
size_t i = offset, j = 0;; ++i, ++j) {
919 if (i >= count || !str[i])
921 if (tolower(str[i]) != tolower(sample[j]))
937 template <
class T1,
class T2>
938 inline size_t strnistr(
939 _In_reads_or_z_opt_(count)
const T1* str,
941 _In_z_
const T2* sample,
942 _In_
const std::locale& locale)
944 _Assume_(str || !count);
946 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
947 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
948 for (
size_t offset = 0;; ++offset) {
949 for (
size_t i = offset, j = 0;; ++i, ++j) {
952 if (i >= count || !str[i])
954 if (ctype1.tolower(str[i]) != ctype2.tolower(sample[j]))
968 template <
class T1,
class T2>
969 inline size_t strcpy(
970 _Out_writes_z_(_String_length_(src) + 1) T1* dst,
971 _In_z_
const T2* src)
973 _Assume_(dst && src);
974 for (
size_t i = 0; ; ++i) {
975 if ((dst[i] = src[i]) == 0)
989 template <
class T1,
class T2>
990 inline size_t strncpy(
991 _Out_writes_(count) _Post_maybez_ T1* dst,
992 _In_reads_or_z_opt_(count)
const T2* src, _In_
size_t count)
994 _Assume_(dst && src || !count);
995 for (
size_t i = 0; ; ++i) {
998 if ((dst[i] = src[i]) == 0)
1013 template <
class T1,
class T2>
1014 inline size_t strncpy(
1015 _Out_writes_(count_dst) _Post_maybez_ T1* dst, _In_
size_t count_dst,
1016 _In_reads_or_z_opt_(count_src)
const T2* src, _In_
size_t count_src)
1018 _Assume_(dst || !count_dst);
1019 _Assume_(src || !count_src);
1020 for (
size_t i = 0; ; ++i)
1024 if (i >= count_src) {
1028 if ((dst[i] = src[i]) == 0)
1041 template <
class T1,
class T2>
1042 inline size_t strcat(
1043 _In_z_ _Out_writes_z_(_String_length_(dst) + _String_length_(src) + 1) T1* dst,
1044 _In_z_
const T2* src)
1046 _Assume_(dst && src);
1047 for (
size_t i = 0, j = stdex::strlen<T1>(dst); ; ++i, ++j) {
1048 if ((dst[j] = src[i]) == 0)
1062 template <
class T1,
class T2>
1063 inline size_t strncat(
1065 _In_reads_or_z_opt_(count)
const T2* src, _In_
size_t count)
1067 _Assume_(dst && src || !count);
1068 for (
size_t i = 0, j = stdex::strlen<T1>(dst); ; ++i, ++j) {
1071 if ((dst[j] = src[i]) == 0)
1086 template <
class T1,
class T2>
1087 inline size_t strncat(
1088 _Out_writes_(count_dst) _Post_maybez_ T1* dst, _In_
size_t count_dst,
1089 _In_reads_or_z_opt_(count_src)
const T2* src, _In_
size_t count_src)
1091 _Assume_(dst || !count_dst);
1092 _Assume_(src || !count_src);
1093 for (
size_t i = 0, j = stdex::strnlen<T1>(dst, count_dst); ; ++i, ++j)
1097 if (i >= count_src) {
1101 if ((dst[j] = src[i]) == 0)
1117 inline _Check_return_ _Ret_maybenull_z_ T* strdup(_In_opt_z_
const T* str)
1119 if (!str) _Unlikely_
1121 size_t count = strlen(str) + 1;
1122 T* dst =
new T[count];
1123 strncpy(dst, count, str, SIZE_MAX);
1139 inline _Ret_z_ T* strndup(
1140 _In_reads_or_z_opt_(count)
const T* str,
1143 T* dst =
new T[count];
1144 strncpy(dst, count, str, SIZE_MAX);
1158 inline size_t crlf2nl(_Out_writes_z_(strlen(src)) T* dst, _In_z_
const T* src)
1163 for (i = j = 0; src[j];) {
1164 if (src[j] !=
'\r' || src[j + 1] !=
'\n')
1165 dst[i++] = src[j++];
1181 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1182 inline void crlf2nl(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& dst, _In_z_
const _Elem* src)
1185 _Assume_(src != dst.c_str());
1187 dst.reserve(strlen(src));
1188 for (
size_t j = 0; src[j];) {
1189 if (src[j] !=
'\r' || src[j + 1] !=
'\n')
1203 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1204 inline void crlf2nl(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& str)
1207 for (i = j = 0, n = str.size(); j < n;) {
1208 if (str[j] !=
'\r' || str[j + 1] !=
'\n')
1209 str[i++] = str[j++];
1219 template <
class T,
class T_bin>
1220 inline T_bin strtoint(
1221 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1222 _Out_opt_
size_t* end,
1224 _Out_ uint8_t& flags)
1226 _Assume_(str || !count);
1227 _Assume_(radix == 0 || 2 <= radix && radix <= 36);
1230 T_bin value = 0, digit,
1232 max_ui_pre1, max_ui_pre2;
1238 if (i >= count || !str[i])
goto error;
1239 if (!isspace(str[i]))
break;
1243 if (str[i] ==
'+') {
1246 if (i >= count || !str[i])
goto error;
1248 else if (str[i] ==
'-') {
1251 if (i >= count || !str[i])
goto error;
1256 if (str[i] ==
'0' && i + 1 < count && (str[i + 1] ==
'x' || str[i + 1] ==
'X')) {
1258 if (i >= count || !str[i])
goto error;
1263 if (str[i] ==
'0') {
1265 if (i >= count || !str[i])
goto error;
1266 if (str[i] ==
'x' || str[i] ==
'X') {
1269 if (i >= count || !str[i])
goto error;
1279 max_ui_pre1 = max_ui / (T_bin)radix;
1280 max_ui_pre2 = max_ui % (T_bin)radix;
1282 if (
'0' <= str[i] && str[i] <=
'9')
1283 digit = (T_bin)str[i] -
'0';
1284 else if (
'A' <= str[i] && str[i] <=
'Z')
1285 digit = (T_bin)str[i] -
'A' +
'\x0a';
1286 else if (
'a' <= str[i] && str[i] <=
'z')
1287 digit = (T_bin)str[i] -
'a' +
'\x0a';
1290 if (digit >= (T_bin)radix)
1293 if (value < max_ui_pre1 ||
1294 (value == max_ui_pre1 && digit <= max_ui_pre2))
1295 value = value * (T_bin)radix + digit;
1302 if (i >= count || !str[i])
1322 template <
class T,
class T_bin>
1324 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1325 _Out_opt_
size_t* end,
1331 switch (
sizeof(T_bin)) {
1333 value = (T_bin)strtoint<T, uint8_t>(str, count, end, radix, flags);
1334 if ((flags & 0x01) && (value & 0x80)) {
1338 return (flags & 0x02) ?
1339 (flags & 0x01) ? (T_bin)0x80 : (T_bin)0x7f :
1340 (flags & 0x01) ? -value : value;
1343 value = (T_bin)strtoint<T, uint16_t>(str, count, end, radix, flags);
1344 if ((flags & 0x01) && (value & 0x8000)) {
1348 return (flags & 0x02) ?
1349 (flags & 0x01) ? (T_bin)0x8000 : (T_bin)0x7fff :
1350 (flags & 0x01) ? -value : value;
1353 value = (T_bin)strtoint<T, uint32_t>(str, count, end, radix, flags);
1354 if ((flags & 0x01) && (value & 0x80000000)) {
1358 return (flags & 0x02) ?
1359 (flags & 0x01) ? (T_bin)0x80000000 : (T_bin)0x7fffffff :
1360 (flags & 0x01) ? -value : value;
1363 value = (T_bin)strtoint<T, uint64_t>(str, count, end, radix, flags);
1364 if ((flags & 0x01) && (value & 0x8000000000000000)) {
1368 return (flags & 0x02) ?
1369 (flags & 0x01) ? (T_bin)0x8000000000000000 : (T_bin)0x7fffffffffffffff :
1370 (flags & 0x01) ? -value : value;
1373 throw std::invalid_argument(
"Unsupported bit length");
1387 template <
class T,
class T_bin>
1388 inline T_bin strtouint(
1389 _In_reads_or_z_opt_(count)
const T* str,
1391 _Out_opt_
size_t* end,
1397 switch (
sizeof(T_bin)) {
1398 case 1: value = (T_bin)strtoint<T, uint8_t>(str, count, end, radix, flags);
break;
1399 case 2: value = (T_bin)strtoint<T, uint16_t>(str, count, end, radix, flags);
break;
1400 case 4: value = (T_bin)strtoint<T, uint32_t>(str, count, end, radix, flags);
break;
1401 case 8: value = (T_bin)strtoint<T, uint64_t>(str, count, end, radix, flags);
break;
1402 default:
throw std::invalid_argument(
"Unsupported bit length");
1405 return (flags & 0x02) ?
1406 (flags & 0x01) ? (T_bin)0 : (T_bin)-1 :
1407 (flags & 0x01) ? ~value : value;
1421 inline int32_t strto32(
1422 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1423 _Out_opt_
size_t* end,
1426 return strtoint<T, int32_t>(str, count, end, radix);
1440 inline int64_t strto64(
1441 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1442 _Out_opt_
size_t* end,
1445 return strtoint<T, int64_t>(str, count, end, radix);
1460 inline intptr_t strtoi(
1461 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1462 _Out_opt_
size_t* end,
1465#if defined(_WIN64) || defined(__LP64__)
1466 return (intptr_t)strto64(str, count, end, radix);
1468 return (intptr_t)strto32(str, count, end, radix);
1483 inline uint32_t strtou32(
1484 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1485 _Out_opt_
size_t* end,
1488 return strtouint<T, uint32_t>(str, count, end, radix);
1502 inline uint64_t strtou64(
1503 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1504 _Out_opt_
size_t* end,
1507 return strtouint<T, uint64_t>(str, count, end, radix);
1522 inline size_t strtoui(
1523 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1524 _Out_opt_
size_t* end,
1527#if defined(_WIN64) || defined(__LP64__)
1528 return (
size_t)strtou64(str, count, end, radix);
1530 return (
size_t)strtou32(str, count, end, radix);
1535 inline int vsnprintf(_Out_z_cap_(capacity)
char* str, _In_
size_t capacity, _In_z_ _Printf_format_string_params_(2)
const char* format, _In_opt_ locale_t locale, _In_ va_list arg)
1540#pragma warning(suppress: 4996)
1541 r = _vsnprintf_l(str, capacity, format, locale, arg);
1543 r = ::vsnprintf(str, capacity, format, arg);
1545 if (r == -1 && strnlen(str, capacity) == capacity) {
1547 capacity += std::max<size_t>(capacity / 8, 0x80);
1548 if (capacity > INT_MAX)
1549 throw std::invalid_argument(
"string too big");
1550 return (
int)capacity;
1555 inline int vsnprintf(_Out_z_cap_(capacity)
wchar_t* str, _In_
size_t capacity, _In_z_ _Printf_format_string_params_(2)
const wchar_t* format, _In_opt_ locale_t locale, _In_ va_list arg)
1560#pragma warning(suppress: 4996)
1561 r = _vsnwprintf_l(str, capacity, format, locale, arg);
1563 r = vswprintf(str, capacity, format, arg);
1565 if (r == -1 && strnlen(str, capacity) == capacity) {
1567 capacity += std::max<size_t>(capacity / 8, 0x80);
1568 if (capacity > INT_MAX)
1569 throw std::invalid_argument(
"string too big");
1570 return (
int)capacity;
1586 template<
class _Elem,
class _Traits,
class _Ax>
1587 inline size_t vappendf(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& str, _In_z_ _Printf_format_string_params_(2)
const _Elem* format, _In_opt_ locale_t locale, _In_ va_list arg)
1589 _Elem buf[1024 /
sizeof(_Elem)];
1592 int count = vsnprintf(buf, _countof(buf) - 1, format, locale, arg);
1595 str.append(buf, count);
1598 for (
size_t capacity = 2 * 1024 /
sizeof(_Elem);; capacity *= 2) {
1600 auto buf_dyn = std::make_unique<_Elem[]>(capacity);
1601 count = vsnprintf(buf_dyn.get(), capacity - 1, format, locale, arg);
1603 str.append(buf_dyn.get(), count);
1618 template<
class _Elem,
class _Traits,
class _Ax>
1619 inline size_t appendf(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& str, _In_z_ _Printf_format_string_params_(2)
const _Elem* format, _In_opt_ locale_t locale, ...)
1622 va_start(arg, locale);
1623 size_t n = vappendf(str, format, locale, arg);
1636 template<
class _Elem,
class _Traits,
class _Ax>
1637 inline void vsprintf(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& str, _In_z_ _Printf_format_string_params_(2)
const _Elem* format, _In_opt_ locale_t locale, _In_ va_list arg)
1640 vappendf(str, format, locale, arg);
1650 template<
class _Elem,
class _Traits,
class _Ax>
1651 inline void sprintf(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& str, _In_z_ _Printf_format_string_params_(2)
const _Elem* format, _In_opt_ locale_t locale, ...)
1654 va_start(arg, locale);
1655 vsprintf(str, format, locale, arg);
1668 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1669 inline std::basic_string<_Elem, _Traits, _Ax> vsprintf(_In_z_ _Printf_format_string_params_(2)
const _Elem* format, _In_opt_ locale_t locale, _In_ va_list arg)
1671 std::basic_string<_Elem, _Traits, _Ax> str;
1672 vappendf(str, format, locale, arg);
1684 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1685 inline std::basic_string<_Elem, _Traits, _Ax> sprintf(_In_z_ _Printf_format_string_params_(2)
const _Elem* format, _In_opt_ locale_t locale, ...)
1688 va_start(arg, locale);
1689 auto str = vsprintf(format, locale, arg);
1695 inline size_t strftime(_Out_z_cap_(capacity)
char* str, _In_
size_t capacity, _In_z_ _Printf_format_string_
const char* format, _In_
const struct tm* time, _In_opt_ locale_t locale)
1698 return _strftime_l(str, capacity, format, time, locale);
1700 return strftime_l(str, capacity, format, time, locale);
1704 inline size_t strftime(_Out_z_cap_(capacity)
wchar_t* str, _In_
size_t capacity, _In_z_ _Printf_format_string_
const wchar_t* format, _In_
const struct tm* time, _In_opt_ locale_t locale)
1707 return _wcsftime_l(str, capacity, format, time, locale);
1709 return wcsftime_l(str, capacity, format, time, locale);
1722 template<
class _Elem,
class _Traits,
class _Ax>
1723 inline void strcatftime(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& str, _In_z_ _Printf_format_string_
const _Elem* format, _In_
const struct tm* time, _In_opt_ locale_t locale)
1725 _Elem buf[1024 /
sizeof(_Elem)];
1728 size_t count = strftime(buf, _countof(buf), format, time, locale);
1731 str.append(buf, count);
1734 for (
size_t capacity = 2 * 1024 /
sizeof(_Elem);; capacity *= 2) {
1736 auto buf_dyn = std::make_unique<_Elem[]>(capacity);
1737 count = strftime(buf_dyn.get(), capacity, format, time, locale);
1739 str.append(buf_dyn.get(), count);
1754 template<
class _Elem,
class _Traits,
class _Ax>
1755 inline void strftime(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& str, _In_z_ _Printf_format_string_
const _Elem* format, _In_
const struct tm* time, _In_opt_ locale_t locale)
1758 strcatftime(str, format, time, locale);
1771 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1772 inline std::basic_string<_Elem, _Traits, _Ax> strftime(_In_z_ _Printf_format_string_
const _Elem* format, _In_
const struct tm* time, _In_opt_ locale_t locale)
1774 std::basic_string<_Elem, _Traits, _Ax> str;
1775 strcatftime(str, format, time, locale);
1785 inline void strlwr(_Inout_z_ T* str)
1788 for (
size_t i = 0; str[i]; ++i)
1789 str[i] = tolower(str[i]);
1799 inline void strlwr(_Inout_z_ T* str, _In_
const std::locale& locale)
1802 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
1803 for (
size_t i = 0; str[i]; ++i)
1804 str[i] = ctype.tolower(str[i]);
1814 inline void strlwr(_Inout_updates_z_(count) T* str, _In_
size_t count)
1816 _Assume_(str || !count);
1817 for (
size_t i = 0; i < count && str[i]; ++i)
1818 str[i] = tolower(str[i]);
1826 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1827 inline void strlwr(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& str)
1841 inline void strlwr(_Inout_updates_z_(count) T* str, _In_
size_t count, _In_
const std::locale& locale)
1843 _Assume_(str || !count);
1844 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
1845 for (
size_t i = 0; i < count && str[i]; ++i)
1846 str[i] = ctype.tolower(str[i]);
1855 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1856 inline void strlwr(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& str, _In_
const std::locale& locale)
1858 const auto& ctype = std::use_facet<std::ctype<_Elem>>(locale);
1860 c = ctype.tolower(c);
1869 inline void strupr(_Inout_z_ T* str)
1872 for (
size_t i = 0; str[i]; ++i)
1873 str[i] = toupper(str[i]);
1883 inline void strupr(_Inout_z_ T* str, _In_
const std::locale& locale)
1886 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
1887 for (
size_t i = 0; str[i]; ++i)
1888 str[i] = ctype.toupper(str[i]);
1898 inline void strupr(_Inout_updates_z_(count) T* str, _In_
size_t count)
1900 _Assume_(str || !count);
1901 for (
size_t i = 0; i < count && str[i]; ++i)
1902 str[i] = toupper(str[i]);
1913 inline void strupr(_Inout_updates_z_(count) T* str, _In_
size_t count, _In_
const std::locale& locale)
1915 _Assume_(str || !count);
1916 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
1917 for (
size_t i = 0; i < count && str[i]; ++i)
1918 str[i] = ctype.toupper(str[i]);
1926 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1927 inline void strupr(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& str)
1939 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1940 inline void strupr(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& str, _In_
const std::locale& locale)
1942 const auto& ctype = std::use_facet<std::ctype<_Elem>>(locale);
1944 c = ctype.toupper(c);
1956 inline size_t ltrim(
1957 _Inout_z_count_(count) T* str, _In_
size_t count)
1959 for (
size_t i = 0;; ++i) {
1961 if (count) str[0] = 0;
1968 if (!isspace(str[i])) {
1970 return strnlen(str, count);
1971 size_t n = count != SIZE_MAX ? strncpy(str, str + i, count - i) : strcpy(str, str + i);
1988 inline size_t ltrim(
1989 _Inout_z_count_(count) T* str, _In_
size_t count,
1990 _In_
const std::locale& locale)
1992 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
1993 for (
size_t i = 0;; ++i) {
1995 if (count) str[0] = 0;
2002 if (!ctype.is(ctype.space, str[i])) {
2004 return strnlen(str, count);
2005 size_t n = count != SIZE_MAX ? strncpy(str, str + i, count - i) : strcpy(str, str + i);
2017 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
2018 inline void ltrim(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& s)
2025 [&](_In_ _Elem ch) { return !isspace(ch); }));
2034 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
2035 inline void ltrim(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& s, _In_
const std::locale& locale)
2037 const auto& ctype = std::use_facet<std::ctype<_Elem>>(locale);
2043 [&](_In_ _Elem ch) { return !ctype.is(ctype.space, ch); }));
2055 inline size_t rtrim(
2056 _Inout_z_count_(count) T* str, _In_
size_t count)
2058 for (
size_t i = 0, j = 0;;) {
2059 if (i >= count || !str[i]) {
2060 if (j < count) str[j] = 0;
2063 if (!isspace(str[i]))
2080 inline size_t rtrim(
2081 _Inout_z_count_(count) T* str, _In_
size_t count,
2082 _In_
const std::locale& locale)
2084 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
2085 for (
size_t i = 0, j = 0;;) {
2086 if (i >= count || !str[i]) {
2087 if (j < count) str[j] = 0;
2090 if (!ctype.is(ctype.space, str[i]))
2102 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
2103 static inline void rtrim(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& s)
2109 [&](_In_ _Elem ch) { return !isspace(ch); }).base(),
2119 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
2120 static inline void rtrim(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& s, _In_
const std::locale& locale)
2122 const auto& ctype = std::use_facet<std::ctype<_Elem>>(locale);
2127 [&](_In_ _Elem ch) { return !ctype.is(ctype.space, ch); }).base(),
2141 _Inout_z_count_(count) T* str, _In_
size_t count)
2143 return ltrim(str, rtrim(str, count));
2157 _Inout_z_count_(count) T* str, _In_
size_t count,
2158 _In_
const std::locale& locale)
2160 return ltrim(str, rtrim(str, count, locale), locale);
2168 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
2169 static inline void trim(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& s)
2171 auto nonspace = [&](_In_ _Elem ch) {
return !isspace(ch); };
2192 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
2193 static inline void trim(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& s, _In_
const std::locale& locale)
2195 const auto& ctype = std::use_facet<std::ctype<_Elem>>(locale);
2196 auto nonspace = [&](_In_ _Elem ch) {
return !ctype.is(ctype.space, ch); };