pw_containers: Rename VariableLengthEntryQueue

Rename VariableLengthEntryQueue to InlineVarLenEntryQueue. "Inline" is
important for describing the data structure and is necessary for
consistency with other Pigweed containers.

Change-Id: I171885a4944bade1468e72093c99cf4aef7cb651
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/187311
Pigweed-Auto-Submit: Wyatt Hepler <hepler@google.com>
Reviewed-by: Armando Montanez <amontanez@google.com>
Commit-Queue: Auto-Submit <auto-submit@pigweed-service-accounts.iam.gserviceaccount.com>
This commit is contained in:
Wyatt Hepler 2024-02-26 22:04:56 +00:00 committed by CQ Bot Account
parent 17c586758a
commit 55dcce2af4
6 changed files with 291 additions and 300 deletions

View File

@ -35,9 +35,9 @@ pw::InlineQueue
---------------
.. doxygentypedef:: pw::InlineQueue
----------------------------
pw::VariableLengthEntryQueue
----------------------------
--------------------------
pw::InlineVarLenEntryQueue
--------------------------
.. doxygenfile:: pw_containers/inline_var_len_entry_queue.h
:sections: detaileddescription
@ -49,14 +49,14 @@ Example
:sync: c++
Queues are declared with their max size
(``VariableLengthEntryQueue<kMaxSize>``) but may be used without
specifying the size (``VariableLengthEntryQueue<>&``).
(``InlineVarLenEntryQueue<kMaxSize>``) but may be used without
specifying the size (``InlineVarLenEntryQueue<>&``).
.. code-block:: c++
// Declare a queue with capacity sufficient for one 10-byte entry or
// multiple smaller entries.
pw::VariableLengthEntryQueue<10> queue;
pw::InlineVarLenEntryQueue<10> queue;
// Push an entry, asserting if the entry does not fit.
queue.push(queue, data)
@ -68,14 +68,14 @@ Example
// Remove an entry.
queue.pop();
Alternately, a ``VariableLengthEntryQueue`` may be initialized in an
Alternately, a ``InlineVarLenEntryQueue`` may be initialized in an
existing ``uint32_t`` array.
.. code-block:: c++
// Initialize a VariableLengthEntryQueue.
// Initialize a InlineVarLenEntryQueue.
uint32_t buffer[32];
auto& queue = pw::VariableLengthEntryQueue<>::Init(buffer);
auto& queue = pw::InlineVarLenEntryQueue<>::Init(buffer);
// Largest supported entry is 114 B (13 B overhead + 1 B prefix)
assert(queue.max_size_bytes() == 114u);
@ -86,8 +86,8 @@ Example
.. tab-item:: C
:sync: c
A ``VariableLengthEntryQueue`` may be declared and initialized in C with
the :c:macro:`PW_VARIABLE_LENGTH_ENTRY_QUEUE_DECLARE` macro.
A ``InlineVarLenEntryQueue`` may be declared and initialized in C with the
:c:macro:`PW_VARIABLE_LENGTH_ENTRY_QUEUE_DECLARE` macro.
.. code-block:: c
@ -96,39 +96,39 @@ Example
PW_VARIABLE_LENGTH_ENTRY_QUEUE_DECLARE(queue, 10);
// Push an entry, asserting if the entry does not fit.
pw_VariableLengthEntryQueue_Push(queue, "12345", 5);
pw_InlineVarLenEntryQueue_Push(queue, "12345", 5);
// Use push_overwrite() to push entries, overwriting older entries
// as needed.
pw_VariableLengthEntryQueue_PushOverwrite(queue, "abcdefg", 7);
pw_InlineVarLenEntryQueue_PushOverwrite(queue, "abcdefg", 7);
// Remove an entry.
pw_VariableLengthEntryQueue_Pop(queue);
pw_InlineVarLenEntryQueue_Pop(queue);
Alternately, a ``VariableLengthEntryQueue`` may be initialized in an
Alternately, a ``InlineVarLenEntryQueue`` may be initialized in an
existing ``uint32_t`` array.
.. code-block:: c
// Initialize a VariableLengthEntryQueue.
// Initialize a InlineVarLenEntryQueue.
uint32_t buffer[32];
pw_VariableLengthEntryQueue_Init(buffer, 32);
pw_InlineVarLenEntryQueue_Init(buffer, 32);
// Largest supported entry is 114 B (13 B overhead + 1 B prefix)
assert(pw_VariableLengthEntryQueue_MaxSizeBytes(buffer) == 114u);
assert(pw_InlineVarLenEntryQueue_MaxSizeBytes(buffer) == 114u);
// Write some data
pw_VariableLengthEntryQueue_PushOverwrite(buffer, "123", 3);
pw_InlineVarLenEntryQueue_PushOverwrite(buffer, "123", 3);
Queue vs. deque
===============
This module provides :cpp:type:`VariableLengthEntryQueue`, but no corresponding
``VariableLengthEntryDeque`` class. Following the C++ Standard Library style,
This module provides :cpp:type:`InlineVarLenEntryQueue`, but no corresponding
``InlineVarLenEntryDeque`` class. Following the C++ Standard Library style,
the deque class would provide ``push_front()`` and ``pop_back()`` operations in
addition to ``push_back()`` and ``pop_front()`` (equivalent to a queue's
``push()`` and ``pop()``).
There is no ``VariableLengthEntryDeque`` class because there is no efficient way
There is no ``InlineVarLenEntryDeque`` class because there is no efficient way
to implement ``push_front()`` and ``pop_back()``. These operations would
necessarily be O(n), since each entry knows the position of the next entry, but
not the previous, as in a single-linked list. Given that these operations would

View File

@ -35,7 +35,7 @@ static const uint8_t* Data(const uint32_t* queue) {
return (const uint8_t*)&queue[3];
}
static uint32_t WrapIndex(pw_VariableLengthEntryQueue_ConstHandle queue,
static uint32_t WrapIndex(pw_InlineVarLenEntryQueue_ConstHandle queue,
uint32_t offset) {
if (offset >= BufferSize(queue)) {
offset -= BufferSize(queue);
@ -49,7 +49,7 @@ typedef struct {
} EntrySize;
// Returns the size of an entry, including both the prefix length and data size.
static EntrySize ReadEntrySize(pw_VariableLengthEntryQueue_ConstHandle queue,
static EntrySize ReadEntrySize(pw_InlineVarLenEntryQueue_ConstHandle queue,
uint32_t offset) {
EntrySize size = {0, 0};
@ -65,7 +65,7 @@ static EntrySize ReadEntrySize(pw_VariableLengthEntryQueue_ConstHandle queue,
return size;
}
static uint32_t EncodePrefix(pw_VariableLengthEntryQueue_ConstHandle queue,
static uint32_t EncodePrefix(pw_InlineVarLenEntryQueue_ConstHandle queue,
uint8_t prefix[PW_VARINT_MAX_INT32_SIZE_BYTES],
uint32_t data_size_bytes) {
const uint32_t prefix_size = (uint32_t)pw_varint_Encode32(
@ -74,25 +74,25 @@ static uint32_t EncodePrefix(pw_VariableLengthEntryQueue_ConstHandle queue,
// Check that the ring buffer is capable of holding entries of this size.
PW_CHECK_UINT_LE(prefix_size + data_size_bytes,
Capacity(queue),
"Entry is too large for this VariableLengthEntryQueue");
"Entry is too large for this InlineVarLenEntryQueue");
return prefix_size;
}
// Returns the total encoded size of an entry.
static uint32_t ReadEncodedEntrySize(
pw_VariableLengthEntryQueue_ConstHandle queue, uint32_t offset) {
pw_InlineVarLenEntryQueue_ConstHandle queue, uint32_t offset) {
const EntrySize entry_size = ReadEntrySize(queue, offset);
return entry_size.prefix + entry_size.data;
}
static uint32_t PopNonEmpty(pw_VariableLengthEntryQueue_Handle queue) {
static uint32_t PopNonEmpty(pw_InlineVarLenEntryQueue_Handle queue) {
const uint32_t entry_size = ReadEncodedEntrySize(queue, HEAD(queue));
HEAD(queue) = WrapIndex(queue, HEAD(queue) + entry_size);
return entry_size;
}
// Copies data to the buffer, wrapping around the end if needed.
static uint32_t CopyAndWrap(pw_VariableLengthEntryQueue_Handle queue,
static uint32_t CopyAndWrap(pw_InlineVarLenEntryQueue_Handle queue,
uint32_t tail,
const uint8_t* data,
uint32_t size) {
@ -111,7 +111,7 @@ static uint32_t CopyAndWrap(pw_VariableLengthEntryQueue_Handle queue,
return WrapIndex(queue, tail + size);
}
static void AppendEntryKnownToFit(pw_VariableLengthEntryQueue_Handle queue,
static void AppendEntryKnownToFit(pw_InlineVarLenEntryQueue_Handle queue,
const uint8_t* prefix,
uint32_t prefix_size,
const void* data,
@ -123,7 +123,7 @@ static void AppendEntryKnownToFit(pw_VariableLengthEntryQueue_Handle queue,
}
static inline uint32_t AvailableBytes(
pw_VariableLengthEntryQueue_ConstHandle queue) {
pw_InlineVarLenEntryQueue_ConstHandle queue) {
uint32_t tail = TAIL(queue);
if (tail < HEAD(queue)) {
tail += BufferSize(queue);
@ -131,9 +131,9 @@ static inline uint32_t AvailableBytes(
return Capacity(queue) - (tail - HEAD(queue));
}
void pw_VariableLengthEntryQueue_Push(pw_VariableLengthEntryQueue_Handle queue,
const void* data,
const uint32_t data_size_bytes) {
void pw_InlineVarLenEntryQueue_Push(pw_InlineVarLenEntryQueue_Handle queue,
const void* data,
const uint32_t data_size_bytes) {
uint8_t prefix[PW_VARINT_MAX_INT32_SIZE_BYTES];
uint32_t prefix_size = EncodePrefix(queue, prefix, data_size_bytes);
@ -143,8 +143,8 @@ void pw_VariableLengthEntryQueue_Push(pw_VariableLengthEntryQueue_Handle queue,
AppendEntryKnownToFit(queue, prefix, prefix_size, data, data_size_bytes);
}
void pw_VariableLengthEntryQueue_PushOverwrite(
pw_VariableLengthEntryQueue_Handle queue,
void pw_InlineVarLenEntryQueue_PushOverwrite(
pw_InlineVarLenEntryQueue_Handle queue,
const void* data,
const uint32_t data_size_bytes) {
uint8_t prefix[PW_VARINT_MAX_INT32_SIZE_BYTES];
@ -158,24 +158,24 @@ void pw_VariableLengthEntryQueue_PushOverwrite(
AppendEntryKnownToFit(queue, prefix, prefix_size, data, data_size_bytes);
}
void pw_VariableLengthEntryQueue_Pop(pw_VariableLengthEntryQueue_Handle queue) {
PW_CHECK(!pw_VariableLengthEntryQueue_Empty(queue));
void pw_InlineVarLenEntryQueue_Pop(pw_InlineVarLenEntryQueue_Handle queue) {
PW_CHECK(!pw_InlineVarLenEntryQueue_Empty(queue));
PopNonEmpty(queue);
}
void pw_VariableLengthEntryQueue_Iterator_Advance(
pw_VariableLengthEntryQueue_Iterator* iterator) {
void pw_InlineVarLenEntryQueue_Iterator_Advance(
pw_InlineVarLenEntryQueue_Iterator* iterator) {
iterator->_pw_offset = WrapIndex(
iterator->_pw_queue,
iterator->_pw_offset +
ReadEncodedEntrySize(iterator->_pw_queue, iterator->_pw_offset));
}
pw_VariableLengthEntryQueue_Entry pw_VariableLengthEntryQueue_GetEntry(
const pw_VariableLengthEntryQueue_Iterator* iterator) {
pw_VariableLengthEntryQueue_ConstHandle queue = iterator->_pw_queue;
pw_InlineVarLenEntryQueue_Entry pw_InlineVarLenEntryQueue_GetEntry(
const pw_InlineVarLenEntryQueue_Iterator* iterator) {
pw_InlineVarLenEntryQueue_ConstHandle queue = iterator->_pw_queue;
pw_VariableLengthEntryQueue_Entry entry;
pw_InlineVarLenEntryQueue_Entry entry;
EntrySize size = ReadEntrySize(queue, iterator->_pw_offset);
uint32_t offset_1 = WrapIndex(queue, iterator->_pw_offset + size.prefix);
@ -194,10 +194,8 @@ pw_VariableLengthEntryQueue_Entry pw_VariableLengthEntryQueue_GetEntry(
return entry;
}
uint32_t pw_VariableLengthEntryQueue_Entry_Copy(
const pw_VariableLengthEntryQueue_Entry* entry,
void* dest,
uint32_t count) {
uint32_t pw_InlineVarLenEntryQueue_Entry_Copy(
const pw_InlineVarLenEntryQueue_Entry* entry, void* dest, uint32_t count) {
PW_DCHECK(dest != NULL || count == 0u);
const uint32_t entry_size = entry->size_1 + entry->size_2;
@ -217,14 +215,14 @@ uint32_t pw_VariableLengthEntryQueue_Entry_Copy(
return to_copy;
}
const uint8_t* _pw_VariableLengthEntryQueue_Entry_GetPointerChecked(
const pw_VariableLengthEntryQueue_Entry* entry, size_t index) {
const uint8_t* _pw_InlineVarLenEntryQueue_Entry_GetPointerChecked(
const pw_InlineVarLenEntryQueue_Entry* entry, size_t index) {
PW_CHECK_UINT_LT(index, entry->size_1 + entry->size_2);
return _pw_VariableLengthEntryQueue_Entry_GetPointer(entry, index);
return _pw_InlineVarLenEntryQueue_Entry_GetPointer(entry, index);
}
uint32_t pw_VariableLengthEntryQueue_Size(
pw_VariableLengthEntryQueue_ConstHandle queue) {
uint32_t pw_InlineVarLenEntryQueue_Size(
pw_InlineVarLenEntryQueue_ConstHandle queue) {
uint32_t entry_count = 0;
uint32_t offset = HEAD(queue);
@ -235,8 +233,8 @@ uint32_t pw_VariableLengthEntryQueue_Size(
return entry_count;
}
uint32_t pw_VariableLengthEntryQueue_SizeBytes(
pw_VariableLengthEntryQueue_ConstHandle queue) {
uint32_t pw_InlineVarLenEntryQueue_SizeBytes(
pw_InlineVarLenEntryQueue_ConstHandle queue) {
uint32_t total_entry_size_bytes = 0;
uint32_t offset = HEAD(queue);

View File

@ -38,60 +38,59 @@ struct SizeEquals {
using TestStep = std::variant<PushOverwrite, Push, Pop, Clear, SizeEquals>;
// Copies an entry, which might be wrapped, to a single std::vector.
std::vector<std::byte> ReadEntry(
const pw_VariableLengthEntryQueue_Iterator& it) {
auto entry = pw_VariableLengthEntryQueue_GetEntry(&it);
std::vector<std::byte> ReadEntry(const pw_InlineVarLenEntryQueue_Iterator& it) {
auto entry = pw_InlineVarLenEntryQueue_GetEntry(&it);
std::vector<std::byte> value(entry.size_1 + entry.size_2);
EXPECT_EQ(value.size(),
pw_VariableLengthEntryQueue_Entry_Copy(
pw_InlineVarLenEntryQueue_Entry_Copy(
&entry, value.data(), entry.size_1 + entry.size_2));
return value;
}
// Declares a test that performs a series of operations on the C and C++
// versions of VariableLengthEntryQueue and the "oracle" class, and checks that
// versions of InlineVarLenEntryQueue and the "oracle" class, and checks that
// they match after every step.
#define DATA_DRIVEN_TEST(program, max_entry_size) \
TEST(VariableLengthEntryQueue, \
TEST(InlineVarLenEntryQueue, \
DataDrivenTest_##program##_MaxSizeBytes##max_entry_size) { \
pw::VariableLengthEntryQueue<max_entry_size> cpp_queue; \
pw::InlineVarLenEntryQueue<max_entry_size> cpp_queue; \
PW_VARIABLE_LENGTH_ENTRY_QUEUE_DECLARE(c_queue, max_entry_size); \
pw::containers::VariableLengthEntryQueueTestOracle oracle(max_entry_size); \
pw::containers::InlineVarLenEntryQueueTestOracle oracle(max_entry_size); \
\
/* Check the queue sizes */ \
static_assert(sizeof(cpp_queue) == sizeof(c_queue)); \
ASSERT_EQ(cpp_queue.raw_storage().data(), \
reinterpret_cast<const std::byte*>(&cpp_queue)); \
ASSERT_EQ(cpp_queue.raw_storage().size_bytes(), \
pw_VariableLengthEntryQueue_RawStorageSizeBytes(c_queue)); \
pw_InlineVarLenEntryQueue_RawStorageSizeBytes(c_queue)); \
\
for (const TestStep& step : program) { \
/* Take the action */ \
if (auto ow = std::get_if<PushOverwrite>(&step); ow != nullptr) { \
cpp_queue.push_overwrite(pw::as_bytes(pw::span(ow->data))); \
pw_VariableLengthEntryQueue_PushOverwrite( \
pw_InlineVarLenEntryQueue_PushOverwrite( \
c_queue, ow->data.data(), static_cast<uint32_t>(ow->data.size())); \
oracle.push_overwrite(pw::as_bytes(pw::span(ow->data))); \
} else if (auto push = std::get_if<Push>(&step); push != nullptr) { \
cpp_queue.push(pw::as_bytes(pw::span(push->data))); \
pw_VariableLengthEntryQueue_Push( \
pw_InlineVarLenEntryQueue_Push( \
c_queue, \
push->data.data(), \
static_cast<uint32_t>(push->data.size())); \
oracle.push(pw::as_bytes(pw::span(push->data))); \
} else if (std::holds_alternative<Pop>(step)) { \
cpp_queue.pop(); \
pw_VariableLengthEntryQueue_Pop(c_queue); \
pw_InlineVarLenEntryQueue_Pop(c_queue); \
oracle.pop(); \
} else if (auto size = std::get_if<SizeEquals>(&step); \
size != nullptr) { \
const size_t actual = cpp_queue.size(); \
ASSERT_EQ(actual, pw_VariableLengthEntryQueue_Size(c_queue)); \
ASSERT_EQ(actual, pw_InlineVarLenEntryQueue_Size(c_queue)); \
ASSERT_EQ(oracle.size(), actual); \
ASSERT_EQ(size->expected, actual); \
} else if (std::holds_alternative<Clear>(step)) { \
cpp_queue.clear(); \
pw_VariableLengthEntryQueue_Clear(c_queue); \
pw_InlineVarLenEntryQueue_Clear(c_queue); \
oracle.clear(); \
} else { \
FAIL() << "Unhandled case"; \
@ -101,16 +100,16 @@ std::vector<std::byte> ReadEntry(
ASSERT_EQ(cpp_queue.size_bytes(), oracle.size_bytes()); \
ASSERT_EQ(cpp_queue.max_size_bytes(), oracle.max_size_bytes()); \
\
ASSERT_EQ(pw_VariableLengthEntryQueue_Size(c_queue), oracle.size()); \
ASSERT_EQ(pw_VariableLengthEntryQueue_SizeBytes(c_queue), \
ASSERT_EQ(pw_InlineVarLenEntryQueue_Size(c_queue), oracle.size()); \
ASSERT_EQ(pw_InlineVarLenEntryQueue_SizeBytes(c_queue), \
oracle.size_bytes()); \
ASSERT_EQ(pw_VariableLengthEntryQueue_MaxSizeBytes(c_queue), \
ASSERT_EQ(pw_InlineVarLenEntryQueue_MaxSizeBytes(c_queue), \
oracle.max_size_bytes()); \
\
/* Compare the contents */ \
auto oracle_it = oracle.begin(); \
auto c_queue_it = pw_VariableLengthEntryQueue_Begin(c_queue); \
const auto c_queue_end = pw_VariableLengthEntryQueue_End(c_queue); \
auto c_queue_it = pw_InlineVarLenEntryQueue_Begin(c_queue); \
const auto c_queue_end = pw_InlineVarLenEntryQueue_End(c_queue); \
uint32_t entries_compared = 0; \
\
for (auto entry : cpp_queue) { \
@ -121,15 +120,15 @@ std::vector<std::byte> ReadEntry(
std::vector<std::byte>(entry.begin(), entry.end())); \
\
ASSERT_NE(oracle_it, oracle.end()); \
ASSERT_FALSE(pw_VariableLengthEntryQueue_Iterator_Equal( \
&c_queue_it, &c_queue_end)); \
ASSERT_FALSE(pw_InlineVarLenEntryQueue_Iterator_Equal(&c_queue_it, \
&c_queue_end)); \
\
++oracle_it; \
pw_VariableLengthEntryQueue_Iterator_Advance(&c_queue_it); \
pw_InlineVarLenEntryQueue_Iterator_Advance(&c_queue_it); \
} \
ASSERT_EQ(entries_compared, oracle.size()); \
ASSERT_TRUE(pw_VariableLengthEntryQueue_Iterator_Equal(&c_queue_it, \
&c_queue_end)); \
ASSERT_TRUE(pw_InlineVarLenEntryQueue_Iterator_Equal(&c_queue_it, \
&c_queue_end)); \
ASSERT_EQ(oracle_it, oracle.end()); \
} \
} \
@ -232,37 +231,37 @@ constexpr TestStep kClear[] = {
DATA_DRIVEN_TEST(kClear, 7);
DATA_DRIVEN_TEST(kClear, 100);
TEST(VariableLengthEntryQueue, DeclareMacro) {
TEST(InlineVarLenEntryQueue, DeclareMacro) {
PW_VARIABLE_LENGTH_ENTRY_QUEUE_DECLARE(queue, 123);
constexpr size_t kArraySizeBytes =
123 + 1 /*prefix*/ + 1 /* end */ + 3 /* round up */ +
PW_VARIABLE_LENGTH_ENTRY_QUEUE_HEADER_SIZE_UINT32 * 4;
static_assert(sizeof(queue) == kArraySizeBytes);
EXPECT_EQ(pw_VariableLengthEntryQueue_RawStorageSizeBytes(queue),
EXPECT_EQ(pw_InlineVarLenEntryQueue_RawStorageSizeBytes(queue),
kArraySizeBytes - 3 /* padding isn't included */);
EXPECT_EQ(pw_VariableLengthEntryQueue_MaxSizeBytes(queue), 123u);
EXPECT_EQ(pw_VariableLengthEntryQueue_SizeBytes(queue), 0u);
EXPECT_TRUE(pw_VariableLengthEntryQueue_Empty(queue));
EXPECT_EQ(pw_InlineVarLenEntryQueue_MaxSizeBytes(queue), 123u);
EXPECT_EQ(pw_InlineVarLenEntryQueue_SizeBytes(queue), 0u);
EXPECT_TRUE(pw_InlineVarLenEntryQueue_Empty(queue));
}
TEST(VariableLengthEntryQueue, InitializeExistingBuffer) {
TEST(InlineVarLenEntryQueue, InitializeExistingBuffer) {
constexpr size_t kArraySize =
10 + PW_VARIABLE_LENGTH_ENTRY_QUEUE_HEADER_SIZE_UINT32;
uint32_t queue[kArraySize];
pw_VariableLengthEntryQueue_Init(queue, kArraySize);
pw_InlineVarLenEntryQueue_Init(queue, kArraySize);
EXPECT_EQ(pw_VariableLengthEntryQueue_RawStorageSizeBytes(queue),
EXPECT_EQ(pw_InlineVarLenEntryQueue_RawStorageSizeBytes(queue),
sizeof(queue));
EXPECT_EQ(pw_VariableLengthEntryQueue_MaxSizeBytes(queue),
EXPECT_EQ(pw_InlineVarLenEntryQueue_MaxSizeBytes(queue),
sizeof(uint32_t) * 10u - 1 /*prefix*/ - 1 /*end*/);
EXPECT_EQ(pw_VariableLengthEntryQueue_SizeBytes(queue), 0u);
EXPECT_EQ(pw_VariableLengthEntryQueue_Size(queue), 0u);
EXPECT_TRUE(pw_VariableLengthEntryQueue_Empty(queue));
EXPECT_EQ(pw_InlineVarLenEntryQueue_SizeBytes(queue), 0u);
EXPECT_EQ(pw_InlineVarLenEntryQueue_Size(queue), 0u);
EXPECT_TRUE(pw_InlineVarLenEntryQueue_Empty(queue));
}
TEST(VariableLengthEntryQueue, MaxSizeElement) {
TEST(InlineVarLenEntryQueue, MaxSizeElement) {
// Test max size elements for a few sizes. Commented out statements fail an
// assert because the elements are too large.
PW_VARIABLE_LENGTH_ENTRY_QUEUE_DECLARE(q16, 126);
@ -270,36 +269,36 @@ TEST(VariableLengthEntryQueue, MaxSizeElement) {
PW_VARIABLE_LENGTH_ENTRY_QUEUE_DECLARE(q18, 128);
PW_VARIABLE_LENGTH_ENTRY_QUEUE_DECLARE(q19, 129);
pw_VariableLengthEntryQueue_PushOverwrite(q16, kBigEntryBytes, 126);
pw_VariableLengthEntryQueue_PushOverwrite(q17, kBigEntryBytes, 126);
pw_VariableLengthEntryQueue_PushOverwrite(q18, kBigEntryBytes, 126);
pw_VariableLengthEntryQueue_PushOverwrite(q19, kBigEntryBytes, 126);
pw_InlineVarLenEntryQueue_PushOverwrite(q16, kBigEntryBytes, 126);
pw_InlineVarLenEntryQueue_PushOverwrite(q17, kBigEntryBytes, 126);
pw_InlineVarLenEntryQueue_PushOverwrite(q18, kBigEntryBytes, 126);
pw_InlineVarLenEntryQueue_PushOverwrite(q19, kBigEntryBytes, 126);
// pw_VariableLengthEntryQueue_PushOverwrite(q16, kBigEntryBytes, 127);
pw_VariableLengthEntryQueue_PushOverwrite(q17, kBigEntryBytes, 127);
pw_VariableLengthEntryQueue_PushOverwrite(q18, kBigEntryBytes, 127);
pw_VariableLengthEntryQueue_PushOverwrite(q19, kBigEntryBytes, 127);
// pw_InlineVarLenEntryQueue_PushOverwrite(q16, kBigEntryBytes, 127);
pw_InlineVarLenEntryQueue_PushOverwrite(q17, kBigEntryBytes, 127);
pw_InlineVarLenEntryQueue_PushOverwrite(q18, kBigEntryBytes, 127);
pw_InlineVarLenEntryQueue_PushOverwrite(q19, kBigEntryBytes, 127);
// pw_VariableLengthEntryQueue_PushOverwrite(q16, kBigEntryBytes, 128);
// pw_VariableLengthEntryQueue_PushOverwrite(q17, kBigEntryBytes, 128);
pw_VariableLengthEntryQueue_PushOverwrite(q18, kBigEntryBytes, 128);
pw_VariableLengthEntryQueue_PushOverwrite(q19, kBigEntryBytes, 128);
// pw_InlineVarLenEntryQueue_PushOverwrite(q16, kBigEntryBytes, 128);
// pw_InlineVarLenEntryQueue_PushOverwrite(q17, kBigEntryBytes, 128);
pw_InlineVarLenEntryQueue_PushOverwrite(q18, kBigEntryBytes, 128);
pw_InlineVarLenEntryQueue_PushOverwrite(q19, kBigEntryBytes, 128);
// pw_VariableLengthEntryQueue_PushOverwrite(q16, kBigEntryBytes, 129);
// pw_VariableLengthEntryQueue_PushOverwrite(q17, kBigEntryBytes, 129);
// pw_VariableLengthEntryQueue_PushOverwrite(q18, kBigEntryBytes, 129);
pw_VariableLengthEntryQueue_PushOverwrite(q19, kBigEntryBytes, 129);
// pw_InlineVarLenEntryQueue_PushOverwrite(q16, kBigEntryBytes, 129);
// pw_InlineVarLenEntryQueue_PushOverwrite(q17, kBigEntryBytes, 129);
// pw_InlineVarLenEntryQueue_PushOverwrite(q18, kBigEntryBytes, 129);
pw_InlineVarLenEntryQueue_PushOverwrite(q19, kBigEntryBytes, 129);
EXPECT_EQ(pw_VariableLengthEntryQueue_Size(q16), 1u);
EXPECT_EQ(pw_VariableLengthEntryQueue_Size(q17), 1u);
EXPECT_EQ(pw_VariableLengthEntryQueue_Size(q18), 1u);
EXPECT_EQ(pw_VariableLengthEntryQueue_Size(q19), 1u);
EXPECT_EQ(pw_InlineVarLenEntryQueue_Size(q16), 1u);
EXPECT_EQ(pw_InlineVarLenEntryQueue_Size(q17), 1u);
EXPECT_EQ(pw_InlineVarLenEntryQueue_Size(q18), 1u);
EXPECT_EQ(pw_InlineVarLenEntryQueue_Size(q19), 1u);
}
constexpr const char* kStrings[] = {"Haart", "Sandro", "", "Gelu", "Solmyr"};
TEST(VariableLengthEntryQueueClass, Iterate) {
pw::BasicVariableLengthEntryQueue<char, 32> queue;
TEST(InlineVarLenEntryQueueClass, Iterate) {
pw::BasicInlineVarLenEntryQueue<char, 32> queue;
for (const char* string : kStrings) {
queue.push(std::string_view(string));
@ -314,8 +313,8 @@ TEST(VariableLengthEntryQueueClass, Iterate) {
ASSERT_EQ(i, 5u);
}
TEST(VariableLengthEntryQueueClass, IterateOverwrittenElements) {
pw::BasicVariableLengthEntryQueue<char, 6> queue;
TEST(InlineVarLenEntryQueueClass, IterateOverwrittenElements) {
pw::BasicInlineVarLenEntryQueue<char, 6> queue;
for (const char* string : kStrings) {
queue.push_overwrite(std::string_view(string));
@ -330,12 +329,12 @@ TEST(VariableLengthEntryQueueClass, IterateOverwrittenElements) {
}
}
TEST(VariableLengthEntryQueueClass, InitializeExistingBuffer) {
TEST(InlineVarLenEntryQueueClass, InitializeExistingBuffer) {
constexpr size_t kArraySize =
10 + PW_VARIABLE_LENGTH_ENTRY_QUEUE_HEADER_SIZE_UINT32;
uint32_t queue_array[kArraySize]{50, 50, 99};
pw::VariableLengthEntryQueue<>& queue =
pw::VariableLengthEntryQueue<>::Init(queue_array, kArraySize);
pw::InlineVarLenEntryQueue<>& queue =
pw::InlineVarLenEntryQueue<>::Init(queue_array, kArraySize);
EXPECT_EQ(queue.raw_storage().data(),
reinterpret_cast<const std::byte*>(queue_array));
@ -347,8 +346,8 @@ TEST(VariableLengthEntryQueueClass, InitializeExistingBuffer) {
EXPECT_TRUE(queue.empty());
}
TEST(VariableLengthEntryQueueClass, Entry) {
pw::BasicVariableLengthEntryQueue<char, 5> queue;
TEST(InlineVarLenEntryQueueClass, Entry) {
pw::BasicInlineVarLenEntryQueue<char, 5> queue;
queue.push("12"); // Split the next entry across the end.
queue.push_overwrite(std::string_view("ABCDE"));

View File

@ -22,12 +22,12 @@
/// @file pw_containers/inline_var_len_entry_queue.h
///
/// A `VariableLengthEntryQueue` is a queue of inline variable-length binary
/// A `InlineVarLenEntryQueue` is a queue of inline variable-length binary
/// entries. It is implemented as a ring (circular) buffer and supports
/// operations to append entries and overwrite if necessary. Entries may be zero
/// bytes up to the maximum size supported by the queue.
///
/// The `VariableLengthEntryQueue` has a few interesting properties.
/// The `InlineVarLenEntryQueue` has a few interesting properties.
///
/// - Data and metadata are stored inline in a contiguous block of
/// `uint32_t`-aligned memory.
@ -45,23 +45,23 @@
/// decode the buffer from a block of memory).
/// - C support is required.
///
/// `VariableLengthEntryQueue` is implemented in C and provides complete C and
/// C++ APIs. The `VariableLengthEntryQueue` C++ class is structured similarly
/// to `pw::InlineQueue` and `pw::Vector`.
/// `InlineVarLenEntryQueue` is implemented in C and provides complete C and C++
/// APIs. The `InlineVarLenEntryQueue` C++ class is structured similarly to
/// `pw::InlineQueue` and `pw::Vector`.
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
/// @defgroup inline_var_len_entry_queue_c_api VariableLengthEntryQueue C API
/// @defgroup inline_var_len_entry_queue_c_api InlineVarLenEntryQueue C API
/// @{
/// Handle that refers to a `VariableLengthEntryQueue`. In memory, the queue
/// is a `uint32_t` array.
typedef uint32_t* pw_VariableLengthEntryQueue_Handle;
typedef const uint32_t* pw_VariableLengthEntryQueue_ConstHandle;
/// Handle that refers to a `InlineVarLenEntryQueue`. In memory, the queue is a
/// `uint32_t` array.
typedef uint32_t* pw_InlineVarLenEntryQueue_Handle;
typedef const uint32_t* pw_InlineVarLenEntryQueue_ConstHandle;
/// Declares and initializes a `VariableLengthEntryQueue` that can hold up to
/// Declares and initializes a `InlineVarLenEntryQueue` that can hold up to
/// `max_size_bytes` bytes. `max_size_bytes` is the largest supported size for a
/// single entry; attempting to store larger entries is invalid and will fail an
/// assertion.
@ -73,55 +73,54 @@ typedef const uint32_t* pw_VariableLengthEntryQueue_ConstHandle;
_PW_VAR_QUEUE_DATA_SIZE_UINT32(max_size_bytes)] = { \
_PW_VAR_QUEUE_DATA_SIZE_BYTES(max_size_bytes), /*head=*/0u, /*tail=*/0u}
/// The size of the `VariableLengthEntryQueue` header, in `uint32_t` elements.
/// The size of the `InlineVarLenEntryQueue` header, in `uint32_t` elements.
/// This header stores the buffer length and head and tail offsets.
///
/// The underlying `uint32_t` array of a `VariableLengthEntryQueue` must be
/// larger than this size.
/// The underlying `uint32_t` array of a `InlineVarLenEntryQueue` must be larger
/// than this size.
#define PW_VARIABLE_LENGTH_ENTRY_QUEUE_HEADER_SIZE_UINT32 (3)
/// Initializes a `VariableLengthEntryQueue` in place in a `uint32_t` array. The
/// Initializes a `InlineVarLenEntryQueue` in place in a `uint32_t` array. The
/// array MUST be larger than
/// @c_macro{PW_VARIABLE_LENGTH_ENTRY_QUEUE_HEADER_SIZE_UINT32} (3) elements.
static inline void pw_VariableLengthEntryQueue_Init(uint32_t array[],
size_t array_size_uint32);
static inline void pw_InlineVarLenEntryQueue_Init(uint32_t array[],
size_t array_size_uint32);
/// Empties the queue.
static inline void pw_VariableLengthEntryQueue_Clear(
pw_VariableLengthEntryQueue_Handle queue);
static inline void pw_InlineVarLenEntryQueue_Clear(
pw_InlineVarLenEntryQueue_Handle queue);
/// Appends an entry to the end of the queue.
///
/// @pre The entry MUST NOT be larger than `max_size_bytes()`.
void pw_VariableLengthEntryQueue_Push(pw_VariableLengthEntryQueue_Handle queue,
const void* data,
uint32_t data_size_bytes);
void pw_InlineVarLenEntryQueue_Push(pw_InlineVarLenEntryQueue_Handle queue,
const void* data,
uint32_t data_size_bytes);
/// Appends an entry to the end of the queue, removing entries with `Pop`
/// as necessary to make room.
///
/// @pre The entry MUST NOT be larger than `max_size_bytes()`.
void pw_VariableLengthEntryQueue_PushOverwrite(
pw_VariableLengthEntryQueue_Handle queue,
void pw_InlineVarLenEntryQueue_PushOverwrite(
pw_InlineVarLenEntryQueue_Handle queue,
const void* data,
uint32_t data_size_bytes);
/// Removes the first entry from queue.
///
/// @pre The queue MUST have at least one entry.
void pw_VariableLengthEntryQueue_Pop(pw_VariableLengthEntryQueue_Handle queue);
void pw_InlineVarLenEntryQueue_Pop(pw_InlineVarLenEntryQueue_Handle queue);
/// Iterator object for a `VariableLengthEntryQueue`. Iterators are checked for
/// equality with
/// @cpp_func{pw_VariableLengthEntryQueue_Iterator_Equal}.
/// Iterator object for a `InlineVarLenEntryQueue`. Iterators are checked for
/// equality with @cpp_func{pw_InlineVarLenEntryQueue_Iterator_Equal}.
///
/// Iterators are invalidated by any operations that change the container or
/// its underlying data (push/pop/init).
typedef struct {
// Private: do not access these fields directly!
pw_VariableLengthEntryQueue_ConstHandle _pw_queue;
pw_InlineVarLenEntryQueue_ConstHandle _pw_queue;
uint32_t _pw_offset;
} pw_VariableLengthEntryQueue_Iterator;
} pw_InlineVarLenEntryQueue_Iterator;
/// An entry in the queue. Entries may be stored in up to two segments, so this
/// struct includes pointers to both portions of the entry.
@ -130,30 +129,29 @@ typedef struct {
uint32_t size_1;
const uint8_t* data_2;
uint32_t size_2;
} pw_VariableLengthEntryQueue_Entry;
} pw_InlineVarLenEntryQueue_Entry;
/// Returns an iterator to the start of the `VariableLengthEntryQueue`.
static inline pw_VariableLengthEntryQueue_Iterator
pw_VariableLengthEntryQueue_Begin(
pw_VariableLengthEntryQueue_ConstHandle queue);
/// Returns an iterator to the start of the `InlineVarLenEntryQueue`.
static inline pw_InlineVarLenEntryQueue_Iterator
pw_InlineVarLenEntryQueue_Begin(pw_InlineVarLenEntryQueue_ConstHandle queue);
/// Returns an iterator that points past the end of the queue.
static inline pw_VariableLengthEntryQueue_Iterator
pw_VariableLengthEntryQueue_End(pw_VariableLengthEntryQueue_ConstHandle queue);
static inline pw_InlineVarLenEntryQueue_Iterator pw_InlineVarLenEntryQueue_End(
pw_InlineVarLenEntryQueue_ConstHandle queue);
/// Advances an iterator to point to the next entry in the queue. It is
/// invalid to call `Advance` on an iterator equal to the `End` iterator.
void pw_VariableLengthEntryQueue_Iterator_Advance(
pw_VariableLengthEntryQueue_Iterator* iterator);
void pw_InlineVarLenEntryQueue_Iterator_Advance(
pw_InlineVarLenEntryQueue_Iterator* iterator);
/// Compares two iterators for equality.
static inline bool pw_VariableLengthEntryQueue_Iterator_Equal(
const pw_VariableLengthEntryQueue_Iterator* lhs,
const pw_VariableLengthEntryQueue_Iterator* rhs);
static inline bool pw_InlineVarLenEntryQueue_Iterator_Equal(
const pw_InlineVarLenEntryQueue_Iterator* lhs,
const pw_InlineVarLenEntryQueue_Iterator* rhs);
/// Dereferences an iterator, loading the entry it points to.
pw_VariableLengthEntryQueue_Entry pw_VariableLengthEntryQueue_GetEntry(
const pw_VariableLengthEntryQueue_Iterator* iterator);
pw_InlineVarLenEntryQueue_Entry pw_InlineVarLenEntryQueue_GetEntry(
const pw_InlineVarLenEntryQueue_Iterator* iterator);
/// Copies the contents of the entry to the provided buffer. The entry may be
/// split into two regions; this serializes it into one buffer.
@ -162,41 +160,41 @@ pw_VariableLengthEntryQueue_Entry pw_VariableLengthEntryQueue_GetEntry(
/// @param dest The buffer into which to copy the serialized entry
/// @param count Copy up to this many bytes; must not be larger than the `dest`
/// buffer, but may be larger than the entry
uint32_t pw_VariableLengthEntryQueue_Entry_Copy(
const pw_VariableLengthEntryQueue_Entry* entry, void* dest, uint32_t count);
uint32_t pw_InlineVarLenEntryQueue_Entry_Copy(
const pw_InlineVarLenEntryQueue_Entry* entry, void* dest, uint32_t count);
/// Returns the byte at the specified index in the entry. Asserts if index is
/// out-of-bounds.
static inline uint8_t pw_VariableLengthEntryQueue_Entry_At(
const pw_VariableLengthEntryQueue_Entry* entry, size_t index);
static inline uint8_t pw_InlineVarLenEntryQueue_Entry_At(
const pw_InlineVarLenEntryQueue_Entry* entry, size_t index);
/// Returns the number of variable-length entries in the queue. This is O(n) in
/// the number of entries in the queue.
uint32_t pw_VariableLengthEntryQueue_Size(
pw_VariableLengthEntryQueue_ConstHandle queue);
uint32_t pw_InlineVarLenEntryQueue_Size(
pw_InlineVarLenEntryQueue_ConstHandle queue);
/// Returns the combined size in bytes of all entries in the queue, excluding
/// metadata. This is O(n) in the number of entries in the queue.
uint32_t pw_VariableLengthEntryQueue_SizeBytes(
pw_VariableLengthEntryQueue_ConstHandle queue);
uint32_t pw_InlineVarLenEntryQueue_SizeBytes(
pw_InlineVarLenEntryQueue_ConstHandle queue);
/// Returns the the maximum number of bytes that can be stored in the queue.
/// This is largest possible value of `size_bytes()`, and the size of the
/// largest single entry that can be stored in this queue. Attempting to store a
/// larger entry is invalid and results in a crash.
static inline uint32_t pw_VariableLengthEntryQueue_MaxSizeBytes(
pw_VariableLengthEntryQueue_ConstHandle queue);
static inline uint32_t pw_InlineVarLenEntryQueue_MaxSizeBytes(
pw_InlineVarLenEntryQueue_ConstHandle queue);
/// Returns the size of the raw underlying `VariableLengthEntryQueue` storage.
/// This size may be used to copy a `VariableLengthEntryQueue` into another
/// Returns the size of the raw underlying `InlineVarLenEntryQueue` storage.
/// This size may be used to copy a `InlineVarLenEntryQueue` into another
/// 32-bit aligned memory location.
static inline uint32_t pw_VariableLengthEntryQueue_RawStorageSizeBytes(
pw_VariableLengthEntryQueue_ConstHandle queue);
static inline uint32_t pw_InlineVarLenEntryQueue_RawStorageSizeBytes(
pw_InlineVarLenEntryQueue_ConstHandle queue);
/// Returns true if the `VariableLengthEntryQueue` is empty, false if it has at
/// Returns true if the `InlineVarLenEntryQueue` is empty, false if it has at
/// least one entry.
static inline bool pw_VariableLengthEntryQueue_Empty(
pw_VariableLengthEntryQueue_ConstHandle queue);
static inline bool pw_InlineVarLenEntryQueue_Empty(
pw_InlineVarLenEntryQueue_ConstHandle queue);
/// @}
@ -219,70 +217,69 @@ static inline bool pw_VariableLengthEntryQueue_Empty(
PW_VARIABLE_LENGTH_ENTRY_QUEUE_HEADER_SIZE_UINT32) * \
sizeof(uint32_t)
static inline void pw_VariableLengthEntryQueue_Init(uint32_t array[],
size_t array_size_uint32) {
static inline void pw_InlineVarLenEntryQueue_Init(uint32_t array[],
size_t array_size_uint32) {
array[0] = _PW_VAR_QUEUE_GET_ARRAY_SIZE_BYTES(array_size_uint32);
array[1] = 0; // head
array[2] = 0; // tail
}
static inline void pw_VariableLengthEntryQueue_Clear(
pw_VariableLengthEntryQueue_Handle queue) {
static inline void pw_InlineVarLenEntryQueue_Clear(
pw_InlineVarLenEntryQueue_Handle queue) {
_PW_VAR_QUEUE_HEAD = 0; // head
_PW_VAR_QUEUE_TAIL = 0; // tail
}
static inline pw_VariableLengthEntryQueue_Iterator
pw_VariableLengthEntryQueue_Begin(
pw_VariableLengthEntryQueue_ConstHandle queue) {
pw_VariableLengthEntryQueue_Iterator begin = {queue, _PW_VAR_QUEUE_HEAD};
static inline pw_InlineVarLenEntryQueue_Iterator
pw_InlineVarLenEntryQueue_Begin(pw_InlineVarLenEntryQueue_ConstHandle queue) {
pw_InlineVarLenEntryQueue_Iterator begin = {queue, _PW_VAR_QUEUE_HEAD};
return begin;
}
static inline pw_VariableLengthEntryQueue_Iterator
pw_VariableLengthEntryQueue_End(pw_VariableLengthEntryQueue_ConstHandle queue) {
pw_VariableLengthEntryQueue_Iterator end = {queue, _PW_VAR_QUEUE_TAIL};
static inline pw_InlineVarLenEntryQueue_Iterator pw_InlineVarLenEntryQueue_End(
pw_InlineVarLenEntryQueue_ConstHandle queue) {
pw_InlineVarLenEntryQueue_Iterator end = {queue, _PW_VAR_QUEUE_TAIL};
return end;
}
static inline bool pw_VariableLengthEntryQueue_Iterator_Equal(
const pw_VariableLengthEntryQueue_Iterator* lhs,
const pw_VariableLengthEntryQueue_Iterator* rhs) {
static inline bool pw_InlineVarLenEntryQueue_Iterator_Equal(
const pw_InlineVarLenEntryQueue_Iterator* lhs,
const pw_InlineVarLenEntryQueue_Iterator* rhs) {
return lhs->_pw_offset == rhs->_pw_offset && lhs->_pw_queue == rhs->_pw_queue;
}
// Private function that returns a pointer to the specified index in the Entry.
static inline const uint8_t* _pw_VariableLengthEntryQueue_Entry_GetPointer(
const pw_VariableLengthEntryQueue_Entry* entry, size_t index) {
static inline const uint8_t* _pw_InlineVarLenEntryQueue_Entry_GetPointer(
const pw_InlineVarLenEntryQueue_Entry* entry, size_t index) {
if (index < entry->size_1) {
return &entry->data_1[index];
}
return &entry->data_2[index - entry->size_1];
}
const uint8_t* _pw_VariableLengthEntryQueue_Entry_GetPointerChecked(
const pw_VariableLengthEntryQueue_Entry* entry, size_t index);
const uint8_t* _pw_InlineVarLenEntryQueue_Entry_GetPointerChecked(
const pw_InlineVarLenEntryQueue_Entry* entry, size_t index);
static inline uint8_t pw_VariableLengthEntryQueue_Entry_At(
const pw_VariableLengthEntryQueue_Entry* entry, size_t index) {
return *_pw_VariableLengthEntryQueue_Entry_GetPointerChecked(entry, index);
static inline uint8_t pw_InlineVarLenEntryQueue_Entry_At(
const pw_InlineVarLenEntryQueue_Entry* entry, size_t index) {
return *_pw_InlineVarLenEntryQueue_Entry_GetPointerChecked(entry, index);
}
static inline uint32_t pw_VariableLengthEntryQueue_RawStorageSizeBytes(
pw_VariableLengthEntryQueue_ConstHandle queue) {
static inline uint32_t pw_InlineVarLenEntryQueue_RawStorageSizeBytes(
pw_InlineVarLenEntryQueue_ConstHandle queue) {
return PW_VARIABLE_LENGTH_ENTRY_QUEUE_HEADER_SIZE_UINT32 * sizeof(uint32_t) +
_PW_VAR_QUEUE_ARRAY_SIZE_BYTES;
}
static inline uint32_t pw_VariableLengthEntryQueue_MaxSizeBytes(
pw_VariableLengthEntryQueue_ConstHandle queue) {
static inline uint32_t pw_InlineVarLenEntryQueue_MaxSizeBytes(
pw_InlineVarLenEntryQueue_ConstHandle queue) {
return _PW_VAR_QUEUE_ARRAY_SIZE_BYTES - 1 -
(uint32_t)pw_varint_EncodedSizeBytes(_PW_VAR_QUEUE_ARRAY_SIZE_BYTES -
1);
}
static inline bool pw_VariableLengthEntryQueue_Empty(
pw_VariableLengthEntryQueue_ConstHandle queue) {
static inline bool pw_InlineVarLenEntryQueue_Empty(
pw_InlineVarLenEntryQueue_ConstHandle queue) {
return _PW_VAR_QUEUE_HEAD == _PW_VAR_QUEUE_TAIL;
}
@ -305,26 +302,26 @@ static inline bool pw_VariableLengthEntryQueue_Empty(
namespace pw {
// A`BasicVariableLengthEntryQueue` with a known maximum size of a single entry.
// A`BasicInlineVarLenEntryQueue` with a known maximum size of a single entry.
// The member functions are immplemented in the generic-capacity base.
// TODO: b/303056683 - Add helper for calculating kMaxSizeBytes for N entries of
// a particular size.
template <typename T,
size_t kMaxSizeBytes = containers::internal::kGenericSized>
class BasicVariableLengthEntryQueue : public BasicVariableLengthEntryQueue<
T,
containers::internal::kGenericSized> {
class BasicInlineVarLenEntryQueue
: public BasicInlineVarLenEntryQueue<T,
containers::internal::kGenericSized> {
private:
using Base =
BasicVariableLengthEntryQueue<T, containers::internal::kGenericSized>;
BasicInlineVarLenEntryQueue<T, containers::internal::kGenericSized>;
public:
constexpr BasicVariableLengthEntryQueue() : Base(kMaxSizeBytes) {}
constexpr BasicInlineVarLenEntryQueue() : Base(kMaxSizeBytes) {}
// `BasicVariableLengthEntryQueue` is trivially copyable.
BasicVariableLengthEntryQueue(const BasicVariableLengthEntryQueue&) = default;
BasicVariableLengthEntryQueue& operator=(
const BasicVariableLengthEntryQueue&) = default;
// `BasicInlineVarLenEntryQueue` is trivially copyable.
BasicInlineVarLenEntryQueue(const BasicInlineVarLenEntryQueue&) = default;
BasicInlineVarLenEntryQueue& operator=(const BasicInlineVarLenEntryQueue&) =
default;
private:
static_assert(kMaxSizeBytes <=
@ -341,12 +338,12 @@ class BasicVariableLengthEntryQueue : public BasicVariableLengthEntryQueue<
/// Variable-length entry queue class template for any byte type (e.g.
/// ``std::byte`` or ``uint8_t``).
///
/// ``BasicVariableLengthEntryQueue`` instances are declared with their capacity
/// / max single entry size (``BasicVariableLengthEntryQueue<char, 64>``), but
/// ``BasicInlineVarLenEntryQueue`` instances are declared with their capacity
/// / max single entry size (``BasicInlineVarLenEntryQueue<char, 64>``), but
/// may be referred to without the size
/// (``BasicVariableLengthEntryQueue<char>&``).
/// (``BasicInlineVarLenEntryQueue<char>&``).
template <typename T>
class BasicVariableLengthEntryQueue<T, containers::internal::kGenericSized> {
class BasicInlineVarLenEntryQueue<T, containers::internal::kGenericSized> {
public:
class Entry;
@ -364,90 +361,88 @@ class BasicVariableLengthEntryQueue<T, containers::internal::kGenericSized> {
// TODO: b/303046109 - Provide a non-const iterator.
using const_iterator = iterator;
/// @copydoc pw_VariableLengthEntryQueue_Init
/// @copydoc pw_InlineVarLenEntryQueue_Init
template <size_t kArraySize>
static BasicVariableLengthEntryQueue& Init(uint32_t (&array)[kArraySize]) {
static BasicInlineVarLenEntryQueue& Init(uint32_t (&array)[kArraySize]) {
static_assert(
kArraySize > PW_VARIABLE_LENGTH_ENTRY_QUEUE_HEADER_SIZE_UINT32,
"VariableLengthEntryQueue must be backed by an array with more than "
"InlineVarLenEntryQueue must be backed by an array with more than "
"PW_VARIABLE_LENGTH_ENTRY_QUEUE_HEADER_SIZE_UINT32 (3) elements");
return Init(array, kArraySize);
}
/// @copydoc pw_VariableLengthEntryQueue_Init
static BasicVariableLengthEntryQueue& Init(uint32_t array[],
size_t array_size_uint32) {
pw_VariableLengthEntryQueue_Init(array, array_size_uint32);
return *std::launder(
reinterpret_cast<BasicVariableLengthEntryQueue*>(array));
/// @copydoc pw_InlineVarLenEntryQueue_Init
static BasicInlineVarLenEntryQueue& Init(uint32_t array[],
size_t array_size_uint32) {
pw_InlineVarLenEntryQueue_Init(array, array_size_uint32);
return *std::launder(reinterpret_cast<BasicInlineVarLenEntryQueue*>(array));
}
/// Returns the first entry in the queue.
Entry front() const { return *begin(); }
/// @copydoc pw_VariableLengthEntryQueue_Begin
/// @copydoc pw_InlineVarLenEntryQueue_Begin
const_iterator begin() const {
return const_iterator(pw_VariableLengthEntryQueue_Begin(array_));
return const_iterator(pw_InlineVarLenEntryQueue_Begin(array_));
}
const_iterator cbegin() const { return begin(); }
/// @copydoc pw_VariableLengthEntryQueue_End
/// @copydoc pw_InlineVarLenEntryQueue_End
const_iterator end() const {
return const_iterator(pw_VariableLengthEntryQueue_End(array_));
return const_iterator(pw_InlineVarLenEntryQueue_End(array_));
}
const_iterator cend() const { return end(); }
/// @copydoc pw_VariableLengthEntryQueue_Empty
/// @copydoc pw_InlineVarLenEntryQueue_Empty
[[nodiscard]] bool empty() const {
return pw_VariableLengthEntryQueue_Empty(array_);
return pw_InlineVarLenEntryQueue_Empty(array_);
}
/// @copydoc pw_VariableLengthEntryQueue_Size
size_type size() const { return pw_VariableLengthEntryQueue_Size(array_); }
/// @copydoc pw_InlineVarLenEntryQueue_Size
size_type size() const { return pw_InlineVarLenEntryQueue_Size(array_); }
/// @copydoc pw_VariableLengthEntryQueue_SizeBytes
/// @copydoc pw_InlineVarLenEntryQueue_SizeBytes
size_type size_bytes() const {
return pw_VariableLengthEntryQueue_SizeBytes(array_);
return pw_InlineVarLenEntryQueue_SizeBytes(array_);
}
/// @copydoc pw_VariableLengthEntryQueue_MaxSizeBytes
/// @copydoc pw_InlineVarLenEntryQueue_MaxSizeBytes
size_type max_size_bytes() const {
return pw_VariableLengthEntryQueue_MaxSizeBytes(array_);
return pw_InlineVarLenEntryQueue_MaxSizeBytes(array_);
}
/// Underlying storage of the variable-length entry queue. May be used to
/// memcpy the queue.
span<const T> raw_storage() const {
return span<const T>(
reinterpret_cast<const T*>(array_),
pw_VariableLengthEntryQueue_RawStorageSizeBytes(array_));
return span<const T>(reinterpret_cast<const T*>(array_),
pw_InlineVarLenEntryQueue_RawStorageSizeBytes(array_));
}
/// @copydoc pw_VariableLengthEntryQueue_Clear
void clear() { pw_VariableLengthEntryQueue_Clear(array_); }
/// @copydoc pw_InlineVarLenEntryQueue_Clear
void clear() { pw_InlineVarLenEntryQueue_Clear(array_); }
/// @copydoc pw_VariableLengthEntryQueue_Push
/// @copydoc pw_InlineVarLenEntryQueue_Push
void push(span<const T> value) {
pw_VariableLengthEntryQueue_Push(
pw_InlineVarLenEntryQueue_Push(
array_, value.data(), static_cast<size_type>(value.size()));
}
/// @copydoc pw_VariableLengthEntryQueue_PushOverwrite
/// @copydoc pw_InlineVarLenEntryQueue_PushOverwrite
void push_overwrite(span<const T> value) {
pw_VariableLengthEntryQueue_PushOverwrite(
pw_InlineVarLenEntryQueue_PushOverwrite(
array_, value.data(), static_cast<size_type>(value.size()));
}
/// @copydoc pw_VariableLengthEntryQueue_Pop
void pop() { pw_VariableLengthEntryQueue_Pop(array_); }
/// @copydoc pw_InlineVarLenEntryQueue_Pop
void pop() { pw_InlineVarLenEntryQueue_Pop(array_); }
protected:
constexpr BasicVariableLengthEntryQueue(uint32_t max_size_bytes)
constexpr BasicInlineVarLenEntryQueue(uint32_t max_size_bytes)
: array_{_PW_VAR_QUEUE_DATA_SIZE_BYTES(max_size_bytes), 0, 0} {}
BasicVariableLengthEntryQueue(const BasicVariableLengthEntryQueue&) = default;
BasicVariableLengthEntryQueue& operator=(
const BasicVariableLengthEntryQueue&) = default;
BasicInlineVarLenEntryQueue(const BasicInlineVarLenEntryQueue&) = default;
BasicInlineVarLenEntryQueue& operator=(const BasicInlineVarLenEntryQueue&) =
default;
private:
static_assert(std::is_integral_v<T> || std::is_same_v<T, std::byte>);
@ -458,7 +453,7 @@ class BasicVariableLengthEntryQueue<T, containers::internal::kGenericSized> {
/// Refers to an entry in-place in the queue. Entries may be discontiguous.
template <typename T>
class BasicVariableLengthEntryQueue<T>::Entry {
class BasicInlineVarLenEntryQueue<T>::Entry {
public:
using value_type = T;
using size_type = std::uint32_t;
@ -503,11 +498,11 @@ class BasicVariableLengthEntryQueue<T>::Entry {
private:
friend class Entry;
constexpr iterator(const pw_VariableLengthEntryQueue_Entry& entry,
constexpr iterator(const pw_InlineVarLenEntryQueue_Entry& entry,
size_t index)
: entry_(&entry), index_(index) {}
const pw_VariableLengthEntryQueue_Entry* entry_;
const pw_InlineVarLenEntryQueue_Entry* entry_;
size_t index_;
};
@ -519,7 +514,7 @@ class BasicVariableLengthEntryQueue<T>::Entry {
const_reference at(size_t index) const {
return *reinterpret_cast<const T*>(
_pw_VariableLengthEntryQueue_Entry_GetPointerChecked(&entry_, index));
_pw_InlineVarLenEntryQueue_Entry_GetPointerChecked(&entry_, index));
}
const_reference operator[](size_t index) const {
@ -539,13 +534,13 @@ class BasicVariableLengthEntryQueue<T>::Entry {
span(reinterpret_cast<const_pointer>(entry_.data_2), entry_.size_2));
}
/// @copydoc pw_VariableLengthEntryQueue_Entry_Copy
/// @copydoc pw_InlineVarLenEntryQueue_Entry_Copy
///
/// Copying with `copy()` is likely more efficient than an iterator-based copy
/// with `std::copy()`, since `copy()` uses one or two `memcpy` calls instead
/// of copying byte-by-byte.
size_type copy(T* dest, size_type count) const {
return pw_VariableLengthEntryQueue_Entry_Copy(&entry_, dest, count);
return pw_InlineVarLenEntryQueue_Entry_Copy(&entry_, dest, count);
}
const_iterator begin() const { return const_iterator(entry_, 0); }
@ -559,28 +554,28 @@ class BasicVariableLengthEntryQueue<T>::Entry {
size_type size() const { return entry_.size_1 + entry_.size_2; }
private:
friend class BasicVariableLengthEntryQueue;
friend class BasicInlineVarLenEntryQueue;
static const T* GetIndex(const pw_VariableLengthEntryQueue_Entry& entry,
static const T* GetIndex(const pw_InlineVarLenEntryQueue_Entry& entry,
size_t index) {
return reinterpret_cast<const T*>(
_pw_VariableLengthEntryQueue_Entry_GetPointer(&entry, index));
_pw_InlineVarLenEntryQueue_Entry_GetPointer(&entry, index));
}
explicit constexpr Entry(const pw_VariableLengthEntryQueue_Entry& entry)
explicit constexpr Entry(const pw_InlineVarLenEntryQueue_Entry& entry)
: entry_(entry) {}
constexpr Entry() : entry_{} {}
pw_VariableLengthEntryQueue_Entry entry_;
pw_InlineVarLenEntryQueue_Entry entry_;
};
/// Iterator object for a `VariableLengthEntryQueue`.
/// Iterator object for a `InlineVarLenEntryQueue`.
///
/// Iterators are invalidated by any operations that change the container or
/// its underlying data (push/pop/init).
template <typename T>
class BasicVariableLengthEntryQueue<T>::iterator {
class BasicInlineVarLenEntryQueue<T>::iterator {
public:
using difference_type = std::ptrdiff_t;
using value_type = Entry;
@ -594,7 +589,7 @@ class BasicVariableLengthEntryQueue<T>::iterator {
constexpr iterator& operator=(const iterator&) = default;
iterator& operator++() {
pw_VariableLengthEntryQueue_Iterator_Advance(&iterator_);
pw_InlineVarLenEntryQueue_Iterator_Advance(&iterator_);
entry_.entry_.data_1 = nullptr; // mark the entry as unloaded
return *this;
}
@ -614,31 +609,30 @@ class BasicVariableLengthEntryQueue<T>::iterator {
}
bool operator==(const iterator& rhs) const {
return pw_VariableLengthEntryQueue_Iterator_Equal(&iterator_,
&rhs.iterator_);
return pw_InlineVarLenEntryQueue_Iterator_Equal(&iterator_, &rhs.iterator_);
}
bool operator!=(const iterator& rhs) const { return !(*this == rhs); }
private:
friend class BasicVariableLengthEntryQueue;
friend class BasicInlineVarLenEntryQueue;
explicit constexpr iterator(const pw_VariableLengthEntryQueue_Iterator& it)
explicit constexpr iterator(const pw_InlineVarLenEntryQueue_Iterator& it)
: iterator_(it) {}
void LoadEntry() const {
if (entry_.entry_.data_1 == nullptr) {
entry_.entry_ = pw_VariableLengthEntryQueue_GetEntry(&iterator_);
entry_.entry_ = pw_InlineVarLenEntryQueue_GetEntry(&iterator_);
}
}
pw_VariableLengthEntryQueue_Iterator iterator_;
pw_InlineVarLenEntryQueue_Iterator iterator_;
mutable Entry entry_;
};
/// Variable-length entry queue that uses ``std::byte`` for the byte type.
template <size_t kMaxSizeBytes = containers::internal::kGenericSized>
using VariableLengthEntryQueue =
BasicVariableLengthEntryQueue<std::byte, kMaxSizeBytes>;
using InlineVarLenEntryQueue =
BasicInlineVarLenEntryQueue<std::byte, kMaxSizeBytes>;
/// @}

View File

@ -24,11 +24,11 @@
namespace pw::containers {
// Behaves like a VariableLengthEntryQueue should, but with a std::deque-based
// Behaves like a InlineVarLenEntryQueue should, but with a std::deque-based
// implementation.
class VariableLengthEntryQueueTestOracle {
class InlineVarLenEntryQueueTestOracle {
public:
VariableLengthEntryQueueTestOracle(uint32_t max_size_bytes)
InlineVarLenEntryQueueTestOracle(uint32_t max_size_bytes)
: max_size_bytes_(max_size_bytes),
raw_size_bytes_(0),
raw_capacity_bytes_(

View File

@ -65,7 +65,7 @@ static void TokenizeIntegersOnly(uint32_t token, int arg_count, ...) {
}
// Write the encoded log to the ring buffer
pw_VariableLengthEntryQueue_PushOverwrite(buffer, encoded, index);
pw_InlineVarLenEntryQueue_PushOverwrite(buffer, encoded, index);
va_end(args);
}
@ -99,35 +99,35 @@ const char* RunTestAndReturnPassed(void) {
TOKENIZE_INTS("One arg, 5 bytes: %ld", (long)INT32_MAX);
TOKENIZE_INTS("Three args, 4 bytes: %d %d %d", 1, 63, 128);
ASSERT_EQ(pw_VariableLengthEntryQueue_Size(buffer), 4u);
ASSERT_EQ(pw_InlineVarLenEntryQueue_Size(buffer), 4u);
pw_VariableLengthEntryQueue_Iterator it =
pw_VariableLengthEntryQueue_Begin(buffer);
pw_VariableLengthEntryQueue_Entry entry =
pw_VariableLengthEntryQueue_GetEntry(&it);
pw_InlineVarLenEntryQueue_Iterator it =
pw_InlineVarLenEntryQueue_Begin(buffer);
pw_InlineVarLenEntryQueue_Entry entry =
pw_InlineVarLenEntryQueue_GetEntry(&it);
ASSERT_EQ(entry.size_1, sizeof(uint32_t) + 0);
ASSERT_EQ(entry.size_2, 0u);
pw_VariableLengthEntryQueue_Iterator_Advance(&it);
entry = pw_VariableLengthEntryQueue_GetEntry(&it);
pw_InlineVarLenEntryQueue_Iterator_Advance(&it);
entry = pw_InlineVarLenEntryQueue_GetEntry(&it);
ASSERT_EQ(entry.size_1, sizeof(uint32_t) + 1);
ASSERT_EQ(entry.size_2, 0u);
pw_VariableLengthEntryQueue_Iterator_Advance(&it);
entry = pw_VariableLengthEntryQueue_GetEntry(&it);
pw_InlineVarLenEntryQueue_Iterator_Advance(&it);
entry = pw_InlineVarLenEntryQueue_GetEntry(&it);
ASSERT_EQ(entry.size_1, sizeof(uint32_t) + 5);
ASSERT_EQ(entry.size_2, 0u);
pw_VariableLengthEntryQueue_Iterator_Advance(&it);
entry = pw_VariableLengthEntryQueue_GetEntry(&it);
pw_InlineVarLenEntryQueue_Iterator_Advance(&it);
entry = pw_InlineVarLenEntryQueue_GetEntry(&it);
ASSERT_EQ(entry.size_1, sizeof(uint32_t) + 4);
ASSERT_EQ(entry.size_2, 0u);
pw_VariableLengthEntryQueue_Iterator_Advance(&it);
pw_VariableLengthEntryQueue_Iterator end =
pw_VariableLengthEntryQueue_End(buffer);
ASSERT_EQ(pw_VariableLengthEntryQueue_Iterator_Equal(&it, &end), true);
pw_InlineVarLenEntryQueue_Iterator_Advance(&it);
pw_InlineVarLenEntryQueue_Iterator end =
pw_InlineVarLenEntryQueue_End(buffer);
ASSERT_EQ(pw_InlineVarLenEntryQueue_Iterator_Equal(&it, &end), true);
return "passed";
}