19#elif defined(__APPLE__)
33 using locale_t = _locale_t;
35 inline locale_t create_locale(_In_
int category, _In_z_
const char* locale) {
return _create_locale(category, locale); }
36 inline locale_t create_locale(_In_
int category, _In_z_
const wchar_t* locale) {
return _wcreate_locale(category, locale); }
37 inline void free_locale(_In_opt_ locale_t locale) { _free_locale(locale); }
39 using locale_t = ::locale_t;
41 inline locale_t create_locale(_In_
int category, _In_z_
const char* locale)
45 case LC_ALL : mask = LC_ALL_MASK ;
break;
46 case LC_COLLATE : mask = LC_COLLATE_MASK ;
break;
47 case LC_CTYPE : mask = LC_CTYPE_MASK ;
break;
48 case LC_MESSAGES: mask = LC_MESSAGES_MASK;
break;
49 case LC_MONETARY: mask = LC_MONETARY_MASK;
break;
50 case LC_NUMERIC : mask = LC_NUMERIC_MASK ;
break;
51 case LC_TIME : mask = LC_TIME_MASK ;
break;
53 return newlocale(mask, locale, LC_GLOBAL_LOCALE);
56 inline void free_locale(_In_opt_ locale_t locale) { freelocale(locale); }
77 using locale = std::unique_ptr<__crt_locale_pointers, free_locale_delete>;
78#elif defined(__APPLE__)
79 using locale = std::unique_ptr<struct _xlocale, free_locale_delete>;
81 using locale = std::unique_ptr<struct __locale_struct, free_locale_delete>;
87 const locale locale_C(create_locale(LC_ALL,
"C"));
93 typedef wchar_t utf16_t;
95 typedef char16_t utf16_t;
103 inline bool is_high_surrogate(_In_ utf16_t chr)
105 return 0xd800 < chr && chr < 0xdc00;
113 inline bool is_low_surrogate(_In_ utf16_t chr)
115 return 0xdc00 < chr && chr < 0xe000;
123 inline bool is_surrogate_pair(_In_reads_(2)
const utf16_t* str)
125 return is_high_surrogate(str[0]) && is_low_surrogate(str[1]);
133 inline char32_t surrogate_pair_to_ucs4(_In_reads_(2)
const utf16_t* str)
135 _Assume_(is_surrogate_pair(str));
137 ((
char32_t)(str[0] - 0xd800) << 10) +
138 (char32_t)(str[1] - 0xdc00) +
147 inline void ucs4_to_surrogate_pair(_Out_writes_(2) utf16_t* str, _In_
char32_t chr)
149 _Assume_(chr >= 0x10000);
151 str[0] = 0xd800 + (char32_t)((chr >> 10) & 0x3ff);
152 str[1] = 0xdc00 + (char32_t)(chr & 0x3ff);
160 inline bool iscombining(_In_
char32_t chr)
163 (0x0300 <= chr && chr < 0x0370) ||
164 (0x1dc0 <= chr && chr < 0x1e00) ||
165 (0x20d0 <= chr && chr < 0x2100) ||
166 (0xfe20 <= chr && chr < 0xfe30);
175 inline size_t islbreak(_In_ T chr)
177 return chr ==
'\n' || chr ==
'\r';
187 inline size_t islbreak(_In_reads_or_z_opt_(count)
const T* chr, _In_
size_t count)
189 _Assume_(chr || !count);
190 if (count >= 2 && ((chr[0] ==
'\r' && chr[1] ==
'\n') || (chr[0] ==
'\n' && chr[1] ==
'\r')))
192 if (count > 1 && (chr[0] ==
'\n' || chr[0] ==
'\r'))
203 inline size_t glyphlen(_In_reads_or_z_opt_(count)
const wchar_t* glyph, _In_
size_t count)
205 _Assume_(glyph || !count);
208 size_t i = count < 2 || !is_surrogate_pair(glyph) ? 1 : 2;
212 for (; i < count && iscombining(glyph[i]); ++i);
226 inline size_t strlen(_In_z_
const T* str)
230 for (i = 0; str[i]; ++i);
243 inline size_t strnlen(_In_reads_or_z_opt_(count)
const T* str, _In_
size_t count)
245 _Assume_(str || !count);
247 for (i = 0; i < count && str[i]; ++i);
251 constexpr auto npos{
static_cast<size_t>(-1) };
262 inline size_t strchr(_In_z_
const T* str, _In_ T chr)
265 for (
size_t i = 0; str[i]; ++i)
266 if (str[i] == chr)
return i;
280 inline size_t strnchr(
281 _In_reads_or_z_opt_(count)
const T* str,
285 _Assume_(str || !count);
286 for (
size_t i = 0; i < count && str[i]; ++i)
287 if (str[i] == chr)
return i;
301 inline size_t strrnchr(
302 _In_reads_or_z_opt_(count)
const T* str,
306 _Assume_(str || !count);
308 for (
size_t i = 0; i < count && str[i]; ++i)
309 if (str[i] == chr) z = i;
323 inline size_t strnichr(
324 _In_reads_or_z_opt_(count)
const T* str,
327 _In_
const std::locale& locale)
329 _Assume_(str || !count);
330 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
331 chr = ctype.tolower(chr);
332 for (
size_t i = 0; i < count && str[i]; ++i)
333 if (ctype.tolower(str[i]) == chr)
return i;
347 inline size_t strrnichr(
348 _In_reads_or_z_opt_(count)
const T* str,
351 _In_
const std::locale& locale)
353 _Assume_(str || !count);
354 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
355 chr = ctype.tolower(chr);
357 for (
size_t i = 0; i < count && str[i]; ++i)
358 if (ctype.tolower(str[i]) == chr) z = i;
370 template <
class T1,
class T2>
371 inline int strcmp(
const T1* str1,
const T2* str2)
373 _Assume_(str1 && str2);
375 for (
size_t i = 0; (a = str1[i]) | (b = str2[i]); ++i) {
376 if (a > b)
return +1;
377 if (a < b)
return -1;
392 template <
class T1,
class T2>
394 _In_reads_or_z_opt_(count1)
const T1* str1, _In_
size_t count1,
395 _In_reads_or_z_opt_(count2)
const T2* str2, _In_
size_t count2)
397 _Assume_(str1 || !count1);
398 _Assume_(str2 || !count2);
399 size_t i; T1 a; T2 b;
400 for (i = 0; i < count1 && i < count2 && ((a = str1[i]) | (b = str2[i])); ++i) {
401 if (a > b)
return +1;
402 if (a < b)
return -1;
404 if (i < count1 && str1[i])
return +1;
405 if (i < count2 && str2[i])
return -1;
418 template <
class T1,
class T2>
419 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)
421 _Assume_((str1 && str2) || !count);
422 size_t i; T1 a; T2 b;
423 for (i = 0; i < count && ((a = str1[i]) | (b = str2[i])); ++i) {
424 if (a > b)
return +1;
425 if (a < b)
return -1;
427 if (i < count && str1[i])
return +1;
428 if (i < count && str2[i])
return -1;
444 _In_reads_or_z_opt_(count1)
const T* str1, _In_
size_t count1,
445 _In_reads_or_z_opt_(count2)
const T* str2, _In_
size_t count2,
446 _In_
const std::locale& locale)
448 _Assume_(str1 || !count1);
449 _Assume_(str2 || !count2);
450 auto& collate = std::use_facet<std::collate<T>>(locale);
451 return collate.compare(str1, str1 + count1, str2, str2 + count2);
462 template <
class T1,
class T2>
463 inline int stricmp(_In_z_
const T1* str1, _In_z_
const T2* str2, _In_
const std::locale& locale)
467 size_t i; T1 a; T2 b;
468 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
469 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
470 for (i = 0; (a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i])); i++) {
471 if (a > b)
return +1;
472 if (a < b)
return -1;
474 if (str1[i])
return +1;
475 if (str2[i])
return -1;
488 template <
class T1,
class T2>
489 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)
491 _Assume_(str1 || !count);
492 _Assume_(str2 || !count);
493 size_t i; T1 a; T2 b;
494 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
495 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
496 for (i = 0; i < count && ((a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i]))); i++) {
497 if (a > b)
return +1;
498 if (a < b)
return -1;
500 if (i < count && str1[i])
return +1;
501 if (i < count && str2[i])
return -1;
515 template <
class T1,
class T2>
517 _In_reads_or_z_opt_(count1)
const T1* str1, _In_
size_t count1,
518 _In_reads_or_z_opt_(count2)
const T2* str2, _In_
size_t count2,
519 _In_
const std::locale& locale)
521 _Assume_(str1 || !count1);
522 _Assume_(str2 || !count2);
523 size_t i; T1 a; T2 b;
524 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
525 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
526 for (i = 0; i < count1 && i < count2 && ((a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i]))); i++) {
527 if (a > b)
return +1;
528 if (a < b)
return -1;
530 if (i < count1 && str1[i])
return +1;
531 if (i < count2 && str2[i])
return -1;
543 template <
class T1,
class T2>
544 inline size_t strstr(
545 _In_z_
const T1* str,
546 _In_z_
const T2* sample)
550 for (
size_t offset = 0;; ++offset) {
551 for (
size_t i = offset, j = 0;; ++i, ++j) {
556 if (str[i] != sample[j])
571 template <
class T1,
class T2>
572 inline size_t strnstr(
573 _In_reads_or_z_opt_(count)
const T1* str,
575 _In_z_
const T2* sample)
577 _Assume_(str || !count);
579 for (
size_t offset = 0;; ++offset) {
580 for (
size_t i = offset, j = 0;; ++i, ++j) {
583 if (i >= count || !str[i])
585 if (str[i] != sample[j])
599 template <
class T1,
class T2>
600 inline size_t stristr(
601 _In_z_
const T1* str,
602 _In_z_
const T2* sample,
603 _In_
const std::locale& locale)
607 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
608 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
609 for (
size_t offset = 0;; ++offset) {
610 for (
size_t i = offset, j = 0;; ++i, ++j) {
615 if (ctype1.tolower(str[i]) != ctype2.tolower(sample[j]))
630 template <
class T1,
class T2>
631 inline size_t strnistr(
632 _In_reads_or_z_opt_(count)
const T1* str,
634 _In_z_
const T2* sample,
635 _In_
const std::locale& locale)
637 _Assume_(str || !count);
639 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
640 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
641 for (
size_t offset = 0;; ++offset) {
642 for (
size_t i = offset, j = 0;; ++i, ++j) {
645 if (i >= count || !str[i])
647 if (ctype1.tolower(str[i]) != ctype2.tolower(sample[j]))
661 template <
class T1,
class T2>
662 inline size_t strcpy(
663 _Out_writes_z_(_String_length_(src) + 1) T1* dst,
664 _In_z_
const T2* src)
666 _Assume_(dst && src);
667 for (
size_t i = 0; ; ++i) {
668 if ((dst[i] = src[i]) == 0)
682 template <
class T1,
class T2>
683 inline size_t strncpy(
684 _Out_writes_(count) _Post_maybez_ T1* dst,
685 _In_reads_or_z_opt_(count)
const T2* src, _In_
size_t count)
687 _Assume_(dst && src || !count);
688 for (
size_t i = 0; ; ++i) {
691 if ((dst[i] = src[i]) == 0)
706 template <
class T1,
class T2>
707 inline size_t strncpy(
708 _Out_writes_(count_dst) _Post_maybez_ T1* dst, _In_
size_t count_dst,
709 _In_reads_or_z_opt_(count_src)
const T2* src, _In_
size_t count_src)
711 _Assume_(dst || !count_dst);
712 _Assume_(src || !count_src);
713 for (
size_t i = 0; ; ++i)
717 if (i >= count_src) {
721 if ((dst[i] = src[i]) == 0)
734 template <
class T1,
class T2>
735 inline size_t strcat(
736 _In_z_ _Out_writes_z_(_String_length_(dst) + _String_length_(src) + 1) T1* dst,
737 _In_z_
const T2* src)
739 _Assume_(dst && src);
740 for (
size_t i = 0, j = stdex::strlen<T1>(dst); ; ++i, ++j) {
741 if ((dst[j] = src[i]) == 0)
755 template <
class T1,
class T2>
756 inline size_t strncat(
758 _In_reads_or_z_opt_(count)
const T2* src, _In_
size_t count)
760 _Assume_(dst && src || !count);
761 for (
size_t i = 0, j = stdex::strlen<T1>(dst); ; ++i, ++j) {
764 if ((dst[j] = src[i]) == 0)
779 template <
class T1,
class T2>
780 inline size_t strncat(
781 _Out_writes_(count_dst) _Post_maybez_ T1* dst, _In_
size_t count_dst,
782 _In_reads_or_z_opt_(count_src)
const T2* src, _In_
size_t count_src)
784 _Assume_(dst || !count_dst);
785 _Assume_(src || !count_src);
786 for (
size_t i = 0, j = stdex::strnlen<T1>(dst, count_dst); ; ++i, ++j)
790 if (i >= count_src) {
794 if ((dst[j] = src[i]) == 0)
810 inline _Check_return_ _Ret_maybenull_z_ T* strdup(_In_opt_z_
const T* str)
814 size_t count = strlen(str) + 1;
815 T* dst =
new T[count];
816 strncpy(dst, count, str, SIZE_MAX);
832 inline _Ret_z_ T* strndup(
833 _In_reads_or_z_opt_(count)
const T* str,
836 T* dst =
new T[count];
837 strncpy(dst, count, str, SIZE_MAX);
851 inline size_t crlf2nl(_Out_writes_z_(strlen(src)) T* dst, _In_z_
const T* src)
856 for (i = j = 0; src[j];) {
857 if (src[j] !=
'\r' || src[j + 1] !=
'\n')
874 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
875 inline void crlf2nl(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &dst, _In_z_
const _Elem* src)
878 _Assume_(src != dst.c_str());
880 dst.reserve(strlen(src));
881 for (
size_t j = 0; src[j];) {
882 if (src[j] !=
'\r' || src[j + 1] !=
'\n')
896 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
897 inline void crlf2nl(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& str)
900 for (i = j = 0, n = str.size(); j < n;) {
901 if (str[j] !=
'\r' || str[j + 1] !=
'\n')
912 template <
class T,
class T_bin>
913 inline T_bin strtoint(
914 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
915 _Out_opt_
size_t* end,
917 _Out_ uint8_t& flags)
919 _Assume_(str || !count);
920 _Assume_(radix == 0 || 2 <= radix && radix <= 36);
923 T_bin value = 0, digit,
925 max_ui_pre1, max_ui_pre2;
931 if (i >= count || !str[i])
goto error;
932 if (!isspace(str[i]))
break;
939 if (i >= count || !str[i])
goto error;
941 else if (str[i] ==
'-') {
944 if (i >= count || !str[i])
goto error;
949 if (str[i] ==
'0' && i + 1 < count && (str[i + 1] ==
'x' || str[i + 1] ==
'X')) {
951 if (i >= count || !str[i])
goto error;
958 if (i >= count || !str[i])
goto error;
959 if (str[i] ==
'x' || str[i] ==
'X') {
962 if (i >= count || !str[i])
goto error;
972 max_ui_pre1 = max_ui / (T_bin)radix;
973 max_ui_pre2 = max_ui % (T_bin)radix;
975 if (
'0' <= str[i] && str[i] <=
'9')
976 digit = (T_bin)str[i] -
'0';
977 else if (
'A' <= str[i] && str[i] <=
'Z')
978 digit = (T_bin)str[i] -
'A' +
'\x0a';
979 else if (
'a' <= str[i] && str[i] <=
'z')
980 digit = (T_bin)str[i] -
'a' +
'\x0a';
983 if (digit >= (T_bin)radix)
986 if (value < max_ui_pre1 ||
987 (value == max_ui_pre1 && digit <= max_ui_pre2))
988 value = value * (T_bin)radix + digit;
995 if (i >= count || !str[i])
1015 template <
class T,
class T_bin>
1017 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1018 _Out_opt_
size_t* end,
1024 switch (
sizeof(T_bin)) {
1026 value = (T_bin)strtoint<T, uint8_t>(str, count, end, radix, flags);
1027 if ((flags & 0x01) && (value & 0x80)) {
1031 return (flags & 0x02) ?
1032 (flags & 0x01) ? (T_bin)0x80 : (T_bin)0x7f :
1033 (flags & 0x01) ? -value : value;
1036 value = (T_bin)strtoint<T, uint16_t>(str, count, end, radix, flags);
1037 if ((flags & 0x01) && (value & 0x8000)) {
1041 return (flags & 0x02) ?
1042 (flags & 0x01) ? (T_bin)0x8000 : (T_bin)0x7fff :
1043 (flags & 0x01) ? -value : value;
1046 value = (T_bin)strtoint<T, uint32_t>(str, count, end, radix, flags);
1047 if ((flags & 0x01) && (value & 0x80000000)) {
1051 return (flags & 0x02) ?
1052 (flags & 0x01) ? (T_bin)0x80000000 : (T_bin)0x7fffffff :
1053 (flags & 0x01) ? -value : value;
1056 value = (T_bin)strtoint<T, uint64_t>(str, count, end, radix, flags);
1057 if ((flags & 0x01) && (value & 0x8000000000000000)) {
1061 return (flags & 0x02) ?
1062 (flags & 0x01) ? (T_bin)0x8000000000000000 : (T_bin)0x7fffffffffffffff :
1063 (flags & 0x01) ? -value : value;
1066 throw std::invalid_argument(
"Unsupported bit length");
1080 template <
class T,
class T_bin>
1081 inline T_bin strtouint(
1082 _In_reads_or_z_opt_(count)
const T* str,
1084 _Out_opt_
size_t* end,
1090 switch (
sizeof(T_bin)) {
1091 case 1: value = (T_bin)strtoint<T, uint8_t>(str, count, end, radix, flags);
break;
1092 case 2: value = (T_bin)strtoint<T, uint16_t>(str, count, end, radix, flags);
break;
1093 case 4: value = (T_bin)strtoint<T, uint32_t>(str, count, end, radix, flags);
break;
1094 case 8: value = (T_bin)strtoint<T, uint64_t>(str, count, end, radix, flags);
break;
1095 default:
throw std::invalid_argument(
"Unsupported bit length");
1098 return (flags & 0x02) ?
1099 (flags & 0x01) ? (T_bin)0 : (T_bin)-1 :
1100 (flags & 0x01) ? ~value : value;
1114 inline int32_t strto32(
1115 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1116 _Out_opt_
size_t* end,
1119 return strtoint<T, int32_t>(str, count, end, radix);
1133 inline int64_t strto64(
1134 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1135 _Out_opt_
size_t* end,
1138 return strtoint<T, int64_t>(str, count, end, radix);
1153 inline intptr_t strtoi(
1154 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1155 _Out_opt_
size_t* end,
1158#if defined(_WIN64) || defined(__LP64__)
1159 return (intptr_t)strto64(str, count, end, radix);
1161 return (intptr_t)strto32(str, count, end, radix);
1176 inline uint32_t strtou32(
1177 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1178 _Out_opt_
size_t* end,
1181 return strtouint<T, uint32_t>(str, count, end, radix);
1195 inline uint64_t strtou64(
1196 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1197 _Out_opt_
size_t* end,
1200 return strtouint<T, uint64_t>(str, count, end, radix);
1215 inline size_t strtoui(
1216 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1217 _Out_opt_
size_t* end,
1220#if defined(_WIN64) || defined(__LP64__)
1221 return (
size_t)strtou64(str, count, end, radix);
1223 return (
size_t)strtou32(str, count, end, radix);
1228 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)
1233#pragma warning(suppress: 4996)
1234 r = _vsnprintf_l(str, capacity, format, locale, arg);
1236 r = ::vsnprintf(str, capacity, format, arg);
1238 if (r == -1 && strnlen(str, capacity) == capacity) {
1240 capacity += std::max<size_t>(capacity / 8, 0x80);
1241 if (capacity > INT_MAX)
1242 throw std::invalid_argument(
"string too big");
1243 return (
int)capacity;
1248 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)
1253#pragma warning(suppress: 4996)
1254 r = _vsnwprintf_l(str, capacity, format, locale, arg);
1256 r = vswprintf(str, capacity, format, arg);
1258 if (r == -1 && strnlen(str, capacity) == capacity) {
1260 capacity += std::max<size_t>(capacity / 8, 0x80);
1261 if (capacity > INT_MAX)
1262 throw std::invalid_argument(
"string too big");
1263 return (
int)capacity;
1277 template<
class _Elem,
class _Traits,
class _Ax>
1278 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)
1280 _Elem buf[1024/
sizeof(_Elem)];
1283 int count = vsnprintf(buf, _countof(buf) - 1, format, locale, arg);
1286 str.append(buf, count);
1288 for (
size_t capacity = 2*1024/
sizeof(_Elem);; capacity *= 2) {
1290 auto buf_dyn = std::make_unique<_Elem[]>(capacity);
1291 count = vsnprintf(buf_dyn.get(), capacity - 1, format, locale, arg);
1293 str.append(buf_dyn.get(), count);
1307 template<
class _Elem,
class _Traits,
class _Ax>
1308 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, ...)
1311 va_start(arg, locale);
1312 vappendf(str, format, locale, arg);
1324 template<
class _Elem,
class _Traits,
class _Ax>
1325 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)
1328 vappendf(str, format, locale, arg);
1338 template<
class _Elem,
class _Traits,
class _Ax>
1339 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, ...)
1342 va_start(arg, locale);
1343 vsprintf(str, format, locale, arg);
1356 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1357 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)
1359 std::basic_string<_Elem, _Traits, _Ax> str;
1360 vappendf(str, format, locale, arg);
1372 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1373 inline std::basic_string<_Elem, _Traits, _Ax> sprintf(_In_z_ _Printf_format_string_params_(2)
const _Elem *format, _In_opt_ locale_t locale, ...)
1376 va_start(arg, locale);
1377 auto str = vsprintf(format, locale, arg);
1383 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)
1386 return _strftime_l(str, capacity, format, time, locale);
1388 return strftime_l(str, capacity, format, time, locale);
1392 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)
1395 return _wcsftime_l(str, capacity, format, time, locale);
1397 return wcsftime_l(str, capacity, format, time, locale);
1410 template<
class _Elem,
class _Traits,
class _Ax>
1411 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)
1413 _Elem buf[1024/
sizeof(_Elem)];
1416 size_t count = strftime(buf, _countof(buf), format, time, locale);
1419 str.append(buf, count);
1421 for (
size_t capacity = 2*1024/
sizeof(_Elem);; capacity *= 2) {
1423 auto buf_dyn = std::make_unique<_Elem[]>(capacity);
1424 count = strftime(buf_dyn.get(), capacity, format, time, locale);
1426 str.append(buf_dyn.get(), count);
1441 template<
class _Elem,
class _Traits,
class _Ax>
1442 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)
1445 strcatftime(str, format, time, locale);
1458 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1459 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)
1461 std::basic_string<_Elem, _Traits, _Ax> str;
1462 strcatftime(str, format, time, locale);
1472 inline void uuidtostr(_Out_writes_z_(39)
char str[39], _In_
const uuid_t&
id)
1475 _snprintf_s_l(str, 39, _TRUNCATE,
"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", NULL,
1478 static_cast<unsigned int>(
id.Data2),
1479 static_cast<unsigned int>(
id.Data3),
1480 static_cast<unsigned int>(
id.Data4[0]),
static_cast<unsigned int>(
id.Data4[1]),
1481 static_cast<unsigned int>(
id.Data4[2]),
static_cast<unsigned int>(
id.Data4[3]),
static_cast<unsigned int>(
id.Data4[4]),
static_cast<unsigned int>(
id.Data4[5]),
static_cast<unsigned int>(
id.Data4[6]),
static_cast<unsigned int>(
id.Data4[7]));
1483 *
reinterpret_cast<const uint32_t*
>(&
id[0]),
1484 static_cast<unsigned int>(*
reinterpret_cast<const uint16_t*
>(&
id[4])),
1485 static_cast<unsigned int>(*
reinterpret_cast<const uint16_t*
>(&
id[6])),
1486 static_cast<unsigned int>(
id[8]),
static_cast<unsigned int>(
id[9]),
1487 static_cast<unsigned int>(
id[10])),
static_cast<unsigned int>(
id[11]),
static_cast<unsigned int>(
id[12]),
static_cast<unsigned int>(
id)),
static_cast<unsigned int>(
id[14]),
static_cast<unsigned int>(
id[15]));
1497 inline void uuidtostr(_Out_writes_z_(39)
wchar_t str[39], _In_
const uuid_t&
id)
1500 _snwprintf_s_l(str, 39, _TRUNCATE, L
"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", NULL,
1503 static_cast<unsigned int>(
id.Data2),
1504 static_cast<unsigned int>(
id.Data3),
1505 static_cast<unsigned int>(
id.Data4[0]),
static_cast<unsigned int>(
id.Data4[1]),
1506 static_cast<unsigned int>(
id.Data4[2]),
static_cast<unsigned int>(
id.Data4[3]),
static_cast<unsigned int>(
id.Data4[4]),
static_cast<unsigned int>(
id.Data4[5]),
static_cast<unsigned int>(
id.Data4[6]),
static_cast<unsigned int>(
id.Data4[7]));
1508 *
reinterpret_cast<const uint32_t*
>(&
id[0]),
1509 static_cast<unsigned int>(*
reinterpret_cast<const uint16_t*
>(&
id[4])),
1510 static_cast<unsigned int>(*
reinterpret_cast<const uint16_t*
>(&
id[6])),
1511 static_cast<unsigned int>(
id[8]),
static_cast<unsigned int>(
id[9]),
1512 static_cast<unsigned int>(
id[10])),
static_cast<unsigned int>(
id[11]),
static_cast<unsigned int>(
id[12]),
static_cast<unsigned int>(
id)),
static_cast<unsigned int>(
id[14]),
static_cast<unsigned int>(
id[15]));
1524 inline void strlwr(_Inout_z_ T* str, _In_
const std::locale& locale)
1527 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
1528 for (
size_t i = 0; str[i]; ++i)
1529 str[i] = ctype.tolower(str[i]);
1541 inline void strlwr(_Inout_updates_z_(count) T* str, _In_
size_t count, _In_
const std::locale& locale)
1543 _Assume_(str || !count);
1544 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
1545 for (
size_t i = 0; i < count && str[i]; ++i)
1546 str[i] = ctype.tolower(str[i]);
1557 inline void strupr(_Inout_z_ T* str, _In_
const std::locale& locale)
1560 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
1561 for (
size_t i = 0; str[i]; ++i)
1562 str[i] = ctype.toupper(str[i]);
1574 inline void strupr(_Inout_updates_z_(count) T* str, _In_
size_t count, _In_
const std::locale& locale)
1576 _Assume_(str || !count);
1577 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
1578 for (
size_t i = 0; i < count && str[i]; ++i)
1579 str[i] = ctype.toupper(str[i]);
1589 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1590 inline void strupr(_Inout_ std::basic_string<_Elem, _Traits, _Ax>& str, _In_
const std::locale& locale)
1592 const auto& ctype = std::use_facet<std::ctype<_Elem>>(locale);
1593 for (
size_t i = 0; i < str.size(); ++i)
1594 str[i] = ctype.toupper(str[i]);
1606 inline size_t ltrim(
1607 _Inout_z_count_(count) T* str, _In_
size_t count,
1608 _In_
const std::locale& locale)
1610 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
1611 for (
size_t i = 0;; ++i) {
1613 if (count) str[0] = 0;
1620 if (!ctype.is(ctype.space, str[i])) {
1622 return strnlen(str, count);
1623 size_t n = count != SIZE_MAX ? strncpy(str, str + i, count - i) : strcpy(str, str + i);
1635 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1636 inline void ltrim(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &s, _In_
const std::locale& locale)
1638 const auto& ctype = std::use_facet<std::ctype<_Elem>>(locale);
1644 [&](_Elem ch) { return !ctype.is(ctype.space, ch); }));
1656 inline size_t rtrim(
1657 _Inout_z_count_(count) T* str, _In_
size_t count,
1658 _In_
const std::locale& locale)
1660 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
1661 for (
size_t i = 0, j = 0;;) {
1662 if (i >= count || !str[i]) {
1663 if (j < count) str[j] = 0;
1666 if (!ctype.is(ctype.space, str[i]))
1678 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1679 static inline void rtrim(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &s, _In_
const std::locale& locale)
1681 const auto& ctype = std::use_facet<std::ctype<_Elem>>(locale);
1686 [&](_Elem ch) { return !ctype.is(ctype.space, ch); }).base(),
1700 _Inout_z_count_(count) T* str, _In_
size_t count,
1701 _In_
const std::locale& locale)
1703 return ltrim(str, rtrim(str, count, locale), locale);
1711 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1712 static inline void trim(_Inout_ std::basic_string<_Elem, _Traits, _Ax> &s, _In_
const std::locale& locale)
1714 const auto& ctype = std::use_facet<std::ctype<_Elem>>(locale);
1720 [&](_Elem ch) { return !ctype.is(ctype.space, ch); }));
1725 [&](_Elem ch) { return !ctype.is(ctype.space, ch); }).base(),
Deleter for unique_ptr using free_locale.
Definition string.hpp:63
void operator()(locale_t locale) const
Delete a pointer.
Definition string.hpp:67