Files
rippled/beast/asio/basic_streambuf.h
Vinnie Falco 3461bafaa2 Beast.Asio:
New classes:

  class async_completion:
    Helper class for implementing asynchronous initiation functions.
    See n3964:
        Library Foundations for Asynchronous Operations, Revision 1
        http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3964.pdf

  class basic_streambuf:
    Meets the requirements of Streambuf.

  class buffered_readstream:
    Buffers a ReadStream with a ConstBufferSequence.

  class consuming_buffers:
    Adapts a BufferSequence which wraps the underlying buffer
    sequence and presents fewer bytes, with the retained bytes
    occurring at the end of the sequence.

  class handler_alloc:
    A C++ Allocator the uses asio handler allocation hooks.

  class static_streambuf:
    An implementation of the Streambuf concept that uses a
    fixed size buffer with size determined at compile-time.

  class streambuf_readstream:
    Buffers a ReadStream with a Streambuf.

New functions:

  append_buffers()
    Returns a new BufferSequence which efficiently concatenates
    two or more buffer sequences together.

  prepare_buffers()
    Shortens a buffer sequence. The bytes excluded are at the
    end of the underlying buffer sequence.

  boost::asio::read_until()
    A copy of boost::asio::read_until overloads, modified to work
    with a beast::asio::basic_streambuf.

Debugging:

  buffers_to_string()

    Convert a ConstBufferSequence to a human readable string
    suitable for diagnostics.

type_check.h:

  Metafunctions for checking asio concepts:
    AsyncReadStream, AsyncWriteStream
    SyncReadStream, SyncWriteStream
    ConstBufferSequence, MutableBufferSequence
    Streambuf
    Handler

Changes:

* All symbols moved up a namespace level.
* streambuf provides all move and copy special members,
  behavior of moved from objects is well-defined.

Fixes:

* Fix basic_streambuf iterator category.
2016-04-20 05:16:38 -04:00

351 lines
9.6 KiB
C++

//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_ASIO_BASIC_STREAMBUF_H_INCLUDED
#define BEAST_ASIO_BASIC_STREAMBUF_H_INCLUDED
#include <beast/empty_base_optimization.h>
#include <boost/asio/buffer.hpp>
#include <boost/intrusive/list.hpp>
#include <iterator>
#include <limits>
#include <memory>
#include <type_traits>
namespace beast {
/** A `Streambuf` that uses multiple buffers internally.
The implementation uses a sequence of one or more character arrays
of varying sizes. Additional character array objects are appended to
the sequence to accommodate changes in the size of the character
sequence.
@tparam Allocator The allocator to use for managing memory.
*/
template<class Allocator>
class basic_streambuf
#if ! GENERATING_DOCS
: private empty_base_optimization<
typename std::allocator_traits<Allocator>::
template rebind_alloc<std::uint8_t>>
#endif
{
public:
using allocator_type = typename
std::allocator_traits<Allocator>::
template rebind_alloc<std::uint8_t>;
private:
class element;
using alloc_traits = std::allocator_traits<allocator_type>;
using list_type = typename boost::intrusive::make_list<element,
boost::intrusive::constant_time_size<true>>::type;
using iterator = typename list_type::iterator;
using const_iterator = typename list_type::const_iterator;
using size_type = typename std::allocator_traits<Allocator>::size_type;
using const_buffer = boost::asio::const_buffer;
using mutable_buffer = boost::asio::mutable_buffer;
static_assert(std::is_base_of<std::bidirectional_iterator_tag,
typename std::iterator_traits<iterator>::iterator_category>::value,
"BidirectionalIterator requirements not met");
static_assert(std::is_base_of<std::bidirectional_iterator_tag,
typename std::iterator_traits<const_iterator>::iterator_category>::value,
"BidirectionalIterator requirements not met");
list_type list_; // list of allocated buffers
iterator out_; // element that contains out_pos_
size_type alloc_size_; // min amount to allocate
size_type in_size_ = 0; // size of the input sequence
size_type in_pos_ = 0; // input offset in list_.front()
size_type out_pos_ = 0; // output offset in *out_
size_type out_end_ = 0; // output end offset in list_.back()
public:
class const_buffers_type;
class mutable_buffers_type;
/// Destructor.
~basic_streambuf();
/** Move constructor.
The output sequence of this object will be empty.
After the move, the moved-from object will have an
empty input and output sequence, with no internal
buffers allocated.
@param other The stream buffer to move from.
*/
basic_streambuf(basic_streambuf&& other);
/** Move constructor.
The output sequence of this object will be empty.
After the move, the moved-from object will have an
empty input and output sequence, with no internal
buffers allocated.
@param other The stream buffer to move from.
@param alloc The allocator to associate with the
stream buffer.
*/
basic_streambuf(basic_streambuf&& other,
allocator_type const& alloc);
/** Move assignment.
The output sequence of this object will be empty.
After the move, the moved-from object will have an
empty input and output sequence, with no internal
buffers allocated.
@param other The stream buffer to move from.
*/
basic_streambuf&
operator=(basic_streambuf&& other);
/// Copy constructor.
basic_streambuf(basic_streambuf const& other);
/** Copy constructor.
The output sequence of this object will be empty.
@param other The stream buffer to copy.
@param alloc The allocator to associate with the
stream buffer.
*/
basic_streambuf(basic_streambuf const& other,
allocator_type const& alloc);
/** Copy assignment.
The output sequence of this object will be empty.
@param other The stream buffer to copy.
*/
basic_streambuf& operator=(basic_streambuf const& other);
/** Copy constructor.
The output sequence of this object will be empty.
@param other The stream buffer to copy.
*/
template<class OtherAlloc>
basic_streambuf(basic_streambuf<OtherAlloc> const& other);
/** Copy constructor.
The output sequence of this object will be empty.
@param other The stream buffer to copy.
@param alloc The allocator to associate with the
stream buffer.
*/
template<class OtherAlloc>
basic_streambuf(basic_streambuf<OtherAlloc> const& other,
allocator_type const& alloc);
/** Copy assignment.
The output sequence of this object will be empty.
@param other The stream buffer to copy.
*/
template<class OtherAlloc>
basic_streambuf& operator=(basic_streambuf<OtherAlloc> const& other);
/** Construct a stream buffer.
@param alloc_size The size of buffer to allocate. This is a soft
limit, calls to prepare for buffers exceeding this size will allocate
the larger size.
@param alloc The allocator to use.
*/
explicit
basic_streambuf(std::size_t alloc_size = 1024,
Allocator const& alloc = allocator_type{});
/// Get the associated allocator
allocator_type
get_allocator() const
{
return this->member();
}
/// Get the maximum size of the basic_streambuf.
size_type
max_size() const
{
return std::numeric_limits<std::size_t>::max();
}
/// Get the size of the input sequence.
size_type
size() const
{
return in_size_;
}
/// Get a list of buffers that represents the output sequence, with the given size.
mutable_buffers_type
prepare(size_type n);
/// Move bytes from the output sequence to the input sequence.
void
commit(size_type n);
/// Get a list of buffers that represents the input sequence.
const_buffers_type
data() const;
/// Remove bytes from the input sequence.
void
consume(size_type n);
/// Clear everything.
void
clear();
// Helper for read_until
template<class OtherAllocator>
friend
std::size_t
read_size_helper(basic_streambuf<
OtherAllocator> const& streambuf, std::size_t max_size);
private:
void
move_assign(basic_streambuf& other, std::false_type);
void
move_assign(basic_streambuf& other, std::true_type);
void
copy_assign(basic_streambuf const& other, std::false_type);
void
copy_assign(basic_streambuf const& other, std::true_type);
void
delete_list();
std::size_t
prepare_size() const;
void
debug_check() const;
};
/// The type used to represent the input sequence as a list of buffers.
template<class Allocator>
class basic_streambuf<Allocator>::const_buffers_type
{
basic_streambuf const* sb_ = nullptr;
friend class basic_streambuf;
explicit
const_buffers_type(basic_streambuf const& sb);
public:
using value_type = boost::asio::const_buffer;
class const_iterator;
const_buffers_type() = default;
const_buffers_type(const_buffers_type const&) = default;
const_buffers_type& operator=(const_buffers_type const&) = default;
const_iterator
begin() const;
const_iterator
end() const;
};
/// The type used to represent the output sequence as a list of buffers.
template<class Allocator>
class basic_streambuf<Allocator>::mutable_buffers_type
{
basic_streambuf const* sb_;
friend class basic_streambuf;
explicit
mutable_buffers_type(basic_streambuf const& sb);
public:
using value_type = mutable_buffer;
class const_iterator;
mutable_buffers_type() = default;
mutable_buffers_type(mutable_buffers_type const&) = default;
mutable_buffers_type& operator=(mutable_buffers_type const&) = default;
const_iterator
begin() const;
const_iterator
end() const;
};
/** Format output to a stream buffer.
@param streambuf The streambuf to write to.
@param t The object to write.
@return The stream buffer.
*/
template<class Alloc, class T>
basic_streambuf<Alloc>&
operator<<(basic_streambuf<Alloc>& buf, T const& t);
/** Convert the entire basic_streambuf to a string.
@param streambuf The streambuf to convert.
@return A string representing the contents of the input sequence.
*/
template<class Allocator>
std::string
to_string(basic_streambuf<Allocator> const& streambuf);
} // beast
#include <beast/asio/impl/basic_streambuf.ipp>
#endif