100.00% Lines (46/46)
100.00% Functions (10/10)
| TLA | Baseline | Branch | ||||||
|---|---|---|---|---|---|---|---|---|
| Line | Hits | Code | Line | Hits | Code | |||
| 1 | // | 1 | // | |||||
| 2 | // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com) | 2 | // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com) | |||||
| 3 | // | 3 | // | |||||
| 4 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | 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) | 5 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |||||
| 6 | // | 6 | // | |||||
| 7 | // Official repository: https://github.com/cppalliance/capy | 7 | // Official repository: https://github.com/cppalliance/capy | |||||
| 8 | // | 8 | // | |||||
| 9 | 9 | |||||||
| 10 | #ifndef BOOST_CAPY_BUFFERS_CONSUMING_BUFFERS_HPP | 10 | #ifndef BOOST_CAPY_BUFFERS_CONSUMING_BUFFERS_HPP | |||||
| 11 | #define BOOST_CAPY_BUFFERS_CONSUMING_BUFFERS_HPP | 11 | #define BOOST_CAPY_BUFFERS_CONSUMING_BUFFERS_HPP | |||||
| 12 | 12 | |||||||
| 13 | #include <boost/capy/detail/config.hpp> | 13 | #include <boost/capy/detail/config.hpp> | |||||
| 14 | #include <boost/capy/buffers.hpp> | 14 | #include <boost/capy/buffers.hpp> | |||||
| 15 | 15 | |||||||
| 16 | #include <cstddef> | 16 | #include <cstddef> | |||||
| 17 | #include <iterator> | 17 | #include <iterator> | |||||
| 18 | #include <ranges> | 18 | #include <ranges> | |||||
| 19 | #include <type_traits> | 19 | #include <type_traits> | |||||
| 20 | 20 | |||||||
| 21 | namespace boost { | 21 | namespace boost { | |||||
| 22 | namespace capy { | 22 | namespace capy { | |||||
| 23 | 23 | |||||||
| 24 | namespace detail { | 24 | namespace detail { | |||||
| 25 | 25 | |||||||
| 26 | template<class T> | 26 | template<class T> | |||||
| 27 | struct buffer_type_for; | 27 | struct buffer_type_for; | |||||
| 28 | 28 | |||||||
| 29 | template<MutableBufferSequence T> | 29 | template<MutableBufferSequence T> | |||||
| 30 | struct buffer_type_for<T> | 30 | struct buffer_type_for<T> | |||||
| 31 | { | 31 | { | |||||
| 32 | using type = mutable_buffer; | 32 | using type = mutable_buffer; | |||||
| 33 | }; | 33 | }; | |||||
| 34 | 34 | |||||||
| 35 | template<ConstBufferSequence T> | 35 | template<ConstBufferSequence T> | |||||
| 36 | requires (!MutableBufferSequence<T>) | 36 | requires (!MutableBufferSequence<T>) | |||||
| 37 | struct buffer_type_for<T> | 37 | struct buffer_type_for<T> | |||||
| 38 | { | 38 | { | |||||
| 39 | using type = const_buffer; | 39 | using type = const_buffer; | |||||
| 40 | }; | 40 | }; | |||||
| 41 | 41 | |||||||
| 42 | } // namespace detail | 42 | } // namespace detail | |||||
| 43 | 43 | |||||||
| 44 | /** Wrapper for consuming a buffer sequence incrementally. | 44 | /** Wrapper for consuming a buffer sequence incrementally. | |||||
| 45 | 45 | |||||||
| 46 | This class wraps a buffer sequence and tracks the current | 46 | This class wraps a buffer sequence and tracks the current | |||||
| 47 | position. It provides a `consume(n)` function that advances | 47 | position. It provides a `consume(n)` function that advances | |||||
| 48 | through the sequence as bytes are processed. | 48 | through the sequence as bytes are processed. | |||||
| 49 | 49 | |||||||
| 50 | Works with both mutable and const buffer sequences. | 50 | Works with both mutable and const buffer sequences. | |||||
| 51 | 51 | |||||||
| 52 | @tparam BufferSequence The buffer sequence type. | 52 | @tparam BufferSequence The buffer sequence type. | |||||
| 53 | */ | 53 | */ | |||||
| 54 | template<class BufferSequence> | 54 | template<class BufferSequence> | |||||
| 55 | requires MutableBufferSequence<BufferSequence> || | 55 | requires MutableBufferSequence<BufferSequence> || | |||||
| 56 | ConstBufferSequence<BufferSequence> | 56 | ConstBufferSequence<BufferSequence> | |||||
| 57 | class consuming_buffers | 57 | class consuming_buffers | |||||
| 58 | { | 58 | { | |||||
| 59 | using iterator_type = decltype(capy::begin(std::declval<BufferSequence const&>())); | 59 | using iterator_type = decltype(capy::begin(std::declval<BufferSequence const&>())); | |||||
| 60 | using end_iterator_type = decltype(capy::end(std::declval<BufferSequence const&>())); | 60 | using end_iterator_type = decltype(capy::end(std::declval<BufferSequence const&>())); | |||||
| 61 | using buffer_type = typename detail::buffer_type_for<BufferSequence>::type; | 61 | using buffer_type = typename detail::buffer_type_for<BufferSequence>::type; | |||||
| 62 | 62 | |||||||
| 63 | BufferSequence const& bufs_; | 63 | BufferSequence const& bufs_; | |||||
| 64 | iterator_type it_; | 64 | iterator_type it_; | |||||
| 65 | end_iterator_type end_; | 65 | end_iterator_type end_; | |||||
| 66 | std::size_t consumed_ = 0; // Bytes consumed in current buffer | 66 | std::size_t consumed_ = 0; // Bytes consumed in current buffer | |||||
| 67 | 67 | |||||||
| 68 | public: | 68 | public: | |||||
| 69 | /** Construct from a buffer sequence. | 69 | /** Construct from a buffer sequence. | |||||
| 70 | 70 | |||||||
| 71 | @param bufs The buffer sequence to wrap. | 71 | @param bufs The buffer sequence to wrap. | |||||
| 72 | */ | 72 | */ | |||||
| HITCBC | 73 | 203 | explicit consuming_buffers(BufferSequence const& bufs) noexcept | 73 | 203 | explicit consuming_buffers(BufferSequence const& bufs) noexcept | ||
| HITCBC | 74 | 203 | : bufs_(bufs) | 74 | 203 | : bufs_(bufs) | ||
| HITCBC | 75 | 203 | , it_(capy::begin(bufs)) | 75 | 203 | , it_(capy::begin(bufs)) | ||
| HITCBC | 76 | 203 | , end_(capy::end(bufs)) | 76 | 203 | , end_(capy::end(bufs)) | ||
| 77 | { | 77 | { | |||||
| HITCBC | 78 | 203 | } | 78 | 203 | } | ||
| 79 | 79 | |||||||
| 80 | /** Consume n bytes from the buffer sequence. | 80 | /** Consume n bytes from the buffer sequence. | |||||
| 81 | 81 | |||||||
| 82 | Advances the current position by n bytes, moving to the | 82 | Advances the current position by n bytes, moving to the | |||||
| 83 | next buffer when the current one is exhausted. | 83 | next buffer when the current one is exhausted. | |||||
| 84 | 84 | |||||||
| 85 | @param n The number of bytes to consume. | 85 | @param n The number of bytes to consume. | |||||
| 86 | */ | 86 | */ | |||||
| HITCBC | 87 | 162 | void consume(std::size_t n) noexcept | 87 | 162 | void consume(std::size_t n) noexcept | ||
| 88 | { | 88 | { | |||||
| HITCBC | 89 | 274 | while (n > 0 && it_ != end_) | 89 | 274 | while (n > 0 && it_ != end_) | ||
| 90 | { | 90 | { | |||||
| HITCBC | 91 | 112 | auto const& buf = *it_; | 91 | 112 | auto const& buf = *it_; | ||
| HITCBC | 92 | 112 | std::size_t const buf_size = buf.size(); | 92 | 112 | std::size_t const buf_size = buf.size(); | ||
| HITCBC | 93 | 112 | std::size_t const remaining = buf_size - consumed_; | 93 | 112 | std::size_t const remaining = buf_size - consumed_; | ||
| 94 | 94 | |||||||
| HITCBC | 95 | 112 | if (n < remaining) | 95 | 112 | if (n < remaining) | ||
| 96 | { | 96 | { | |||||
| 97 | // Consume part of current buffer | 97 | // Consume part of current buffer | |||||
| HITCBC | 98 | 30 | consumed_ += n; | 98 | 30 | consumed_ += n; | ||
| HITCBC | 99 | 30 | n = 0; | 99 | 30 | n = 0; | ||
| 100 | } | 100 | } | |||||
| 101 | else | 101 | else | |||||
| 102 | { | 102 | { | |||||
| 103 | // Consume rest of current buffer and move to next | 103 | // Consume rest of current buffer and move to next | |||||
| HITCBC | 104 | 82 | n -= remaining; | 104 | 82 | n -= remaining; | ||
| HITCBC | 105 | 82 | consumed_ = 0; | 105 | 82 | consumed_ = 0; | ||
| HITCBC | 106 | 82 | ++it_; | 106 | 82 | ++it_; | ||
| 107 | } | 107 | } | |||||
| 108 | } | 108 | } | |||||
| HITCBC | 109 | 162 | } | 109 | 162 | } | ||
| 110 | 110 | |||||||
| 111 | /** Iterator for the consuming buffer sequence. | 111 | /** Iterator for the consuming buffer sequence. | |||||
| 112 | 112 | |||||||
| 113 | Returns buffers starting from the current position, | 113 | Returns buffers starting from the current position, | |||||
| 114 | with the first buffer adjusted for consumed bytes. | 114 | with the first buffer adjusted for consumed bytes. | |||||
| 115 | */ | 115 | */ | |||||
| 116 | class const_iterator | 116 | class const_iterator | |||||
| 117 | { | 117 | { | |||||
| 118 | iterator_type it_; | 118 | iterator_type it_; | |||||
| 119 | end_iterator_type end_; | 119 | end_iterator_type end_; | |||||
| 120 | std::size_t consumed_; | 120 | std::size_t consumed_; | |||||
| 121 | 121 | |||||||
| 122 | public: | 122 | public: | |||||
| 123 | using iterator_category = std::bidirectional_iterator_tag; | 123 | using iterator_category = std::bidirectional_iterator_tag; | |||||
| 124 | using value_type = buffer_type; | 124 | using value_type = buffer_type; | |||||
| 125 | using difference_type = std::ptrdiff_t; | 125 | using difference_type = std::ptrdiff_t; | |||||
| 126 | using pointer = value_type*; | 126 | using pointer = value_type*; | |||||
| 127 | using reference = value_type; | 127 | using reference = value_type; | |||||
| 128 | 128 | |||||||
| 129 | // Default constructor required for forward_iterator | 129 | // Default constructor required for forward_iterator | |||||
| 130 | const_iterator() noexcept = default; | 130 | const_iterator() noexcept = default; | |||||
| 131 | 131 | |||||||
| 132 | /// Construct from position and consumed byte count. | 132 | /// Construct from position and consumed byte count. | |||||
| HITCBC | 133 | 826 | const_iterator( | 133 | 826 | const_iterator( | ||
| 134 | iterator_type it, | 134 | iterator_type it, | |||||
| 135 | end_iterator_type end, | 135 | end_iterator_type end, | |||||
| 136 | std::size_t consumed) noexcept | 136 | std::size_t consumed) noexcept | |||||
| HITCBC | 137 | 826 | : it_(it) | 137 | 826 | : it_(it) | ||
| HITCBC | 138 | 826 | , end_(end) | 138 | 826 | , end_(end) | ||
| HITCBC | 139 | 826 | , consumed_(consumed) | 139 | 826 | , consumed_(consumed) | ||
| 140 | { | 140 | { | |||||
| HITCBC | 141 | 826 | } | 141 | 826 | } | ||
| 142 | 142 | |||||||
| 143 | /// Test for equality. | 143 | /// Test for equality. | |||||
| HITCBC | 144 | 518 | bool operator==(const_iterator const& other) const noexcept | 144 | 518 | bool operator==(const_iterator const& other) const noexcept | ||
| 145 | { | 145 | { | |||||
| HITCBC | 146 | 518 | return it_ == other.it_ && consumed_ == other.consumed_; | 146 | 518 | return it_ == other.it_ && consumed_ == other.consumed_; | ||
| 147 | } | 147 | } | |||||
| 148 | 148 | |||||||
| 149 | /// Test for inequality. | 149 | /// Test for inequality. | |||||
| HITCBC | 150 | 518 | bool operator!=(const_iterator const& other) const noexcept | 150 | 518 | bool operator!=(const_iterator const& other) const noexcept | ||
| 151 | { | 151 | { | |||||
| HITCBC | 152 | 518 | return !(*this == other); | 152 | 518 | return !(*this == other); | ||
| 153 | } | 153 | } | |||||
| 154 | 154 | |||||||
| 155 | /// Return the current buffer, adjusted for consumed bytes. | 155 | /// Return the current buffer, adjusted for consumed bytes. | |||||
| HITCBC | 156 | 457 | value_type operator*() const noexcept | 156 | 457 | value_type operator*() const noexcept | ||
| 157 | { | 157 | { | |||||
| HITCBC | 158 | 457 | auto const& buf = *it_; | 158 | 457 | auto const& buf = *it_; | ||
| 159 | if constexpr (std::is_same_v<buffer_type, mutable_buffer>) | 159 | if constexpr (std::is_same_v<buffer_type, mutable_buffer>) | |||||
| 160 | { | 160 | { | |||||
| HITCBC | 161 | 579 | return buffer_type( | 161 | 579 | return buffer_type( | ||
| HITCBC | 162 | 193 | static_cast<char*>(buf.data()) + consumed_, | 162 | 193 | static_cast<char*>(buf.data()) + consumed_, | ||
| HITCBC | 163 | 386 | buf.size() - consumed_); | 163 | 386 | buf.size() - consumed_); | ||
| 164 | } | 164 | } | |||||
| 165 | else | 165 | else | |||||
| 166 | { | 166 | { | |||||
| HITCBC | 167 | 792 | return buffer_type( | 167 | 792 | return buffer_type( | ||
| HITCBC | 168 | 264 | static_cast<char const*>(buf.data()) + consumed_, | 168 | 264 | static_cast<char const*>(buf.data()) + consumed_, | ||
| HITCBC | 169 | 528 | buf.size() - consumed_); | 169 | 528 | buf.size() - consumed_); | ||
| 170 | } | 170 | } | |||||
| 171 | } | 171 | } | |||||
| 172 | 172 | |||||||
| 173 | /// Advance to the next element. | 173 | /// Advance to the next element. | |||||
| HITCBC | 174 | 427 | const_iterator& operator++() noexcept | 174 | 427 | const_iterator& operator++() noexcept | ||
| 175 | { | 175 | { | |||||
| HITCBC | 176 | 427 | consumed_ = 0; | 176 | 427 | consumed_ = 0; | ||
| HITCBC | 177 | 427 | ++it_; | 177 | 427 | ++it_; | ||
| HITCBC | 178 | 427 | return *this; | 178 | 427 | return *this; | ||
| 179 | } | 179 | } | |||||
| 180 | 180 | |||||||
| 181 | /// Advance to the next element (postfix). | 181 | /// Advance to the next element (postfix). | |||||
| HITCBC | 182 | 274 | const_iterator operator++(int) noexcept | 182 | 274 | const_iterator operator++(int) noexcept | ||
| 183 | { | 183 | { | |||||
| HITCBC | 184 | 274 | const_iterator tmp = *this; | 184 | 274 | const_iterator tmp = *this; | ||
| HITCBC | 185 | 274 | ++*this; | 185 | 274 | ++*this; | ||
| HITCBC | 186 | 274 | return tmp; | 186 | 274 | return tmp; | ||
| 187 | } | 187 | } | |||||
| 188 | 188 | |||||||
| 189 | /// Move to the previous element. | 189 | /// Move to the previous element. | |||||
| 190 | const_iterator& operator--() noexcept | 190 | const_iterator& operator--() noexcept | |||||
| 191 | { | 191 | { | |||||
| 192 | if (consumed_ == 0) | 192 | if (consumed_ == 0) | |||||
| 193 | { | 193 | { | |||||
| 194 | --it_; | 194 | --it_; | |||||
| 195 | // Set consumed_ to the size of the previous buffer | 195 | // Set consumed_ to the size of the previous buffer | |||||
| 196 | // This is a simplified implementation for bidirectional requirement | 196 | // This is a simplified implementation for bidirectional requirement | |||||
| 197 | if (it_ != end_) | 197 | if (it_ != end_) | |||||
| 198 | { | 198 | { | |||||
| 199 | auto const& buf = *it_; | 199 | auto const& buf = *it_; | |||||
| 200 | consumed_ = buf.size(); | 200 | consumed_ = buf.size(); | |||||
| 201 | } | 201 | } | |||||
| 202 | } | 202 | } | |||||
| 203 | else | 203 | else | |||||
| 204 | { | 204 | { | |||||
| 205 | consumed_ = 0; | 205 | consumed_ = 0; | |||||
| 206 | } | 206 | } | |||||
| 207 | return *this; | 207 | return *this; | |||||
| 208 | } | 208 | } | |||||
| 209 | 209 | |||||||
| 210 | /// Move to the previous element (postfix). | 210 | /// Move to the previous element (postfix). | |||||
| 211 | const_iterator operator--(int) noexcept | 211 | const_iterator operator--(int) noexcept | |||||
| 212 | { | 212 | { | |||||
| 213 | const_iterator tmp = *this; | 213 | const_iterator tmp = *this; | |||||
| 214 | --*this; | 214 | --*this; | |||||
| 215 | return tmp; | 215 | return tmp; | |||||
| 216 | } | 216 | } | |||||
| 217 | }; | 217 | }; | |||||
| 218 | 218 | |||||||
| 219 | /** Return iterator to beginning of remaining buffers. | 219 | /** Return iterator to beginning of remaining buffers. | |||||
| 220 | 220 | |||||||
| 221 | @return Iterator pointing to the first remaining buffer, | 221 | @return Iterator pointing to the first remaining buffer, | |||||
| 222 | adjusted for consumed bytes in the current buffer. | 222 | adjusted for consumed bytes in the current buffer. | |||||
| 223 | */ | 223 | */ | |||||
| HITCBC | 224 | 413 | const_iterator begin() const noexcept | 224 | 413 | const_iterator begin() const noexcept | ||
| 225 | { | 225 | { | |||||
| HITCBC | 226 | 413 | return const_iterator(it_, end_, consumed_); | 226 | 413 | return const_iterator(it_, end_, consumed_); | ||
| 227 | } | 227 | } | |||||
| 228 | 228 | |||||||
| 229 | /** Return iterator to end of buffer sequence. | 229 | /** Return iterator to end of buffer sequence. | |||||
| 230 | 230 | |||||||
| 231 | @return End iterator. | 231 | @return End iterator. | |||||
| 232 | */ | 232 | */ | |||||
| HITCBC | 233 | 413 | const_iterator end() const noexcept | 233 | 413 | const_iterator end() const noexcept | ||
| 234 | { | 234 | { | |||||
| HITCBC | 235 | 413 | return const_iterator(end_, end_, 0); | 235 | 413 | return const_iterator(end_, end_, 0); | ||
| 236 | } | 236 | } | |||||
| 237 | }; | 237 | }; | |||||
| 238 | 238 | |||||||
| 239 | } // namespace capy | 239 | } // namespace capy | |||||
| 240 | } // namespace boost | 240 | } // namespace boost | |||||
| 241 | 241 | |||||||
| 242 | #endif | 242 | #endif | |||||