mirror of
https://github.com/HowardHinnant/date.git
synced 2025-08-03 12:44:27 +02: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:
50
date.h
50
date.h
@@ -5364,22 +5364,22 @@ template <class CharT, class Traits, class ...Args>
|
|||||||
void
|
void
|
||||||
read(std::basic_istream<CharT, Traits>& is, CharT a0, Args&& ...args)
|
read(std::basic_istream<CharT, Traits>& is, CharT a0, Args&& ...args)
|
||||||
{
|
{
|
||||||
|
// No-op if a0 == CharT{}
|
||||||
if (a0 != CharT{})
|
if (a0 != CharT{})
|
||||||
{
|
{
|
||||||
auto ic = is.peek();
|
auto ic = is.peek();
|
||||||
if (Traits::eq_int_type(ic, Traits::eof()) ||
|
if (Traits::eq_int_type(ic, Traits::eof()))
|
||||||
!Traits::eq(Traits::to_char_type(ic), a0))
|
{
|
||||||
|
is.setstate(std::ios::failbit | std::ios::eofbit);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!Traits::eq(Traits::to_char_type(ic), a0))
|
||||||
{
|
{
|
||||||
is.setstate(std::ios::failbit);
|
is.setstate(std::ios::failbit);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
(void)is.get();
|
(void)is.get();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
while (isspace(is.peek()))
|
|
||||||
(void)is.get();
|
|
||||||
}
|
|
||||||
read(is, std::forward<Args>(args)...);
|
read(is, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5486,12 +5486,6 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
using detail::rld;
|
using detail::rld;
|
||||||
for (; *fmt && is.rdstate() == std::ios::goodbit; ++fmt)
|
for (; *fmt && is.rdstate() == std::ios::goodbit; ++fmt)
|
||||||
{
|
{
|
||||||
if (isspace(*fmt))
|
|
||||||
{
|
|
||||||
// space matches 0 or more white space characters
|
|
||||||
ws(is);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
switch (*fmt)
|
switch (*fmt)
|
||||||
{
|
{
|
||||||
case 'a':
|
case 'a':
|
||||||
@@ -5791,20 +5785,23 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
case 't':
|
case 't':
|
||||||
if (command)
|
if (command)
|
||||||
{
|
{
|
||||||
// %n and %t match 1 or more white space characters
|
// %n matches a single white space character
|
||||||
// consecutive %n and %t count as one
|
// %t matches 0 or 1 white space characters
|
||||||
auto ic = is.peek();
|
auto ic = is.peek();
|
||||||
if (Traits::eq_int_type(ic, Traits::eof()))
|
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;
|
break;
|
||||||
}
|
}
|
||||||
ws(is);
|
if (isspace(ic))
|
||||||
for (++fmt; *fmt == 'n' || *fmt == 't'; ++fmt)
|
{
|
||||||
;
|
(void)is.get();
|
||||||
--fmt;
|
}
|
||||||
|
else if (*fmt == 'n')
|
||||||
|
is.setstate(ios_base::failbit);
|
||||||
command = nullptr;
|
command = nullptr;
|
||||||
width = -1;
|
width = -1;
|
||||||
modified = CharT{};
|
modified = CharT{};
|
||||||
@@ -6192,8 +6189,13 @@ from_stream(std::basic_istream<CharT, Traits>& is, const CharT* fmt,
|
|||||||
modified = CharT{};
|
modified = CharT{};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else // !command
|
||||||
read(is, *fmt);
|
{
|
||||||
|
if (isspace(*fmt))
|
||||||
|
ws(is); // space matches 0 or more white space characters
|
||||||
|
else
|
||||||
|
read(is, *fmt);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -740,6 +740,81 @@ test_leading_ws()
|
|||||||
assert(d2 == may/4/2017);
|
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
|
int
|
||||||
main()
|
main()
|
||||||
{
|
{
|
||||||
@@ -769,4 +844,7 @@ main()
|
|||||||
test_Z();
|
test_Z();
|
||||||
test_trailing_Z();
|
test_trailing_Z();
|
||||||
test_leading_ws();
|
test_leading_ws();
|
||||||
|
test_space();
|
||||||
|
test_n();
|
||||||
|
test_t();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user