Line data Source code
1 : // 2 : // Copyright (c) 2024 Christian Mazakas 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_DETAIL_HEADER_IMPL_HPP 11 : #define BOOST_HTTP_PROTO_DETAIL_HEADER_IMPL_HPP 12 : 13 : #include <boost/http_proto/detail/except.hpp> 14 : #include <boost/http_proto/message_base.hpp> 15 : #include <boost/http_proto/detail/header.hpp> 16 : #include <boost/core/span.hpp> 17 : #include <cstddef> 18 : 19 : namespace boost { 20 : namespace http_proto { 21 : namespace detail { 22 : 23 : struct prefix_op 24 : { 25 : message_base& mb_; 26 : span<char> prefix_; 27 : char* buf_ = nullptr; 28 : std::size_t n_ = 0; 29 : 30 35 : prefix_op( 31 : message_base& mb, 32 : std::size_t n) 33 35 : : mb_{mb} 34 35 : , n_{n} 35 : { 36 35 : auto& h = mb_.h_; 37 35 : if( h.buf && n <= h.prefix ) 38 : { 39 9 : prefix_ = {h.buf, n}; 40 9 : return; 41 : } 42 : 43 : // allocate or grow 44 26 : if( n > h.prefix && 45 24 : static_cast<std::size_t>(n - h.prefix) > 46 24 : static_cast<std::size_t>(max_offset - h.size) ) 47 : { 48 1 : throw_length_error(); 49 : } 50 : 51 25 : auto n1 = header::bytes_needed( 52 25 : n + h.size - h.prefix, 53 25 : h.count); 54 : 55 25 : auto p = new char[n1]; 56 25 : if( h.buf != nullptr ) 57 : { 58 5 : std::memcpy( 59 5 : p + n, 60 5 : h.buf + h.prefix, 61 5 : h.size - h.prefix); 62 5 : h.copy_table(p + n1); 63 : } 64 : else 65 : { 66 20 : std::memcpy( 67 20 : p + n, 68 20 : h.cbuf + h.prefix, 69 20 : h.size - h.prefix); 70 : } 71 : 72 25 : prefix_ = {p, n}; 73 25 : buf_ = h.buf; 74 : 75 25 : h.buf = p; 76 25 : h.cbuf = p; 77 25 : h.size = static_cast< 78 25 : offset_type>(h.size + 79 25 : n - h.prefix); 80 25 : h.prefix = static_cast< 81 : offset_type>(n); 82 25 : h.cap = n1; 83 : } 84 : 85 : prefix_op(prefix_op&&) = delete; 86 : prefix_op(prefix_op const&) = delete; 87 : 88 34 : ~prefix_op() 89 34 : { 90 34 : auto& h = mb_.h_; 91 34 : if( n_ < h.prefix ) 92 : { 93 5 : std::memmove( 94 5 : h.buf + n_, 95 5 : h.buf + h.prefix, 96 5 : h.size - h.prefix); 97 5 : h.size = static_cast< 98 5 : offset_type>(h.size - 99 5 : h.prefix + n_); 100 5 : h.prefix = static_cast< 101 5 : offset_type>(n_); 102 : } 103 34 : delete[] buf_; 104 34 : } 105 : }; 106 : 107 : } // detail 108 : } // http_proto 109 : } // boost 110 : 111 : #endif // BOOST_HTTP_PROTO_DETAIL_HEADER_IMPL_HPP