28 using locale_t = _locale_t;
30 inline locale_t create_locale(_In_
int category, _In_z_
const char* locale) {
return _create_locale(category, locale); }
31 inline locale_t create_locale(_In_
int category, _In_z_
const wchar_t* locale) {
return _wcreate_locale(category, locale); }
32 inline void free_locale(_In_opt_ locale_t locale) { _free_locale(locale); }
34 using locale_t = ::locale_t;
36 inline locale_t create_locale(_In_
int category, _In_z_
const char* locale)
40 case LC_ALL : mask = LC_ALL_MASK ;
break;
41 case LC_COLLATE : mask = LC_COLLATE_MASK ;
break;
42 case LC_CTYPE : mask = LC_CTYPE_MASK ;
break;
43 case LC_MESSAGES: mask = LC_MESSAGES_MASK;
break;
44 case LC_MONETARY: mask = LC_MONETARY_MASK;
break;
45 case LC_NUMERIC : mask = LC_NUMERIC_MASK ;
break;
46 case LC_TIME : mask = LC_TIME_MASK ;
break;
48 return newlocale(mask, locale, LC_GLOBAL_LOCALE);
51 inline void free_locale(_In_opt_ locale_t locale) { freelocale(locale); }
72 using locale = std::unique_ptr<__crt_locale_pointers, free_locale_delete>;
73#elif defined(__APPLE__)
74 using locale = std::unique_ptr<struct _xlocale, free_locale_delete>;
76 using locale = std::unique_ptr<struct __locale_struct, free_locale_delete>;
82 const locale locale_C(create_locale(LC_ALL,
"C"));
88 typedef wchar_t utf16_t;
90 typedef char16_t utf16_t;
98 inline bool is_high_surrogate(_In_ utf16_t chr)
100 return 0xd800 < chr && chr < 0xdc00;
108 inline bool is_low_surrogate(_In_ utf16_t chr)
110 return 0xdc00 < chr && chr < 0xe000;
118 inline bool is_surrogate_pair(_In_reads_(2)
const utf16_t* str)
120 return is_high_surrogate(str[0]) && is_low_surrogate(str[1]);
128 inline char32_t surrogate_pair_to_ucs4(_In_reads_(2)
const utf16_t* str)
130 _Assume_(is_surrogate_pair(str));
132 ((
char32_t)(str[0] - 0xd800) << 10) +
133 (char32_t)(str[1] - 0xdc00) +
142 inline void ucs4_to_surrogate_pair(_Out_writes_(2) utf16_t* str, _In_
char32_t chr)
144 _Assume_(chr >= 0x10000);
146 str[0] = 0xd800 + (char32_t)((chr >> 10) & 0x3ff);
147 str[1] = 0xdc00 + (char32_t)(chr & 0x3ff);
155 inline bool iscombining(_In_
char32_t chr)
158 (0x0300 <= chr && chr < 0x0370) ||
159 (0x1dc0 <= chr && chr < 0x1e00) ||
160 (0x20d0 <= chr && chr < 0x2100) ||
161 (0xfe20 <= chr && chr < 0xfe30);
170 inline size_t islbreak(_In_ T chr)
172 return chr ==
'\n' || chr ==
'\r';
182 inline size_t islbreak(_In_reads_or_z_opt_(count)
const T* chr, _In_
size_t count)
184 _Assume_(chr || !count);
185 if (count >= 2 && ((chr[0] ==
'\r' && chr[1] ==
'\n') || (chr[0] ==
'\n' && chr[1] ==
'\r')))
187 if (count > 1 && (chr[0] ==
'\n' || chr[0] ==
'\r'))
198 inline size_t glyphlen(_In_reads_or_z_opt_(count)
const wchar_t* glyph, _In_
size_t count)
200 _Assume_(glyph || !count);
203 size_t i = count < 2 || !is_surrogate_pair(glyph) ? 1 : 2;
207 for (; i < count && iscombining(glyph[i]); ++i);
221 inline size_t strlen(_In_z_
const T* str)
225 for (i = 0; str[i]; ++i);
238 inline size_t strnlen(_In_reads_or_z_opt_(count)
const T* str, _In_
size_t count)
240 _Assume_(str || !count);
242 for (i = 0; i < count && str[i]; ++i);
246 constexpr auto npos{
static_cast<size_t>(-1) };
257 inline size_t strchr(_In_z_
const T* str, _In_ T chr)
260 for (
size_t i = 0; str[i]; ++i)
261 if (str[i] == chr)
return i;
275 inline size_t strnchr(
276 _In_reads_or_z_opt_(count)
const T* str,
280 _Assume_(str || !count);
281 for (
size_t i = 0; i < count && str[i]; ++i)
282 if (str[i] == chr)
return i;
296 inline size_t strrnchr(
297 _In_reads_or_z_opt_(count)
const T* str,
301 _Assume_(str || !count);
303 for (
size_t i = 0; i < count && str[i]; ++i)
304 if (str[i] == chr) z = i;
318 inline size_t strnichr(
319 _In_reads_or_z_opt_(count)
const T* str,
322 _In_
const std::locale& locale)
324 _Assume_(str || !count);
325 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
326 chr = ctype.tolower(chr);
327 for (
size_t i = 0; i < count && str[i]; ++i)
328 if (ctype.tolower(str[i]) == chr)
return i;
342 inline size_t strrnichr(
343 _In_reads_or_z_opt_(count)
const T* str,
346 _In_
const std::locale& locale)
348 _Assume_(str || !count);
349 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
350 chr = ctype.tolower(chr);
352 for (
size_t i = 0; i < count && str[i]; ++i)
353 if (ctype.tolower(str[i]) == chr) z = i;
365 template <
class T1,
class T2>
366 inline int strcmp(
const T1* str1,
const T2* str2)
368 _Assume_(str1 && str2);
370 for (
size_t i = 0; (a = str1[i]) | (b = str2[i]); ++i) {
371 if (a > b)
return +1;
372 if (a < b)
return -1;
387 template <
class T1,
class T2>
389 _In_reads_or_z_opt_(count1)
const T1* str1, _In_
size_t count1,
390 _In_reads_or_z_opt_(count2)
const T2* str2, _In_
size_t count2)
392 _Assume_(str1 || !count1);
393 _Assume_(str2 || !count2);
394 size_t i; T1 a; T2 b;
395 for (i = 0; i < count1 && i < count2 && ((a = str1[i]) | (b = str2[i])); ++i) {
396 if (a > b)
return +1;
397 if (a < b)
return -1;
399 if (i < count1 && str1[i])
return +1;
400 if (i < count2 && str2[i])
return -1;
413 template <
class T1,
class T2>
414 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)
416 _Assume_((str1 && str2) || !count);
417 size_t i; T1 a; T2 b;
418 for (i = 0; i < count && ((a = str1[i]) | (b = str2[i])); ++i) {
419 if (a > b)
return +1;
420 if (a < b)
return -1;
422 if (i < count && str1[i])
return +1;
423 if (i < count && str2[i])
return -1;
439 _In_reads_or_z_opt_(count1)
const T* str1, _In_
size_t count1,
440 _In_reads_or_z_opt_(count2)
const T* str2, _In_
size_t count2,
441 _In_
const std::locale& locale)
443 _Assume_(str1 || !count1);
444 _Assume_(str2 || !count2);
445 auto& collate = std::use_facet<std::collate<T>>(locale);
446 return collate.compare(str1, str1 + count1, str2, str2 + count2);
457 template <
class T1,
class T2>
458 inline int stricmp(_In_z_
const T1* str1, _In_z_
const T2* str2, _In_
const std::locale& locale)
462 size_t i; T1 a; T2 b;
463 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
464 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
465 for (i = 0; (a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i])); i++) {
466 if (a > b)
return +1;
467 if (a < b)
return -1;
469 if (str1[i])
return +1;
470 if (str2[i])
return -1;
483 template <
class T1,
class T2>
484 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)
486 _Assume_(str1 || !count);
487 _Assume_(str2 || !count);
488 size_t i; T1 a; T2 b;
489 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
490 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
491 for (i = 0; i < count && ((a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i]))); i++) {
492 if (a > b)
return +1;
493 if (a < b)
return -1;
495 if (i < count && str1[i])
return +1;
496 if (i < count && str2[i])
return -1;
510 template <
class T1,
class T2>
512 _In_reads_or_z_opt_(count1)
const T1* str1, _In_
size_t count1,
513 _In_reads_or_z_opt_(count2)
const T2* str2, _In_
size_t count2,
514 _In_
const std::locale& locale)
516 _Assume_(str1 || !count1);
517 _Assume_(str2 || !count2);
518 size_t i; T1 a; T2 b;
519 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
520 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
521 for (i = 0; i < count1 && i < count2 && ((a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i]))); i++) {
522 if (a > b)
return +1;
523 if (a < b)
return -1;
525 if (i < count1 && str1[i])
return +1;
526 if (i < count2 && str2[i])
return -1;
538 template <
class T1,
class T2>
539 inline size_t strstr(
540 _In_z_
const T1* str,
541 _In_z_
const T2* sample)
545 for (
size_t offset = 0;; ++offset) {
546 for (
size_t i = offset, j = 0;; ++i, ++j) {
551 if (str[i] != sample[j])
566 template <
class T1,
class T2>
567 inline size_t strnstr(
568 _In_reads_or_z_opt_(count)
const T1* str,
570 _In_z_
const T2* sample)
572 _Assume_(str || !count);
574 for (
size_t offset = 0;; ++offset) {
575 for (
size_t i = offset, j = 0;; ++i, ++j) {
578 if (i >= count || !str[i])
580 if (str[i] != sample[j])
594 template <
class T1,
class T2>
595 inline size_t stristr(
596 _In_z_
const T1* str,
597 _In_z_
const T2* sample,
598 _In_
const std::locale& locale)
602 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
603 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
604 for (
size_t offset = 0;; ++offset) {
605 for (
size_t i = offset, j = 0;; ++i, ++j) {
610 if (ctype1.tolower(str[i]) != ctype2.tolower(sample[j]))
625 template <
class T1,
class T2>
626 inline size_t strnistr(
627 _In_reads_or_z_opt_(count)
const T1* str,
629 _In_z_
const T2* sample,
630 _In_
const std::locale& locale)
632 _Assume_(str || !count);
634 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
635 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
636 for (
size_t offset = 0;; ++offset) {
637 for (
size_t i = offset, j = 0;; ++i, ++j) {
640 if (i >= count || !str[i])
642 if (ctype1.tolower(str[i]) != ctype2.tolower(sample[j]))
656 template <
class T1,
class T2>
657 inline size_t strcpy(
658 _Out_writes_z_(_String_length_(src) + 1) T1* dst,
659 _In_z_
const T2* src)
661 _Assume_(dst && src);
662 for (
size_t i = 0; ; ++i) {
663 if ((dst[i] = src[i]) == 0)
677 template <
class T1,
class T2>
678 inline size_t strncpy(
679 _Out_writes_(count) _Post_maybez_ T1* dst,
680 _In_reads_or_z_opt_(count)
const T2* src, _In_
size_t count)
682 _Assume_(dst && src || !count);
683 for (
size_t i = 0; ; ++i) {
686 if ((dst[i] = src[i]) == 0)
701 template <
class T1,
class T2>
702 inline size_t strncpy(
703 _Out_writes_(count_dst) _Post_maybez_ T1* dst, _In_
size_t count_dst,
704 _In_reads_or_z_opt_(count_src)
const T2* src, _In_
size_t count_src)
706 _Assume_(dst || !count_dst);
707 _Assume_(src || !count_src);
708 for (
size_t i = 0; ; ++i)
712 if (i >= count_src) {
716 if ((dst[i] = src[i]) == 0)
729 template <
class T1,
class T2>
730 inline size_t strcat(
731 _In_z_ _Out_writes_z_(_String_length_(dst) + _String_length_(src) + 1) T1* dst,
732 _In_z_
const T2* src)
734 _Assume_(dst && src);
735 for (
size_t i = 0, j = stdex::strlen<T1>(dst); ; ++i, ++j) {
736 if ((dst[j] = src[i]) == 0)
750 template <
class T1,
class T2>
751 inline size_t strncat(
753 _In_reads_or_z_opt_(count)
const T2* src, _In_
size_t count)
755 _Assume_(dst && src || !count);
756 for (
size_t i = 0, j = stdex::strlen<T1>(dst); ; ++i, ++j) {
759 if ((dst[j] = src[i]) == 0)
774 template <
class T1,
class T2>
775 inline size_t strncat(
776 _Out_writes_(count_dst) _Post_maybez_ T1* dst, _In_
size_t count_dst,
777 _In_reads_or_z_opt_(count_src)
const T2* src, _In_
size_t count_src)
779 _Assume_(dst || !count_dst);
780 _Assume_(src || !count_src);
781 for (
size_t i = 0, j = stdex::strnlen<T1>(dst, count_dst); ; ++i, ++j)
785 if (i >= count_src) {
789 if ((dst[j] = src[i]) == 0)
805 inline _Check_return_ _Ret_maybenull_z_ T* strdup(_In_opt_z_
const T* str)
809 size_t count = strlen(str) + 1;
810 T* dst =
new T[count];
811 strncpy(dst, count, str, SIZE_MAX);
827 inline _Ret_z_ T* strndup(
828 _In_reads_or_z_opt_(count)
const T* str,
831 T* dst =
new T[count];
832 strncpy(dst, count, str, SIZE_MAX);
846 inline size_t crlf2nl(_Out_writes_z_(strlen(src)) T* dst, _In_z_
const T* src)
851 for (i = j = 0; src[j];) {
852 if (src[j] !=
'\r' || src[j + 1] !=
'\n')
869 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
870 inline void crlf2nl(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &dst, _In_z_
const _Elem* src)
873 _Assume_(src != dst.c_str());
875 dst.reserve(strlen(src));
876 for (
size_t j = 0; src[j];) {
877 if (src[j] !=
'\r' || src[j + 1] !=
'\n')
891 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
892 inline void crlf2nl(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& str)
895 for (i = j = 0, n = str.size(); j < n;) {
896 if (str[j] !=
'\r' || str[j + 1] !=
'\n')
907 template <
class T,
class T_bin>
908 inline T_bin strtoint(
909 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
910 _Out_opt_
size_t* end,
912 _Out_ uint8_t& flags)
914 _Assume_(str || !count);
915 _Assume_(radix == 0 || 2 <= radix && radix <= 36);
918 T_bin value = 0, digit,
920 max_ui_pre1, max_ui_pre2;
926 if (i >= count || !str[i])
goto error;
927 if (!isspace(str[i]))
break;
934 if (i >= count || !str[i])
goto error;
936 else if (str[i] ==
'-') {
939 if (i >= count || !str[i])
goto error;
944 if (str[i] ==
'0' && i + 1 < count && (str[i + 1] ==
'x' || str[i + 1] ==
'X')) {
946 if (i >= count || !str[i])
goto error;
953 if (i >= count || !str[i])
goto error;
954 if (str[i] ==
'x' || str[i] ==
'X') {
957 if (i >= count || !str[i])
goto error;
967 max_ui_pre1 = max_ui / (T_bin)radix;
968 max_ui_pre2 = max_ui % (T_bin)radix;
970 if (
'0' <= str[i] && str[i] <=
'9')
971 digit = (T_bin)str[i] -
'0';
972 else if (
'A' <= str[i] && str[i] <=
'Z')
973 digit = (T_bin)str[i] -
'A' +
'\x0a';
974 else if (
'a' <= str[i] && str[i] <=
'z')
975 digit = (T_bin)str[i] -
'a' +
'\x0a';
978 if (digit >= (T_bin)radix)
981 if (value < max_ui_pre1 ||
982 (value == max_ui_pre1 && digit <= max_ui_pre2))
983 value = value * (T_bin)radix + digit;
990 if (i >= count || !str[i])
1010 template <
class T,
class T_bin>
1012 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1013 _Out_opt_
size_t* end,
1019 switch (
sizeof(T_bin)) {
1021 value = (T_bin)strtoint<T, uint8_t>(str, count, end, radix, flags);
1022 if ((flags & 0x01) && (value & 0x80)) {
1026 return (flags & 0x02) ?
1027 (flags & 0x01) ? (T_bin)0x80 : (T_bin)0x7f :
1028 (flags & 0x01) ? -value : value;
1031 value = (T_bin)strtoint<T, uint16_t>(str, count, end, radix, flags);
1032 if ((flags & 0x01) && (value & 0x8000)) {
1036 return (flags & 0x02) ?
1037 (flags & 0x01) ? (T_bin)0x8000 : (T_bin)0x7fff :
1038 (flags & 0x01) ? -value : value;
1041 value = (T_bin)strtoint<T, uint32_t>(str, count, end, radix, flags);
1042 if ((flags & 0x01) && (value & 0x80000000)) {
1046 return (flags & 0x02) ?
1047 (flags & 0x01) ? (T_bin)0x80000000 : (T_bin)0x7fffffff :
1048 (flags & 0x01) ? -value : value;
1051 value = (T_bin)strtoint<T, uint64_t>(str, count, end, radix, flags);
1052 if ((flags & 0x01) && (value & 0x8000000000000000)) {
1056 return (flags & 0x02) ?
1057 (flags & 0x01) ? (T_bin)0x8000000000000000 : (T_bin)0x7fffffffffffffff :
1058 (flags & 0x01) ? -value : value;
1061 throw std::invalid_argument(
"Unsupported bit length");
1075 template <
class T,
class T_bin>
1076 inline T_bin strtouint(
1077 _In_reads_or_z_opt_(count)
const T* str,
1079 _Out_opt_
size_t* end,
1085 switch (
sizeof(T_bin)) {
1086 case 1: value = (T_bin)strtoint<T, uint8_t>(str, count, end, radix, flags);
break;
1087 case 2: value = (T_bin)strtoint<T, uint16_t>(str, count, end, radix, flags);
break;
1088 case 4: value = (T_bin)strtoint<T, uint32_t>(str, count, end, radix, flags);
break;
1089 case 8: value = (T_bin)strtoint<T, uint64_t>(str, count, end, radix, flags);
break;
1090 default:
throw std::invalid_argument(
"Unsupported bit length");
1093 return (flags & 0x02) ?
1094 (flags & 0x01) ? (T_bin)0 : (T_bin)-1 :
1095 (flags & 0x01) ? ~value : value;
1109 inline int32_t strto32(
1110 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1111 _Out_opt_
size_t* end,
1114 return strtoint<T, int32_t>(str, count, end, radix);
1128 inline int64_t strto64(
1129 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1130 _Out_opt_
size_t* end,
1133 return strtoint<T, int64_t>(str, count, end, radix);
1148 inline intptr_t strtoi(
1149 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1150 _Out_opt_
size_t* end,
1153#if defined(_WIN64) || defined(__LP64__)
1154 return (intptr_t)strto64(str, count, end, radix);
1156 return (intptr_t)strto32(str, count, end, radix);
1171 inline uint32_t strtou32(
1172 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1173 _Out_opt_
size_t* end,
1176 return strtouint<T, uint32_t>(str, count, end, radix);
1190 inline uint64_t strtou64(
1191 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1192 _Out_opt_
size_t* end,
1195 return strtouint<T, uint64_t>(str, count, end, radix);
1210 inline size_t strtoui(
1211 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1212 _Out_opt_
size_t* end,
1215#if defined(_WIN64) || defined(__LP64__)
1216 return (
size_t)strtou64(str, count, end, radix);
1218 return (
size_t)strtou32(str, count, end, radix);
1223 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)
1228#pragma warning(suppress: 4996)
1229 r = _vsnprintf_l(str, capacity, format, locale, arg);
1231 r = ::vsnprintf(str, capacity, format, arg);
1233 if (r == -1 && strnlen(str, capacity) == capacity) {
1235 capacity += std::max<size_t>(capacity / 8, 0x80);
1236 if (capacity > INT_MAX)
1237 throw std::invalid_argument(
"string too big");
1238 return (
int)capacity;
1243 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)
1248#pragma warning(suppress: 4996)
1249 r = _vsnwprintf_l(str, capacity, format, locale, arg);
1251 r = vswprintf(str, capacity, format, arg);
1253 if (r == -1 && strnlen(str, capacity) == capacity) {
1255 capacity += std::max<size_t>(capacity / 8, 0x80);
1256 if (capacity > INT_MAX)
1257 throw std::invalid_argument(
"string too big");
1258 return (
int)capacity;
1272 template<
class _Elem,
class _Traits,
class _Ax>
1273 inline void vappendf(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _Printf_format_string_params_(2)
const _Elem *format, _In_opt_ locale_t locale, _In_ va_list arg)
1275 _Elem buf[1024/
sizeof(_Elem)];
1278 int count = vsnprintf(buf, _countof(buf) - 1, format, locale, arg);
1281 str.append(buf, count);
1283 for (
size_t capacity = 2*1024/
sizeof(_Elem);; capacity *= 2) {
1285 auto buf_dyn = std::make_unique<_Elem[]>(capacity);
1286 count = vsnprintf(buf_dyn.get(), capacity - 1, format, locale, arg);
1288 str.append(buf_dyn.get(), count);
1302 template<
class _Elem,
class _Traits,
class _Ax>
1303 inline void appendf(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _Printf_format_string_params_(2)
const _Elem *format, _In_opt_ locale_t locale, ...)
1306 va_start(arg, locale);
1307 vappendf(str, format, locale, arg);
1319 template<
class _Elem,
class _Traits,
class _Ax>
1320 inline void vsprintf(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _Printf_format_string_params_(2)
const _Elem *format, _In_opt_ locale_t locale, _In_ va_list arg)
1323 vappendf(str, format, locale, arg);
1333 template<
class _Elem,
class _Traits,
class _Ax>
1334 inline void sprintf(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _Printf_format_string_params_(2)
const _Elem *format, _In_opt_ locale_t locale, ...)
1337 va_start(arg, locale);
1338 vsprintf(str, format, locale, arg);
1351 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1352 inline std::basic_string<_Elem, _Traits, _Ax> vsprintf(_In_z_ _Printf_format_string_params_(2)
const _Elem *format, _In_opt_ locale_t locale, _In_ va_list arg)
1354 std::basic_string<_Elem, _Traits, _Ax> str;
1355 vappendf(str, format, locale, arg);
1367 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1368 inline std::basic_string<_Elem, _Traits, _Ax> sprintf(_In_z_ _Printf_format_string_params_(2)
const _Elem *format, _In_opt_ locale_t locale, ...)
1371 va_start(arg, locale);
1372 auto str = vsprintf(format, locale, arg);
1378 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)
1381 return _strftime_l(str, capacity, format, time, locale);
1383 return strftime_l(str, capacity, format, time, locale);
1387 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)
1390 return _wcsftime_l(str, capacity, format, time, locale);
1392 return wcsftime_l(str, capacity, format, time, locale);
1405 template<
class _Elem,
class _Traits,
class _Ax>
1406 inline void strcatftime(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _Printf_format_string_
const _Elem *format, _In_
const struct tm* time, _In_opt_ locale_t locale)
1408 _Elem buf[1024/
sizeof(_Elem)];
1411 size_t count = strftime(buf, _countof(buf), format, time, locale);
1414 str.append(buf, count);
1416 for (
size_t capacity = 2*1024/
sizeof(_Elem);; capacity *= 2) {
1418 auto buf_dyn = std::make_unique<_Elem[]>(capacity);
1419 count = strftime(buf_dyn.get(), capacity, format, time, locale);
1421 str.append(buf_dyn.get(), count);
1436 template<
class _Elem,
class _Traits,
class _Ax>
1437 inline void strftime(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &str, _In_z_ _Printf_format_string_
const _Elem *format, _In_
const struct tm* time, _In_opt_ locale_t locale)
1440 strcatftime(str, format, time, locale);
1453 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1454 inline std::basic_string<_Elem, _Traits, _Ax> strftime(_In_z_ _Printf_format_string_
const _Elem *format, _In_
const struct tm* time, _In_opt_ locale_t locale)
1456 std::basic_string<_Elem, _Traits, _Ax> str;
1457 strcatftime(str, format, time, locale);
1469 inline void strlwr(_Inout_z_ T* str, _In_
const std::locale& locale)
1472 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
1473 for (
size_t i = 0; str[i]; ++i)
1474 str[i] = ctype.tolower(str[i]);
1486 inline void strlwr(_Inout_updates_z_(count) T* str, _In_
size_t count, _In_
const std::locale& locale)
1488 _Assume_(str || !count);
1489 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
1490 for (
size_t i = 0; i < count && str[i]; ++i)
1491 str[i] = ctype.tolower(str[i]);
1502 inline void strupr(_Inout_z_ T* str, _In_
const std::locale& locale)
1505 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
1506 for (
size_t i = 0; str[i]; ++i)
1507 str[i] = ctype.toupper(str[i]);
1519 inline void strupr(_Inout_updates_z_(count) T* str, _In_
size_t count, _In_
const std::locale& locale)
1521 _Assume_(str || !count);
1522 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
1523 for (
size_t i = 0; i < count && str[i]; ++i)
1524 str[i] = ctype.toupper(str[i]);
1534 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1535 inline void strupr(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& str, _In_
const std::locale& locale)
1537 const auto& ctype = std::use_facet<std::ctype<_Elem>>(locale);
1538 for (
size_t i = 0; i < str.size(); ++i)
1539 str[i] = ctype.toupper(str[i]);
1551 inline size_t ltrim(
1552 _Inout_z_count_(count) T* str, _In_
size_t count,
1553 _In_
const std::locale& locale)
1555 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
1556 for (
size_t i = 0;; ++i) {
1558 if (count) str[0] = 0;
1565 if (!ctype.is(ctype.space, str[i])) {
1567 return strnlen(str, count);
1568 size_t n = count != SIZE_MAX ? strncpy(str, str + i, count - i) : strcpy(str, str + i);
1580 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1581 inline void ltrim(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &s, _In_
const std::locale& locale)
1583 const auto& ctype = std::use_facet<std::ctype<_Elem>>(locale);
1589 [&](_Elem ch) { return !ctype.is(ctype.space, ch); }));
1601 inline size_t rtrim(
1602 _Inout_z_count_(count) T* str, _In_
size_t count,
1603 _In_
const std::locale& locale)
1605 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
1606 for (
size_t i = 0, j = 0;;) {
1607 if (i >= count || !str[i]) {
1608 if (j < count) str[j] = 0;
1611 if (!ctype.is(ctype.space, str[i]))
1623 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1624 static inline void rtrim(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &s, _In_
const std::locale& locale)
1626 const auto& ctype = std::use_facet<std::ctype<_Elem>>(locale);
1631 [&](_Elem ch) { return !ctype.is(ctype.space, ch); }).base(),
1645 _Inout_z_count_(count) T* str, _In_
size_t count,
1646 _In_
const std::locale& locale)
1648 return ltrim(str, rtrim(str, count, locale), locale);
1656 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1657 static inline void trim(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &s, _In_
const std::locale& locale)
1659 const auto& ctype = std::use_facet<std::ctype<_Elem>>(locale);
1665 [&](_Elem ch) { return !ctype.is(ctype.space, ch); }));
1670 [&](_Elem ch) { return !ctype.is(ctype.space, ch); }).base(),
Deleter for unique_ptr using free_locale.
Definition string.hpp:58
void operator()(locale_t locale) const
Delete a pointer.
Definition string.hpp:62