13 #ifndef CIRCULAR_BUFFER_HH
14 #define CIRCULAR_BUFFER_HH
37 buf = it.buf; p = it.p;
return *
this;
44 return index(p) - index(it.p);
49 if (p == buf->last) p =
nullptr;
53 if (p ==
nullptr) p = buf->last;
63 if (p == buf->last) p =
nullptr;
65 if (p ==
nullptr) p = buf->last;
83 return index(p) < index(it.p);
90 [[nodiscard]]
size_t index(
const T* q)
const {
91 return q ? buf->index(q) : buf->size();
117 buf = allocate(buffer_capacity);
118 stop = buf + buffer_capacity;
129 last = uninitialized_copy(cb.
begin(), cb.
end(), buf);
134 if (last == stop) last = buf;
147 if (
this == &cb)
return *
this;
151 uninitialized_copy(cb.
begin(), cb.
end(), buff),
167 std::swap(buf, cb.buf);
168 std::swap(stop, cb.stop);
169 std::swap(first, cb.first);
170 std::swap(last, cb.last);
171 std::swap(siz, cb.siz);
187 [[nodiscard]]
auto&
operator[](
size_t i) {
return *add(first, i); }
188 [[nodiscard]]
auto&
operator[](
size_t i)
const {
return *add(first, i); }
190 [[nodiscard]]
auto&
front() {
return *first; }
191 [[nodiscard]]
auto&
front()
const {
return *first; }
192 [[nodiscard]]
auto&
back() {
return *((last == buf ? stop : last) - 1); }
193 [[nodiscard]]
auto&
back()
const {
return *((last == buf ? stop : last) - 1); }
195 [[nodiscard]]
size_t size()
const {
return siz; }
196 [[nodiscard]]
bool empty()
const {
return size() == 0; }
199 [[nodiscard]]
size_t capacity()
const {
return stop - buf; }
202 if (new_capacity ==
capacity())
return;
203 T* new_buf = allocate(new_capacity);
238 for (
size_t i = 0; i <
size(); ++i, increment(first)) {
253 while (next != dst) {
262 [[nodiscard]] T* uninitialized_move_n(
iterator src,
size_t n, T* dst) {
264 ::new (dst) T(std::move(*src));
270 template<
typename ValT>
void push_back_impl(ValT
t) {
271 ::new (last) T(
static_cast<ValT
>(
t));
276 template<
typename ValT>
void push_front_impl(ValT
t) {
279 ::new (first) T(
static_cast<ValT
>(
t));
287 template<
typename Po
inter>
void increment(Pointer& p)
const {
288 if (++p == stop) p = buf;
290 template<
typename Po
inter>
void decrement(Pointer& p)
const {
291 if (p == buf) p = stop;
294 template<
typename Po
inter> [[nodiscard]] Pointer add(Pointer p,
difference_type n)
const {
299 template<
typename Po
inter> [[nodiscard]] Pointer sub(Pointer p,
difference_type n)
const {
305 [[nodiscard]]
size_t index(
const T* p)
const {
308 : (stop - first) + (p - buf);
311 [[nodiscard]] T* allocate(
size_t n) {
312 return (n == 0) ? nullptr
313 :
static_cast<T*
>(malloc(n *
sizeof(T)));
321 void reset(T* new_buf, T* new_last,
size_t new_capacity) {
323 siz = new_last - new_buf;
324 first = buf = new_buf;
325 stop = buf + new_capacity;
326 last = new_last == stop ? buf : new_last;
358 void push_back(U&& u) { checkGrow(); buf.push_back(std::forward<U>(u)); }
366 T
t = std::move(buf.front());
371 [[nodiscard]]
const T&
front()
const {
return buf.front(); }
372 [[nodiscard]]
const T&
back()
const {
return buf.back(); }
373 [[nodiscard]]
const T&
operator[](
size_t i)
const {
return buf[i]; }
375 [[nodiscard]]
auto begin() {
return buf.begin(); }
376 [[nodiscard]]
auto end() {
return buf.end(); }
377 [[nodiscard]]
auto begin()
const {
return buf.begin(); }
378 [[nodiscard]]
auto end()
const {
return buf.end(); }
379 [[nodiscard]]
auto rbegin() {
return buf.rbegin(); }
380 [[nodiscard]]
auto rbegin()
const {
return buf.rbegin(); }
381 [[nodiscard]]
auto rend() {
return buf.rend(); }
382 [[nodiscard]]
auto rend()
const {
return buf.rend(); }
384 [[nodiscard]]
size_t size()
const {
return buf.size(); }
385 [[nodiscard]]
bool empty()
const {
return buf.empty(); }
394 buf.set_capacity(
std::max(
size_t(4), buf.capacity() * 2));
This code is heavily based on boost circular_buffer: http://www.boost.org/doc/libs/1_55_0/doc/html/ci...
bool operator==(const cb_iterator &it) const
cb_iterator(const cb_iterator &it)
T & operator[](difference_type n) const
cb_iterator & operator--()
cb_iterator & operator=(const cb_iterator &it)
std::random_access_iterator_tag iterator_category
cb_iterator(const BUF *buf_, T *p_)
cb_iterator & operator-=(difference_type n)
ptrdiff_t difference_type
cb_iterator & operator+=(difference_type n)
bool operator>(const cb_iterator &it) const
bool operator<(const cb_iterator &it) const
cb_iterator operator--(int)
cb_iterator operator+(difference_type n)
cb_iterator & operator++()
cb_iterator operator-(difference_type n)
bool operator<=(const cb_iterator &it) const
bool operator!=(const cb_iterator &it) const
bool operator>=(const cb_iterator &it) const
difference_type operator-(const cb_iterator &it) const
cb_iterator operator++(int)
This implements a queue on top of circular_buffer (not part of boost).
cb_queue(size_t capacity)
void push_back(std::initializer_list< U > list)
typename circular_buffer< T >::reverse_iterator reverse_iterator
typename circular_buffer< T >::const_iterator const_iterator
typename circular_buffer< T >::iterator iterator
const T & operator[](size_t i) const
typename circular_buffer< T >::value_type value_type
typename circular_buffer< T >::const_reverse_iterator const_reverse_iterator
Circular buffer class, based on boost::circular_buffer/.
std::reverse_iterator< const_iterator > const_reverse_iterator
circular_buffer & operator=(const circular_buffer &cb)
std::reverse_iterator< iterator > reverse_iterator
void push_front(const T &t)
circular_buffer(circular_buffer &&cb) noexcept
void set_capacity(size_t new_capacity)
void push_back(const T &t)
circular_buffer()=default
auto & operator[](size_t i)
ptrdiff_t difference_type
void push_back(std::initializer_list< T > list)
cb_iterator< circular_buffer< T >, const T > const_iterator
circular_buffer & operator=(circular_buffer &&cb) noexcept
void swap(circular_buffer &cb) noexcept
circular_buffer(size_t buffer_capacity)
auto & operator[](size_t i) const
cb_iterator< circular_buffer< T >, T > iterator
circular_buffer(const circular_buffer &cb)
constexpr vecN< N, T > min(const vecN< N, T > &x, const vecN< N, T > &y)
constexpr vecN< N, T > max(const vecN< N, T > &x, const vecN< N, T > &y)
uint32_t next(octet_iterator &it, octet_iterator end)