to_stream sets failbit if required to supply a bad name:

* for an invalid month
* for an invalid weekday
This commit is contained in:
Howard Hinnant 2017-10-15 13:53:20 -04:00
parent 94eb182256
commit 66a97f907e

View File

@ -4371,6 +4371,19 @@ extract_weekday(std::basic_ostream<CharT, Traits>& os, const fields<Duration>& f
return wd; return wd;
} }
template <class CharT, class Traits, class Duration>
unsigned
extract_month(std::basic_ostream<CharT, Traits>& os, const fields<Duration>& fds)
{
if (!fds.ymd.month().ok())
{
// fds does not contain a valid month
os.setstate(std::ios::failbit);
return 0;
}
return static_cast<unsigned>(fds.ymd.month());
}
} // namespace detail } // namespace detail
#if ONLY_C_LOCALE #if ONLY_C_LOCALE
@ -4568,6 +4581,7 @@ to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
{ {
using namespace std; using namespace std;
using namespace std::chrono; using namespace std::chrono;
using namespace detail;
tm tm{}; tm tm{};
#if !ONLY_C_LOCALE #if !ONLY_C_LOCALE
auto& facet = use_facet<time_put<CharT>>(os.getloc()); auto& facet = use_facet<time_put<CharT>>(os.getloc());
@ -4584,14 +4598,14 @@ to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
{ {
if (modified == CharT{}) if (modified == CharT{})
{ {
tm.tm_wday = static_cast<int>(detail::extract_weekday(os, fds)); tm.tm_wday = static_cast<int>(extract_weekday(os, fds));
if (os.fail()) if (os.fail())
return os; return os;
#if !ONLY_C_LOCALE #if !ONLY_C_LOCALE
const CharT f[] = {'%', *fmt}; const CharT f[] = {'%', *fmt};
facet.put(os, os, os.fill(), &tm, begin(f), end(f)); facet.put(os, os, os.fill(), &tm, begin(f), end(f));
#else // ONLY_C_LOCALE #else // ONLY_C_LOCALE
os << detail::weekday_names().first[tm.tm_wday+7*(*fmt == 'a')]; os << weekday_names().first[tm.tm_wday+7*(*fmt == 'a')];
#endif // ONLY_C_LOCALE #endif // ONLY_C_LOCALE
} }
else else
@ -4611,12 +4625,12 @@ to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
{ {
if (modified == CharT{}) if (modified == CharT{})
{ {
tm.tm_mon = static_cast<int>(unsigned(fds.ymd.month())) - 1; tm.tm_mon = static_cast<int>(extract_month(os, fds)) - 1;
#if !ONLY_C_LOCALE #if !ONLY_C_LOCALE
const CharT f[] = {'%', *fmt}; const CharT f[] = {'%', *fmt};
facet.put(os, os, os.fill(), &tm, begin(f), end(f)); facet.put(os, os, os.fill(), &tm, begin(f), end(f));
#else // ONLY_C_LOCALE #else // ONLY_C_LOCALE
os << detail::month_names().first[tm.tm_mon+12*(*fmt == 'b')]; os << month_names().first[tm.tm_mon+12*(*fmt == 'b')];
#endif // ONLY_C_LOCALE #endif // ONLY_C_LOCALE
} }
else else
@ -4645,9 +4659,9 @@ to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
tm.tm_min = static_cast<int>(fds.tod.minutes().count()); tm.tm_min = static_cast<int>(fds.tod.minutes().count());
tm.tm_hour = static_cast<int>(fds.tod.hours().count()); tm.tm_hour = static_cast<int>(fds.tod.hours().count());
tm.tm_mday = static_cast<int>(static_cast<unsigned>(ymd.day())); tm.tm_mday = static_cast<int>(static_cast<unsigned>(ymd.day()));
tm.tm_mon = static_cast<int>(static_cast<unsigned>(ymd.month()) - 1); tm.tm_mon = static_cast<int>(extract_month(os, fds) - 1);
tm.tm_year = static_cast<int>(ymd.year()) - 1900; tm.tm_year = static_cast<int>(ymd.year()) - 1900;
tm.tm_wday = static_cast<int>(detail::extract_weekday(os, fds)); tm.tm_wday = static_cast<int>(extract_weekday(os, fds));
if (os.fail()) if (os.fail())
return os; return os;
tm.tm_yday = static_cast<int>((ld - local_days(ymd.year()/1/1)).count()); tm.tm_yday = static_cast<int>((ld - local_days(ymd.year()/1/1)).count());
@ -4660,11 +4674,10 @@ to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
#else // ONLY_C_LOCALE #else // ONLY_C_LOCALE
if (*fmt == 'c') if (*fmt == 'c')
{ {
auto wd = static_cast<int>(detail::extract_weekday(os, fds)); auto wd = static_cast<int>(extract_weekday(os, fds));
os << detail::weekday_names().first[static_cast<unsigned>(wd)+7] os << weekday_names().first[static_cast<unsigned>(wd)+7]
<< ' '; << ' ';
os << detail::month_names().first[ os << month_names().first[extract_month(os, fds)-1+12] << ' ';
static_cast<unsigned>(fds.ymd.month())-1+12] << ' ';
auto d = static_cast<int>(static_cast<unsigned>(fds.ymd.day())); auto d = static_cast<int>(static_cast<unsigned>(fds.ymd.day()));
if (d < 10) if (d < 10)
os << ' '; os << ' ';
@ -4676,7 +4689,7 @@ to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
else // *fmt == 'x' else // *fmt == 'x'
{ {
auto const& ymd = fds.ymd; auto const& ymd = fds.ymd;
detail::save_stream<CharT, Traits> _(os); save_stream<CharT, Traits> _(os);
os.fill('0'); os.fill('0');
os.flags(std::ios::dec | std::ios::right); os.flags(std::ios::dec | std::ios::right);
os.width(2); os.width(2);
@ -4702,7 +4715,7 @@ to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
if (modified == CharT{}) if (modified == CharT{})
{ {
#endif #endif
detail::save_stream<CharT, Traits> _(os); save_stream<CharT, Traits> _(os);
os.fill('0'); os.fill('0');
os.flags(std::ios::dec | std::ios::right); os.flags(std::ios::dec | std::ios::right);
if (y >= 0) if (y >= 0)
@ -4744,7 +4757,7 @@ to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
if (modified == CharT{}) if (modified == CharT{})
{ {
#endif #endif
detail::save_stream<CharT, Traits> _(os); save_stream<CharT, Traits> _(os);
if (*fmt == CharT{'d'}) if (*fmt == CharT{'d'})
os.fill('0'); os.fill('0');
os.flags(std::ios::dec | std::ios::right); os.flags(std::ios::dec | std::ios::right);
@ -4775,7 +4788,7 @@ to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
if (modified == CharT{}) if (modified == CharT{})
{ {
auto const& ymd = fds.ymd; auto const& ymd = fds.ymd;
detail::save_stream<CharT, Traits> _(os); save_stream<CharT, Traits> _(os);
os.fill('0'); os.fill('0');
os.flags(std::ios::dec | std::ios::right); os.flags(std::ios::dec | std::ios::right);
os.width(2); os.width(2);
@ -4801,7 +4814,7 @@ to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
if (modified == CharT{}) if (modified == CharT{})
{ {
auto const& ymd = fds.ymd; auto const& ymd = fds.ymd;
detail::save_stream<CharT, Traits> _(os); save_stream<CharT, Traits> _(os);
os.fill('0'); os.fill('0');
os.flags(std::ios::dec | std::ios::right); os.flags(std::ios::dec | std::ios::right);
os.width(4); os.width(4);
@ -4836,7 +4849,7 @@ to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
os << y; os << y;
else else
{ {
detail::save_stream<CharT, Traits> _(os); save_stream<CharT, Traits> _(os);
os.fill('0'); os.fill('0');
os.flags(std::ios::dec | std::ios::right); os.flags(std::ios::dec | std::ios::right);
os.width(2); os.width(2);
@ -4894,7 +4907,7 @@ to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
auto ld = local_days(fds.ymd); auto ld = local_days(fds.ymd);
auto y = fds.ymd.year(); auto y = fds.ymd.year();
auto doy = ld - local_days(y/jan/1) + days{1}; auto doy = ld - local_days(y/jan/1) + days{1};
detail::save_stream<CharT, Traits> _(os); save_stream<CharT, Traits> _(os);
os.fill('0'); os.fill('0');
os.flags(std::ios::dec | std::ios::right); os.flags(std::ios::dec | std::ios::right);
os.width(3); os.width(3);
@ -5000,9 +5013,9 @@ to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
} }
#else #else
if (fds.tod.hours() < hours{12}) if (fds.tod.hours() < hours{12})
os << detail::ampm_names().first[0]; os << ampm_names().first[0];
else else
os << detail::ampm_names().first[1]; os << ampm_names().first[1];
#endif #endif
modified = CharT{}; modified = CharT{};
command = nullptr; command = nullptr;
@ -5029,7 +5042,7 @@ to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
#else #else
time_of_day<seconds> tod(duration_cast<seconds>(fds.tod.to_duration())); time_of_day<seconds> tod(duration_cast<seconds>(fds.tod.to_duration()));
tod.make12(); tod.make12();
detail::save_stream<CharT, Traits> _(os); save_stream<CharT, Traits> _(os);
os.fill('0'); os.fill('0');
os.width(2); os.width(2);
os << tod.hours().count() << CharT{':'}; os << tod.hours().count() << CharT{':'};
@ -5039,9 +5052,9 @@ to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
os << tod.seconds().count() << CharT{' '}; os << tod.seconds().count() << CharT{' '};
tod.make24(); tod.make24();
if (tod.hours() < hours{12}) if (tod.hours() < hours{12})
os << detail::ampm_names().first[0]; os << ampm_names().first[0];
else else
os << detail::ampm_names().first[1]; os << ampm_names().first[1];
#endif #endif
modified = CharT{}; modified = CharT{};
command = nullptr; command = nullptr;
@ -5133,7 +5146,7 @@ to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
case 'u': case 'u':
if (command) if (command)
{ {
auto wd = detail::extract_weekday(os, fds); auto wd = extract_weekday(os, fds);
if (os.fail()) if (os.fail())
return os; return os;
#if !ONLY_C_LOCALE #if !ONLY_C_LOCALE
@ -5185,7 +5198,7 @@ to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
{ {
const CharT f[] = {'%', modified, *fmt}; const CharT f[] = {'%', modified, *fmt};
tm.tm_year = static_cast<int>(ymd.year()) - 1900; tm.tm_year = static_cast<int>(ymd.year()) - 1900;
tm.tm_wday = static_cast<int>(detail::extract_weekday(os, fds)); tm.tm_wday = static_cast<int>(extract_weekday(os, fds));
if (os.fail()) if (os.fail())
return os; return os;
tm.tm_yday = static_cast<int>((ld - local_days(ymd.year()/1/1)).count()); tm.tm_yday = static_cast<int>((ld - local_days(ymd.year()/1/1)).count());
@ -5228,7 +5241,7 @@ to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
const CharT f[] = {'%', modified, *fmt}; const CharT f[] = {'%', modified, *fmt};
auto const& ymd = fds.ymd; auto const& ymd = fds.ymd;
tm.tm_year = static_cast<int>(ymd.year()) - 1900; tm.tm_year = static_cast<int>(ymd.year()) - 1900;
tm.tm_wday = static_cast<int>(detail::extract_weekday(os, fds)); tm.tm_wday = static_cast<int>(extract_weekday(os, fds));
if (os.fail()) if (os.fail())
return os; return os;
tm.tm_yday = static_cast<int>((ld - local_days(ymd.year()/1/1)).count()); tm.tm_yday = static_cast<int>((ld - local_days(ymd.year()/1/1)).count());
@ -5248,7 +5261,7 @@ to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
case 'w': case 'w':
if (command) if (command)
{ {
auto wd = detail::extract_weekday(os, fds); auto wd = extract_weekday(os, fds);
if (os.fail()) if (os.fail())
return os; return os;
#if !ONLY_C_LOCALE #if !ONLY_C_LOCALE
@ -5300,7 +5313,7 @@ to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
{ {
const CharT f[] = {'%', modified, *fmt}; const CharT f[] = {'%', modified, *fmt};
tm.tm_year = static_cast<int>(ymd.year()) - 1900; tm.tm_year = static_cast<int>(ymd.year()) - 1900;
tm.tm_wday = static_cast<int>(detail::extract_weekday(os, fds)); tm.tm_wday = static_cast<int>(extract_weekday(os, fds));
if (os.fail()) if (os.fail())
return os; return os;
tm.tm_yday = static_cast<int>((ld - local_days(ymd.year()/1/1)).count()); tm.tm_yday = static_cast<int>((ld - local_days(ymd.year()/1/1)).count());