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_IPP 11 : #define BOOST_HTTP_PROTO_IMPL_SERIALIZER_IPP 12 : 13 : #include <boost/http_proto/serializer.hpp> 14 : #include <boost/http_proto/detail/except.hpp> 15 : #include <stddef.h> 16 : 17 : namespace boost { 18 : namespace http_proto { 19 : 20 : //------------------------------------------------ 21 : /* 22 : 23 : write algorithm: 24 : 25 : get buffers from serializer 26 : - can fail with ec 27 : - can perform blocking I/O 28 : 29 : write buffers to socket 30 : - consume the written amount 31 : 32 : serializer supply algorithm 33 : - supply a const buffer sequence for everything 34 : serializer sr; 35 : sr.set_body( cb ); 36 : - supply a const buffer sequence iteratively 37 : serializer sr; 38 : sr.set_body_some( cb ); 39 : - write into serializer-provided buffers iteratively 40 : sr.set_body( source( ... ) ); 41 : */ 42 : //------------------------------------------------ 43 : 44 0 : serializer:: 45 0 : ~serializer() 46 : { 47 0 : } 48 : 49 0 : serializer:: 50 : serializer( 51 0 : std::size_t buffer_size) 52 0 : : ws_(buffer_size) 53 : { 54 0 : } 55 : 56 : void 57 0 : serializer:: 58 : reset( 59 : message_view_base const& m) noexcept 60 : { 61 0 : ws_.clear(); 62 0 : h_ = m.ph_; 63 0 : src_ = nullptr; 64 0 : st_ = state::init; 65 : 66 0 : cb_ = nullptr; 67 0 : cbn_ = 0; 68 0 : cbi_ = 0; 69 0 : } 70 : 71 : //------------------------------------------------ 72 : 73 : auto 74 0 : serializer:: 75 : prepare() -> 76 : result<buffers> 77 : { 78 0 : if(st_ == state::init) 79 0 : init_impl(); 80 : 81 : //if(! expect:100 continue) 82 : 83 0 : if(src_) 84 : { 85 : // source body 86 0 : auto cb0 = cb_; 87 : const_buffer* p; 88 0 : if(hbuf_.size() > 0) 89 : { 90 0 : *cb0 = hbuf_; 91 0 : p = cb0 + 1; 92 : } 93 : else 94 : { 95 0 : ++cb0; 96 0 : p = cb0; 97 : } 98 0 : ++p; 99 0 : auto dest = buf_.prepare(); 100 0 : auto rv = src_->read( 101 : dest.first.data(), 102 0 : dest.first.size()); 103 0 : if(rv.has_error()) 104 0 : return rv.error(); 105 0 : buf_.commit(rv->bytes); 106 0 : if( rv->more && 107 0 : dest.second.size() > 0) 108 : { 109 0 : rv = src_->read( 110 : dest.second.data(), 111 0 : dest.second.size()); 112 0 : if(rv.has_error()) 113 0 : return rv.error(); 114 0 : buf_.commit(rv->bytes); 115 : } 116 0 : more_ = rv->more; 117 0 : auto src = buf_.data(); 118 0 : *p++ = src.first; 119 0 : if(src.second.size() > 0) 120 0 : *p++ = src.second; 121 0 : return buffers(cb0, p - cb0); 122 : } 123 : 124 : // buffers body 125 0 : if(hbuf_.size() > 0) 126 : { 127 0 : BOOST_ASSERT(cbi_ == 0); 128 0 : cb_[0] = hbuf_; 129 0 : return buffers(cb_, 1 + cbn_); 130 : } 131 0 : return buffers( 132 0 : &cb_[1 + cbi_], cbn_ - cbi_); 133 : } 134 : 135 : void 136 0 : serializer:: 137 : consume( 138 : std::size_t n) noexcept 139 : { 140 0 : BOOST_ASSERT( 141 : st_ == state::ok); 142 : 143 : // header 144 0 : if(hbuf_.size() > 0) 145 : { 146 0 : if(n <= hbuf_.size()) 147 : { 148 0 : hbuf_ += n; 149 0 : return; 150 : } 151 : 152 0 : n -= hbuf_.size(); 153 0 : hbuf_ = {}; 154 : } 155 : 156 0 : if(src_) 157 : { 158 : // source body 159 0 : buf_.consume(n); 160 : 161 0 : if( buf_.empty() && 162 0 : ! more_) 163 : { 164 0 : st_ = state::done; 165 : } 166 : } 167 : else 168 : { 169 : // buffers body 170 0 : while(n > 0) 171 : { 172 : // n was out of range 173 0 : BOOST_ASSERT(cbi_ != cbn_); 174 0 : auto i = cbi_ + 1; 175 0 : if(n < cb_[i].size()) 176 : { 177 0 : cb_[i] += n; 178 0 : return; 179 : } 180 : 181 0 : n -= cb_[i].size(); 182 0 : ++cbi_; 183 : } 184 0 : st_ = state::done; 185 : } 186 : } 187 : 188 : //------------------------------------------------ 189 : 190 : void 191 0 : serializer:: 192 : init_impl() 193 : { 194 0 : BOOST_ASSERT(st_ == state::init); 195 : 196 : // header 197 0 : hbuf_ = { h_->buf, h_->size }; 198 : 199 0 : if(src_) 200 : { 201 : // source body 202 0 : buf_ = { ws_.data(), ws_.size() }; 203 : } 204 : else 205 : { 206 : // buffers body 207 : } 208 : 209 0 : st_ = state::ok; 210 0 : } 211 : 212 : } // http_proto 213 : } // boost 214 : 215 : #endif