Fix problem in read_until's match_condition handling when the delimiter lies at the end of the data.
diff --git a/asio/include/asio/impl/read_until.ipp b/asio/include/asio/impl/read_until.ipp index dffd312..3ed7dbe 100644 --- a/asio/include/asio/impl/read_until.ipp +++ b/asio/include/asio/impl/read_until.ipp
@@ -277,19 +277,16 @@ // Look for a match. std::pair<iterator, bool> result = match_condition(start, end); - if (result.first != end) + if (result.second) { - if (result.second) - { - // Full match. We're done. - ec = asio::error_code(); - return result.first - begin; - } - else - { - // Partial match. Next search needs to start from beginning of match. - next_search_start = result.first - begin; - } + // Full match. We're done. + ec = asio::error_code(); + return result.first - begin; + } + else if (result.first != end) + { + // Partial match. Next search needs to start from beginning of match. + next_search_start = result.first - begin; } else { @@ -857,20 +854,17 @@ // Look for a match. std::pair<iterator, bool> result = match_condition_(start, end); - if (result.first != end) + if (result.second) { - if (result.second) - { - // Full match. We're done. - std::size_t bytes = result.first - begin; - handler_(ec, bytes); - return; - } - else - { - // Partial match. Next search needs to start from beginning of match. - next_search_start_ = result.first - begin; - } + // Full match. We're done. + std::size_t bytes = result.first - begin; + handler_(ec, bytes); + return; + } + else if (result.first != end) + { + // Partial match. Next search needs to start from beginning of match. + next_search_start_ = result.first - begin; } else { @@ -950,21 +944,18 @@ // Look for a match. std::size_t next_search_start; std::pair<iterator, bool> result = match_condition(begin, end); - if (result.first != end) + if (result.second) { - if (result.second) - { - // Full match. We're done. - asio::error_code ec; - std::size_t bytes = result.first - begin; - s.get_io_service().post(detail::bind_handler(handler, ec, bytes)); - return; - } - else - { - // Partial match. Next search needs to start from beginning of match. - next_search_start = result.first - begin; - } + // Full match. We're done. + asio::error_code ec; + std::size_t bytes = result.first - begin; + s.get_io_service().post(detail::bind_handler(handler, ec, bytes)); + return; + } + else if (result.first != end) + { + // Partial match. Next search needs to start from beginning of match. + next_search_start = result.first - begin; } else {
diff --git a/asio/src/tests/unit/read_until.cpp b/asio/src/tests/unit/read_until.cpp index 19218c2..b381f12 100644 --- a/asio/src/tests/unit/read_until.cpp +++ b/asio/src/tests/unit/read_until.cpp
@@ -121,52 +121,81 @@ asio::error_code ec; s.reset(read_data, sizeof(read_data)); + sb1.consume(sb1.size()); std::size_t length = asio::read_until(s, sb1, 'Z'); BOOST_CHECK(length == 26); s.reset(read_data, sizeof(read_data)); s.next_read_length(1); + sb1.consume(sb1.size()); length = asio::read_until(s, sb1, 'Z'); BOOST_CHECK(length == 26); s.reset(read_data, sizeof(read_data)); s.next_read_length(10); + sb1.consume(sb1.size()); length = asio::read_until(s, sb1, 'Z'); BOOST_CHECK(length == 26); s.reset(read_data, sizeof(read_data)); + sb1.consume(sb1.size()); length = asio::read_until(s, sb1, 'Z', ec); BOOST_CHECK(!ec); BOOST_CHECK(length == 26); s.reset(read_data, sizeof(read_data)); s.next_read_length(1); + sb1.consume(sb1.size()); length = asio::read_until(s, sb1, 'Z', ec); BOOST_CHECK(!ec); BOOST_CHECK(length == 26); s.reset(read_data, sizeof(read_data)); s.next_read_length(10); + sb1.consume(sb1.size()); length = asio::read_until(s, sb1, 'Z', ec); BOOST_CHECK(!ec); BOOST_CHECK(length == 26); s.reset(read_data, sizeof(read_data)); + sb2.consume(sb2.size()); length = asio::read_until(s, sb2, 'Z', ec); BOOST_CHECK(ec == asio::error::not_found); BOOST_CHECK(length == 0); s.reset(read_data, sizeof(read_data)); s.next_read_length(1); + sb2.consume(sb2.size()); length = asio::read_until(s, sb2, 'Z', ec); BOOST_CHECK(ec == asio::error::not_found); BOOST_CHECK(length == 0); s.reset(read_data, sizeof(read_data)); s.next_read_length(10); + sb2.consume(sb2.size()); length = asio::read_until(s, sb2, 'Z', ec); BOOST_CHECK(ec == asio::error::not_found); BOOST_CHECK(length == 0); + + s.reset(read_data, sizeof(read_data)); + sb2.consume(sb2.size()); + length = asio::read_until(s, sb2, 'Y', ec); + BOOST_CHECK(!ec); + BOOST_CHECK(length == 25); + + s.reset(read_data, sizeof(read_data)); + s.next_read_length(1); + sb2.consume(sb2.size()); + length = asio::read_until(s, sb2, 'Y', ec); + BOOST_CHECK(!ec); + BOOST_CHECK(length == 25); + + s.reset(read_data, sizeof(read_data)); + s.next_read_length(10); + sb2.consume(sb2.size()); + length = asio::read_until(s, sb2, 'Y', ec); + BOOST_CHECK(!ec); + BOOST_CHECK(length == 25); } void test_string_read_until() @@ -178,52 +207,81 @@ asio::error_code ec; s.reset(read_data, sizeof(read_data)); + sb1.consume(sb1.size()); std::size_t length = asio::read_until(s, sb1, "XYZ"); BOOST_CHECK(length == 26); s.reset(read_data, sizeof(read_data)); s.next_read_length(1); + sb1.consume(sb1.size()); length = asio::read_until(s, sb1, "XYZ"); BOOST_CHECK(length == 26); s.reset(read_data, sizeof(read_data)); s.next_read_length(10); + sb1.consume(sb1.size()); length = asio::read_until(s, sb1, "XYZ"); BOOST_CHECK(length == 26); s.reset(read_data, sizeof(read_data)); + sb1.consume(sb1.size()); length = asio::read_until(s, sb1, "XYZ", ec); BOOST_CHECK(!ec); BOOST_CHECK(length == 26); s.reset(read_data, sizeof(read_data)); s.next_read_length(1); + sb1.consume(sb1.size()); length = asio::read_until(s, sb1, "XYZ", ec); BOOST_CHECK(!ec); BOOST_CHECK(length == 26); s.reset(read_data, sizeof(read_data)); s.next_read_length(10); + sb1.consume(sb1.size()); length = asio::read_until(s, sb1, "XYZ", ec); BOOST_CHECK(!ec); BOOST_CHECK(length == 26); s.reset(read_data, sizeof(read_data)); + sb2.consume(sb2.size()); length = asio::read_until(s, sb2, "XYZ", ec); BOOST_CHECK(ec == asio::error::not_found); BOOST_CHECK(length == 0); s.reset(read_data, sizeof(read_data)); s.next_read_length(1); + sb2.consume(sb2.size()); length = asio::read_until(s, sb2, "XYZ", ec); BOOST_CHECK(ec == asio::error::not_found); BOOST_CHECK(length == 0); s.reset(read_data, sizeof(read_data)); s.next_read_length(10); + sb2.consume(sb2.size()); length = asio::read_until(s, sb2, "XYZ", ec); BOOST_CHECK(ec == asio::error::not_found); BOOST_CHECK(length == 0); + + s.reset(read_data, sizeof(read_data)); + sb2.consume(sb2.size()); + length = asio::read_until(s, sb2, "WXY", ec); + BOOST_CHECK(!ec); + BOOST_CHECK(length == 25); + + s.reset(read_data, sizeof(read_data)); + s.next_read_length(1); + sb2.consume(sb2.size()); + length = asio::read_until(s, sb2, "WXY", ec); + BOOST_CHECK(!ec); + BOOST_CHECK(length == 25); + + s.reset(read_data, sizeof(read_data)); + s.next_read_length(10); + sb2.consume(sb2.size()); + length = asio::read_until(s, sb2, "WXY", ec); + BOOST_CHECK(!ec); + BOOST_CHECK(length == 25); } class match_char @@ -260,52 +318,81 @@ asio::error_code ec; s.reset(read_data, sizeof(read_data)); + sb1.consume(sb1.size()); std::size_t length = asio::read_until(s, sb1, match_char('Z')); BOOST_CHECK(length == 26); s.reset(read_data, sizeof(read_data)); s.next_read_length(1); + sb1.consume(sb1.size()); length = asio::read_until(s, sb1, match_char('Z')); BOOST_CHECK(length == 26); s.reset(read_data, sizeof(read_data)); s.next_read_length(10); + sb1.consume(sb1.size()); length = asio::read_until(s, sb1, match_char('Z')); BOOST_CHECK(length == 26); s.reset(read_data, sizeof(read_data)); + sb1.consume(sb1.size()); length = asio::read_until(s, sb1, match_char('Z'), ec); BOOST_CHECK(!ec); BOOST_CHECK(length == 26); s.reset(read_data, sizeof(read_data)); s.next_read_length(1); + sb1.consume(sb1.size()); length = asio::read_until(s, sb1, match_char('Z'), ec); BOOST_CHECK(!ec); BOOST_CHECK(length == 26); s.reset(read_data, sizeof(read_data)); s.next_read_length(10); + sb1.consume(sb1.size()); length = asio::read_until(s, sb1, match_char('Z'), ec); BOOST_CHECK(!ec); BOOST_CHECK(length == 26); s.reset(read_data, sizeof(read_data)); + sb2.consume(sb2.size()); length = asio::read_until(s, sb2, match_char('Z'), ec); BOOST_CHECK(ec == asio::error::not_found); BOOST_CHECK(length == 0); s.reset(read_data, sizeof(read_data)); s.next_read_length(1); + sb2.consume(sb2.size()); length = asio::read_until(s, sb2, match_char('Z'), ec); BOOST_CHECK(ec == asio::error::not_found); BOOST_CHECK(length == 0); s.reset(read_data, sizeof(read_data)); s.next_read_length(10); + sb2.consume(sb2.size()); length = asio::read_until(s, sb2, match_char('Z'), ec); BOOST_CHECK(ec == asio::error::not_found); BOOST_CHECK(length == 0); + + s.reset(read_data, sizeof(read_data)); + sb2.consume(sb2.size()); + length = asio::read_until(s, sb2, match_char('Y'), ec); + BOOST_CHECK(!ec); + BOOST_CHECK(length == 25); + + s.reset(read_data, sizeof(read_data)); + s.next_read_length(1); + sb2.consume(sb2.size()); + length = asio::read_until(s, sb2, match_char('Y'), ec); + BOOST_CHECK(!ec); + BOOST_CHECK(length == 25); + + s.reset(read_data, sizeof(read_data)); + s.next_read_length(10); + sb2.consume(sb2.size()); + length = asio::read_until(s, sb2, match_char('Y'), ec); + BOOST_CHECK(!ec); + BOOST_CHECK(length == 25); } void async_read_handler( @@ -331,6 +418,7 @@ ec = asio::error_code(); length = 0; called = false; + sb1.consume(sb1.size()); asio::async_read_until(s, sb1, 'Z', boost::bind(async_read_handler, asio::placeholders::error, &ec, asio::placeholders::bytes_transferred, &length, &called)); @@ -345,6 +433,7 @@ ec = asio::error_code(); length = 0; called = false; + sb1.consume(sb1.size()); asio::async_read_until(s, sb1, 'Z', boost::bind(async_read_handler, asio::placeholders::error, &ec, asio::placeholders::bytes_transferred, &length, &called)); @@ -359,6 +448,7 @@ ec = asio::error_code(); length = 0; called = false; + sb1.consume(sb1.size()); asio::async_read_until(s, sb1, 'Z', boost::bind(async_read_handler, asio::placeholders::error, &ec, asio::placeholders::bytes_transferred, &length, &called)); @@ -372,6 +462,7 @@ ec = asio::error_code(); length = 0; called = false; + sb2.consume(sb2.size()); asio::async_read_until(s, sb2, 'Z', boost::bind(async_read_handler, asio::placeholders::error, &ec, asio::placeholders::bytes_transferred, &length, &called)); @@ -386,6 +477,7 @@ ec = asio::error_code(); length = 0; called = false; + sb2.consume(sb2.size()); asio::async_read_until(s, sb2, 'Z', boost::bind(async_read_handler, asio::placeholders::error, &ec, asio::placeholders::bytes_transferred, &length, &called)); @@ -400,6 +492,7 @@ ec = asio::error_code(); length = 0; called = false; + sb2.consume(sb2.size()); asio::async_read_until(s, sb2, 'Z', boost::bind(async_read_handler, asio::placeholders::error, &ec, asio::placeholders::bytes_transferred, &length, &called)); @@ -408,6 +501,50 @@ BOOST_CHECK(called); BOOST_CHECK(ec == asio::error::not_found); BOOST_CHECK(length == 0); + + s.reset(read_data, sizeof(read_data)); + ec = asio::error_code(); + length = 0; + called = false; + sb2.consume(sb2.size()); + asio::async_read_until(s, sb2, 'Y', + boost::bind(async_read_handler, asio::placeholders::error, &ec, + asio::placeholders::bytes_transferred, &length, &called)); + ios.reset(); + ios.run(); + BOOST_CHECK(called); + BOOST_CHECK(!ec); + BOOST_CHECK(length == 25); + + s.reset(read_data, sizeof(read_data)); + s.next_read_length(1); + ec = asio::error_code(); + length = 0; + called = false; + sb2.consume(sb2.size()); + asio::async_read_until(s, sb2, 'Y', + boost::bind(async_read_handler, asio::placeholders::error, &ec, + asio::placeholders::bytes_transferred, &length, &called)); + ios.reset(); + ios.run(); + BOOST_CHECK(called); + BOOST_CHECK(!ec); + BOOST_CHECK(length == 25); + + s.reset(read_data, sizeof(read_data)); + s.next_read_length(10); + ec = asio::error_code(); + length = 0; + called = false; + sb2.consume(sb2.size()); + asio::async_read_until(s, sb2, 'Y', + boost::bind(async_read_handler, asio::placeholders::error, &ec, + asio::placeholders::bytes_transferred, &length, &called)); + ios.reset(); + ios.run(); + BOOST_CHECK(called); + BOOST_CHECK(!ec); + BOOST_CHECK(length == 25); } void test_string_async_read_until() @@ -424,6 +561,7 @@ ec = asio::error_code(); length = 0; called = false; + sb1.consume(sb1.size()); asio::async_read_until(s, sb1, "XYZ", boost::bind(async_read_handler, asio::placeholders::error, &ec, asio::placeholders::bytes_transferred, &length, &called)); @@ -438,6 +576,7 @@ ec = asio::error_code(); length = 0; called = false; + sb1.consume(sb1.size()); asio::async_read_until(s, sb1, "XYZ", boost::bind(async_read_handler, asio::placeholders::error, &ec, asio::placeholders::bytes_transferred, &length, &called)); @@ -452,6 +591,7 @@ ec = asio::error_code(); length = 0; called = false; + sb1.consume(sb1.size()); asio::async_read_until(s, sb1, "XYZ", boost::bind(async_read_handler, asio::placeholders::error, &ec, asio::placeholders::bytes_transferred, &length, &called)); @@ -465,6 +605,7 @@ ec = asio::error_code(); length = 0; called = false; + sb2.consume(sb2.size()); asio::async_read_until(s, sb2, "XYZ", boost::bind(async_read_handler, asio::placeholders::error, &ec, asio::placeholders::bytes_transferred, &length, &called)); @@ -479,6 +620,7 @@ ec = asio::error_code(); length = 0; called = false; + sb2.consume(sb2.size()); asio::async_read_until(s, sb2, "XYZ", boost::bind(async_read_handler, asio::placeholders::error, &ec, asio::placeholders::bytes_transferred, &length, &called)); @@ -493,6 +635,7 @@ ec = asio::error_code(); length = 0; called = false; + sb2.consume(sb2.size()); asio::async_read_until(s, sb2, "XYZ", boost::bind(async_read_handler, asio::placeholders::error, &ec, asio::placeholders::bytes_transferred, &length, &called)); @@ -501,6 +644,50 @@ BOOST_CHECK(called); BOOST_CHECK(ec == asio::error::not_found); BOOST_CHECK(length == 0); + + s.reset(read_data, sizeof(read_data)); + ec = asio::error_code(); + length = 0; + called = false; + sb2.consume(sb2.size()); + asio::async_read_until(s, sb2, "WXY", + boost::bind(async_read_handler, asio::placeholders::error, &ec, + asio::placeholders::bytes_transferred, &length, &called)); + ios.reset(); + ios.run(); + BOOST_CHECK(called); + BOOST_CHECK(!ec); + BOOST_CHECK(length == 25); + + s.reset(read_data, sizeof(read_data)); + s.next_read_length(1); + ec = asio::error_code(); + length = 0; + called = false; + sb2.consume(sb2.size()); + asio::async_read_until(s, sb2, "WXY", + boost::bind(async_read_handler, asio::placeholders::error, &ec, + asio::placeholders::bytes_transferred, &length, &called)); + ios.reset(); + ios.run(); + BOOST_CHECK(called); + BOOST_CHECK(!ec); + BOOST_CHECK(length == 25); + + s.reset(read_data, sizeof(read_data)); + s.next_read_length(10); + ec = asio::error_code(); + length = 0; + called = false; + sb2.consume(sb2.size()); + asio::async_read_until(s, sb2, "WXY", + boost::bind(async_read_handler, asio::placeholders::error, &ec, + asio::placeholders::bytes_transferred, &length, &called)); + ios.reset(); + ios.run(); + BOOST_CHECK(called); + BOOST_CHECK(!ec); + BOOST_CHECK(length == 25); } void test_match_condition_async_read_until() @@ -517,6 +704,7 @@ ec = asio::error_code(); length = 0; called = false; + sb1.consume(sb1.size()); asio::async_read_until(s, sb1, match_char('Z'), boost::bind(async_read_handler, asio::placeholders::error, &ec, asio::placeholders::bytes_transferred, &length, &called)); @@ -531,6 +719,7 @@ ec = asio::error_code(); length = 0; called = false; + sb1.consume(sb1.size()); asio::async_read_until(s, sb1, match_char('Z'), boost::bind(async_read_handler, asio::placeholders::error, &ec, asio::placeholders::bytes_transferred, &length, &called)); @@ -545,6 +734,7 @@ ec = asio::error_code(); length = 0; called = false; + sb1.consume(sb1.size()); asio::async_read_until(s, sb1, match_char('Z'), boost::bind(async_read_handler, asio::placeholders::error, &ec, asio::placeholders::bytes_transferred, &length, &called)); @@ -558,6 +748,7 @@ ec = asio::error_code(); length = 0; called = false; + sb2.consume(sb2.size()); asio::async_read_until(s, sb2, match_char('Z'), boost::bind(async_read_handler, asio::placeholders::error, &ec, asio::placeholders::bytes_transferred, &length, &called)); @@ -572,6 +763,7 @@ ec = asio::error_code(); length = 0; called = false; + sb2.consume(sb2.size()); asio::async_read_until(s, sb2, match_char('Z'), boost::bind(async_read_handler, asio::placeholders::error, &ec, asio::placeholders::bytes_transferred, &length, &called)); @@ -586,6 +778,7 @@ ec = asio::error_code(); length = 0; called = false; + sb2.consume(sb2.size()); asio::async_read_until(s, sb2, match_char('Z'), boost::bind(async_read_handler, asio::placeholders::error, &ec, asio::placeholders::bytes_transferred, &length, &called)); @@ -594,6 +787,50 @@ BOOST_CHECK(called); BOOST_CHECK(ec == asio::error::not_found); BOOST_CHECK(length == 0); + + s.reset(read_data, sizeof(read_data)); + ec = asio::error_code(); + length = 0; + called = false; + sb2.consume(sb2.size()); + asio::async_read_until(s, sb2, match_char('Y'), + boost::bind(async_read_handler, asio::placeholders::error, &ec, + asio::placeholders::bytes_transferred, &length, &called)); + ios.reset(); + ios.run(); + BOOST_CHECK(called); + BOOST_CHECK(!ec); + BOOST_CHECK(length == 25); + + s.reset(read_data, sizeof(read_data)); + s.next_read_length(1); + ec = asio::error_code(); + length = 0; + called = false; + sb2.consume(sb2.size()); + asio::async_read_until(s, sb2, match_char('Y'), + boost::bind(async_read_handler, asio::placeholders::error, &ec, + asio::placeholders::bytes_transferred, &length, &called)); + ios.reset(); + ios.run(); + BOOST_CHECK(called); + BOOST_CHECK(!ec); + BOOST_CHECK(length == 25); + + s.reset(read_data, sizeof(read_data)); + s.next_read_length(10); + ec = asio::error_code(); + length = 0; + called = false; + sb2.consume(sb2.size()); + asio::async_read_until(s, sb2, match_char('Y'), + boost::bind(async_read_handler, asio::placeholders::error, &ec, + asio::placeholders::bytes_transferred, &length, &called)); + ios.reset(); + ios.run(); + BOOST_CHECK(called); + BOOST_CHECK(!ec); + BOOST_CHECK(length == 25); } test_suite* init_unit_test_suite(int, char*[])