baudvine::RingBuf
STL-like ring buffer in C++11
deque_ringbuf.h
1 // Copyright © 2021 Dominic van Berkel <dominic@baudvine.net>
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to deal
5 // in the Software without restriction, including without limitation the rights
6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 // copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so.
9 //
10 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
11 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
13 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
14 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
15 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
16 // SOFTWARE.
17 
18 #pragma once
19 
20 #include <cstddef>
21 #include <deque>
22 #include <type_traits>
23 
24 namespace baudvine {
25 
26 // A ring buffer based on std::deque. Inefficient, but compact and easily
27 // verifiable.
28 template <typename Elem,
29  std::size_t Capacity,
30  typename Allocator = std::allocator<Elem>>
31 class DequeRingBuf {
32  public:
33  using storage = std::deque<Elem, Allocator>;
34  using allocator_type = typename storage::allocator_type;
35  using value_type = typename storage::value_type;
36  using reference = typename storage::reference;
37  using const_reference = typename storage::const_reference;
38  using iterator = typename storage::iterator;
39  using const_iterator = typename storage::const_iterator;
40  using reverse_iterator = typename storage::reverse_iterator;
41  using const_reverse_iterator = typename storage::const_reverse_iterator;
42  using difference_type = typename storage::difference_type;
43  using size_type = typename storage::size_type;
44 
45  private:
46  storage data_{};
47 
48  public:
49  DequeRingBuf() = default;
50  DequeRingBuf(const allocator_type& alloc) : data_(alloc) {}
51  DequeRingBuf(const DequeRingBuf& other, const allocator_type& allocator)
52  : data_(other.data_, allocator) {}
53  DequeRingBuf(DequeRingBuf&& other, const allocator_type& allocator)
54  : data_(std::move(other.data_), allocator) {}
55 
56  allocator_type get_allocator() const { return data_.get_allocator(); }
57 
58  reference front() { return data_.front(); }
59  const_reference front() const { return data_.front(); }
60  reference back() { return data_.back(); }
61  const_reference back() const { return data_.back(); }
62  reference at(size_type index) { return data_.at(index); }
63  const_reference at(size_type index) const { return data_.at(index); }
64  reference operator[](size_type index) { return data_[index]; }
65  const_reference operator[](size_type index) const { return data_[index]; }
66 
67  iterator begin() { return data_.begin(); }
68  iterator end() { return data_.end(); }
69  const_iterator begin() const { return data_.begin(); }
70  const_iterator end() const { return data_.end(); }
71  const_iterator cbegin() const { return data_.cbegin(); }
72  const_iterator cend() const { return data_.cend(); }
73  reverse_iterator rbegin() { return data_.rbegin(); }
74  reverse_iterator rend() { return data_.rend(); }
75  const_reverse_iterator rbegin() const { return data_.rbegin(); }
76  const_reverse_iterator rend() const { return data_.rend(); }
77  const_reverse_iterator crbegin() const { return data_.crbegin(); }
78  const_reverse_iterator crend() const { return data_.crend(); }
79 
80  bool empty() const { return data_.empty(); }
81  size_type size() const { return data_.size(); }
82  constexpr size_type max_size() const { return Capacity; }
83 
84  void clear() noexcept(noexcept(data_.clear())) { return data_.clear(); }
85  iterator erase(const_iterator pos) noexcept(noexcept(data_.erase(pos))) {
86  return data_.erase(pos);
87  }
88  iterator erase(const_iterator first,
89  const_iterator last) noexcept(noexcept(data_.erase(first,
90  last))) {
91  return data_.erase(first, last);
92  }
93 
94  void push_front(const_reference value) { emplace_front(value); }
95  void push_front(value_type&& value) { emplace_front(std::move(value)); }
96 
97  template <typename... Args>
98  reference emplace_front(Args&&... args) {
99  if (max_size() == 0) {
100  return data_.front();
101  }
102 
103  data_.emplace_front(std::forward<Args>(args)...);
104 
105  if (size() > max_size()) {
106  pop_back();
107  }
108  return data_.front();
109  }
110 
111  void push_back(const_reference value) { emplace_back(value); }
112  void push_back(value_type&& value) { emplace_back(std::move(value)); }
113 
114  template <typename... Args>
115  reference emplace_back(Args&&... args) {
116  if (max_size() == 0) {
117  return data_.back();
118  }
119 
120  data_.emplace_back(std::forward<Args>(args)...);
121 
122  if (size() > max_size()) {
123  pop_front();
124  }
125  return data_.back();
126  }
127 
128  void pop_front() noexcept(noexcept(data_.pop_front())) {
129  return data_.pop_front();
130  }
131  void pop_back() noexcept(noexcept(data_.pop_back())) {
132  return data_.pop_back();
133  }
134 
135  void swap(DequeRingBuf& other) noexcept(noexcept(data_.swap(other.data_))) {
136  return data_.swap(other.data_);
137  }
138 
139  friend bool operator<(const DequeRingBuf& lhs, const DequeRingBuf& rhs) {
140  return lhs.data_ < rhs.data_;
141  }
142  friend bool operator>(const DequeRingBuf& lhs, const DequeRingBuf& rhs) {
143  return lhs.data_ > rhs.data_;
144  }
145  friend bool operator<=(const DequeRingBuf& lhs, const DequeRingBuf& rhs) {
146  return lhs.data_ <= rhs.data_;
147  }
148  friend bool operator>=(const DequeRingBuf& lhs, const DequeRingBuf& rhs) {
149  return lhs.data_ >= rhs.data_;
150  }
151  friend bool operator==(const DequeRingBuf& lhs, const DequeRingBuf& rhs) {
152  return lhs.data_ == rhs.data_;
153  }
154  friend bool operator!=(const DequeRingBuf& lhs, const DequeRingBuf& rhs) {
155  return lhs.data_ != rhs.data_;
156  }
157 };
158 
159 } // namespace baudvine
baudvine::DequeRingBuf
Definition: deque_ringbuf.h:31
baudvine
The baudvine "project".
Definition: deque_ringbuf.h:24