// // Copyright (c) 2016-2019 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) // // Official repository: https://github.com/boostorg/beast // #ifndef BOOST_BEAST_HTTP_DETAIL_CHUNK_ENCODE_HPP #define BOOST_BEAST_HTTP_DETAIL_CHUNK_ENCODE_HPP #include #include #include #include #include #include namespace boost { namespace beast { namespace http { namespace detail { struct chunk_extensions { virtual ~chunk_extensions() = default; virtual net::const_buffer str() = 0; }; template struct chunk_extensions_impl : chunk_extensions { ChunkExtensions ext_; chunk_extensions_impl(ChunkExtensions&& ext) noexcept : ext_(std::move(ext)) { } chunk_extensions_impl(ChunkExtensions const& ext) : ext_(ext) { } net::const_buffer str() override { auto const s = ext_.str(); return {s.data(), s.size()}; } }; template struct is_chunk_extensions : std::false_type {}; template struct is_chunk_extensions() = std::declval().str() )>> : std::true_type { }; //------------------------------------------------------------------------------ /** A buffer sequence containing a chunk-encoding header */ class chunk_size { template 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; } struct sequence { net::const_buffer b; char data[1 + 2 * sizeof(std::size_t)]; explicit sequence(std::size_t n) { char* it0 = data + sizeof(data); auto it = to_hex(it0, n); b = {it, static_cast(it0 - it)}; } }; std::shared_ptr sp_; public: using value_type = net::const_buffer; using const_iterator = value_type const*; chunk_size(chunk_size const& other) = default; /** Construct a chunk header @param n The number of octets in this chunk. */ chunk_size(std::size_t n) : sp_(std::make_shared(n)) { } const_iterator begin() const { return &sp_->b; } const_iterator end() const { return begin() + 1; } }; //------------------------------------------------------------------------------ /// Returns a buffer sequence holding a CRLF for chunk encoding inline net::const_buffer const& chunk_crlf() { static net::const_buffer const cb{"\r\n", 2}; return cb; } /// Returns a buffer sequence holding a final chunk header inline net::const_buffer const& chunk_last() { static net::const_buffer const cb{"0\r\n", 3}; return cb; } //------------------------------------------------------------------------------ #if 0 template struct chunk_crlf_iter_type { class value_type { char const s[2] = {'\r', '\n'}; public: value_type() = default; operator net::const_buffer() const { return {s, sizeof(s)}; } }; static value_type value; }; template typename chunk_crlf_iter_type::value_type chunk_crlf_iter_type::value; using chunk_crlf_iter = chunk_crlf_iter_type; #endif //------------------------------------------------------------------------------ struct chunk_size0 { using value_type = net::const_buffer; using const_iterator = value_type const*; const_iterator begin() const { return &chunk_last(); } const_iterator end() const { return begin() + 1; } }; //------------------------------------------------------------------------------ template::value> struct buffers_or_fields { using type = typename T::writer::const_buffers_type; }; template struct buffers_or_fields { using type = T; }; } // detail } // http } // beast } // boost #endif