22#include "pw_assert/assert.h"
23#include "pw_bytes/span.h"
24#include "pw_containers/internal/var_len_entry.h"
25#include "pw_containers/internal/var_len_entry_queue_iterator.h"
26#include "pw_containers/internal/wrap.h"
27#include "pw_preprocessor/compiler.h"
28#include "pw_span/cast.h"
29#include "pw_span/span.h"
36#define PW_VAR_QUEUE_DATA_SIZE_BYTES(max_size_bytes) \
37 (PW_VARINT_ENCODED_SIZE_BYTES(max_size_bytes) + max_size_bytes + \
41namespace pw::containers::internal {
44class GenericVarLenEntryQueueBase;
46template <
typename Derived,
typename T>
47class GenericVarLenEntryQueue;
49template <
typename D1,
typename T1,
typename D2,
typename T2>
50constexpr void CopyVarLenEntriesImpl(
const GenericVarLenEntryQueue<D1, T1>& src,
51 GenericVarLenEntryQueue<D2, T2>& dst,
54template <
typename D1,
typename T1,
typename D2,
typename T2>
55constexpr void MoveVarLenEntriesImpl(GenericVarLenEntryQueue<D1, T1>& src,
56 GenericVarLenEntryQueue<D2, T2>& dst,
65 size_t total_data_size;
116 bytes.begin() +
static_cast<span<std::byte>::difference_type
>(head),
121 template <
typename D1,
typename T1,
typename D2,
typename T2>
122 friend constexpr void CopyVarLenEntriesImpl(
127 template <
typename D1,
typename T1,
typename D2,
typename T2>
128 friend constexpr void MoveVarLenEntriesImpl(
138template <
typename Derived,
typename T>
156 constexpr const_iterator
begin()
const {
157 return const_iterator(GetBuffer(), GetHead());
159 constexpr const_iterator cbegin()
const {
return begin(); }
163 constexpr const_iterator
end()
const {
164 return const_iterator(GetBuffer(), GetTail());
166 constexpr const_iterator cend()
const {
return end(); }
169 [[nodiscard]]
constexpr bool empty()
const {
return GetHead() == GetTail(); }
173 constexpr size_t size()
const {
174 return Base::GetInfo(GetBytes(), GetHead(), GetTail()).num_entries;
179 constexpr size_t max_size()
const {
return GetBuffer().size() - 1; }
184 return Base::GetInfo(GetBytes(), GetHead(), GetTail()).total_data_size;
218 return Push(data,
false);
252 constexpr size_t GetHead()
const {
return derived().head(); }
253 constexpr void SetHead(
size_t head) {
return derived().set_head(head); }
254 constexpr size_t GetTail()
const {
return derived().tail(); }
255 constexpr void SetTail(
size_t tail) {
return derived().set_tail(tail); }
256 constexpr span<T> GetBuffer() {
return derived().buffer(); }
257 constexpr span<const T> GetBuffer()
const {
return derived().buffer(); }
262 constexpr ByteSpan GetBytes() {
return AsWritableBytes(GetBuffer()); }
263 constexpr ConstByteSpan GetBytes()
const {
return AsBytes(GetBuffer()); }
267 template <
typename D1,
typename T1,
typename D2,
typename T2>
268 friend constexpr void CopyVarLenEntriesImpl(
269 const GenericVarLenEntryQueue<D1, T1>& src,
270 GenericVarLenEntryQueue<D2, T2>& dst,
273 template <
typename D1,
typename T1,
typename D2,
typename T2>
274 friend constexpr void MoveVarLenEntriesImpl(
275 GenericVarLenEntryQueue<D1, T1>& src,
276 GenericVarLenEntryQueue<D2, T2>& dst,
279 static_assert(std::is_integral_v<T> || std::is_same_v<T, std::byte>);
280 static_assert(
sizeof(T) ==
sizeof(std::byte));
282 constexpr Derived& derived() {
return *
static_cast<Derived*
>(
this); }
283 constexpr const Derived& derived()
const {
284 return *
static_cast<const Derived*
>(
this);
289 static constexpr ByteSpan AsWritableBytes(span<T> data);
293 static constexpr ConstByteSpan AsBytes(span<const T> data);
298 constexpr bool Push(span<const T> data,
bool overwrite);
303template <
typename D1,
typename T1,
typename D2,
typename T2>
304constexpr void CopyVarLenEntries(
const GenericVarLenEntryQueue<D1, T1>& src,
305 GenericVarLenEntryQueue<D2, T2>& dst) {
306 CopyVarLenEntriesImpl(src, dst,
false);
313template <
typename D1,
typename T1,
typename D2,
typename T2>
314constexpr void CopyVarLenEntriesOverwrite(
315 const GenericVarLenEntryQueue<D1, T1>& src,
316 GenericVarLenEntryQueue<D2, T2>& dst) {
317 CopyVarLenEntriesImpl(src, dst,
true);
322template <
typename D1,
typename T1,
typename D2,
typename T2>
323constexpr void MoveVarLenEntries(GenericVarLenEntryQueue<D1, T1>& src,
324 GenericVarLenEntryQueue<D2, T2>& dst) {
325 MoveVarLenEntriesImpl(src, dst,
false);
332template <
typename D1,
typename T1,
typename D2,
typename T2>
333constexpr void MoveVarLenEntriesOverwrite(
334 GenericVarLenEntryQueue<D1, T1>& src,
335 GenericVarLenEntryQueue<D2, T2>& dst) {
336 MoveVarLenEntriesImpl(src, dst,
true);
342constexpr GenericVarLenEntryQueueBase::Info
347 while (head != tail) {
348 auto [prefix_size, data_size] = ReadVarLenEntrySize(bytes, head);
349 size_t entry_size = ReadVarLenEntryEncodedSize(bytes, head);
350 IncrementWithWrap(head, entry_size, bytes.size());
352 info.total_data_size += data_size;
359 PW_ASSERT(head < bytes.size());
360 PW_ASSERT(tail < bytes.size());
362 head += bytes.size();
364 return head - tail - 1;
374 auto size_u32 =
static_cast<uint32_t
>(data.size());
375 size_t encoded = varint::Encode(size_u32,
ByteSpan(tmp,
sizeof(tmp)));
379 size_t needed_bytes = prefix.size() + data.size();
380 PW_ASSERT(needed_bytes < bytes.size());
385 while (needed_bytes > available_bytes) {
389 if (needed_bytes > available_bytes) {
402 size_t entry_size = ReadVarLenEntryEncodedSize(bytes, head);
403 IncrementWithWrap(head, entry_size, bytes.size());
416 size_t offset = src_head;
417 while (src_head != src_tail) {
418 size_t src_entry_size = ReadVarLenEntryEncodedSize(src_bytes, src_head);
419 if (src_entry_size <= available) {
422 }
else if (!overwrite) {
426 }
else if ((dst_bytes.size() - 1) < src_entry_size ||
427 (dst_bytes.size() - 1 - src_entry_size) < to_copy) {
433 while (dst_head != dst_tail && available < src_entry_size) {
434 size_t dst_entry_size = ReadVarLenEntryEncodedSize(dst_bytes, dst_head);
435 IncrementWithWrap(dst_head, dst_entry_size, dst_bytes.size());
436 available += dst_entry_size;
441 to_copy += src_entry_size;
442 available -= src_entry_size;
443 IncrementWithWrap(src_head, src_entry_size, src_bytes.size());
449 size_t src_chunk = src_bytes.size() - offset;
450 if (src_chunk >= to_copy) {
451 CopyAndWrap(src_bytes.subspan(offset, to_copy), dst_bytes, dst_tail);
453 CopyAndWrap(src_bytes.subspan(offset), dst_bytes, dst_tail);
454 CopyAndWrap(src_bytes.subspan(0, to_copy - src_chunk), dst_bytes, dst_tail);
467 size_t first_chunk = bytes.size() - tail;
468 if (first_chunk >= data.size()) {
469 first_chunk = data.size();
472 static_cast<span<std::byte>::difference_type
>(first_chunk),
478 data.begin() +
static_cast<span<std::byte>::difference_type
>(first_chunk),
479 bytes.begin() +
static_cast<span<std::byte>::difference_type
>(tail));
480 IncrementWithWrap(tail, data.size(), bytes.size());
483constexpr std::pair<ConstByteSpan, ConstByteSpan>
491 return std::make_pair(bytes.subspan(head, tail - head),
ConstByteSpan());
493 return std::make_pair(bytes.subspan(head), bytes.subspan(0, tail));
499template <
typename Derived,
typename T>
506template <
typename Derived,
typename T>
513template <
typename Derived,
typename T>
516 size_t head = GetHead();
517 PopNonEmpty(GetBytes(), head);
521template <
typename Derived,
typename T>
527template <
typename Derived,
typename T>
530 auto [first, second] =
531 Base::ContiguousRawStorage(GetBytes(), GetHead(), GetTail());
532 return std::make_pair(span_cast<const T>(first), span_cast<const T>(second));
535template <
typename Derived,
typename T>
538 size_t tail = encoded_size_bytes();
539 Base::Dering(bytes, GetHead());
542 return span_cast<const T>(bytes.subspan(0, tail));
545template <
typename Derived,
typename T>
548 if constexpr (std::is_same_v<T, std::byte>) {
551 return as_writable_bytes(data);
555template <
typename Derived,
typename T>
556constexpr ConstByteSpan GenericVarLenEntryQueue<Derived, T>::AsBytes(
557 span<const T> data) {
558 if constexpr (std::is_same_v<T, std::byte>) {
561 return as_bytes(data);
565template <
typename Derived,
typename T>
566constexpr bool GenericVarLenEntryQueue<Derived, T>::Push(span<const T> data,
568 size_t head = GetHead();
569 size_t tail = GetTail();
570 bool result = Base::Push(AsBytes(data), overwrite, GetBytes(), head, tail);
576template <
typename D1,
typename T1,
typename D2,
typename T2>
577constexpr void CopyVarLenEntriesImpl(
const GenericVarLenEntryQueue<D1, T1>& src,
578 GenericVarLenEntryQueue<D2, T2>& dst,
580 size_t src_head = src.GetHead();
581 size_t dst_head = dst.GetHead();
582 size_t dst_tail = dst.GetTail();
590 dst.SetHead(dst_head);
591 dst.SetTail(dst_tail);
594template <
typename D1,
typename T1,
typename D2,
typename T2>
595constexpr void MoveVarLenEntriesImpl(GenericVarLenEntryQueue<D1, T1>& src,
596 GenericVarLenEntryQueue<D2, T2>& dst,
598 size_t src_head = src.GetHead();
599 size_t dst_head = dst.GetHead();
600 size_t dst_tail = dst.GetTail();
608 src.SetHead(src_head);
609 dst.SetHead(dst_head);
610 dst.SetTail(dst_tail);
Definition: generic_var_len_entry_queue.h:61
static constexpr std::pair< ConstByteSpan, ConstByteSpan > ContiguousRawStorage(ConstByteSpan bytes, size_t head, size_t tail)
Definition: generic_var_len_entry_queue.h:484
static constexpr Info GetInfo(ConstByteSpan bytes, size_t head, size_t tail)
Definition: generic_var_len_entry_queue.h:343
static void Dering(ByteSpan bytes, size_t head)
Moves entries to be contiguous and start from the beginning of the buffer.
Definition: generic_var_len_entry_queue.h:113
static constexpr size_t PopNonEmpty(ConstByteSpan bytes, size_t &head)
Removes an entry from the head of the queue. Must not be empty.
Definition: generic_var_len_entry_queue.h:400
static constexpr void CopyAndWrap(ConstByteSpan data, ByteSpan bytes, size_t &tail)
Copies data to the buffer, wrapping around the end if needed.
Definition: generic_var_len_entry_queue.h:458
static constexpr bool Push(ConstByteSpan data, bool overwrite, ByteSpan bytes, size_t &head, size_t &tail)
Add an entry to the tail of the queue.
Definition: generic_var_len_entry_queue.h:367
static constexpr void CopyEntries(ConstByteSpan src_bytes, size_t &src_head, size_t src_tail, ByteSpan dst_bytes, size_t &dst_head, size_t &dst_tail, bool overwrite)
Definition: generic_var_len_entry_queue.h:407
static constexpr size_t AvailableBytes(ConstByteSpan bytes, size_t head, size_t tail)
Returns the number of bytes not being used to store entries.
Definition: generic_var_len_entry_queue.h:357
Definition: generic_var_len_entry_queue.h:139
constexpr size_t encoded_size_bytes() const
Definition: generic_var_len_entry_queue.h:189
span< const T > dering()
Moves entries to be contiguous and start from the beginning of the buffer.
Definition: generic_var_len_entry_queue.h:536
constexpr bool try_push(span< const T > data)
Definition: generic_var_len_entry_queue.h:217
constexpr iterator begin()
Returns an iterator to the start of the queue.
Definition: generic_var_len_entry_queue.h:155
constexpr void push_overwrite(span< const T > data)
Definition: generic_var_len_entry_queue.h:226
constexpr std::pair< span< const T >, span< const T > > contiguous_raw_storage() const
Definition: generic_var_len_entry_queue.h:529
constexpr value_type front()
Definition: generic_var_len_entry_queue.h:501
constexpr iterator end()
Returns an iterator to the end of the queue.
Definition: generic_var_len_entry_queue.h:162
constexpr size_t size_bytes() const
Definition: generic_var_len_entry_queue.h:183
constexpr size_t size() const
Definition: generic_var_len_entry_queue.h:173
constexpr void push(span< const T > data)
Definition: generic_var_len_entry_queue.h:210
static constexpr size_t DataSizeBytes(size_t max_size_bytes)
Definition: generic_var_len_entry_queue.h:150
constexpr size_t max_size() const
Definition: generic_var_len_entry_queue.h:179
constexpr void clear()
Empties the queue.
Definition: generic_var_len_entry_queue.h:522
constexpr size_t max_size_bytes() const
Definition: generic_var_len_entry_queue.h:197
constexpr bool empty() const
Returns true if the queue is empty, false if it has at least one entry.
Definition: generic_var_len_entry_queue.h:169
constexpr void pop()
Definition: generic_var_len_entry_queue.h:514
Refers to an entry in-place in the queue. Entries may be discontiguous.
Definition: var_len_entry.h:65
Definition: var_len_entry_queue_iterator.h:46
constexpr OutputIt copy(InputIt first, InputIt last, OutputIt d_first)
constexpr backport of <algorithm>'s std::copy for C++17.
Definition: algorithm.h:355
constexpr size_t kMaxVarint32SizeBytes
Maximum size of a varint (LEB128) encoded uint32_t.
Definition: varint.h:74
constexpr size_t EncodedSize(T value)
Computes the size of an integer when encoded as a varint.
Definition: varint.h:123
Definition: generic_var_len_entry_queue.h:63