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 size_t glyphlen(_In_reads_or_z_opt_(count)
const wchar_t* glyph, _In_
size_t count)
188 _Assume_(glyph || !count);
191 size_t i = count < 2 || !is_surrogate_pair(glyph) ? 1 : 2;
195 for (; i < count && iscombining(glyph[i]); ++i);
209 inline T tolower(_In_ T chr)
211 return isupper(chr) ? chr | 0x20 : chr;
222 inline T toupper(_In_ T chr)
224 return islower(chr) ? chr | ~0x20 : chr;
235 inline size_t strlen(_In_z_
const T* str)
239 for (i = 0; str[i]; ++i);
252 inline size_t strnlen(_In_reads_or_z_opt_(count)
const T* str, _In_
size_t count)
254 _Assume_(str || !count);
256 for (i = 0; i < count && str[i]; ++i);
260 constexpr auto npos{
static_cast<size_t>(-1) };
271 inline size_t strchr(_In_z_
const T* str, _In_ T chr)
274 for (
size_t i = 0; str[i]; ++i)
275 if (str[i] == chr)
return i;
289 inline size_t strnchr(
290 _In_reads_or_z_opt_(count)
const T* str,
294 _Assume_(str || !count);
295 for (
size_t i = 0; i < count && str[i]; ++i)
296 if (str[i] == chr)
return i;
310 inline size_t strrnchr(
311 _In_reads_or_z_opt_(count)
const T* str,
315 _Assume_(str || !count);
317 for (
size_t i = 0; i < count && str[i]; ++i)
318 if (str[i] == chr) z = i;
332 _In_reads_or_z_opt_(count)
const T* str,
335 _Assume_(str || !count);
336 for (
size_t i = 0; i < count && str[i]; ++i)
337 if (!isspace(str[i]))
353 _In_reads_or_z_opt_(count)
const T* str,
355 _In_
const std::locale& locale)
357 _Assume_(str || !count);
358 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
359 for (
size_t i = 0; i < count && str[i]; ++i)
360 if (!ctype.is(ctype.space, str[i]))
375 inline size_t strnichr(
376 _In_reads_or_z_opt_(count)
const T* str,
380 _Assume_(str || !count);
382 for (
size_t i = 0; i < count && str[i]; ++i)
383 if (tolower(str[i]) == chr)
return i;
398 inline size_t strnichr(
399 _In_reads_or_z_opt_(count)
const T* str,
402 _In_
const std::locale& locale)
404 _Assume_(str || !count);
405 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
406 chr = ctype.tolower(chr);
407 for (
size_t i = 0; i < count && str[i]; ++i)
408 if (ctype.tolower(str[i]) == chr)
return i;
422 inline size_t strrnichr(
423 _In_reads_or_z_opt_(count)
const T* str,
427 _Assume_(str || !count);
430 for (
size_t i = 0; i < count && str[i]; ++i)
431 if (tolower(str[i]) == chr) z = i;
446 inline size_t strrnichr(
447 _In_reads_or_z_opt_(count)
const T* str,
450 _In_
const std::locale& locale)
452 _Assume_(str || !count);
453 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
454 chr = ctype.tolower(chr);
456 for (
size_t i = 0; i < count && str[i]; ++i)
457 if (ctype.tolower(str[i]) == chr) z = i;
469 template <
class T1,
class T2>
470 inline int strcmp(
const T1* str1,
const T2* str2)
472 _Assume_(str1 && str2);
474 for (
size_t i = 0; (a = str1[i]) | (b = str2[i]); ++i) {
475 if (a > b)
return +1;
476 if (a < b)
return -1;
491 template <
class T1,
class T2>
493 _In_reads_or_z_opt_(count1)
const T1* str1, _In_
size_t count1,
494 _In_reads_or_z_opt_(count2)
const T2* str2, _In_
size_t count2)
496 _Assume_(str1 || !count1);
497 _Assume_(str2 || !count2);
498 size_t i; T1 a; T2 b;
499 for (i = 0; i < count1 && i < count2 && ((a = str1[i]) | (b = str2[i])); ++i) {
500 if (a > b)
return +1;
501 if (a < b)
return -1;
503 if (i < count1 && str1[i])
return +1;
504 if (i < count2 && str2[i])
return -1;
517 template <
class T1,
class T2>
518 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)
520 _Assume_((str1 && str2) || !count);
521 size_t i; T1 a; T2 b;
522 for (i = 0; i < count && ((a = str1[i]) | (b = str2[i])); ++i) {
523 if (a > b)
return +1;
524 if (a < b)
return -1;
526 if (i < count && str1[i])
return +1;
527 if (i < count && str2[i])
return -1;
544 _In_reads_or_z_opt_(count1)
const T* str1, _In_
size_t count1,
545 _In_reads_or_z_opt_(count2)
const T* str2, _In_
size_t count2,
546 _In_
const std::locale& locale)
548 _Assume_(str1 || !count1);
549 _Assume_(str2 || !count2);
550 auto& collate = std::use_facet<std::collate<T>>(locale);
551 return collate.compare(str1, str1 + count1, str2, str2 + count2);
562 template <
class T1,
class T2>
563 inline int stricmp(_In_z_
const T1* str1, _In_z_
const T2* str2)
567 size_t i; T1 a; T2 b;
568 for (i = 0; (a = tolower(str1[i])) | (b = tolower(str2[i])); i++) {
569 if (a > b)
return +1;
570 if (a < b)
return -1;
572 if (str1[i])
return +1;
573 if (str2[i])
return -1;
586 template <
class T1,
class T2>
587 inline int stricmp(_In_z_
const T1* str1, _In_z_
const T2* str2, _In_
const std::locale& locale)
591 size_t i; T1 a; T2 b;
592 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
593 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
594 for (i = 0; (a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i])); i++) {
595 if (a > b)
return +1;
596 if (a < b)
return -1;
598 if (str1[i])
return +1;
599 if (str2[i])
return -1;
612 template <
class T1,
class T2>
613 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)
615 _Assume_(str1 || !count);
616 _Assume_(str2 || !count);
617 size_t i; T1 a; T2 b;
618 for (i = 0; i < count && ((a = tolower(str1[i])) | (b = tolower(str2[i]))); i++) {
619 if (a > b)
return +1;
620 if (a < b)
return -1;
622 if (i < count && str1[i])
return +1;
623 if (i < count && str2[i])
return -1;
637 template <
class T1,
class T2>
638 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)
640 _Assume_(str1 || !count);
641 _Assume_(str2 || !count);
642 size_t i; T1 a; T2 b;
643 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
644 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
645 for (i = 0; i < count && ((a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i]))); i++) {
646 if (a > b)
return +1;
647 if (a < b)
return -1;
649 if (i < count && str1[i])
return +1;
650 if (i < count && str2[i])
return -1;
664 template <
class T1,
class T2>
666 _In_reads_or_z_opt_(count1)
const T1* str1, _In_
size_t count1,
667 _In_reads_or_z_opt_(count2)
const T2* str2, _In_
size_t count2)
669 _Assume_(str1 || !count1);
670 _Assume_(str2 || !count2);
671 size_t i; T1 a; T2 b;
672 for (i = 0; i < count1 && i < count2 && ((a = tolower(str1[i])) | (b = tolower(str2[i]))); i++) {
673 if (a > b)
return +1;
674 if (a < b)
return -1;
676 if (i < count1 && str1[i])
return +1;
677 if (i < count2 && str2[i])
return -1;
692 template <
class T1,
class T2>
694 _In_reads_or_z_opt_(count1)
const T1* str1, _In_
size_t count1,
695 _In_reads_or_z_opt_(count2)
const T2* str2, _In_
size_t count2,
696 _In_
const std::locale& locale)
698 _Assume_(str1 || !count1);
699 _Assume_(str2 || !count2);
700 size_t i; T1 a; T2 b;
701 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
702 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
703 for (i = 0; i < count1 && i < count2 && ((a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i]))); i++) {
704 if (a > b)
return +1;
705 if (a < b)
return -1;
707 if (i < count1 && str1[i])
return +1;
708 if (i < count2 && str2[i])
return -1;
720 template <
class T1,
class T2>
721 inline size_t strstr(
722 _In_z_
const T1* str,
723 _In_z_
const T2* sample)
727 for (
size_t offset = 0;; ++offset) {
728 for (
size_t i = offset, j = 0;; ++i, ++j) {
733 if (str[i] != sample[j])
748 template <
class T1,
class T2>
749 inline size_t strnstr(
750 _In_reads_or_z_opt_(count)
const T1* str,
752 _In_z_
const T2* sample)
754 _Assume_(str || !count);
756 for (
size_t offset = 0;; ++offset) {
757 for (
size_t i = offset, j = 0;; ++i, ++j) {
760 if (i >= count || !str[i])
762 if (str[i] != sample[j])
776 template <
class T1,
class T2>
777 inline size_t stristr(
778 _In_z_
const T1* str,
779 _In_z_
const T2* sample)
783 for (
size_t offset = 0;; ++offset) {
784 for (
size_t i = offset, j = 0;; ++i, ++j) {
789 if (tolower(str[i]) != tolower(sample[j]))
804 template <
class T1,
class T2>
805 inline size_t stristr(
806 _In_z_
const T1* str,
807 _In_z_
const T2* sample,
808 _In_
const std::locale& locale)
812 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
813 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
814 for (
size_t offset = 0;; ++offset) {
815 for (
size_t i = offset, j = 0;; ++i, ++j) {
820 if (ctype1.tolower(str[i]) != ctype2.tolower(sample[j]))
835 template <
class T1,
class T2>
836 inline size_t strnistr(
837 _In_reads_or_z_opt_(count)
const T1* str,
839 _In_z_
const T2* sample)
841 _Assume_(str || !count);
843 for (
size_t offset = 0;; ++offset) {
844 for (
size_t i = offset, j = 0;; ++i, ++j) {
847 if (i >= count || !str[i])
849 if (tolower(str[i]) != tolower(sample[j]))
865 template <
class T1,
class T2>
866 inline size_t strnistr(
867 _In_reads_or_z_opt_(count)
const T1* str,
869 _In_z_
const T2* sample,
870 _In_
const std::locale& locale)
872 _Assume_(str || !count);
874 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
875 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
876 for (
size_t offset = 0;; ++offset) {
877 for (
size_t i = offset, j = 0;; ++i, ++j) {
880 if (i >= count || !str[i])
882 if (ctype1.tolower(str[i]) != ctype2.tolower(sample[j]))
896 template <
class T1,
class T2>
897 inline size_t strcpy(
898 _Out_writes_z_(_String_length_(src) + 1) T1* dst,
899 _In_z_
const T2* src)
901 _Assume_(dst && src);
902 for (
size_t i = 0; ; ++i) {
903 if ((dst[i] = src[i]) == 0)
917 template <
class T1,
class T2>
918 inline size_t strncpy(
919 _Out_writes_(count) _Post_maybez_ T1* dst,
920 _In_reads_or_z_opt_(count)
const T2* src, _In_
size_t count)
922 _Assume_(dst && src || !count);
923 for (
size_t i = 0; ; ++i) {
926 if ((dst[i] = src[i]) == 0)
941 template <
class T1,
class T2>
942 inline size_t strncpy(
943 _Out_writes_(count_dst) _Post_maybez_ T1* dst, _In_
size_t count_dst,
944 _In_reads_or_z_opt_(count_src)
const T2* src, _In_
size_t count_src)
946 _Assume_(dst || !count_dst);
947 _Assume_(src || !count_src);
948 for (
size_t i = 0; ; ++i)
952 if (i >= count_src) {
956 if ((dst[i] = src[i]) == 0)
969 template <
class T1,
class T2>
970 inline size_t strcat(
971 _In_z_ _Out_writes_z_(_String_length_(dst) + _String_length_(src) + 1) T1* dst,
972 _In_z_
const T2* src)
974 _Assume_(dst && src);
975 for (
size_t i = 0, j = stdex::strlen<T1>(dst); ; ++i, ++j) {
976 if ((dst[j] = src[i]) == 0)
990 template <
class T1,
class T2>
991 inline size_t strncat(
993 _In_reads_or_z_opt_(count)
const T2* src, _In_
size_t count)
995 _Assume_(dst && src || !count);
996 for (
size_t i = 0, j = stdex::strlen<T1>(dst); ; ++i, ++j) {
999 if ((dst[j] = src[i]) == 0)
1014 template <
class T1,
class T2>
1015 inline size_t strncat(
1016 _Out_writes_(count_dst) _Post_maybez_ T1* dst, _In_
size_t count_dst,
1017 _In_reads_or_z_opt_(count_src)
const T2* src, _In_
size_t count_src)
1019 _Assume_(dst || !count_dst);
1020 _Assume_(src || !count_src);
1021 for (
size_t i = 0, j = stdex::strnlen<T1>(dst, count_dst); ; ++i, ++j)
1025 if (i >= count_src) {
1029 if ((dst[j] = src[i]) == 0)
1045 inline _Check_return_ _Ret_maybenull_z_ T* strdup(_In_opt_z_
const T* str)
1047 if (!str) _Unlikely_
1049 size_t count = strlen(str) + 1;
1050 T* dst =
new T[count];
1051 strncpy(dst, count, str, SIZE_MAX);
1067 inline _Ret_z_ T* strndup(
1068 _In_reads_or_z_opt_(count)
const T* str,
1071 T* dst =
new T[count];
1072 strncpy(dst, count, str, SIZE_MAX);
1086 inline size_t crlf2nl(_Out_writes_z_(strlen(src)) T* dst, _In_z_
const T* src)
1091 for (i = j = 0; src[j];) {
1092 if (src[j] !=
'\r' || src[j + 1] !=
'\n')
1093 dst[i++] = src[j++];
1109 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1110 inline void crlf2nl(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& dst, _In_z_
const _Elem* src)
1113 _Assume_(src != dst.c_str());
1115 dst.reserve(strlen(src));
1116 for (
size_t j = 0; src[j];) {
1117 if (src[j] !=
'\r' || src[j + 1] !=
'\n')
1131 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1132 inline void crlf2nl(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& str)
1135 for (i = j = 0, n = str.size(); j < n;) {
1136 if (str[j] !=
'\r' || str[j + 1] !=
'\n')
1137 str[i++] = str[j++];
1147 template <
class T,
class T_bin>
1148 inline T_bin strtoint(
1149 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1150 _Out_opt_
size_t* end,
1152 _Out_ uint8_t& flags)
1154 _Assume_(str || !count);
1155 _Assume_(radix == 0 || 2 <= radix && radix <= 36);
1158 T_bin value = 0, digit,
1160 max_ui_pre1, max_ui_pre2;
1166 if (i >= count || !str[i])
goto error;
1167 if (!isspace(str[i]))
break;
1171 if (str[i] ==
'+') {
1174 if (i >= count || !str[i])
goto error;
1176 else if (str[i] ==
'-') {
1179 if (i >= count || !str[i])
goto error;
1184 if (str[i] ==
'0' && i + 1 < count && (str[i + 1] ==
'x' || str[i + 1] ==
'X')) {
1186 if (i >= count || !str[i])
goto error;
1191 if (str[i] ==
'0') {
1193 if (i >= count || !str[i])
goto error;
1194 if (str[i] ==
'x' || str[i] ==
'X') {
1197 if (i >= count || !str[i])
goto error;
1207 max_ui_pre1 = max_ui / (T_bin)radix;
1208 max_ui_pre2 = max_ui % (T_bin)radix;
1210 if (
'0' <= str[i] && str[i] <=
'9')
1211 digit = (T_bin)str[i] -
'0';
1212 else if (
'A' <= str[i] && str[i] <=
'Z')
1213 digit = (T_bin)str[i] -
'A' +
'\x0a';
1214 else if (
'a' <= str[i] && str[i] <=
'z')
1215 digit = (T_bin)str[i] -
'a' +
'\x0a';
1218 if (digit >= (T_bin)radix)
1221 if (value < max_ui_pre1 ||
1222 (value == max_ui_pre1 && digit <= max_ui_pre2))
1223 value = value * (T_bin)radix + digit;
1230 if (i >= count || !str[i])
1250 template <
class T,
class T_bin>
1252 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1253 _Out_opt_
size_t* end,
1259 switch (
sizeof(T_bin)) {
1261 value = (T_bin)strtoint<T, uint8_t>(str, count, end, radix, flags);
1262 if ((flags & 0x01) && (value & 0x80)) {
1266 return (flags & 0x02) ?
1267 (flags & 0x01) ? (T_bin)0x80 : (T_bin)0x7f :
1268 (flags & 0x01) ? -value : value;
1271 value = (T_bin)strtoint<T, uint16_t>(str, count, end, radix, flags);
1272 if ((flags & 0x01) && (value & 0x8000)) {
1276 return (flags & 0x02) ?
1277 (flags & 0x01) ? (T_bin)0x8000 : (T_bin)0x7fff :
1278 (flags & 0x01) ? -value : value;
1281 value = (T_bin)strtoint<T, uint32_t>(str, count, end, radix, flags);
1282 if ((flags & 0x01) && (value & 0x80000000)) {
1286 return (flags & 0x02) ?
1287 (flags & 0x01) ? (T_bin)0x80000000 : (T_bin)0x7fffffff :
1288 (flags & 0x01) ? -value : value;
1291 value = (T_bin)strtoint<T, uint64_t>(str, count, end, radix, flags);
1292 if ((flags & 0x01) && (value & 0x8000000000000000)) {
1296 return (flags & 0x02) ?
1297 (flags & 0x01) ? (T_bin)0x8000000000000000 : (T_bin)0x7fffffffffffffff :
1298 (flags & 0x01) ? -value : value;
1301 throw std::invalid_argument(
"Unsupported bit length");
1315 template <
class T,
class T_bin>
1316 inline T_bin strtouint(
1317 _In_reads_or_z_opt_(count)
const T* str,
1319 _Out_opt_
size_t* end,
1325 switch (
sizeof(T_bin)) {
1326 case 1: value = (T_bin)strtoint<T, uint8_t>(str, count, end, radix, flags);
break;
1327 case 2: value = (T_bin)strtoint<T, uint16_t>(str, count, end, radix, flags);
break;
1328 case 4: value = (T_bin)strtoint<T, uint32_t>(str, count, end, radix, flags);
break;
1329 case 8: value = (T_bin)strtoint<T, uint64_t>(str, count, end, radix, flags);
break;
1330 default:
throw std::invalid_argument(
"Unsupported bit length");
1333 return (flags & 0x02) ?
1334 (flags & 0x01) ? (T_bin)0 : (T_bin)-1 :
1335 (flags & 0x01) ? ~value : value;
1349 inline int32_t strto32(
1350 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1351 _Out_opt_
size_t* end,
1354 return strtoint<T, int32_t>(str, count, end, radix);
1368 inline int64_t strto64(
1369 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1370 _Out_opt_
size_t* end,
1373 return strtoint<T, int64_t>(str, count, end, radix);
1388 inline intptr_t strtoi(
1389 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1390 _Out_opt_
size_t* end,
1393#if defined(_WIN64) || defined(__LP64__)
1394 return (intptr_t)strto64(str, count, end, radix);
1396 return (intptr_t)strto32(str, count, end, radix);
1411 inline uint32_t strtou32(
1412 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1413 _Out_opt_
size_t* end,
1416 return strtouint<T, uint32_t>(str, count, end, radix);
1430 inline uint64_t strtou64(
1431 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1432 _Out_opt_
size_t* end,
1435 return strtouint<T, uint64_t>(str, count, end, radix);
1450 inline size_t strtoui(
1451 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1452 _Out_opt_
size_t* end,
1455#if defined(_WIN64) || defined(__LP64__)
1456 return (
size_t)strtou64(str, count, end, radix);
1458 return (
size_t)strtou32(str, count, end, radix);
1463 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)
1468#pragma warning(suppress: 4996)
1469 r = _vsnprintf_l(str, capacity, format, locale, arg);
1471 r = ::vsnprintf(str, capacity, format, arg);
1473 if (r == -1 && strnlen(str, capacity) == capacity) {
1475 capacity += std::max<size_t>(capacity / 8, 0x80);
1476 if (capacity > INT_MAX)
1477 throw std::invalid_argument(
"string too big");
1478 return (
int)capacity;
1483 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)
1488#pragma warning(suppress: 4996)
1489 r = _vsnwprintf_l(str, capacity, format, locale, arg);
1491 r = vswprintf(str, capacity, format, arg);
1493 if (r == -1 && strnlen(str, capacity) == capacity) {
1495 capacity += std::max<size_t>(capacity / 8, 0x80);
1496 if (capacity > INT_MAX)
1497 throw std::invalid_argument(
"string too big");
1498 return (
int)capacity;
1514 template<
class _Elem,
class _Traits,
class _Ax>
1515 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)
1517 _Elem buf[1024 /
sizeof(_Elem)];
1520 int count = vsnprintf(buf, _countof(buf) - 1, format, locale, arg);
1523 str.append(buf, count);
1526 for (
size_t capacity = 2 * 1024 /
sizeof(_Elem);; capacity *= 2) {
1528 auto buf_dyn = std::make_unique<_Elem[]>(capacity);
1529 count = vsnprintf(buf_dyn.get(), capacity - 1, format, locale, arg);
1531 str.append(buf_dyn.get(), count);
1546 template<
class _Elem,
class _Traits,
class _Ax>
1547 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, ...)
1550 va_start(arg, locale);
1551 size_t n = vappendf(str, format, locale, arg);
1564 template<
class _Elem,
class _Traits,
class _Ax>
1565 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)
1568 vappendf(str, format, locale, arg);
1578 template<
class _Elem,
class _Traits,
class _Ax>
1579 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, ...)
1582 va_start(arg, locale);
1583 vsprintf(str, format, locale, arg);
1596 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1597 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)
1599 std::basic_string<_Elem, _Traits, _Ax> str;
1600 vappendf(str, format, locale, arg);
1612 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1613 inline std::basic_string<_Elem, _Traits, _Ax> sprintf(_In_z_ _Printf_format_string_params_(2)
const _Elem* format, _In_opt_ locale_t locale, ...)
1616 va_start(arg, locale);
1617 auto str = vsprintf(format, locale, arg);
1623 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)
1626 return _strftime_l(str, capacity, format, time, locale);
1628 return strftime_l(str, capacity, format, time, locale);
1632 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)
1635 return _wcsftime_l(str, capacity, format, time, locale);
1637 return wcsftime_l(str, capacity, format, time, locale);
1650 template<
class _Elem,
class _Traits,
class _Ax>
1651 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)
1653 _Elem buf[1024 /
sizeof(_Elem)];
1656 size_t count = strftime(buf, _countof(buf), format, time, locale);
1659 str.append(buf, count);
1662 for (
size_t capacity = 2 * 1024 /
sizeof(_Elem);; capacity *= 2) {
1664 auto buf_dyn = std::make_unique<_Elem[]>(capacity);
1665 count = strftime(buf_dyn.get(), capacity, format, time, locale);
1667 str.append(buf_dyn.get(), count);
1682 template<
class _Elem,
class _Traits,
class _Ax>
1683 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)
1686 strcatftime(str, format, time, locale);
1699 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1700 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)
1702 std::basic_string<_Elem, _Traits, _Ax> str;
1703 strcatftime(str, format, time, locale);
1713 inline void strlwr(_Inout_z_ T* str)
1716 for (
size_t i = 0; str[i]; ++i)
1717 str[i] = tolower(str[i]);
1727 inline void strlwr(_Inout_z_ T* str, _In_
const std::locale& locale)
1730 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
1731 for (
size_t i = 0; str[i]; ++i)
1732 str[i] = ctype.tolower(str[i]);
1742 inline void strlwr(_Inout_updates_z_(count) T* str, _In_
size_t count)
1744 _Assume_(str || !count);
1745 for (
size_t i = 0; i < count && str[i]; ++i)
1746 str[i] = tolower(str[i]);
1757 inline void strlwr(_Inout_updates_z_(count) T* str, _In_
size_t count, _In_
const std::locale& locale)
1759 _Assume_(str || !count);
1760 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
1761 for (
size_t i = 0; i < count && str[i]; ++i)
1762 str[i] = ctype.tolower(str[i]);
1771 inline void strupr(_Inout_z_ T* str)
1774 for (
size_t i = 0; str[i]; ++i)
1775 str[i] = toupper(str[i]);
1785 inline void strupr(_Inout_z_ T* str, _In_
const std::locale& locale)
1788 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
1789 for (
size_t i = 0; str[i]; ++i)
1790 str[i] = ctype.toupper(str[i]);
1800 inline void strupr(_Inout_updates_z_(count) T* str, _In_
size_t count)
1802 _Assume_(str || !count);
1803 for (
size_t i = 0; i < count && str[i]; ++i)
1804 str[i] = toupper(str[i]);
1815 inline void strupr(_Inout_updates_z_(count) T* str, _In_
size_t count, _In_
const std::locale& locale)
1817 _Assume_(str || !count);
1818 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
1819 for (
size_t i = 0; i < count && str[i]; ++i)
1820 str[i] = ctype.toupper(str[i]);
1828 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1829 inline void strupr(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& str)
1831 for (
size_t i = 0; i < str.size(); ++i)
1832 str[i] = toupper(str[i]);
1841 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1842 inline void strupr(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& str, _In_
const std::locale& locale)
1844 const auto& ctype = std::use_facet<std::ctype<_Elem>>(locale);
1845 for (
size_t i = 0; i < str.size(); ++i)
1846 str[i] = ctype.toupper(str[i]);
1858 inline size_t ltrim(
1859 _Inout_z_count_(count) T* str, _In_
size_t count)
1861 for (
size_t i = 0;; ++i) {
1863 if (count) str[0] = 0;
1870 if (!isspace(str[i])) {
1872 return strnlen(str, count);
1873 size_t n = count != SIZE_MAX ? strncpy(str, str + i, count - i) : strcpy(str, str + i);
1890 inline size_t ltrim(
1891 _Inout_z_count_(count) T* str, _In_
size_t count,
1892 _In_
const std::locale& locale)
1894 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
1895 for (
size_t i = 0;; ++i) {
1897 if (count) str[0] = 0;
1904 if (!ctype.is(ctype.space, str[i])) {
1906 return strnlen(str, count);
1907 size_t n = count != SIZE_MAX ? strncpy(str, str + i, count - i) : strcpy(str, str + i);
1919 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1920 inline void ltrim(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& s)
1927 [&](_In_ _Elem ch) { return !isspace(ch); }));
1936 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1937 inline void ltrim(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& s, _In_
const std::locale& locale)
1939 const auto& ctype = std::use_facet<std::ctype<_Elem>>(locale);
1945 [&](_In_ _Elem ch) { return !ctype.is(ctype.space, ch); }));
1957 inline size_t rtrim(
1958 _Inout_z_count_(count) T* str, _In_
size_t count)
1960 for (
size_t i = 0, j = 0;;) {
1961 if (i >= count || !str[i]) {
1962 if (j < count) str[j] = 0;
1965 if (!isspace(str[i]))
1982 inline size_t rtrim(
1983 _Inout_z_count_(count) T* str, _In_
size_t count,
1984 _In_
const std::locale& locale)
1986 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
1987 for (
size_t i = 0, j = 0;;) {
1988 if (i >= count || !str[i]) {
1989 if (j < count) str[j] = 0;
1992 if (!ctype.is(ctype.space, str[i]))
2004 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
2005 static inline void rtrim(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& s)
2011 [&](_In_ _Elem ch) { return !isspace(ch); }).base(),
2021 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
2022 static inline void rtrim(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& s, _In_
const std::locale& locale)
2024 const auto& ctype = std::use_facet<std::ctype<_Elem>>(locale);
2029 [&](_In_ _Elem ch) { return !ctype.is(ctype.space, ch); }).base(),
2043 _Inout_z_count_(count) T* str, _In_
size_t count)
2045 return ltrim(str, rtrim(str, count));
2059 _Inout_z_count_(count) T* str, _In_
size_t count,
2060 _In_
const std::locale& locale)
2062 return ltrim(str, rtrim(str, count, locale), locale);
2070 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
2071 static inline void trim(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& s)
2073 auto nonspace = [&](_In_ _Elem ch) {
return !isspace(ch); };
2094 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
2095 static inline void trim(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& s, _In_
const std::locale& locale)
2097 const auto& ctype = std::use_facet<std::ctype<_Elem>>(locale);
2098 auto nonspace = [&](_In_ _Elem ch) {
return !ctype.is(ctype.space, ch); };