forked from HowardHinnant/date
And yet more fixes to allow duplicate flags on parse
This commit is contained in:
@@ -4664,13 +4664,15 @@ to_stream(std::basic_ostream<CharT, Traits>& os, const CharT* fmt,
|
|||||||
if (*fmt == 'c' && !fds.has_tod)
|
if (*fmt == 'c' && !fds.has_tod)
|
||||||
os.setstate(std::ios::failbit);
|
os.setstate(std::ios::failbit);
|
||||||
#if !ONLY_C_LOCALE
|
#if !ONLY_C_LOCALE
|
||||||
if (*fmt == 'c')
|
|
||||||
tm = std::tm{};
|
tm = std::tm{};
|
||||||
auto const& ymd = fds.ymd;
|
auto const& ymd = fds.ymd;
|
||||||
auto ld = local_days(ymd);
|
auto ld = local_days(ymd);
|
||||||
|
if (*fmt == 'c')
|
||||||
|
{
|
||||||
tm.tm_sec = static_cast<int>(fds.tod.seconds().count());
|
tm.tm_sec = static_cast<int>(fds.tod.seconds().count());
|
||||||
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>(extract_month(os, fds) - 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;
|
||||||
@@ -5990,6 +5992,20 @@ read(std::basic_istream<CharT, Traits>& is, rld a0, Args&& ...args)
|
|||||||
read(is, std::forward<Args>(args)...);
|
read(is, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class T, class CharT, class Traits>
|
||||||
|
inline
|
||||||
|
void
|
||||||
|
checked_set(T& value, T from, T not_a_value, std::basic_ios<CharT, Traits>& is)
|
||||||
|
{
|
||||||
|
if (!is.fail())
|
||||||
|
{
|
||||||
|
if (value == not_a_value)
|
||||||
|
value = std::move(from);
|
||||||
|
else if (value != from)
|
||||||
|
is.setstate(std::ios::failbit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace detail;
|
} // namespace detail;
|
||||||
|
|
||||||
template <class CharT, class Traits, class Duration, class Alloc = std::allocator<CharT>>
|
template <class CharT, class Traits, class Duration, class Alloc = std::allocator<CharT>>
|
||||||
@@ -6011,71 +6027,133 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
auto& f = use_facet<time_get<CharT>>(is.getloc());
|
auto& f = use_facet<time_get<CharT>>(is.getloc());
|
||||||
std::tm tm{};
|
std::tm tm{};
|
||||||
#endif
|
#endif
|
||||||
std::basic_string<CharT, Traits, Alloc> temp_abbrev;
|
|
||||||
minutes temp_offset{};
|
|
||||||
const CharT* command = nullptr;
|
const CharT* command = nullptr;
|
||||||
auto modified = CharT{};
|
auto modified = CharT{};
|
||||||
auto width = -1;
|
auto width = -1;
|
||||||
CONSTDATA int not_a_year = numeric_limits<short>::min();
|
|
||||||
int Y = not_a_year;
|
CONSTDATA int not_a_year = numeric_limits<int>::min();
|
||||||
CONSTDATA int not_a_century = not_a_year / 100;
|
|
||||||
int C = not_a_century;
|
|
||||||
CONSTDATA int not_a_2digit_year = 100;
|
CONSTDATA int not_a_2digit_year = 100;
|
||||||
int y = not_a_2digit_year;
|
CONSTDATA int not_a_century = not_a_year / 100;
|
||||||
CONSTDATA int not_a_month = 0;
|
CONSTDATA int not_a_month = 0;
|
||||||
CONSTDATA int not_a_day = 0;
|
CONSTDATA int not_a_day = 0;
|
||||||
CONSTDATA int not_a_doy = 0;
|
CONSTDATA int not_a_hour = numeric_limits<int>::min();
|
||||||
int m = not_a_month;
|
|
||||||
int d = not_a_day;
|
|
||||||
int j = not_a_doy;
|
|
||||||
CONSTDATA int not_a_weekday = 7;
|
|
||||||
int wd = not_a_weekday;
|
|
||||||
CONSTDATA int not_a_hour_12_value = 0;
|
CONSTDATA int not_a_hour_12_value = 0;
|
||||||
int I = not_a_hour_12_value;
|
CONSTDATA int not_a_minute = not_a_hour;
|
||||||
hours h{};
|
CONSTDATA Duration not_a_second = Duration::min();
|
||||||
minutes min{};
|
CONSTDATA int not_a_doy = 0;
|
||||||
Duration s{};
|
CONSTDATA int not_a_weekday = 7;
|
||||||
int g = not_a_2digit_year;
|
|
||||||
int G = not_a_year;
|
|
||||||
CONSTDATA int not_a_week_num = 100;
|
CONSTDATA int not_a_week_num = 100;
|
||||||
int V = not_a_week_num;
|
CONSTDATA int not_a_ampm = -1;
|
||||||
int U = not_a_week_num;
|
CONSTDATA minutes not_a_offset = minutes::min();
|
||||||
int W = not_a_week_num;
|
|
||||||
|
int Y = not_a_year; // c, F, Y *
|
||||||
|
int y = not_a_2digit_year; // D, x, y *
|
||||||
|
int g = not_a_2digit_year; // g *
|
||||||
|
int G = not_a_year; // G *
|
||||||
|
int C = not_a_century; // C *
|
||||||
|
int m = not_a_month; // b, B, h, m, c, D, F, x *
|
||||||
|
int d = not_a_day; // c, d, D, e, F, x *
|
||||||
|
int j = not_a_doy; // j *
|
||||||
|
int wd = not_a_weekday; // a, A, u, w *
|
||||||
|
int H = not_a_hour; // c, H, R, T, X *
|
||||||
|
int I = not_a_hour_12_value; // I, r *
|
||||||
|
int p = not_a_ampm; // p, r *
|
||||||
|
int M = not_a_minute; // c, M, r, R, T, X *
|
||||||
|
Duration s = not_a_second; // c, r, S, T, X *
|
||||||
|
int U = not_a_week_num; // U *
|
||||||
|
int V = not_a_week_num; // V *
|
||||||
|
int W = not_a_week_num; // W *
|
||||||
|
std::basic_string<CharT, Traits, Alloc> temp_abbrev; // Z *
|
||||||
|
minutes temp_offset = not_a_offset; // z *
|
||||||
|
|
||||||
using detail::read;
|
using detail::read;
|
||||||
using detail::rs;
|
using detail::rs;
|
||||||
using detail::ru;
|
using detail::ru;
|
||||||
using detail::rld;
|
using detail::rld;
|
||||||
|
using detail::checked_set;
|
||||||
for (; *fmt && is.rdstate() == std::ios::goodbit; ++fmt)
|
for (; *fmt && is.rdstate() == std::ios::goodbit; ++fmt)
|
||||||
{
|
{
|
||||||
switch (*fmt)
|
switch (*fmt)
|
||||||
{
|
{
|
||||||
case 'a':
|
case 'a':
|
||||||
case 'A':
|
case 'A':
|
||||||
|
case 'u':
|
||||||
|
case 'w': // wd: a, A, u, w
|
||||||
if (command)
|
if (command)
|
||||||
|
{
|
||||||
|
int trial_wd = not_a_weekday;
|
||||||
|
if (*fmt == 'a' || *fmt == 'A')
|
||||||
{
|
{
|
||||||
if (modified == CharT{})
|
if (modified == CharT{})
|
||||||
{
|
{
|
||||||
#if !ONLY_C_LOCALE
|
#if !ONLY_C_LOCALE
|
||||||
ios_base::iostate err = ios_base::goodbit;
|
ios_base::iostate err = ios_base::goodbit;
|
||||||
f.get(is, nullptr, is, err, &tm, command, fmt+1);
|
f.get(is, nullptr, is, err, &tm, command, fmt+1);
|
||||||
if ((err & ios::failbit) == 0)
|
|
||||||
wd = tm.tm_wday;
|
|
||||||
is.setstate(err);
|
is.setstate(err);
|
||||||
|
if (!is.fail())
|
||||||
|
trial_wd = tm.tm_wday;
|
||||||
#else
|
#else
|
||||||
auto nm = detail::weekday_names();
|
auto nm = detail::weekday_names();
|
||||||
auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first;
|
auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first;
|
||||||
if (!is.fail())
|
if (!is.fail())
|
||||||
wd = i % 7;
|
trial_wd = i % 7;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
read(is, CharT{'%'}, width, modified, *fmt);
|
read(is, CharT{'%'}, width, modified, *fmt);
|
||||||
|
}
|
||||||
|
else // *fmt == 'u' || *fmt == 'w'
|
||||||
|
{
|
||||||
|
#if !ONLY_C_LOCALE
|
||||||
|
if (modified == CharT{})
|
||||||
|
#else
|
||||||
|
if (modified != CharT{'E'})
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
read(is, ru{trial_wd, 1, width == -1 ? 1u : static_cast<unsigned>(width)});
|
||||||
|
if (!is.fail())
|
||||||
|
{
|
||||||
|
if (*fmt == 'u')
|
||||||
|
{
|
||||||
|
if (!(1 <= trial_wd && trial_wd <= 7))
|
||||||
|
{
|
||||||
|
trial_wd = not_a_weekday;
|
||||||
|
is.setstate(ios_base::failbit);
|
||||||
|
}
|
||||||
|
else if (trial_wd == 7)
|
||||||
|
trial_wd = 0;
|
||||||
|
}
|
||||||
|
else // *fmt == 'w'
|
||||||
|
{
|
||||||
|
if (!(0 <= trial_wd && trial_wd <= 6))
|
||||||
|
{
|
||||||
|
trial_wd = not_a_weekday;
|
||||||
|
is.setstate(ios_base::failbit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if !ONLY_C_LOCALE
|
||||||
|
else if (modified == CharT{'O'})
|
||||||
|
{
|
||||||
|
ios_base::iostate err = ios_base::goodbit;
|
||||||
|
f.get(is, nullptr, is, err, &tm, command, fmt+1);
|
||||||
|
is.setstate(err);
|
||||||
|
if (!is.fail())
|
||||||
|
trial_wd = tm.tm_wday;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
read(is, CharT{'%'}, width, modified, *fmt);
|
||||||
|
}
|
||||||
|
if (trial_wd != not_a_weekday)
|
||||||
|
checked_set(wd, trial_wd, not_a_weekday, is);
|
||||||
|
}
|
||||||
|
else // !command
|
||||||
|
read(is, *fmt);
|
||||||
command = nullptr;
|
command = nullptr;
|
||||||
width = -1;
|
width = -1;
|
||||||
modified = CharT{};
|
modified = CharT{};
|
||||||
}
|
|
||||||
else
|
|
||||||
read(is, *fmt);
|
|
||||||
break;
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
case 'B':
|
case 'B':
|
||||||
@@ -6084,18 +6162,20 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
{
|
{
|
||||||
if (modified == CharT{})
|
if (modified == CharT{})
|
||||||
{
|
{
|
||||||
|
int ttm = not_a_month;
|
||||||
#if !ONLY_C_LOCALE
|
#if !ONLY_C_LOCALE
|
||||||
ios_base::iostate err = ios_base::goodbit;
|
ios_base::iostate err = ios_base::goodbit;
|
||||||
f.get(is, nullptr, is, err, &tm, command, fmt+1);
|
f.get(is, nullptr, is, err, &tm, command, fmt+1);
|
||||||
if ((err & ios::failbit) == 0)
|
if ((err & ios::failbit) == 0)
|
||||||
m = tm.tm_mon + 1;
|
ttm = tm.tm_mon + 1;
|
||||||
is.setstate(err);
|
is.setstate(err);
|
||||||
#else
|
#else
|
||||||
auto nm = detail::month_names();
|
auto nm = detail::month_names();
|
||||||
auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first;
|
auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first;
|
||||||
if (!is.fail())
|
if (!is.fail())
|
||||||
m = i % 12 + 1;
|
ttm = i % 12 + 1;
|
||||||
#endif
|
#endif
|
||||||
|
checked_set(m, ttm, not_a_month, is);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
read(is, CharT{'%'}, width, modified, *fmt);
|
read(is, CharT{'%'}, width, modified, *fmt);
|
||||||
@@ -6116,45 +6196,44 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
f.get(is, nullptr, is, err, &tm, command, fmt+1);
|
f.get(is, nullptr, is, err, &tm, command, fmt+1);
|
||||||
if ((err & ios::failbit) == 0)
|
if ((err & ios::failbit) == 0)
|
||||||
{
|
{
|
||||||
Y = tm.tm_year + 1900;
|
checked_set(Y, tm.tm_year + 1900, not_a_year, is);
|
||||||
m = tm.tm_mon + 1;
|
checked_set(m, tm.tm_mon + 1, not_a_month, is);
|
||||||
d = tm.tm_mday;
|
checked_set(d, tm.tm_mday, not_a_day, is);
|
||||||
h = hours{tm.tm_hour};
|
checked_set(H, tm.tm_hour, not_a_hour, is);
|
||||||
min = minutes{tm.tm_min};
|
checked_set(M, tm.tm_min, not_a_minute, is);
|
||||||
s = duration_cast<Duration>(seconds{tm.tm_sec});
|
checked_set(s, duration_cast<Duration>(seconds{tm.tm_sec}),
|
||||||
|
not_a_second, is);
|
||||||
}
|
}
|
||||||
is.setstate(err);
|
is.setstate(err);
|
||||||
#else
|
#else
|
||||||
|
// "%a %b %e %T %Y"
|
||||||
auto nm = detail::weekday_names();
|
auto nm = detail::weekday_names();
|
||||||
auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first;
|
auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first;
|
||||||
if (is.fail())
|
checked_set(wd, static_cast<int>(i % 7), not_a_weekday, is);
|
||||||
goto broken;
|
|
||||||
wd = i % 7;
|
|
||||||
ws(is);
|
ws(is);
|
||||||
nm = detail::month_names();
|
nm = detail::month_names();
|
||||||
i = detail::scan_keyword(is, nm.first, nm.second) - nm.first;
|
i = detail::scan_keyword(is, nm.first, nm.second) - nm.first;
|
||||||
if (is.fail())
|
checked_set(m, static_cast<int>(i % 12 + 1), not_a_month, is);
|
||||||
goto broken;
|
|
||||||
m = i % 12 + 1;
|
|
||||||
ws(is);
|
ws(is);
|
||||||
read(is, rs{d, 1, 2});
|
int td = not_a_day;
|
||||||
if (is.fail())
|
read(is, rs{td, 1, 2});
|
||||||
goto broken;
|
checked_set(d, td, not_a_day, is);
|
||||||
ws(is);
|
ws(is);
|
||||||
using dfs = detail::decimal_format_seconds<Duration>;
|
using dfs = detail::decimal_format_seconds<Duration>;
|
||||||
CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width;
|
CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width;
|
||||||
int H;
|
int tH;
|
||||||
int M;
|
int tM;
|
||||||
long double S;
|
long double S;
|
||||||
read(is, ru{H, 1, 2}, CharT{':'}, ru{M, 1, 2},
|
read(is, ru{tH, 1, 2}, CharT{':'}, ru{tM, 1, 2},
|
||||||
CharT{':'}, rld{S, 1, w});
|
CharT{':'}, rld{S, 1, w});
|
||||||
if (is.fail())
|
checked_set(H, tH, not_a_hour, is);
|
||||||
goto broken;
|
checked_set(M, tM, not_a_minute, is);
|
||||||
h = hours{H};
|
checked_set(s, round<Duration>(duration<long double>{S}),
|
||||||
min = minutes{M};
|
not_a_second, is);
|
||||||
s = round<Duration>(duration<long double>{S});
|
|
||||||
ws(is);
|
ws(is);
|
||||||
read(is, rs{Y, 1, 4u});
|
int tY = not_a_year;
|
||||||
|
read(is, rs{tY, 1, 4u});
|
||||||
|
checked_set(Y, tY, not_a_year, is);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -6176,14 +6255,21 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
f.get(is, nullptr, is, err, &tm, command, fmt+1);
|
f.get(is, nullptr, is, err, &tm, command, fmt+1);
|
||||||
if ((err & ios::failbit) == 0)
|
if ((err & ios::failbit) == 0)
|
||||||
{
|
{
|
||||||
Y = tm.tm_year + 1900;
|
checked_set(Y, tm.tm_year + 1900, not_a_year, is);
|
||||||
m = tm.tm_mon + 1;
|
checked_set(m, tm.tm_mon + 1, not_a_month, is);
|
||||||
d = tm.tm_mday;
|
checked_set(d, tm.tm_mday, not_a_day, is);
|
||||||
}
|
}
|
||||||
is.setstate(err);
|
is.setstate(err);
|
||||||
#else
|
#else
|
||||||
read(is, ru{m, 1, 2}, CharT{'/'}, ru{d, 1, 2}, CharT{'/'},
|
// "%m/%d/%y"
|
||||||
rs{y, 1, 2});
|
int ty = not_a_2digit_year;
|
||||||
|
int tm = not_a_month;
|
||||||
|
int td = not_a_day;
|
||||||
|
read(is, ru{tm, 1, 2}, CharT{'/'}, ru{td, 1, 2}, CharT{'/'},
|
||||||
|
rs{ty, 1, 2});
|
||||||
|
checked_set(y, ty, not_a_2digit_year, is);
|
||||||
|
checked_set(m, tm, not_a_month, is);
|
||||||
|
checked_set(d, td, not_a_day, is);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -6205,25 +6291,25 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
f.get(is, nullptr, is, err, &tm, command, fmt+1);
|
f.get(is, nullptr, is, err, &tm, command, fmt+1);
|
||||||
if ((err & ios::failbit) == 0)
|
if ((err & ios::failbit) == 0)
|
||||||
{
|
{
|
||||||
h = hours{tm.tm_hour};
|
checked_set(H, tm.tm_hour, not_a_hour, is);
|
||||||
min = minutes{tm.tm_min};
|
checked_set(M, tm.tm_min, not_a_minute, is);
|
||||||
s = duration_cast<Duration>(seconds{tm.tm_sec});
|
checked_set(s, duration_cast<Duration>(seconds{tm.tm_sec}),
|
||||||
|
not_a_second, is);
|
||||||
}
|
}
|
||||||
is.setstate(err);
|
is.setstate(err);
|
||||||
#else
|
#else
|
||||||
|
// "%T"
|
||||||
using dfs = detail::decimal_format_seconds<Duration>;
|
using dfs = detail::decimal_format_seconds<Duration>;
|
||||||
CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width;
|
CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width;
|
||||||
int H;
|
int tH = not_a_hour;
|
||||||
int M;
|
int tM = not_a_minute;
|
||||||
long double S;
|
long double S;
|
||||||
read(is, ru{H, 1, 2}, CharT{':'}, ru{M, 1, 2},
|
read(is, ru{tH, 1, 2}, CharT{':'}, ru{tM, 1, 2},
|
||||||
CharT{':'}, rld{S, 1, w});
|
CharT{':'}, rld{S, 1, w});
|
||||||
if (!is.fail())
|
checked_set(H, tH, not_a_hour, is);
|
||||||
{
|
checked_set(M, tM, not_a_minute, is);
|
||||||
h = hours{H};
|
checked_set(s, round<Duration>(duration<long double>{S}),
|
||||||
min = minutes{M};
|
not_a_second, is);
|
||||||
s = round<Duration>(duration<long double>{S});
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -6238,11 +6324,12 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
case 'C':
|
case 'C':
|
||||||
if (command)
|
if (command)
|
||||||
{
|
{
|
||||||
|
int tC = not_a_century;
|
||||||
#if !ONLY_C_LOCALE
|
#if !ONLY_C_LOCALE
|
||||||
if (modified == CharT{})
|
if (modified == CharT{})
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
read(is, rs{C, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
|
read(is, rs{tC, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
|
||||||
#if !ONLY_C_LOCALE
|
#if !ONLY_C_LOCALE
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -6252,11 +6339,12 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
if ((err & ios::failbit) == 0)
|
if ((err & ios::failbit) == 0)
|
||||||
{
|
{
|
||||||
auto tY = tm.tm_year + 1900;
|
auto tY = tm.tm_year + 1900;
|
||||||
C = (tY >= 0 ? tY : tY-99) / 100;
|
tC = (tY >= 0 ? tY : tY-99) / 100;
|
||||||
}
|
}
|
||||||
is.setstate(err);
|
is.setstate(err);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
checked_set(C, tC, not_a_century, is);
|
||||||
command = nullptr;
|
command = nullptr;
|
||||||
width = -1;
|
width = -1;
|
||||||
modified = CharT{};
|
modified = CharT{};
|
||||||
@@ -6268,9 +6356,17 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
if (command)
|
if (command)
|
||||||
{
|
{
|
||||||
if (modified == CharT{})
|
if (modified == CharT{})
|
||||||
read(is, ru{m, 1, 2}, CharT{'\0'}, CharT{'/'}, CharT{'\0'},
|
{
|
||||||
ru{d, 1, 2}, CharT{'\0'}, CharT{'/'}, CharT{'\0'},
|
int tm = not_a_month;
|
||||||
rs{y, 1, 2});
|
int td = not_a_day;
|
||||||
|
int ty = not_a_2digit_year;
|
||||||
|
read(is, ru{tm, 1, 2}, CharT{'\0'}, CharT{'/'}, CharT{'\0'},
|
||||||
|
ru{td, 1, 2}, CharT{'\0'}, CharT{'/'}, CharT{'\0'},
|
||||||
|
rs{ty, 1, 2});
|
||||||
|
checked_set(y, ty, not_a_2digit_year, is);
|
||||||
|
checked_set(m, tm, not_a_month, is);
|
||||||
|
checked_set(d, td, not_a_day, is);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
read(is, CharT{'%'}, width, modified, *fmt);
|
read(is, CharT{'%'}, width, modified, *fmt);
|
||||||
command = nullptr;
|
command = nullptr;
|
||||||
@@ -6284,8 +6380,16 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
if (command)
|
if (command)
|
||||||
{
|
{
|
||||||
if (modified == CharT{})
|
if (modified == CharT{})
|
||||||
read(is, rs{Y, 1, width == -1 ? 4u : static_cast<unsigned>(width)},
|
{
|
||||||
CharT{'-'}, ru{m, 1, 2}, CharT{'-'}, ru{d, 1, 2});
|
int tY = not_a_year;
|
||||||
|
int tm = not_a_month;
|
||||||
|
int td = not_a_day;
|
||||||
|
read(is, rs{tY, 1, width == -1 ? 4u : static_cast<unsigned>(width)},
|
||||||
|
CharT{'-'}, ru{tm, 1, 2}, CharT{'-'}, ru{td, 1, 2});
|
||||||
|
checked_set(Y, tY, not_a_year, is);
|
||||||
|
checked_set(m, tm, not_a_month, is);
|
||||||
|
checked_set(d, td, not_a_day, is);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
read(is, CharT{'%'}, width, modified, *fmt);
|
read(is, CharT{'%'}, width, modified, *fmt);
|
||||||
command = nullptr;
|
command = nullptr;
|
||||||
@@ -6305,7 +6409,9 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
if (modified != CharT{'E'})
|
if (modified != CharT{'E'})
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
read(is, rs{d, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
|
int td = not_a_day;
|
||||||
|
read(is, rs{td, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
|
||||||
|
checked_set(d, td, not_a_day, is);
|
||||||
}
|
}
|
||||||
#if !ONLY_C_LOCALE
|
#if !ONLY_C_LOCALE
|
||||||
else if (modified == CharT{'O'})
|
else if (modified == CharT{'O'})
|
||||||
@@ -6316,7 +6422,7 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
width = -1;
|
width = -1;
|
||||||
modified = CharT{};
|
modified = CharT{};
|
||||||
if ((err & ios::failbit) == 0)
|
if ((err & ios::failbit) == 0)
|
||||||
d = tm.tm_mday;
|
checked_set(d, tm.tm_mday, not_a_day, is);
|
||||||
is.setstate(err);
|
is.setstate(err);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -6338,10 +6444,9 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
if (modified != CharT{'E'})
|
if (modified != CharT{'E'})
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
int H;
|
int tH = not_a_hour;
|
||||||
read(is, ru{H, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
|
read(is, ru{tH, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
|
||||||
if (!is.fail())
|
checked_set(H, tH, not_a_hour, is);
|
||||||
h = hours{H};
|
|
||||||
}
|
}
|
||||||
#if !ONLY_C_LOCALE
|
#if !ONLY_C_LOCALE
|
||||||
else if (modified == CharT{'O'})
|
else if (modified == CharT{'O'})
|
||||||
@@ -6349,7 +6454,7 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
ios_base::iostate err = ios_base::goodbit;
|
ios_base::iostate err = ios_base::goodbit;
|
||||||
f.get(is, nullptr, is, err, &tm, command, fmt+1);
|
f.get(is, nullptr, is, err, &tm, command, fmt+1);
|
||||||
if ((err & ios::failbit) == 0)
|
if ((err & ios::failbit) == 0)
|
||||||
h = hours{tm.tm_hour};
|
checked_set(H, tm.tm_hour, not_a_hour, is);
|
||||||
is.setstate(err);
|
is.setstate(err);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -6367,16 +6472,12 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
{
|
{
|
||||||
if (modified == CharT{})
|
if (modified == CharT{})
|
||||||
{
|
{
|
||||||
|
int tI = not_a_hour_12_value;
|
||||||
// reads in an hour into I, but most be in [1, 12]
|
// reads in an hour into I, but most be in [1, 12]
|
||||||
read(is, rs{I, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
|
read(is, rs{tI, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
|
||||||
if (I != not_a_hour_12_value)
|
if (!(1 <= tI && tI <= 12))
|
||||||
{
|
is.setstate(ios::failbit);
|
||||||
if (!(1 <= I && I <= 12))
|
checked_set(I, tI, not_a_hour_12_value, is);
|
||||||
{
|
|
||||||
I = not_a_hour_12_value;
|
|
||||||
goto broken;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
read(is, CharT{'%'}, width, modified, *fmt);
|
read(is, CharT{'%'}, width, modified, *fmt);
|
||||||
@@ -6391,7 +6492,11 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
if (command)
|
if (command)
|
||||||
{
|
{
|
||||||
if (modified == CharT{})
|
if (modified == CharT{})
|
||||||
read(is, ru{j, 1, width == -1 ? 3u : static_cast<unsigned>(width)});
|
{
|
||||||
|
int tj = not_a_doy;
|
||||||
|
read(is, ru{tj, 1, width == -1 ? 3u : static_cast<unsigned>(width)});
|
||||||
|
checked_set(j, tj, not_a_doy, is);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
read(is, CharT{'%'}, width, modified, *fmt);
|
read(is, CharT{'%'}, width, modified, *fmt);
|
||||||
command = nullptr;
|
command = nullptr;
|
||||||
@@ -6410,10 +6515,9 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
if (modified != CharT{'E'})
|
if (modified != CharT{'E'})
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
int M;
|
int tM = not_a_minute;
|
||||||
read(is, ru{M, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
|
read(is, ru{tM, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
|
||||||
if (!is.fail())
|
checked_set(M, tM, not_a_minute, is);
|
||||||
min = minutes{M};
|
|
||||||
}
|
}
|
||||||
#if !ONLY_C_LOCALE
|
#if !ONLY_C_LOCALE
|
||||||
else if (modified == CharT{'O'})
|
else if (modified == CharT{'O'})
|
||||||
@@ -6421,7 +6525,7 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
ios_base::iostate err = ios_base::goodbit;
|
ios_base::iostate err = ios_base::goodbit;
|
||||||
f.get(is, nullptr, is, err, &tm, command, fmt+1);
|
f.get(is, nullptr, is, err, &tm, command, fmt+1);
|
||||||
if ((err & ios::failbit) == 0)
|
if ((err & ios::failbit) == 0)
|
||||||
min = minutes{tm.tm_min};
|
checked_set(M, tm.tm_min, not_a_minute, is);
|
||||||
is.setstate(err);
|
is.setstate(err);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -6442,14 +6546,18 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
#else
|
#else
|
||||||
if (modified != CharT{'E'})
|
if (modified != CharT{'E'})
|
||||||
#endif
|
#endif
|
||||||
read(is, rs{m, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
|
{
|
||||||
|
int tm = not_a_month;
|
||||||
|
read(is, rs{tm, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
|
||||||
|
checked_set(m, tm, not_a_month, is);
|
||||||
|
}
|
||||||
#if !ONLY_C_LOCALE
|
#if !ONLY_C_LOCALE
|
||||||
else if (modified == CharT{'O'})
|
else if (modified == CharT{'O'})
|
||||||
{
|
{
|
||||||
ios_base::iostate err = ios_base::goodbit;
|
ios_base::iostate err = ios_base::goodbit;
|
||||||
f.get(is, nullptr, is, err, &tm, command, fmt+1);
|
f.get(is, nullptr, is, err, &tm, command, fmt+1);
|
||||||
if ((err & ios::failbit) == 0)
|
if ((err & ios::failbit) == 0)
|
||||||
m = tm.tm_mon + 1;
|
checked_set(m, tm.tm_mon + 1, not_a_month, is);
|
||||||
is.setstate(err);
|
is.setstate(err);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -6496,39 +6604,29 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
read(is, *fmt);
|
read(is, *fmt);
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
// Error if haven't yet seen %I
|
|
||||||
if (command)
|
if (command)
|
||||||
{
|
{
|
||||||
if (modified == CharT{})
|
if (modified == CharT{})
|
||||||
{
|
{
|
||||||
|
int tp = not_a_ampm;
|
||||||
#if !ONLY_C_LOCALE
|
#if !ONLY_C_LOCALE
|
||||||
if (I == not_a_hour_12_value)
|
|
||||||
goto broken;
|
|
||||||
tm = std::tm{};
|
tm = std::tm{};
|
||||||
tm.tm_hour = I;
|
tm.tm_hour = 1;
|
||||||
ios_base::iostate err = ios_base::goodbit;
|
ios_base::iostate err = ios_base::goodbit;
|
||||||
f.get(is, nullptr, is, err, &tm, command, fmt+1);
|
f.get(is, nullptr, is, err, &tm, command, fmt+1);
|
||||||
if (err & ios::failbit)
|
is.setstate(err);
|
||||||
goto broken;
|
if (tm.tm_hour == 1)
|
||||||
h = hours{tm.tm_hour};
|
tp = 0;
|
||||||
I = not_a_hour_12_value;
|
else if (tm.tm_hour == 13)
|
||||||
|
tp = 1;
|
||||||
|
else
|
||||||
|
is.setstate(err);
|
||||||
#else
|
#else
|
||||||
if (I == not_a_hour_12_value)
|
|
||||||
goto broken;
|
|
||||||
auto nm = detail::ampm_names();
|
auto nm = detail::ampm_names();
|
||||||
auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first;
|
auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first;
|
||||||
if (is.fail())
|
tp = i;
|
||||||
goto broken;
|
|
||||||
h = hours{I};
|
|
||||||
if (i == 1)
|
|
||||||
{
|
|
||||||
if (h != hours{12})
|
|
||||||
h += hours{12};
|
|
||||||
}
|
|
||||||
else if (h == hours{12})
|
|
||||||
h = hours{0};
|
|
||||||
I = not_a_hour_12_value;
|
|
||||||
#endif
|
#endif
|
||||||
|
checked_set(p, tp, not_a_ampm, is);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
read(is, CharT{'%'}, width, modified, *fmt);
|
read(is, CharT{'%'}, width, modified, *fmt);
|
||||||
@@ -6550,36 +6648,29 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
f.get(is, nullptr, is, err, &tm, command, fmt+1);
|
f.get(is, nullptr, is, err, &tm, command, fmt+1);
|
||||||
if ((err & ios::failbit) == 0)
|
if ((err & ios::failbit) == 0)
|
||||||
{
|
{
|
||||||
h = hours{tm.tm_hour};
|
checked_set(H, tm.tm_hour, not_a_hour, is);
|
||||||
min = minutes{tm.tm_min};
|
checked_set(M, tm.tm_min, not_a_hour, is);
|
||||||
s = duration_cast<Duration>(seconds{tm.tm_sec});
|
checked_set(s, duration_cast<Duration>(seconds{tm.tm_sec}),
|
||||||
|
not_a_second, is);
|
||||||
}
|
}
|
||||||
is.setstate(err);
|
is.setstate(err);
|
||||||
#else
|
#else
|
||||||
|
// "%I:%M:%S %p"
|
||||||
using dfs = detail::decimal_format_seconds<Duration>;
|
using dfs = detail::decimal_format_seconds<Duration>;
|
||||||
CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width;
|
CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width;
|
||||||
int H;
|
|
||||||
int M;
|
|
||||||
long double S;
|
long double S;
|
||||||
read(is, ru{H, 1, 2}, CharT{':'}, ru{M, 1, 2},
|
int tI = not_a_hour_12_value;
|
||||||
|
int tM = not_a_minute;
|
||||||
|
read(is, ru{tI, 1, 2}, CharT{':'}, ru{tM, 1, 2},
|
||||||
CharT{':'}, rld{S, 1, w});
|
CharT{':'}, rld{S, 1, w});
|
||||||
if (is.fail() || !(1 <= H && H <= 12))
|
checked_set(I, tI, not_a_hour_12_value, is);
|
||||||
goto broken;
|
checked_set(M, tM, not_a_minute, is);
|
||||||
|
checked_set(s, round<Duration>(duration<long double>{S}),
|
||||||
|
not_a_second, is);
|
||||||
ws(is);
|
ws(is);
|
||||||
auto nm = detail::ampm_names();
|
auto nm = detail::ampm_names();
|
||||||
auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first;
|
auto i = detail::scan_keyword(is, nm.first, nm.second) - nm.first;
|
||||||
if (is.fail())
|
checked_set(p, static_cast<int>(i), not_a_ampm, is);
|
||||||
goto broken;
|
|
||||||
h = hours{H};
|
|
||||||
if (i == 1)
|
|
||||||
{
|
|
||||||
if (h != hours{12})
|
|
||||||
h += hours{12};
|
|
||||||
}
|
|
||||||
else if (h == hours{12})
|
|
||||||
h = hours{0};
|
|
||||||
min = minutes{M};
|
|
||||||
s = round<Duration>(duration<long double>{S});
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -6596,14 +6687,12 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
{
|
{
|
||||||
if (modified == CharT{})
|
if (modified == CharT{})
|
||||||
{
|
{
|
||||||
int H, M;
|
int tH = not_a_hour;
|
||||||
read(is, ru{H, 1, 2}, CharT{'\0'}, CharT{':'}, CharT{'\0'},
|
int tM = not_a_minute;
|
||||||
ru{M, 1, 2}, CharT{'\0'});
|
read(is, ru{tH, 1, 2}, CharT{'\0'}, CharT{':'}, CharT{'\0'},
|
||||||
if (!is.fail())
|
ru{tM, 1, 2}, CharT{'\0'});
|
||||||
{
|
checked_set(H, tH, not_a_hour, is);
|
||||||
h = hours{H};
|
checked_set(M, tM, not_a_minute, is);
|
||||||
min = minutes{M};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
read(is, CharT{'%'}, width, modified, *fmt);
|
read(is, CharT{'%'}, width, modified, *fmt);
|
||||||
@@ -6627,8 +6716,8 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width;
|
CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width;
|
||||||
long double S;
|
long double S;
|
||||||
read(is, rld{S, 1, width == -1 ? w : static_cast<unsigned>(width)});
|
read(is, rld{S, 1, width == -1 ? w : static_cast<unsigned>(width)});
|
||||||
if (!is.fail())
|
checked_set(s, round<Duration>(duration<long double>{S}),
|
||||||
s = round<Duration>(duration<long double>{S});
|
not_a_second, is);
|
||||||
}
|
}
|
||||||
#if !ONLY_C_LOCALE
|
#if !ONLY_C_LOCALE
|
||||||
else if (modified == CharT{'O'})
|
else if (modified == CharT{'O'})
|
||||||
@@ -6636,7 +6725,8 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
ios_base::iostate err = ios_base::goodbit;
|
ios_base::iostate err = ios_base::goodbit;
|
||||||
f.get(is, nullptr, is, err, &tm, command, fmt+1);
|
f.get(is, nullptr, is, err, &tm, command, fmt+1);
|
||||||
if ((err & ios::failbit) == 0)
|
if ((err & ios::failbit) == 0)
|
||||||
s = duration_cast<Duration>(seconds{tm.tm_sec});
|
checked_set(s, duration_cast<Duration>(seconds{tm.tm_sec}),
|
||||||
|
not_a_second, is);
|
||||||
is.setstate(err);
|
is.setstate(err);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -6656,17 +6746,15 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
{
|
{
|
||||||
using dfs = detail::decimal_format_seconds<Duration>;
|
using dfs = detail::decimal_format_seconds<Duration>;
|
||||||
CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width;
|
CONSTDATA auto w = Duration::period::den == 1 ? 2 : 3 + dfs::width;
|
||||||
int H;
|
int tH = not_a_hour;
|
||||||
int M;
|
int tM = not_a_minute;
|
||||||
long double S;
|
long double S;
|
||||||
read(is, ru{H, 1, 2}, CharT{':'}, ru{M, 1, 2},
|
read(is, ru{tH, 1, 2}, CharT{':'}, ru{tM, 1, 2},
|
||||||
CharT{':'}, rld{S, 1, w});
|
CharT{':'}, rld{S, 1, w});
|
||||||
if (!is.fail())
|
checked_set(H, tH, not_a_hour, is);
|
||||||
{
|
checked_set(M, tM, not_a_minute, is);
|
||||||
h = hours{H};
|
checked_set(s, round<Duration>(duration<long double>{S}),
|
||||||
min = minutes{M};
|
not_a_second, is);
|
||||||
s = round<Duration>(duration<long double>{S});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
read(is, CharT{'%'}, width, modified, *fmt);
|
read(is, CharT{'%'}, width, modified, *fmt);
|
||||||
@@ -6685,14 +6773,18 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
#else
|
#else
|
||||||
if (modified != CharT{'O'})
|
if (modified != CharT{'O'})
|
||||||
#endif
|
#endif
|
||||||
read(is, rs{Y, 1, width == -1 ? 4u : static_cast<unsigned>(width)});
|
{
|
||||||
|
int tY = not_a_year;
|
||||||
|
read(is, rs{tY, 1, width == -1 ? 4u : static_cast<unsigned>(width)});
|
||||||
|
checked_set(Y, tY, not_a_year, is);
|
||||||
|
}
|
||||||
#if !ONLY_C_LOCALE
|
#if !ONLY_C_LOCALE
|
||||||
else if (modified == CharT{'E'})
|
else if (modified == CharT{'E'})
|
||||||
{
|
{
|
||||||
ios_base::iostate err = ios_base::goodbit;
|
ios_base::iostate err = ios_base::goodbit;
|
||||||
f.get(is, nullptr, is, err, &tm, command, fmt+1);
|
f.get(is, nullptr, is, err, &tm, command, fmt+1);
|
||||||
if ((err & ios::failbit) == 0)
|
if ((err & ios::failbit) == 0)
|
||||||
Y = tm.tm_year + 1900;
|
checked_set(Y, tm.tm_year + 1900, not_a_year, is);
|
||||||
is.setstate(err);
|
is.setstate(err);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -6711,14 +6803,18 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
#if !ONLY_C_LOCALE
|
#if !ONLY_C_LOCALE
|
||||||
if (modified == CharT{})
|
if (modified == CharT{})
|
||||||
#endif
|
#endif
|
||||||
read(is, ru{y, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
|
{
|
||||||
|
int ty = not_a_2digit_year;
|
||||||
|
read(is, ru{ty, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
|
||||||
|
checked_set(y, ty, not_a_2digit_year, is);
|
||||||
|
}
|
||||||
#if !ONLY_C_LOCALE
|
#if !ONLY_C_LOCALE
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ios_base::iostate err = ios_base::goodbit;
|
ios_base::iostate err = ios_base::goodbit;
|
||||||
f.get(is, nullptr, is, err, &tm, command, fmt+1);
|
f.get(is, nullptr, is, err, &tm, command, fmt+1);
|
||||||
if ((err & ios::failbit) == 0)
|
if ((err & ios::failbit) == 0)
|
||||||
Y = tm.tm_year + 1900;
|
checked_set(Y, tm.tm_year + 1900, not_a_year, is);
|
||||||
is.setstate(err);
|
is.setstate(err);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -6733,7 +6829,11 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
if (command)
|
if (command)
|
||||||
{
|
{
|
||||||
if (modified == CharT{})
|
if (modified == CharT{})
|
||||||
read(is, ru{g, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
|
{
|
||||||
|
int tg = not_a_2digit_year;
|
||||||
|
read(is, ru{tg, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
|
||||||
|
checked_set(g, tg, not_a_2digit_year, is);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
read(is, CharT{'%'}, width, modified, *fmt);
|
read(is, CharT{'%'}, width, modified, *fmt);
|
||||||
command = nullptr;
|
command = nullptr;
|
||||||
@@ -6747,7 +6847,11 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
if (command)
|
if (command)
|
||||||
{
|
{
|
||||||
if (modified == CharT{})
|
if (modified == CharT{})
|
||||||
read(is, rs{G, 1, width == -1 ? 4u : static_cast<unsigned>(width)});
|
{
|
||||||
|
int tG = not_a_year;
|
||||||
|
read(is, rs{tG, 1, width == -1 ? 4u : static_cast<unsigned>(width)});
|
||||||
|
checked_set(G, tG, not_a_year, is);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
read(is, CharT{'%'}, width, modified, *fmt);
|
read(is, CharT{'%'}, width, modified, *fmt);
|
||||||
command = nullptr;
|
command = nullptr;
|
||||||
@@ -6761,7 +6865,11 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
if (command)
|
if (command)
|
||||||
{
|
{
|
||||||
if (modified == CharT{})
|
if (modified == CharT{})
|
||||||
read(is, ru{U, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
|
{
|
||||||
|
int tU = not_a_week_num;
|
||||||
|
read(is, ru{tU, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
|
||||||
|
checked_set(U, tU, not_a_week_num, is);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
read(is, CharT{'%'}, width, modified, *fmt);
|
read(is, CharT{'%'}, width, modified, *fmt);
|
||||||
command = nullptr;
|
command = nullptr;
|
||||||
@@ -6775,7 +6883,11 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
if (command)
|
if (command)
|
||||||
{
|
{
|
||||||
if (modified == CharT{})
|
if (modified == CharT{})
|
||||||
read(is, ru{V, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
|
{
|
||||||
|
int tV = not_a_week_num;
|
||||||
|
read(is, ru{tV, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
|
||||||
|
checked_set(V, tV, not_a_week_num, is);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
read(is, CharT{'%'}, width, modified, *fmt);
|
read(is, CharT{'%'}, width, modified, *fmt);
|
||||||
command = nullptr;
|
command = nullptr;
|
||||||
@@ -6789,59 +6901,11 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
if (command)
|
if (command)
|
||||||
{
|
{
|
||||||
if (modified == CharT{})
|
if (modified == CharT{})
|
||||||
read(is, ru{W, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
|
|
||||||
else
|
|
||||||
read(is, CharT{'%'}, width, modified, *fmt);
|
|
||||||
command = nullptr;
|
|
||||||
width = -1;
|
|
||||||
modified = CharT{};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
read(is, *fmt);
|
|
||||||
break;
|
|
||||||
case 'u':
|
|
||||||
case 'w':
|
|
||||||
if (command)
|
|
||||||
{
|
{
|
||||||
#if !ONLY_C_LOCALE
|
int tW = not_a_week_num;
|
||||||
if (modified == CharT{})
|
read(is, ru{tW, 1, width == -1 ? 2u : static_cast<unsigned>(width)});
|
||||||
#else
|
checked_set(W, tW, not_a_week_num, is);
|
||||||
if (modified != CharT{'E'})
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
read(is, ru{wd, 1, width == -1 ? 1u : static_cast<unsigned>(width)});
|
|
||||||
if (!is.fail())
|
|
||||||
{
|
|
||||||
if (*fmt == 'u')
|
|
||||||
{
|
|
||||||
if (!(1 <= wd && wd <= 7))
|
|
||||||
{
|
|
||||||
wd = not_a_weekday;
|
|
||||||
is.setstate(ios_base::failbit);
|
|
||||||
}
|
}
|
||||||
else if (wd == 7)
|
|
||||||
wd = 0;
|
|
||||||
}
|
|
||||||
else // *fmt == 'w'
|
|
||||||
{
|
|
||||||
if (!(0 <= wd && wd <= 6))
|
|
||||||
{
|
|
||||||
wd = not_a_weekday;
|
|
||||||
is.setstate(ios_base::failbit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#if !ONLY_C_LOCALE
|
|
||||||
else if (modified == CharT{'O'})
|
|
||||||
{
|
|
||||||
ios_base::iostate err = ios_base::goodbit;
|
|
||||||
f.get(is, nullptr, is, err, &tm, command, fmt+1);
|
|
||||||
if ((err & ios::failbit) == 0)
|
|
||||||
wd = tm.tm_wday;
|
|
||||||
is.setstate(err);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
else
|
else
|
||||||
read(is, CharT{'%'}, width, modified, *fmt);
|
read(is, CharT{'%'}, width, modified, *fmt);
|
||||||
command = nullptr;
|
command = nullptr;
|
||||||
@@ -6887,12 +6951,13 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
case 'z':
|
case 'z':
|
||||||
if (command)
|
if (command)
|
||||||
{
|
{
|
||||||
int H, M;
|
int tH, tM;
|
||||||
|
minutes toff = not_a_offset;
|
||||||
if (modified == CharT{})
|
if (modified == CharT{})
|
||||||
{
|
{
|
||||||
read(is, rs{H, 2, 2});
|
read(is, rs{tH, 2, 2});
|
||||||
if (!is.fail())
|
if (!is.fail())
|
||||||
temp_offset = hours{H};
|
toff = hours{tH};
|
||||||
if (is.good())
|
if (is.good())
|
||||||
{
|
{
|
||||||
auto ic = is.peek();
|
auto ic = is.peek();
|
||||||
@@ -6901,18 +6966,18 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
auto c = static_cast<char>(Traits::to_char_type(ic));
|
auto c = static_cast<char>(Traits::to_char_type(ic));
|
||||||
if ('0' <= c && c <= '9')
|
if ('0' <= c && c <= '9')
|
||||||
{
|
{
|
||||||
read(is, ru{M, 2, 2});
|
read(is, ru{tM, 2, 2});
|
||||||
if (!is.fail())
|
if (!is.fail())
|
||||||
temp_offset += minutes{ H < 0 ? -M : M };
|
toff += minutes{ tH < 0 ? -tM : tM };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
read(is, rs{H, 1, 2});
|
read(is, rs{tH, 1, 2});
|
||||||
if (!is.fail())
|
if (!is.fail())
|
||||||
temp_offset = hours{H};
|
toff = hours{tH};
|
||||||
if (is.good())
|
if (is.good())
|
||||||
{
|
{
|
||||||
auto ic = is.peek();
|
auto ic = is.peek();
|
||||||
@@ -6922,13 +6987,14 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
if (c == ':')
|
if (c == ':')
|
||||||
{
|
{
|
||||||
(void)is.get();
|
(void)is.get();
|
||||||
read(is, ru{M, 2, 2});
|
read(is, ru{tM, 2, 2});
|
||||||
if (!is.fail())
|
if (!is.fail())
|
||||||
temp_offset += minutes{ H < 0 ? -M : M };
|
toff += minutes{ tH < 0 ? -tM : tM };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
checked_set(temp_offset, toff, not_a_offset, is);
|
||||||
command = nullptr;
|
command = nullptr;
|
||||||
width = -1;
|
width = -1;
|
||||||
modified = CharT{};
|
modified = CharT{};
|
||||||
@@ -6941,10 +7007,7 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
{
|
{
|
||||||
if (modified == CharT{})
|
if (modified == CharT{})
|
||||||
{
|
{
|
||||||
if (!temp_abbrev.empty())
|
std::basic_string<CharT, Traits, Alloc> buf;
|
||||||
is.setstate(ios::failbit);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
while (is.rdstate() == std::ios::goodbit)
|
while (is.rdstate() == std::ios::goodbit)
|
||||||
{
|
{
|
||||||
auto i = is.rdbuf()->sgetc();
|
auto i = is.rdbuf()->sgetc();
|
||||||
@@ -6959,12 +7022,12 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
if (!(CharT{1} < wc && wc < CharT{127}) || !(isalnum(c) ||
|
if (!(CharT{1} < wc && wc < CharT{127}) || !(isalnum(c) ||
|
||||||
c == '_' || c == '/' || c == '-' || c == '+'))
|
c == '_' || c == '/' || c == '-' || c == '+'))
|
||||||
break;
|
break;
|
||||||
temp_abbrev.push_back(c);
|
buf.push_back(c);
|
||||||
is.rdbuf()->sbumpc();
|
is.rdbuf()->sbumpc();
|
||||||
}
|
}
|
||||||
if (temp_abbrev.empty())
|
if (buf.empty())
|
||||||
is.setstate(ios::failbit);
|
is.setstate(ios::failbit);
|
||||||
}
|
checked_set(temp_abbrev, buf, {}, is);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
read(is, CharT{'%'}, width, modified, *fmt);
|
read(is, CharT{'%'}, width, modified, *fmt);
|
||||||
@@ -7193,9 +7256,55 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
fds.ymd = ymd;
|
fds.ymd = ymd;
|
||||||
fds.tod = time_of_day<Duration>{h};
|
if (I != not_a_hour_12_value)
|
||||||
fds.tod.m_ = min;
|
{
|
||||||
|
if (!(1 <= I && I <= 12))
|
||||||
|
goto broken;
|
||||||
|
if (p != not_a_ampm)
|
||||||
|
{
|
||||||
|
// p is in [0, 1] == [AM, PM]
|
||||||
|
// Store trial H in I
|
||||||
|
if (I == 12)
|
||||||
|
--p;
|
||||||
|
I += p*12;
|
||||||
|
// Either set H from I or make sure H and I are consistent
|
||||||
|
if (H == not_a_hour)
|
||||||
|
H = I;
|
||||||
|
else if (I != H)
|
||||||
|
goto broken;
|
||||||
|
}
|
||||||
|
else // p == not_a_ampm
|
||||||
|
{
|
||||||
|
// if H, make sure H and I could be consistent
|
||||||
|
if (H != not_a_hour)
|
||||||
|
{
|
||||||
|
if (I == 12)
|
||||||
|
{
|
||||||
|
if (H != 0 && H != 12)
|
||||||
|
goto broken;
|
||||||
|
}
|
||||||
|
else if (!(I == H || I == H+12))
|
||||||
|
{
|
||||||
|
goto broken;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (H != not_a_hour)
|
||||||
|
{
|
||||||
|
fds.has_tod = true;
|
||||||
|
fds.tod = time_of_day<Duration>{hours{H}};
|
||||||
|
}
|
||||||
|
if (M != not_a_minute)
|
||||||
|
{
|
||||||
|
fds.has_tod = true;
|
||||||
|
fds.tod.m_ = minutes{M};
|
||||||
|
}
|
||||||
|
if (s != not_a_second)
|
||||||
|
{
|
||||||
|
fds.has_tod = true;
|
||||||
fds.tod.s_ = detail::decimal_format_seconds<Duration>{s};
|
fds.tod.s_ = detail::decimal_format_seconds<Duration>{s};
|
||||||
|
}
|
||||||
if (wd != not_a_weekday)
|
if (wd != not_a_weekday)
|
||||||
fds.wd = weekday{static_cast<unsigned>(wd)};
|
fds.wd = weekday{static_cast<unsigned>(wd)};
|
||||||
if (abbrev != nullptr)
|
if (abbrev != nullptr)
|
||||||
@@ -7348,6 +7457,7 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
minutes offset_local{};
|
minutes offset_local{};
|
||||||
auto offptr = offset ? offset : &offset_local;
|
auto offptr = offset ? offset : &offset_local;
|
||||||
fields<CT> fds{};
|
fields<CT> fds{};
|
||||||
|
fds.has_tod = true;
|
||||||
from_stream(is, fmt, fds, abbrev, offptr);
|
from_stream(is, fmt, fds, abbrev, offptr);
|
||||||
if (!fds.ymd.ok() || !fds.tod.in_conventional_range())
|
if (!fds.ymd.ok() || !fds.tod.in_conventional_range())
|
||||||
is.setstate(ios::failbit);
|
is.setstate(ios::failbit);
|
||||||
@@ -7366,6 +7476,7 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
using CT = typename common_type<Duration, seconds>::type;
|
using CT = typename common_type<Duration, seconds>::type;
|
||||||
fields<CT> fds{};
|
fields<CT> fds{};
|
||||||
|
fds.has_tod = true;
|
||||||
from_stream(is, fmt, fds, abbrev, offset);
|
from_stream(is, fmt, fds, abbrev, offset);
|
||||||
if (!fds.ymd.ok() || !fds.tod.in_conventional_range())
|
if (!fds.ymd.ok() || !fds.tod.in_conventional_range())
|
||||||
is.setstate(ios::failbit);
|
is.setstate(ios::failbit);
|
||||||
@@ -7387,6 +7498,8 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
using CT = typename common_type<Duration, seconds>::type;
|
using CT = typename common_type<Duration, seconds>::type;
|
||||||
fields<CT> fds{};
|
fields<CT> fds{};
|
||||||
from_stream(is, fmt, fds, abbrev, offset);
|
from_stream(is, fmt, fds, abbrev, offset);
|
||||||
|
if (!fds.has_tod)
|
||||||
|
is.setstate(ios::failbit);
|
||||||
if (!is.fail())
|
if (!is.fail())
|
||||||
d = duration_cast<Duration>(fds.tod.to_duration());
|
d = duration_cast<Duration>(fds.tod.to_duration());
|
||||||
return is;
|
return is;
|
||||||
|
@@ -1951,6 +1951,7 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
minutes offset_local{};
|
minutes offset_local{};
|
||||||
auto offptr = offset ? offset : &offset_local;
|
auto offptr = offset ? offset : &offset_local;
|
||||||
fields<CT> fds{};
|
fields<CT> fds{};
|
||||||
|
fds.has_tod = true;
|
||||||
from_stream(is, fmt, fds, abbrev, offptr);
|
from_stream(is, fmt, fds, abbrev, offptr);
|
||||||
if (!fds.ymd.ok())
|
if (!fds.ymd.ok())
|
||||||
is.setstate(ios::failbit);
|
is.setstate(ios::failbit);
|
||||||
@@ -2071,6 +2072,7 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
minutes offset_local{};
|
minutes offset_local{};
|
||||||
auto offptr = offset ? offset : &offset_local;
|
auto offptr = offset ? offset : &offset_local;
|
||||||
fields<CT> fds{};
|
fields<CT> fds{};
|
||||||
|
fds.has_tod = true;
|
||||||
from_stream(is, fmt, fds, abbrev, offptr);
|
from_stream(is, fmt, fds, abbrev, offptr);
|
||||||
if (!fds.ymd.ok() || !fds.tod.in_conventional_range())
|
if (!fds.ymd.ok() || !fds.tod.in_conventional_range())
|
||||||
is.setstate(ios::failbit);
|
is.setstate(ios::failbit);
|
||||||
@@ -2182,6 +2184,7 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
minutes offset_local{};
|
minutes offset_local{};
|
||||||
auto offptr = offset ? offset : &offset_local;
|
auto offptr = offset ? offset : &offset_local;
|
||||||
fields<CT> fds{};
|
fields<CT> fds{};
|
||||||
|
fds.has_tod = true;
|
||||||
from_stream(is, fmt, fds, abbrev, offptr);
|
from_stream(is, fmt, fds, abbrev, offptr);
|
||||||
if (!fds.ymd.ok() || !fds.tod.in_conventional_range())
|
if (!fds.ymd.ok() || !fds.tod.in_conventional_range())
|
||||||
is.setstate(ios::failbit);
|
is.setstate(ios::failbit);
|
||||||
|
Reference in New Issue
Block a user