File indexing completed on 2025-01-18 09:29:28
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_BEAST_HTTP_DETAIL_CHUNK_ENCODE_HPP
0011 #define BOOST_BEAST_HTTP_DETAIL_CHUNK_ENCODE_HPP
0012
0013 #include <boost/beast/http/type_traits.hpp>
0014 #include <boost/asio/buffer.hpp>
0015 #include <algorithm>
0016 #include <array>
0017 #include <cstddef>
0018 #include <memory>
0019
0020 namespace boost {
0021 namespace beast {
0022 namespace http {
0023 namespace detail {
0024
0025 struct chunk_extensions
0026 {
0027 virtual ~chunk_extensions() = default;
0028 virtual net::const_buffer str() = 0;
0029 };
0030
0031 template<class ChunkExtensions>
0032 struct chunk_extensions_impl : chunk_extensions
0033 {
0034 ChunkExtensions ext_;
0035
0036 chunk_extensions_impl(ChunkExtensions&& ext) noexcept
0037 : ext_(std::move(ext))
0038 {
0039 }
0040
0041 chunk_extensions_impl(ChunkExtensions const& ext)
0042 : ext_(ext)
0043 {
0044 }
0045
0046 net::const_buffer
0047 str() override
0048 {
0049 auto const s = ext_.str();
0050 return {s.data(), s.size()};
0051 }
0052 };
0053
0054 template<class T, class = void>
0055 struct is_chunk_extensions : std::false_type {};
0056
0057 template<class T>
0058 struct is_chunk_extensions<T, beast::detail::void_t<decltype(
0059 std::declval<string_view&>() = std::declval<T&>().str()
0060 )>> : std::true_type
0061 {
0062 };
0063
0064
0065
0066
0067
0068 class chunk_size
0069 {
0070 template<class OutIter>
0071 static
0072 OutIter
0073 to_hex(OutIter last, std::size_t n)
0074 {
0075 if(n == 0)
0076 {
0077 *--last = '0';
0078 return last;
0079 }
0080 while(n)
0081 {
0082 *--last = "0123456789abcdef"[n&0xf];
0083 n>>=4;
0084 }
0085 return last;
0086 }
0087
0088 struct sequence
0089 {
0090 net::const_buffer b;
0091 char data[1 + 2 * sizeof(std::size_t)];
0092
0093 explicit
0094 sequence(std::size_t n)
0095 {
0096 char* it0 = data + sizeof(data);
0097 auto it = to_hex(it0, n);
0098 b = {it,
0099 static_cast<std::size_t>(it0 - it)};
0100 }
0101 };
0102
0103 std::shared_ptr<sequence> sp_;
0104
0105 public:
0106 using value_type = net::const_buffer;
0107
0108 using const_iterator = value_type const*;
0109
0110 chunk_size(chunk_size const& other) = default;
0111
0112
0113
0114
0115
0116 chunk_size(std::size_t n)
0117 : sp_(std::make_shared<sequence>(n))
0118 {
0119 }
0120
0121 const_iterator
0122 begin() const
0123 {
0124 return &sp_->b;
0125 }
0126
0127 const_iterator
0128 end() const
0129 {
0130 return begin() + 1;
0131 }
0132 };
0133
0134
0135
0136
0137 inline
0138 net::const_buffer const&
0139 chunk_crlf()
0140 {
0141 static net::const_buffer const cb{"\r\n", 2};
0142 return cb;
0143 }
0144
0145
0146 inline
0147 net::const_buffer const&
0148 chunk_last()
0149 {
0150 static net::const_buffer const cb{"0\r\n", 3};
0151 return cb;
0152 }
0153
0154
0155
0156 #if 0
0157 template<class = void>
0158 struct chunk_crlf_iter_type
0159 {
0160 class value_type
0161 {
0162 char const s[2] = {'\r', '\n'};
0163
0164 public:
0165 value_type() = default;
0166
0167 operator
0168 net::const_buffer() const
0169 {
0170 return {s, sizeof(s)};
0171 }
0172 };
0173 static value_type value;
0174 };
0175
0176 template<class T>
0177 typename chunk_crlf_iter_type<T>::value_type
0178 chunk_crlf_iter_type<T>::value;
0179
0180 using chunk_crlf_iter = chunk_crlf_iter_type<void>;
0181 #endif
0182
0183
0184
0185 struct chunk_size0
0186 {
0187 using value_type = net::const_buffer;
0188 using const_iterator = value_type const*;
0189
0190 const_iterator
0191 begin() const
0192 {
0193 return &chunk_last();
0194 }
0195
0196 const_iterator
0197 end() const
0198 {
0199 return begin() + 1;
0200 }
0201 };
0202
0203
0204
0205 template<class T,
0206 bool = is_fields<T>::value>
0207 struct buffers_or_fields
0208 {
0209 using type = typename
0210 T::writer::const_buffers_type;
0211 };
0212
0213 template<class T>
0214 struct buffers_or_fields<T, false>
0215 {
0216 using type = T;
0217 };
0218
0219 }
0220 }
0221 }
0222 }
0223
0224 #endif