chunk_encode.hpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  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. #ifndef BOOST_BEAST_HTTP_DETAIL_CHUNK_ENCODE_HPP
  10. #define BOOST_BEAST_HTTP_DETAIL_CHUNK_ENCODE_HPP
  11. #include <boost/beast/http/type_traits.hpp>
  12. #include <boost/asio/buffer.hpp>
  13. #include <algorithm>
  14. #include <array>
  15. #include <cstddef>
  16. #include <memory>
  17. namespace boost {
  18. namespace beast {
  19. namespace http {
  20. namespace detail {
  21. struct chunk_extensions
  22. {
  23. virtual ~chunk_extensions() = default;
  24. virtual net::const_buffer str() = 0;
  25. };
  26. template<class ChunkExtensions>
  27. struct chunk_extensions_impl : chunk_extensions
  28. {
  29. ChunkExtensions ext_;
  30. chunk_extensions_impl(ChunkExtensions&& ext) noexcept
  31. : ext_(std::move(ext))
  32. {
  33. }
  34. chunk_extensions_impl(ChunkExtensions const& ext)
  35. : ext_(ext)
  36. {
  37. }
  38. net::const_buffer
  39. str() override
  40. {
  41. auto const s = ext_.str();
  42. return {s.data(), s.size()};
  43. }
  44. };
  45. template<class T, class = void>
  46. struct is_chunk_extensions : std::false_type {};
  47. template<class T>
  48. struct is_chunk_extensions<T, beast::detail::void_t<decltype(
  49. std::declval<string_view&>() = std::declval<T&>().str()
  50. )>> : std::true_type
  51. {
  52. };
  53. //------------------------------------------------------------------------------
  54. /** A buffer sequence containing a chunk-encoding header
  55. */
  56. class chunk_size
  57. {
  58. template<class OutIter>
  59. static
  60. OutIter
  61. to_hex(OutIter last, std::size_t n)
  62. {
  63. if(n == 0)
  64. {
  65. *--last = '0';
  66. return last;
  67. }
  68. while(n)
  69. {
  70. *--last = "0123456789abcdef"[n&0xf];
  71. n>>=4;
  72. }
  73. return last;
  74. }
  75. struct sequence
  76. {
  77. net::const_buffer b;
  78. char data[1 + 2 * sizeof(std::size_t)];
  79. explicit
  80. sequence(std::size_t n)
  81. {
  82. char* it0 = data + sizeof(data);
  83. auto it = to_hex(it0, n);
  84. b = {it,
  85. static_cast<std::size_t>(it0 - it)};
  86. }
  87. };
  88. std::shared_ptr<sequence> sp_;
  89. public:
  90. using value_type = net::const_buffer;
  91. using const_iterator = value_type const*;
  92. chunk_size(chunk_size const& other) = default;
  93. /** Construct a chunk header
  94. @param n The number of octets in this chunk.
  95. */
  96. chunk_size(std::size_t n)
  97. : sp_(std::make_shared<sequence>(n))
  98. {
  99. }
  100. const_iterator
  101. begin() const
  102. {
  103. return &sp_->b;
  104. }
  105. const_iterator
  106. end() const
  107. {
  108. return begin() + 1;
  109. }
  110. };
  111. //------------------------------------------------------------------------------
  112. /// Returns a buffer sequence holding a CRLF for chunk encoding
  113. inline
  114. net::const_buffer const&
  115. chunk_crlf()
  116. {
  117. static net::const_buffer const cb{"\r\n", 2};
  118. return cb;
  119. }
  120. /// Returns a buffer sequence holding a final chunk header
  121. inline
  122. net::const_buffer const&
  123. chunk_last()
  124. {
  125. static net::const_buffer const cb{"0\r\n", 3};
  126. return cb;
  127. }
  128. //------------------------------------------------------------------------------
  129. #if 0
  130. template<class = void>
  131. struct chunk_crlf_iter_type
  132. {
  133. class value_type
  134. {
  135. char const s[2] = {'\r', '\n'};
  136. public:
  137. value_type() = default;
  138. operator
  139. net::const_buffer() const
  140. {
  141. return {s, sizeof(s)};
  142. }
  143. };
  144. static value_type value;
  145. };
  146. template<class T>
  147. typename chunk_crlf_iter_type<T>::value_type
  148. chunk_crlf_iter_type<T>::value;
  149. using chunk_crlf_iter = chunk_crlf_iter_type<void>;
  150. #endif
  151. //------------------------------------------------------------------------------
  152. struct chunk_size0
  153. {
  154. using value_type = net::const_buffer;
  155. using const_iterator = value_type const*;
  156. const_iterator
  157. begin() const
  158. {
  159. return &chunk_last();
  160. }
  161. const_iterator
  162. end() const
  163. {
  164. return begin() + 1;
  165. }
  166. };
  167. //------------------------------------------------------------------------------
  168. template<class T,
  169. bool = is_fields<T>::value>
  170. struct buffers_or_fields
  171. {
  172. using type = typename
  173. T::writer::const_buffers_type;
  174. };
  175. template<class T>
  176. struct buffers_or_fields<T, false>
  177. {
  178. using type = T;
  179. };
  180. } // detail
  181. } // http
  182. } // beast
  183. } // boost
  184. #endif