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 (
static_cast<char32_t>(str[0] - 0xd800) << 10) +
75 static_cast<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 +
static_cast<char32_t>((chr >> 10) & 0x3ff);
89 str[1] = 0xdc00 +
static_cast<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 bool is7bit(_In_ T chr)
199 return '\x00' <= chr && chr <=
'\x7f';
208 inline size_t glyphlen(_In_reads_or_z_opt_(count)
const wchar_t* glyph, _In_
size_t count)
210 _Assume_(glyph || !count);
213 size_t i = count < 2 || !is_surrogate_pair(glyph) ? 1 : 2;
217 for (; i < count && iscombining(glyph[i]); ++i);
229 inline size_t glyphrlen(_In_reads_or_z_opt_(count)
const wchar_t* str, _In_
size_t count)
231 _Assume_(count && str && str[count - 1]);
232 for (
size_t i = count; i--;) {
233 if (!iscombining(str[i])) {
235 return count - (!is_low_surrogate(str[i]) || i == 0 || !is_high_surrogate(str[i - 1]) ? i : i - 1);
252 inline T tolower(_In_ T chr)
254 return isupper(chr) ? chr | 0x20 : chr;
265 inline T toupper(_In_ T chr)
267 return islower(chr) ? chr | ~0x20 : chr;
278 inline size_t strlen(_In_z_
const T* str)
282 for (i = 0; str[i]; ++i);
295 inline size_t strnlen(_In_reads_or_z_opt_(count)
const T* str, _In_
size_t count)
297 _Assume_(str || !count);
299 for (i = 0; i < count && str[i]; ++i);
310 template <
class T,
size_t N>
311 inline size_t strnlen(_In_
const T (&str)[N])
313 return strnlen(str, N);
316 constexpr auto npos{
static_cast<size_t>(-1) };
327 inline size_t strchr(_In_z_
const T* str, _In_ T chr)
330 for (
size_t i = 0; str[i]; ++i)
331 if (str[i] == chr)
return i;
345 inline size_t strnchr(
346 _In_reads_or_z_opt_(count)
const T* str,
350 _Assume_(str || !count);
351 for (
size_t i = 0; i < count && str[i]; ++i)
352 if (str[i] == chr)
return i;
364 template <
class T,
size_t N>
365 inline size_t strnchr(
366 _In_
const T (&str)[N],
369 return strnchr(str, N, chr);
381 inline size_t strrchr(
387 for (
size_t i = 0; str[i]; ++i)
388 if (str[i] == chr) z = i;
402 inline size_t strrnchr(
403 _In_reads_or_z_opt_(count)
const T* str,
407 _Assume_(str || !count);
409 for (
size_t i = 0; i < count && str[i]; ++i)
410 if (str[i] == chr) z = i;
422 template <
class T,
size_t N>
423 inline size_t strrnchr(
424 _In_
const T (&str)[N],
427 return strrnchr(str, N, chr);
439 inline size_t strichr(
445 for (
size_t i = 0; str[i]; ++i)
446 if (tolower(str[i]) == chr)
return i;
460 inline size_t strichr(
463 _In_
const std::locale& locale)
466 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
467 chr = ctype.tolower(chr);
468 for (
size_t i = 0; str[i]; ++i)
469 if (ctype.tolower(str[i]) == chr)
return i;
483 inline size_t strnichr(
484 _In_reads_or_z_opt_(count)
const T* str,
488 _Assume_(str || !count);
490 for (
size_t i = 0; i < count && str[i]; ++i)
491 if (tolower(str[i]) == chr)
return i;
506 inline size_t strnichr(
507 _In_reads_or_z_opt_(count)
const T* str,
510 _In_
const std::locale& locale)
512 _Assume_(str || !count);
513 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
514 chr = ctype.tolower(chr);
515 for (
size_t i = 0; i < count && str[i]; ++i)
516 if (ctype.tolower(str[i]) == chr)
return i;
528 template <
class T,
size_t N>
529 inline size_t strnichr(
530 _In_
const T (&str)[N],
533 return strnichr(str, N, chr);
545 template <
class T,
size_t N>
546 inline size_t strnichr(
547 _In_
const T (&str)[N],
549 _In_
const std::locale& locale)
551 return strnichr(str, N, chr, locale);
563 inline size_t strrichr(
570 for (
size_t i = 0; str[i]; ++i)
571 if (tolower(str[i]) == chr) z = i;
585 inline size_t strrichr(
586 _In_reads_or_z_opt_(count)
const T* str,
588 _In_
const std::locale& locale)
591 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
592 chr = ctype.tolower(chr);
594 for (
size_t i = 0; str[i]; ++i)
595 if (ctype.tolower(str[i]) == chr) z = i;
609 inline size_t strrnichr(
610 _In_reads_or_z_opt_(count)
const T* str,
614 _Assume_(str || !count);
617 for (
size_t i = 0; i < count && str[i]; ++i)
618 if (tolower(str[i]) == chr) z = i;
633 inline size_t strrnichr(
634 _In_reads_or_z_opt_(count)
const T* str,
637 _In_
const std::locale& locale)
639 _Assume_(str || !count);
640 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
641 chr = ctype.tolower(chr);
643 for (
size_t i = 0; i < count && str[i]; ++i)
644 if (ctype.tolower(str[i]) == chr) z = i;
656 template <
class T,
size_t N>
657 inline size_t strrnichr(
658 _In_
const T (&str)[N],
661 return strrnichr(str, N, chr);
673 template <
class T,
size_t N>
674 inline size_t strrnichr(
675 _In_
const T (&str)[N],
677 _In_
const std::locale& locale)
679 return strrnichr(str, N, chr, locale);
730 _In_reads_or_z_opt_(count)
const T* str,
733 _Assume_(str || !count);
734 for (
size_t i = 0; i < count && str[i]; ++i)
735 if (!isspace(str[i]))
751 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
752 _In_
const std::locale& locale)
754 _Assume_(str || !count);
755 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
756 for (
size_t i = 0; i < count && str[i]; ++i)
757 if (!ctype.is(ctype.space, str[i]))
769 template <
class T,
size_t N>
770 inline bool isblank(_In_
const T (&str)[N])
772 return isblank(str, N);
783 template <
class T,
size_t N>
785 _In_
const T (&str)[N],
786 _In_
const std::locale& locale)
788 return isblank(str, N, locale);
817 inline bool is7bit(_In_reads_or_z_opt_(count)
const T* str, _In_
size_t count)
819 _Assume_(str || !count);
820 for (
size_t i = 0; i < count && str[i]; i++)
833 template <
class T,
size_t N>
834 inline bool is7bit(_In_
const T (&str)[N])
836 return is7bit(str, N);
847 template <
class T1,
class T2>
848 inline int strcmp(_In_z_
const T1* str1, _In_z_
const T2* str2)
852 size_t i; T1 a; T2 b;
853 for (i = 0; (a = str1[i]) | (b = str2[i]); ++i) {
854 if (a > b)
return +1;
855 if (a < b)
return -1;
857 if (str1[i])
return +1;
858 if (str2[i])
return -1;
871 template <
class T1,
class T2>
872 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)
874 _Assume_(str1 || !count);
875 _Assume_(str2 || !count);
876 size_t i; T1 a; T2 b;
877 for (i = 0; i < count && ((a = str1[i]) | (b = str2[i])); ++i) {
878 if (a > b)
return +1;
879 if (a < b)
return -1;
881 if (i < count && str1[i])
return +1;
882 if (i < count && str2[i])
return -1;
896 template <
class T1,
class T2>
898 _In_reads_or_z_opt_(count1)
const T1* str1, _In_
size_t count1,
899 _In_reads_or_z_opt_(count2)
const T2* str2, _In_
size_t count2)
901 _Assume_(str1 || !count1);
902 _Assume_(str2 || !count2);
903 size_t i; T1 a; T2 b;
904 for (i = 0; i < count1 && i < count2 && ((a = str1[i]) | (b = str2[i])); ++i) {
905 if (a > b)
return +1;
906 if (a < b)
return -1;
908 if (i < count1 && str1[i])
return +1;
909 if (i < count2 && str2[i])
return -1;
921 template <
class T1,
size_t N1,
class T2,
size_t N2>
923 _In_
const T1 (&str1)[N1],
924 _In_
const T2 (&str2)[N2])
926 return strncmp(str1, N1, str2, N2);
937 template <
class T1,
class T2>
938 inline int strrcmp(_In_z_
const T1* str1, _In_z_
const T2* str2)
943 _Assume_(str1 || !i);
944 _Assume_(str2 || !j);
945 size_t k; T1 a; T2 b;
946 for (k = 1; i && j; k++) {
948 if ((a = str1[i]) > (b = str2[j]))
return +1;
949 if (a < b)
return -1;
951 if (i && !j)
return +1;
952 if (!i && j)
return -1;
965 template <
class T1,
class T2>
966 inline int strrncmp(_In_reads_or_z_opt_(count)
const T1* str1, _In_reads_or_z_opt_(count)
const T2* str2, _In_
size_t count)
969 i = strnlen(str1, count),
970 j = strnlen(str2, count);
971 _Assume_(str1 || !i);
972 _Assume_(str2 || !j);
973 size_t k; T1 a; T2 b;
974 for (k = 1; i && j; k++) {
976 if ((a = str1[i]) > (b = str2[j]))
return +1;
977 if (a < b)
return -1;
979 if (i && !j)
return +1;
980 if (!i && j)
return -1;
994 template <
class T1,
class T2>
996 _In_reads_or_z_opt_(count1)
const T1* str1, _In_
size_t count1,
997 _In_reads_or_z_opt_(count2)
const T2* str2, _In_
size_t count2)
1000 i = strnlen(str1, count1),
1001 j = strnlen(str2, count2);
1002 _Assume_(str1 || !i);
1003 _Assume_(str2 || !j);
1004 size_t k; T1 a; T2 b;
1005 for (k = 1; i && j; k++) {
1007 if ((a = str1[i]) > (b = str2[j]))
return +1;
1008 if (a < b)
return -1;
1010 if (i && !j)
return +1;
1011 if (!i && j)
return -1;
1023 template <
class T1,
size_t N1,
class T2,
size_t N2>
1024 inline int strrncmp(
1025 _In_
const T1 (&str1)[N1],
1026 _In_
const T2 (&str2)[N2])
1028 return strrncmp(str1, N1, str2, N2);
1039 template <
class T1,
class T2>
1040 inline int stricmp(_In_z_
const T1* str1, _In_z_
const T2* str2)
1044 size_t i; T1 a; T2 b;
1045 for (i = 0; (a = tolower(str1[i])) | (b = tolower(str2[i])); ++i) {
1046 if (a > b)
return +1;
1047 if (a < b)
return -1;
1049 if (str1[i])
return +1;
1050 if (str2[i])
return -1;
1063 template <
class T1,
class T2>
1064 inline int stricmp(_In_z_
const T1* str1, _In_z_
const T2* str2, _In_
const std::locale& locale)
1068 size_t i; T1 a; T2 b;
1069 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
1070 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
1071 for (i = 0; (a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i])); ++i) {
1072 if (a > b)
return +1;
1073 if (a < b)
return -1;
1075 if (str1[i])
return +1;
1076 if (str2[i])
return -1;
1089 template <
class T1,
class T2>
1090 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)
1092 _Assume_(str1 || !count);
1093 _Assume_(str2 || !count);
1094 size_t i; T1 a; T2 b;
1095 for (i = 0; i < count && ((a = tolower(str1[i])) | (b = tolower(str2[i]))); ++i) {
1096 if (a > b)
return +1;
1097 if (a < b)
return -1;
1099 if (i < count && str1[i])
return +1;
1100 if (i < count && str2[i])
return -1;
1114 template <
class T1,
class T2>
1115 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)
1117 _Assume_(str1 || !count);
1118 _Assume_(str2 || !count);
1119 size_t i; T1 a; T2 b;
1120 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
1121 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
1122 for (i = 0; i < count && ((a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i]))); ++i) {
1123 if (a > b)
return +1;
1124 if (a < b)
return -1;
1126 if (i < count && str1[i])
return +1;
1127 if (i < count && str2[i])
return -1;
1141 template <
class T1,
class T2>
1142 inline int strnicmp(
1143 _In_reads_or_z_opt_(count1)
const T1* str1, _In_
size_t count1,
1144 _In_reads_or_z_opt_(count2)
const T2* str2, _In_
size_t count2)
1146 _Assume_(str1 || !count1);
1147 _Assume_(str2 || !count2);
1148 size_t i; T1 a; T2 b;
1149 for (i = 0; i < count1 && i < count2 && ((a = tolower(str1[i])) | (b = tolower(str2[i]))); ++i) {
1150 if (a > b)
return +1;
1151 if (a < b)
return -1;
1153 if (i < count1 && str1[i])
return +1;
1154 if (i < count2 && str2[i])
return -1;
1169 template <
class T1,
class T2>
1170 inline int strnicmp(
1171 _In_reads_or_z_opt_(count1)
const T1* str1, _In_
size_t count1,
1172 _In_reads_or_z_opt_(count2)
const T2* str2, _In_
size_t count2,
1173 _In_
const std::locale& locale)
1175 _Assume_(str1 || !count1);
1176 _Assume_(str2 || !count2);
1177 size_t i; T1 a; T2 b;
1178 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
1179 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
1180 for (i = 0; i < count1 && i < count2 && ((a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i]))); ++i) {
1181 if (a > b)
return +1;
1182 if (a < b)
return -1;
1184 if (i < count1 && str1[i])
return +1;
1185 if (i < count2 && str2[i])
return -1;
1197 template <
class T1,
size_t N1,
class T2,
size_t N2>
1198 inline int strnicmp(
1199 _In_
const T1 (&str1)[N1],
1200 _In_
const T2 (&str2)[N2])
1202 strnicmp(str1, N1, str2, N2);
1214 template <
class T1,
size_t N1,
class T2,
size_t N2>
1215 inline int strnicmp(
1216 _In_
const T1 (&str1)[N1],
1217 _In_
const T2 (&str2)[N2],
1218 _In_
const std::locale& locale)
1220 strnicmp(str1, N1, str2, N2, locale);
1234 _In_z_
const T* str1,
1235 _In_z_
const T* str2,
1236 _In_
const std::locale& locale)
1240 auto& collate = std::use_facet<std::collate<T>>(locale);
1241 return collate.compare(str1, str1 + strlen(str1), str2, str2 + strlen(str2));
1256 inline int strncoll(
1257 _In_reads_or_z_opt_(count1)
const T* str1, _In_
size_t count1,
1258 _In_reads_or_z_opt_(count2)
const T* str2, _In_
size_t count2,
1259 _In_
const std::locale& locale)
1261 _Assume_(str1 || !count1);
1262 _Assume_(str2 || !count2);
1263 auto& collate = std::use_facet<std::collate<T>>(locale);
1264 return collate.compare(str1, str1 + count1, str2, str2 + count2);
1276 template <
class T,
size_t N1,
size_t N2>
1277 inline int strncoll(
1278 _In_
const T (&str1)[N1],
1279 _In_
const T (&str2)[N2],
1280 _In_
const std::locale& locale)
1282 return strncoll(str1, N1, str2, N2, locale);
1293 template <
class T1,
class T2>
1294 inline size_t strstr(
1295 _In_z_
const T1* str,
1296 _In_z_
const T2* sample)
1300 for (
size_t offset = 0;; ++offset) {
1301 for (
size_t i = offset, j = 0;; ++i, ++j) {
1306 if (str[i] != sample[j])
1321 template <
class T1,
class T2>
1322 inline size_t strnstr(
1323 _In_reads_or_z_opt_(count)
const T1* str, _In_
size_t count,
1324 _In_z_
const T2* sample)
1326 _Assume_(str || !count);
1328 for (
size_t offset = 0;; ++offset) {
1329 for (
size_t i = offset, j = 0;; ++i, ++j) {
1332 if (i >= count || !str[i])
1334 if (str[i] != sample[j])
1348 template <
class T1,
size_t N1,
class T2>
1349 inline size_t strnstr(
1350 _In_
const T1 (&str)[N1],
1351 _In_z_
const T2* sample)
1353 return strnstr(str, N1, sample);
1364 template <
class T1,
class T2>
1365 inline size_t stristr(
1366 _In_z_
const T1* str,
1367 _In_z_
const T2* sample)
1371 for (
size_t offset = 0;; ++offset) {
1372 for (
size_t i = offset, j = 0;; ++i, ++j) {
1377 if (tolower(str[i]) != tolower(sample[j]))
1392 template <
class T1,
class T2>
1393 inline size_t stristr(
1394 _In_z_
const T1* str,
1395 _In_z_
const T2* sample,
1396 _In_
const std::locale& locale)
1400 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
1401 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
1402 for (
size_t offset = 0;; ++offset) {
1403 for (
size_t i = offset, j = 0;; ++i, ++j) {
1408 if (ctype1.tolower(str[i]) != ctype2.tolower(sample[j]))
1423 template <
class T1,
class T2>
1424 inline size_t strnistr(
1425 _In_reads_or_z_opt_(count)
const T1* str,
1427 _In_z_
const T2* sample)
1429 _Assume_(str || !count);
1431 for (
size_t offset = 0;; ++offset) {
1432 for (
size_t i = offset, j = 0;; ++i, ++j) {
1435 if (i >= count || !str[i])
1437 if (tolower(str[i]) != tolower(sample[j]))
1453 template <
class T1,
class T2>
1454 inline size_t strnistr(
1455 _In_reads_or_z_opt_(count)
const T1* str,
1457 _In_z_
const T2* sample,
1458 _In_
const std::locale& locale)
1460 _Assume_(str || !count);
1462 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
1463 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
1464 for (
size_t offset = 0;; ++offset) {
1465 for (
size_t i = offset, j = 0;; ++i, ++j) {
1468 if (i >= count || !str[i])
1470 if (ctype1.tolower(str[i]) != ctype2.tolower(sample[j]))
1484 template <
class T1,
size_t N1,
class T2>
1485 inline size_t strnistr(
1486 _In_
const T1 (&str)[N1],
1487 _In_z_
const T2* sample)
1489 return strnistr(str, N1, sample);
1501 template <
class T1,
size_t N1,
class T2>
1502 inline size_t strnistr(
1503 _In_
const T1 (&str)[N1],
1504 _In_z_
const T2* sample,
1505 _In_
const std::locale& locale)
1507 return strnistr(str, N1, sample, locale);
1518 template <
class T1,
class T2>
1519 inline size_t strcpy(
1520 _Out_writes_z_(_String_length_(src) + 1) T1* dst,
1521 _In_z_
const T2* src)
1525 for (
size_t i = 0; ; ++i) {
1526 if ((dst[i] =
static_cast<T1
>(src[i])) == 0)
1540 template <
class T1,
class T2>
1541 inline size_t strncpy(
1542 _Out_writes_(count) _Post_maybez_ T1* dst,
1543 _In_reads_or_z_opt_(count)
const T2* src, _In_
size_t count)
1545 _Assume_(dst || !count);
1546 _Assume_(src || !count);
1547 for (
size_t i = 0; ; ++i) {
1550 if ((dst[i] =
static_cast<T1
>(src[i])) == 0)
1565 template <
class T1,
class T2>
1566 inline size_t strncpy(
1567 _Out_writes_(count_dst) _Post_maybez_ T1* dst, _In_
size_t count_dst,
1568 _In_reads_or_z_opt_(count_src)
const T2* src, _In_
size_t count_src)
1570 _Assume_(dst || !count_dst);
1571 _Assume_(src || !count_src);
1572 for (
size_t i = 0; ; ++i)
1576 if (i >= count_src) {
1580 if ((dst[i] =
static_cast<T1
>(src[i])) == 0)
1593 template <
class T1,
size_t N1,
class T2,
size_t N2>
1594 inline size_t strncpy(
1595 _Out_ _Post_maybez_ T1 (&dst)[N1],
1596 _In_
const T2 (&src)[N2])
1598 return strncpy(dst, N1, src, N2);
1609 template <
class T1,
class T2>
1610 inline size_t strcat(
1611 _In_z_ _Out_writes_z_(_String_length_(dst) + _String_length_(src) + 1) T1* dst,
1612 _In_z_
const T2* src)
1616 for (
size_t i = 0, j = stdex::strlen<T1>(dst); ; ++i, ++j) {
1617 if ((dst[j] =
static_cast<T1
>(src[i])) == 0)
1631 template <
class T1,
class T2>
1632 inline size_t strncat(
1634 _In_reads_or_z_opt_(count)
const T2* src, _In_
size_t count)
1636 _Assume_(dst || !count);
1637 _Assume_(src || !count);
1638 for (
size_t i = 0, j = stdex::strlen<T1>(dst); ; ++i, ++j) {
1641 if ((dst[j] =
static_cast<T1
>(src[i])) == 0)
1656 template <
class T1,
class T2>
1657 inline size_t strncat(
1658 _Out_writes_(count_dst) _Post_maybez_ T1* dst, _In_
size_t count_dst,
1659 _In_reads_or_z_opt_(count_src)
const T2* src, _In_
size_t count_src)
1661 _Assume_(dst || !count_dst);
1662 _Assume_(src || !count_src);
1663 for (
size_t i = 0, j = stdex::strnlen<T1>(dst, count_dst); ; ++i, ++j)
1667 if (i >= count_src) {
1671 if ((dst[j] =
static_cast<T1
>(src[i])) == 0)
1687 inline _Check_return_ _Ret_maybenull_z_ T* strdup(_In_opt_z_
const T* str)
1689 if (!str) _Unlikely_
1691 size_t count = strlen(str) + 1;
1692 T* dst =
new T[count];
1693 strncpy(dst, count, str, SIZE_MAX);
1709 inline _Ret_z_ T* strndup(
1710 _In_reads_or_z_opt_(count)
const T* str,
1713 T* dst =
new T[count];
1714 strncpy(dst, count, str, SIZE_MAX);
1728 template <
class T,
size_t N>
1729 inline _Check_return_ _Ret_maybenull_z_ T* strndup(_In_
const T (&str)[N])
1731 return strndup(str, N);
1744 inline size_t crlf2nl(_Out_writes_z_(_String_length_(src) + 1) T* dst, _In_z_
const T* src)
1749 for (i = j = 0; src[j];) {
1750 if (src[j] !=
'\r' || src[j + 1] !=
'\n')
1751 dst[i++] = src[j++];
1767 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
1768 inline void crlf2nl(_Inout_ std::basic_string<T, TR, AX>& dst, _In_z_
const T* src)
1771 _Assume_(src != dst.data());
1773 dst.reserve(strlen(src));
1774 for (
size_t j = 0; src[j];) {
1775 if (src[j] !=
'\r' || src[j + 1] !=
'\n')
1789 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
1790 inline void crlf2nl(_Inout_ std::basic_string<T, TR, AX>& str)
1793 for (i = j = 0, n = str.size(); j < n;) {
1794 if (str[j] !=
'\r' || str[j + 1] !=
'\n')
1795 str[i++] = str[j++];
1805 template <
class T,
class T_bin>
1806 inline T_bin strtoint(
1807 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1808 _Out_opt_
size_t* end,
1810 _Out_ uint8_t& flags)
1812 _Assume_(str || !count);
1813 _Assume_(radix == 0 || 2 <= radix && radix <= 36);
1816 T_bin value = 0, digit,
1818 max_ui_pre1, max_ui_pre2;
1824 if (i >= count || !str[i])
goto error;
1825 if (!isspace(str[i]))
break;
1829 if (str[i] ==
'+') {
1832 if (i >= count || !str[i])
goto error;
1834 else if (str[i] ==
'-') {
1837 if (i >= count || !str[i])
goto error;
1842 if (str[i] ==
'0' && i + 1 < count && (str[i + 1] ==
'x' || str[i + 1] ==
'X')) {
1844 if (i >= count || !str[i])
goto error;
1849 if (str[i] ==
'0') {
1851 if (i >= count || !str[i])
goto error;
1852 if (str[i] ==
'x' || str[i] ==
'X') {
1855 if (i >= count || !str[i])
goto error;
1865 max_ui_pre1 = max_ui / (T_bin)radix;
1866 max_ui_pre2 = max_ui % (T_bin)radix;
1868 if (
'0' <= str[i] && str[i] <=
'9')
1869 digit = (T_bin)str[i] -
'0';
1870 else if (
'A' <= str[i] && str[i] <=
'Z')
1871 digit = (T_bin)str[i] -
'A' +
'\x0a';
1872 else if (
'a' <= str[i] && str[i] <=
'z')
1873 digit = (T_bin)str[i] -
'a' +
'\x0a';
1876 if (digit >= (T_bin)radix)
1879 if (value < max_ui_pre1 ||
1880 (value == max_ui_pre1 && digit <= max_ui_pre2))
1881 value = value * (T_bin)radix + digit;
1888 if (i >= count || !str[i])
1908 template <
class T,
class T_bin>
1910 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1911 _Out_opt_
size_t* end,
1917 switch (
sizeof(T_bin)) {
1919 value = (T_bin)strtoint<T, uint8_t>(str, count, end, radix, flags);
1920 if ((flags & 0x01) && (value & 0x80)) {
1924 return (flags & 0x02) ?
1925 (flags & 0x01) ? (T_bin)0x80 : (T_bin)0x7f :
1926 (flags & 0x01) ? -value : value;
1929 value = (T_bin)strtoint<T, uint16_t>(str, count, end, radix, flags);
1930 if ((flags & 0x01) && (value & 0x8000)) {
1934 return (flags & 0x02) ?
1935 (flags & 0x01) ? (T_bin)0x8000 : (T_bin)0x7fff :
1936 (flags & 0x01) ? -value : value;
1939 value = (T_bin)strtoint<T, uint32_t>(str, count, end, radix, flags);
1940 if ((flags & 0x01) && (value & 0x80000000)) {
1944 return (flags & 0x02) ?
1945 (flags & 0x01) ? (T_bin)0x80000000 : (T_bin)0x7fffffff :
1946 (flags & 0x01) ? -value : value;
1949 value = (T_bin)strtoint<T, uint64_t>(str, count, end, radix, flags);
1950 if ((flags & 0x01) && (value & 0x8000000000000000)) {
1954 return (flags & 0x02) ?
1955 (flags & 0x01) ? (T_bin)0x8000000000000000 : (T_bin)0x7fffffffffffffff :
1956 (flags & 0x01) ? -value : value;
1959 throw std::invalid_argument(
"Unsupported bit length");
1972 template <
class T,
size_t N,
class T_bin>
1974 _In_
const T (&str)[N],
1975 _Out_opt_
size_t* end,
1978 return strtoint<T, T_bin>(str, N, end, radix);
1991 template <
class T,
class T_bin>
1992 inline T_bin strtouint(
1993 _In_reads_or_z_opt_(count)
const T* str,
1995 _Out_opt_
size_t* end,
2001 switch (
sizeof(T_bin)) {
2002 case 1: value = (T_bin)strtoint<T, uint8_t>(str, count, end, radix, flags);
break;
2003 case 2: value = (T_bin)strtoint<T, uint16_t>(str, count, end, radix, flags);
break;
2004 case 4: value = (T_bin)strtoint<T, uint32_t>(str, count, end, radix, flags);
break;
2005 case 8: value = (T_bin)strtoint<T, uint64_t>(str, count, end, radix, flags);
break;
2006 default:
throw std::invalid_argument(
"Unsupported bit length");
2009 return (flags & 0x02) ?
2010 (flags & 0x01) ? (T_bin)0 : (T_bin)-1 :
2011 (flags & 0x01) ? ~value : value;
2023 template <
class T,
size_t N,
class T_bin>
2024 inline T_bin strtouint(
2025 _In_
const T (&str)[N],
2026 _Out_opt_
size_t* end,
2029 return strtouint<T, T_bin>(str, N, end, radix);
2043 inline int32_t strto32(
2044 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
2045 _Out_opt_
size_t* end,
2048 return strtoint<T, int32_t>(str, count, end, radix);
2060 template <
class T,
size_t N>
2061 inline int32_t strto32(
2062 _In_
const T (&str)[N],
2063 _Out_opt_
size_t* end,
2066 return strto32<T>(str, N, end, radix);
2080 inline int64_t strto64(
2081 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
2082 _Out_opt_
size_t* end,
2085 return strtoint<T, int64_t>(str, count, end, radix);
2097 template <
class T,
size_t N>
2098 inline int64_t strto64(
2099 _In_
const T (&str)[N],
2100 _Out_opt_
size_t* end,
2103 return strto64<T>(str, N, end, radix);
2118 inline ptrdiff_t strtoi(
2119 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
2120 _Out_opt_
size_t* end,
2123#if defined(_WIN64) || defined(__LP64__)
2124 return static_cast<ptrdiff_t
>(strto64(str, count, end, radix));
2126 return static_cast<ptrdiff_t
>(strto32(str, count, end, radix));
2140 template <
class T,
size_t N>
2141 inline ptrdiff_t strtoi(
2142 _In_
const T (&str)[N],
2143 _Out_opt_
size_t* end,
2146 return strtoi<T>(str, N, end, radix);
2160 inline uint32_t strtou32(
2161 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
2162 _Out_opt_
size_t* end,
2165 return strtouint<T, uint32_t>(str, count, end, radix);
2177 template <
class T,
size_t N>
2178 inline uint32_t strtou32(
2179 _In_
const T (&str)[N],
2180 _Out_opt_
size_t* end,
2183 return strtou32(str, N, end, radix);
2197 inline uint64_t strtou64(
2198 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
2199 _Out_opt_
size_t* end,
2202 return strtouint<T, uint64_t>(str, count, end, radix);
2214 template <
class T,
size_t N>
2215 inline uint64_t strtou64(
2216 _In_
const T (&str)[N],
2217 _Out_opt_
size_t* end,
2220 return strtou64<T>(str, N, end, radix);
2235 inline size_t strtoui(
2236 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
2237 _Out_opt_
size_t* end,
2240#if defined(_WIN64) || defined(__LP64__)
2241 return static_cast<size_t>(strtou64(str, count, end, radix));
2243 return static_cast<size_t>(strtou32(str, count, end, radix));
2257 template <
class T,
size_t N>
2258 inline size_t strtoui(
2259 _In_
const T (&str)[N],
2260 _Out_opt_
size_t* end,
2263 return strtoui<T>(str, N, end, radix);
2276 inline double strtod(
2277 _In_reads_or_z_opt_(count)
const char* str, _In_
size_t count,
2278 _Out_opt_
size_t* end,
2279 _In_opt_ locale_t locale)
2281 std::string tmp(str, strnlen(str, count));
2285 r = _strtod_l(tmp.c_str(), &_end, locale);
2287 r = strtod_l(tmp.c_str(), &_end, locale);
2289 if (end) *end = (size_t)(_end - tmp.c_str());
2303 inline double strtod(
2304 _In_reads_or_z_opt_(count)
const wchar_t* str, _In_
size_t count,
2305 _Out_opt_
size_t* end,
2306 _In_opt_ locale_t locale)
2308 std::wstring tmp(str, strnlen(str, count));
2312 r = _wcstod_l(tmp.c_str(), &_end, locale);
2314 r = wcstod_l(tmp.c_str(), &_end, locale);
2316 if (end) *end = (size_t)(_end - tmp.c_str());
2321 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)
2326#pragma warning(suppress: 4996)
2327 r = _vsnprintf_l(str, capacity, format, locale, arg);
2329 r = ::vsnprintf(str, capacity, format, arg);
2331 if (r == -1 && strnlen(str, capacity) == capacity) {
2333 capacity += std::max<size_t>(capacity / 8, 0x80);
2334 if (capacity > INT_MAX)
2335 throw std::invalid_argument(
"string too big");
2336 return (
int)capacity;
2341 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)
2346#pragma warning(suppress: 4996)
2347 r = _vsnwprintf_l(str, capacity, format, locale, arg);
2349 r = vswprintf(str, capacity, format, arg);
2351 if (r == -1 && strnlen(str, capacity) == capacity) {
2353 capacity += std::max<size_t>(capacity / 8, 0x80);
2354 if (capacity > INT_MAX)
2355 throw std::invalid_argument(
"string too big");
2356 return (
int)capacity;
2372 template<
class T,
class TR,
class AX>
2373 inline size_t vappendf(_Inout_ std::basic_string<T, TR, AX>& str, _In_z_ _Printf_format_string_params_(2)
const T* format, _In_opt_ locale_t locale, _In_ va_list arg)
2375 T buf[1024 /
sizeof(T)];
2378 int count = vsnprintf(buf, _countof(buf) - 1, format, locale, arg);
2381 str.append(buf, count);
2384 for (
size_t capacity = 2 * 1024 /
sizeof(T);; capacity *= 2) {
2386 auto buf_dyn = std::make_unique<T[]>(capacity);
2387 count = vsnprintf(buf_dyn.get(), capacity - 1, format, locale, arg);
2389 str.append(buf_dyn.get(), count);
2404 template<
class T,
class TR,
class AX>
2405 inline size_t appendf(_Inout_ std::basic_string<T, TR, AX>& str, _In_z_ _Printf_format_string_params_(2)
const T* format, _In_opt_ locale_t locale, ...)
2408 va_start(arg, locale);
2409 size_t n = vappendf(str, format, locale, arg);
2422 template<
class T,
class TR,
class AX>
2423 inline void vsprintf(_Inout_ std::basic_string<T, TR, AX>& str, _In_z_ _Printf_format_string_params_(2)
const T* format, _In_opt_ locale_t locale, _In_ va_list arg)
2426 vappendf(str, format, locale, arg);
2436 template<
class T,
class TR,
class AX>
2437 inline void sprintf(_Inout_ std::basic_string<T, TR, AX>& str, _In_z_ _Printf_format_string_params_(2)
const T* format, _In_opt_ locale_t locale, ...)
2440 va_start(arg, locale);
2441 vsprintf(str, format, locale, arg);
2454 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
2455 inline std::basic_string<T, TR, AX> vsprintf(_In_z_ _Printf_format_string_params_(2)
const T* format, _In_opt_ locale_t locale, _In_ va_list arg)
2457 std::basic_string<T, TR, AX> str;
2458 vappendf(str, format, locale, arg);
2470 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
2471 inline std::basic_string<T, TR, AX> sprintf(_In_z_ _Printf_format_string_params_(2)
const T* format, _In_opt_ locale_t locale, ...)
2474 va_start(arg, locale);
2475 auto str = vsprintf(format, locale, arg);
2481 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)
2484 return _strftime_l(str, capacity, format, time, locale);
2486 return strftime_l(str, capacity, format, time, locale);
2490 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)
2493 return _wcsftime_l(str, capacity, format, time, locale);
2495 return wcsftime_l(str, capacity, format, time, locale);
2508 template<
class T,
class TR,
class AX>
2509 inline void strcatftime(_Inout_ std::basic_string<T, TR, AX>& str, _In_z_ _Printf_format_string_
const T* format, _In_
const struct tm* time, _In_opt_ locale_t locale)
2511 T buf[1024 /
sizeof(T)];
2514 size_t count = strftime(buf, _countof(buf), format, time, locale);
2517 str.append(buf, count);
2520 for (
size_t capacity = 2 * 1024 /
sizeof(T);; capacity *= 2) {
2522 auto buf_dyn = std::make_unique<T[]>(capacity);
2523 count = strftime(buf_dyn.get(), capacity, format, time, locale);
2525 str.append(buf_dyn.get(), count);
2540 template<
class T,
class TR,
class AX>
2541 inline void strftime(_Inout_ std::basic_string<T, TR, AX>& str, _In_z_ _Printf_format_string_
const T* format, _In_
const struct tm* time, _In_opt_ locale_t locale)
2544 strcatftime(str, format, time, locale);
2557 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
2558 inline std::basic_string<T, TR, AX> strftime(_In_z_ _Printf_format_string_
const T* format, _In_
const struct tm* time, _In_opt_ locale_t locale)
2560 std::basic_string<T, TR, AX> str;
2561 strcatftime(str, format, time, locale);
2600 inline void strlwr(_Inout_updates_z_(count) T* str, _In_
size_t count)
2602 _Assume_(str || !count);
2603 for (
size_t i = 0; i < count && str[i]; ++i)
2604 str[i] = tolower(str[i]);
2615 inline void strlwr(_Inout_updates_z_(count) T* str, _In_
size_t count, _In_
const std::locale& locale)
2617 _Assume_(str || !count);
2618 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
2619 for (
size_t i = 0; i < count && str[i]; ++i)
2620 str[i] = ctype.tolower(str[i]);
2628 template<
class T,
size_t N>
2629 inline void strlwr(_Inout_ T (&str)[N])
2640 template<
class T,
size_t N>
2641 inline void strlwr(_Inout_ T (&str)[N], _In_
const std::locale& locale)
2643 strlwr(str, count, locale);
2651 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
2652 inline void strlwr(_Inout_ std::basic_string<T, TR, AX>& str)
2664 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
2665 inline void strlwr(_Inout_ std::basic_string<T, TR, AX>& str, _In_
const std::locale& locale)
2667 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
2669 c = ctype.tolower(c);
2707 inline void strupr(_Inout_updates_z_(count) T* str, _In_
size_t count)
2709 _Assume_(str || !count);
2710 for (
size_t i = 0; i < count && str[i]; ++i)
2711 str[i] = toupper(str[i]);
2722 inline void strupr(_Inout_updates_z_(count) T* str, _In_
size_t count, _In_
const std::locale& locale)
2724 _Assume_(str || !count);
2725 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
2726 for (
size_t i = 0; i < count && str[i]; ++i)
2727 str[i] = ctype.toupper(str[i]);
2735 template<
class T,
size_t N>
2736 inline void strupr(_Inout_ T (&str)[N])
2738 return strupr(str, N);
2747 template<
class T,
size_t N>
2748 inline void strupr(_Inout_ T (&str)[N], _In_
const std::locale& locale)
2750 return strupr(str, N, locale);
2758 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
2759 inline void strupr(_Inout_ std::basic_string<T, TR, AX>& str)
2771 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
2772 inline void strupr(_Inout_ std::basic_string<T, TR, AX>& str, _In_
const std::locale& locale)
2774 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
2776 c = ctype.toupper(c);
2788 inline size_t ltrim(
2789 _Inout_z_count_(count) T* str, _In_
size_t count)
2791 for (
size_t i = 0;; ++i) {
2793 if (count) str[0] = 0;
2800 if (!isspace(str[i])) {
2802 return strnlen(str, count);
2803 size_t n = count != SIZE_MAX ? strncpy(str, str + i, count - i) : strcpy(str, str + i);
2820 inline size_t ltrim(
2821 _Inout_z_count_(count) T* str, _In_
size_t count,
2822 _In_
const std::locale& locale)
2824 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
2825 for (
size_t i = 0;; ++i) {
2827 if (count) str[0] = 0;
2834 if (!ctype.is(ctype.space, str[i])) {
2836 return strnlen(str, count);
2837 size_t n = count != SIZE_MAX ? strncpy(str, str + i, count - i) : strcpy(str, str + i);
2849 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
2850 inline void ltrim(_Inout_ std::basic_string<T, TR, AX>& s)
2857 [&](_In_ T ch) { return !isspace(ch); }));
2866 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
2867 inline void ltrim(_Inout_ std::basic_string<T, TR, AX>& s, _In_
const std::locale& locale)
2869 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
2875 [&](_In_ T ch) { return !ctype.is(ctype.space, ch); }));
2887 inline size_t rtrim(
2888 _Inout_z_count_(count) T* str, _In_
size_t count)
2890 for (
size_t i = 0, j = 0;;) {
2891 if (i >= count || !str[i]) {
2892 if (j < count) str[j] = 0;
2895 if (!isspace(str[i]))
2912 inline size_t rtrim(
2913 _Inout_z_count_(count) T* str, _In_
size_t count,
2914 _In_
const std::locale& locale)
2916 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
2917 for (
size_t i = 0, j = 0;;) {
2918 if (i >= count || !str[i]) {
2919 if (j < count) str[j] = 0;
2922 if (!ctype.is(ctype.space, str[i]))
2934 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
2935 static inline void rtrim(_Inout_ std::basic_string<T, TR, AX>& s)
2941 [&](_In_ T ch) { return !isspace(ch); }).base(),
2951 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
2952 static inline void rtrim(_Inout_ std::basic_string<T, TR, AX>& s, _In_
const std::locale& locale)
2954 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
2959 [&](_In_ T ch) { return !ctype.is(ctype.space, ch); }).base(),
2973 _Inout_z_count_(count) T* str, _In_
size_t count)
2975 return ltrim(str, rtrim(str, count));
2989 _Inout_z_count_(count) T* str, _In_
size_t count,
2990 _In_
const std::locale& locale)
2992 return ltrim(str, rtrim(str, count, locale), locale);
3000 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
3001 static inline void trim(_Inout_ std::basic_string<T, TR, AX>& s)
3003 auto nonspace = [&](_In_ T ch) {
return !isspace(ch); };
3024 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
3025 static inline void trim(_Inout_ std::basic_string<T, TR, AX>& s, _In_
const std::locale& locale)
3027 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
3028 auto nonspace = [&](_In_ T ch) {
return !ctype.is(ctype.space, ch); };