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)
1647 inline size_t strcpy(
1648 _Out_ _Post_maybez_ utf32_t* dst,
1649 _In_z_
const utf16_t* src)
1653 for (
size_t j = 0, i = 0; ; ++j, ++i) {
1654 if ((dst[j] = (is_surrogate_pair(&src[i]) ? surrogate_pair_to_ucs4(&src[i++]) :
static_cast<utf32_t
>(src[i]))) == 0)
1668 template <
class T1,
class T2>
1670 _Out_writes_(count) _Post_maybez_ T1* dst,
1671 _In_reads_or_z_opt_(count)
const T2* src, _In_
size_t count)
1673 stdex_assert(dst || !count);
1674 stdex_assert(src || !count);
1675 for (
size_t i = 0; ; ++i) {
1678 if ((dst[i] =
static_cast<T1
>(src[i])) == 0)
1693 template <
class T1,
class T2>
1695 _Out_writes_(count_dst) _Post_maybez_ T1* dst, _In_
size_t count_dst,
1696 _In_reads_or_z_opt_(count_src)
const T2* src, _In_
size_t count_src)
1698 stdex_assert(dst || !count_dst);
1699 stdex_assert(src || !count_src);
1700 for (
size_t i = 0; ; ++i)
1704 if (i >= count_src) {
1708 if ((dst[i] =
static_cast<T1
>(src[i])) == 0)
1723 inline size_t strncpy(
1724 _Out_writes_(count_dst) _Post_maybez_ utf32_t* dst, _In_
size_t count_dst,
1725 _In_reads_or_z_opt_(count_src)
const utf16_t* src, _In_
size_t count_src)
1727 stdex_assert(dst || !count_dst);
1728 stdex_assert(src || !count_src);
1729 for (
size_t j = 0, i = 0; ; ++j, ++i)
1733 if (i >= count_src) {
1737 if ((dst[j] = (i + 1 < count_src && is_surrogate_pair(&src[i]) ? surrogate_pair_to_ucs4(&src[i++]) :
static_cast<utf32_t
>(src[i]))) == 0)
1750 template <
class T1,
size_t N1,
class T2,
size_t N2>
1752 _Out_ _Post_maybez_ T1 (&dst)[N1],
1753 _In_
const T2 (&src)[N2])
1755 return strncpy(dst, N1, src, N2);
1766 template <
class T1,
class T2>
1768 _In_z_ _Out_writes_z_(_String_length_(dst) + _String_length_(src) + 1) T1* dst,
1769 _In_z_
const T2* src)
1773 for (
size_t i = 0, j = stdex::strlen<T1>(dst); ; ++i, ++j) {
1774 if ((dst[j] =
static_cast<T1
>(src[i])) == 0)
1788 template <
class T1,
class T2>
1791 _In_reads_or_z_opt_(count)
const T2* src, _In_
size_t count)
1793 stdex_assert(dst || !count);
1794 stdex_assert(src || !count);
1795 for (
size_t i = 0, j = stdex::strlen<T1>(dst); ; ++i, ++j) {
1798 if ((dst[j] =
static_cast<T1
>(src[i])) == 0)
1813 template <
class T1,
class T2>
1815 _Out_writes_(count_dst) _Post_maybez_ T1* dst, _In_
size_t count_dst,
1816 _In_reads_or_z_opt_(count_src)
const T2* src, _In_
size_t count_src)
1818 stdex_assert(dst || !count_dst);
1819 stdex_assert(src || !count_src);
1820 for (
size_t i = 0, j = stdex::strnlen<T1>(dst, count_dst); ; ++i, ++j)
1824 if (i >= count_src) {
1828 if ((dst[j] =
static_cast<T1
>(src[i])) == 0)
1844 _Check_return_ _Ret_maybenull_z_ T* strdup(_In_opt_z_
const T* str)
1846 if (!str) _Unlikely_
1848 size_t count = strlen(str) + 1;
1849 T* dst =
new T[count];
1850 strncpy(dst, count, str, SIZE_MAX);
1867 _In_reads_or_z_opt_(count)
const T* str,
1870 T* dst =
new T[count];
1871 strncpy(dst, count, str, SIZE_MAX);
1885 template <
class T,
size_t N>
1886 _Check_return_ _Ret_maybenull_z_ T* strndup(_In_
const T (&str)[N])
1888 return strndup(str, N);
1901 size_t crlf2nl(_Out_writes_z_(_String_length_(src) + 1) T* dst, _In_z_
const T* src)
1906 for (i = j = 0; src[j];) {
1907 if (src[j] !=
'\r' || src[j + 1] !=
'\n')
1908 dst[i++] = src[j++];
1924 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
1925 void crlf2nl(_Inout_ std::basic_string<T, TR, AX>& dst, _In_z_
const T* src)
1928 stdex_assert(src != dst.data());
1930 dst.reserve(strlen(src));
1931 for (
size_t j = 0; src[j];) {
1932 if (src[j] !=
'\r' || src[j + 1] !=
'\n')
1946 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
1947 void crlf2nl(_Inout_ std::basic_string<T, TR, AX>& str)
1950 for (i = j = 0, n = str.size(); j < n;) {
1951 if (str[j] !=
'\r' || str[j + 1] !=
'\n')
1952 str[i++] = str[j++];
1962 template <
class T,
class T_bin>
1964 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1965 _Out_opt_
size_t* end,
1967 _Out_ uint8_t& flags)
1969 stdex_assert(str || !count);
1970 stdex_assert(radix == 0 || 2 <= radix && radix <= 36);
1973 T_bin value = 0, digit,
1975 max_ui_pre1, max_ui_pre2;
1981 if (i >= count || !str[i])
goto error;
1982 if (!isspace(str[i]))
break;
1986 if (str[i] ==
'+') {
1989 if (i >= count || !str[i])
goto error;
1991 else if (str[i] ==
'-') {
1994 if (i >= count || !str[i])
goto error;
1999 if (str[i] ==
'0' && i + 1 < count && (str[i + 1] ==
'x' || str[i + 1] ==
'X')) {
2001 if (i >= count || !str[i])
goto error;
2006 if (str[i] ==
'0') {
2008 if (i >= count || !str[i])
goto error;
2009 if (str[i] ==
'x' || str[i] ==
'X') {
2012 if (i >= count || !str[i])
goto error;
2022 max_ui_pre1 = max_ui / (T_bin)radix;
2023 max_ui_pre2 = max_ui % (T_bin)radix;
2025 if (
'0' <= str[i] && str[i] <=
'9')
2026 digit = (T_bin)str[i] -
'0';
2027 else if (
'A' <= str[i] && str[i] <=
'Z')
2028 digit = (T_bin)str[i] -
'A' +
'\x0a';
2029 else if (
'a' <= str[i] && str[i] <=
'z')
2030 digit = (T_bin)str[i] -
'a' +
'\x0a';
2033 if (digit >= (T_bin)radix)
2036 if (value < max_ui_pre1 ||
2037 (value == max_ui_pre1 && digit <= max_ui_pre2))
2038 value = value * (T_bin)radix + digit;
2045 if (i >= count || !str[i])
2065 template <
class T,
class T_bin>
2067 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
2068 _Out_opt_
size_t* end,
2074 switch (
sizeof(T_bin)) {
2076 value = (T_bin)strtoint<T, uint8_t>(str, count, end, radix, flags);
2077 if ((flags & 0x01) && (value & 0x80)) {
2081 return (flags & 0x02) ?
2082 (flags & 0x01) ? (T_bin)0x80 : (T_bin)0x7f :
2083 (flags & 0x01) ? -value : value;
2086 value = (T_bin)strtoint<T, uint16_t>(str, count, end, radix, flags);
2087 if ((flags & 0x01) && (value & 0x8000)) {
2091 return (flags & 0x02) ?
2092 (flags & 0x01) ? (T_bin)0x8000 : (T_bin)0x7fff :
2093 (flags & 0x01) ? -value : value;
2096 value = (T_bin)strtoint<T, uint32_t>(str, count, end, radix, flags);
2097 if ((flags & 0x01) && (value & 0x80000000)) {
2101 return (flags & 0x02) ?
2102 (flags & 0x01) ? (T_bin)0x80000000 : (T_bin)0x7fffffff :
2103 (flags & 0x01) ? -value : value;
2106 value = (T_bin)strtoint<T, uint64_t>(str, count, end, radix, flags);
2107 if ((flags & 0x01) && (value & 0x8000000000000000)) {
2111 return (flags & 0x02) ?
2112 (flags & 0x01) ? (T_bin)0x8000000000000000 : (T_bin)0x7fffffffffffffff :
2113 (flags & 0x01) ? -value : value;
2116 throw std::invalid_argument(
"Unsupported bit length");
2129 template <
class T,
size_t N,
class T_bin>
2131 _In_
const T (&str)[N],
2132 _Out_opt_
size_t* end,
2135 return strtoint<T, T_bin>(str, N, end, radix);
2148 template <
class T,
class T_bin>
2150 _In_reads_or_z_opt_(count)
const T* str,
2152 _Out_opt_
size_t* end,
2158 switch (
sizeof(T_bin)) {
2159 case 1: value = (T_bin)strtoint<T, uint8_t>(str, count, end, radix, flags);
break;
2160 case 2: value = (T_bin)strtoint<T, uint16_t>(str, count, end, radix, flags);
break;
2161 case 4: value = (T_bin)strtoint<T, uint32_t>(str, count, end, radix, flags);
break;
2162 case 8: value = (T_bin)strtoint<T, uint64_t>(str, count, end, radix, flags);
break;
2163 default:
throw std::invalid_argument(
"Unsupported bit length");
2166 return (flags & 0x02) ?
2167 (flags & 0x01) ? (T_bin)0 : (T_bin)-1 :
2168 (flags & 0x01) ? ~value : value;
2180 template <
class T,
size_t N,
class T_bin>
2182 _In_
const T (&str)[N],
2183 _Out_opt_
size_t* end,
2186 return strtouint<T, T_bin>(str, N, end, radix);
2201 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
2202 _Out_opt_
size_t* end,
2205 return strtoint<T, int8_t>(str, count, end, radix);
2217 template <
class T,
size_t N>
2219 _In_
const T (&str)[N],
2220 _Out_opt_
size_t* end,
2223 return strto8<T>(str, N, end, radix);
2238 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
2239 _Out_opt_
size_t* end,
2242 return strtoint<T, int16_t>(str, count, end, radix);
2254 template <
class T,
size_t N>
2256 _In_
const T (&str)[N],
2257 _Out_opt_
size_t* end,
2260 return strto16<T>(str, N, end, radix);
2275 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
2276 _Out_opt_
size_t* end,
2279 return strtoint<T, int32_t>(str, count, end, radix);
2291 template <
class T,
size_t N>
2293 _In_
const T (&str)[N],
2294 _Out_opt_
size_t* end,
2297 return strto32<T>(str, N, end, radix);
2312 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
2313 _Out_opt_
size_t* end,
2316 return strtoint<T, int64_t>(str, count, end, radix);
2328 template <
class T,
size_t N>
2330 _In_
const T (&str)[N],
2331 _Out_opt_
size_t* end,
2334 return strto64<T>(str, N, end, radix);
2350 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
2351 _Out_opt_
size_t* end,
2354#if defined(_WIN64) || defined(__LP64__)
2355 return static_cast<ptrdiff_t
>(strto64(str, count, end, radix));
2357 return static_cast<ptrdiff_t
>(strto32(str, count, end, radix));
2371 template <
class T,
size_t N>
2373 _In_
const T (&str)[N],
2374 _Out_opt_
size_t* end,
2377 return strtoi<T>(str, N, end, radix);
2392 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
2393 _Out_opt_
size_t* end,
2396 return strtouint<T, uint8_t>(str, count, end, radix);
2408 template <
class T,
size_t N>
2410 _In_
const T (&str)[N],
2411 _Out_opt_
size_t* end,
2414 return strtou8(str, N, end, radix);
2429 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
2430 _Out_opt_
size_t* end,
2433 return strtouint<T, uint16_t>(str, count, end, radix);
2445 template <
class T,
size_t N>
2447 _In_
const T (&str)[N],
2448 _Out_opt_
size_t* end,
2451 return strtou16(str, N, end, radix);
2466 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
2467 _Out_opt_
size_t* end,
2470 return strtouint<T, uint32_t>(str, count, end, radix);
2482 template <
class T,
size_t N>
2484 _In_
const T (&str)[N],
2485 _Out_opt_
size_t* end,
2488 return strtou32(str, N, end, radix);
2503 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
2504 _Out_opt_
size_t* end,
2507 return strtouint<T, uint64_t>(str, count, end, radix);
2519 template <
class T,
size_t N>
2521 _In_
const T (&str)[N],
2522 _Out_opt_
size_t* end,
2525 return strtou64<T>(str, N, end, radix);
2541 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
2542 _Out_opt_
size_t* end,
2545#if defined(_WIN64) || defined(__LP64__)
2546 return static_cast<size_t>(strtou64(str, count, end, radix));
2548 return static_cast<size_t>(strtou32(str, count, end, radix));
2562 template <
class T,
size_t N>
2564 _In_
const T (&str)[N],
2565 _Out_opt_
size_t* end,
2568 return strtoui<T>(str, N, end, radix);
2581 inline double strtod(
2582 _In_reads_or_z_opt_(count)
const char* str, _In_
size_t count,
2583 _Out_opt_
size_t* end,
2584 _In_opt_ locale_t locale)
2586 count = strnlen(str, count);
2587 stdex_assert(str || !count);
2588 std::string tmp(str, count);
2592 r = _strtod_l(tmp.c_str(), &_end, locale);
2594 r = strtod_l(tmp.c_str(), &_end, locale);
2596 if (end) *end = (size_t)(_end - tmp.c_str());
2610 inline double strtod(
2611 _In_reads_or_z_opt_(count)
const wchar_t* str, _In_
size_t count,
2612 _Out_opt_
size_t* end,
2613 _In_opt_ locale_t locale)
2615 count = strnlen(str, count);
2616 stdex_assert(str || !count);
2617 std::wstring tmp(str, count);
2621 r = _wcstod_l(tmp.c_str(), &_end, locale);
2623 r = wcstod_l(tmp.c_str(), &_end, locale);
2625 if (end) *end = (size_t)(_end - tmp.c_str());
2630 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)
2633#pragma warning(suppress: 4996)
2634 return _vsnprintf_l(str, capacity, format, locale, arg);
2636 va_list arg_mutable;
2637 va_copy(arg_mutable, arg);
2638 return ::vsnprintf_l(str, capacity, locale, format, arg_mutable);
2642 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)
2645#pragma warning(suppress: 4996)
2646 return _vsnwprintf_l(str, capacity, format, locale, arg);
2648 va_list arg_mutable;
2649 va_copy(arg_mutable, arg);
2650 return ::vswprintf_l(str, capacity, locale, format, arg_mutable);
2665 template<
class T,
class TR,
class AX>
2666 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)
2668 T buf[1024 /
sizeof(T)];
2671 int count = vsnprintf(buf, _countof(buf), format, locale, arg);
2672 if (0 <= count &&
static_cast<size_t>(count) <= _countof(buf)) {
2674 str.append(buf,
static_cast<size_t>(count));
2675 return static_cast<size_t>(count);
2681 count = vsnprintf(NULL, 0, format, locale, arg);
2682 stdex_assert(count >= 0);
2684 case EINVAL:
throw std::invalid_argument(
"invalid vsnprintf arguments");
2685 case EILSEQ:
throw std::runtime_error(
"encoding error");
2686 default:
throw std::runtime_error(
"failed to format string");
2689 size_t offset = str.size();
2690 str.resize(offset + count);
2691 if (vsnprintf(&str[offset], count + 1, format, locale, arg) != count) _Unlikely_
2692 throw std::runtime_error(
"failed to format string");
2694 size_t offset = str.size();
2695 for (
size_t capacity = 2 * 1024 /
sizeof(T);; capacity *= 2) {
2699 str.resize(offset + capacity);
2700 count = vsnprintf(&str[offset], capacity, format, locale, arg);
2701 if (0 <= count &&
static_cast<size_t>(count) <= capacity) {
2702 str.resize(offset +
static_cast<size_t>(count));
2703 return static_cast<size_t>(count);
2706 case EINVAL:
throw std::invalid_argument(
"invalid vsnprintf arguments");
2707 case EILSEQ:
throw std::runtime_error(
"encoding error");
2708 default:
throw std::runtime_error(
"failed to format string");
2712 return static_cast<size_t>(count);
2724 template<
class T,
class TR,
class AX>
2725 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, ...)
2728 va_start(arg, locale);
2729 size_t n = vappendf(str, format, locale, arg);
2742 template<
class T,
class TR,
class AX>
2743 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)
2746 vappendf(str, format, locale, arg);
2756 template<
class T,
class TR,
class AX>
2757 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, ...)
2760 va_start(arg, locale);
2761 vsprintf(str, format, locale, arg);
2774 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
2775 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)
2777 std::basic_string<T, TR, AX> str;
2778 vappendf(str, format, locale, arg);
2790 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
2791 std::basic_string<T, TR, AX> sprintf(_In_z_ _Printf_format_string_params_(2)
const T* format, _In_opt_ locale_t locale, ...)
2794 va_start(arg, locale);
2795 auto str = vsprintf(format, locale, arg);
2801 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)
2804 return _strftime_l(str, capacity, format, time, locale);
2806 return strftime_l(str, capacity, format, time, locale);
2810 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)
2813 return _wcsftime_l(str, capacity, format, time, locale);
2815 return wcsftime_l(str, capacity, format, time, locale);
2828 template<
class T,
class TR,
class AX>
2829 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)
2831 T buf[1024 /
sizeof(T)];
2834 size_t count = strftime(buf, _countof(buf), format, time, locale);
2837 str.append(buf, count);
2840 size_t offset = str.size();
2841 for (
size_t capacity = 2 * 1024 /
sizeof(T);; capacity *= 2) {
2843 str.resize(offset + capacity);
2844 count = strftime(&str[offset], capacity + 1, format, time, locale);
2846 str.resize(offset + count);
2860 template<
class T,
class TR,
class AX>
2861 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)
2864 strcatftime(str, format, time, locale);
2876 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
2877 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)
2879 std::basic_string<T, TR, AX> str;
2880 strcatftime(str, format, time, locale);
2919 void strlwr(_Inout_updates_z_(count) T* str, _In_
size_t count)
2921 stdex_assert(str || !count);
2922 for (
size_t i = 0; i < count && str[i]; ++i)
2923 str[i] = tolower(str[i]);
2934 void strlwr(_Inout_updates_z_(count) T* str, _In_
size_t count, _In_
const std::locale& locale)
2936 stdex_assert(str || !count);
2937 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
2938 for (
size_t i = 0; i < count && str[i]; ++i)
2939 str[i] = ctype.tolower(str[i]);
2947 template<
class T,
size_t N>
2948 void strlwr(_Inout_ T (&str)[N])
2959 template<
class T,
size_t N>
2960 void strlwr(_Inout_ T (&str)[N], _In_
const std::locale& locale)
2962 strlwr(str, N, locale);
2970 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
2971 void strlwr(_Inout_ std::basic_string<T, TR, AX>& str)
2983 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
2984 void strlwr(_Inout_ std::basic_string<T, TR, AX>& str, _In_
const std::locale& locale)
2986 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
2988 c = ctype.tolower(c);
3026 void strupr(_Inout_updates_z_(count) T* str, _In_
size_t count)
3028 stdex_assert(str || !count);
3029 for (
size_t i = 0; i < count && str[i]; ++i)
3030 str[i] = toupper(str[i]);
3041 void strupr(_Inout_updates_z_(count) T* str, _In_
size_t count, _In_
const std::locale& locale)
3043 stdex_assert(str || !count);
3044 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
3045 for (
size_t i = 0; i < count && str[i]; ++i)
3046 str[i] = ctype.toupper(str[i]);
3054 template<
class T,
size_t N>
3055 void strupr(_Inout_ T (&str)[N])
3057 return strupr(str, N);
3066 template<
class T,
size_t N>
3067 void strupr(_Inout_ T (&str)[N], _In_
const std::locale& locale)
3069 return strupr(str, N, locale);
3077 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
3078 void strupr(_Inout_ std::basic_string<T, TR, AX>& str)
3090 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
3091 void strupr(_Inout_ std::basic_string<T, TR, AX>& str, _In_
const std::locale& locale)
3093 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
3095 c = ctype.toupper(c);
3108 _Inout_z_count_(count) T* str, _In_
size_t count)
3110 for (
size_t i = 0;; ++i) {
3112 if (count) str[0] = 0;
3119 if (!isspace(str[i])) {
3121 return strnlen(str, count);
3122 size_t n = count != SIZE_MAX ? strncpy(str, str + i, count - i) : strcpy(str, str + i);
3140 _Inout_z_count_(count) T* str, _In_
size_t count,
3141 _In_
const std::locale& locale)
3143 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
3144 for (
size_t i = 0;; ++i) {
3146 if (count) str[0] = 0;
3153 if (!ctype.is(ctype.space, str[i])) {
3155 return strnlen(str, count);
3156 size_t n = count != SIZE_MAX ? strncpy(str, str + i, count - i) : strcpy(str, str + i);
3168 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
3169 void ltrim(_Inout_ std::basic_string<T, TR, AX>& s)
3176 [&](_In_ T ch) { return !isspace(ch); }));
3185 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
3186 void ltrim(_Inout_ std::basic_string<T, TR, AX>& s, _In_
const std::locale& locale)
3188 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
3194 [&](_In_ T ch) { return !ctype.is(ctype.space, ch); }));
3207 _Inout_z_count_(count) T* str, _In_
size_t count)
3209 for (
size_t i = 0, j = 0;;) {
3210 if (i >= count || !str[i]) {
3211 if (j < count) str[j] = 0;
3214 if (!isspace(str[i]))
3232 _Inout_z_count_(count) T* str, _In_
size_t count,
3233 _In_
const std::locale& locale)
3235 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
3236 for (
size_t i = 0, j = 0;;) {
3237 if (i >= count || !str[i]) {
3238 if (j < count) str[j] = 0;
3241 if (!ctype.is(ctype.space, str[i]))
3253 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
3254 void rtrim(_Inout_ std::basic_string<T, TR, AX>& s)
3260 [&](_In_ T ch) { return !isspace(ch); }).base(),
3270 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
3271 void rtrim(_Inout_ std::basic_string<T, TR, AX>& s, _In_
const std::locale& locale)
3273 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
3278 [&](_In_ T ch) { return !ctype.is(ctype.space, ch); }).base(),
3292 _Inout_z_count_(count) T* str, _In_
size_t count)
3294 return ltrim(str, rtrim(str, count));
3308 _Inout_z_count_(count) T* str, _In_
size_t count,
3309 _In_
const std::locale& locale)
3311 return ltrim(str, rtrim(str, count, locale), locale);
3319 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
3320 void trim(_Inout_ std::basic_string<T, TR, AX>& s)
3322 auto nonspace = [&](_In_ T ch) {
return !isspace(ch); };
3343 template<
class T,
class TR = std::
char_traits<T>,
class AX = std::allocator<T>>
3344 void trim(_Inout_ std::basic_string<T, TR, AX>& s, _In_
const std::locale& locale)
3346 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
3347 auto nonspace = [&](_In_ T ch) {
return !ctype.is(ctype.space, ch); };