Files
boost_beast/include/beast/http/detail/chunk_encode.hpp
T

133 lines
3.0 KiB
C++
Raw Normal View History

2016-04-19 20:29:16 -04:00
//
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
2014-11-12 16:15:33 -08:00
#ifndef BEAST_HTTP_DETAIL_CHUNK_ENCODE_HPP
#define BEAST_HTTP_DETAIL_CHUNK_ENCODE_HPP
2014-11-12 16:15:33 -08:00
2016-05-07 17:06:46 -04:00
#include <beast/core/buffer_cat.hpp>
2014-11-12 16:15:33 -08:00
#include <boost/asio/buffer.hpp>
2016-09-25 12:17:32 -04:00
#include <boost/assert.hpp>
2016-05-07 17:06:46 -04:00
#include <boost/logic/tribool.hpp>
2014-11-12 16:15:33 -08:00
#include <algorithm>
#include <array>
#include <cstddef>
#include <iterator>
2015-10-07 20:46:52 -07:00
#include <type_traits>
2014-11-12 16:15:33 -08:00
namespace beast {
namespace http {
namespace detail {
2016-05-07 17:06:46 -04:00
class chunk_encode_text
2014-11-12 16:15:33 -08:00
{
2016-05-07 17:06:46 -04:00
boost::asio::const_buffer cb_;
2014-11-12 16:15:33 -08:00
// Storage for the longest hex string we might need, plus delimiters.
2016-05-07 17:06:46 -04:00
std::array<char, 2 * sizeof(std::size_t) + 2> buf_;
2016-08-26 08:01:44 -04:00
template<class OutIter>
2016-05-07 17:06:46 -04:00
static
OutIter
to_hex(OutIter last, std::size_t n)
{
if(n == 0)
{
*--last = '0';
return last;
}
while(n)
{
*--last = "0123456789abcdef"[n&0xf];
n>>=4;
}
return last;
}
2014-11-12 16:15:33 -08:00
public:
using value_type = boost::asio::const_buffer;
2016-05-07 17:06:46 -04:00
using const_iterator = value_type const*;
2014-11-12 16:15:33 -08:00
2016-05-07 17:06:46 -04:00
chunk_encode_text(chunk_encode_text const& other)
{
auto const n =
boost::asio::buffer_size(other.cb_);
buf_ = other.buf_;
cb_ = boost::asio::const_buffer(
&buf_[buf_.size() - n], n);
}
2014-11-12 16:15:33 -08:00
2016-05-07 17:06:46 -04:00
explicit
chunk_encode_text(std::size_t n)
{
buf_[buf_.size() - 2] = '\r';
buf_[buf_.size() - 1] = '\n';
auto it = to_hex(buf_.end() - 2, n);
cb_ = boost::asio::const_buffer{&*it,
static_cast<std::size_t>(
std::distance(it, buf_.end()))};
}
2014-11-12 16:15:33 -08:00
const_iterator
begin() const
{
2016-05-07 17:06:46 -04:00
return &cb_;
2014-11-12 16:15:33 -08:00
}
const_iterator
end() const
{
2016-05-07 17:06:46 -04:00
return begin() + 1;
2014-11-12 16:15:33 -08:00
}
};
2016-05-07 17:06:46 -04:00
/** Returns a chunk-encoded ConstBufferSequence.
2014-11-12 16:15:33 -08:00
2016-05-07 17:06:46 -04:00
This returns a buffer sequence representing the
first chunk of a chunked transfer coded body.
2014-11-12 16:15:33 -08:00
@param buffers The input buffer sequence.
2016-03-11 06:40:37 -05:00
@return A chunk-encoded ConstBufferSequence representing the input.
2016-05-07 17:06:46 -04:00
@see <a href=https://tools.ietf.org/html/rfc7230#section-4.1.3>rfc7230 section 4.1.3</a>
2014-11-12 16:15:33 -08:00
*/
2016-03-11 06:40:37 -05:00
template<class ConstBufferSequence>
#if GENERATING_DOCS
implementation_defined
#else
2016-05-07 17:06:46 -04:00
beast::detail::buffer_cat_helper<boost::asio::const_buffer,
chunk_encode_text, ConstBufferSequence, boost::asio::const_buffers_1>
2016-03-11 06:40:37 -05:00
#endif
2016-05-07 17:06:46 -04:00
chunk_encode(ConstBufferSequence const& buffers)
2014-11-12 16:15:33 -08:00
{
2016-05-07 17:06:46 -04:00
using boost::asio::buffer_size;
return buffer_cat(
chunk_encode_text{buffer_size(buffers)},
buffers,
boost::asio::const_buffers_1{"\r\n", 2});
2014-11-12 16:15:33 -08:00
}
2016-03-11 06:40:37 -05:00
/// Returns a chunked encoding final chunk.
2014-11-12 16:15:33 -08:00
inline
2016-03-11 06:40:37 -05:00
#if GENERATING_DOCS
implementation_defined
#else
2014-11-12 16:15:33 -08:00
boost::asio::const_buffers_1
2016-03-11 06:40:37 -05:00
#endif
2014-11-12 16:15:33 -08:00
chunk_encode_final()
{
return boost::asio::const_buffers_1(
"0\r\n\r\n", 5);
}
} // detail
2014-11-12 16:15:33 -08:00
} // http
} // beast
#endif