diff --git a/date.h b/date.h index 0951199..67d2f73 100644 --- a/date.h +++ b/date.h @@ -5364,22 +5364,22 @@ template void read(std::basic_istream& 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)...); } @@ -5486,12 +5486,6 @@ from_stream(std::basic_istream& 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& 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& 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; } } diff --git a/test/date_test/parse.pass.cpp b/test/date_test/parse.pass.cpp index d93f394..6db370d 100644 --- a/test/date_test/parse.pass.cpp +++ b/test/date_test/parse.pass.cpp @@ -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(); }