Line data Source code
1 : // 2 : // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.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/cppalliance/http_proto 8 : // 9 : 10 : #ifndef BOOST_HTTP_PROTO_IMPL_SERIALIZER_HPP 11 : #define BOOST_HTTP_PROTO_IMPL_SERIALIZER_HPP 12 : 13 : #include <boost/http_proto/detail/except.hpp> 14 : #include <boost/buffers/range.hpp> 15 : 16 : namespace boost { 17 : namespace http_proto { 18 : 19 : class serializer:: 20 : const_buffers_type 21 : { 22 : std::size_t n_ = 0; 23 : buffers::const_buffer const* p_ = nullptr; 24 : 25 : friend class serializer; 26 : 27 30 : const_buffers_type( 28 : buffers::const_buffer const* p, 29 : std::size_t n) noexcept 30 30 : : n_(n) 31 30 : , p_(p) 32 : { 33 30 : } 34 : 35 : public: 36 : using iterator = buffers::const_buffer const*; 37 : using const_iterator = iterator; 38 : using value_type = buffers::const_buffer; 39 : using reference = buffers::const_buffer; 40 : using const_reference = buffers::const_buffer; 41 : using size_type = std::size_t; 42 : using difference_type = std::ptrdiff_t; 43 : 44 : const_buffers_type() = default; 45 : const_buffers_type( 46 : const_buffers_type const&) = default; 47 : const_buffers_type& operator=( 48 : const_buffers_type const&) = default; 49 : 50 : iterator 51 59 : begin() const noexcept 52 : { 53 59 : return p_; 54 : } 55 : 56 : iterator 57 59 : end() const noexcept 58 : { 59 59 : return p_ + n_; 60 : } 61 : }; 62 : 63 : //------------------------------------------------ 64 : 65 : template< 66 : class ConstBufferSequence, 67 : class> 68 : void 69 7 : serializer:: 70 : start( 71 : message_view_base const& m, 72 : ConstBufferSequence&& body) 73 : { 74 7 : start_init(m); 75 7 : auto const& bs = 76 : ws_.push(std::forward< 77 : ConstBufferSequence>(body)); 78 7 : std::size_t n = std::distance( 79 : buffers::begin(bs), 80 : buffers::end(bs)); 81 7 : buf_ = make_array(n); 82 7 : auto p = buf_.data(); 83 14 : for(buffers::const_buffer b : 84 7 : buffers::range(bs)) 85 7 : *p++ = b; 86 7 : start_buffers(m); 87 7 : } 88 : 89 : template< 90 : class Source, 91 : class> 92 : auto 93 8 : serializer:: 94 : start( 95 : message_view_base const& m, 96 : Source&& src0) -> 97 : typename std::decay< 98 : Source>::type& 99 : { 100 8 : start_init(m); 101 8 : auto& src = ws_.push( 102 : std::forward< 103 : Source>(src0)); 104 8 : start_source( 105 8 : m, std::addressof(src)); 106 8 : return src; 107 : } 108 : 109 : //------------------------------------------------ 110 : 111 : inline 112 : auto 113 26 : serializer:: 114 : make_array(std::size_t n) -> 115 : detail::array_of_const_buffers 116 : { 117 : return { 118 : ws_.push_array(n, 119 52 : buffers::const_buffer{}), 120 26 : n }; 121 : } 122 : 123 : //------------------------------------------------ 124 : 125 : template<class T> 126 : auto 127 17 : serializer:: 128 : source:: 129 : read_impl( 130 : T const& bs) -> 131 : results 132 : { 133 17 : results rv; 134 17 : constexpr int SmallArraySize = 16; 135 17 : buffers::mutable_buffer tmp[SmallArraySize]; 136 17 : auto const tmp_end = 137 : tmp + SmallArraySize; 138 17 : auto it = buffers::begin(bs); 139 17 : auto const end_ = buffers::end(bs); 140 28 : while(it != end_) 141 : { 142 17 : auto p = tmp; 143 17 : do 144 : { 145 34 : *p++ = *it++; 146 : } 147 : while( 148 34 : p != tmp_end && 149 : it != end_); 150 17 : rv += on_read( 151 : buffers::mutable_buffer_span( 152 17 : tmp, p - tmp)); 153 17 : if(rv.ec.failed()) 154 0 : return rv; 155 17 : if(rv.finished) 156 6 : break; 157 : } 158 17 : return rv; 159 : } 160 : 161 : } // http_proto 162 : } // boost 163 : 164 : #endif