Add support for dynamic buffer sequences.

This commit adds:

- New dynamic_string_buffer and dynamic_vector_buffer adapter classes that meet
  the DynamicBufferSequence type requirements.

- New dynamic_buffer() factory functions for creating a dynamic buffer adapter
  for a vector or string.

- New overloads for the read(), async_read(), write() and async_write(),
  read_until() and async_read_until() free functions.

N.B. the read_at, async_read_at, write_at and async_write_at functions have not
yet been updated to support dynamic buffer sequences.
diff --git a/asio/include/asio/basic_streambuf.hpp b/asio/include/asio/basic_streambuf.hpp
index bacc485..b55c2f6 100644
--- a/asio/include/asio/basic_streambuf.hpp
+++ b/asio/include/asio/basic_streambuf.hpp
@@ -155,7 +155,7 @@
    * }
    * @endcode
    */
-  std::size_t size() const
+  std::size_t size() const ASIO_NOEXCEPT
   {
     return pptr() - gptr();
   }
@@ -165,11 +165,21 @@
    * @returns The allowed maximum of the sum of the sizes of the input sequence
    * and output sequence.
    */
-  std::size_t max_size() const
+  std::size_t max_size() const ASIO_NOEXCEPT
   {
     return max_size_;
   }
 
+  /// Get the current capacity of the basic_streambuf.
+  /**
+   * @returns The current total capacity of the streambuf, i.e. for both the
+   * input sequence and output sequence.
+   */
+  std::size_t capacity() const ASIO_NOEXCEPT
+  {
+    return buffer_.capacity();
+  }
+
   /// Get a list of buffers that represents the input sequence.
   /**
    * @returns An object of type @c const_buffers_type that satisfies
@@ -179,7 +189,7 @@
    * @note The returned object is invalidated by any @c basic_streambuf member
    * function that modifies the input sequence or output sequence.
    */
-  const_buffers_type data() const
+  const_buffers_type data() const ASIO_NOEXCEPT
   {
     return asio::buffer(asio::const_buffer(gptr(),
           (pptr() - gptr()) * sizeof(char_type)));
@@ -350,15 +360,89 @@
   }
 };
 
-// Helper function to get the preferred size for reading data. Used for any
-// user-provided specialisations of basic_streambuf.
+/// Adapts basic_streambuf to the dynamic buffer sequence type requirements.
+#if defined(GENERATING_DOCUMENTATION)
+template <typename Allocator = std::allocator<char> >
+#else
 template <typename Allocator>
-inline std::size_t read_size_helper(
-    basic_streambuf<Allocator>& sb, std::size_t max_size)
+#endif
+class basic_streambuf_ref
 {
-  return std::min<std::size_t>(512,
-      std::min<std::size_t>(max_size, sb.max_size() - sb.size()));
-}
+public:
+  /// The type used to represent the input sequence as a list of buffers.
+  typedef typename basic_streambuf<Allocator>::const_buffers_type
+    const_buffers_type;
+
+  /// The type used to represent the output sequence as a list of buffers.
+  typedef typename basic_streambuf<Allocator>::mutable_buffers_type
+    mutable_buffers_type;
+
+  /// Construct a basic_streambuf_ref for the given basic_streambuf object.
+  explicit basic_streambuf_ref(basic_streambuf<Allocator>& sb)
+    : sb_(sb)
+  {
+  }
+
+  /// Copy construct a basic_streambuf_ref.
+  basic_streambuf_ref(const basic_streambuf_ref& other) ASIO_NOEXCEPT
+    : sb_(other.sb_)
+  {
+  }
+
+#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+  /// Move construct a basic_streambuf_ref.
+  basic_streambuf_ref(basic_streambuf_ref&& other) ASIO_NOEXCEPT
+    : sb_(other.sb_)
+  {
+  }
+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+  /// Get the size of the input sequence.
+  std::size_t size() const ASIO_NOEXCEPT
+  {
+    return sb_.size();
+  }
+
+  /// Get the maximum size of the dynamic buffer.
+  std::size_t max_size() const ASIO_NOEXCEPT
+  {
+    return sb_.max_size();
+  }
+
+  /// Get the current capacity of the dynamic buffer.
+  std::size_t capacity() const ASIO_NOEXCEPT
+  {
+    return sb_.capacity();
+  }
+
+  /// Get a list of buffers that represents the input sequence.
+  const_buffers_type data() const ASIO_NOEXCEPT
+  {
+    return sb_.data();
+  }
+
+  /// Get a list of buffers that represents the output sequence, with the given
+  /// size.
+  mutable_buffers_type prepare(std::size_t n)
+  {
+    return sb_.prepare(n);
+  }
+
+  /// Move bytes from the output sequence to the input sequence.
+  void commit(std::size_t n)
+  {
+    return sb_.commit(n);
+  }
+
+  /// Remove characters from the input sequence.
+  void consume(std::size_t n)
+  {
+    return sb_.consume(n);
+  }
+
+private:
+  basic_streambuf<Allocator>& sb_;
+};
 
 } // namespace asio
 
diff --git a/asio/include/asio/basic_streambuf_fwd.hpp b/asio/include/asio/basic_streambuf_fwd.hpp
index 8fd0ae8..4ac3e42 100644
--- a/asio/include/asio/basic_streambuf_fwd.hpp
+++ b/asio/include/asio/basic_streambuf_fwd.hpp
@@ -26,6 +26,9 @@
 template <typename Allocator = std::allocator<char> >
 class basic_streambuf;
 
+template <typename Allocator = std::allocator<char> >
+class basic_streambuf_ref;
+
 } // namespace asio
 
 #endif // !defined(ASIO_NO_IOSTREAM)
diff --git a/asio/include/asio/buffer.hpp b/asio/include/asio/buffer.hpp
index 2cc06bb..b2da915 100644
--- a/asio/include/asio/buffer.hpp
+++ b/asio/include/asio/buffer.hpp
@@ -18,10 +18,13 @@
 #include "asio/detail/config.hpp"
 #include <cstddef>
 #include <cstring>
+#include <limits>
+#include <stdexcept>
 #include <string>
 #include <vector>
 #include "asio/detail/array_fwd.hpp"
 #include "asio/detail/is_buffer_sequence.hpp"
+#include "asio/detail/throw_exception.hpp"
 #include "asio/detail/type_traits.hpp"
 
 #if defined(ASIO_MSVC)
@@ -345,6 +348,18 @@
 {
 };
 
+/// Trait to determine whether a type satisfies the DynamicBufferSequence
+/// requirements.
+template <typename T>
+struct is_dynamic_buffer_sequence
+#if defined(GENERATING_DOCUMENTATION)
+  : integral_constant<bool, automatically_determined>
+#else // defined(GENERATING_DOCUMENTATION)
+  : asio::detail::is_dynamic_buffer_sequence<T>
+#endif // defined(GENERATING_DOCUMENTATION)
+{
+};
+
 /// (Deprecated: Use the socket/descriptor wait() and async_wait() member
 /// functions.) An implementation of both the ConstBufferSequence and
 /// MutableBufferSequence concepts to represent a null buffer sequence.
@@ -1324,6 +1339,356 @@
 
 /*@}*/
 
+/// Adapt a basic_string to the DynamicBufferSequence requirements.
+/**
+ * Requires that <tt>sizeof(Elem) == 1</tt>.
+ */
+template <typename Elem, typename Traits, typename Allocator>
+class dynamic_string_buffer
+{
+public:
+  /// The type used to represent the input sequence as a list of buffers.
+  typedef const_buffers_1 const_buffers_type;
+
+  /// The type used to represent the output sequence as a list of buffers.
+  typedef mutable_buffers_1 mutable_buffers_type;
+
+  /// Construct a dynamic buffer from a string.
+  /**
+   * @param s The string to be used as backing storage for the dynamic buffer.
+   * Any existing data in the string is treated as the dynamic buffer's input
+   * sequence. The object stores a reference to the string and the user is
+   * responsible for ensuring that the string object remains valid until the
+   * dynamic_string_buffer object is destroyed.
+   */
+  explicit dynamic_string_buffer(std::basic_string<Elem, Traits, Allocator>& s,
+      std::size_t maximum_size = (std::numeric_limits<std::size_t>::max)())
+    : string_(s),
+      size_(string_.size()),
+      max_size_(maximum_size)
+  {
+  }
+
+#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+  /// Move construct a dynamic buffer.
+  dynamic_string_buffer(dynamic_string_buffer&& other)
+    : string_(other.string_),
+      size_(other.size_),
+      max_size_(other.max_size_)
+  {
+  }
+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+  /// Get the size of the input sequence.
+  std::size_t size() const ASIO_NOEXCEPT
+  {
+    return size_;
+  }
+
+  /// Get the maximum size of the dynamic buffer.
+  /**
+   * @returns The allowed maximum of the sum of the sizes of the input sequence
+   * and output sequence.
+   */
+  std::size_t max_size() const ASIO_NOEXCEPT
+  {
+    return max_size_;
+  }
+
+  /// Get the current capacity of the dynamic buffer.
+  /**
+   * @returns The current total capacity of the buffer, i.e. for both the input
+   * sequence and output sequence.
+   */
+  std::size_t capacity() const ASIO_NOEXCEPT
+  {
+    return string_.capacity();
+  }
+
+  /// Get a list of buffers that represents the input sequence.
+  /**
+   * @returns An object of type @c const_buffers_type that satisfies
+   * ConstBufferSequence requirements, representing the basic_string memory in
+   * input sequence.
+   *
+   * @note The returned object is invalidated by any @c dynamic_string_buffer
+   * or @c basic_string member function that modifies the input sequence or
+   * output sequence.
+   */
+  const_buffers_type data() const ASIO_NOEXCEPT
+  {
+    return asio::buffer(string_, size_);
+  }
+
+  /// Get a list of buffers that represents the output sequence, with the given
+  /// size.
+  /**
+   * Ensures that the output sequence can accommodate @c n bytes, resizing the
+   * basic_string object as necessary.
+   *
+   * @returns An object of type @c mutable_buffers_type that satisfies
+   * MutableBufferSequence requirements, representing basic_string memory
+   * at the start of the output sequence of size @c n.
+   *
+   * @throws std::length_error If <tt>size() + n > max_size()</tt>.
+   *
+   * @note The returned object is invalidated by any @c dynamic_string_buffer
+   * or @c basic_string member function that modifies the input sequence or
+   * output sequence.
+   */
+  mutable_buffers_type prepare(std::size_t n)
+  {
+    if (size () > max_size() || max_size() - size() < n)
+    {
+      std::length_error ex("dynamic_string_buffer too long");
+      asio::detail::throw_exception(ex);
+    }
+
+    string_.resize(size_ + n);
+
+    return asio::buffer(asio::buffer(string_) + size_, n);
+  }
+
+  /// Move bytes from the output sequence to the input sequence.
+  /**
+   * @param n The number of bytes to append from the start of the output
+   * sequence to the end of the input sequence. The remainder of the output
+   * sequence is discarded.
+   *
+   * Requires a preceding call <tt>prepare(x)</tt> where <tt>x >= n</tt>, and
+   * no intervening operations that modify the input or output sequence.
+   *
+   * @note If @c n is greater than the size of the output sequence, the entire
+   * output sequence is moved to the input sequence and no error is issued.
+   */
+  void commit(std::size_t n)
+  {
+    size_ += (std::min)(n, string_.size() - size_);
+    string_.resize(size_);
+  }
+
+  /// Remove characters from the input sequence.
+  /**
+   * Removes @c n characters from the beginning of the input sequence.
+   *
+   * @note If @c n is greater than the size of the input sequence, the entire
+   * input sequence is consumed and no error is issued.
+   */
+  void consume(std::size_t n)
+  {
+    std::size_t consume_length = (std::min)(n, size_);
+    string_.erase(consume_length);
+    size_ -= consume_length;
+  }
+
+private:
+  std::basic_string<Elem, Traits, Allocator>& string_;
+  std::size_t size_;
+  const std::size_t max_size_;
+};
+
+/// Adapt a vector to the DynamicBufferSequence requirements.
+/**
+ * Requires that <tt>sizeof(Elem) == 1</tt>.
+ */
+template <typename Elem, typename Allocator>
+class dynamic_vector_buffer
+{
+public:
+  /// The type used to represent the input sequence as a list of buffers.
+  typedef const_buffers_1 const_buffers_type;
+
+  /// The type used to represent the output sequence as a list of buffers.
+  typedef mutable_buffers_1 mutable_buffers_type;
+
+  /// Construct a dynamic buffer from a string.
+  /**
+   * @param s The string to be used as backing storage for the dynamic buffer.
+   * Any existing data in the string is treated as the dynamic buffer's input
+   * sequence. The object stores a reference to the string and the user is
+   * responsible for ensuring that the string object remains valid until the
+   * dynamic_vector_buffer object is destroyed.
+   */
+  explicit dynamic_vector_buffer(std::vector<Elem, Allocator>& v,
+      std::size_t maximum_size = (std::numeric_limits<std::size_t>::max)())
+    : vector_(v),
+      size_(vector_.size()),
+      max_size_(maximum_size)
+  {
+  }
+
+#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+  /// Move construct a dynamic buffer.
+  dynamic_vector_buffer(dynamic_vector_buffer&& other)
+    : vector_(other.vector_),
+      size_(other.size_),
+      max_size_(other.max_size_)
+  {
+  }
+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
+
+  /// Get the size of the input sequence.
+  std::size_t size() const ASIO_NOEXCEPT
+  {
+    return size_;
+  }
+
+  /// Get the maximum size of the dynamic buffer.
+  /**
+   * @returns The allowed maximum of the sum of the sizes of the input sequence
+   * and output sequence.
+   */
+  std::size_t max_size() const ASIO_NOEXCEPT
+  {
+    return max_size_;
+  }
+
+  /// Get the current capacity of the dynamic buffer.
+  /**
+   * @returns The current total capacity of the buffer, i.e. for both the input
+   * sequence and output sequence.
+   */
+  std::size_t capacity() const ASIO_NOEXCEPT
+  {
+    return vector_.capacity();
+  }
+
+  /// Get a list of buffers that represents the input sequence.
+  /**
+   * @returns An object of type @c const_buffers_type that satisfies
+   * ConstBufferSequence requirements, representing the basic_string memory in
+   * input sequence.
+   *
+   * @note The returned object is invalidated by any @c dynamic_vector_buffer
+   * or @c basic_string member function that modifies the input sequence or
+   * output sequence.
+   */
+  const_buffers_type data() const ASIO_NOEXCEPT
+  {
+    return asio::buffer(vector_, size_);
+  }
+
+  /// Get a list of buffers that represents the output sequence, with the given
+  /// size.
+  /**
+   * Ensures that the output sequence can accommodate @c n bytes, resizing the
+   * basic_string object as necessary.
+   *
+   * @returns An object of type @c mutable_buffers_type that satisfies
+   * MutableBufferSequence requirements, representing basic_string memory
+   * at the start of the output sequence of size @c n.
+   *
+   * @throws std::length_error If <tt>size() + n > max_size()</tt>.
+   *
+   * @note The returned object is invalidated by any @c dynamic_vector_buffer
+   * or @c basic_string member function that modifies the input sequence or
+   * output sequence.
+   */
+  mutable_buffers_type prepare(std::size_t n)
+  {
+    if (size () > max_size() || max_size() - size() < n)
+    {
+      std::length_error ex("dynamic_vector_buffer too long");
+      asio::detail::throw_exception(ex);
+    }
+
+    vector_.resize(size_ + n);
+
+    return asio::buffer(asio::buffer(vector_) + size_, n);
+  }
+
+  /// Move bytes from the output sequence to the input sequence.
+  /**
+   * @param n The number of bytes to append from the start of the output
+   * sequence to the end of the input sequence. The remainder of the output
+   * sequence is discarded.
+   *
+   * Requires a preceding call <tt>prepare(x)</tt> where <tt>x >= n</tt>, and
+   * no intervening operations that modify the input or output sequence.
+   *
+   * @note If @c n is greater than the size of the output sequence, the entire
+   * output sequence is moved to the input sequence and no error is issued.
+   */
+  void commit(std::size_t n)
+  {
+    size_ += (std::min)(n, vector_.size() - size_);
+    vector_.resize(size_);
+  }
+
+  /// Remove characters from the input sequence.
+  /**
+   * Removes @c n characters from the beginning of the input sequence.
+   *
+   * @note If @c n is greater than the size of the input sequence, the entire
+   * input sequence is consumed and no error is issued.
+   */
+  void consume(std::size_t n)
+  {
+    std::size_t consume_length = (std::min)(n, size_);
+    vector_.erase(consume_length);
+    size_ -= consume_length;
+  }
+
+private:
+  std::vector<Elem, Allocator>& vector_;
+  std::size_t size_;
+  const std::size_t max_size_;
+};
+
+/** @defgroup dynamic_buffer asio::dynamic_buffer
+ *
+ * @brief The asio::dynamic_buffer function is used to create a
+ * dynamically resized buffer from a @c std::basic_string or @c std::vector.
+ */
+/*@{*/
+
+/// Create a new dynamic buffer that represents the given string.
+/**
+ * @returns <tt>dynamic_string_buffer<Elem, Traits, Allocator>(data)</tt>.
+ */
+template <typename Elem, typename Traits, typename Allocator>
+inline dynamic_string_buffer<Elem, Traits, Allocator> dynamic_buffer(
+    std::basic_string<Elem, Traits, Allocator>& data)
+{
+  return dynamic_string_buffer<Elem, Traits, Allocator>(data);
+}
+
+/// Create a new dynamic buffer that represents the given string.
+/**
+ * @returns <tt>dynamic_string_buffer<Elem, Traits, Allocator>(data,
+ * max_size)</tt>.
+ */
+template <typename Elem, typename Traits, typename Allocator>
+inline dynamic_string_buffer<Elem, Traits, Allocator> dynamic_buffer(
+    std::basic_string<Elem, Traits, Allocator>& data, std::size_t max_size)
+{
+  return dynamic_string_buffer<Elem, Traits, Allocator>(data, max_size);
+}
+
+/// Create a new dynamic buffer that represents the given vector.
+/**
+ * @returns <tt>dynamic_vector_buffer<Elem, Allocator>(data)</tt>.
+ */
+template <typename Elem, typename Allocator>
+inline dynamic_vector_buffer<Elem, Allocator> dynamic_buffer(
+    std::vector<Elem, Allocator>& data)
+{
+  return dynamic_vector_buffer<Elem, Allocator>(data);
+}
+
+/// Create a new dynamic buffer that represents the given vector.
+/**
+ * @returns <tt>dynamic_vector_buffer<Elem, Allocator>(data, max_size)</tt>.
+ */
+template <typename Elem, typename Allocator>
+inline dynamic_vector_buffer<Elem, Allocator> dynamic_buffer(
+    std::vector<Elem, Allocator>& data, std::size_t max_size)
+{
+  return dynamic_vector_buffer<Elem, Allocator>(data, max_size);
+}
+
+/*@}*/
+
 /** @defgroup buffer_copy asio::buffer_copy
  *
  * @brief The asio::buffer_copy function is used to copy bytes from a
@@ -1334,7 +1699,7 @@
  * @li A 2-argument form: @c buffer_copy(target, source)
  *
  * @li A 3-argument form: @c buffer_copy(target, source, max_bytes_to_copy)
-
+ *
  * Both forms return the number of bytes actually copied. The number of bytes
  * copied is the lesser of:
  *
diff --git a/asio/include/asio/detail/is_buffer_sequence.hpp b/asio/include/asio/detail/is_buffer_sequence.hpp
index 7d8c18f..e1049b2 100644
--- a/asio/include/asio/detail/is_buffer_sequence.hpp
+++ b/asio/include/asio/detail/is_buffer_sequence.hpp
@@ -23,20 +23,27 @@
 namespace asio {
 namespace detail {
 
-struct begin_end_memfns_base
+struct buffer_sequence_memfns_base
 {
   void begin();
   void end();
+  void size();
+  void max_size();
+  void capacity();
+  void data();
+  void prepare();
+  void commit();
+  void consume();
 };
 
 template <typename T>
-struct begin_end_memfns_derived
-  : T, begin_end_memfns_base
+struct buffer_sequence_memfns_derived
+  : T, buffer_sequence_memfns_base
 {
 };
 
 template <typename T, T>
-struct begin_end_memfns_check
+struct buffer_sequence_memfns_check
 {
 };
 
@@ -45,18 +52,81 @@
 
 template <typename T>
 char begin_memfn_helper(
-    begin_end_memfns_check<
-      void (begin_end_memfns_base::*)(),
-      &begin_end_memfns_derived<T>::begin>*);
+    buffer_sequence_memfns_check<
+      void (buffer_sequence_memfns_base::*)(),
+      &buffer_sequence_memfns_derived<T>::begin>*);
 
 template <typename>
 char (&end_memfn_helper(...))[2];
 
 template <typename T>
 char end_memfn_helper(
-    begin_end_memfns_check<
-      void (begin_end_memfns_base::*)(),
-      &begin_end_memfns_derived<T>::end>*);
+    buffer_sequence_memfns_check<
+      void (buffer_sequence_memfns_base::*)(),
+      &buffer_sequence_memfns_derived<T>::end>*);
+
+template <typename>
+char (&size_memfn_helper(...))[2];
+
+template <typename T>
+char size_memfn_helper(
+    buffer_sequence_memfns_check<
+      void (buffer_sequence_memfns_base::*)(),
+      &buffer_sequence_memfns_derived<T>::size>*);
+
+template <typename>
+char (&max_size_memfn_helper(...))[2];
+
+template <typename T>
+char max_size_memfn_helper(
+    buffer_sequence_memfns_check<
+      void (buffer_sequence_memfns_base::*)(),
+      &buffer_sequence_memfns_derived<T>::max_size>*);
+
+template <typename>
+char (&capacity_memfn_helper(...))[2];
+
+template <typename T>
+char capacity_memfn_helper(
+    buffer_sequence_memfns_check<
+      void (buffer_sequence_memfns_base::*)(),
+      &buffer_sequence_memfns_derived<T>::capacity>*);
+
+template <typename>
+char (&data_memfn_helper(...))[2];
+
+template <typename T>
+char data_memfn_helper(
+    buffer_sequence_memfns_check<
+      void (buffer_sequence_memfns_base::*)(),
+      &buffer_sequence_memfns_derived<T>::data>*);
+
+template <typename>
+char (&prepare_memfn_helper(...))[2];
+
+template <typename T>
+char prepare_memfn_helper(
+    buffer_sequence_memfns_check<
+      void (buffer_sequence_memfns_base::*)(),
+      &buffer_sequence_memfns_derived<T>::data>*);
+
+template <typename>
+char (&commit_memfn_helper(...))[2];
+
+template <typename T>
+char commit_memfn_helper(
+    buffer_sequence_memfns_check<
+      void (buffer_sequence_memfns_base::*)(),
+      &buffer_sequence_memfns_derived<T>::commit>*);
+
+template <typename>
+char (&consume_memfn_helper(...))[2];
+
+template <typename T>
+char consume_memfn_helper(
+    buffer_sequence_memfns_check<
+      void (buffer_sequence_memfns_base::*)(),
+      &buffer_sequence_memfns_derived<T>::consume>*);
 
 template <typename, typename>
 char (&value_type_const_iterator_typedefs_helper(...))[2];
@@ -67,6 +137,20 @@
     typename enable_if<is_convertible<
       typename T::value_type, Buffer>::value>::type*);
 
+template <typename>
+char (&const_buffers_type_typedef_helper(...))[2];
+
+template <typename T>
+char const_buffers_type_typedef_helper(
+    typename T::const_buffers_type*);
+
+template <typename>
+char (&mutable_buffers_type_typedef_helper(...))[2];
+
+template <typename T>
+char mutable_buffers_type_typedef_helper(
+    typename T::mutable_buffers_type*);
+
 template <typename T, typename Buffer>
 struct is_buffer_sequence_class
   : integral_constant<bool,
@@ -84,6 +168,29 @@
 {
 };
 
+template <typename T>
+struct is_dynamic_buffer_sequence_class
+  : integral_constant<bool,
+      sizeof(size_memfn_helper<T>(0)) != 1 &&
+      sizeof(max_size_memfn_helper<T>(0)) != 1 &&
+      sizeof(capacity_memfn_helper<T>(0)) != 1 &&
+      sizeof(data_memfn_helper<T>(0)) != 1 &&
+      sizeof(consume_memfn_helper<T>(0)) != 1 &&
+      sizeof(prepare_memfn_helper<T>(0)) != 1 &&
+      sizeof(commit_memfn_helper<T>(0)) != 1 &&
+      sizeof(const_buffers_type_typedef_helper<T>(0)) == 1 &&
+      sizeof(mutable_buffers_type_typedef_helper<T>(0)) == 1>
+{
+};
+
+template <typename T>
+struct is_dynamic_buffer_sequence
+  : conditional<is_class<T>::value,
+      is_dynamic_buffer_sequence_class<T>,
+      false_type>::type
+{
+};
+
 } // namespace detail
 } // namespace asio
 
diff --git a/asio/include/asio/impl/read.hpp b/asio/include/asio/impl/read.hpp
index 2eaba11..99c2788 100644
--- a/asio/include/asio/impl/read.hpp
+++ b/asio/include/asio/impl/read.hpp
@@ -39,7 +39,10 @@
 template <typename SyncReadStream, typename MutableBufferSequence,
     typename CompletionCondition>
 std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
-    CompletionCondition completion_condition, asio::error_code& ec)
+    CompletionCondition completion_condition, asio::error_code& ec,
+    typename enable_if<
+      is_mutable_buffer_sequence<MutableBufferSequence>::value
+    >::type*)
 {
   ec = asio::error_code();
   asio::detail::consuming_buffers<
@@ -59,7 +62,10 @@
 }
 
 template <typename SyncReadStream, typename MutableBufferSequence>
-inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers)
+inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
+    typename enable_if<
+      is_mutable_buffer_sequence<MutableBufferSequence>::value
+    >::type*)
 {
   asio::error_code ec;
   std::size_t bytes_transferred = read(s, buffers, transfer_all(), ec);
@@ -69,7 +75,10 @@
 
 template <typename SyncReadStream, typename MutableBufferSequence>
 inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
-    asio::error_code& ec)
+    asio::error_code& ec,
+    typename enable_if<
+      is_mutable_buffer_sequence<MutableBufferSequence>::value
+    >::type*)
 {
   return read(s, buffers, transfer_all(), ec);
 }
@@ -77,7 +86,10 @@
 template <typename SyncReadStream, typename MutableBufferSequence,
     typename CompletionCondition>
 inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
-    CompletionCondition completion_condition)
+    CompletionCondition completion_condition,
+    typename enable_if<
+      is_mutable_buffer_sequence<MutableBufferSequence>::value
+    >::type*)
 {
   asio::error_code ec;
   std::size_t bytes_transferred = read(s, buffers, completion_condition, ec);
@@ -85,39 +97,98 @@
   return bytes_transferred;
 }
 
+template <typename SyncReadStream, typename DynamicBufferSequence,
+    typename CompletionCondition>
+std::size_t read(SyncReadStream& s,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    CompletionCondition completion_condition, asio::error_code& ec,
+    typename enable_if<
+      is_dynamic_buffer_sequence<DynamicBufferSequence>::value
+    >::type*)
+{
+  typename decay<DynamicBufferSequence>::type b(
+      ASIO_MOVE_CAST(DynamicBufferSequence)(buffers));
+
+  ec = asio::error_code();
+  std::size_t total_transferred = 0;
+  std::size_t max_size = detail::adapt_completion_condition_result(
+        completion_condition(ec, total_transferred));
+  std::size_t bytes_available = std::min<std::size_t>(
+        std::max<std::size_t>(512, b.capacity() - b.size()),
+        std::min<std::size_t>(max_size, b.max_size() - b.size()));
+  while (bytes_available > 0)
+  {
+    std::size_t bytes_transferred = s.read_some(b.prepare(bytes_available), ec);
+    b.commit(bytes_transferred);
+    total_transferred += bytes_transferred;
+    max_size = detail::adapt_completion_condition_result(
+          completion_condition(ec, total_transferred));
+    bytes_available = std::min<std::size_t>(
+          std::max<std::size_t>(512, b.capacity() - b.size()),
+          std::min<std::size_t>(max_size, b.max_size() - b.size()));
+  }
+  return total_transferred;
+}
+
+template <typename SyncReadStream, typename DynamicBufferSequence>
+inline std::size_t read(SyncReadStream& s,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    typename enable_if<
+      is_dynamic_buffer_sequence<DynamicBufferSequence>::value
+    >::type*)
+{
+  asio::error_code ec;
+  std::size_t bytes_transferred = read(s,
+      ASIO_MOVE_CAST(DynamicBufferSequence)(buffers), transfer_all(), ec);
+  asio::detail::throw_error(ec, "read");
+  return bytes_transferred;
+}
+
+template <typename SyncReadStream, typename DynamicBufferSequence>
+inline std::size_t read(SyncReadStream& s,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    asio::error_code& ec,
+    typename enable_if<
+      is_dynamic_buffer_sequence<DynamicBufferSequence>::value
+    >::type*)
+{
+  return read(s, ASIO_MOVE_CAST(DynamicBufferSequence)(buffers),
+      transfer_all(), ec);
+}
+
+template <typename SyncReadStream, typename DynamicBufferSequence,
+    typename CompletionCondition>
+inline std::size_t read(SyncReadStream& s,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    CompletionCondition completion_condition,
+    typename enable_if<
+      is_dynamic_buffer_sequence<DynamicBufferSequence>::value
+    >::type*)
+{
+  asio::error_code ec;
+  std::size_t bytes_transferred = read(s,
+      ASIO_MOVE_CAST(DynamicBufferSequence)(buffers),
+      completion_condition, ec);
+  asio::detail::throw_error(ec, "read");
+  return bytes_transferred;
+}
+
 #if !defined(ASIO_NO_IOSTREAM)
 
 template <typename SyncReadStream, typename Allocator,
     typename CompletionCondition>
-std::size_t read(SyncReadStream& s,
+inline std::size_t read(SyncReadStream& s,
     asio::basic_streambuf<Allocator>& b,
     CompletionCondition completion_condition, asio::error_code& ec)
 {
-  ec = asio::error_code();
-  std::size_t total_transferred = 0;
-  std::size_t max_size = detail::adapt_completion_condition_result(
-        completion_condition(ec, total_transferred));
-  std::size_t bytes_available = read_size_helper(b, max_size);
-  while (bytes_available > 0)
-  {
-    std::size_t bytes_transferred = s.read_some(b.prepare(bytes_available), ec);
-    b.commit(bytes_transferred);
-    total_transferred += bytes_transferred;
-    max_size = detail::adapt_completion_condition_result(
-          completion_condition(ec, total_transferred));
-    bytes_available = read_size_helper(b, max_size);
-  }
-  return total_transferred;
+  return read(s, basic_streambuf_ref<Allocator>(b), completion_condition, ec);
 }
 
 template <typename SyncReadStream, typename Allocator>
 inline std::size_t read(SyncReadStream& s,
     asio::basic_streambuf<Allocator>& b)
 {
-  asio::error_code ec;
-  std::size_t bytes_transferred = read(s, b, transfer_all(), ec);
-  asio::detail::throw_error(ec, "read");
-  return bytes_transferred;
+  return read(s, basic_streambuf_ref<Allocator>(b));
 }
 
 template <typename SyncReadStream, typename Allocator>
@@ -125,7 +196,7 @@
     asio::basic_streambuf<Allocator>& b,
     asio::error_code& ec)
 {
-  return read(s, b, transfer_all(), ec);
+  return read(s, basic_streambuf_ref<Allocator>(b), ec);
 }
 
 template <typename SyncReadStream, typename Allocator,
@@ -134,10 +205,7 @@
     asio::basic_streambuf<Allocator>& b,
     CompletionCondition completion_condition)
 {
-  asio::error_code ec;
-  std::size_t bytes_transferred = read(s, b, completion_condition, ec);
-  asio::detail::throw_error(ec, "read");
-  return bytes_transferred;
+  return read(s, basic_streambuf_ref<Allocator>(b), completion_condition);
 }
 
 #endif // !defined(ASIO_NO_IOSTREAM)
@@ -562,7 +630,10 @@
     void (asio::error_code, std::size_t))
 async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
     CompletionCondition completion_condition,
-    ASIO_MOVE_ARG(ReadHandler) handler)
+    ASIO_MOVE_ARG(ReadHandler) handler,
+    typename enable_if<
+      is_mutable_buffer_sequence<MutableBufferSequence>::value
+    >::type*)
 {
   // If you get an error on the following line it means that your handler does
   // not meet the documented type requirements for a ReadHandler.
@@ -585,7 +656,10 @@
 inline ASIO_INITFN_RESULT_TYPE(ReadHandler,
     void (asio::error_code, std::size_t))
 async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
-    ASIO_MOVE_ARG(ReadHandler) handler)
+    ASIO_MOVE_ARG(ReadHandler) handler,
+    typename enable_if<
+      is_mutable_buffer_sequence<MutableBufferSequence>::value
+    >::type*)
 {
   // If you get an error on the following line it means that your handler does
   // not meet the documented type requirements for a ReadHandler.
@@ -603,23 +677,22 @@
   return init.result.get();
 }
 
-#if !defined(ASIO_NO_IOSTREAM)
-
 namespace detail
 {
-  template <typename AsyncReadStream, typename Allocator,
+  template <typename AsyncReadStream, typename DynamicBufferSequence,
       typename CompletionCondition, typename ReadHandler>
-  class read_streambuf_op
+  class read_dynbuf_op
     : detail::base_from_completion_cond<CompletionCondition>
   {
   public:
-    read_streambuf_op(AsyncReadStream& stream,
-        basic_streambuf<Allocator>& streambuf,
+    template <typename BufferSequence>
+    read_dynbuf_op(AsyncReadStream& stream,
+        ASIO_MOVE_ARG(BufferSequence) buffers,
         CompletionCondition completion_condition, ReadHandler& handler)
       : detail::base_from_completion_cond<
           CompletionCondition>(completion_condition),
         stream_(stream),
-        streambuf_(streambuf),
+        buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)),
         start_(0),
         total_transferred_(0),
         handler_(ASIO_MOVE_CAST(ReadHandler)(handler))
@@ -627,20 +700,20 @@
     }
 
 #if defined(ASIO_HAS_MOVE)
-    read_streambuf_op(const read_streambuf_op& other)
+    read_dynbuf_op(const read_dynbuf_op& other)
       : detail::base_from_completion_cond<CompletionCondition>(other),
         stream_(other.stream_),
-        streambuf_(other.streambuf_),
+        buffers_(other.buffers_),
         start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(other.handler_)
     {
     }
 
-    read_streambuf_op(read_streambuf_op&& other)
+    read_dynbuf_op(read_dynbuf_op&& other)
       : detail::base_from_completion_cond<CompletionCondition>(other),
         stream_(other.stream_),
-        streambuf_(other.streambuf_),
+        buffers_(ASIO_MOVE_CAST(DynamicBufferSequence)(other.buffers_)),
         start_(other.start_),
         total_transferred_(other.total_transferred_),
         handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))
@@ -656,16 +729,24 @@
       {
         case 1:
         max_size = this->check_for_completion(ec, total_transferred_);
-        bytes_available = read_size_helper(streambuf_, max_size);
+        bytes_available = std::min<std::size_t>(
+              std::max<std::size_t>(512,
+                buffers_.capacity() - buffers_.size()),
+              std::min<std::size_t>(max_size,
+                buffers_.max_size() - buffers_.size()));
         for (;;)
         {
-          stream_.async_read_some(streambuf_.prepare(bytes_available),
-              ASIO_MOVE_CAST(read_streambuf_op)(*this));
+          stream_.async_read_some(buffers_.prepare(bytes_available),
+              ASIO_MOVE_CAST(read_dynbuf_op)(*this));
           return; default:
           total_transferred_ += bytes_transferred;
-          streambuf_.commit(bytes_transferred);
+          buffers_.commit(bytes_transferred);
           max_size = this->check_for_completion(ec, total_transferred_);
-          bytes_available = read_size_helper(streambuf_, max_size);
+          bytes_available = std::min<std::size_t>(
+                std::max<std::size_t>(512,
+                  buffers_.capacity() - buffers_.size()),
+                std::min<std::size_t>(max_size,
+                  buffers_.max_size() - buffers_.size()));
           if ((!ec && bytes_transferred == 0) || bytes_available == 0)
             break;
         }
@@ -676,36 +757,36 @@
 
   //private:
     AsyncReadStream& stream_;
-    asio::basic_streambuf<Allocator>& streambuf_;
+    DynamicBufferSequence buffers_;
     int start_;
     std::size_t total_transferred_;
     ReadHandler handler_;
   };
 
-  template <typename AsyncReadStream, typename Allocator,
+  template <typename AsyncReadStream, typename DynamicBufferSequence,
       typename CompletionCondition, typename ReadHandler>
   inline void* asio_handler_allocate(std::size_t size,
-      read_streambuf_op<AsyncReadStream, Allocator,
+      read_dynbuf_op<AsyncReadStream, DynamicBufferSequence,
         CompletionCondition, ReadHandler>* this_handler)
   {
     return asio_handler_alloc_helpers::allocate(
         size, this_handler->handler_);
   }
 
-  template <typename AsyncReadStream, typename Allocator,
+  template <typename AsyncReadStream, typename DynamicBufferSequence,
       typename CompletionCondition, typename ReadHandler>
   inline void asio_handler_deallocate(void* pointer, std::size_t size,
-      read_streambuf_op<AsyncReadStream, Allocator,
+      read_dynbuf_op<AsyncReadStream, DynamicBufferSequence,
         CompletionCondition, ReadHandler>* this_handler)
   {
     asio_handler_alloc_helpers::deallocate(
         pointer, size, this_handler->handler_);
   }
 
-  template <typename AsyncReadStream, typename Allocator,
+  template <typename AsyncReadStream, typename DynamicBufferSequence,
       typename CompletionCondition, typename ReadHandler>
   inline bool asio_handler_is_continuation(
-      read_streambuf_op<AsyncReadStream, Allocator,
+      read_dynbuf_op<AsyncReadStream, DynamicBufferSequence,
         CompletionCondition, ReadHandler>* this_handler)
   {
     return this_handler->start_ == 0 ? true
@@ -714,9 +795,10 @@
   }
 
   template <typename Function, typename AsyncReadStream,
-      typename Allocator, typename CompletionCondition, typename ReadHandler>
+      typename DynamicBufferSequence, typename CompletionCondition,
+      typename ReadHandler>
   inline void asio_handler_invoke(Function& function,
-      read_streambuf_op<AsyncReadStream, Allocator,
+      read_dynbuf_op<AsyncReadStream, DynamicBufferSequence,
         CompletionCondition, ReadHandler>* this_handler)
   {
     asio_handler_invoke_helpers::invoke(
@@ -724,9 +806,10 @@
   }
 
   template <typename Function, typename AsyncReadStream,
-      typename Allocator, typename CompletionCondition, typename ReadHandler>
+      typename DynamicBufferSequence, typename CompletionCondition,
+      typename ReadHandler>
   inline void asio_handler_invoke(const Function& function,
-      read_streambuf_op<AsyncReadStream, Allocator,
+      read_dynbuf_op<AsyncReadStream, DynamicBufferSequence,
         CompletionCondition, ReadHandler>* this_handler)
   {
     asio_handler_invoke_helpers::invoke(
@@ -736,52 +819,71 @@
 
 #if !defined(GENERATING_DOCUMENTATION)
 
-template <typename AsyncReadStream, typename Allocator,
-    typename CompletionCondition, typename ReadHandler, typename Allocator1>
+template <typename AsyncReadStream, typename DynamicBufferSequence,
+    typename CompletionCondition, typename ReadHandler, typename Allocator>
 struct associated_allocator<
-    detail::read_streambuf_op<AsyncReadStream,
-      Allocator, CompletionCondition, ReadHandler>,
-    Allocator1>
+    detail::read_dynbuf_op<AsyncReadStream,
+      DynamicBufferSequence, CompletionCondition, ReadHandler>,
+    Allocator>
 {
-  typedef typename associated_allocator<ReadHandler, Allocator1>::type type;
+  typedef typename associated_allocator<ReadHandler, Allocator>::type type;
 
   static type get(
-      const detail::read_streambuf_op<AsyncReadStream, Allocator,
-        CompletionCondition, ReadHandler>& h,
-      const Allocator1& a = Allocator1()) ASIO_NOEXCEPT
+      const detail::read_dynbuf_op<AsyncReadStream,
+        DynamicBufferSequence, CompletionCondition, ReadHandler>& h,
+      const Allocator& a = Allocator()) ASIO_NOEXCEPT
   {
-    return associated_allocator<ReadHandler, Allocator1>::get(h.handler_, a);
+    return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
   }
 };
 
-template <typename AsyncReadStream, typename Executor,
-    typename CompletionCondition, typename ReadHandler, typename Executor1>
+template <typename AsyncReadStream, typename DynamicBufferSequence,
+    typename CompletionCondition, typename ReadHandler, typename Executor>
 struct associated_executor<
-    detail::read_streambuf_op<AsyncReadStream,
-      Executor, CompletionCondition, ReadHandler>,
-    Executor1>
+    detail::read_dynbuf_op<AsyncReadStream,
+      DynamicBufferSequence, CompletionCondition, ReadHandler>,
+    Executor>
 {
-  typedef typename associated_executor<ReadHandler, Executor1>::type type;
+  typedef typename associated_executor<ReadHandler, Executor>::type type;
 
   static type get(
-      const detail::read_streambuf_op<AsyncReadStream, Executor,
-        CompletionCondition, ReadHandler>& h,
-      const Executor1& ex = Executor1()) ASIO_NOEXCEPT
+      const detail::read_dynbuf_op<AsyncReadStream,
+        DynamicBufferSequence, CompletionCondition, ReadHandler>& h,
+      const Executor& ex = Executor()) ASIO_NOEXCEPT
   {
-    return associated_executor<ReadHandler, Executor1>::get(h.handler_, ex);
+    return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
   }
 };
 
 #endif // !defined(GENERATING_DOCUMENTATION)
 
-template <typename AsyncReadStream, typename Allocator,
+template <typename AsyncReadStream,
+    typename DynamicBufferSequence, typename ReadHandler>
+inline ASIO_INITFN_RESULT_TYPE(ReadHandler,
+    void (asio::error_code, std::size_t))
+async_read(AsyncReadStream& s,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    ASIO_MOVE_ARG(ReadHandler) handler,
+    typename enable_if<
+      is_dynamic_buffer_sequence<DynamicBufferSequence>::value
+    >::type*)
+{
+  return async_read(s,
+      ASIO_MOVE_CAST(DynamicBufferSequence)(buffers),
+      transfer_all(), ASIO_MOVE_CAST(ReadHandler)(handler));
+}
+
+template <typename AsyncReadStream, typename DynamicBufferSequence,
     typename CompletionCondition, typename ReadHandler>
 inline ASIO_INITFN_RESULT_TYPE(ReadHandler,
     void (asio::error_code, std::size_t))
 async_read(AsyncReadStream& s,
-    asio::basic_streambuf<Allocator>& b,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
     CompletionCondition completion_condition,
-    ASIO_MOVE_ARG(ReadHandler) handler)
+    ASIO_MOVE_ARG(ReadHandler) handler,
+    typename enable_if<
+      is_dynamic_buffer_sequence<DynamicBufferSequence>::value
+    >::type*)
 {
   // If you get an error on the following line it means that your handler does
   // not meet the documented type requirements for a ReadHandler.
@@ -790,36 +892,39 @@
   async_completion<ReadHandler,
     void (asio::error_code, std::size_t)> init(handler);
 
-  detail::read_streambuf_op<AsyncReadStream, Allocator,
-    CompletionCondition, ASIO_HANDLER_TYPE(
-      ReadHandler, void (asio::error_code, std::size_t))>(
-        s, b, completion_condition, init.handler)(
-          asio::error_code(), 0, 1);
+  detail::read_dynbuf_op<AsyncReadStream,
+    typename decay<DynamicBufferSequence>::type,
+      CompletionCondition, ASIO_HANDLER_TYPE(
+        ReadHandler, void (asio::error_code, std::size_t))>(
+          s, ASIO_MOVE_CAST(DynamicBufferSequence)(buffers),
+            completion_condition, init.handler)(
+              asio::error_code(), 0, 1);
 
   return init.result.get();
 }
 
+#if !defined(ASIO_NO_IOSTREAM)
+
 template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
 inline ASIO_INITFN_RESULT_TYPE(ReadHandler,
     void (asio::error_code, std::size_t))
-async_read(AsyncReadStream& s,
-    asio::basic_streambuf<Allocator>& b,
+async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,
     ASIO_MOVE_ARG(ReadHandler) handler)
 {
-  // If you get an error on the following line it means that your handler does
-  // not meet the documented type requirements for a ReadHandler.
-  ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;
+  return async_read(s, basic_streambuf_ref<Allocator>(b),
+      ASIO_MOVE_CAST(ReadHandler)(handler));
+}
 
-  async_completion<ReadHandler,
-    void (asio::error_code, std::size_t)> init(handler);
-
-  detail::read_streambuf_op<AsyncReadStream, Allocator,
-    detail::transfer_all_t, ASIO_HANDLER_TYPE(
-      ReadHandler, void (asio::error_code, std::size_t))>(
-        s, b, transfer_all(), init.handler)(
-          asio::error_code(), 0, 1);
-
-  return init.result.get();
+template <typename AsyncReadStream, typename Allocator,
+    typename CompletionCondition, typename ReadHandler>
+inline ASIO_INITFN_RESULT_TYPE(ReadHandler,
+    void (asio::error_code, std::size_t))
+async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,
+    CompletionCondition completion_condition,
+    ASIO_MOVE_ARG(ReadHandler) handler)
+{
+  return async_read(s, basic_streambuf_ref<Allocator>(b),
+      completion_condition, ASIO_MOVE_CAST(ReadHandler)(handler));
 }
 
 #endif // !defined(ASIO_NO_IOSTREAM)
diff --git a/asio/include/asio/impl/read_until.hpp b/asio/include/asio/impl/read_until.hpp
index a27353e..cdada8a 100644
--- a/asio/include/asio/impl/read_until.hpp
+++ b/asio/include/asio/impl/read_until.hpp
@@ -35,32 +35,35 @@
 
 namespace asio {
 
-template <typename SyncReadStream, typename Allocator>
+template <typename SyncReadStream, typename DynamicBufferSequence>
 inline std::size_t read_until(SyncReadStream& s,
-    asio::basic_streambuf<Allocator>& b, char delim)
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers, char delim)
 {
   asio::error_code ec;
-  std::size_t bytes_transferred = read_until(s, b, delim, ec);
+  std::size_t bytes_transferred = read_until(s,
+      ASIO_MOVE_CAST(DynamicBufferSequence)(buffers), delim, ec);
   asio::detail::throw_error(ec, "read_until");
   return bytes_transferred;
 }
 
-template <typename SyncReadStream, typename Allocator>
+template <typename SyncReadStream, typename DynamicBufferSequence>
 std::size_t read_until(SyncReadStream& s,
-    asio::basic_streambuf<Allocator>& b, char delim,
-    asio::error_code& ec)
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    char delim, asio::error_code& ec)
 {
+  typename decay<DynamicBufferSequence>::type b(
+      ASIO_MOVE_CAST(DynamicBufferSequence)(buffers));
+
   std::size_t search_position = 0;
   for (;;)
   {
     // Determine the range of the data to be searched.
-    typedef typename asio::basic_streambuf<
-      Allocator>::const_buffers_type const_buffers_type;
-    typedef asio::buffers_iterator<const_buffers_type> iterator;
-    const_buffers_type buffers = b.data();
-    iterator begin = iterator::begin(buffers);
+    typedef typename DynamicBufferSequence::const_buffers_type buffers_type;
+    typedef buffers_iterator<buffers_type> iterator;
+    buffers_type data_buffers = b.data();
+    iterator begin = iterator::begin(data_buffers);
     iterator start_pos = begin + search_position;
-    iterator end = iterator::end(buffers);
+    iterator end = iterator::end(data_buffers);
 
     // Look for a match.
     iterator iter = std::find(start_pos, end, delim);
@@ -84,19 +87,23 @@
     }
 
     // Need more data.
-    std::size_t bytes_to_read = read_size_helper(b, 65536);
+    std::size_t bytes_to_read = std::min<std::size_t>(
+          std::max<std::size_t>(512, b.capacity() - b.size()),
+          std::min<std::size_t>(65536, b.max_size() - b.size()));
     b.commit(s.read_some(b.prepare(bytes_to_read), ec));
     if (ec)
       return 0;
   }
 }
 
-template <typename SyncReadStream, typename Allocator>
+template <typename SyncReadStream, typename DynamicBufferSequence>
 inline std::size_t read_until(SyncReadStream& s,
-    asio::basic_streambuf<Allocator>& b, const std::string& delim)
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    const std::string& delim)
 {
   asio::error_code ec;
-  std::size_t bytes_transferred = read_until(s, b, delim, ec);
+  std::size_t bytes_transferred = read_until(s,
+      ASIO_MOVE_CAST(DynamicBufferSequence)(buffers), delim, ec);
   asio::detail::throw_error(ec, "read_until");
   return bytes_transferred;
 }
@@ -136,22 +143,24 @@
   }
 } // namespace detail
 
-template <typename SyncReadStream, typename Allocator>
+template <typename SyncReadStream, typename DynamicBufferSequence>
 std::size_t read_until(SyncReadStream& s,
-    asio::basic_streambuf<Allocator>& b, const std::string& delim,
-    asio::error_code& ec)
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    const std::string& delim, asio::error_code& ec)
 {
+  typename decay<DynamicBufferSequence>::type b(
+      ASIO_MOVE_CAST(DynamicBufferSequence)(buffers));
+
   std::size_t search_position = 0;
   for (;;)
   {
     // Determine the range of the data to be searched.
-    typedef typename asio::basic_streambuf<
-      Allocator>::const_buffers_type const_buffers_type;
-    typedef asio::buffers_iterator<const_buffers_type> iterator;
-    const_buffers_type buffers = b.data();
-    iterator begin = iterator::begin(buffers);
+    typedef typename DynamicBufferSequence::const_buffers_type buffers_type;
+    typedef buffers_iterator<buffers_type> iterator;
+    buffers_type data_buffers = b.data();
+    iterator begin = iterator::begin(data_buffers);
     iterator start_pos = begin + search_position;
-    iterator end = iterator::end(buffers);
+    iterator end = iterator::end(data_buffers);
 
     // Look for a match.
     std::pair<iterator, bool> result = detail::partial_search(
@@ -184,7 +193,9 @@
     }
 
     // Need more data.
-    std::size_t bytes_to_read = read_size_helper(b, 65536);
+    std::size_t bytes_to_read = std::min<std::size_t>(
+          std::max<std::size_t>(512, b.capacity() - b.size()),
+          std::min<std::size_t>(65536, b.max_size() - b.size()));
     b.commit(s.read_some(b.prepare(bytes_to_read), ec));
     if (ec)
       return 0;
@@ -193,29 +204,33 @@
 
 #if defined(ASIO_HAS_BOOST_REGEX)
 
-template <typename SyncReadStream, typename Allocator>
+template <typename SyncReadStream, typename DynamicBufferSequence>
 inline std::size_t read_until(SyncReadStream& s,
-    asio::basic_streambuf<Allocator>& b, const boost::regex& expr)
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    const boost::regex& expr)
 {
   asio::error_code ec;
-  std::size_t bytes_transferred = read_until(s, b, expr, ec);
+  std::size_t bytes_transferred = read_until(s,
+      ASIO_MOVE_CAST(DynamicBufferSequence)(buffers), expr, ec);
   asio::detail::throw_error(ec, "read_until");
   return bytes_transferred;
 }
 
-template <typename SyncReadStream, typename Allocator>
+template <typename SyncReadStream, typename DynamicBufferSequence>
 std::size_t read_until(SyncReadStream& s,
-    asio::basic_streambuf<Allocator>& b, const boost::regex& expr,
-    asio::error_code& ec)
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    const boost::regex& expr, asio::error_code& ec)
 {
+  typename decay<DynamicBufferSequence>::type b(
+      ASIO_MOVE_CAST(DynamicBufferSequence)(buffers));
+
   std::size_t search_position = 0;
   for (;;)
   {
     // Determine the range of the data to be searched.
-    typedef typename asio::basic_streambuf<
-      Allocator>::const_buffers_type const_buffers_type;
-    typedef asio::buffers_iterator<const_buffers_type> iterator;
-    const_buffers_type buffers = b.data();
+    typedef typename DynamicBufferSequence::const_buffers_type buffers_type;
+    typedef buffers_iterator<buffers_type> iterator;
+    buffers_type buffers = b.data();
     iterator begin = iterator::begin(buffers);
     iterator start_pos = begin + search_position;
     iterator end = iterator::end(buffers);
@@ -262,23 +277,41 @@
 
 #endif // defined(ASIO_HAS_BOOST_REGEX)
 
-template <typename SyncReadStream, typename Allocator, typename MatchCondition>
+template <typename SyncReadStream,
+    typename DynamicBufferSequence, typename MatchCondition>
+inline std::size_t read_until(SyncReadStream& s,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    MatchCondition match_condition,
+    typename enable_if<is_match_condition<MatchCondition>::value>::type*)
+{
+  asio::error_code ec;
+  std::size_t bytes_transferred = read_until(s,
+      ASIO_MOVE_CAST(DynamicBufferSequence)(buffers),
+      match_condition, ec);
+  asio::detail::throw_error(ec, "read_until");
+  return bytes_transferred;
+}
+
+template <typename SyncReadStream,
+    typename DynamicBufferSequence, typename MatchCondition>
 std::size_t read_until(SyncReadStream& s,
-    asio::basic_streambuf<Allocator>& b,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
     MatchCondition match_condition, asio::error_code& ec,
     typename enable_if<is_match_condition<MatchCondition>::value>::type*)
 {
+  typename decay<DynamicBufferSequence>::type b(
+      ASIO_MOVE_CAST(DynamicBufferSequence)(buffers));
+
   std::size_t search_position = 0;
   for (;;)
   {
     // Determine the range of the data to be searched.
-    typedef typename asio::basic_streambuf<
-      Allocator>::const_buffers_type const_buffers_type;
-    typedef asio::buffers_iterator<const_buffers_type> iterator;
-    const_buffers_type buffers = b.data();
-    iterator begin = iterator::begin(buffers);
+    typedef typename DynamicBufferSequence::const_buffers_type buffers_type;
+    typedef buffers_iterator<buffers_type> iterator;
+    buffers_type data_buffers = b.data();
+    iterator begin = iterator::begin(data_buffers);
     iterator start_pos = begin + search_position;
-    iterator end = iterator::end(buffers);
+    iterator end = iterator::end(data_buffers);
 
     // Look for a match.
     std::pair<iterator, bool> result = match_condition(start_pos, end);
@@ -307,35 +340,98 @@
     }
 
     // Need more data.
-    std::size_t bytes_to_read = read_size_helper(b, 65536);
+    std::size_t bytes_to_read = std::min<std::size_t>(
+          std::max<std::size_t>(512, b.capacity() - b.size()),
+          std::min<std::size_t>(65536, b.max_size() - b.size()));
     b.commit(s.read_some(b.prepare(bytes_to_read), ec));
     if (ec)
       return 0;
   }
 }
 
+#if !defined(ASIO_NO_IOSTREAM)
+
+template <typename SyncReadStream, typename Allocator>
+inline std::size_t read_until(SyncReadStream& s,
+    asio::basic_streambuf<Allocator>& b, char delim)
+{
+  return read_until(s, basic_streambuf_ref<Allocator>(b), delim);
+}
+
+template <typename SyncReadStream, typename Allocator>
+inline std::size_t read_until(SyncReadStream& s,
+    asio::basic_streambuf<Allocator>& b, char delim,
+    asio::error_code& ec)
+{
+  return read_until(s, basic_streambuf_ref<Allocator>(b), delim, ec);
+}
+
+template <typename SyncReadStream, typename Allocator>
+inline std::size_t read_until(SyncReadStream& s,
+    asio::basic_streambuf<Allocator>& b, const std::string& delim)
+{
+  return read_until(s, basic_streambuf_ref<Allocator>(b), delim);
+}
+
+template <typename SyncReadStream, typename Allocator>
+inline std::size_t read_until(SyncReadStream& s,
+    asio::basic_streambuf<Allocator>& b, const std::string& delim,
+    asio::error_code& ec)
+{
+  return read_until(s, basic_streambuf_ref<Allocator>(b), delim, ec);
+}
+
+#if defined(ASIO_HAS_BOOST_REGEX)
+
+template <typename SyncReadStream, typename Allocator>
+inline std::size_t read_until(SyncReadStream& s,
+    asio::basic_streambuf<Allocator>& b, const boost::regex& expr)
+{
+  return read_until(s, basic_streambuf_ref<Allocator>(b), expr);
+}
+
+template <typename SyncReadStream, typename Allocator>
+inline std::size_t read_until(SyncReadStream& s,
+    asio::basic_streambuf<Allocator>& b, const boost::regex& expr,
+    asio::error_code& ec)
+{
+  return read_until(s, basic_streambuf_ref<Allocator>(b), expr, ec);
+}
+
+#endif // defined(ASIO_HAS_BOOST_REGEX)
+
 template <typename SyncReadStream, typename Allocator, typename MatchCondition>
 inline std::size_t read_until(SyncReadStream& s,
     asio::basic_streambuf<Allocator>& b, MatchCondition match_condition,
     typename enable_if<is_match_condition<MatchCondition>::value>::type*)
 {
-  asio::error_code ec;
-  std::size_t bytes_transferred = read_until(s, b, match_condition, ec);
-  asio::detail::throw_error(ec, "read_until");
-  return bytes_transferred;
+  return read_until(s, basic_streambuf_ref<Allocator>(b), match_condition);
 }
 
+template <typename SyncReadStream, typename Allocator, typename MatchCondition>
+inline std::size_t read_until(SyncReadStream& s,
+    asio::basic_streambuf<Allocator>& b,
+    MatchCondition match_condition, asio::error_code& ec,
+    typename enable_if<is_match_condition<MatchCondition>::value>::type*)
+{
+  return read_until(s, basic_streambuf_ref<Allocator>(b), match_condition, ec);
+}
+
+#endif // !defined(ASIO_NO_IOSTREAM)
+
 namespace detail
 {
-  template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+  template <typename AsyncReadStream,
+      typename DynamicBufferSequence, typename ReadHandler>
   class read_until_delim_op
   {
   public:
+    template <typename BufferSequence>
     read_until_delim_op(AsyncReadStream& stream,
-        asio::basic_streambuf<Allocator>& streambuf,
+        ASIO_MOVE_ARG(BufferSequence) buffers,
         char delim, ReadHandler& handler)
       : stream_(stream),
-        streambuf_(streambuf),
+        buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)),
         delim_(delim),
         start_(0),
         search_position_(0),
@@ -346,7 +442,7 @@
 #if defined(ASIO_HAS_MOVE)
     read_until_delim_op(const read_until_delim_op& other)
       : stream_(other.stream_),
-        streambuf_(other.streambuf_),
+        buffers_(other.buffers_),
         delim_(other.delim_),
         start_(other.start_),
         search_position_(other.search_position_),
@@ -356,7 +452,7 @@
 
     read_until_delim_op(read_until_delim_op&& other)
       : stream_(other.stream_),
-        streambuf_(other.streambuf_),
+        buffers_(ASIO_MOVE_CAST(DynamicBufferSequence)(other.buffers_)),
         delim_(other.delim_),
         start_(other.start_),
         search_position_(other.search_position_),
@@ -377,10 +473,10 @@
         {
           {
             // Determine the range of the data to be searched.
-            typedef typename asio::basic_streambuf<
-              Allocator>::const_buffers_type const_buffers_type;
-            typedef asio::buffers_iterator<const_buffers_type> iterator;
-            const_buffers_type buffers = streambuf_.data();
+            typedef typename DynamicBufferSequence::const_buffers_type
+              buffers_type;
+            typedef buffers_iterator<buffers_type> iterator;
+            buffers_type buffers = buffers_.data();
             iterator begin = iterator::begin(buffers);
             iterator start_pos = begin + search_position_;
             iterator end = iterator::end(buffers);
@@ -395,7 +491,7 @@
             }
 
             // No match yet. Check if buffer is full.
-            else if (streambuf_.size() == streambuf_.max_size())
+            else if (buffers_.size() == buffers_.max_size())
             {
               search_position_ = not_found;
               bytes_to_read = 0;
@@ -406,7 +502,11 @@
             {
               // Next search can start with the new data.
               search_position_ = end - begin;
-              bytes_to_read = read_size_helper(streambuf_, 65536);
+              bytes_to_read = std::min<std::size_t>(
+                    std::max<std::size_t>(512,
+                      buffers_.capacity() - buffers_.size()),
+                    std::min<std::size_t>(65536,
+                      buffers_.max_size() - buffers_.size()));
             }
           }
 
@@ -415,10 +515,10 @@
             break;
 
           // Start a new asynchronous read operation to obtain more data.
-          stream_.async_read_some(streambuf_.prepare(bytes_to_read),
+          stream_.async_read_some(buffers_.prepare(bytes_to_read),
               ASIO_MOVE_CAST(read_until_delim_op)(*this));
           return; default:
-          streambuf_.commit(bytes_transferred);
+          buffers_.commit(bytes_transferred);
           if (ec || bytes_transferred == 0)
             break;
         }
@@ -437,56 +537,59 @@
 
   //private:
     AsyncReadStream& stream_;
-    asio::basic_streambuf<Allocator>& streambuf_;
+    DynamicBufferSequence buffers_;
     char delim_;
     int start_;
     std::size_t search_position_;
     ReadHandler handler_;
   };
 
-  template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+  template <typename AsyncReadStream,
+      typename DynamicBufferSequence, typename ReadHandler>
   inline void* asio_handler_allocate(std::size_t size,
       read_until_delim_op<AsyncReadStream,
-        Allocator, ReadHandler>* this_handler)
+        DynamicBufferSequence, ReadHandler>* this_handler)
   {
     return asio_handler_alloc_helpers::allocate(
         size, this_handler->handler_);
   }
 
-  template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+  template <typename AsyncReadStream,
+      typename DynamicBufferSequence, typename ReadHandler>
   inline void asio_handler_deallocate(void* pointer, std::size_t size,
       read_until_delim_op<AsyncReadStream,
-        Allocator, ReadHandler>* this_handler)
+        DynamicBufferSequence, ReadHandler>* this_handler)
   {
     asio_handler_alloc_helpers::deallocate(
         pointer, size, this_handler->handler_);
   }
 
-  template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+  template <typename AsyncReadStream,
+      typename DynamicBufferSequence, typename ReadHandler>
   inline bool asio_handler_is_continuation(
       read_until_delim_op<AsyncReadStream,
-        Allocator, ReadHandler>* this_handler)
+        DynamicBufferSequence, ReadHandler>* this_handler)
   {
     return this_handler->start_ == 0 ? true
       : asio_handler_cont_helpers::is_continuation(
           this_handler->handler_);
   }
 
-  template <typename Function, typename AsyncReadStream, typename Allocator,
-      typename ReadHandler>
+  template <typename Function, typename AsyncReadStream,
+      typename DynamicBufferSequence, typename ReadHandler>
   inline void asio_handler_invoke(Function& function,
       read_until_delim_op<AsyncReadStream,
-        Allocator, ReadHandler>* this_handler)
+        DynamicBufferSequence, ReadHandler>* this_handler)
   {
     asio_handler_invoke_helpers::invoke(
         function, this_handler->handler_);
   }
 
-  template <typename Function, typename AsyncReadStream, typename Allocator,
-      typename ReadHandler>
+  template <typename Function, typename AsyncReadStream,
+      typename DynamicBufferSequence, typename ReadHandler>
   inline void asio_handler_invoke(const Function& function,
       read_until_delim_op<AsyncReadStream,
-        Allocator, ReadHandler>* this_handler)
+        DynamicBufferSequence, ReadHandler>* this_handler)
   {
     asio_handler_invoke_helpers::invoke(
         function, this_handler->handler_);
@@ -495,48 +598,51 @@
 
 #if !defined(GENERATING_DOCUMENTATION)
 
-template <typename AsyncReadStream, typename Allocator,
-    typename ReadHandler, typename Allocator1>
+template <typename AsyncReadStream, typename DynamicBufferSequence,
+    typename ReadHandler, typename Allocator>
 struct associated_allocator<
-    detail::read_until_delim_op<AsyncReadStream, Allocator, ReadHandler>,
-    Allocator1>
+    detail::read_until_delim_op<AsyncReadStream,
+      DynamicBufferSequence, ReadHandler>,
+    Allocator>
 {
-  typedef typename associated_allocator<ReadHandler, Allocator1>::type type;
+  typedef typename associated_allocator<ReadHandler, Allocator>::type type;
 
   static type get(
-      const detail::read_until_delim_op<
-        AsyncReadStream, Allocator, ReadHandler>& h,
-      const Allocator1& a = Allocator1()) ASIO_NOEXCEPT
+      const detail::read_until_delim_op<AsyncReadStream,
+        DynamicBufferSequence, ReadHandler>& h,
+      const Allocator& a = Allocator()) ASIO_NOEXCEPT
   {
-    return associated_allocator<ReadHandler, Allocator1>::get(h.handler_, a);
+    return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
   }
 };
 
-template <typename AsyncReadStream, typename Executor,
-    typename ReadHandler, typename Executor1>
+template <typename AsyncReadStream, typename DynamicBufferSequence,
+    typename ReadHandler, typename Executor>
 struct associated_executor<
-    detail::read_until_delim_op<AsyncReadStream, Executor, ReadHandler>,
-    Executor1>
+    detail::read_until_delim_op<AsyncReadStream,
+      DynamicBufferSequence, ReadHandler>,
+    Executor>
 {
-  typedef typename associated_executor<ReadHandler, Executor1>::type type;
+  typedef typename associated_executor<ReadHandler, Executor>::type type;
 
   static type get(
-      const detail::read_until_delim_op<
-        AsyncReadStream, Executor, ReadHandler>& h,
-      const Executor1& ex = Executor1()) ASIO_NOEXCEPT
+      const detail::read_until_delim_op<AsyncReadStream,
+        DynamicBufferSequence, ReadHandler>& h,
+      const Executor& ex = Executor()) ASIO_NOEXCEPT
   {
-    return associated_executor<ReadHandler, Executor1>::get(h.handler_, ex);
+    return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
   }
 };
 
 #endif // !defined(GENERATING_DOCUMENTATION)
 
-template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+template <typename AsyncReadStream,
+    typename DynamicBufferSequence, typename ReadHandler>
 ASIO_INITFN_RESULT_TYPE(ReadHandler,
     void (asio::error_code, std::size_t))
 async_read_until(AsyncReadStream& s,
-    asio::basic_streambuf<Allocator>& b, char delim,
-    ASIO_MOVE_ARG(ReadHandler) handler)
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    char delim, ASIO_MOVE_ARG(ReadHandler) handler)
 {
   // If you get an error on the following line it means that your handler does
   // not meet the documented type requirements for a ReadHandler.
@@ -546,25 +652,28 @@
     void (asio::error_code, std::size_t)> init(handler);
 
   detail::read_until_delim_op<AsyncReadStream,
-    Allocator, ASIO_HANDLER_TYPE(ReadHandler,
-      void (asio::error_code, std::size_t))>(
-        s, b, delim, init.handler)(
-          asio::error_code(), 0, 1);
+    typename decay<DynamicBufferSequence>::type,
+      ASIO_HANDLER_TYPE(ReadHandler,
+        void (asio::error_code, std::size_t))>(
+          s, ASIO_MOVE_CAST(DynamicBufferSequence)(buffers),
+            delim, init.handler)(asio::error_code(), 0, 1);
 
   return init.result.get();
 }
 
 namespace detail
 {
-  template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+  template <typename AsyncReadStream,
+      typename DynamicBufferSequence, typename ReadHandler>
   class read_until_delim_string_op
   {
   public:
+    template <typename BufferSequence>
     read_until_delim_string_op(AsyncReadStream& stream,
-        asio::basic_streambuf<Allocator>& streambuf,
+        ASIO_MOVE_ARG(BufferSequence) buffers,
         const std::string& delim, ReadHandler& handler)
       : stream_(stream),
-        streambuf_(streambuf),
+        buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)),
         delim_(delim),
         start_(0),
         search_position_(0),
@@ -575,7 +684,7 @@
 #if defined(ASIO_HAS_MOVE)
     read_until_delim_string_op(const read_until_delim_string_op& other)
       : stream_(other.stream_),
-        streambuf_(other.streambuf_),
+        buffers_(other.buffers_),
         delim_(other.delim_),
         start_(other.start_),
         search_position_(other.search_position_),
@@ -585,7 +694,7 @@
 
     read_until_delim_string_op(read_until_delim_string_op&& other)
       : stream_(other.stream_),
-        streambuf_(other.streambuf_),
+        buffers_(ASIO_MOVE_CAST(DynamicBufferSequence)(other.buffers_)),
         delim_(ASIO_MOVE_CAST(std::string)(other.delim_)),
         start_(other.start_),
         search_position_(other.search_position_),
@@ -606,10 +715,10 @@
         {
           {
             // Determine the range of the data to be searched.
-            typedef typename asio::basic_streambuf<
-              Allocator>::const_buffers_type const_buffers_type;
-            typedef asio::buffers_iterator<const_buffers_type> iterator;
-            const_buffers_type buffers = streambuf_.data();
+            typedef typename DynamicBufferSequence::const_buffers_type
+              buffers_type;
+            typedef buffers_iterator<buffers_type> iterator;
+            buffers_type buffers = buffers_.data();
             iterator begin = iterator::begin(buffers);
             iterator start_pos = begin + search_position_;
             iterator end = iterator::end(buffers);
@@ -625,7 +734,7 @@
             }
 
             // No match yet. Check if buffer is full.
-            else if (streambuf_.size() == streambuf_.max_size())
+            else if (buffers_.size() == buffers_.max_size())
             {
               search_position_ = not_found;
               bytes_to_read = 0;
@@ -646,7 +755,11 @@
                 search_position_ = end - begin;
               }
 
-              bytes_to_read = read_size_helper(streambuf_, 65536);
+              bytes_to_read = std::min<std::size_t>(
+                    std::max<std::size_t>(512,
+                      buffers_.capacity() - buffers_.size()),
+                    std::min<std::size_t>(65536,
+                      buffers_.max_size() - buffers_.size()));
             }
           }
 
@@ -655,10 +768,10 @@
             break;
 
           // Start a new asynchronous read operation to obtain more data.
-          stream_.async_read_some(streambuf_.prepare(bytes_to_read),
+          stream_.async_read_some(buffers_.prepare(bytes_to_read),
               ASIO_MOVE_CAST(read_until_delim_string_op)(*this));
           return; default:
-          streambuf_.commit(bytes_transferred);
+          buffers_.commit(bytes_transferred);
           if (ec || bytes_transferred == 0)
             break;
         }
@@ -677,35 +790,38 @@
 
   //private:
     AsyncReadStream& stream_;
-    asio::basic_streambuf<Allocator>& streambuf_;
+    DynamicBufferSequence buffers_;
     std::string delim_;
     int start_;
     std::size_t search_position_;
     ReadHandler handler_;
   };
 
-  template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+  template <typename AsyncReadStream,
+      typename DynamicBufferSequence, typename ReadHandler>
   inline void* asio_handler_allocate(std::size_t size,
       read_until_delim_string_op<AsyncReadStream,
-        Allocator, ReadHandler>* this_handler)
+        DynamicBufferSequence, ReadHandler>* this_handler)
   {
     return asio_handler_alloc_helpers::allocate(
         size, this_handler->handler_);
   }
 
-  template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+  template <typename AsyncReadStream,
+      typename DynamicBufferSequence, typename ReadHandler>
   inline void asio_handler_deallocate(void* pointer, std::size_t size,
       read_until_delim_string_op<AsyncReadStream,
-        Allocator, ReadHandler>* this_handler)
+        DynamicBufferSequence, ReadHandler>* this_handler)
   {
     asio_handler_alloc_helpers::deallocate(
         pointer, size, this_handler->handler_);
   }
 
-  template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+  template <typename AsyncReadStream,
+      typename DynamicBufferSequence, typename ReadHandler>
   inline bool asio_handler_is_continuation(
       read_until_delim_string_op<AsyncReadStream,
-        Allocator, ReadHandler>* this_handler)
+        DynamicBufferSequence, ReadHandler>* this_handler)
   {
     return this_handler->start_ == 0 ? true
       : asio_handler_cont_helpers::is_continuation(
@@ -713,20 +829,20 @@
   }
 
   template <typename Function, typename AsyncReadStream,
-      typename Allocator, typename ReadHandler>
+      typename DynamicBufferSequence, typename ReadHandler>
   inline void asio_handler_invoke(Function& function,
       read_until_delim_string_op<AsyncReadStream,
-        Allocator, ReadHandler>* this_handler)
+        DynamicBufferSequence, ReadHandler>* this_handler)
   {
     asio_handler_invoke_helpers::invoke(
         function, this_handler->handler_);
   }
 
   template <typename Function, typename AsyncReadStream,
-      typename Allocator, typename ReadHandler>
+      typename DynamicBufferSequence, typename ReadHandler>
   inline void asio_handler_invoke(const Function& function,
       read_until_delim_string_op<AsyncReadStream,
-        Allocator, ReadHandler>* this_handler)
+        DynamicBufferSequence, ReadHandler>* this_handler)
   {
     asio_handler_invoke_helpers::invoke(
         function, this_handler->handler_);
@@ -735,50 +851,51 @@
 
 #if !defined(GENERATING_DOCUMENTATION)
 
-template <typename AsyncReadStream, typename Allocator,
-    typename ReadHandler, typename Allocator1>
+template <typename AsyncReadStream, typename DynamicBufferSequence,
+    typename ReadHandler, typename Allocator>
 struct associated_allocator<
-    detail::read_until_delim_string_op<
-      AsyncReadStream, Allocator, ReadHandler>,
-    Allocator1>
+    detail::read_until_delim_string_op<AsyncReadStream,
+      DynamicBufferSequence, ReadHandler>,
+    Allocator>
 {
-  typedef typename associated_allocator<ReadHandler, Allocator1>::type type;
+  typedef typename associated_allocator<ReadHandler, Allocator>::type type;
 
   static type get(
-      const detail::read_until_delim_string_op<
-        AsyncReadStream, Allocator, ReadHandler>& h,
-      const Allocator1& a = Allocator1()) ASIO_NOEXCEPT
+      const detail::read_until_delim_string_op<AsyncReadStream,
+        DynamicBufferSequence, ReadHandler>& h,
+      const Allocator& a = Allocator()) ASIO_NOEXCEPT
   {
-    return associated_allocator<ReadHandler, Allocator1>::get(h.handler_, a);
+    return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
   }
 };
 
-template <typename AsyncReadStream, typename Executor,
-    typename ReadHandler, typename Executor1>
+template <typename AsyncReadStream, typename DynamicBufferSequence,
+    typename ReadHandler, typename Executor>
 struct associated_executor<
-    detail::read_until_delim_string_op<
-      AsyncReadStream, Executor, ReadHandler>,
-    Executor1>
+    detail::read_until_delim_string_op<AsyncReadStream,
+      DynamicBufferSequence, ReadHandler>,
+    Executor>
 {
-  typedef typename associated_executor<ReadHandler, Executor1>::type type;
+  typedef typename associated_executor<ReadHandler, Executor>::type type;
 
   static type get(
-      const detail::read_until_delim_string_op<
-        AsyncReadStream, Executor, ReadHandler>& h,
-      const Executor1& ex = Executor1()) ASIO_NOEXCEPT
+      const detail::read_until_delim_string_op<AsyncReadStream,
+        DynamicBufferSequence, ReadHandler>& h,
+      const Executor& ex = Executor()) ASIO_NOEXCEPT
   {
-    return associated_executor<ReadHandler, Executor1>::get(h.handler_, ex);
+    return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
   }
 };
 
 #endif // !defined(GENERATING_DOCUMENTATION)
 
-template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+template <typename AsyncReadStream,
+    typename DynamicBufferSequence, typename ReadHandler>
 ASIO_INITFN_RESULT_TYPE(ReadHandler,
     void (asio::error_code, std::size_t))
 async_read_until(AsyncReadStream& s,
-    asio::basic_streambuf<Allocator>& b, const std::string& delim,
-    ASIO_MOVE_ARG(ReadHandler) handler)
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    const std::string& delim, ASIO_MOVE_ARG(ReadHandler) handler)
 {
   // If you get an error on the following line it means that your handler does
   // not meet the documented type requirements for a ReadHandler.
@@ -788,10 +905,11 @@
     void (asio::error_code, std::size_t)> init(handler);
 
   detail::read_until_delim_string_op<AsyncReadStream,
-    Allocator, ASIO_HANDLER_TYPE(ReadHandler,
-      void (asio::error_code, std::size_t))>(
-        s, b, delim, init.handler)(
-          asio::error_code(), 0, 1);
+    typename decay<DynamicBufferSequence>::type,
+      ASIO_HANDLER_TYPE(ReadHandler,
+        void (asio::error_code, std::size_t))>(
+          s, ASIO_MOVE_CAST(DynamicBufferSequence)(buffers),
+            delim, init.handler)(asio::error_code(), 0, 1);
 
   return init.result.get();
 }
@@ -800,16 +918,17 @@
 
 namespace detail
 {
-  template <typename AsyncReadStream, typename Allocator,
+  template <typename AsyncReadStream, typename DynamicBufferSequence,
       typename RegEx, typename ReadHandler>
   class read_until_expr_op
   {
   public:
+    template <typename BufferSequence>
     read_until_expr_op(AsyncReadStream& stream,
-        asio::basic_streambuf<Allocator>& streambuf,
+        ASIO_MOVE_ARG(BufferSequence) buffers,
         const boost::regex& expr, ReadHandler& handler)
       : stream_(stream),
-        streambuf_(streambuf),
+        buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)),
         expr_(expr),
         start_(0),
         search_position_(0),
@@ -820,7 +939,7 @@
 #if defined(ASIO_HAS_MOVE)
     read_until_expr_op(const read_until_expr_op& other)
       : stream_(other.stream_),
-        streambuf_(other.streambuf_),
+        buffers_(other.buffers_),
         expr_(other.expr_),
         start_(other.start_),
         search_position_(other.search_position_),
@@ -830,7 +949,7 @@
 
     read_until_expr_op(read_until_expr_op&& other)
       : stream_(other.stream_),
-        streambuf_(other.streambuf_),
+        buffers_(ASIO_MOVE_CAST(DynamicBufferSequence)(other.buffers)),
         expr_(other.expr_),
         start_(other.start_),
         search_position_(other.search_position_),
@@ -851,10 +970,10 @@
         {
           {
             // Determine the range of the data to be searched.
-            typedef typename asio::basic_streambuf<
-              Allocator>::const_buffers_type const_buffers_type;
-            typedef asio::buffers_iterator<const_buffers_type> iterator;
-            const_buffers_type buffers = streambuf_.data();
+            typedef typename DynamicBufferSequence::const_buffers_type
+              buffers_type;
+            typedef buffers_iterator<buffers_type> iterator;
+            buffers_type buffers = buffers_.data();
             iterator begin = iterator::begin(buffers);
             iterator start_pos = begin + search_position_;
             iterator end = iterator::end(buffers);
@@ -873,7 +992,7 @@
             }
 
             // No match yet. Check if buffer is full.
-            else if (streambuf_.size() == streambuf_.max_size())
+            else if (buffers_.size() == buffers_.max_size())
             {
               search_position_ = not_found;
               bytes_to_read = 0;
@@ -894,7 +1013,11 @@
                 search_position_ = end - begin;
               }
 
-              bytes_to_read = read_size_helper(streambuf_, 65536);
+              bytes_to_read = std::min<std::size_t>(
+                    std::max<std::size_t>(512,
+                      buffers_.capacity() - buffers_.size()),
+                    std::min<std::size_t>(65536,
+                      buffers_.max_size() - buffers_.size()));
             }
           }
 
@@ -903,10 +1026,10 @@
             break;
 
           // Start a new asynchronous read operation to obtain more data.
-          stream_.async_read_some(streambuf_.prepare(bytes_to_read),
+          stream_.async_read_some(buffers_.prepare(bytes_to_read),
               ASIO_MOVE_CAST(read_until_expr_op)(*this));
           return; default:
-          streambuf_.commit(bytes_transferred);
+          buffers_.commit(bytes_transferred);
           if (ec || bytes_transferred == 0)
             break;
         }
@@ -925,59 +1048,59 @@
 
   //private:
     AsyncReadStream& stream_;
-    asio::basic_streambuf<Allocator>& streambuf_;
+    DynamicBufferSequence buffers_;
     RegEx expr_;
     int start_;
     std::size_t search_position_;
     ReadHandler handler_;
   };
 
-  template <typename AsyncReadStream, typename Allocator,
+  template <typename AsyncReadStream, typename DynamicBufferSequence,
       typename RegEx, typename ReadHandler>
   inline void* asio_handler_allocate(std::size_t size,
       read_until_expr_op<AsyncReadStream,
-        Allocator, RegEx, ReadHandler>* this_handler)
+        DynamicBufferSequence, RegEx, ReadHandler>* this_handler)
   {
     return asio_handler_alloc_helpers::allocate(
         size, this_handler->handler_);
   }
 
-  template <typename AsyncReadStream, typename Allocator,
+  template <typename AsyncReadStream, typename DynamicBufferSequence,
       typename RegEx, typename ReadHandler>
   inline void asio_handler_deallocate(void* pointer, std::size_t size,
       read_until_expr_op<AsyncReadStream,
-        Allocator, RegEx, ReadHandler>* this_handler)
+        DynamicBufferSequence, RegEx, ReadHandler>* this_handler)
   {
     asio_handler_alloc_helpers::deallocate(
         pointer, size, this_handler->handler_);
   }
 
-  template <typename AsyncReadStream, typename Allocator,
+  template <typename AsyncReadStream, typename DynamicBufferSequence,
       typename RegEx, typename ReadHandler>
   inline bool asio_handler_is_continuation(
       read_until_expr_op<AsyncReadStream,
-        Allocator, RegEx, ReadHandler>* this_handler)
+        DynamicBufferSequence, RegEx, ReadHandler>* this_handler)
   {
     return this_handler->start_ == 0 ? true
       : asio_handler_cont_helpers::is_continuation(
           this_handler->handler_);
   }
 
-  template <typename Function, typename AsyncReadStream, typename Allocator,
-      typename RegEx, typename ReadHandler>
+  template <typename Function, typename AsyncReadStream,
+      typename DynamicBufferSequence, typename RegEx, typename ReadHandler>
   inline void asio_handler_invoke(Function& function,
       read_until_expr_op<AsyncReadStream,
-        Allocator, RegEx, ReadHandler>* this_handler)
+        DynamicBufferSequence, RegEx, ReadHandler>* this_handler)
   {
     asio_handler_invoke_helpers::invoke(
         function, this_handler->handler_);
   }
 
-  template <typename Function, typename AsyncReadStream, typename Allocator,
-      typename RegEx, typename ReadHandler>
+  template <typename Function, typename AsyncReadStream,
+      typename DynamicBufferSequence, typename RegEx, typename ReadHandler>
   inline void asio_handler_invoke(const Function& function,
       read_until_expr_op<AsyncReadStream,
-        Allocator, RegEx, ReadHandler>* this_handler)
+        DynamicBufferSequence, RegEx, ReadHandler>* this_handler)
   {
     asio_handler_invoke_helpers::invoke(
         function, this_handler->handler_);
@@ -986,47 +1109,51 @@
 
 #if !defined(GENERATING_DOCUMENTATION)
 
-template <typename AsyncReadStream, typename Allocator,
-    typename RegEx, typename ReadHandler, typename Allocator1>
+template <typename AsyncReadStream, typename DynamicBufferSequence,
+    typename RegEx, typename ReadHandler, typename Allocator>
 struct associated_allocator<
-    detail::read_until_expr_op<AsyncReadStream, Allocator, RegEx, ReadHandler>,
-    Allocator1>
+    detail::read_until_expr_op<AsyncReadStream,
+      DynamicBufferSequence, RegEx, ReadHandler>,
+    Allocator>
 {
-  typedef typename associated_allocator<ReadHandler, Allocator1>::type type;
+  typedef typename associated_allocator<ReadHandler, Allocator>::type type;
 
   static type get(
       const detail::read_until_expr_op<AsyncReadStream,
-        Allocator, RegEx, ReadHandler>& h,
-      const Allocator1& a = Allocator1()) ASIO_NOEXCEPT
+        DynamicBufferSequence, RegEx, ReadHandler>& h,
+      const Allocator& a = Allocator()) ASIO_NOEXCEPT
   {
-    return associated_allocator<ReadHandler, Allocator1>::get(h.handler_, a);
+    return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
   }
 };
 
-template <typename AsyncReadStream, typename Executor,
-    typename RegEx, typename ReadHandler, typename Executor1>
+template <typename AsyncReadStream, typename DynamicBufferSequence,
+    typename RegEx, typename ReadHandler, typename Executor>
 struct associated_executor<
-    detail::read_until_expr_op<AsyncReadStream, Executor, RegEx, ReadHandler>,
-    Executor1>
+    detail::read_until_expr_op<AsyncReadStream,
+      DynamicBufferSequence, RegEx, ReadHandler>,
+    Executor>
 {
-  typedef typename associated_executor<ReadHandler, Executor1>::type type;
+  typedef typename associated_executor<ReadHandler, Executor>::type type;
 
   static type get(
       const detail::read_until_expr_op<AsyncReadStream,
-        Executor, RegEx, ReadHandler>& h,
-      const Executor1& ex = Executor1()) ASIO_NOEXCEPT
+        DynamicBufferSequence, RegEx, ReadHandler>& h,
+      const Executor& ex = Executor()) ASIO_NOEXCEPT
   {
-    return associated_executor<ReadHandler, Executor1>::get(h.handler_, ex);
+    return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
   }
 };
 
 #endif // !defined(GENERATING_DOCUMENTATION)
 
-template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+template <typename AsyncReadStream,
+    typename DynamicBufferSequence, typename ReadHandler>
 ASIO_INITFN_RESULT_TYPE(ReadHandler,
     void (asio::error_code, std::size_t))
 async_read_until(AsyncReadStream& s,
-    asio::basic_streambuf<Allocator>& b, const boost::regex& expr,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    const boost::regex& expr,
     ASIO_MOVE_ARG(ReadHandler) handler)
 {
   // If you get an error on the following line it means that your handler does
@@ -1036,11 +1163,12 @@
   async_completion<ReadHandler,
     void (asio::error_code, std::size_t)> init(handler);
 
-  detail::read_until_expr_op<AsyncReadStream, Allocator,
-    boost::regex, ASIO_HANDLER_TYPE(ReadHandler,
-      void (asio::error_code, std::size_t))>(
-        s, b, expr, init.handler)(
-          asio::error_code(), 0, 1);
+  detail::read_until_expr_op<AsyncReadStream,
+    typename decay<DynamicBufferSequence>::type,
+      boost::regex, ASIO_HANDLER_TYPE(ReadHandler,
+        void (asio::error_code, std::size_t))>(
+          s, ASIO_MOVE_CAST(DynamicBufferSequence)(buffers),
+            expr, init.handler)(asio::error_code(), 0, 1);
 
   return init.result.get();
 }
@@ -1049,16 +1177,17 @@
 
 namespace detail
 {
-  template <typename AsyncReadStream, typename Allocator,
+  template <typename AsyncReadStream, typename DynamicBufferSequence,
       typename MatchCondition, typename ReadHandler>
   class read_until_match_op
   {
   public:
+    template <typename BufferSequence>
     read_until_match_op(AsyncReadStream& stream,
-        asio::basic_streambuf<Allocator>& streambuf,
+        ASIO_MOVE_ARG(BufferSequence) buffers,
         MatchCondition match_condition, ReadHandler& handler)
       : stream_(stream),
-        streambuf_(streambuf),
+        buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)),
         match_condition_(match_condition),
         start_(0),
         search_position_(0),
@@ -1069,7 +1198,7 @@
 #if defined(ASIO_HAS_MOVE)
     read_until_match_op(const read_until_match_op& other)
       : stream_(other.stream_),
-        streambuf_(other.streambuf_),
+        buffers_(other.buffers_),
         match_condition_(other.match_condition_),
         start_(other.start_),
         search_position_(other.search_position_),
@@ -1079,7 +1208,7 @@
 
     read_until_match_op(read_until_match_op&& other)
       : stream_(other.stream_),
-        streambuf_(other.streambuf_),
+        buffers_(ASIO_MOVE_CAST(DynamicBufferSequence)(other.buffers_)),
         match_condition_(other.match_condition_),
         start_(other.start_),
         search_position_(other.search_position_),
@@ -1100,10 +1229,10 @@
         {
           {
             // Determine the range of the data to be searched.
-            typedef typename asio::basic_streambuf<
-              Allocator>::const_buffers_type const_buffers_type;
-            typedef asio::buffers_iterator<const_buffers_type> iterator;
-            const_buffers_type buffers = streambuf_.data();
+            typedef typename DynamicBufferSequence::const_buffers_type
+              buffers_type;
+            typedef buffers_iterator<buffers_type> iterator;
+            buffers_type buffers = buffers_.data();
             iterator begin = iterator::begin(buffers);
             iterator start_pos = begin + search_position_;
             iterator end = iterator::end(buffers);
@@ -1118,7 +1247,7 @@
             }
 
             // No match yet. Check if buffer is full.
-            else if (streambuf_.size() == streambuf_.max_size())
+            else if (buffers_.size() == buffers_.max_size())
             {
               search_position_ = not_found;
               bytes_to_read = 0;
@@ -1139,7 +1268,11 @@
                 search_position_ = end - begin;
               }
 
-              bytes_to_read = read_size_helper(streambuf_, 65536);
+              bytes_to_read = std::min<std::size_t>(
+                    std::max<std::size_t>(512,
+                      buffers_.capacity() - buffers_.size()),
+                    std::min<std::size_t>(65536,
+                      buffers_.max_size() - buffers_.size()));
             }
           }
 
@@ -1148,10 +1281,10 @@
             break;
 
           // Start a new asynchronous read operation to obtain more data.
-          stream_.async_read_some(streambuf_.prepare(bytes_to_read),
+          stream_.async_read_some(buffers_.prepare(bytes_to_read),
               ASIO_MOVE_CAST(read_until_match_op)(*this));
           return; default:
-          streambuf_.commit(bytes_transferred);
+          buffers_.commit(bytes_transferred);
           if (ec || bytes_transferred == 0)
             break;
         }
@@ -1170,59 +1303,61 @@
 
   //private:
     AsyncReadStream& stream_;
-    asio::basic_streambuf<Allocator>& streambuf_;
+    DynamicBufferSequence buffers_;
     MatchCondition match_condition_;
     int start_;
     std::size_t search_position_;
     ReadHandler handler_;
   };
 
-  template <typename AsyncReadStream, typename Allocator,
+  template <typename AsyncReadStream, typename DynamicBufferSequence,
       typename MatchCondition, typename ReadHandler>
   inline void* asio_handler_allocate(std::size_t size,
-      read_until_match_op<AsyncReadStream,
-        Allocator, MatchCondition, ReadHandler>* this_handler)
+      read_until_match_op<AsyncReadStream, DynamicBufferSequence,
+        MatchCondition, ReadHandler>* this_handler)
   {
     return asio_handler_alloc_helpers::allocate(
         size, this_handler->handler_);
   }
 
-  template <typename AsyncReadStream, typename Allocator,
+  template <typename AsyncReadStream, typename DynamicBufferSequence,
       typename MatchCondition, typename ReadHandler>
   inline void asio_handler_deallocate(void* pointer, std::size_t size,
-      read_until_match_op<AsyncReadStream,
-        Allocator, MatchCondition, ReadHandler>* this_handler)
+      read_until_match_op<AsyncReadStream, DynamicBufferSequence,
+        MatchCondition, ReadHandler>* this_handler)
   {
     asio_handler_alloc_helpers::deallocate(
         pointer, size, this_handler->handler_);
   }
 
-  template <typename AsyncReadStream, typename Allocator,
+  template <typename AsyncReadStream, typename DynamicBufferSequence,
       typename MatchCondition, typename ReadHandler>
   inline bool asio_handler_is_continuation(
-      read_until_match_op<AsyncReadStream,
-        Allocator, MatchCondition, ReadHandler>* this_handler)
+      read_until_match_op<AsyncReadStream, DynamicBufferSequence,
+        MatchCondition, ReadHandler>* this_handler)
   {
     return this_handler->start_ == 0 ? true
       : asio_handler_cont_helpers::is_continuation(
           this_handler->handler_);
   }
 
-  template <typename Function, typename AsyncReadStream, typename Allocator,
-      typename MatchCondition, typename ReadHandler>
+  template <typename Function, typename AsyncReadStream,
+      typename DynamicBufferSequence, typename MatchCondition,
+      typename ReadHandler>
   inline void asio_handler_invoke(Function& function,
-      read_until_match_op<AsyncReadStream,
-        Allocator, MatchCondition, ReadHandler>* this_handler)
+      read_until_match_op<AsyncReadStream, DynamicBufferSequence,
+        MatchCondition, ReadHandler>* this_handler)
   {
     asio_handler_invoke_helpers::invoke(
         function, this_handler->handler_);
   }
 
-  template <typename Function, typename AsyncReadStream, typename Allocator,
-      typename MatchCondition, typename ReadHandler>
+  template <typename Function, typename AsyncReadStream,
+      typename DynamicBufferSequence, typename MatchCondition,
+      typename ReadHandler>
   inline void asio_handler_invoke(const Function& function,
-      read_until_match_op<AsyncReadStream,
-        Allocator, MatchCondition, ReadHandler>* this_handler)
+      read_until_match_op<AsyncReadStream, DynamicBufferSequence,
+      MatchCondition, ReadHandler>* this_handler)
   {
     asio_handler_invoke_helpers::invoke(
         function, this_handler->handler_);
@@ -1231,50 +1366,50 @@
 
 #if !defined(GENERATING_DOCUMENTATION)
 
-template <typename AsyncReadStream, typename Allocator,
-    typename MatchCondition, typename ReadHandler, typename Allocator1>
+template <typename AsyncReadStream, typename DynamicBufferSequence,
+    typename MatchCondition, typename ReadHandler, typename Allocator>
 struct associated_allocator<
     detail::read_until_match_op<AsyncReadStream,
-      Allocator, MatchCondition, ReadHandler>,
-    Allocator1>
+      DynamicBufferSequence, MatchCondition, ReadHandler>,
+    Allocator>
 {
-  typedef typename associated_allocator<ReadHandler, Allocator1>::type type;
+  typedef typename associated_allocator<ReadHandler, Allocator>::type type;
 
   static type get(
       const detail::read_until_match_op<AsyncReadStream,
-        Allocator, MatchCondition, ReadHandler>& h,
-      const Allocator1& a = Allocator1()) ASIO_NOEXCEPT
+        DynamicBufferSequence, MatchCondition, ReadHandler>& h,
+      const Allocator& a = Allocator()) ASIO_NOEXCEPT
   {
-    return associated_allocator<ReadHandler, Allocator1>::get(h.handler_, a);
+    return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);
   }
 };
 
-template <typename AsyncReadStream, typename Executor,
-    typename MatchCondition, typename ReadHandler, typename Executor1>
+template <typename AsyncReadStream, typename DynamicBufferSequence,
+    typename MatchCondition, typename ReadHandler, typename Executor>
 struct associated_executor<
     detail::read_until_match_op<AsyncReadStream,
-      Executor, MatchCondition, ReadHandler>,
-    Executor1>
+      DynamicBufferSequence, MatchCondition, ReadHandler>,
+    Executor>
 {
-  typedef typename associated_executor<ReadHandler, Executor1>::type type;
+  typedef typename associated_executor<ReadHandler, Executor>::type type;
 
   static type get(
       const detail::read_until_match_op<AsyncReadStream,
-        Executor, MatchCondition, ReadHandler>& h,
-      const Executor1& ex = Executor1()) ASIO_NOEXCEPT
+        DynamicBufferSequence, MatchCondition, ReadHandler>& h,
+      const Executor& ex = Executor()) ASIO_NOEXCEPT
   {
-    return associated_executor<ReadHandler, Executor1>::get(h.handler_, ex);
+    return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);
   }
 };
 
 #endif // !defined(GENERATING_DOCUMENTATION)
 
-template <typename AsyncReadStream, typename Allocator,
+template <typename AsyncReadStream, typename DynamicBufferSequence,
     typename MatchCondition, typename ReadHandler>
 ASIO_INITFN_RESULT_TYPE(ReadHandler,
     void (asio::error_code, std::size_t))
 async_read_until(AsyncReadStream& s,
-    asio::basic_streambuf<Allocator>& b,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
     MatchCondition match_condition, ASIO_MOVE_ARG(ReadHandler) handler,
     typename enable_if<is_match_condition<MatchCondition>::value>::type*)
 {
@@ -1285,15 +1420,70 @@
   async_completion<ReadHandler,
     void (asio::error_code, std::size_t)> init(handler);
 
-  detail::read_until_match_op<AsyncReadStream, Allocator,
-    MatchCondition, ASIO_HANDLER_TYPE(ReadHandler,
-      void (asio::error_code, std::size_t))>(
-        s, b, match_condition, init.handler)(
-          asio::error_code(), 0, 1);
+  detail::read_until_match_op<AsyncReadStream,
+    typename decay<DynamicBufferSequence>::type,
+      MatchCondition, ASIO_HANDLER_TYPE(ReadHandler,
+        void (asio::error_code, std::size_t))>(
+          s, ASIO_MOVE_CAST(DynamicBufferSequence)(buffers),
+            match_condition, init.handler)(asio::error_code(), 0, 1);
 
   return init.result.get();
 }
 
+#if !defined(ASIO_NO_IOSTREAM)
+
+template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+inline ASIO_INITFN_RESULT_TYPE(ReadHandler,
+    void (asio::error_code, std::size_t))
+async_read_until(AsyncReadStream& s,
+    asio::basic_streambuf<Allocator>& b,
+    char delim, ASIO_MOVE_ARG(ReadHandler) handler)
+{
+  return async_read_until(s, basic_streambuf_ref<Allocator>(b),
+      delim, ASIO_MOVE_CAST(ReadHandler)(handler));
+}
+
+template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+inline ASIO_INITFN_RESULT_TYPE(ReadHandler,
+    void (asio::error_code, std::size_t))
+async_read_until(AsyncReadStream& s,
+    asio::basic_streambuf<Allocator>& b, const std::string& delim,
+    ASIO_MOVE_ARG(ReadHandler) handler)
+{
+  return async_read_until(s, basic_streambuf_ref<Allocator>(b),
+      delim, ASIO_MOVE_CAST(ReadHandler)(handler));
+}
+
+#if defined(ASIO_HAS_BOOST_REGEX)
+
+template <typename AsyncReadStream, typename Allocator, typename ReadHandler>
+inline ASIO_INITFN_RESULT_TYPE(ReadHandler,
+    void (asio::error_code, std::size_t))
+async_read_until(AsyncReadStream& s,
+    asio::basic_streambuf<Allocator>& b, const boost::regex& expr,
+    ASIO_MOVE_ARG(ReadHandler) handler)
+{
+  return async_read_until(s, basic_streambuf_ref<Allocator>(b),
+      expr, ASIO_MOVE_CAST(ReadHandler)(handler));
+}
+
+#endif // defined(ASIO_HAS_BOOST_REGEX)
+
+template <typename AsyncReadStream, typename Allocator,
+    typename MatchCondition, typename ReadHandler>
+inline ASIO_INITFN_RESULT_TYPE(ReadHandler,
+    void (asio::error_code, std::size_t))
+async_read_until(AsyncReadStream& s,
+    asio::basic_streambuf<Allocator>& b,
+    MatchCondition match_condition, ASIO_MOVE_ARG(ReadHandler) handler,
+    typename enable_if<is_match_condition<MatchCondition>::value>::type*)
+{
+  return async_read_until(s, basic_streambuf_ref<Allocator>(b),
+      match_condition, ASIO_MOVE_CAST(ReadHandler)(handler));
+}
+
+#endif // !defined(ASIO_NO_IOSTREAM)
+
 } // namespace asio
 
 #include "asio/detail/pop_options.hpp"
diff --git a/asio/include/asio/impl/write.hpp b/asio/include/asio/impl/write.hpp
index d1ce449..da87fe9 100644
--- a/asio/include/asio/impl/write.hpp
+++ b/asio/include/asio/impl/write.hpp
@@ -37,7 +37,10 @@
 template <typename SyncWriteStream, typename ConstBufferSequence,
     typename CompletionCondition>
 std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
-    CompletionCondition completion_condition, asio::error_code& ec)
+    CompletionCondition completion_condition, asio::error_code& ec,
+    typename enable_if<
+      is_const_buffer_sequence<ConstBufferSequence>::value
+    >::type*)
 {
   ec = asio::error_code();
   asio::detail::consuming_buffers<
@@ -57,7 +60,10 @@
 }
 
 template <typename SyncWriteStream, typename ConstBufferSequence>
-inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers)
+inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
+    typename enable_if<
+      is_const_buffer_sequence<ConstBufferSequence>::value
+    >::type*)
 {
   asio::error_code ec;
   std::size_t bytes_transferred = write(s, buffers, transfer_all(), ec);
@@ -67,7 +73,10 @@
 
 template <typename SyncWriteStream, typename ConstBufferSequence>
 inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
-    asio::error_code& ec)
+    asio::error_code& ec,
+    typename enable_if<
+      is_const_buffer_sequence<ConstBufferSequence>::value
+    >::type*)
 {
   return write(s, buffers, transfer_all(), ec);
 }
@@ -75,7 +84,10 @@
 template <typename SyncWriteStream, typename ConstBufferSequence,
     typename CompletionCondition>
 inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
-    CompletionCondition completion_condition)
+    CompletionCondition completion_condition,
+    typename enable_if<
+      is_const_buffer_sequence<ConstBufferSequence>::value
+    >::type*)
 {
   asio::error_code ec;
   std::size_t bytes_transferred = write(s, buffers, completion_condition, ec);
@@ -83,27 +95,83 @@
   return bytes_transferred;
 }
 
+template <typename SyncWriteStream, typename DynamicBufferSequence,
+    typename CompletionCondition>
+std::size_t write(SyncWriteStream& s,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    CompletionCondition completion_condition, asio::error_code& ec,
+    typename enable_if<
+      is_dynamic_buffer_sequence<DynamicBufferSequence>::value
+    >::type*)
+{
+  typename decay<DynamicBufferSequence>::type b(
+      ASIO_MOVE_CAST(DynamicBufferSequence)(buffers));
+
+  std::size_t bytes_transferred = write(s, b.data(), completion_condition, ec);
+  b.consume(bytes_transferred);
+  return bytes_transferred;
+}
+
+template <typename SyncWriteStream, typename DynamicBufferSequence>
+inline std::size_t write(SyncWriteStream& s,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    typename enable_if<
+      is_dynamic_buffer_sequence<DynamicBufferSequence>::value
+    >::type*)
+{
+  asio::error_code ec;
+  std::size_t bytes_transferred = write(s,
+      ASIO_MOVE_CAST(DynamicBufferSequence)(buffers),
+      transfer_all(), ec);
+  asio::detail::throw_error(ec, "write");
+  return bytes_transferred;
+}
+
+template <typename SyncWriteStream, typename DynamicBufferSequence>
+inline std::size_t write(SyncWriteStream& s,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    asio::error_code& ec,
+    typename enable_if<
+      is_dynamic_buffer_sequence<DynamicBufferSequence>::value
+    >::type*)
+{
+  return write(s, ASIO_MOVE_CAST(DynamicBufferSequence)(buffers),
+      transfer_all(), ec);
+}
+
+template <typename SyncWriteStream, typename DynamicBufferSequence,
+    typename CompletionCondition>
+inline std::size_t write(SyncWriteStream& s,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    CompletionCondition completion_condition,
+    typename enable_if<
+      is_dynamic_buffer_sequence<DynamicBufferSequence>::value
+    >::type*)
+{
+  asio::error_code ec;
+  std::size_t bytes_transferred = write(s,
+      ASIO_MOVE_CAST(DynamicBufferSequence)(buffers),
+      completion_condition, ec);
+  asio::detail::throw_error(ec, "write");
+  return bytes_transferred;
+}
+
 #if !defined(ASIO_NO_IOSTREAM)
 
 template <typename SyncWriteStream, typename Allocator,
     typename CompletionCondition>
-std::size_t write(SyncWriteStream& s,
+inline std::size_t write(SyncWriteStream& s,
     asio::basic_streambuf<Allocator>& b,
     CompletionCondition completion_condition, asio::error_code& ec)
 {
-  std::size_t bytes_transferred = write(s, b.data(), completion_condition, ec);
-  b.consume(bytes_transferred);
-  return bytes_transferred;
+  return write(s, basic_streambuf_ref<Allocator>(b), completion_condition, ec);
 }
 
 template <typename SyncWriteStream, typename Allocator>
 inline std::size_t write(SyncWriteStream& s,
     asio::basic_streambuf<Allocator>& b)
 {
-  asio::error_code ec;
-  std::size_t bytes_transferred = write(s, b, transfer_all(), ec);
-  asio::detail::throw_error(ec, "write");
-  return bytes_transferred;
+  return write(s, basic_streambuf_ref<Allocator>(b));
 }
 
 template <typename SyncWriteStream, typename Allocator>
@@ -111,7 +179,7 @@
     asio::basic_streambuf<Allocator>& b,
     asio::error_code& ec)
 {
-  return write(s, b, transfer_all(), ec);
+  return write(s, basic_streambuf_ref<Allocator>(b), ec);
 }
 
 template <typename SyncWriteStream, typename Allocator,
@@ -120,10 +188,7 @@
     asio::basic_streambuf<Allocator>& b,
     CompletionCondition completion_condition)
 {
-  asio::error_code ec;
-  std::size_t bytes_transferred = write(s, b, completion_condition, ec);
-  asio::detail::throw_error(ec, "write");
-  return bytes_transferred;
+  return write(s, basic_streambuf_ref<Allocator>(b), completion_condition);
 }
 
 #endif // !defined(ASIO_NO_IOSTREAM)
@@ -625,7 +690,10 @@
     void (asio::error_code, std::size_t))
 async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
     CompletionCondition completion_condition,
-    ASIO_MOVE_ARG(WriteHandler) handler)
+    ASIO_MOVE_ARG(WriteHandler) handler,
+    typename enable_if<
+      is_const_buffer_sequence<ConstBufferSequence>::value
+    >::type*)
 {
   // If you get an error on the following line it means that your handler does
   // not meet the documented type requirements for a WriteHandler.
@@ -648,7 +716,10 @@
 inline ASIO_INITFN_RESULT_TYPE(WriteHandler,
     void (asio::error_code, std::size_t))
 async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
-    ASIO_MOVE_ARG(WriteHandler) handler)
+    ASIO_MOVE_ARG(WriteHandler) handler,
+    typename enable_if<
+      is_const_buffer_sequence<ConstBufferSequence>::value
+    >::type*)
 {
   // If you get an error on the following line it means that your handler does
   // not meet the documented type requirements for a WriteHandler.
@@ -666,82 +737,112 @@
   return init.result.get();
 }
 
-#if !defined(ASIO_NO_IOSTREAM)
-
 namespace detail
 {
-  template <typename Allocator, typename WriteHandler>
-  class write_streambuf_handler
+  template <typename AsyncWriteStream, typename DynamicBufferSequence,
+      typename CompletionCondition, typename WriteHandler>
+  class write_dynbuf_op
   {
   public:
-    write_streambuf_handler(asio::basic_streambuf<Allocator>& streambuf,
-        WriteHandler& handler)
-      : streambuf_(streambuf),
+    template <typename BufferSequence>
+    write_dynbuf_op(AsyncWriteStream& stream,
+        ASIO_MOVE_ARG(BufferSequence) buffers,
+        CompletionCondition completion_condition, WriteHandler& handler)
+      : stream_(stream),
+        buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)),
+        completion_condition_(
+          ASIO_MOVE_CAST(CompletionCondition)(completion_condition)),
         handler_(ASIO_MOVE_CAST(WriteHandler)(handler))
     {
     }
 
 #if defined(ASIO_HAS_MOVE)
-    write_streambuf_handler(const write_streambuf_handler& other)
-      : streambuf_(other.streambuf_),
+    write_dynbuf_op(const write_dynbuf_op& other)
+      : stream_(other.stream_),
+        buffers_(other.buffers_),
+        completion_condition_(other.completion_condition_),
         handler_(other.handler_)
     {
     }
 
-    write_streambuf_handler(write_streambuf_handler&& other)
-      : streambuf_(other.streambuf_),
+    write_dynbuf_op(write_dynbuf_op&& other)
+      : stream_(other.stream_),
+        buffers_(ASIO_MOVE_CAST(DynamicBufferSequence)(other.buffers_)),
+        completion_condition_(
+          ASIO_MOVE_CAST(CompletionCondition)(other.completion_condition_)),
         handler_(ASIO_MOVE_CAST(WriteHandler)(other.handler_))
     {
     }
 #endif // defined(ASIO_HAS_MOVE)
 
     void operator()(const asio::error_code& ec,
-        const std::size_t bytes_transferred)
+        std::size_t bytes_transferred, int start = 0)
     {
-      streambuf_.consume(bytes_transferred);
-      handler_(ec, bytes_transferred);
+      switch (start)
+      {
+        case 1:
+        async_write(stream_, buffers_.data(), completion_condition_,
+            ASIO_MOVE_CAST(write_dynbuf_op)(*this));
+        return; default:
+        buffers_.consume(bytes_transferred);
+        handler_(ec, static_cast<const std::size_t&>(bytes_transferred));
+      }
     }
 
   //private:
-    asio::basic_streambuf<Allocator>& streambuf_;
+    AsyncWriteStream& stream_;
+    DynamicBufferSequence buffers_;
+    CompletionCondition completion_condition_;
     WriteHandler handler_;
   };
 
-  template <typename Allocator, typename WriteHandler>
+  template <typename AsyncWriteStream, typename DynamicBufferSequence,
+      typename CompletionCondition, typename WriteHandler>
   inline void* asio_handler_allocate(std::size_t size,
-      write_streambuf_handler<Allocator, WriteHandler>* this_handler)
+      write_dynbuf_op<AsyncWriteStream, DynamicBufferSequence,
+        CompletionCondition, WriteHandler>* this_handler)
   {
     return asio_handler_alloc_helpers::allocate(
         size, this_handler->handler_);
   }
 
-  template <typename Allocator, typename WriteHandler>
+  template <typename AsyncWriteStream, typename DynamicBufferSequence,
+      typename CompletionCondition, typename WriteHandler>
   inline void asio_handler_deallocate(void* pointer, std::size_t size,
-      write_streambuf_handler<Allocator, WriteHandler>* this_handler)
+      write_dynbuf_op<AsyncWriteStream, DynamicBufferSequence,
+        CompletionCondition, WriteHandler>* this_handler)
   {
     asio_handler_alloc_helpers::deallocate(
         pointer, size, this_handler->handler_);
   }
 
-  template <typename Allocator, typename WriteHandler>
+  template <typename AsyncWriteStream, typename DynamicBufferSequence,
+      typename CompletionCondition, typename WriteHandler>
   inline bool asio_handler_is_continuation(
-      write_streambuf_handler<Allocator, WriteHandler>* this_handler)
+      write_dynbuf_op<AsyncWriteStream, DynamicBufferSequence,
+        CompletionCondition, WriteHandler>* this_handler)
   {
     return asio_handler_cont_helpers::is_continuation(
         this_handler->handler_);
   }
 
-  template <typename Function, typename Allocator, typename WriteHandler>
+  template <typename Function, typename AsyncWriteStream,
+      typename DynamicBufferSequence, typename CompletionCondition,
+      typename WriteHandler>
   inline void asio_handler_invoke(Function& function,
-      write_streambuf_handler<Allocator, WriteHandler>* this_handler)
+      write_dynbuf_op<AsyncWriteStream, DynamicBufferSequence,
+        CompletionCondition, WriteHandler>* this_handler)
   {
     asio_handler_invoke_helpers::invoke(
         function, this_handler->handler_);
   }
 
-  template <typename Function, typename Allocator, typename WriteHandler>
+  template <typename Function, typename AsyncWriteStream,
+      typename DynamicBufferSequence, typename CompletionCondition,
+      typename WriteHandler>
   inline void asio_handler_invoke(const Function& function,
-      write_streambuf_handler<Allocator, WriteHandler>* this_handler)
+      write_dynbuf_op<AsyncWriteStream, DynamicBufferSequence,
+        CompletionCondition, WriteHandler>* this_handler)
   {
     asio_handler_invoke_helpers::invoke(
         function, this_handler->handler_);
@@ -750,38 +851,103 @@
 
 #if !defined(GENERATING_DOCUMENTATION)
 
-template <typename Allocator, typename WriteHandler, typename Allocator1>
+template <typename AsyncWriteStream, typename DynamicBufferSequence,
+    typename CompletionCondition, typename WriteHandler, typename Allocator>
 struct associated_allocator<
-    detail::write_streambuf_handler<Allocator, WriteHandler>,
-    Allocator1>
+    detail::write_dynbuf_op<AsyncWriteStream,
+      DynamicBufferSequence, CompletionCondition, WriteHandler>,
+    Allocator>
 {
-  typedef typename associated_allocator<WriteHandler, Allocator1>::type type;
+  typedef typename associated_allocator<WriteHandler, Allocator>::type type;
 
   static type get(
-      const detail::write_streambuf_handler<Allocator, WriteHandler>& h,
-      const Allocator1& a = Allocator1()) ASIO_NOEXCEPT
+      const detail::write_dynbuf_op<AsyncWriteStream,
+        DynamicBufferSequence, CompletionCondition, WriteHandler>& h,
+      const Allocator& a = Allocator()) ASIO_NOEXCEPT
   {
-    return associated_allocator<WriteHandler, Allocator1>::get(h.handler_, a);
+    return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);
   }
 };
 
-template <typename Executor, typename WriteHandler, typename Executor1>
+template <typename AsyncWriteStream, typename DynamicBufferSequence,
+    typename CompletionCondition, typename WriteHandler, typename Executor>
 struct associated_executor<
-    detail::write_streambuf_handler<Executor, WriteHandler>,
-    Executor1>
+    detail::write_dynbuf_op<AsyncWriteStream,
+      DynamicBufferSequence, CompletionCondition, WriteHandler>,
+    Executor>
 {
-  typedef typename associated_executor<WriteHandler, Executor1>::type type;
+  typedef typename associated_executor<WriteHandler, Executor>::type type;
 
   static type get(
-      const detail::write_streambuf_handler<Executor, WriteHandler>& h,
-      const Executor1& ex = Executor1()) ASIO_NOEXCEPT
+      const detail::write_dynbuf_op<AsyncWriteStream,
+        DynamicBufferSequence, CompletionCondition, WriteHandler>& h,
+      const Executor& ex = Executor()) ASIO_NOEXCEPT
   {
-    return associated_executor<WriteHandler, Executor1>::get(h.handler_, ex);
+    return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);
   }
 };
 
 #endif // !defined(GENERATING_DOCUMENTATION)
 
+template <typename AsyncWriteStream,
+    typename DynamicBufferSequence, typename WriteHandler>
+inline ASIO_INITFN_RESULT_TYPE(WriteHandler,
+    void (asio::error_code, std::size_t))
+async_write(AsyncWriteStream& s,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    ASIO_MOVE_ARG(WriteHandler) handler,
+    typename enable_if<
+      is_dynamic_buffer_sequence<DynamicBufferSequence>::value
+    >::type*)
+{
+  return async_write(s,
+      ASIO_MOVE_CAST(DynamicBufferSequence)(buffers),
+      transfer_all(), ASIO_MOVE_CAST(WriteHandler)(handler));
+}
+
+template <typename AsyncWriteStream, typename DynamicBufferSequence,
+    typename CompletionCondition, typename WriteHandler>
+inline ASIO_INITFN_RESULT_TYPE(WriteHandler,
+    void (asio::error_code, std::size_t))
+async_write(AsyncWriteStream& s,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    CompletionCondition completion_condition,
+    ASIO_MOVE_ARG(WriteHandler) handler,
+    typename enable_if<
+      is_dynamic_buffer_sequence<DynamicBufferSequence>::value
+    >::type*)
+{
+  // If you get an error on the following line it means that your handler does
+  // not meet the documented type requirements for a WriteHandler.
+  ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
+
+  async_completion<WriteHandler,
+    void (asio::error_code, std::size_t)> init(handler);
+
+  detail::write_dynbuf_op<AsyncWriteStream,
+    typename decay<DynamicBufferSequence>::type,
+      CompletionCondition, ASIO_HANDLER_TYPE(
+        WriteHandler, void (asio::error_code, std::size_t))>(
+          s, ASIO_MOVE_CAST(DynamicBufferSequence)(buffers),
+            completion_condition, init.handler)(
+              asio::error_code(), 0, 1);
+
+  return init.result.get();
+}
+
+#if !defined(ASIO_NO_IOSTREAM)
+
+template <typename AsyncWriteStream, typename Allocator, typename WriteHandler>
+inline ASIO_INITFN_RESULT_TYPE(WriteHandler,
+    void (asio::error_code, std::size_t))
+async_write(AsyncWriteStream& s,
+    asio::basic_streambuf<Allocator>& b,
+    ASIO_MOVE_ARG(WriteHandler) handler)
+{
+  return async_write(s, basic_streambuf_ref<Allocator>(b),
+      ASIO_MOVE_CAST(WriteHandler)(handler));
+}
+
 template <typename AsyncWriteStream, typename Allocator,
     typename CompletionCondition, typename WriteHandler>
 inline ASIO_INITFN_RESULT_TYPE(WriteHandler,
@@ -791,41 +957,8 @@
     CompletionCondition completion_condition,
     ASIO_MOVE_ARG(WriteHandler) handler)
 {
-  // If you get an error on the following line it means that your handler does
-  // not meet the documented type requirements for a WriteHandler.
-  ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
-
-  async_completion<WriteHandler,
-    void (asio::error_code, std::size_t)> init(handler);
-
-  async_write(s, b.data(), completion_condition,
-    detail::write_streambuf_handler<Allocator, ASIO_HANDLER_TYPE(
-      WriteHandler, void (asio::error_code, std::size_t))>(
-        b, init.handler));
-
-  return init.result.get();
-}
-
-template <typename AsyncWriteStream, typename Allocator, typename WriteHandler>
-inline ASIO_INITFN_RESULT_TYPE(WriteHandler,
-    void (asio::error_code, std::size_t))
-async_write(AsyncWriteStream& s,
-    asio::basic_streambuf<Allocator>& b,
-    ASIO_MOVE_ARG(WriteHandler) handler)
-{
-  // If you get an error on the following line it means that your handler does
-  // not meet the documented type requirements for a WriteHandler.
-  ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;
-
-  async_completion<WriteHandler,
-    void (asio::error_code, std::size_t)> init(handler);
-
-  async_write(s, b.data(), transfer_all(),
-    detail::write_streambuf_handler<Allocator, ASIO_HANDLER_TYPE(
-      WriteHandler, void (asio::error_code, std::size_t))>(
-        b, init.handler));
-
-  return init.result.get();
+  return async_write(s, basic_streambuf_ref<Allocator>(b),
+      completion_condition, ASIO_MOVE_CAST(WriteHandler)(handler));
 }
 
 #endif // !defined(ASIO_NO_IOSTREAM)
diff --git a/asio/include/asio/read.hpp b/asio/include/asio/read.hpp
index 12c7653..7de90cc 100644
--- a/asio/include/asio/read.hpp
+++ b/asio/include/asio/read.hpp
@@ -19,6 +19,7 @@
 #include <cstddef>
 #include "asio/async_result.hpp"
 #include "asio/basic_streambuf_fwd.hpp"
+#include "asio/buffer.hpp"
 #include "asio/error.hpp"
 
 #include "asio/detail/push_options.hpp"
@@ -70,7 +71,10 @@
  *     asio::transfer_all()); @endcode
  */
 template <typename SyncReadStream, typename MutableBufferSequence>
-std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers);
+std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
+    typename enable_if<
+      is_mutable_buffer_sequence<MutableBufferSequence>::value
+    >::type* = 0);
 
 /// Attempt to read a certain amount of data from a stream before returning.
 /**
@@ -110,7 +114,10 @@
  */
 template <typename SyncReadStream, typename MutableBufferSequence>
 std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
-    asio::error_code& ec);
+    asio::error_code& ec,
+    typename enable_if<
+      is_mutable_buffer_sequence<MutableBufferSequence>::value
+    >::type* = 0);
 
 /// Attempt to read a certain amount of data from a stream before returning.
 /**
@@ -161,7 +168,10 @@
 template <typename SyncReadStream, typename MutableBufferSequence,
   typename CompletionCondition>
 std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
-    CompletionCondition completion_condition);
+    CompletionCondition completion_condition,
+    typename enable_if<
+      is_mutable_buffer_sequence<MutableBufferSequence>::value
+    >::type* = 0);
 
 /// Attempt to read a certain amount of data from a stream before returning.
 /**
@@ -205,7 +215,169 @@
 template <typename SyncReadStream, typename MutableBufferSequence,
     typename CompletionCondition>
 std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,
-    CompletionCondition completion_condition, asio::error_code& ec);
+    CompletionCondition completion_condition, asio::error_code& ec,
+    typename enable_if<
+      is_mutable_buffer_sequence<MutableBufferSequence>::value
+    >::type* = 0);
+
+/// Attempt to read a certain amount of data from a stream before returning.
+/**
+ * This function is used to read a certain number of bytes of data from a
+ * stream. The call will block until one of the following conditions is true:
+ *
+ * @li The specified dynamic buffer sequence is full (that is, it has reached
+ * maximum size).
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * read_some function.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param buffers The dynamic buffer sequence into which the data will be read.
+ *
+ * @returns The number of bytes transferred.
+ *
+ * @throws asio::system_error Thrown on failure.
+ *
+ * @note This overload is equivalent to calling:
+ * @code asio::read(
+ *     s, buffers,
+ *     asio::transfer_all()); @endcode
+ */
+template <typename SyncReadStream, typename DynamicBufferSequence>
+std::size_t read(SyncReadStream& s,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    typename enable_if<
+      is_dynamic_buffer_sequence<DynamicBufferSequence>::value
+    >::type* = 0);
+
+/// Attempt to read a certain amount of data from a stream before returning.
+/**
+ * This function is used to read a certain number of bytes of data from a
+ * stream. The call will block until one of the following conditions is true:
+ *
+ * @li The supplied buffer is full (that is, it has reached maximum size).
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * read_some function.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param buffers The dynamic buffer sequence into which the data will be read.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes transferred.
+ *
+ * @note This overload is equivalent to calling:
+ * @code asio::read(
+ *     s, buffers,
+ *     asio::transfer_all(), ec); @endcode
+ */
+template <typename SyncReadStream, typename DynamicBufferSequence>
+std::size_t read(SyncReadStream& s,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    asio::error_code& ec,
+    typename enable_if<
+      is_dynamic_buffer_sequence<DynamicBufferSequence>::value
+    >::type* = 0);
+
+/// Attempt to read a certain amount of data from a stream before returning.
+/**
+ * This function is used to read a certain number of bytes of data from a
+ * stream. The call will block until one of the following conditions is true:
+ *
+ * @li The specified dynamic buffer sequence is full (that is, it has reached
+ * maximum size).
+ *
+ * @li The completion_condition function object returns 0.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * read_some function.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param buffers The dynamic buffer sequence into which the data will be read.
+ *
+ * @param completion_condition The function object to be called to determine
+ * whether the read operation is complete. The signature of the function object
+ * must be:
+ * @code std::size_t completion_condition(
+ *   // Result of latest read_some operation.
+ *   const asio::error_code& error,
+ *
+ *   // Number of bytes transferred so far.
+ *   std::size_t bytes_transferred
+ * ); @endcode
+ * A return value of 0 indicates that the read operation is complete. A non-zero
+ * return value indicates the maximum number of bytes to be read on the next
+ * call to the stream's read_some function.
+ *
+ * @returns The number of bytes transferred.
+ *
+ * @throws asio::system_error Thrown on failure.
+ */
+template <typename SyncReadStream, typename DynamicBufferSequence,
+    typename CompletionCondition>
+std::size_t read(SyncReadStream& s,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    CompletionCondition completion_condition,
+    typename enable_if<
+      is_dynamic_buffer_sequence<DynamicBufferSequence>::value
+    >::type* = 0);
+
+/// Attempt to read a certain amount of data from a stream before returning.
+/**
+ * This function is used to read a certain number of bytes of data from a
+ * stream. The call will block until one of the following conditions is true:
+ *
+ * @li The specified dynamic buffer sequence is full (that is, it has reached
+ * maximum size).
+ *
+ * @li The completion_condition function object returns 0.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * read_some function.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param buffers The dynamic buffer sequence into which the data will be read.
+ *
+ * @param completion_condition The function object to be called to determine
+ * whether the read operation is complete. The signature of the function object
+ * must be:
+ * @code std::size_t completion_condition(
+ *   // Result of latest read_some operation.
+ *   const asio::error_code& error,
+ *
+ *   // Number of bytes transferred so far.
+ *   std::size_t bytes_transferred
+ * ); @endcode
+ * A return value of 0 indicates that the read operation is complete. A non-zero
+ * return value indicates the maximum number of bytes to be read on the next
+ * call to the stream's read_some function.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes read. If an error occurs, returns the total
+ * number of bytes successfully transferred prior to the error.
+ */
+template <typename SyncReadStream, typename DynamicBufferSequence,
+    typename CompletionCondition>
+std::size_t read(SyncReadStream& s,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    CompletionCondition completion_condition, asio::error_code& ec,
+    typename enable_if<
+      is_dynamic_buffer_sequence<DynamicBufferSequence>::value
+    >::type* = 0);
 
 #if !defined(ASIO_NO_IOSTREAM)
 
@@ -425,7 +597,10 @@
 ASIO_INITFN_RESULT_TYPE(ReadHandler,
     void (asio::error_code, std::size_t))
 async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
-    ASIO_MOVE_ARG(ReadHandler) handler);
+    ASIO_MOVE_ARG(ReadHandler) handler,
+    typename enable_if<
+      is_mutable_buffer_sequence<MutableBufferSequence>::value
+    >::type* = 0);
 
 /// Start an asynchronous operation to read a certain amount of data from a
 /// stream.
@@ -496,7 +671,141 @@
     void (asio::error_code, std::size_t))
 async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,
     CompletionCondition completion_condition,
-    ASIO_MOVE_ARG(ReadHandler) handler);
+    ASIO_MOVE_ARG(ReadHandler) handler,
+    typename enable_if<
+      is_mutable_buffer_sequence<MutableBufferSequence>::value
+    >::type* = 0);
+
+/// Start an asynchronous operation to read a certain amount of data from a
+/// stream.
+/**
+ * This function is used to asynchronously read a certain number of bytes of
+ * data from a stream. The function call always returns immediately. The
+ * asynchronous operation will continue until one of the following conditions is
+ * true:
+ *
+ * @li The specified dynamic buffer sequence is full (that is, it has reached
+ * maximum size).
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * async_read_some function, and is known as a <em>composed operation</em>. The
+ * program must ensure that the stream performs no other read operations (such
+ * as async_read, the stream's async_read_some function, or any other composed
+ * operations that perform reads) until this operation completes.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the AsyncReadStream concept.
+ *
+ * @param buffers The dynamic buffer sequence into which the data will be read.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param handler The handler to be called when the read operation completes.
+ * Copies will be made of the handler as required. The function signature of the
+ * handler must be:
+ * @code void handler(
+ *   const asio::error_code& error, // Result of operation.
+ *
+ *   std::size_t bytes_transferred           // Number of bytes copied into the
+ *                                           // buffers. If an error occurred,
+ *                                           // this will be the  number of
+ *                                           // bytes successfully transferred
+ *                                           // prior to the error.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation of
+ * the handler will be performed in a manner equivalent to using
+ * asio::io_service::post().
+ *
+ * @note This overload is equivalent to calling:
+ * @code asio::async_read(
+ *     s, buffers,
+ *     asio::transfer_all(),
+ *     handler); @endcode
+ */
+template <typename AsyncReadStream,
+    typename DynamicBufferSequence, typename ReadHandler>
+ASIO_INITFN_RESULT_TYPE(ReadHandler,
+    void (asio::error_code, std::size_t))
+async_read(AsyncReadStream& s,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    ASIO_MOVE_ARG(ReadHandler) handler,
+    typename enable_if<
+      is_dynamic_buffer_sequence<DynamicBufferSequence>::value
+    >::type* = 0);
+
+/// Start an asynchronous operation to read a certain amount of data from a
+/// stream.
+/**
+ * This function is used to asynchronously read a certain number of bytes of
+ * data from a stream. The function call always returns immediately. The
+ * asynchronous operation will continue until one of the following conditions is
+ * true:
+ *
+ * @li The specified dynamic buffer sequence is full (that is, it has reached
+ * maximum size).
+ *
+ * @li The completion_condition function object returns 0.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * async_read_some function, and is known as a <em>composed operation</em>. The
+ * program must ensure that the stream performs no other read operations (such
+ * as async_read, the stream's async_read_some function, or any other composed
+ * operations that perform reads) until this operation completes.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the AsyncReadStream concept.
+ *
+ * @param buffers The dynamic buffer sequence into which the data will be read.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param completion_condition The function object to be called to determine
+ * whether the read operation is complete. The signature of the function object
+ * must be:
+ * @code std::size_t completion_condition(
+ *   // Result of latest async_read_some operation.
+ *   const asio::error_code& error,
+ *
+ *   // Number of bytes transferred so far.
+ *   std::size_t bytes_transferred
+ * ); @endcode
+ * A return value of 0 indicates that the read operation is complete. A non-zero
+ * return value indicates the maximum number of bytes to be read on the next
+ * call to the stream's async_read_some function.
+ *
+ * @param handler The handler to be called when the read operation completes.
+ * Copies will be made of the handler as required. The function signature of the
+ * handler must be:
+ * @code void handler(
+ *   const asio::error_code& error, // Result of operation.
+ *
+ *   std::size_t bytes_transferred           // Number of bytes copied into the
+ *                                           // buffers. If an error occurred,
+ *                                           // this will be the  number of
+ *                                           // bytes successfully transferred
+ *                                           // prior to the error.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation of
+ * the handler will be performed in a manner equivalent to using
+ * asio::io_service::post().
+ */
+template <typename AsyncReadStream, typename DynamicBufferSequence,
+    typename CompletionCondition, typename ReadHandler>
+ASIO_INITFN_RESULT_TYPE(ReadHandler,
+    void (asio::error_code, std::size_t))
+async_read(AsyncReadStream& s,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    CompletionCondition completion_condition,
+    ASIO_MOVE_ARG(ReadHandler) handler,
+    typename enable_if<
+      is_dynamic_buffer_sequence<DynamicBufferSequence>::value
+    >::type* = 0);
 
 #if !defined(ASIO_NO_IOSTREAM)
 
diff --git a/asio/include/asio/read_until.hpp b/asio/include/asio/read_until.hpp
index 212b6f5..083acac 100644
--- a/asio/include/asio/read_until.hpp
+++ b/asio/include/asio/read_until.hpp
@@ -17,12 +17,10 @@
 
 #include "asio/detail/config.hpp"
 
-#if !defined(ASIO_NO_IOSTREAM)
-
 #include <cstddef>
 #include <string>
 #include "asio/async_result.hpp"
-#include "asio/basic_streambuf.hpp"
+#include "asio/basic_streambuf_fwd.hpp"
 #include "asio/detail/regex_fwd.hpp"
 #include "asio/detail/type_traits.hpp"
 #include "asio/error.hpp"
@@ -66,11 +64,483 @@
 /**
  * @defgroup read_until asio::read_until
  *
- * @brief Read data into a streambuf until it contains a delimiter, matches a
- * regular expression, or a function object indicates a match.
+ * @brief Read data into a dynamic buffer sequence, or into a streambuf, until
+ * it contains a delimiter, matches a regular expression, or a function object
+ * indicates a match.
  */
 /*@{*/
 
+/// Read data into a dynamic buffer sequence until it contains a specified
+/// delimiter.
+/**
+ * This function is used to read data into the specified dynamic buffer
+ * sequence until the dynamic buffer sequence's get area contains the specified
+ * delimiter. The call will block until one of the following conditions is
+ * true:
+ *
+ * @li The get area of the dynamic buffer sequence contains the specified
+ * delimiter.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * read_some function. If the dynamic buffer sequence's get area already
+ * contains the delimiter, the function returns immediately.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param buffers The dynamic buffer sequence into which the data will be read.
+ *
+ * @param delim The delimiter character.
+ *
+ * @returns The number of bytes in the dynamic buffer sequence's get area up to
+ * and including the delimiter.
+ *
+ * @throws asio::system_error Thrown on failure.
+ *
+ * @note After a successful read_until operation, the dynamic buffer sequence
+ * may contain additional data beyond the delimiter. An application will
+ * typically leave that data in the dynamic buffer sequence for a subsequent
+ * read_until operation to examine.
+ *
+ * @par Example
+ * To read data into a @c std::string until a newline is encountered:
+ * @code std::string data;
+ * std::string n = asio::read_until(s,
+ *     asio::dynamic_buffer(data), '\n');
+ * std::string line = data.substr(0, n);
+ * data.erase(0, n); @endcode
+ * After the @c read_until operation completes successfully, the string @c data
+ * contains the delimiter:
+ * @code { 'a', 'b', ..., 'c', '\n', 'd', 'e', ... } @endcode
+ * The call to @c substr then extracts the data up to and including the
+ * delimiter, so that the string @c line contains:
+ * @code { 'a', 'b', ..., 'c', '\n' } @endcode
+ * After the call to @c erase, the remaining data is left in the buffer @c b as
+ * follows:
+ * @code { 'd', 'e', ... } @endcode
+ * This data may be the start of a new line, to be extracted by a subsequent
+ * @c read_until operation.
+ */
+template <typename SyncReadStream, typename DynamicBufferSequence>
+std::size_t read_until(SyncReadStream& s,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers, char delim);
+
+/// Read data into a dynamic buffer sequence until it contains a specified
+/// delimiter.
+/**
+ * This function is used to read data into the specified dynamic buffer
+ * sequence until the dynamic buffer sequence's get area contains the specified
+ * delimiter. The call will block until one of the following conditions is
+ * true:
+ *
+ * @li The get area of the dynamic buffer sequence contains the specified
+ * delimiter.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * read_some function. If the dynamic buffer sequence's get area already
+ * contains the delimiter, the function returns immediately.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param buffers The dynamic buffer sequence into which the data will be read.
+ *
+ * @param delim The delimiter character.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes in the dynamic buffer sequence's get area up to
+ * and including the delimiter. Returns 0 if an error occurred.
+ *
+ * @note After a successful read_until operation, the dynamic buffer sequence
+ * may contain additional data beyond the delimiter. An application will
+ * typically leave that data in the dynamic buffer sequence for a subsequent
+ * read_until operation to examine.
+ */
+template <typename SyncReadStream, typename DynamicBufferSequence>
+std::size_t read_until(SyncReadStream& s,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    char delim, asio::error_code& ec);
+
+/// Read data into a dynamic buffer sequence until it contains a specified
+/// delimiter.
+/**
+ * This function is used to read data into the specified dynamic buffer
+ * sequence until the dynamic buffer sequence's get area contains the specified
+ * delimiter. The call will block until one of the following conditions is
+ * true:
+ *
+ * @li The get area of the dynamic buffer sequence contains the specified
+ * delimiter.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * read_some function. If the dynamic buffer sequence's get area already
+ * contains the delimiter, the function returns immediately.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param buffers The dynamic buffer sequence into which the data will be read.
+ *
+ * @param delim The delimiter string.
+ *
+ * @returns The number of bytes in the dynamic buffer sequence's get area up to
+ * and including the delimiter.
+ *
+ * @note After a successful read_until operation, the dynamic buffer sequence
+ * may contain additional data beyond the delimiter. An application will
+ * typically leave that data in the dynamic buffer sequence for a subsequent
+ * read_until operation to examine.
+ *
+ * @par Example
+ * To read data into a @c std::string until a CR-LF sequence is encountered:
+ * @code std::string data;
+ * std::string n = asio::read_until(s,
+ *     asio::dynamic_buffer(data), "\r\n");
+ * std::string line = data.substr(0, n);
+ * data.erase(0, n); @endcode
+ * After the @c read_until operation completes successfully, the string @c data
+ * contains the delimiter:
+ * @code { 'a', 'b', ..., 'c', '\r', '\n', 'd', 'e', ... } @endcode
+ * The call to @c substr then extracts the data up to and including the
+ * delimiter, so that the string @c line contains:
+ * @code { 'a', 'b', ..., 'c', '\r', '\n' } @endcode
+ * After the call to @c erase, the remaining data is left in the buffer @c b as
+ * follows:
+ * @code { 'd', 'e', ... } @endcode
+ * This data may be the start of a new line, to be extracted by a subsequent
+ * @c read_until operation.
+ */
+template <typename SyncReadStream,
+    typename DynamicBufferSequence, typename Allocator>
+std::size_t read_until(SyncReadStream& s,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    const std::basic_string<char, std::char_traits<char>, Allocator>& delim);
+
+/// Read data into a dynamic buffer sequence until it contains a specified
+/// delimiter.
+/**
+ * This function is used to read data into the specified dynamic buffer
+ * sequence until the dynamic buffer sequence's get area contains the specified
+ * delimiter. The call will block until one of the following conditions is
+ * true:
+ *
+ * @li The get area of the dynamic buffer sequence contains the specified
+ * delimiter.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * read_some function. If the dynamic buffer sequence's get area already
+ * contains the delimiter, the function returns immediately.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param buffers The dynamic buffer sequence into which the data will be read.
+ *
+ * @param delim The delimiter string.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes in the dynamic buffer sequence's get area up to
+ * and including the delimiter. Returns 0 if an error occurred.
+ *
+ * @note After a successful read_until operation, the dynamic buffer sequence
+ * may contain additional data beyond the delimiter. An application will
+ * typically leave that data in the dynamic buffer sequence for a subsequent
+ * read_until operation to examine.
+ */
+template <typename SyncReadStream,
+    typename DynamicBufferSequence, typename Allocator>
+std::size_t read_until(SyncReadStream& s,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    const std::basic_string<char, std::char_traits<char>, Allocator>& delim,
+    asio::error_code& ec);
+
+#if defined(ASIO_HAS_BOOST_REGEX) \
+  || defined(GENERATING_DOCUMENTATION)
+
+/// Read data into a dynamic buffer sequence until some part of the data it
+/// contains matches a regular expression.
+/**
+ * This function is used to read data into the specified dynamic buffer
+ * sequence until the dynamic buffer sequence's get area contains some data
+ * that matches a regular expression. The call will block until one of the
+ * following conditions is true:
+ *
+ * @li A substring of the dynamic buffer sequence's get area matches the
+ * regular expression.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * read_some function. If the dynamic buffer sequence's get area already
+ * contains data that matches the regular expression, the function returns
+ * immediately.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param buffers A dynamic buffer sequence into which the data will be read.
+ *
+ * @param expr The regular expression.
+ *
+ * @returns The number of bytes in the dynamic buffer sequence's get area up to
+ * and including the substring that matches the regular expression.
+ *
+ * @throws asio::system_error Thrown on failure.
+ *
+ * @note After a successful read_until operation, the dynamic buffer sequence
+ * may contain additional data beyond that which matched the regular
+ * expression. An application will typically leave that data in the dynamic
+ * buffer sequence for a subsequent read_until operation to examine.
+ *
+ * @par Example
+ * To read data into a @c std::string until a CR-LF sequence is encountered:
+ * @code std::string data;
+ * std::string n = asio::read_until(s,
+ *     asio::dynamic_buffer(data), boost::regex("\r\n"));
+ * std::string line = data.substr(0, n);
+ * data.erase(0, n); @endcode
+ * After the @c read_until operation completes successfully, the string @c data
+ * contains the delimiter:
+ * @code { 'a', 'b', ..., 'c', '\r', '\n', 'd', 'e', ... } @endcode
+ * The call to @c substr then extracts the data up to and including the
+ * delimiter, so that the string @c line contains:
+ * @code { 'a', 'b', ..., 'c', '\r', '\n' } @endcode
+ * After the call to @c erase, the remaining data is left in the buffer @c b as
+ * follows:
+ * @code { 'd', 'e', ... } @endcode
+ * This data may be the start of a new line, to be extracted by a subsequent
+ * @c read_until operation.
+ */
+template <typename SyncReadStream, typename DynamicBufferSequence>
+std::size_t read_until(SyncReadStream& s,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    const boost::regex& expr);
+
+/// Read data into a dynamic buffer sequence until some part of the data it
+/// contains matches a regular expression.
+/**
+ * This function is used to read data into the specified dynamic buffer
+ * sequence until the dynamic buffer sequence's get area contains some data
+ * that matches a regular expression. The call will block until one of the
+ * following conditions is true:
+ *
+ * @li A substring of the dynamic buffer sequence's get area matches the
+ * regular expression.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * read_some function. If the dynamic buffer sequence's get area already
+ * contains data that matches the regular expression, the function returns
+ * immediately.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param buffers A dynamic buffer sequence into which the data will be read.
+ *
+ * @param expr The regular expression.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes in the dynamic buffer sequence's get area up to
+ * and including the substring that matches the regular expression. Returns 0
+ * if an error occurred.
+ *
+ * @note After a successful read_until operation, the dynamic buffer sequence
+ * may contain additional data beyond that which matched the regular
+ * expression. An application will typically leave that data in the dynamic
+ * buffer sequence for a subsequent read_until operation to examine.
+ */
+template <typename SyncReadStream, typename DynamicBufferSequence>
+std::size_t read_until(SyncReadStream& s,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    const boost::regex& expr, asio::error_code& ec);
+
+#endif // defined(ASIO_HAS_BOOST_REGEX)
+       // || defined(GENERATING_DOCUMENTATION)
+
+/// Read data into a dynamic buffer sequence until a function object indicates a
+/// match.
+
+/**
+ * This function is used to read data into the specified dynamic buffer
+ * sequence until a user-defined match condition function object, when applied
+ * to the data contained in the dynamic buffer sequence, indicates a successful
+ * match. The call will block until one of the following conditions is true:
+ *
+ * @li The match condition function object returns a std::pair where the second
+ * element evaluates to true.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * read_some function. If the match condition function object already indicates
+ * a match, the function returns immediately.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param buffers A dynamic buffer sequence into which the data will be read.
+ *
+ * @param match_condition The function object to be called to determine whether
+ * a match exists. The signature of the function object must be:
+ * @code pair<iterator, bool> match_condition(iterator begin, iterator end);
+ * @endcode
+ * where @c iterator represents the type:
+ * @code buffers_iterator<typename DynamicBufferSequence::const_buffers_type>
+ * @endcode
+ * The iterator parameters @c begin and @c end define the range of bytes to be
+ * scanned to determine whether there is a match. The @c first member of the
+ * return value is an iterator marking one-past-the-end of the bytes that have
+ * been consumed by the match function. This iterator is used to calculate the
+ * @c begin parameter for any subsequent invocation of the match condition. The
+ * @c second member of the return value is true if a match has been found, false
+ * otherwise.
+ *
+ * @returns The number of bytes in the dynamic_buffer_sequence's get area that
+ * have been fully consumed by the match function.
+ *
+ * @throws asio::system_error Thrown on failure.
+ *
+ * @note After a successful read_until operation, the dynamic buffer sequence
+ * may contain additional data beyond that which matched the function object.
+ * An application will typically leave that data in the dynamic buffer sequence
+ * for a subsequent read_until operation to examine.
+
+ * @note The default implementation of the @c is_match_condition type trait
+ * evaluates to true for function pointers and function objects with a
+ * @c result_type typedef. It must be specialised for other user-defined
+ * function objects.
+ *
+ * @par Examples
+ * To read data into a dynamic buffer sequence until whitespace is encountered:
+ * @code typedef asio::buffers_iterator<
+ *     asio::const_buffers_1> iterator;
+ *
+ * std::pair<iterator, bool>
+ * match_whitespace(iterator begin, iterator end)
+ * {
+ *   iterator i = begin;
+ *   while (i != end)
+ *     if (std::isspace(*i++))
+ *       return std::make_pair(i, true);
+ *   return std::make_pair(i, false);
+ * }
+ * ...
+ * std::string data;
+ * asio::read_until(s, data, match_whitespace);
+ * @endcode
+ *
+ * To read data into a @c std::string until a matching character is found:
+ * @code class match_char
+ * {
+ * public:
+ *   explicit match_char(char c) : c_(c) {}
+ *
+ *   template <typename Iterator>
+ *   std::pair<Iterator, bool> operator()(
+ *       Iterator begin, Iterator end) const
+ *   {
+ *     Iterator i = begin;
+ *     while (i != end)
+ *       if (c_ == *i++)
+ *         return std::make_pair(i, true);
+ *     return std::make_pair(i, false);
+ *   }
+ *
+ * private:
+ *   char c_;
+ * };
+ *
+ * namespace asio {
+ *   template <> struct is_match_condition<match_char>
+ *     : public boost::true_type {};
+ * } // namespace asio
+ * ...
+ * std::string data;
+ * asio::read_until(s, data, match_char('a'));
+ * @endcode
+ */
+template <typename SyncReadStream,
+    typename DynamicBufferSequence, typename MatchCondition>
+std::size_t read_until(SyncReadStream& s,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    MatchCondition match_condition,
+    typename enable_if<is_match_condition<MatchCondition>::value>::type* = 0);
+
+/// Read data into a dynamic buffer sequence until a function object indicates a
+/// match.
+/**
+ * This function is used to read data into the specified dynamic buffer
+ * sequence until a user-defined match condition function object, when applied
+ * to the data contained in the dynamic buffer sequence, indicates a successful
+ * match. The call will block until one of the following conditions is true:
+ *
+ * @li The match condition function object returns a std::pair where the second
+ * element evaluates to true.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * read_some function. If the match condition function object already indicates
+ * a match, the function returns immediately.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the SyncReadStream concept.
+ *
+ * @param buffers A dynamic buffer sequence into which the data will be read.
+ *
+ * @param match_condition The function object to be called to determine whether
+ * a match exists. The signature of the function object must be:
+ * @code pair<iterator, bool> match_condition(iterator begin, iterator end);
+ * @endcode
+ * where @c iterator represents the type:
+ * @code buffers_iterator<DynamicBufferSequence::const_buffers_type>
+ * @endcode
+ * The iterator parameters @c begin and @c end define the range of bytes to be
+ * scanned to determine whether there is a match. The @c first member of the
+ * return value is an iterator marking one-past-the-end of the bytes that have
+ * been consumed by the match function. This iterator is used to calculate the
+ * @c begin parameter for any subsequent invocation of the match condition. The
+ * @c second member of the return value is true if a match has been found, false
+ * otherwise.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes in the dynamic buffer sequence's get area that
+ * have been fully consumed by the match function. Returns 0 if an error
+ * occurred.
+ *
+ * @note After a successful read_until operation, the dynamic buffer sequence
+ * may contain additional data beyond that which matched the function object.
+ * An application will typically leave that data in the dynamic buffer sequence
+ * for a subsequent read_until operation to examine.
+ *
+ * @note The default implementation of the @c is_match_condition type trait
+ * evaluates to true for function pointers and function objects with a
+ * @c result_type typedef. It must be specialised for other user-defined
+ * function objects.
+ */
+template <typename SyncReadStream,
+    typename DynamicBufferSequence, typename MatchCondition>
+std::size_t read_until(SyncReadStream& s,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    MatchCondition match_condition, asio::error_code& ec,
+    typename enable_if<is_match_condition<MatchCondition>::value>::type* = 0);
+
+#if !defined(ASIO_NO_IOSTREAM)
+
 /// Read data into a streambuf until it contains a specified delimiter.
 /**
  * This function is used to read data into the specified streambuf until the
@@ -386,7 +856,8 @@
  *
  * @note After a successful read_until operation, the streambuf may contain
  * additional data beyond that which matched the function object. An application
- * will typically leave that data in the streambuf for a subsequent
+ * will typically leave that data in the streambuf for a subsequent read_until
+ * operation to examine.
  *
  * @note The default implementation of the @c is_match_condition type trait
  * evaluates to true for function pointers and function objects with a
@@ -490,7 +961,8 @@
  *
  * @note After a successful read_until operation, the streambuf may contain
  * additional data beyond that which matched the function object. An application
- * will typically leave that data in the streambuf for a subsequent
+ * will typically leave that data in the streambuf for a subsequent read_until
+ * operation to examine.
  *
  * @note The default implementation of the @c is_match_condition type trait
  * evaluates to true for function pointers and function objects with a
@@ -503,16 +975,438 @@
     MatchCondition match_condition, asio::error_code& ec,
     typename enable_if<is_match_condition<MatchCondition>::value>::type* = 0);
 
+#endif // !defined(ASIO_NO_IOSTREAM)
+
 /*@}*/
 /**
  * @defgroup async_read_until asio::async_read_until
  *
- * @brief Start an asynchronous operation to read data into a streambuf until it
- * contains a delimiter, matches a regular expression, or a function object
- * indicates a match.
+ * @brief Start an asynchronous operation to read data into a dynamic buffer
+ * sequence, or into a streambuf, until it contains a delimiter, matches a
+ * regular expression, or a function object indicates a match.
  */
 /*@{*/
 
+/// Start an asynchronous operation to read data into a dynamic buffer sequence
+/// until it contains a specified delimiter.
+/**
+ * This function is used to asynchronously read data into the specified dynamic
+ * buffer sequence until the dynamic buffer sequence's get area contains the
+ * specified delimiter. The function call always returns immediately. The
+ * asynchronous operation will continue until one of the following conditions
+ * is true:
+ *
+ * @li The get area of the dynamic buffer sequence contains the specified
+ * delimiter.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * async_read_some function, and is known as a <em>composed operation</em>. If
+ * the dynamic buffer sequence's get area already contains the delimiter, this
+ * asynchronous operation completes immediately. The program must ensure that
+ * the stream performs no other read operations (such as async_read,
+ * async_read_until, the stream's async_read_some function, or any other
+ * composed operations that perform reads) until this operation completes.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the AsyncReadStream concept.
+ *
+ * @param buffers The dynamic buffer sequence into which the data will be read.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param delim The delimiter character.
+ *
+ * @param handler The handler to be called when the read operation completes.
+ * Copies will be made of the handler as required. The function signature of the
+ * handler must be:
+ * @code void handler(
+ *   // Result of operation.
+ *   const asio::error_code& error,
+ *
+ *   // The number of bytes in the dynamic buffer sequence's
+ *   // get area up to and including the delimiter.
+ *   // 0 if an error occurred.
+ *   std::size_t bytes_transferred
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation of
+ * the handler will be performed in a manner equivalent to using
+ * asio::io_service::post().
+ *
+ * @note After a successful async_read_until operation, the dynamic buffer
+ * sequence may contain additional data beyond the delimiter. An application
+ * will typically leave that data in the dynamic buffer sequence for a
+ * subsequent async_read_until operation to examine.
+ *
+ * @par Example
+ * To asynchronously read data into a @c std::string until a newline is
+ * encountered:
+ * @code std::string data;
+ * ...
+ * void handler(const asio::error_code& e, std::size_t size)
+ * {
+ *   if (!e)
+ *   {
+ *     std::string line = data.substr(0, n);
+ *     data.erase(0, n); @endcode
+ *     ...
+ *   }
+ * }
+ * ...
+ * asio::async_read_until(s, data, '\n', handler); @endcode
+ * After the @c async_read_until operation completes successfully, the buffer
+ * @c data contains the delimiter:
+ * @code { 'a', 'b', ..., 'c', '\n', 'd', 'e', ... } @endcode
+ * The call to @c substr then extracts the data up to and including the
+ * delimiter, so that the string @c line contains:
+ * @code { 'a', 'b', ..., 'c', '\n' } @endcode
+ * After the call to @c erase, the remaining data is left in the buffer @c data
+ * as follows:
+ * @code { 'd', 'e', ... } @endcode
+ * This data may be the start of a new line, to be extracted by a subsequent
+ * @c async_read_until operation.
+ */
+template <typename AsyncReadStream,
+    typename DynamicBufferSequence, typename ReadHandler>
+ASIO_INITFN_RESULT_TYPE(ReadHandler,
+    void (asio::error_code, std::size_t))
+async_read_until(AsyncReadStream& s,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    char delim, ASIO_MOVE_ARG(ReadHandler) handler);
+
+/// Start an asynchronous operation to read data into a dynamic buffer sequence
+/// until it contains a specified delimiter.
+/**
+ * This function is used to asynchronously read data into the specified dynamic
+ * buffer sequence until the dynamic buffer sequence's get area contains the
+ * specified delimiter. The function call always returns immediately. The
+ * asynchronous operation will continue until one of the following conditions
+ * is true:
+ *
+ * @li The get area of the dynamic buffer sequence contains the specified
+ * delimiter.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * async_read_some function, and is known as a <em>composed operation</em>. If
+ * the dynamic buffer sequence's get area already contains the delimiter, this
+ * asynchronous operation completes immediately. The program must ensure that
+ * the stream performs no other read operations (such as async_read,
+ * async_read_until, the stream's async_read_some function, or any other
+ * composed operations that perform reads) until this operation completes.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the AsyncReadStream concept.
+ *
+ * @param buffers The dynamic buffer sequence into which the data will be read.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param delim The delimiter string.
+ *
+ * @param handler The handler to be called when the read operation completes.
+ * Copies will be made of the handler as required. The function signature of the
+ * handler must be:
+ * @code void handler(
+ *   // Result of operation.
+ *   const asio::error_code& error,
+ *
+ *   // The number of bytes in the dynamic buffer sequence's
+ *   // get area up to and including the delimiter.
+ *   // 0 if an error occurred.
+ *   std::size_t bytes_transferred
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation of
+ * the handler will be performed in a manner equivalent to using
+ * asio::io_service::post().
+ *
+ * @note After a successful async_read_until operation, the dynamic buffer
+ * sequence may contain additional data beyond the delimiter. An application
+ * will typically leave that data in the dynamic buffer sequence for a
+ * subsequent async_read_until operation to examine.
+ *
+ * @par Example
+ * To asynchronously read data into a @c std::string until a CR-LF sequence is
+ * encountered:
+ * @code std::string data;
+ * ...
+ * void handler(const asio::error_code& e, std::size_t size)
+ * {
+ *   if (!e)
+ *   {
+ *     std::string line = data.substr(0, n);
+ *     data.erase(0, n);
+ *     ...
+ *   }
+ * }
+ * ...
+ * asio::async_read_until(s, data, "\r\n", handler); @endcode
+ * After the @c async_read_until operation completes successfully, the string
+ * @c data contains the delimiter:
+ * @code { 'a', 'b', ..., 'c', '\r', '\n', 'd', 'e', ... } @endcode
+ * The call to @c substr then extracts the data up to and including the
+ * delimiter, so that the string @c line contains:
+ * @code { 'a', 'b', ..., 'c', '\r', '\n' } @endcode
+ * After the call to @c erase, the remaining data is left in the string @c data
+ * as follows:
+ * @code { 'd', 'e', ... } @endcode
+ * This data may be the start of a new line, to be extracted by a subsequent
+ * @c async_read_until operation.
+ */
+template <typename AsyncReadStream,
+    typename DynamicBufferSequence, typename ReadHandler>
+ASIO_INITFN_RESULT_TYPE(ReadHandler,
+    void (asio::error_code, std::size_t))
+async_read_until(AsyncReadStream& s,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    const std::string& delim,
+    ASIO_MOVE_ARG(ReadHandler) handler);
+
+#if defined(ASIO_HAS_BOOST_REGEX) \
+  || defined(GENERATING_DOCUMENTATION)
+
+/// Start an asynchronous operation to read data into a dynamic buffer sequence
+/// until some part of its data matches a regular expression.
+/**
+ * This function is used to asynchronously read data into the specified dynamic
+ * buffer sequence until the dynamic buffer sequence's get area contains some
+ * data that matches a regular expression. The function call always returns
+ * immediately. The asynchronous operation will continue until one of the
+ * following conditions is true:
+ *
+ * @li A substring of the dynamic buffer sequence's get area matches the regular
+ * expression.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * async_read_some function, and is known as a <em>composed operation</em>. If
+ * the dynamic buffer sequence's get area already contains data that matches
+ * the regular expression, this asynchronous operation completes immediately.
+ * The program must ensure that the stream performs no other read operations
+ * (such as async_read, async_read_until, the stream's async_read_some
+ * function, or any other composed operations that perform reads) until this
+ * operation completes.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the AsyncReadStream concept.
+ *
+ * @param buffers The dynamic buffer sequence into which the data will be read.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param expr The regular expression.
+ *
+ * @param handler The handler to be called when the read operation completes.
+ * Copies will be made of the handler as required. The function signature of the
+ * handler must be:
+ * @code void handler(
+ *   // Result of operation.
+ *   const asio::error_code& error,
+ *
+ *   // The number of bytes in the dynamic buffer
+ *   // sequence's get area up to and including the
+ *   // substring that matches the regular expression.
+ *   // 0 if an error occurred.
+ *   std::size_t bytes_transferred
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation of
+ * the handler will be performed in a manner equivalent to using
+ * asio::io_service::post().
+ *
+ * @note After a successful async_read_until operation, the dynamic buffer
+ * sequence may contain additional data beyond that which matched the regular
+ * expression. An application will typically leave that data in the dynamic
+ * buffer sequence for a subsequent async_read_until operation to examine.
+ *
+ * @par Example
+ * To asynchronously read data into a @c std::string until a CR-LF sequence is
+ * encountered:
+ * @code std::string data;
+ * ...
+ * void handler(const asio::error_code& e, std::size_t size)
+ * {
+ *   if (!e)
+ *   {
+ *     std::string line = data.substr(0, n);
+ *     data.erase(0, n);
+ *     ...
+ *   }
+ * }
+ * ...
+ * asio::async_read_until(s, data,
+ *     boost::regex("\r\n"), handler); @endcode
+ * After the @c async_read_until operation completes successfully, the string
+ * @c data contains the data which matched the regular expression:
+ * @code { 'a', 'b', ..., 'c', '\r', '\n', 'd', 'e', ... } @endcode
+ * The call to @c substr then extracts the data up to and including the match,
+ * so that the string @c line contains:
+ * @code { 'a', 'b', ..., 'c', '\r', '\n' } @endcode
+ * After the call to @c erase, the remaining data is left in the string @c data
+ * as follows:
+ * @code { 'd', 'e', ... } @endcode
+ * This data may be the start of a new line, to be extracted by a subsequent
+ * @c async_read_until operation.
+ */
+template <typename AsyncReadStream,
+    typename DynamicBufferSequence, typename ReadHandler>
+ASIO_INITFN_RESULT_TYPE(ReadHandler,
+    void (asio::error_code, std::size_t))
+async_read_until(AsyncReadStream& s,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    const boost::regex& expr,
+    ASIO_MOVE_ARG(ReadHandler) handler);
+
+#endif // defined(ASIO_HAS_BOOST_REGEX)
+       // || defined(GENERATING_DOCUMENTATION)
+
+/// Start an asynchronous operation to read data into a dynamic buffer sequence
+/// until a function object indicates a match.
+/**
+ * This function is used to asynchronously read data into the specified dynamic
+ * buffer sequence until a user-defined match condition function object, when
+ * applied to the data contained in the dynamic buffer sequence, indicates a
+ * successful match. The function call always returns immediately. The
+ * asynchronous operation will continue until one of the following conditions
+ * is true:
+ *
+ * @li The match condition function object returns a std::pair where the second
+ * element evaluates to true.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * async_read_some function, and is known as a <em>composed operation</em>. If
+ * the match condition function object already indicates a match, this
+ * asynchronous operation completes immediately. The program must ensure that
+ * the stream performs no other read operations (such as async_read,
+ * async_read_until, the stream's async_read_some function, or any other
+ * composed operations that perform reads) until this operation completes.
+ *
+ * @param s The stream from which the data is to be read. The type must support
+ * the AsyncReadStream concept.
+ *
+ * @param buffers The dynamic buffer sequence into which the data will be read.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called.
+ *
+ * @param match_condition The function object to be called to determine whether
+ * a match exists. The signature of the function object must be:
+ * @code pair<iterator, bool> match_condition(iterator begin, iterator end);
+ * @endcode
+ * where @c iterator represents the type:
+ * @code buffers_iterator<typename DynamicBufferSequence::const_buffers_type>
+ * @endcode
+ * The iterator parameters @c begin and @c end define the range of bytes to be
+ * scanned to determine whether there is a match. The @c first member of the
+ * return value is an iterator marking one-past-the-end of the bytes that have
+ * been consumed by the match function. This iterator is used to calculate the
+ * @c begin parameter for any subsequent invocation of the match condition. The
+ * @c second member of the return value is true if a match has been found, false
+ * otherwise.
+ *
+ * @param handler The handler to be called when the read operation completes.
+ * Copies will be made of the handler as required. The function signature of the
+ * handler must be:
+ * @code void handler(
+ *   // Result of operation.
+ *   const asio::error_code& error,
+ *
+ *   // The number of bytes in the dynamic buffer sequence's
+ *   // get area that have been fully consumed by the match
+ *   // function. O if an error occurred.
+ *   std::size_t bytes_transferred
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation of
+ * the handler will be performed in a manner equivalent to using
+ * asio::io_service::post().
+ *
+ * @note After a successful async_read_until operation, the dynamic buffer
+ * sequence may contain additional data beyond that which matched the function
+ * object. An application will typically leave that data in the dynamic buffer
+ * sequence for a subsequent async_read_until operation to examine.
+ *
+ * @note The default implementation of the @c is_match_condition type trait
+ * evaluates to true for function pointers and function objects with a
+ * @c result_type typedef. It must be specialised for other user-defined
+ * function objects.
+ *
+ * @par Examples
+ * To asynchronously read data into a @c std::string until whitespace is
+ * encountered:
+ * @code typedef asio::buffers_iterator<
+ *     asio::const_buffers_1> iterator;
+ *
+ * std::pair<iterator, bool>
+ * match_whitespace(iterator begin, iterator end)
+ * {
+ *   iterator i = begin;
+ *   while (i != end)
+ *     if (std::isspace(*i++))
+ *       return std::make_pair(i, true);
+ *   return std::make_pair(i, false);
+ * }
+ * ...
+ * void handler(const asio::error_code& e, std::size_t size);
+ * ...
+ * std::string data;
+ * asio::async_read_until(s, data, match_whitespace, handler);
+ * @endcode
+ *
+ * To asynchronously read data into a @c std::string until a matching character
+ * is found:
+ * @code class match_char
+ * {
+ * public:
+ *   explicit match_char(char c) : c_(c) {}
+ *
+ *   template <typename Iterator>
+ *   std::pair<Iterator, bool> operator()(
+ *       Iterator begin, Iterator end) const
+ *   {
+ *     Iterator i = begin;
+ *     while (i != end)
+ *       if (c_ == *i++)
+ *         return std::make_pair(i, true);
+ *     return std::make_pair(i, false);
+ *   }
+ *
+ * private:
+ *   char c_;
+ * };
+ *
+ * namespace asio {
+ *   template <> struct is_match_condition<match_char>
+ *     : public boost::true_type {};
+ * } // namespace asio
+ * ...
+ * void handler(const asio::error_code& e, std::size_t size);
+ * ...
+ * std::string data;
+ * asio::async_read_until(s, data, match_char('a'), handler);
+ * @endcode
+ */
+template <typename AsyncReadStream, typename DynamicBufferSequence,
+    typename MatchCondition, typename ReadHandler>
+ASIO_INITFN_RESULT_TYPE(ReadHandler,
+    void (asio::error_code, std::size_t))
+async_read_until(AsyncReadStream& s,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    MatchCondition match_condition, ASIO_MOVE_ARG(ReadHandler) handler,
+    typename enable_if<is_match_condition<MatchCondition>::value>::type* = 0);
+
+#if !defined(ASIO_NO_IOSTREAM)
+
 /// Start an asynchronous operation to read data into a streambuf until it
 /// contains a specified delimiter.
 /**
@@ -910,6 +1804,8 @@
     MatchCondition match_condition, ASIO_MOVE_ARG(ReadHandler) handler,
     typename enable_if<is_match_condition<MatchCondition>::value>::type* = 0);
 
+#endif // !defined(ASIO_NO_IOSTREAM)
+
 /*@}*/
 
 } // namespace asio
@@ -918,6 +1814,4 @@
 
 #include "asio/impl/read_until.hpp"
 
-#endif // !defined(ASIO_NO_IOSTREAM)
-
 #endif // ASIO_READ_UNTIL_HPP
diff --git a/asio/include/asio/write.hpp b/asio/include/asio/write.hpp
index 6799179..968c550 100644
--- a/asio/include/asio/write.hpp
+++ b/asio/include/asio/write.hpp
@@ -19,6 +19,7 @@
 #include <cstddef>
 #include "asio/async_result.hpp"
 #include "asio/basic_streambuf_fwd.hpp"
+#include "asio/buffer.hpp"
 #include "asio/error.hpp"
 
 #include "asio/detail/push_options.hpp"
@@ -69,7 +70,10 @@
  *     asio::transfer_all()); @endcode
  */
 template <typename SyncWriteStream, typename ConstBufferSequence>
-std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers);
+std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
+    typename enable_if<
+      is_const_buffer_sequence<ConstBufferSequence>::value
+    >::type* = 0);
 
 /// Write all of the supplied data to a stream before returning.
 /**
@@ -109,7 +113,10 @@
  */
 template <typename SyncWriteStream, typename ConstBufferSequence>
 std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
-    asio::error_code& ec);
+    asio::error_code& ec,
+    typename enable_if<
+      is_const_buffer_sequence<ConstBufferSequence>::value
+    >::type* = 0);
 
 /// Write a certain amount of data to a stream before returning.
 /**
@@ -160,7 +167,10 @@
 template <typename SyncWriteStream, typename ConstBufferSequence,
     typename CompletionCondition>
 std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
-    CompletionCondition completion_condition);
+    CompletionCondition completion_condition,
+    typename enable_if<
+      is_const_buffer_sequence<ConstBufferSequence>::value
+    >::type* = 0);
 
 /// Write a certain amount of data to a stream before returning.
 /**
@@ -204,7 +214,170 @@
 template <typename SyncWriteStream, typename ConstBufferSequence,
     typename CompletionCondition>
 std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,
-    CompletionCondition completion_condition, asio::error_code& ec);
+    CompletionCondition completion_condition, asio::error_code& ec,
+    typename enable_if<
+      is_const_buffer_sequence<ConstBufferSequence>::value
+    >::type* = 0);
+
+/// Write all of the supplied data to a stream before returning.
+/**
+ * This function is used to write a certain number of bytes of data to a stream.
+ * The call will block until one of the following conditions is true:
+ *
+ * @li All of the data in the supplied dynamic buffer sequence has been written.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * write_some function.
+ *
+ * @param s The stream to which the data is to be written. The type must support
+ * the SyncWriteStream concept.
+ *
+ * @param buffers The dynamic buffer sequence from which data will be written.
+ * Successfully written data is automatically consumed from the buffers.
+ *
+ * @returns The number of bytes transferred.
+ *
+ * @throws asio::system_error Thrown on failure.
+ *
+ * @note This overload is equivalent to calling:
+ * @code asio::write(
+ *     s, buffers,
+ *     asio::transfer_all()); @endcode
+ */
+template <typename SyncWriteStream, typename DynamicBufferSequence>
+std::size_t write(SyncWriteStream& s,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    typename enable_if<
+      is_dynamic_buffer_sequence<DynamicBufferSequence>::value
+    >::type* = 0);
+
+/// Write all of the supplied data to a stream before returning.
+/**
+ * This function is used to write a certain number of bytes of data to a stream.
+ * The call will block until one of the following conditions is true:
+ *
+ * @li All of the data in the supplied dynamic buffer sequence has been written.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * write_some function.
+ *
+ * @param s The stream to which the data is to be written. The type must support
+ * the SyncWriteStream concept.
+ *
+ * @param buffers The dynamic buffer sequence from which data will be written.
+ * Successfully written data is automatically consumed from the buffers.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes transferred.
+ *
+ * @note This overload is equivalent to calling:
+ * @code asio::write(
+ *     s, buffers,
+ *     asio::transfer_all(), ec); @endcode
+ */
+template <typename SyncWriteStream, typename DynamicBufferSequence>
+std::size_t write(SyncWriteStream& s,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    asio::error_code& ec,
+    typename enable_if<
+      is_dynamic_buffer_sequence<DynamicBufferSequence>::value
+    >::type* = 0);
+
+/// Write a certain amount of data to a stream before returning.
+/**
+ * This function is used to write a certain number of bytes of data to a stream.
+ * The call will block until one of the following conditions is true:
+ *
+ * @li All of the data in the supplied dynamic buffer sequence has been written.
+ *
+ * @li The completion_condition function object returns 0.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * write_some function.
+ *
+ * @param s The stream to which the data is to be written. The type must support
+ * the SyncWriteStream concept.
+ *
+ * @param buffers The dynamic buffer sequence from which data will be written.
+ * Successfully written data is automatically consumed from the buffers.
+ *
+ * @param completion_condition The function object to be called to determine
+ * whether the write operation is complete. The signature of the function object
+ * must be:
+ * @code std::size_t completion_condition(
+ *   // Result of latest write_some operation.
+ *   const asio::error_code& error,
+ *
+ *   // Number of bytes transferred so far.
+ *   std::size_t bytes_transferred
+ * ); @endcode
+ * A return value of 0 indicates that the write operation is complete. A
+ * non-zero return value indicates the maximum number of bytes to be written on
+ * the next call to the stream's write_some function.
+ *
+ * @returns The number of bytes transferred.
+ *
+ * @throws asio::system_error Thrown on failure.
+ */
+template <typename SyncWriteStream, typename DynamicBufferSequence,
+    typename CompletionCondition>
+std::size_t write(SyncWriteStream& s,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    CompletionCondition completion_condition,
+    typename enable_if<
+      is_dynamic_buffer_sequence<DynamicBufferSequence>::value
+    >::type* = 0);
+
+/// Write a certain amount of data to a stream before returning.
+/**
+ * This function is used to write a certain number of bytes of data to a stream.
+ * The call will block until one of the following conditions is true:
+ *
+ * @li All of the data in the supplied dynamic buffer sequence has been written.
+ *
+ * @li The completion_condition function object returns 0.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * write_some function.
+ *
+ * @param s The stream to which the data is to be written. The type must support
+ * the SyncWriteStream concept.
+ *
+ * @param buffers The dynamic buffer sequence from which data will be written.
+ * Successfully written data is automatically consumed from the buffers.
+ *
+ * @param completion_condition The function object to be called to determine
+ * whether the write operation is complete. The signature of the function object
+ * must be:
+ * @code std::size_t completion_condition(
+ *   // Result of latest write_some operation.
+ *   const asio::error_code& error,
+ *
+ *   // Number of bytes transferred so far.
+ *   std::size_t bytes_transferred
+ * ); @endcode
+ * A return value of 0 indicates that the write operation is complete. A
+ * non-zero return value indicates the maximum number of bytes to be written on
+ * the next call to the stream's write_some function.
+ *
+ * @param ec Set to indicate what error occurred, if any.
+ *
+ * @returns The number of bytes written. If an error occurs, returns the total
+ * number of bytes successfully transferred prior to the error.
+ */
+template <typename SyncWriteStream, typename DynamicBufferSequence,
+    typename CompletionCondition>
+std::size_t write(SyncWriteStream& s,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    CompletionCondition completion_condition, asio::error_code& ec,
+    typename enable_if<
+      is_dynamic_buffer_sequence<DynamicBufferSequence>::value
+    >::type* = 0);
 
 #if !defined(ASIO_NO_IOSTREAM)
 
@@ -416,7 +589,10 @@
 ASIO_INITFN_RESULT_TYPE(WriteHandler,
     void (asio::error_code, std::size_t))
 async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
-    ASIO_MOVE_ARG(WriteHandler) handler);
+    ASIO_MOVE_ARG(WriteHandler) handler,
+    typename enable_if<
+      is_const_buffer_sequence<ConstBufferSequence>::value
+    >::type* = 0);
 
 /// Start an asynchronous operation to write a certain amount of data to a
 /// stream.
@@ -491,7 +667,133 @@
     void (asio::error_code, std::size_t))
 async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,
     CompletionCondition completion_condition,
-    ASIO_MOVE_ARG(WriteHandler) handler);
+    ASIO_MOVE_ARG(WriteHandler) handler,
+    typename enable_if<
+      is_const_buffer_sequence<ConstBufferSequence>::value
+    >::type* = 0);
+
+/// Start an asynchronous operation to write all of the supplied data to a
+/// stream.
+/**
+ * This function is used to asynchronously write a certain number of bytes of
+ * data to a stream. The function call always returns immediately. The
+ * asynchronous operation will continue until one of the following conditions
+ * is true:
+ *
+ * @li All of the data in the supplied dynamic buffer sequence has been written.
+ *
+ * @li An error occurred.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * async_write_some function, and is known as a <em>composed operation</em>. The
+ * program must ensure that the stream performs no other write operations (such
+ * as async_write, the stream's async_write_some function, or any other composed
+ * operations that perform writes) until this operation completes.
+ *
+ * @param s The stream to which the data is to be written. The type must support
+ * the AsyncWriteStream concept.
+ *
+ * @param buffers The dynamic buffer sequence from which data will be written.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called. Successfully written
+ * data is automatically consumed from the buffers.
+ *
+ * @param handler The handler to be called when the write operation completes.
+ * Copies will be made of the handler as required. The function signature of the
+ * handler must be:
+ * @code void handler(
+ *   const asio::error_code& error, // Result of operation.
+ *
+ *   std::size_t bytes_transferred           // Number of bytes written from the
+ *                                           // buffers. If an error occurred,
+ *                                           // this will be less than the sum
+ *                                           // of the buffer sizes.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation of
+ * the handler will be performed in a manner equivalent to using
+ * asio::io_service::post().
+ */
+template <typename AsyncWriteStream,
+    typename DynamicBufferSequence, typename WriteHandler>
+ASIO_INITFN_RESULT_TYPE(WriteHandler,
+    void (asio::error_code, std::size_t))
+async_write(AsyncWriteStream& s,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    ASIO_MOVE_ARG(WriteHandler) handler,
+    typename enable_if<
+      is_dynamic_buffer_sequence<DynamicBufferSequence>::value
+    >::type* = 0);
+
+/// Start an asynchronous operation to write a certain amount of data to a
+/// stream.
+/**
+ * This function is used to asynchronously write a certain number of bytes of
+ * data to a stream. The function call always returns immediately. The
+ * asynchronous operation will continue until one of the following conditions
+ * is true:
+ *
+ * @li All of the data in the supplied dynamic buffer sequence has been written.
+ *
+ * @li The completion_condition function object returns 0.
+ *
+ * This operation is implemented in terms of zero or more calls to the stream's
+ * async_write_some function, and is known as a <em>composed operation</em>. The
+ * program must ensure that the stream performs no other write operations (such
+ * as async_write, the stream's async_write_some function, or any other composed
+ * operations that perform writes) until this operation completes.
+ *
+ * @param s The stream to which the data is to be written. The type must support
+ * the AsyncWriteStream concept.
+ *
+ * @param buffers The dynamic buffer sequence from which data will be written.
+ * Although the buffers object may be copied as necessary, ownership of the
+ * underlying memory blocks is retained by the caller, which must guarantee
+ * that they remain valid until the handler is called. Successfully written
+ * data is automatically consumed from the buffers.
+ *
+ * @param completion_condition The function object to be called to determine
+ * whether the write operation is complete. The signature of the function object
+ * must be:
+ * @code std::size_t completion_condition(
+ *   // Result of latest async_write_some operation.
+ *   const asio::error_code& error,
+ *
+ *   // Number of bytes transferred so far.
+ *   std::size_t bytes_transferred
+ * ); @endcode
+ * A return value of 0 indicates that the write operation is complete. A
+ * non-zero return value indicates the maximum number of bytes to be written on
+ * the next call to the stream's async_write_some function.
+ *
+ * @param handler The handler to be called when the write operation completes.
+ * Copies will be made of the handler as required. The function signature of the
+ * handler must be:
+ * @code void handler(
+ *   const asio::error_code& error, // Result of operation.
+ *
+ *   std::size_t bytes_transferred           // Number of bytes written from the
+ *                                           // buffers. If an error occurred,
+ *                                           // this will be less than the sum
+ *                                           // of the buffer sizes.
+ * ); @endcode
+ * Regardless of whether the asynchronous operation completes immediately or
+ * not, the handler will not be invoked from within this function. Invocation of
+ * the handler will be performed in a manner equivalent to using
+ * asio::io_service::post().
+ */
+template <typename AsyncWriteStream, typename DynamicBufferSequence,
+    typename CompletionCondition, typename WriteHandler>
+ASIO_INITFN_RESULT_TYPE(WriteHandler,
+    void (asio::error_code, std::size_t))
+async_write(AsyncWriteStream& s,
+    ASIO_MOVE_ARG(DynamicBufferSequence) buffers,
+    CompletionCondition completion_condition,
+    ASIO_MOVE_ARG(WriteHandler) handler,
+    typename enable_if<
+      is_dynamic_buffer_sequence<DynamicBufferSequence>::value
+    >::type* = 0);
 
 #if !defined(ASIO_NO_IOSTREAM)
 
diff --git a/asio/src/tests/unit/buffer.cpp b/asio/src/tests/unit/buffer.cpp
index 0ba4317..44d7779 100644
--- a/asio/src/tests/unit/buffer.cpp
+++ b/asio/src/tests/unit/buffer.cpp
@@ -232,6 +232,21 @@
     std::size_t size36 = buffer_copy(
         mutable_buffer_sequence, const_buffer_sequence, 128);
     (void)size36;
+
+    // dynamic_buffer function overloads.
+
+    dynamic_string_buffer<char, std::string::traits_type,
+      std::string::allocator_type> db1 = dynamic_buffer(string_data);
+    (void)db1;
+    dynamic_string_buffer<char, std::string::traits_type,
+      std::string::allocator_type> db2 = dynamic_buffer(string_data, 1024);
+    (void)db2;
+    dynamic_vector_buffer<char, std::allocator<char> >
+      db3 = dynamic_buffer(vector_data);
+    (void)db3;
+    dynamic_vector_buffer<char, std::allocator<char> >
+      db4 = dynamic_buffer(vector_data, 1024);
+    (void)db4;
   }
   catch (std::exception&)
   {