18#elif defined(__APPLE__)
30 using locale_t = _locale_t;
32 inline locale_t create_locale(_In_
int category, _In_z_
const char* locale) {
return _create_locale(category, locale); }
33 inline locale_t create_locale(_In_
int category, _In_z_
const wchar_t* locale) {
return _wcreate_locale(category, locale); }
34 inline void free_locale(_In_opt_ locale_t locale) { _free_locale(locale); }
36 using locale_t = ::locale_t;
38 inline locale_t create_locale(_In_
int category, _In_z_
const char* locale)
42 case LC_ALL : mask = LC_ALL_MASK ;
break;
43 case LC_COLLATE : mask = LC_COLLATE_MASK ;
break;
44 case LC_CTYPE : mask = LC_CTYPE_MASK ;
break;
45 case LC_MESSAGES: mask = LC_MESSAGES_MASK;
break;
46 case LC_MONETARY: mask = LC_MONETARY_MASK;
break;
47 case LC_NUMERIC : mask = LC_NUMERIC_MASK ;
break;
48 case LC_TIME : mask = LC_TIME_MASK ;
break;
50 return newlocale(mask, locale, LC_GLOBAL_LOCALE);
53 inline void free_locale(_In_opt_ locale_t locale) { freelocale(locale); }
74 using locale = std::unique_ptr<__crt_locale_pointers, free_locale_delete>;
75#elif defined(__APPLE__)
76 using locale = std::unique_ptr<struct _xlocale, free_locale_delete>;
78 using locale = std::unique_ptr<struct __locale_struct, free_locale_delete>;
84 const locale locale_C(create_locale(LC_ALL,
"C"));
90 typedef wchar_t utf16_t;
92 typedef char16_t utf16_t;
100 inline bool is_high_surrogate(_In_ utf16_t chr)
102 return 0xd800 < chr && chr < 0xdc00;
110 inline bool is_low_surrogate(_In_ utf16_t chr)
112 return 0xdc00 < chr && chr < 0xe000;
120 inline bool is_surrogate_pair(_In_reads_(2)
const utf16_t* str)
122 return is_high_surrogate(str[0]) && is_low_surrogate(str[1]);
130 inline char32_t surrogate_pair_to_ucs4(_In_reads_(2)
const utf16_t* str)
132 _Assume_(is_surrogate_pair(str));
134 ((
char32_t)(str[0] - 0xd800) << 10) +
135 (char32_t)(str[1] - 0xdc00) +
144 inline void ucs4_to_surrogate_pair(_Out_writes_(2) utf16_t* str, _In_
char32_t chr)
146 _Assume_(chr >= 0x10000);
148 str[0] = 0xd800 + (char32_t)((chr >> 10) & 0x3ff);
149 str[1] = 0xdc00 + (char32_t)(chr & 0x3ff);
157 inline bool iscombining(_In_
char32_t chr)
160 (0x0300 <= chr && chr < 0x0370) ||
161 (0x1dc0 <= chr && chr < 0x1e00) ||
162 (0x20d0 <= chr && chr < 0x2100) ||
163 (0xfe20 <= chr && chr < 0xfe30);
172 inline size_t islbreak(_In_ T chr)
174 return chr ==
'\n' || chr ==
'\r';
184 inline size_t islbreak(_In_reads_or_z_opt_(count)
const T* chr, _In_
size_t count)
186 _Assume_(chr || !count);
187 if (count >= 2 && ((chr[0] ==
'\r' && chr[1] ==
'\n') || (chr[0] ==
'\n' && chr[1] ==
'\r')))
189 if (count > 1 && (chr[0] ==
'\n' || chr[0] ==
'\r'))
200 inline size_t glyphlen(_In_reads_or_z_opt_(count)
const wchar_t* glyph, _In_
size_t count)
202 _Assume_(glyph || !count);
205 size_t i = count < 2 || !is_surrogate_pair(glyph) ? 1 : 2;
209 for (; i < count && iscombining(glyph[i]); ++i);
223 inline size_t strlen(_In_z_
const T* str)
227 for (i = 0; str[i]; ++i);
240 inline size_t strnlen(_In_reads_or_z_opt_(count)
const T* str, _In_
size_t count)
242 _Assume_(str || !count);
244 for (i = 0; i < count && str[i]; ++i);
248 constexpr auto npos{
static_cast<size_t>(-1) };
259 inline size_t strchr(_In_z_
const T* str, _In_ T chr)
262 for (
size_t i = 0; str[i]; ++i)
263 if (str[i] == chr)
return i;
277 inline size_t strnchr(
278 _In_reads_or_z_opt_(count)
const T* str,
282 _Assume_(str || !count);
283 for (
size_t i = 0; i < count && str[i]; ++i)
284 if (str[i] == chr)
return i;
298 inline size_t strrnchr(
299 _In_reads_or_z_opt_(count)
const T* str,
303 _Assume_(str || !count);
305 for (
size_t i = 0; i < count && str[i]; ++i)
306 if (str[i] == chr) z = i;
320 inline size_t strnichr(
321 _In_reads_or_z_opt_(count)
const T* str,
324 _In_
const std::locale& locale)
326 _Assume_(str || !count);
327 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
328 chr = ctype.tolower(chr);
329 for (
size_t i = 0; i < count && str[i]; ++i)
330 if (ctype.tolower(str[i]) == chr)
return i;
344 inline size_t strrnichr(
345 _In_reads_or_z_opt_(count)
const T* str,
348 _In_
const std::locale& locale)
350 _Assume_(str || !count);
351 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
352 chr = ctype.tolower(chr);
354 for (
size_t i = 0; i < count && str[i]; ++i)
355 if (ctype.tolower(str[i]) == chr) z = i;
367 template <
class T1,
class T2>
368 inline int strcmp(
const T1* str1,
const T2* str2)
370 _Assume_(str1 && str2);
372 for (
size_t i = 0; (a = str1[i]) | (b = str2[i]); ++i) {
373 if (a > b)
return +1;
374 if (a < b)
return -1;
389 template <
class T1,
class T2>
391 _In_reads_or_z_opt_(count1)
const T1* str1, _In_
size_t count1,
392 _In_reads_or_z_opt_(count2)
const T2* str2, _In_
size_t count2)
394 _Assume_(str1 || !count1);
395 _Assume_(str2 || !count2);
396 size_t i; T1 a; T2 b;
397 for (i = 0; i < count1 && i < count2 && ((a = str1[i]) | (b = str2[i])); ++i) {
398 if (a > b)
return +1;
399 if (a < b)
return -1;
401 if (i < count1 && str1[i])
return +1;
402 if (i < count2 && str2[i])
return -1;
415 template <
class T1,
class T2>
416 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)
418 _Assume_((str1 && str2) || !count);
419 size_t i; T1 a; T2 b;
420 for (i = 0; i < count && ((a = str1[i]) | (b = str2[i])); ++i) {
421 if (a > b)
return +1;
422 if (a < b)
return -1;
424 if (i < count && str1[i])
return +1;
425 if (i < count && str2[i])
return -1;
441 _In_reads_or_z_opt_(count1)
const T* str1, _In_
size_t count1,
442 _In_reads_or_z_opt_(count2)
const T* str2, _In_
size_t count2,
443 _In_
const std::locale& locale)
445 _Assume_(str1 || !count1);
446 _Assume_(str2 || !count2);
447 auto& collate = std::use_facet<std::collate<T>>(locale);
448 return collate.compare(str1, str1 + count1, str2, str2 + count2);
459 template <
class T1,
class T2>
460 inline int stricmp(_In_z_
const T1* str1, _In_z_
const T2* str2, _In_
const std::locale& locale)
464 size_t i; T1 a; T2 b;
465 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
466 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
467 for (i = 0; (a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i])); i++) {
468 if (a > b)
return +1;
469 if (a < b)
return -1;
471 if (str1[i])
return +1;
472 if (str2[i])
return -1;
485 template <
class T1,
class T2>
486 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)
488 _Assume_(str1 || !count);
489 _Assume_(str2 || !count);
490 size_t i; T1 a; T2 b;
491 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
492 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
493 for (i = 0; i < count && ((a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i]))); i++) {
494 if (a > b)
return +1;
495 if (a < b)
return -1;
497 if (i < count && str1[i])
return +1;
498 if (i < count && str2[i])
return -1;
512 template <
class T1,
class T2>
514 _In_reads_or_z_opt_(count1)
const T1* str1, _In_
size_t count1,
515 _In_reads_or_z_opt_(count2)
const T2* str2, _In_
size_t count2,
516 _In_
const std::locale& locale)
518 _Assume_(str1 || !count1);
519 _Assume_(str2 || !count2);
520 size_t i; T1 a; T2 b;
521 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
522 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
523 for (i = 0; i < count1 && i < count2 && ((a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i]))); i++) {
524 if (a > b)
return +1;
525 if (a < b)
return -1;
527 if (i < count1 && str1[i])
return +1;
528 if (i < count2 && str2[i])
return -1;
540 template <
class T1,
class T2>
541 inline size_t strstr(
542 _In_z_
const T1* str,
543 _In_z_
const T2* sample)
547 for (
size_t offset = 0;; ++offset) {
548 for (
size_t i = offset, j = 0;; ++i, ++j) {
553 if (str[i] != sample[j])
568 template <
class T1,
class T2>
569 inline size_t strnstr(
570 _In_reads_or_z_opt_(count)
const T1* str,
572 _In_z_
const T2* sample)
574 _Assume_(str || !count);
576 for (
size_t offset = 0;; ++offset) {
577 for (
size_t i = offset, j = 0;; ++i, ++j) {
580 if (i >= count || !str[i])
582 if (str[i] != sample[j])
596 template <
class T1,
class T2>
597 inline size_t stristr(
598 _In_z_
const T1* str,
599 _In_z_
const T2* sample,
600 _In_
const std::locale& locale)
604 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
605 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
606 for (
size_t offset = 0;; ++offset) {
607 for (
size_t i = offset, j = 0;; ++i, ++j) {
612 if (ctype1.tolower(str[i]) != ctype2.tolower(sample[j]))
627 template <
class T1,
class T2>
628 inline size_t strnistr(
629 _In_reads_or_z_opt_(count)
const T1* str,
631 _In_z_
const T2* sample,
632 _In_
const std::locale& locale)
634 _Assume_(str || !count);
636 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
637 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
638 for (
size_t offset = 0;; ++offset) {
639 for (
size_t i = offset, j = 0;; ++i, ++j) {
642 if (i >= count || !str[i])
644 if (ctype1.tolower(str[i]) != ctype2.tolower(sample[j]))
658 template <
class T1,
class T2>
659 inline size_t strcpy(
660 _Out_writes_z_(_String_length_(src) + 1) T1* dst,
661 _In_z_
const T2* src)
663 _Assume_(dst && src);
664 for (
size_t i = 0; ; ++i) {
665 if ((dst[i] = src[i]) == 0)
679 template <
class T1,
class T2>
680 inline size_t strncpy(
681 _Out_writes_(count) _Post_maybez_ T1* dst,
682 _In_reads_or_z_opt_(count)
const T2* src, _In_
size_t count)
684 _Assume_(dst && src || !count);
685 for (
size_t i = 0; ; ++i) {
688 if ((dst[i] = src[i]) == 0)
703 template <
class T1,
class T2>
704 inline size_t strncpy(
705 _Out_writes_(count_dst) _Post_maybez_ T1* dst, _In_
size_t count_dst,
706 _In_reads_or_z_opt_(count_src)
const T2* src, _In_
size_t count_src)
708 _Assume_(dst || !count_dst);
709 _Assume_(src || !count_src);
710 for (
size_t i = 0; ; ++i)
714 if (i >= count_src) {
718 if ((dst[i] = src[i]) == 0)
731 template <
class T1,
class T2>
732 inline size_t strcat(
733 _In_z_ _Out_writes_z_(_String_length_(dst) + _String_length_(src) + 1) T1* dst,
734 _In_z_
const T2* src)
736 _Assume_(dst && src);
737 for (
size_t i = 0, j = stdex::strlen<T1>(dst); ; ++i, ++j) {
738 if ((dst[j] = src[i]) == 0)
752 template <
class T1,
class T2>
753 inline size_t strncat(
755 _In_reads_or_z_opt_(count)
const T2* src, _In_
size_t count)
757 _Assume_(dst && src || !count);
758 for (
size_t i = 0, j = stdex::strlen<T1>(dst); ; ++i, ++j) {
761 if ((dst[j] = src[i]) == 0)
776 template <
class T1,
class T2>
777 inline size_t strncat(
778 _Out_writes_(count_dst) _Post_maybez_ T1* dst, _In_
size_t count_dst,
779 _In_reads_or_z_opt_(count_src)
const T2* src, _In_
size_t count_src)
781 _Assume_(dst || !count_dst);
782 _Assume_(src || !count_src);
783 for (
size_t i = 0, j = stdex::strnlen<T1>(dst, count_dst); ; ++i, ++j)
787 if (i >= count_src) {
791 if ((dst[j] = src[i]) == 0)
807 inline _Check_return_ _Ret_maybenull_z_ T* strdup(_In_opt_z_
const T* str)
811 size_t count = strlen(str) + 1;
812 T* dst =
new T[count];
813 strncpy(dst, count, str, SIZE_MAX);
829 inline _Ret_z_ T* strndup(
830 _In_reads_or_z_opt_(count)
const T* str,
833 T* dst =
new T[count];
834 strncpy(dst, count, str, SIZE_MAX);
848 inline size_t crlf2nl(_Out_writes_z_(strlen(src)) T* dst, _In_z_
const T* src)
853 for (i = j = 0; src[j];) {
854 if (src[j] !=
'\r' || src[j + 1] !=
'\n')
871 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
872 inline void crlf2nl(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &dst, _In_z_
const _Elem* src)
875 _Assume_(src != dst.c_str());
877 dst.reserve(strlen(src));
878 for (
size_t j = 0; src[j];) {
879 if (src[j] !=
'\r' || src[j + 1] !=
'\n')
893 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
894 inline void crlf2nl(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& str)
897 for (i = j = 0, n = str.size(); j < n;) {
898 if (str[j] !=
'\r' || str[j + 1] !=
'\n')
909 template <
class T,
class T_bin>
910 inline T_bin strtoint(
911 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
912 _Out_opt_
size_t* end,
914 _Out_ uint8_t& flags)
916 _Assume_(str || !count);
917 _Assume_(radix == 0 || 2 <= radix && radix <= 36);
920 T_bin value = 0, digit,
922 max_ui_pre1, max_ui_pre2;
928 if (i >= count || !str[i])
goto error;
929 if (!isspace(str[i]))
break;
936 if (i >= count || !str[i])
goto error;
938 else if (str[i] ==
'-') {
941 if (i >= count || !str[i])
goto error;
946 if (str[i] ==
'0' && i + 1 < count && (str[i + 1] ==
'x' || str[i + 1] ==
'X')) {
948 if (i >= count || !str[i])
goto error;
955 if (i >= count || !str[i])
goto error;
956 if (str[i] ==
'x' || str[i] ==
'X') {
959 if (i >= count || !str[i])
goto error;
969 max_ui_pre1 = max_ui / (T_bin)radix;
970 max_ui_pre2 = max_ui % (T_bin)radix;
972 if (
'0' <= str[i] && str[i] <=
'9')
973 digit = (T_bin)str[i] -
'0';
974 else if (
'A' <= str[i] && str[i] <=
'Z')
975 digit = (T_bin)str[i] -
'A' +
'\x0a';
976 else if (
'a' <= str[i] && str[i] <=
'z')
977 digit = (T_bin)str[i] -
'a' +
'\x0a';
980 if (digit >= (T_bin)radix)
983 if (value < max_ui_pre1 ||
984 (value == max_ui_pre1 && digit <= max_ui_pre2))
985 value = value * (T_bin)radix + digit;
992 if (i >= count || !str[i])
1012 template <
class T,
class T_bin>
1014 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1015 _Out_opt_
size_t* end,
1021 switch (
sizeof(T_bin)) {
1023 value = (T_bin)strtoint<T, uint8_t>(str, count, end, radix, flags);
1024 if ((flags & 0x01) && (value & 0x80)) {
1028 return (flags & 0x02) ?
1029 (flags & 0x01) ? (T_bin)0x80 : (T_bin)0x7f :
1030 (flags & 0x01) ? -value : value;
1033 value = (T_bin)strtoint<T, uint16_t>(str, count, end, radix, flags);
1034 if ((flags & 0x01) && (value & 0x8000)) {
1038 return (flags & 0x02) ?
1039 (flags & 0x01) ? (T_bin)0x8000 : (T_bin)0x7fff :
1040 (flags & 0x01) ? -value : value;
1043 value = (T_bin)strtoint<T, uint32_t>(str, count, end, radix, flags);
1044 if ((flags & 0x01) && (value & 0x80000000)) {
1048 return (flags & 0x02) ?
1049 (flags & 0x01) ? (T_bin)0x80000000 : (T_bin)0x7fffffff :
1050 (flags & 0x01) ? -value : value;
1053 value = (T_bin)strtoint<T, uint64_t>(str, count, end, radix, flags);
1054 if ((flags & 0x01) && (value & 0x8000000000000000)) {
1058 return (flags & 0x02) ?
1059 (flags & 0x01) ? (T_bin)0x8000000000000000 : (T_bin)0x7fffffffffffffff :
1060 (flags & 0x01) ? -value : value;
1063 throw std::invalid_argument(
"Unsupported bit length");
1077 template <
class T,
class T_bin>
1078 inline T_bin strtouint(
1079 _In_reads_or_z_opt_(count)
const T* str,
1081 _Out_opt_
size_t* end,
1087 switch (
sizeof(T_bin)) {
1088 case 1: value = (T_bin)strtoint<T, uint8_t>(str, count, end, radix, flags);
break;
1089 case 2: value = (T_bin)strtoint<T, uint16_t>(str, count, end, radix, flags);
break;
1090 case 4: value = (T_bin)strtoint<T, uint32_t>(str, count, end, radix, flags);
break;
1091 case 8: value = (T_bin)strtoint<T, uint64_t>(str, count, end, radix, flags);
break;
1092 default:
throw std::invalid_argument(
"Unsupported bit length");
1095 return (flags & 0x02) ?
1096 (flags & 0x01) ? (T_bin)0 : (T_bin)-1 :
1097 (flags & 0x01) ? ~value : value;
1111 inline int32_t strto32(
1112 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1113 _Out_opt_
size_t* end,
1116 return strtoint<T, int32_t>(str, count, end, radix);
1130 inline int64_t strto64(
1131 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1132 _Out_opt_
size_t* end,
1135 return strtoint<T, int64_t>(str, count, end, radix);
1150 inline intptr_t strtoi(
1151 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1152 _Out_opt_
size_t* end,
1155#if defined(_WIN64) || defined(__LP64__)
1156 return (intptr_t)strto64(str, count, end, radix);
1158 return (intptr_t)strto32(str, count, end, radix);
1173 inline uint32_t strtou32(
1174 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1175 _Out_opt_
size_t* end,
1178 return strtouint<T, uint32_t>(str, count, end, radix);
1192 inline uint64_t strtou64(
1193 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1194 _Out_opt_
size_t* end,
1197 return strtouint<T, uint64_t>(str, count, end, radix);
1212 inline size_t strtoui(
1213 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1214 _Out_opt_
size_t* end,
1217#if defined(_WIN64) || defined(__LP64__)
1218 return (
size_t)strtou64(str, count, end, radix);
1220 return (
size_t)strtou32(str, count, end, radix);
1225 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)
1230#pragma warning(suppress: 4996)
1231 r = _vsnprintf_l(str, capacity, format, locale, arg);
1233 r = ::vsnprintf(str, capacity, format, arg);
1235 if (r == -1 && strnlen(str, capacity) == capacity) {
1237 capacity += std::max<size_t>(capacity / 8, 0x80);
1238 if (capacity > INT_MAX)
1239 throw std::invalid_argument(
"string too big");
1240 return (
int)capacity;
1245 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)
1250#pragma warning(suppress: 4996)
1251 r = _vsnwprintf_l(str, capacity, format, locale, arg);
1253 r = vswprintf(str, capacity, format, arg);
1255 if (r == -1 && strnlen(str, capacity) == capacity) {
1257 capacity += std::max<size_t>(capacity / 8, 0x80);
1258 if (capacity > INT_MAX)
1259 throw std::invalid_argument(
"string too big");
1260 return (
int)capacity;
1274 template<
class _Elem,
class _Traits,
class _Ax>
1275 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)
1277 _Elem buf[1024/
sizeof(_Elem)];
1280 int count = vsnprintf(buf, _countof(buf) - 1, format, locale, arg);
1283 str.append(buf, count);
1285 for (
size_t capacity = 2*1024/
sizeof(_Elem);; capacity *= 2) {
1287 auto buf_dyn = std::make_unique<_Elem[]>(capacity);
1288 count = vsnprintf(buf_dyn.get(), capacity - 1, format, locale, arg);
1290 str.append(buf_dyn.get(), count);
1304 template<
class _Elem,
class _Traits,
class _Ax>
1305 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, ...)
1308 va_start(arg, locale);
1309 vappendf(str, format, locale, arg);
1321 template<
class _Elem,
class _Traits,
class _Ax>
1322 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)
1325 vappendf(str, format, locale, arg);
1335 template<
class _Elem,
class _Traits,
class _Ax>
1336 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, ...)
1339 va_start(arg, locale);
1340 vsprintf(str, format, locale, arg);
1353 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1354 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)
1356 std::basic_string<_Elem, _Traits, _Ax> str;
1357 vappendf(str, format, locale, arg);
1369 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1370 inline std::basic_string<_Elem, _Traits, _Ax> sprintf(_In_z_ _Printf_format_string_params_(2)
const _Elem *format, _In_opt_ locale_t locale, ...)
1373 va_start(arg, locale);
1374 auto str = vsprintf(format, locale, arg);
1380 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)
1383 return _strftime_l(str, capacity, format, time, locale);
1385 return strftime_l(str, capacity, format, time, locale);
1389 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)
1392 return _wcsftime_l(str, capacity, format, time, locale);
1394 return wcsftime_l(str, capacity, format, time, locale);
1407 template<
class _Elem,
class _Traits,
class _Ax>
1408 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)
1410 _Elem buf[1024/
sizeof(_Elem)];
1413 size_t count = strftime(buf, _countof(buf), format, time, locale);
1416 str.append(buf, count);
1418 for (
size_t capacity = 2*1024/
sizeof(_Elem);; capacity *= 2) {
1420 auto buf_dyn = std::make_unique<_Elem[]>(capacity);
1421 count = strftime(buf_dyn.get(), capacity, format, time, locale);
1423 str.append(buf_dyn.get(), count);
1438 template<
class _Elem,
class _Traits,
class _Ax>
1439 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)
1442 strcatftime(str, format, time, locale);
1455 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1456 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)
1458 std::basic_string<_Elem, _Traits, _Ax> str;
1459 strcatftime(str, format, time, locale);
1471 inline void strlwr(_Inout_z_ T* str, _In_
const std::locale& locale)
1474 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
1475 for (
size_t i = 0; str[i]; ++i)
1476 str[i] = ctype.tolower(str[i]);
1488 inline void strlwr(_Inout_updates_z_(count) T* str, _In_
size_t count, _In_
const std::locale& locale)
1490 _Assume_(str || !count);
1491 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
1492 for (
size_t i = 0; i < count && str[i]; ++i)
1493 str[i] = ctype.tolower(str[i]);
1504 inline void strupr(_Inout_z_ T* str, _In_
const std::locale& locale)
1507 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
1508 for (
size_t i = 0; str[i]; ++i)
1509 str[i] = ctype.toupper(str[i]);
1521 inline void strupr(_Inout_updates_z_(count) T* str, _In_
size_t count, _In_
const std::locale& locale)
1523 _Assume_(str || !count);
1524 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
1525 for (
size_t i = 0; i < count && str[i]; ++i)
1526 str[i] = ctype.toupper(str[i]);
1536 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1537 inline void strupr(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& str, _In_
const std::locale& locale)
1539 const auto& ctype = std::use_facet<std::ctype<_Elem>>(locale);
1540 for (
size_t i = 0; i < str.size(); ++i)
1541 str[i] = ctype.toupper(str[i]);
1553 inline size_t ltrim(
1554 _Inout_z_count_(count) T* str, _In_
size_t count,
1555 _In_
const std::locale& locale)
1557 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
1558 for (
size_t i = 0;; ++i) {
1560 if (count) str[0] = 0;
1567 if (!ctype.is(ctype.space, str[i])) {
1569 return strnlen(str, count);
1570 size_t n = count != SIZE_MAX ? strncpy(str, str + i, count - i) : strcpy(str, str + i);
1582 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1583 inline void ltrim(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &s, _In_
const std::locale& locale)
1585 const auto& ctype = std::use_facet<std::ctype<_Elem>>(locale);
1591 [&](_Elem ch) { return !ctype.is(ctype.space, ch); }));
1603 inline size_t rtrim(
1604 _Inout_z_count_(count) T* str, _In_
size_t count,
1605 _In_
const std::locale& locale)
1607 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
1608 for (
size_t i = 0, j = 0;;) {
1609 if (i >= count || !str[i]) {
1610 if (j < count) str[j] = 0;
1613 if (!ctype.is(ctype.space, str[i]))
1625 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1626 static inline void rtrim(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &s, _In_
const std::locale& locale)
1628 const auto& ctype = std::use_facet<std::ctype<_Elem>>(locale);
1633 [&](_Elem ch) { return !ctype.is(ctype.space, ch); }).base(),
1647 _Inout_z_count_(count) T* str, _In_
size_t count,
1648 _In_
const std::locale& locale)
1650 return ltrim(str, rtrim(str, count, locale), locale);
1658 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1659 static inline void trim(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &s, _In_
const std::locale& locale)
1661 const auto& ctype = std::use_facet<std::ctype<_Elem>>(locale);
1667 [&](_Elem ch) { return !ctype.is(ctype.space, ch); }));
1672 [&](_Elem ch) { return !ctype.is(ctype.space, ch); }).base(),
Deleter for unique_ptr using free_locale.
Definition string.hpp:60
void operator()(locale_t locale) const
Delete a pointer.
Definition string.hpp:64