forked from HowardHinnant/date
Set failbit instead of throw within to_stream
* This is for consistency with other std streaming operations.
This commit is contained in:
60
date.h
60
date.h
@ -4213,18 +4213,26 @@ struct fields
|
|||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
|
||||||
template <class Duration>
|
template <class CharT, class Traits, class Duration>
|
||||||
unsigned
|
unsigned
|
||||||
extract_weekday(const fields<Duration>& fds)
|
extract_weekday(std::basic_ostream<CharT, Traits>& os, const fields<Duration>& fds)
|
||||||
{
|
{
|
||||||
if (!fds.ymd.ok() && !fds.wd.ok())
|
if (!fds.ymd.ok() && !fds.wd.ok())
|
||||||
throw std::runtime_error("Can not format %u with unknown weekday");
|
{
|
||||||
|
// fds does not contain a valid weekday
|
||||||
|
os.setstate(std::ios::failbit);
|
||||||
|
return 7;
|
||||||
|
}
|
||||||
unsigned wd;
|
unsigned wd;
|
||||||
if (fds.ymd.ok())
|
if (fds.ymd.ok())
|
||||||
{
|
{
|
||||||
wd = static_cast<unsigned>(weekday{fds.ymd});
|
wd = static_cast<unsigned>(weekday{fds.ymd});
|
||||||
if (fds.wd.ok() && wd != static_cast<unsigned>(fds.wd))
|
if (fds.wd.ok() && wd != static_cast<unsigned>(fds.wd))
|
||||||
throw std::runtime_error("Can not format %u with inconsistent weekday");
|
{
|
||||||
|
// fds.ymd and fds.wd are inconsistent
|
||||||
|
os.setstate(std::ios::failbit);
|
||||||
|
return 7;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
wd = static_cast<unsigned>(fds.wd);
|
wd = static_cast<unsigned>(fds.wd);
|
||||||
@ -4247,10 +4255,6 @@ to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
|
|||||||
CharT modified = CharT{};
|
CharT modified = CharT{};
|
||||||
for (; *fmt; ++fmt)
|
for (; *fmt; ++fmt)
|
||||||
{
|
{
|
||||||
if (!command && modified != CharT{})
|
|
||||||
throw std::logic_error("loop invariant broken: !command && modified");
|
|
||||||
else if (modified != CharT{} && modified != CharT{'E'} && modified != CharT{'O'})
|
|
||||||
throw std::logic_error(std::string("bad value for modified: ") + char(modified));
|
|
||||||
switch (*fmt)
|
switch (*fmt)
|
||||||
{
|
{
|
||||||
case 'a':
|
case 'a':
|
||||||
@ -4259,7 +4263,9 @@ 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(fds));
|
tm.tm_wday = static_cast<int>(detail::extract_weekday(os, fds));
|
||||||
|
if (os.fail())
|
||||||
|
return;
|
||||||
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));
|
||||||
}
|
}
|
||||||
@ -4311,7 +4317,9 @@ to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
|
|||||||
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>(static_cast<unsigned>(ymd.month()) - 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(fds));
|
tm.tm_wday = static_cast<int>(detail::extract_weekday(os, fds));
|
||||||
|
if (os.fail())
|
||||||
|
return;
|
||||||
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());
|
||||||
CharT f[3] = {'%'};
|
CharT f[3] = {'%'};
|
||||||
auto fe = begin(f) + 1;
|
auto fe = begin(f) + 1;
|
||||||
@ -4720,7 +4728,9 @@ to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
|
|||||||
case 'u':
|
case 'u':
|
||||||
if (command)
|
if (command)
|
||||||
{
|
{
|
||||||
auto wd = detail::extract_weekday(fds);
|
auto wd = detail::extract_weekday(os, fds);
|
||||||
|
if (os.fail())
|
||||||
|
return;
|
||||||
if (modified == CharT{'O'})
|
if (modified == CharT{'O'})
|
||||||
{
|
{
|
||||||
const CharT f[] = {'%', modified, *fmt};
|
const CharT f[] = {'%', modified, *fmt};
|
||||||
@ -4751,7 +4761,9 @@ 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(fds));
|
tm.tm_wday = static_cast<int>(detail::extract_weekday(os, fds));
|
||||||
|
if (os.fail())
|
||||||
|
return;
|
||||||
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());
|
||||||
facet.put(os, os, os.fill(), &tm, begin(f), end(f));
|
facet.put(os, os, os.fill(), &tm, begin(f), end(f));
|
||||||
modified = CharT{};
|
modified = CharT{};
|
||||||
@ -4788,7 +4800,9 @@ 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(fds));
|
tm.tm_wday = static_cast<int>(detail::extract_weekday(os, fds));
|
||||||
|
if (os.fail())
|
||||||
|
return;
|
||||||
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());
|
||||||
facet.put(os, os, os.fill(), &tm, begin(f), end(f));
|
facet.put(os, os, os.fill(), &tm, begin(f), end(f));
|
||||||
modified = CharT{};
|
modified = CharT{};
|
||||||
@ -4820,7 +4834,9 @@ to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
|
|||||||
case 'w':
|
case 'w':
|
||||||
if (command)
|
if (command)
|
||||||
{
|
{
|
||||||
auto wd = detail::extract_weekday(fds);
|
auto wd = detail::extract_weekday(os, fds);
|
||||||
|
if (os.fail())
|
||||||
|
return;
|
||||||
if (modified == CharT{'O'})
|
if (modified == CharT{'O'})
|
||||||
{
|
{
|
||||||
const CharT f[] = {'%', modified, *fmt};
|
const CharT f[] = {'%', modified, *fmt};
|
||||||
@ -4851,7 +4867,9 @@ 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(fds));
|
tm.tm_wday = static_cast<int>(detail::extract_weekday(os, fds));
|
||||||
|
if (os.fail())
|
||||||
|
return;
|
||||||
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());
|
||||||
facet.put(os, os, os.fill(), &tm, begin(f), end(f));
|
facet.put(os, os, os.fill(), &tm, begin(f), end(f));
|
||||||
modified = CharT{};
|
modified = CharT{};
|
||||||
@ -4955,7 +4973,11 @@ to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
|
|||||||
if (command)
|
if (command)
|
||||||
{
|
{
|
||||||
if (offset_sec == nullptr)
|
if (offset_sec == nullptr)
|
||||||
throw std::runtime_error("Can not format %z with unknown offset");
|
{
|
||||||
|
// Can not format %z with unknown offset
|
||||||
|
os.setstate(ios::failbit);
|
||||||
|
return;
|
||||||
|
}
|
||||||
auto m = duration_cast<minutes>(*offset_sec);
|
auto m = duration_cast<minutes>(*offset_sec);
|
||||||
auto neg = m < minutes{0};
|
auto neg = m < minutes{0};
|
||||||
m = date::abs(m);
|
m = date::abs(m);
|
||||||
@ -4985,7 +5007,11 @@ to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
|
|||||||
if (modified == CharT{})
|
if (modified == CharT{})
|
||||||
{
|
{
|
||||||
if (abbrev == nullptr)
|
if (abbrev == nullptr)
|
||||||
throw std::runtime_error("Can not format %Z with unknown time_zone");
|
{
|
||||||
|
// Can not format %Z with unknown time_zone
|
||||||
|
os.setstate(ios::failbit);
|
||||||
|
return;
|
||||||
|
}
|
||||||
for (auto c : *abbrev)
|
for (auto c : *abbrev)
|
||||||
os << CharT(c);
|
os << CharT(c);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user