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*[])