24#include "lib/stdcompat/utility.h"
25#include "pw_allocator/allocator.h"
26#include "pw_allocator/unique_ptr.h"
27#include "pw_assert/assert.h"
28#include "pw_containers/internal/count_and_capacity.h"
29#include "pw_containers/internal/generic_deque.h"
30#include "pw_containers/storage.h"
31#include "pw_polyfill/language_feature_macros.h"
32#include "pw_span/span.h"
52template <
typename T,
typename SizeType = u
int16_t>
56 containers::internal::CountAndCapacity<SizeType>> {
61 containers::internal::CountAndCapacity<SizeType>>;
64 using typename Base::const_iterator;
65 using typename Base::const_pointer;
66 using typename Base::const_reference;
67 using typename Base::difference_type;
68 using typename Base::iterator;
69 using typename Base::pointer;
70 using typename Base::reference;
71 using typename Base::size_type;
72 using typename Base::value_type;
81 :
Deque(Aligned::Align(buffer)) {}
85 template <
size_t kAlignment,
size_t kSizeBytes>
88 :
Deque(Aligned(buffer.data(), buffer.size())) {
89 static_assert(kAlignment >=
alignof(value_type));
102 constexpr size_type max_size() const noexcept {
return Base::capacity(); }
107 template <
typename,
typename>
110 template <
typename,
size_t,
typename>
111 friend class FixedDeque;
113 static constexpr bool kFixedCapacity =
true;
119 static constexpr Aligned Align(span<std::byte> unaligned_buffer) {
120 Aligned buffer(unaligned_buffer.data(), unaligned_buffer.size());
122 if constexpr (
alignof(value_type) >
alignof(std::byte)) {
123 void* data_void = buffer.data_;
124 buffer.data_ =
static_cast<std::byte*
>(std::align(
125 alignof(value_type),
sizeof(value_type), data_void, buffer.size_));
126 if (buffer.data_ ==
nullptr) {
134 constexpr Aligned(std::byte* aligned_data,
size_t size_bytes)
135 : data_(aligned_data), size_(size_bytes) {}
137 constexpr std::byte* data()
const {
return data_; }
138 constexpr size_t capacity()
const {
return size_ /
sizeof(value_type); }
145 explicit constexpr Deque(Aligned buffer) noexcept
146 : Base(
static_cast<size_type
>(buffer.capacity())),
147 buffer_(buffer.data()) {}
149 constexpr void MoveBufferFrom(Deque& other)
noexcept {
151 buffer_ = cpp20::exchange(other.buffer_,
nullptr);
152 Base::MoveAssignIndices(other);
155 void MoveItemsFrom(Deque& other) {
156 this->
assign(std::make_move_iterator(other.begin()),
157 std::make_move_iterator(other.end()));
161 void SwapBufferWith(Deque& other)
noexcept {
162 Base::SwapIndices(other);
163 std::swap(buffer_, other.buffer_);
166 void SwapValuesWith(Deque& other);
168 pointer data() {
return std::launder(
reinterpret_cast<pointer
>(buffer_)); }
169 const_pointer data()
const {
170 return std::launder(
reinterpret_cast<const_pointer
>(buffer_));
190 typename SizeType = uint16_t>
193 public Deque<T, SizeType> {
198 : containers::internal::ArrayStorage<T, kInlineCapacity>{},
213 template <
size_t kOtherCapacity,
214 typename = std::enable_if_t<kOtherCapacity <= kInlineCapacity>>
219 template <
size_t kOtherCapacity,
220 typename = std::enable_if_t<kOtherCapacity <= kInlineCapacity>>
229 template <
size_t kOtherCapacity>
231 this->SwapValuesWith(other);
235 static_assert(kInlineCapacity <= std::numeric_limits<SizeType>::max(),
236 "The capacity is too large for the size; use a large SizeType");
246template <
typename T,
typename SizeType>
247class FixedDeque<T, containers::kAllocatedStorage, SizeType> final
249 public Deque<T, SizeType> {
265 std::byte* array =
static_cast<std::byte*
>(allocator.
Allocate(layout));
266 return FixedDeque(allocator, array, array !=
nullptr ? layout.size() : 0u);
275 span(storage_unique_ptr.get(), storage_unique_ptr.size())) {}
283 other.storage_unique_ptr)},
285 this->MoveBufferFrom(other);
289 this->MoveBufferFrom(other);
296 this->SwapBufferWith(other);
297 std::swap(storage_unique_ptr, other.storage_unique_ptr);
303 template <
size_t kInlineCapacity>
310 : containers::internal::DynamicStorage{
UniquePtr<std::byte[]>(
311 aligned_buffer, size_bytes, allocator)},
312 Deque<T, SizeType>(typename
Deque<T, SizeType>::Aligned(
313 storage_unique_ptr.get(), size_bytes)) {}
316template <
typename T,
typename SizeType>
317void Deque<T, SizeType>::SwapValuesWith(Deque& other) {
321 if (this->size() < other.size()) {
329 const SizeType smaller_size = smaller->
size();
331 std::swap_ranges(smaller->begin(), smaller->end(), larger->begin());
334 smaller->push_back(std::move(*it));
337 while (larger->size() > smaller_size) {
Definition: allocator.h:36
void * Allocate(Layout layout)
Definition: allocator.h:44
Definition: unique_ptr.h:43
Definition: generic_deque.h:185
constexpr size_type size() const noexcept
Returns the number of elements in the deque.
Definition: generic_deque.h:69
constexpr size_type capacity() const noexcept
Returns the maximum number of elements in the deque.
Definition: generic_deque.h:74
Definition: span_impl.h:235
FixedDeque(UniquePtr< std::byte[]> &&storage) noexcept
Definition: deque.h:272
void swap(FixedDeque< T, kInlineCapacity, SizeType > &other)
Definition: deque.h:304
Deque(const Deque &)=delete
Copying is not supported since it can fail.
void swap(FixedDeque< T, kOtherCapacity, SizeType > &other)
Definition: deque.h:230
constexpr Deque(span< std::byte > buffer) noexcept
Definition: deque.h:80
constexpr Deque(containers::Storage< kAlignment, kSizeBytes > &buffer) noexcept
Definition: deque.h:86
FixedDeque(FixedDeque &&other) noexcept
Definition: deque.h:281
static FixedDeque Allocate(Allocator &allocator, const SizeType capacity)
Definition: deque.h:254
constexpr FixedDeque()
Definition: deque.h:197
void swap(FixedDeque &other) noexcept
Definition: deque.h:295
Deque(Deque &&)=delete
Move is not supported to avoid confusion about deque/buffer pairings.
void assign(size_type count, const value_type &value)
Sets the contents to count copies of value. Crashes if cannot fit.
Definition: generic_deque.h:216
static FixedDeque TryAllocate(Allocator &allocator, SizeType capacity)
Definition: deque.h:263
constexpr size_t kAllocatedStorage
Definition: storage.h:78
#define PW_CONSTEXPR_CPP20
Definition: language_feature_macros.h:27
The Pigweed namespace.
Definition: alignment.h:27