-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Cyril Sharma
committed
Dec 6, 2024
1 parent
a05959b
commit d4b1c5f
Showing
6 changed files
with
318 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
#pragma once | ||
|
||
#include "fixed_containers/fixed_red_black_tree_nodes.hpp" | ||
#include "fixed_containers/fixed_red_black_tree_types.hpp" | ||
#include "fixed_containers/fixed_red_black_tree_view.hpp" | ||
#include "fixed_containers/map_entry_raw_view.hpp" | ||
|
||
#include <iterator> | ||
#include <type_traits> | ||
|
||
namespace fixed_containers | ||
{ | ||
|
||
class FixedMapRawView { | ||
using Compactness = fixed_red_black_tree_detail::RedBlackTreeNodeColorCompactness; | ||
using StorageType = fixed_red_black_tree_detail::RedBlackTreeStorageType; | ||
using NodeIndex = fixed_red_black_tree_detail::NodeIndex; | ||
|
||
public: | ||
class Iterator | ||
{ | ||
private: | ||
FixedRedBlackTreeRawView::Iterator base_iterator_; | ||
std::ptrdiff_t value_offset_; | ||
|
||
// We need this constructor to avoid default initializing the base_iterator_. | ||
Iterator(MapEntryRawView map_entry, | ||
const std::byte* ptr, | ||
std::size_t value_size_bytes, | ||
std::size_t max_size_bytes, | ||
Compactness compactness, | ||
StorageType storage_type, | ||
bool end = false) noexcept : | ||
base_iterator_( | ||
ptr, | ||
static_cast<size_t>(map_entry.value_offset()) + value_size_bytes, | ||
max_size_bytes, compactness, storage_type, end | ||
), | ||
value_offset_(map_entry.value_offset()) {} | ||
|
||
public: | ||
// Define iterator traits | ||
using value_type = const std::byte*; | ||
using difference_type = std::ptrdiff_t; | ||
using pointer = value_type*; | ||
using const_pointer = const value_type*; | ||
using reference = value_type&; | ||
using const_reference = const value_type&; | ||
using iterator_category = std::forward_iterator_tag; | ||
|
||
// Constructor that initializes the base iterator | ||
Iterator(const std::byte* ptr, | ||
std::size_t key_size_bytes, | ||
std::size_t key_align_bytes, | ||
std::size_t value_size_bytes, | ||
std::size_t value_align_bytes, | ||
std::size_t max_size_bytes, | ||
Compactness compactness, | ||
StorageType storage_type, | ||
bool end = false) noexcept : | ||
Iterator( | ||
MapEntryRawView(ptr, key_size_bytes, key_align_bytes, value_size_bytes, value_align_bytes), | ||
ptr, key_size_bytes, max_size_bytes, | ||
compactness, storage_type, end) {} | ||
|
||
Iterator() noexcept: base_iterator_(), value_offset_(0) {} | ||
Iterator(const Iterator&) noexcept = default; | ||
Iterator(Iterator&&) noexcept = default; | ||
Iterator& operator=(const Iterator&) noexcept = default; | ||
Iterator& operator=(Iterator&&) noexcept = default; | ||
|
||
Iterator& operator++() | ||
{ | ||
++base_iterator_; | ||
return *this; | ||
} | ||
|
||
Iterator operator++(int) & noexcept | ||
{ | ||
Iterator tmp = *this; | ||
++base_iterator_; | ||
return tmp; | ||
} | ||
|
||
const_reference operator*() const | ||
{ | ||
return *base_iterator_; | ||
} | ||
|
||
const_pointer operator->() const | ||
{ | ||
return base_iterator_.operator->(); | ||
} | ||
|
||
bool operator==(const Iterator& other) const | ||
{ | ||
return base_iterator_ == other.base_iterator_; | ||
} | ||
|
||
bool operator!=(const Iterator& other) const | ||
{ | ||
return !(*this == other); | ||
} | ||
|
||
[[nodiscard]] const std::byte* key() const { return *base_iterator_; } | ||
|
||
[[nodiscard]] const std::byte* value() const { return std::next(*base_iterator_, value_offset_); } | ||
|
||
[[nodiscard]] std::size_t size() const { return base_iterator_.size(); } | ||
}; | ||
|
||
private: | ||
const std::byte* tree_ptr_; | ||
const std::size_t key_size_bytes_; | ||
const std::size_t key_align_bytes_; | ||
const std::size_t value_size_bytes_; | ||
const std::size_t value_align_bytes_; | ||
const std::size_t max_size_bytes_; | ||
const Compactness compactness_; | ||
const StorageType storage_type_; | ||
|
||
public: | ||
FixedMapRawView(const void* tree_ptr, | ||
std::size_t key_size_bytes, | ||
std::size_t key_align_bytes, | ||
std::size_t value_size_bytes, | ||
std::size_t value_align_bytes, | ||
std::size_t max_size_bytes, | ||
Compactness compactness, | ||
StorageType storage_type): | ||
tree_ptr_{reinterpret_cast<const std::byte*>(tree_ptr)} | ||
, key_size_bytes_{key_size_bytes} | ||
, key_align_bytes_{key_align_bytes} | ||
, value_size_bytes_{value_size_bytes} | ||
, value_align_bytes_{value_align_bytes} | ||
, max_size_bytes_{max_size_bytes} | ||
, compactness_{compactness} | ||
, storage_type_{storage_type} | ||
{ | ||
} | ||
|
||
[[nodiscard]] Iterator begin() const | ||
{ | ||
return Iterator( | ||
tree_ptr_, | ||
key_size_bytes_, key_align_bytes_, value_size_bytes_, value_align_bytes_, | ||
max_size_bytes_, compactness_, storage_type_ | ||
); | ||
} | ||
|
||
[[nodiscard]] Iterator end() const | ||
{ | ||
return Iterator( | ||
tree_ptr_, | ||
key_size_bytes_, key_align_bytes_, value_size_bytes_, value_align_bytes_, | ||
max_size_bytes_, compactness_, storage_type_, | ||
true | ||
); | ||
} | ||
|
||
[[nodiscard]] std::size_t size() const { return end().size(); } | ||
}; | ||
|
||
} // namespace fixed_containers |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
#include <cstddef> | ||
class MapEntryRawView | ||
{ | ||
private: | ||
const std::byte* base_ptr_; | ||
const std::ptrdiff_t value_offs_; | ||
|
||
public: | ||
static constexpr std::ptrdiff_t get_value_offs(std::size_t key_size, | ||
std::size_t /*key_alignment*/, | ||
std::size_t /*value_size*/, | ||
std::size_t value_alignment) | ||
{ | ||
std::size_t value_offs = key_size; | ||
// align the value start addr to the correct alignment | ||
if (value_offs % value_alignment != 0) | ||
{ | ||
value_offs += value_alignment - value_offs % value_alignment; | ||
} | ||
return static_cast<std::ptrdiff_t>(value_offs); | ||
} | ||
|
||
public: | ||
MapEntryRawView(const void* ptr, | ||
std::size_t key_size, | ||
std::size_t key_alignment, | ||
std::size_t value_size, | ||
std::size_t value_alignment) | ||
: base_ptr_{reinterpret_cast<const std::byte*>(ptr)} | ||
, value_offs_{get_value_offs(key_size, key_alignment, value_size, value_alignment)} | ||
{ | ||
} | ||
|
||
[[nodiscard]] const std::byte* key() const { return base_ptr_; } | ||
|
||
[[nodiscard]] const std::byte* value() const { return std::next(base_ptr_, value_offs_); } | ||
|
||
[[nodiscard]] std::ptrdiff_t value_offset() const { return value_offs_; } | ||
|
||
|
||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
#include "fixed_containers/fixed_map_raw_view.hpp" | ||
|
||
#include "mock_testing_types.hpp" | ||
#include "test_utilities_common.hpp" | ||
#include "fixed_containers/fixed_map.hpp" | ||
#include <gtest/gtest.h> | ||
|
||
#include <array> | ||
#include <cstddef> | ||
#include <cstdint> | ||
#include <iterator> | ||
#include <ranges> | ||
|
||
namespace fixed_containers | ||
{ | ||
namespace | ||
{ | ||
|
||
static_assert(std::forward_iterator<FixedMapRawView::Iterator>); | ||
static_assert(std::ranges::forward_range<FixedMapRawView>); | ||
|
||
template <typename T> | ||
T get_from_ptr(const std::byte* ptr) | ||
{ | ||
return *reinterpret_cast<const T*>(ptr); | ||
} | ||
|
||
template <typename Key, typename Value> | ||
void test_and_increment(auto& map_it, auto& view_it) | ||
{ | ||
EXPECT_EQ(map_it->first, get_from_ptr<Key>(view_it.key())); | ||
EXPECT_EQ(map_it->second, get_from_ptr<Value>(view_it.value())); | ||
++map_it; | ||
++view_it; | ||
} | ||
|
||
template <typename Map> | ||
FixedMapRawView get_view_of_map(const Map& map) | ||
{ | ||
return FixedMapRawView(&map, | ||
sizeof(typename Map::key_type), | ||
alignof(typename Map::key_type), | ||
sizeof(typename Map::mapped_type), | ||
alignof(typename Map::mapped_type), | ||
map.max_size(), | ||
// Ideally we'd grab these from the map too. | ||
fixed_red_black_tree_detail::RedBlackTreeNodeColorCompactness::EMBEDDED_COLOR, | ||
fixed_red_black_tree_detail::RedBlackTreeStorageType::FIXED_INDEX_POOL); | ||
} | ||
|
||
|
||
TEST(FixedMapRawView, IntIntMap) | ||
{ | ||
const auto map = make_fixed_map<int, int>({{1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 0}}); | ||
const FixedMapRawView view = get_view_of_map(map); | ||
EXPECT_EQ(map.size(), view.size()); | ||
auto map_it = map.begin(); | ||
FixedMapRawView::Iterator view_it = view.begin(); | ||
for (std::size_t i = 0; i < map.size(); i++) | ||
{ | ||
test_and_increment<int, int>(map_it, view_it); | ||
} | ||
EXPECT_EQ(map_it, map.end()); | ||
EXPECT_EQ(view_it, view.end()); | ||
} | ||
|
||
TEST(FixedMapRawView, CharCharMap) | ||
{ | ||
FixedMap<char, char, 10> map{}; | ||
map['a'] = 'A'; | ||
map['b'] = 'B'; | ||
map['c'] = 'C'; | ||
map['z'] = 'Z'; | ||
|
||
const FixedMapRawView view = get_view_of_map(map); | ||
EXPECT_EQ(map.size(), view.size()); | ||
auto map_it = map.begin(); | ||
auto view_it = view.begin(); | ||
for (std::size_t i = 0; i < map.size(); i++) | ||
{ | ||
test_and_increment<char, char>(map_it, view_it); | ||
} | ||
EXPECT_EQ(map_it, map.end()); | ||
EXPECT_EQ(view_it, view.end()); | ||
} | ||
} | ||
} // namespace fixed_containers |