diff --git a/BUILD.bazel b/BUILD.bazel index 16aa39d2..c4c9306b 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -433,6 +433,13 @@ cc_library( copts = ["-std=c++20"], ) +cc_library( + name = "fixed_deque_raw_view", + hdrs = ["include/fixed_containers/fixed_deque_raw_view.hpp"], + includes = ["include"], + copts = ["-std=c++20"], +) + cc_library( name = "fixed_queue", hdrs = ["include/fixed_containers/fixed_queue.hpp"], diff --git a/CMakeLists.txt b/CMakeLists.txt index 2738060d..60ae7e29 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -185,6 +185,8 @@ if(BUILD_TESTS) add_test_dependencies(fixed_unordered_set_test) add_executable(fixed_unordered_set_raw_view_test test/fixed_unordered_set_raw_view_test.cpp) add_test_dependencies(fixed_unordered_set_raw_view_test) + add_executable(fixed_queue_raw_view_test test/fixed_queue_raw_view_test.cpp) + add_test_dependencies(fixed_queue_raw_view_test) add_executable(fixed_stack_test test/fixed_stack_test.cpp) add_test_dependencies(fixed_stack_test) add_executable(fixed_queue_test test/fixed_queue_test.cpp) diff --git a/include/fixed_containers/fixed_deque_raw_view.hpp b/include/fixed_containers/fixed_deque_raw_view.hpp new file mode 100644 index 00000000..ada436a5 --- /dev/null +++ b/include/fixed_containers/fixed_deque_raw_view.hpp @@ -0,0 +1,107 @@ +#pragma once + +#include "fixed_containers/forward_iterator.hpp" + +#include + +template +class FixedDequeRawView +{ +public: + class ReferenceProvider + { + friend class FixedDequeRawView; + + private: + const FixedDequeRawView* parent_; + + IndexType current_idx_; + + explicit constexpr ReferenceProvider(const FixedDoublyLinkedListRawView* parent) noexcept + : parent_{parent} + , current_idx_{static_cast(parent_->stat().start)} + { + } + + public: + constexpr ReferenceProvider() noexcept + : parent_{nullptr} + , current_idx_{0} + { + } + + constexpr void advance() noexcept { + current_idx_ = parent_->next_index(current_idx_); + } + + [[nodiscard]] constexpr const std::byte* get() const noexcept + { + return parent_->value_at(current_idx_); + } + + constexpr bool operator==(const ReferenceProvider& other) const noexcept = default; + }; + +private: + const std::byte* data_ptr_; + std::size_t elem_size_bytes_; + std::size_t elem_align_bytes_; + std::size_t max_elem_count_; + +public: + using Iterator = + ForwardIterator; + using iterator = Iterator; + using const_iterator = iterator; + + FixedDequeRawView(const void* data_ptr, + std::size_t elem_size_bytes, + std::size_t elem_align_bytes, + std::size_t max_elem_count) + : data_ptr_{static_cast(data_ptr)} + , elem_size_bytes_{elem_size_bytes} + , elem_align_bytes_{elem_align_bytes} + , max_elem_count_{max_elem_count} + { + } + + [[nodiscard]] Iterator begin() const { return std::next(Iterator{ReferenceProvider{this}}); } + + [[nodiscard]] Iterator end() const { return Iterator{ReferenceProvider{this}}; } + + [[nodiscard]] StartingIntegerAndDistance stat() const + { + // The bookkeeping fields are stored after the data in fixed_deque + return *reinterpret_cast( + std::next(data_ptr_, value_storage_size())); + } + + [[nodiscard]] StartingIntegerAndDistance size() const { return stat().distance; } + +public: + + [[nodiscard]] constexpr const std::byte* value_at(IndexType index) const noexcept + { + return std::next(value_storage_start(), + static_cast(elem_size_bytes_ * index)); + } + + [[nodiscard]] constexpr const std::byte* value_storage_start() const noexcept + { + return data_ptr_; + } + + [[nodiscard]] constexpr std::ptrdiff_t value_storage_size() const noexcept + { + // The size of the data portion of the queue. + std::size_t raw_size = max_elem_count_ * elem_size_bytes_; + return static_cast(raw_size); + } + + [[nodiscard]] constexpr std::ptrdiff_t next_index(IndexType idx) const noexcept + { + auto stats = stat(); + IndexType nidx = (stats.start + idx + 1) % max_elem_count_; + return nidx; + } +}; diff --git a/test/fixed_deque_raw_view_test.cpp b/test/fixed_deque_raw_view_test.cpp new file mode 100644 index 00000000..cebc1e64 --- /dev/null +++ b/test/fixed_deque_raw_view_test.cpp @@ -0,0 +1,76 @@ +#include "fixed_containers/fixed_deque_raw_view.hpp" + +#include "mock_testing_types.hpp" + +#include "fixed_containers/concepts.hpp" +#include "fixed_containers/fixed_deque.hpp" +#include "fixed_containers/map_entry.hpp" + +#include + +#include +#include +#include + +namespace fixed_containers +{ +namespace +{ +static_assert(std::forward_iterator); +static_assert(std::ranges::forward_range); + +static_assert(sizeof(MapEntry) == sizeof(int)); +static_assert(sizeof(MapEntry) == sizeof(char)); +static_assert(sizeof(MapEntry) == sizeof(MockAligned64)); + +template +T get_from_ptr(const std::byte* ptr) +{ + return *reinterpret_cast(ptr); +} + +template +void test_and_increment(auto& map_it, auto& view_it) +{ + EXPECT_EQ(*map_it, get_from_ptr(*view_it)); + ++map_it; + ++view_it; +} +} // namespace + +TEST(FixedUnorderedSetRawView, IntSet) +{ + auto dq = make_fixed_deque({1, 2, 3, 5, 8, 13}); + const FixedDequeRawView view{&dq, sizeof(int), alignof(int), dq.max_size()}; + EXPECT_EQ(set.size(), view.size()); + auto set_it = set.begin(); + auto view_it = view.begin(); + for (std::size_t i = 0; i < set.size(); i++) + { + test_and_increment(set_it, view_it); + } + EXPECT_EQ(set_it, set.end()); + EXPECT_EQ(view_it, view.end()); +} + +// TEST(FixedUnorderedsetRawView, StructSet) +// { +// FixedUnorderedSet set{}; +// set.insert({21}); +// set.insert({34}); +// set.insert({55}); + +// const FixedUnorderedSetRawView view{&set, sizeof(MockAligned64), alignof(MockAligned64), 10}; + +// EXPECT_EQ(set.size(), view.size()); +// auto set_it = set.begin(); +// auto view_it = view.begin(); +// for (std::size_t i = 0; i < set.size(); i++) +// { +// test_and_increment(set_it, view_it); +// } +// EXPECT_EQ(set_it, set.end()); +// EXPECT_EQ(view_it, view.end()); +// } + +} // namespace fixed_containers