Pigweed
 
Loading...
Searching...
No Matches
inline_queue.h
1// Copyright 2023 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14#pragma once
15
16#include <initializer_list>
17#include <utility>
18
19#include "pw_containers/inline_deque.h"
20
21namespace pw {
22
23template <typename T, typename SizeType, size_t kCapacity>
24class BasicInlineQueue;
25
34template <typename T, size_t kCapacity = containers::internal::kGenericSized>
36
37template <typename ValueType,
38 typename SizeType,
39 size_t kCapacity = containers::internal::kGenericSized>
41 : public BasicInlineQueue<ValueType,
42 SizeType,
43 containers::internal::kGenericSized> {
44 private:
45 using QueueBase = BasicInlineQueue<ValueType,
46 SizeType,
47 containers::internal::kGenericSized>;
48
49 public:
50 using typename QueueBase::const_iterator;
51 using typename QueueBase::const_pointer;
52 using typename QueueBase::const_reference;
53 using typename QueueBase::difference_type;
54 using typename QueueBase::iterator;
55 using typename QueueBase::pointer;
56 using typename QueueBase::reference;
57 using typename QueueBase::size_type;
58 using typename QueueBase::value_type;
59
60 // Constructors
61
62 BasicInlineQueue() noexcept : deque_() {}
63
64 // Explicit zero element constexpr constructor. Using this constructor will
65 // place the entire object in .data, which will increase ROM size. Use with
66 // caution if working with large capacity sizes.
67 constexpr BasicInlineQueue(ConstexprTag constexpr_tag) noexcept
68 : deque_(constexpr_tag) {}
69
70 BasicInlineQueue(size_type count, const_reference value)
71 : deque_(count, value) {}
72
73 explicit BasicInlineQueue(size_type count) : deque_(count) {}
74
75 template <
76 typename InputIterator,
77 typename = containers::internal::EnableIfInputIterator<InputIterator>>
78 BasicInlineQueue(InputIterator start, InputIterator finish)
79 : deque_(start, finish) {}
80
81 BasicInlineQueue(const std::initializer_list<value_type>& list) {
82 *this = list;
83 }
84
86 BasicInlineQueue(const BasicInlineQueue& other) { *this = other; }
87
91 template <size_t kOtherCapacity>
94 *this = other;
95 }
96
98 BasicInlineQueue(BasicInlineQueue&& other) { *this = std::move(other); }
99
103 template <size_t kOtherCapacity>
106 *this = std::move(other);
107 }
108
109 template <typename T, typename = containers::internal::EnableIfIterable<T>>
110 BasicInlineQueue(const T& other) {
111 *this = other;
112 }
113
114 //
115 BasicInlineQueue& operator=(const std::initializer_list<value_type>& list) {
116 deque_ = std::move(list);
117 return *this;
118 }
119
122 deque_ = other.deque_;
123 return *this;
124 }
125
129 template <size_t kOtherCapacity>
132 deque_ = other.deque_;
133 return *this;
134 }
135
138 deque_ = std::move(other.deque_);
139 return *this;
140 }
141
145 template <size_t kOtherCapacity>
148 deque_ = std::move(other.deque_);
149 return *this;
150 }
151
152 template <typename T, typename = containers::internal::EnableIfIterable<T>>
153 BasicInlineQueue& operator=(const T& other) {
155 other.end());
156 return *this;
157 }
158
159 // Size
160
161 static constexpr size_type max_size() { return capacity(); }
162 static constexpr size_type capacity() { return kCapacity; }
163
164 private:
165 template <typename OtherValueType, typename OtherSizeType, size_t kOtherSized>
166 friend class BasicInlineQueue;
167
168 // The deque() function is defined differently for the generic-sized and
169 // known-sized specializations. This data() implementation simply returns the
170 // generic-sized deque_. The generic-sized deque() function casts *this to a
171 // known zero-sized specialzation to access this exact function.
172 BasicInlineDeque<ValueType, SizeType>& deque() { return deque_; }
173 const BasicInlineDeque<ValueType, SizeType>& deque() const { return deque_; }
174
175 BasicInlineDeque<ValueType, SizeType, kCapacity> deque_;
176};
177
178// Defines the generic-sized BasicInlineDeque<T> specialization, which
179// serves as the base class for BasicInlineDeque<T> of any capacity.
180//
181// Except for constructors, all other methods should be implemented on this
182// generic-sized specialization.
183template <typename ValueType, typename SizeType>
184class BasicInlineQueue<ValueType,
185 SizeType,
186 containers::internal::kGenericSized> {
187 private:
189
190 public:
191 using const_iterator = typename Deque::const_iterator;
192 using const_pointer = typename Deque::const_pointer;
193 using const_reference = typename Deque::const_reference;
194 using difference_type = typename Deque::difference_type;
195 using iterator = typename Deque::iterator;
196 using pointer = typename Deque::pointer;
197 using reference = typename Deque::reference;
198 using size_type = typename Deque::size_type;
199 using value_type = typename Deque::value_type;
200
201 // Access
202
203 reference at(size_type index) { return deque().at(index); }
204 const_reference at(size_type index) const { return deque().at(index); }
205
206 reference operator[](size_type index) { return deque()[index]; }
207 const_reference operator[](size_type index) const { return deque()[index]; }
208
209 reference front() { return deque().front(); }
210 const_reference front() const { return deque().front(); }
211
212 reference back() { return deque().back(); }
213 const_reference back() const { return deque().back(); }
214
215 std::pair<span<const value_type>, span<const value_type>> contiguous_data()
216 const {
217 return deque().contiguous_data();
218 }
219 std::pair<span<value_type>, span<value_type>> contiguous_data() {
220 return deque().contiguous_data();
221 }
222
223 // Iterate
224
225 iterator begin() noexcept { return deque().begin(); }
226 const_iterator begin() const noexcept { return cbegin(); }
227 const_iterator cbegin() const noexcept { return deque().cbegin(); }
228
229 iterator end() noexcept { return deque().end(); }
230 const_iterator end() const noexcept { return cend(); }
231 const_iterator cend() const noexcept { return deque().cend(); }
232
233 // Size
234
235 [[nodiscard]] bool empty() const noexcept { return deque().empty(); }
236
237 [[nodiscard]] bool full() const noexcept { return deque().full(); }
238
239 size_type size() const noexcept { return deque().size(); }
240
241 size_type max_size() const noexcept { return capacity(); }
242
243 size_type capacity() const noexcept { return deque().capacity(); }
244
245 // Modify
246
247 void clear() noexcept { deque().clear(); }
248
249 void push(const value_type& value) { emplace(value); }
250
251 void push(value_type&& value) { emplace(std::move(value)); }
252
253 template <typename... Args>
254 void emplace(Args&&... args) {
255 deque().emplace_back(std::forward<Args>(args)...);
256 }
257
258 void push_overwrite(const value_type& value) { emplace_overwrite(value); }
259
260 void push_overwrite(value_type&& value) {
261 emplace_overwrite(std::move(value));
262 }
263
264 template <typename... Args>
265 void emplace_overwrite(Args&&... args) {
266 if (full()) {
267 pop();
268 }
269 emplace(std::forward<Args>(args)...);
270 }
271
272 void pop() { deque().pop_front(); }
273
274 protected:
275 constexpr BasicInlineQueue() noexcept = default;
276
277 // Polymorphic-sized `pw::InlineQueue<T>` may not be used with `unique_ptr`
278 // or `delete`. `delete` could be supported using C++20's destroying delete.
279 ~BasicInlineQueue() = default;
280
281 private:
282 // The underlying BasicInlineDeque is not part of the generic-sized class. It
283 // is provided in the derived class from which this instance was constructed.
284 // To access the data, down-cast this to a known max size specialization, and
285 // return a reference to a generic-sized BasicInlineDeque, which is the same
286 // reference for all sizes.
288 return static_cast<BasicInlineQueue<value_type, size_type, 0>*>(this)
289 ->deque();
290 }
291 const BasicInlineDeque<ValueType, SizeType>& deque() const {
292 return static_cast<const BasicInlineQueue<value_type, size_type, 0>*>(this)
293 ->deque();
294 }
295};
296
297} // namespace pw
Definition: inline_deque.h:76
Definition: inline_queue.h:43
BasicInlineQueue & operator=(BasicInlineQueue< ValueType, SizeType, kOtherCapacity > &&other)
Definition: inline_queue.h:146
BasicInlineQueue & operator=(const BasicInlineQueue< ValueType, SizeType, kOtherCapacity > &other)
Definition: inline_queue.h:130
BasicInlineQueue & operator=(BasicInlineQueue &&other)
Move assigns from matching capacity.
Definition: inline_queue.h:137
BasicInlineQueue & operator=(const BasicInlineQueue &other)
Copy assigns from matching capacity.
Definition: inline_queue.h:121
BasicInlineQueue(BasicInlineQueue &&other)
Move constructs for matching capacity.
Definition: inline_queue.h:98
BasicInlineQueue(BasicInlineQueue< ValueType, SizeType, kOtherCapacity > &&other)
Definition: inline_queue.h:104
BasicInlineQueue(const BasicInlineQueue< ValueType, SizeType, kOtherCapacity > &other)
Definition: inline_queue.h:92
BasicInlineQueue(const BasicInlineQueue &other)
Copy constructs for matching capacity.
Definition: inline_queue.h:86
Provides basic helpers for reading and writing UTF-8 encoded strings.
Definition: alignment.h:27
Definition: constexpr_tag.h:46