1//
2// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
3//
4// Distributed under the Boost Software License, Version 1.0. (See accompanying
5// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6//
7// Official repository: https://github.com/boostorg/beast
8//
9
10#ifndef BOOST_BEAST_HTTP_DETAIL_CHUNK_ENCODE_HPP
11#define BOOST_BEAST_HTTP_DETAIL_CHUNK_ENCODE_HPP
12
13#include <boost/beast/http/type_traits.hpp>
14#include <boost/asio/buffer.hpp>
15#include <algorithm>
16#include <array>
17#include <cstddef>
18#include <memory>
19
20namespace boost {
21namespace beast {
22namespace http {
23namespace detail {
24
25struct chunk_extensions
26{
27 virtual ~chunk_extensions() = default;
28 virtual net::const_buffer str() = 0;
29};
30
31template<class ChunkExtensions>
32struct chunk_extensions_impl : chunk_extensions
33{
34 ChunkExtensions ext_;
35
36 chunk_extensions_impl(ChunkExtensions&& ext) noexcept
37 : ext_(std::move(ext))
38 {
39 }
40
41 chunk_extensions_impl(ChunkExtensions const& ext)
42 : ext_(ext)
43 {
44 }
45
46 net::const_buffer
47 str() override
48 {
49 auto const s = ext_.str();
50 return {s.data(), s.size()};
51 }
52};
53
54template<class T, class = void>
55struct is_chunk_extensions : std::false_type {};
56
57template<class T>
58struct is_chunk_extensions<T, beast::detail::void_t<decltype(
59 std::declval<string_view&>() = std::declval<T&>().str()
60 )>> : std::true_type
61{
62};
63
64//------------------------------------------------------------------------------
65
66/** A buffer sequence containing a chunk-encoding header
67*/
68class chunk_size
69{
70 template<class OutIter>
71 static
72 OutIter
73 to_hex(OutIter last, std::size_t n)
74 {
75 if(n == 0)
76 {
77 *--last = '0';
78 return last;
79 }
80 while(n)
81 {
82 *--last = "0123456789abcdef"[n&0xf];
83 n>>=4;
84 }
85 return last;
86 }
87
88 struct sequence
89 {
90 net::const_buffer b;
91 char data[1 + 2 * sizeof(std::size_t)];
92
93 explicit
94 sequence(std::size_t n)
95 {
96 char* it0 = data + sizeof(data);
97 auto it = to_hex(last: it0, n);
98 b = {it,
99 static_cast<std::size_t>(it0 - it)};
100 }
101 };
102
103 std::shared_ptr<sequence> sp_;
104
105public:
106 using value_type = net::const_buffer;
107
108 using const_iterator = value_type const*;
109
110 chunk_size(chunk_size const& other) = default;
111
112 /** Construct a chunk header
113
114 @param n The number of octets in this chunk.
115 */
116 chunk_size(std::size_t n)
117 : sp_(std::make_shared<sequence>(args&: n))
118 {
119 }
120
121 const_iterator
122 begin() const
123 {
124 return &sp_->b;
125 }
126
127 const_iterator
128 end() const
129 {
130 return begin() + 1;
131 }
132};
133
134//------------------------------------------------------------------------------
135
136/// Returns a buffer sequence holding a CRLF for chunk encoding
137inline
138net::const_buffer const&
139chunk_crlf()
140{
141 static net::const_buffer const cb{"\r\n", 2};
142 return cb;
143}
144
145/// Returns a buffer sequence holding a final chunk header
146inline
147net::const_buffer const&
148chunk_last()
149{
150 static net::const_buffer const cb{"0\r\n", 3};
151 return cb;
152}
153
154//------------------------------------------------------------------------------
155
156#if 0
157template<class = void>
158struct chunk_crlf_iter_type
159{
160 class value_type
161 {
162 char const s[2] = {'\r', '\n'};
163
164 public:
165 value_type() = default;
166
167 operator
168 net::const_buffer() const
169 {
170 return {s, sizeof(s)};
171 }
172 };
173 static value_type value;
174};
175
176template<class T>
177typename chunk_crlf_iter_type<T>::value_type
178chunk_crlf_iter_type<T>::value;
179
180using chunk_crlf_iter = chunk_crlf_iter_type<void>;
181#endif
182
183//------------------------------------------------------------------------------
184
185struct chunk_size0
186{
187 using value_type = net::const_buffer;
188 using const_iterator = value_type const*;
189
190 const_iterator
191 begin() const
192 {
193 return &chunk_last();
194 }
195
196 const_iterator
197 end() const
198 {
199 return begin() + 1;
200 }
201};
202
203//------------------------------------------------------------------------------
204
205template<class T,
206 bool = is_fields<T>::value>
207struct buffers_or_fields
208{
209 using type = typename
210 T::writer::const_buffers_type;
211};
212
213template<class T>
214struct buffers_or_fields<T, false>
215{
216 using type = T;
217};
218
219} // detail
220} // http
221} // beast
222} // boost
223
224#endif
225

source code of boost/libs/beast/include/boost/beast/http/detail/chunk_encode.hpp