Pigweed
C/C++ API Reference
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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#include "pw_containers/internal/generic_queue.h"
21
22namespace pw {
23namespace containers::internal {
24
25template <typename Derived, typename Deque>
26class BasicInlineQueueImpl;
27
28} // namespace containers::internal
29
30template <typename T, typename SizeType, size_t kCapacity>
31class BasicInlineQueue;
32
41template <typename T, size_t kCapacity = containers::internal::kGenericSized>
43
44template <typename ValueType,
45 typename SizeType,
46 size_t kCapacity = containers::internal::kGenericSized>
48 : public BasicInlineQueue<ValueType,
49 SizeType,
50 containers::internal::kGenericSized> {
51 private:
52 using Base = BasicInlineQueue<ValueType,
53 SizeType,
54 containers::internal::kGenericSized>;
55
56 public:
57 using typename Base::const_iterator;
58 using typename Base::const_pointer;
59 using typename Base::const_reference;
60 using typename Base::difference_type;
61 using typename Base::iterator;
62 using typename Base::pointer;
63 using typename Base::reference;
64 using typename Base::size_type;
65 using typename Base::value_type;
66
67 // Constructors
68
69 BasicInlineQueue() noexcept {}
70
71 // Explicit zero element constexpr constructor. Using this constructor will
72 // place the entire object in .data, which will increase ROM size. Use with
73 // caution if working with large capacity sizes.
74 constexpr BasicInlineQueue(ConstexprTag constexpr_tag) noexcept
75 : deque_(constexpr_tag) {}
76
77 BasicInlineQueue(size_type count, const_reference value)
78 : deque_(count, value) {}
79
80 explicit BasicInlineQueue(size_type count) : deque_(count) {}
81
82 template <
83 typename InputIterator,
84 typename = containers::internal::EnableIfInputIterator<InputIterator>>
85 BasicInlineQueue(InputIterator start, InputIterator finish)
86 : deque_(start, finish) {}
87
88 BasicInlineQueue(const std::initializer_list<value_type>& list)
89 : deque_(list) {}
90
92 BasicInlineQueue(const BasicInlineQueue& other) : deque_(other) {}
93
97 template <size_t kOtherCapacity>
100 *this = other;
101 }
102
105 : deque_(std::move(other.deque_)) {}
106
110 template <size_t kOtherCapacity>
113 *this = std::move(other);
114 }
115
116 template <typename T, typename = containers::internal::EnableIfIterable<T>>
117 BasicInlineQueue(const T& other) : deque_(other.begin(), other.end()) {}
118
119 BasicInlineQueue& operator=(const std::initializer_list<value_type>& list) {
120 deque_ = std::move(list);
121 return *this;
122 }
123
126 deque_ = other.deque_;
127 return *this;
128 }
129
133 template <size_t kOtherCapacity>
136 deque_ = other.deque_;
137 return *this;
138 }
139
142 deque_ = std::move(other.deque_);
143 return *this;
144 }
145
149 template <size_t kOtherCapacity>
152 deque_ = std::move(other.deque_);
153 return *this;
154 }
155
156 template <typename T, typename = containers::internal::EnableIfIterable<T>>
157 BasicInlineQueue& operator=(const T& other) {
159 other.end());
160 return *this;
161 }
162
163 // Size
164
165 static constexpr size_type max_size() { return capacity(); }
166 static constexpr size_type capacity() { return kCapacity; }
167
168 private:
169 template <typename OtherValueType, typename OtherSizeType, size_t kOtherSized>
170 friend class BasicInlineQueue;
171
172 template <typename, typename>
173 friend class containers::internal::BasicInlineQueueImpl;
174
175 // The deque() function is defined differently for the generic-sized and
176 // known-sized specializations. This deque() implementation simply returns the
177 // generic-sized deque_. The generic-sized deque() function casts *this to a
178 // known zero-sized specialzation to access this exact function.
179 BasicInlineDeque<ValueType, SizeType>& deque() { return deque_; }
180 const BasicInlineDeque<ValueType, SizeType>& deque() const { return deque_; }
181
182 BasicInlineDeque<ValueType, SizeType, kCapacity> deque_;
183};
184
185// Defines the generic-sized BasicInlineDeque<T> specialization, which
186// serves as the base class for BasicInlineDeque<T> of any capacity.
187//
188// Except for constructors, all other methods should be implemented on this
189// generic-sized specialization.
190template <typename ValueType, typename SizeType>
191class BasicInlineQueue<ValueType, SizeType, containers::internal::kGenericSized>
193 BasicInlineQueue<ValueType,
194 SizeType,
195 containers::internal::kGenericSized>,
196 BasicInlineDeque<ValueType, SizeType>> {
197 private:
200 BasicInlineQueue<ValueType,
201 SizeType,
202 containers::internal::kGenericSized>,
203 Deque>;
204
205 public:
206 using typename Base::const_iterator;
207 using typename Base::const_pointer;
208 using typename Base::const_reference;
209 using typename Base::difference_type;
210 using typename Base::iterator;
211 using typename Base::pointer;
212 using typename Base::reference;
213 using typename Base::size_type;
214 using typename Base::value_type;
215
216 protected:
217 constexpr BasicInlineQueue() noexcept = default;
218
219 // Polymorphic-sized `pw::InlineQueue<T>` may not be used with `unique_ptr`
220 // or `delete`. `delete` could be supported using C++20's destroying delete.
221 ~BasicInlineQueue() = default;
222
223 protected:
224 template <typename, typename>
225 friend class containers::internal::GenericQueue;
226
227 template <size_t kCapacity>
229
230 // The underlying BasicInlineDeque is not part of the generic-sized class. It
231 // is provided in the derived class from which this instance was constructed.
232 // To access the data, down-cast this to a known max size specialization, and
233 // return a reference to a generic-sized BasicInlineDeque, which is the same
234 // reference for all sizes.
235 Deque& deque() { return static_cast<Derived<0>*>(this)->deque(); }
236 const Deque& deque() const {
237 return static_cast<const Derived<0>*>(this)->deque();
238 }
239};
240
241namespace containers::internal {
242
243template <typename Derived, typename Deque>
244class BasicInlineQueueImpl : public GenericQueue<Derived, Deque> {
245 private:
246 using Base = GenericQueue<Derived, Deque>;
247
248 public:
249 using typename Base::const_iterator;
250 using typename Base::const_pointer;
251 using typename Base::const_reference;
252 using typename Base::difference_type;
253 using typename Base::iterator;
254 using typename Base::pointer;
255 using typename Base::reference;
256 using typename Base::size_type;
257 using typename Base::value_type;
258
259 // Access
260
261 reference at(size_type index) { return deque().at(index); }
262 const_reference at(size_type index) const { return deque().at(index); }
263
264 reference operator[](size_type index) { return deque()[index]; }
265 const_reference operator[](size_type index) const { return deque()[index]; }
266
267 std::pair<span<const value_type>, span<const value_type>> contiguous_data()
268 const {
269 return deque().contiguous_data();
270 }
271 std::pair<span<value_type>, span<value_type>> contiguous_data() {
272 return deque().contiguous_data();
273 }
274
275 // Iterate
276
277 iterator begin() noexcept { return deque().begin(); }
278 const_iterator begin() const noexcept { return cbegin(); }
279 const_iterator cbegin() const noexcept { return deque().cbegin(); }
280
281 iterator end() noexcept { return deque().end(); }
282 const_iterator end() const noexcept { return cend(); }
283 const_iterator cend() const noexcept { return deque().cend(); }
284
285 // Size
286
287 [[nodiscard]] bool full() const noexcept { return deque().full(); }
288
289 // Modify
290
291 void clear() noexcept { deque().clear(); }
292
293 void push_overwrite(const value_type& value) { emplace_overwrite(value); }
294
295 void push_overwrite(value_type&& value) {
296 emplace_overwrite(std::move(value));
297 }
298
299 template <typename... Args>
300 void emplace_overwrite(Args&&... args) {
301 if (full()) {
302 Base::pop();
303 }
304 Base::emplace(std::forward<Args>(args)...);
305 }
306
307 private:
308 using Base::deque;
309};
310
311} // namespace containers::internal
312} // namespace pw
Definition: inline_queue.h:50
BasicInlineQueue & operator=(BasicInlineQueue< ValueType, SizeType, kOtherCapacity > &&other)
Definition: inline_queue.h:150
BasicInlineQueue & operator=(const BasicInlineQueue< ValueType, SizeType, kOtherCapacity > &other)
Definition: inline_queue.h:134
BasicInlineQueue & operator=(BasicInlineQueue &&other)
Move assigns from matching capacity.
Definition: inline_queue.h:141
BasicInlineQueue & operator=(const BasicInlineQueue &other)
Copy assigns from matching capacity.
Definition: inline_queue.h:125
BasicInlineQueue(BasicInlineQueue &&other)
Move constructs for matching capacity.
Definition: inline_queue.h:104
BasicInlineQueue(BasicInlineQueue< ValueType, SizeType, kOtherCapacity > &&other)
Definition: inline_queue.h:111
BasicInlineQueue(const BasicInlineQueue< ValueType, SizeType, kOtherCapacity > &other)
Definition: inline_queue.h:98
BasicInlineQueue(const BasicInlineQueue &other)
Copy constructs for matching capacity.
Definition: inline_queue.h:92
Provides basic helpers for reading and writing UTF-8 encoded strings.
Definition: alignment.h:27
Definition: constexpr_tag.h:46