diff --git a/Subtrees/beast/modules/beast_asio/basics/BufferType.h b/Subtrees/beast/modules/beast_asio/basics/BufferType.h index 99b9065b2..27d0678f4 100644 --- a/Subtrees/beast/modules/beast_asio/basics/BufferType.h +++ b/Subtrees/beast/modules/beast_asio/basics/BufferType.h @@ -31,8 +31,9 @@ template class BufferType { public: - typedef Buffer value_type; - typedef typename std::vector ::const_iterator const_iterator; + typedef Buffer value_type; + typedef std::vector container_type; + typedef typename container_type::const_iterator const_iterator; /** Construct a null buffer. This is the equivalent of @ref asio::null_buffers. @@ -42,6 +43,19 @@ public: { } + /** Construct from a container. + Ownership of the container is transferred, the caller's + value becomes undefined, but valid. + */ + explicit BufferType (container_type& container) + : m_size (0) + { + m_buffers.swap (container); + for (typename container_type::const_iterator iter (m_buffers.begin ()); + iter != m_buffers.end (); ++iter) + m_size += boost::asio::buffer_size (*iter); + } + /** Construct a BufferType from an existing BufferSequence. @see assign */ diff --git a/Subtrees/beast/modules/beast_asio/basics/ContentBodyBuffer.cpp b/Subtrees/beast/modules/beast_asio/basics/ContentBodyBuffer.cpp new file mode 100644 index 000000000..006ee5216 --- /dev/null +++ b/Subtrees/beast/modules/beast_asio/basics/ContentBodyBuffer.cpp @@ -0,0 +1,101 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + 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. +*/ +//============================================================================== + +ContentBodyBuffer::ContentBodyBuffer (size_type blocksize) + : m_blocksize (blocksize) + , m_size (0) +{ +} + +ContentBodyBuffer::~ContentBodyBuffer () +{ + for (Handles::iterator iter (m_handles.begin()); + iter != m_handles.end(); ++iter) + { + void* const buffer (*iter); + std::free (buffer); + } +} + +void ContentBodyBuffer::swapWith (ContentBodyBuffer& other) +{ + std::swap (m_blocksize, other.m_blocksize); + std::swap (m_size, other.m_size); + m_handles.swap (other.m_handles); +} + +void ContentBodyBuffer::commit (size_type n) +{ + m_size += n; + bassert (m_size <= m_handles.size () * m_blocksize); +} + +ConstBuffers ContentBodyBuffer::data () const +{ + size_type n (m_size); + std::vector v; + v.reserve ((m_size + m_blocksize - 1) / m_blocksize); + for (Handles::const_iterator iter (m_handles.begin()); + iter != m_handles.end() && n > 0; ++iter) + { + size_type const amount (std::min (n, m_blocksize)); + v.push_back (MutableBuffer (*iter, amount)); + n -= amount; + } + return ConstBuffers (v); +} + +ContentBodyBuffer::size_type ContentBodyBuffer::size () const +{ + return m_size; +} + +MutableBuffers ContentBodyBuffer::prepare (size_type n) +{ + reserve (n); + std::vector v; + size_type offset (m_size % m_blocksize); + for (Handles::iterator iter = m_handles.begin () + (m_size / m_blocksize); + iter != m_handles.end () && n > 0; ++iter) + { + size_type const amount (std::min (n, m_blocksize - offset)); + v.push_back (MutableBuffer (*iter, amount)); + n -= amount; + offset = 0; + } + return MutableBuffers (v); +} + +void ContentBodyBuffer::reserve (size_type n) +{ + size_type count ((m_size + n + m_blocksize - 1) / m_blocksize); + if (count > m_handles.size ()) + for (count -= m_handles.size (); count-- > 0;) + m_handles.push_back (std::malloc (m_blocksize)); +} + +void ContentBodyBuffer::shrink_to_fit () +{ + size_type const count ((m_size + m_blocksize - 1) / m_blocksize); + while (m_handles.size () > count) + { + std::free (m_handles.back ()); + m_handles.erase (m_handles.end () - 1); + } +} \ No newline at end of file diff --git a/Subtrees/beast/modules/beast_asio/basics/ContentBodyBuffer.h b/Subtrees/beast/modules/beast_asio/basics/ContentBodyBuffer.h new file mode 100644 index 000000000..63c51d9d7 --- /dev/null +++ b/Subtrees/beast/modules/beast_asio/basics/ContentBodyBuffer.h @@ -0,0 +1,78 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + 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_BASICS_CONTENTBODYBUFFER_H_INCLUDED +#define BEAST_ASIO_BASICS_CONTENTBODYBUFFER_H_INCLUDED + +/** Dynamic storage optimized for a large Content-Body of unknown size. + This comes at the expense of discontiguous storage of the segments. + We derive from SharedObject to make transfer of ownership inexpensive. +*/ +class ContentBodyBuffer +{ +public: + enum + { + defaultBlocksize = 32 * 1024 + }; + + typedef std::size_t size_type; + typedef ConstBuffers const_buffers_tyoe; + typedef MutableBuffers mutable_buffers_type; + + explicit ContentBodyBuffer (size_type blocksize = defaultBlocksize); + + ~ContentBodyBuffer (); + + /** Swap the contents of this buffer with another. + This is the preferred way to transfer ownership. + */ + void swapWith (ContentBodyBuffer& other); + + /** Move bytes from the output to the input sequence. + This will invalidate references to buffers. + */ + void commit (size_type n); + + /** Returns a buffer to the input sequence. */ + ConstBuffers data () const; + + /** Returns the size of the input sequence. */ + size_type size () const; + + /** Reserve space in the output sequence. + This also returns a buffer suitable for writing. + */ + MutableBuffers prepare (size_type n); + + /** Reserve space in the output sequence. */ + void reserve (size_type n); + + /** Release memory while preserving the input sequence. */ + void shrink_to_fit (); + +private: + typedef std::vector Handles; + + size_type m_blocksize; + size_type m_size; + Handles m_handles; +}; + +#endif