src/detail/circular_buffer.cpp
100.0% Lines (91/91)
100.0% List of functions (14/14)
85.0% Branches (34/40)
Functions (14)
Function
Calls
Lines
Branches
Blocks
boost::burl::detail::circular_buffer::empty() const
:27
6441x
100.0%
–
100.0%
boost::burl::detail::circular_buffer::full() const
:34
6439x
100.0%
–
100.0%
boost::burl::detail::circular_buffer::wrapped() const
:41
10060x
100.0%
–
100.0%
boost::burl::detail::circular_buffer::size() const
:48
7190x
100.0%
–
100.0%
boost::burl::detail::circular_buffer::data() const
:55
9721x
100.0%
100.0%
100.0%
boost::burl::detail::circular_buffer::first(unsigned long) const
:65
93x
100.0%
100.0%
100.0%
boost::burl::detail::circular_buffer::prepare() const
:73
9575x
100.0%
100.0%
100.0%
boost::burl::detail::circular_buffer::prepare_one() const
:87
40x
100.0%
100.0%
100.0%
boost::burl::detail::circular_buffer::commit(unsigned long)
:97
9553x
100.0%
100.0%
100.0%
boost::burl::detail::circular_buffer::consume(unsigned long)
:106
3796x
100.0%
100.0%
100.0%
boost::burl::detail::circular_buffer::reset(char*)
:118
52x
100.0%
50.0%
67.0%
boost::burl::detail::circular_buffer::shed(unsigned long)
:129
318x
100.0%
50.0%
60.0%
boost::burl::detail::circular_buffer::slide(char*)
:140
207x
100.0%
50.0%
60.0%
boost::burl::detail::circular_buffer::linearize(char*)
:151
521x
100.0%
92.9%
97.0%
| Line | Branch | TLA | Hits | Source Code |
|---|---|---|---|---|
| 1 | // | |||
| 2 | // Copyright (c) 2026 Mohammad Nejati | |||
| 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/burl | |||
| 8 | // | |||
| 9 | ||||
| 10 | #include <boost/burl/detail/circular_buffer.hpp> | |||
| 11 | ||||
| 12 | #include "util.hpp" | |||
| 13 | ||||
| 14 | #include <boost/assert.hpp> | |||
| 15 | ||||
| 16 | #include <algorithm> | |||
| 17 | #include <cstring> | |||
| 18 | ||||
| 19 | namespace boost | |||
| 20 | { | |||
| 21 | namespace burl | |||
| 22 | { | |||
| 23 | namespace detail | |||
| 24 | { | |||
| 25 | ||||
| 26 | bool | |||
| 27 | 6441x | circular_buffer:: | ||
| 28 | empty() const noexcept | |||
| 29 | { | |||
| 30 | 6441x | return len == 0; | ||
| 31 | } | |||
| 32 | ||||
| 33 | bool | |||
| 34 | 6439x | circular_buffer:: | ||
| 35 | full() const noexcept | |||
| 36 | { | |||
| 37 | 6439x | return len == cap; | ||
| 38 | } | |||
| 39 | ||||
| 40 | bool | |||
| 41 | 10060x | circular_buffer:: | ||
| 42 | wrapped() const noexcept | |||
| 43 | { | |||
| 44 | 10060x | return pos + len > cap; | ||
| 45 | } | |||
| 46 | ||||
| 47 | std::size_t | |||
| 48 | 7190x | circular_buffer:: | ||
| 49 | size() const noexcept | |||
| 50 | { | |||
| 51 | 7190x | return len; | ||
| 52 | } | |||
| 53 | ||||
| 54 | std::array<capy::const_buffer, 2> | |||
| 55 | 9721x | circular_buffer:: | ||
| 56 | data() const noexcept | |||
| 57 | { | |||
| 58 |
2/2✓ Branch 1 taken 9038 times.
✓ Branch 2 taken 683 times.
|
9721x | if(!wrapped()) | |
| 59 | 9038x | return { { { ptr + pos, len }, { ptr, 0 } } }; | ||
| 60 | 683x | return { { { ptr + pos, cap - pos }, | ||
| 61 | 683x | { ptr, len - (cap - pos) } } }; | ||
| 62 | } | |||
| 63 | ||||
| 64 | capy::const_buffer | |||
| 65 | 93x | circular_buffer:: | ||
| 66 | first(std::size_t n) const noexcept | |||
| 67 | { | |||
| 68 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 91 times.
|
93x | auto const k = wrapped() ? cap - pos : len; | |
| 69 | 93x | return { ptr + pos, clamp(k, n) }; | ||
| 70 | } | |||
| 71 | ||||
| 72 | std::array<capy::mutable_buffer, 2> | |||
| 73 | 9575x | circular_buffer:: | ||
| 74 | prepare() const noexcept | |||
| 75 | { | |||
| 76 | 9575x | std::size_t w = pos + len; | ||
| 77 |
2/2✓ Branch 0 taken 687 times.
✓ Branch 1 taken 8888 times.
|
9575x | if(w >= cap) | |
| 78 | 687x | w -= cap; | ||
| 79 | 9575x | std::size_t const free = cap - len; | ||
| 80 |
2/2✓ Branch 0 taken 4257 times.
✓ Branch 1 taken 5318 times.
|
9575x | if(w + free <= cap) | |
| 81 | 4257x | return { { { ptr + w, free }, { ptr, 0 } } }; | ||
| 82 | 5318x | return { { { ptr + w, cap - w }, | ||
| 83 | 5318x | { ptr, free - (cap - w) } } }; | ||
| 84 | } | |||
| 85 | ||||
| 86 | capy::mutable_buffer | |||
| 87 | 40x | circular_buffer:: | ||
| 88 | prepare_one() const noexcept | |||
| 89 | { | |||
| 90 | 40x | std::size_t w = pos + len; | ||
| 91 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 36 times.
|
40x | if(w >= cap) | |
| 92 | 4x | w -= cap; | ||
| 93 | 40x | return { ptr + w, clamp(cap - len, cap - w) }; | ||
| 94 | } | |||
| 95 | ||||
| 96 | void | |||
| 97 | 9553x | circular_buffer:: | ||
| 98 | commit(std::size_t n) noexcept | |||
| 99 | { | |||
| 100 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 9552 times.
|
9553x | if(n > cap - len) | |
| 101 | 1x | n = cap - len; | ||
| 102 | 9553x | len += n; | ||
| 103 | 9553x | } | ||
| 104 | ||||
| 105 | void | |||
| 106 | 3796x | circular_buffer:: | ||
| 107 | consume(std::size_t n) noexcept | |||
| 108 | { | |||
| 109 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 3795 times.
|
3796x | if(n > len) | |
| 110 | 1x | n = len; | ||
| 111 | 3796x | pos += n; | ||
| 112 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3790 times.
|
3796x | if(pos >= cap) | |
| 113 | 6x | pos -= cap; | ||
| 114 | 3796x | len -= n; | ||
| 115 | 3796x | } | ||
| 116 | ||||
| 117 | void | |||
| 118 | 52x | circular_buffer:: | ||
| 119 | reset(char* p) noexcept | |||
| 120 | { | |||
| 121 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
|
52x | BOOST_ASSERT(p <= ptr + cap); | |
| 122 | 52x | cap = static_cast<std::size_t>((ptr + cap) - p); | ||
| 123 | 52x | ptr = p; | ||
| 124 | 52x | pos = 0; | ||
| 125 | 52x | len = 0; | ||
| 126 | 52x | } | ||
| 127 | ||||
| 128 | void | |||
| 129 | 318x | circular_buffer:: | ||
| 130 | shed(std::size_t n) noexcept | |||
| 131 | { | |||
| 132 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 318 times.
|
318x | BOOST_ASSERT(pos == 0); | |
| 133 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 318 times.
|
318x | BOOST_ASSERT(n <= len); | |
| 134 | 318x | ptr += n; | ||
| 135 | 318x | cap -= n; | ||
| 136 | 318x | len -= n; | ||
| 137 | 318x | } | ||
| 138 | ||||
| 139 | void | |||
| 140 | 207x | circular_buffer:: | ||
| 141 | slide(char* p) noexcept | |||
| 142 | { | |||
| 143 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 207 times.
|
207x | BOOST_ASSERT(pos == 0); | |
| 144 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 207 times.
|
207x | BOOST_ASSERT(p <= ptr); | |
| 145 | 207x | std::memmove(p, ptr, len); | ||
| 146 | 207x | cap += static_cast<std::size_t>(ptr - p); | ||
| 147 | 207x | ptr = p; | ||
| 148 | 207x | } | ||
| 149 | ||||
| 150 | char* | |||
| 151 | 521x | circular_buffer:: | ||
| 152 | linearize(char* floor) noexcept | |||
| 153 | { | |||
| 154 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 521 times.
|
521x | BOOST_ASSERT(floor <= ptr); | |
| 155 | 521x | char* p = floor; | ||
| 156 |
6/6✓ Branch 0 taken 197 times.
✓ Branch 1 taken 324 times.
✓ Branch 3 taken 156 times.
✓ Branch 4 taken 41 times.
✓ Branch 5 taken 156 times.
✓ Branch 6 taken 365 times.
|
521x | if(len != 0 && !wrapped()) | |
| 157 | { | |||
| 158 | 156x | p = ptr + pos; | ||
| 159 | } | |||
| 160 |
2/2✓ Branch 0 taken 41 times.
✓ Branch 1 taken 324 times.
|
365x | else if(len != 0) | |
| 161 | { | |||
| 162 | 41x | auto const bufs = data(); | ||
| 163 | 41x | auto const* a = static_cast<char const*>(bufs[0].data()); | ||
| 164 | 41x | auto an = bufs[0].size(); | ||
| 165 | 41x | auto const* b = static_cast<char const*>(bufs[1].data()); | ||
| 166 | 41x | auto const bn = bufs[1].size(); | ||
| 167 | 41x | auto const gap = static_cast<std::size_t>(ptr - floor) + (cap - len); | ||
| 168 | ||||
| 169 | // leapfrogging to the floor runs ceil(an / gap) rounds | |||
| 170 | // and re-moves the wrapped range each round; past a | |||
| 171 | // bound the in-place rotate is cheaper, and it is the | |||
| 172 | // only option when gap == 0 | |||
| 173 |
2/2✓ Branch 0 taken 22 times.
✓ Branch 1 taken 19 times.
|
41x | if(an <= gap * 16) | |
| 174 | { | |||
| 175 | 22x | char* base = floor; | ||
| 176 | do | |||
| 177 | { | |||
| 178 | 24x | auto const k = (std::min)(an, gap); | ||
| 179 | 24x | b = static_cast<char const*>(std::memmove(base + k, b, bn)); | ||
| 180 | 24x | std::memcpy(base, a, k); | ||
| 181 | 24x | an -= k; | ||
| 182 | 24x | base += k; | ||
| 183 | 24x | a += k; | ||
| 184 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22 times.
|
24x | } while(an); | |
| 185 | } | |||
| 186 | else | |||
| 187 | { | |||
| 188 | 19x | std::rotate(ptr, ptr + pos, ptr + cap); | ||
| 189 | 19x | p = ptr; | ||
| 190 | } | |||
| 191 | } | |||
| 192 | 521x | cap = static_cast<std::size_t>((ptr + cap) - p); | ||
| 193 | 521x | ptr = p; | ||
| 194 | 521x | pos = 0; | ||
| 195 | 521x | return p; | ||
| 196 | } | |||
| 197 | ||||
| 198 | } // namespace detail | |||
| 199 | } // namespace burl | |||
| 200 | } // namespace boost | |||
| 201 |