mirror of
https://github.com/HowardHinnant/date.git
synced 2025-01-14 01:37:57 +08:00
Tweak white space parsing rules (again):
* White space matches zero or more white space characters. * %n matches one white space character. * %t matches zero or one white space characters.
This commit is contained in:
parent
cf0481b9af
commit
f493bd67f2
50
date.h
50
date.h
@ -5364,22 +5364,22 @@ template <class CharT, class Traits, class ...Args>
|
||||
void
|
||||
read(std::basic_istream<CharT, Traits>& is, CharT a0, Args&& ...args)
|
||||
{
|
||||
// No-op if a0 == CharT{}
|
||||
if (a0 != CharT{})
|
||||
{
|
||||
auto ic = is.peek();
|
||||
if (Traits::eq_int_type(ic, Traits::eof()) ||
|
||||
!Traits::eq(Traits::to_char_type(ic), a0))
|
||||
if (Traits::eq_int_type(ic, Traits::eof()))
|
||||
{
|
||||
is.setstate(std::ios::failbit | std::ios::eofbit);
|
||||
return;
|
||||
}
|
||||
if (!Traits::eq(Traits::to_char_type(ic), a0))
|
||||
{
|
||||
is.setstate(std::ios::failbit);
|
||||
return;
|
||||
}
|
||||
(void)is.get();
|
||||
}
|
||||
else
|
||||
{
|
||||
while (isspace(is.peek()))
|
||||
(void)is.get();
|
||||
}
|
||||
read(is, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
@ -5486,12 +5486,6 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
||||
using detail::rld;
|
||||
for (; *fmt && is.rdstate() == std::ios::goodbit; ++fmt)
|
||||
{
|
||||
if (isspace(*fmt))
|
||||
{
|
||||
// space matches 0 or more white space characters
|
||||
ws(is);
|
||||
continue;
|
||||
}
|
||||
switch (*fmt)
|
||||
{
|
||||
case 'a':
|
||||
@ -5791,20 +5785,23 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
||||
case 't':
|
||||
if (command)
|
||||
{
|
||||
// %n and %t match 1 or more white space characters
|
||||
// consecutive %n and %t count as one
|
||||
// %n matches a single white space character
|
||||
// %t matches 0 or 1 white space characters
|
||||
auto ic = is.peek();
|
||||
if (Traits::eq_int_type(ic, Traits::eof()))
|
||||
break;
|
||||
if (!isspace(ic))
|
||||
{
|
||||
is.setstate(ios::failbit);
|
||||
ios_base::iostate err = ios_base::eofbit;
|
||||
if (*fmt == 'n')
|
||||
err |= ios_base::failbit;
|
||||
is.setstate(err);
|
||||
break;
|
||||
}
|
||||
ws(is);
|
||||
for (++fmt; *fmt == 'n' || *fmt == 't'; ++fmt)
|
||||
;
|
||||
--fmt;
|
||||
if (isspace(ic))
|
||||
{
|
||||
(void)is.get();
|
||||
}
|
||||
else if (*fmt == 'n')
|
||||
is.setstate(ios_base::failbit);
|
||||
command = nullptr;
|
||||
width = -1;
|
||||
modified = CharT{};
|
||||
@ -6192,8 +6189,13 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
||||
modified = CharT{};
|
||||
}
|
||||
}
|
||||
else
|
||||
read(is, *fmt);
|
||||
else // !command
|
||||
{
|
||||
if (isspace(*fmt))
|
||||
ws(is); // space matches 0 or more white space characters
|
||||
else
|
||||
read(is, *fmt);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -740,6 +740,81 @@ test_leading_ws()
|
||||
assert(d2 == may/4/2017);
|
||||
}
|
||||
|
||||
void
|
||||
test_space()
|
||||
{
|
||||
using namespace std;
|
||||
using namespace date;
|
||||
{
|
||||
istringstream in{"05/04/17"};
|
||||
year_month_day d1;
|
||||
in >> parse(" %D", d1);
|
||||
assert(d1 == may/4/2017);
|
||||
}
|
||||
{
|
||||
istringstream in{" 05/04/17"};
|
||||
year_month_day d1;
|
||||
in >> parse(" %D", d1);
|
||||
assert(d1 == may/4/2017);
|
||||
}
|
||||
{
|
||||
istringstream in{" 05/04/17"};
|
||||
year_month_day d1;
|
||||
in >> parse(" %D", d1);
|
||||
assert(d1 == may/4/2017);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test_n()
|
||||
{
|
||||
using namespace std;
|
||||
using namespace date;
|
||||
{
|
||||
istringstream in{"05/04/17"};
|
||||
year_month_day d1;
|
||||
in >> parse("%n%D", d1);
|
||||
assert(in.fail());
|
||||
}
|
||||
{
|
||||
istringstream in{" 05/04/17"};
|
||||
year_month_day d1;
|
||||
in >> parse("%n%D", d1);
|
||||
assert(d1 == may/4/2017);
|
||||
}
|
||||
{
|
||||
istringstream in{" 05/04/17"};
|
||||
year_month_day d1;
|
||||
in >> parse("%n%D", d1);
|
||||
assert(in.fail());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test_t()
|
||||
{
|
||||
using namespace std;
|
||||
using namespace date;
|
||||
{
|
||||
istringstream in{"05/04/17"};
|
||||
year_month_day d1;
|
||||
in >> parse("%t%D", d1);
|
||||
assert(d1 == may/4/2017);
|
||||
}
|
||||
{
|
||||
istringstream in{" 05/04/17"};
|
||||
year_month_day d1;
|
||||
in >> parse("%t%D", d1);
|
||||
assert(d1 == may/4/2017);
|
||||
}
|
||||
{
|
||||
istringstream in{" 05/04/17"};
|
||||
year_month_day d1;
|
||||
in >> parse("%t%D", d1);
|
||||
assert(in.fail());
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
@ -769,4 +844,7 @@ main()
|
||||
test_Z();
|
||||
test_trailing_Z();
|
||||
test_leading_ws();
|
||||
test_space();
|
||||
test_n();
|
||||
test_t();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user