Skip to content

Commit e326b90

Browse files
committed
<xloctime>: Fix time_put::do_put to correctly handle %c and %r format in C locale
1 parent f3ae96a commit e326b90

2 files changed

Lines changed: 57 additions & 24 deletions

File tree

stl/inc/xloctime

Lines changed: 57 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -888,24 +888,36 @@ protected:
888888

889889
virtual _OutIt __CLR_OR_THIS_CALL do_put(_OutIt _Dest, ios_base& _Iosbase, _Elem, const tm* _Pt, char _Specifier,
890890
char _Modifier = '\0') const { // put formatted time from _Pt to _Dest for [_Fmtfirst, _Fmtlast)
891-
char _Fmt[5] = "!%x\0"; // '!' for nonzero count, null for modifier
891+
const char* _Fmt_ptr = nullptr;
892+
char _Fmt[5] = "!%x\0"; // '!' for nonzero count, null for modifier
892893
size_t _Count;
893894
size_t _Num;
894895
string _Str;
895896

896-
if (_Modifier == '\0') {
897-
_Fmt[2] = _Specifier;
898-
} else { // add both modifier and specifier
899-
_Fmt[2] = _Modifier;
900-
_Fmt[3] = _Specifier;
897+
if (_Iosbase.getloc() == locale::classic()) {
898+
if (_Specifier == 'c') {
899+
_Fmt_ptr = "!%a %b %e %T %Y";
900+
} else if (_Specifier == 'r') {
901+
_Fmt_ptr = "!%I:%M:%S %p";
902+
}
903+
}
904+
905+
if (!_Fmt_ptr) {
906+
if (_Modifier == '\0') {
907+
_Fmt[2] = _Specifier;
908+
} else { // add both modifier and specifier
909+
_Fmt[2] = _Modifier;
910+
_Fmt[3] = _Specifier;
911+
}
912+
_Fmt_ptr = _Fmt;
901913
}
902914

903915
int& _Errno_ref = errno; // Nonzero cost, pay it once
904916
const int _Old_errno = _Errno_ref;
905917

906918
for (_Num = 16;; _Num *= 2) { // convert into ever larger string buffer until success
907919
_Str.append(_Num, '\0');
908-
_Count = _Strftime(&_Str[0], _Str.size(), _Fmt, _Pt, _Tnames._Getptr());
920+
_Count = _Strftime(&_Str[0], _Str.size(), _Fmt_ptr, _Pt, _Tnames._Getptr());
909921
if (0 < _Count) {
910922
break;
911923
} else if (_Errno_ref == EINVAL) {
@@ -1034,24 +1046,36 @@ protected:
10341046

10351047
virtual _OutIt __CLR_OR_THIS_CALL do_put(_OutIt _Dest, ios_base& _Iosbase, _Elem, const tm* _Pt, char _Specifier,
10361048
char _Modifier = '\0') const { // put formatted time from _Pt to _Dest for [_Fmtfirst, _Fmtlast)
1037-
wchar_t _Fmt[5] = L"!%x\0"; // ! for nonzero count, null for modifier
1049+
const wchar_t* _Fmt_ptr = nullptr;
1050+
wchar_t _Fmt[5] = L"!%x\0"; // ! for nonzero count, null for modifier
10381051
size_t _Count;
10391052
size_t _Num;
10401053
wstring _Str;
10411054

1042-
if (_Modifier == '\0') {
1043-
_Fmt[2] = static_cast<_Elem>(_Specifier); // conversion rule unspecified
1044-
} else { // add both modifier and specifier
1045-
_Fmt[2] = static_cast<_Elem>(_Modifier);
1046-
_Fmt[3] = static_cast<_Elem>(_Specifier);
1055+
if (_Iosbase.getloc() == locale::classic()) {
1056+
if (_Specifier == 'c') {
1057+
_Fmt_ptr = L"!%a %b %e %T %Y";
1058+
} else if (_Specifier == 'r') {
1059+
_Fmt_ptr = L"!%I:%M:%S %p";
1060+
}
1061+
}
1062+
1063+
if (!_Fmt_ptr) {
1064+
if (_Modifier == '\0') {
1065+
_Fmt[2] = static_cast<_Elem>(_Specifier);
1066+
} else {
1067+
_Fmt[2] = static_cast<_Elem>(_Modifier);
1068+
_Fmt[3] = static_cast<_Elem>(_Specifier);
1069+
}
1070+
_Fmt_ptr = _Fmt;
10471071
}
10481072

10491073
int& _Errno_ref = errno; // Nonzero cost, pay it once
10501074
const int _Old_errno = _Errno_ref;
10511075

10521076
for (_Num = 16;; _Num *= 2) { // convert into ever larger string buffer until success
10531077
_Str.append(_Num, '\0');
1054-
_Count = _Wcsftime(&_Str[0], _Str.size(), _Fmt, _Pt, _Tnames._Getptr());
1078+
_Count = _Wcsftime(&_Str[0], _Str.size(), _Fmt_ptr, _Pt, _Tnames._Getptr());
10551079
if (0 < _Count) {
10561080
break;
10571081
} else if (_Errno_ref == EINVAL) {
@@ -1183,24 +1207,36 @@ protected:
11831207

11841208
virtual _OutIt __CLR_OR_THIS_CALL do_put(_OutIt _Dest, ios_base& _Iosbase, _Elem, const tm* _Pt, char _Specifier,
11851209
char _Modifier = '\0') const { // put formatted time from _Pt to _Dest for [_Fmtfirst, _Fmtlast)
1186-
wchar_t _Fmt[5] = L"!%x\0"; // ! for nonzero count, null for modifier
1210+
const wchar_t* _Fmt_ptr = nullptr;
1211+
wchar_t _Fmt[5] = L"!%x\0"; // ! for nonzero count, null for modifier
11871212
size_t _Count;
11881213
size_t _Num;
11891214
wstring _Str;
11901215

1191-
if (_Modifier == '\0') {
1192-
_Fmt[2] = static_cast<_Elem>(_Specifier); // conversion rule unspecified
1193-
} else { // add both modifier and specifier
1194-
_Fmt[2] = static_cast<_Elem>(_Modifier);
1195-
_Fmt[3] = static_cast<_Elem>(_Specifier);
1216+
if (_Iosbase.getloc() == locale::classic()) {
1217+
if (_Specifier == 'c') {
1218+
_Fmt_ptr = L"!%a %b %e %T %Y";
1219+
} else if (_Specifier == 'r') {
1220+
_Fmt_ptr = L"!%I:%M:%S %p";
1221+
}
1222+
}
1223+
1224+
if (!_Fmt_ptr) {
1225+
if (_Modifier == '\0') {
1226+
_Fmt[2] = static_cast<_Elem>(_Specifier);
1227+
} else {
1228+
_Fmt[2] = static_cast<_Elem>(_Modifier);
1229+
_Fmt[3] = static_cast<_Elem>(_Specifier);
1230+
}
1231+
_Fmt_ptr = _Fmt;
11961232
}
11971233

11981234
int& _Errno_ref = errno; // Nonzero cost, pay it once
11991235
const int _Old_errno = _Errno_ref;
12001236

12011237
for (_Num = 16;; _Num *= 2) { // convert into ever larger string buffer until success
12021238
_Str.append(_Num, '\0');
1203-
_Count = _Wcsftime(&_Str[0], _Str.size(), _Fmt, _Pt, _Tnames._Getptr());
1239+
_Count = _Wcsftime(&_Str[0], _Str.size(), _Fmt_ptr, _Pt, _Tnames._Getptr());
12041240
if (0 < _Count) {
12051241
break;
12061242
} else if (_Errno_ref == EINVAL) {

tests/libcxx/expected_results.txt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -566,9 +566,6 @@ std/localization/locale.categories/category.time/locale.time.get/locale.time.get
566566
std/localization/locale.categories/category.time/locale.time.get/locale.time.get.members/get_weekday.pass.cpp FAIL
567567
std/localization/locale.categories/category.time/locale.time.get/locale.time.get.members/get_weekday_wide.pass.cpp FAIL
568568

569-
# GH-6134 <xloctime>: time_put::do_put does not match strftime for the %c and %r specifiers in the "C" locale
570-
std/localization/locale.categories/category.time/locale.time.put/locale.time.put.members/put2.pass.cpp FAIL
571-
572569
# GH-6135 <xloctime>: time_put_byname doesn't encode the output in UTF-8 even if the locale name contains ".UTF-8"
573570
std/localization/locale.categories/category.time/locale.time.put.byname/put1.pass.cpp FAIL
574571

0 commit comments

Comments
 (0)