26 using locale_t = _locale_t;
28 inline locale_t create_locale(_In_
int category, _In_z_
const char* locale) {
return _create_locale(category, locale); }
29 inline locale_t create_locale(_In_
int category, _In_z_
const wchar_t* locale) {
return _wcreate_locale(category, locale); }
30 inline void free_locale(_In_opt_ locale_t locale) { _free_locale(locale); }
32 using locale_t = ::locale_t;
34 inline locale_t create_locale(_In_
int category, _In_z_
const char* locale)
38 case LC_ALL : mask = LC_ALL_MASK ;
break;
39 case LC_COLLATE : mask = LC_COLLATE_MASK ;
break;
40 case LC_CTYPE : mask = LC_CTYPE_MASK ;
break;
41 case LC_MESSAGES: mask = LC_MESSAGES_MASK;
break;
42 case LC_MONETARY: mask = LC_MONETARY_MASK;
break;
43 case LC_NUMERIC : mask = LC_NUMERIC_MASK ;
break;
44 case LC_TIME : mask = LC_TIME_MASK ;
break;
46 return newlocale(mask, locale, LC_GLOBAL_LOCALE);
49 inline void free_locale(_In_opt_ locale_t locale) { freelocale(locale); }
70 using locale = std::unique_ptr<__crt_locale_pointers, free_locale_delete>;
71#elif defined(__APPLE__)
72 using locale = std::unique_ptr<struct _xlocale, free_locale_delete>;
74 using locale = std::unique_ptr<struct __locale_struct, free_locale_delete>;
80 static locale locale_C(create_locale(LC_ALL,
"C"));
86 typedef wchar_t utf16_t;
88 typedef char16_t utf16_t;
96 inline bool is_high_surrogate(_In_ utf16_t chr)
98 return 0xd800 < chr && chr < 0xdc00;
106 inline bool is_low_surrogate(_In_ utf16_t chr)
108 return 0xdc00 < chr && chr < 0xe000;
116 inline bool is_surrogate_pair(_In_reads_(2)
const utf16_t* str)
118 return is_high_surrogate(str[0]) && is_low_surrogate(str[1]);
126 inline char32_t surrogate_pair_to_ucs4(_In_reads_(2)
const utf16_t* str)
128 assert(is_surrogate_pair(str));
130 ((
char32_t)(str[0] - 0xd800) << 10) +
131 (char32_t)(str[1] - 0xdc00) +
140 inline void ucs4_to_surrogate_pair(_Out_writes_(2) utf16_t* str, _In_
char32_t chr)
142 assert(chr >= 0x10000);
144 str[0] = 0xd800 + (char32_t)((chr >> 10) & 0x3ff);
145 str[1] = 0xdc00 + (char32_t)(chr & 0x3ff);
153 inline bool iscombining(_In_
char32_t chr)
156 (0x0300 <= chr && chr < 0x0370) ||
157 (0x1dc0 <= chr && chr < 0x1e00) ||
158 (0x20d0 <= chr && chr < 0x2100) ||
159 (0xfe20 <= chr && chr < 0xfe30);
168 inline size_t islbreak(_In_ T chr)
170 return chr ==
'\n' || chr ==
'\r';
180 inline size_t islbreak(_In_reads_or_z_opt_(count)
const T* chr, _In_
size_t count)
182 _Analysis_assume_(chr || !count);
183 if (count >= 2 && ((chr[0] ==
'\r' && chr[1] ==
'\n') || (chr[0] ==
'\n' && chr[1] ==
'\r')))
185 if (count > 1 && (chr[0] ==
'\n' || chr[0] ==
'\r'))
196 inline size_t glyphlen(_In_reads_or_z_opt_(count)
const wchar_t* glyph, _In_
size_t count)
198 _Analysis_assume_(glyph || !count);
201 size_t i = count < 2 || !is_surrogate_pair(glyph) ? 1 : 2;
205 for (; i < count && iscombining(glyph[i]); ++i);
219 inline size_t strlen(_In_z_
const T* str)
223 for (i = 0; str[i]; ++i);
236 inline size_t strnlen(_In_reads_or_z_opt_(count)
const T* str, _In_
size_t count)
238 assert(str || !count);
240 for (i = 0; i < count && str[i]; ++i);
244 constexpr auto npos{
static_cast<size_t>(-1) };
255 inline size_t strchr(_In_z_
const T* str, _In_ T chr)
258 for (
size_t i = 0; str[i]; ++i)
259 if (str[i] == chr)
return i;
273 inline size_t strnchr(
274 _In_reads_or_z_opt_(count)
const T* str,
278 assert(str || !count);
279 for (
size_t i = 0; i < count && str[i]; ++i)
280 if (str[i] == chr)
return i;
294 inline size_t strrnchr(
295 _In_reads_or_z_opt_(count)
const T* str,
299 assert(str || !count);
301 for (
size_t i = 0; i < count && str[i]; ++i)
302 if (str[i] == chr) z = i;
316 inline size_t strnichr(
317 _In_reads_or_z_opt_(count)
const T* str,
320 _In_
const std::locale& locale)
322 assert(str || !count);
323 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
324 chr = ctype.tolower(chr);
325 for (
size_t i = 0; i < count && str[i]; ++i)
326 if (ctype.tolower(str[i]) == chr)
return i;
340 inline size_t strrnichr(
341 _In_reads_or_z_opt_(count)
const T* str,
344 _In_
const std::locale& locale)
346 assert(str || !count);
347 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
348 chr = ctype.tolower(chr);
350 for (
size_t i = 0; i < count && str[i]; ++i)
351 if (ctype.tolower(str[i]) == chr) z = i;
365 template <
class T1,
class T2>
367 _In_reads_or_z_opt_(count1)
const T1* str1, _In_
size_t count1,
368 _In_reads_or_z_opt_(count2)
const T2* str2, _In_
size_t count2)
370 assert(str1 || !count1);
371 assert(str2 || !count2);
372 size_t i; T1 a; T2 b;
373 for (i = 0; i < count1 && i < count2 && ((a = str1[i]) | (b = str2[i])); ++i) {
374 if (a > b)
return +1;
375 if (a < b)
return -1;
377 if (i < count1 && str1[i])
return +1;
378 if (i < count2 && str2[i])
return -1;
394 _In_reads_or_z_opt_(count1)
const T* str1, _In_
size_t count1,
395 _In_reads_or_z_opt_(count2)
const T* str2, _In_
size_t count2,
396 _In_
const std::locale& locale)
398 assert(str1 || !count1);
399 assert(str2 || !count2);
400 auto& collate = std::use_facet<std::collate<T>>(locale);
401 return collate.compare(str1, str1 + count1, str2, str2 + count2);
412 template <
class T1,
class T2>
413 inline int stricmp(_In_z_
const T1* str1, _In_z_
const T2* str2, _In_
const std::locale& locale)
417 size_t i; T1 a; T2 b;
418 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
419 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
420 for (i = 0; (a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i])); i++) {
421 if (a > b)
return +1;
422 if (a < b)
return -1;
424 if (str1[i])
return +1;
425 if (str2[i])
return -1;
438 template <
class T1,
class T2>
439 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)
441 assert(str1 || !count);
442 assert(str2 || !count);
443 size_t i; T1 a; T2 b;
444 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
445 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
446 for (i = 0; i < count && ((a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i]))); i++) {
447 if (a > b)
return +1;
448 if (a < b)
return -1;
450 if (i < count && str1[i])
return +1;
451 if (i < count && str2[i])
return -1;
465 template <
class T1,
class T2>
467 _In_reads_or_z_opt_(count1)
const T1* str1, _In_
size_t count1,
468 _In_reads_or_z_opt_(count2)
const T2* str2, _In_
size_t count2,
469 _In_
const std::locale& locale)
471 assert(str1 || !count1);
472 assert(str2 || !count2);
473 size_t i; T1 a; T2 b;
474 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
475 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
476 for (i = 0; i < count1 && i < count2 && ((a = ctype1.tolower(str1[i])) | (b = ctype2.tolower(str2[i]))); i++) {
477 if (a > b)
return +1;
478 if (a < b)
return -1;
480 if (i < count1 && str1[i])
return +1;
481 if (i < count2 && str2[i])
return -1;
493 template <
class T1,
class T2>
494 inline size_t strstr(
495 _In_z_
const T1* str,
496 _In_z_
const T2* sample)
500 for (
size_t offset = 0;; ++offset) {
501 for (
size_t i = offset, j = 0;; ++i, ++j) {
506 if (str[i] != sample[j])
521 template <
class T1,
class T2>
522 inline size_t strnstr(
523 _In_reads_or_z_opt_(count)
const T1* str,
525 _In_z_
const T2* sample)
527 assert(str || !count);
529 for (
size_t offset = 0;; ++offset) {
530 for (
size_t i = offset, j = 0;; ++i, ++j) {
533 if (i >= count || !str[i])
535 if (str[i] != sample[j])
549 template <
class T1,
class T2>
550 inline size_t stristr(
551 _In_z_
const T1* str,
552 _In_z_
const T2* sample,
553 _In_
const std::locale& locale)
557 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
558 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
559 for (
size_t offset = 0;; ++offset) {
560 for (
size_t i = offset, j = 0;; ++i, ++j) {
565 if (ctype1.tolower(str[i]) != ctype2.tolower(sample[j]))
580 template <
class T1,
class T2>
581 inline size_t strnistr(
582 _In_reads_or_z_opt_(count)
const T1* str,
584 _In_z_
const T2* sample,
585 _In_
const std::locale& locale)
587 assert(str || !count);
589 const auto& ctype1 = std::use_facet<std::ctype<T1>>(locale);
590 const auto& ctype2 = std::use_facet<std::ctype<T2>>(locale);
591 for (
size_t offset = 0;; ++offset) {
592 for (
size_t i = offset, j = 0;; ++i, ++j) {
595 if (i >= count || !str[i])
597 if (ctype1.tolower(str[i]) != ctype2.tolower(sample[j]))
611 template <
class T1,
class T2>
612 inline size_t strcpy(
613 _Out_writes_z_(_String_length_(src) + 1) T1* dst,
614 _In_z_
const T2* src)
617 for (
size_t i = 0; ; ++i) {
618 if ((dst[i] = src[i]) == 0)
632 template <
class T1,
class T2>
633 inline size_t strncpy(
634 _Out_writes_(count) _Post_maybez_ T1* dst,
635 _In_reads_or_z_opt_(count)
const T2* src, _In_
size_t count)
637 assert(dst && src || !count);
638 for (
size_t i = 0; ; ++i) {
641 if ((dst[i] = src[i]) == 0)
656 template <
class T1,
class T2>
657 inline size_t strncpy(
658 _Out_writes_(count_dst) _Post_maybez_ T1* dst, _In_
size_t count_dst,
659 _In_reads_or_z_opt_(count_src)
const T2* src, _In_
size_t count_src)
661 assert(dst || !count_dst);
662 assert(src || !count_src);
663 for (
size_t i = 0; ; ++i)
671 if ((dst[i] = src[i]) == 0)
684 template <
class T1,
class T2>
685 inline size_t strcat(
686 _In_z_ _Out_writes_z_(_String_length_(dst) + _String_length_(src) + 1) T1* dst,
687 _In_z_
const T2* src)
690 for (
size_t i = 0, j = stdex::strlen<T1>(dst); ; ++i, ++j) {
691 if ((dst[j] = src[i]) == 0)
705 template <
class T1,
class T2>
706 inline size_t strncat(
707 _Out_writes_(count) _Post_maybez_ T1* dst,
708 _In_reads_or_z_opt_(count)
const T2* src, _In_
size_t count)
710 assert(dst && src || !count);
711 for (
size_t i = 0, j = stdex::strlen<T1>(dst); ; ++i, ++j) {
714 if ((dst[j] = src[i]) == 0)
729 template <
class T1,
class T2>
730 inline size_t strncat(
731 _Out_writes_(count_dst) _Post_maybez_ T1* dst, _In_
size_t count_dst,
732 _In_reads_or_z_opt_(count_src)
const T2* src, _In_
size_t count_src)
734 assert(dst || !count_dst);
735 assert(src || !count_src);
736 for (
size_t i = 0, j = stdex::strnlen<T1>(dst, count_dst); ; ++i, ++j)
744 if ((dst[j] = src[i]) == 0)
760 inline _Check_return_ _Ret_maybenull_z_ T* strdup(_In_opt_z_
const T* str)
764 size_t count = strlen(str) + 1;
765 T* dst =
new T[count];
766 strncpy(dst, count, str, SIZE_MAX);
782 inline _Ret_z_ T* strndup(
783 _In_reads_or_z_opt_(count)
const T* str,
786 T* dst =
new T[count];
787 strncpy(dst, count, str, SIZE_MAX);
801 inline size_t crlf2nl(_Out_writes_z_(strlen(src)) T* dst, _In_z_
const T* src)
806 for (i = j = 0; src[j];) {
807 if (src[j] !=
'\r' || src[j + 1] !=
'\n')
819 template <
class T,
class T_bin>
820 inline T_bin strtoint(
821 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
822 _Out_opt_
size_t* end,
824 _Out_ uint8_t& flags)
826 assert(str || !count);
827 assert(radix == 0 || 2 <= radix && radix <= 36);
830 T_bin value = 0, digit,
832 max_ui_pre1, max_ui_pre2;
838 if (i >= count || !str[i])
goto error;
839 if (!isspace(str[i]))
break;
846 if (i >= count || !str[i])
goto error;
848 else if (str[i] ==
'-') {
851 if (i >= count || !str[i])
goto error;
856 if (str[i] ==
'0' && i + 1 < count && (str[i + 1] ==
'x' || str[i + 1] ==
'X')) {
858 if (i >= count || !str[i])
goto error;
865 if (i >= count || !str[i])
goto error;
866 if (str[i] ==
'x' || str[i] ==
'X') {
869 if (i >= count || !str[i])
goto error;
879 max_ui_pre1 = max_ui / (T_bin)radix;
880 max_ui_pre2 = max_ui % (T_bin)radix;
882 if (
'0' <= str[i] && str[i] <=
'9')
883 digit = (T_bin)str[i] -
'0';
884 else if (
'A' <= str[i] && str[i] <=
'Z')
885 digit = (T_bin)str[i] -
'A' +
'\x0a';
886 else if (
'a' <= str[i] && str[i] <=
'z')
887 digit = (T_bin)str[i] -
'a' +
'\x0a';
890 if (digit >= (T_bin)radix)
893 if (value < max_ui_pre1 ||
894 (value == max_ui_pre1 && digit <= max_ui_pre2))
895 value = value * (T_bin)radix + digit;
902 if (i >= count || !str[i])
922 template <
class T,
class T_bin>
924 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
925 _Out_opt_
size_t* end,
931 switch (
sizeof(T_bin)) {
933 value = (T_bin)strtoint<T, uint8_t>(str, count, end, radix, flags);
934 if ((flags & 0x01) && (value & 0x80)) {
938 return (flags & 0x02) ?
939 (flags & 0x01) ? (T_bin)0x80 : (T_bin)0x7f :
940 (flags & 0x01) ? -value : value;
943 value = (T_bin)strtoint<T, uint16_t>(str, count, end, radix, flags);
944 if ((flags & 0x01) && (value & 0x8000)) {
948 return (flags & 0x02) ?
949 (flags & 0x01) ? (T_bin)0x8000 : (T_bin)0x7fff :
950 (flags & 0x01) ? -value : value;
953 value = (T_bin)strtoint<T, uint32_t>(str, count, end, radix, flags);
954 if ((flags & 0x01) && (value & 0x80000000)) {
958 return (flags & 0x02) ?
959 (flags & 0x01) ? (T_bin)0x80000000 : (T_bin)0x7fffffff :
960 (flags & 0x01) ? -value : value;
963 value = (T_bin)strtoint<T, uint64_t>(str, count, end, radix, flags);
964 if ((flags & 0x01) && (value & 0x8000000000000000)) {
968 return (flags & 0x02) ?
969 (flags & 0x01) ? (T_bin)0x8000000000000000 : (T_bin)0x7fffffffffffffff :
970 (flags & 0x01) ? -value : value;
973 throw std::invalid_argument(
"Unsupported bit length");
987 template <
class T,
class T_bin>
988 inline T_bin strtouint(
989 _In_reads_or_z_opt_(count)
const T* str,
991 _Out_opt_
size_t* end,
997 switch (
sizeof(T_bin)) {
998 case 1: value = (T_bin)strtoint<T, uint8_t>(str, count, end, radix, flags);
break;
999 case 2: value = (T_bin)strtoint<T, uint16_t>(str, count, end, radix, flags);
break;
1000 case 4: value = (T_bin)strtoint<T, uint32_t>(str, count, end, radix, flags);
break;
1001 case 8: value = (T_bin)strtoint<T, uint64_t>(str, count, end, radix, flags);
break;
1002 default:
throw std::invalid_argument(
"Unsupported bit length");
1005 return (flags & 0x02) ?
1006 (flags & 0x01) ? (T_bin)0 : (T_bin)-1 :
1007 (flags & 0x01) ? ~value : value;
1021 inline int32_t strto32(
1022 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1023 _Out_opt_
size_t* end,
1026 return strtoint<T, int32_t>(str, count, end, radix);
1040 inline int64_t strto64(
1041 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1042 _Out_opt_
size_t* end,
1045 return strtoint<T, int64_t>(str, count, end, radix);
1060 inline intptr_t strtoi(
1061 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1062 _Out_opt_
size_t* end,
1065#if defined(_WIN64) || defined(__LP64__)
1066 return (intptr_t)strto64(str, count, end, radix);
1068 return (intptr_t)strto32(str, count, end, radix);
1083 inline uint32_t strtou32(
1084 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1085 _Out_opt_
size_t* end,
1088 return strtouint<T, uint32_t>(str, count, end, radix);
1102 inline uint64_t strtou64(
1103 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1104 _Out_opt_
size_t* end,
1107 return strtouint<T, uint64_t>(str, count, end, radix);
1122 inline size_t strtoui(
1123 _In_reads_or_z_opt_(count)
const T* str, _In_
size_t count,
1124 _Out_opt_
size_t* end,
1127#if defined(_WIN64) || defined(__LP64__)
1128 return (
size_t)strtou64(str, count, end, radix);
1130 return (
size_t)strtou32(str, count, end, radix);
1135 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)
1140#pragma warning(suppress: 4996)
1141 r = _vsnprintf_l(str, capacity, format, locale, arg);
1143 r = ::vsnprintf(str, capacity, format, arg);
1145 if (r == -1 && strnlen(str, capacity) == capacity) {
1147 capacity += std::max<size_t>(capacity / 8, 0x80);
1148 if (capacity > INT_MAX)
1149 throw std::invalid_argument(
"string too big");
1150 return (
int)capacity;
1155 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)
1161#pragma warning(suppress: 4996)
1162 r = _vsnwprintf_l(str, capacity, format, locale, arg);
1164 r = vswprintf(str, capacity, format, arg);
1166 if (r == -1 && strnlen(str, capacity) == capacity) {
1168 capacity += std::max<size_t>(capacity / 8, 0x80);
1169 if (capacity > INT_MAX)
1170 throw std::invalid_argument(
"string too big");
1171 return (
int)capacity;
1185 template<
class _Elem,
class _Traits,
class _Ax>
1186 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)
1188 _Elem buf[1024/
sizeof(_Elem)];
1191 int count = vsnprintf(buf, _countof(buf) - 1, format, locale, arg);
1194 str.append(buf, count);
1196 for (
size_t capacity = 2*1024/
sizeof(_Elem);; capacity *= 2) {
1198 auto buf_dyn = std::make_unique<_Elem[]>(capacity);
1199 count = vsnprintf(buf_dyn.get(), capacity - 1, format, locale, arg);
1201 str.append(buf_dyn.get(), count);
1215 template<
class _Elem,
class _Traits,
class _Ax>
1216 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, ...)
1219 va_start(arg, locale);
1220 vappendf(str, format, locale, arg);
1232 template<
class _Elem,
class _Traits,
class _Ax>
1233 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)
1236 vappendf(str, format, locale, arg);
1246 template<
class _Elem,
class _Traits,
class _Ax>
1247 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, ...)
1250 va_start(arg, locale);
1251 vsprintf(str, format, locale, arg);
1264 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1265 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)
1267 std::basic_string<_Elem, _Traits, _Ax> str;
1268 vappendf(str, format, locale, arg);
1280 template<
class _Elem,
class _Traits = std::
char_traits<_Elem>,
class _Ax = std::allocator<_Elem>>
1281 inline std::basic_string<_Elem, _Traits, _Ax> sprintf(_In_z_ _Printf_format_string_params_(2)
const _Elem *format, _In_opt_ locale_t locale, ...)
1284 va_start(arg, locale);
1285 auto str = vsprintf(format, locale, arg);
1298 inline void strlwr(_Inout_z_ T* str, _In_
const std::locale& locale)
1301 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
1302 for (
size_t i = 0; str[i]; ++i)
1303 str[i] = ctype.tolower(str[i]);
1315 inline void strlwr(_Inout_updates_z_(count) T* str, _In_
size_t count, _In_
const std::locale& locale)
1317 assert(str || !count);
1318 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
1319 for (
size_t i = 0; i < count && str[i]; ++i)
1320 str[i] = ctype.tolower(str[i]);
1331 inline void strupr(_Inout_z_ T* str, _In_
const std::locale& locale)
1334 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
1335 for (
size_t i = 0; str[i]; ++i)
1336 str[i] = ctype.toupper(str[i]);
1349 (_Inout_updates_z_(count) T* str, _In_
size_t count, _In_
const std::locale& locale)
1351 assert(str || !count);
1352 const auto& ctype = std::use_facet<std::ctype<T>>(locale);
1353 for (
size_t i = 0; i < count && str[i]; ++i)
1354 str[i] = ctype.toupper(str[i]);
Deleter for unique_ptr using free_locale.
Definition string.hpp:56
void operator()(locale_t locale) const
Delete a pointer.
Definition string.hpp:60