31 using utf16_t = wchar_t;
32 using utf32_t = char32_t;
34 using utf16_t = char16_t;
35 using utf32_t = wchar_t;
43 inline bool is_high_surrogate(_In_ utf16_t chr)
45 return 0xd800 < chr && chr < 0xdc00;
53 inline bool is_low_surrogate(_In_ utf16_t chr)
55 return 0xdc00 < chr && chr < 0xe000;
63 inline bool is_surrogate_pair(_In_reads_(2)
const utf16_t* str)
65 return is_high_surrogate(str[0]) && is_low_surrogate(str[1]);
73 inline utf32_t surrogate_pair_to_ucs4(_In_reads_(2)
const utf16_t* str)
75 stdex_assert(is_surrogate_pair(str));
77 (
static_cast<utf32_t
>(str[0] - 0xd800) << 10) +
78 static_cast<utf32_t
>(str[1] - 0xdc00) +
87 inline void ucs4_to_surrogate_pair(_Out_writes_(2) utf16_t* str, _In_ utf32_t chr)
89 stdex_assert(chr >= 0x10000);
91 str[0] = 0xd800 +
static_cast<utf16_t
>((chr >> 10) & 0x3ff);
92 str[1] = 0xdc00 +
static_cast<utf16_t
>(chr & 0x3ff);
100 inline bool iscombining(_In_ utf32_t chr)
103 (0x0300 <= chr && chr < 0x0370) ||
104 (0x1dc0 <= chr && chr < 0x1e00) ||
105 (0x20d0 <= chr && chr < 0x2100) ||
106 (0xfe20 <= chr && chr < 0xfe30);
115 bool islbreak(_In_ T chr)
117 return chr ==
'\n' || chr ==
'\r';
129 size_t islbreak(_In_reads_or_z_opt_(count)
const T* chr, _In_
size_t count)
131 stdex_assert(chr || !count);
132 if (count >= 2 && ((chr[0] ==
'\r' && chr[1] ==
'\n') || (chr[0] ==
'\n' && chr[1] ==
'\r')))
134 if (count > 1 && (chr[0] ==
'\n' || chr[0] ==
'\r'))
145 bool isspace(_In_ T chr)
147 return chr ==
' ' || chr ==
'\t' || chr ==
'\n' || chr ==
'\r' || chr ==
'\v' || chr ==
'\f';
156 bool ispunct(_In_ T chr)
158 return (
'!' <= chr && chr <=
'/') || (
':' <= chr && chr <=
'@') || (
'[' <= chr && chr <=
'`') || (
'{' <= chr && chr <=
'~');
167 bool islower(_In_ T chr)
169 return 'a' <= chr && chr <=
'z';
178 bool isupper(_In_ T chr)
180 return 'A' <= chr && chr <=
'Z';
189 bool isdigit(_In_ T chr)
191 return '0' <= chr && chr <=
'9';
200 bool isalpha(_In_ T chr)
202 return islower(chr) || isupper(chr);
211 bool is7bit(_In_ T chr)
213 return '\x00' <= chr && chr <=
'\x7f';
222 inline size_t glyphlen(_In_reads_or_z_opt_(count)
const utf16_t* glyph, _In_
size_t count)
224 stdex_assert(glyph || !count);
226 size_t i = count < 2 || !is_surrogate_pair(glyph) ? 1 : 2;
227 for (; i < count && iscombining(glyph[i]); ++i);
239 inline size_t glyphlen(_In_reads_or_z_opt_(count)
const utf32_t* glyph, _In_
size_t count)
241 stdex_assert(glyph || !count);
244 for (; i < count && iscombining(glyph[i]); ++i);
256 inline size_t glyphrlen(_In_reads_or_z_opt_(count)
const utf16_t* str, _In_
size_t count)
258 stdex_assert(count && str && str[count - 1]);
259 for (
size_t i = count; i--;) {
260 if (!iscombining(str[i]))
261 return count - (!is_low_surrogate(str[i]) || i == 0 || !is_high_surrogate(str[i - 1]) ? i : i - 1);
272 inline size_t glyphrlen(_In_reads_or_z_opt_(count)
const utf32_t* str, _In_
size_t count)
274 stdex_assert(count && str && str[count - 1]);
275 for (
size_t i = count; i--;) {
276 if (!iscombining(str[i]))
277 return count - (i == 0 ? i : i - 1);
290 T tolower(_In_ T chr)
292 return isupper(chr) ? chr | 0x20 : chr;
303 T toupper(_In_ T chr)
305 return islower(chr) ? chr | ~0x20 : chr;
316 size_t strlen(_In_z_
const T* str)
320 for (i = 0; str[i]; ++i);
333 size_t strnlen(_In_reads_or_z_opt_(count)
const T* str, _In_
size_t count)
335 stdex_assert(str || !count);
337 for (i = 0; i < count && str[i]; ++i);
348 template <
class T,
size_t N>
349 size_t strnlen(_In_
const T (&str)[N])
351 return strnlen(str, N);
354 constexpr auto npos{
static_cast<size_t>(-1) };
365 size_t strchr(_In_z_
const T* str, _In_ T chr)
368 for (
size_t i = 0; str[i]; ++i)
369 if (str[i] == chr)
return i;
384 _In_reads_or_z_opt_(count)
const T* str,
388 stdex_assert(str || !count);
389 for (
size_t i = 0; i < count && str[i]; ++i)
390 if (str[i] == chr)
return i;
402 template <
class T,
size_t N>
404 _In_
const T (&str)[N],
407 return strnchr(str, N, chr);
425 for (
size_t i = 0; str[i]; ++i)
426 if (str[i] == chr) z = i;
441 _In_reads_or_z_opt_(count)
const T* str,
445 stdex_assert(str || !count);
447 for (
size_t i = 0; i < count && str[i]; ++i)
448 if (str[i] == chr) z = i;
460 template <
class T,
size_t N>
462 _In_
const T (&str)[N],
465 return strrnchr(str, N, chr);
483 for (
size_t i = 0; str[i]; ++i)
484 if (tolower(str[i]) == chr)
return i;
501 _In_
const std::locale& locale)
504 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
505 chr = ctype.tolower(chr);
506 for (
size_t i = 0; str[i]; ++i)
507 if (ctype.tolower(str[i]) == chr)
return i;
522 _In_reads_or_z_opt_(count)
const T* str,
526 stdex_assert(str || !count);
528 for (
size_t i = 0; i < count && str[i]; ++i)
529 if (tolower(str[i]) == chr)
return i;
545 _In_reads_or_z_opt_(count)
const T* str,
548 _In_
const std::locale& locale)
550 stdex_assert(str || !count);
551 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
552 chr = ctype.tolower(chr);
553 for (
size_t i = 0; i < count && str[i]; ++i)
554 if (ctype.tolower(str[i]) == chr)
return i;
566 template <
class T,
size_t N>
568 _In_
const T (&str)[N],
571 return strnichr(str, N, chr);
583 template <
class T,
size_t N>
585 _In_
const T (&str)[N],
587 _In_
const std::locale& locale)
589 return strnichr(str, N, chr, locale);
608 for (
size_t i = 0; str[i]; ++i)
609 if (tolower(str[i]) == chr) z = i;
624 _In_reads_or_z_opt_(count)
const T* str,
626 _In_
const std::locale& locale)
629 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
630 chr = ctype.tolower(chr);
632 for (
size_t i = 0; str[i]; ++i)
633 if (ctype.tolower(str[i]) == chr) z = i;
648 _In_reads_or_z_opt_(count)
const T* str,
652 stdex_assert(str || !count);
655 for (
size_t i = 0; i < count && str[i]; ++i)
656 if (tolower(str[i]) == chr) z = i;
672 _In_reads_or_z_opt_(count)
const T* str,
675 _In_
const std::locale& locale)
677 stdex_assert(str || !count);
678 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
679 chr = ctype.tolower(chr);
681 for (
size_t i = 0; i < count && str[i]; ++i)
682 if (ctype.tolower(str[i]) == chr) z = i;
694 template <
class T,
size_t N>
696 _In_
const T (&str)[N],
699 return strrnichr(str, N, chr);
711 template <
class T,
size_t N>
713 _In_
const T (&str)[N],
715 _In_
const std::locale& locale)
717 return strrnichr(str, N, chr, locale);
768 _In_reads_or_z_opt_(count)
const T* str,
771 stdex_assert(str || !count);
772 for (
size_t i = 0; i < count && str[i]; ++i)
773 if (!isspace(str[i]))
789 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
790 _In_
const std::locale& locale)
792 stdex_assert(str || !count);
793 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
794 for (
size_t i = 0; i < count && str[i]; ++i)
795 if (!ctype.is(ctype.space, str[i]))
807 template <
class T,
size_t N>
808 bool isblank(_In_
const T (&str)[N])
810 return isblank(str, N);
821 template <
class T,
size_t N>
823 _In_
const T (&str)[N],
824 _In_
const std::locale& locale)
826 return isblank(str, N, locale);
855 bool is7bit(_In_reads_or_z_opt_(count)
const T* str, _In_
size_t count)
857 stdex_assert(str || !count);
858 for (
size_t i = 0; i < count && str[i]; i++)
871 template <
class T,
size_t N>
872 bool is7bit(_In_
const T (&str)[N])
874 return is7bit(str, N);
885 template <
class T1,
class T2>
886 int strcmp(_In_z_
const T1* str1, _In_z_
const T2* str2)
890 size_t i; T1 a; T2 b;
891 for (i = 0; (a = str1[i]) | (b = str2[i]); ++i) {
892 if (a > b)
return +1;
893 if (a < b)
return -1;
895 if (str1[i])
return +1;
896 if (str2[i])
return -1;
909 template <
class T1,
class T2>
910 int strncmp(_In_reads_or_z_opt_(count)
const T1* str1, _In_reads_or_z_opt_(count)
const T2* str2, _In_
size_t count)
912 stdex_assert(str1 || !count);
913 stdex_assert(str2 || !count);
914 size_t i; T1 a; T2 b;
915 for (i = 0; i < count && ((a = str1[i]) | (b = str2[i])); ++i) {
916 if (a > b)
return +1;
917 if (a < b)
return -1;
919 if (i < count && str1[i])
return +1;
920 if (i < count && str2[i])
return -1;
934 template <
class T1,
class T2>
936 _In_reads_or_z_opt_(count1)
const T1* str1, _In_
size_t count1,
937 _In_reads_or_z_opt_(count2)
const T2* str2, _In_
size_t count2)
939 stdex_assert(str1 || !count1);
940 stdex_assert(str2 || !count2);
942 for (i = 0; i < count1 && i < count2; ++i) {
945 if (!a && !b)
return 0;
946 if (a > b)
return +1;
947 if (a < b)
return -1;
949 if (i < count1 && str1[i])
return +1;
950 if (i < count2 && str2[i])
return -1;
962 template <
class T1,
size_t N1,
class T2,
size_t N2>
964 _In_
const T1 (&str1)[N1],
965 _In_
const T2 (&str2)[N2])
967 return strncmp(str1, N1, str2, N2);
981 _In_reads_or_z_opt_(count1)
const utf32_t* str1, _In_
size_t count1,
982 _In_reads_or_z_opt_(count2)
const utf16_t* str2, _In_
size_t count2)
984 stdex_assert(str1 || !count1);
985 stdex_assert(str2 || !count2);
986 size_t i, j, j_next; utf32_t a, b;
987 for (i = 0, j = 0; i < count1 && j < count2; ++i, j = j_next) {
991 if (j + 1 >= count2 || !is_surrogate_pair(&str2[j])) {
992 b =
static_cast<utf32_t
>(str2[j]);
996 b = surrogate_pair_to_ucs4(&str2[j]);
1001 if (a > b)
return +1;
1002 if (a < b)
return -1;
1004 if (i < count1 && str1[i])
return +1;
1005 if (j < count2 && str2[j])
return -1;
1017 template <
size_t N1,
size_t N2>
1019 _In_
const utf32_t (&str1)[N1],
1020 _In_
const utf16_t (&str2)[N2])
1022 return strncmp(str1, N1, str2, N2);
1033 template <
class T1,
class T2>
1034 int strrcmp(_In_z_
const T1* str1, _In_z_
const T2* str2)
1039 stdex_assert(str1 || !i);
1040 stdex_assert(str2 || !j);
1041 size_t k; T1 a; T2 b;
1042 for (k = 1; i && j; k++) {
1044 if ((a = str1[i]) > (b = str2[j]))
return +1;
1045 if (a < b)
return -1;
1047 if (i && !j)
return +1;
1048 if (!i && j)
return -1;
1061 template <
class T1,
class T2>
1062 int strrncmp(_In_reads_or_z_opt_(count)
const T1* str1, _In_reads_or_z_opt_(count)
const T2* str2, _In_
size_t count)
1065 i = strnlen(str1, count),
1066 j = strnlen(str2, count);
1067 stdex_assert(str1 || !i);
1068 stdex_assert(str2 || !j);
1069 size_t k; T1 a; T2 b;
1070 for (k = 1; i && j; k++) {
1072 if ((a = str1[i]) > (b = str2[j]))
return +1;
1073 if (a < b)
return -1;
1075 if (i && !j)
return +1;
1076 if (!i && j)
return -1;
1090 template <
class T1,
class T2>
1092 _In_reads_or_z_opt_(count1)
const T1* str1, _In_
size_t count1,
1093 _In_reads_or_z_opt_(count2)
const T2* str2, _In_
size_t count2)
1096 i = strnlen(str1, count1),
1097 j = strnlen(str2, count2);
1098 stdex_assert(str1 || !i);
1099 stdex_assert(str2 || !j);
1100 size_t k; T1 a; T2 b;
1101 for (k = 1; i && j; k++) {
1103 if ((a = str1[i]) > (b = str2[j]))
return +1;
1104 if (a < b)
return -1;
1106 if (i && !j)
return +1;
1107 if (!i && j)
return -1;
1119 template <
class T1,
size_t N1,
class T2,
size_t N2>
1121 _In_
const T1 (&str1)[N1],
1122 _In_
const T2 (&str2)[N2])
1124 return strrncmp(str1, N1, str2, N2);
1135 template <
class T1,
class T2>
1136 int stricmp(_In_z_
const T1* str1, _In_z_
const T2* str2)
1141 for (i = 0; ; ++i) {
1142 auto a = tolower(str1[i]);
1143 auto b = tolower(str2[i]);
1144 if (!a && !b)
return 0;
1145 if (a > b)
return +1;
1146 if (a < b)
return -1;
1159 template <
class T1,
class T2>
1160 int stricmp(_In_z_
const T1* str1, _In_z_
const T2* str2, _In_
const std::locale& locale)
1165 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
1166 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
1168 auto a = ctype1.tolower(str1[i]);
1169 auto b = ctype2.tolower(str2[i]);
1170 if (!a && !b)
return 0;
1171 if (a > b)
return +1;
1172 if (a < b)
return -1;
1185 template <
class T1,
class T2>
1186 int strnicmp(_In_reads_or_z_opt_(count)
const T1* str1, _In_reads_or_z_opt_(count)
const T2* str2, _In_
size_t count)
1188 stdex_assert(str1 || !count);
1189 stdex_assert(str2 || !count);
1191 for (i = 0; i < count; ++i) {
1192 auto a = tolower(str1[i]);
1193 auto b = tolower(str2[i]);
1194 if (!a && !b)
return 0;
1195 if (a > b)
return +1;
1196 if (a < b)
return -1;
1198 if (i < count && str1[i])
return +1;
1199 if (i < count && str2[i])
return -1;
1213 template <
class T1,
class T2>
1214 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)
1216 stdex_assert(str1 || !count);
1217 stdex_assert(str2 || !count);
1219 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
1220 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
1221 for (i = 0; i < count; ++i) {
1222 auto a = ctype1.tolower(str1[i]);
1223 auto b = ctype2.tolower(str2[i]);
1224 if (!a && !b)
return 0;
1225 if (a > b)
return +1;
1226 if (a < b)
return -1;
1228 if (i < count && str1[i])
return +1;
1229 if (i < count && str2[i])
return -1;
1243 template <
class T1,
class T2>
1245 _In_reads_or_z_opt_(count1)
const T1* str1, _In_
size_t count1,
1246 _In_reads_or_z_opt_(count2)
const T2* str2, _In_
size_t count2)
1248 stdex_assert(str1 || !count1);
1249 stdex_assert(str2 || !count2);
1251 for (i = 0; i < count1 && i < count2; ++i) {
1252 auto a = tolower(str1[i]);
1253 auto b = tolower(str2[i]);
1254 if (!a && !b)
return 0;
1255 if (a > b)
return +1;
1256 if (a < b)
return -1;
1258 if (i < count1 && str1[i])
return +1;
1259 if (i < count2 && str2[i])
return -1;
1274 template <
class T1,
class T2>
1276 _In_reads_or_z_opt_(count1)
const T1* str1, _In_
size_t count1,
1277 _In_reads_or_z_opt_(count2)
const T2* str2, _In_
size_t count2,
1278 _In_
const std::locale& locale)
1280 stdex_assert(str1 || !count1);
1281 stdex_assert(str2 || !count2);
1283 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
1284 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
1285 for (i = 0; i < count1 && i < count2; ++i) {
1286 auto a = ctype1.tolower(str1[i]);
1287 auto b = ctype2.tolower(str2[i]);
1288 if (!a && !b)
return 0;
1289 if (a > b)
return +1;
1290 if (a < b)
return -1;
1292 if (i < count1 && str1[i])
return +1;
1293 if (i < count2 && str2[i])
return -1;
1305 template <
class T1,
size_t N1,
class T2,
size_t N2>
1307 _In_
const T1 (&str1)[N1],
1308 _In_
const T2 (&str2)[N2])
1310 strnicmp(str1, N1, str2, N2);
1322 template <
class T1,
size_t N1,
class T2,
size_t N2>
1324 _In_
const T1 (&str1)[N1],
1325 _In_
const T2 (&str2)[N2],
1326 _In_
const std::locale& locale)
1328 strnicmp(str1, N1, str2, N2, locale);
1342 _In_z_
const T* str1,
1343 _In_z_
const T* str2,
1344 _In_
const std::locale& locale)
1348 auto& collate = std::use_facet<std::collate<T>>(locale);
1349 return collate.compare(str1, str1 + strlen(str1), str2, str2 + strlen(str2));
1365 _In_reads_or_z_opt_(count1)
const T* str1, _In_
size_t count1,
1366 _In_reads_or_z_opt_(count2)
const T* str2, _In_
size_t count2,
1367 _In_
const std::locale& locale)
1369 stdex_assert(str1 || !count1);
1370 stdex_assert(str2 || !count2);
1371 auto& collate = std::use_facet<std::collate<T>>(locale);
1372 return collate.compare(str1, str1 + count1, str2, str2 + count2);
1384 template <
class T,
size_t N1,
size_t N2>
1386 _In_
const T (&str1)[N1],
1387 _In_
const T (&str2)[N2],
1388 _In_
const std::locale& locale)
1390 return strncoll(str1, N1, str2, N2, locale);
1401 template <
class T1,
class T2>
1403 _In_z_
const T1* str,
1404 _In_z_
const T2* sample)
1407 stdex_assert(sample);
1408 for (
size_t offset = 0;; ++offset) {
1409 for (
size_t i = offset, j = 0;; ++i, ++j) {
1414 if (str[i] != sample[j])
1429 template <
class T1,
class T2>
1431 _In_reads_or_z_opt_(count)
const T1* str, _In_
size_t count,
1432 _In_z_
const T2* sample)
1434 stdex_assert(str || !count);
1435 stdex_assert(sample);
1436 for (
size_t offset = 0;; ++offset) {
1437 for (
size_t i = offset, j = 0;; ++i, ++j) {
1440 if (i >= count || !str[i])
1442 if (str[i] != sample[j])
1456 template <
class T1,
size_t N1,
class T2>
1458 _In_
const T1 (&str)[N1],
1459 _In_z_
const T2* sample)
1461 return strnstr(str, N1, sample);
1472 template <
class T1,
class T2>
1474 _In_z_
const T1* str,
1475 _In_z_
const T2* sample)
1478 stdex_assert(sample);
1479 for (
size_t offset = 0;; ++offset) {
1480 for (
size_t i = offset, j = 0;; ++i, ++j) {
1485 if (tolower(str[i]) != tolower(sample[j]))
1500 template <
class T1,
class T2>
1502 _In_z_
const T1* str,
1503 _In_z_
const T2* sample,
1504 _In_
const std::locale& locale)
1507 stdex_assert(sample);
1508 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
1509 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
1510 for (
size_t offset = 0;; ++offset) {
1511 for (
size_t i = offset, j = 0;; ++i, ++j) {
1516 if (ctype1.tolower(str[i]) != ctype2.tolower(sample[j]))
1531 template <
class T1,
class T2>
1533 _In_reads_or_z_opt_(count)
const T1* str,
1535 _In_z_
const T2* sample)
1537 stdex_assert(str || !count);
1538 stdex_assert(sample);
1539 for (
size_t offset = 0;; ++offset) {
1540 for (
size_t i = offset, j = 0;; ++i, ++j) {
1543 if (i >= count || !str[i])
1545 if (tolower(str[i]) != tolower(sample[j]))
1561 template <
class T1,
class T2>
1563 _In_reads_or_z_opt_(count)
const T1* str,
1565 _In_z_
const T2* sample,
1566 _In_
const std::locale& locale)
1568 stdex_assert(str || !count);
1569 stdex_assert(sample);
1570 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
1571 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
1572 for (
size_t offset = 0;; ++offset) {
1573 for (
size_t i = offset, j = 0;; ++i, ++j) {
1576 if (i >= count || !str[i])
1578 if (ctype1.tolower(str[i]) != ctype2.tolower(sample[j]))
1592 template <
class T1,
size_t N1,
class T2>
1594 _In_
const T1 (&str)[N1],
1595 _In_z_
const T2* sample)
1597 return strnistr(str, N1, sample);
1609 template <
class T1,
size_t N1,
class T2>
1611 _In_
const T1 (&str)[N1],
1612 _In_z_
const T2* sample,
1613 _In_
const std::locale& locale)
1615 return strnistr(str, N1, sample, locale);
1626 template <
class T1,
class T2>
1628 _Out_writes_z_(_String_length_(src) + 1) T1* dst,
1629 _In_z_
const T2* src)
1633 for (
size_t i = 0; ; ++i) {
1634 if ((dst[i] =
static_cast<T1
>(src[i])) == 0)
1648 template <
class T1,
class T2>
1650 _Out_writes_(count) _Post_maybez_ T1* dst,
1651 _In_reads_or_z_opt_(count)
const T2* src, _In_
size_t count)
1653 stdex_assert(dst || !count);
1654 stdex_assert(src || !count);
1655 for (
size_t i = 0; ; ++i) {
1658 if ((dst[i] =
static_cast<T1
>(src[i])) == 0)
1673 template <
class T1,
class T2>
1675 _Out_writes_(count_dst) _Post_maybez_ T1* dst, _In_
size_t count_dst,
1676 _In_reads_or_z_opt_(count_src)
const T2* src, _In_
size_t count_src)
1678 stdex_assert(dst || !count_dst);
1679 stdex_assert(src || !count_src);
1680 for (
size_t i = 0; ; ++i)
1684 if (i >= count_src) {
1688 if ((dst[i] =
static_cast<T1
>(src[i])) == 0)
1701 template <
class T1,
size_t N1,
class T2,
size_t N2>
1703 _Out_ _Post_maybez_ T1 (&dst)[N1],
1704 _In_
const T2 (&src)[N2])
1706 return strncpy(dst, N1, src, N2);
1717 template <
class T1,
class T2>
1719 _In_z_ _Out_writes_z_(_String_length_(dst) + _String_length_(src) + 1) T1* dst,
1720 _In_z_
const T2* src)
1724 for (
size_t i = 0, j = stdex::strlen<T1>(dst); ; ++i, ++j) {
1725 if ((dst[j] =
static_cast<T1
>(src[i])) == 0)
1739 template <
class T1,
class T2>
1742 _In_reads_or_z_opt_(count)
const T2* src, _In_
size_t count)
1744 stdex_assert(dst || !count);
1745 stdex_assert(src || !count);
1746 for (
size_t i = 0, j = stdex::strlen<T1>(dst); ; ++i, ++j) {
1749 if ((dst[j] =
static_cast<T1
>(src[i])) == 0)
1764 template <
class T1,
class T2>
1766 _Out_writes_(count_dst) _Post_maybez_ T1* dst, _In_
size_t count_dst,
1767 _In_reads_or_z_opt_(count_src)
const T2* src, _In_
size_t count_src)
1769 stdex_assert(dst || !count_dst);
1770 stdex_assert(src || !count_src);
1771 for (
size_t i = 0, j = stdex::strnlen<T1>(dst, count_dst); ; ++i, ++j)
1775 if (i >= count_src) {
1779 if ((dst[j] =
static_cast<T1
>(src[i])) == 0)
1795 _Check_return_ _Ret_maybenull_z_ T* strdup(_In_opt_z_
const T* str)
1797 if (!str) _Unlikely_
1799 size_t count = strlen(str) + 1;
1800 T* dst =
new T[count];
1801 strncpy(dst, count, str, SIZE_MAX);
1818 _In_reads_or_z_opt_(count)
const T* str,
1821 T* dst =
new T[count];
1822 strncpy(dst, count, str, SIZE_MAX);
1836 template <
class T,
size_t N>
1837 _Check_return_ _Ret_maybenull_z_ T* strndup(_In_
const T (&str)[N])
1839 return strndup(str, N);
1852 size_t crlf2nl(_Out_writes_z_(_String_length_(src) + 1) T* dst, _In_z_
const T* src)
1857 for (i = j = 0; src[j];) {
1858 if (src[j] !=
'\r' || src[j + 1] !=
'\n')
1859 dst[i++] = src[j++];
1875 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
1876 void crlf2nl(_Inout_ std::basic_string<T, TR, AX>& dst, _In_z_
const T* src)
1879 stdex_assert(src != dst.data());
1881 dst.reserve(strlen(src));
1882 for (
size_t j = 0; src[j];) {
1883 if (src[j] !=
'\r' || src[j + 1] !=
'\n')
1897 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
1898 void crlf2nl(_Inout_ std::basic_string<T, TR, AX>& str)
1901 for (i = j = 0, n = str.size(); j < n;) {
1902 if (str[j] !=
'\r' || str[j + 1] !=
'\n')
1903 str[i++] = str[j++];
1913 template <
class T,
class T_bin>
1915 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1916 _Out_opt_
size_t* end,
1918 _Out_ uint8_t& flags)
1920 stdex_assert(str || !count);
1921 stdex_assert(radix == 0 || 2 <= radix && radix <= 36);
1924 T_bin value = 0, digit,
1926 max_ui_pre1, max_ui_pre2;
1932 if (i >= count || !str[i])
goto error;
1933 if (!isspace(str[i]))
break;
1937 if (str[i] ==
'+') {
1940 if (i >= count || !str[i])
goto error;
1942 else if (str[i] ==
'-') {
1945 if (i >= count || !str[i])
goto error;
1950 if (str[i] ==
'0' && i + 1 < count && (str[i + 1] ==
'x' || str[i + 1] ==
'X')) {
1952 if (i >= count || !str[i])
goto error;
1957 if (str[i] ==
'0') {
1959 if (i >= count || !str[i])
goto error;
1960 if (str[i] ==
'x' || str[i] ==
'X') {
1963 if (i >= count || !str[i])
goto error;
1973 max_ui_pre1 = max_ui / (T_bin)radix;
1974 max_ui_pre2 = max_ui % (T_bin)radix;
1976 if (
'0' <= str[i] && str[i] <=
'9')
1977 digit = (T_bin)str[i] -
'0';
1978 else if (
'A' <= str[i] && str[i] <=
'Z')
1979 digit = (T_bin)str[i] -
'A' +
'\x0a';
1980 else if (
'a' <= str[i] && str[i] <=
'z')
1981 digit = (T_bin)str[i] -
'a' +
'\x0a';
1984 if (digit >= (T_bin)radix)
1987 if (value < max_ui_pre1 ||
1988 (value == max_ui_pre1 && digit <= max_ui_pre2))
1989 value = value * (T_bin)radix + digit;
1996 if (i >= count || !str[i])
2016 template <
class T,
class T_bin>
2018 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
2019 _Out_opt_
size_t* end,
2025 switch (
sizeof(T_bin)) {
2027 value = (T_bin)strtoint<T, uint8_t>(str, count, end, radix, flags);
2028 if ((flags & 0x01) && (value & 0x80)) {
2032 return (flags & 0x02) ?
2033 (flags & 0x01) ? (T_bin)0x80 : (T_bin)0x7f :
2034 (flags & 0x01) ? -value : value;
2037 value = (T_bin)strtoint<T, uint16_t>(str, count, end, radix, flags);
2038 if ((flags & 0x01) && (value & 0x8000)) {
2042 return (flags & 0x02) ?
2043 (flags & 0x01) ? (T_bin)0x8000 : (T_bin)0x7fff :
2044 (flags & 0x01) ? -value : value;
2047 value = (T_bin)strtoint<T, uint32_t>(str, count, end, radix, flags);
2048 if ((flags & 0x01) && (value & 0x80000000)) {
2052 return (flags & 0x02) ?
2053 (flags & 0x01) ? (T_bin)0x80000000 : (T_bin)0x7fffffff :
2054 (flags & 0x01) ? -value : value;
2057 value = (T_bin)strtoint<T, uint64_t>(str, count, end, radix, flags);
2058 if ((flags & 0x01) && (value & 0x8000000000000000)) {
2062 return (flags & 0x02) ?
2063 (flags & 0x01) ? (T_bin)0x8000000000000000 : (T_bin)0x7fffffffffffffff :
2064 (flags & 0x01) ? -value : value;
2067 throw std::invalid_argument(
"Unsupported bit length");
2080 template <
class T,
size_t N,
class T_bin>
2082 _In_
const T (&str)[N],
2083 _Out_opt_
size_t* end,
2086 return strtoint<T, T_bin>(str, N, end, radix);
2099 template <
class T,
class T_bin>
2101 _In_reads_or_z_opt_(count)
const T* str,
2103 _Out_opt_
size_t* end,
2109 switch (
sizeof(T_bin)) {
2110 case 1: value = (T_bin)strtoint<T, uint8_t>(str, count, end, radix, flags);
break;
2111 case 2: value = (T_bin)strtoint<T, uint16_t>(str, count, end, radix, flags);
break;
2112 case 4: value = (T_bin)strtoint<T, uint32_t>(str, count, end, radix, flags);
break;
2113 case 8: value = (T_bin)strtoint<T, uint64_t>(str, count, end, radix, flags);
break;
2114 default:
throw std::invalid_argument(
"Unsupported bit length");
2117 return (flags & 0x02) ?
2118 (flags & 0x01) ? (T_bin)0 : (T_bin)-1 :
2119 (flags & 0x01) ? ~value : value;
2131 template <
class T,
size_t N,
class T_bin>
2133 _In_
const T (&str)[N],
2134 _Out_opt_
size_t* end,
2137 return strtouint<T, T_bin>(str, N, end, radix);
2152 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
2153 _Out_opt_
size_t* end,
2156 return strtoint<T, int8_t>(str, count, end, radix);
2168 template <
class T,
size_t N>
2170 _In_
const T (&str)[N],
2171 _Out_opt_
size_t* end,
2174 return strto8<T>(str, N, end, radix);
2189 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
2190 _Out_opt_
size_t* end,
2193 return strtoint<T, int16_t>(str, count, end, radix);
2205 template <
class T,
size_t N>
2207 _In_
const T (&str)[N],
2208 _Out_opt_
size_t* end,
2211 return strto16<T>(str, N, end, radix);
2226 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
2227 _Out_opt_
size_t* end,
2230 return strtoint<T, int32_t>(str, count, end, radix);
2242 template <
class T,
size_t N>
2244 _In_
const T (&str)[N],
2245 _Out_opt_
size_t* end,
2248 return strto32<T>(str, N, end, radix);
2263 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
2264 _Out_opt_
size_t* end,
2267 return strtoint<T, int64_t>(str, count, end, radix);
2279 template <
class T,
size_t N>
2281 _In_
const T (&str)[N],
2282 _Out_opt_
size_t* end,
2285 return strto64<T>(str, N, end, radix);
2301 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
2302 _Out_opt_
size_t* end,
2305#if defined(_WIN64) || defined(__LP64__)
2306 return static_cast<ptrdiff_t
>(strto64(str, count, end, radix));
2308 return static_cast<ptrdiff_t
>(strto32(str, count, end, radix));
2322 template <
class T,
size_t N>
2324 _In_
const T (&str)[N],
2325 _Out_opt_
size_t* end,
2328 return strtoi<T>(str, N, end, radix);
2343 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
2344 _Out_opt_
size_t* end,
2347 return strtouint<T, uint8_t>(str, count, end, radix);
2359 template <
class T,
size_t N>
2361 _In_
const T (&str)[N],
2362 _Out_opt_
size_t* end,
2365 return strtou8(str, N, end, radix);
2380 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
2381 _Out_opt_
size_t* end,
2384 return strtouint<T, uint16_t>(str, count, end, radix);
2396 template <
class T,
size_t N>
2398 _In_
const T (&str)[N],
2399 _Out_opt_
size_t* end,
2402 return strtou16(str, N, end, radix);
2417 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
2418 _Out_opt_
size_t* end,
2421 return strtouint<T, uint32_t>(str, count, end, radix);
2433 template <
class T,
size_t N>
2435 _In_
const T (&str)[N],
2436 _Out_opt_
size_t* end,
2439 return strtou32(str, N, end, radix);
2454 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
2455 _Out_opt_
size_t* end,
2458 return strtouint<T, uint64_t>(str, count, end, radix);
2470 template <
class T,
size_t N>
2472 _In_
const T (&str)[N],
2473 _Out_opt_
size_t* end,
2476 return strtou64<T>(str, N, end, radix);
2492 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
2493 _Out_opt_
size_t* end,
2496#if defined(_WIN64) || defined(__LP64__)
2497 return static_cast<size_t>(strtou64(str, count, end, radix));
2499 return static_cast<size_t>(strtou32(str, count, end, radix));
2513 template <
class T,
size_t N>
2515 _In_
const T (&str)[N],
2516 _Out_opt_
size_t* end,
2519 return strtoui<T>(str, N, end, radix);
2532 inline double strtod(
2533 _In_reads_or_z_opt_(count)
const char* str, _In_
size_t count,
2534 _Out_opt_
size_t* end,
2535 _In_opt_ locale_t locale)
2537 count = strnlen(str, count);
2538 stdex_assert(str || !count);
2539 std::string tmp(str, count);
2543 r = _strtod_l(tmp.c_str(), &_end, locale);
2545 r = strtod_l(tmp.c_str(), &_end, locale);
2547 if (end) *end = (size_t)(_end - tmp.c_str());
2561 inline double strtod(
2562 _In_reads_or_z_opt_(count)
const wchar_t* str, _In_
size_t count,
2563 _Out_opt_
size_t* end,
2564 _In_opt_ locale_t locale)
2566 count = strnlen(str, count);
2567 stdex_assert(str || !count);
2568 std::wstring tmp(str, count);
2572 r = _wcstod_l(tmp.c_str(), &_end, locale);
2574 r = wcstod_l(tmp.c_str(), &_end, locale);
2576 if (end) *end = (size_t)(_end - tmp.c_str());
2581 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)
2584#pragma warning(suppress: 4996)
2585 return _vsnprintf_l(str, capacity, format, locale, arg);
2587 va_list arg_mutable;
2588 va_copy(arg_mutable, arg);
2589 return ::vsnprintf_l(str, capacity, locale, format, arg_mutable);
2593 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)
2596#pragma warning(suppress: 4996)
2597 return _vsnwprintf_l(str, capacity, format, locale, arg);
2599 va_list arg_mutable;
2600 va_copy(arg_mutable, arg);
2601 return ::vswprintf_l(str, capacity, locale, format, arg_mutable);
2616 template<
class T,
class TR,
class AX>
2617 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)
2619 T buf[1024 /
sizeof(T)];
2622 int count = vsnprintf(buf, _countof(buf), format, locale, arg);
2623 if (0 <= count &&
static_cast<size_t>(count) <= _countof(buf)) {
2625 str.append(buf,
static_cast<size_t>(count));
2626 return static_cast<size_t>(count);
2632 count = vsnprintf(NULL, 0, format, locale, arg);
2633 stdex_assert(count >= 0);
2635 case EINVAL:
throw std::invalid_argument(
"invalid vsnprintf arguments");
2636 case EILSEQ:
throw std::runtime_error(
"encoding error");
2637 default:
throw std::runtime_error(
"failed to format string");
2640 size_t offset = str.size();
2641 str.resize(offset + count);
2642 if (vsnprintf(&str[offset], count + 1, format, locale, arg) != count) _Unlikely_
2643 throw std::runtime_error(
"failed to format string");
2645 size_t offset = str.size();
2646 for (
size_t capacity = 2 * 1024 /
sizeof(T);; capacity *= 2) {
2650 str.resize(offset + capacity);
2651 count = vsnprintf(&str[offset], capacity, format, locale, arg);
2652 if (0 <= count &&
static_cast<size_t>(count) <= capacity) {
2653 str.resize(offset +
static_cast<size_t>(count));
2654 return static_cast<size_t>(count);
2657 case EINVAL:
throw std::invalid_argument(
"invalid vsnprintf arguments");
2658 case EILSEQ:
throw std::runtime_error(
"encoding error");
2659 default:
throw std::runtime_error(
"failed to format string");
2663 return static_cast<size_t>(count);
2675 template<
class T,
class TR,
class AX>
2676 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, ...)
2679 va_start(arg, locale);
2680 size_t n = vappendf(str, format, locale, arg);
2693 template<
class T,
class TR,
class AX>
2694 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)
2697 vappendf(str, format, locale, arg);
2707 template<
class T,
class TR,
class AX>
2708 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, ...)
2711 va_start(arg, locale);
2712 vsprintf(str, format, locale, arg);
2725 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
2726 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)
2728 std::basic_string<T, TR, AX> str;
2729 vappendf(str, format, locale, arg);
2741 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
2742 std::basic_string<T, TR, AX> sprintf(_In_z_ _Printf_format_string_params_(2)
const T* format, _In_opt_ locale_t locale, ...)
2745 va_start(arg, locale);
2746 auto str = vsprintf(format, locale, arg);
2752 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)
2755 return _strftime_l(str, capacity, format, time, locale);
2757 return strftime_l(str, capacity, format, time, locale);
2761 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)
2764 return _wcsftime_l(str, capacity, format, time, locale);
2766 return wcsftime_l(str, capacity, format, time, locale);
2779 template<
class T,
class TR,
class AX>
2780 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)
2782 T buf[1024 /
sizeof(T)];
2785 size_t count = strftime(buf, _countof(buf), format, time, locale);
2788 str.append(buf, count);
2791 size_t offset = str.size();
2792 for (
size_t capacity = 2 * 1024 /
sizeof(T);; capacity *= 2) {
2794 str.resize(offset + capacity);
2795 count = strftime(&str[offset], capacity + 1, format, time, locale);
2797 str.resize(offset + count);
2811 template<
class T,
class TR,
class AX>
2812 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)
2815 strcatftime(str, format, time, locale);
2827 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
2828 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)
2830 std::basic_string<T, TR, AX> str;
2831 strcatftime(str, format, time, locale);
2870 void strlwr(_Inout_updates_z_(count) T* str, _In_
size_t count)
2872 stdex_assert(str || !count);
2873 for (
size_t i = 0; i < count && str[i]; ++i)
2874 str[i] = tolower(str[i]);
2885 void strlwr(_Inout_updates_z_(count) T* str, _In_
size_t count, _In_
const std::locale& locale)
2887 stdex_assert(str || !count);
2888 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
2889 for (
size_t i = 0; i < count && str[i]; ++i)
2890 str[i] = ctype.tolower(str[i]);
2898 template<
class T,
size_t N>
2899 void strlwr(_Inout_ T (&str)[N])
2910 template<
class T,
size_t N>
2911 void strlwr(_Inout_ T (&str)[N], _In_
const std::locale& locale)
2913 strlwr(str, N, locale);
2921 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
2922 void strlwr(_Inout_ std::basic_string<T, TR, AX>& str)
2934 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
2935 void strlwr(_Inout_ std::basic_string<T, TR, AX>& str, _In_
const std::locale& locale)
2937 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
2939 c = ctype.tolower(c);
2977 void strupr(_Inout_updates_z_(count) T* str, _In_
size_t count)
2979 stdex_assert(str || !count);
2980 for (
size_t i = 0; i < count && str[i]; ++i)
2981 str[i] = toupper(str[i]);
2992 void strupr(_Inout_updates_z_(count) T* str, _In_
size_t count, _In_
const std::locale& locale)
2994 stdex_assert(str || !count);
2995 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
2996 for (
size_t i = 0; i < count && str[i]; ++i)
2997 str[i] = ctype.toupper(str[i]);
3005 template<
class T,
size_t N>
3006 void strupr(_Inout_ T (&str)[N])
3008 return strupr(str, N);
3017 template<
class T,
size_t N>
3018 void strupr(_Inout_ T (&str)[N], _In_
const std::locale& locale)
3020 return strupr(str, N, locale);
3028 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
3029 void strupr(_Inout_ std::basic_string<T, TR, AX>& str)
3041 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
3042 void strupr(_Inout_ std::basic_string<T, TR, AX>& str, _In_
const std::locale& locale)
3044 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
3046 c = ctype.toupper(c);
3059 _Inout_z_count_(count) T* str, _In_
size_t count)
3061 for (
size_t i = 0;; ++i) {
3063 if (count) str[0] = 0;
3070 if (!isspace(str[i])) {
3072 return strnlen(str, count);
3073 size_t n = count != SIZE_MAX ? strncpy(str, str + i, count - i) : strcpy(str, str + i);
3091 _Inout_z_count_(count) T* str, _In_
size_t count,
3092 _In_
const std::locale& locale)
3094 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
3095 for (
size_t i = 0;; ++i) {
3097 if (count) str[0] = 0;
3104 if (!ctype.is(ctype.space, str[i])) {
3106 return strnlen(str, count);
3107 size_t n = count != SIZE_MAX ? strncpy(str, str + i, count - i) : strcpy(str, str + i);
3119 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
3120 void ltrim(_Inout_ std::basic_string<T, TR, AX>& s)
3127 [&](_In_ T ch) { return !isspace(ch); }));
3136 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
3137 void ltrim(_Inout_ std::basic_string<T, TR, AX>& s, _In_
const std::locale& locale)
3139 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
3145 [&](_In_ T ch) { return !ctype.is(ctype.space, ch); }));
3158 _Inout_z_count_(count) T* str, _In_
size_t count)
3160 for (
size_t i = 0, j = 0;;) {
3161 if (i >= count || !str[i]) {
3162 if (j < count) str[j] = 0;
3165 if (!isspace(str[i]))
3183 _Inout_z_count_(count) T* str, _In_
size_t count,
3184 _In_
const std::locale& locale)
3186 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
3187 for (
size_t i = 0, j = 0;;) {
3188 if (i >= count || !str[i]) {
3189 if (j < count) str[j] = 0;
3192 if (!ctype.is(ctype.space, str[i]))
3204 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
3205 void rtrim(_Inout_ std::basic_string<T, TR, AX>& s)
3211 [&](_In_ T ch) { return !isspace(ch); }).base(),
3221 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
3222 void rtrim(_Inout_ std::basic_string<T, TR, AX>& s, _In_
const std::locale& locale)
3224 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
3229 [&](_In_ T ch) { return !ctype.is(ctype.space, ch); }).base(),
3243 _Inout_z_count_(count) T* str, _In_
size_t count)
3245 return ltrim(str, rtrim(str, count));
3259 _Inout_z_count_(count) T* str, _In_
size_t count,
3260 _In_
const std::locale& locale)
3262 return ltrim(str, rtrim(str, count, locale), locale);
3270 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
3271 void trim(_Inout_ std::basic_string<T, TR, AX>& s)
3273 auto nonspace = [&](_In_ T ch) {
return !isspace(ch); };
3294 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
3295 void trim(_Inout_ std::basic_string<T, TR, AX>& s, _In_
const std::locale& locale)
3297 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
3298 auto nonspace = [&](_In_ T ch) {
return !ctype.is(ctype.space, ch); };