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_DETAIL_IMPL_CIRCULAR_BUFFER_IPP 11 : #define BOOST_HTTP_PROTO_DETAIL_IMPL_CIRCULAR_BUFFER_IPP 12 : 13 : #include <boost/http_proto/detail/circular_buffer.hpp> 14 : #include <boost/http_proto/detail/except.hpp> 15 : #include <boost/assert.hpp> 16 : #include <boost/static_assert.hpp> 17 : 18 : namespace boost { 19 : namespace http_proto { 20 : namespace detail { 21 : 22 : BOOST_STATIC_ASSERT( 23 : is_const_buffers<circular_buffer::const_buffers_type>::value); 24 : BOOST_STATIC_ASSERT( 25 : is_mutable_buffers<circular_buffer::mutable_buffers_type>::value); 26 : BOOST_STATIC_ASSERT( 27 : is_dynamic_buffer<circular_buffer>::value); 28 : 29 6 : circular_buffer:: 30 : circular_buffer( 31 : void* base, 32 6 : std::size_t capacity) noexcept 33 : : base_(reinterpret_cast< 34 : unsigned char*>(base)) 35 6 : , cap_(capacity) 36 : { 37 6 : } 38 : 39 : std::size_t 40 9 : circular_buffer:: 41 : size() const noexcept 42 : { 43 9 : return in_len_; 44 : } 45 : 46 : std::size_t 47 0 : circular_buffer:: 48 : max_size() const noexcept 49 : { 50 0 : return cap_; 51 : } 52 : 53 : std::size_t 54 11 : circular_buffer:: 55 : capacity() const noexcept 56 : { 57 11 : return cap_; 58 : } 59 : 60 : auto 61 4 : circular_buffer:: 62 : data() const noexcept -> 63 : const_buffers_type 64 : { 65 4 : if(in_pos_ + in_len_ <= cap_) 66 : return { 67 : const_buffer{ 68 4 : base_ + in_pos_, in_len_ }, 69 4 : const_buffer{ base_, 0} }; 70 : return { 71 : const_buffer{ 72 0 : base_ + in_pos_, cap_ - in_pos_}, 73 : const_buffer{ 74 0 : base_, in_len_- (cap_ - in_pos_)}}; 75 : } 76 : 77 : auto 78 7 : circular_buffer:: 79 : prepare(std::size_t n) -> 80 : mutable_buffers_type 81 : { 82 : // Buffer is too small for n 83 7 : if(n > cap_ - in_len_) 84 0 : detail::throw_length_error(); 85 : 86 7 : out_size_ = n; 87 7 : auto const pos = ( 88 7 : in_pos_ + in_len_) % cap_; 89 7 : if(pos + n <= cap_) 90 : return { 91 : mutable_buffer{ 92 7 : base_ + pos, n}, 93 7 : mutable_buffer{base_, 0}}; 94 : return { 95 : mutable_buffer{ 96 0 : base_ + pos, cap_ - pos}, 97 : mutable_buffer{ 98 0 : base_, n - (cap_ - pos)}}; 99 : } 100 : 101 : void 102 7 : circular_buffer:: 103 : commit(std::size_t n) 104 : { 105 : // Precondition violation 106 7 : if(n > out_size_) 107 0 : detail::throw_length_error(); 108 : 109 7 : in_len_ += n; 110 7 : out_size_ = 0; 111 7 : } 112 : 113 : void 114 0 : circular_buffer:: 115 : uncommit( 116 : std::size_t n) 117 : { 118 : // Precondition violation 119 0 : if( n > in_len_ || 120 0 : out_size_ > 0) 121 0 : detail::throw_length_error(); 122 : 123 0 : in_len_ -= n; 124 0 : } 125 : 126 : void 127 4 : circular_buffer:: 128 : consume(std::size_t n) noexcept 129 : { 130 4 : if(n < in_len_) 131 : { 132 0 : in_pos_ = (in_pos_ + n) % cap_; 133 0 : in_len_ -= n; 134 : } 135 : else 136 : { 137 : // make prepare return a 138 : // bigger single buffer 139 4 : in_pos_ = 0; 140 4 : in_len_ = 0; 141 : } 142 4 : } 143 : 144 : } // detail 145 : } // http_proto 146 : } // boost 147 : 148 : #endif